Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Mar 2016 00:16:22 +0000 (17:16 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 17 Mar 2016 00:16:22 +0000 (17:16 -0700)
Pull SCSI updates from James Bottomley:
 "This pull includes driver updates from the usual suspects (stex, hpsa,
  ncr5380, scsi_dh, qla2xxx, be2iscsi, hisi_sas, cxlflash, aacraid,
  mp3sas, megaraid_sas, ibmvscsi, ufs) plus an assortment of
  miscellaneous fixes.

  The major user visible change of this pull is that we've moved from
  monotonically increasing host number to an ida allocated one (meaning
  the numbers get re-used) because someone managed to wrap the count in
  an iscsi system.  We don't believe there will be any adverse
  consequences of this"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (230 commits)
  MAINTAINERS: use new email address for James Bottomley
  mpt3sas: Remove unnecessary synchronize_irq() before free_irq()
  sg: fix dxferp in from_to case
  cxlflash: Increase cmd_per_lun for better throughput
  cxlflash: Fix to avoid unnecessary scan with internal LUNs
  cxlflash: Reorder user context initialization
  cxlflash: Simplify attach path error cleanup
  cxlflash: Split out context initialization
  cxlflash: Unmap problem state area before detaching master context
  cxlflash: Simplify PCI registration
  scsi: storvsc: fix SRB_STATUS_ABORTED handling
  be2iscsi: set the boot_kset pointer to NULL in case of failure
  sd: Fix discard granularity when LBPRZ=1
  be2iscsi: Remove unnecessary synchronize_irq() before free_irq()
  scsi_sysfs: call 'device_add' after attaching device handler
  scsi_dh_emc: update 'access_state' field
  scsi_dh_rdac: update 'access_state' field
  scsi_dh_alua: update 'access_state' field
  scsi_dh_alua: use common definitions for ALUA state
  scsi: Add 'access_state' and 'preferred_path' attribute
  ...

1960 files changed:
Documentation/DocBook/media/v4l/media-types.xml
Documentation/cpu-freq/intel-pstate.txt
Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/omap/omap.txt
Documentation/devicetree/bindings/edac/apm-xgene-edac.txt
Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/hwmon/nsa320-mcu.txt [new file with mode: 0644]
Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
Documentation/devicetree/bindings/iio/iio-bindings.txt
Documentation/devicetree/bindings/interrupt-controller/al,alpine-msix.txt [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
Documentation/devicetree/bindings/interrupt-controller/marvell,odmi-controller.txt [new file with mode: 0644]
Documentation/devicetree/bindings/interrupt-controller/mips-gic.txt
Documentation/devicetree/bindings/interrupt-controller/sigma,smp8642-intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/leds/leds-is31fl32xx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/designware-pcie.txt
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
Documentation/devicetree/bindings/pci/pci-thunder-ecam.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/pci-thunder-pem.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/xilinx-pcie.txt
Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/nxp,lpc1850-scu.txt
Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
Documentation/devicetree/bindings/pinctrl/qcom,ipq4019-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regmap/regmap.txt
Documentation/devicetree/bindings/regulator/act8945a-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/lp872x.txt
Documentation/devicetree/bindings/regulator/max77802.txt
Documentation/devicetree/bindings/regulator/regulator-max77620.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/regulator.txt
Documentation/devicetree/bindings/regulator/tps65217.txt
Documentation/devicetree/bindings/rtc/alphascale,asm9260-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/epson,rx6110.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/maxim,ds3231.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/microchip,pic32-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs4271.txt
Documentation/devicetree/bindings/spi/adi,axi-spi-engine.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/icpdas-lp8841-spi-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi-rockchip.txt
Documentation/devicetree/bindings/spi/spi-xilinx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/hwmon/adm1275
Documentation/hwmon/lm25066
Documentation/hwmon/ltc2990 [new file with mode: 0644]
Documentation/hwmon/max16064
Documentation/hwmon/max34440
Documentation/hwmon/max8688
Documentation/hwmon/nsa320 [new file with mode: 0644]
Documentation/hwmon/ntc_thermistor
Documentation/hwmon/pmbus
Documentation/hwmon/zl6100
Documentation/kernel-parameters.txt
Documentation/memory-hotplug.txt
Documentation/printk-formats.txt
Documentation/ptp/testptp.c
Documentation/rtc.txt
Documentation/sysctl/kernel.txt
Documentation/virtual/kvm/api.txt
Documentation/virtual/kvm/devices/s390_flic.txt
Documentation/virtual/kvm/devices/vcpu.txt [new file with mode: 0644]
Documentation/virtual/kvm/devices/vm.txt
Documentation/virtual/kvm/mmu.txt
Documentation/vm/page_owner.txt
Documentation/vm/slub.txt
Documentation/watchdog/watchdog-parameters.txt
Documentation/x86/early-microcode.txt
Documentation/x86/exception-tables.txt
Documentation/x86/x86_64/boot-options.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/pci.h
arch/alpha/kernel/smp.c
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/configs/axs101_defconfig
arch/arc/configs/axs103_defconfig
arch/arc/configs/axs103_smp_defconfig
arch/arc/configs/nsim_700_defconfig
arch/arc/configs/nsim_hs_defconfig
arch/arc/configs/nsim_hs_smp_defconfig
arch/arc/configs/nsimosci_defconfig
arch/arc/configs/nsimosci_hs_defconfig
arch/arc/configs/nsimosci_hs_smp_defconfig
arch/arc/configs/tb10x_defconfig
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/dma.h
arch/arc/include/asm/io.h
arch/arc/include/asm/irq.h
arch/arc/include/asm/irqflags-arcv2.h
arch/arc/include/asm/pci.h [new file with mode: 0644]
arch/arc/kernel/Makefile
arch/arc/kernel/entry-arcv2.S
arch/arc/kernel/intc-compact.c
arch/arc/kernel/mcip.c
arch/arc/kernel/pcibios.c [new file with mode: 0644]
arch/arc/kernel/setup.c
arch/arc/kernel/smp.c
arch/arc/plat-axs10x/Kconfig
arch/arm/Kconfig
arch/arm/boot/compressed/Makefile
arch/arm/boot/dts/am335x-bone-common.dtsi
arch/arm/boot/dts/am335x-chilisom.dtsi
arch/arm/boot/dts/am335x-nano.dts
arch/arm/boot/dts/am335x-pepper.dts
arch/arm/boot/dts/am335x-shc.dts
arch/arm/boot/dts/am335x-sl50.dts
arch/arm/boot/dts/am57xx-beagle-x15.dts
arch/arm/boot/dts/am57xx-cl-som-am57x.dts
arch/arm/boot/dts/armada-xp-axpwifiap.dts
arch/arm/boot/dts/armada-xp-db.dts
arch/arm/boot/dts/armada-xp-gp.dts
arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
arch/arm/boot/dts/armada-xp-linksys-mamba.dts
arch/arm/boot/dts/armada-xp-matrix.dts
arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
arch/arm/boot/dts/armada-xp-synology-ds414.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/kirkwood-ds112.dts
arch/arm/boot/dts/mt2701-pinfunc.h [new file with mode: 0644]
arch/arm/boot/dts/orion5x-linkstation-lswtgl.dts
arch/arm/boot/dts/r8a7791-porter.dts
arch/arm/boot/dts/sama5d2-pinfunc.h
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/tps65217.dtsi [new file with mode: 0644]
arch/arm/boot/dts/vfxxx.dtsi
arch/arm/include/asm/arch_gicv3.h
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/kvm_asm.h
arch/arm/include/asm/kvm_emulate.h
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/kvm_hyp.h [new file with mode: 0644]
arch/arm/include/asm/kvm_mmu.h
arch/arm/include/asm/pci.h
arch/arm/include/asm/virt.h
arch/arm/kernel/Makefile
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/kvm/Makefile
arch/arm/kvm/arm.c
arch/arm/kvm/coproc.c
arch/arm/kvm/coproc.h
arch/arm/kvm/emulate.c
arch/arm/kvm/guest.c
arch/arm/kvm/handle_exit.c
arch/arm/kvm/hyp/Makefile [new file with mode: 0644]
arch/arm/kvm/hyp/banked-sr.c [new file with mode: 0644]
arch/arm/kvm/hyp/cp15-sr.c [new file with mode: 0644]
arch/arm/kvm/hyp/entry.S [new file with mode: 0644]
arch/arm/kvm/hyp/hyp-entry.S [new file with mode: 0644]
arch/arm/kvm/hyp/s2-setup.c [new file with mode: 0644]
arch/arm/kvm/hyp/switch.c [new file with mode: 0644]
arch/arm/kvm/hyp/tlb.c [new file with mode: 0644]
arch/arm/kvm/hyp/vfp.S [new file with mode: 0644]
arch/arm/kvm/init.S
arch/arm/kvm/interrupts.S
arch/arm/kvm/interrupts_head.S [deleted file]
arch/arm/kvm/mmio.c
arch/arm/kvm/mmu.c
arch/arm/kvm/psci.c
arch/arm/kvm/reset.c
arch/arm/mach-imx/gpc.c
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-mvebu/Kconfig
arch/arm/mach-netx/fb.c
arch/arm/mach-nspire/clcd.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-shmobile/common.h
arch/arm/mach-shmobile/headsmp-scu.S
arch/arm/mach-shmobile/headsmp.S
arch/arm/mach-shmobile/platsmp-apmu.c
arch/arm/mach-shmobile/platsmp-scu.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-socfpga/Makefile
arch/arm/mach-socfpga/core.h
arch/arm/mach-socfpga/l2_cache.c [new file with mode: 0644]
arch/arm/mach-socfpga/ocram.c [new file with mode: 0644]
arch/arm/mach-socfpga/socfpga.c
arch/arm/mm/mmap.c
arch/arm/mm/pageattr.c
arch/arm/plat-samsung/pm-check.c
arch/arm/vdso/vdso.S
arch/arm64/Kconfig
arch/arm64/boot/dts/apm/apm-storm.dtsi
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/cacheflush.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/hw_breakpoint.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_hyp.h [new file with mode: 0644]
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/kvm_perf_event.h [new file with mode: 0644]
arch/arm64/include/asm/pci.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/virt.h
arch/arm64/include/uapi/asm/kvm.h
arch/arm64/kernel/asm-offsets.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/head.S
arch/arm64/kernel/pci.c
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/sleep.S
arch/arm64/kernel/smp.c
arch/arm64/kvm/Kconfig
arch/arm64/kvm/Makefile
arch/arm64/kvm/guest.c
arch/arm64/kvm/hyp-init.S
arch/arm64/kvm/hyp.S
arch/arm64/kvm/hyp/Makefile
arch/arm64/kvm/hyp/debug-sr.c
arch/arm64/kvm/hyp/entry.S
arch/arm64/kvm/hyp/hyp-entry.S
arch/arm64/kvm/hyp/hyp.h [deleted file]
arch/arm64/kvm/hyp/s2-setup.c [new file with mode: 0644]
arch/arm64/kvm/hyp/switch.c
arch/arm64/kvm/hyp/sysreg-sr.c
arch/arm64/kvm/hyp/timer-sr.c [deleted file]
arch/arm64/kvm/hyp/tlb.c
arch/arm64/kvm/hyp/vgic-v2-sr.c [deleted file]
arch/arm64/kvm/hyp/vgic-v3-sr.c
arch/arm64/kvm/reset.c
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/hugetlbpage.c
arch/arm64/mm/init.c
arch/arm64/mm/mmap.c
arch/avr32/include/asm/cmpxchg.h
arch/avr32/include/asm/pci.h
arch/avr32/include/uapi/asm/unistd.h
arch/avr32/kernel/setup.c
arch/avr32/kernel/syscall-stubs.S
arch/avr32/kernel/syscall_table.S
arch/blackfin/Kconfig
arch/blackfin/include/asm/pci.h
arch/blackfin/include/asm/pgtable.h
arch/blackfin/mach-common/smp.c
arch/c6x/kernel/setup.c
arch/cris/include/asm/pci.h
arch/frv/include/asm/pci.h
arch/hexagon/kernel/smp.c
arch/ia64/Kconfig
arch/ia64/include/asm/pci.h
arch/ia64/kernel/efi.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/smpboot.c
arch/ia64/pci/fixup.c
arch/ia64/sn/kernel/io_acpi_init.c
arch/ia64/sn/kernel/io_init.c
arch/m32r/Kconfig
arch/m32r/kernel/setup.c
arch/m32r/kernel/smpboot.c
arch/m32r/mm/init.c
arch/m68k/include/asm/MC68328.h
arch/m68k/include/asm/MC68EZ328.h
arch/m68k/include/asm/MC68VZ328.h
arch/m68k/include/asm/m54xxacr.h
arch/m68k/include/asm/mac_iop.h
arch/m68k/include/asm/mcftimer.h
arch/m68k/include/asm/pci.h
arch/m68k/kernel/entry.S
arch/m68k/kernel/signal.c
arch/m68k/mac/via.c
arch/metag/kernel/smp.c
arch/microblaze/Kconfig
arch/microblaze/include/asm/pci.h
arch/microblaze/kernel/setup.c
arch/microblaze/pci/pci-common.c
arch/mips/Kconfig
arch/mips/ath79/irq.c
arch/mips/bmips/irq.c
arch/mips/boot/compressed/uart-16550.c
arch/mips/boot/dts/brcm/bcm6328.dtsi
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/include/asm/mach-ath79/ath79.h
arch/mips/include/asm/pci.h
arch/mips/include/asm/smp-ops.h
arch/mips/jz4740/gpio.c
arch/mips/kernel/Makefile
arch/mips/kernel/r2300_fpu.S
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/setup.c
arch/mips/kernel/smp-cmp.c
arch/mips/kernel/smp-cps.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smp.c
arch/mips/kernel/traps.c
arch/mips/kvm/mips.c
arch/mips/mm/mmap.c
arch/mips/mm/sc-mips.c
arch/mips/pci/fixup-loongson3.c
arch/mn10300/include/asm/pci.h
arch/mn10300/kernel/smp.c
arch/parisc/include/asm/cache.h
arch/parisc/include/asm/cacheflush.h
arch/parisc/include/asm/floppy.h
arch/parisc/include/asm/pci.h
arch/parisc/include/uapi/asm/unistd.h
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/smp.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/syscall_table.S
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/kvm_book3s_64.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/pci.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/xics.h
arch/powerpc/include/uapi/asm/kvm.h
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp.c
arch/powerpc/kvm/Makefile
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_64_vio.c
arch/powerpc/kvm/book3s_64_vio_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_rm_xics.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_pr_papr.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/hash64_64k.c
arch/powerpc/mm/hugepage-hash64.c
arch/powerpc/mm/hugetlbpage-book3e.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/mmap.c
arch/powerpc/mm/pgtable.c
arch/powerpc/perf/hv-24x7.c
arch/powerpc/sysdev/xics/icp-native.c
arch/s390/Kconfig
arch/s390/include/asm/clp.h
arch/s390/include/asm/fpu/internal.h
arch/s390/include/asm/gmap.h [new file with mode: 0644]
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/pci.h
arch/s390/include/asm/pci_clp.h
arch/s390/include/asm/percpu.h
arch/s390/include/asm/perf_event.h
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/rwsem.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/xor.h
arch/s390/include/uapi/asm/clp.h [new file with mode: 0644]
arch/s390/include/uapi/asm/kvm.h
arch/s390/include/uapi/asm/sie.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/cpcmd.c
arch/s390/kernel/debug.c
arch/s390/kernel/dis.c
arch/s390/kernel/dumpstack.c
arch/s390/kernel/early.c
arch/s390/kernel/entry.S
arch/s390/kernel/head64.S
arch/s390/kernel/irq.c
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/perf_event.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/stacktrace.c
arch/s390/kernel/time.c
arch/s390/kernel/traps.c
arch/s390/kvm/diag.c
arch/s390/kvm/gaccess.c
arch/s390/kvm/gaccess.h
arch/s390/kvm/guestdbg.c
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/lib/Makefile
arch/s390/lib/xor.c [new file with mode: 0644]
arch/s390/mm/Makefile
arch/s390/mm/extmem.c
arch/s390/mm/fault.c
arch/s390/mm/gmap.c [new file with mode: 0644]
arch/s390/mm/hugetlbpage.c
arch/s390/mm/pageattr.c
arch/s390/mm/pgalloc.c [new file with mode: 0644]
arch/s390/mm/pgtable.c
arch/s390/mm/vmem.c
arch/s390/oprofile/Makefile
arch/s390/oprofile/backtrace.c [deleted file]
arch/s390/oprofile/init.c
arch/s390/pci/pci.c
arch/s390/pci/pci_clp.c
arch/s390/pci/pci_debug.c
arch/s390/pci/pci_dma.c
arch/s390/pci/pci_event.c
arch/score/kernel/setup.c
arch/sh/Kconfig
arch/sh/include/asm/pci.h
arch/sh/kernel/setup.c
arch/sh/kernel/smp.c
arch/sparc/Makefile
arch/sparc/include/asm/pci.h
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/entry.S
arch/sparc/kernel/head_64.S
arch/sparc/kernel/hvcalls.S
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/smp_32.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/sparc_ksyms_64.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/syscalls.S
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/mm/init_64.c
arch/tile/Kconfig
arch/tile/include/asm/pci.h
arch/tile/kernel/setup.c
arch/tile/kernel/smpboot.c
arch/um/kernel/reboot.c
arch/um/kernel/signal.c
arch/unicore32/include/asm/pci.h
arch/unicore32/include/mach/hardware.h
arch/unicore32/kernel/setup.c
arch/x86/Kbuild
arch/x86/Kconfig
arch/x86/Kconfig.debug
arch/x86/boot/cpuflags.h
arch/x86/boot/mkcpustr.c
arch/x86/boot/tools/build.c
arch/x86/configs/i386_defconfig
arch/x86/crypto/crc32-pclmul_glue.c
arch/x86/crypto/crc32c-intel_glue.c
arch/x86/crypto/crct10dif-pclmul_glue.c
arch/x86/entry/calling.h
arch/x86/entry/common.c
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/entry/entry_64_compat.S
arch/x86/entry/syscall_32.c
arch/x86/entry/syscall_64.c
arch/x86/entry/syscalls/syscall_64.tbl
arch/x86/entry/syscalls/syscalltbl.sh
arch/x86/entry/vdso/vdso2c.h
arch/x86/entry/vdso/vdso32-setup.c
arch/x86/entry/vdso/vdso32/system_call.S
arch/x86/entry/vdso/vma.c
arch/x86/entry/vsyscall/vsyscall_gtod.c
arch/x86/events/Makefile [new file with mode: 0644]
arch/x86/events/amd/core.c [new file with mode: 0644]
arch/x86/events/amd/ibs.c [new file with mode: 0644]
arch/x86/events/amd/iommu.c [new file with mode: 0644]
arch/x86/events/amd/iommu.h [new file with mode: 0644]
arch/x86/events/amd/uncore.c [new file with mode: 0644]
arch/x86/events/core.c [new file with mode: 0644]
arch/x86/events/intel/bts.c [new file with mode: 0644]
arch/x86/events/intel/core.c [new file with mode: 0644]
arch/x86/events/intel/cqm.c [new file with mode: 0644]
arch/x86/events/intel/cstate.c [new file with mode: 0644]
arch/x86/events/intel/ds.c [new file with mode: 0644]
arch/x86/events/intel/knc.c [new file with mode: 0644]
arch/x86/events/intel/lbr.c [new file with mode: 0644]
arch/x86/events/intel/p4.c [new file with mode: 0644]
arch/x86/events/intel/p6.c [new file with mode: 0644]
arch/x86/events/intel/pt.c [new file with mode: 0644]
arch/x86/events/intel/pt.h [new file with mode: 0644]
arch/x86/events/intel/rapl.c [new file with mode: 0644]
arch/x86/events/intel/uncore.c [new file with mode: 0644]
arch/x86/events/intel/uncore.h [new file with mode: 0644]
arch/x86/events/intel/uncore_nhmex.c [new file with mode: 0644]
arch/x86/events/intel/uncore_snb.c [new file with mode: 0644]
arch/x86/events/intel/uncore_snbep.c [new file with mode: 0644]
arch/x86/events/msr.c [new file with mode: 0644]
arch/x86/events/perf_event.h [new file with mode: 0644]
arch/x86/include/asm/alternative.h
arch/x86/include/asm/amd_nb.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/arch_hweight.h
arch/x86/include/asm/asm.h
arch/x86/include/asm/barrier.h
arch/x86/include/asm/bitops.h
arch/x86/include/asm/cacheflush.h
arch/x86/include/asm/clocksource.h
arch/x86/include/asm/cmpxchg.h
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/cpufeatures.h [new file with mode: 0644]
arch/x86/include/asm/desc_defs.h
arch/x86/include/asm/dmi.h
arch/x86/include/asm/elf.h
arch/x86/include/asm/fixmap.h
arch/x86/include/asm/fpu/internal.h
arch/x86/include/asm/fpu/xstate.h
arch/x86/include/asm/frame.h
arch/x86/include/asm/imr.h
arch/x86/include/asm/ipi.h
arch/x86/include/asm/irq_work.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/kvm_page_track.h [new file with mode: 0644]
arch/x86/include/asm/kvm_para.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/microcode.h
arch/x86/include/asm/microcode_intel.h
arch/x86/include/asm/mmu.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/mwait.h
arch/x86/include/asm/pci.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/proto.h
arch/x86/include/asm/sections.h
arch/x86/include/asm/sighandling.h
arch/x86/include/asm/smap.h
arch/x86/include/asm/smp.h
arch/x86/include/asm/string_64.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/tlbflush.h
arch/x86/include/asm/topology.h
arch/x86/include/asm/tsc.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/asm/vdso.h
arch/x86/include/asm/vgtod.h
arch/x86/include/uapi/asm/hyperv.h
arch/x86/include/uapi/asm/sigcontext.h
arch/x86/include/uapi/asm/ucontext.h
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/apic_flat_64.c
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/apic/ipi.c
arch/x86/kernel/asm-offsets.c
arch/x86/kernel/asm-offsets_32.c
arch/x86/kernel/asm-offsets_64.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs_64.c
arch/x86/kernel/cpu/centaur.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cyrix.c
arch/x86/kernel/cpu/hypervisor.c
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/intel_pt.h [deleted file]
arch/x86/kernel/cpu/match.c
arch/x86/kernel/cpu/mcheck/mce-inject.c
arch/x86/kernel/cpu/mcheck/mce-severity.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mcheck/p5.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/mcheck/threshold.c
arch/x86/kernel/cpu/mcheck/winchip.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/cpu/microcode/intel_lib.c
arch/x86/kernel/cpu/mkcapflags.sh
arch/x86/kernel/cpu/mshyperv.c
arch/x86/kernel/cpu/mtrr/centaur.c
arch/x86/kernel/cpu/mtrr/cleanup.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/cpu/perf_event.c [deleted file]
arch/x86/kernel/cpu/perf_event.h [deleted file]
arch/x86/kernel/cpu/perf_event_amd.c [deleted file]
arch/x86/kernel/cpu/perf_event_amd_ibs.c [deleted file]
arch/x86/kernel/cpu/perf_event_amd_iommu.c [deleted file]
arch/x86/kernel/cpu/perf_event_amd_iommu.h [deleted file]
arch/x86/kernel/cpu/perf_event_amd_uncore.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_bts.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_cqm.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_cstate.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_ds.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_lbr.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_pt.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_rapl.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_uncore.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_uncore.h [deleted file]
arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c [deleted file]
arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c [deleted file]
arch/x86/kernel/cpu/perf_event_knc.c [deleted file]
arch/x86/kernel/cpu/perf_event_msr.c [deleted file]
arch/x86/kernel/cpu/perf_event_p4.c [deleted file]
arch/x86/kernel/cpu/perf_event_p6.c [deleted file]
arch/x86/kernel/cpu/rdrand.c
arch/x86/kernel/cpu/topology.c
arch/x86/kernel/cpu/transmeta.c
arch/x86/kernel/cpu/vmware.c
arch/x86/kernel/crash.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/e820.c
arch/x86/kernel/fpu/core.c
arch/x86/kernel/fpu/init.c
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/head64.c
arch/x86/kernel/head_32.S
arch/x86/kernel/head_64.S
arch/x86/kernel/hpet.c
arch/x86/kernel/kgdb.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/mcount_64.S
arch/x86/kernel/mpparse.c
arch/x86/kernel/msr.c
arch/x86/kernel/nmi.c
arch/x86/kernel/pmem.c
arch/x86/kernel/process.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/test_nx.c
arch/x86/kernel/test_rodata.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/verify_cpu.S
arch/x86/kernel/vm86_32.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kernel/x8664_ksyms_64.c
arch/x86/kvm/Makefile
arch/x86/kvm/assigned-dev.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/emulate.c
arch/x86/kvm/hyperv.c
arch/x86/kvm/i8254.c
arch/x86/kvm/i8254.h
arch/x86/kvm/ioapic.c
arch/x86/kvm/ioapic.h
arch/x86/kvm/irq.c
arch/x86/kvm/irq.h
arch/x86/kvm/irq_comm.c
arch/x86/kvm/lapic.c
arch/x86/kvm/lapic.h
arch/x86/kvm/mmu.c
arch/x86/kvm/mmu.h
arch/x86/kvm/page_track.c [new file with mode: 0644]
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/pmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/trace.h
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/lguest/boot.c
arch/x86/lib/clear_page_64.S
arch/x86/lib/cmdline.c
arch/x86/lib/copy_page_64.S
arch/x86/lib/copy_user_64.S
arch/x86/lib/delay.c
arch/x86/lib/memcpy_64.S
arch/x86/lib/memmove_64.S
arch/x86/lib/memset_64.S
arch/x86/mm/dump_pagetables.c
arch/x86/mm/extable.c
arch/x86/mm/fault.c
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/kasan_init_64.c
arch/x86/mm/kmmio.c
arch/x86/mm/mmap.c
arch/x86/mm/mpx.c
arch/x86/mm/numa.c
arch/x86/mm/pageattr.c
arch/x86/mm/pat.c
arch/x86/mm/setup_nx.c
arch/x86/oprofile/op_model_amd.c
arch/x86/pci/common.c
arch/x86/pci/fixup.c
arch/x86/pci/intel_mid_pci.c
arch/x86/pci/irq.c
arch/x86/pci/vmd.c
arch/x86/platform/efi/quirks.c
arch/x86/platform/geode/alix.c
arch/x86/platform/geode/geos.c
arch/x86/platform/geode/net5501.c
arch/x86/platform/intel-mid/mfld.c
arch/x86/platform/intel-mid/mrfl.c
arch/x86/platform/intel-quark/imr.c
arch/x86/platform/intel-quark/imr_selftest.c
arch/x86/um/asm/barrier.h
arch/x86/um/os-Linux/task_size.c
arch/x86/um/sys_call_table_32.c
arch/x86/um/sys_call_table_64.c
arch/x86/um/user-offsets.c
arch/x86/xen/enlighten.c
arch/x86/xen/pmu.c
arch/x86/xen/smp.c
arch/xtensa/Kconfig
arch/xtensa/include/asm/pci.h
arch/xtensa/kernel/smp.c
block/Kconfig
block/blk-map.c
block/blk-merge.c
block/partition-generic.c
drivers/acpi/Makefile
drivers/acpi/acpi_amba.c [new file with mode: 0644]
drivers/acpi/acpi_apd.c
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_processor.c
drivers/acpi/acpi_video.c
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/acpredef.h
drivers/acpi/acpica/dbcmds.c
drivers/acpi/acpica/dbconvert.c
drivers/acpi/acpica/dsmethod.c
drivers/acpi/acpica/dsobject.c
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/evgpeinit.c
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/exconfig.c
drivers/acpi/acpica/exoparg3.c
drivers/acpi/acpica/nseval.c
drivers/acpi/acpica/nsinit.c
drivers/acpi/acpica/psargs.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbprint.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/tbxfload.c
drivers/acpi/acpica/utcache.c
drivers/acpi/acpica/utnonansi.c
drivers/acpi/acpica/uttrack.c
drivers/acpi/acpica/utxferror.c
drivers/acpi/acpica/utxfinit.c
drivers/acpi/apei/apei-base.c
drivers/acpi/apei/einj.c
drivers/acpi/apei/erst.c
drivers/acpi/apei/ghes.c
drivers/acpi/bgrt.c
drivers/acpi/bus.c
drivers/acpi/cppc_acpi.c
drivers/acpi/ec_sys.c
drivers/acpi/fan.c
drivers/acpi/internal.h
drivers/acpi/nfit.c
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/pmic/intel_pmic_crc.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/tables.c
drivers/acpi/utils.c
drivers/android/binder.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ahci_xgene.c
drivers/ata/libahci.c
drivers/ata/libata-scsi.c
drivers/ata/pata_macio.c
drivers/ata/pata_rb532_cf.c
drivers/base/memory.c
drivers/base/power/domain.c
drivers/base/power/domain_governor.c
drivers/base/power/opp/core.c
drivers/base/power/opp/cpu.c
drivers/base/power/opp/debugfs.c
drivers/base/power/opp/opp.h
drivers/base/power/trace.c
drivers/base/property.c
drivers/base/regmap/internal.h
drivers/base/regmap/regcache-flat.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap-mmio.c
drivers/base/regmap/regmap.c
drivers/block/paride/pd.c
drivers/block/paride/pt.c
drivers/char/agp/uninorth-agp.c
drivers/char/random.c
drivers/clk/ti/dpll3xxx.c
drivers/clocksource/Kconfig
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/arm_global_timer.c
drivers/clocksource/exynos_mct.c
drivers/clocksource/rockchip_timer.c
drivers/clocksource/time-lpc32xx.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/amd_freq_sensitivity.c
drivers/cpufreq/cpufreq-dt.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_ondemand.c
drivers/cpufreq/cpufreq_ondemand.h [new file with mode: 0644]
drivers/cpufreq/cpufreq_performance.c
drivers/cpufreq/cpufreq_powersave.c
drivers/cpufreq/cpufreq_userspace.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/mt8173-cpufreq.c
drivers/cpufreq/powernv-cpufreq.c
drivers/cpuidle/governors/menu.c
drivers/devfreq/tegra-devfreq.c
drivers/dma/at_xdmac.c
drivers/dma/fsldma.c
drivers/dma/iop-adma.c
drivers/dma/mv_xor.c
drivers/dma/pxa_dma.c
drivers/dma/qcom_bam_dma.c
drivers/edac/Kconfig
drivers/edac/Makefile
drivers/edac/altera_edac.c
drivers/edac/amd64_edac.c
drivers/edac/debugfs.c
drivers/edac/edac_mc.c
drivers/edac/edac_pci.c
drivers/edac/mce_amd.c
drivers/edac/mpc85xx_edac.c
drivers/edac/sb_edac.c
drivers/edac/xgene_edac.c
drivers/firmware/iscsi_ibft.c
drivers/gpio/gpio-rcar.c
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
drivers/gpu/drm/amd/amdgpu/atombios_dp.c
drivers/gpu/drm/amd/amdgpu/cz_dpm.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/bochs/bochs_drv.c
drivers/gpu/drm/cirrus/cirrus_drv.c
drivers/gpu/drm/drm_gem_cma_helper.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
drivers/gpu/drm/i2c/tda998x_drv.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_csr.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/imx/ipuv3-crtc.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/nouveau/nouveau_platform.c
drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/omapdrm/omap_gem.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/sti/sti_cursor.c
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sti/sti_hqvdp.c
drivers/gpu/drm/tegra/gem.c
drivers/gpu/drm/vc4/vc4_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/host1x/bus.c
drivers/gpu/host1x/cdma.c
drivers/gpu/host1x/dev.c
drivers/gpu/host1x/dev.h
drivers/gpu/host1x/job.c
drivers/gpu/ipu-v3/ipu-common.c
drivers/hv/hyperv_vmbus.h
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/iio_hwmon.c
drivers/hwmon/ltc2990.c [new file with mode: 0644]
drivers/hwmon/nsa320-hwmon.c [new file with mode: 0644]
drivers/hwmon/ntc_thermistor.c
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/pmbus/adm1275.c
drivers/hwmon/vexpress-hwmon.c [new file with mode: 0644]
drivers/hwmon/vexpress.c [deleted file]
drivers/i2c/busses/i2c-brcmstb.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/ide/pdc202xx_new.c
drivers/ide/pmac.c
drivers/infiniband/core/device.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/hw/mlx5/srq.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/dmar.c
drivers/iommu/intel-iommu.c
drivers/irqchip/Kconfig
drivers/irqchip/Makefile
drivers/irqchip/irq-alpine-msi.c [new file with mode: 0644]
drivers/irqchip/irq-armada-370-xp.c
drivers/irqchip/irq-ath79-cpu.c [new file with mode: 0644]
drivers/irqchip/irq-ath79-misc.c [new file with mode: 0644]
drivers/irqchip/irq-atmel-aic-common.c
drivers/irqchip/irq-atmel-aic-common.h
drivers/irqchip/irq-atmel-aic.c
drivers/irqchip/irq-atmel-aic5.c
drivers/irqchip/irq-bcm2836.c
drivers/irqchip/irq-bcm6345-l1.c [new file with mode: 0644]
drivers/irqchip/irq-gic-realview.c
drivers/irqchip/irq-gic-v2m.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-mips-gic.c
drivers/irqchip/irq-mvebu-odmi.c [new file with mode: 0644]
drivers/irqchip/irq-mxs.c
drivers/irqchip/irq-sunxi-nmi.c
drivers/irqchip/irq-tango.c [new file with mode: 0644]
drivers/irqchip/irq-ts4800.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/led-class.c
drivers/leds/led-core.c
drivers/leds/led-triggers.c
drivers/leds/leds-88pm860x.c
drivers/leds/leds-da903x.c
drivers/leds/leds-gpio.c
drivers/leds/leds-is31fl32xx.c [new file with mode: 0644]
drivers/leds/leds-lm3533.c
drivers/leds/leds-lp3944.c
drivers/leds/leds-lp8788.c
drivers/leds/leds-max8997.c
drivers/leds/leds-s3c24xx.c
drivers/leds/leds-wm831x-status.c
drivers/macintosh/macio_asic.c
drivers/mailbox/pcc.c
drivers/media/i2c/adp1653.c
drivers/media/i2c/adv7604.c
drivers/media/media-device.c
drivers/media/platform/coda/coda-bit.c
drivers/media/usb/au0828/au0828-video.c
drivers/mfd/max77686.c
drivers/misc/cxl/pci.c
drivers/misc/lkdtm.c
drivers/mtd/tests/mtd_nandecctest.c
drivers/mtd/ubi/upd.c
drivers/net/can/spi/mcp251x.c
drivers/net/can/usb/gs_usb.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/altera/altera_tse_main.c
drivers/net/ethernet/aurora/nb8800.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/brocade/bna/bna_tx_rx.c
drivers/net/ethernet/cavium/thunder/nic.h
drivers/net/ethernet/cavium/thunder/nic_main.c
drivers/net/ethernet/cavium/thunder/nic_reg.h
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/freescale/fman/fman.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/hisilicon/Kconfig
drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/e1000e/defines.h
drivers/net/ethernet/intel/e1000e/ptp.c
drivers/net/ethernet/intel/e1000e/regs.h
drivers/net/ethernet/jme.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/port.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/moxa/moxart_ether.c
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/synopsys/dwc_eth_qos.c
drivers/net/ethernet/toshiba/spider_net.c
drivers/net/phy/micrel.c
drivers/net/ppp/ppp_generic.c
drivers/net/usb/ax88172a.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/nvdimm/bus.c
drivers/nvdimm/e820.c
drivers/nvdimm/pmem.c
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/of/of_mdio.c
drivers/of/of_pci.c
drivers/parisc/Kconfig
drivers/parisc/eisa_enumerator.c
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/access.c
drivers/pci/bus.c
drivers/pci/host/Kconfig
drivers/pci/host/Makefile
drivers/pci/host/pci-dra7xx.c
drivers/pci/host/pci-exynos.c
drivers/pci/host/pci-host-common.c [new file with mode: 0644]
drivers/pci/host/pci-host-common.h [new file with mode: 0644]
drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-hyperv.c [new file with mode: 0644]
drivers/pci/host/pci-imx6.c
drivers/pci/host/pci-keystone-dw.c
drivers/pci/host/pci-keystone.c
drivers/pci/host/pci-layerscape.c
drivers/pci/host/pci-tegra.c
drivers/pci/host/pci-thunder-ecam.c [new file with mode: 0644]
drivers/pci/host/pci-thunder-pem.c [new file with mode: 0644]
drivers/pci/host/pcie-altera.c
drivers/pci/host/pcie-designware-plat.c [new file with mode: 0644]
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-designware.h
drivers/pci/host/pcie-qcom.c
drivers/pci/host/pcie-rcar.c
drivers/pci/host/pcie-spear13xx.c
drivers/pci/host/pcie-xilinx-nwl.c [new file with mode: 0644]
drivers/pci/host/pcie-xilinx.c
drivers/pci/hotplug/s390_pci_hpc.c
drivers/pci/iov.c
drivers/pci/pci-label.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/Kconfig
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/pcie/pme.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/rom.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/bcm/pinctrl-bcm2835.c
drivers/pinctrl/core.c
drivers/pinctrl/core.h
drivers/pinctrl/freescale/pinctrl-imx.c
drivers/pinctrl/freescale/pinctrl-imx.h
drivers/pinctrl/freescale/pinctrl-imx50.c
drivers/pinctrl/freescale/pinctrl-imx53.c
drivers/pinctrl/freescale/pinctrl-imx6dl.c
drivers/pinctrl/freescale/pinctrl-imx6q.c
drivers/pinctrl/freescale/pinctrl-imx6sl.c
drivers/pinctrl/freescale/pinctrl-imx6sx.c
drivers/pinctrl/freescale/pinctrl-imx6ul.c
drivers/pinctrl/freescale/pinctrl-imx7d.c
drivers/pinctrl/intel/pinctrl-intel.c
drivers/pinctrl/mediatek/Kconfig
drivers/pinctrl/mediatek/Makefile
drivers/pinctrl/mediatek/pinctrl-mt2701.c [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mt6397.c
drivers/pinctrl/mediatek/pinctrl-mt7623.c [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mt8127.c
drivers/pinctrl/mediatek/pinctrl-mt8135.c
drivers/pinctrl/mediatek/pinctrl-mt8173.c
drivers/pinctrl/mediatek/pinctrl-mtk-common.c
drivers/pinctrl/mediatek/pinctrl-mtk-common.h
drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h [new file with mode: 0644]
drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h [new file with mode: 0644]
drivers/pinctrl/meson/pinctrl-meson.c
drivers/pinctrl/meson/pinctrl-meson.h
drivers/pinctrl/meson/pinctrl-meson8.c
drivers/pinctrl/meson/pinctrl-meson8b.c
drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-at91-pio4.c
drivers/pinctrl/pinctrl-coh901.c
drivers/pinctrl/pinctrl-lpc18xx.c
drivers/pinctrl/pinctrl-pic32.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-pic32.h [new file with mode: 0644]
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/pinctrl-st.c
drivers/pinctrl/pinctrl-tegra-xusb.c [deleted file]
drivers/pinctrl/pinctrl-tegra.c [deleted file]
drivers/pinctrl/pinctrl-tegra.h [deleted file]
drivers/pinctrl/pinctrl-tegra114.c [deleted file]
drivers/pinctrl/pinctrl-tegra124.c [deleted file]
drivers/pinctrl/pinctrl-tegra20.c [deleted file]
drivers/pinctrl/pinctrl-tegra210.c [deleted file]
drivers/pinctrl/pinctrl-tegra30.c [deleted file]
drivers/pinctrl/pinctrl-zynq.c
drivers/pinctrl/pxa/pinctrl-pxa2xx.c
drivers/pinctrl/qcom/Kconfig
drivers/pinctrl/qcom/Makefile
drivers/pinctrl/qcom/pinctrl-ipq4019.c [new file with mode: 0644]
drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
drivers/pinctrl/sh-pfc/Kconfig
drivers/pinctrl/sh-pfc/Makefile
drivers/pinctrl/sh-pfc/core.c
drivers/pinctrl/sh-pfc/pfc-r8a7778.c
drivers/pinctrl/sh-pfc/pfc-r8a7779.c
drivers/pinctrl/sh-pfc/pfc-r8a7790.c
drivers/pinctrl/sh-pfc/pfc-r8a7791.c
drivers/pinctrl/sh-pfc/pfc-r8a7794.c
drivers/pinctrl/sh-pfc/pfc-r8a7795.c
drivers/pinctrl/sh-pfc/pfc-sh7734.c
drivers/pinctrl/sh-pfc/sh_pfc.h
drivers/pinctrl/stm32/Kconfig [new file with mode: 0644]
drivers/pinctrl/stm32/Makefile [new file with mode: 0644]
drivers/pinctrl/stm32/pinctrl-stm32.c [new file with mode: 0644]
drivers/pinctrl/stm32/pinctrl-stm32.h [new file with mode: 0644]
drivers/pinctrl/stm32/pinctrl-stm32f429.c [new file with mode: 0644]
drivers/pinctrl/sunxi/Kconfig
drivers/pinctrl/sunxi/Makefile
drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c [new file with mode: 0644]
drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c
drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c [new file with mode: 0644]
drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/pinctrl/tegra/Kconfig [new file with mode: 0644]
drivers/pinctrl/tegra/Makefile [new file with mode: 0644]
drivers/pinctrl/tegra/pinctrl-tegra-xusb.c [new file with mode: 0644]
drivers/pinctrl/tegra/pinctrl-tegra.c [new file with mode: 0644]
drivers/pinctrl/tegra/pinctrl-tegra.h [new file with mode: 0644]
drivers/pinctrl/tegra/pinctrl-tegra114.c [new file with mode: 0644]
drivers/pinctrl/tegra/pinctrl-tegra124.c [new file with mode: 0644]
drivers/pinctrl/tegra/pinctrl-tegra20.c [new file with mode: 0644]
drivers/pinctrl/tegra/pinctrl-tegra210.c [new file with mode: 0644]
drivers/pinctrl/tegra/pinctrl-tegra30.c [new file with mode: 0644]
drivers/pinctrl/uniphier/Kconfig
drivers/pinctrl/uniphier/Makefile
drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c [deleted file]
drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c [deleted file]
drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c [deleted file]
drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c [deleted file]
drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c [deleted file]
drivers/pinctrl/uniphier/pinctrl-proxstream2.c [deleted file]
drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c [new file with mode: 0644]
drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c [new file with mode: 0644]
drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c [new file with mode: 0644]
drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c [new file with mode: 0644]
drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c [new file with mode: 0644]
drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c [new file with mode: 0644]
drivers/pnp/pnpacpi/rsparser.c
drivers/power/bq27xxx_battery_i2c.c
drivers/powercap/intel_rapl.c
drivers/ptp/ptp_chardev.c
drivers/rapidio/rio.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/act8865-regulator.c
drivers/regulator/act8945a-regulator.c [new file with mode: 0644]
drivers/regulator/ad5398.c
drivers/regulator/axp20x-regulator.c
drivers/regulator/core.c
drivers/regulator/da9210-regulator.c
drivers/regulator/fan53555.c
drivers/regulator/gpio-regulator.c
drivers/regulator/helpers.c
drivers/regulator/hi655x-regulator.c [new file with mode: 0644]
drivers/regulator/lp872x.c
drivers/regulator/ltc3589.c
drivers/regulator/max77620-regulator.c [new file with mode: 0644]
drivers/regulator/max77686-regulator.c [new file with mode: 0644]
drivers/regulator/max77686.c [deleted file]
drivers/regulator/max77802-regulator.c [new file with mode: 0644]
drivers/regulator/max77802.c [deleted file]
drivers/regulator/mt6397-regulator.c
drivers/regulator/of_regulator.c
drivers/regulator/pv88060-regulator.c
drivers/regulator/pv88090-regulator.c
drivers/regulator/pwm-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/regulator/vexpress-regulator.c [new file with mode: 0644]
drivers/regulator/vexpress.c [deleted file]
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/class.c
drivers/rtc/interface.c
drivers/rtc/rtc-as3722.c
drivers/rtc/rtc-asm9260.c [new file with mode: 0644]
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1685.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-ds3234.c [deleted file]
drivers/rtc/rtc-generic.c
drivers/rtc/rtc-hym8563.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-max77802.c [deleted file]
drivers/rtc/rtc-mt6397.c
drivers/rtc/rtc-palmas.c
drivers/rtc/rtc-pcf2123.c
drivers/rtc/rtc-pcf2127.c
drivers/rtc/rtc-pcf85063.c
drivers/rtc/rtc-pcf8523.c
drivers/rtc/rtc-pic32.c [new file with mode: 0644]
drivers/rtc/rtc-rv3029c2.c
drivers/rtc/rtc-rv8803.c
drivers/rtc/rtc-rx6110.c [new file with mode: 0644]
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-s5m.c
drivers/rtc/rtc-sysfs.c
drivers/rtc/rtc-tps6586x.c
drivers/rtc/rtc-tps65910.c
drivers/rtc/rtc-tps80031.c
drivers/rtc/rtc-vr41xx.c
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/dasd_proc.c
drivers/s390/block/dcssblk.c
drivers/s390/char/monreader.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/sclp_cpi_sys.c
drivers/s390/char/tape_core.c
drivers/s390/char/vmlogrdr.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/ccwreq.c
drivers/s390/cio/cio.c
drivers/s390/cio/device.c
drivers/s390/net/lcs.c
drivers/s390/net/qeth_l3_main.c
drivers/scsi/iscsi_boot_sysfs.c
drivers/scsi/mac53c94.c
drivers/scsi/mesh.c
drivers/sh/pm_runtime.c
drivers/sh/superhyway/superhyway.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-axi-spi-engine.c [new file with mode: 0644]
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm2835aux.c
drivers/spi/spi-dw-mid.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-imx.c
drivers/spi/spi-lp8841-rtc.c [new file with mode: 0644]
drivers/spi/spi-pl022.c
drivers/spi/spi-pxa2xx-dma.c
drivers/spi/spi-pxa2xx-pci.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-pxa2xx.h
drivers/spi/spi-rockchip.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi.c
drivers/ssb/Kconfig
drivers/staging/media/davinci_vpfe/vpfe_video.c
drivers/target/target_core_tmr.c
drivers/usb/chipidea/ci_hdrc_pci.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/otg.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hub.c
drivers/usb/dwc2/Kconfig
drivers/usb/dwc2/core.c
drivers/usb/dwc2/hcd_ddma.c
drivers/usb/dwc2/hcd_intr.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/udc/amd5536udc.c
drivers/usb/gadget/udc/fsl_qe_udc.c
drivers/usb/gadget/udc/goku_udc.c
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/net2280.h
drivers/usb/gadget/udc/pch_udc.c
drivers/usb/gadget/udc/udc-core.c
drivers/usb/musb/musb_host.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/cp210x.c
drivers/usb/serial/mxu11x0.c [deleted file]
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/vfio/pci/vfio_pci.c
drivers/vfio/platform/vfio_platform_common.c
drivers/vfio/vfio_iommu_type1.c
drivers/vhost/vhost.c
drivers/video/console/fbcon.c
drivers/video/fbdev/acornfb.c
drivers/video/fbdev/amba-clcd-versatile.c
drivers/video/fbdev/amba-clcd.c
drivers/video/fbdev/atmel_lcdfb.c
drivers/video/fbdev/aty/aty128fb.c
drivers/video/fbdev/aty/radeon_base.c
drivers/video/fbdev/ep93xx-fb.c
drivers/video/fbdev/gbefb.c
drivers/video/fbdev/imsttfb.c
drivers/video/fbdev/imxfb.c
drivers/video/fbdev/matrox/matroxfb_base.h
drivers/video/fbdev/mx3fb.c
drivers/video/fbdev/nuc900fb.c
drivers/video/fbdev/offb.c
drivers/video/fbdev/omap/lcdc.c
drivers/video/fbdev/pxa168fb.c
drivers/video/fbdev/pxafb.c
drivers/video/fbdev/s3c-fb.c
drivers/video/fbdev/s3c2410fb.c
drivers/video/fbdev/sa1100fb.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_pci_modern.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/sun4v_wdt.c [new file with mode: 0644]
drivers/xen/Kconfig
drivers/xen/balloon.c
drivers/xen/events/events_2l.c
drivers/zorro/zorro-sysfs.c
fs/affs/file.c
fs/autofs4/autofs_i.h
fs/autofs4/dev-ioctl.c
fs/autofs4/expire.c
fs/autofs4/init.c
fs/autofs4/inode.c
fs/autofs4/root.c
fs/autofs4/symlink.c
fs/autofs4/waitq.c
fs/binfmt_elf.c
fs/block_dev.c
fs/btrfs/disk-io.c
fs/btrfs/root-tree.c
fs/buffer.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/super.h
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifssmb.c
fs/cifs/smb2pdu.c
fs/dax.c
fs/dcache.c
fs/ext2/file.c
fs/ext2/inode.c
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/move_extent.c
fs/fs-writeback.c
fs/hpfs/namei.c
fs/jffs2/README.Locking
fs/jffs2/build.c
fs/jffs2/dir.c
fs/jffs2/file.c
fs/jffs2/gc.c
fs/jffs2/nodelist.h
fs/mpage.c
fs/namei.c
fs/ncpfs/dir.c
fs/ocfs2/aops.c
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/dlm/dlmcommon.h
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/dlmthread.c
fs/ocfs2/mmap.c
fs/ocfs2/super.c
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/overlayfs/super.c
fs/pnode.c
fs/read_write.c
fs/super.c
fs/userfaultfd.c
fs/xattr.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_aops.h
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_log_recover.c
include/acpi/acoutput.h
include/acpi/acpixf.h
include/acpi/processor.h
include/asm-generic/pci-bridge.h [deleted file]
include/asm-generic/pci-dma-compat.h [deleted file]
include/asm-generic/qspinlock.h
include/asm-generic/qspinlock_types.h
include/asm-generic/vmlinux.lds.h
include/dt-bindings/pinctrl/mt7623-pinfunc.h [new file with mode: 0644]
include/kvm/arm_arch_timer.h
include/kvm/arm_pmu.h [new file with mode: 0644]
include/kvm/arm_vgic.h
include/linux/ata.h
include/linux/atomic.h
include/linux/auto_dev-ioctl.h
include/linux/auto_fs.h
include/linux/bio.h
include/linux/blkdev.h
include/linux/cache.h
include/linux/ceph/ceph_features.h
include/linux/clockchips.h
include/linux/clocksource.h
include/linux/compiler.h
include/linux/cpu.h
include/linux/cpufreq.h
include/linux/cpuhotplug.h [new file with mode: 0644]
include/linux/dax.h
include/linux/dcache.h
include/linux/dma-mapping.h
include/linux/fault-inject.h
include/linux/ftrace.h
include/linux/gfp.h
include/linux/init.h
include/linux/interrupt.h
include/linux/ioport.h
include/linux/irq.h
include/linux/irqchip/mips-gic.h
include/linux/irqdomain.h
include/linux/iscsi_boot_sysfs.h
include/linux/kasan.h
include/linux/kvm_host.h
include/linux/latencytop.h
include/linux/leds.h
include/linux/libata.h
include/linux/libnvdimm.h
include/linux/list.h
include/linux/lockdep.h
include/linux/memcontrol.h
include/linux/memory.h
include/linux/memory_hotplug.h
include/linux/mfd/max77686-private.h
include/linux/migrate.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmdebug.h
include/linux/mmzone.h
include/linux/notifier.h
include/linux/page_ext.h
include/linux/page_owner.h
include/linux/pagemap.h
include/linux/pci-dma-compat.h [new file with mode: 0644]
include/linux/pci.h
include/linux/pci_ids.h
include/linux/perf_event.h
include/linux/platform_data/ntc_thermistor.h
include/linux/pm_domain.h
include/linux/pm_opp.h
include/linux/poison.h
include/linux/posix-timers.h
include/linux/power/bq27xxx_battery.h
include/linux/pps_kernel.h
include/linux/ptp_clock_kernel.h
include/linux/pxa2xx_ssp.h
include/linux/random.h
include/linux/rcupdate.h
include/linux/regmap.h
include/linux/regulator/act8865.h
include/linux/regulator/driver.h
include/linux/regulator/lp872x.h
include/linux/regulator/machine.h
include/linux/rtc.h
include/linux/sched.h
include/linux/sched/sysctl.h
include/linux/skbuff.h
include/linux/slab.h
include/linux/slab_def.h
include/linux/slub_def.h
include/linux/spi/spi.h
include/linux/srcu.h
include/linux/stmmac.h
include/linux/swait.h [new file with mode: 0644]
include/linux/tick.h
include/linux/timekeeper_internal.h
include/linux/timekeeping.h
include/linux/trace_events.h
include/linux/tracepoint-defs.h
include/linux/tracepoint.h
include/linux/wait.h
include/linux/writeback.h
include/net/iw_handler.h
include/sound/hdaudio.h
include/trace/events/asoc.h
include/trace/events/btrfs.h
include/trace/events/compaction.h
include/trace/events/cpuhp.h [new file with mode: 0644]
include/trace/events/gfpflags.h [deleted file]
include/trace/events/huge_memory.h
include/trace/events/kmem.h
include/trace/events/kvm.h
include/trace/events/mmflags.h [new file with mode: 0644]
include/trace/events/power.h
include/trace/events/timer.h
include/trace/events/vmscan.h
include/uapi/linux/auto_fs.h
include/uapi/linux/auto_fs4.h
include/uapi/linux/bpf.h
include/uapi/linux/kvm.h
include/uapi/linux/media.h
include/uapi/linux/ndctl.h
include/uapi/linux/ptp_clock.h
init/Kconfig
init/main.c
kernel/cpu.c
kernel/debug/kdb/kdb_bp.c
kernel/events/core.c
kernel/events/uprobes.c
kernel/futex.c
kernel/irq/Kconfig
kernel/irq/Makefile
kernel/irq/chip.c
kernel/irq/handle.c
kernel/irq/internals.h
kernel/irq/ipi.c [new file with mode: 0644]
kernel/irq/irqdesc.c
kernel/irq/irqdomain.c
kernel/irq/manage.c
kernel/irq/proc.c
kernel/irq/spurious.c
kernel/kallsyms.c
kernel/kexec_core.c
kernel/kexec_file.c
kernel/latencytop.c
kernel/locking/lockdep.c
kernel/locking/mcs_spinlock.h
kernel/locking/mutex.c
kernel/locking/qspinlock.c
kernel/locking/qspinlock_paravirt.h
kernel/locking/qspinlock_stat.h
kernel/memremap.c
kernel/power/hibernate.c
kernel/power/process.c
kernel/power/suspend.c
kernel/profile.c
kernel/rcu/rcutorture.c
kernel/rcu/tiny_plugin.h
kernel/rcu/tree.c
kernel/rcu/tree.h
kernel/rcu/tree_plugin.h
kernel/rcu/update.c
kernel/resource.c
kernel/sched/Makefile
kernel/sched/clock.c
kernel/sched/core.c
kernel/sched/cpufreq.c [new file with mode: 0644]
kernel/sched/cputime.c
kernel/sched/deadline.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/sched/stats.h
kernel/sched/swait.c [new file with mode: 0644]
kernel/smp.c
kernel/smpboot.c
kernel/smpboot.h
kernel/softirq.c
kernel/sysctl.c
kernel/time/clocksource.c
kernel/time/jiffies.c
kernel/time/posix-cpu-timers.c
kernel/time/tick-sched.c
kernel/time/tick-sched.h
kernel/time/timekeeping.c
kernel/trace/power-traces.c
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_syscalls.c
kernel/tsacct.c
kernel/workqueue.c
lib/Kconfig.debug
lib/atomic64_test.c
lib/cpumask.c
lib/list_debug.c
lib/test_printf.c
lib/test_static_keys.c
lib/vsprintf.c
mm/Kconfig.debug
mm/Makefile
mm/compaction.c
mm/debug-pagealloc.c [deleted file]
mm/debug.c
mm/failslab.c
mm/filemap.c
mm/huge_memory.c
mm/hugetlb.c
mm/internal.h
mm/kasan/kasan.c
mm/kmemcheck.c
mm/madvise.c
mm/memblock.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mempool.c
mm/migrate.c
mm/mmap.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_ext.c
mm/page_owner.c
mm/page_poison.c [new file with mode: 0644]
mm/rmap.c
mm/shmem.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slub.c
mm/truncate.c
mm/vmscan.c
mm/vmstat.c
mm/workingset.c
net/bridge/br_fdb.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/filter.c
net/core/rtnetlink.c
net/core/skbuff.c
net/ipv4/igmp.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/syncookies.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_minisocks.c
net/ipv4/udp_tunnel.c
net/ipv6/exthdrs_core.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/mcast.c
net/ipv6/syncookies.c
net/ipv6/udp.c
net/mac80211/agg-rx.c
net/mac80211/ieee80211_i.h
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/rds/page.c
net/sched/act_ipt.c
net/sctp/ipv6.c
net/sctp/proc.c
net/sunrpc/cache.c
net/switchdev/switchdev.c
net/tipc/socket.c
net/tipc/subscr.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/sme.c
net/wireless/wext-core.c
scripts/checkpatch.pl
scripts/kallsyms.c
scripts/ld-version.sh
scripts/link-vmlinux.sh
scripts/namespace.pl
scripts/sortextable.c
security/selinux/hooks.c
sound/arm/pxa2xx-pcm-lib.c
sound/core/control_compat.c
sound/core/pcm_compat.c
sound/core/rawmidi_compat.c
sound/core/seq/oss/seq_oss.c
sound/core/seq/oss/seq_oss_device.h
sound/core/seq/oss/seq_oss_init.c
sound/core/timer_compat.c
sound/hda/hdac_controller.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/intel8x0.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/ppc/pmac.c
sound/soc/codecs/ab8500-codec.c
sound/soc/codecs/adau17x1.h
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/da732x.c
sound/soc/codecs/max98088.c
sound/soc/codecs/max98095.c
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/wl1273.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8983.c
sound/soc/codecs/wm8985.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/intel/boards/cht_bsw_rt5645.c
sound/soc/intel/boards/mfld_machine.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/n810.c
sound/soc/omap/omap-pcm.c
sound/soc/omap/rx51.c
sound/soc/pxa/corgi.c
sound/soc/pxa/magician.c
sound/soc/pxa/poodle.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tosa.c
sound/soc/qcom/lpass-cpu.c
sound/soc/samsung/i2s.c
sound/soc/soc-dapm.c
sound/usb/quirks.c
tools/build/Makefile.build
tools/build/Makefile.feature
tools/build/feature/Makefile
tools/build/feature/test-all.c
tools/build/feature/test-compile.c
tools/build/feature/test-libcrypto.c [new file with mode: 0644]
tools/lib/api/Build
tools/lib/api/Makefile
tools/lib/api/debug-internal.h [new file with mode: 0644]
tools/lib/api/debug.c [new file with mode: 0644]
tools/lib/api/debug.h [new file with mode: 0644]
tools/lib/api/fs/fs.c
tools/lib/api/fs/fs.h
tools/lib/bpf/libbpf.c
tools/lib/lockdep/Makefile
tools/lib/lockdep/common.c
tools/lib/lockdep/include/liblockdep/common.h
tools/lib/lockdep/lockdep.c
tools/lib/lockdep/preload.c
tools/lib/lockdep/tests/AA.c
tools/lib/lockdep/tests/ABA.c [new file with mode: 0644]
tools/lib/lockdep/tests/ABBA_2threads.c [new file with mode: 0644]
tools/lib/lockdep/uinclude/linux/compiler.h
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/perf/Documentation/perf-config.txt
tools/perf/Documentation/perf-inject.txt
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf-stat.txt
tools/perf/Documentation/perf-top.txt
tools/perf/Documentation/perfconfig.example
tools/perf/Documentation/tips.txt
tools/perf/Makefile
tools/perf/Makefile.perf
tools/perf/arch/arm/Makefile
tools/perf/arch/arm64/Makefile
tools/perf/arch/powerpc/Makefile
tools/perf/arch/powerpc/util/Build
tools/perf/arch/powerpc/util/book3s_hcalls.h [new file with mode: 0644]
tools/perf/arch/powerpc/util/book3s_hv_exits.h [new file with mode: 0644]
tools/perf/arch/powerpc/util/kvm-stat.c [new file with mode: 0644]
tools/perf/arch/s390/util/kvm-stat.c
tools/perf/arch/x86/Makefile
tools/perf/arch/x86/tests/rdpmc.c
tools/perf/arch/x86/util/intel-bts.c
tools/perf/arch/x86/util/intel-pt.c
tools/perf/arch/x86/util/kvm-stat.c
tools/perf/bench/mem-memcpy-x86-64-asm.S
tools/perf/builtin-annotate.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-config.c
tools/perf/builtin-diff.c
tools/perf/builtin-help.c
tools/perf/builtin-inject.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kvm.c
tools/perf/builtin-mem.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/config/Makefile
tools/perf/jvmti/Makefile [new file with mode: 0644]
tools/perf/jvmti/jvmti_agent.c [new file with mode: 0644]
tools/perf/jvmti/jvmti_agent.h [new file with mode: 0644]
tools/perf/jvmti/libjvmti.c [new file with mode: 0644]
tools/perf/perf.c
tools/perf/perf.h
tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
tools/perf/tests/.gitignore
tools/perf/tests/Build
tools/perf/tests/bp_signal.c
tools/perf/tests/bpf-script-test-relocation.c [new file with mode: 0644]
tools/perf/tests/bpf.c
tools/perf/tests/code-reading.c
tools/perf/tests/hists_cumulate.c
tools/perf/tests/hists_filter.c
tools/perf/tests/hists_output.c
tools/perf/tests/llvm.c
tools/perf/tests/llvm.h
tools/perf/tests/make
tools/perf/tests/parse-events.c
tools/perf/tests/vmlinux-kallsyms.c
tools/perf/ui/browser.c
tools/perf/ui/browser.h
tools/perf/ui/browsers/annotate.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/hists.c
tools/perf/ui/hist.c
tools/perf/ui/stdio/hist.c
tools/perf/util/Build
tools/perf/util/auxtrace.c
tools/perf/util/auxtrace.h
tools/perf/util/bpf-loader.c
tools/perf/util/bpf-loader.h
tools/perf/util/build-id.c
tools/perf/util/build-id.h
tools/perf/util/cache.h
tools/perf/util/callchain.c
tools/perf/util/color.c
tools/perf/util/config.c
tools/perf/util/cpumap.c
tools/perf/util/cpumap.h
tools/perf/util/ctype.c
tools/perf/util/data-convert-bt.c
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/demangle-java.c [new file with mode: 0644]
tools/perf/util/demangle-java.h [new file with mode: 0644]
tools/perf/util/dso.c
tools/perf/util/env.c
tools/perf/util/env.h
tools/perf/util/event.c
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/genelf.c [new file with mode: 0644]
tools/perf/util/genelf.h [new file with mode: 0644]
tools/perf/util/genelf_debug.c [new file with mode: 0644]
tools/perf/util/header.c
tools/perf/util/header.h
tools/perf/util/help-unknown-cmd.c
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/jit.h [new file with mode: 0644]
tools/perf/util/jitdump.c [new file with mode: 0644]
tools/perf/util/jitdump.h [new file with mode: 0644]
tools/perf/util/kvm-stat.h
tools/perf/util/machine.h
tools/perf/util/mem-events.c [new file with mode: 0644]
tools/perf/util/mem-events.h [new file with mode: 0644]
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.l
tools/perf/util/parse-events.y
tools/perf/util/pmu.c
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/setup.py
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/stat-shadow.c
tools/perf/util/stat.c
tools/perf/util/stat.h
tools/perf/util/strbuf.c
tools/perf/util/strbuf.h
tools/perf/util/symbol-elf.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/trace-event.c
tools/perf/util/tsc.c
tools/perf/util/util.c
tools/perf/util/util.h
tools/power/x86/turbostat/turbostat.8
tools/power/x86/turbostat/turbostat.c
tools/testing/nvdimm/test/nfit.c
tools/testing/selftests/rcutorture/bin/parse-console.sh
tools/testing/selftests/x86/Makefile
tools/testing/selftests/x86/check_initial_reg_state.c [new file with mode: 0644]
tools/testing/selftests/x86/ptrace_syscall.c
tools/testing/selftests/x86/sigreturn.c
tools/testing/selftests/x86/syscall_nt.c
tools/vm/slabinfo.c
virt/kvm/arm/arch_timer.c
virt/kvm/arm/hyp/timer-sr.c [new file with mode: 0644]
virt/kvm/arm/hyp/vgic-v2-sr.c [new file with mode: 0644]
virt/kvm/arm/pmu.c [new file with mode: 0644]
virt/kvm/arm/vgic-v2-emul.c
virt/kvm/arm/vgic-v2.c
virt/kvm/arm/vgic-v3.c
virt/kvm/arm/vgic.c
virt/kvm/async_pf.c
virt/kvm/kvm_main.c

index 1af3842509105ea45fd815ad953781d901b03bfe..0ee0f3386cdf3c7881e88546c03e5347c3e5e721 100644 (file)
            <entry><constant>MEDIA_ENT_F_CONN_COMPOSITE</constant></entry>
            <entry>Connector for a RGB composite signal.</entry>
          </row>
-         <row>
-           <entry><constant>MEDIA_ENT_F_CONN_TEST</constant></entry>
-           <entry>Connector for a test generator.</entry>
-         </row>
          <row>
            <entry><constant>MEDIA_ENT_F_CAM_SENSOR</constant></entry>
            <entry>Camera video sensor entity.</entry>
index f7b12c071d5356ceed76231a07b4e49f59e9f8d8..e6bd1e6512a54baaf9e3634bbadbd24c5e29f1ea 100644 (file)
@@ -25,7 +25,7 @@ callback, so cpufreq core can't request a transition to a specific frequency.
 The driver provides minimum and maximum frequency limits and callbacks to set a
 policy. The policy in cpufreq sysfs is referred to as the "scaling governor".
 The cpufreq core can request the driver to operate in any of the two policies:
-"performance: and "powersave". The driver decides which frequency to use based
+"performance" and "powersave". The driver decides which frequency to use based
 on the above policy selection considering minimum and maximum frequency limits.
 
 The Intel P-State driver falls under the latter category, which implements the
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt
new file mode 100644 (file)
index 0000000..885f93d
--- /dev/null
@@ -0,0 +1,49 @@
+Altera SoCFPGA ECC Manager
+This driver uses the EDAC framework to implement the SOCFPGA ECC Manager.
+The ECC Manager counts and corrects single bit errors and counts/handles
+double bit errors which are uncorrectable.
+
+Required Properties:
+- compatible : Should be "altr,socfpga-ecc-manager"
+- #address-cells: must be 1
+- #size-cells: must be 1
+- ranges : standard definition, should translate from local addresses
+
+Subcomponents:
+
+L2 Cache ECC
+Required Properties:
+- compatible : Should be "altr,socfpga-l2-ecc"
+- reg : Address and size for ECC error interrupt clear registers.
+- interrupts : Should be single bit error interrupt, then double bit error
+       interrupt. Note the rising edge type.
+
+On Chip RAM ECC
+Required Properties:
+- compatible : Should be "altr,socfpga-ocram-ecc"
+- reg : Address and size for ECC error interrupt clear registers.
+- iram : phandle to On-Chip RAM definition.
+- interrupts : Should be single bit error interrupt, then double bit error
+       interrupt. Note the rising edge type.
+
+Example:
+
+       eccmgr: eccmgr@ffd08140 {
+               compatible = "altr,socfpga-ecc-manager";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               l2-ecc@ffd08140 {
+                       compatible = "altr,socfpga-l2-ecc";
+                       reg = <0xffd08140 0x4>;
+                       interrupts = <0 36 1>, <0 37 1>;
+               };
+
+               ocram-ecc@ffd08144 {
+                       compatible = "altr,socfpga-ocram-ecc";
+                       reg = <0xffd08144 0x4>;
+                       iram = <&ocram>;
+                       interrupts = <0 178 1>, <0 179 1>;
+               };
+       };
index a2bd593881cab361fa739d9a12e63ee7ba63ef50..66422d6631841d9e6eba9be63e453176ebd43f2e 100644 (file)
@@ -23,6 +23,7 @@ Optional properties:
   during suspend.
 - ti,no-reset-on-init: When present, the module should not be reset at init
 - ti,no-idle-on-init: When present, the module should not be idled at init
+- ti,no-idle: When present, the module is never allowed to idle.
 
 Example:
 
index 78e2a31c58d0735b40254e592e1fa7c73983d571..1006b04894642685a984081121c4b9229181a55c 100644 (file)
@@ -16,6 +16,10 @@ Required properties:
 - regmap-mcba          : Regmap of the MCB-A (memory bridge) resource.
 - regmap-mcbb          : Regmap of the MCB-B (memory bridge) resource.
 - regmap-efuse         : Regmap of the PMD efuse resource.
+- regmap-rb            : Regmap of the register bus resource. This property
+                         is optional only for compatibility. If the RB
+                         error conditions are not cleared, it will
+                         continuously generate interrupt.
 - reg                  : First resource shall be the CPU bus (PCP) resource.
 - interrupts            : Interrupt-specifier for MCU, PMD, L3, or SoC error
                          IRQ(s).
@@ -64,6 +68,11 @@ Example:
                reg = <0x0 0x1054a000 0x0 0x20>;
        };
 
+       rb: rb@7e000000 {
+               compatible = "apm,xgene-rb", "syscon";
+               reg = <0x0 0x7e000000 0x0 0x10>;
+       };
+
        edac@78800000 {
                compatible = "apm,xgene-edac";
                #address-cells = <2>;
@@ -73,6 +82,7 @@ Example:
                regmap-mcba = <&mcba>;
                regmap-mcbb = <&mcbb>;
                regmap-efuse = <&efuse>;
+               regmap-rb = <&rb>;
                reg = <0x0 0x78800000 0x0 0x100>;
                interrupts = <0x0 0x20 0x4>,
                             <0x0 0x21 0x4>,
diff --git a/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt b/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt
new file mode 100644 (file)
index 0000000..ef37528
--- /dev/null
@@ -0,0 +1,49 @@
+* Microchip PIC32 GPIO devices (PIO).
+
+Required properties:
+ - compatible: "microchip,pic32mzda-gpio"
+ - reg: Base address and length for the device.
+ - interrupts: The port interrupt shared by all pins.
+ - gpio-controller: Marks the port as GPIO controller.
+ - #gpio-cells: Two. The first cell is the pin number and
+   the second cell is used to specify the gpio polarity as defined in
+   defined in <dt-bindings/gpio/gpio.h>:
+      0 = GPIO_ACTIVE_HIGH
+      1 = GPIO_ACTIVE_LOW
+      2 = GPIO_OPEN_DRAIN
+ - interrupt-controller: Marks the device node as an interrupt controller.
+ - #interrupt-cells: Two. The first cell is the GPIO number and second cell
+   is used to specify the trigger type as defined in
+   <dt-bindings/interrupt-controller/irq.h>:
+      IRQ_TYPE_EDGE_RISING
+      IRQ_TYPE_EDGE_FALLING
+      IRQ_TYPE_EDGE_BOTH
+ - clocks: Clock specifier (see clock bindings for details).
+ - microchip,gpio-bank: Specifies which bank a controller owns.
+ - gpio-ranges: Interaction with the PINCTRL subsystem.
+
+Example:
+
+/* PORTA */
+gpio0: gpio0@1f860000 {
+       compatible = "microchip,pic32mzda-gpio";
+       reg = <0x1f860000 0x100>;
+       interrupts = <118 IRQ_TYPE_LEVEL_HIGH>;
+       #gpio-cells = <2>;
+       gpio-controller;
+       interrupt-controller;
+       #interrupt-cells = <2>;
+       clocks = <&PBCLK4>;
+       microchip,gpio-bank = <0>;
+       gpio-ranges = <&pic32_pinctrl 0 0 16>;
+};
+
+keys {
+       ...
+
+       button@sw1 {
+               label = "ESC";
+               linux,code = <1>;
+               gpios = <&gpio0 12 0>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/hwmon/nsa320-mcu.txt b/Documentation/devicetree/bindings/hwmon/nsa320-mcu.txt
new file mode 100644 (file)
index 0000000..0863e06
--- /dev/null
@@ -0,0 +1,20 @@
+Bindings for the fan / temperature monitor microcontroller used on
+the Zyxel NSA 320 and several subsequent models.
+
+Required properties:
+- compatible   : "zyxel,nsa320-mcu"
+- data-gpios   : The GPIO pin connected to the data line on the MCU
+- clk-gpios    : The GPIO pin connected to the clock line on the MCU
+- act-gpios    : The GPIO pin connected to the active line on the MCU
+
+Example:
+
+       hwmon {
+               compatible = "zyxel,nsa320-mcu";
+               pinctrl-0 = <&pmx_mcu_data &pmx_mcu_clk &pmx_mcu_act>;
+               pinctrl-names = "default";
+
+               data-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+               clk-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+               act-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
+       };
index a04a80f9cc706030677f398736b990665490525b..c3b9c4cfe8dfe32962642e36cbe4ec625190f8d5 100644 (file)
@@ -10,6 +10,7 @@ Requires node properties:
        "murata,ncp03wb473"
        "murata,ncp15wl333"
        "murata,ncp03wf104"
+       "murata,ncp15xh103"
 
 /* Usage of vendor name "ntc" is deprecated */
 <DEPRECATED>   "ntc,ncp15wb473"
index 0b447d9ad196652eb367fe12718fd9eae3fdf4ea..68d6f8ce063b87ca41496d387f58916916e004ae 100644 (file)
@@ -82,7 +82,7 @@ vdd channel is connected to output 0 of the &ref device.
 
        ...
 
-       iio_hwmon {
+       iio-hwmon {
                compatible = "iio-hwmon";
                io-channels = <&adc 0>, <&adc 1>, <&adc 2>,
                        <&adc 3>, <&adc 4>, <&adc 5>,
diff --git a/Documentation/devicetree/bindings/interrupt-controller/al,alpine-msix.txt b/Documentation/devicetree/bindings/interrupt-controller/al,alpine-msix.txt
new file mode 100644 (file)
index 0000000..f6f1c14
--- /dev/null
@@ -0,0 +1,26 @@
+Alpine MSIX controller
+
+See arm,gic-v3.txt for SPI and MSI definitions.
+
+Required properties:
+
+- compatible: should be "al,alpine-msix"
+- reg: physical base address and size of the registers
+- interrupt-parent: specifies the parent interrupt controller.
+- interrupt-controller: identifies the node as an interrupt controller
+- msi-controller: identifies the node as an PCI Message Signaled Interrupt
+                 controller
+- al,msi-base-spi: SPI base of the MSI frame
+- al,msi-num-spis: number of SPIs assigned to the MSI frame, relative to SPI0
+
+Example:
+
+msix: msix {
+       compatible = "al,alpine-msix";
+       reg = <0x0 0xfbe00000 0x0 0x100000>;
+       interrupt-parent = <&gic>;
+       interrupt-controller;
+       msi-controller;
+       al,msi-base-spi = <160>;
+       al,msi-num-spis = <160>;
+};
index 5a1cb4bc3dfe84c67664c65eeb2a64ac4a92c1ff..793c20ff8fcccdfb9200b78c6447133c11af5742 100644 (file)
@@ -16,6 +16,7 @@ Main node required properties:
        "arm,cortex-a15-gic"
        "arm,cortex-a7-gic"
        "arm,cortex-a9-gic"
+       "arm,eb11mp-gic"
        "arm,gic-400"
        "arm,pl390"
        "arm,tc11mp-gic"
diff --git a/Documentation/devicetree/bindings/interrupt-controller/marvell,odmi-controller.txt b/Documentation/devicetree/bindings/interrupt-controller/marvell,odmi-controller.txt
new file mode 100644 (file)
index 0000000..8af0a8e
--- /dev/null
@@ -0,0 +1,44 @@
+
+* Marvell ODMI for MSI support
+
+Some Marvell SoCs have an On-Die Message Interrupt (ODMI) controller
+which can be used by on-board peripheral for MSI interrupts.
+
+Required properties:
+
+- compatible           : The value here should contain:
+
+    "marvell,ap806-odmi-controller", "marvell,odmi-controller".
+
+- interrupt,controller : Identifies the node as an interrupt controller.
+
+- msi-controller       : Identifies the node as an MSI controller.
+
+- marvell,odmi-frames  : Number of ODMI frames available. Each frame
+                         provides a number of events.
+
+- reg                  : List of register definitions, one for each
+                         ODMI frame.
+
+- marvell,spi-base     : List of GIC base SPI interrupts, one for each
+                         ODMI frame. Those SPI interrupts are 0-based,
+                         i.e marvell,spi-base = <128> will use SPI #96.
+                         See Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+                         for details about the GIC Device Tree binding.
+
+- interrupt-parent     : Reference to the parent interrupt controller.
+
+Example:
+
+       odmi: odmi@300000 {
+               compatible = "marvell,ap806-odm-controller",
+                            "marvell,odmi-controller";
+               interrupt-controller;
+               msi-controller;
+               marvell,odmi-frames = <4>;
+               reg = <0x300000 0x4000>,
+                     <0x304000 0x4000>,
+                     <0x308000 0x4000>,
+                     <0x30C000 0x4000>;
+               marvell,spi-base = <128>, <136>, <144>, <152>;
+       };
index aae4c384ee1f2047836876ef8e1ff609e3a5770e..173595305e2667e4098b8e977b2a603782f406a8 100644 (file)
@@ -23,6 +23,12 @@ Optional properties:
 - mti,reserved-cpu-vectors : Specifies the list of CPU interrupt vectors
   to which the GIC may not route interrupts.  Valid values are 2 - 7.
   This property is ignored if the CPU is started in EIC mode.
+- mti,reserved-ipi-vectors : Specifies the range of GIC interrupts that are
+  reserved for IPIs.
+  It accepts 2 values, the 1st is the starting interrupt and the 2nd is the size
+  of the reserved range.
+  If not specified, the driver will allocate the last 2 * number of VPEs in the
+  system.
 
 Required properties for timer sub-node:
 - compatible : Should be "mti,gic-timer".
@@ -44,6 +50,7 @@ Example:
                #interrupt-cells = <3>;
 
                mti,reserved-cpu-vectors = <7>;
+               mti,reserved-ipi-vectors = <40 8>;
 
                timer {
                        compatible = "mti,gic-timer";
diff --git a/Documentation/devicetree/bindings/interrupt-controller/sigma,smp8642-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/sigma,smp8642-intc.txt
new file mode 100644 (file)
index 0000000..1f441fa
--- /dev/null
@@ -0,0 +1,49 @@
+Sigma Designs SMP86xx/SMP87xx secondary interrupt controller
+
+Required properties:
+- compatible: should be "sigma,smp8642-intc"
+- reg: physical address of MMIO region
+- ranges: address space mapping of child nodes
+- interrupt-parent: phandle of parent interrupt controller
+- interrupt-controller: boolean
+- #address-cells: should be <1>
+- #size-cells: should be <1>
+
+One child node per control block with properties:
+- reg: address of registers for this control block
+- interrupt-controller: boolean
+- #interrupt-cells: should be <2>, interrupt index and flags per interrupts.txt
+- interrupts: interrupt spec of primary interrupt controller
+
+Example:
+
+interrupt-controller@6e000 {
+       compatible = "sigma,smp8642-intc";
+       reg = <0x6e000 0x400>;
+       ranges = <0x0 0x6e000 0x400>;
+       interrupt-parent = <&gic>;
+       interrupt-controller;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       irq0: interrupt-controller@0 {
+               reg = <0x000 0x100>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       irq1: interrupt-controller@100 {
+               reg = <0x100 0x100>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       irq2: interrupt-controller@300 {
+               reg = <0x300 0x100>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/leds/leds-is31fl32xx.txt b/Documentation/devicetree/bindings/leds/leds-is31fl32xx.txt
new file mode 100644 (file)
index 0000000..926c211
--- /dev/null
@@ -0,0 +1,52 @@
+Binding for ISSI IS31FL32xx and Si-En SN32xx LED Drivers
+
+The IS31FL32xx/SN32xx family of LED drivers are I2C devices with multiple
+constant-current channels, each with independent 256-level PWM control.
+Each LED is represented as a sub-node of the device.
+
+Required properties:
+- compatible: one of
+       issi,is31fl3236
+       issi,is31fl3235
+       issi,is31fl3218
+       issi,is31fl3216
+       si-en,sn3218
+       si-en,sn3216
+- reg: I2C slave address
+- address-cells : must be 1
+- size-cells : must be 0
+
+LED sub-node properties:
+- reg : LED channel number (1..N)
+- label :  (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
+- linux,default-trigger :  (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
+
+
+Example:
+
+is31fl3236: led-controller@3c {
+       compatible = "issi,is31fl3236";
+       reg = <0x3c>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       led@1 {
+               reg = <1>;
+               label = "EB:blue:usr0";
+       };
+       led@2 {
+               reg = <2>;
+               label = "EB:blue:usr1";
+       };
+       ...
+       led@36 {
+               reg = <36>;
+               label = "EB:blue:usr35";
+       };
+};
+
+For more product information please see the links below:
+http://www.issi.com/US/product-analog-fxled-driver.shtml
+http://www.si-en.com/product.asp?parentid=890
index 5b0853df9d5a4c0da73e8bdf07e115d08fd8b28b..64f2fff121288cb0560a6186b6cddce6ecc33978 100644 (file)
@@ -28,3 +28,20 @@ Optional properties:
 - clock-names: Must include the following entries:
        - "pcie"
        - "pcie_bus"
+
+Example configuration:
+
+       pcie: pcie@0xdffff000 {
+               compatible = "snps,dw-pcie";
+               reg = <0xdffff000 0x1000>, /* Controller registers */
+                     <0xd0000000 0x2000>; /* PCI config space */
+               reg-names = "ctrlreg", "config";
+               #address-cells = <3>;
+               #size-cells = <2>;
+               device_type = "pci";
+               ranges = <0x81000000 0 0x00000000 0xde000000 0 0x00010000
+                         0x82000000 0 0xd0400000 0xd0400000 0 0x0d000000>;
+               interrupts = <25>, <24>;
+               #interrupt-cells = <1>;
+               num-lanes = <1>;
+       };
index 6fbba53a309b79da6aef780a35f58eedfe4ad019..3be80c68941a7aa1e19172e23d287b8c4bddd327 100644 (file)
@@ -13,6 +13,13 @@ Required properties:
 - clock-names: Must include the following additional entries:
        - "pcie_phy"
 
+Optional properties:
+- fsl,tx-deemph-gen1: Gen1 De-emphasis value. Default: 0
+- fsl,tx-deemph-gen2-3p5db: Gen2 (3.5db) De-emphasis value. Default: 0
+- fsl,tx-deemph-gen2-6db: Gen2 (6db) De-emphasis value. Default: 20
+- fsl,tx-swing-full: Gen2 TX SWING FULL value. Default: 127
+- fsl,tx-swing-low: TX launch amplitude swing_low value. Default: 127
+
 Example:
 
        pcie@0x01000000 {
diff --git a/Documentation/devicetree/bindings/pci/pci-thunder-ecam.txt b/Documentation/devicetree/bindings/pci/pci-thunder-ecam.txt
new file mode 100644 (file)
index 0000000..f478874
--- /dev/null
@@ -0,0 +1,30 @@
+* ThunderX PCI host controller for pass-1.x silicon
+
+Firmware-initialized PCI host controller to on-chip devices found on
+some Cavium ThunderX processors.  These devices have ECAM-based config
+access, but the BARs are all at fixed addresses.  We handle the fixed
+addresses by synthesizing Enhanced Allocation (EA) capabilities for
+these devices.
+
+The properties and their meanings are identical to those described in
+host-generic-pci.txt except as listed below.
+
+Properties of the host controller node that differ from
+host-generic-pci.txt:
+
+- compatible     : Must be "cavium,pci-host-thunder-ecam"
+
+Example:
+
+       pcie@84b000000000 {
+               compatible = "cavium,pci-host-thunder-ecam";
+               device_type = "pci";
+               msi-parent = <&its>;
+               msi-map = <0 &its 0x30000 0x10000>;
+               bus-range = <0 31>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               #stream-id-cells = <1>;
+               reg = <0x84b0 0x00000000 0 0x02000000>;  /* Configuration space */
+               ranges = <0x03000000 0x8180 0x00000000 0x8180 0x00000000 0x80 0x00000000>; /* mem ranges */
+       };
diff --git a/Documentation/devicetree/bindings/pci/pci-thunder-pem.txt b/Documentation/devicetree/bindings/pci/pci-thunder-pem.txt
new file mode 100644 (file)
index 0000000..f131fae
--- /dev/null
@@ -0,0 +1,43 @@
+* ThunderX PEM PCIe host controller
+
+Firmware-initialized PCI host controller found on some Cavium
+ThunderX processors.
+
+The properties and their meanings are identical to those described in
+host-generic-pci.txt except as listed below.
+
+Properties of the host controller node that differ from
+host-generic-pci.txt:
+
+- compatible     : Must be "cavium,pci-host-thunder-pem"
+
+- reg            : Two entries: First the configuration space for down
+                   stream devices base address and size, as accessed
+                   from the parent bus. Second, the register bank of
+                   the PEM device PCIe bridge.
+
+Example:
+
+    pci@87e0,c2000000 {
+       compatible = "cavium,pci-host-thunder-pem";
+       device_type = "pci";
+       msi-parent = <&its>;
+       msi-map = <0 &its 0x10000 0x10000>;
+       bus-range = <0x8f 0xc7>;
+       #size-cells = <2>;
+       #address-cells = <3>;
+
+       reg = <0x8880 0x8f000000 0x0 0x39000000>,  /* Configuration space */
+             <0x87e0 0xc2000000 0x0 0x00010000>; /* PEM space */
+       ranges = <0x01000000 0x00 0x00020000 0x88b0 0x00020000 0x00 0x00010000>, /* I/O */
+                <0x03000000 0x00 0x10000000 0x8890 0x10000000 0x0f 0xf0000000>, /* mem64 */
+                <0x43000000 0x10 0x00000000 0x88a0 0x00000000 0x10 0x00000000>, /* mem64-pref */
+                <0x03000000 0x87e0 0xc2f00000 0x87e0 0xc2000000 0x00 0x00100000>; /* mem64 PEM BAR4 */
+
+       #interrupt-cells = <1>;
+       interrupt-map-mask = <0 0 0 7>;
+       interrupt-map = <0 0 0 1 &gic0 0 0 0 24 4>, /* INTA */
+                       <0 0 0 2 &gic0 0 0 0 25 4>, /* INTB */
+                       <0 0 0 3 &gic0 0 0 0 26 4>, /* INTC */
+                       <0 0 0 4 &gic0 0 0 0 27 4>; /* INTD */
+    };
diff --git a/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt b/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
new file mode 100644 (file)
index 0000000..337fc97
--- /dev/null
@@ -0,0 +1,68 @@
+* Xilinx NWL PCIe Root Port Bridge DT description
+
+Required properties:
+- compatible: Should contain "xlnx,nwl-pcie-2.11"
+- #address-cells: Address representation for root ports, set to <3>
+- #size-cells: Size representation for root ports, set to <2>
+- #interrupt-cells: specifies the number of cells needed to encode an
+       interrupt source. The value must be 1.
+- reg: Should contain Bridge, PCIe Controller registers location,
+       configuration space, and length
+- reg-names: Must include the following entries:
+       "breg": bridge registers
+       "pcireg": PCIe controller registers
+       "cfg": configuration space region
+- device_type: must be "pci"
+- interrupts: Should contain NWL PCIe interrupt
+- interrupt-names: Must include the following entries:
+       "msi1, msi0": interrupt asserted when MSI is received
+       "intx": interrupt asserted when a legacy interrupt is received
+       "misc": interrupt asserted when miscellaneous is received
+- interrupt-map-mask and interrupt-map: standard PCI properties to define the
+       mapping of the PCI interface to interrupt numbers.
+- ranges: ranges for the PCI memory regions (I/O space region is not
+       supported by hardware)
+       Please refer to the standard PCI bus binding document for a more
+       detailed explanation
+- msi-controller: indicates that this is MSI controller node
+- msi-parent:  MSI parent of the root complex itself
+- legacy-interrupt-controller: Interrupt controller device node for Legacy interrupts
+       - interrupt-controller: identifies the node as an interrupt controller
+       - #interrupt-cells: should be set to 1
+       - #address-cells: specifies the number of cells needed to encode an
+               address. The value must be 0.
+
+
+Example:
+++++++++
+
+nwl_pcie: pcie@fd0e0000 {
+       #address-cells = <3>;
+       #size-cells = <2>;
+       compatible = "xlnx,nwl-pcie-2.11";
+       #interrupt-cells = <1>;
+       msi-controller;
+       device_type = "pci";
+       interrupt-parent = <&gic>;
+       interrupts = <0 114 4>, <0 115 4>, <0 116 4>, <0 117 4>, <0 118 4>;
+       interrupt-names = "msi0", "msi1", "intx", "dummy", "misc";
+       interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+       interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc 0x1>,
+                       <0x0 0x0 0x0 0x2 &pcie_intc 0x2>,
+                       <0x0 0x0 0x0 0x3 &pcie_intc 0x3>,
+                       <0x0 0x0 0x0 0x4 &pcie_intc 0x4>;
+
+       msi-parent = <&nwl_pcie>;
+       reg = <0x0 0xfd0e0000 0x0 0x1000>,
+             <0x0 0xfd480000 0x0 0x1000>,
+             <0x0 0xe0000000 0x0 0x1000000>;
+       reg-names = "breg", "pcireg", "cfg";
+       ranges = <0x02000000 0x00000000 0xe1000000 0x00000000 0xe1000000 0 0x0f000000>;
+
+       pcie_intc: legacy-interrupt-controller {
+               interrupt-controller;
+               #address-cells = <0>;
+               #interrupt-cells = <1>;
+       };
+
+};
index 02f979a48aeb2a40f3942f6669b464508c4faafe..fd57a81180a4759be7fcbfb4bf23ea3f2985bde7 100644 (file)
@@ -17,7 +17,7 @@ Required properties:
        Please refer to the standard PCI bus binding document for a more
        detailed explanation
 
-Optional properties:
+Optional properties for Zynq/Microblaze:
 - bus-range: PCI bus numbers covered
 
 Interrupt controller child node
@@ -38,13 +38,13 @@ the four INTx interrupts in ISR and route them to this domain.
 
 Example:
 ++++++++
-
+Zynq:
        pci_express: axi-pcie@50000000 {
                #address-cells = <3>;
                #size-cells = <2>;
                #interrupt-cells = <1>;
                compatible = "xlnx,axi-pcie-host-1.00.a";
-               reg = < 0x50000000 0x10000000 >;
+               reg = < 0x50000000 0x1000000 >;
                device_type = "pci";
                interrupts = < 0 52 4 >;
                interrupt-map-mask = <0 0 0 7>;
@@ -60,3 +60,29 @@ Example:
                        #interrupt-cells = <1>;
                };
        };
+
+
+Microblaze:
+       pci_express: axi-pcie@10000000 {
+               #address-cells = <3>;
+               #size-cells = <2>;
+               #interrupt-cells = <1>;
+               compatible = "xlnx,axi-pcie-host-1.00.a";
+               reg = <0x10000000 0x4000000>;
+               device_type = "pci";
+               interrupt-parent = <&microblaze_0_intc>;
+               interrupts = <1 2>;
+               interrupt-map-mask = <0 0 0 7>;
+               interrupt-map = <0 0 0 1 &pcie_intc 1>,
+                               <0 0 0 2 &pcie_intc 2>,
+                               <0 0 0 3 &pcie_intc 3>,
+                               <0 0 0 4 &pcie_intc 4>;
+               ranges = <0x02000000 0x00000000 0x80000000 0x80000000 0x00000000 0x10000000>;
+
+               pcie_intc: interrupt-controller {
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <1>;
+               };
+
+       };
index 9213b27e1036666f98fa077fb05e066b793fca0e..69617220c5d6b582c16bc12df96a6d70f6d3a81e 100644 (file)
@@ -21,6 +21,8 @@ Required properties:
   "allwinner,sun9i-a80-r-pinctrl"
   "allwinner,sun8i-a83t-pinctrl"
   "allwinner,sun8i-h3-pinctrl"
+  "allwinner,sun8i-h3-r-pinctrl"
+  "allwinner,sun50i-a64-pinctrl"
 
 - reg: Should contain the register physical address and length for the
   pin controller.
diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/brcm,ns2-pinmux.txt
new file mode 100644 (file)
index 0000000..e295dda
--- /dev/null
@@ -0,0 +1,102 @@
+Broadcom Northstar2 IOMUX Controller
+
+The Northstar2 IOMUX controller supports group based mux configuration. There
+are some individual pins that support modifying the pinconf parameters.
+
+Required properties:
+
+- compatible:
+    Must be "brcm,ns2-pinmux"
+
+- reg:
+    Define the base and range of the I/O address space that contains the
+    Northstar2 IOMUX and pin configuration registers.
+
+Properties in sub nodes:
+
+- function:
+    The mux function to select
+
+- groups:
+    The list of groups to select with a given function
+
+- pins:
+    List of pin names to change configuration
+
+The generic properties bias-disable, bias-pull-down, bias-pull-up,
+drive-strength, slew-rate, input-enable, input-disable are supported
+for some individual pins listed at the end.
+
+For more details, refer to
+Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+
+For example:
+
+       pinctrl: pinctrl@6501d130 {
+               compatible = "brcm,ns2-pinmux";
+               reg = <0x6501d130 0x08>,
+                     <0x660a0028 0x04>,
+                     <0x660009b0 0x40>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&nand_sel &uart3_rx &sdio0_d4>;
+
+               /* Select nand function */
+               nand_sel: nand_sel {
+                       function = "nand";
+                       groups = "nand_grp";
+               };
+
+               /* Pull up the uart3 rx pin */
+               uart3_rx: uart3_rx {
+                       pins = "uart3_sin";
+                       bias-pull-up;
+               };
+
+               /* Set the drive strength of sdio d4 pin */
+               sdio0_d4: sdio0_d4 {
+                       pins = "sdio0_data4";
+                       drive-strength = <8>;
+               };
+       };
+
+List of supported functions and groups in Northstar2:
+
+"nand": "nand_grp"
+
+"nor": "nor_data_grp", "nor_adv_grp", "nor_addr_0_3_grp", "nor_addr_4_5_grp",
+       "nor_addr_6_7_grp", "nor_addr_8_9_grp", "nor_addr_10_11_grp",
+       "nor_addr_12_15_grp"
+
+"gpio": "gpio_0_1_grp", "gpio_2_5_grp", "gpio_6_7_grp", "gpio_8_9_grp",
+       "gpio_10_11_grp", "gpio_12_13_grp", "gpio_14_17_grp", "gpio_18_19_grp",
+       "gpio_20_21_grp", "gpio_22_23_grp", "gpio_24_25_grp", "gpio_26_27_grp",
+       "gpio_28_29_grp", "gpio_30_31_grp"
+
+"pcie": "pcie_ab1_clk_wak_grp", "pcie_a3_clk_wak_grp", "pcie_b3_clk_wak_grp",
+       "pcie_b2_clk_wak_grp", "pcie_a2_clk_wak_grp"
+
+"uart0": "uart0_modem_grp", "uart0_rts_cts_grp", "uart0_in_out_grp"
+
+"uart1": "uart1_ext_clk_grp", "uart1_dcd_dsr_grp", "uart1_ri_dtr_grp",
+       "uart1_rts_cts_grp", "uart1_in_out_grp"
+
+"uart2": "uart2_rts_cts_grp"
+
+"pwm": "pwm_0_grp", "pwm_1_grp", "pwm_2_grp", "pwm_3_grp"
+
+
+List of pins that support pinconf parameters:
+
+"qspi_wp", "qspi_hold", "qspi_cs", "qspi_sck", "uart3_sin", "uart3_sout",
+"qspi_mosi", "qspi_miso", "spi0_fss", "spi0_rxd", "spi0_txd", "spi0_sck",
+"spi1_fss", "spi1_rxd", "spi1_txd", "spi1_sck", "sdio0_data7",
+"sdio0_emmc_rst", "sdio0_led_on", "sdio0_wp", "sdio0_data3", "sdio0_data4",
+"sdio0_data5", "sdio0_data6", "sdio0_cmd", "sdio0_data0", "sdio0_data1",
+"sdio0_data2", "sdio1_led_on", "sdio1_wp", "sdio0_cd_l", "sdio0_clk",
+"sdio1_data5", "sdio1_data6", "sdio1_data7", "sdio1_emmc_rst", "sdio1_data1",
+"sdio1_data2", "sdio1_data3", "sdio1_data4", "sdio1_cd_l", "sdio1_clk",
+"sdio1_cmd", "sdio1_data0", "ext_mdio_0", "ext_mdc_0", "usb3_p1_vbus_ppc",
+"usb3_p1_overcurrent", "usb3_p0_vbus_ppc", "usb3_p0_overcurrent",
+"usb2_presence_indication", "usb2_vbus_present", "usb2_vbus_ppc",
+"usb2_overcurrent", "sata_led1", "sata_led0"
diff --git a/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt
new file mode 100644 (file)
index 0000000..4b5efa5
--- /dev/null
@@ -0,0 +1,60 @@
+* Microchip PIC32 Pin Controller
+
+Please refer to pinctrl-bindings.txt, ../gpio/gpio.txt, and
+../interrupt-controller/interrupts.txt for generic information regarding
+pin controller, GPIO, and interrupt bindings.
+
+PIC32 'pin configuration node' is a node of a group of pins which can be
+used for a specific device or function. This node represents configuraions of
+pins, optional function, and optional mux related configuration.
+
+Required properties for pin controller node:
+ - compatible: "microchip,pic32mada-pinctrl"
+ - reg: Address range of the pinctrl registers.
+ - clocks: Clock specifier (see clock bindings for details)
+
+Required properties for pin configuration sub-nodes:
+ - pins: List of pins to which the configuration applies.
+
+Optional properties for pin configuration sub-nodes:
+----------------------------------------------------
+ - function: Mux function for the specified pins.
+ - bias-pull-up: Enable weak pull-up.
+ - bias-pull-down: Enable weak pull-down.
+ - input-enable: Set the pin as an input.
+ - output-low: Set the pin as an output level low.
+ - output-high: Set the pin as an output level high.
+ - microchip,digital: Enable digital I/O.
+ - microchip,analog: Enable analog I/O.
+
+Example:
+
+pic32_pinctrl: pinctrl@1f801400{
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "microchip,pic32mzda-pinctrl";
+       reg = <0x1f801400 0x400>;
+       clocks = <&PBCLK1>;
+
+       pinctrl_uart2: pinctrl_uart2 {
+               uart2-tx {
+                       pins = "G9";
+                       function = "U2TX";
+                       microchip,digital;
+                       output-low;
+               };
+               uart2-rx {
+                       pins = "B0";
+                       function = "U2RX";
+                       microchip,digital;
+                       input-enable;
+               };
+       };
+};
+
+uart2: serial@1f822200 {
+       compatible = "microchip,pic32mzda-uart";
+       reg = <0x1f822200 0x50>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+};
index df0309c5750563fd6febf8edded1487336ee1108..bd8b0c69fa447b056221814d1c0a25375d18620b 100644 (file)
@@ -22,6 +22,10 @@ The following generic nodes are supported:
  - input-schmitt-disable
  - slew-rate
 
+NXP specific properties:
+ - nxp,gpio-pin-interrupt : Assign pin to gpio pin interrupt controller
+                           irq number 0 to 7. See example below.
+
 Not all pins support all properties so either refer to the NXP 1850/4350
 user manual or the pin table in the pinctrl-lpc18xx driver for supported
 pin properties.
@@ -54,4 +58,14 @@ pinctrl: pinctrl@40086000 {
                        bias-disable;
                };
        };
+
+       gpio_joystick_pins: gpio-joystick-pins {
+               gpio_joystick_1_cfg {
+                       pins =  "p9_0";
+                       function = "gpio";
+                       nxp,gpio-pin-interrupt = <0>;
+                       input-enable;
+                       bias-disable;
+               };
+       };
 };
index 9ffb0b276bb4864eab7a41368d754f035d4ab56b..17631d0a9af7bd01fe316b06f9caae6815f7d70f 100644 (file)
@@ -6,6 +6,7 @@ Required properties:
 - compatible: value should be one of the following.
        "mediatek,mt2701-pinctrl", compatible with mt2701 pinctrl.
        "mediatek,mt6397-pinctrl", compatible with mt6397 pinctrl.
+       "mediatek,mt7623-pinctrl", compatible with mt7623 pinctrl.
        "mediatek,mt8127-pinctrl", compatible with mt8127 pinctrl.
        "mediatek,mt8135-pinctrl", compatible with mt8135 pinctrl.
        "mediatek,mt8173-pinctrl", compatible with mt8173 pinctrl.
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq4019-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,ipq4019-pinctrl.txt
new file mode 100644 (file)
index 0000000..cfb8500
--- /dev/null
@@ -0,0 +1,74 @@
+Qualcomm Atheros IPQ4019 TLMM block
+
+This is the Top Level Mode Multiplexor block found on the Qualcomm IPQ8019
+platform, it provides pinctrl, pinmux, pinconf, and gpiolib facilities.
+
+Required properties:
+- compatible: "qcom,ipq4019-pinctrl"
+- reg: Should be the base address and length of the TLMM block.
+- interrupts: Should be the parent IRQ of the TLMM block.
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells: Should be two.
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells : Should be two.
+                The first cell is the gpio pin number and the
+                second cell is used for optional parameters.
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an abitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+ pins, function, bias-disable, bias-pull-down, bias-pull,up, drive-strength.
+
+Non-empty subnodes must specify the 'pins' property.
+Note that not all properties are valid for all pins.
+
+
+Valid values for qcom,pins are:
+  gpio0-gpio99
+    Supports mux, bias and drive-strength
+
+Valid values for qcom,function are:
+gpio, blsp_uart1, blsp_i2c0, blsp_i2c1, blsp_uart0, blsp_spi1, blsp_spi0
+
+Example:
+
+       tlmm: pinctrl@1000000 {
+               compatible = "qcom,ipq4019-pinctrl";
+               reg = <0x1000000 0x300000>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               interrupts = <0 208 0>;
+
+               serial_pins: serial_pinmux {
+                       mux {
+                               pins = "gpio60", "gpio61";
+                               function = "blsp_uart0";
+                               bias-disable;
+                       };
+               };
+       };
index 0cd701b1947fdc35bc8ec036cac82b053f237712..c68b9554561f07e47ddebaa2a5f4c068313f6193 100644 (file)
@@ -22,7 +22,7 @@ Required properties for iomux controller:
   - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
                       "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
                       "rockchip,rk3228-pinctrl", "rockchip,rk3288-pinctrl"
-                      "rockchip,rk3368-pinctrl"
+                      "rockchip,rk3368-pinctrl", "rockchip,rk3399-pinctrl"
   - rockchip,grf: phandle referencing a syscon providing the
         "general register files"
 
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
new file mode 100644 (file)
index 0000000..7b4800c
--- /dev/null
@@ -0,0 +1,126 @@
+* STM32 GPIO and Pin Mux/Config controller
+
+STMicroelectronics's STM32 MCUs intregrate a GPIO and Pin mux/config hardware
+controller. It controls the input/output settings on the available pins and
+also provides ability to multiplex and configure the output of various on-chip
+controllers onto these pads.
+
+Pin controller node:
+Required properies:
+ - compatible: value should be one of the following:
+   (a) "st,stm32f429-pinctrl"
+ - #address-cells: The value of this property must be 1
+ - #size-cells : The value of this property must be 1
+ - ranges      : defines mapping between pin controller node (parent) to
+   gpio-bank node (children).
+ - pins-are-numbered: Specify the subnodes are using numbered pinmux to
+   specify pins.
+
+GPIO controller/bank node:
+Required properties:
+ - gpio-controller : Indicates this device is a GPIO controller
+ - #gpio-cells   : Should be two.
+                       The first cell is the pin number
+                       The second one is the polarity:
+                               - 0 for active high
+                               - 1 for active low
+ - reg           : The gpio address range, relative to the pinctrl range
+ - clocks        : clock that drives this bank
+ - st,bank-name          : Should be a name string for this bank as specified in
+   the datasheet
+
+Optional properties:
+ - reset:        : Reference to the reset controller
+
+Example:
+#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
+...
+
+       pin-controller {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "st,stm32f429-pinctrl";
+               ranges = <0 0x40020000 0x3000>;
+               pins-are-numbered;
+
+               gpioa: gpio@40020000 {
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       reg = <0x0 0x400>;
+                       resets = <&reset_ahb1 0>;
+                       st,bank-name = "GPIOA";
+               };
+               ...
+               pin-functions nodes follow...
+       };
+
+Contents of function subnode node:
+----------------------------------
+Subnode format
+A pinctrl node should contain at least one subnode representing the
+pinctrl group available on the machine. Each subnode will list the
+pins it needs, and how they should be configured, with regard to muxer
+configuration, pullups, drive, output high/low and output speed.
+
+    node {
+       pinmux = <PIN_NUMBER_PINMUX>;
+       GENERIC_PINCONFIG;
+    };
+
+Required properties:
+- pinmux: integer array, represents gpio pin number and mux setting.
+  Supported pin number and mux varies for different SoCs, and are defined in
+  dt-bindings/pinctrl/<soc>-pinfunc.h directly.
+  These defines are calculated as:
+    ((port * 16 + line) << 8) | function
+  With:
+    - port: The gpio port index (PA = 0, PB = 1, ..., PK = 11)
+    - line: The line offset within the port (PA0 = 0, PA1 = 1, ..., PA15 = 15)
+    - function: The function number, can be:
+      * 0 : GPIO
+      * 1 : Alternate Function 0
+      * 2 : Alternate Function 1
+      * 3 : Alternate Function 2
+      * ...
+      * 16 : Alternate Function 15
+      * 17 : Analog
+
+Optional properties:
+- GENERIC_PINCONFIG: is the generic pinconfig options to use.
+  Available options are:
+   - bias-disable,
+   - bias-pull-down,
+   - bias-pull-up,
+   - drive-push-pull,
+   - drive-open-drain,
+   - output-low
+   - output-high
+   - slew-rate = <x>, with x being:
+       < 0 > : Low speed
+       < 1 > : Medium speed
+       < 2 > : Fast speed
+       < 3 > : High speed
+
+Example:
+
+pin-controller {
+...
+       usart1_pins_a: usart1@0 {
+               pins1 {
+                       pinmux = <STM32F429_PA9_FUNC_USART1_TX>;
+                       bias-disable;
+                       drive-push-pull;
+                       slew-rate = <0>;
+               };
+               pins2 {
+                       pinmux = <STM32F429_PA10_FUNC_USART1_RX>;
+                       bias-disable;
+               };
+       };
+};
+
+&usart1 {
+       pinctrl-0 = <&usart1_pins_a>;
+       pinctrl-names = "default";
+       status = "okay";
+};
index b494f8b8ef72d8869756c7b18181649e41ef8164..e98a9652ccc8c4d3a2263fe5a67b9064b27d1f04 100644 (file)
@@ -5,15 +5,18 @@ Index     Device     Endianness properties
 ---------------------------------------------------
 1         BE         'big-endian'
 2         LE         'little-endian'
+3        Native     'native-endian'
 
 For one device driver, which will run in different scenarios above
 on different SoCs using the devicetree, we need one way to simplify
 this.
 
-Required properties:
-- {big,little}-endian: these are boolean properties, if absent
-  meaning that the CPU and the Device are in the same endianness mode,
-  these properties are for register values and all the buffers only.
+Optional properties:
+- {big,little,native}-endian: these are boolean properties, if absent
+  then the implementation will choose a default based on the device
+  being controlled.  These properties are for register values and all
+  the buffers only.  Native endian means that the CPU and device have
+  the same endianness.
 
 Examples:
 Scenario 1 : CPU in LE mode & device in LE mode.
diff --git a/Documentation/devicetree/bindings/regulator/act8945a-regulator.txt b/Documentation/devicetree/bindings/regulator/act8945a-regulator.txt
new file mode 100644 (file)
index 0000000..5c80a77
--- /dev/null
@@ -0,0 +1,80 @@
+Device-Tree bindings for regulators of Active-semi ACT8945A Multi-Function Device
+
+Required properties:
+ - compatible: "active-semi,act8945a", please refer to ../mfd/act8945a.txt.
+
+Optional properties:
+- active-semi,vsel-high: Indicates if the VSEL pin is set to logic-high.
+  If this property is missing, assume the VSEL pin is set to logic-low.
+
+Optional input supply properties:
+  - vp1-supply: The input supply for REG_DCDC1
+  - vp2-supply: The input supply for REG_DCDC2
+  - vp3-supply: The input supply for REG_DCDC3
+  - inl45-supply: The input supply for REG_LDO1 and REG_LDO2
+  - inl67-supply: The input supply for REG_LDO3 and REG_LDO4
+
+Any standard regulator properties can be used to configure the single regulator.
+
+The valid names for regulators are:
+       REG_DCDC1, REG_DCDC2, REG_DCDC3, REG_LDO1, REG_LDO2, REG_LDO3, REG_LDO4.
+
+Example:
+       pmic@5b {
+               compatible = "active-semi,act8945a";
+               reg = <0x5b>;
+               status = "okay";
+
+               active-semi,vsel-high;
+
+               regulators {
+                       vdd_1v35_reg: REG_DCDC1 {
+                               regulator-name = "VDD_1V35";
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                       };
+
+                       vdd_1v2_reg: REG_DCDC2 {
+                               regulator-name = "VDD_1V2";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-always-on;
+                       };
+
+                       vdd_3v3_reg: REG_DCDC3 {
+                               regulator-name = "VDD_3V3";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vdd_fuse_reg: REG_LDO1 {
+                               regulator-name = "VDD_FUSE";
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-always-on;
+                       };
+
+                       vdd_3v3_lp_reg: REG_LDO2 {
+                               regulator-name = "VDD_3V3_LP";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vdd_led_reg: REG_LDO3 {
+                               regulator-name = "VDD_LED";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vdd_sdhc_1v8_reg: REG_LDO4 {
+                               regulator-name = "VDD_SDHC_1V8";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt b/Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt
new file mode 100644 (file)
index 0000000..14cfdc5
--- /dev/null
@@ -0,0 +1,29 @@
+Hisilicon Hi655x Voltage regulators
+
+Note:
+The Hi655x regulator control is managed by Hi655x PMIC.
+So the node of this regulator must be child node of Hi655x
+PMIC node.
+
+The driver uses the regulator core framework, so please also
+take the bindings of regulator.txt for reference.
+
+The valid names for regulators are:
+
+LDO2_2V8 LDO7_SDIO LDO10_2V85 LDO13_1V8 LDO14_2V8
+LDO15_1V8 LDO17_2V5 LDO19_3V0 LDO21_1V8 LDO22_1V2
+
+Example:
+        pmic: pmic@f8000000 {
+                compatible = "hisilicon,hi655x-pmic";
+               ...
+               regulators {
+                       ldo2: LDO2@a21 {
+                               regulator-name = "LDO2_2V8";
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <3200000>;
+                               regulator-enable-ramp-delay = <120>;
+                       };
+                       ...
+               }
+       }
index 78183182dad9e04cd9d33d7d20309e8f1a35371b..ca58a68ffdf1c1f830a2a6daa3149d28c6d9bf89 100644 (file)
@@ -28,6 +28,7 @@ Optional properties:
   - ti,dvs-gpio: GPIO specifier for external DVS pin control of LP872x devices.
   - ti,dvs-vsel: DVS selector. 0 = SEL_V1, 1 = SEL_V2.
   - ti,dvs-state: initial DVS pin state. 0 = DVS_LOW, 1 = DVS_HIGH.
+  - enable-gpios: GPIO specifier for EN pin control of LP872x devices.
 
   Sub nodes for regulator_init_data
     LP8720 has maximum 6 nodes. (child name: ldo1 ~ 5 and buck)
index 09d796ed48be4243005e464add1b266678eba4a0..879e98d3b9aa9c8a56492d724e889e64fc2e50fd 100644 (file)
@@ -60,7 +60,7 @@ The possible values for "regulator-initial-mode" and "regulator-mode" are:
        1: Normal regulator voltage output mode.
        3: Low Power which reduces the quiescent current down to only 1uA
 
-The list of valid modes are defined in the dt-bindings/clock/maxim,max77802.h
+The valid modes list is defined in the dt-bindings/regulator/maxim,max77802.h
 header and can be included by device tree source files.
 
 The standard "regulator-mode" property can only be used for regulators that
diff --git a/Documentation/devicetree/bindings/regulator/regulator-max77620.txt b/Documentation/devicetree/bindings/regulator/regulator-max77620.txt
new file mode 100644 (file)
index 0000000..b3c8ca6
--- /dev/null
@@ -0,0 +1,200 @@
+Regulator DT binding for MAX77620 Power management IC from Maxim Semiconductor.
+
+Device has multiple DCDC(sd[0-3] and LDOs(ldo[0-8]). The input supply
+of these regulators are defined under parent device node.
+Details of regulator properties are defined as child node under
+sub-node "regulators" which is child node of device node.
+
+Please refer file <Documentation/devicetree/bindings/regulator/regulator.txt>
+for common regulator bindings used by client.
+
+Following are properties of parent node related to regulators.
+
+Optional properties:
+-------------------
+The input supply of regulators are the optional properties on the
+parent device node. The input supply of these regulators are provided
+through following properties:
+in-sd0-supply:         Input supply for SD0, INA-SD0 or INB-SD0 pins.
+in-sd1-supply:         Input supply for SD1.
+in-sd2-supply:         Input supply for SD2.
+in-sd3-supply:         Input supply for SD3.
+in-ldo0-1-supply:      Input supply for LDO0 and LDO1.
+in-ldo2-supply:                Input supply for LDO2.
+in-ldo3-5-supply:      Input supply for LDO3 and LDO5
+in-ldo4-6-supply:      Input supply for LDO4 and LDO6.
+in-ldo7-8-supply:      Input supply for LDO7 and LDO8.
+
+Optional sub nodes for regulators under "regulators" subnode:
+------------------------------------------------------------
+The subnodes name is the name of regulator and it must be one of:
+       sd[0-3], ldo[0-8]
+
+Each sub-node should contain the constraints and initialization
+information for that regulator. The definition for each of these
+nodes is defined using the standard binding for regulators found at
+<Documentation/devicetree/bindings/regulator/regulator.txt>.
+
+Theres are also additional properties for SD/LDOs. These additional properties
+are required to configure FPS configuration parameters for SDs and LDOs.
+Please refer <devicetree/bindings/mfd/max77620.txt> for more detail of Flexible
+Power Sequence (FPS).
+Following are additional properties:
+
+- maxim,active-fps-source:             FPS source for the regulators to get
+                                       enabled/disabled when system is in
+                                       active state.  Valid values are:
+                                       - MAX77620_FPS_SRC_0,
+                                               FPS source is FPS0.
+                                       - MAX77620_FPS_SRC_1,
+                                               FPS source is FPS1
+                                       - MAX77620_FPS_SRC_2 and
+                                               FPS source is FPS2
+                                       - MAX77620_FPS_SRC_NONE.
+                                               Regulator is not controlled
+                                               by FPS events and it gets
+                                               enabled/disabled by register
+                                               access.
+                                       Absence of this property will leave
+                                       the FPS configuration register for that
+                                       regulator to default configuration.
+
+- maxim,active-fps-power-up-slot:      Sequencing event slot number on which
+                                       the regulator get enabled when
+                                       master FPS input event set to HIGH.
+                                       Valid values are 0 to 7.
+                                       This is applicable if FPS source is
+                                       selected as FPS0, FPS1 or FPS2.
+                       
+- maxim,active-fps-power-down-slot:    Sequencing event slot number on which
+                                       the regulator get disabled when master
+                                       FPS input event set to LOW.
+                                       Valid values are 0 to 7.
+                                       This is applicable if FPS source is
+                                       selected as FPS0, FPS1 or FPS2.
+                       
+- maxim,suspend-fps-source:            This is same as property
+                                       "maxim,active-fps-source" but value
+                                       get configured when system enters in
+                                       to suspend state.
+
+- maxim,suspend-fps-power-up-slot:     This is same as property
+                                       "maxim,active-fps-power-up-slot" but
+                                       this value get configured into FPS
+                                       configuration register when system
+                                       enters into suspend.
+                                       This is applicable if suspend state
+                                       FPS source is selected as FPS0, FPS1 or
+
+- maxim,suspend-fps-power-down-slot:   This is same as property
+                                       "maxim,active-fps-power-down-slot" but
+                                       this value get configured into FPS
+                                       configuration register when system
+                                       enters into suspend.
+                                       This is applicable if suspend state
+                                       FPS source is selected as FPS0, FPS1 or
+                                       FPS2.
+
+Example:
+--------
+#include <dt-bindings/mfd/max77620.h>
+...
+max77620@3c {
+       in-ldo0-1-supply = <&max77620_sd2>;
+       in-ldo7-8-supply = <&max77620_sd2>;
+       regulators {
+               sd0 {
+                       regulator-name = "vdd-core";
+                       regulator-min-microvolt = <600000>;
+                       regulator-max-microvolt = <1400000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+                       maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+               };
+
+               sd1 {
+                       regulator-name = "vddio-ddr";
+                       regulator-min-microvolt = <1200000>;
+                       regulator-max-microvolt = <1200000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+                       maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
+               };
+
+               sd2 {
+                       regulator-name = "vdd-pre-reg";
+                       regulator-min-microvolt = <1350000>;
+                       regulator-max-microvolt = <1350000>;
+               };
+
+               sd3 {
+                       regulator-name = "vdd-1v8";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               ldo0 {
+                       regulator-name = "avdd-sys";
+                       regulator-min-microvolt = <1200000>;
+                       regulator-max-microvolt = <1200000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               ldo1 {
+                       regulator-name = "vdd-pex";
+                       regulator-min-microvolt = <1050000>;
+                       regulator-max-microvolt = <1050000>;
+               };
+
+               ldo2 {
+                       regulator-name = "vddio-sdmmc3";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <3300000>;
+               };
+
+               ldo3 {
+                       regulator-name = "vdd-cam-hv";
+                       regulator-min-microvolt = <2800000>;
+                       regulator-max-microvolt = <2800000>;
+               };
+
+               ldo4 {
+                       regulator-name = "vdd-rtc";
+                       regulator-min-microvolt = <1250000>;
+                       regulator-max-microvolt = <1250000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               ldo5 {
+                       regulator-name = "avdd-ts-hv";
+                       regulator-min-microvolt = <3000000>;
+                       regulator-max-microvolt = <3000000>;
+               };
+
+               ldo6 {
+                       regulator-name = "vdd-ts";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               ldo7 {
+                       regulator-name = "vdd-gen-pll-edp";
+                       regulator-min-microvolt = <1050000>;
+                       regulator-max-microvolt = <1050000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               ldo8 {
+                       regulator-name = "vdd-hdmi-dp";
+                       regulator-min-microvolt = <1050000>;
+                       regulator-max-microvolt = <1050000>;
+               };
+       };
+};
index 1d112fc456aa9e0ecf31a8e5d796001e24ce20b5..ecfc593cac15b3bbebf9ce115f7745a80b264917 100644 (file)
@@ -44,6 +44,11 @@ Optional properties:
   any consumer request.
 - regulator-pull-down: Enable pull down resistor when the regulator is disabled.
 - regulator-over-current-protection: Enable over current protection.
+- regulator-active-discharge: tristate, enable/disable active discharge of
+  regulators. The values are:
+       0: Disable active discharge.
+       1: Enable active discharge.
+       Absence of this property will leave configuration to default.
 
 Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
index d18109657da6c0154d3abebd980178f91b4a9102..4f05d208c95cfeac7ebbc217003d34f08e0f4772 100644 (file)
@@ -26,11 +26,7 @@ Example:
                ti,pmic-shutdown-controller;
 
                regulators {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
                        dcdc1_reg: dcdc1 {
-                               reg = <0>;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <1800000>;
                                regulator-boot-on;
@@ -38,7 +34,6 @@ Example:
                        };
 
                        dcdc2_reg: dcdc2 {
-                               reg = <1>;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
@@ -46,7 +41,6 @@ Example:
                        };
 
                        dcdc3_reg: dcc3 {
-                               reg = <2>;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-boot-on;
@@ -54,7 +48,6 @@ Example:
                        };
 
                        ldo1_reg: ldo1 {
-                               reg = <3>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
@@ -62,7 +55,6 @@ Example:
                        };
 
                        ldo2_reg: ldo2 {
-                               reg = <4>;
                                regulator-min-microvolt = <900000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
@@ -70,7 +62,6 @@ Example:
                        };
 
                        ldo3_reg: ldo3 {
-                               reg = <5>;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
@@ -78,7 +69,6 @@ Example:
                        };
 
                        ldo4_reg: ldo4 {
-                               reg = <6>;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
diff --git a/Documentation/devicetree/bindings/rtc/alphascale,asm9260-rtc.txt b/Documentation/devicetree/bindings/rtc/alphascale,asm9260-rtc.txt
new file mode 100644 (file)
index 0000000..76ebca5
--- /dev/null
@@ -0,0 +1,19 @@
+* Alphascale asm9260 SoC Real Time Clock
+
+Required properties:
+- compatible: Should be "alphascale,asm9260-rtc"
+- reg: Physical base address of the controller and length
+       of memory mapped region.
+- interrupts: IRQ line for the RTC.
+- clocks: Reference to the clock entry.
+- clock-names: should contain:
+  * "ahb" for the SoC RTC clock
+
+Example:
+rtc0: rtc@800a0000 {
+       compatible = "alphascale,asm9260-rtc";
+       reg = <0x800a0000 0x100>;
+       clocks = <&acc CLKID_AHB_RTC>;
+       clock-names = "ahb";
+       interrupts = <2>;
+};
diff --git a/Documentation/devicetree/bindings/rtc/epson,rx6110.txt b/Documentation/devicetree/bindings/rtc/epson,rx6110.txt
new file mode 100644 (file)
index 0000000..3dc313e
--- /dev/null
@@ -0,0 +1,39 @@
+Epson RX6110 Real Time Clock
+============================
+
+The Epson RX6110 can be used with SPI or I2C busses. The kind of
+bus depends on the SPISEL pin and can not be configured via software.
+
+I2C mode
+--------
+
+Required properties:
+  - compatible: should be: "epson,rx6110"
+  - reg : the I2C address of the device for I2C
+
+Example:
+
+       rtc: rtc@32 {
+               compatible = "epson,rx6110"
+               reg = <0x32>;
+       };
+
+SPI mode
+--------
+
+Required properties:
+  - compatible: should be: "epson,rx6110"
+  - reg: chip select number
+  - spi-cs-high: RX6110 needs chipselect high
+  - spi-cpha: RX6110 works with SPI shifted clock phase
+  - spi-cpol: RX6110 works with SPI inverse clock polarity
+
+Example:
+
+       rtc: rtc@3 {
+               compatible = "epson,rx6110"
+               reg = <3>
+               spi-cs-high;
+               spi-cpha;
+               spi-cpol;
+       };
diff --git a/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt b/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt
new file mode 100644 (file)
index 0000000..ddef330
--- /dev/null
@@ -0,0 +1,37 @@
+* Maxim DS3231 Real Time Clock
+
+Required properties:
+see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+
+Optional property:
+- #clock-cells: Should be 1.
+- clock-output-names:
+  overwrite the default clock names "ds3231_clk_sqw" and "ds3231_clk_32khz".
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. Following indices are allowed:
+    - 0: square-wave output on the SQW pin
+    - 1: square-wave output on the 32kHz pin
+
+- interrupts: rtc alarm/event interrupt. When this property is selected,
+  clock on the SQW pin cannot be used.
+
+Example:
+
+ds3231: ds3231@51 {
+       compatible = "maxim,ds3231";
+       reg = <0x68>;
+       #clock-cells = <1>;
+};
+
+device1 {
+...
+       clocks = <&ds3231 0>;
+...
+};
+
+device2 {
+...
+       clocks = <&ds3231 1>;
+...
+};
diff --git a/Documentation/devicetree/bindings/rtc/microchip,pic32-rtc.txt b/Documentation/devicetree/bindings/rtc/microchip,pic32-rtc.txt
new file mode 100644 (file)
index 0000000..180b714
--- /dev/null
@@ -0,0 +1,21 @@
+* Microchip PIC32 Real Time Clock and Calendar
+
+The RTCC keeps time in hours, minutes, and seconds, and one half second. It
+provides a calendar in weekday, date, month, and year. It also provides a
+configurable alarm.
+
+Required properties:
+- compatible: should be: "microchip,pic32mzda-rtc"
+- reg: physical base address of the controller and length of memory mapped
+    region.
+- interrupts: RTC alarm/event interrupt
+- clocks: clock phandle
+
+Example:
+
+       rtc: rtc@1f8c0000 {
+               compatible = "microchip,pic32mzda-rtc";
+               reg = <0x1f8c0000 0x60>;
+               interrupts = <166 IRQ_TYPE_EDGE_RISING>;
+               clocks = <&PBCLK6>;
+       };
index e2cd1d7539e527897cc34566508ed56f070a60cb..6e699ceabacdedcc9d27043bb74cf53d88c5544a 100644 (file)
@@ -33,12 +33,19 @@ Optional properties:
        Note that this is not needed in case the clocks are stable
        throughout the entire runtime of the codec.
 
+ - vd-supply:  Digital power
+ - vl-supply:  Logic power
+ - va-supply:  Analog Power
+
 Examples:
 
        codec_i2c: cs4271@10 {
                compatible = "cirrus,cs4271";
                reg = <0x10>;
                reset-gpio = <&gpio 23 0>;
+               vd-supply = <&vdd_3v3_reg>;
+               vl-supply = <&vdd_3v3_reg>;
+               va-supply = <&vdd_3v3_reg>;
        };
 
        codec_spi: cs4271@0 {
diff --git a/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.txt b/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.txt
new file mode 100644 (file)
index 0000000..8a18d71
--- /dev/null
@@ -0,0 +1,31 @@
+Analog Devices AXI SPI Engine controller Device Tree Bindings
+
+Required properties:
+- compatible           : Must be "adi,axi-spi-engine-1.00.a""
+- reg                  : Physical base address and size of the register map.
+- interrupts           : Property with a value describing the interrupt
+                         number.
+- clock-names          : List of input clock names - "s_axi_aclk", "spi_clk"
+- clocks               : Clock phandles and specifiers (See clock bindings for
+                         details on clock-names and clocks).
+- #address-cells       : Must be <1>
+- #size-cells          : Must be <0>
+
+Optional subnodes:
+       Subnodes are use to represent the SPI slave devices connected to the SPI
+       master. They follow the generic SPI bindings as outlined in spi-bus.txt.
+
+Example:
+
+    spi@@44a00000 {
+               compatible = "adi,axi-spi-engine-1.00.a";
+               reg = <0x44a00000 0x1000>;
+               interrupts = <0 56 4>;
+               clocks = <&clkc 15 &clkc 15>;
+               clock-names = "s_axi_aclk", "spi_clk";
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               /* SPI devices */
+    };
diff --git a/Documentation/devicetree/bindings/spi/icpdas-lp8841-spi-rtc.txt b/Documentation/devicetree/bindings/spi/icpdas-lp8841-spi-rtc.txt
new file mode 100644 (file)
index 0000000..852b651
--- /dev/null
@@ -0,0 +1,54 @@
+* ICP DAS LP-8841 SPI Controller for RTC
+
+ICP DAS LP-8841 contains a DS-1302 RTC. RTC is connected to an IO
+memory register, which acts as an SPI master device.
+
+The device uses the standard MicroWire half-duplex transfer timing.
+Master output is set on low clock and sensed by the RTC on the rising
+edge. Master input is set by the RTC on the trailing edge and is sensed
+by the master on low clock.
+
+Required properties:
+
+- #address-cells: should be 1
+
+- #size-cells: should be 0
+
+- compatible: should be "icpdas,lp8841-spi-rtc"
+
+- reg: should provide IO memory address
+
+Requirements to SPI slave nodes:
+
+- There can be only one slave device.
+
+- The spi slave node should claim the following flags which are
+  required by the spi controller.
+
+  - spi-3wire: The master itself has only 3 wire. It cannor work in
+    full duplex mode.
+
+  - spi-cs-high: DS-1302 has active high chip select line. The master
+    doesn't support active low.
+
+  - spi-lsb-first: DS-1302 requires least significant bit first
+    transfers. The master only support this type of bit ordering.
+
+
+Example:
+
+spi@901c {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       compatible = "icpdas,lp8841-spi-rtc";
+       reg = <0x901c 0x1>;
+
+       rtc@0 {
+               compatible = "maxim,ds1302";
+               reg = <0>;
+               spi-max-frequency = <500000>;
+               spi-3wire;
+               spi-lsb-first;
+               spi-cs-high;
+       };
+};
index 0c491bda4c65f9bace70c051fc06389261d82cad..1b14d69d8903a448a1138e38bf8332828bfd551e 100644 (file)
@@ -9,6 +9,7 @@ Required Properties:
     "rockchip,rk3066-spi" for rk3066.
     "rockchip,rk3188-spi", "rockchip,rk3066-spi" for rk3188.
     "rockchip,rk3288-spi", "rockchip,rk3066-spi" for rk3288.
+    "rockchip,rk3399-spi", "rockchip,rk3066-spi" for rk3399.
 - reg: physical base address of the controller and length of memory mapped
        region.
 - interrupts: The interrupt number to the cpu. The interrupt specifier format
diff --git a/Documentation/devicetree/bindings/spi/spi-xilinx.txt b/Documentation/devicetree/bindings/spi/spi-xilinx.txt
new file mode 100644 (file)
index 0000000..c7b7856
--- /dev/null
@@ -0,0 +1,22 @@
+Xilinx SPI controller Device Tree Bindings
+-------------------------------------------------
+
+Required properties:
+- compatible           : Should be "xlnx,xps-spi-2.00.a" or "xlnx,xps-spi-2.00.b"
+- reg                  : Physical base address and size of SPI registers map.
+- interrupts           : Property with a value describing the interrupt
+                         number.
+- interrupt-parent     : Must be core interrupt controller
+
+Optional properties:
+- xlnx,num-ss-bits     : Number of chip selects used.
+
+Example:
+       axi_quad_spi@41e00000 {
+                       compatible = "xlnx,xps-spi-2.00.a";
+                       interrupt-parent = <&intc>;
+                       interrupts = <0 31 1>;
+                       reg = <0x41e00000 0x10000>;
+                       xlnx,num-ss-bits = <0x1>;
+       };
+
index 72e2c5a2b3278facb20378383cbb63baa6485e0f..dd72e0541e83e3631679fb9b1f639f2c26f963c2 100644 (file)
@@ -120,6 +120,7 @@ intercontrol        Inter Control Group
 invensense     InvenSense Inc.
 isee   ISEE 2007 S.L.
 isil   Intersil
+issi   Integrated Silicon Solutions Inc.
 jedec  JEDEC Solid State Technology Association
 karo   Ka-Ro electronics GmbH
 keymile        Keymile GmbH
@@ -204,6 +205,7 @@ seagate     Seagate Technology PLC
 semtech        Semtech Corporation
 sgx    SGX Sensortech
 sharp  Sharp Corporation
+si-en  Si-En Technology Ltd.
 sigma  Sigma Designs, Inc.
 sil    Silicon Image
 silabs Silicon Laboratories
index d697229e3c18e2571f4846eb8801094daf52eb2e..791bc0bd91e6b25d59d526742ef2b12c07a3a794 100644 (file)
@@ -14,6 +14,10 @@ Supported chips:
     Prefix: 'adm1276'
     Addresses scanned: -
     Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
+  * Analog Devices ADM1278
+    Prefix: 'adm1278'
+    Addresses scanned: -
+    Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1278.pdf
   * Analog Devices ADM1293/ADM1294
     Prefix: 'adm1293', 'adm1294'
     Addresses scanned: -
@@ -25,13 +29,15 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-This driver supports hardware montoring for Analog Devices ADM1075, ADM1275,
-ADM1276, ADM1293, and ADM1294 Hot-Swap Controller and Digital Power Monitors.
+This driver supports hardware monitoring for Analog Devices ADM1075, ADM1275,
+ADM1276, ADM1278, ADM1293, and ADM1294 Hot-Swap Controller and Digital
+Power Monitors.
 
-ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 are hot-swap controllers that
-allow a circuit board to be removed from or inserted into a live backplane.
-They also feature current and voltage readback via an integrated 12
-bit analog-to-digital converter (ADC), accessed using a PMBus interface.
+ADM1075, ADM1275, ADM1276, ADM1278, ADM1293, and ADM1294 are hot-swap
+controllers that allow a circuit board to be removed from or inserted into
+a live backplane. They also feature current and voltage readback via an
+integrated 12 bit analog-to-digital converter (ADC), accessed using a
+PMBus interface.
 
 The driver is a client driver to the core PMBus driver. Please see
 Documentation/hwmon/pmbus for details on PMBus client drivers.
@@ -96,3 +102,14 @@ power1_reset_history        Write any value to reset history.
 
                        Power attributes are supported on ADM1075, ADM1276,
                        ADM1293, and ADM1294.
+
+temp1_input            Chip temperature.
+                       Temperature attributes are only available on ADM1278.
+temp1_max              Maximum chip temperature.
+temp1_max_alarm                Temperature alarm.
+temp1_crit             Critical chip temperature.
+temp1_crit_alarm       Critical temperature high alarm.
+temp1_highest          Highest observed temperature.
+temp1_reset_history    Write any value to reset history.
+
+                       Temperature attributes are supported on ADM1278.
index b34c3de5c1bcfccf76f64b3442cf3433bc6ff472..2cb20ebb234d4944956512992b1a2d1787c4cbef 100644 (file)
@@ -36,7 +36,7 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-This driver supports hardware montoring for National Semiconductor / TI LM25056,
+This driver supports hardware monitoring for National Semiconductor / TI LM25056,
 LM25063, LM25066, LM5064, and LM5066 Power Management, Monitoring, Control, and
 Protection ICs.
 
diff --git a/Documentation/hwmon/ltc2990 b/Documentation/hwmon/ltc2990
new file mode 100644 (file)
index 0000000..c25211e
--- /dev/null
@@ -0,0 +1,43 @@
+Kernel driver ltc2990
+=====================
+
+Supported chips:
+  * Linear Technology LTC2990
+    Prefix: 'ltc2990'
+    Addresses scanned: -
+    Datasheet: http://www.linear.com/product/ltc2990
+
+Author: Mike Looijmans <mike.looijmans@topic.nl>
+
+
+Description
+-----------
+
+LTC2990 is a Quad I2C Voltage, Current and Temperature Monitor.
+The chip's inputs can measure 4 voltages, or two inputs together (1+2 and 3+4)
+can be combined to measure a differential voltage, which is typically used to
+measure current through a series resistor, or a temperature.
+
+This driver currently uses the 2x differential mode only. In order to support
+other modes, the driver will need to be expanded.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for PMBus devices. You will have to instantiate
+devices explicitly.
+
+
+Sysfs attributes
+----------------
+
+The "curr*_input" measurements actually report the voltage drop across the
+input pins in microvolts. This is equivalent to the current through a 1mOhm
+sense resistor. Divide the reported value by the actual sense resistor value
+in mOhm to get the actual value.
+
+in0_input     Voltage at Vcc pin in millivolt (range 2.5V to 5V)
+temp1_input   Internal chip temperature in millidegrees Celcius
+curr1_input   Current in mA across v1-v2 assuming a 1mOhm sense resistor.
+curr2_input   Current in mA across v3-v4 assuming a 1mOhm sense resistor.
index d59cc7829bec1b223a8e3b577741624d9cc4ee6a..265370f5cb82340221186eb84f297e3bf1241637 100644 (file)
@@ -13,7 +13,7 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-This driver supports hardware montoring for Maxim MAX16064 Quad Power-Supply
+This driver supports hardware monitoring for Maxim MAX16064 Quad Power-Supply
 Controller with Active-Voltage Output Control and PMBus Interface.
 
 The driver is a client driver to the core PMBus driver.
index 37cbf472a19d19aef7aea0217d008943eb28909f..f5b1fcaa9e4e41ae76d050ff41fe9c8b1d59ab3d 100644 (file)
@@ -33,7 +33,7 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-This driver supports hardware montoring for Maxim MAX34440 PMBus 6-Channel
+This driver supports hardware monitoring for Maxim MAX34440 PMBus 6-Channel
 Power-Supply Manager, MAX34441 PMBus 5-Channel Power-Supply Manager
 and Intelligent Fan Controller, and MAX34446 PMBus Power-Supply Data Logger.
 It also supports the MAX34460 and MAX34461 PMBus Voltage Monitor & Sequencers.
index e78078638b9142906b8308c4700f25d2f8a2ef88..ca233bec7a8a83985cf31a06f96e74d02e922d54 100644 (file)
@@ -13,7 +13,7 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-This driver supports hardware montoring for Maxim MAX8688 Digital Power-Supply
+This driver supports hardware monitoring for Maxim MAX8688 Digital Power-Supply
 Controller/Monitor with PMBus Interface.
 
 The driver is a client driver to the core PMBus driver. Please see
diff --git a/Documentation/hwmon/nsa320 b/Documentation/hwmon/nsa320
new file mode 100644 (file)
index 0000000..fdbd694
--- /dev/null
@@ -0,0 +1,53 @@
+Kernel driver nsa320_hwmon
+==========================
+
+Supported chips:
+  * Holtek HT46R065 microcontroller with onboard firmware that configures
+       it to act as a hardware monitor.
+    Prefix: 'nsa320'
+    Addresses scanned: none
+    Datasheet: Not available, driver was reverse engineered based upon the
+       Zyxel kernel source
+
+Author:
+  Adam Baker <linux@baker-net.org.uk>
+
+Description
+-----------
+
+This chip is known to be used in the Zyxel NSA320 and NSA325 NAS Units and
+also in some variants of the NSA310 but the driver has only been tested
+on the NSA320. In all of these devices it is connected to the same 3 GPIO
+lines which are used to provide chip select, clock and data lines. The
+interface behaves similarly to SPI but at much lower speeds than are normally
+used for SPI.
+
+Following each chip select pulse the chip will generate a single 32 bit word
+that contains 0x55 as a marker to indicate that data is being read correctly,
+followed by an 8 bit fan speed in 100s of RPM and a 16 bit temperature in
+tenths of a degree.
+
+
+sysfs-Interface
+---------------
+
+temp1_input - temperature input
+fan1_input - fan speed
+
+Notes
+-----
+
+The access timings used in the driver are the same as used in the Zyxel
+provided kernel. Testing has shown that if the delay between chip select and
+the first clock pulse is reduced from 100 ms to just under 10ms then the chip
+will not produce any output. If the duration of either phase of the clock
+is reduced from 100 us to less than 15 us then data pulses are likely to be
+read twice corrupting the output. The above analysis is based upon a sample
+of one unit but suggests that the Zyxel provided delay values include a
+reasonable tolerance.
+
+The driver incorporates a limit that it will not check for updated values
+faster than once a second. This is because the hardware takes a relatively long
+time to read the data from the device and when it does it reads both temp and
+fan speed. As the most likely case for two accesses in quick succession is
+to read both of these values avoiding a second read delay is desirable.
index 1d4cc847c6fe6a9cc53ec39b36961bc94c78ad17..8b9ff23edc32380369515ebfcef46b1d4512f992 100644 (file)
@@ -3,9 +3,9 @@ Kernel driver ntc_thermistor
 
 Supported thermistors from Murata:
 * Murata NTC Thermistors NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473,
-  NCP15WL333, NCP03WF104
+  NCP15WL333, NCP03WF104, NCP15XH103
   Prefixes: 'ncp15wb473', 'ncp18wb473', 'ncp21wb473', 'ncp03wb473',
-  'ncp15wl333', 'ncp03wf104'
+  'ncp15wl333', 'ncp03wf104', 'ncp15xh103'
   Datasheet: Publicly available at Murata
 
 Supported thermistors from EPCOS:
index b397675e876d4daa7dae76ca0bef2e1559a0f1da..dfd9c65996c00e3e6fa1578a66d923d263914c5e 100644 (file)
@@ -43,7 +43,7 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-This driver supports hardware montoring for various PMBus compliant devices.
+This driver supports hardware monitoring for various PMBus compliant devices.
 It supports voltage, current, power, and temperature sensors as supported
 by the device.
 
index 33908a4d68ff9e0b47e26560f15ff5f4e550161b..477a94b131ae7779624b6f630f5663d0e525fe91 100644 (file)
@@ -60,7 +60,7 @@ Author: Guenter Roeck <linux@roeck-us.net>
 Description
 -----------
 
-This driver supports hardware montoring for Intersil / Zilker Labs ZL6100 and
+This driver supports hardware monitoring for Intersil / Zilker Labs ZL6100 and
 compatible digital DC-DC controllers.
 
 The driver is a client driver to the core PMBus driver. Please see
index 9a53c929f017d16527270bc2244352edf1d34cd8..def479154d59b1ad8d6db322a533c3123246b258 100644 (file)
@@ -193,6 +193,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        (e.g. thinkpad_acpi, sony_acpi, etc.) instead
                        of the ACPI video.ko driver.
 
+       acpi_force_32bit_fadt_addr
+                       force FADT to use 32 bit addresses rather than the
+                       64 bit X_* addresses. Some firmware have broken 64
+                       bit addresses for force ACPI ignore these and use
+                       the older legacy 32 bit addresses.
+
        acpica_no_return_repair [HW, ACPI]
                        Disable AML predefined validation mechanism
                        This mechanism can repair the evaluation result to make
@@ -666,7 +672,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        clearcpuid=BITNUM [X86]
                        Disable CPUID feature X for the kernel. See
-                       arch/x86/include/asm/cpufeature.h for the valid bit
+                       arch/x86/include/asm/cpufeatures.h for the valid bit
                        numbers. Note the Linux specific bits are not necessarily
                        stable over kernel options, but the vendor specific
                        ones should be.
@@ -1687,6 +1693,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        ip=             [IP_PNP]
                        See Documentation/filesystems/nfs/nfsroot.txt.
 
+       irqaffinity=    [SMP] Set the default irq affinity mask
+                       Format:
+                       <cpu number>,...,<cpu number>
+                       or
+                       <cpu number>-<cpu number>
+                       (must be a positive range in ascending order)
+                       or a mixture
+                       <cpu number>,...,<cpu number>-<cpu number>
+
        irqfixup        [HW]
                        When an interrupt is not handled search all handlers
                        for it. Intended to get systems with badly broken
@@ -1750,7 +1765,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        keepinitrd      [HW,ARM]
 
-       kernelcore=nn[KMG]      [KNL,X86,IA-64,PPC] This parameter
+       kernelcore=     [KNL,X86,IA-64,PPC]
+                       Format: nn[KMGTPE] | "mirror"
+                       This parameter
                        specifies the amount of memory usable by the kernel
                        for non-movable allocations.  The requested amount is
                        spread evenly throughout all nodes in the system. The
@@ -1766,6 +1783,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        use the HighMem zone if it exists, and the Normal
                        zone if it does not.
 
+                       Instead of specifying the amount of memory (nn[KMGTPE]),
+                       you can specify "mirror" option. In case "mirror"
+                       option is specified, mirrored (reliable) memory is used
+                       for non-movable allocations and remaining memory is used
+                       for Movable pages. nn[KMGTPE] and "mirror" are exclusive,
+                       so you can NOT specify nn[KMGTPE] and "mirror" at the same
+                       time.
+
        kgdbdbgp=       [KGDB,HW] kgdb over EHCI usb debug port.
                        Format: <Controller#>[,poll interval]
                        The controller # is the number of the ehci usb debug
@@ -2566,6 +2591,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        nointroute      [IA-64]
 
+       noinvpcid       [X86] Disable the INVPCID cpu feature.
+
        nojitter        [IA-64] Disables jitter checking for ITC timers.
 
        no-kvmclock     [X86,KVM] Disable paravirtualized KVM clock driver
@@ -2721,6 +2748,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        we can turn it on.
                        on: enable the feature
 
+       page_poison=    [KNL] Boot-time parameter changing the state of
+                       poisoning on the buddy allocator.
+                       off: turn off poisoning
+                       on: turn on poisoning
+
        panic=          [KNL] Kernel behaviour on panic: delay <timeout>
                        timeout > 0: seconds before rebooting
                        timeout = 0: wait forever
@@ -3491,6 +3523,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        ro              [KNL] Mount root device read-only on boot
 
+       rodata=         [KNL]
+               on      Mark read-only kernel memory as read-only (default).
+               off     Leave read-only kernel memory writable for debugging.
+
        root=           [KNL] Root filesystem
                        See name_to_dev_t comment in init/do_mounts.c.
 
@@ -3528,6 +3564,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 
        sched_debug     [KNL] Enables verbose scheduler debug messages.
 
+       schedstats=     [KNL,X86] Enable or disable scheduled statistics.
+                       Allowed values are enable and disable. This feature
+                       incurs a small amount of overhead in the scheduler
+                       but is useful for debugging and performance tuning.
+
        skew_tick=      [KNL] Offset the periodic timer tick per cpu to mitigate
                        xtime_lock contention on larger systems, and/or RCU lock
                        contention on all systems with CONFIG_MAXSMP set.
index ce2cfcf35c27a0d0972547e82f61fbc38c85b5ab..443f4b44ad97cddc2d8b645c29a55ff88573f864 100644 (file)
@@ -256,10 +256,27 @@ If the memory block is offline, you'll read "offline".
 
 5.2. How to online memory
 ------------
-Even if the memory is hot-added, it is not at ready-to-use state.
-For using newly added memory, you have to "online" the memory block.
+When the memory is hot-added, the kernel decides whether or not to "online"
+it according to the policy which can be read from "auto_online_blocks" file:
 
-For onlining, you have to write "online" to the memory block's state file as:
+% cat /sys/devices/system/memory/auto_online_blocks
+
+The default is "offline" which means the newly added memory is not in a
+ready-to-use state and you have to "online" the newly added memory blocks
+manually. Automatic onlining can be requested by writing "online" to
+"auto_online_blocks" file:
+
+% echo online > /sys/devices/system/memory/auto_online_blocks
+
+This sets a global policy and impacts all memory blocks that will subsequently
+be hotplugged. Currently offline blocks keep their state. It is possible, under
+certain circumstances, that some memory blocks will be added but will fail to
+online. User space tools can check their "state" files
+(/sys/devices/system/memory/memoryXXX/state) and try to online them manually.
+
+If the automatic onlining wasn't requested, failed, or some memory block was
+offlined it is possible to change the individual block's state by writing to the
+"state" file:
 
 % echo online > /sys/devices/system/memory/memoryXXX/state
 
index 5d1128bf02824aaf2e16ef332e7cef014cccf7b6..5962949944fd7307530f26c54c65d783745a8a27 100644 (file)
@@ -298,6 +298,24 @@ bitmap and its derivatives such as cpumask and nodemask:
 
        Passed by reference.
 
+Flags bitfields such as page flags, gfp_flags:
+
+       %pGp    referenced|uptodate|lru|active|private
+       %pGg    GFP_USER|GFP_DMA32|GFP_NOWARN
+       %pGv    read|exec|mayread|maywrite|mayexec|denywrite
+
+       For printing flags bitfields as a collection of symbolic constants that
+       would construct the value. The type of flags is given by the third
+       character. Currently supported are [p]age flags, [v]ma_flags (both
+       expect unsigned long *) and [g]fp_flags (expects gfp_t *). The flag
+       names and print order depends on the particular type.
+
+       Note that this format should not be used directly in TP_printk() part
+       of a tracepoint. Instead, use the show_*_flags() functions from
+       <trace/events/mmflags.h>.
+
+       Passed by reference.
+
 Network device features:
 
        %pNF    0x000000000000c000
index 6c6247aaa7b93a0a038e5f65b30679486b410cc2..d99012f41602aca39f2468eb79fc03ea83626852 100644 (file)
@@ -277,13 +277,15 @@ int main(int argc, char *argv[])
                               "  %d external time stamp channels\n"
                               "  %d programmable periodic signals\n"
                               "  %d pulse per second\n"
-                              "  %d programmable pins\n",
+                              "  %d programmable pins\n"
+                              "  %d cross timestamping\n",
                               caps.max_adj,
                               caps.n_alarm,
                               caps.n_ext_ts,
                               caps.n_per_out,
                               caps.pps,
-                              caps.n_pins);
+                              caps.n_pins,
+                              caps.cross_timestamping);
                }
        }
 
index 8446f1ea1410b87b071047dc310a787a92606c31..ddc366026e00f60b8491fe50587e35836656835b 100644 (file)
@@ -157,6 +157,12 @@ wakealarm:  The time at which the clock will generate a system wakeup
                 the epoch by default, or if there's a leading +, seconds in the
                 future, or if there is a leading +=, seconds ahead of the current
                 alarm.
+offset:                 The amount which the rtc clock has been adjusted in firmware.
+                Visible only if the driver supports clock offset adjustment.
+                The unit is parts per billion, i.e. The number of clock ticks
+                which are added to or removed from the rtc's base clock per
+                billion ticks. A positive value makes a day pass more slowly,
+                longer, and a negative value makes a day pass more quickly.
 
 IOCTL INTERFACE
 ---------------
index a93b414672a71ac6fa9bac1e848215804bde139c..f4444c94ff285db493961c54a1527a189da20fd2 100644 (file)
@@ -58,6 +58,8 @@ show up in /proc/sys/kernel:
 - panic_on_stackoverflow
 - panic_on_unrecovered_nmi
 - panic_on_warn
+- perf_cpu_time_max_percent
+- perf_event_paranoid
 - pid_max
 - powersave-nap               [ PPC only ]
 - printk
@@ -639,6 +641,17 @@ allowed to execute.
 
 ==============================================================
 
+perf_event_paranoid:
+
+Controls use of the performance events system by unprivileged
+users (without CAP_SYS_ADMIN).  The default value is 1.
+
+ -1: Allow use of (almost) all events by all users
+>=0: Disallow raw tracepoint access by users without CAP_IOC_LOCK
+>=1: Disallow CPU event access by users without CAP_SYS_ADMIN
+>=2: Disallow kernel profiling by users without CAP_SYS_ADMIN
+
+==============================================================
 
 pid_max:
 
@@ -760,6 +773,14 @@ rtsig-nr shows the number of RT signals currently queued.
 
 ==============================================================
 
+sched_schedstats:
+
+Enables/disables scheduler statistics. Enabling this feature
+incurs a small amount of overhead in the scheduler but is
+useful for debugging and performance tuning.
+
+==============================================================
+
 sg-big-buff:
 
 This file shows the size of the generic SCSI (sg) buffer.
index 07e4cdf024073033e2a52213bcbed4d562111a33..4d0542c5206b8f88e80b7506e4abfb6acb28e6e7 100644 (file)
@@ -2507,8 +2507,9 @@ struct kvm_create_device {
 
 4.80 KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR
 
-Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device
-Type: device ioctl, vm ioctl
+Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
+  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
+Type: device ioctl, vm ioctl, vcpu ioctl
 Parameters: struct kvm_device_attr
 Returns: 0 on success, -1 on error
 Errors:
@@ -2533,8 +2534,9 @@ struct kvm_device_attr {
 
 4.81 KVM_HAS_DEVICE_ATTR
 
-Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device
-Type: device ioctl, vm ioctl
+Capability: KVM_CAP_DEVICE_CTRL, KVM_CAP_VM_ATTRIBUTES for vm device,
+  KVM_CAP_VCPU_ATTRIBUTES for vcpu device
+Type: device ioctl, vm ioctl, vcpu ioctl
 Parameters: struct kvm_device_attr
 Returns: 0 on success, -1 on error
 Errors:
@@ -2577,6 +2579,8 @@ Possible features:
          Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
        - KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for the CPU.
          Depends on KVM_CAP_ARM_PSCI_0_2.
+       - KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
+         Depends on KVM_CAP_ARM_PMU_V3.
 
 
 4.83 KVM_ARM_PREFERRED_TARGET
@@ -3035,6 +3039,87 @@ Returns: 0 on success, -1 on error
 
 Queues an SMI on the thread's vcpu.
 
+4.97 KVM_CAP_PPC_MULTITCE
+
+Capability: KVM_CAP_PPC_MULTITCE
+Architectures: ppc
+Type: vm
+
+This capability means the kernel is capable of handling hypercalls
+H_PUT_TCE_INDIRECT and H_STUFF_TCE without passing those into the user
+space. This significantly accelerates DMA operations for PPC KVM guests.
+User space should expect that its handlers for these hypercalls
+are not going to be called if user space previously registered LIOBN
+in KVM (via KVM_CREATE_SPAPR_TCE or similar calls).
+
+In order to enable H_PUT_TCE_INDIRECT and H_STUFF_TCE use in the guest,
+user space might have to advertise it for the guest. For example,
+IBM pSeries (sPAPR) guest starts using them if "hcall-multi-tce" is
+present in the "ibm,hypertas-functions" device-tree property.
+
+The hypercalls mentioned above may or may not be processed successfully
+in the kernel based fast path. If they can not be handled by the kernel,
+they will get passed on to user space. So user space still has to have
+an implementation for these despite the in kernel acceleration.
+
+This capability is always enabled.
+
+4.98 KVM_CREATE_SPAPR_TCE_64
+
+Capability: KVM_CAP_SPAPR_TCE_64
+Architectures: powerpc
+Type: vm ioctl
+Parameters: struct kvm_create_spapr_tce_64 (in)
+Returns: file descriptor for manipulating the created TCE table
+
+This is an extension for KVM_CAP_SPAPR_TCE which only supports 32bit
+windows, described in 4.62 KVM_CREATE_SPAPR_TCE
+
+This capability uses extended struct in ioctl interface:
+
+/* for KVM_CAP_SPAPR_TCE_64 */
+struct kvm_create_spapr_tce_64 {
+       __u64 liobn;
+       __u32 page_shift;
+       __u32 flags;
+       __u64 offset;   /* in pages */
+       __u64 size;     /* in pages */
+};
+
+The aim of extension is to support an additional bigger DMA window with
+a variable page size.
+KVM_CREATE_SPAPR_TCE_64 receives a 64bit window size, an IOMMU page shift and
+a bus offset of the corresponding DMA window, @size and @offset are numbers
+of IOMMU pages.
+
+@flags are not used at the moment.
+
+The rest of functionality is identical to KVM_CREATE_SPAPR_TCE.
+
+4.98 KVM_REINJECT_CONTROL
+
+Capability: KVM_CAP_REINJECT_CONTROL
+Architectures: x86
+Type: vm ioctl
+Parameters: struct kvm_reinject_control (in)
+Returns: 0 on success,
+         -EFAULT if struct kvm_reinject_control cannot be read,
+         -ENXIO if KVM_CREATE_PIT or KVM_CREATE_PIT2 didn't succeed earlier.
+
+i8254 (PIT) has two modes, reinject and !reinject.  The default is reinject,
+where KVM queues elapsed i8254 ticks and monitors completion of interrupt from
+vector(s) that i8254 injects.  Reinject mode dequeues a tick and injects its
+interrupt whenever there isn't a pending interrupt from i8254.
+!reinject mode injects an interrupt as soon as a tick arrives.
+
+struct kvm_reinject_control {
+       __u8 pit_reinject;
+       __u8 reserved[31];
+};
+
+pit_reinject = 0 (!reinject mode) is recommended, unless running an old
+operating system that uses the PIT for timing (e.g. Linux 2.4.x).
+
 5. The kvm_run structure
 ------------------------
 
@@ -3339,6 +3424,7 @@ EOI was received.
 
                struct kvm_hyperv_exit {
 #define KVM_EXIT_HYPERV_SYNIC          1
+#define KVM_EXIT_HYPERV_HCALL          2
                        __u32 type;
                        union {
                                struct {
@@ -3347,6 +3433,11 @@ EOI was received.
                                        __u64 evt_page;
                                        __u64 msg_page;
                                } synic;
+                               struct {
+                                       __u64 input;
+                                       __u64 result;
+                                       __u64 params[2];
+                               } hcall;
                        } u;
                };
                /* KVM_EXIT_HYPERV */
index d1ad9d5cae467ceb2c1169ce8b53d70078aedf27..e3e314cb83e83fd08f99fc0f3859727b22eb0cc1 100644 (file)
@@ -88,6 +88,8 @@ struct kvm_s390_io_adapter_req {
       perform a gmap translation for the guest address provided in addr,
       pin a userspace page for the translated address and add it to the
       list of mappings
+      Note: A new mapping will be created unconditionally; therefore,
+            the calling code should avoid making duplicate mappings.
 
     KVM_S390_IO_ADAPTER_UNMAP
       release a userspace page for the translated address specified in addr
diff --git a/Documentation/virtual/kvm/devices/vcpu.txt b/Documentation/virtual/kvm/devices/vcpu.txt
new file mode 100644 (file)
index 0000000..c041658
--- /dev/null
@@ -0,0 +1,33 @@
+Generic vcpu interface
+====================================
+
+The virtual cpu "device" also accepts the ioctls KVM_SET_DEVICE_ATTR,
+KVM_GET_DEVICE_ATTR, and KVM_HAS_DEVICE_ATTR. The interface uses the same struct
+kvm_device_attr as other devices, but targets VCPU-wide settings and controls.
+
+The groups and attributes per virtual cpu, if any, are architecture specific.
+
+1. GROUP: KVM_ARM_VCPU_PMU_V3_CTRL
+Architectures: ARM64
+
+1.1. ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_IRQ
+Parameters: in kvm_device_attr.addr the address for PMU overflow interrupt is a
+            pointer to an int
+Returns: -EBUSY: The PMU overflow interrupt is already set
+         -ENXIO: The overflow interrupt not set when attempting to get it
+         -ENODEV: PMUv3 not supported
+         -EINVAL: Invalid PMU overflow interrupt number supplied
+
+A value describing the PMUv3 (Performance Monitor Unit v3) overflow interrupt
+number for this vcpu. This interrupt could be a PPI or SPI, but the interrupt
+type must be same for each vcpu. As a PPI, the interrupt number is the same for
+all vcpus, while as an SPI it must be a separate number per vcpu.
+
+1.2 ATTRIBUTE: KVM_ARM_VCPU_PMU_V3_INIT
+Parameters: no additional parameter in kvm_device_attr.addr
+Returns: -ENODEV: PMUv3 not supported
+         -ENXIO: PMUv3 not properly configured as required prior to calling this
+                 attribute
+         -EBUSY: PMUv3 already initialized
+
+Request the initialization of the PMUv3.
index f083a168eb350b80895f25a23621b87a131be84b..a9ea8774a45feb50e463c8ff7c1f20dccd7f2052 100644 (file)
@@ -84,3 +84,55 @@ Returns:    -EBUSY in case 1 or more vcpus are already activated (only in write
            -EFAULT if the given address is not accessible from kernel space
            -ENOMEM if not enough memory is available to process the ioctl
            0 in case of success
+
+3. GROUP: KVM_S390_VM_TOD
+Architectures: s390
+
+3.1. ATTRIBUTE: KVM_S390_VM_TOD_HIGH
+
+Allows user space to set/get the TOD clock extension (u8).
+
+Parameters: address of a buffer in user space to store the data (u8) to
+Returns:    -EFAULT if the given address is not accessible from kernel space
+           -EINVAL if setting the TOD clock extension to != 0 is not supported
+
+3.2. ATTRIBUTE: KVM_S390_VM_TOD_LOW
+
+Allows user space to set/get bits 0-63 of the TOD clock register as defined in
+the POP (u64).
+
+Parameters: address of a buffer in user space to store the data (u64) to
+Returns:    -EFAULT if the given address is not accessible from kernel space
+
+4. GROUP: KVM_S390_VM_CRYPTO
+Architectures: s390
+
+4.1. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_AES_KW (w/o)
+
+Allows user space to enable aes key wrapping, including generating a new
+wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.2. ATTRIBUTE: KVM_S390_VM_CRYPTO_ENABLE_DEA_KW (w/o)
+
+Allows user space to enable dea key wrapping, including generating a new
+wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.3. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_AES_KW (w/o)
+
+Allows user space to disable aes key wrapping, clearing the wrapping key.
+
+Parameters: none
+Returns:    0
+
+4.4. ATTRIBUTE: KVM_S390_VM_CRYPTO_DISABLE_DEA_KW (w/o)
+
+Allows user space to disable dea key wrapping, clearing the wrapping key.
+
+Parameters: none
+Returns:    0
index daf9c0f742d22e882637391539e90ea31eb788f3..481b6a9c25d5a1737aef54f55a3aa712c859f970 100644 (file)
@@ -358,7 +358,8 @@ In the first case there are two additional complications:
 - if CR4.SMEP is enabled: since we've turned the page into a kernel page,
   the kernel may now execute it.  We handle this by also setting spte.nx.
   If we get a user fetch or read fault, we'll change spte.u=1 and
-  spte.nx=gpte.nx back.
+  spte.nx=gpte.nx back.  For this to work, KVM forces EFER.NX to 1 when
+  shadow paging is in use.
 - if CR4.SMAP is disabled: since the page has been changed to a kernel
   page, it can not be reused when CR4.SMAP is enabled. We set
   CR4.SMAP && !CR0.WP into shadow page's role to avoid this case. Note,
@@ -391,11 +392,11 @@ To instantiate a large spte, four constraints must be satisfied:
   write-protected pages
 - the guest page must be wholly contained by a single memory slot
 
-To check the last two conditions, the mmu maintains a ->write_count set of
+To check the last two conditions, the mmu maintains a ->disallow_lpage set of
 arrays for each memory slot and large page size.  Every write protected page
-causes its write_count to be incremented, thus preventing instantiation of
+causes its disallow_lpage to be incremented, thus preventing instantiation of
 a large spte.  The frames at the end of an unaligned memory slot have
-artificially inflated ->write_counts so they can never be instantiated.
+artificially inflated ->disallow_lpages so they can never be instantiated.
 
 Zapping all pages (page generation count)
 =========================================
index 8f3ce9b3aa11b27c52bc20b395765b5df0833d71..ffff1439076a51af81c83e91602c9bfd08bed308 100644 (file)
@@ -28,10 +28,11 @@ with page owner and page owner is disabled in runtime due to no enabling
 boot option, runtime overhead is marginal. If disabled in runtime, it
 doesn't require memory to store owner information, so there is no runtime
 memory overhead. And, page owner inserts just two unlikely branches into
-the page allocator hotpath and if it returns false then allocation is
-done like as the kernel without page owner. These two unlikely branches
-would not affect to allocation performance. Following is the kernel's
-code size change due to this facility.
+the page allocator hotpath and if not enabled, then allocation is done
+like as the kernel without page owner. These two unlikely branches should
+not affect to allocation performance, especially if the static keys jump
+label patching functionality is available. Following is the kernel's code
+size change due to this facility.
 
 - Without page owner
    text    data     bss     dec     hex filename
index f0d340959319e43481ba1b78177c3bece2a1c346..84652419bff25860595dde898b5de363bb98cf2b 100644 (file)
@@ -35,8 +35,8 @@ slub_debug=<Debug-Options>,<slab name>
                                Enable options only for select slabs
 
 Possible debug options are
-       F               Sanity checks on (enables SLAB_DEBUG_FREE. Sorry
-                       SLAB legacy issues)
+       F               Sanity checks on (enables SLAB_DEBUG_CONSISTENCY_CHECKS
+                       Sorry SLAB legacy issues)
        Z               Red zoning
        P               Poisoning (object and padding)
        U               User tracking (free and alloc)
index 9f9ec9f76039404a15114c97fe67535fe41fa88c..4e4b6f10d8410f84d8ea64ac51c68a6932bf2158 100644 (file)
@@ -400,3 +400,7 @@ wm8350_wdt:
 nowayout: Watchdog cannot be stopped once started
        (default=kernel config parameter)
 -------------------------------------------------
+sun4v_wdt:
+timeout_ms: Watchdog timeout in milliseconds 1..180000, default=60000)
+nowayout: Watchdog cannot be stopped once started
+-------------------------------------------------
index d62bea6796dad967a2fb651ecb4974d6e4ad2886..c956d99cf1de40a7b2ff49c7e02c9e5fcfa8f472 100644 (file)
@@ -40,3 +40,28 @@ cp ../microcode.bin kernel/x86/microcode/GenuineIntel.bin (or AuthenticAMD.bin)
 find . | cpio -o -H newc >../ucode.cpio
 cd ..
 cat ucode.cpio /boot/initrd-3.5.0.img >/boot/initrd-3.5.0.ucode.img
+
+Builtin microcode
+=================
+
+We can also load builtin microcode supplied through the regular firmware
+builtin method CONFIG_FIRMWARE_IN_KERNEL. Here's an example:
+
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin"
+CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware"
+
+This basically means, you have the following tree structure locally:
+
+/lib/firmware/
+|-- amd-ucode
+...
+|   |-- microcode_amd_fam15h.bin
+...
+|-- intel-ucode
+...
+|   |-- 06-3a-09
+...
+
+so that the build system can find those files and integrate them into
+the final kernel image. The early loader finds them and applies them.
index 32901aa36f0a99f7c087aa7c510bbceb0ec14a89..e396bcd8d830428a30231986fd6f1a2ee9bdd921 100644 (file)
@@ -290,3 +290,38 @@ Due to the way that the exception table is built and needs to be ordered,
 only use exceptions for code in the .text section.  Any other section
 will cause the exception table to not be sorted correctly, and the
 exceptions will fail.
+
+Things changed when 64-bit support was added to x86 Linux. Rather than
+double the size of the exception table by expanding the two entries
+from 32-bits to 64 bits, a clever trick was used to store addresses
+as relative offsets from the table itself. The assembly code changed
+from:
+       .long 1b,3b
+to:
+        .long (from) - .
+        .long (to) - .
+
+and the C-code that uses these values converts back to absolute addresses
+like this:
+
+       ex_insn_addr(const struct exception_table_entry *x)
+       {
+               return (unsigned long)&x->insn + x->insn;
+       }
+
+In v4.6 the exception table entry was expanded with a new field "handler".
+This is also 32-bits wide and contains a third relative function
+pointer which points to one of:
+
+1) int ex_handler_default(const struct exception_table_entry *fixup)
+   This is legacy case that just jumps to the fixup code
+2) int ex_handler_fault(const struct exception_table_entry *fixup)
+   This case provides the fault number of the trap that occurred at
+   entry->insn. It is used to distinguish page faults from machine
+   check.
+3) int ex_handler_ext(const struct exception_table_entry *fixup)
+   This case is used for uaccess_err ... we need to set a flag
+   in the task structure. Before the handler functions existed this
+   case was handled by adding a large offset to the fixup to tag
+   it as special.
+More functions can easily be added.
index 68ed3114c363bf7332b2515b156bf0953ca88d24..0965a71f994243e70b3ae04fe78f73263666c1af 100644 (file)
@@ -60,6 +60,8 @@ Machine check
                threshold to 1. Enabling this may make memory predictive failure
                analysis less effective if the bios sets thresholds for memory
                errors since we will not see details for all errors.
+   mce=recovery
+               Force-enable recoverable machine check code paths
 
    nomce (for compatibility with i386): same as mce=off
 
index 59231070d5449e84e50b74c19187c8f251e34aec..cb2789afd3f88a7cda07d6b0edd1257d953b3f1f 100644 (file)
@@ -920,17 +920,24 @@ M:        Emilio López <emilio@elopez.com.ar>
 S:     Maintained
 F:     drivers/clk/sunxi/
 
-ARM/Amlogic MesonX SoC support
+ARM/Amlogic Meson SoC support
 M:     Carlo Caione <carlo@caione.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-meson@googlegroups.com
+W:     http://linux-meson.com/
 S:     Maintained
-F:     drivers/media/rc/meson-ir.c
-N:     meson[x68]
+F:     arch/arm/mach-meson/
+F:     arch/arm/boot/dts/meson*
+N:     meson
 
 ARM/Annapurna Labs ALPINE ARCHITECTURE
 M:     Tsahee Zidenberg <tsahee@annapurnalabs.com>
+M:     Antoine Tenart <antoine.tenart@free-electrons.com>
 S:     Maintained
 F:     arch/arm/mach-alpine/
+F:     arch/arm/boot/dts/alpine*
+F:     arch/arm64/boot/dts/al/
+F:     drivers/*/*alpine*
 
 ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT
 M:     Nicolas Ferre <nicolas.ferre@atmel.com>
@@ -2415,6 +2422,7 @@ F:        arch/mips/bmips/*
 F:     arch/mips/include/asm/mach-bmips/*
 F:     arch/mips/kernel/*bmips*
 F:     arch/mips/boot/dts/brcm/bcm*.dts*
+F:     drivers/irqchip/irq-bcm63*
 F:     drivers/irqchip/irq-bcm7*
 F:     drivers/irqchip/irq-brcmstb*
 F:     include/linux/bcm963xx_nvram.h
@@ -3444,7 +3452,6 @@ F:        drivers/usb/dwc2/
 DESIGNWARE USB3 DRD IP DRIVER
 M:     Felipe Balbi <balbi@kernel.org>
 L:     linux-usb@vger.kernel.org
-L:     linux-omap@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:     Maintained
 F:     drivers/usb/dwc3/
@@ -4512,6 +4519,12 @@ L:       linuxppc-dev@lists.ozlabs.org
 S:     Maintained
 F:     drivers/dma/fsldma.*
 
+FREESCALE GPMI NAND DRIVER
+M:     Han Xu <han.xu@nxp.com>
+L:     linux-mtd@lists.infradead.org
+S:     Maintained
+F:     drivers/mtd/nand/gpmi-nand/*
+
 FREESCALE I2C CPM DRIVER
 M:     Jochen Friedrich <jochen@scram.de>
 L:     linuxppc-dev@lists.ozlabs.org
@@ -4528,7 +4541,7 @@ F:        include/linux/platform_data/video-imxfb.h
 F:     drivers/video/fbdev/imxfb.c
 
 FREESCALE QUAD SPI DRIVER
-M:     Han Xu <han.xu@freescale.com>
+M:     Han Xu <han.xu@nxp.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
 F:     drivers/mtd/spi-nor/fsl-quadspi.c
@@ -4542,6 +4555,15 @@ S:       Maintained
 F:     drivers/net/ethernet/freescale/fs_enet/
 F:     include/linux/fs_enet_pd.h
 
+FREESCALE IMX / MXC FEC DRIVER
+M:     Fugang Duan <fugang.duan@nxp.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/ethernet/freescale/fec_main.c
+F:     drivers/net/ethernet/freescale/fec_ptp.c
+F:     drivers/net/ethernet/freescale/fec.h
+F:     Documentation/devicetree/bindings/net/fsl-fec.txt
+
 FREESCALE QUICC ENGINE LIBRARY
 L:     linuxppc-dev@lists.ozlabs.org
 S:     Orphan
@@ -5183,6 +5205,7 @@ F:        arch/x86/kernel/cpu/mshyperv.c
 F:     drivers/hid/hid-hyperv.c
 F:     drivers/hv/
 F:     drivers/input/serio/hyperv-keyboard.c
+F:     drivers/pci/host/pci-hyperv.c
 F:     drivers/net/hyperv/
 F:     drivers/scsi/storvsc_drv.c
 F:     drivers/video/fbdev/hyperv_fb.c
@@ -6757,6 +6780,7 @@ S:        Maintained
 F:     Documentation/networking/mac80211-injection.txt
 F:     include/net/mac80211.h
 F:     net/mac80211/
+F:     drivers/net/wireless/mac80211_hwsim.[ch]
 
 MACVLAN DRIVER
 M:     Patrick McHardy <kaber@trash.net>
@@ -6886,7 +6910,7 @@ MAXIM MAX77802 MULTIFUNCTION PMIC DEVICE DRIVERS
 M:     Javier Martinez Canillas <javier@osg.samsung.com>
 L:     linux-kernel@vger.kernel.org
 S:     Supported
-F:     drivers/*/*max77802.c
+F:     drivers/*/*max77802*.c
 F:     Documentation/devicetree/bindings/*/*max77802.txt
 F:     include/dt-bindings/*/*max77802.h
 
@@ -6896,7 +6920,7 @@ M:        Krzysztof Kozlowski <k.kozlowski@samsung.com>
 L:     linux-kernel@vger.kernel.org
 S:     Supported
 F:     drivers/*/max14577.c
-F:     drivers/*/max77686.c
+F:     drivers/*/max77686*.c
 F:     drivers/*/max77693.c
 F:     drivers/extcon/extcon-max14577.c
 F:     drivers/extcon/extcon-max77693.c
@@ -7353,7 +7377,7 @@ F:        drivers/tty/isicom.c
 F:     include/linux/isicom.h
 
 MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
-M:     Felipe Balbi <balbi@kernel.org>
+M:     Bin Liu <b-liu@ti.com>
 L:     linux-usb@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:     Maintained
@@ -7376,6 +7400,17 @@ W:       https://www.myricom.com/support/downloads/myri10ge.html
 S:     Supported
 F:     drivers/net/ethernet/myricom/myri10ge/
 
+NAND FLASH SUBSYSTEM
+M:     Boris Brezillon <boris.brezillon@free-electrons.com>
+R:     Richard Weinberger <richard@nod.at>
+L:     linux-mtd@lists.infradead.org
+W:     http://www.linux-mtd.infradead.org/
+Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
+T:     git git://github.com/linux-nand/linux.git
+S:     Maintained
+F:     drivers/mtd/nand/
+F:     include/linux/mtd/nand*.h
+
 NATSEMI ETHERNET DRIVER (DP8381x)
 S:     Orphan
 F:     drivers/net/ethernet/natsemi/natsemi.c
@@ -7685,13 +7720,13 @@ S:      Maintained
 F:     arch/nios2/
 
 NOKIA N900 POWER SUPPLY DRIVERS
-M:     Pali Rohár <pali.rohar@gmail.com>
-S:     Maintained
+R:     Pali Rohár <pali.rohar@gmail.com>
 F:     include/linux/power/bq2415x_charger.h
 F:     include/linux/power/bq27xxx_battery.h
 F:     include/linux/power/isp1704_charger.h
 F:     drivers/power/bq2415x_charger.c
 F:     drivers/power/bq27xxx_battery.c
+F:     drivers/power/bq27xxx_battery_i2c.c
 F:     drivers/power/isp1704_charger.c
 F:     drivers/power/rx51_battery.c
 
@@ -7922,11 +7957,9 @@ F:       drivers/media/platform/omap3isp/
 F:     drivers/staging/media/omap4iss/
 
 OMAP USB SUPPORT
-M:     Felipe Balbi <balbi@kernel.org>
 L:     linux-usb@vger.kernel.org
 L:     linux-omap@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
-S:     Maintained
+S:     Orphan
 F:     drivers/usb/*/*omap*
 F:     arch/arm/*omap*/usb*
 
@@ -8350,12 +8383,20 @@ L:      linux-pci@vger.kernel.org
 S:     Maintained
 F:     drivers/pci/host/*designware*
 
+PCI DRIVER FOR SYNOPSYS PROTOTYPING DEVICE
+M:     Joao Pinto <jpinto@synopsys.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/pci/designware-pcie.txt
+F:     drivers/pci/host/pcie-designware-plat.c
+
 PCI DRIVER FOR GENERIC OF HOSTS
 M:     Will Deacon <will.deacon@arm.com>
 L:     linux-pci@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/pci/host-generic-pci.txt
+F:     drivers/pci/host/pci-host-common.c
 F:     drivers/pci/host/pci-host-generic.c
 
 PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
@@ -8401,6 +8442,14 @@ L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 F:     drivers/pci/host/*qcom*
 
+PCIE DRIVER FOR CAVIUM THUNDERX
+M:     David Daney <david.daney@cavium.com>
+L:     linux-pci@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Supported
+F:     Documentation/devicetree/bindings/pci/pci-thunder-*
+F:     drivers/pci/host/pci-thunder-*
+
 PCMCIA SUBSYSTEM
 P:     Linux PCMCIA Team
 L:     linux-pcmcia@lists.infradead.org
@@ -8443,6 +8492,7 @@ PERFORMANCE EVENTS SUBSYSTEM
 M:     Peter Zijlstra <peterz@infradead.org>
 M:     Ingo Molnar <mingo@redhat.com>
 M:     Arnaldo Carvalho de Melo <acme@kernel.org>
+R:     Alexander Shishkin <alexander.shishkin@linux.intel.com>
 L:     linux-kernel@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
 S:     Supported
@@ -9557,6 +9607,12 @@ M:       Andreas Noever <andreas.noever@gmail.com>
 S:     Maintained
 F:     drivers/thunderbolt/
 
+TI BQ27XXX POWER SUPPLY DRIVER
+R:     Andrew F. Davis <afd@ti.com>
+F:     include/linux/power/bq27xxx_battery.h
+F:     drivers/power/bq27xxx_battery.c
+F:     drivers/power/bq27xxx_battery_i2c.c
+
 TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER
 M:     John Stultz <john.stultz@linaro.org>
 M:     Thomas Gleixner <tglx@linutronix.de>
index fbe1b921798f9c985270ea95dfce7215f5abe8e9..7b3ecdcdc6c1815ca6241a72b1967593a0335b41 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION =
 NAME = Blurry Fish Butt
 
 # *DOCUMENTATION*
index 98f2eeee8f681117908a3958a4698de514388bd9..a06c24b3a2e13baaca1a4f41f16544a012f009a9 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <asm/machvec.h>
-#include <asm-generic/pci-bridge.h>
 
 /*
  * The following structure is used to manage multiple PCI busses.
@@ -66,13 +65,6 @@ extern void pcibios_set_master(struct pci_dev *dev);
    decisions.  */
 #define PCI_DMA_BUS_IS_PHYS  0
 
-#ifdef CONFIG_PCI
-
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
-#endif
-
 /* TODO: integrate with include/asm-generic/pci.h ? */
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
index 2f24447fef92071b0ba9b94d09f8ed1fdc25d2d1..46bf263c315318cabb1c1530e6584f2060512497 100644 (file)
@@ -168,7 +168,7 @@ smp_callin(void)
              cpuid, current, current->active_mm));
 
        preempt_disable();
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 /* Wait until hwrpb->txrdy is clear for cpu.  Return -1 on timeout.  */
index 0655495470ad499acc022d622914746929d47ea1..07a5cb944d4ff730d1015cdcbff9ffc82d3905f8 100644 (file)
@@ -12,13 +12,12 @@ config ARC
        select BUILDTIME_EXTABLE_SORT
        select COMMON_CLK
        select CLONE_BACKWARDS
-       # ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
-       select DEVTMPFS if !INITRAMFS_SOURCE=""
        select GENERIC_ATOMIC64
        select GENERIC_CLOCKEVENTS
        select GENERIC_FIND_FIRST_BIT
        # for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
        select GENERIC_IRQ_SHOW
+       select GENERIC_PCI_IOMAP
        select GENERIC_PENDING_IRQ if SMP
        select GENERIC_SMP_IDLE_THREAD
        select HAVE_ARCH_KGDB
@@ -39,6 +38,9 @@ config ARC
        select PERF_USE_VMALLOC
        select HAVE_DEBUG_STACKOVERFLOW
 
+config MIGHT_HAVE_PCI
+       bool
+
 config TRACE_IRQFLAGS_SUPPORT
        def_bool y
 
@@ -275,14 +277,6 @@ config ARC_DCCM_BASE
        default "0xA0000000"
        depends on ARC_HAS_DCCM
 
-config ARC_HAS_HW_MPY
-       bool "Use Hardware Multiplier (Normal or Faster XMAC)"
-       default y
-       help
-         Influences how gcc generates code for MPY operations.
-         If enabled, MPYxx insns are generated, provided by Standard/XMAC
-         Multipler. Otherwise software multipy lib is used
-
 choice
        prompt "MMU Version"
        default ARC_MMU_V3 if ARC_CPU_770
@@ -542,14 +536,6 @@ config ARC_DBG_TLB_MISS_COUNT
          Counts number of I and D TLB Misses and exports them via Debugfs
          The counters can be cleared via Debugfs as well
 
-if SMP
-
-config ARC_IPI_DBG
-       bool "Debug Inter Core interrupts"
-       default n
-
-endif
-
 endif
 
 config ARC_UBOOT_SUPPORT
@@ -587,6 +573,28 @@ config FORCE_MAX_ZONEORDER
 
 source "net/Kconfig"
 source "drivers/Kconfig"
+
+menu "Bus Support"
+
+config PCI
+       bool "PCI support" if MIGHT_HAVE_PCI
+       help
+         PCI is the name of a bus system, i.e., the way the CPU talks to
+         the other stuff inside your box.  Find out if your board/platform
+         has PCI.
+
+         Note: PCIe support for Synopsys Device will be available only
+         when HAPS DX is configured with PCIe RC bitmap. If you have PCI,
+         say Y, otherwise N.
+
+config PCI_SYSCALL
+       def_bool PCI
+
+source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
+
+endmenu
+
 source "fs/Kconfig"
 source "arch/arc/Kconfig.debug"
 source "security/Kconfig"
index aeb19021099e315967ba95524e9528c48da0d159..c8230f3395f281f9c11ee6de130137d84e1bb543 100644 (file)
@@ -74,10 +74,6 @@ ldflags-$(CONFIG_CPU_BIG_ENDIAN)     += -EB
 # --build-id w/o "-marclinux". Default arc-elf32-ld is OK
 ldflags-$(upto_gcc44)                  += -marclinux
 
-ifndef CONFIG_ARC_HAS_HW_MPY
-       cflags-y        += -mno-mpy
-endif
-
 LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name)
 
 # Modules with short calls might break for calls into builtin-kernel
index f1ac9818b751e1fab854f2c1a4440b9ca8af3e85..5d4e2a07ad3eb8d11c605f385b881769d44b16ae 100644 (file)
@@ -39,6 +39,7 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -73,7 +74,6 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_LOGO=y
@@ -91,12 +91,10 @@ CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT3_FS=y
-CONFIG_EXT4_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
index 323486d6ee83419a9e50d5c53fa042f53e08ebed..87ee46b237ef7baa6dc5008f968e5c914d03aee4 100644 (file)
@@ -39,14 +39,10 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_AXS=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
@@ -78,14 +74,12 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
@@ -97,12 +91,10 @@ CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT3_FS=y
-CONFIG_EXT4_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
index 66191cd0447eaabc524a36ec497e7047043dc9a4..d80daf4f7e735aa3787df6f75957c2b9a273b361 100644 (file)
@@ -40,14 +40,10 @@ CONFIG_IP_PNP_RARP=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_AXS=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
@@ -79,14 +75,12 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
 # CONFIG_LOGO_LINUX_CLUT224 is not set
-CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
@@ -98,12 +92,10 @@ CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT3_FS=y
-CONFIG_EXT4_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
index 138f9d8879570a8b329415d9238c710fa6e5b032..f41095340b6a7a8662fc4e51e16e39524f359ae7 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -26,7 +27,6 @@ CONFIG_ARC_PLAT_SIM=y
 CONFIG_ARC_BUILTIN_DTB_NAME="nsim_700"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -34,6 +34,7 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -51,7 +52,6 @@ CONFIG_SERIAL_ARC=y
 CONFIG_SERIAL_ARC_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_IOMMU_SUPPORT is not set
@@ -63,4 +63,3 @@ CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_DEBUG_PREEMPT is not set
-CONFIG_XZ_DEC=y
index f68838e8068af53eb2ebb29c83d88cb10dc0bfac..cfaa33cb59217c6261667ec4d51b2762fea985ab 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -49,7 +50,6 @@ CONFIG_SERIAL_ARC=y
 CONFIG_SERIAL_ARC_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_IOMMU_SUPPORT is not set
@@ -61,4 +61,3 @@ CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 # CONFIG_DEBUG_PREEMPT is not set
-CONFIG_XZ_DEC=y
index 96bd1c20fb0badeb5d3ebf41f2671f6558939c22..bb2a8dc778b5be48943f25f4415abbe73c476969 100644 (file)
@@ -2,6 +2,7 @@ CONFIG_CROSS_COMPILE="arc-linux-"
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
@@ -21,13 +22,11 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_SIM=y
-CONFIG_ARC_BOARD_ML509=y
 CONFIG_ISA_ARCV2=y
 CONFIG_SMP=y
 CONFIG_ARC_BUILTIN_DTB_NAME="nsim_hs_idu"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -35,6 +34,7 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -49,7 +49,6 @@ CONFIG_SERIAL_ARC=y
 CONFIG_SERIAL_ARC_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_IOMMU_SUPPORT is not set
@@ -60,4 +59,3 @@ CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_XZ_DEC=y
index 31e1d95764ff91dc10fe80d936a5613e6f713cc4..646182e93753af74110471f7739fab2454246b1b 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -58,7 +59,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_HID is not set
index fcae66683ca0bd5865924a88816a388e763604cd..ceca2541950d1bbe7f950bad17ab2c598c79c65a 100644 (file)
@@ -34,12 +34,12 @@ CONFIG_UNIX_DIAG=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 # CONFIG_IPV6 is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_BLK_DEV is not set
 CONFIG_NETDEVICES=y
-CONFIG_NET_OSCI_LAN=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_MOUSE_PS2_ALPS is not set
 # CONFIG_MOUSE_PS2_LOGIPS2PP is not set
@@ -58,7 +58,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_HID is not set
index b01b659168ea4a1c36ac85e0ee41c545aa697ec8..4b6da90f6f261e3d9783719a5bbc2060bf2e8408 100644 (file)
@@ -2,6 +2,7 @@ CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="ARCLinux"
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
@@ -18,15 +19,11 @@ CONFIG_MODULES=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARC_PLAT_SIM=y
-CONFIG_ARC_BOARD_ML509=y
 CONFIG_ISA_ARCV2=y
 CONFIG_SMP=y
-CONFIG_ARC_HAS_LL64=y
-# CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs_idu"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=y
@@ -40,6 +37,7 @@ CONFIG_INET=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -56,14 +54,11 @@ CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
-CONFIG_NET_OSCI_LAN=y
 # CONFIG_WLAN is not set
 CONFIG_INPUT_EVDEV=y
 CONFIG_MOUSE_PS2_TOUCHKIT=y
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIO_LIBPS2=y
 CONFIG_SERIO_ARC_PS2=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
@@ -75,9 +70,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_HWMON is not set
 CONFIG_FB=y
-CONFIG_ARCPGU_RGB888=y
-CONFIG_ARCPGU_DISPTYPE=0
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 # CONFIG_HID is not set
index 3b4dc9cebcf15234f3d42a4efd2e40b9c5bd4150..9b342eaf95aec97830e155a00250d3d419e6d24d 100644 (file)
@@ -3,6 +3,7 @@ CONFIG_CROSS_COMPILE="arc-linux-"
 CONFIG_DEFAULT_HOSTNAME="tb10x"
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -26,12 +27,10 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLOCK is not set
 CONFIG_ARC_PLAT_TB10X=y
 CONFIG_ARC_CACHE_LINE_SHIFT=5
-CONFIG_ARC_STACK_NONEXEC=y
 CONFIG_HZ=250
 CONFIG_ARC_BUILTIN_DTB_NAME="abilis_tb100_dvk"
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_COMPACTION is not set
-# CONFIG_CROSS_MEMORY_ATTACH is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -44,8 +43,8 @@ CONFIG_IP_MULTICAST=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
-CONFIG_PROC_DEVICETREE=y
 CONFIG_NETDEVICES=y
 # CONFIG_NET_CADENCE is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
@@ -55,9 +54,6 @@ CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 CONFIG_STMMAC_ETH=y
-CONFIG_STMMAC_DEBUG_FS=y
-CONFIG_STMMAC_DA=y
-CONFIG_STMMAC_CHAINED=y
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
@@ -91,7 +87,6 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_LEDS_TRIGGER_TRANSIENT=y
 CONFIG_DMADEVICES=y
 CONFIG_DW_DMAC=y
-CONFIG_NET_DMA=y
 CONFIG_ASYNC_TX_DMA=y
 # CONFIG_IOMMU_SUPPORT is not set
 # CONFIG_DNOTIFY is not set
@@ -100,17 +95,16 @@ CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_DEBUG_INFO=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_FS=y
 CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_DEBUG_STACKOVERFLOW=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
index fdc5be5b10295d612e0b1b70765c74641d55814c..f9f4c6f59fdbb3f450ec13420e94f2ee1cb4428c 100644 (file)
@@ -10,7 +10,8 @@
 #define _ASM_ARC_ARCREGS_H
 
 /* Build Configuration Registers */
-#define ARC_REG_DCCMBASE_BCR   0x61    /* DCCM Base Addr */
+#define ARC_REG_AUX_DCCM       0x18    /* DCCM Base Addr ARCv2 */
+#define ARC_REG_DCCM_BASE_BUILD        0x61    /* DCCM Base Addr ARCompact */
 #define ARC_REG_CRC_BCR                0x62
 #define ARC_REG_VECBASE_BCR    0x68
 #define ARC_REG_PERIBASE_BCR   0x69
 #define ARC_REG_DPFP_BCR       0x6C    /* ARCompact: Dbl Precision FPU */
 #define ARC_REG_FP_V2_BCR      0xc8    /* ARCv2 FPU */
 #define ARC_REG_SLC_BCR                0xce
-#define ARC_REG_DCCM_BCR       0x74    /* DCCM Present + SZ */
+#define ARC_REG_DCCM_BUILD     0x74    /* DCCM size (common) */
 #define ARC_REG_TIMERS_BCR     0x75
 #define ARC_REG_AP_BCR         0x76
-#define ARC_REG_ICCM_BCR       0x78
+#define ARC_REG_ICCM_BUILD     0x78    /* ICCM size (common) */
 #define ARC_REG_XY_MEM_BCR     0x79
 #define ARC_REG_MAC_BCR                0x7a
 #define ARC_REG_MUL_BCR                0x7b
@@ -36,6 +37,7 @@
 #define ARC_REG_IRQ_BCR                0xF3
 #define ARC_REG_SMART_BCR      0xFF
 #define ARC_REG_CLUSTER_BCR    0xcf
+#define ARC_REG_AUX_ICCM       0x208   /* ICCM Base Addr (ARCv2) */
 
 /* status32 Bits Positions */
 #define STATUS_AE_BIT          5       /* Exception active */
@@ -246,7 +248,7 @@ struct bcr_perip {
 #endif
 };
 
-struct bcr_iccm {
+struct bcr_iccm_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int base:16, pad:5, sz:3, ver:8;
 #else
@@ -254,17 +256,15 @@ struct bcr_iccm {
 #endif
 };
 
-/* DCCM Base Address Register: ARC_REG_DCCMBASE_BCR */
-struct bcr_dccm_base {
+struct bcr_iccm_arcv2 {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int addr:24, ver:8;
+       unsigned int pad:8, sz11:4, sz01:4, sz10:4, sz00:4, ver:8;
 #else
-       unsigned int ver:8, addr:24;
+       unsigned int ver:8, sz00:4, sz10:4, sz01:4, sz11:4, pad:8;
 #endif
 };
 
-/* DCCM RAM Configuration Register: ARC_REG_DCCM_BCR */
-struct bcr_dccm {
+struct bcr_dccm_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int res:21, sz:3, ver:8;
 #else
@@ -272,6 +272,14 @@ struct bcr_dccm {
 #endif
 };
 
+struct bcr_dccm_arcv2 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad2:12, cyc:3, pad1:1, sz1:4, sz0:4, ver:8;
+#else
+       unsigned int ver:8, sz0:4, sz1:4, pad1:1, cyc:3, pad2:12;
+#endif
+};
+
 /* ARCompact: Both SP and DP FPU BCRs have same format */
 struct bcr_fp_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
@@ -315,9 +323,9 @@ struct bcr_bpu_arcv2 {
 
 struct bcr_generic {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-       unsigned int pad:24, ver:8;
+       unsigned int info:24, ver:8;
 #else
-       unsigned int ver:8, pad:24;
+       unsigned int ver:8, info:24;
 #endif
 };
 
index ca7c45181de925a112443024d76e27d46933f6dd..01e47a69b034fcbe91cdce729c799064036c8b96 100644 (file)
 #define ASM_ARC_DMA_H
 
 #define MAX_DMA_ADDRESS 0xC0000000
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy   0
+#endif
 
 #endif
index 694ece8a024372bef7fd24b3ccb1e9dc323b4afe..947bf0cfdec0065632f6b9831ddbe2f48a3b8a33 100644 (file)
 extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
 extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
                                  unsigned long flags);
+static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+       return (void __iomem *)port;
+}
+
+static inline void ioport_unmap(void __iomem *addr)
+{
+}
+
 extern void iounmap(const void __iomem *addr);
 
 #define ioremap_nocache(phy, sz)       ioremap(phy, sz)
index 4fd7d62a6e30aa513b9e04f6ee881c219b96da96..49014f0ef36d19458203b904f41513f776aeedff 100644 (file)
 #ifdef CONFIG_ISA_ARCOMPACT
 #define TIMER0_IRQ      3
 #define TIMER1_IRQ      4
-#define IPI_IRQ                (NR_CPU_IRQS-1) /* dummy to enable SMP build for up hardware */
 #else
 #define TIMER0_IRQ      16
 #define TIMER1_IRQ      17
-#define IPI_IRQ         19
 #endif
 
 #include <linux/interrupt.h>
index 1fc18ee06cf2df7f3dc971241f38f846a857133b..37c2f751eebf03d8f9f16d997bacdcb5b8f6323f 100644 (file)
@@ -22,6 +22,7 @@
 #define AUX_IRQ_CTRL           0x00E
 #define AUX_IRQ_ACT            0x043   /* Active Intr across all levels */
 #define AUX_IRQ_LVL_PEND       0x200   /* Pending Intr across all levels */
+#define AUX_IRQ_HINT           0x201   /* For generating Soft Interrupts */
 #define AUX_IRQ_PRIORITY       0x206
 #define ICAUSE                 0x40a
 #define AUX_IRQ_SELECT         0x40b
@@ -115,6 +116,16 @@ static inline int arch_irqs_disabled(void)
        return arch_irqs_disabled_flags(arch_local_save_flags());
 }
 
+static inline void arc_softirq_trigger(int irq)
+{
+       write_aux_reg(AUX_IRQ_HINT, irq);
+}
+
+static inline void arc_softirq_clear(int irq)
+{
+       write_aux_reg(AUX_IRQ_HINT, 0);
+}
+
 #else
 
 .macro IRQ_DISABLE  scratch
diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
new file mode 100644 (file)
index 0000000..ba56c23
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.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 _ASM_ARC_PCI_H
+#define _ASM_ARC_PCI_H
+
+#ifdef __KERNEL__
+#include <linux/ioport.h>
+
+#define PCIBIOS_MIN_IO 0x100
+#define PCIBIOS_MIN_MEM 0x100000
+
+#define pcibios_assign_all_busses()    1
+/*
+ * The PCI address space does equal the physical memory address space.
+ * The networking and block device layers use this boolean for bounce
+ * buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS    1
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_ARC_PCI_H */
index e7f3625a19b51dc5f117e13fc71b2930bbb4b52d..1bc2036b19d754c00beee3187abd6a3ba013d099 100644 (file)
@@ -12,6 +12,7 @@ obj-y := arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
 obj-y  += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
 obj-$(CONFIG_ISA_ARCOMPACT)            += entry-compact.o intc-compact.o
 obj-$(CONFIG_ISA_ARCV2)                        += entry-arcv2.o intc-arcv2.o
+obj-$(CONFIG_PCI)                      += pcibios.o
 
 obj-$(CONFIG_MODULES)                  += arcksyms.o module.o
 obj-$(CONFIG_SMP)                      += smp.o
index b178302947065660bc4765d86f66276045e29055..c1264607bbff3dca457fd47b8f078b62993b7af7 100644 (file)
@@ -45,11 +45,12 @@ VECTOR      reserved                ; Reserved slots
 VECTOR handle_interrupt        ; (16) Timer0
 VECTOR handle_interrupt        ; unused (Timer1)
 VECTOR handle_interrupt        ; unused (WDT)
-VECTOR handle_interrupt        ; (19) ICI (inter core interrupt)
-VECTOR handle_interrupt
-VECTOR handle_interrupt
-VECTOR handle_interrupt
-VECTOR handle_interrupt        ; (23) End of fixed IRQs
+VECTOR handle_interrupt        ; (19) Inter core Interrupt (IPI)
+VECTOR handle_interrupt        ; (20) perf Interrupt
+VECTOR handle_interrupt        ; (21) Software Triggered Intr (Self IPI)
+VECTOR handle_interrupt        ; unused
+VECTOR handle_interrupt        ; (23) unused
+# End of fixed IRQs
 
 .rept CONFIG_ARC_NUMBER_OF_INTERRUPTS - 8
        VECTOR  handle_interrupt
index 06bcedf19b622b4ef26503660349bc07a8a52d2e..224d1c3aa9c41dafdf52554450c2fa3b32ac8689 100644 (file)
@@ -81,9 +81,6 @@ static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
 {
        switch (irq) {
        case TIMER0_IRQ:
-#ifdef CONFIG_SMP
-       case IPI_IRQ:
-#endif
                irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
                break;
        default:
index bc771f58fefb4a9c67c90781bf520d4004f61fa2..c41c364b926cab9f50b6550e501f3ea1a8300017 100644 (file)
 #include <linux/smp.h>
 #include <linux/irq.h>
 #include <linux/spinlock.h>
+#include <asm/irqflags-arcv2.h>
 #include <asm/mcip.h>
 #include <asm/setup.h>
 
+#define IPI_IRQ                19
+#define SOFTIRQ_IRQ    21
+
 static char smp_cpuinfo_buf[128];
 static int idu_detected;
 
@@ -22,6 +26,7 @@ static DEFINE_RAW_SPINLOCK(mcip_lock);
 static void mcip_setup_per_cpu(int cpu)
 {
        smp_ipi_irq_setup(cpu, IPI_IRQ);
+       smp_ipi_irq_setup(cpu, SOFTIRQ_IRQ);
 }
 
 static void mcip_ipi_send(int cpu)
@@ -29,46 +34,44 @@ static void mcip_ipi_send(int cpu)
        unsigned long flags;
        int ipi_was_pending;
 
+       /* ARConnect can only send IPI to others */
+       if (unlikely(cpu == raw_smp_processor_id())) {
+               arc_softirq_trigger(SOFTIRQ_IRQ);
+               return;
+       }
+
+       raw_spin_lock_irqsave(&mcip_lock, flags);
+
        /*
-        * NOTE: We must spin here if the other cpu hasn't yet
-        * serviced a previous message. This can burn lots
-        * of time, but we MUST follows this protocol or
-        * ipi messages can be lost!!!
-        * Also, we must release the lock in this loop because
-        * the other side may get to this same loop and not
-        * be able to ack -- thus causing deadlock.
+        * If receiver already has a pending interrupt, elide sending this one.
+        * Linux cross core calling works well with concurrent IPIs
+        * coalesced into one
+        * see arch/arc/kernel/smp.c: ipi_send_msg_one()
         */
+       __mcip_cmd(CMD_INTRPT_READ_STATUS, cpu);
+       ipi_was_pending = read_aux_reg(ARC_REG_MCIP_READBACK);
+       if (!ipi_was_pending)
+               __mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu);
 
-       do {
-               raw_spin_lock_irqsave(&mcip_lock, flags);
-               __mcip_cmd(CMD_INTRPT_READ_STATUS, cpu);
-               ipi_was_pending = read_aux_reg(ARC_REG_MCIP_READBACK);
-               if (ipi_was_pending == 0)
-                       break; /* break out but keep lock */
-               raw_spin_unlock_irqrestore(&mcip_lock, flags);
-       } while (1);
-
-       __mcip_cmd(CMD_INTRPT_GENERATE_IRQ, cpu);
        raw_spin_unlock_irqrestore(&mcip_lock, flags);
-
-#ifdef CONFIG_ARC_IPI_DBG
-       if (ipi_was_pending)
-               pr_info("IPI ACK delayed from cpu %d\n", cpu);
-#endif
 }
 
 static void mcip_ipi_clear(int irq)
 {
        unsigned int cpu, c;
        unsigned long flags;
-       unsigned int __maybe_unused copy;
+
+       if (unlikely(irq == SOFTIRQ_IRQ)) {
+               arc_softirq_clear(irq);
+               return;
+       }
 
        raw_spin_lock_irqsave(&mcip_lock, flags);
 
        /* Who sent the IPI */
        __mcip_cmd(CMD_INTRPT_CHECK_SOURCE, 0);
 
-       copy = cpu = read_aux_reg(ARC_REG_MCIP_READBACK);       /* 1,2,4,8... */
+       cpu = read_aux_reg(ARC_REG_MCIP_READBACK);      /* 1,2,4,8... */
 
        /*
         * In rare case, multiple concurrent IPIs sent to same target can
@@ -82,12 +85,6 @@ static void mcip_ipi_clear(int irq)
        } while (cpu);
 
        raw_spin_unlock_irqrestore(&mcip_lock, flags);
-
-#ifdef CONFIG_ARC_IPI_DBG
-       if (c != __ffs(copy))
-               pr_info("IPIs from %x coalesced to %x\n",
-                       copy, raw_smp_processor_id());
-#endif
 }
 
 static void mcip_probe_n_setup(void)
@@ -111,10 +108,11 @@ static void mcip_probe_n_setup(void)
        READ_BCR(ARC_REG_MCIP_BCR, mp);
 
        sprintf(smp_cpuinfo_buf,
-               "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s\n",
+               "Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s%s\n",
                mp.ver, mp.num_cores,
                IS_AVAIL1(mp.ipi, "IPI "),
                IS_AVAIL1(mp.idu, "IDU "),
+               IS_AVAIL1(mp.llm, "LLM "),
                IS_AVAIL1(mp.dbg, "DEBUG "),
                IS_AVAIL1(mp.gfrc, "GFRC"));
 
diff --git a/arch/arc/kernel/pcibios.c b/arch/arc/kernel/pcibios.c
new file mode 100644 (file)
index 0000000..72e1d73
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014-2015 Synopsys, Inc. (www.synopsys.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.
+ */
+
+#include <linux/pci.h>
+
+/*
+ * We don't have to worry about legacy ISA devices, so nothing to do here
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+                               resource_size_t size, resource_size_t align)
+{
+       return res->start;
+}
+
+void pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
index a7edceba5f8447db5c2a2a28be9e87c78ef0a511..cdc821df1809209df9792bcf9ecada0bc991753f 100644 (file)
@@ -42,6 +42,53 @@ struct task_struct *_current_task[NR_CPUS];  /* For stack switching */
 
 struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
 
+static void read_decode_ccm_bcr(struct cpuinfo_arc *cpu)
+{
+       if (is_isa_arcompact()) {
+               struct bcr_iccm_arcompact iccm;
+               struct bcr_dccm_arcompact dccm;
+
+               READ_BCR(ARC_REG_ICCM_BUILD, iccm);
+               if (iccm.ver) {
+                       cpu->iccm.sz = 4096 << iccm.sz; /* 8K to 512K */
+                       cpu->iccm.base_addr = iccm.base << 16;
+               }
+
+               READ_BCR(ARC_REG_DCCM_BUILD, dccm);
+               if (dccm.ver) {
+                       unsigned long base;
+                       cpu->dccm.sz = 2048 << dccm.sz; /* 2K to 256K */
+
+                       base = read_aux_reg(ARC_REG_DCCM_BASE_BUILD);
+                       cpu->dccm.base_addr = base & ~0xF;
+               }
+       } else {
+               struct bcr_iccm_arcv2 iccm;
+               struct bcr_dccm_arcv2 dccm;
+               unsigned long region;
+
+               READ_BCR(ARC_REG_ICCM_BUILD, iccm);
+               if (iccm.ver) {
+                       cpu->iccm.sz = 256 << iccm.sz00;        /* 512B to 16M */
+                       if (iccm.sz00 == 0xF && iccm.sz01 > 0)
+                               cpu->iccm.sz <<= iccm.sz01;
+
+                       region = read_aux_reg(ARC_REG_AUX_ICCM);
+                       cpu->iccm.base_addr = region & 0xF0000000;
+               }
+
+               READ_BCR(ARC_REG_DCCM_BUILD, dccm);
+               if (dccm.ver) {
+                       cpu->dccm.sz = 256 << dccm.sz0;
+                       if (dccm.sz0 == 0xF && dccm.sz1 > 0)
+                               cpu->dccm.sz <<= dccm.sz1;
+
+                       region = read_aux_reg(ARC_REG_AUX_DCCM);
+                       cpu->dccm.base_addr = region & 0xF0000000;
+               }
+       }
+}
+
 static void read_arc_build_cfg_regs(void)
 {
        struct bcr_perip uncached_space;
@@ -76,36 +123,11 @@ static void read_arc_build_cfg_regs(void)
        cpu->extn.swap = read_aux_reg(ARC_REG_SWAP_BCR) ? 1 : 0;        /* 1,3 */
        cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR) ? 1 : 0;
        cpu->extn.minmax = read_aux_reg(ARC_REG_MIXMAX_BCR) > 1 ? 1 : 0; /* 2 */
-
-       /* Note that we read the CCM BCRs independent of kernel config
-        * This is to catch the cases where user doesn't know that
-        * CCMs are present in hardware build
-        */
-       {
-               struct bcr_iccm iccm;
-               struct bcr_dccm dccm;
-               struct bcr_dccm_base dccm_base;
-               unsigned int bcr_32bit_val;
-
-               bcr_32bit_val = read_aux_reg(ARC_REG_ICCM_BCR);
-               if (bcr_32bit_val) {
-                       iccm = *((struct bcr_iccm *)&bcr_32bit_val);
-                       cpu->iccm.base_addr = iccm.base << 16;
-                       cpu->iccm.sz = 0x2000 << (iccm.sz - 1);
-               }
-
-               bcr_32bit_val = read_aux_reg(ARC_REG_DCCM_BCR);
-               if (bcr_32bit_val) {
-                       dccm = *((struct bcr_dccm *)&bcr_32bit_val);
-                       cpu->dccm.sz = 0x800 << (dccm.sz);
-
-                       READ_BCR(ARC_REG_DCCMBASE_BCR, dccm_base);
-                       cpu->dccm.base_addr = dccm_base.addr << 8;
-               }
-       }
-
        READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem);
 
+       /* Read CCM BCRs for boot reporting even if not enabled in Kconfig */
+       read_decode_ccm_bcr(cpu);
+
        read_decode_mmu_bcr();
        read_decode_cache_bcr();
 
@@ -237,8 +259,6 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 
                        n += scnprintf(buf + n, len - n, "mpy[opt %d] ", opt);
                }
-               n += scnprintf(buf + n, len - n, "%s",
-                              IS_USED_CFG(CONFIG_ARC_HAS_HW_MPY));
        }
 
        n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n",
index ef6e9e15b82abf72d946ab45c3e20096854605c5..4cb3add77c75cc8da0600f385c8851fa12559240 100644 (file)
@@ -142,7 +142,7 @@ void start_kernel_secondary(void)
 
        local_irq_enable();
        preempt_disable();
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 /*
@@ -336,11 +336,8 @@ irqreturn_t do_IPI(int irq, void *dev_id)
                int rc;
 
                rc = __do_IPI(msg);
-#ifdef CONFIG_ARC_IPI_DBG
-               /* IPI received but no valid @msg */
                if (rc)
                        pr_info("IPI with bogus msg %ld in %ld\n", msg, copy);
-#endif
                pending &= ~(1U << msg);
        } while (pending);
 
index d475f9d4847c05dc844efcaf8c0edf21ad868ad1..426ac4b8bb393889ae15947403b96f2c76eae345 100644 (file)
@@ -11,6 +11,7 @@ menuconfig ARC_PLAT_AXS10X
        select DW_APB_ICTL
        select GPIO_DWAPB
        select OF_GPIO
+       select MIGHT_HAVE_PCI
        select GENERIC_IRQ_CHIP
        select ARCH_REQUIRE_GPIOLIB
        help
index 4f799e567fc870502ae147f3c26c5bb402315a9d..1d00da16d980707e633a2391fac51381254276a7 100644 (file)
@@ -1212,7 +1212,6 @@ config PCI_HOST_ITE8152
        select DMABOUNCE
 
 source "drivers/pci/Kconfig"
-source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
index 7a6a58ef8aaf815728fd59b0ca7af752495595b0..43788b1a1ac5e64372e1f3d3b012ba97a2e2d6ea 100644 (file)
@@ -195,5 +195,7 @@ CFLAGS_font.o := -Dstatic=
 $(obj)/font.c: $(FONTC)
        $(call cmd,shipped)
 
+AFLAGS_hyp-stub.o := -Wa,-march=armv7-a
+
 $(obj)/hyp-stub.S: $(srctree)/arch/$(SRCARCH)/kernel/hyp-stub.S
        $(call cmd,shipped)
index f3db13d2d90e7d457954c2cd93f3b9df45cb57d2..0cc150b87b86271a7b177afbbc5da952f70aa636 100644 (file)
        };
 };
 
+
+/include/ "tps65217.dtsi"
+
 &tps {
-       compatible = "ti,tps65217";
        /*
         * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
         * mode") at poweroff.  Most BeagleBone versions do not support RTC-only
        ti,pmic-shutdown-controller;
 
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        regulator-name = "vdds_dpr";
                        regulator-always-on;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <925000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <925000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        regulator-name = "vio,vrtc,vdds";
                        regulator-always-on;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        regulator-name = "vdd_3v3aux";
                        regulator-always-on;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        regulator-name = "vdd_1v8";
                        regulator-always-on;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        regulator-name = "vdd_3v3a";
                        regulator-always-on;
                };
index fda457b07e15c282887ede12eee576d56c6f3855..857d9894103a9edf6a7754585b5dddd6276d74e6 100644 (file)
 
 };
 
-&tps {
-       compatible = "ti,tps65217";
+/include/ "tps65217.dtsi"
 
+&tps {
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        regulator-name = "vdds_dpr";
                        regulator-always-on;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <925000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <925000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        regulator-name = "vio,vrtc,vdds";
                        regulator-boot-on;
                        regulator-always-on;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        regulator-name = "vdd_3v3aux";
                        regulator-boot-on;
                        regulator-always-on;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        regulator-name = "vdd_1v8";
                        regulator-boot-on;
                        regulator-always-on;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        regulator-name = "vdd_3v3d";
                        regulator-boot-on;
                        regulator-always-on;
index 77559a1ded60fb4530d90aef42323ca187ed6ac9..f313999c503e1df2add311257af95594d51e464e 100644 (file)
        wp-gpios = <&gpio3 18 0>;
 };
 
-&tps {
-       compatible = "ti,tps65217";
+#include "tps65217.dtsi"
 
+&tps {
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        /* +1.5V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <1450000>;
                        regulator-max-microvolt = <1550000>;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_MPU voltage limits 0.95V - 1.1V with Â±4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <915000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_CORE voltage limits 0.95V - 1.1V with Â±4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <915000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        /* +1.8V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <1750000>;
                        regulator-max-microvolt = <1870000>;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        /* +3.3V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <3175000>;
                        regulator-max-microvolt = <3430000>;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        /* +1.8V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <1750000>;
                        regulator-max-microvolt = <1870000>;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        /* +3.3V voltage with Â±4% tolerance */
                        regulator-min-microvolt = <3175000>;
                        regulator-max-microvolt = <3430000>;
index 471a3a70ea1f173ce15190f77443e6860e15c328..8867aaaec54d565de7f147af80e2e1cb6c4b2967 100644 (file)
        vin-supply = <&vbat>;
 };
 
-&tps {
-       compatible = "ti,tps65217";
+/include/ "tps65217.dtsi"
 
+&tps {
        backlight {
                isel = <1>; /* ISET1 */
                fdim = <200>; /* TPS65217_BL_FDIM_200HZ */
        };
 
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        /* VDD_1V8 system supply */
                        regulator-always-on;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_CORE voltage limits 0.95V - 1.26V with +/-4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <925000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_MPU voltage limits 0.95V - 1.1V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <925000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        /* VRTC 1.8V always-on supply */
                        regulator-name = "vrtc,vdds";
                        regulator-always-on;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        /* 3.3V rail */
                        regulator-name = "vdd_3v3aux";
                        regulator-always-on;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        /* VDD_3V3A 3.3V rail */
                        regulator-name = "vdd_3v3a";
                        regulator-min-microvolt = <3300000>;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        /* VDD_3V3B 3.3V rail */
                        regulator-name = "vdd_3v3b";
                        regulator-always-on;
index 1b5b044fcd910bc316863370ba4cfe6cab976530..865de8500f1c85cb8505dcf5d35c07c4a660aed9 100644 (file)
@@ -46,7 +46,7 @@
                        gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
                        linux,code = <KEY_BACK>;
                        debounce-interval = <1000>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
 
                front_button {
@@ -54,7 +54,7 @@
                        gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
                        linux,code = <KEY_FRONT>;
                        debounce-interval = <1000>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                };
        };
 
index d38edfa53bb9a95df14936af36dc600c55e8e2bc..3303c281697b017901f103aa96fee5af0a25ef8a 100644 (file)
        pinctrl-0 = <&uart4_pins>;
 };
 
+#include "tps65217.dtsi"
+
 &tps {
-       compatible = "ti,tps65217";
        ti,pmic-shutdown-controller;
 
        interrupt-parent = <&intc>;
        interrupts = <7>;       /* NNMI */
 
        regulators {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
                dcdc1_reg: regulator@0 {
-                       reg = <0>;
                        /* VDDS_DDR */
                        regulator-min-microvolt = <1500000>;
                        regulator-max-microvolt = <1500000>;
                };
 
                dcdc2_reg: regulator@1 {
-                       reg = <1>;
                        /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <925000>;
                };
 
                dcdc3_reg: regulator@2 {
-                       reg = <2>;
                        /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
                        regulator-name = "vdd_core";
                        regulator-min-microvolt = <925000>;
                };
 
                ldo1_reg: regulator@3 {
-                       reg = <3>;
                        /* VRTC / VIO / VDDS*/
                        regulator-always-on;
                        regulator-min-microvolt = <1800000>;
                };
 
                ldo2_reg: regulator@4 {
-                       reg = <4>;
                        /* VDD_3V3AUX */
                        regulator-always-on;
                        regulator-min-microvolt = <3300000>;
                };
 
                ldo3_reg: regulator@5 {
-                       reg = <5>;
                        /* VDD_1V8 */
                        regulator-min-microvolt = <1800000>;
                        regulator-max-microvolt = <1800000>;
                };
 
                ldo4_reg: regulator@6 {
-                       reg = <6>;
                        /* VDD_3V3A */
                        regulator-min-microvolt = <3300000>;
                        regulator-max-microvolt = <3300000>;
index 36c0fa6c362ae32000701ffec7e81df73f2a187a..a0986c65be0cfa71856947c58f57abe8df61c7fd 100644 (file)
 
                sound0_master: simple-audio-card,codec {
                        sound-dai = <&tlv320aic3104>;
+                       assigned-clocks = <&clkoutmux2_clk_mux>;
+                       assigned-clock-parents = <&sys_clk2_dclk_div>;
                        clocks = <&clkout2_clk>;
                };
        };
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&mcasp3_pins_default>;
        pinctrl-1 = <&mcasp3_pins_sleep>;
+       assigned-clocks = <&mcasp3_ahclkx_mux>;
+       assigned-clock-parents = <&sys_clkin2>;
        status = "okay";
 
        op-mode = <0>;  /* MCASP_IIS_MODE */
index 8d93882dc8d541a77c870e635813c32a7c77b79d..1c06cb76da07c14132e60cd29f5406dab9e9db66 100644 (file)
                ti,debounce-tol = /bits/ 16 <10>;
                ti,debounce-rep = /bits/ 16 <1>;
 
-               linux,wakeup;
+               wakeup-source;
        };
 };
 
index 23fc670c0427710168ce41ef012f9e37b8218eb6..5c21b236721fcb9d6e2b5055cbc89ae9527df7f1 100644 (file)
@@ -70,8 +70,8 @@
        soc {
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
-                         MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                         MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                pcie-controller {
                        status = "okay";
index f774101416a5522841c475252d0a86842e475b29..ebe1d267406df5ab30e3a3189b669733eb8fcaa4 100644 (file)
@@ -76,8 +76,8 @@
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
                          MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000
-                         MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                         MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                devbus-bootcs {
                        status = "okay";
index 4878d7353069fc2720e15d76af307618daced15c..5730b875c4f51a1aa2743d8881b18d6dbc0b27cd 100644 (file)
@@ -95,8 +95,8 @@
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
                          MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000
-                         MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                         MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                devbus-bootcs {
                        status = "okay";
index fb9e1bbf23385b85b0b82ddb153b922b2d2e0178..8af463f26ea1e162360952dbc03c0a9bda807cd5 100644 (file)
@@ -65,8 +65,8 @@
        soc {
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
                        MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
-                       MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                       MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                       MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                       MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                pcie-controller {
                        status = "okay";
index 6e9820e141f8de5a850edcd7e74f0ea2a1acd1ed..b89e6cf1271a1370aead2a000e729cefad376ab0 100644 (file)
@@ -70,8 +70,8 @@
        soc {
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
-                         MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                         MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                pcie-controller {
                        status = "okay";
index 6ab33837a2b6d0a5aaf4e48763bb838451a346bd..6522b04f4a8e7c7a759100153d7d990f1fb160d3 100644 (file)
@@ -68,8 +68,8 @@
        soc {
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
-                         MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                         MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                internal-regs {
                        serial@12000 {
index 62175a8848bc2234343a8627d7cdf0ababfee851..d19f44c709257d9a35644d71cb49a04e354c42d8 100644 (file)
@@ -64,8 +64,8 @@
        soc {
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
-                         MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                         MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                pcie-controller {
                        status = "okay";
index a5db17782e085662d01a22683c5c364be5c25c8c..853bd392a4fe20155ed1469a23175213814ca9dc 100644 (file)
@@ -65,9 +65,9 @@
        soc {
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xd0000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
-                         MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000
-                         MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                         MBUS_ID(0x01, 0x2f) 0 0 0xe8000000 0x8000000
+                         MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                devbus-bootcs {
                        status = "okay";
index 2391b11dc546b859dd3ab23a700be5a8a63ea83b..d17dab0a6f513e9c04ff2675f5f9d44d7f6953b3 100644 (file)
@@ -78,8 +78,8 @@
        soc {
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
-                         MBUS_ID(0x09, 0x09) 0 0 0xf8100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf8110000 0x10000>;
+                         MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
                pcie-controller {
                        status = "okay";
index c4d9175b90dceab5aa64ca1973505652bf325bee..f82aa44c3ceed540fef7e291c571c2b49c5b2e1f 100644 (file)
                               0x48485200 0x2E00>;
                        #address-cells = <1>;
                        #size-cells = <1>;
+
+                       /*
+                        * Do not allow gating of cpsw clock as workaround
+                        * for errata i877. Keeping internal clock disabled
+                        * causes the device switching characteristics
+                        * to degrade over time and eventually fail to meet
+                        * the data manual delay time/skew specs.
+                        */
+                       ti,no-idle;
+
                        /*
                         * rx_thresh_pend
                         * rx_pend
index 1c6c07538a78e8fc72ce4e511922b40aee616ad3..302d1168f42427053f271c2925b3a1fa23f250db 100644 (file)
                };
        };
 
-       iio_hwmon {
+       iio-hwmon {
                compatible = "iio-hwmon";
                io-channels = <&lradc 8>;
        };
index fae7b9069fc43a6ef8bb2dae43d23460e0939aab..f637ec900cc8d13a0073dce096d0e3c5e9cdfc20 100644 (file)
                };
        };
 
-       iio_hwmon {
+       iio-hwmon {
                compatible = "iio-hwmon";
                io-channels = <&lradc 8>;
        };
index 4f6ae921656f16dfd3814d7a70972be798e0fce9..f74d3db4846dacacd54b37e9cb1d35d707689368 100644 (file)
                                #size-cells = <1>;
                                reg = <0x2100000 0x10000>;
                                ranges = <0 0x2100000 0x10000>;
-                               interrupt-parent = <&intc>;
                                clocks = <&clks IMX6QDL_CLK_CAAM_MEM>,
                                         <&clks IMX6QDL_CLK_CAAM_ACLK>,
                                         <&clks IMX6QDL_CLK_CAAM_IPG>,
index bf4143c6cb8f10991d4abbaae126966f9f9c753c..b84af3da8c84d596b2b950489541c4efd9216783 100644 (file)
@@ -14,7 +14,7 @@
 #include "kirkwood-synology.dtsi"
 
 / {
-       model = "Synology DS111";
+       model = "Synology DS112";
        compatible = "synology,ds111", "marvell,kirkwood";
 
        memory {
diff --git a/arch/arm/boot/dts/mt2701-pinfunc.h b/arch/arm/boot/dts/mt2701-pinfunc.h
new file mode 100644 (file)
index 0000000..e24ebc8
--- /dev/null
@@ -0,0 +1,735 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Biao Huang <biao.huang@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DTS_MT2701_PINFUNC_H
+#define __DTS_MT2701_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define MT2701_PIN_0_PWRAP_SPI0_MI__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
+#define MT2701_PIN_0_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDO (MTK_PIN_NO(0) | 1)
+#define MT2701_PIN_0_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDI (MTK_PIN_NO(0) | 2)
+
+#define MT2701_PIN_1_PWRAP_SPI0_MO__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
+#define MT2701_PIN_1_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDI (MTK_PIN_NO(1) | 1)
+#define MT2701_PIN_1_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDO (MTK_PIN_NO(1) | 2)
+
+#define MT2701_PIN_2_PWRAP_INT__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
+#define MT2701_PIN_2_PWRAP_INT__FUNC_PWRAP_INT (MTK_PIN_NO(2) | 1)
+
+#define MT2701_PIN_3_PWRAP_SPI0_CK__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
+#define MT2701_PIN_3_PWRAP_SPI0_CK__FUNC_PWRAP_SPICK_I (MTK_PIN_NO(3) | 1)
+
+#define MT2701_PIN_4_PWRAP_SPI0_CSN__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
+#define MT2701_PIN_4_PWRAP_SPI0_CSN__FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(4) | 1)
+
+#define MT2701_PIN_5_PWRAP_SPI0_CK2__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
+#define MT2701_PIN_5_PWRAP_SPI0_CK2__FUNC_PWRAP_SPICK2_I (MTK_PIN_NO(5) | 1)
+#define MT2701_PIN_5_PWRAP_SPI0_CK2__FUNC_ANT_SEL1 (MTK_PIN_NO(5) | 5)
+
+#define MT2701_PIN_6_PWRAP_SPI0_CSN2__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
+#define MT2701_PIN_6_PWRAP_SPI0_CSN2__FUNC_PWRAP_SPICS2_B_I (MTK_PIN_NO(6) | 1)
+#define MT2701_PIN_6_PWRAP_SPI0_CSN2__FUNC_ANT_SEL0 (MTK_PIN_NO(6) | 5)
+#define MT2701_PIN_6_PWRAP_SPI0_CSN2__FUNC_DBG_MON_A_0 (MTK_PIN_NO(6) | 7)
+
+#define MT2701_PIN_7_SPI1_CSN__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
+#define MT2701_PIN_7_SPI1_CSN__FUNC_SPI1_CS (MTK_PIN_NO(7) | 1)
+#define MT2701_PIN_7_SPI1_CSN__FUNC_KCOL0 (MTK_PIN_NO(7) | 4)
+#define MT2701_PIN_7_SPI1_CSN__FUNC_DBG_MON_B_12 (MTK_PIN_NO(7) | 7)
+
+#define MT2701_PIN_8_SPI1_MI__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
+#define MT2701_PIN_8_SPI1_MI__FUNC_SPI1_MI (MTK_PIN_NO(8) | 1)
+#define MT2701_PIN_8_SPI1_MI__FUNC_SPI1_MO (MTK_PIN_NO(8) | 2)
+#define MT2701_PIN_8_SPI1_MI__FUNC_KCOL1 (MTK_PIN_NO(8) | 4)
+#define MT2701_PIN_8_SPI1_MI__FUNC_DBG_MON_B_13 (MTK_PIN_NO(8) | 7)
+
+#define MT2701_PIN_9_SPI1_MO__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
+#define MT2701_PIN_9_SPI1_MO__FUNC_SPI1_MO (MTK_PIN_NO(9) | 1)
+#define MT2701_PIN_9_SPI1_MO__FUNC_SPI1_MI (MTK_PIN_NO(9) | 2)
+#define MT2701_PIN_9_SPI1_MO__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(9) | 3)
+#define MT2701_PIN_9_SPI1_MO__FUNC_KCOL2 (MTK_PIN_NO(9) | 4)
+#define MT2701_PIN_9_SPI1_MO__FUNC_DBG_MON_B_14 (MTK_PIN_NO(9) | 7)
+
+#define MT2701_PIN_10_RTC32K_CK__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
+#define MT2701_PIN_10_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(10) | 1)
+
+#define MT2701_PIN_11_WATCHDOG__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
+#define MT2701_PIN_11_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(11) | 1)
+
+#define MT2701_PIN_12_SRCLKENA__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
+#define MT2701_PIN_12_SRCLKENA__FUNC_SRCLKENA (MTK_PIN_NO(12) | 1)
+
+#define MT2701_PIN_13_SRCLKENAI__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
+#define MT2701_PIN_13_SRCLKENAI__FUNC_SRCLKENAI (MTK_PIN_NO(13) | 1)
+
+#define MT2701_PIN_14_URXD2__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
+#define MT2701_PIN_14_URXD2__FUNC_URXD2 (MTK_PIN_NO(14) | 1)
+#define MT2701_PIN_14_URXD2__FUNC_UTXD2 (MTK_PIN_NO(14) | 2)
+#define MT2701_PIN_14_URXD2__FUNC_SRCCLKENAI2 (MTK_PIN_NO(14) | 5)
+#define MT2701_PIN_14_URXD2__FUNC_DBG_MON_B_30 (MTK_PIN_NO(14) | 7)
+
+#define MT2701_PIN_15_UTXD2__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
+#define MT2701_PIN_15_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(15) | 1)
+#define MT2701_PIN_15_UTXD2__FUNC_URXD2 (MTK_PIN_NO(15) | 2)
+#define MT2701_PIN_15_UTXD2__FUNC_DBG_MON_B_31 (MTK_PIN_NO(15) | 7)
+
+#define MT2701_PIN_18_PCM_CLK__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
+#define MT2701_PIN_18_PCM_CLK__FUNC_PCM_CLK0 (MTK_PIN_NO(18) | 1)
+#define MT2701_PIN_18_PCM_CLK__FUNC_MRG_CLK (MTK_PIN_NO(18) | 2)
+#define MT2701_PIN_18_PCM_CLK__FUNC_MM_TEST_CK (MTK_PIN_NO(18) | 4)
+#define MT2701_PIN_18_PCM_CLK__FUNC_CONN_DSP_JCK (MTK_PIN_NO(18) | 5)
+#define MT2701_PIN_18_PCM_CLK__FUNC_WCN_PCM_CLKO (MTK_PIN_NO(18) | 6)
+#define MT2701_PIN_18_PCM_CLK__FUNC_DBG_MON_A_3 (MTK_PIN_NO(18) | 7)
+
+#define MT2701_PIN_19_PCM_SYNC__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
+#define MT2701_PIN_19_PCM_SYNC__FUNC_PCM_SYNC (MTK_PIN_NO(19) | 1)
+#define MT2701_PIN_19_PCM_SYNC__FUNC_MRG_SYNC (MTK_PIN_NO(19) | 2)
+#define MT2701_PIN_19_PCM_SYNC__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(19) | 5)
+#define MT2701_PIN_19_PCM_SYNC__FUNC_WCN_PCM_SYNC (MTK_PIN_NO(19) | 6)
+#define MT2701_PIN_19_PCM_SYNC__FUNC_DBG_MON_A_5 (MTK_PIN_NO(19) | 7)
+
+#define MT2701_PIN_20_PCM_RX__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
+#define MT2701_PIN_20_PCM_RX__FUNC_PCM_RX (MTK_PIN_NO(20) | 1)
+#define MT2701_PIN_20_PCM_RX__FUNC_MRG_RX (MTK_PIN_NO(20) | 2)
+#define MT2701_PIN_20_PCM_RX__FUNC_MRG_TX (MTK_PIN_NO(20) | 3)
+#define MT2701_PIN_20_PCM_RX__FUNC_PCM_TX (MTK_PIN_NO(20) | 4)
+#define MT2701_PIN_20_PCM_RX__FUNC_CONN_DSP_JDI (MTK_PIN_NO(20) | 5)
+#define MT2701_PIN_20_PCM_RX__FUNC_WCN_PCM_RX (MTK_PIN_NO(20) | 6)
+#define MT2701_PIN_20_PCM_RX__FUNC_DBG_MON_A_4 (MTK_PIN_NO(20) | 7)
+
+#define MT2701_PIN_21_PCM_TX__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
+#define MT2701_PIN_21_PCM_TX__FUNC_PCM_TX (MTK_PIN_NO(21) | 1)
+#define MT2701_PIN_21_PCM_TX__FUNC_MRG_TX (MTK_PIN_NO(21) | 2)
+#define MT2701_PIN_21_PCM_TX__FUNC_MRG_RX (MTK_PIN_NO(21) | 3)
+#define MT2701_PIN_21_PCM_TX__FUNC_PCM_RX (MTK_PIN_NO(21) | 4)
+#define MT2701_PIN_21_PCM_TX__FUNC_CONN_DSP_JMS (MTK_PIN_NO(21) | 5)
+#define MT2701_PIN_21_PCM_TX__FUNC_WCN_PCM_TX (MTK_PIN_NO(21) | 6)
+#define MT2701_PIN_21_PCM_TX__FUNC_DBG_MON_A_2 (MTK_PIN_NO(21) | 7)
+
+#define MT2701_PIN_22_EINT0__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
+#define MT2701_PIN_22_EINT0__FUNC_UCTS0 (MTK_PIN_NO(22) | 1)
+#define MT2701_PIN_22_EINT0__FUNC_KCOL3 (MTK_PIN_NO(22) | 3)
+#define MT2701_PIN_22_EINT0__FUNC_CONN_DSP_JDO (MTK_PIN_NO(22) | 4)
+#define MT2701_PIN_22_EINT0__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(22) | 5)
+#define MT2701_PIN_22_EINT0__FUNC_DBG_MON_A_30 (MTK_PIN_NO(22) | 7)
+#define MT2701_PIN_22_EINT0__FUNC_PCIE0_PERST_N (MTK_PIN_NO(22) | 10)
+
+#define MT2701_PIN_23_EINT1__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
+#define MT2701_PIN_23_EINT1__FUNC_URTS0 (MTK_PIN_NO(23) | 1)
+#define MT2701_PIN_23_EINT1__FUNC_KCOL2 (MTK_PIN_NO(23) | 3)
+#define MT2701_PIN_23_EINT1__FUNC_CONN_MCU_TDO (MTK_PIN_NO(23) | 4)
+#define MT2701_PIN_23_EINT1__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(23) | 5)
+#define MT2701_PIN_23_EINT1__FUNC_DBG_MON_A_29 (MTK_PIN_NO(23) | 7)
+#define MT2701_PIN_23_EINT1__FUNC_PCIE1_PERST_N (MTK_PIN_NO(23) | 10)
+
+#define MT2701_PIN_24_EINT2__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
+#define MT2701_PIN_24_EINT2__FUNC_UCTS1 (MTK_PIN_NO(24) | 1)
+#define MT2701_PIN_24_EINT2__FUNC_KCOL1 (MTK_PIN_NO(24) | 3)
+#define MT2701_PIN_24_EINT2__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(24) | 4)
+#define MT2701_PIN_24_EINT2__FUNC_DBG_MON_A_28 (MTK_PIN_NO(24) | 7)
+#define MT2701_PIN_24_EINT2__FUNC_PCIE2_PERST_N (MTK_PIN_NO(24) | 10)
+
+#define MT2701_PIN_25_EINT3__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
+#define MT2701_PIN_25_EINT3__FUNC_URTS1 (MTK_PIN_NO(25) | 1)
+#define MT2701_PIN_25_EINT3__FUNC_KCOL0 (MTK_PIN_NO(25) | 3)
+#define MT2701_PIN_25_EINT3__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(25) | 4)
+#define MT2701_PIN_25_EINT3__FUNC_DBG_MON_A_27 (MTK_PIN_NO(25) | 7)
+
+#define MT2701_PIN_26_EINT4__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
+#define MT2701_PIN_26_EINT4__FUNC_UCTS3 (MTK_PIN_NO(26) | 1)
+#define MT2701_PIN_26_EINT4__FUNC_DRV_VBUS_P1 (MTK_PIN_NO(26) | 2)
+#define MT2701_PIN_26_EINT4__FUNC_KROW3 (MTK_PIN_NO(26) | 3)
+#define MT2701_PIN_26_EINT4__FUNC_CONN_MCU_TCK0 (MTK_PIN_NO(26) | 4)
+#define MT2701_PIN_26_EINT4__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(26) | 5)
+#define MT2701_PIN_26_EINT4__FUNC_PCIE2_WAKE_N (MTK_PIN_NO(26) | 6)
+#define MT2701_PIN_26_EINT4__FUNC_DBG_MON_A_26 (MTK_PIN_NO(26) | 7)
+
+#define MT2701_PIN_27_EINT5__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
+#define MT2701_PIN_27_EINT5__FUNC_URTS3 (MTK_PIN_NO(27) | 1)
+#define MT2701_PIN_27_EINT5__FUNC_IDDIG_P1 (MTK_PIN_NO(27) | 2)
+#define MT2701_PIN_27_EINT5__FUNC_KROW2 (MTK_PIN_NO(27) | 3)
+#define MT2701_PIN_27_EINT5__FUNC_CONN_MCU_TDI (MTK_PIN_NO(27) | 4)
+#define MT2701_PIN_27_EINT5__FUNC_PCIE1_WAKE_N (MTK_PIN_NO(27) | 6)
+#define MT2701_PIN_27_EINT5__FUNC_DBG_MON_A_25 (MTK_PIN_NO(27) | 7)
+
+#define MT2701_PIN_28_EINT6__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
+#define MT2701_PIN_28_EINT6__FUNC_DRV_VBUS (MTK_PIN_NO(28) | 1)
+#define MT2701_PIN_28_EINT6__FUNC_KROW1 (MTK_PIN_NO(28) | 3)
+#define MT2701_PIN_28_EINT6__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(28) | 4)
+#define MT2701_PIN_28_EINT6__FUNC_PCIE0_WAKE_N (MTK_PIN_NO(28) | 6)
+#define MT2701_PIN_28_EINT6__FUNC_DBG_MON_A_24 (MTK_PIN_NO(28) | 7)
+
+#define MT2701_PIN_29_EINT7__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
+#define MT2701_PIN_29_EINT7__FUNC_IDDIG (MTK_PIN_NO(29) | 1)
+#define MT2701_PIN_29_EINT7__FUNC_MSDC1_WP (MTK_PIN_NO(29) | 2)
+#define MT2701_PIN_29_EINT7__FUNC_KROW0 (MTK_PIN_NO(29) | 3)
+#define MT2701_PIN_29_EINT7__FUNC_CONN_MCU_TMS (MTK_PIN_NO(29) | 4)
+#define MT2701_PIN_29_EINT7__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(29) | 5)
+#define MT2701_PIN_29_EINT7__FUNC_DBG_MON_A_23 (MTK_PIN_NO(29) | 7)
+#define MT2701_PIN_29_EINT7__FUNC_PCIE2_PERST_N (MTK_PIN_NO(29) | 14)
+
+#define MT2701_PIN_33_I2S1_DATA__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
+#define MT2701_PIN_33_I2S1_DATA__FUNC_I2S1_DATA (MTK_PIN_NO(33) | 1)
+#define MT2701_PIN_33_I2S1_DATA__FUNC_I2S1_DATA_BYPS (MTK_PIN_NO(33) | 2)
+#define MT2701_PIN_33_I2S1_DATA__FUNC_PCM_TX (MTK_PIN_NO(33) | 3)
+#define MT2701_PIN_33_I2S1_DATA__FUNC_IMG_TEST_CK (MTK_PIN_NO(33) | 4)
+#define MT2701_PIN_33_I2S1_DATA__FUNC_G1_RXD0 (MTK_PIN_NO(33) | 5)
+#define MT2701_PIN_33_I2S1_DATA__FUNC_WCN_PCM_TX (MTK_PIN_NO(33) | 6)
+#define MT2701_PIN_33_I2S1_DATA__FUNC_DBG_MON_B_8 (MTK_PIN_NO(33) | 7)
+
+#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
+#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_I2S1_DATA_IN (MTK_PIN_NO(34) | 1)
+#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_PCM_RX (MTK_PIN_NO(34) | 3)
+#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_VDEC_TEST_CK (MTK_PIN_NO(34) | 4)
+#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_G1_RXD1 (MTK_PIN_NO(34) | 5)
+#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_WCN_PCM_RX (MTK_PIN_NO(34) | 6)
+#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_DBG_MON_B_7 (MTK_PIN_NO(34) | 7)
+
+#define MT2701_PIN_35_I2S1_BCK__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
+#define MT2701_PIN_35_I2S1_BCK__FUNC_I2S1_BCK (MTK_PIN_NO(35) | 1)
+#define MT2701_PIN_35_I2S1_BCK__FUNC_PCM_CLK0 (MTK_PIN_NO(35) | 3)
+#define MT2701_PIN_35_I2S1_BCK__FUNC_G1_RXD2 (MTK_PIN_NO(35) | 5)
+#define MT2701_PIN_35_I2S1_BCK__FUNC_WCN_PCM_CLKO (MTK_PIN_NO(35) | 6)
+#define MT2701_PIN_35_I2S1_BCK__FUNC_DBG_MON_B_9 (MTK_PIN_NO(35) | 7)
+
+#define MT2701_PIN_36_I2S1_LRCK__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
+#define MT2701_PIN_36_I2S1_LRCK__FUNC_I2S1_LRCK (MTK_PIN_NO(36) | 1)
+#define MT2701_PIN_36_I2S1_LRCK__FUNC_PCM_SYNC (MTK_PIN_NO(36) | 3)
+#define MT2701_PIN_36_I2S1_LRCK__FUNC_G1_RXD3 (MTK_PIN_NO(36) | 5)
+#define MT2701_PIN_36_I2S1_LRCK__FUNC_WCN_PCM_SYNC (MTK_PIN_NO(36) | 6)
+#define MT2701_PIN_36_I2S1_LRCK__FUNC_DBG_MON_B_10 (MTK_PIN_NO(36) | 7)
+
+#define MT2701_PIN_37_I2S1_MCLK__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
+#define MT2701_PIN_37_I2S1_MCLK__FUNC_I2S1_MCLK (MTK_PIN_NO(37) | 1)
+#define MT2701_PIN_37_I2S1_MCLK__FUNC_G1_RXDV (MTK_PIN_NO(37) | 5)
+#define MT2701_PIN_37_I2S1_MCLK__FUNC_DBG_MON_B_11 (MTK_PIN_NO(37) | 7)
+
+#define MT2701_PIN_39_JTMS__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
+#define MT2701_PIN_39_JTMS__FUNC_JTMS (MTK_PIN_NO(39) | 1)
+#define MT2701_PIN_39_JTMS__FUNC_CONN_MCU_TMS (MTK_PIN_NO(39) | 2)
+#define MT2701_PIN_39_JTMS__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(39) | 3)
+#define MT2701_PIN_39_JTMS__FUNC_DFD_TMS_XI (MTK_PIN_NO(39) | 4)
+
+#define MT2701_PIN_40_JTCK__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
+#define MT2701_PIN_40_JTCK__FUNC_JTCK (MTK_PIN_NO(40) | 1)
+#define MT2701_PIN_40_JTCK__FUNC_CONN_MCU_TCK1 (MTK_PIN_NO(40) | 2)
+#define MT2701_PIN_40_JTCK__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(40) | 3)
+#define MT2701_PIN_40_JTCK__FUNC_DFD_TCK_XI (MTK_PIN_NO(40) | 4)
+
+#define MT2701_PIN_41_JTDI__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
+#define MT2701_PIN_41_JTDI__FUNC_JTDI (MTK_PIN_NO(41) | 1)
+#define MT2701_PIN_41_JTDI__FUNC_CONN_MCU_TDI (MTK_PIN_NO(41) | 2)
+#define MT2701_PIN_41_JTDI__FUNC_DFD_TDI_XI (MTK_PIN_NO(41) | 4)
+
+#define MT2701_PIN_42_JTDO__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
+#define MT2701_PIN_42_JTDO__FUNC_JTDO (MTK_PIN_NO(42) | 1)
+#define MT2701_PIN_42_JTDO__FUNC_CONN_MCU_TDO (MTK_PIN_NO(42) | 2)
+#define MT2701_PIN_42_JTDO__FUNC_DFD_TDO (MTK_PIN_NO(42) | 4)
+
+#define MT2701_PIN_43_NCLE__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
+#define MT2701_PIN_43_NCLE__FUNC_NCLE (MTK_PIN_NO(43) | 1)
+#define MT2701_PIN_43_NCLE__FUNC_EXT_XCS2 (MTK_PIN_NO(43) | 2)
+
+#define MT2701_PIN_44_NCEB1__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
+#define MT2701_PIN_44_NCEB1__FUNC_NCEB1 (MTK_PIN_NO(44) | 1)
+#define MT2701_PIN_44_NCEB1__FUNC_IDDIG (MTK_PIN_NO(44) | 2)
+
+#define MT2701_PIN_45_NCEB0__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
+#define MT2701_PIN_45_NCEB0__FUNC_NCEB0 (MTK_PIN_NO(45) | 1)
+#define MT2701_PIN_45_NCEB0__FUNC_DRV_VBUS (MTK_PIN_NO(45) | 2)
+
+#define MT2701_PIN_46_IR__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
+#define MT2701_PIN_46_IR__FUNC_IR (MTK_PIN_NO(46) | 1)
+
+#define MT2701_PIN_47_NREB__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
+#define MT2701_PIN_47_NREB__FUNC_NREB (MTK_PIN_NO(47) | 1)
+#define MT2701_PIN_47_NREB__FUNC_IDDIG_P1 (MTK_PIN_NO(47) | 2)
+
+#define MT2701_PIN_48_NRNB__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
+#define MT2701_PIN_48_NRNB__FUNC_NRNB (MTK_PIN_NO(48) | 1)
+#define MT2701_PIN_48_NRNB__FUNC_DRV_VBUS_P1 (MTK_PIN_NO(48) | 2)
+
+#define MT2701_PIN_49_I2S0_DATA__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
+#define MT2701_PIN_49_I2S0_DATA__FUNC_I2S0_DATA (MTK_PIN_NO(49) | 1)
+#define MT2701_PIN_49_I2S0_DATA__FUNC_I2S0_DATA_BYPS (MTK_PIN_NO(49) | 2)
+#define MT2701_PIN_49_I2S0_DATA__FUNC_PCM_TX (MTK_PIN_NO(49) | 3)
+#define MT2701_PIN_49_I2S0_DATA__FUNC_WCN_I2S_DO (MTK_PIN_NO(49) | 6)
+#define MT2701_PIN_49_I2S0_DATA__FUNC_DBG_MON_B_3 (MTK_PIN_NO(49) | 7)
+
+#define MT2701_PIN_53_SPI0_CSN__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
+#define MT2701_PIN_53_SPI0_CSN__FUNC_SPI0_CS (MTK_PIN_NO(53) | 1)
+#define MT2701_PIN_53_SPI0_CSN__FUNC_SPDIF (MTK_PIN_NO(53) | 3)
+#define MT2701_PIN_53_SPI0_CSN__FUNC_ADC_CK (MTK_PIN_NO(53) | 4)
+#define MT2701_PIN_53_SPI0_CSN__FUNC_PWM1 (MTK_PIN_NO(53) | 5)
+#define MT2701_PIN_53_SPI0_CSN__FUNC_DBG_MON_A_7 (MTK_PIN_NO(53) | 7)
+
+#define MT2701_PIN_54_SPI0_CK__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
+#define MT2701_PIN_54_SPI0_CK__FUNC_SPI0_CK (MTK_PIN_NO(54) | 1)
+#define MT2701_PIN_54_SPI0_CK__FUNC_SPDIF_IN1 (MTK_PIN_NO(54) | 3)
+#define MT2701_PIN_54_SPI0_CK__FUNC_ADC_DAT_IN (MTK_PIN_NO(54) | 4)
+#define MT2701_PIN_54_SPI0_CK__FUNC_DBG_MON_A_10 (MTK_PIN_NO(54) | 7)
+
+#define MT2701_PIN_55_SPI0_MI__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
+#define MT2701_PIN_55_SPI0_MI__FUNC_SPI0_MI (MTK_PIN_NO(55) | 1)
+#define MT2701_PIN_55_SPI0_MI__FUNC_SPI0_MO (MTK_PIN_NO(55) | 2)
+#define MT2701_PIN_55_SPI0_MI__FUNC_MSDC1_WP (MTK_PIN_NO(55) | 3)
+#define MT2701_PIN_55_SPI0_MI__FUNC_ADC_WS (MTK_PIN_NO(55) | 4)
+#define MT2701_PIN_55_SPI0_MI__FUNC_PWM2 (MTK_PIN_NO(55) | 5)
+#define MT2701_PIN_55_SPI0_MI__FUNC_DBG_MON_A_8 (MTK_PIN_NO(55) | 7)
+
+#define MT2701_PIN_56_SPI0_MO__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
+#define MT2701_PIN_56_SPI0_MO__FUNC_SPI0_MO (MTK_PIN_NO(56) | 1)
+#define MT2701_PIN_56_SPI0_MO__FUNC_SPI0_MI (MTK_PIN_NO(56) | 2)
+#define MT2701_PIN_56_SPI0_MO__FUNC_SPDIF_IN0 (MTK_PIN_NO(56) | 3)
+#define MT2701_PIN_56_SPI0_MO__FUNC_DBG_MON_A_9 (MTK_PIN_NO(56) | 7)
+
+#define MT2701_PIN_57_SDA1__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
+#define MT2701_PIN_57_SDA1__FUNC_SDA1 (MTK_PIN_NO(57) | 1)
+
+#define MT2701_PIN_58_SCL1__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
+#define MT2701_PIN_58_SCL1__FUNC_SCL1 (MTK_PIN_NO(58) | 1)
+
+#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
+#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_I2S0_DATA_IN (MTK_PIN_NO(72) | 1)
+#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_PCM_RX (MTK_PIN_NO(72) | 3)
+#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_PWM0 (MTK_PIN_NO(72) | 4)
+#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_DISP_PWM (MTK_PIN_NO(72) | 5)
+#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_WCN_I2S_DI (MTK_PIN_NO(72) | 6)
+#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_DBG_MON_B_2 (MTK_PIN_NO(72) | 7)
+
+#define MT2701_PIN_73_I2S0_LRCK__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
+#define MT2701_PIN_73_I2S0_LRCK__FUNC_I2S0_LRCK (MTK_PIN_NO(73) | 1)
+#define MT2701_PIN_73_I2S0_LRCK__FUNC_PCM_SYNC (MTK_PIN_NO(73) | 3)
+#define MT2701_PIN_73_I2S0_LRCK__FUNC_WCN_I2S_LRCK (MTK_PIN_NO(73) | 6)
+#define MT2701_PIN_73_I2S0_LRCK__FUNC_DBG_MON_B_5 (MTK_PIN_NO(73) | 7)
+
+#define MT2701_PIN_74_I2S0_BCK__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
+#define MT2701_PIN_74_I2S0_BCK__FUNC_I2S0_BCK (MTK_PIN_NO(74) | 1)
+#define MT2701_PIN_74_I2S0_BCK__FUNC_PCM_CLK0 (MTK_PIN_NO(74) | 3)
+#define MT2701_PIN_74_I2S0_BCK__FUNC_WCN_I2S_BCK (MTK_PIN_NO(74) | 6)
+#define MT2701_PIN_74_I2S0_BCK__FUNC_DBG_MON_B_4 (MTK_PIN_NO(74) | 7)
+
+#define MT2701_PIN_75_SDA0__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
+#define MT2701_PIN_75_SDA0__FUNC_SDA0 (MTK_PIN_NO(75) | 1)
+
+#define MT2701_PIN_76_SCL0__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+#define MT2701_PIN_76_SCL0__FUNC_SCL0 (MTK_PIN_NO(76) | 1)
+
+#define MT2701_PIN_77_SDA2__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
+#define MT2701_PIN_77_SDA2__FUNC_SDA2 (MTK_PIN_NO(77) | 1)
+
+#define MT2701_PIN_78_SCL2__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
+#define MT2701_PIN_78_SCL2__FUNC_SCL2 (MTK_PIN_NO(78) | 1)
+
+#define MT2701_PIN_79_URXD0__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
+#define MT2701_PIN_79_URXD0__FUNC_URXD0 (MTK_PIN_NO(79) | 1)
+#define MT2701_PIN_79_URXD0__FUNC_UTXD0 (MTK_PIN_NO(79) | 2)
+#define MT2701_PIN_79_URXD0__FUNC_ (MTK_PIN_NO(79) | 5)
+
+#define MT2701_PIN_80_UTXD0__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
+#define MT2701_PIN_80_UTXD0__FUNC_UTXD0 (MTK_PIN_NO(80) | 1)
+#define MT2701_PIN_80_UTXD0__FUNC_URXD0 (MTK_PIN_NO(80) | 2)
+
+#define MT2701_PIN_81_URXD1__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
+#define MT2701_PIN_81_URXD1__FUNC_URXD1 (MTK_PIN_NO(81) | 1)
+#define MT2701_PIN_81_URXD1__FUNC_UTXD1 (MTK_PIN_NO(81) | 2)
+
+#define MT2701_PIN_82_UTXD1__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
+#define MT2701_PIN_82_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(82) | 1)
+#define MT2701_PIN_82_UTXD1__FUNC_URXD1 (MTK_PIN_NO(82) | 2)
+
+#define MT2701_PIN_83_LCM_RST__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+#define MT2701_PIN_83_LCM_RST__FUNC_LCM_RST (MTK_PIN_NO(83) | 1)
+#define MT2701_PIN_83_LCM_RST__FUNC_VDAC_CK_XI (MTK_PIN_NO(83) | 2)
+#define MT2701_PIN_83_LCM_RST__FUNC_DBG_MON_B_1 (MTK_PIN_NO(83) | 7)
+
+#define MT2701_PIN_84_DSI_TE__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
+#define MT2701_PIN_84_DSI_TE__FUNC_DSI_TE (MTK_PIN_NO(84) | 1)
+#define MT2701_PIN_84_DSI_TE__FUNC_DBG_MON_B_0 (MTK_PIN_NO(84) | 7)
+
+#define MT2701_PIN_91_TDN3__FUNC_GPI91 (MTK_PIN_NO(91) | 0)
+#define MT2701_PIN_91_TDN3__FUNC_TDN3 (MTK_PIN_NO(91) | 1)
+
+#define MT2701_PIN_92_TDP3__FUNC_GPI92 (MTK_PIN_NO(92) | 0)
+#define MT2701_PIN_92_TDP3__FUNC_TDP3 (MTK_PIN_NO(92) | 1)
+
+#define MT2701_PIN_93_TDN2__FUNC_GPI93 (MTK_PIN_NO(93) | 0)
+#define MT2701_PIN_93_TDN2__FUNC_TDN2 (MTK_PIN_NO(93) | 1)
+
+#define MT2701_PIN_94_TDP2__FUNC_GPI94 (MTK_PIN_NO(94) | 0)
+#define MT2701_PIN_94_TDP2__FUNC_TDP2 (MTK_PIN_NO(94) | 1)
+
+#define MT2701_PIN_95_TCN__FUNC_GPI95 (MTK_PIN_NO(95) | 0)
+#define MT2701_PIN_95_TCN__FUNC_TCN (MTK_PIN_NO(95) | 1)
+
+#define MT2701_PIN_96_TCP__FUNC_GPI96 (MTK_PIN_NO(96) | 0)
+#define MT2701_PIN_96_TCP__FUNC_TCP (MTK_PIN_NO(96) | 1)
+
+#define MT2701_PIN_97_TDN1__FUNC_GPI97 (MTK_PIN_NO(97) | 0)
+#define MT2701_PIN_97_TDN1__FUNC_TDN1 (MTK_PIN_NO(97) | 1)
+
+#define MT2701_PIN_98_TDP1__FUNC_GPI98 (MTK_PIN_NO(98) | 0)
+#define MT2701_PIN_98_TDP1__FUNC_TDP1 (MTK_PIN_NO(98) | 1)
+
+#define MT2701_PIN_99_TDN0__FUNC_GPI99 (MTK_PIN_NO(99) | 0)
+#define MT2701_PIN_99_TDN0__FUNC_TDN0 (MTK_PIN_NO(99) | 1)
+
+#define MT2701_PIN_100_TDP0__FUNC_GPI100 (MTK_PIN_NO(100) | 0)
+#define MT2701_PIN_100_TDP0__FUNC_TDP0 (MTK_PIN_NO(100) | 1)
+
+#define MT2701_PIN_101_SPI2_CSN__FUNC_GPIO101 (MTK_PIN_NO(101) | 0)
+#define MT2701_PIN_101_SPI2_CSN__FUNC_SPI2_CS (MTK_PIN_NO(101) | 1)
+#define MT2701_PIN_101_SPI2_CSN__FUNC_SCL3 (MTK_PIN_NO(101) | 3)
+#define MT2701_PIN_101_SPI2_CSN__FUNC_KROW0 (MTK_PIN_NO(101) | 4)
+
+#define MT2701_PIN_102_SPI2_MI__FUNC_GPIO102 (MTK_PIN_NO(102) | 0)
+#define MT2701_PIN_102_SPI2_MI__FUNC_SPI2_MI (MTK_PIN_NO(102) | 1)
+#define MT2701_PIN_102_SPI2_MI__FUNC_SPI2_MO (MTK_PIN_NO(102) | 2)
+#define MT2701_PIN_102_SPI2_MI__FUNC_SDA3 (MTK_PIN_NO(102) | 3)
+#define MT2701_PIN_102_SPI2_MI__FUNC_KROW1 (MTK_PIN_NO(102) | 4)
+
+#define MT2701_PIN_103_SPI2_MO__FUNC_GPIO103 (MTK_PIN_NO(103) | 0)
+#define MT2701_PIN_103_SPI2_MO__FUNC_SPI2_MO (MTK_PIN_NO(103) | 1)
+#define MT2701_PIN_103_SPI2_MO__FUNC_SPI2_MI (MTK_PIN_NO(103) | 2)
+#define MT2701_PIN_103_SPI2_MO__FUNC_SCL3 (MTK_PIN_NO(103) | 3)
+#define MT2701_PIN_103_SPI2_MO__FUNC_KROW2 (MTK_PIN_NO(103) | 4)
+
+#define MT2701_PIN_104_SPI2_CLK__FUNC_GPIO104 (MTK_PIN_NO(104) | 0)
+#define MT2701_PIN_104_SPI2_CLK__FUNC_SPI2_CK (MTK_PIN_NO(104) | 1)
+#define MT2701_PIN_104_SPI2_CLK__FUNC_SDA3 (MTK_PIN_NO(104) | 3)
+#define MT2701_PIN_104_SPI2_CLK__FUNC_KROW3 (MTK_PIN_NO(104) | 4)
+
+#define MT2701_PIN_105_MSDC1_CMD__FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
+#define MT2701_PIN_105_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(105) | 1)
+#define MT2701_PIN_105_MSDC1_CMD__FUNC_ANT_SEL0 (MTK_PIN_NO(105) | 2)
+#define MT2701_PIN_105_MSDC1_CMD__FUNC_SDA1 (MTK_PIN_NO(105) | 3)
+#define MT2701_PIN_105_MSDC1_CMD__FUNC_I2SOUT_BCK (MTK_PIN_NO(105) | 6)
+#define MT2701_PIN_105_MSDC1_CMD__FUNC_DBG_MON_B_27 (MTK_PIN_NO(105) | 7)
+
+#define MT2701_PIN_106_MSDC1_CLK__FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
+#define MT2701_PIN_106_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(106) | 1)
+#define MT2701_PIN_106_MSDC1_CLK__FUNC_ANT_SEL1 (MTK_PIN_NO(106) | 2)
+#define MT2701_PIN_106_MSDC1_CLK__FUNC_SCL1 (MTK_PIN_NO(106) | 3)
+#define MT2701_PIN_106_MSDC1_CLK__FUNC_I2SOUT_LRCK (MTK_PIN_NO(106) | 6)
+#define MT2701_PIN_106_MSDC1_CLK__FUNC_DBG_MON_B_28 (MTK_PIN_NO(106) | 7)
+
+#define MT2701_PIN_107_MSDC1_DAT0__FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
+#define MT2701_PIN_107_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(107) | 1)
+#define MT2701_PIN_107_MSDC1_DAT0__FUNC_ANT_SEL2 (MTK_PIN_NO(107) | 2)
+#define MT2701_PIN_107_MSDC1_DAT0__FUNC_UTXD0 (MTK_PIN_NO(107) | 5)
+#define MT2701_PIN_107_MSDC1_DAT0__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(107) | 6)
+#define MT2701_PIN_107_MSDC1_DAT0__FUNC_DBG_MON_B_26 (MTK_PIN_NO(107) | 7)
+
+#define MT2701_PIN_108_MSDC1_DAT1__FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
+#define MT2701_PIN_108_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(108) | 1)
+#define MT2701_PIN_108_MSDC1_DAT1__FUNC_ANT_SEL3 (MTK_PIN_NO(108) | 2)
+#define MT2701_PIN_108_MSDC1_DAT1__FUNC_PWM0 (MTK_PIN_NO(108) | 3)
+#define MT2701_PIN_108_MSDC1_DAT1__FUNC_URXD0 (MTK_PIN_NO(108) | 5)
+#define MT2701_PIN_108_MSDC1_DAT1__FUNC_PWM1 (MTK_PIN_NO(108) | 6)
+#define MT2701_PIN_108_MSDC1_DAT1__FUNC_DBG_MON_B_25 (MTK_PIN_NO(108) | 7)
+
+#define MT2701_PIN_109_MSDC1_DAT2__FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
+#define MT2701_PIN_109_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(109) | 1)
+#define MT2701_PIN_109_MSDC1_DAT2__FUNC_ANT_SEL4 (MTK_PIN_NO(109) | 2)
+#define MT2701_PIN_109_MSDC1_DAT2__FUNC_SDA2 (MTK_PIN_NO(109) | 3)
+#define MT2701_PIN_109_MSDC1_DAT2__FUNC_UTXD1 (MTK_PIN_NO(109) | 5)
+#define MT2701_PIN_109_MSDC1_DAT2__FUNC_PWM2 (MTK_PIN_NO(109) | 6)
+#define MT2701_PIN_109_MSDC1_DAT2__FUNC_DBG_MON_B_24 (MTK_PIN_NO(109) | 7)
+
+#define MT2701_PIN_110_MSDC1_DAT3__FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
+#define MT2701_PIN_110_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(110) | 1)
+#define MT2701_PIN_110_MSDC1_DAT3__FUNC_ANT_SEL5 (MTK_PIN_NO(110) | 2)
+#define MT2701_PIN_110_MSDC1_DAT3__FUNC_SCL2 (MTK_PIN_NO(110) | 3)
+#define MT2701_PIN_110_MSDC1_DAT3__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(110) | 4)
+#define MT2701_PIN_110_MSDC1_DAT3__FUNC_URXD1 (MTK_PIN_NO(110) | 5)
+#define MT2701_PIN_110_MSDC1_DAT3__FUNC_PWM3 (MTK_PIN_NO(110) | 6)
+#define MT2701_PIN_110_MSDC1_DAT3__FUNC_DBG_MON_B_23 (MTK_PIN_NO(110) | 7)
+
+#define MT2701_PIN_111_MSDC0_DAT7__FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
+#define MT2701_PIN_111_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(111) | 1)
+#define MT2701_PIN_111_MSDC0_DAT7__FUNC_NLD7 (MTK_PIN_NO(111) | 4)
+
+#define MT2701_PIN_112_MSDC0_DAT6__FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
+#define MT2701_PIN_112_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(112) | 1)
+#define MT2701_PIN_112_MSDC0_DAT6__FUNC_NLD6 (MTK_PIN_NO(112) | 4)
+
+#define MT2701_PIN_113_MSDC0_DAT5__FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
+#define MT2701_PIN_113_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(113) | 1)
+#define MT2701_PIN_113_MSDC0_DAT5__FUNC_NLD5 (MTK_PIN_NO(113) | 4)
+
+#define MT2701_PIN_114_MSDC0_DAT4__FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
+#define MT2701_PIN_114_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(114) | 1)
+#define MT2701_PIN_114_MSDC0_DAT4__FUNC_NLD4 (MTK_PIN_NO(114) | 4)
+
+#define MT2701_PIN_115_MSDC0_RSTB__FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
+#define MT2701_PIN_115_MSDC0_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(115) | 1)
+#define MT2701_PIN_115_MSDC0_RSTB__FUNC_NLD8 (MTK_PIN_NO(115) | 4)
+
+#define MT2701_PIN_116_MSDC0_CMD__FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
+#define MT2701_PIN_116_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(116) | 1)
+#define MT2701_PIN_116_MSDC0_CMD__FUNC_NALE (MTK_PIN_NO(116) | 4)
+
+#define MT2701_PIN_117_MSDC0_CLK__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
+#define MT2701_PIN_117_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(117) | 1)
+#define MT2701_PIN_117_MSDC0_CLK__FUNC_NWEB (MTK_PIN_NO(117) | 4)
+
+#define MT2701_PIN_118_MSDC0_DAT3__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
+#define MT2701_PIN_118_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(118) | 1)
+#define MT2701_PIN_118_MSDC0_DAT3__FUNC_NLD3 (MTK_PIN_NO(118) | 4)
+
+#define MT2701_PIN_119_MSDC0_DAT2__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
+#define MT2701_PIN_119_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(119) | 1)
+#define MT2701_PIN_119_MSDC0_DAT2__FUNC_NLD2 (MTK_PIN_NO(119) | 4)
+
+#define MT2701_PIN_120_MSDC0_DAT1__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
+#define MT2701_PIN_120_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(120) | 1)
+#define MT2701_PIN_120_MSDC0_DAT1__FUNC_NLD1 (MTK_PIN_NO(120) | 4)
+
+#define MT2701_PIN_121_MSDC0_DAT0__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
+#define MT2701_PIN_121_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(121) | 1)
+#define MT2701_PIN_121_MSDC0_DAT0__FUNC_NLD0 (MTK_PIN_NO(121) | 4)
+#define MT2701_PIN_121_MSDC0_DAT0__FUNC_WATCHDOG (MTK_PIN_NO(121) | 5)
+
+#define MT2701_PIN_122_CEC__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
+#define MT2701_PIN_122_CEC__FUNC_CEC (MTK_PIN_NO(122) | 1)
+#define MT2701_PIN_122_CEC__FUNC_SDA2 (MTK_PIN_NO(122) | 4)
+#define MT2701_PIN_122_CEC__FUNC_URXD0 (MTK_PIN_NO(122) | 5)
+
+#define MT2701_PIN_123_HTPLG__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+#define MT2701_PIN_123_HTPLG__FUNC_HTPLG (MTK_PIN_NO(123) | 1)
+#define MT2701_PIN_123_HTPLG__FUNC_SCL2 (MTK_PIN_NO(123) | 4)
+#define MT2701_PIN_123_HTPLG__FUNC_UTXD0 (MTK_PIN_NO(123) | 5)
+
+#define MT2701_PIN_124_HDMISCK__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+#define MT2701_PIN_124_HDMISCK__FUNC_HDMISCK (MTK_PIN_NO(124) | 1)
+#define MT2701_PIN_124_HDMISCK__FUNC_SDA1 (MTK_PIN_NO(124) | 4)
+#define MT2701_PIN_124_HDMISCK__FUNC_PWM3 (MTK_PIN_NO(124) | 5)
+
+#define MT2701_PIN_125_HDMISD__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
+#define MT2701_PIN_125_HDMISD__FUNC_HDMISD (MTK_PIN_NO(125) | 1)
+#define MT2701_PIN_125_HDMISD__FUNC_SCL1 (MTK_PIN_NO(125) | 4)
+#define MT2701_PIN_125_HDMISD__FUNC_PWM4 (MTK_PIN_NO(125) | 5)
+
+#define MT2701_PIN_126_I2S0_MCLK__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
+#define MT2701_PIN_126_I2S0_MCLK__FUNC_I2S0_MCLK (MTK_PIN_NO(126) | 1)
+#define MT2701_PIN_126_I2S0_MCLK__FUNC_WCN_I2S_MCLK (MTK_PIN_NO(126) | 6)
+#define MT2701_PIN_126_I2S0_MCLK__FUNC_DBG_MON_B_6 (MTK_PIN_NO(126) | 7)
+
+#define MT2701_PIN_199_SPI1_CLK__FUNC_GPIO199 (MTK_PIN_NO(199) | 0)
+#define MT2701_PIN_199_SPI1_CLK__FUNC_SPI1_CK (MTK_PIN_NO(199) | 1)
+#define MT2701_PIN_199_SPI1_CLK__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(199) | 3)
+#define MT2701_PIN_199_SPI1_CLK__FUNC_KCOL3 (MTK_PIN_NO(199) | 4)
+#define MT2701_PIN_199_SPI1_CLK__FUNC_DBG_MON_B_15 (MTK_PIN_NO(199) | 7)
+
+#define MT2701_PIN_200_SPDIF_OUT__FUNC_GPIO200 (MTK_PIN_NO(200) | 0)
+#define MT2701_PIN_200_SPDIF_OUT__FUNC_SPDIF_OUT (MTK_PIN_NO(200) | 1)
+#define MT2701_PIN_200_SPDIF_OUT__FUNC_G1_TXD3 (MTK_PIN_NO(200) | 5)
+#define MT2701_PIN_200_SPDIF_OUT__FUNC_URXD2 (MTK_PIN_NO(200) | 6)
+#define MT2701_PIN_200_SPDIF_OUT__FUNC_DBG_MON_B_16 (MTK_PIN_NO(200) | 7)
+
+#define MT2701_PIN_201_SPDIF_IN0__FUNC_GPIO201 (MTK_PIN_NO(201) | 0)
+#define MT2701_PIN_201_SPDIF_IN0__FUNC_SPDIF_IN0 (MTK_PIN_NO(201) | 1)
+#define MT2701_PIN_201_SPDIF_IN0__FUNC_G1_TXEN (MTK_PIN_NO(201) | 5)
+#define MT2701_PIN_201_SPDIF_IN0__FUNC_UTXD2 (MTK_PIN_NO(201) | 6)
+#define MT2701_PIN_201_SPDIF_IN0__FUNC_DBG_MON_B_17 (MTK_PIN_NO(201) | 7)
+
+#define MT2701_PIN_202_SPDIF_IN1__FUNC_GPIO202 (MTK_PIN_NO(202) | 0)
+#define MT2701_PIN_202_SPDIF_IN1__FUNC_SPDIF_IN1 (MTK_PIN_NO(202) | 1)
+
+#define MT2701_PIN_203_PWM0__FUNC_GPIO203 (MTK_PIN_NO(203) | 0)
+#define MT2701_PIN_203_PWM0__FUNC_PWM0 (MTK_PIN_NO(203) | 1)
+#define MT2701_PIN_203_PWM0__FUNC_DISP_PWM (MTK_PIN_NO(203) | 2)
+#define MT2701_PIN_203_PWM0__FUNC_G1_TXD2 (MTK_PIN_NO(203) | 5)
+#define MT2701_PIN_203_PWM0__FUNC_DBG_MON_B_18 (MTK_PIN_NO(203) | 7)
+#define MT2701_PIN_203_PWM0__FUNC_I2S2_DATA (MTK_PIN_NO(203) | 9)
+
+#define MT2701_PIN_204_PWM1__FUNC_GPIO204 (MTK_PIN_NO(204) | 0)
+#define MT2701_PIN_204_PWM1__FUNC_PWM1 (MTK_PIN_NO(204) | 1)
+#define MT2701_PIN_204_PWM1__FUNC_CLKM3 (MTK_PIN_NO(204) | 2)
+#define MT2701_PIN_204_PWM1__FUNC_G1_TXD1 (MTK_PIN_NO(204) | 5)
+#define MT2701_PIN_204_PWM1__FUNC_DBG_MON_B_19 (MTK_PIN_NO(204) | 7)
+#define MT2701_PIN_204_PWM1__FUNC_I2S3_DATA (MTK_PIN_NO(204) | 9)
+
+#define MT2701_PIN_205_PWM2__FUNC_GPIO205 (MTK_PIN_NO(205) | 0)
+#define MT2701_PIN_205_PWM2__FUNC_PWM2 (MTK_PIN_NO(205) | 1)
+#define MT2701_PIN_205_PWM2__FUNC_CLKM2 (MTK_PIN_NO(205) | 2)
+#define MT2701_PIN_205_PWM2__FUNC_G1_TXD0 (MTK_PIN_NO(205) | 5)
+#define MT2701_PIN_205_PWM2__FUNC_DBG_MON_B_20 (MTK_PIN_NO(205) | 7)
+
+#define MT2701_PIN_206_PWM3__FUNC_GPIO206 (MTK_PIN_NO(206) | 0)
+#define MT2701_PIN_206_PWM3__FUNC_PWM3 (MTK_PIN_NO(206) | 1)
+#define MT2701_PIN_206_PWM3__FUNC_CLKM1 (MTK_PIN_NO(206) | 2)
+#define MT2701_PIN_206_PWM3__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(206) | 3)
+#define MT2701_PIN_206_PWM3__FUNC_G1_TXC (MTK_PIN_NO(206) | 5)
+#define MT2701_PIN_206_PWM3__FUNC_DBG_MON_B_21 (MTK_PIN_NO(206) | 7)
+
+#define MT2701_PIN_207_PWM4__FUNC_GPIO207 (MTK_PIN_NO(207) | 0)
+#define MT2701_PIN_207_PWM4__FUNC_PWM4 (MTK_PIN_NO(207) | 1)
+#define MT2701_PIN_207_PWM4__FUNC_CLKM0 (MTK_PIN_NO(207) | 2)
+#define MT2701_PIN_207_PWM4__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(207) | 3)
+#define MT2701_PIN_207_PWM4__FUNC_G1_RXC (MTK_PIN_NO(207) | 5)
+#define MT2701_PIN_207_PWM4__FUNC_DBG_MON_B_22 (MTK_PIN_NO(207) | 7)
+
+#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_GPIO208 (MTK_PIN_NO(208) | 0)
+#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_AUD_EXT_CK1 (MTK_PIN_NO(208) | 1)
+#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_PWM0 (MTK_PIN_NO(208) | 2)
+#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_ANT_SEL5 (MTK_PIN_NO(208) | 4)
+#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_DISP_PWM (MTK_PIN_NO(208) | 5)
+#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_DBG_MON_A_31 (MTK_PIN_NO(208) | 7)
+#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_PCIE0_PERST_N (MTK_PIN_NO(208) | 11)
+
+#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_GPIO209 (MTK_PIN_NO(209) | 0)
+#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_AUD_EXT_CK2 (MTK_PIN_NO(209) | 1)
+#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_MSDC1_WP (MTK_PIN_NO(209) | 2)
+#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_PWM1 (MTK_PIN_NO(209) | 5)
+#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_DBG_MON_A_32 (MTK_PIN_NO(209) | 7)
+#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_PCIE1_PERST_N (MTK_PIN_NO(209) | 11)
+
+#define MT2701_PIN_236_EXT_SDIO3__FUNC_GPIO236 (MTK_PIN_NO(236) | 0)
+#define MT2701_PIN_236_EXT_SDIO3__FUNC_EXT_SDIO3 (MTK_PIN_NO(236) | 1)
+#define MT2701_PIN_236_EXT_SDIO3__FUNC_IDDIG (MTK_PIN_NO(236) | 2)
+#define MT2701_PIN_236_EXT_SDIO3__FUNC_DBG_MON_A_1 (MTK_PIN_NO(236) | 7)
+
+#define MT2701_PIN_237_EXT_SDIO2__FUNC_GPIO237 (MTK_PIN_NO(237) | 0)
+#define MT2701_PIN_237_EXT_SDIO2__FUNC_EXT_SDIO2 (MTK_PIN_NO(237) | 1)
+#define MT2701_PIN_237_EXT_SDIO2__FUNC_DRV_VBUS (MTK_PIN_NO(237) | 2)
+
+#define MT2701_PIN_238_EXT_SDIO1__FUNC_GPIO238 (MTK_PIN_NO(238) | 0)
+#define MT2701_PIN_238_EXT_SDIO1__FUNC_EXT_SDIO1 (MTK_PIN_NO(238) | 1)
+#define MT2701_PIN_238_EXT_SDIO1__FUNC_IDDIG_P1 (MTK_PIN_NO(238) | 2)
+
+#define MT2701_PIN_239_EXT_SDIO0__FUNC_GPIO239 (MTK_PIN_NO(239) | 0)
+#define MT2701_PIN_239_EXT_SDIO0__FUNC_EXT_SDIO0 (MTK_PIN_NO(239) | 1)
+#define MT2701_PIN_239_EXT_SDIO0__FUNC_DRV_VBUS_P1 (MTK_PIN_NO(239) | 2)
+
+#define MT2701_PIN_240_EXT_XCS__FUNC_GPIO240 (MTK_PIN_NO(240) | 0)
+#define MT2701_PIN_240_EXT_XCS__FUNC_EXT_XCS (MTK_PIN_NO(240) | 1)
+
+#define MT2701_PIN_241_EXT_SCK__FUNC_GPIO241 (MTK_PIN_NO(241) | 0)
+#define MT2701_PIN_241_EXT_SCK__FUNC_EXT_SCK (MTK_PIN_NO(241) | 1)
+
+#define MT2701_PIN_242_URTS2__FUNC_GPIO242 (MTK_PIN_NO(242) | 0)
+#define MT2701_PIN_242_URTS2__FUNC_URTS2 (MTK_PIN_NO(242) | 1)
+#define MT2701_PIN_242_URTS2__FUNC_UTXD3 (MTK_PIN_NO(242) | 2)
+#define MT2701_PIN_242_URTS2__FUNC_URXD3 (MTK_PIN_NO(242) | 3)
+#define MT2701_PIN_242_URTS2__FUNC_SCL1 (MTK_PIN_NO(242) | 4)
+#define MT2701_PIN_242_URTS2__FUNC_DBG_MON_B_32 (MTK_PIN_NO(242) | 7)
+
+#define MT2701_PIN_243_UCTS2__FUNC_GPIO243 (MTK_PIN_NO(243) | 0)
+#define MT2701_PIN_243_UCTS2__FUNC_UCTS2 (MTK_PIN_NO(243) | 1)
+#define MT2701_PIN_243_UCTS2__FUNC_URXD3 (MTK_PIN_NO(243) | 2)
+#define MT2701_PIN_243_UCTS2__FUNC_UTXD3 (MTK_PIN_NO(243) | 3)
+#define MT2701_PIN_243_UCTS2__FUNC_SDA1 (MTK_PIN_NO(243) | 4)
+#define MT2701_PIN_243_UCTS2__FUNC_DBG_MON_A_6 (MTK_PIN_NO(243) | 7)
+
+#define MT2701_PIN_244_HDMI_SDA_RX__FUNC_GPIO244 (MTK_PIN_NO(244) | 0)
+#define MT2701_PIN_244_HDMI_SDA_RX__FUNC_HDMI_SDA_RX (MTK_PIN_NO(244) | 1)
+
+#define MT2701_PIN_245_HDMI_SCL_RX__FUNC_GPIO245 (MTK_PIN_NO(245) | 0)
+#define MT2701_PIN_245_HDMI_SCL_RX__FUNC_HDMI_SCL_RX (MTK_PIN_NO(245) | 1)
+
+#define MT2701_PIN_246_MHL_SENCE__FUNC_GPIO246 (MTK_PIN_NO(246) | 0)
+
+#define MT2701_PIN_247_HDMI_HPD_CBUS_RX__FUNC_GPIO247 (MTK_PIN_NO(247) | 0)
+#define MT2701_PIN_247_HDMI_HPD_CBUS_RX__FUNC_HDMI_HPD_RX (MTK_PIN_NO(247) | 1)
+
+#define MT2701_PIN_248_HDMI_TESTOUTP_RX__FUNC_GPIO248 (MTK_PIN_NO(248) | 0)
+#define MT2701_PIN_248_HDMI_TESTOUTP_RX__FUNC_HDMI_TESTOUTP_RX (MTK_PIN_NO(248) | 1)
+
+#define MT2701_PIN_249_MSDC0E_RSTB__FUNC_MSDC0E_RSTB (MTK_PIN_NO(249) | 9)
+
+#define MT2701_PIN_250_MSDC0E_DAT7__FUNC_MSDC3_DAT7 (MTK_PIN_NO(250) | 9)
+#define MT2701_PIN_250_MSDC0E_DAT7__FUNC_PCIE0_CLKREQ_N (MTK_PIN_NO(250) | 14)
+
+#define MT2701_PIN_251_MSDC0E_DAT6__FUNC_MSDC3_DAT6 (MTK_PIN_NO(251) | 9)
+#define MT2701_PIN_251_MSDC0E_DAT6__FUNC_PCIE0_WAKE_N (MTK_PIN_NO(251) | 14)
+
+#define MT2701_PIN_252_MSDC0E_DAT5__FUNC_MSDC3_DAT5 (MTK_PIN_NO(252) | 9)
+#define MT2701_PIN_252_MSDC0E_DAT5__FUNC_PCIE1_CLKREQ_N (MTK_PIN_NO(252) | 14)
+
+#define MT2701_PIN_253_MSDC0E_DAT4__FUNC_MSDC3_DAT4 (MTK_PIN_NO(253) | 9)
+#define MT2701_PIN_253_MSDC0E_DAT4__FUNC_PCIE1_WAKE_N (MTK_PIN_NO(253) | 14)
+
+#define MT2701_PIN_254_MSDC0E_DAT3__FUNC_MSDC3_DAT3 (MTK_PIN_NO(254) | 9)
+#define MT2701_PIN_254_MSDC0E_DAT3__FUNC_PCIE2_CLKREQ_N (MTK_PIN_NO(254) | 14)
+
+#define MT2701_PIN_255_MSDC0E_DAT2__FUNC_MSDC3_DAT2 (MTK_PIN_NO(255) | 9)
+#define MT2701_PIN_255_MSDC0E_DAT2__FUNC_PCIE2_WAKE_N (MTK_PIN_NO(255) | 14)
+
+#define MT2701_PIN_256_MSDC0E_DAT1__FUNC_MSDC3_DAT1 (MTK_PIN_NO(256) | 9)
+
+#define MT2701_PIN_257_MSDC0E_DAT0__FUNC_MSDC3_DAT0 (MTK_PIN_NO(257) | 9)
+
+#define MT2701_PIN_258_MSDC0E_CMD__FUNC_MSDC3_CMD (MTK_PIN_NO(258) | 9)
+
+#define MT2701_PIN_259_MSDC0E_CLK__FUNC_MSDC3_CLK (MTK_PIN_NO(259) | 9)
+
+#define MT2701_PIN_260_MSDC0E_DSL__FUNC_MSDC3_DSL (MTK_PIN_NO(260) | 9)
+
+#define MT2701_PIN_261_MSDC1_INS__FUNC_GPIO261 (MTK_PIN_NO(261) | 0)
+#define MT2701_PIN_261_MSDC1_INS__FUNC_MSDC1_INS (MTK_PIN_NO(261) | 1)
+#define MT2701_PIN_261_MSDC1_INS__FUNC_DBG_MON_B_29 (MTK_PIN_NO(261) | 7)
+
+#define MT2701_PIN_262_G2_TXEN__FUNC_GPIO262 (MTK_PIN_NO(262) | 0)
+#define MT2701_PIN_262_G2_TXEN__FUNC_G2_TXEN (MTK_PIN_NO(262) | 1)
+
+#define MT2701_PIN_263_G2_TXD3__FUNC_GPIO263 (MTK_PIN_NO(263) | 0)
+#define MT2701_PIN_263_G2_TXD3__FUNC_G2_TXD3 (MTK_PIN_NO(263) | 1)
+#define MT2701_PIN_263_G2_TXD3__FUNC_ANT_SEL5 (MTK_PIN_NO(263) | 6)
+
+#define MT2701_PIN_264_G2_TXD2__FUNC_GPIO264 (MTK_PIN_NO(264) | 0)
+#define MT2701_PIN_264_G2_TXD2__FUNC_G2_TXD2 (MTK_PIN_NO(264) | 1)
+#define MT2701_PIN_264_G2_TXD2__FUNC_ANT_SEL4 (MTK_PIN_NO(264) | 6)
+
+#define MT2701_PIN_265_G2_TXD1__FUNC_GPIO265 (MTK_PIN_NO(265) | 0)
+#define MT2701_PIN_265_G2_TXD1__FUNC_G2_TXD1 (MTK_PIN_NO(265) | 1)
+#define MT2701_PIN_265_G2_TXD1__FUNC_ANT_SEL3 (MTK_PIN_NO(265) | 6)
+
+#define MT2701_PIN_266_G2_TXD0__FUNC_GPIO266 (MTK_PIN_NO(266) | 0)
+#define MT2701_PIN_266_G2_TXD0__FUNC_G2_TXD0 (MTK_PIN_NO(266) | 1)
+#define MT2701_PIN_266_G2_TXD0__FUNC_ANT_SEL2 (MTK_PIN_NO(266) | 6)
+
+#define MT2701_PIN_267_G2_TXC__FUNC_GPIO267 (MTK_PIN_NO(267) | 0)
+#define MT2701_PIN_267_G2_TXC__FUNC_G2_TXC (MTK_PIN_NO(267) | 1)
+
+#define MT2701_PIN_268_G2_RXC__FUNC_GPIO268 (MTK_PIN_NO(268) | 0)
+#define MT2701_PIN_268_G2_RXC__FUNC_G2_RXC (MTK_PIN_NO(268) | 1)
+
+#define MT2701_PIN_269_G2_RXD0__FUNC_GPIO269 (MTK_PIN_NO(269) | 0)
+#define MT2701_PIN_269_G2_RXD0__FUNC_G2_RXD0 (MTK_PIN_NO(269) | 1)
+
+#define MT2701_PIN_270_G2_RXD1__FUNC_GPIO270 (MTK_PIN_NO(270) | 0)
+#define MT2701_PIN_270_G2_RXD1__FUNC_G2_RXD1 (MTK_PIN_NO(270) | 1)
+
+#define MT2701_PIN_271_G2_RXD2__FUNC_GPIO271 (MTK_PIN_NO(271) | 0)
+#define MT2701_PIN_271_G2_RXD2__FUNC_G2_RXD2 (MTK_PIN_NO(271) | 1)
+
+#define MT2701_PIN_272_G2_RXD3__FUNC_GPIO272 (MTK_PIN_NO(272) | 0)
+#define MT2701_PIN_272_G2_RXD3__FUNC_G2_RXD3 (MTK_PIN_NO(272) | 1)
+
+#define MT2701_PIN_274_G2_RXDV__FUNC_GPIO274 (MTK_PIN_NO(274) | 0)
+#define MT2701_PIN_274_G2_RXDV__FUNC_G2_RXDV (MTK_PIN_NO(274) | 1)
+
+#define MT2701_PIN_275_MDC__FUNC_GPIO275 (MTK_PIN_NO(275) | 0)
+#define MT2701_PIN_275_MDC__FUNC_MDC (MTK_PIN_NO(275) | 1)
+#define MT2701_PIN_275_MDC__FUNC_ANT_SEL0 (MTK_PIN_NO(275) | 6)
+
+#define MT2701_PIN_276_MDIO__FUNC_GPIO276 (MTK_PIN_NO(276) | 0)
+#define MT2701_PIN_276_MDIO__FUNC_MDIO (MTK_PIN_NO(276) | 1)
+#define MT2701_PIN_276_MDIO__FUNC_ANT_SEL1 (MTK_PIN_NO(276) | 6)
+
+#define MT2701_PIN_278_JTAG_RESET__FUNC_GPIO278 (MTK_PIN_NO(278) | 0)
+#define MT2701_PIN_278_JTAG_RESET__FUNC_JTAG_RESET (MTK_PIN_NO(278) | 1)
+
+#endif /* __DTS_MT2701_PINFUNC_H */
index 420788229e6f8a30b6c3a114018c209ebad151c4..aae8a7aceab75d53f84a2eb94fc0d6e020e773a9 100644 (file)
        };
 };
 
+&devbus_bootcs {
+       status = "okay";
+       devbus,keep-config;
+
+       flash@0 {
+               compatible = "jedec-flash";
+               reg = <0 0x40000>;
+               bank-width = <1>;
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       header@0 {
+                               reg = <0 0x30000>;
+                               read-only;
+                       };
+
+                       uboot@30000 {
+                               reg = <0x30000 0xF000>;
+                               read-only;
+                       };
+
+                       uboot_env@3F000 {
+                               reg = <0x3F000 0x1000>;
+                       };
+               };
+       };
+};
+
 &mdio {
        status = "okay";
 
index 6713b1ea732b0b1d2282368ce5b50e42a9ae6043..01d239c3eaaaa3fe4ca8ab7854fbca9faa3e23e4 100644 (file)
        pinctrl-names = "default";
 
        status = "okay";
-       renesas,enable-gpio = <&gpio5 31 GPIO_ACTIVE_HIGH>;
 };
 
 &usbphy {
index 1afe24629d1f85de2a9ec3f8ef62c6372d014abd..b0c912feaa2f0e016b65ff27e272b82c2b0795ed 100644 (file)
@@ -90,7 +90,7 @@
 #define PIN_PA14__I2SC1_MCK            PINMUX_PIN(PIN_PA14, 4, 2)
 #define PIN_PA14__FLEXCOM3_IO2         PINMUX_PIN(PIN_PA14, 5, 1)
 #define PIN_PA14__D9                   PINMUX_PIN(PIN_PA14, 6, 2)
-#define PIN_PA15                       14
+#define PIN_PA15                       15
 #define PIN_PA15__GPIO                 PINMUX_PIN(PIN_PA15, 0, 0)
 #define PIN_PA15__SPI0_MOSI            PINMUX_PIN(PIN_PA15, 1, 1)
 #define PIN_PA15__TF1                  PINMUX_PIN(PIN_PA15, 2, 1)
index 3ed4abdaaa9cc4efe8b8c169b01a49f8e6b938fd..15cbc747c2425e5aa95b2c0b86aada0a14b8e46e 100644 (file)
                        status = "disabled";
                };
 
+               eccmgr: eccmgr@ffd08140 {
+                       compatible = "altr,socfpga-ecc-manager";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       l2-ecc@ffd08140 {
+                               compatible = "altr,socfpga-l2-ecc";
+                               reg = <0xffd08140 0x4>;
+                               interrupts = <0 36 1>, <0 37 1>;
+                       };
+
+                       ocram-ecc@ffd08144 {
+                               compatible = "altr,socfpga-ocram-ecc";
+                               reg = <0xffd08144 0x4>;
+                               iram = <&ocram>;
+                               interrupts = <0 178 1>, <0 179 1>;
+                       };
+               };
+
                L2: l2-cache@fffef000 {
                        compatible = "arm,pl310-cache";
                        reg = <0xfffef000 0x1000>;
diff --git a/arch/arm/boot/dts/tps65217.dtsi b/arch/arm/boot/dts/tps65217.dtsi
new file mode 100644 (file)
index 0000000..a632724
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
+ */
+
+/*
+ * Integrated Power Management Chip
+ * http://www.ti.com/lit/ds/symlink/tps65217.pdf
+ */
+
+&tps {
+       compatible = "ti,tps65217";
+
+       regulators {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               dcdc1_reg: regulator@0 {
+                       reg = <0>;
+                       regulator-compatible = "dcdc1";
+               };
+
+               dcdc2_reg: regulator@1 {
+                       reg = <1>;
+                       regulator-compatible = "dcdc2";
+               };
+
+               dcdc3_reg: regulator@2 {
+                       reg = <2>;
+                       regulator-compatible = "dcdc3";
+               };
+
+               ldo1_reg: regulator@3 {
+                       reg = <3>;
+                       regulator-compatible = "ldo1";
+               };
+
+               ldo2_reg: regulator@4 {
+                       reg = <4>;
+                       regulator-compatible = "ldo2";
+               };
+
+               ldo3_reg: regulator@5 {
+                       reg = <5>;
+                       regulator-compatible = "ldo3";
+               };
+
+               ldo4_reg: regulator@6 {
+                       reg = <6>;
+                       regulator-compatible = "ldo4";
+               };
+       };
+};
index a9ceb5bac40ef244dc6ca18602eef4072b87a57d..4539f8d909a532121771c2259598d596c1e1971e 100644 (file)
                                status = "disabled";
                        };
                };
+
+               iio-hwmon {
+                       compatible = "iio-hwmon";
+                       io-channels = <&adc0 16>, <&adc1 16>;
+               };
        };
 };
index 7da5503c0591411f43df6bc767fb8c4eef314789..e08d151840567dcb6085271200601666836b0771 100644 (file)
@@ -117,6 +117,7 @@ static inline u32 gic_read_iar(void)
        u32 irqstat;
 
        asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat));
+       dsb(sy);
        return irqstat;
 }
 
index d5525bfc7e3e61879d278ae08b446e185c206982..9156fc303afd8d278671c6d4d277d866fdd2ad7b 100644 (file)
@@ -491,7 +491,6 @@ static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
 #endif
 
 #ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
 void set_kernel_text_rw(void);
 void set_kernel_text_ro(void);
 #else
index 194c91b610ffecfd4071da89d16b923c614bf68d..15d58b42d5a18aa6e56203dd2f15d6843afc97a0 100644 (file)
 #ifndef __ARM_KVM_ASM_H__
 #define __ARM_KVM_ASM_H__
 
-/* 0 is reserved as an invalid value. */
-#define c0_MPIDR       1       /* MultiProcessor ID Register */
-#define c0_CSSELR      2       /* Cache Size Selection Register */
-#define c1_SCTLR       3       /* System Control Register */
-#define c1_ACTLR       4       /* Auxiliary Control Register */
-#define c1_CPACR       5       /* Coprocessor Access Control */
-#define c2_TTBR0       6       /* Translation Table Base Register 0 */
-#define c2_TTBR0_high  7       /* TTBR0 top 32 bits */
-#define c2_TTBR1       8       /* Translation Table Base Register 1 */
-#define c2_TTBR1_high  9       /* TTBR1 top 32 bits */
-#define c2_TTBCR       10      /* Translation Table Base Control R. */
-#define c3_DACR                11      /* Domain Access Control Register */
-#define c5_DFSR                12      /* Data Fault Status Register */
-#define c5_IFSR                13      /* Instruction Fault Status Register */
-#define c5_ADFSR       14      /* Auxilary Data Fault Status R */
-#define c5_AIFSR       15      /* Auxilary Instrunction Fault Status R */
-#define c6_DFAR                16      /* Data Fault Address Register */
-#define c6_IFAR                17      /* Instruction Fault Address Register */
-#define c7_PAR         18      /* Physical Address Register */
-#define c7_PAR_high    19      /* PAR top 32 bits */
-#define c9_L2CTLR      20      /* Cortex A15/A7 L2 Control Register */
-#define c10_PRRR       21      /* Primary Region Remap Register */
-#define c10_NMRR       22      /* Normal Memory Remap Register */
-#define c12_VBAR       23      /* Vector Base Address Register */
-#define c13_CID                24      /* Context ID Register */
-#define c13_TID_URW    25      /* Thread ID, User R/W */
-#define c13_TID_URO    26      /* Thread ID, User R/O */
-#define c13_TID_PRIV   27      /* Thread ID, Privileged */
-#define c14_CNTKCTL    28      /* Timer Control Register (PL1) */
-#define c10_AMAIR0     29      /* Auxilary Memory Attribute Indirection Reg0 */
-#define c10_AMAIR1     30      /* Auxilary Memory Attribute Indirection Reg1 */
-#define NR_CP15_REGS   31      /* Number of regs (incl. invalid) */
+#include <asm/virt.h>
 
 #define ARM_EXCEPTION_RESET      0
 #define ARM_EXCEPTION_UNDEFINED   1
@@ -86,19 +55,15 @@ struct kvm_vcpu;
 extern char __kvm_hyp_init[];
 extern char __kvm_hyp_init_end[];
 
-extern char __kvm_hyp_exit[];
-extern char __kvm_hyp_exit_end[];
-
 extern char __kvm_hyp_vector[];
 
-extern char __kvm_hyp_code_start[];
-extern char __kvm_hyp_code_end[];
-
 extern void __kvm_flush_vm_context(void);
 extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
 
 extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
+
+extern void __init_stage2_translation(void);
 #endif
 
 #endif /* __ARM_KVM_ASM_H__ */
index 3095df091ff8a571cf9b6b074c56beb69ad9243d..ee5328fc4b066eaf68c252d375f76758392a08c7 100644 (file)
@@ -68,12 +68,12 @@ static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu)
 
 static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu)
 {
-       return &vcpu->arch.regs.usr_regs.ARM_pc;
+       return &vcpu->arch.ctxt.gp_regs.usr_regs.ARM_pc;
 }
 
 static inline unsigned long *vcpu_cpsr(struct kvm_vcpu *vcpu)
 {
-       return &vcpu->arch.regs.usr_regs.ARM_cpsr;
+       return &vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr;
 }
 
 static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
@@ -83,13 +83,13 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
 
 static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
 {
-       unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
+       unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
        return (cpsr_mode > USR_MODE && cpsr_mode < SYSTEM_MODE);
 }
 
 static inline bool vcpu_mode_priv(struct kvm_vcpu *vcpu)
 {
-       unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
+       unsigned long cpsr_mode = vcpu->arch.ctxt.gp_regs.usr_regs.ARM_cpsr & MODE_MASK;
        return cpsr_mode > USR_MODE;;
 }
 
@@ -108,11 +108,6 @@ static inline phys_addr_t kvm_vcpu_get_fault_ipa(struct kvm_vcpu *vcpu)
        return ((phys_addr_t)vcpu->arch.fault.hpfar & HPFAR_MASK) << 8;
 }
 
-static inline unsigned long kvm_vcpu_get_hyp_pc(struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.fault.hyp_pc;
-}
-
 static inline bool kvm_vcpu_dabt_isvalid(struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_get_hsr(vcpu) & HSR_ISV;
@@ -143,6 +138,11 @@ static inline bool kvm_vcpu_dabt_iss1tw(struct kvm_vcpu *vcpu)
        return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_S1PTW;
 }
 
+static inline bool kvm_vcpu_dabt_is_cm(struct kvm_vcpu *vcpu)
+{
+       return !!(kvm_vcpu_get_hsr(vcpu) & HSR_DABT_CM);
+}
+
 /* Get Access Size from a data abort */
 static inline int kvm_vcpu_dabt_get_as(struct kvm_vcpu *vcpu)
 {
@@ -192,7 +192,7 @@ static inline u32 kvm_vcpu_hvc_get_imm(struct kvm_vcpu *vcpu)
 
 static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 {
-       return vcpu->arch.cp15[c0_MPIDR] & MPIDR_HWID_BITMASK;
+       return vcpu_cp15(vcpu, c0_MPIDR) & MPIDR_HWID_BITMASK;
 }
 
 static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
index f9f27792d8edc3d7a5f77b03ba72b0c051376f55..385070180c2587df524fed552ac0f36b71cac26b 100644 (file)
@@ -85,20 +85,61 @@ struct kvm_vcpu_fault_info {
        u32 hsr;                /* Hyp Syndrome Register */
        u32 hxfar;              /* Hyp Data/Inst. Fault Address Register */
        u32 hpfar;              /* Hyp IPA Fault Address Register */
-       u32 hyp_pc;             /* PC when exception was taken from Hyp mode */
 };
 
-typedef struct vfp_hard_struct kvm_cpu_context_t;
+/*
+ * 0 is reserved as an invalid value.
+ * Order should be kept in sync with the save/restore code.
+ */
+enum vcpu_sysreg {
+       __INVALID_SYSREG__,
+       c0_MPIDR,               /* MultiProcessor ID Register */
+       c0_CSSELR,              /* Cache Size Selection Register */
+       c1_SCTLR,               /* System Control Register */
+       c1_ACTLR,               /* Auxiliary Control Register */
+       c1_CPACR,               /* Coprocessor Access Control */
+       c2_TTBR0,               /* Translation Table Base Register 0 */
+       c2_TTBR0_high,          /* TTBR0 top 32 bits */
+       c2_TTBR1,               /* Translation Table Base Register 1 */
+       c2_TTBR1_high,          /* TTBR1 top 32 bits */
+       c2_TTBCR,               /* Translation Table Base Control R. */
+       c3_DACR,                /* Domain Access Control Register */
+       c5_DFSR,                /* Data Fault Status Register */
+       c5_IFSR,                /* Instruction Fault Status Register */
+       c5_ADFSR,               /* Auxilary Data Fault Status R */
+       c5_AIFSR,               /* Auxilary Instrunction Fault Status R */
+       c6_DFAR,                /* Data Fault Address Register */
+       c6_IFAR,                /* Instruction Fault Address Register */
+       c7_PAR,                 /* Physical Address Register */
+       c7_PAR_high,            /* PAR top 32 bits */
+       c9_L2CTLR,              /* Cortex A15/A7 L2 Control Register */
+       c10_PRRR,               /* Primary Region Remap Register */
+       c10_NMRR,               /* Normal Memory Remap Register */
+       c12_VBAR,               /* Vector Base Address Register */
+       c13_CID,                /* Context ID Register */
+       c13_TID_URW,            /* Thread ID, User R/W */
+       c13_TID_URO,            /* Thread ID, User R/O */
+       c13_TID_PRIV,           /* Thread ID, Privileged */
+       c14_CNTKCTL,            /* Timer Control Register (PL1) */
+       c10_AMAIR0,             /* Auxilary Memory Attribute Indirection Reg0 */
+       c10_AMAIR1,             /* Auxilary Memory Attribute Indirection Reg1 */
+       NR_CP15_REGS            /* Number of regs (incl. invalid) */
+};
+
+struct kvm_cpu_context {
+       struct kvm_regs gp_regs;
+       struct vfp_hard_struct vfp;
+       u32 cp15[NR_CP15_REGS];
+};
+
+typedef struct kvm_cpu_context kvm_cpu_context_t;
 
 struct kvm_vcpu_arch {
-       struct kvm_regs regs;
+       struct kvm_cpu_context ctxt;
 
        int target; /* Processor target */
        DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
 
-       /* System control coprocessor (cp15) */
-       u32 cp15[NR_CP15_REGS];
-
        /* The CPU type we expose to the VM */
        u32 midr;
 
@@ -111,9 +152,6 @@ struct kvm_vcpu_arch {
        /* Exception Information */
        struct kvm_vcpu_fault_info fault;
 
-       /* Floating point registers (VFP and Advanced SIMD/NEON) */
-       struct vfp_hard_struct vfp_guest;
-
        /* Host FP context */
        kvm_cpu_context_t *host_cpu_context;
 
@@ -158,12 +196,14 @@ struct kvm_vcpu_stat {
        u64 exits;
 };
 
+#define vcpu_cp15(v,r) (v)->arch.ctxt.cp15[r]
+
 int kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
 int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
 int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
 int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
-u64 kvm_call_hyp(void *hypfn, ...);
+unsigned long kvm_call_hyp(void *hypfn, ...);
 void force_vm_exit(const cpumask_t *mask);
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
@@ -220,6 +260,11 @@ static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr,
        kvm_call_hyp((void*)hyp_stack_ptr, vector_ptr, pgd_ptr);
 }
 
+static inline void __cpu_init_stage2(void)
+{
+       kvm_call_hyp(__init_stage2_translation);
+}
+
 static inline int kvm_arch_dev_ioctl_check_extension(long ext)
 {
        return 0;
@@ -242,5 +287,20 @@ static inline void kvm_arm_init_debug(void) {}
 static inline void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arm_clear_debug(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) {}
+static inline int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
+                                            struct kvm_device_attr *attr)
+{
+       return -ENXIO;
+}
+static inline int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
+                                            struct kvm_device_attr *attr)
+{
+       return -ENXIO;
+}
+static inline int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
+                                            struct kvm_device_attr *attr)
+{
+       return -ENXIO;
+}
 
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/asm/kvm_hyp.h b/arch/arm/include/asm/kvm_hyp.h
new file mode 100644 (file)
index 0000000..f0e8607
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM_KVM_HYP_H__
+#define __ARM_KVM_HYP_H__
+
+#include <linux/compiler.h>
+#include <linux/kvm_host.h>
+#include <asm/kvm_mmu.h>
+#include <asm/vfp.h>
+
+#define __hyp_text __section(.hyp.text) notrace
+
+#define kern_hyp_va(v) (v)
+#define hyp_kern_va(v) (v)
+
+#define __ACCESS_CP15(CRn, Op1, CRm, Op2)      \
+       "mrc", "mcr", __stringify(p15, Op1, %0, CRn, CRm, Op2), u32
+#define __ACCESS_CP15_64(Op1, CRm)             \
+       "mrrc", "mcrr", __stringify(p15, Op1, %Q0, %R0, CRm), u64
+#define __ACCESS_VFP(CRn)                      \
+       "mrc", "mcr", __stringify(p10, 7, %0, CRn, cr0, 0), u32
+
+#define __write_sysreg(v, r, w, c, t)  asm volatile(w " " c : : "r" ((t)(v)))
+#define write_sysreg(v, ...)           __write_sysreg(v, __VA_ARGS__)
+
+#define __read_sysreg(r, w, c, t) ({                           \
+       t __val;                                                \
+       asm volatile(r " " c : "=r" (__val));                   \
+       __val;                                                  \
+})
+#define read_sysreg(...)               __read_sysreg(__VA_ARGS__)
+
+#define write_special(v, r)                                    \
+       asm volatile("msr " __stringify(r) ", %0" : : "r" (v))
+#define read_special(r) ({                                     \
+       u32 __val;                                              \
+       asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \
+       __val;                                                  \
+})
+
+#define TTBR0          __ACCESS_CP15_64(0, c2)
+#define TTBR1          __ACCESS_CP15_64(1, c2)
+#define VTTBR          __ACCESS_CP15_64(6, c2)
+#define PAR            __ACCESS_CP15_64(0, c7)
+#define CNTV_CVAL      __ACCESS_CP15_64(3, c14)
+#define CNTVOFF                __ACCESS_CP15_64(4, c14)
+
+#define MIDR           __ACCESS_CP15(c0, 0, c0, 0)
+#define CSSELR         __ACCESS_CP15(c0, 2, c0, 0)
+#define VPIDR          __ACCESS_CP15(c0, 4, c0, 0)
+#define VMPIDR         __ACCESS_CP15(c0, 4, c0, 5)
+#define SCTLR          __ACCESS_CP15(c1, 0, c0, 0)
+#define CPACR          __ACCESS_CP15(c1, 0, c0, 2)
+#define HCR            __ACCESS_CP15(c1, 4, c1, 0)
+#define HDCR           __ACCESS_CP15(c1, 4, c1, 1)
+#define HCPTR          __ACCESS_CP15(c1, 4, c1, 2)
+#define HSTR           __ACCESS_CP15(c1, 4, c1, 3)
+#define TTBCR          __ACCESS_CP15(c2, 0, c0, 2)
+#define HTCR           __ACCESS_CP15(c2, 4, c0, 2)
+#define VTCR           __ACCESS_CP15(c2, 4, c1, 2)
+#define DACR           __ACCESS_CP15(c3, 0, c0, 0)
+#define DFSR           __ACCESS_CP15(c5, 0, c0, 0)
+#define IFSR           __ACCESS_CP15(c5, 0, c0, 1)
+#define ADFSR          __ACCESS_CP15(c5, 0, c1, 0)
+#define AIFSR          __ACCESS_CP15(c5, 0, c1, 1)
+#define HSR            __ACCESS_CP15(c5, 4, c2, 0)
+#define DFAR           __ACCESS_CP15(c6, 0, c0, 0)
+#define IFAR           __ACCESS_CP15(c6, 0, c0, 2)
+#define HDFAR          __ACCESS_CP15(c6, 4, c0, 0)
+#define HIFAR          __ACCESS_CP15(c6, 4, c0, 2)
+#define HPFAR          __ACCESS_CP15(c6, 4, c0, 4)
+#define ICIALLUIS      __ACCESS_CP15(c7, 0, c1, 0)
+#define ATS1CPR                __ACCESS_CP15(c7, 0, c8, 0)
+#define TLBIALLIS      __ACCESS_CP15(c8, 0, c3, 0)
+#define TLBIALLNSNHIS  __ACCESS_CP15(c8, 4, c3, 4)
+#define PRRR           __ACCESS_CP15(c10, 0, c2, 0)
+#define NMRR           __ACCESS_CP15(c10, 0, c2, 1)
+#define AMAIR0         __ACCESS_CP15(c10, 0, c3, 0)
+#define AMAIR1         __ACCESS_CP15(c10, 0, c3, 1)
+#define VBAR           __ACCESS_CP15(c12, 0, c0, 0)
+#define CID            __ACCESS_CP15(c13, 0, c0, 1)
+#define TID_URW                __ACCESS_CP15(c13, 0, c0, 2)
+#define TID_URO                __ACCESS_CP15(c13, 0, c0, 3)
+#define TID_PRIV       __ACCESS_CP15(c13, 0, c0, 4)
+#define HTPIDR         __ACCESS_CP15(c13, 4, c0, 2)
+#define CNTKCTL                __ACCESS_CP15(c14, 0, c1, 0)
+#define CNTV_CTL       __ACCESS_CP15(c14, 0, c3, 1)
+#define CNTHCTL                __ACCESS_CP15(c14, 4, c1, 0)
+
+#define VFP_FPEXC      __ACCESS_VFP(FPEXC)
+
+/* AArch64 compatibility macros, only for the timer so far */
+#define read_sysreg_el0(r)             read_sysreg(r##_el0)
+#define write_sysreg_el0(v, r)         write_sysreg(v, r##_el0)
+
+#define cntv_ctl_el0                   CNTV_CTL
+#define cntv_cval_el0                  CNTV_CVAL
+#define cntvoff_el2                    CNTVOFF
+#define cnthctl_el2                    CNTHCTL
+
+void __timer_save_state(struct kvm_vcpu *vcpu);
+void __timer_restore_state(struct kvm_vcpu *vcpu);
+
+void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
+void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
+
+void __sysreg_save_state(struct kvm_cpu_context *ctxt);
+void __sysreg_restore_state(struct kvm_cpu_context *ctxt);
+
+void asmlinkage __vfp_save_state(struct vfp_hard_struct *vfp);
+void asmlinkage __vfp_restore_state(struct vfp_hard_struct *vfp);
+static inline bool __vfp_enabled(void)
+{
+       return !(read_sysreg(HCPTR) & (HCPTR_TCP(11) | HCPTR_TCP(10)));
+}
+
+void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt);
+void __hyp_text __banked_restore_state(struct kvm_cpu_context *ctxt);
+
+int asmlinkage __guest_enter(struct kvm_vcpu *vcpu,
+                            struct kvm_cpu_context *host);
+int asmlinkage __hyp_do_panic(const char *, int, u32);
+
+#endif /* __ARM_KVM_HYP_H__ */
index a520b7987a29c3626c0f58b86d896fefaf69ad06..da44be9db4fab3ed973d03abd6060cf8b0f8ae29 100644 (file)
@@ -179,7 +179,7 @@ struct kvm;
 
 static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
 {
-       return (vcpu->arch.cp15[c1_SCTLR] & 0b101) == 0b101;
+       return (vcpu_cp15(vcpu, c1_SCTLR) & 0b101) == 0b101;
 }
 
 static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu,
index a5635444ca410b49b5109a65535321d9c3df8d5c..057d381f4e57bb95167db49c9aea2b52ef303b76 100644 (file)
@@ -2,9 +2,6 @@
 #define ASMARM_PCI_H
 
 #ifdef __KERNEL__
-#include <asm-generic/pci-dma-compat.h>
-#include <asm-generic/pci-bridge.h>
-
 #include <asm/mach/pci.h> /* for pci_sys_data */
 
 extern unsigned long pcibios_min_io;
@@ -41,5 +38,4 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 }
 
 #endif /* __KERNEL__ */
 #endif
index 4371f45c578401c7f233e565dbb5fd36d9d59d52..d4ceaf5f299b8d03d6e638a3ea5f72fb5b60a93e 100644 (file)
@@ -74,6 +74,15 @@ static inline bool is_hyp_mode_mismatched(void)
 {
        return !!(__boot_cpu_mode & BOOT_CPU_MODE_MISMATCH);
 }
+
+static inline bool is_kernel_in_hyp_mode(void)
+{
+       return false;
+}
+
+/* The section containing the hypervisor text */
+extern char __hyp_text_start[];
+extern char __hyp_text_end[];
 #endif
 
 #endif /* __ASSEMBLY__ */
index 2c5f160be65e44cbabc2c5d01b023d56df0a1985..ad325a8c7e1e5d1dfbad11e8846169696d36e6bc 100644 (file)
@@ -88,6 +88,7 @@ obj-$(CONFIG_DEBUG_LL)        += debug.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 
 obj-$(CONFIG_ARM_VIRT_EXT)     += hyp-stub.o
+AFLAGS_hyp-stub.o              :=-Wa,-march=armv7-a
 ifeq ($(CONFIG_ARM_PSCI),y)
 obj-$(CONFIG_SMP)              += psci_smp.o
 endif
index 871b8267d211af0e5eaf9d5fb9f8329ae33696e1..27d05813ff09c09d167a27b2c790bf1ba0135ba5 100644 (file)
@@ -170,41 +170,11 @@ int main(void)
   DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE);
   BLANK();
 #ifdef CONFIG_KVM_ARM_HOST
-  DEFINE(VCPU_KVM,             offsetof(struct kvm_vcpu, kvm));
-  DEFINE(VCPU_MIDR,            offsetof(struct kvm_vcpu, arch.midr));
-  DEFINE(VCPU_CP15,            offsetof(struct kvm_vcpu, arch.cp15));
-  DEFINE(VCPU_VFP_GUEST,       offsetof(struct kvm_vcpu, arch.vfp_guest));
-  DEFINE(VCPU_VFP_HOST,                offsetof(struct kvm_vcpu, arch.host_cpu_context));
-  DEFINE(VCPU_REGS,            offsetof(struct kvm_vcpu, arch.regs));
-  DEFINE(VCPU_USR_REGS,                offsetof(struct kvm_vcpu, arch.regs.usr_regs));
-  DEFINE(VCPU_SVC_REGS,                offsetof(struct kvm_vcpu, arch.regs.svc_regs));
-  DEFINE(VCPU_ABT_REGS,                offsetof(struct kvm_vcpu, arch.regs.abt_regs));
-  DEFINE(VCPU_UND_REGS,                offsetof(struct kvm_vcpu, arch.regs.und_regs));
-  DEFINE(VCPU_IRQ_REGS,                offsetof(struct kvm_vcpu, arch.regs.irq_regs));
-  DEFINE(VCPU_FIQ_REGS,                offsetof(struct kvm_vcpu, arch.regs.fiq_regs));
-  DEFINE(VCPU_PC,              offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc));
-  DEFINE(VCPU_CPSR,            offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr));
-  DEFINE(VCPU_HCR,             offsetof(struct kvm_vcpu, arch.hcr));
-  DEFINE(VCPU_IRQ_LINES,       offsetof(struct kvm_vcpu, arch.irq_lines));
-  DEFINE(VCPU_HSR,             offsetof(struct kvm_vcpu, arch.fault.hsr));
-  DEFINE(VCPU_HxFAR,           offsetof(struct kvm_vcpu, arch.fault.hxfar));
-  DEFINE(VCPU_HPFAR,           offsetof(struct kvm_vcpu, arch.fault.hpfar));
-  DEFINE(VCPU_HYP_PC,          offsetof(struct kvm_vcpu, arch.fault.hyp_pc));
-  DEFINE(VCPU_VGIC_CPU,                offsetof(struct kvm_vcpu, arch.vgic_cpu));
-  DEFINE(VGIC_V2_CPU_HCR,      offsetof(struct vgic_cpu, vgic_v2.vgic_hcr));
-  DEFINE(VGIC_V2_CPU_VMCR,     offsetof(struct vgic_cpu, vgic_v2.vgic_vmcr));
-  DEFINE(VGIC_V2_CPU_MISR,     offsetof(struct vgic_cpu, vgic_v2.vgic_misr));
-  DEFINE(VGIC_V2_CPU_EISR,     offsetof(struct vgic_cpu, vgic_v2.vgic_eisr));
-  DEFINE(VGIC_V2_CPU_ELRSR,    offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr));
-  DEFINE(VGIC_V2_CPU_APR,      offsetof(struct vgic_cpu, vgic_v2.vgic_apr));
-  DEFINE(VGIC_V2_CPU_LR,       offsetof(struct vgic_cpu, vgic_v2.vgic_lr));
-  DEFINE(VGIC_CPU_NR_LR,       offsetof(struct vgic_cpu, nr_lr));
-  DEFINE(VCPU_TIMER_CNTV_CTL,  offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
-  DEFINE(VCPU_TIMER_CNTV_CVAL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_cval));
-  DEFINE(KVM_TIMER_CNTVOFF,    offsetof(struct kvm, arch.timer.cntvoff));
-  DEFINE(KVM_TIMER_ENABLED,    offsetof(struct kvm, arch.timer.enabled));
-  DEFINE(KVM_VGIC_VCTRL,       offsetof(struct kvm, arch.vgic.vctrl_base));
-  DEFINE(KVM_VTTBR,            offsetof(struct kvm, arch.vttbr));
+  DEFINE(VCPU_GUEST_CTXT,      offsetof(struct kvm_vcpu, arch.ctxt));
+  DEFINE(VCPU_HOST_CTXT,       offsetof(struct kvm_vcpu, arch.host_cpu_context));
+  DEFINE(CPU_CTXT_VFP,         offsetof(struct kvm_cpu_context, vfp));
+  DEFINE(CPU_CTXT_GP_REGS,     offsetof(struct kvm_cpu_context, gp_regs));
+  DEFINE(GP_REGS_USR,          offsetof(struct kvm_regs, usr_regs));
 #endif
   BLANK();
 #ifdef CONFIG_VDSO
index 7d0cba6f1cc5efadff31fd0cde2aca3279e120da..139791ed473d5264682c004ea2ea7af8ddd28f5d 100644 (file)
@@ -176,13 +176,13 @@ static struct resource mem_res[] = {
                .name = "Kernel code",
                .start = 0,
                .end = 0,
-               .flags = IORESOURCE_MEM
+               .flags = IORESOURCE_SYSTEM_RAM
        },
        {
                .name = "Kernel data",
                .start = 0,
                .end = 0,
-               .flags = IORESOURCE_MEM
+               .flags = IORESOURCE_SYSTEM_RAM
        }
 };
 
@@ -851,7 +851,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc)
                res->name  = "System RAM";
                res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
                res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
-               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
                request_resource(&iomem_resource, res);
 
index 37312f6749f3dd641f48803b67c8f26a4623a8a2..baee70267f2939367ab412a8adaa5df929bb3f10 100644 (file)
@@ -409,7 +409,7 @@ asmlinkage void secondary_start_kernel(void)
        /*
         * OK, it's off to the idle thread for us
         */
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 void __init smp_cpus_done(unsigned int max_cpus)
index 8b60fde5ce48a628e5d1f2c682d2aa0684ed6642..b4139cbbbdd9830e7a4b74d9e306094bd1fe78b6 100644 (file)
        *(.proc.info.init)                                              \
        VMLINUX_SYMBOL(__proc_info_end) = .;
 
+#define HYPERVISOR_TEXT                                                        \
+       VMLINUX_SYMBOL(__hyp_text_start) = .;                           \
+       *(.hyp.text)                                                    \
+       VMLINUX_SYMBOL(__hyp_text_end) = .;
+
 #define IDMAP_TEXT                                                     \
        ALIGN_FUNCTION();                                               \
        VMLINUX_SYMBOL(__idmap_text_start) = .;                         \
@@ -108,6 +113,7 @@ SECTIONS
                        TEXT_TEXT
                        SCHED_TEXT
                        LOCK_TEXT
+                       HYPERVISOR_TEXT
                        KPROBES_TEXT
                        *(.gnu.warning)
                        *(.glue_7)
index c5eef02c52ba76b24ac7fa996e04a988d674e751..eb1bf4309c13a8c517288b0aa72e86f0fc376b06 100644 (file)
@@ -17,6 +17,7 @@ AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
 KVM := ../../../virt/kvm
 kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
 
+obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
index dda1959f0ddeb947e8a8020d7da0b02bb19f89cc..76552b51c7aea64fb9b8cc84436abad526991732 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/kvm.h>
 #include <trace/events/kvm.h>
+#include <kvm/arm_pmu.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -265,6 +266,7 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
        kvm_mmu_free_memory_caches(vcpu);
        kvm_timer_vcpu_terminate(vcpu);
        kvm_vgic_vcpu_destroy(vcpu);
+       kvm_pmu_vcpu_destroy(vcpu);
        kmem_cache_free(kvm_vcpu_cache, vcpu);
 }
 
@@ -320,6 +322,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
        vcpu->cpu = -1;
 
        kvm_arm_set_running_vcpu(NULL);
+       kvm_timer_vcpu_put(vcpu);
 }
 
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
@@ -506,18 +509,18 @@ static void kvm_arm_resume_guest(struct kvm *kvm)
        struct kvm_vcpu *vcpu;
 
        kvm_for_each_vcpu(i, vcpu, kvm) {
-               wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
+               struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
 
                vcpu->arch.pause = false;
-               wake_up_interruptible(wq);
+               swake_up(wq);
        }
 }
 
 static void vcpu_sleep(struct kvm_vcpu *vcpu)
 {
-       wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu);
+       struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
 
-       wait_event_interruptible(*wq, ((!vcpu->arch.power_off) &&
+       swait_event_interruptible(*wq, ((!vcpu->arch.power_off) &&
                                       (!vcpu->arch.pause)));
 }
 
@@ -577,6 +580,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                 * non-preemptible context.
                 */
                preempt_disable();
+               kvm_pmu_flush_hwstate(vcpu);
                kvm_timer_flush_hwstate(vcpu);
                kvm_vgic_flush_hwstate(vcpu);
 
@@ -593,6 +597,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) ||
                        vcpu->arch.power_off || vcpu->arch.pause) {
                        local_irq_enable();
+                       kvm_pmu_sync_hwstate(vcpu);
                        kvm_timer_sync_hwstate(vcpu);
                        kvm_vgic_sync_hwstate(vcpu);
                        preempt_enable();
@@ -642,10 +647,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
                trace_kvm_exit(ret, kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu));
 
                /*
-                * We must sync the timer state before the vgic state so that
-                * the vgic can properly sample the updated state of the
+                * We must sync the PMU and timer state before the vgic state so
+                * that the vgic can properly sample the updated state of the
                 * interrupt line.
                 */
+               kvm_pmu_sync_hwstate(vcpu);
                kvm_timer_sync_hwstate(vcpu);
 
                kvm_vgic_sync_hwstate(vcpu);
@@ -823,11 +829,54 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+static int kvm_arm_vcpu_set_attr(struct kvm_vcpu *vcpu,
+                                struct kvm_device_attr *attr)
+{
+       int ret = -ENXIO;
+
+       switch (attr->group) {
+       default:
+               ret = kvm_arm_vcpu_arch_set_attr(vcpu, attr);
+               break;
+       }
+
+       return ret;
+}
+
+static int kvm_arm_vcpu_get_attr(struct kvm_vcpu *vcpu,
+                                struct kvm_device_attr *attr)
+{
+       int ret = -ENXIO;
+
+       switch (attr->group) {
+       default:
+               ret = kvm_arm_vcpu_arch_get_attr(vcpu, attr);
+               break;
+       }
+
+       return ret;
+}
+
+static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu,
+                                struct kvm_device_attr *attr)
+{
+       int ret = -ENXIO;
+
+       switch (attr->group) {
+       default:
+               ret = kvm_arm_vcpu_arch_has_attr(vcpu, attr);
+               break;
+       }
+
+       return ret;
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp,
                         unsigned int ioctl, unsigned long arg)
 {
        struct kvm_vcpu *vcpu = filp->private_data;
        void __user *argp = (void __user *)arg;
+       struct kvm_device_attr attr;
 
        switch (ioctl) {
        case KVM_ARM_VCPU_INIT: {
@@ -870,6 +919,21 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                        return -E2BIG;
                return kvm_arm_copy_reg_indices(vcpu, user_list->reg);
        }
+       case KVM_SET_DEVICE_ATTR: {
+               if (copy_from_user(&attr, argp, sizeof(attr)))
+                       return -EFAULT;
+               return kvm_arm_vcpu_set_attr(vcpu, &attr);
+       }
+       case KVM_GET_DEVICE_ATTR: {
+               if (copy_from_user(&attr, argp, sizeof(attr)))
+                       return -EFAULT;
+               return kvm_arm_vcpu_get_attr(vcpu, &attr);
+       }
+       case KVM_HAS_DEVICE_ATTR: {
+               if (copy_from_user(&attr, argp, sizeof(attr)))
+                       return -EFAULT;
+               return kvm_arm_vcpu_has_attr(vcpu, &attr);
+       }
        default:
                return -EINVAL;
        }
@@ -967,6 +1031,11 @@ long kvm_arch_vm_ioctl(struct file *filp,
        }
 }
 
+static void cpu_init_stage2(void *dummy)
+{
+       __cpu_init_stage2();
+}
+
 static void cpu_init_hyp_mode(void *dummy)
 {
        phys_addr_t boot_pgd_ptr;
@@ -985,6 +1054,7 @@ static void cpu_init_hyp_mode(void *dummy)
        vector_ptr = (unsigned long)__kvm_hyp_vector;
 
        __cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
+       __cpu_init_stage2();
 
        kvm_arm_init_debug();
 }
@@ -1035,6 +1105,82 @@ static inline void hyp_cpu_pm_init(void)
 }
 #endif
 
+static void teardown_common_resources(void)
+{
+       free_percpu(kvm_host_cpu_state);
+}
+
+static int init_common_resources(void)
+{
+       kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t);
+       if (!kvm_host_cpu_state) {
+               kvm_err("Cannot allocate host CPU state\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int init_subsystems(void)
+{
+       int err;
+
+       /*
+        * Init HYP view of VGIC
+        */
+       err = kvm_vgic_hyp_init();
+       switch (err) {
+       case 0:
+               vgic_present = true;
+               break;
+       case -ENODEV:
+       case -ENXIO:
+               vgic_present = false;
+               break;
+       default:
+               return err;
+       }
+
+       /*
+        * Init HYP architected timer support
+        */
+       err = kvm_timer_hyp_init();
+       if (err)
+               return err;
+
+       kvm_perf_init();
+       kvm_coproc_table_init();
+
+       return 0;
+}
+
+static void teardown_hyp_mode(void)
+{
+       int cpu;
+
+       if (is_kernel_in_hyp_mode())
+               return;
+
+       free_hyp_pgds();
+       for_each_possible_cpu(cpu)
+               free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
+}
+
+static int init_vhe_mode(void)
+{
+       /*
+        * Execute the init code on each CPU.
+        */
+       on_each_cpu(cpu_init_stage2, NULL, 1);
+
+       /* set size of VMID supported by CPU */
+       kvm_vmid_bits = kvm_get_vmid_bits();
+       kvm_info("%d-bit VMID\n", kvm_vmid_bits);
+
+       kvm_info("VHE mode initialized successfully\n");
+       return 0;
+}
+
 /**
  * Inits Hyp-mode on all online CPUs
  */
@@ -1065,7 +1211,7 @@ static int init_hyp_mode(void)
                stack_page = __get_free_page(GFP_KERNEL);
                if (!stack_page) {
                        err = -ENOMEM;
-                       goto out_free_stack_pages;
+                       goto out_err;
                }
 
                per_cpu(kvm_arm_hyp_stack_page, cpu) = stack_page;
@@ -1074,16 +1220,16 @@ static int init_hyp_mode(void)
        /*
         * Map the Hyp-code called directly from the host
         */
-       err = create_hyp_mappings(__kvm_hyp_code_start, __kvm_hyp_code_end);
+       err = create_hyp_mappings(__hyp_text_start, __hyp_text_end);
        if (err) {
                kvm_err("Cannot map world-switch code\n");
-               goto out_free_mappings;
+               goto out_err;
        }
 
        err = create_hyp_mappings(__start_rodata, __end_rodata);
        if (err) {
                kvm_err("Cannot map rodata section\n");
-               goto out_free_mappings;
+               goto out_err;
        }
 
        /*
@@ -1095,20 +1241,10 @@ static int init_hyp_mode(void)
 
                if (err) {
                        kvm_err("Cannot map hyp stack\n");
-                       goto out_free_mappings;
+                       goto out_err;
                }
        }
 
-       /*
-        * Map the host CPU structures
-        */
-       kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t);
-       if (!kvm_host_cpu_state) {
-               err = -ENOMEM;
-               kvm_err("Cannot allocate host CPU state\n");
-               goto out_free_mappings;
-       }
-
        for_each_possible_cpu(cpu) {
                kvm_cpu_context_t *cpu_ctxt;
 
@@ -1117,7 +1253,7 @@ static int init_hyp_mode(void)
 
                if (err) {
                        kvm_err("Cannot map host CPU state: %d\n", err);
-                       goto out_free_context;
+                       goto out_err;
                }
        }
 
@@ -1126,34 +1262,22 @@ static int init_hyp_mode(void)
         */
        on_each_cpu(cpu_init_hyp_mode, NULL, 1);
 
-       /*
-        * Init HYP view of VGIC
-        */
-       err = kvm_vgic_hyp_init();
-       switch (err) {
-       case 0:
-               vgic_present = true;
-               break;
-       case -ENODEV:
-       case -ENXIO:
-               vgic_present = false;
-               break;
-       default:
-               goto out_free_context;
-       }
-
-       /*
-        * Init HYP architected timer support
-        */
-       err = kvm_timer_hyp_init();
-       if (err)
-               goto out_free_context;
-
 #ifndef CONFIG_HOTPLUG_CPU
        free_boot_hyp_pgd();
 #endif
 
-       kvm_perf_init();
+       cpu_notifier_register_begin();
+
+       err = __register_cpu_notifier(&hyp_init_cpu_nb);
+
+       cpu_notifier_register_done();
+
+       if (err) {
+               kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
+               goto out_err;
+       }
+
+       hyp_cpu_pm_init();
 
        /* set size of VMID supported by CPU */
        kvm_vmid_bits = kvm_get_vmid_bits();
@@ -1162,14 +1286,9 @@ static int init_hyp_mode(void)
        kvm_info("Hyp mode initialized successfully\n");
 
        return 0;
-out_free_context:
-       free_percpu(kvm_host_cpu_state);
-out_free_mappings:
-       free_hyp_pgds();
-out_free_stack_pages:
-       for_each_possible_cpu(cpu)
-               free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
+
 out_err:
+       teardown_hyp_mode();
        kvm_err("error initializing Hyp mode: %d\n", err);
        return err;
 }
@@ -1213,26 +1332,27 @@ int kvm_arch_init(void *opaque)
                }
        }
 
-       cpu_notifier_register_begin();
-
-       err = init_hyp_mode();
+       err = init_common_resources();
        if (err)
-               goto out_err;
+               return err;
 
-       err = __register_cpu_notifier(&hyp_init_cpu_nb);
-       if (err) {
-               kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
+       if (is_kernel_in_hyp_mode())
+               err = init_vhe_mode();
+       else
+               err = init_hyp_mode();
+       if (err)
                goto out_err;
-       }
-
-       cpu_notifier_register_done();
 
-       hyp_cpu_pm_init();
+       err = init_subsystems();
+       if (err)
+               goto out_hyp;
 
-       kvm_coproc_table_init();
        return 0;
+
+out_hyp:
+       teardown_hyp_mode();
 out_err:
-       cpu_notifier_register_done();
+       teardown_common_resources();
        return err;
 }
 
index f3d88dc388bc560778d49dacfded70aebde44a89..1bb2b79c01ff1ac5a9e37cbc1b672d24a1798456 100644 (file)
@@ -16,6 +16,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
+#include <linux/bsearch.h>
 #include <linux/mm.h>
 #include <linux/kvm_host.h>
 #include <linux/uaccess.h>
@@ -54,8 +56,8 @@ static inline void vcpu_cp15_reg64_set(struct kvm_vcpu *vcpu,
                                       const struct coproc_reg *r,
                                       u64 val)
 {
-       vcpu->arch.cp15[r->reg] = val & 0xffffffff;
-       vcpu->arch.cp15[r->reg + 1] = val >> 32;
+       vcpu_cp15(vcpu, r->reg) = val & 0xffffffff;
+       vcpu_cp15(vcpu, r->reg + 1) = val >> 32;
 }
 
 static inline u64 vcpu_cp15_reg64_get(struct kvm_vcpu *vcpu,
@@ -63,9 +65,9 @@ static inline u64 vcpu_cp15_reg64_get(struct kvm_vcpu *vcpu,
 {
        u64 val;
 
-       val = vcpu->arch.cp15[r->reg + 1];
+       val = vcpu_cp15(vcpu, r->reg + 1);
        val = val << 32;
-       val = val | vcpu->arch.cp15[r->reg];
+       val = val | vcpu_cp15(vcpu, r->reg);
        return val;
 }
 
@@ -104,7 +106,7 @@ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
         * vcpu_id, but we read the 'U' bit from the underlying
         * hardware directly.
         */
-       vcpu->arch.cp15[c0_MPIDR] = ((read_cpuid_mpidr() & MPIDR_SMP_BITMASK) |
+       vcpu_cp15(vcpu, c0_MPIDR) = ((read_cpuid_mpidr() & MPIDR_SMP_BITMASK) |
                                     ((vcpu->vcpu_id >> 2) << MPIDR_LEVEL_BITS) |
                                     (vcpu->vcpu_id & 3));
 }
@@ -117,7 +119,7 @@ static bool access_actlr(struct kvm_vcpu *vcpu,
        if (p->is_write)
                return ignore_write(vcpu, p);
 
-       *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR];
+       *vcpu_reg(vcpu, p->Rt1) = vcpu_cp15(vcpu, c1_ACTLR);
        return true;
 }
 
@@ -139,7 +141,7 @@ static bool access_l2ctlr(struct kvm_vcpu *vcpu,
        if (p->is_write)
                return ignore_write(vcpu, p);
 
-       *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR];
+       *vcpu_reg(vcpu, p->Rt1) = vcpu_cp15(vcpu, c9_L2CTLR);
        return true;
 }
 
@@ -156,7 +158,7 @@ static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
        ncores = min(ncores, 3U);
        l2ctlr |= (ncores & 3) << 24;
 
-       vcpu->arch.cp15[c9_L2CTLR] = l2ctlr;
+       vcpu_cp15(vcpu, c9_L2CTLR) = l2ctlr;
 }
 
 static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
@@ -171,7 +173,7 @@ static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
        else
                actlr &= ~(1U << 6);
 
-       vcpu->arch.cp15[c1_ACTLR] = actlr;
+       vcpu_cp15(vcpu, c1_ACTLR) = actlr;
 }
 
 /*
@@ -218,9 +220,9 @@ bool access_vm_reg(struct kvm_vcpu *vcpu,
 
        BUG_ON(!p->is_write);
 
-       vcpu->arch.cp15[r->reg] = *vcpu_reg(vcpu, p->Rt1);
+       vcpu_cp15(vcpu, r->reg) = *vcpu_reg(vcpu, p->Rt1);
        if (p->is_64bit)
-               vcpu->arch.cp15[r->reg + 1] = *vcpu_reg(vcpu, p->Rt2);
+               vcpu_cp15(vcpu, r->reg + 1) = *vcpu_reg(vcpu, p->Rt2);
 
        kvm_toggle_cache(vcpu, was_enabled);
        return true;
@@ -381,17 +383,26 @@ static const struct coproc_reg cp15_regs[] = {
        { CRn(15), CRm( 0), Op1( 4), Op2( 0), is32, access_cbar},
 };
 
+static int check_reg_table(const struct coproc_reg *table, unsigned int n)
+{
+       unsigned int i;
+
+       for (i = 1; i < n; i++) {
+               if (cmp_reg(&table[i-1], &table[i]) >= 0) {
+                       kvm_err("reg table %p out of order (%d)\n", table, i - 1);
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
 /* Target specific emulation tables */
 static struct kvm_coproc_target_table *target_tables[KVM_ARM_NUM_TARGETS];
 
 void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table)
 {
-       unsigned int i;
-
-       for (i = 1; i < table->num; i++)
-               BUG_ON(cmp_reg(&table->table[i-1],
-                              &table->table[i]) >= 0);
-
+       BUG_ON(check_reg_table(table->table, table->num));
        target_tables[table->target] = table;
 }
 
@@ -405,29 +416,32 @@ static const struct coproc_reg *get_target_table(unsigned target, size_t *num)
        return table->table;
 }
 
+#define reg_to_match_value(x)                                          \
+       ({                                                              \
+               unsigned long val;                                      \
+               val  = (x)->CRn << 11;                                  \
+               val |= (x)->CRm << 7;                                   \
+               val |= (x)->Op1 << 4;                                   \
+               val |= (x)->Op2 << 1;                                   \
+               val |= !(x)->is_64bit;                                  \
+               val;                                                    \
+        })
+
+static int match_reg(const void *key, const void *elt)
+{
+       const unsigned long pval = (unsigned long)key;
+       const struct coproc_reg *r = elt;
+
+       return pval - reg_to_match_value(r);
+}
+
 static const struct coproc_reg *find_reg(const struct coproc_params *params,
                                         const struct coproc_reg table[],
                                         unsigned int num)
 {
-       unsigned int i;
-
-       for (i = 0; i < num; i++) {
-               const struct coproc_reg *r = &table[i];
-
-               if (params->is_64bit != r->is_64)
-                       continue;
-               if (params->CRn != r->CRn)
-                       continue;
-               if (params->CRm != r->CRm)
-                       continue;
-               if (params->Op1 != r->Op1)
-                       continue;
-               if (params->Op2 != r->Op2)
-                       continue;
+       unsigned long pval = reg_to_match_value(params);
 
-               return r;
-       }
-       return NULL;
+       return bsearch((void *)pval, table, num, sizeof(table[0]), match_reg);
 }
 
 static int emulate_cp15(struct kvm_vcpu *vcpu,
@@ -645,6 +659,9 @@ static struct coproc_reg invariant_cp15[] = {
        { CRn( 0), CRm( 0), Op1( 0), Op2( 3), is32, NULL, get_TLBTR },
        { CRn( 0), CRm( 0), Op1( 0), Op2( 6), is32, NULL, get_REVIDR },
 
+       { CRn( 0), CRm( 0), Op1( 1), Op2( 1), is32, NULL, get_CLIDR },
+       { CRn( 0), CRm( 0), Op1( 1), Op2( 7), is32, NULL, get_AIDR },
+
        { CRn( 0), CRm( 1), Op1( 0), Op2( 0), is32, NULL, get_ID_PFR0 },
        { CRn( 0), CRm( 1), Op1( 0), Op2( 1), is32, NULL, get_ID_PFR1 },
        { CRn( 0), CRm( 1), Op1( 0), Op2( 2), is32, NULL, get_ID_DFR0 },
@@ -660,9 +677,6 @@ static struct coproc_reg invariant_cp15[] = {
        { CRn( 0), CRm( 2), Op1( 0), Op2( 3), is32, NULL, get_ID_ISAR3 },
        { CRn( 0), CRm( 2), Op1( 0), Op2( 4), is32, NULL, get_ID_ISAR4 },
        { CRn( 0), CRm( 2), Op1( 0), Op2( 5), is32, NULL, get_ID_ISAR5 },
-
-       { CRn( 0), CRm( 0), Op1( 1), Op2( 1), is32, NULL, get_CLIDR },
-       { CRn( 0), CRm( 0), Op1( 1), Op2( 7), is32, NULL, get_AIDR },
 };
 
 /*
@@ -901,7 +915,7 @@ static int vfp_get_reg(const struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
        if (vfpid < num_fp_regs()) {
                if (KVM_REG_SIZE(id) != 8)
                        return -ENOENT;
-               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpregs[vfpid],
+               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpregs[vfpid],
                                   id);
        }
 
@@ -911,13 +925,13 @@ static int vfp_get_reg(const struct kvm_vcpu *vcpu, u64 id, void __user *uaddr)
 
        switch (vfpid) {
        case KVM_REG_ARM_VFP_FPEXC:
-               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpexc, id);
+               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpexc, id);
        case KVM_REG_ARM_VFP_FPSCR:
-               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpscr, id);
+               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpscr, id);
        case KVM_REG_ARM_VFP_FPINST:
-               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpinst, id);
+               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpinst, id);
        case KVM_REG_ARM_VFP_FPINST2:
-               return reg_to_user(uaddr, &vcpu->arch.vfp_guest.fpinst2, id);
+               return reg_to_user(uaddr, &vcpu->arch.ctxt.vfp.fpinst2, id);
        case KVM_REG_ARM_VFP_MVFR0:
                val = fmrx(MVFR0);
                return reg_to_user(uaddr, &val, id);
@@ -945,7 +959,7 @@ static int vfp_set_reg(struct kvm_vcpu *vcpu, u64 id, const void __user *uaddr)
        if (vfpid < num_fp_regs()) {
                if (KVM_REG_SIZE(id) != 8)
                        return -ENOENT;
-               return reg_from_user(&vcpu->arch.vfp_guest.fpregs[vfpid],
+               return reg_from_user(&vcpu->arch.ctxt.vfp.fpregs[vfpid],
                                     uaddr, id);
        }
 
@@ -955,13 +969,13 @@ static int vfp_set_reg(struct kvm_vcpu *vcpu, u64 id, const void __user *uaddr)
 
        switch (vfpid) {
        case KVM_REG_ARM_VFP_FPEXC:
-               return reg_from_user(&vcpu->arch.vfp_guest.fpexc, uaddr, id);
+               return reg_from_user(&vcpu->arch.ctxt.vfp.fpexc, uaddr, id);
        case KVM_REG_ARM_VFP_FPSCR:
-               return reg_from_user(&vcpu->arch.vfp_guest.fpscr, uaddr, id);
+               return reg_from_user(&vcpu->arch.ctxt.vfp.fpscr, uaddr, id);
        case KVM_REG_ARM_VFP_FPINST:
-               return reg_from_user(&vcpu->arch.vfp_guest.fpinst, uaddr, id);
+               return reg_from_user(&vcpu->arch.ctxt.vfp.fpinst, uaddr, id);
        case KVM_REG_ARM_VFP_FPINST2:
-               return reg_from_user(&vcpu->arch.vfp_guest.fpinst2, uaddr, id);
+               return reg_from_user(&vcpu->arch.ctxt.vfp.fpinst2, uaddr, id);
        /* These are invariant. */
        case KVM_REG_ARM_VFP_MVFR0:
                if (reg_from_user(&val, uaddr, id))
@@ -1030,7 +1044,7 @@ int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
                val = vcpu_cp15_reg64_get(vcpu, r);
                ret = reg_to_user(uaddr, &val, reg->id);
        } else if (KVM_REG_SIZE(reg->id) == 4) {
-               ret = reg_to_user(uaddr, &vcpu->arch.cp15[r->reg], reg->id);
+               ret = reg_to_user(uaddr, &vcpu_cp15(vcpu, r->reg), reg->id);
        }
 
        return ret;
@@ -1060,7 +1074,7 @@ int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
                if (!ret)
                        vcpu_cp15_reg64_set(vcpu, r, val);
        } else if (KVM_REG_SIZE(reg->id) == 4) {
-               ret = reg_from_user(&vcpu->arch.cp15[r->reg], uaddr, reg->id);
+               ret = reg_from_user(&vcpu_cp15(vcpu, r->reg), uaddr, reg->id);
        }
 
        return ret;
@@ -1096,7 +1110,7 @@ static int write_demux_regids(u64 __user *uindices)
 static u64 cp15_to_index(const struct coproc_reg *reg)
 {
        u64 val = KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT);
-       if (reg->is_64) {
+       if (reg->is_64bit) {
                val |= KVM_REG_SIZE_U64;
                val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
                /*
@@ -1210,8 +1224,8 @@ void kvm_coproc_table_init(void)
        unsigned int i;
 
        /* Make sure tables are unique and in order. */
-       for (i = 1; i < ARRAY_SIZE(cp15_regs); i++)
-               BUG_ON(cmp_reg(&cp15_regs[i-1], &cp15_regs[i]) >= 0);
+       BUG_ON(check_reg_table(cp15_regs, ARRAY_SIZE(cp15_regs)));
+       BUG_ON(check_reg_table(invariant_cp15, ARRAY_SIZE(invariant_cp15)));
 
        /* We abuse the reset function to overwrite the table itself. */
        for (i = 0; i < ARRAY_SIZE(invariant_cp15); i++)
@@ -1248,7 +1262,7 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
        const struct coproc_reg *table;
 
        /* Catch someone adding a register without putting in reset entry. */
-       memset(vcpu->arch.cp15, 0x42, sizeof(vcpu->arch.cp15));
+       memset(vcpu->arch.ctxt.cp15, 0x42, sizeof(vcpu->arch.ctxt.cp15));
 
        /* Generic chip reset first (so target could override). */
        reset_coproc_regs(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
@@ -1257,6 +1271,6 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
        reset_coproc_regs(vcpu, table, num);
 
        for (num = 1; num < NR_CP15_REGS; num++)
-               if (vcpu->arch.cp15[num] == 0x42424242)
-                       panic("Didn't reset vcpu->arch.cp15[%zi]", num);
+               if (vcpu_cp15(vcpu, num) == 0x42424242)
+                       panic("Didn't reset vcpu_cp15(vcpu, %zi)", num);
 }
index 88d24a3a977812b512e8e0c03144fec796727f8b..eef1759c2b65b90c5e5916f261f93b74b0739249 100644 (file)
@@ -37,7 +37,7 @@ struct coproc_reg {
        unsigned long Op1;
        unsigned long Op2;
 
-       bool is_64;
+       bool is_64bit;
 
        /* Trapped access from guest, if non-NULL. */
        bool (*access)(struct kvm_vcpu *,
@@ -47,7 +47,7 @@ struct coproc_reg {
        /* Initialization for vcpu. */
        void (*reset)(struct kvm_vcpu *, const struct coproc_reg *);
 
-       /* Index into vcpu->arch.cp15[], or 0 if we don't need to save it. */
+       /* Index into vcpu_cp15(vcpu, ...), or 0 if we don't need to save it. */
        unsigned long reg;
 
        /* Value (usually reset value) */
@@ -104,25 +104,25 @@ static inline void reset_unknown(struct kvm_vcpu *vcpu,
                                 const struct coproc_reg *r)
 {
        BUG_ON(!r->reg);
-       BUG_ON(r->reg >= ARRAY_SIZE(vcpu->arch.cp15));
-       vcpu->arch.cp15[r->reg] = 0xdecafbad;
+       BUG_ON(r->reg >= ARRAY_SIZE(vcpu->arch.ctxt.cp15));
+       vcpu_cp15(vcpu, r->reg) = 0xdecafbad;
 }
 
 static inline void reset_val(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
 {
        BUG_ON(!r->reg);
-       BUG_ON(r->reg >= ARRAY_SIZE(vcpu->arch.cp15));
-       vcpu->arch.cp15[r->reg] = r->val;
+       BUG_ON(r->reg >= ARRAY_SIZE(vcpu->arch.ctxt.cp15));
+       vcpu_cp15(vcpu, r->reg) = r->val;
 }
 
 static inline void reset_unknown64(struct kvm_vcpu *vcpu,
                                   const struct coproc_reg *r)
 {
        BUG_ON(!r->reg);
-       BUG_ON(r->reg + 1 >= ARRAY_SIZE(vcpu->arch.cp15));
+       BUG_ON(r->reg + 1 >= ARRAY_SIZE(vcpu->arch.ctxt.cp15));
 
-       vcpu->arch.cp15[r->reg] = 0xdecafbad;
-       vcpu->arch.cp15[r->reg+1] = 0xd0c0ffee;
+       vcpu_cp15(vcpu, r->reg) = 0xdecafbad;
+       vcpu_cp15(vcpu, r->reg+1) = 0xd0c0ffee;
 }
 
 static inline int cmp_reg(const struct coproc_reg *i1,
@@ -141,7 +141,7 @@ static inline int cmp_reg(const struct coproc_reg *i1,
                return i1->Op1 - i2->Op1;
        if (i1->Op2 != i2->Op2)
                return i1->Op2 - i2->Op2;
-       return i2->is_64 - i1->is_64;
+       return i2->is_64bit - i1->is_64bit;
 }
 
 
@@ -150,8 +150,8 @@ static inline int cmp_reg(const struct coproc_reg *i1,
 #define CRm64(_x)       .CRn = _x, .CRm = 0
 #define Op1(_x)        .Op1 = _x
 #define Op2(_x)        .Op2 = _x
-#define is64           .is_64 = true
-#define is32           .is_64 = false
+#define is64           .is_64bit = true
+#define is32           .is_64bit = false
 
 bool access_vm_reg(struct kvm_vcpu *vcpu,
                   const struct coproc_params *p,
index dc99159857b4ae70d7d3785b75a1c3f0f8639906..a494def3f19569d4eef5bb6658f2e62d54eb1b9c 100644 (file)
@@ -112,7 +112,7 @@ static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][15] = {
  */
 unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)
 {
-       unsigned long *reg_array = (unsigned long *)&vcpu->arch.regs;
+       unsigned long *reg_array = (unsigned long *)&vcpu->arch.ctxt.gp_regs;
        unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK;
 
        switch (mode) {
@@ -147,15 +147,15 @@ unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu)
        unsigned long mode = *vcpu_cpsr(vcpu) & MODE_MASK;
        switch (mode) {
        case SVC_MODE:
-               return &vcpu->arch.regs.KVM_ARM_SVC_spsr;
+               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_SVC_spsr;
        case ABT_MODE:
-               return &vcpu->arch.regs.KVM_ARM_ABT_spsr;
+               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_ABT_spsr;
        case UND_MODE:
-               return &vcpu->arch.regs.KVM_ARM_UND_spsr;
+               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_UND_spsr;
        case IRQ_MODE:
-               return &vcpu->arch.regs.KVM_ARM_IRQ_spsr;
+               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_IRQ_spsr;
        case FIQ_MODE:
-               return &vcpu->arch.regs.KVM_ARM_FIQ_spsr;
+               return &vcpu->arch.ctxt.gp_regs.KVM_ARM_FIQ_spsr;
        default:
                BUG();
        }
@@ -266,8 +266,8 @@ void kvm_skip_instr(struct kvm_vcpu *vcpu, bool is_wide_instr)
 
 static u32 exc_vector_base(struct kvm_vcpu *vcpu)
 {
-       u32 sctlr = vcpu->arch.cp15[c1_SCTLR];
-       u32 vbar = vcpu->arch.cp15[c12_VBAR];
+       u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR);
+       u32 vbar = vcpu_cp15(vcpu, c12_VBAR);
 
        if (sctlr & SCTLR_V)
                return 0xffff0000;
@@ -282,7 +282,7 @@ static u32 exc_vector_base(struct kvm_vcpu *vcpu)
 static void kvm_update_psr(struct kvm_vcpu *vcpu, unsigned long mode)
 {
        unsigned long cpsr = *vcpu_cpsr(vcpu);
-       u32 sctlr = vcpu->arch.cp15[c1_SCTLR];
+       u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR);
 
        *vcpu_cpsr(vcpu) = (cpsr & ~MODE_MASK) | mode;
 
@@ -357,22 +357,22 @@ static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr)
 
        if (is_pabt) {
                /* Set IFAR and IFSR */
-               vcpu->arch.cp15[c6_IFAR] = addr;
-               is_lpae = (vcpu->arch.cp15[c2_TTBCR] >> 31);
+               vcpu_cp15(vcpu, c6_IFAR) = addr;
+               is_lpae = (vcpu_cp15(vcpu, c2_TTBCR) >> 31);
                /* Always give debug fault for now - should give guest a clue */
                if (is_lpae)
-                       vcpu->arch.cp15[c5_IFSR] = 1 << 9 | 0x22;
+                       vcpu_cp15(vcpu, c5_IFSR) = 1 << 9 | 0x22;
                else
-                       vcpu->arch.cp15[c5_IFSR] = 2;
+                       vcpu_cp15(vcpu, c5_IFSR) = 2;
        } else { /* !iabt */
                /* Set DFAR and DFSR */
-               vcpu->arch.cp15[c6_DFAR] = addr;
-               is_lpae = (vcpu->arch.cp15[c2_TTBCR] >> 31);
+               vcpu_cp15(vcpu, c6_DFAR) = addr;
+               is_lpae = (vcpu_cp15(vcpu, c2_TTBCR) >> 31);
                /* Always give debug fault for now - should give guest a clue */
                if (is_lpae)
-                       vcpu->arch.cp15[c5_DFSR] = 1 << 9 | 0x22;
+                       vcpu_cp15(vcpu, c5_DFSR) = 1 << 9 | 0x22;
                else
-                       vcpu->arch.cp15[c5_DFSR] = 2;
+                       vcpu_cp15(vcpu, c5_DFSR) = 2;
        }
 
 }
index 5fa69d7bae58a06ef19f7ca72fd04cf6603d6963..9093ed0f8b2a71e1d226fd31832a81d764242da6 100644 (file)
@@ -25,7 +25,6 @@
 #include <asm/cputype.h>
 #include <asm/uaccess.h>
 #include <asm/kvm.h>
-#include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
 
@@ -55,7 +54,7 @@ static u64 core_reg_offset_from_id(u64 id)
 static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
        u32 __user *uaddr = (u32 __user *)(long)reg->addr;
-       struct kvm_regs *regs = &vcpu->arch.regs;
+       struct kvm_regs *regs = &vcpu->arch.ctxt.gp_regs;
        u64 off;
 
        if (KVM_REG_SIZE(reg->id) != 4)
@@ -72,7 +71,7 @@ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
        u32 __user *uaddr = (u32 __user *)(long)reg->addr;
-       struct kvm_regs *regs = &vcpu->arch.regs;
+       struct kvm_regs *regs = &vcpu->arch.ctxt.gp_regs;
        u64 off, val;
 
        if (KVM_REG_SIZE(reg->id) != 4)
@@ -161,7 +160,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
        u64 val;
 
        val = kvm_arm_timer_get_reg(vcpu, reg->id);
-       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
+       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
 }
 
 static unsigned long num_core_regs(void)
index 3ede90d8b20bae91c4b8f20173b307cc1b0659fd..3f1ef0dbc899182cae378773064c67e2e2289eb3 100644 (file)
@@ -147,13 +147,6 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
        switch (exception_index) {
        case ARM_EXCEPTION_IRQ:
                return 1;
-       case ARM_EXCEPTION_UNDEFINED:
-               kvm_err("Undefined exception in Hyp mode at: %#08lx\n",
-                       kvm_vcpu_get_hyp_pc(vcpu));
-               BUG();
-               panic("KVM: Hypervisor undefined exception!\n");
-       case ARM_EXCEPTION_DATA_ABORT:
-       case ARM_EXCEPTION_PREF_ABORT:
        case ARM_EXCEPTION_HVC:
                /*
                 * See ARM ARM B1.14.1: "Hyp traps on instructions
diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile
new file mode 100644 (file)
index 0000000..8dfa5f7
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Makefile for Kernel-based Virtual Machine module, HYP part
+#
+
+KVM=../../../../virt/kvm
+
+obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
+obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o
+
+obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
+obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o
+obj-$(CONFIG_KVM_ARM_HOST) += vfp.o
+obj-$(CONFIG_KVM_ARM_HOST) += banked-sr.o
+obj-$(CONFIG_KVM_ARM_HOST) += entry.o
+obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o
+obj-$(CONFIG_KVM_ARM_HOST) += switch.o
+obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o
diff --git a/arch/arm/kvm/hyp/banked-sr.c b/arch/arm/kvm/hyp/banked-sr.c
new file mode 100644 (file)
index 0000000..111bda8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Original code:
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.com>
+ *
+ * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/kvm_hyp.h>
+
+__asm__(".arch_extension     virt");
+
+void __hyp_text __banked_save_state(struct kvm_cpu_context *ctxt)
+{
+       ctxt->gp_regs.usr_regs.ARM_sp   = read_special(SP_usr);
+       ctxt->gp_regs.usr_regs.ARM_pc   = read_special(ELR_hyp);
+       ctxt->gp_regs.usr_regs.ARM_cpsr = read_special(SPSR);
+       ctxt->gp_regs.KVM_ARM_SVC_sp    = read_special(SP_svc);
+       ctxt->gp_regs.KVM_ARM_SVC_lr    = read_special(LR_svc);
+       ctxt->gp_regs.KVM_ARM_SVC_spsr  = read_special(SPSR_svc);
+       ctxt->gp_regs.KVM_ARM_ABT_sp    = read_special(SP_abt);
+       ctxt->gp_regs.KVM_ARM_ABT_lr    = read_special(LR_abt);
+       ctxt->gp_regs.KVM_ARM_ABT_spsr  = read_special(SPSR_abt);
+       ctxt->gp_regs.KVM_ARM_UND_sp    = read_special(SP_und);
+       ctxt->gp_regs.KVM_ARM_UND_lr    = read_special(LR_und);
+       ctxt->gp_regs.KVM_ARM_UND_spsr  = read_special(SPSR_und);
+       ctxt->gp_regs.KVM_ARM_IRQ_sp    = read_special(SP_irq);
+       ctxt->gp_regs.KVM_ARM_IRQ_lr    = read_special(LR_irq);
+       ctxt->gp_regs.KVM_ARM_IRQ_spsr  = read_special(SPSR_irq);
+       ctxt->gp_regs.KVM_ARM_FIQ_r8    = read_special(R8_fiq);
+       ctxt->gp_regs.KVM_ARM_FIQ_r9    = read_special(R9_fiq);
+       ctxt->gp_regs.KVM_ARM_FIQ_r10   = read_special(R10_fiq);
+       ctxt->gp_regs.KVM_ARM_FIQ_fp    = read_special(R11_fiq);
+       ctxt->gp_regs.KVM_ARM_FIQ_ip    = read_special(R12_fiq);
+       ctxt->gp_regs.KVM_ARM_FIQ_sp    = read_special(SP_fiq);
+       ctxt->gp_regs.KVM_ARM_FIQ_lr    = read_special(LR_fiq);
+       ctxt->gp_regs.KVM_ARM_FIQ_spsr  = read_special(SPSR_fiq);
+}
+
+void __hyp_text __banked_restore_state(struct kvm_cpu_context *ctxt)
+{
+       write_special(ctxt->gp_regs.usr_regs.ARM_sp,    SP_usr);
+       write_special(ctxt->gp_regs.usr_regs.ARM_pc,    ELR_hyp);
+       write_special(ctxt->gp_regs.usr_regs.ARM_cpsr,  SPSR_cxsf);
+       write_special(ctxt->gp_regs.KVM_ARM_SVC_sp,     SP_svc);
+       write_special(ctxt->gp_regs.KVM_ARM_SVC_lr,     LR_svc);
+       write_special(ctxt->gp_regs.KVM_ARM_SVC_spsr,   SPSR_svc);
+       write_special(ctxt->gp_regs.KVM_ARM_ABT_sp,     SP_abt);
+       write_special(ctxt->gp_regs.KVM_ARM_ABT_lr,     LR_abt);
+       write_special(ctxt->gp_regs.KVM_ARM_ABT_spsr,   SPSR_abt);
+       write_special(ctxt->gp_regs.KVM_ARM_UND_sp,     SP_und);
+       write_special(ctxt->gp_regs.KVM_ARM_UND_lr,     LR_und);
+       write_special(ctxt->gp_regs.KVM_ARM_UND_spsr,   SPSR_und);
+       write_special(ctxt->gp_regs.KVM_ARM_IRQ_sp,     SP_irq);
+       write_special(ctxt->gp_regs.KVM_ARM_IRQ_lr,     LR_irq);
+       write_special(ctxt->gp_regs.KVM_ARM_IRQ_spsr,   SPSR_irq);
+       write_special(ctxt->gp_regs.KVM_ARM_FIQ_r8,     R8_fiq);
+       write_special(ctxt->gp_regs.KVM_ARM_FIQ_r9,     R9_fiq);
+       write_special(ctxt->gp_regs.KVM_ARM_FIQ_r10,    R10_fiq);
+       write_special(ctxt->gp_regs.KVM_ARM_FIQ_fp,     R11_fiq);
+       write_special(ctxt->gp_regs.KVM_ARM_FIQ_ip,     R12_fiq);
+       write_special(ctxt->gp_regs.KVM_ARM_FIQ_sp,     SP_fiq);
+       write_special(ctxt->gp_regs.KVM_ARM_FIQ_lr,     LR_fiq);
+       write_special(ctxt->gp_regs.KVM_ARM_FIQ_spsr,   SPSR_fiq);
+}
diff --git a/arch/arm/kvm/hyp/cp15-sr.c b/arch/arm/kvm/hyp/cp15-sr.c
new file mode 100644 (file)
index 0000000..c478281
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Original code:
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.com>
+ *
+ * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/kvm_hyp.h>
+
+static u64 *cp15_64(struct kvm_cpu_context *ctxt, int idx)
+{
+       return (u64 *)(ctxt->cp15 + idx);
+}
+
+void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
+{
+       ctxt->cp15[c0_MPIDR]            = read_sysreg(VMPIDR);
+       ctxt->cp15[c0_CSSELR]           = read_sysreg(CSSELR);
+       ctxt->cp15[c1_SCTLR]            = read_sysreg(SCTLR);
+       ctxt->cp15[c1_CPACR]            = read_sysreg(CPACR);
+       *cp15_64(ctxt, c2_TTBR0)        = read_sysreg(TTBR0);
+       *cp15_64(ctxt, c2_TTBR1)        = read_sysreg(TTBR1);
+       ctxt->cp15[c2_TTBCR]            = read_sysreg(TTBCR);
+       ctxt->cp15[c3_DACR]             = read_sysreg(DACR);
+       ctxt->cp15[c5_DFSR]             = read_sysreg(DFSR);
+       ctxt->cp15[c5_IFSR]             = read_sysreg(IFSR);
+       ctxt->cp15[c5_ADFSR]            = read_sysreg(ADFSR);
+       ctxt->cp15[c5_AIFSR]            = read_sysreg(AIFSR);
+       ctxt->cp15[c6_DFAR]             = read_sysreg(DFAR);
+       ctxt->cp15[c6_IFAR]             = read_sysreg(IFAR);
+       *cp15_64(ctxt, c7_PAR)          = read_sysreg(PAR);
+       ctxt->cp15[c10_PRRR]            = read_sysreg(PRRR);
+       ctxt->cp15[c10_NMRR]            = read_sysreg(NMRR);
+       ctxt->cp15[c10_AMAIR0]          = read_sysreg(AMAIR0);
+       ctxt->cp15[c10_AMAIR1]          = read_sysreg(AMAIR1);
+       ctxt->cp15[c12_VBAR]            = read_sysreg(VBAR);
+       ctxt->cp15[c13_CID]             = read_sysreg(CID);
+       ctxt->cp15[c13_TID_URW]         = read_sysreg(TID_URW);
+       ctxt->cp15[c13_TID_URO]         = read_sysreg(TID_URO);
+       ctxt->cp15[c13_TID_PRIV]        = read_sysreg(TID_PRIV);
+       ctxt->cp15[c14_CNTKCTL]         = read_sysreg(CNTKCTL);
+}
+
+void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
+{
+       write_sysreg(ctxt->cp15[c0_MPIDR],      VMPIDR);
+       write_sysreg(ctxt->cp15[c0_CSSELR],     CSSELR);
+       write_sysreg(ctxt->cp15[c1_SCTLR],      SCTLR);
+       write_sysreg(ctxt->cp15[c1_CPACR],      CPACR);
+       write_sysreg(*cp15_64(ctxt, c2_TTBR0),  TTBR0);
+       write_sysreg(*cp15_64(ctxt, c2_TTBR1),  TTBR1);
+       write_sysreg(ctxt->cp15[c2_TTBCR],      TTBCR);
+       write_sysreg(ctxt->cp15[c3_DACR],       DACR);
+       write_sysreg(ctxt->cp15[c5_DFSR],       DFSR);
+       write_sysreg(ctxt->cp15[c5_IFSR],       IFSR);
+       write_sysreg(ctxt->cp15[c5_ADFSR],      ADFSR);
+       write_sysreg(ctxt->cp15[c5_AIFSR],      AIFSR);
+       write_sysreg(ctxt->cp15[c6_DFAR],       DFAR);
+       write_sysreg(ctxt->cp15[c6_IFAR],       IFAR);
+       write_sysreg(*cp15_64(ctxt, c7_PAR),    PAR);
+       write_sysreg(ctxt->cp15[c10_PRRR],      PRRR);
+       write_sysreg(ctxt->cp15[c10_NMRR],      NMRR);
+       write_sysreg(ctxt->cp15[c10_AMAIR0],    AMAIR0);
+       write_sysreg(ctxt->cp15[c10_AMAIR1],    AMAIR1);
+       write_sysreg(ctxt->cp15[c12_VBAR],      VBAR);
+       write_sysreg(ctxt->cp15[c13_CID],       CID);
+       write_sysreg(ctxt->cp15[c13_TID_URW],   TID_URW);
+       write_sysreg(ctxt->cp15[c13_TID_URO],   TID_URO);
+       write_sysreg(ctxt->cp15[c13_TID_PRIV],  TID_PRIV);
+       write_sysreg(ctxt->cp15[c14_CNTKCTL],   CNTKCTL);
+}
diff --git a/arch/arm/kvm/hyp/entry.S b/arch/arm/kvm/hyp/entry.S
new file mode 100644 (file)
index 0000000..21c2388
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/kvm_arm.h>
+
+       .arch_extension     virt
+
+       .text
+       .pushsection    .hyp.text, "ax"
+
+#define USR_REGS_OFFSET                (CPU_CTXT_GP_REGS + GP_REGS_USR)
+
+/* int __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host) */
+ENTRY(__guest_enter)
+       @ Save host registers
+       add     r1, r1, #(USR_REGS_OFFSET + S_R4)
+       stm     r1!, {r4-r12}
+       str     lr, [r1, #4]    @ Skip SP_usr (already saved)
+
+       @ Restore guest registers
+       add     r0, r0,  #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0)
+       ldr     lr, [r0, #S_LR]
+       ldm     r0, {r0-r12}
+
+       clrex
+       eret
+ENDPROC(__guest_enter)
+
+ENTRY(__guest_exit)
+       /*
+        * return convention:
+        * guest r0, r1, r2 saved on the stack
+        * r0: vcpu pointer
+        * r1: exception code
+        */
+
+       add     r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R3)
+       stm     r2!, {r3-r12}
+       str     lr, [r2, #4]
+       add     r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0)
+       pop     {r3, r4, r5}            @ r0, r1, r2
+       stm     r2, {r3-r5}
+
+       ldr     r0, [r0, #VCPU_HOST_CTXT]
+       add     r0, r0, #(USR_REGS_OFFSET + S_R4)
+       ldm     r0!, {r4-r12}
+       ldr     lr, [r0, #4]
+
+       mov     r0, r1
+       bx      lr
+ENDPROC(__guest_exit)
+
+/*
+ * If VFPv3 support is not available, then we will not switch the VFP
+ * registers; however cp10 and cp11 accesses will still trap and fallback
+ * to the regular coprocessor emulation code, which currently will
+ * inject an undefined exception to the guest.
+ */
+#ifdef CONFIG_VFPv3
+ENTRY(__vfp_guest_restore)
+       push    {r3, r4, lr}
+
+       @ NEON/VFP used.  Turn on VFP access.
+       mrc     p15, 4, r1, c1, c1, 2           @ HCPTR
+       bic     r1, r1, #(HCPTR_TCP(10) | HCPTR_TCP(11))
+       mcr     p15, 4, r1, c1, c1, 2           @ HCPTR
+       isb
+
+       @ Switch VFP/NEON hardware state to the guest's
+       mov     r4, r0
+       ldr     r0, [r0, #VCPU_HOST_CTXT]
+       add     r0, r0, #CPU_CTXT_VFP
+       bl      __vfp_save_state
+       add     r0, r4, #(VCPU_GUEST_CTXT + CPU_CTXT_VFP)
+       bl      __vfp_restore_state
+
+       pop     {r3, r4, lr}
+       pop     {r0, r1, r2}
+       clrex
+       eret
+ENDPROC(__vfp_guest_restore)
+#endif
+
+       .popsection
+
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
new file mode 100644 (file)
index 0000000..7809138
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/linkage.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
+
+       .arch_extension     virt
+
+       .text
+       .pushsection    .hyp.text, "ax"
+
+.macro load_vcpu       reg
+       mrc     p15, 4, \reg, c13, c0, 2        @ HTPIDR
+.endm
+
+/********************************************************************
+ * Hypervisor exception vector and handlers
+ *
+ *
+ * The KVM/ARM Hypervisor ABI is defined as follows:
+ *
+ * Entry to Hyp mode from the host kernel will happen _only_ when an HVC
+ * instruction is issued since all traps are disabled when running the host
+ * kernel as per the Hyp-mode initialization at boot time.
+ *
+ * HVC instructions cause a trap to the vector page + offset 0x14 (see hyp_hvc
+ * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
+ * host kernel) and they cause a trap to the vector page + offset 0x8 when HVC
+ * instructions are called from within Hyp-mode.
+ *
+ * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
+ *    Switching to Hyp mode is done through a simple HVC #0 instruction. The
+ *    exception vector code will check that the HVC comes from VMID==0.
+ *    - r0 contains a pointer to a HYP function
+ *    - r1, r2, and r3 contain arguments to the above function.
+ *    - The HYP function will be called with its arguments in r0, r1 and r2.
+ *    On HYP function return, we return directly to SVC.
+ *
+ * Note that the above is used to execute code in Hyp-mode from a host-kernel
+ * point of view, and is a different concept from performing a world-switch and
+ * executing guest code SVC mode (with a VMID != 0).
+ */
+
+       .align 5
+__kvm_hyp_vector:
+       .global __kvm_hyp_vector
+
+       @ Hyp-mode exception vector
+       W(b)    hyp_reset
+       W(b)    hyp_undef
+       W(b)    hyp_svc
+       W(b)    hyp_pabt
+       W(b)    hyp_dabt
+       W(b)    hyp_hvc
+       W(b)    hyp_irq
+       W(b)    hyp_fiq
+
+.macro invalid_vector label, cause
+       .align
+\label:        mov     r0, #\cause
+       b       __hyp_panic
+.endm
+
+       invalid_vector  hyp_reset       ARM_EXCEPTION_RESET
+       invalid_vector  hyp_undef       ARM_EXCEPTION_UNDEFINED
+       invalid_vector  hyp_svc         ARM_EXCEPTION_SOFTWARE
+       invalid_vector  hyp_pabt        ARM_EXCEPTION_PREF_ABORT
+       invalid_vector  hyp_dabt        ARM_EXCEPTION_DATA_ABORT
+       invalid_vector  hyp_fiq         ARM_EXCEPTION_FIQ
+
+ENTRY(__hyp_do_panic)
+       mrs     lr, cpsr
+       bic     lr, lr, #MODE_MASK
+       orr     lr, lr, #SVC_MODE
+THUMB( orr     lr, lr, #PSR_T_BIT      )
+       msr     spsr_cxsf, lr
+       ldr     lr, =panic
+       msr     ELR_hyp, lr
+       ldr     lr, =kvm_call_hyp
+       clrex
+       eret
+ENDPROC(__hyp_do_panic)
+
+hyp_hvc:
+       /*
+        * Getting here is either because of a trap from a guest,
+        * or from executing HVC from the host kernel, which means
+        * "do something in Hyp mode".
+        */
+       push    {r0, r1, r2}
+
+       @ Check syndrome register
+       mrc     p15, 4, r1, c5, c2, 0   @ HSR
+       lsr     r0, r1, #HSR_EC_SHIFT
+       cmp     r0, #HSR_EC_HVC
+       bne     guest_trap              @ Not HVC instr.
+
+       /*
+        * Let's check if the HVC came from VMID 0 and allow simple
+        * switch to Hyp mode
+        */
+       mrrc    p15, 6, r0, r2, c2
+       lsr     r2, r2, #16
+       and     r2, r2, #0xff
+       cmp     r2, #0
+       bne     guest_trap              @ Guest called HVC
+
+       /*
+        * Getting here means host called HVC, we shift parameters and branch
+        * to Hyp function.
+        */
+       pop     {r0, r1, r2}
+
+       /* Check for __hyp_get_vectors */
+       cmp     r0, #-1
+       mrceq   p15, 4, r0, c12, c0, 0  @ get HVBAR
+       beq     1f
+
+       push    {lr}
+
+       mov     lr, r0
+       mov     r0, r1
+       mov     r1, r2
+       mov     r2, r3
+
+THUMB( orr     lr, #1)
+       blx     lr                      @ Call the HYP function
+
+       pop     {lr}
+1:     eret
+
+guest_trap:
+       load_vcpu r0                    @ Load VCPU pointer to r0
+
+#ifdef CONFIG_VFPv3
+       @ Check for a VFP access
+       lsr     r1, r1, #HSR_EC_SHIFT
+       cmp     r1, #HSR_EC_CP_0_13
+       beq     __vfp_guest_restore
+#endif
+
+       mov     r1, #ARM_EXCEPTION_HVC
+       b       __guest_exit
+
+hyp_irq:
+       push    {r0, r1, r2}
+       mov     r1, #ARM_EXCEPTION_IRQ
+       load_vcpu r0                    @ Load VCPU pointer to r0
+       b       __guest_exit
+
+       .ltorg
+
+       .popsection
diff --git a/arch/arm/kvm/hyp/s2-setup.c b/arch/arm/kvm/hyp/s2-setup.c
new file mode 100644 (file)
index 0000000..7be39af
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/types.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_hyp.h>
+
+void __hyp_text __init_stage2_translation(void)
+{
+       u64 val;
+
+       val = read_sysreg(VTCR) & ~VTCR_MASK;
+
+       val |= read_sysreg(HTCR) & VTCR_HTCR_SH;
+       val |= KVM_VTCR_SL0 | KVM_VTCR_T0SZ | KVM_VTCR_S;
+
+       write_sysreg(val, VTCR);
+}
diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
new file mode 100644 (file)
index 0000000..b13caa9
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/kvm_asm.h>
+#include <asm/kvm_hyp.h>
+
+__asm__(".arch_extension     virt");
+
+/*
+ * Activate the traps, saving the host's fpexc register before
+ * overwriting it. We'll restore it on VM exit.
+ */
+static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host)
+{
+       u32 val;
+
+       /*
+        * We are about to set HCPTR.TCP10/11 to trap all floating point
+        * register accesses to HYP, however, the ARM ARM clearly states that
+        * traps are only taken to HYP if the operation would not otherwise
+        * trap to SVC.  Therefore, always make sure that for 32-bit guests,
+        * we set FPEXC.EN to prevent traps to SVC, when setting the TCP bits.
+        */
+       val = read_sysreg(VFP_FPEXC);
+       *fpexc_host = val;
+       if (!(val & FPEXC_EN)) {
+               write_sysreg(val | FPEXC_EN, VFP_FPEXC);
+               isb();
+       }
+
+       write_sysreg(vcpu->arch.hcr | vcpu->arch.irq_lines, HCR);
+       /* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */
+       write_sysreg(HSTR_T(15), HSTR);
+       write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR);
+       val = read_sysreg(HDCR);
+       write_sysreg(val | HDCR_TPM | HDCR_TPMCR, HDCR);
+}
+
+static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
+{
+       u32 val;
+
+       write_sysreg(0, HCR);
+       write_sysreg(0, HSTR);
+       val = read_sysreg(HDCR);
+       write_sysreg(val & ~(HDCR_TPM | HDCR_TPMCR), HDCR);
+       write_sysreg(0, HCPTR);
+}
+
+static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
+{
+       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+       write_sysreg(kvm->arch.vttbr, VTTBR);
+       write_sysreg(vcpu->arch.midr, VPIDR);
+}
+
+static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu)
+{
+       write_sysreg(0, VTTBR);
+       write_sysreg(read_sysreg(MIDR), VPIDR);
+}
+
+static void __hyp_text __vgic_save_state(struct kvm_vcpu *vcpu)
+{
+       __vgic_v2_save_state(vcpu);
+}
+
+static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu)
+{
+       __vgic_v2_restore_state(vcpu);
+}
+
+static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
+{
+       u32 hsr = read_sysreg(HSR);
+       u8 ec = hsr >> HSR_EC_SHIFT;
+       u32 hpfar, far;
+
+       vcpu->arch.fault.hsr = hsr;
+
+       if (ec == HSR_EC_IABT)
+               far = read_sysreg(HIFAR);
+       else if (ec == HSR_EC_DABT)
+               far = read_sysreg(HDFAR);
+       else
+               return true;
+
+       /*
+        * B3.13.5 Reporting exceptions taken to the Non-secure PL2 mode:
+        *
+        * Abort on the stage 2 translation for a memory access from a
+        * Non-secure PL1 or PL0 mode:
+        *
+        * For any Access flag fault or Translation fault, and also for any
+        * Permission fault on the stage 2 translation of a memory access
+        * made as part of a translation table walk for a stage 1 translation,
+        * the HPFAR holds the IPA that caused the fault. Otherwise, the HPFAR
+        * is UNKNOWN.
+        */
+       if (!(hsr & HSR_DABT_S1PTW) && (hsr & HSR_FSC_TYPE) == FSC_PERM) {
+               u64 par, tmp;
+
+               par = read_sysreg(PAR);
+               write_sysreg(far, ATS1CPR);
+               isb();
+
+               tmp = read_sysreg(PAR);
+               write_sysreg(par, PAR);
+
+               if (unlikely(tmp & 1))
+                       return false; /* Translation failed, back to guest */
+
+               hpfar = ((tmp >> 12) & ((1UL << 28) - 1)) << 4;
+       } else {
+               hpfar = read_sysreg(HPFAR);
+       }
+
+       vcpu->arch.fault.hxfar = far;
+       vcpu->arch.fault.hpfar = hpfar;
+       return true;
+}
+
+static int __hyp_text __guest_run(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpu_context *host_ctxt;
+       struct kvm_cpu_context *guest_ctxt;
+       bool fp_enabled;
+       u64 exit_code;
+       u32 fpexc;
+
+       vcpu = kern_hyp_va(vcpu);
+       write_sysreg(vcpu, HTPIDR);
+
+       host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
+       guest_ctxt = &vcpu->arch.ctxt;
+
+       __sysreg_save_state(host_ctxt);
+       __banked_save_state(host_ctxt);
+
+       __activate_traps(vcpu, &fpexc);
+       __activate_vm(vcpu);
+
+       __vgic_restore_state(vcpu);
+       __timer_restore_state(vcpu);
+
+       __sysreg_restore_state(guest_ctxt);
+       __banked_restore_state(guest_ctxt);
+
+       /* Jump in the fire! */
+again:
+       exit_code = __guest_enter(vcpu, host_ctxt);
+       /* And we're baaack! */
+
+       if (exit_code == ARM_EXCEPTION_HVC && !__populate_fault_info(vcpu))
+               goto again;
+
+       fp_enabled = __vfp_enabled();
+
+       __banked_save_state(guest_ctxt);
+       __sysreg_save_state(guest_ctxt);
+       __timer_save_state(vcpu);
+       __vgic_save_state(vcpu);
+
+       __deactivate_traps(vcpu);
+       __deactivate_vm(vcpu);
+
+       __banked_restore_state(host_ctxt);
+       __sysreg_restore_state(host_ctxt);
+
+       if (fp_enabled) {
+               __vfp_save_state(&guest_ctxt->vfp);
+               __vfp_restore_state(&host_ctxt->vfp);
+       }
+
+       write_sysreg(fpexc, VFP_FPEXC);
+
+       return exit_code;
+}
+
+__alias(__guest_run) int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
+
+static const char * const __hyp_panic_string[] = {
+       [ARM_EXCEPTION_RESET]      = "\nHYP panic: RST   PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_UNDEFINED]  = "\nHYP panic: UNDEF PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_SOFTWARE]   = "\nHYP panic: SVC   PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_PREF_ABORT] = "\nHYP panic: PABRT PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_DATA_ABORT] = "\nHYP panic: DABRT PC:%08x ADDR:%08x",
+       [ARM_EXCEPTION_IRQ]        = "\nHYP panic: IRQ   PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_FIQ]        = "\nHYP panic: FIQ   PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_HVC]        = "\nHYP panic: HVC   PC:%08x CPSR:%08x",
+};
+
+void __hyp_text __noreturn __hyp_panic(int cause)
+{
+       u32 elr = read_special(ELR_hyp);
+       u32 val;
+
+       if (cause == ARM_EXCEPTION_DATA_ABORT)
+               val = read_sysreg(HDFAR);
+       else
+               val = read_special(SPSR);
+
+       if (read_sysreg(VTTBR)) {
+               struct kvm_vcpu *vcpu;
+               struct kvm_cpu_context *host_ctxt;
+
+               vcpu = (struct kvm_vcpu *)read_sysreg(HTPIDR);
+               host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
+               __deactivate_traps(vcpu);
+               __deactivate_vm(vcpu);
+               __sysreg_restore_state(host_ctxt);
+       }
+
+       /* Call panic for real */
+       __hyp_do_panic(__hyp_panic_string[cause], elr, val);
+
+       unreachable();
+}
diff --git a/arch/arm/kvm/hyp/tlb.c b/arch/arm/kvm/hyp/tlb.c
new file mode 100644 (file)
index 0000000..a263600
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Original code:
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.com>
+ *
+ * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/kvm_hyp.h>
+
+/**
+ * Flush per-VMID TLBs
+ *
+ * __kvm_tlb_flush_vmid(struct kvm *kvm);
+ *
+ * We rely on the hardware to broadcast the TLB invalidation to all CPUs
+ * inside the inner-shareable domain (which is the case for all v7
+ * implementations).  If we come across a non-IS SMP implementation, we'll
+ * have to use an IPI based mechanism. Until then, we stick to the simple
+ * hardware assisted version.
+ *
+ * As v7 does not support flushing per IPA, just nuke the whole TLB
+ * instead, ignoring the ipa value.
+ */
+static void __hyp_text __tlb_flush_vmid(struct kvm *kvm)
+{
+       dsb(ishst);
+
+       /* Switch to requested VMID */
+       kvm = kern_hyp_va(kvm);
+       write_sysreg(kvm->arch.vttbr, VTTBR);
+       isb();
+
+       write_sysreg(0, TLBIALLIS);
+       dsb(ish);
+       isb();
+
+       write_sysreg(0, VTTBR);
+}
+
+__alias(__tlb_flush_vmid) void __kvm_tlb_flush_vmid(struct kvm *kvm);
+
+static void __hyp_text __tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
+{
+       __tlb_flush_vmid(kvm);
+}
+
+__alias(__tlb_flush_vmid_ipa) void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm,
+                                                           phys_addr_t ipa);
+
+static void __hyp_text __tlb_flush_vm_context(void)
+{
+       write_sysreg(0, TLBIALLNSNHIS);
+       write_sysreg(0, ICIALLUIS);
+       dsb(ish);
+}
+
+__alias(__tlb_flush_vm_context) void __kvm_flush_vm_context(void);
diff --git a/arch/arm/kvm/hyp/vfp.S b/arch/arm/kvm/hyp/vfp.S
new file mode 100644 (file)
index 0000000..7c297e8
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/vfpmacros.h>
+
+       .text
+       .pushsection    .hyp.text, "ax"
+
+/* void __vfp_save_state(struct vfp_hard_struct *vfp); */
+ENTRY(__vfp_save_state)
+       push    {r4, r5}
+       VFPFMRX r1, FPEXC
+
+       @ Make sure *really* VFP is enabled so we can touch the registers.
+       orr     r5, r1, #FPEXC_EN
+       tst     r5, #FPEXC_EX           @ Check for VFP Subarchitecture
+       bic     r5, r5, #FPEXC_EX       @ FPEXC_EX disable
+       VFPFMXR FPEXC, r5
+       isb
+
+       VFPFMRX r2, FPSCR
+       beq     1f
+
+       @ If FPEXC_EX is 0, then FPINST/FPINST2 reads are upredictable, so
+       @ we only need to save them if FPEXC_EX is set.
+       VFPFMRX r3, FPINST
+       tst     r5, #FPEXC_FP2V
+       VFPFMRX r4, FPINST2, ne         @ vmrsne
+1:
+       VFPFSTMIA r0, r5                @ Save VFP registers
+       stm     r0, {r1-r4}             @ Save FPEXC, FPSCR, FPINST, FPINST2
+       pop     {r4, r5}
+       bx      lr
+ENDPROC(__vfp_save_state)
+
+/* void __vfp_restore_state(struct vfp_hard_struct *vfp);
+ * Assume FPEXC_EN is on and FPEXC_EX is off */
+ENTRY(__vfp_restore_state)
+       VFPFLDMIA r0, r1                @ Load VFP registers
+       ldm     r0, {r0-r3}             @ Load FPEXC, FPSCR, FPINST, FPINST2
+
+       VFPFMXR FPSCR, r1
+       tst     r0, #FPEXC_EX           @ Check for VFP Subarchitecture
+       beq     1f
+       VFPFMXR FPINST, r2
+       tst     r0, #FPEXC_FP2V
+       VFPFMXR FPINST2, r3, ne
+1:
+       VFPFMXR FPEXC, r0               @ FPEXC (last, in case !EN)
+       bx      lr
+ENDPROC(__vfp_restore_state)
+
+       .popsection
index 3988e72d16ff9f20efdad72c51dab74b01f559b2..1f9ae17476f90876e45e9a691ffd5bb35b593221 100644 (file)
@@ -84,14 +84,6 @@ __do_hyp_init:
        orr     r0, r0, r1
        mcr     p15, 4, r0, c2, c0, 2   @ HTCR
 
-       mrc     p15, 4, r1, c2, c1, 2   @ VTCR
-       ldr     r2, =VTCR_MASK
-       bic     r1, r1, r2
-       bic     r0, r0, #(~VTCR_HTCR_SH)        @ clear non-reusable HTCR bits
-       orr     r1, r0, r1
-       orr     r1, r1, #(KVM_VTCR_SL0 | KVM_VTCR_T0SZ | KVM_VTCR_S)
-       mcr     p15, 4, r1, c2, c1, 2   @ VTCR
-
        @ Use the same memory attributes for hyp. accesses as the kernel
        @ (copy MAIRx ro HMAIRx).
        mrc     p15, 0, r0, c10, c2, 0
index 900ef6dd8f727e9a510b79cd0d9e36dbafa26cfa..b1bd316f14c0adb31a161a3474b1706fa605064c 100644 (file)
  */
 
 #include <linux/linkage.h>
-#include <linux/const.h>
-#include <asm/unified.h>
-#include <asm/page.h>
-#include <asm/ptrace.h>
-#include <asm/asm-offsets.h>
-#include <asm/kvm_asm.h>
-#include <asm/kvm_arm.h>
-#include <asm/vfpmacros.h>
-#include "interrupts_head.S"
 
        .text
 
-__kvm_hyp_code_start:
-       .globl __kvm_hyp_code_start
-
-/********************************************************************
- * Flush per-VMID TLBs
- *
- * void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
- *
- * We rely on the hardware to broadcast the TLB invalidation to all CPUs
- * inside the inner-shareable domain (which is the case for all v7
- * implementations).  If we come across a non-IS SMP implementation, we'll
- * have to use an IPI based mechanism. Until then, we stick to the simple
- * hardware assisted version.
- *
- * As v7 does not support flushing per IPA, just nuke the whole TLB
- * instead, ignoring the ipa value.
- */
-ENTRY(__kvm_tlb_flush_vmid_ipa)
-       push    {r2, r3}
-
-       dsb     ishst
-       add     r0, r0, #KVM_VTTBR
-       ldrd    r2, r3, [r0]
-       mcrr    p15, 6, rr_lo_hi(r2, r3), c2    @ Write VTTBR
-       isb
-       mcr     p15, 0, r0, c8, c3, 0   @ TLBIALLIS (rt ignored)
-       dsb     ish
-       isb
-       mov     r2, #0
-       mov     r3, #0
-       mcrr    p15, 6, r2, r3, c2      @ Back to VMID #0
-       isb                             @ Not necessary if followed by eret
-
-       pop     {r2, r3}
-       bx      lr
-ENDPROC(__kvm_tlb_flush_vmid_ipa)
-
-/**
- * void __kvm_tlb_flush_vmid(struct kvm *kvm) - Flush per-VMID TLBs
- *
- * Reuses __kvm_tlb_flush_vmid_ipa() for ARMv7, without passing address
- * parameter
- */
-
-ENTRY(__kvm_tlb_flush_vmid)
-       b       __kvm_tlb_flush_vmid_ipa
-ENDPROC(__kvm_tlb_flush_vmid)
-
-/********************************************************************
- * Flush TLBs and instruction caches of all CPUs inside the inner-shareable
- * domain, for all VMIDs
- *
- * void __kvm_flush_vm_context(void);
- */
-ENTRY(__kvm_flush_vm_context)
-       mov     r0, #0                  @ rn parameter for c15 flushes is SBZ
-
-       /* Invalidate NS Non-Hyp TLB Inner Shareable (TLBIALLNSNHIS) */
-       mcr     p15, 4, r0, c8, c3, 4
-       /* Invalidate instruction caches Inner Shareable (ICIALLUIS) */
-       mcr     p15, 0, r0, c7, c1, 0
-       dsb     ish
-       isb                             @ Not necessary if followed by eret
-
-       bx      lr
-ENDPROC(__kvm_flush_vm_context)
-
-
-/********************************************************************
- *  Hypervisor world-switch code
- *
- *
- * int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
- */
-ENTRY(__kvm_vcpu_run)
-       @ Save the vcpu pointer
-       mcr     p15, 4, vcpu, c13, c0, 2        @ HTPIDR
-
-       save_host_regs
-
-       restore_vgic_state
-       restore_timer_state
-
-       @ Store hardware CP15 state and load guest state
-       read_cp15_state store_to_vcpu = 0
-       write_cp15_state read_from_vcpu = 1
-
-       @ If the host kernel has not been configured with VFPv3 support,
-       @ then it is safer if we deny guests from using it as well.
-#ifdef CONFIG_VFPv3
-       @ Set FPEXC_EN so the guest doesn't trap floating point instructions
-       VFPFMRX r2, FPEXC               @ VMRS
-       push    {r2}
-       orr     r2, r2, #FPEXC_EN
-       VFPFMXR FPEXC, r2               @ VMSR
-#endif
-
-       @ Configure Hyp-role
-       configure_hyp_role vmentry
-
-       @ Trap coprocessor CRx accesses
-       set_hstr vmentry
-       set_hcptr vmentry, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11))
-       set_hdcr vmentry
-
-       @ Write configured ID register into MIDR alias
-       ldr     r1, [vcpu, #VCPU_MIDR]
-       mcr     p15, 4, r1, c0, c0, 0
-
-       @ Write guest view of MPIDR into VMPIDR
-       ldr     r1, [vcpu, #CP15_OFFSET(c0_MPIDR)]
-       mcr     p15, 4, r1, c0, c0, 5
-
-       @ Set up guest memory translation
-       ldr     r1, [vcpu, #VCPU_KVM]
-       add     r1, r1, #KVM_VTTBR
-       ldrd    r2, r3, [r1]
-       mcrr    p15, 6, rr_lo_hi(r2, r3), c2    @ Write VTTBR
-
-       @ We're all done, just restore the GPRs and go to the guest
-       restore_guest_regs
-       clrex                           @ Clear exclusive monitor
-       eret
-
-__kvm_vcpu_return:
-       /*
-        * return convention:
-        * guest r0, r1, r2 saved on the stack
-        * r0: vcpu pointer
-        * r1: exception code
-        */
-       save_guest_regs
-
-       @ Set VMID == 0
-       mov     r2, #0
-       mov     r3, #0
-       mcrr    p15, 6, r2, r3, c2      @ Write VTTBR
-
-       @ Don't trap coprocessor accesses for host kernel
-       set_hstr vmexit
-       set_hdcr vmexit
-       set_hcptr vmexit, (HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11)), after_vfp_restore
-
-#ifdef CONFIG_VFPv3
-       @ Switch VFP/NEON hardware state to the host's
-       add     r7, vcpu, #VCPU_VFP_GUEST
-       store_vfp_state r7
-       add     r7, vcpu, #VCPU_VFP_HOST
-       ldr     r7, [r7]
-       restore_vfp_state r7
-
-after_vfp_restore:
-       @ Restore FPEXC_EN which we clobbered on entry
-       pop     {r2}
-       VFPFMXR FPEXC, r2
-#else
-after_vfp_restore:
-#endif
-
-       @ Reset Hyp-role
-       configure_hyp_role vmexit
-
-       @ Let host read hardware MIDR
-       mrc     p15, 0, r2, c0, c0, 0
-       mcr     p15, 4, r2, c0, c0, 0
-
-       @ Back to hardware MPIDR
-       mrc     p15, 0, r2, c0, c0, 5
-       mcr     p15, 4, r2, c0, c0, 5
-
-       @ Store guest CP15 state and restore host state
-       read_cp15_state store_to_vcpu = 1
-       write_cp15_state read_from_vcpu = 0
-
-       save_timer_state
-       save_vgic_state
-
-       restore_host_regs
-       clrex                           @ Clear exclusive monitor
-#ifndef CONFIG_CPU_ENDIAN_BE8
-       mov     r0, r1                  @ Return the return code
-       mov     r1, #0                  @ Clear upper bits in return value
-#else
-       @ r1 already has return code
-       mov     r0, #0                  @ Clear upper bits in return value
-#endif /* CONFIG_CPU_ENDIAN_BE8 */
-       bx      lr                      @ return to IOCTL
-
 /********************************************************************
  *  Call function in Hyp mode
  *
  *
- * u64 kvm_call_hyp(void *hypfn, ...);
+ * unsigned long kvm_call_hyp(void *hypfn, ...);
  *
  * This is not really a variadic function in the classic C-way and care must
  * be taken when calling this to ensure parameters are passed in registers
@@ -232,7 +35,7 @@ after_vfp_restore:
  * passed as r0, r1, and r2 (a maximum of 3 arguments in addition to the
  * function pointer can be passed).  The function being called must be mapped
  * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
- * passed in r0 and r1.
+ * passed in r0 (strictly 32bit).
  *
  * A function pointer with a value of 0xffffffff has a special meaning,
  * and is used to implement __hyp_get_vectors in the same way as in
@@ -246,281 +49,4 @@ after_vfp_restore:
 ENTRY(kvm_call_hyp)
        hvc     #0
        bx      lr
-
-/********************************************************************
- * Hypervisor exception vector and handlers
- *
- *
- * The KVM/ARM Hypervisor ABI is defined as follows:
- *
- * Entry to Hyp mode from the host kernel will happen _only_ when an HVC
- * instruction is issued since all traps are disabled when running the host
- * kernel as per the Hyp-mode initialization at boot time.
- *
- * HVC instructions cause a trap to the vector page + offset 0x14 (see hyp_hvc
- * below) when the HVC instruction is called from SVC mode (i.e. a guest or the
- * host kernel) and they cause a trap to the vector page + offset 0x8 when HVC
- * instructions are called from within Hyp-mode.
- *
- * Hyp-ABI: Calling HYP-mode functions from host (in SVC mode):
- *    Switching to Hyp mode is done through a simple HVC #0 instruction. The
- *    exception vector code will check that the HVC comes from VMID==0 and if
- *    so will push the necessary state (SPSR, lr_usr) on the Hyp stack.
- *    - r0 contains a pointer to a HYP function
- *    - r1, r2, and r3 contain arguments to the above function.
- *    - The HYP function will be called with its arguments in r0, r1 and r2.
- *    On HYP function return, we return directly to SVC.
- *
- * Note that the above is used to execute code in Hyp-mode from a host-kernel
- * point of view, and is a different concept from performing a world-switch and
- * executing guest code SVC mode (with a VMID != 0).
- */
-
-/* Handle undef, svc, pabt, or dabt by crashing with a user notice */
-.macro bad_exception exception_code, panic_str
-       push    {r0-r2}
-       mrrc    p15, 6, r0, r1, c2      @ Read VTTBR
-       lsr     r1, r1, #16
-       ands    r1, r1, #0xff
-       beq     99f
-
-       load_vcpu                       @ Load VCPU pointer
-       .if \exception_code == ARM_EXCEPTION_DATA_ABORT
-       mrc     p15, 4, r2, c5, c2, 0   @ HSR
-       mrc     p15, 4, r1, c6, c0, 0   @ HDFAR
-       str     r2, [vcpu, #VCPU_HSR]
-       str     r1, [vcpu, #VCPU_HxFAR]
-       .endif
-       .if \exception_code == ARM_EXCEPTION_PREF_ABORT
-       mrc     p15, 4, r2, c5, c2, 0   @ HSR
-       mrc     p15, 4, r1, c6, c0, 2   @ HIFAR
-       str     r2, [vcpu, #VCPU_HSR]
-       str     r1, [vcpu, #VCPU_HxFAR]
-       .endif
-       mov     r1, #\exception_code
-       b       __kvm_vcpu_return
-
-       @ We were in the host already. Let's craft a panic-ing return to SVC.
-99:    mrs     r2, cpsr
-       bic     r2, r2, #MODE_MASK
-       orr     r2, r2, #SVC_MODE
-THUMB( orr     r2, r2, #PSR_T_BIT      )
-       msr     spsr_cxsf, r2
-       mrs     r1, ELR_hyp
-       ldr     r2, =panic
-       msr     ELR_hyp, r2
-       ldr     r0, =\panic_str
-       clrex                           @ Clear exclusive monitor
-       eret
-.endm
-
-       .text
-
-       .align 5
-__kvm_hyp_vector:
-       .globl __kvm_hyp_vector
-
-       @ Hyp-mode exception vector
-       W(b)    hyp_reset
-       W(b)    hyp_undef
-       W(b)    hyp_svc
-       W(b)    hyp_pabt
-       W(b)    hyp_dabt
-       W(b)    hyp_hvc
-       W(b)    hyp_irq
-       W(b)    hyp_fiq
-
-       .align
-hyp_reset:
-       b       hyp_reset
-
-       .align
-hyp_undef:
-       bad_exception ARM_EXCEPTION_UNDEFINED, und_die_str
-
-       .align
-hyp_svc:
-       bad_exception ARM_EXCEPTION_HVC, svc_die_str
-
-       .align
-hyp_pabt:
-       bad_exception ARM_EXCEPTION_PREF_ABORT, pabt_die_str
-
-       .align
-hyp_dabt:
-       bad_exception ARM_EXCEPTION_DATA_ABORT, dabt_die_str
-
-       .align
-hyp_hvc:
-       /*
-        * Getting here is either becuase of a trap from a guest or from calling
-        * HVC from the host kernel, which means "switch to Hyp mode".
-        */
-       push    {r0, r1, r2}
-
-       @ Check syndrome register
-       mrc     p15, 4, r1, c5, c2, 0   @ HSR
-       lsr     r0, r1, #HSR_EC_SHIFT
-       cmp     r0, #HSR_EC_HVC
-       bne     guest_trap              @ Not HVC instr.
-
-       /*
-        * Let's check if the HVC came from VMID 0 and allow simple
-        * switch to Hyp mode
-        */
-       mrrc    p15, 6, r0, r2, c2
-       lsr     r2, r2, #16
-       and     r2, r2, #0xff
-       cmp     r2, #0
-       bne     guest_trap              @ Guest called HVC
-
-       /*
-        * Getting here means host called HVC, we shift parameters and branch
-        * to Hyp function.
-        */
-       pop     {r0, r1, r2}
-
-       /* Check for __hyp_get_vectors */
-       cmp     r0, #-1
-       mrceq   p15, 4, r0, c12, c0, 0  @ get HVBAR
-       beq     1f
-
-       push    {lr}
-       mrs     lr, SPSR
-       push    {lr}
-
-       mov     lr, r0
-       mov     r0, r1
-       mov     r1, r2
-       mov     r2, r3
-
-THUMB( orr     lr, #1)
-       blx     lr                      @ Call the HYP function
-
-       pop     {lr}
-       msr     SPSR_csxf, lr
-       pop     {lr}
-1:     eret
-
-guest_trap:
-       load_vcpu                       @ Load VCPU pointer to r0
-       str     r1, [vcpu, #VCPU_HSR]
-
-       @ Check if we need the fault information
-       lsr     r1, r1, #HSR_EC_SHIFT
-#ifdef CONFIG_VFPv3
-       cmp     r1, #HSR_EC_CP_0_13
-       beq     switch_to_guest_vfp
-#endif
-       cmp     r1, #HSR_EC_IABT
-       mrceq   p15, 4, r2, c6, c0, 2   @ HIFAR
-       beq     2f
-       cmp     r1, #HSR_EC_DABT
-       bne     1f
-       mrc     p15, 4, r2, c6, c0, 0   @ HDFAR
-
-2:     str     r2, [vcpu, #VCPU_HxFAR]
-
-       /*
-        * B3.13.5 Reporting exceptions taken to the Non-secure PL2 mode:
-        *
-        * Abort on the stage 2 translation for a memory access from a
-        * Non-secure PL1 or PL0 mode:
-        *
-        * For any Access flag fault or Translation fault, and also for any
-        * Permission fault on the stage 2 translation of a memory access
-        * made as part of a translation table walk for a stage 1 translation,
-        * the HPFAR holds the IPA that caused the fault. Otherwise, the HPFAR
-        * is UNKNOWN.
-        */
-
-       /* Check for permission fault, and S1PTW */
-       mrc     p15, 4, r1, c5, c2, 0   @ HSR
-       and     r0, r1, #HSR_FSC_TYPE
-       cmp     r0, #FSC_PERM
-       tsteq   r1, #(1 << 7)           @ S1PTW
-       mrcne   p15, 4, r2, c6, c0, 4   @ HPFAR
-       bne     3f
-
-       /* Preserve PAR */
-       mrrc    p15, 0, r0, r1, c7      @ PAR
-       push    {r0, r1}
-
-       /* Resolve IPA using the xFAR */
-       mcr     p15, 0, r2, c7, c8, 0   @ ATS1CPR
-       isb
-       mrrc    p15, 0, r0, r1, c7      @ PAR
-       tst     r0, #1
-       bne     4f                      @ Failed translation
-       ubfx    r2, r0, #12, #20
-       lsl     r2, r2, #4
-       orr     r2, r2, r1, lsl #24
-
-       /* Restore PAR */
-       pop     {r0, r1}
-       mcrr    p15, 0, r0, r1, c7      @ PAR
-
-3:     load_vcpu                       @ Load VCPU pointer to r0
-       str     r2, [r0, #VCPU_HPFAR]
-
-1:     mov     r1, #ARM_EXCEPTION_HVC
-       b       __kvm_vcpu_return
-
-4:     pop     {r0, r1}                @ Failed translation, return to guest
-       mcrr    p15, 0, r0, r1, c7      @ PAR
-       clrex
-       pop     {r0, r1, r2}
-       eret
-
-/*
- * If VFPv3 support is not available, then we will not switch the VFP
- * registers; however cp10 and cp11 accesses will still trap and fallback
- * to the regular coprocessor emulation code, which currently will
- * inject an undefined exception to the guest.
- */
-#ifdef CONFIG_VFPv3
-switch_to_guest_vfp:
-       push    {r3-r7}
-
-       @ NEON/VFP used.  Turn on VFP access.
-       set_hcptr vmtrap, (HCPTR_TCP(10) | HCPTR_TCP(11))
-
-       @ Switch VFP/NEON hardware state to the guest's
-       add     r7, r0, #VCPU_VFP_HOST
-       ldr     r7, [r7]
-       store_vfp_state r7
-       add     r7, r0, #VCPU_VFP_GUEST
-       restore_vfp_state r7
-
-       pop     {r3-r7}
-       pop     {r0-r2}
-       clrex
-       eret
-#endif
-
-       .align
-hyp_irq:
-       push    {r0, r1, r2}
-       mov     r1, #ARM_EXCEPTION_IRQ
-       load_vcpu                       @ Load VCPU pointer to r0
-       b       __kvm_vcpu_return
-
-       .align
-hyp_fiq:
-       b       hyp_fiq
-
-       .ltorg
-
-__kvm_hyp_code_end:
-       .globl  __kvm_hyp_code_end
-
-       .section ".rodata"
-
-und_die_str:
-       .ascii  "unexpected undefined exception in Hyp mode at: %#08x\n"
-pabt_die_str:
-       .ascii  "unexpected prefetch abort in Hyp mode at: %#08x\n"
-dabt_die_str:
-       .ascii  "unexpected data abort in Hyp mode at: %#08x\n"
-svc_die_str:
-       .ascii  "unexpected HVC/SVC trap in Hyp mode at: %#08x\n"
+ENDPROC(kvm_call_hyp)
diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
deleted file mode 100644 (file)
index 51a5950..0000000
+++ /dev/null
@@ -1,648 +0,0 @@
-#include <linux/irqchip/arm-gic.h>
-#include <asm/assembler.h>
-
-#define VCPU_USR_REG(_reg_nr)  (VCPU_USR_REGS + (_reg_nr * 4))
-#define VCPU_USR_SP            (VCPU_USR_REG(13))
-#define VCPU_USR_LR            (VCPU_USR_REG(14))
-#define CP15_OFFSET(_cp15_reg_idx) (VCPU_CP15 + (_cp15_reg_idx * 4))
-
-/*
- * Many of these macros need to access the VCPU structure, which is always
- * held in r0. These macros should never clobber r1, as it is used to hold the
- * exception code on the return path (except of course the macro that switches
- * all the registers before the final jump to the VM).
- */
-vcpu   .req    r0              @ vcpu pointer always in r0
-
-/* Clobbers {r2-r6} */
-.macro store_vfp_state vfp_base
-       @ The VFPFMRX and VFPFMXR macros are the VMRS and VMSR instructions
-       VFPFMRX r2, FPEXC
-       @ Make sure VFP is enabled so we can touch the registers.
-       orr     r6, r2, #FPEXC_EN
-       VFPFMXR FPEXC, r6
-
-       VFPFMRX r3, FPSCR
-       tst     r2, #FPEXC_EX           @ Check for VFP Subarchitecture
-       beq     1f
-       @ If FPEXC_EX is 0, then FPINST/FPINST2 reads are upredictable, so
-       @ we only need to save them if FPEXC_EX is set.
-       VFPFMRX r4, FPINST
-       tst     r2, #FPEXC_FP2V
-       VFPFMRX r5, FPINST2, ne         @ vmrsne
-       bic     r6, r2, #FPEXC_EX       @ FPEXC_EX disable
-       VFPFMXR FPEXC, r6
-1:
-       VFPFSTMIA \vfp_base, r6         @ Save VFP registers
-       stm     \vfp_base, {r2-r5}      @ Save FPEXC, FPSCR, FPINST, FPINST2
-.endm
-
-/* Assume FPEXC_EN is on and FPEXC_EX is off, clobbers {r2-r6} */
-.macro restore_vfp_state vfp_base
-       VFPFLDMIA \vfp_base, r6         @ Load VFP registers
-       ldm     \vfp_base, {r2-r5}      @ Load FPEXC, FPSCR, FPINST, FPINST2
-
-       VFPFMXR FPSCR, r3
-       tst     r2, #FPEXC_EX           @ Check for VFP Subarchitecture
-       beq     1f
-       VFPFMXR FPINST, r4
-       tst     r2, #FPEXC_FP2V
-       VFPFMXR FPINST2, r5, ne
-1:
-       VFPFMXR FPEXC, r2       @ FPEXC (last, in case !EN)
-.endm
-
-/* These are simply for the macros to work - value don't have meaning */
-.equ usr, 0
-.equ svc, 1
-.equ abt, 2
-.equ und, 3
-.equ irq, 4
-.equ fiq, 5
-
-.macro push_host_regs_mode mode
-       mrs     r2, SP_\mode
-       mrs     r3, LR_\mode
-       mrs     r4, SPSR_\mode
-       push    {r2, r3, r4}
-.endm
-
-/*
- * Store all host persistent registers on the stack.
- * Clobbers all registers, in all modes, except r0 and r1.
- */
-.macro save_host_regs
-       /* Hyp regs. Only ELR_hyp (SPSR_hyp already saved) */
-       mrs     r2, ELR_hyp
-       push    {r2}
-
-       /* usr regs */
-       push    {r4-r12}        @ r0-r3 are always clobbered
-       mrs     r2, SP_usr
-       mov     r3, lr
-       push    {r2, r3}
-
-       push_host_regs_mode svc
-       push_host_regs_mode abt
-       push_host_regs_mode und
-       push_host_regs_mode irq
-
-       /* fiq regs */
-       mrs     r2, r8_fiq
-       mrs     r3, r9_fiq
-       mrs     r4, r10_fiq
-       mrs     r5, r11_fiq
-       mrs     r6, r12_fiq
-       mrs     r7, SP_fiq
-       mrs     r8, LR_fiq
-       mrs     r9, SPSR_fiq
-       push    {r2-r9}
-.endm
-
-.macro pop_host_regs_mode mode
-       pop     {r2, r3, r4}
-       msr     SP_\mode, r2
-       msr     LR_\mode, r3
-       msr     SPSR_\mode, r4
-.endm
-
-/*
- * Restore all host registers from the stack.
- * Clobbers all registers, in all modes, except r0 and r1.
- */
-.macro restore_host_regs
-       pop     {r2-r9}
-       msr     r8_fiq, r2
-       msr     r9_fiq, r3
-       msr     r10_fiq, r4
-       msr     r11_fiq, r5
-       msr     r12_fiq, r6
-       msr     SP_fiq, r7
-       msr     LR_fiq, r8
-       msr     SPSR_fiq, r9
-
-       pop_host_regs_mode irq
-       pop_host_regs_mode und
-       pop_host_regs_mode abt
-       pop_host_regs_mode svc
-
-       pop     {r2, r3}
-       msr     SP_usr, r2
-       mov     lr, r3
-       pop     {r4-r12}
-
-       pop     {r2}
-       msr     ELR_hyp, r2
-.endm
-
-/*
- * Restore SP, LR and SPSR for a given mode. offset is the offset of
- * this mode's registers from the VCPU base.
- *
- * Assumes vcpu pointer in vcpu reg
- *
- * Clobbers r1, r2, r3, r4.
- */
-.macro restore_guest_regs_mode mode, offset
-       add     r1, vcpu, \offset
-       ldm     r1, {r2, r3, r4}
-       msr     SP_\mode, r2
-       msr     LR_\mode, r3
-       msr     SPSR_\mode, r4
-.endm
-
-/*
- * Restore all guest registers from the vcpu struct.
- *
- * Assumes vcpu pointer in vcpu reg
- *
- * Clobbers *all* registers.
- */
-.macro restore_guest_regs
-       restore_guest_regs_mode svc, #VCPU_SVC_REGS
-       restore_guest_regs_mode abt, #VCPU_ABT_REGS
-       restore_guest_regs_mode und, #VCPU_UND_REGS
-       restore_guest_regs_mode irq, #VCPU_IRQ_REGS
-
-       add     r1, vcpu, #VCPU_FIQ_REGS
-       ldm     r1, {r2-r9}
-       msr     r8_fiq, r2
-       msr     r9_fiq, r3
-       msr     r10_fiq, r4
-       msr     r11_fiq, r5
-       msr     r12_fiq, r6
-       msr     SP_fiq, r7
-       msr     LR_fiq, r8
-       msr     SPSR_fiq, r9
-
-       @ Load return state
-       ldr     r2, [vcpu, #VCPU_PC]
-       ldr     r3, [vcpu, #VCPU_CPSR]
-       msr     ELR_hyp, r2
-       msr     SPSR_cxsf, r3
-
-       @ Load user registers
-       ldr     r2, [vcpu, #VCPU_USR_SP]
-       ldr     r3, [vcpu, #VCPU_USR_LR]
-       msr     SP_usr, r2
-       mov     lr, r3
-       add     vcpu, vcpu, #(VCPU_USR_REGS)
-       ldm     vcpu, {r0-r12}
-.endm
-
-/*
- * Save SP, LR and SPSR for a given mode. offset is the offset of
- * this mode's registers from the VCPU base.
- *
- * Assumes vcpu pointer in vcpu reg
- *
- * Clobbers r2, r3, r4, r5.
- */
-.macro save_guest_regs_mode mode, offset
-       add     r2, vcpu, \offset
-       mrs     r3, SP_\mode
-       mrs     r4, LR_\mode
-       mrs     r5, SPSR_\mode
-       stm     r2, {r3, r4, r5}
-.endm
-
-/*
- * Save all guest registers to the vcpu struct
- * Expects guest's r0, r1, r2 on the stack.
- *
- * Assumes vcpu pointer in vcpu reg
- *
- * Clobbers r2, r3, r4, r5.
- */
-.macro save_guest_regs
-       @ Store usr registers
-       add     r2, vcpu, #VCPU_USR_REG(3)
-       stm     r2, {r3-r12}
-       add     r2, vcpu, #VCPU_USR_REG(0)
-       pop     {r3, r4, r5}            @ r0, r1, r2
-       stm     r2, {r3, r4, r5}
-       mrs     r2, SP_usr
-       mov     r3, lr
-       str     r2, [vcpu, #VCPU_USR_SP]
-       str     r3, [vcpu, #VCPU_USR_LR]
-
-       @ Store return state
-       mrs     r2, ELR_hyp
-       mrs     r3, spsr
-       str     r2, [vcpu, #VCPU_PC]
-       str     r3, [vcpu, #VCPU_CPSR]
-
-       @ Store other guest registers
-       save_guest_regs_mode svc, #VCPU_SVC_REGS
-       save_guest_regs_mode abt, #VCPU_ABT_REGS
-       save_guest_regs_mode und, #VCPU_UND_REGS
-       save_guest_regs_mode irq, #VCPU_IRQ_REGS
-.endm
-
-/* Reads cp15 registers from hardware and stores them in memory
- * @store_to_vcpu: If 0, registers are written in-order to the stack,
- *                otherwise to the VCPU struct pointed to by vcpup
- *
- * Assumes vcpu pointer in vcpu reg
- *
- * Clobbers r2 - r12
- */
-.macro read_cp15_state store_to_vcpu
-       mrc     p15, 0, r2, c1, c0, 0   @ SCTLR
-       mrc     p15, 0, r3, c1, c0, 2   @ CPACR
-       mrc     p15, 0, r4, c2, c0, 2   @ TTBCR
-       mrc     p15, 0, r5, c3, c0, 0   @ DACR
-       mrrc    p15, 0, r6, r7, c2      @ TTBR 0
-       mrrc    p15, 1, r8, r9, c2      @ TTBR 1
-       mrc     p15, 0, r10, c10, c2, 0 @ PRRR
-       mrc     p15, 0, r11, c10, c2, 1 @ NMRR
-       mrc     p15, 2, r12, c0, c0, 0  @ CSSELR
-
-       .if \store_to_vcpu == 0
-       push    {r2-r12}                @ Push CP15 registers
-       .else
-       str     r2, [vcpu, #CP15_OFFSET(c1_SCTLR)]
-       str     r3, [vcpu, #CP15_OFFSET(c1_CPACR)]
-       str     r4, [vcpu, #CP15_OFFSET(c2_TTBCR)]
-       str     r5, [vcpu, #CP15_OFFSET(c3_DACR)]
-       add     r2, vcpu, #CP15_OFFSET(c2_TTBR0)
-       strd    r6, r7, [r2]
-       add     r2, vcpu, #CP15_OFFSET(c2_TTBR1)
-       strd    r8, r9, [r2]
-       str     r10, [vcpu, #CP15_OFFSET(c10_PRRR)]
-       str     r11, [vcpu, #CP15_OFFSET(c10_NMRR)]
-       str     r12, [vcpu, #CP15_OFFSET(c0_CSSELR)]
-       .endif
-
-       mrc     p15, 0, r2, c13, c0, 1  @ CID
-       mrc     p15, 0, r3, c13, c0, 2  @ TID_URW
-       mrc     p15, 0, r4, c13, c0, 3  @ TID_URO
-       mrc     p15, 0, r5, c13, c0, 4  @ TID_PRIV
-       mrc     p15, 0, r6, c5, c0, 0   @ DFSR
-       mrc     p15, 0, r7, c5, c0, 1   @ IFSR
-       mrc     p15, 0, r8, c5, c1, 0   @ ADFSR
-       mrc     p15, 0, r9, c5, c1, 1   @ AIFSR
-       mrc     p15, 0, r10, c6, c0, 0  @ DFAR
-       mrc     p15, 0, r11, c6, c0, 2  @ IFAR
-       mrc     p15, 0, r12, c12, c0, 0 @ VBAR
-
-       .if \store_to_vcpu == 0
-       push    {r2-r12}                @ Push CP15 registers
-       .else
-       str     r2, [vcpu, #CP15_OFFSET(c13_CID)]
-       str     r3, [vcpu, #CP15_OFFSET(c13_TID_URW)]
-       str     r4, [vcpu, #CP15_OFFSET(c13_TID_URO)]
-       str     r5, [vcpu, #CP15_OFFSET(c13_TID_PRIV)]
-       str     r6, [vcpu, #CP15_OFFSET(c5_DFSR)]
-       str     r7, [vcpu, #CP15_OFFSET(c5_IFSR)]
-       str     r8, [vcpu, #CP15_OFFSET(c5_ADFSR)]
-       str     r9, [vcpu, #CP15_OFFSET(c5_AIFSR)]
-       str     r10, [vcpu, #CP15_OFFSET(c6_DFAR)]
-       str     r11, [vcpu, #CP15_OFFSET(c6_IFAR)]
-       str     r12, [vcpu, #CP15_OFFSET(c12_VBAR)]
-       .endif
-
-       mrc     p15, 0, r2, c14, c1, 0  @ CNTKCTL
-       mrrc    p15, 0, r4, r5, c7      @ PAR
-       mrc     p15, 0, r6, c10, c3, 0  @ AMAIR0
-       mrc     p15, 0, r7, c10, c3, 1  @ AMAIR1
-
-       .if \store_to_vcpu == 0
-       push    {r2,r4-r7}
-       .else
-       str     r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)]
-       add     r12, vcpu, #CP15_OFFSET(c7_PAR)
-       strd    r4, r5, [r12]
-       str     r6, [vcpu, #CP15_OFFSET(c10_AMAIR0)]
-       str     r7, [vcpu, #CP15_OFFSET(c10_AMAIR1)]
-       .endif
-.endm
-
-/*
- * Reads cp15 registers from memory and writes them to hardware
- * @read_from_vcpu: If 0, registers are read in-order from the stack,
- *                 otherwise from the VCPU struct pointed to by vcpup
- *
- * Assumes vcpu pointer in vcpu reg
- */
-.macro write_cp15_state read_from_vcpu
-       .if \read_from_vcpu == 0
-       pop     {r2,r4-r7}
-       .else
-       ldr     r2, [vcpu, #CP15_OFFSET(c14_CNTKCTL)]
-       add     r12, vcpu, #CP15_OFFSET(c7_PAR)
-       ldrd    r4, r5, [r12]
-       ldr     r6, [vcpu, #CP15_OFFSET(c10_AMAIR0)]
-       ldr     r7, [vcpu, #CP15_OFFSET(c10_AMAIR1)]
-       .endif
-
-       mcr     p15, 0, r2, c14, c1, 0  @ CNTKCTL
-       mcrr    p15, 0, r4, r5, c7      @ PAR
-       mcr     p15, 0, r6, c10, c3, 0  @ AMAIR0
-       mcr     p15, 0, r7, c10, c3, 1  @ AMAIR1
-
-       .if \read_from_vcpu == 0
-       pop     {r2-r12}
-       .else
-       ldr     r2, [vcpu, #CP15_OFFSET(c13_CID)]
-       ldr     r3, [vcpu, #CP15_OFFSET(c13_TID_URW)]
-       ldr     r4, [vcpu, #CP15_OFFSET(c13_TID_URO)]
-       ldr     r5, [vcpu, #CP15_OFFSET(c13_TID_PRIV)]
-       ldr     r6, [vcpu, #CP15_OFFSET(c5_DFSR)]
-       ldr     r7, [vcpu, #CP15_OFFSET(c5_IFSR)]
-       ldr     r8, [vcpu, #CP15_OFFSET(c5_ADFSR)]
-       ldr     r9, [vcpu, #CP15_OFFSET(c5_AIFSR)]
-       ldr     r10, [vcpu, #CP15_OFFSET(c6_DFAR)]
-       ldr     r11, [vcpu, #CP15_OFFSET(c6_IFAR)]
-       ldr     r12, [vcpu, #CP15_OFFSET(c12_VBAR)]
-       .endif
-
-       mcr     p15, 0, r2, c13, c0, 1  @ CID
-       mcr     p15, 0, r3, c13, c0, 2  @ TID_URW
-       mcr     p15, 0, r4, c13, c0, 3  @ TID_URO
-       mcr     p15, 0, r5, c13, c0, 4  @ TID_PRIV
-       mcr     p15, 0, r6, c5, c0, 0   @ DFSR
-       mcr     p15, 0, r7, c5, c0, 1   @ IFSR
-       mcr     p15, 0, r8, c5, c1, 0   @ ADFSR
-       mcr     p15, 0, r9, c5, c1, 1   @ AIFSR
-       mcr     p15, 0, r10, c6, c0, 0  @ DFAR
-       mcr     p15, 0, r11, c6, c0, 2  @ IFAR
-       mcr     p15, 0, r12, c12, c0, 0 @ VBAR
-
-       .if \read_from_vcpu == 0
-       pop     {r2-r12}
-       .else
-       ldr     r2, [vcpu, #CP15_OFFSET(c1_SCTLR)]
-       ldr     r3, [vcpu, #CP15_OFFSET(c1_CPACR)]
-       ldr     r4, [vcpu, #CP15_OFFSET(c2_TTBCR)]
-       ldr     r5, [vcpu, #CP15_OFFSET(c3_DACR)]
-       add     r12, vcpu, #CP15_OFFSET(c2_TTBR0)
-       ldrd    r6, r7, [r12]
-       add     r12, vcpu, #CP15_OFFSET(c2_TTBR1)
-       ldrd    r8, r9, [r12]
-       ldr     r10, [vcpu, #CP15_OFFSET(c10_PRRR)]
-       ldr     r11, [vcpu, #CP15_OFFSET(c10_NMRR)]
-       ldr     r12, [vcpu, #CP15_OFFSET(c0_CSSELR)]
-       .endif
-
-       mcr     p15, 0, r2, c1, c0, 0   @ SCTLR
-       mcr     p15, 0, r3, c1, c0, 2   @ CPACR
-       mcr     p15, 0, r4, c2, c0, 2   @ TTBCR
-       mcr     p15, 0, r5, c3, c0, 0   @ DACR
-       mcrr    p15, 0, r6, r7, c2      @ TTBR 0
-       mcrr    p15, 1, r8, r9, c2      @ TTBR 1
-       mcr     p15, 0, r10, c10, c2, 0 @ PRRR
-       mcr     p15, 0, r11, c10, c2, 1 @ NMRR
-       mcr     p15, 2, r12, c0, c0, 0  @ CSSELR
-.endm
-
-/*
- * Save the VGIC CPU state into memory
- *
- * Assumes vcpu pointer in vcpu reg
- */
-.macro save_vgic_state
-       /* Get VGIC VCTRL base into r2 */
-       ldr     r2, [vcpu, #VCPU_KVM]
-       ldr     r2, [r2, #KVM_VGIC_VCTRL]
-       cmp     r2, #0
-       beq     2f
-
-       /* Compute the address of struct vgic_cpu */
-       add     r11, vcpu, #VCPU_VGIC_CPU
-
-       /* Save all interesting registers */
-       ldr     r4, [r2, #GICH_VMCR]
-       ldr     r5, [r2, #GICH_MISR]
-       ldr     r6, [r2, #GICH_EISR0]
-       ldr     r7, [r2, #GICH_EISR1]
-       ldr     r8, [r2, #GICH_ELRSR0]
-       ldr     r9, [r2, #GICH_ELRSR1]
-       ldr     r10, [r2, #GICH_APR]
-ARM_BE8(rev    r4, r4  )
-ARM_BE8(rev    r5, r5  )
-ARM_BE8(rev    r6, r6  )
-ARM_BE8(rev    r7, r7  )
-ARM_BE8(rev    r8, r8  )
-ARM_BE8(rev    r9, r9  )
-ARM_BE8(rev    r10, r10        )
-
-       str     r4, [r11, #VGIC_V2_CPU_VMCR]
-       str     r5, [r11, #VGIC_V2_CPU_MISR]
-#ifdef CONFIG_CPU_ENDIAN_BE8
-       str     r6, [r11, #(VGIC_V2_CPU_EISR + 4)]
-       str     r7, [r11, #VGIC_V2_CPU_EISR]
-       str     r8, [r11, #(VGIC_V2_CPU_ELRSR + 4)]
-       str     r9, [r11, #VGIC_V2_CPU_ELRSR]
-#else
-       str     r6, [r11, #VGIC_V2_CPU_EISR]
-       str     r7, [r11, #(VGIC_V2_CPU_EISR + 4)]
-       str     r8, [r11, #VGIC_V2_CPU_ELRSR]
-       str     r9, [r11, #(VGIC_V2_CPU_ELRSR + 4)]
-#endif
-       str     r10, [r11, #VGIC_V2_CPU_APR]
-
-       /* Clear GICH_HCR */
-       mov     r5, #0
-       str     r5, [r2, #GICH_HCR]
-
-       /* Save list registers */
-       add     r2, r2, #GICH_LR0
-       add     r3, r11, #VGIC_V2_CPU_LR
-       ldr     r4, [r11, #VGIC_CPU_NR_LR]
-1:     ldr     r6, [r2], #4
-ARM_BE8(rev    r6, r6  )
-       str     r6, [r3], #4
-       subs    r4, r4, #1
-       bne     1b
-2:
-.endm
-
-/*
- * Restore the VGIC CPU state from memory
- *
- * Assumes vcpu pointer in vcpu reg
- */
-.macro restore_vgic_state
-       /* Get VGIC VCTRL base into r2 */
-       ldr     r2, [vcpu, #VCPU_KVM]
-       ldr     r2, [r2, #KVM_VGIC_VCTRL]
-       cmp     r2, #0
-       beq     2f
-
-       /* Compute the address of struct vgic_cpu */
-       add     r11, vcpu, #VCPU_VGIC_CPU
-
-       /* We only restore a minimal set of registers */
-       ldr     r3, [r11, #VGIC_V2_CPU_HCR]
-       ldr     r4, [r11, #VGIC_V2_CPU_VMCR]
-       ldr     r8, [r11, #VGIC_V2_CPU_APR]
-ARM_BE8(rev    r3, r3  )
-ARM_BE8(rev    r4, r4  )
-ARM_BE8(rev    r8, r8  )
-
-       str     r3, [r2, #GICH_HCR]
-       str     r4, [r2, #GICH_VMCR]
-       str     r8, [r2, #GICH_APR]
-
-       /* Restore list registers */
-       add     r2, r2, #GICH_LR0
-       add     r3, r11, #VGIC_V2_CPU_LR
-       ldr     r4, [r11, #VGIC_CPU_NR_LR]
-1:     ldr     r6, [r3], #4
-ARM_BE8(rev    r6, r6  )
-       str     r6, [r2], #4
-       subs    r4, r4, #1
-       bne     1b
-2:
-.endm
-
-#define CNTHCTL_PL1PCTEN       (1 << 0)
-#define CNTHCTL_PL1PCEN                (1 << 1)
-
-/*
- * Save the timer state onto the VCPU and allow physical timer/counter access
- * for the host.
- *
- * Assumes vcpu pointer in vcpu reg
- * Clobbers r2-r5
- */
-.macro save_timer_state
-       ldr     r4, [vcpu, #VCPU_KVM]
-       ldr     r2, [r4, #KVM_TIMER_ENABLED]
-       cmp     r2, #0
-       beq     1f
-
-       mrc     p15, 0, r2, c14, c3, 1  @ CNTV_CTL
-       str     r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
-
-       isb
-
-       mrrc    p15, 3, rr_lo_hi(r2, r3), c14   @ CNTV_CVAL
-       ldr     r4, =VCPU_TIMER_CNTV_CVAL
-       add     r5, vcpu, r4
-       strd    r2, r3, [r5]
-
-       @ Ensure host CNTVCT == CNTPCT
-       mov     r2, #0
-       mcrr    p15, 4, r2, r2, c14     @ CNTVOFF
-
-1:
-       mov     r2, #0                  @ Clear ENABLE
-       mcr     p15, 0, r2, c14, c3, 1  @ CNTV_CTL
-
-       @ Allow physical timer/counter access for the host
-       mrc     p15, 4, r2, c14, c1, 0  @ CNTHCTL
-       orr     r2, r2, #(CNTHCTL_PL1PCEN | CNTHCTL_PL1PCTEN)
-       mcr     p15, 4, r2, c14, c1, 0  @ CNTHCTL
-.endm
-
-/*
- * Load the timer state from the VCPU and deny physical timer/counter access
- * for the host.
- *
- * Assumes vcpu pointer in vcpu reg
- * Clobbers r2-r5
- */
-.macro restore_timer_state
-       @ Disallow physical timer access for the guest
-       @ Physical counter access is allowed
-       mrc     p15, 4, r2, c14, c1, 0  @ CNTHCTL
-       orr     r2, r2, #CNTHCTL_PL1PCTEN
-       bic     r2, r2, #CNTHCTL_PL1PCEN
-       mcr     p15, 4, r2, c14, c1, 0  @ CNTHCTL
-
-       ldr     r4, [vcpu, #VCPU_KVM]
-       ldr     r2, [r4, #KVM_TIMER_ENABLED]
-       cmp     r2, #0
-       beq     1f
-
-       ldr     r2, [r4, #KVM_TIMER_CNTVOFF]
-       ldr     r3, [r4, #(KVM_TIMER_CNTVOFF + 4)]
-       mcrr    p15, 4, rr_lo_hi(r2, r3), c14   @ CNTVOFF
-
-       ldr     r4, =VCPU_TIMER_CNTV_CVAL
-       add     r5, vcpu, r4
-       ldrd    r2, r3, [r5]
-       mcrr    p15, 3, rr_lo_hi(r2, r3), c14   @ CNTV_CVAL
-       isb
-
-       ldr     r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
-       and     r2, r2, #3
-       mcr     p15, 0, r2, c14, c3, 1  @ CNTV_CTL
-1:
-.endm
-
-.equ vmentry,  0
-.equ vmexit,   1
-
-/* Configures the HSTR (Hyp System Trap Register) on entry/return
- * (hardware reset value is 0) */
-.macro set_hstr operation
-       mrc     p15, 4, r2, c1, c1, 3
-       ldr     r3, =HSTR_T(15)
-       .if \operation == vmentry
-       orr     r2, r2, r3              @ Trap CR{15}
-       .else
-       bic     r2, r2, r3              @ Don't trap any CRx accesses
-       .endif
-       mcr     p15, 4, r2, c1, c1, 3
-.endm
-
-/* Configures the HCPTR (Hyp Coprocessor Trap Register) on entry/return
- * (hardware reset value is 0). Keep previous value in r2.
- * An ISB is emited on vmexit/vmtrap, but executed on vmexit only if
- * VFP wasn't already enabled (always executed on vmtrap).
- * If a label is specified with vmexit, it is branched to if VFP wasn't
- * enabled.
- */
-.macro set_hcptr operation, mask, label = none
-       mrc     p15, 4, r2, c1, c1, 2
-       ldr     r3, =\mask
-       .if \operation == vmentry
-       orr     r3, r2, r3              @ Trap coproc-accesses defined in mask
-       .else
-       bic     r3, r2, r3              @ Don't trap defined coproc-accesses
-       .endif
-       mcr     p15, 4, r3, c1, c1, 2
-       .if \operation != vmentry
-       .if \operation == vmexit
-       tst     r2, #(HCPTR_TCP(10) | HCPTR_TCP(11))
-       beq     1f
-       .endif
-       isb
-       .if \label != none
-       b       \label
-       .endif
-1:
-       .endif
-.endm
-
-/* Configures the HDCR (Hyp Debug Configuration Register) on entry/return
- * (hardware reset value is 0) */
-.macro set_hdcr operation
-       mrc     p15, 4, r2, c1, c1, 1
-       ldr     r3, =(HDCR_TPM|HDCR_TPMCR)
-       .if \operation == vmentry
-       orr     r2, r2, r3              @ Trap some perfmon accesses
-       .else
-       bic     r2, r2, r3              @ Don't trap any perfmon accesses
-       .endif
-       mcr     p15, 4, r2, c1, c1, 1
-.endm
-
-/* Enable/Disable: stage-2 trans., trap interrupts, trap wfi, trap smc */
-.macro configure_hyp_role operation
-       .if \operation == vmentry
-       ldr     r2, [vcpu, #VCPU_HCR]
-       ldr     r3, [vcpu, #VCPU_IRQ_LINES]
-       orr     r2, r2, r3
-       .else
-       mov     r2, #0
-       .endif
-       mcr     p15, 4, r2, c1, c1, 0   @ HCR
-.endm
-
-.macro load_vcpu
-       mrc     p15, 4, vcpu, c13, c0, 2        @ HTPIDR
-.endm
index 7f33b2056ae6d92f568ad71fbf28cd52044b11fb..0f6600f05137921b61fe5c9a80b87302e7d03234 100644 (file)
@@ -206,7 +206,8 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
        run->mmio.is_write      = is_write;
        run->mmio.phys_addr     = fault_ipa;
        run->mmio.len           = len;
-       memcpy(run->mmio.data, data_buf, len);
+       if (is_write)
+               memcpy(run->mmio.data, data_buf, len);
 
        if (!ret) {
                /* We handled the access successfully in the kernel. */
index aba61fd3697aa6260f6b0b3626434e2859bc3248..58dbd5c439df45bc10497954db0e61b433646cd6 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/kvm_mmio.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
+#include <asm/virt.h>
 
 #include "trace.h"
 
@@ -598,6 +599,9 @@ int create_hyp_mappings(void *from, void *to)
        unsigned long start = KERN_TO_HYP((unsigned long)from);
        unsigned long end = KERN_TO_HYP((unsigned long)to);
 
+       if (is_kernel_in_hyp_mode())
+               return 0;
+
        start = start & PAGE_MASK;
        end = PAGE_ALIGN(end);
 
@@ -630,6 +634,9 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
        unsigned long start = KERN_TO_HYP((unsigned long)from);
        unsigned long end = KERN_TO_HYP((unsigned long)to);
 
+       if (is_kernel_in_hyp_mode())
+               return 0;
+
        /* Check for a valid kernel IO mapping */
        if (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1))
                return -EINVAL;
@@ -1430,6 +1437,22 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
                        goto out_unlock;
                }
 
+               /*
+                * Check for a cache maintenance operation. Since we
+                * ended-up here, we know it is outside of any memory
+                * slot. But we can't find out if that is for a device,
+                * or if the guest is just being stupid. The only thing
+                * we know for sure is that this range cannot be cached.
+                *
+                * So let's assume that the guest is just being
+                * cautious, and skip the instruction.
+                */
+               if (kvm_vcpu_dabt_is_cm(vcpu)) {
+                       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+                       ret = 1;
+                       goto out_unlock;
+               }
+
                /*
                 * The IPA is reported as [MAX:12], so we need to
                 * complement it with the bottom 12 bits from the
index a9b3b905e661dec55672e459f1119b3eb466b373..c2b131527a643f6e6808b78f8c53e9751d0f71a9 100644 (file)
@@ -70,7 +70,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 {
        struct kvm *kvm = source_vcpu->kvm;
        struct kvm_vcpu *vcpu = NULL;
-       wait_queue_head_t *wq;
+       struct swait_queue_head *wq;
        unsigned long cpu_id;
        unsigned long context_id;
        phys_addr_t target_pc;
@@ -119,7 +119,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
        smp_mb();               /* Make sure the above is visible */
 
        wq = kvm_arch_vcpu_wq(vcpu);
-       wake_up_interruptible(wq);
+       swake_up(wq);
 
        return PSCI_RET_SUCCESS;
 }
index eeb85858d6bbe6dff02ac453ea2f19a889cd8810..0048b5a62a509b4762ca5810d5a0e0b49db654de 100644 (file)
@@ -71,7 +71,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        }
 
        /* Reset core registers */
-       memcpy(&vcpu->arch.regs, reset_regs, sizeof(vcpu->arch.regs));
+       memcpy(&vcpu->arch.ctxt.gp_regs, reset_regs, sizeof(vcpu->arch.ctxt.gp_regs));
 
        /* Reset CP15 registers */
        kvm_reset_coprocs(vcpu);
index cfc696b972f323e07b5e9a180755130e63e5e1b2..fd87205324710ffcfca1871c01ea23a7da8856b4 100644 (file)
@@ -374,8 +374,13 @@ static struct pu_domain imx6q_pu_domain = {
                .name = "PU",
                .power_off = imx6q_pm_pu_power_off,
                .power_on = imx6q_pm_pu_power_on,
-               .power_off_latency_ns = 25000,
-               .power_on_latency_ns = 2000000,
+               .states = {
+                       [0] = {
+                               .power_off_latency_ns = 25000,
+                               .power_on_latency_ns = 2000000,
+                       },
+               },
+               .state_count = 1,
        },
 };
 
index 77d6b1bab278292e31a6435294e824a6a76648b9..ee06fabdf60e69e014317c9703787da5f31dc79f 100644 (file)
@@ -86,8 +86,8 @@ static int lpc32xx_clcd_setup(struct clcd_fb *fb)
 {
        dma_addr_t dma;
 
-       fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
-               PANEL_SIZE, &dma, GFP_KERNEL);
+       fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, PANEL_SIZE, &dma,
+                                         GFP_KERNEL);
        if (!fb->fb.screen_base) {
                printk(KERN_ERR "CLCD: unable to map framebuffer\n");
                return -ENOMEM;
@@ -116,15 +116,14 @@ static int lpc32xx_clcd_setup(struct clcd_fb *fb)
 
 static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
 {
-       return dma_mmap_writecombine(&fb->dev->dev, vma,
-               fb->fb.screen_base, fb->fb.fix.smem_start,
-               fb->fb.fix.smem_len);
+       return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
+                          fb->fb.fix.smem_start, fb->fb.fix.smem_len);
 }
 
 static void lpc32xx_clcd_remove(struct clcd_fb *fb)
 {
-       dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-               fb->fb.screen_base, fb->fb.fix.smem_start);
+       dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
+                   fb->fb.fix.smem_start);
 }
 
 /*
index 64e3d2ce9a076650b7eb3056cd4194419ae7d3dd..b003e3afd693008b9023cdf58911e438ceee30ea 100644 (file)
@@ -3,7 +3,6 @@ menuconfig ARCH_MVEBU
        depends on ARCH_MULTI_V7 || ARCH_MULTI_V5
        select ARCH_SUPPORTS_BIG_ENDIAN
        select CLKSRC_MMIO
-       select GENERIC_IRQ_CHIP
        select PINCTRL
        select PLAT_ORION
        select SOC_BUS
@@ -29,6 +28,7 @@ config MACH_ARMADA_370
        bool "Marvell Armada 370 boards"
        depends on ARCH_MULTI_V7
        select ARMADA_370_CLK
+       select ARMADA_370_XP_IRQ
        select CPU_PJ4B
        select MACH_MVEBU_V7
        select PINCTRL_ARMADA_370
@@ -39,6 +39,7 @@ config MACH_ARMADA_370
 config MACH_ARMADA_375
        bool "Marvell Armada 375 boards"
        depends on ARCH_MULTI_V7
+       select ARMADA_370_XP_IRQ
        select ARM_ERRATA_720789
        select ARM_ERRATA_753970
        select ARM_GIC
@@ -58,6 +59,7 @@ config MACH_ARMADA_38X
        select ARM_ERRATA_720789
        select ARM_ERRATA_753970
        select ARM_GIC
+       select ARMADA_370_XP_IRQ
        select ARMADA_38X_CLK
        select HAVE_ARM_SCU
        select HAVE_ARM_TWD if SMP
@@ -72,6 +74,7 @@ config MACH_ARMADA_39X
        bool "Marvell Armada 39x boards"
        depends on ARCH_MULTI_V7
        select ARM_GIC
+       select ARMADA_370_XP_IRQ
        select ARMADA_39X_CLK
        select CACHE_L2X0
        select HAVE_ARM_SCU
@@ -86,6 +89,7 @@ config MACH_ARMADA_39X
 config MACH_ARMADA_XP
        bool "Marvell Armada XP boards"
        depends on ARCH_MULTI_V7
+       select ARMADA_370_XP_IRQ
        select ARMADA_XP_CLK
        select CPU_PJ4B
        select MACH_MVEBU_V7
index d122ee6ab9913aa8e8f2896ea0fee44a01832068..8814ee5e98fd52ff75412fd863542954037dafb8 100644 (file)
@@ -42,8 +42,8 @@ int netx_clcd_setup(struct clcd_fb *fb)
 
        fb->panel = netx_panel;
 
-       fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, 1024*1024,
-                                                   &dma, GFP_KERNEL);
+       fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, 1024 * 1024, &dma,
+                                         GFP_KERNEL);
        if (!fb->fb.screen_base) {
                printk(KERN_ERR "CLCD: unable to map framebuffer\n");
                return -ENOMEM;
@@ -57,16 +57,14 @@ int netx_clcd_setup(struct clcd_fb *fb)
 
 int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
 {
-       return dma_mmap_writecombine(&fb->dev->dev, vma,
-                                    fb->fb.screen_base,
-                                    fb->fb.fix.smem_start,
-                                    fb->fb.fix.smem_len);
+       return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
+                          fb->fb.fix.smem_start, fb->fb.fix.smem_len);
 }
 
 void netx_clcd_remove(struct clcd_fb *fb)
 {
-       dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-                             fb->fb.screen_base, fb->fb.fix.smem_start);
+       dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
+                   fb->fb.fix.smem_start);
 }
 
 static AMBA_AHB_DEVICE(fb, "fb", 0, 0x00104000, { NETX_IRQ_LCD }, NULL);
index abea12617b173e2b34f794c4bdf98b8b5d518c48..ea0e5b2ca1cd49e6328faccbb467c1d7b669430f 100644 (file)
@@ -90,8 +90,8 @@ int nspire_clcd_setup(struct clcd_fb *fb)
        panel_size = ((panel->mode.xres * panel->mode.yres) * panel->bpp) / 8;
        panel_size = ALIGN(panel_size, PAGE_SIZE);
 
-       fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
-               panel_size, &dma, GFP_KERNEL);
+       fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, panel_size, &dma,
+                                         GFP_KERNEL);
 
        if (!fb->fb.screen_base) {
                pr_err("CLCD: unable to map framebuffer\n");
@@ -107,13 +107,12 @@ int nspire_clcd_setup(struct clcd_fb *fb)
 
 int nspire_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
 {
-       return dma_mmap_writecombine(&fb->dev->dev, vma,
-               fb->fb.screen_base, fb->fb.fix.smem_start,
-               fb->fb.fix.smem_len);
+       return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
+                          fb->fb.fix.smem_start, fb->fb.fix.smem_len);
 }
 
 void nspire_clcd_remove(struct clcd_fb *fb)
 {
-       dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-               fb->fb.screen_base, fb->fb.fix.smem_start);
+       dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
+                   fb->fb.fix.smem_start);
 }
index 809827265fb39d1b8a7178481bb91e87951c4a14..bab814d2f37dcc9a18229d5e912422a653307088 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <asm/setup.h>
 #include <asm/mach/arch.h>
+#include <asm/system_info.h>
 
 #include "common.h"
 
@@ -77,12 +78,31 @@ static const char *const n900_boards_compat[] __initconst = {
        NULL,
 };
 
+/* Set system_rev from atags */
+static void __init rx51_set_system_rev(const struct tag *tags)
+{
+       const struct tag *tag;
+
+       if (tags->hdr.tag != ATAG_CORE)
+               return;
+
+       for_each_tag(tag, tags) {
+               if (tag->hdr.tag == ATAG_REVISION) {
+                       system_rev = tag->u.revision.rev;
+                       break;
+               }
+       }
+}
+
 /* Legacy userspace on Nokia N900 needs ATAGS exported in /proc/atags,
  * save them while the data is still not overwritten
  */
 static void __init rx51_reserve(void)
 {
-       save_atags((const struct tag *)(PAGE_OFFSET + 0x100));
+       const struct tag *tags = (const struct tag *)(PAGE_OFFSET + 0x100);
+
+       save_atags(tags);
+       rx51_set_system_rev(tags);
        omap_reserve();
 }
 
index 7b76ce01c21dd3aa3b4cad36ce2431f3c8350900..8633c703546a65c2e5b0071ffca0d5a12b664884 100644 (file)
@@ -101,10 +101,8 @@ static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
 
 static void set_onenand_cfg(void __iomem *onenand_base)
 {
-       u32 reg;
+       u32 reg = ONENAND_SYS_CFG1_RDY | ONENAND_SYS_CFG1_INT;
 
-       reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
-       reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
        reg |=  (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
                ONENAND_SYS_CFG1_BL_16;
        if (onenand_flags & ONENAND_FLAG_SYNCREAD)
@@ -123,6 +121,7 @@ static void set_onenand_cfg(void __iomem *onenand_base)
                reg |= ONENAND_SYS_CFG1_VHF;
        else
                reg &= ~ONENAND_SYS_CFG1_VHF;
+
        writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 }
 
@@ -289,6 +288,7 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
                }
        }
 
+       onenand_async.sync_write = true;
        omap2_onenand_calc_async_timings(&t);
 
        ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
index 0437537751bc0c593dbe3554e216727b845f3a78..f7ff3b9dad8784aeab4d3752061514a8498774ae 100644 (file)
@@ -191,12 +191,22 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct omap_device *od;
+       int err;
 
        switch (event) {
        case BUS_NOTIFY_DEL_DEVICE:
                if (pdev->archdata.od)
                        omap_device_delete(pdev->archdata.od);
                break;
+       case BUS_NOTIFY_UNBOUND_DRIVER:
+               od = to_omap_device(pdev);
+               if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED)) {
+                       dev_info(dev, "enabled after unload, idling\n");
+                       err = omap_device_idle(pdev);
+                       if (err)
+                               dev_err(dev, "failed to idle\n");
+               }
+               break;
        case BUS_NOTIFY_ADD_DEVICE:
                if (pdev->dev.of_node)
                        omap_device_build_from_dt(pdev);
@@ -602,8 +612,10 @@ static int _od_runtime_resume(struct device *dev)
        int ret;
 
        ret = omap_device_enable(pdev);
-       if (ret)
+       if (ret) {
+               dev_err(dev, "use pm_runtime_put_sync_suspend() in driver?\n");
                return ret;
+       }
 
        return pm_generic_runtime_resume(dev);
 }
index e9f65fec55c0b9beacfdf694424e601b4673327e..b6d62e4cdfddaf53f8d3aa7c1768b5e83255673e 100644 (file)
@@ -2200,6 +2200,11 @@ static int _enable(struct omap_hwmod *oh)
  */
 static int _idle(struct omap_hwmod *oh)
 {
+       if (oh->flags & HWMOD_NO_IDLE) {
+               oh->_int_flags |= _HWMOD_SKIP_ENABLE;
+               return 0;
+       }
+
        pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
        if (oh->_state != _HWMOD_STATE_ENABLED) {
@@ -2504,6 +2509,8 @@ static int __init _init(struct omap_hwmod *oh, void *data)
                        oh->flags |= HWMOD_INIT_NO_RESET;
                if (of_find_property(np, "ti,no-idle-on-init", NULL))
                        oh->flags |= HWMOD_INIT_NO_IDLE;
+               if (of_find_property(np, "ti,no-idle", NULL))
+                       oh->flags |= HWMOD_NO_IDLE;
        }
 
        oh->_state = _HWMOD_STATE_INITIALIZED;
@@ -2630,7 +2637,7 @@ static void __init _setup_postsetup(struct omap_hwmod *oh)
         * XXX HWMOD_INIT_NO_IDLE does not belong in hwmod data -
         * it should be set by the core code as a runtime flag during startup
         */
-       if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
+       if ((oh->flags & (HWMOD_INIT_NO_IDLE | HWMOD_NO_IDLE)) &&
            (postsetup_state == _HWMOD_STATE_IDLE)) {
                oh->_int_flags |= _HWMOD_SKIP_ENABLE;
                postsetup_state = _HWMOD_STATE_ENABLED;
index 76bce11c85a40c477a5b87aab919d5b8dfded5e8..7c7a31169475b72bc8fbbe2f0dabf015b395f257 100644 (file)
@@ -525,6 +525,8 @@ struct omap_hwmod_omap4_prcm {
  *     or idled.
  * HWMOD_OPT_CLKS_NEEDED: The optional clocks are needed for the module to
  *     operate and they need to be handled at the same time as the main_clk.
+ * HWMOD_NO_IDLE: Do not idle the hwmod at all. Useful to handle certain
+ *     IPs like CPSW on DRA7, where clocks to this module cannot be disabled.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -541,6 +543,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_SWSUP_SIDLE_ACT                  (1 << 12)
 #define HWMOD_RECONFIG_IO_CHAIN                        (1 << 13)
 #define HWMOD_OPT_CLKS_NEEDED                  (1 << 14)
+#define HWMOD_NO_IDLE                          (1 << 15)
 
 /*
  * omap_hwmod._int_flags definitions
index 9cb11215cebaeb2e4e0a8355589ce6d7e5270b78..b3a4ed5289ec7c8c35661a1b6062d4387d13d097 100644 (file)
@@ -4,7 +4,6 @@
 extern void shmobile_init_delay(void);
 extern void shmobile_boot_vector(void);
 extern unsigned long shmobile_boot_fn;
-extern unsigned long shmobile_boot_arg;
 extern unsigned long shmobile_boot_size;
 extern void shmobile_smp_boot(void);
 extern void shmobile_smp_sleep(void);
index fa5248c52399c9b5e78e3c1cd7c167523f306424..5e503d91ad70ddf2b8f375ffaf36a09361c9be8c 100644 (file)
@@ -38,9 +38,3 @@ ENTRY(shmobile_boot_scu)
 
        b       secondary_startup
 ENDPROC(shmobile_boot_scu)
-
-       .text
-       .align  2
-       .globl  shmobile_scu_base
-shmobile_scu_base:
-       .space  4
index 330c1fc63197df89684e03578c1c0693b8e6f24f..32e0bf6e3ccb9bd317c68be65ef7071a0c05eeed 100644 (file)
@@ -24,7 +24,6 @@
        .arm
        .align  12
 ENTRY(shmobile_boot_vector)
-       ldr     r0, 2f
        ldr     r1, 1f
        bx      r1
 
@@ -34,9 +33,6 @@ ENDPROC(shmobile_boot_vector)
        .globl  shmobile_boot_fn
 shmobile_boot_fn:
 1:     .space  4
-       .globl  shmobile_boot_arg
-shmobile_boot_arg:
-2:     .space  4
        .globl  shmobile_boot_size
 shmobile_boot_size:
        .long   . - shmobile_boot_vector
@@ -46,13 +42,15 @@ shmobile_boot_size:
  */
 
 ENTRY(shmobile_smp_boot)
-                                               @ r0 = MPIDR_HWID_BITMASK
        mrc     p15, 0, r1, c0, c0, 5           @ r1 = MPIDR
-       and     r0, r1, r0                      @ r0 = cpu_logical_map() value
+       and     r0, r1, #0xffffff               @ MPIDR_HWID_BITMASK
+                                               @ r0 = cpu_logical_map() value
        mov     r1, #0                          @ r1 = CPU index
-       adr     r5, 1f                          @ array of per-cpu mpidr values
-       adr     r6, 2f                          @ array of per-cpu functions
-       adr     r7, 3f                          @ array of per-cpu arguments
+       adr     r2, 1f
+       ldmia   r2, {r5, r6, r7}
+       add     r5, r5, r2                      @ array of per-cpu mpidr values
+       add     r6, r6, r2                      @ array of per-cpu functions
+       add     r7, r7, r2                      @ array of per-cpu arguments
 
 shmobile_smp_boot_find_mpidr:
        ldr     r8, [r5, r1, lsl #2]
@@ -80,12 +78,18 @@ ENTRY(shmobile_smp_sleep)
        b       shmobile_smp_boot
 ENDPROC(shmobile_smp_sleep)
 
+       .align  2
+1:     .long   shmobile_smp_mpidr - .
+       .long   shmobile_smp_fn - 1b
+       .long   shmobile_smp_arg - 1b
+
+       .bss
        .globl  shmobile_smp_mpidr
 shmobile_smp_mpidr:
-1:     .space  NR_CPUS * 4
+       .space  NR_CPUS * 4
        .globl  shmobile_smp_fn
 shmobile_smp_fn:
-2:     .space  NR_CPUS * 4
+       .space  NR_CPUS * 4
        .globl  shmobile_smp_arg
 shmobile_smp_arg:
-3:     .space  NR_CPUS * 4
+       .space  NR_CPUS * 4
index 911884f7e28b174c271c6724c863520afe859868..aba75c89f9c1c5eb2d7070def50bb8e77118df3c 100644 (file)
@@ -123,7 +123,6 @@ void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
 {
        /* install boot code shared by all CPUs */
        shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
-       shmobile_boot_arg = MPIDR_HWID_BITMASK;
 
        /* perform per-cpu setup */
        apmu_parse_cfg(apmu_init_cpu, apmu_config, num);
index 64663110ab6ca0e1d8f06cc04e69175165e2cace..081a097c9219f41785229c9492b95b250151c1f4 100644 (file)
@@ -17,6 +17,9 @@
 #include <asm/smp_scu.h>
 #include "common.h"
 
+
+void __iomem *shmobile_scu_base;
+
 static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
                                          unsigned long action, void *hcpu)
 {
@@ -41,7 +44,6 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
 {
        /* install boot code shared by all CPUs */
        shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
-       shmobile_boot_arg = MPIDR_HWID_BITMASK;
 
        /* enable SCU and cache coherency on booting CPU */
        scu_enable(shmobile_scu_base);
index b854fe2095ad14616b7c4aae209b47f7e4f7ded3..0b024a9dbd4397e7235827dbdaf62d65a5ad3d16 100644 (file)
@@ -92,8 +92,6 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 {
        /* Map the reset vector (in headsmp-scu.S, headsmp.S) */
        __raw_writel(__pa(shmobile_boot_vector), AVECR);
-       shmobile_boot_fn = virt_to_phys(shmobile_boot_scu);
-       shmobile_boot_arg = (unsigned long)shmobile_scu_base;
 
        /* setup r8a7779 specific SCU bits */
        shmobile_scu_base = IOMEM(R8A7779_SCU_BASE);
index b8f9e238e4abc8974a0337365c5e2270599f8077..ed15db19e561f56964480a13be39b36a0df3eb59 100644 (file)
@@ -5,3 +5,5 @@
 obj-y                                  := socfpga.o
 obj-$(CONFIG_SMP)      += headsmp.o platsmp.o
 obj-$(CONFIG_SOCFPGA_SUSPEND)  += pm.o self-refresh.o
+obj-$(CONFIG_EDAC_ALTERA_L2C)  += l2_cache.o
+obj-$(CONFIG_EDAC_ALTERA_OCRAM)        += ocram.o
index 5bc6ea87cdf74bc7e916c297c1144d585564dfd3..575195be66879978cf53c6396efc640620deba26 100644 (file)
@@ -36,6 +36,8 @@
 
 extern void socfpga_init_clocks(void);
 extern void socfpga_sysmgr_init(void);
+void socfpga_init_l2_ecc(void);
+void socfpga_init_ocram_ecc(void);
 
 extern void __iomem *sys_manager_base_addr;
 extern void __iomem *rst_manager_base_addr;
diff --git a/arch/arm/mach-socfpga/l2_cache.c b/arch/arm/mach-socfpga/l2_cache.c
new file mode 100644 (file)
index 0000000..e3907ab
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright Altera Corporation (C) 2016. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+void socfpga_init_l2_ecc(void)
+{
+       struct device_node *np;
+       void __iomem *mapped_l2_edac_addr;
+
+       np = of_find_compatible_node(NULL, NULL, "altr,socfpga-l2-ecc");
+       if (!np) {
+               pr_err("Unable to find socfpga-l2-ecc in dtb\n");
+               return;
+       }
+
+       mapped_l2_edac_addr = of_iomap(np, 0);
+       of_node_put(np);
+       if (!mapped_l2_edac_addr) {
+               pr_err("Unable to find L2 ECC mapping in dtb\n");
+               return;
+       }
+
+       /* Enable ECC */
+       writel(0x01, mapped_l2_edac_addr);
+       iounmap(mapped_l2_edac_addr);
+}
diff --git a/arch/arm/mach-socfpga/ocram.c b/arch/arm/mach-socfpga/ocram.c
new file mode 100644 (file)
index 0000000..60ec643
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright Altera Corporation (C) 2016. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/io.h>
+#include <linux/genalloc.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#define ALTR_OCRAM_CLEAR_ECC          0x00000018
+#define ALTR_OCRAM_ECC_EN             0x00000019
+
+void socfpga_init_ocram_ecc(void)
+{
+       struct device_node *np;
+       void __iomem *mapped_ocr_edac_addr;
+
+       /* Find the OCRAM EDAC device tree node */
+       np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc");
+       if (!np) {
+               pr_err("Unable to find socfpga-ocram-ecc\n");
+               return;
+       }
+
+       mapped_ocr_edac_addr = of_iomap(np, 0);
+       of_node_put(np);
+       if (!mapped_ocr_edac_addr) {
+               pr_err("Unable to map OCRAM ecc regs.\n");
+               return;
+       }
+
+       /* Clear any pending OCRAM ECC interrupts, then enable ECC */
+       writel(ALTR_OCRAM_CLEAR_ECC, mapped_ocr_edac_addr);
+       writel(ALTR_OCRAM_ECC_EN, mapped_ocr_edac_addr);
+
+       iounmap(mapped_ocr_edac_addr);
+}
index a1c0efaa87944c096c1ab3c92d4adbef71c2e804..7e0aad2ec3d1a65859ce0ebbe4b101d3ed561317 100644 (file)
@@ -59,6 +59,11 @@ static void __init socfpga_init_irq(void)
 {
        irqchip_init();
        socfpga_sysmgr_init();
+       if (IS_ENABLED(CONFIG_EDAC_ALTERA_L2C))
+               socfpga_init_l2_ecc();
+
+       if (IS_ENABLED(CONFIG_EDAC_ALTERA_OCRAM))
+               socfpga_init_ocram_ecc();
 }
 
 static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd)
index 4b4058db0781f63e307d4f5101a74d5330ddf337..66353caa35b9f78fa2aa4754dea3ce813593303f 100644 (file)
@@ -173,7 +173,7 @@ unsigned long arch_mmap_rnd(void)
 {
        unsigned long rnd;
 
-       rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1);
+       rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
 
        return rnd << PAGE_SHIFT;
 }
index cf30daff8932504f95422c2aa3b5882b154713b5..d19b1ad29b075fd8624d34edb0d9c18c9ef11e51 100644 (file)
@@ -49,6 +49,9 @@ static int change_memory_common(unsigned long addr, int numpages,
                WARN_ON_ONCE(1);
        }
 
+       if (!numpages)
+               return 0;
+
        if (start < MODULES_VADDR || start >= MODULES_END)
                return -EINVAL;
 
index 04aff2c31b4607a99265d038d3ba0fd3b9a908b3..70f2f699bed3efe0802def3dc879cdd8e8857a05 100644 (file)
@@ -53,8 +53,8 @@ static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
                if (ptr->child != NULL)
                        s3c_pm_run_res(ptr->child, fn, arg);
 
-               if ((ptr->flags & IORESOURCE_MEM) &&
-                   strcmp(ptr->name, "System RAM") == 0) {
+               if ((ptr->flags & IORESOURCE_SYSTEM_RAM)
+                               == IORESOURCE_SYSTEM_RAM) {
                        S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
                                  (unsigned long)ptr->start,
                                  (unsigned long)ptr->end);
index b2b97e3e7babbbb37072b4185faa27a0e47760c8..a62a7b64f49c52706b8e133b1f786dc9dc34842d 100644 (file)
@@ -23,9 +23,8 @@
 #include <linux/const.h>
 #include <asm/page.h>
 
-       __PAGE_ALIGNED_DATA
-
        .globl vdso_start, vdso_end
+       .section .data..ro_after_init
        .balign PAGE_SIZE
 vdso_start:
        .incbin "arch/arm/vdso/vdso.so"
index 8cc62289a63ed9958c9623acaa5462048cc9287b..b3f2522d266d802221bf22d2f5c56349631cab0c 100644 (file)
@@ -235,8 +235,6 @@ config PCI_SYSCALL
        def_bool PCI
 
 source "drivers/pci/Kconfig"
-source "drivers/pci/pcie/Kconfig"
-source "drivers/pci/hotplug/Kconfig"
 
 endmenu
 
@@ -750,6 +748,19 @@ config ARM64_LSE_ATOMICS
          not support these instructions and requires the kernel to be
          built with binutils >= 2.25.
 
+config ARM64_VHE
+       bool "Enable support for Virtualization Host Extensions (VHE)"
+       default y
+       help
+         Virtualization Host Extensions (VHE) allow the kernel to run
+         directly at EL2 (instead of EL1) on processors that support
+         it. This leads to better performance for KVM, as they reduce
+         the cost of the world switch.
+
+         Selecting this option allows the VHE feature to be detected
+         at runtime, and does not affect processors that do not
+         implement this feature.
+
 endmenu
 
 endmenu
index fe30f7671ea3bc2707fb70a312c70e18bb1c2550..3e40bd469cea13c010c08c6434ae1d0aa9df81af 100644 (file)
                        reg = <0x0 0x1054a000 0x0 0x20>;
                };
 
+               rb: rb@7e000000 {
+                       compatible = "apm,xgene-rb", "syscon";
+                       reg = <0x0 0x7e000000 0x0 0x10>;
+               };
+
                edac@78800000 {
                        compatible = "apm,xgene-edac";
                        #address-cells = <2>;
                        regmap-mcba = <&mcba>;
                        regmap-mcbb = <&mcbb>;
                        regmap-efuse = <&efuse>;
+                       regmap-rb = <&rb>;
                        reg = <0x0 0x78800000 0x0 0x100>;
                        interrupts = <0x0 0x20 0x4>,
                                     <0x0 0x21 0x4>,
index 70fd9ffb58cfc08e82f3a978e6630c70eaeb1840..cff532a6744e937015371c80e5533a0fe660b611 100644 (file)
@@ -1,5 +1,3 @@
-
-
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += checksum.h
@@ -31,7 +29,6 @@ generic-y += msgbuf.h
 generic-y += msi.h
 generic-y += mutex.h
 generic-y += pci.h
-generic-y += pci-bridge.h
 generic-y += poll.h
 generic-y += preempt.h
 generic-y += resource.h
index 7fc294c3bc5baab31b13b1e23753d17835ce3b27..22dda613f9c91bd3bcfe3a8aad435f7384795401 100644 (file)
@@ -156,8 +156,4 @@ int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_x(unsigned long addr, int numpages);
 int set_memory_nx(unsigned long addr, int numpages);
 
-#ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
-#endif
-
 #endif
index 8f271b83f9106c7c9753ce2601d3b59e1ffbdfc5..a5c769b1c65b9dbd0a34f381ee603f447421ba5e 100644 (file)
 #define ARM64_HAS_LSE_ATOMICS                  5
 #define ARM64_WORKAROUND_CAVIUM_23154          6
 #define ARM64_WORKAROUND_834220                        7
+/* #define ARM64_HAS_NO_HW_PREFETCH            8 */
+/* #define ARM64_HAS_UAO                       9 */
+/* #define ARM64_ALT_PAN_NOT_UAO               10 */
+#define ARM64_HAS_VIRT_HOST_EXTN               11
 
-#define ARM64_NCAPS                            8
+#define ARM64_NCAPS                            12
 
 #ifndef __ASSEMBLY__
 
index 9732908bfc8a54b546c4cab40802f70a56b36fce..115ea2a64520776485a750b9c7d8d584a3bddb55 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <asm/cputype.h>
 #include <asm/cpufeature.h>
+#include <asm/virt.h>
 
 #ifdef __KERNEL__
 
@@ -35,10 +36,21 @@ struct arch_hw_breakpoint {
        struct arch_hw_breakpoint_ctrl ctrl;
 };
 
+/* Privilege Levels */
+#define AARCH64_BREAKPOINT_EL1 1
+#define AARCH64_BREAKPOINT_EL0 2
+
+#define DBG_HMC_HYP            (1 << 13)
+
 static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
 {
-       return (ctrl.len << 5) | (ctrl.type << 3) | (ctrl.privilege << 1) |
+       u32 val = (ctrl.len << 5) | (ctrl.type << 3) | (ctrl.privilege << 1) |
                ctrl.enabled;
+
+       if (is_kernel_in_hyp_mode() && ctrl.privilege == AARCH64_BREAKPOINT_EL1)
+               val |= DBG_HMC_HYP;
+
+       return val;
 }
 
 static inline void decode_ctrl_reg(u32 reg,
@@ -61,10 +73,6 @@ static inline void decode_ctrl_reg(u32 reg,
 #define ARM_BREAKPOINT_STORE   2
 #define AARCH64_ESR_ACCESS_MASK        (1 << 6)
 
-/* Privilege Levels */
-#define AARCH64_BREAKPOINT_EL1 1
-#define AARCH64_BREAKPOINT_EL0 2
-
 /* Lengths */
 #define ARM_BREAKPOINT_LEN_1   0x1
 #define ARM_BREAKPOINT_LEN_2   0x3
index d201d4b396d15fee10129494b6d274bbf77a2320..b56a0a81e4cbda9a9245f0d518ceb90035d9c9f2 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/types.h>
 
 /* Hyp Configuration Register (HCR) bits */
+#define HCR_E2H                (UL(1) << 34)
 #define HCR_ID         (UL(1) << 33)
 #define HCR_CD         (UL(1) << 32)
 #define HCR_RW_SHIFT   31
@@ -81,7 +82,7 @@
                         HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
 #define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
 #define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
-
+#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
 /* Hyp System Control Register (SCTLR_EL2) bits */
 #define SCTLR_EL2_EE   (1 << 25)
        ECN(SOFTSTP_CUR), ECN(WATCHPT_LOW), ECN(WATCHPT_CUR), \
        ECN(BKPT32), ECN(VECTOR32), ECN(BRK64)
 
+#define CPACR_EL1_FPEN         (3 << 20)
+#define CPACR_EL1_TTA          (1 << 28)
+
 #endif /* __ARM64_KVM_ARM_H__ */
index 52b777b7d407cfd9c2fe5036c1c7ae96bf025c0b..2d02ba67478c45d205ff397aa1b04dc01f61d44b 100644 (file)
@@ -35,9 +35,6 @@ extern char __kvm_hyp_init_end[];
 
 extern char __kvm_hyp_vector[];
 
-#define        __kvm_hyp_code_start    __hyp_text_start
-#define        __kvm_hyp_code_end      __hyp_text_end
-
 extern void __kvm_flush_vm_context(void);
 extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
@@ -45,9 +42,12 @@ extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
 extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
 
 extern u64 __vgic_v3_get_ich_vtr_el2(void);
+extern void __vgic_v3_init_lrs(void);
 
 extern u32 __kvm_get_mdcr_el2(void);
 
+extern void __init_stage2_translation(void);
+
 #endif
 
 #endif /* __ARM_KVM_ASM_H__ */
index 779a5872a2c5fb5f9aa9b49af6f77391aefc2336..40bc1681b6d56cd2b2cc8fa8a155407ce351d54f 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/kvm_mmio.h>
 #include <asm/ptrace.h>
 #include <asm/cputype.h>
+#include <asm/virt.h>
 
 unsigned long *vcpu_reg32(const struct kvm_vcpu *vcpu, u8 reg_num);
 unsigned long *vcpu_spsr32(const struct kvm_vcpu *vcpu);
@@ -43,6 +44,8 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
 static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
 {
        vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
+       if (is_kernel_in_hyp_mode())
+               vcpu->arch.hcr_el2 |= HCR_E2H;
        if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features))
                vcpu->arch.hcr_el2 &= ~HCR_RW;
 }
@@ -189,6 +192,11 @@ static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
        return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW);
 }
 
+static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu)
+{
+       return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_CM);
+}
+
 static inline int kvm_vcpu_dabt_get_as(const struct kvm_vcpu *vcpu)
 {
        return 1 << ((kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT);
index 689d4c95e12fbd0dd7c1cf7ca9521918f37aaab0..71fa6fe9d54addc45099c3f8fbbf35c1c9e38b71 100644 (file)
@@ -25,7 +25,9 @@
 #include <linux/types.h>
 #include <linux/kvm_types.h>
 #include <asm/kvm.h>
+#include <asm/kvm_asm.h>
 #include <asm/kvm_mmio.h>
+#include <asm/kvm_perf_event.h>
 
 #define __KVM_HAVE_ARCH_INTC_INITIALIZED
 
 
 #include <kvm/arm_vgic.h>
 #include <kvm/arm_arch_timer.h>
+#include <kvm/arm_pmu.h>
 
 #define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
 
-#define KVM_VCPU_MAX_FEATURES 3
+#define KVM_VCPU_MAX_FEATURES 4
 
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
@@ -114,6 +117,21 @@ enum vcpu_sysreg {
        MDSCR_EL1,      /* Monitor Debug System Control Register */
        MDCCINT_EL1,    /* Monitor Debug Comms Channel Interrupt Enable Reg */
 
+       /* Performance Monitors Registers */
+       PMCR_EL0,       /* Control Register */
+       PMSELR_EL0,     /* Event Counter Selection Register */
+       PMEVCNTR0_EL0,  /* Event Counter Register (0-30) */
+       PMEVCNTR30_EL0 = PMEVCNTR0_EL0 + 30,
+       PMCCNTR_EL0,    /* Cycle Counter Register */
+       PMEVTYPER0_EL0, /* Event Type Register (0-30) */
+       PMEVTYPER30_EL0 = PMEVTYPER0_EL0 + 30,
+       PMCCFILTR_EL0,  /* Cycle Count Filter Register */
+       PMCNTENSET_EL0, /* Count Enable Set Register */
+       PMINTENSET_EL1, /* Interrupt Enable Set Register */
+       PMOVSSET_EL0,   /* Overflow Flag Status Set Register */
+       PMSWINC_EL0,    /* Software Increment Register */
+       PMUSERENR_EL0,  /* User Enable Register */
+
        /* 32bit specific registers. Keep them at the end of the range */
        DACR32_EL2,     /* Domain Access Control Register */
        IFSR32_EL2,     /* Instruction Fault Status Register */
@@ -211,6 +229,7 @@ struct kvm_vcpu_arch {
        /* VGIC state */
        struct vgic_cpu vgic_cpu;
        struct arch_timer_cpu timer_cpu;
+       struct kvm_pmu pmu;
 
        /*
         * Anything that is not used directly from assembly code goes
@@ -342,5 +361,18 @@ void kvm_arm_init_debug(void);
 void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
 void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
 void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu);
+int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
+                              struct kvm_device_attr *attr);
+int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
+                              struct kvm_device_attr *attr);
+int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
+                              struct kvm_device_attr *attr);
+
+/* #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__) */
+
+static inline void __cpu_init_stage2(void)
+{
+       kvm_call_hyp(__init_stage2_translation);
+}
 
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
new file mode 100644 (file)
index 0000000..a46b019
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2015 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_KVM_HYP_H__
+#define __ARM64_KVM_HYP_H__
+
+#include <linux/compiler.h>
+#include <linux/kvm_host.h>
+#include <asm/kvm_mmu.h>
+#include <asm/kvm_perf_event.h>
+#include <asm/sysreg.h>
+
+#define __hyp_text __section(.hyp.text) notrace
+
+static inline unsigned long __kern_hyp_va(unsigned long v)
+{
+       asm volatile(ALTERNATIVE("and %0, %0, %1",
+                                "nop",
+                                ARM64_HAS_VIRT_HOST_EXTN)
+                    : "+r" (v) : "i" (HYP_PAGE_OFFSET_MASK));
+       return v;
+}
+
+#define kern_hyp_va(v) (typeof(v))(__kern_hyp_va((unsigned long)(v)))
+
+static inline unsigned long __hyp_kern_va(unsigned long v)
+{
+       u64 offset = PAGE_OFFSET - HYP_PAGE_OFFSET;
+       asm volatile(ALTERNATIVE("add %0, %0, %1",
+                                "nop",
+                                ARM64_HAS_VIRT_HOST_EXTN)
+                    : "+r" (v) : "r" (offset));
+       return v;
+}
+
+#define hyp_kern_va(v) (typeof(v))(__hyp_kern_va((unsigned long)(v)))
+
+#define read_sysreg_elx(r,nvh,vh)                                      \
+       ({                                                              \
+               u64 reg;                                                \
+               asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##nvh),\
+                                        "mrs_s %0, " __stringify(r##vh),\
+                                        ARM64_HAS_VIRT_HOST_EXTN)      \
+                            : "=r" (reg));                             \
+               reg;                                                    \
+       })
+
+#define write_sysreg_elx(v,r,nvh,vh)                                   \
+       do {                                                            \
+               u64 __val = (u64)(v);                                   \
+               asm volatile(ALTERNATIVE("msr " __stringify(r##nvh) ", %x0",\
+                                        "msr_s " __stringify(r##vh) ", %x0",\
+                                        ARM64_HAS_VIRT_HOST_EXTN)      \
+                                        : : "rZ" (__val));             \
+       } while (0)
+
+/*
+ * Unified accessors for registers that have a different encoding
+ * between VHE and non-VHE. They must be specified without their "ELx"
+ * encoding.
+ */
+#define read_sysreg_el2(r)                                             \
+       ({                                                              \
+               u64 reg;                                                \
+               asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##_EL2),\
+                                        "mrs %0, " __stringify(r##_EL1),\
+                                        ARM64_HAS_VIRT_HOST_EXTN)      \
+                            : "=r" (reg));                             \
+               reg;                                                    \
+       })
+
+#define write_sysreg_el2(v,r)                                          \
+       do {                                                            \
+               u64 __val = (u64)(v);                                   \
+               asm volatile(ALTERNATIVE("msr " __stringify(r##_EL2) ", %x0",\
+                                        "msr " __stringify(r##_EL1) ", %x0",\
+                                        ARM64_HAS_VIRT_HOST_EXTN)      \
+                                        : : "rZ" (__val));             \
+       } while (0)
+
+#define read_sysreg_el0(r)     read_sysreg_elx(r, _EL0, _EL02)
+#define write_sysreg_el0(v,r)  write_sysreg_elx(v, r, _EL0, _EL02)
+#define read_sysreg_el1(r)     read_sysreg_elx(r, _EL1, _EL12)
+#define write_sysreg_el1(v,r)  write_sysreg_elx(v, r, _EL1, _EL12)
+
+/* The VHE specific system registers and their encoding */
+#define sctlr_EL12              sys_reg(3, 5, 1, 0, 0)
+#define cpacr_EL12              sys_reg(3, 5, 1, 0, 2)
+#define ttbr0_EL12              sys_reg(3, 5, 2, 0, 0)
+#define ttbr1_EL12              sys_reg(3, 5, 2, 0, 1)
+#define tcr_EL12                sys_reg(3, 5, 2, 0, 2)
+#define afsr0_EL12              sys_reg(3, 5, 5, 1, 0)
+#define afsr1_EL12              sys_reg(3, 5, 5, 1, 1)
+#define esr_EL12                sys_reg(3, 5, 5, 2, 0)
+#define far_EL12                sys_reg(3, 5, 6, 0, 0)
+#define mair_EL12               sys_reg(3, 5, 10, 2, 0)
+#define amair_EL12              sys_reg(3, 5, 10, 3, 0)
+#define vbar_EL12               sys_reg(3, 5, 12, 0, 0)
+#define contextidr_EL12         sys_reg(3, 5, 13, 0, 1)
+#define cntkctl_EL12            sys_reg(3, 5, 14, 1, 0)
+#define cntp_tval_EL02          sys_reg(3, 5, 14, 2, 0)
+#define cntp_ctl_EL02           sys_reg(3, 5, 14, 2, 1)
+#define cntp_cval_EL02          sys_reg(3, 5, 14, 2, 2)
+#define cntv_tval_EL02          sys_reg(3, 5, 14, 3, 0)
+#define cntv_ctl_EL02           sys_reg(3, 5, 14, 3, 1)
+#define cntv_cval_EL02          sys_reg(3, 5, 14, 3, 2)
+#define spsr_EL12               sys_reg(3, 5, 4, 0, 0)
+#define elr_EL12                sys_reg(3, 5, 4, 0, 1)
+
+/**
+ * hyp_alternate_select - Generates patchable code sequences that are
+ * used to switch between two implementations of a function, depending
+ * on the availability of a feature.
+ *
+ * @fname: a symbol name that will be defined as a function returning a
+ * function pointer whose type will match @orig and @alt
+ * @orig: A pointer to the default function, as returned by @fname when
+ * @cond doesn't hold
+ * @alt: A pointer to the alternate function, as returned by @fname
+ * when @cond holds
+ * @cond: a CPU feature (as described in asm/cpufeature.h)
+ */
+#define hyp_alternate_select(fname, orig, alt, cond)                   \
+typeof(orig) * __hyp_text fname(void)                                  \
+{                                                                      \
+       typeof(alt) *val = orig;                                        \
+       asm volatile(ALTERNATIVE("nop           \n",                    \
+                                "mov   %0, %1  \n",                    \
+                                cond)                                  \
+                    : "+r" (val) : "r" (alt));                         \
+       return val;                                                     \
+}
+
+void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
+void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
+
+void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
+void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
+
+void __timer_save_state(struct kvm_vcpu *vcpu);
+void __timer_restore_state(struct kvm_vcpu *vcpu);
+
+void __sysreg_save_host_state(struct kvm_cpu_context *ctxt);
+void __sysreg_restore_host_state(struct kvm_cpu_context *ctxt);
+void __sysreg_save_guest_state(struct kvm_cpu_context *ctxt);
+void __sysreg_restore_guest_state(struct kvm_cpu_context *ctxt);
+void __sysreg32_save_state(struct kvm_vcpu *vcpu);
+void __sysreg32_restore_state(struct kvm_vcpu *vcpu);
+
+void __debug_save_state(struct kvm_vcpu *vcpu,
+                       struct kvm_guest_debug_arch *dbg,
+                       struct kvm_cpu_context *ctxt);
+void __debug_restore_state(struct kvm_vcpu *vcpu,
+                          struct kvm_guest_debug_arch *dbg,
+                          struct kvm_cpu_context *ctxt);
+void __debug_cond_save_host_state(struct kvm_vcpu *vcpu);
+void __debug_cond_restore_host_state(struct kvm_vcpu *vcpu);
+
+void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
+void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
+bool __fpsimd_enabled(void);
+
+u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt);
+void __noreturn __hyp_do_panic(unsigned long, ...);
+
+#endif /* __ARM64_KVM_HYP_H__ */
+
index 736433912a1eb69a0398fa2f01d78cff88533893..9a9318adefa6b47581f4653a27e1faf9025a5d4d 100644 (file)
 #include <asm/cpufeature.h>
 
 /*
- * As we only have the TTBR0_EL2 register, we cannot express
+ * As ARMv8.0 only has the TTBR0_EL2 register, we cannot express
  * "negative" addresses. This makes it impossible to directly share
  * mappings with the kernel.
  *
  * Instead, give the HYP mode its own VA region at a fixed offset from
  * the kernel by just masking the top bits (which are all ones for a
  * kernel address).
+ *
+ * ARMv8.1 (using VHE) does have a TTBR1_EL2, and doesn't use these
+ * macros (the entire kernel runs at EL2).
  */
 #define HYP_PAGE_OFFSET_SHIFT  VA_BITS
 #define HYP_PAGE_OFFSET_MASK   ((UL(1) << HYP_PAGE_OFFSET_SHIFT) - 1)
 
 #ifdef __ASSEMBLY__
 
+#include <asm/alternative.h>
+#include <asm/cpufeature.h>
+
 /*
  * Convert a kernel VA into a HYP VA.
  * reg: VA to be converted.
  */
 .macro kern_hyp_va     reg
+alternative_if_not ARM64_HAS_VIRT_HOST_EXTN    
        and     \reg, \reg, #HYP_PAGE_OFFSET_MASK
+alternative_else
+       nop
+alternative_endif
 .endm
 
 #else
diff --git a/arch/arm64/include/asm/kvm_perf_event.h b/arch/arm64/include/asm/kvm_perf_event.h
new file mode 100644 (file)
index 0000000..c18fdeb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_KVM_PERF_EVENT_H
+#define __ASM_KVM_PERF_EVENT_H
+
+#define        ARMV8_PMU_MAX_COUNTERS  32
+#define        ARMV8_PMU_COUNTER_MASK  (ARMV8_PMU_MAX_COUNTERS - 1)
+
+/*
+ * Per-CPU PMCR: config reg
+ */
+#define ARMV8_PMU_PMCR_E       (1 << 0) /* Enable all counters */
+#define ARMV8_PMU_PMCR_P       (1 << 1) /* Reset all counters */
+#define ARMV8_PMU_PMCR_C       (1 << 2) /* Cycle counter reset */
+#define ARMV8_PMU_PMCR_D       (1 << 3) /* CCNT counts every 64th cpu cycle */
+#define ARMV8_PMU_PMCR_X       (1 << 4) /* Export to ETM */
+#define ARMV8_PMU_PMCR_DP      (1 << 5) /* Disable CCNT if non-invasive debug*/
+/* Determines which bit of PMCCNTR_EL0 generates an overflow */
+#define ARMV8_PMU_PMCR_LC      (1 << 6)
+#define        ARMV8_PMU_PMCR_N_SHIFT  11       /* Number of counters supported */
+#define        ARMV8_PMU_PMCR_N_MASK   0x1f
+#define        ARMV8_PMU_PMCR_MASK     0x7f     /* Mask for writable bits */
+
+/*
+ * PMOVSR: counters overflow flag status reg
+ */
+#define        ARMV8_PMU_OVSR_MASK             0xffffffff      /* Mask for writable bits */
+#define        ARMV8_PMU_OVERFLOWED_MASK       ARMV8_PMU_OVSR_MASK
+
+/*
+ * PMXEVTYPER: Event selection reg
+ */
+#define        ARMV8_PMU_EVTYPE_MASK   0xc80003ff      /* Mask for writable bits */
+#define        ARMV8_PMU_EVTYPE_EVENT  0x3ff           /* Mask for EVENT bits */
+
+#define ARMV8_PMU_EVTYPE_EVENT_SW_INCR 0       /* Software increment event */
+
+/*
+ * Event filters for PMUv3
+ */
+#define        ARMV8_PMU_EXCLUDE_EL1   (1 << 31)
+#define        ARMV8_PMU_EXCLUDE_EL0   (1 << 30)
+#define        ARMV8_PMU_INCLUDE_EL2   (1 << 27)
+
+/*
+ * PMUSERENR: user enable reg
+ */
+#define ARMV8_PMU_USERENR_MASK 0xf             /* Mask for writable bits */
+#define ARMV8_PMU_USERENR_EN   (1 << 0) /* PMU regs can be accessed at EL0 */
+#define ARMV8_PMU_USERENR_SW   (1 << 1) /* PMSWINC can be written at EL0 */
+#define ARMV8_PMU_USERENR_CR   (1 << 2) /* Cycle counter can be read at EL0 */
+#define ARMV8_PMU_USERENR_ER   (1 << 3) /* Event counter can be read at EL0 */
+
+#endif
index b008a72f8bc02733347c782f5b9c286cff16f7a2..b9a7ba9ca44c42aef55bf77f8c0df533b9a0ab3b 100644 (file)
@@ -7,8 +7,6 @@
 #include <linux/dma-mapping.h>
 
 #include <asm/io.h>
-#include <asm-generic/pci-bridge.h>
-#include <asm-generic/pci-dma-compat.h>
 
 #define PCIBIOS_MIN_IO         0x1000
 #define PCIBIOS_MIN_MEM                0
index bf464de33f52f77d2520db0a12e53b3749ced6cc..819aff5d593f701d1101d4cc42dbec8cedbc80aa 100644 (file)
@@ -34,7 +34,7 @@
 /*
  * VMALLOC and SPARSEMEM_VMEMMAP ranges.
  *
- * VMEMAP_SIZE: allows the whole VA space to be covered by a struct page array
+ * VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array
  *     (rounded up to PUD_SIZE).
  * VMALLOC_START: beginning of the kernel VA space
  * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
@@ -51,7 +51,9 @@
 
 #define VMALLOC_END            (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
 
-#define vmemmap                        ((struct page *)(VMALLOC_END + SZ_64K))
+#define VMEMMAP_START          (VMALLOC_END + SZ_64K)
+#define vmemmap                        ((struct page *)VMEMMAP_START - \
+                                SECTION_ALIGN_DOWN(memstart_addr >> PAGE_SHIFT))
 
 #define FIRST_USER_ADDRESS     0UL
 
index 7a5df5252dd736e4038e04e40510351820056183..9f22dd607958ad7cd673e79e91c36e28768c35f7 100644 (file)
@@ -23,6 +23,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/ptrace.h>
+
 /*
  * __boot_cpu_mode records what mode CPUs were booted in.
  * A correctly-implemented bootloader must start all CPUs in the same mode:
@@ -50,6 +52,14 @@ static inline bool is_hyp_mode_mismatched(void)
        return __boot_cpu_mode[0] != __boot_cpu_mode[1];
 }
 
+static inline bool is_kernel_in_hyp_mode(void)
+{
+       u64 el;
+
+       asm("mrs %0, CurrentEL" : "=r" (el));
+       return el == CurrentEL_EL2;
+}
+
 /* The section containing the hypervisor text */
 extern char __hyp_text_start[];
 extern char __hyp_text_end[];
index 2d4ca4bb0dd34a18ed6bfde2d5fa4e4319402903..f209ea151dca8ab8559243dffd8662008844b27c 100644 (file)
@@ -94,6 +94,7 @@ struct kvm_regs {
 #define KVM_ARM_VCPU_POWER_OFF         0 /* CPU is started in OFF state */
 #define KVM_ARM_VCPU_EL1_32BIT         1 /* CPU running a 32bit VM */
 #define KVM_ARM_VCPU_PSCI_0_2          2 /* CPU uses PSCI v0.2 */
+#define KVM_ARM_VCPU_PMU_V3            3 /* Support guest PMUv3 */
 
 struct kvm_vcpu_init {
        __u32 target;
@@ -204,6 +205,11 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CTRL      4
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT   0
 
+/* Device Control API on vcpu fd */
+#define KVM_ARM_VCPU_PMU_V3_CTRL       0
+#define   KVM_ARM_VCPU_PMU_V3_IRQ      0
+#define   KVM_ARM_VCPU_PMU_V3_INIT     1
+
 /* KVM_IRQ_LINE irq field index values */
 #define KVM_ARM_IRQ_TYPE_SHIFT         24
 #define KVM_ARM_IRQ_TYPE_MASK          0xff
index fffa4ac6c25a31a8dc7b2d1865b6c2f459aa64f5..b0ab4e93db0d41e7dafa5110425dbc0471742d78 100644 (file)
@@ -110,9 +110,6 @@ int main(void)
   DEFINE(CPU_USER_PT_REGS,     offsetof(struct kvm_regs, regs));
   DEFINE(CPU_FP_REGS,          offsetof(struct kvm_regs, fp_regs));
   DEFINE(VCPU_FPEXC32_EL2,     offsetof(struct kvm_vcpu, arch.ctxt.sys_regs[FPEXC32_EL2]));
-  DEFINE(VCPU_ESR_EL2,         offsetof(struct kvm_vcpu, arch.fault.esr_el2));
-  DEFINE(VCPU_FAR_EL2,         offsetof(struct kvm_vcpu, arch.fault.far_el2));
-  DEFINE(VCPU_HPFAR_EL2,       offsetof(struct kvm_vcpu, arch.fault.hpfar_el2));
   DEFINE(VCPU_HOST_CONTEXT,    offsetof(struct kvm_vcpu, arch.host_cpu_context));
 #endif
 #ifdef CONFIG_CPU_PM
index 5c90aa490a2bee2368ae45bba2628603afe1c659..ba745199297e3b086d0b28320305f4f8885eb48e 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/cpu_ops.h>
 #include <asm/processor.h>
 #include <asm/sysreg.h>
+#include <asm/virt.h>
 
 unsigned long elf_hwcap __read_mostly;
 EXPORT_SYMBOL_GPL(elf_hwcap);
@@ -621,6 +622,11 @@ static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry)
        return has_sre;
 }
 
+static bool runs_at_el2(const struct arm64_cpu_capabilities *entry)
+{
+       return is_kernel_in_hyp_mode();
+}
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
        {
                .desc = "GIC system register CPU interface",
@@ -651,6 +657,11 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                .min_field_value = 2,
        },
 #endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
+       {
+               .desc = "Virtualization Host Extensions",
+               .capability = ARM64_HAS_VIRT_HOST_EXTN,
+               .matches = runs_at_el2,
+       },
        {},
 };
 
index 917d98108b3f05d9b1013020f9f576a3db776bc6..6f2f37743d3b34994b9d91fb1f99890910accbad 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/cache.h>
 #include <asm/cputype.h>
 #include <asm/kernel-pgtable.h>
+#include <asm/kvm_arm.h>
 #include <asm/memory.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
@@ -464,9 +465,27 @@ CPU_LE(    bic     x0, x0, #(3 << 24)      )       // Clear the EE and E0E bits for EL1
        isb
        ret
 
+2:
+#ifdef CONFIG_ARM64_VHE
+       /*
+        * Check for VHE being present. For the rest of the EL2 setup,
+        * x2 being non-zero indicates that we do have VHE, and that the
+        * kernel is intended to run at EL2.
+        */
+       mrs     x2, id_aa64mmfr1_el1
+       ubfx    x2, x2, #8, #4
+#else
+       mov     x2, xzr
+#endif
+
        /* Hyp configuration. */
-2:     mov     x0, #(1 << 31)                  // 64-bit EL1
+       mov     x0, #HCR_RW                     // 64-bit EL1
+       cbz     x2, set_hcr
+       orr     x0, x0, #HCR_TGE                // Enable Host Extensions
+       orr     x0, x0, #HCR_E2H
+set_hcr:
        msr     hcr_el2, x0
+       isb
 
        /* Generic timers. */
        mrs     x0, cnthctl_el2
@@ -526,6 +545,13 @@ CPU_LE(    movk    x0, #0x30d0, lsl #16    )       // Clear EE and E0E on LE systems
        /* Stage-2 translation */
        msr     vttbr_el2, xzr
 
+       cbz     x2, install_el2_stub
+
+       mov     w20, #BOOT_CPU_MODE_EL2         // This CPU booted in EL2
+       isb
+       ret
+
+install_el2_stub:
        /* Hypervisor stub */
        adrp    x0, __hyp_stub_vectors
        add     x0, x0, #:lo12:__hyp_stub_vectors
index b3d098bd34aa3d2a57c3c9b2b3c7b63a6001be9d..c72de668e1d4d0fa549ef3b9f79d3c696ad40c07 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
-#include <asm/pci-bridge.h>
-
 /*
  * Called after each bus is probed, but before its children are examined
  */
index f7ab14c4d5df2c6cb9d754299292409465602259..1b52269ffa87e00a6a6541ff5b56d573c51e60ef 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include <asm/irq_regs.h>
+#include <asm/virt.h>
 
 #include <linux/of.h>
 #include <linux/perf/arm_pmu.h>
@@ -691,9 +692,12 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event,
 
        if (attr->exclude_idle)
                return -EPERM;
+       if (is_kernel_in_hyp_mode() &&
+           attr->exclude_kernel != attr->exclude_hv)
+               return -EINVAL;
        if (attr->exclude_user)
                config_base |= ARMV8_EXCLUDE_EL0;
-       if (attr->exclude_kernel)
+       if (!is_kernel_in_hyp_mode() && attr->exclude_kernel)
                config_base |= ARMV8_EXCLUDE_EL1;
        if (!attr->exclude_hv)
                config_base |= ARMV8_INCLUDE_EL2;
index 8119479147db147c33800f76aa0d07c6072e8559..450987d99b9b9e497411a79f34781a3cb242df6e 100644 (file)
@@ -73,13 +73,13 @@ static struct resource mem_res[] = {
                .name = "Kernel code",
                .start = 0,
                .end = 0,
-               .flags = IORESOURCE_MEM
+               .flags = IORESOURCE_SYSTEM_RAM
        },
        {
                .name = "Kernel data",
                .start = 0,
                .end = 0,
-               .flags = IORESOURCE_MEM
+               .flags = IORESOURCE_SYSTEM_RAM
        }
 };
 
@@ -210,7 +210,7 @@ static void __init request_standard_resources(void)
                res->name  = "System RAM";
                res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
                res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
-               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
                request_resource(&iomem_resource, res);
 
index e33fe33876ab3804f2c6dcd6c5458e576596ef24..fd10eb6638689c1262c34cca7de533453cb383ae 100644 (file)
@@ -145,6 +145,10 @@ ENTRY(cpu_resume_mmu)
 ENDPROC(cpu_resume_mmu)
        .popsection
 cpu_resume_after_mmu:
+#ifdef CONFIG_KASAN
+       mov     x0, sp
+       bl      kasan_unpoison_remaining_stack
+#endif
        mov     x0, #0                  // return zero on success
        ldp     x19, x20, [sp, #16]
        ldp     x21, x22, [sp, #32]
index b1adc51b2c2e7682212554ba8276b5e7c25fbff5..460765799c642396f8b5d2c202c846b481974ff9 100644 (file)
@@ -195,7 +195,7 @@ asmlinkage void secondary_start_kernel(void)
        /*
         * OK, it's off to the idle thread for us
         */
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index a5272c07d1cbf3f72a0689ecc06e07b3aed4161b..de7450df7629961066d0731b237a0fe64c01708e 100644 (file)
@@ -36,6 +36,7 @@ config KVM
        select HAVE_KVM_EVENTFD
        select HAVE_KVM_IRQFD
        select KVM_ARM_VGIC_V3
+       select KVM_ARM_PMU if HW_PERF_EVENTS
        ---help---
          Support hosting virtualized guest machines.
          We don't support KVM with 16K page tables yet, due to the multiple
@@ -48,6 +49,12 @@ config KVM_ARM_HOST
        ---help---
          Provides host support for ARM processors.
 
+config KVM_ARM_PMU
+       bool
+       ---help---
+         Adds support for a virtual Performance Monitoring Unit (PMU) in
+         virtual machines.
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
index caee9ee8e12af1eef4c13ebd1f750d7a3b5ee7f2..122cff482ac459b44346dc3eeca06739338ad8ef 100644 (file)
@@ -26,3 +26,4 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
+kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
index fcb778899a3804455f2e9ef5f3fad33456d2d96e..32fad75bb9ff5960242596685c317ba4086689e5 100644 (file)
@@ -194,7 +194,7 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
        u64 val;
 
        val = kvm_arm_timer_get_reg(vcpu, reg->id);
-       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
+       return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
 }
 
 /**
@@ -380,3 +380,54 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
        }
        return 0;
 }
+
+int kvm_arm_vcpu_arch_set_attr(struct kvm_vcpu *vcpu,
+                              struct kvm_device_attr *attr)
+{
+       int ret;
+
+       switch (attr->group) {
+       case KVM_ARM_VCPU_PMU_V3_CTRL:
+               ret = kvm_arm_pmu_v3_set_attr(vcpu, attr);
+               break;
+       default:
+               ret = -ENXIO;
+               break;
+       }
+
+       return ret;
+}
+
+int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
+                              struct kvm_device_attr *attr)
+{
+       int ret;
+
+       switch (attr->group) {
+       case KVM_ARM_VCPU_PMU_V3_CTRL:
+               ret = kvm_arm_pmu_v3_get_attr(vcpu, attr);
+               break;
+       default:
+               ret = -ENXIO;
+               break;
+       }
+
+       return ret;
+}
+
+int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
+                              struct kvm_device_attr *attr)
+{
+       int ret;
+
+       switch (attr->group) {
+       case KVM_ARM_VCPU_PMU_V3_CTRL:
+               ret = kvm_arm_pmu_v3_has_attr(vcpu, attr);
+               break;
+       default:
+               ret = -ENXIO;
+               break;
+       }
+
+       return ret;
+}
index d073b5a216f72b1db65fbef79efd942b28df6f6e..7d8747c6427cdf474d1aac9b70c7abe51aece035 100644 (file)
@@ -87,26 +87,13 @@ __do_hyp_init:
 #endif
        /*
         * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS bits in
-        * TCR_EL2 and VTCR_EL2.
+        * TCR_EL2.
         */
        mrs     x5, ID_AA64MMFR0_EL1
        bfi     x4, x5, #16, #3
 
        msr     tcr_el2, x4
 
-       ldr     x4, =VTCR_EL2_FLAGS
-       bfi     x4, x5, #16, #3
-       /*
-        * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS bit in
-        * VTCR_EL2.
-        */
-       mrs     x5, ID_AA64MMFR1_EL1
-       ubfx    x5, x5, #5, #1
-       lsl     x5, x5, #VTCR_EL2_VS
-       orr     x4, x4, x5
-
-       msr     vtcr_el2, x4
-
        mrs     x4, mair_el1
        msr     mair_el2, x4
        isb
index 0ccdcbbef3c20ce0b4afa9874eb128cf55beb683..0689a74e6ba0b493ffc669448e34b34579c9f5ec 100644 (file)
@@ -17,7 +17,9 @@
 
 #include <linux/linkage.h>
 
+#include <asm/alternative.h>
 #include <asm/assembler.h>
+#include <asm/cpufeature.h>
 
 /*
  * u64 kvm_call_hyp(void *hypfn, ...);
  * arch/arm64/kernel/hyp_stub.S.
  */
 ENTRY(kvm_call_hyp)
+alternative_if_not ARM64_HAS_VIRT_HOST_EXTN    
        hvc     #0
        ret
+alternative_else
+       b       __vhe_hyp_call
+       nop
+alternative_endif
 ENDPROC(kvm_call_hyp)
index 826032bc3945ba266142f2a5a0d8367322d71a49..b6a8fc5ad1afaa4b498b2d7172a78f8fcf61b541 100644 (file)
@@ -2,9 +2,12 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
-obj-$(CONFIG_KVM_ARM_HOST) += vgic-v2-sr.o
+KVM=../../../../virt/kvm
+
+obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
+obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o
+
 obj-$(CONFIG_KVM_ARM_HOST) += vgic-v3-sr.o
-obj-$(CONFIG_KVM_ARM_HOST) += timer-sr.o
 obj-$(CONFIG_KVM_ARM_HOST) += sysreg-sr.o
 obj-$(CONFIG_KVM_ARM_HOST) += debug-sr.o
 obj-$(CONFIG_KVM_ARM_HOST) += entry.o
@@ -12,3 +15,4 @@ obj-$(CONFIG_KVM_ARM_HOST) += switch.o
 obj-$(CONFIG_KVM_ARM_HOST) += fpsimd.o
 obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
 obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o
+obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o
index c9c1e97501a90df6449acf51eafdea87f34f92c1..053cf8b057c19d556c8fccacd41374abe0fc449f 100644 (file)
@@ -19,9 +19,7 @@
 #include <linux/kvm_host.h>
 
 #include <asm/kvm_asm.h>
-#include <asm/kvm_mmu.h>
-
-#include "hyp.h"
+#include <asm/kvm_hyp.h>
 
 #define read_debug(r,n)                read_sysreg(r##n##_el1)
 #define write_debug(v,r,n)     write_sysreg(v, r##n##_el1)
index fd0fbe9b7e6a4a26866120135e8db7b872392396..ce9e5e5f28cfb782c15090aea84bb282cd0b56c2 100644 (file)
@@ -130,9 +130,15 @@ ENDPROC(__guest_exit)
 ENTRY(__fpsimd_guest_restore)
        stp     x4, lr, [sp, #-16]!
 
+alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
        mrs     x2, cptr_el2
        bic     x2, x2, #CPTR_EL2_TFP
        msr     cptr_el2, x2
+alternative_else
+       mrs     x2, cpacr_el1
+       orr     x2, x2, #CPACR_EL1_FPEN
+       msr     cpacr_el1, x2
+alternative_endif
        isb
 
        mrs     x3, tpidr_el2
index 93e8d983c0bd0c5fa517f002ff12f00c6b7cabec..3488894397ffa528f951a2337c0f12bd5035c089 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <asm/alternative.h>
 #include <asm/assembler.h>
-#include <asm/asm-offsets.h>
 #include <asm/cpufeature.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_asm.h>
        ldp     x0, x1, [sp], #16
 .endm
 
+.macro do_el2_call
+       /*
+        * Shuffle the parameters before calling the function
+        * pointed to in x0. Assumes parameters in x[1,2,3].
+        */
+       sub     sp, sp, #16
+       str     lr, [sp]
+       mov     lr, x0
+       mov     x0, x1
+       mov     x1, x2
+       mov     x2, x3
+       blr     lr
+       ldr     lr, [sp]
+       add     sp, sp, #16
+.endm
+
+ENTRY(__vhe_hyp_call)
+       do_el2_call
+       /*
+        * We used to rely on having an exception return to get
+        * an implicit isb. In the E2H case, we don't have it anymore.
+        * rather than changing all the leaf functions, just do it here
+        * before returning to the rest of the kernel.
+        */
+       isb
+       ret
+ENDPROC(__vhe_hyp_call)
+       
 el1_sync:                              // Guest trapped into EL2
        save_x0_to_x3
 
+alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
        mrs     x1, esr_el2
+alternative_else
+       mrs     x1, esr_el1
+alternative_endif
        lsr     x2, x1, #ESR_ELx_EC_SHIFT
 
        cmp     x2, #ESR_ELx_EC_HVC64
@@ -58,19 +89,13 @@ el1_sync:                           // Guest trapped into EL2
        mrs     x0, vbar_el2
        b       2f
 
-1:     stp     lr, xzr, [sp, #-16]!
-
+1:
        /*
-        * Compute the function address in EL2, and shuffle the parameters.
+        * Perform the EL2 call
         */
        kern_hyp_va     x0
-       mov     lr, x0
-       mov     x0, x1
-       mov     x1, x2
-       mov     x2, x3
-       blr     lr
+       do_el2_call
 
-       ldp     lr, xzr, [sp], #16
 2:     eret
 
 el1_trap:
@@ -83,72 +108,10 @@ el1_trap:
        cmp     x2, #ESR_ELx_EC_FP_ASIMD
        b.eq    __fpsimd_guest_restore
 
-       cmp     x2, #ESR_ELx_EC_DABT_LOW
-       mov     x0, #ESR_ELx_EC_IABT_LOW
-       ccmp    x2, x0, #4, ne
-       b.ne    1f              // Not an abort we care about
-
-       /* This is an abort. Check for permission fault */
-alternative_if_not ARM64_WORKAROUND_834220
-       and     x2, x1, #ESR_ELx_FSC_TYPE
-       cmp     x2, #FSC_PERM
-       b.ne    1f              // Not a permission fault
-alternative_else
-       nop                     // Use the permission fault path to
-       nop                     // check for a valid S1 translation,
-       nop                     // regardless of the ESR value.
-alternative_endif
-
-       /*
-        * Check for Stage-1 page table walk, which is guaranteed
-        * to give a valid HPFAR_EL2.
-        */
-       tbnz    x1, #7, 1f      // S1PTW is set
-
-       /* Preserve PAR_EL1 */
-       mrs     x3, par_el1
-       stp     x3, xzr, [sp, #-16]!
-
-       /*
-        * Permission fault, HPFAR_EL2 is invalid.
-        * Resolve the IPA the hard way using the guest VA.
-        * Stage-1 translation already validated the memory access rights.
-        * As such, we can use the EL1 translation regime, and don't have
-        * to distinguish between EL0 and EL1 access.
-        */
-       mrs     x2, far_el2
-       at      s1e1r, x2
-       isb
-
-       /* Read result */
-       mrs     x3, par_el1
-       ldp     x0, xzr, [sp], #16      // Restore PAR_EL1 from the stack
-       msr     par_el1, x0
-       tbnz    x3, #0, 3f              // Bail out if we failed the translation
-       ubfx    x3, x3, #12, #36        // Extract IPA
-       lsl     x3, x3, #4              // and present it like HPFAR
-       b       2f
-
-1:     mrs     x3, hpfar_el2
-       mrs     x2, far_el2
-
-2:     mrs     x0, tpidr_el2
-       str     w1, [x0, #VCPU_ESR_EL2]
-       str     x2, [x0, #VCPU_FAR_EL2]
-       str     x3, [x0, #VCPU_HPFAR_EL2]
-
+       mrs     x0, tpidr_el2
        mov     x1, #ARM_EXCEPTION_TRAP
        b       __guest_exit
 
-       /*
-        * Translation failed. Just return to the guest and
-        * let it fault again. Another CPU is probably playing
-        * behind our back.
-        */
-3:     restore_x0_to_x3
-
-       eret
-
 el1_irq:
        save_x0_to_x3
        mrs     x0, tpidr_el2
diff --git a/arch/arm64/kvm/hyp/hyp.h b/arch/arm64/kvm/hyp/hyp.h
deleted file mode 100644 (file)
index fb27517..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2015 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __ARM64_KVM_HYP_H__
-#define __ARM64_KVM_HYP_H__
-
-#include <linux/compiler.h>
-#include <linux/kvm_host.h>
-#include <asm/kvm_mmu.h>
-#include <asm/sysreg.h>
-
-#define __hyp_text __section(.hyp.text) notrace
-
-#define kern_hyp_va(v) (typeof(v))((unsigned long)(v) & HYP_PAGE_OFFSET_MASK)
-#define hyp_kern_va(v) (typeof(v))((unsigned long)(v) - HYP_PAGE_OFFSET \
-                                                     + PAGE_OFFSET)
-
-/**
- * hyp_alternate_select - Generates patchable code sequences that are
- * used to switch between two implementations of a function, depending
- * on the availability of a feature.
- *
- * @fname: a symbol name that will be defined as a function returning a
- * function pointer whose type will match @orig and @alt
- * @orig: A pointer to the default function, as returned by @fname when
- * @cond doesn't hold
- * @alt: A pointer to the alternate function, as returned by @fname
- * when @cond holds
- * @cond: a CPU feature (as described in asm/cpufeature.h)
- */
-#define hyp_alternate_select(fname, orig, alt, cond)                   \
-typeof(orig) * __hyp_text fname(void)                                  \
-{                                                                      \
-       typeof(alt) *val = orig;                                        \
-       asm volatile(ALTERNATIVE("nop           \n",                    \
-                                "mov   %0, %1  \n",                    \
-                                cond)                                  \
-                    : "+r" (val) : "r" (alt));                         \
-       return val;                                                     \
-}
-
-void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
-void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
-
-void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
-void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
-
-void __timer_save_state(struct kvm_vcpu *vcpu);
-void __timer_restore_state(struct kvm_vcpu *vcpu);
-
-void __sysreg_save_state(struct kvm_cpu_context *ctxt);
-void __sysreg_restore_state(struct kvm_cpu_context *ctxt);
-void __sysreg32_save_state(struct kvm_vcpu *vcpu);
-void __sysreg32_restore_state(struct kvm_vcpu *vcpu);
-
-void __debug_save_state(struct kvm_vcpu *vcpu,
-                       struct kvm_guest_debug_arch *dbg,
-                       struct kvm_cpu_context *ctxt);
-void __debug_restore_state(struct kvm_vcpu *vcpu,
-                          struct kvm_guest_debug_arch *dbg,
-                          struct kvm_cpu_context *ctxt);
-void __debug_cond_save_host_state(struct kvm_vcpu *vcpu);
-void __debug_cond_restore_host_state(struct kvm_vcpu *vcpu);
-
-void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
-void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
-static inline bool __fpsimd_enabled(void)
-{
-       return !(read_sysreg(cptr_el2) & CPTR_EL2_TFP);
-}
-
-u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt);
-void __noreturn __hyp_do_panic(unsigned long, ...);
-
-#endif /* __ARM64_KVM_HYP_H__ */
-
diff --git a/arch/arm64/kvm/hyp/s2-setup.c b/arch/arm64/kvm/hyp/s2-setup.c
new file mode 100644 (file)
index 0000000..bfc54fd
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/types.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_hyp.h>
+
+void __hyp_text __init_stage2_translation(void)
+{
+       u64 val = VTCR_EL2_FLAGS;
+       u64 tmp;
+
+       /*
+        * Read the PARange bits from ID_AA64MMFR0_EL1 and set the PS
+        * bits in VTCR_EL2. Amusingly, the PARange is 4 bits, while
+        * PS is only 3. Fortunately, bit 19 is RES0 in VTCR_EL2...
+        */
+       val |= (read_sysreg(id_aa64mmfr0_el1) & 7) << 16;
+
+       /*
+        * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS
+        * bit in VTCR_EL2.
+        */
+       tmp = (read_sysreg(id_aa64mmfr1_el1) >> 4) & 0xf;
+       val |= (tmp == 2) ? VTCR_EL2_VS : 0;
+
+       write_sysreg(val, vtcr_el2);
+}
index f0e7bdfae134a727ec7c0ac76466020fdb65e0fb..437cfad5e3d868f58cf45505fbb393cf1b8fa0cb 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hyp.h"
+#include <linux/types.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_hyp.h>
+
+static bool __hyp_text __fpsimd_enabled_nvhe(void)
+{
+       return !(read_sysreg(cptr_el2) & CPTR_EL2_TFP);
+}
+
+static bool __hyp_text __fpsimd_enabled_vhe(void)
+{
+       return !!(read_sysreg(cpacr_el1) & CPACR_EL1_FPEN);
+}
+
+static hyp_alternate_select(__fpsimd_is_enabled,
+                           __fpsimd_enabled_nvhe, __fpsimd_enabled_vhe,
+                           ARM64_HAS_VIRT_HOST_EXTN);
+
+bool __hyp_text __fpsimd_enabled(void)
+{
+       return __fpsimd_is_enabled()();
+}
+
+static void __hyp_text __activate_traps_vhe(void)
+{
+       u64 val;
+
+       val = read_sysreg(cpacr_el1);
+       val |= CPACR_EL1_TTA;
+       val &= ~CPACR_EL1_FPEN;
+       write_sysreg(val, cpacr_el1);
+
+       write_sysreg(__kvm_hyp_vector, vbar_el1);
+}
+
+static void __hyp_text __activate_traps_nvhe(void)
+{
+       u64 val;
+
+       val = CPTR_EL2_DEFAULT;
+       val |= CPTR_EL2_TTA | CPTR_EL2_TFP;
+       write_sysreg(val, cptr_el2);
+}
+
+static hyp_alternate_select(__activate_traps_arch,
+                           __activate_traps_nvhe, __activate_traps_vhe,
+                           ARM64_HAS_VIRT_HOST_EXTN);
 
 static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
 {
@@ -36,20 +82,37 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
        write_sysreg(val, hcr_el2);
        /* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */
        write_sysreg(1 << 15, hstr_el2);
+       /* Make sure we trap PMU access from EL0 to EL2 */
+       write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
+       write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
+       __activate_traps_arch()();
+}
 
-       val = CPTR_EL2_DEFAULT;
-       val |= CPTR_EL2_TTA | CPTR_EL2_TFP;
-       write_sysreg(val, cptr_el2);
+static void __hyp_text __deactivate_traps_vhe(void)
+{
+       extern char vectors[];  /* kernel exception vectors */
 
-       write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
+       write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
+       write_sysreg(CPACR_EL1_FPEN, cpacr_el1);
+       write_sysreg(vectors, vbar_el1);
 }
 
-static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
+static void __hyp_text __deactivate_traps_nvhe(void)
 {
        write_sysreg(HCR_RW, hcr_el2);
+       write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
+}
+
+static hyp_alternate_select(__deactivate_traps_arch,
+                           __deactivate_traps_nvhe, __deactivate_traps_vhe,
+                           ARM64_HAS_VIRT_HOST_EXTN);
+
+static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
+{
+       __deactivate_traps_arch()();
        write_sysreg(0, hstr_el2);
        write_sysreg(read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK, mdcr_el2);
-       write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
+       write_sysreg(0, pmuserenr_el0);
 }
 
 static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
@@ -89,6 +152,86 @@ static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu)
        __vgic_call_restore_state()(vcpu);
 }
 
+static bool __hyp_text __true_value(void)
+{
+       return true;
+}
+
+static bool __hyp_text __false_value(void)
+{
+       return false;
+}
+
+static hyp_alternate_select(__check_arm_834220,
+                           __false_value, __true_value,
+                           ARM64_WORKAROUND_834220);
+
+static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar)
+{
+       u64 par, tmp;
+
+       /*
+        * Resolve the IPA the hard way using the guest VA.
+        *
+        * Stage-1 translation already validated the memory access
+        * rights. As such, we can use the EL1 translation regime, and
+        * don't have to distinguish between EL0 and EL1 access.
+        *
+        * We do need to save/restore PAR_EL1 though, as we haven't
+        * saved the guest context yet, and we may return early...
+        */
+       par = read_sysreg(par_el1);
+       asm volatile("at s1e1r, %0" : : "r" (far));
+       isb();
+
+       tmp = read_sysreg(par_el1);
+       write_sysreg(par, par_el1);
+
+       if (unlikely(tmp & 1))
+               return false; /* Translation failed, back to guest */
+
+       /* Convert PAR to HPFAR format */
+       *hpfar = ((tmp >> 12) & ((1UL << 36) - 1)) << 4;
+       return true;
+}
+
+static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
+{
+       u64 esr = read_sysreg_el2(esr);
+       u8 ec = esr >> ESR_ELx_EC_SHIFT;
+       u64 hpfar, far;
+
+       vcpu->arch.fault.esr_el2 = esr;
+
+       if (ec != ESR_ELx_EC_DABT_LOW && ec != ESR_ELx_EC_IABT_LOW)
+               return true;
+
+       far = read_sysreg_el2(far);
+
+       /*
+        * The HPFAR can be invalid if the stage 2 fault did not
+        * happen during a stage 1 page table walk (the ESR_EL2.S1PTW
+        * bit is clear) and one of the two following cases are true:
+        *   1. The fault was due to a permission fault
+        *   2. The processor carries errata 834220
+        *
+        * Therefore, for all non S1PTW faults where we either have a
+        * permission fault or the errata workaround is enabled, we
+        * resolve the IPA using the AT instruction.
+        */
+       if (!(esr & ESR_ELx_S1PTW) &&
+           (__check_arm_834220()() || (esr & ESR_ELx_FSC_TYPE) == FSC_PERM)) {
+               if (!__translate_far_to_hpfar(far, &hpfar))
+                       return false;
+       } else {
+               hpfar = read_sysreg(hpfar_el2);
+       }
+
+       vcpu->arch.fault.far_el2 = far;
+       vcpu->arch.fault.hpfar_el2 = hpfar;
+       return true;
+}
+
 static int __hyp_text __guest_run(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpu_context *host_ctxt;
@@ -102,7 +245,7 @@ static int __hyp_text __guest_run(struct kvm_vcpu *vcpu)
        host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
        guest_ctxt = &vcpu->arch.ctxt;
 
-       __sysreg_save_state(host_ctxt);
+       __sysreg_save_host_state(host_ctxt);
        __debug_cond_save_host_state(vcpu);
 
        __activate_traps(vcpu);
@@ -116,16 +259,20 @@ static int __hyp_text __guest_run(struct kvm_vcpu *vcpu)
         * to Cortex-A57 erratum #852523.
         */
        __sysreg32_restore_state(vcpu);
-       __sysreg_restore_state(guest_ctxt);
+       __sysreg_restore_guest_state(guest_ctxt);
        __debug_restore_state(vcpu, kern_hyp_va(vcpu->arch.debug_ptr), guest_ctxt);
 
        /* Jump in the fire! */
+again:
        exit_code = __guest_enter(vcpu, host_ctxt);
        /* And we're baaack! */
 
+       if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
+               goto again;
+
        fp_enabled = __fpsimd_enabled();
 
-       __sysreg_save_state(guest_ctxt);
+       __sysreg_save_guest_state(guest_ctxt);
        __sysreg32_save_state(vcpu);
        __timer_save_state(vcpu);
        __vgic_save_state(vcpu);
@@ -133,7 +280,7 @@ static int __hyp_text __guest_run(struct kvm_vcpu *vcpu)
        __deactivate_traps(vcpu);
        __deactivate_vm(vcpu);
 
-       __sysreg_restore_state(host_ctxt);
+       __sysreg_restore_host_state(host_ctxt);
 
        if (fp_enabled) {
                __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs);
@@ -150,11 +297,34 @@ __alias(__guest_run) int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
 
 static const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n";
 
-void __hyp_text __noreturn __hyp_panic(void)
+static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par)
 {
        unsigned long str_va = (unsigned long)__hyp_panic_string;
-       u64 spsr = read_sysreg(spsr_el2);
-       u64 elr = read_sysreg(elr_el2);
+
+       __hyp_do_panic(hyp_kern_va(str_va),
+                      spsr,  elr,
+                      read_sysreg(esr_el2),   read_sysreg_el2(far),
+                      read_sysreg(hpfar_el2), par,
+                      (void *)read_sysreg(tpidr_el2));
+}
+
+static void __hyp_text __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par)
+{
+       panic(__hyp_panic_string,
+             spsr,  elr,
+             read_sysreg_el2(esr),   read_sysreg_el2(far),
+             read_sysreg(hpfar_el2), par,
+             (void *)read_sysreg(tpidr_el2));
+}
+
+static hyp_alternate_select(__hyp_call_panic,
+                           __hyp_call_panic_nvhe, __hyp_call_panic_vhe,
+                           ARM64_HAS_VIRT_HOST_EXTN);
+
+void __hyp_text __noreturn __hyp_panic(void)
+{
+       u64 spsr = read_sysreg_el2(spsr);
+       u64 elr = read_sysreg_el2(elr);
        u64 par = read_sysreg(par_el1);
 
        if (read_sysreg(vttbr_el2)) {
@@ -165,15 +335,11 @@ void __hyp_text __noreturn __hyp_panic(void)
                host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
                __deactivate_traps(vcpu);
                __deactivate_vm(vcpu);
-               __sysreg_restore_state(host_ctxt);
+               __sysreg_restore_host_state(host_ctxt);
        }
 
        /* Call panic for real */
-       __hyp_do_panic(hyp_kern_va(str_va),
-                      spsr,  elr,
-                      read_sysreg(esr_el2),   read_sysreg(far_el2),
-                      read_sysreg(hpfar_el2), par,
-                      (void *)read_sysreg(tpidr_el2));
+       __hyp_call_panic()(spsr, elr, par);
 
        unreachable();
 }
index 425630980229f7c26d05190abb9866d02c1af13a..0f7c40eb3f53f9014ad43f16963cf426611bdeb7 100644 (file)
 #include <linux/kvm_host.h>
 
 #include <asm/kvm_asm.h>
-#include <asm/kvm_mmu.h>
+#include <asm/kvm_hyp.h>
 
-#include "hyp.h"
+/* Yes, this does nothing, on purpose */
+static void __hyp_text __sysreg_do_nothing(struct kvm_cpu_context *ctxt) { }
 
-/* ctxt is already in the HYP VA space */
-void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
+/*
+ * Non-VHE: Both host and guest must save everything.
+ *
+ * VHE: Host must save tpidr*_el[01], actlr_el1, sp0, pc, pstate, and
+ * guest must save everything.
+ */
+
+static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
 {
-       ctxt->sys_regs[MPIDR_EL1]       = read_sysreg(vmpidr_el2);
-       ctxt->sys_regs[CSSELR_EL1]      = read_sysreg(csselr_el1);
-       ctxt->sys_regs[SCTLR_EL1]       = read_sysreg(sctlr_el1);
        ctxt->sys_regs[ACTLR_EL1]       = read_sysreg(actlr_el1);
-       ctxt->sys_regs[CPACR_EL1]       = read_sysreg(cpacr_el1);
-       ctxt->sys_regs[TTBR0_EL1]       = read_sysreg(ttbr0_el1);
-       ctxt->sys_regs[TTBR1_EL1]       = read_sysreg(ttbr1_el1);
-       ctxt->sys_regs[TCR_EL1]         = read_sysreg(tcr_el1);
-       ctxt->sys_regs[ESR_EL1]         = read_sysreg(esr_el1);
-       ctxt->sys_regs[AFSR0_EL1]       = read_sysreg(afsr0_el1);
-       ctxt->sys_regs[AFSR1_EL1]       = read_sysreg(afsr1_el1);
-       ctxt->sys_regs[FAR_EL1]         = read_sysreg(far_el1);
-       ctxt->sys_regs[MAIR_EL1]        = read_sysreg(mair_el1);
-       ctxt->sys_regs[VBAR_EL1]        = read_sysreg(vbar_el1);
-       ctxt->sys_regs[CONTEXTIDR_EL1]  = read_sysreg(contextidr_el1);
        ctxt->sys_regs[TPIDR_EL0]       = read_sysreg(tpidr_el0);
        ctxt->sys_regs[TPIDRRO_EL0]     = read_sysreg(tpidrro_el0);
        ctxt->sys_regs[TPIDR_EL1]       = read_sysreg(tpidr_el1);
-       ctxt->sys_regs[AMAIR_EL1]       = read_sysreg(amair_el1);
-       ctxt->sys_regs[CNTKCTL_EL1]     = read_sysreg(cntkctl_el1);
+       ctxt->gp_regs.regs.sp           = read_sysreg(sp_el0);
+       ctxt->gp_regs.regs.pc           = read_sysreg_el2(elr);
+       ctxt->gp_regs.regs.pstate       = read_sysreg_el2(spsr);
+}
+
+static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
+{
+       ctxt->sys_regs[MPIDR_EL1]       = read_sysreg(vmpidr_el2);
+       ctxt->sys_regs[CSSELR_EL1]      = read_sysreg(csselr_el1);
+       ctxt->sys_regs[SCTLR_EL1]       = read_sysreg_el1(sctlr);
+       ctxt->sys_regs[CPACR_EL1]       = read_sysreg_el1(cpacr);
+       ctxt->sys_regs[TTBR0_EL1]       = read_sysreg_el1(ttbr0);
+       ctxt->sys_regs[TTBR1_EL1]       = read_sysreg_el1(ttbr1);
+       ctxt->sys_regs[TCR_EL1]         = read_sysreg_el1(tcr);
+       ctxt->sys_regs[ESR_EL1]         = read_sysreg_el1(esr);
+       ctxt->sys_regs[AFSR0_EL1]       = read_sysreg_el1(afsr0);
+       ctxt->sys_regs[AFSR1_EL1]       = read_sysreg_el1(afsr1);
+       ctxt->sys_regs[FAR_EL1]         = read_sysreg_el1(far);
+       ctxt->sys_regs[MAIR_EL1]        = read_sysreg_el1(mair);
+       ctxt->sys_regs[VBAR_EL1]        = read_sysreg_el1(vbar);
+       ctxt->sys_regs[CONTEXTIDR_EL1]  = read_sysreg_el1(contextidr);
+       ctxt->sys_regs[AMAIR_EL1]       = read_sysreg_el1(amair);
+       ctxt->sys_regs[CNTKCTL_EL1]     = read_sysreg_el1(cntkctl);
        ctxt->sys_regs[PAR_EL1]         = read_sysreg(par_el1);
        ctxt->sys_regs[MDSCR_EL1]       = read_sysreg(mdscr_el1);
 
-       ctxt->gp_regs.regs.sp           = read_sysreg(sp_el0);
-       ctxt->gp_regs.regs.pc           = read_sysreg(elr_el2);
-       ctxt->gp_regs.regs.pstate       = read_sysreg(spsr_el2);
        ctxt->gp_regs.sp_el1            = read_sysreg(sp_el1);
-       ctxt->gp_regs.elr_el1           = read_sysreg(elr_el1);
-       ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg(spsr_el1);
+       ctxt->gp_regs.elr_el1           = read_sysreg_el1(elr);
+       ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg_el1(spsr);
+}
+
+static hyp_alternate_select(__sysreg_call_save_host_state,
+                           __sysreg_save_state, __sysreg_do_nothing,
+                           ARM64_HAS_VIRT_HOST_EXTN);
+
+void __hyp_text __sysreg_save_host_state(struct kvm_cpu_context *ctxt)
+{
+       __sysreg_call_save_host_state()(ctxt);
+       __sysreg_save_common_state(ctxt);
+}
+
+void __hyp_text __sysreg_save_guest_state(struct kvm_cpu_context *ctxt)
+{
+       __sysreg_save_state(ctxt);
+       __sysreg_save_common_state(ctxt);
 }
 
-void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
+static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
 {
-       write_sysreg(ctxt->sys_regs[MPIDR_EL1],   vmpidr_el2);
-       write_sysreg(ctxt->sys_regs[CSSELR_EL1],  csselr_el1);
-       write_sysreg(ctxt->sys_regs[SCTLR_EL1],   sctlr_el1);
        write_sysreg(ctxt->sys_regs[ACTLR_EL1],   actlr_el1);
-       write_sysreg(ctxt->sys_regs[CPACR_EL1],   cpacr_el1);
-       write_sysreg(ctxt->sys_regs[TTBR0_EL1],   ttbr0_el1);
-       write_sysreg(ctxt->sys_regs[TTBR1_EL1],   ttbr1_el1);
-       write_sysreg(ctxt->sys_regs[TCR_EL1],     tcr_el1);
-       write_sysreg(ctxt->sys_regs[ESR_EL1],     esr_el1);
-       write_sysreg(ctxt->sys_regs[AFSR0_EL1],   afsr0_el1);
-       write_sysreg(ctxt->sys_regs[AFSR1_EL1],   afsr1_el1);
-       write_sysreg(ctxt->sys_regs[FAR_EL1],     far_el1);
-       write_sysreg(ctxt->sys_regs[MAIR_EL1],    mair_el1);
-       write_sysreg(ctxt->sys_regs[VBAR_EL1],    vbar_el1);
-       write_sysreg(ctxt->sys_regs[CONTEXTIDR_EL1], contextidr_el1);
        write_sysreg(ctxt->sys_regs[TPIDR_EL0],   tpidr_el0);
        write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0);
        write_sysreg(ctxt->sys_regs[TPIDR_EL1],   tpidr_el1);
-       write_sysreg(ctxt->sys_regs[AMAIR_EL1],   amair_el1);
-       write_sysreg(ctxt->sys_regs[CNTKCTL_EL1], cntkctl_el1);
-       write_sysreg(ctxt->sys_regs[PAR_EL1],     par_el1);
-       write_sysreg(ctxt->sys_regs[MDSCR_EL1],   mdscr_el1);
-
-       write_sysreg(ctxt->gp_regs.regs.sp,     sp_el0);
-       write_sysreg(ctxt->gp_regs.regs.pc,     elr_el2);
-       write_sysreg(ctxt->gp_regs.regs.pstate, spsr_el2);
-       write_sysreg(ctxt->gp_regs.sp_el1,      sp_el1);
-       write_sysreg(ctxt->gp_regs.elr_el1,     elr_el1);
-       write_sysreg(ctxt->gp_regs.spsr[KVM_SPSR_EL1], spsr_el1);
+       write_sysreg(ctxt->gp_regs.regs.sp,       sp_el0);
+       write_sysreg_el2(ctxt->gp_regs.regs.pc,   elr);
+       write_sysreg_el2(ctxt->gp_regs.regs.pstate, spsr);
+}
+
+static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
+{
+       write_sysreg(ctxt->sys_regs[MPIDR_EL1],         vmpidr_el2);
+       write_sysreg(ctxt->sys_regs[CSSELR_EL1],        csselr_el1);
+       write_sysreg_el1(ctxt->sys_regs[SCTLR_EL1],     sctlr);
+       write_sysreg_el1(ctxt->sys_regs[CPACR_EL1],     cpacr);
+       write_sysreg_el1(ctxt->sys_regs[TTBR0_EL1],     ttbr0);
+       write_sysreg_el1(ctxt->sys_regs[TTBR1_EL1],     ttbr1);
+       write_sysreg_el1(ctxt->sys_regs[TCR_EL1],       tcr);
+       write_sysreg_el1(ctxt->sys_regs[ESR_EL1],       esr);
+       write_sysreg_el1(ctxt->sys_regs[AFSR0_EL1],     afsr0);
+       write_sysreg_el1(ctxt->sys_regs[AFSR1_EL1],     afsr1);
+       write_sysreg_el1(ctxt->sys_regs[FAR_EL1],       far);
+       write_sysreg_el1(ctxt->sys_regs[MAIR_EL1],      mair);
+       write_sysreg_el1(ctxt->sys_regs[VBAR_EL1],      vbar);
+       write_sysreg_el1(ctxt->sys_regs[CONTEXTIDR_EL1],contextidr);
+       write_sysreg_el1(ctxt->sys_regs[AMAIR_EL1],     amair);
+       write_sysreg_el1(ctxt->sys_regs[CNTKCTL_EL1],   cntkctl);
+       write_sysreg(ctxt->sys_regs[PAR_EL1],           par_el1);
+       write_sysreg(ctxt->sys_regs[MDSCR_EL1],         mdscr_el1);
+
+       write_sysreg(ctxt->gp_regs.sp_el1,              sp_el1);
+       write_sysreg_el1(ctxt->gp_regs.elr_el1,         elr);
+       write_sysreg_el1(ctxt->gp_regs.spsr[KVM_SPSR_EL1],spsr);
+}
+
+static hyp_alternate_select(__sysreg_call_restore_host_state,
+                           __sysreg_restore_state, __sysreg_do_nothing,
+                           ARM64_HAS_VIRT_HOST_EXTN);
+
+void __hyp_text __sysreg_restore_host_state(struct kvm_cpu_context *ctxt)
+{
+       __sysreg_call_restore_host_state()(ctxt);
+       __sysreg_restore_common_state(ctxt);
+}
+
+void __hyp_text __sysreg_restore_guest_state(struct kvm_cpu_context *ctxt)
+{
+       __sysreg_restore_state(ctxt);
+       __sysreg_restore_common_state(ctxt);
 }
 
 void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/hyp/timer-sr.c b/arch/arm64/kvm/hyp/timer-sr.c
deleted file mode 100644 (file)
index 1051e5d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012-2015 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <clocksource/arm_arch_timer.h>
-#include <linux/compiler.h>
-#include <linux/kvm_host.h>
-
-#include <asm/kvm_mmu.h>
-
-#include "hyp.h"
-
-/* vcpu is already in the HYP VA space */
-void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
-{
-       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       u64 val;
-
-       if (kvm->arch.timer.enabled) {
-               timer->cntv_ctl = read_sysreg(cntv_ctl_el0);
-               timer->cntv_cval = read_sysreg(cntv_cval_el0);
-       }
-
-       /* Disable the virtual timer */
-       write_sysreg(0, cntv_ctl_el0);
-
-       /* Allow physical timer/counter access for the host */
-       val = read_sysreg(cnthctl_el2);
-       val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
-       write_sysreg(val, cnthctl_el2);
-
-       /* Clear cntvoff for the host */
-       write_sysreg(0, cntvoff_el2);
-}
-
-void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
-{
-       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
-       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
-       u64 val;
-
-       /*
-        * Disallow physical timer access for the guest
-        * Physical counter access is allowed
-        */
-       val = read_sysreg(cnthctl_el2);
-       val &= ~CNTHCTL_EL1PCEN;
-       val |= CNTHCTL_EL1PCTEN;
-       write_sysreg(val, cnthctl_el2);
-
-       if (kvm->arch.timer.enabled) {
-               write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
-               write_sysreg(timer->cntv_cval, cntv_cval_el0);
-               isb();
-               write_sysreg(timer->cntv_ctl, cntv_ctl_el0);
-       }
-}
index 2a7e0d838698d2dff2822bad23865932ce72e3aa..be8177cdd3bf8ef3d2d03a580e494080c88f4029 100644 (file)
@@ -15,7 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "hyp.h"
+#include <asm/kvm_hyp.h>
 
 static void __hyp_text __tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 {
diff --git a/arch/arm64/kvm/hyp/vgic-v2-sr.c b/arch/arm64/kvm/hyp/vgic-v2-sr.c
deleted file mode 100644 (file)
index e717612..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2012-2015 - ARM Ltd
- * Author: Marc Zyngier <marc.zyngier@arm.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/compiler.h>
-#include <linux/irqchip/arm-gic.h>
-#include <linux/kvm_host.h>
-
-#include <asm/kvm_mmu.h>
-
-#include "hyp.h"
-
-/* vcpu is already in the HYP VA space */
-void __hyp_text __vgic_v2_save_state(struct kvm_vcpu *vcpu)
-{
-       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
-       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-       struct vgic_dist *vgic = &kvm->arch.vgic;
-       void __iomem *base = kern_hyp_va(vgic->vctrl_base);
-       u32 eisr0, eisr1, elrsr0, elrsr1;
-       int i, nr_lr;
-
-       if (!base)
-               return;
-
-       nr_lr = vcpu->arch.vgic_cpu.nr_lr;
-       cpu_if->vgic_vmcr = readl_relaxed(base + GICH_VMCR);
-       cpu_if->vgic_misr = readl_relaxed(base + GICH_MISR);
-       eisr0  = readl_relaxed(base + GICH_EISR0);
-       elrsr0 = readl_relaxed(base + GICH_ELRSR0);
-       if (unlikely(nr_lr > 32)) {
-               eisr1  = readl_relaxed(base + GICH_EISR1);
-               elrsr1 = readl_relaxed(base + GICH_ELRSR1);
-       } else {
-               eisr1 = elrsr1 = 0;
-       }
-#ifdef CONFIG_CPU_BIG_ENDIAN
-       cpu_if->vgic_eisr  = ((u64)eisr0 << 32) | eisr1;
-       cpu_if->vgic_elrsr = ((u64)elrsr0 << 32) | elrsr1;
-#else
-       cpu_if->vgic_eisr  = ((u64)eisr1 << 32) | eisr0;
-       cpu_if->vgic_elrsr = ((u64)elrsr1 << 32) | elrsr0;
-#endif
-       cpu_if->vgic_apr    = readl_relaxed(base + GICH_APR);
-
-       writel_relaxed(0, base + GICH_HCR);
-
-       for (i = 0; i < nr_lr; i++)
-               cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
-}
-
-/* vcpu is already in the HYP VA space */
-void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
-{
-       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
-       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
-       struct vgic_dist *vgic = &kvm->arch.vgic;
-       void __iomem *base = kern_hyp_va(vgic->vctrl_base);
-       int i, nr_lr;
-
-       if (!base)
-               return;
-
-       writel_relaxed(cpu_if->vgic_hcr, base + GICH_HCR);
-       writel_relaxed(cpu_if->vgic_vmcr, base + GICH_VMCR);
-       writel_relaxed(cpu_if->vgic_apr, base + GICH_APR);
-
-       nr_lr = vcpu->arch.vgic_cpu.nr_lr;
-       for (i = 0; i < nr_lr; i++)
-               writel_relaxed(cpu_if->vgic_lr[i], base + GICH_LR0 + (i * 4));
-}
index 9142e082f5f3996df9428670f2e107cfc948d2e3..fff7cd42b3a381734d00a4043ccfd626732dfd9c 100644 (file)
@@ -19,9 +19,7 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm_host.h>
 
-#include <asm/kvm_mmu.h>
-
-#include "hyp.h"
+#include <asm/kvm_hyp.h>
 
 #define vtr_to_max_lr_idx(v)           ((v) & 0xf)
 #define vtr_to_nr_pri_bits(v)          (((u32)(v) >> 29) + 1)
                asm volatile("msr_s " __stringify(r) ", %0" : : "r" (__val));\
        } while (0)
 
-/* vcpu is already in the HYP VA space */
+static u64 __hyp_text __gic_v3_get_lr(unsigned int lr)
+{
+       switch (lr & 0xf) {
+       case 0:
+               return read_gicreg(ICH_LR0_EL2);
+       case 1:
+               return read_gicreg(ICH_LR1_EL2);
+       case 2:
+               return read_gicreg(ICH_LR2_EL2);
+       case 3:
+               return read_gicreg(ICH_LR3_EL2);
+       case 4:
+               return read_gicreg(ICH_LR4_EL2);
+       case 5:
+               return read_gicreg(ICH_LR5_EL2);
+       case 6:
+               return read_gicreg(ICH_LR6_EL2);
+       case 7:
+               return read_gicreg(ICH_LR7_EL2);
+       case 8:
+               return read_gicreg(ICH_LR8_EL2);
+       case 9:
+               return read_gicreg(ICH_LR9_EL2);
+       case 10:
+               return read_gicreg(ICH_LR10_EL2);
+       case 11:
+               return read_gicreg(ICH_LR11_EL2);
+       case 12:
+               return read_gicreg(ICH_LR12_EL2);
+       case 13:
+               return read_gicreg(ICH_LR13_EL2);
+       case 14:
+               return read_gicreg(ICH_LR14_EL2);
+       case 15:
+               return read_gicreg(ICH_LR15_EL2);
+       }
+
+       unreachable();
+}
+
+static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
+{
+       switch (lr & 0xf) {
+       case 0:
+               write_gicreg(val, ICH_LR0_EL2);
+               break;
+       case 1:
+               write_gicreg(val, ICH_LR1_EL2);
+               break;
+       case 2:
+               write_gicreg(val, ICH_LR2_EL2);
+               break;
+       case 3:
+               write_gicreg(val, ICH_LR3_EL2);
+               break;
+       case 4:
+               write_gicreg(val, ICH_LR4_EL2);
+               break;
+       case 5:
+               write_gicreg(val, ICH_LR5_EL2);
+               break;
+       case 6:
+               write_gicreg(val, ICH_LR6_EL2);
+               break;
+       case 7:
+               write_gicreg(val, ICH_LR7_EL2);
+               break;
+       case 8:
+               write_gicreg(val, ICH_LR8_EL2);
+               break;
+       case 9:
+               write_gicreg(val, ICH_LR9_EL2);
+               break;
+       case 10:
+               write_gicreg(val, ICH_LR10_EL2);
+               break;
+       case 11:
+               write_gicreg(val, ICH_LR11_EL2);
+               break;
+       case 12:
+               write_gicreg(val, ICH_LR12_EL2);
+               break;
+       case 13:
+               write_gicreg(val, ICH_LR13_EL2);
+               break;
+       case 14:
+               write_gicreg(val, ICH_LR14_EL2);
+               break;
+       case 15:
+               write_gicreg(val, ICH_LR15_EL2);
+               break;
+       }
+}
+
+static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu, int nr_lr)
+{
+       struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
+       int i;
+       bool expect_mi;
+
+       expect_mi = !!(cpu_if->vgic_hcr & ICH_HCR_UIE);
+
+       for (i = 0; i < nr_lr; i++) {
+               if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
+                               continue;
+
+               expect_mi |= (!(cpu_if->vgic_lr[i] & ICH_LR_HW) &&
+                             (cpu_if->vgic_lr[i] & ICH_LR_EOI));
+       }
+
+       if (expect_mi) {
+               cpu_if->vgic_misr  = read_gicreg(ICH_MISR_EL2);
+
+               if (cpu_if->vgic_misr & ICH_MISR_EOI)
+                       cpu_if->vgic_eisr = read_gicreg(ICH_EISR_EL2);
+               else
+                       cpu_if->vgic_eisr = 0;
+       } else {
+               cpu_if->vgic_misr = 0;
+               cpu_if->vgic_eisr = 0;
+       }
+}
+
 void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
        u64 val;
-       u32 max_lr_idx, nr_pri_bits;
 
        /*
         * Make sure stores to the GIC via the memory mapped interface
@@ -53,68 +172,66 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
        dsb(st);
 
        cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
-       cpu_if->vgic_misr  = read_gicreg(ICH_MISR_EL2);
-       cpu_if->vgic_eisr  = read_gicreg(ICH_EISR_EL2);
-       cpu_if->vgic_elrsr = read_gicreg(ICH_ELSR_EL2);
 
-       write_gicreg(0, ICH_HCR_EL2);
-       val = read_gicreg(ICH_VTR_EL2);
-       max_lr_idx = vtr_to_max_lr_idx(val);
-       nr_pri_bits = vtr_to_nr_pri_bits(val);
+       if (vcpu->arch.vgic_cpu.live_lrs) {
+               int i;
+               u32 max_lr_idx, nr_pri_bits;
 
-       switch (max_lr_idx) {
-       case 15:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(15)] = read_gicreg(ICH_LR15_EL2);
-       case 14:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(14)] = read_gicreg(ICH_LR14_EL2);
-       case 13:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(13)] = read_gicreg(ICH_LR13_EL2);
-       case 12:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(12)] = read_gicreg(ICH_LR12_EL2);
-       case 11:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(11)] = read_gicreg(ICH_LR11_EL2);
-       case 10:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(10)] = read_gicreg(ICH_LR10_EL2);
-       case 9:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(9)] = read_gicreg(ICH_LR9_EL2);
-       case 8:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(8)] = read_gicreg(ICH_LR8_EL2);
-       case 7:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(7)] = read_gicreg(ICH_LR7_EL2);
-       case 6:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(6)] = read_gicreg(ICH_LR6_EL2);
-       case 5:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(5)] = read_gicreg(ICH_LR5_EL2);
-       case 4:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(4)] = read_gicreg(ICH_LR4_EL2);
-       case 3:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(3)] = read_gicreg(ICH_LR3_EL2);
-       case 2:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(2)] = read_gicreg(ICH_LR2_EL2);
-       case 1:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(1)] = read_gicreg(ICH_LR1_EL2);
-       case 0:
-               cpu_if->vgic_lr[VGIC_V3_LR_INDEX(0)] = read_gicreg(ICH_LR0_EL2);
-       }
+               cpu_if->vgic_elrsr = read_gicreg(ICH_ELSR_EL2);
 
-       switch (nr_pri_bits) {
-       case 7:
-               cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
-               cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
-       case 6:
-               cpu_if->vgic_ap0r[1] = read_gicreg(ICH_AP0R1_EL2);
-       default:
-               cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
-       }
+               write_gicreg(0, ICH_HCR_EL2);
+               val = read_gicreg(ICH_VTR_EL2);
+               max_lr_idx = vtr_to_max_lr_idx(val);
+               nr_pri_bits = vtr_to_nr_pri_bits(val);
 
-       switch (nr_pri_bits) {
-       case 7:
-               cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
-               cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
-       case 6:
-               cpu_if->vgic_ap1r[1] = read_gicreg(ICH_AP1R1_EL2);
-       default:
-               cpu_if->vgic_ap1r[0] = read_gicreg(ICH_AP1R0_EL2);
+               save_maint_int_state(vcpu, max_lr_idx + 1);
+
+               for (i = 0; i <= max_lr_idx; i++) {
+                       if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
+                               continue;
+
+                       if (cpu_if->vgic_elrsr & (1 << i)) {
+                               cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
+                               continue;
+                       }
+
+                       cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
+                       __gic_v3_set_lr(0, i);
+               }
+
+               switch (nr_pri_bits) {
+               case 7:
+                       cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
+                       cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
+               case 6:
+                       cpu_if->vgic_ap0r[1] = read_gicreg(ICH_AP0R1_EL2);
+               default:
+                       cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
+               }
+
+               switch (nr_pri_bits) {
+               case 7:
+                       cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
+                       cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
+               case 6:
+                       cpu_if->vgic_ap1r[1] = read_gicreg(ICH_AP1R1_EL2);
+               default:
+                       cpu_if->vgic_ap1r[0] = read_gicreg(ICH_AP1R0_EL2);
+               }
+
+               vcpu->arch.vgic_cpu.live_lrs = 0;
+       } else {
+               cpu_if->vgic_misr  = 0;
+               cpu_if->vgic_eisr  = 0;
+               cpu_if->vgic_elrsr = 0xffff;
+               cpu_if->vgic_ap0r[0] = 0;
+               cpu_if->vgic_ap0r[1] = 0;
+               cpu_if->vgic_ap0r[2] = 0;
+               cpu_if->vgic_ap0r[3] = 0;
+               cpu_if->vgic_ap1r[0] = 0;
+               cpu_if->vgic_ap1r[1] = 0;
+               cpu_if->vgic_ap1r[2] = 0;
+               cpu_if->vgic_ap1r[3] = 0;
        }
 
        val = read_gicreg(ICC_SRE_EL2);
@@ -128,6 +245,8 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
        u64 val;
        u32 max_lr_idx, nr_pri_bits;
+       u16 live_lrs = 0;
+       int i;
 
        /*
         * VFIQEn is RES1 if ICC_SRE_EL1.SRE is 1. This causes a
@@ -140,66 +259,46 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
        write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
        isb();
 
-       write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
-       write_gicreg(cpu_if->vgic_vmcr, ICH_VMCR_EL2);
-
        val = read_gicreg(ICH_VTR_EL2);
        max_lr_idx = vtr_to_max_lr_idx(val);
        nr_pri_bits = vtr_to_nr_pri_bits(val);
 
-       switch (nr_pri_bits) {
-       case 7:
-                write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
-                write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
-       case 6:
-                write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2);
-       default:
-                write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2);
-       }                                          
-                                                  
-       switch (nr_pri_bits) {
-       case 7:
-                write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
-                write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
-       case 6:
-                write_gicreg(cpu_if->vgic_ap0r[1], ICH_AP0R1_EL2);
-       default:
-                write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
+       for (i = 0; i <= max_lr_idx; i++) {
+               if (cpu_if->vgic_lr[i] & ICH_LR_STATE)
+                       live_lrs |= (1 << i);
        }
 
-       switch (max_lr_idx) {
-       case 15:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(15)], ICH_LR15_EL2);
-       case 14:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(14)], ICH_LR14_EL2);
-       case 13:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(13)], ICH_LR13_EL2);
-       case 12:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(12)], ICH_LR12_EL2);
-       case 11:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(11)], ICH_LR11_EL2);
-       case 10:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(10)], ICH_LR10_EL2);
-       case 9:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(9)], ICH_LR9_EL2);
-       case 8:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(8)], ICH_LR8_EL2);
-       case 7:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(7)], ICH_LR7_EL2);
-       case 6:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(6)], ICH_LR6_EL2);
-       case 5:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(5)], ICH_LR5_EL2);
-       case 4:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(4)], ICH_LR4_EL2);
-       case 3:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(3)], ICH_LR3_EL2);
-       case 2:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(2)], ICH_LR2_EL2);
-       case 1:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(1)], ICH_LR1_EL2);
-       case 0:
-               write_gicreg(cpu_if->vgic_lr[VGIC_V3_LR_INDEX(0)], ICH_LR0_EL2);
+       write_gicreg(cpu_if->vgic_vmcr, ICH_VMCR_EL2);
+
+       if (live_lrs) {
+               write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
+
+               switch (nr_pri_bits) {
+               case 7:
+                       write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
+                       write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
+               case 6:
+                       write_gicreg(cpu_if->vgic_ap0r[1], ICH_AP0R1_EL2);
+               default:
+                       write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
+               }
+
+               switch (nr_pri_bits) {
+               case 7:
+                       write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
+                       write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
+               case 6:
+                       write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2);
+               default:
+                       write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2);
+               }
+
+               for (i = 0; i <= max_lr_idx; i++) {
+                       if (!(live_lrs & (1 << i)))
+                               continue;
+
+                       __gic_v3_set_lr(cpu_if->vgic_lr[i], i);
+               }
        }
 
        /*
@@ -209,6 +308,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
         */
        isb();
        dsb(sy);
+       vcpu->arch.vgic_cpu.live_lrs = live_lrs;
 
        /*
         * Prevent the guest from touching the GIC system registers if
@@ -220,6 +320,15 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
        }
 }
 
+void __hyp_text __vgic_v3_init_lrs(void)
+{
+       int max_lr_idx = vtr_to_max_lr_idx(read_gicreg(ICH_VTR_EL2));
+       int i;
+
+       for (i = 0; i <= max_lr_idx; i++)
+               __gic_v3_set_lr(0, i);
+}
+
 static u64 __hyp_text __vgic_v3_read_ich_vtr_el2(void)
 {
        return read_gicreg(ICH_VTR_EL2);
index f34745cb3d236fe0a4731f8d02031f8ff764d69c..9677bf069bcc497eaa3aedd0c631210e9b97a390 100644 (file)
@@ -77,7 +77,11 @@ int kvm_arch_dev_ioctl_check_extension(long ext)
        case KVM_CAP_GUEST_DEBUG_HW_WPS:
                r = get_num_wrps();
                break;
+       case KVM_CAP_ARM_PMU_V3:
+               r = kvm_arm_support_pmu_v3();
+               break;
        case KVM_CAP_SET_GUEST_DEBUG:
+       case KVM_CAP_VCPU_ATTRIBUTES:
                r = 1;
                break;
        default:
@@ -120,6 +124,9 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        /* Reset system registers */
        kvm_reset_sys_regs(vcpu);
 
+       /* Reset PMU */
+       kvm_pmu_vcpu_reset(vcpu);
+
        /* Reset timer */
        return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
 }
index 2e90371cfb378b0e064667506a2b74c9275cacfb..61ba591048454c37a92d7855e6059a3f3389ed81 100644 (file)
@@ -20,6 +20,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/bsearch.h>
 #include <linux/kvm_host.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>
@@ -34,6 +35,7 @@
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_host.h>
 #include <asm/kvm_mmu.h>
+#include <asm/perf_event.h>
 
 #include <trace/events/kvm.h>
 
@@ -439,6 +441,344 @@ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
        vcpu_sys_reg(vcpu, MPIDR_EL1) = (1ULL << 31) | mpidr;
 }
 
+static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
+{
+       u64 pmcr, val;
+
+       asm volatile("mrs %0, pmcr_el0\n" : "=r" (pmcr));
+       /* Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) is reset to UNKNOWN
+        * except PMCR.E resetting to zero.
+        */
+       val = ((pmcr & ~ARMV8_PMU_PMCR_MASK)
+              | (ARMV8_PMU_PMCR_MASK & 0xdecafbad)) & (~ARMV8_PMU_PMCR_E);
+       vcpu_sys_reg(vcpu, PMCR_EL0) = val;
+}
+
+static bool pmu_access_el0_disabled(struct kvm_vcpu *vcpu)
+{
+       u64 reg = vcpu_sys_reg(vcpu, PMUSERENR_EL0);
+
+       return !((reg & ARMV8_PMU_USERENR_EN) || vcpu_mode_priv(vcpu));
+}
+
+static bool pmu_write_swinc_el0_disabled(struct kvm_vcpu *vcpu)
+{
+       u64 reg = vcpu_sys_reg(vcpu, PMUSERENR_EL0);
+
+       return !((reg & (ARMV8_PMU_USERENR_SW | ARMV8_PMU_USERENR_EN))
+                || vcpu_mode_priv(vcpu));
+}
+
+static bool pmu_access_cycle_counter_el0_disabled(struct kvm_vcpu *vcpu)
+{
+       u64 reg = vcpu_sys_reg(vcpu, PMUSERENR_EL0);
+
+       return !((reg & (ARMV8_PMU_USERENR_CR | ARMV8_PMU_USERENR_EN))
+                || vcpu_mode_priv(vcpu));
+}
+
+static bool pmu_access_event_counter_el0_disabled(struct kvm_vcpu *vcpu)
+{
+       u64 reg = vcpu_sys_reg(vcpu, PMUSERENR_EL0);
+
+       return !((reg & (ARMV8_PMU_USERENR_ER | ARMV8_PMU_USERENR_EN))
+                || vcpu_mode_priv(vcpu));
+}
+
+static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                       const struct sys_reg_desc *r)
+{
+       u64 val;
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (pmu_access_el0_disabled(vcpu))
+               return false;
+
+       if (p->is_write) {
+               /* Only update writeable bits of PMCR */
+               val = vcpu_sys_reg(vcpu, PMCR_EL0);
+               val &= ~ARMV8_PMU_PMCR_MASK;
+               val |= p->regval & ARMV8_PMU_PMCR_MASK;
+               vcpu_sys_reg(vcpu, PMCR_EL0) = val;
+               kvm_pmu_handle_pmcr(vcpu, val);
+       } else {
+               /* PMCR.P & PMCR.C are RAZ */
+               val = vcpu_sys_reg(vcpu, PMCR_EL0)
+                     & ~(ARMV8_PMU_PMCR_P | ARMV8_PMU_PMCR_C);
+               p->regval = val;
+       }
+
+       return true;
+}
+
+static bool access_pmselr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                         const struct sys_reg_desc *r)
+{
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (pmu_access_event_counter_el0_disabled(vcpu))
+               return false;
+
+       if (p->is_write)
+               vcpu_sys_reg(vcpu, PMSELR_EL0) = p->regval;
+       else
+               /* return PMSELR.SEL field */
+               p->regval = vcpu_sys_reg(vcpu, PMSELR_EL0)
+                           & ARMV8_PMU_COUNTER_MASK;
+
+       return true;
+}
+
+static bool access_pmceid(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                         const struct sys_reg_desc *r)
+{
+       u64 pmceid;
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       BUG_ON(p->is_write);
+
+       if (pmu_access_el0_disabled(vcpu))
+               return false;
+
+       if (!(p->Op2 & 1))
+               asm volatile("mrs %0, pmceid0_el0\n" : "=r" (pmceid));
+       else
+               asm volatile("mrs %0, pmceid1_el0\n" : "=r" (pmceid));
+
+       p->regval = pmceid;
+
+       return true;
+}
+
+static bool pmu_counter_idx_valid(struct kvm_vcpu *vcpu, u64 idx)
+{
+       u64 pmcr, val;
+
+       pmcr = vcpu_sys_reg(vcpu, PMCR_EL0);
+       val = (pmcr >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK;
+       if (idx >= val && idx != ARMV8_PMU_CYCLE_IDX)
+               return false;
+
+       return true;
+}
+
+static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
+                             struct sys_reg_params *p,
+                             const struct sys_reg_desc *r)
+{
+       u64 idx;
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (r->CRn == 9 && r->CRm == 13) {
+               if (r->Op2 == 2) {
+                       /* PMXEVCNTR_EL0 */
+                       if (pmu_access_event_counter_el0_disabled(vcpu))
+                               return false;
+
+                       idx = vcpu_sys_reg(vcpu, PMSELR_EL0)
+                             & ARMV8_PMU_COUNTER_MASK;
+               } else if (r->Op2 == 0) {
+                       /* PMCCNTR_EL0 */
+                       if (pmu_access_cycle_counter_el0_disabled(vcpu))
+                               return false;
+
+                       idx = ARMV8_PMU_CYCLE_IDX;
+               } else {
+                       BUG();
+               }
+       } else if (r->CRn == 14 && (r->CRm & 12) == 8) {
+               /* PMEVCNTRn_EL0 */
+               if (pmu_access_event_counter_el0_disabled(vcpu))
+                       return false;
+
+               idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+       } else {
+               BUG();
+       }
+
+       if (!pmu_counter_idx_valid(vcpu, idx))
+               return false;
+
+       if (p->is_write) {
+               if (pmu_access_el0_disabled(vcpu))
+                       return false;
+
+               kvm_pmu_set_counter_value(vcpu, idx, p->regval);
+       } else {
+               p->regval = kvm_pmu_get_counter_value(vcpu, idx);
+       }
+
+       return true;
+}
+
+static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                              const struct sys_reg_desc *r)
+{
+       u64 idx, reg;
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (pmu_access_el0_disabled(vcpu))
+               return false;
+
+       if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 1) {
+               /* PMXEVTYPER_EL0 */
+               idx = vcpu_sys_reg(vcpu, PMSELR_EL0) & ARMV8_PMU_COUNTER_MASK;
+               reg = PMEVTYPER0_EL0 + idx;
+       } else if (r->CRn == 14 && (r->CRm & 12) == 12) {
+               idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+               if (idx == ARMV8_PMU_CYCLE_IDX)
+                       reg = PMCCFILTR_EL0;
+               else
+                       /* PMEVTYPERn_EL0 */
+                       reg = PMEVTYPER0_EL0 + idx;
+       } else {
+               BUG();
+       }
+
+       if (!pmu_counter_idx_valid(vcpu, idx))
+               return false;
+
+       if (p->is_write) {
+               kvm_pmu_set_counter_event_type(vcpu, p->regval, idx);
+               vcpu_sys_reg(vcpu, reg) = p->regval & ARMV8_PMU_EVTYPE_MASK;
+       } else {
+               p->regval = vcpu_sys_reg(vcpu, reg) & ARMV8_PMU_EVTYPE_MASK;
+       }
+
+       return true;
+}
+
+static bool access_pmcnten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                          const struct sys_reg_desc *r)
+{
+       u64 val, mask;
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (pmu_access_el0_disabled(vcpu))
+               return false;
+
+       mask = kvm_pmu_valid_counter_mask(vcpu);
+       if (p->is_write) {
+               val = p->regval & mask;
+               if (r->Op2 & 0x1) {
+                       /* accessing PMCNTENSET_EL0 */
+                       vcpu_sys_reg(vcpu, PMCNTENSET_EL0) |= val;
+                       kvm_pmu_enable_counter(vcpu, val);
+               } else {
+                       /* accessing PMCNTENCLR_EL0 */
+                       vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= ~val;
+                       kvm_pmu_disable_counter(vcpu, val);
+               }
+       } else {
+               p->regval = vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask;
+       }
+
+       return true;
+}
+
+static bool access_pminten(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                          const struct sys_reg_desc *r)
+{
+       u64 mask = kvm_pmu_valid_counter_mask(vcpu);
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (!vcpu_mode_priv(vcpu))
+               return false;
+
+       if (p->is_write) {
+               u64 val = p->regval & mask;
+
+               if (r->Op2 & 0x1)
+                       /* accessing PMINTENSET_EL1 */
+                       vcpu_sys_reg(vcpu, PMINTENSET_EL1) |= val;
+               else
+                       /* accessing PMINTENCLR_EL1 */
+                       vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= ~val;
+       } else {
+               p->regval = vcpu_sys_reg(vcpu, PMINTENSET_EL1) & mask;
+       }
+
+       return true;
+}
+
+static bool access_pmovs(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                        const struct sys_reg_desc *r)
+{
+       u64 mask = kvm_pmu_valid_counter_mask(vcpu);
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (pmu_access_el0_disabled(vcpu))
+               return false;
+
+       if (p->is_write) {
+               if (r->CRm & 0x2)
+                       /* accessing PMOVSSET_EL0 */
+                       kvm_pmu_overflow_set(vcpu, p->regval & mask);
+               else
+                       /* accessing PMOVSCLR_EL0 */
+                       vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= ~(p->regval & mask);
+       } else {
+               p->regval = vcpu_sys_reg(vcpu, PMOVSSET_EL0) & mask;
+       }
+
+       return true;
+}
+
+static bool access_pmswinc(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                          const struct sys_reg_desc *r)
+{
+       u64 mask;
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (pmu_write_swinc_el0_disabled(vcpu))
+               return false;
+
+       if (p->is_write) {
+               mask = kvm_pmu_valid_counter_mask(vcpu);
+               kvm_pmu_software_increment(vcpu, p->regval & mask);
+               return true;
+       }
+
+       return false;
+}
+
+static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
+                            const struct sys_reg_desc *r)
+{
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return trap_raz_wi(vcpu, p, r);
+
+       if (p->is_write) {
+               if (!vcpu_mode_priv(vcpu))
+                       return false;
+
+               vcpu_sys_reg(vcpu, PMUSERENR_EL0) = p->regval
+                                                   & ARMV8_PMU_USERENR_MASK;
+       } else {
+               p->regval = vcpu_sys_reg(vcpu, PMUSERENR_EL0)
+                           & ARMV8_PMU_USERENR_MASK;
+       }
+
+       return true;
+}
+
 /* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
 #define DBG_BCR_BVR_WCR_WVR_EL1(n)                                     \
        /* DBGBVRn_EL1 */                                               \
@@ -454,6 +794,20 @@ static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
        { Op0(0b10), Op1(0b000), CRn(0b0000), CRm((n)), Op2(0b111),     \
          trap_wcr, reset_wcr, n, 0,  get_wcr, set_wcr }
 
+/* Macro to expand the PMEVCNTRn_EL0 register */
+#define PMU_PMEVCNTR_EL0(n)                                            \
+       /* PMEVCNTRn_EL0 */                                             \
+       { Op0(0b11), Op1(0b011), CRn(0b1110),                           \
+         CRm((0b1000 | (((n) >> 3) & 0x3))), Op2(((n) & 0x7)),         \
+         access_pmu_evcntr, reset_unknown, (PMEVCNTR0_EL0 + n), }
+
+/* Macro to expand the PMEVTYPERn_EL0 register */
+#define PMU_PMEVTYPER_EL0(n)                                           \
+       /* PMEVTYPERn_EL0 */                                            \
+       { Op0(0b11), Op1(0b011), CRn(0b1110),                           \
+         CRm((0b1100 | (((n) >> 3) & 0x3))), Op2(((n) & 0x7)),         \
+         access_pmu_evtyper, reset_unknown, (PMEVTYPER0_EL0 + n), }
+
 /*
  * Architected system registers.
  * Important: Must be sorted ascending by Op0, Op1, CRn, CRm, Op2
@@ -583,10 +937,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
        /* PMINTENSET_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),
-         trap_raz_wi },
+         access_pminten, reset_unknown, PMINTENSET_EL1 },
        /* PMINTENCLR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b010),
-         trap_raz_wi },
+         access_pminten, NULL, PMINTENSET_EL1 },
 
        /* MAIR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1010), CRm(0b0010), Op2(0b000),
@@ -623,43 +977,46 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
        /* PMCR_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b000),
-         trap_raz_wi },
+         access_pmcr, reset_pmcr, },
        /* PMCNTENSET_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b001),
-         trap_raz_wi },
+         access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
        /* PMCNTENCLR_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b010),
-         trap_raz_wi },
+         access_pmcnten, NULL, PMCNTENSET_EL0 },
        /* PMOVSCLR_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b011),
-         trap_raz_wi },
+         access_pmovs, NULL, PMOVSSET_EL0 },
        /* PMSWINC_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b100),
-         trap_raz_wi },
+         access_pmswinc, reset_unknown, PMSWINC_EL0 },
        /* PMSELR_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b101),
-         trap_raz_wi },
+         access_pmselr, reset_unknown, PMSELR_EL0 },
        /* PMCEID0_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b110),
-         trap_raz_wi },
+         access_pmceid },
        /* PMCEID1_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1100), Op2(0b111),
-         trap_raz_wi },
+         access_pmceid },
        /* PMCCNTR_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b000),
-         trap_raz_wi },
+         access_pmu_evcntr, reset_unknown, PMCCNTR_EL0 },
        /* PMXEVTYPER_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b001),
-         trap_raz_wi },
+         access_pmu_evtyper },
        /* PMXEVCNTR_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1101), Op2(0b010),
-         trap_raz_wi },
-       /* PMUSERENR_EL0 */
+         access_pmu_evcntr },
+       /* PMUSERENR_EL0
+        * This register resets as unknown in 64bit mode while it resets as zero
+        * in 32bit mode. Here we choose to reset it as zero for consistency.
+        */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1110), Op2(0b000),
-         trap_raz_wi },
+         access_pmuserenr, reset_val, PMUSERENR_EL0, 0 },
        /* PMOVSSET_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1001), CRm(0b1110), Op2(0b011),
-         trap_raz_wi },
+         access_pmovs, reset_unknown, PMOVSSET_EL0 },
 
        /* TPIDR_EL0 */
        { Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b0000), Op2(0b010),
@@ -668,6 +1025,77 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b0000), Op2(0b011),
          NULL, reset_unknown, TPIDRRO_EL0 },
 
+       /* PMEVCNTRn_EL0 */
+       PMU_PMEVCNTR_EL0(0),
+       PMU_PMEVCNTR_EL0(1),
+       PMU_PMEVCNTR_EL0(2),
+       PMU_PMEVCNTR_EL0(3),
+       PMU_PMEVCNTR_EL0(4),
+       PMU_PMEVCNTR_EL0(5),
+       PMU_PMEVCNTR_EL0(6),
+       PMU_PMEVCNTR_EL0(7),
+       PMU_PMEVCNTR_EL0(8),
+       PMU_PMEVCNTR_EL0(9),
+       PMU_PMEVCNTR_EL0(10),
+       PMU_PMEVCNTR_EL0(11),
+       PMU_PMEVCNTR_EL0(12),
+       PMU_PMEVCNTR_EL0(13),
+       PMU_PMEVCNTR_EL0(14),
+       PMU_PMEVCNTR_EL0(15),
+       PMU_PMEVCNTR_EL0(16),
+       PMU_PMEVCNTR_EL0(17),
+       PMU_PMEVCNTR_EL0(18),
+       PMU_PMEVCNTR_EL0(19),
+       PMU_PMEVCNTR_EL0(20),
+       PMU_PMEVCNTR_EL0(21),
+       PMU_PMEVCNTR_EL0(22),
+       PMU_PMEVCNTR_EL0(23),
+       PMU_PMEVCNTR_EL0(24),
+       PMU_PMEVCNTR_EL0(25),
+       PMU_PMEVCNTR_EL0(26),
+       PMU_PMEVCNTR_EL0(27),
+       PMU_PMEVCNTR_EL0(28),
+       PMU_PMEVCNTR_EL0(29),
+       PMU_PMEVCNTR_EL0(30),
+       /* PMEVTYPERn_EL0 */
+       PMU_PMEVTYPER_EL0(0),
+       PMU_PMEVTYPER_EL0(1),
+       PMU_PMEVTYPER_EL0(2),
+       PMU_PMEVTYPER_EL0(3),
+       PMU_PMEVTYPER_EL0(4),
+       PMU_PMEVTYPER_EL0(5),
+       PMU_PMEVTYPER_EL0(6),
+       PMU_PMEVTYPER_EL0(7),
+       PMU_PMEVTYPER_EL0(8),
+       PMU_PMEVTYPER_EL0(9),
+       PMU_PMEVTYPER_EL0(10),
+       PMU_PMEVTYPER_EL0(11),
+       PMU_PMEVTYPER_EL0(12),
+       PMU_PMEVTYPER_EL0(13),
+       PMU_PMEVTYPER_EL0(14),
+       PMU_PMEVTYPER_EL0(15),
+       PMU_PMEVTYPER_EL0(16),
+       PMU_PMEVTYPER_EL0(17),
+       PMU_PMEVTYPER_EL0(18),
+       PMU_PMEVTYPER_EL0(19),
+       PMU_PMEVTYPER_EL0(20),
+       PMU_PMEVTYPER_EL0(21),
+       PMU_PMEVTYPER_EL0(22),
+       PMU_PMEVTYPER_EL0(23),
+       PMU_PMEVTYPER_EL0(24),
+       PMU_PMEVTYPER_EL0(25),
+       PMU_PMEVTYPER_EL0(26),
+       PMU_PMEVTYPER_EL0(27),
+       PMU_PMEVTYPER_EL0(28),
+       PMU_PMEVTYPER_EL0(29),
+       PMU_PMEVTYPER_EL0(30),
+       /* PMCCFILTR_EL0
+        * This register resets as unknown in 64bit mode while it resets as zero
+        * in 32bit mode. Here we choose to reset it as zero for consistency.
+        */
+       { Op0(0b11), Op1(0b011), CRn(0b1110), CRm(0b1111), Op2(0b111),
+         access_pmu_evtyper, reset_val, PMCCFILTR_EL0, 0 },
+
        /* DACR32_EL2 */
        { Op0(0b11), Op1(0b100), CRn(0b0011), CRm(0b0000), Op2(0b000),
          NULL, reset_unknown, DACR32_EL2 },
@@ -857,6 +1285,20 @@ static const struct sys_reg_desc cp14_64_regs[] = {
        { Op1( 0), CRm( 2), .access = trap_raz_wi },
 };
 
+/* Macro to expand the PMEVCNTRn register */
+#define PMU_PMEVCNTR(n)                                                        \
+       /* PMEVCNTRn */                                                 \
+       { Op1(0), CRn(0b1110),                                          \
+         CRm((0b1000 | (((n) >> 3) & 0x3))), Op2(((n) & 0x7)),         \
+         access_pmu_evcntr }
+
+/* Macro to expand the PMEVTYPERn register */
+#define PMU_PMEVTYPER(n)                                               \
+       /* PMEVTYPERn */                                                \
+       { Op1(0), CRn(0b1110),                                          \
+         CRm((0b1100 | (((n) >> 3) & 0x3))), Op2(((n) & 0x7)),         \
+         access_pmu_evtyper }
+
 /*
  * Trapped cp15 registers. TTBR0/TTBR1 get a double encoding,
  * depending on the way they are accessed (as a 32bit or a 64bit
@@ -885,19 +1327,21 @@ static const struct sys_reg_desc cp15_regs[] = {
        { Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw },
 
        /* PMU */
-       { Op1( 0), CRn( 9), CRm(12), Op2( 0), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(12), Op2( 1), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(12), Op2( 2), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(12), Op2( 3), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(12), Op2( 5), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(12), Op2( 6), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(12), Op2( 7), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(13), Op2( 0), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(13), Op2( 1), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(13), Op2( 2), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(14), Op2( 0), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(14), Op2( 1), trap_raz_wi },
-       { Op1( 0), CRn( 9), CRm(14), Op2( 2), trap_raz_wi },
+       { Op1( 0), CRn( 9), CRm(12), Op2( 0), access_pmcr },
+       { Op1( 0), CRn( 9), CRm(12), Op2( 1), access_pmcnten },
+       { Op1( 0), CRn( 9), CRm(12), Op2( 2), access_pmcnten },
+       { Op1( 0), CRn( 9), CRm(12), Op2( 3), access_pmovs },
+       { Op1( 0), CRn( 9), CRm(12), Op2( 4), access_pmswinc },
+       { Op1( 0), CRn( 9), CRm(12), Op2( 5), access_pmselr },
+       { Op1( 0), CRn( 9), CRm(12), Op2( 6), access_pmceid },
+       { Op1( 0), CRn( 9), CRm(12), Op2( 7), access_pmceid },
+       { Op1( 0), CRn( 9), CRm(13), Op2( 0), access_pmu_evcntr },
+       { Op1( 0), CRn( 9), CRm(13), Op2( 1), access_pmu_evtyper },
+       { Op1( 0), CRn( 9), CRm(13), Op2( 2), access_pmu_evcntr },
+       { Op1( 0), CRn( 9), CRm(14), Op2( 0), access_pmuserenr },
+       { Op1( 0), CRn( 9), CRm(14), Op2( 1), access_pminten },
+       { Op1( 0), CRn( 9), CRm(14), Op2( 2), access_pminten },
+       { Op1( 0), CRn( 9), CRm(14), Op2( 3), access_pmovs },
 
        { Op1( 0), CRn(10), CRm( 2), Op2( 0), access_vm_reg, NULL, c10_PRRR },
        { Op1( 0), CRn(10), CRm( 2), Op2( 1), access_vm_reg, NULL, c10_NMRR },
@@ -908,10 +1352,78 @@ static const struct sys_reg_desc cp15_regs[] = {
        { Op1( 0), CRn(12), CRm(12), Op2( 5), trap_raz_wi },
 
        { Op1( 0), CRn(13), CRm( 0), Op2( 1), access_vm_reg, NULL, c13_CID },
+
+       /* PMEVCNTRn */
+       PMU_PMEVCNTR(0),
+       PMU_PMEVCNTR(1),
+       PMU_PMEVCNTR(2),
+       PMU_PMEVCNTR(3),
+       PMU_PMEVCNTR(4),
+       PMU_PMEVCNTR(5),
+       PMU_PMEVCNTR(6),
+       PMU_PMEVCNTR(7),
+       PMU_PMEVCNTR(8),
+       PMU_PMEVCNTR(9),
+       PMU_PMEVCNTR(10),
+       PMU_PMEVCNTR(11),
+       PMU_PMEVCNTR(12),
+       PMU_PMEVCNTR(13),
+       PMU_PMEVCNTR(14),
+       PMU_PMEVCNTR(15),
+       PMU_PMEVCNTR(16),
+       PMU_PMEVCNTR(17),
+       PMU_PMEVCNTR(18),
+       PMU_PMEVCNTR(19),
+       PMU_PMEVCNTR(20),
+       PMU_PMEVCNTR(21),
+       PMU_PMEVCNTR(22),
+       PMU_PMEVCNTR(23),
+       PMU_PMEVCNTR(24),
+       PMU_PMEVCNTR(25),
+       PMU_PMEVCNTR(26),
+       PMU_PMEVCNTR(27),
+       PMU_PMEVCNTR(28),
+       PMU_PMEVCNTR(29),
+       PMU_PMEVCNTR(30),
+       /* PMEVTYPERn */
+       PMU_PMEVTYPER(0),
+       PMU_PMEVTYPER(1),
+       PMU_PMEVTYPER(2),
+       PMU_PMEVTYPER(3),
+       PMU_PMEVTYPER(4),
+       PMU_PMEVTYPER(5),
+       PMU_PMEVTYPER(6),
+       PMU_PMEVTYPER(7),
+       PMU_PMEVTYPER(8),
+       PMU_PMEVTYPER(9),
+       PMU_PMEVTYPER(10),
+       PMU_PMEVTYPER(11),
+       PMU_PMEVTYPER(12),
+       PMU_PMEVTYPER(13),
+       PMU_PMEVTYPER(14),
+       PMU_PMEVTYPER(15),
+       PMU_PMEVTYPER(16),
+       PMU_PMEVTYPER(17),
+       PMU_PMEVTYPER(18),
+       PMU_PMEVTYPER(19),
+       PMU_PMEVTYPER(20),
+       PMU_PMEVTYPER(21),
+       PMU_PMEVTYPER(22),
+       PMU_PMEVTYPER(23),
+       PMU_PMEVTYPER(24),
+       PMU_PMEVTYPER(25),
+       PMU_PMEVTYPER(26),
+       PMU_PMEVTYPER(27),
+       PMU_PMEVTYPER(28),
+       PMU_PMEVTYPER(29),
+       PMU_PMEVTYPER(30),
+       /* PMCCFILTR */
+       { Op1(0), CRn(14), CRm(15), Op2(7), access_pmu_evtyper },
 };
 
 static const struct sys_reg_desc cp15_64_regs[] = {
        { Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
+       { Op1( 0), CRn( 0), CRm( 9), Op2( 0), access_pmu_evcntr },
        { Op1( 0), CRn( 0), CRm(12), Op2( 0), access_gic_sgi },
        { Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 },
 };
@@ -942,29 +1454,32 @@ static const struct sys_reg_desc *get_target_table(unsigned target,
        }
 }
 
+#define reg_to_match_value(x)                                          \
+       ({                                                              \
+               unsigned long val;                                      \
+               val  = (x)->Op0 << 14;                                  \
+               val |= (x)->Op1 << 11;                                  \
+               val |= (x)->CRn << 7;                                   \
+               val |= (x)->CRm << 3;                                   \
+               val |= (x)->Op2;                                        \
+               val;                                                    \
+        })
+
+static int match_sys_reg(const void *key, const void *elt)
+{
+       const unsigned long pval = (unsigned long)key;
+       const struct sys_reg_desc *r = elt;
+
+       return pval - reg_to_match_value(r);
+}
+
 static const struct sys_reg_desc *find_reg(const struct sys_reg_params *params,
                                         const struct sys_reg_desc table[],
                                         unsigned int num)
 {
-       unsigned int i;
-
-       for (i = 0; i < num; i++) {
-               const struct sys_reg_desc *r = &table[i];
-
-               if (params->Op0 != r->Op0)
-                       continue;
-               if (params->Op1 != r->Op1)
-                       continue;
-               if (params->CRn != r->CRn)
-                       continue;
-               if (params->CRm != r->CRm)
-                       continue;
-               if (params->Op2 != r->Op2)
-                       continue;
+       unsigned long pval = reg_to_match_value(params);
 
-               return r;
-       }
-       return NULL;
+       return bsearch((void *)pval, table, num, sizeof(table[0]), match_sys_reg);
 }
 
 int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
index 82d607c3614ed8454d19f2da5d44a6cc914ee0b3..da30529bb1f65c9e3d5408b2e28ab31bc2283211 100644 (file)
@@ -306,10 +306,6 @@ static __init int setup_hugepagesz(char *opt)
                hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
        } else if (ps == PUD_SIZE) {
                hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
-       } else if (ps == (PAGE_SIZE * CONT_PTES)) {
-               hugetlb_add_hstate(CONT_PTE_SHIFT);
-       } else if (ps == (PMD_SIZE * CONT_PMDS)) {
-               hugetlb_add_hstate((PMD_SHIFT + CONT_PMD_SHIFT) - PAGE_SHIFT);
        } else {
                pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10);
                return 0;
@@ -317,13 +313,3 @@ static __init int setup_hugepagesz(char *opt)
        return 1;
 }
 __setup("hugepagesz=", setup_hugepagesz);
-
-#ifdef CONFIG_ARM64_64K_PAGES
-static __init int add_default_hugepagesz(void)
-{
-       if (size_to_hstate(CONT_PTES * PAGE_SIZE) == NULL)
-               hugetlb_add_hstate(CONT_PMD_SHIFT);
-       return 0;
-}
-arch_initcall(add_default_hugepagesz);
-#endif
index f3b061e67bfe0f4565d5df29322eeaef38a9bcc3..7802f216a67a588ab778b7d2b7649a2979e68b87 100644 (file)
@@ -319,8 +319,8 @@ void __init mem_init(void)
 #endif
                  MLG(VMALLOC_START, VMALLOC_END),
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-                 MLG((unsigned long)vmemmap,
-                     (unsigned long)vmemmap + VMEMMAP_SIZE),
+                 MLG(VMEMMAP_START,
+                     VMEMMAP_START + VMEMMAP_SIZE),
                  MLM((unsigned long)virt_to_page(PAGE_OFFSET),
                      (unsigned long)virt_to_page(high_memory)),
 #endif
index 4c893b5189ddd027537511c5daaca70f158577c4..232f787a088ae8e992c52cba450159a43a900174 100644 (file)
@@ -53,10 +53,10 @@ unsigned long arch_mmap_rnd(void)
 
 #ifdef CONFIG_COMPAT
        if (test_thread_flag(TIF_32BIT))
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_compat_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
        else
 #endif
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
        return rnd << PAGE_SHIFT;
 }
 
index 366bbeaeb405d67daa35adac5ff22a4ecfc7e125..572739b4c4b4ebd01857c6d889fcbdf2688c0710 100644 (file)
@@ -57,7 +57,7 @@ static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
                "       brne    1b\n"
                "2:\n"
                : [ret] "=&r"(ret), [m] "=m"(*m)
-               : "m"(m), [old] "ir"(old), [new] "r"(new)
+               : "m"(m), [old] "Ks21r"(old), [new] "r"(new)
                : "memory", "cc");
        return ret;
 }
index a32a02372017443d24db8848d2a559c548b1f13e..0f5f134b896a132635b412c83a772ba86ea78fa6 100644 (file)
@@ -5,6 +5,4 @@
 
 #define PCI_DMA_BUS_IS_PHYS    (1)
 
-#include <asm-generic/pci-dma-compat.h>
-
 #endif /* __ASM_AVR32_PCI_H__ */
index b60132bb27ea7d7be7d0e306d49e9071142061ac..60c0f3afc1f973a85425369e3c164b870cdecdf9 100644 (file)
 #define __NR_userfaultfd       322
 #define __NR_membarrier                323
 #define __NR_mlock2            324
+#define __NR_copy_file_range    325
 
 #endif /* _UAPI__ASM_AVR32_UNISTD_H */
index 209ae5ad34958044ae3d6addcafa090f890a8be7..e6928896da2a4a2879828df92d940a2ed321a4ea 100644 (file)
@@ -49,13 +49,13 @@ static struct resource __initdata kernel_data = {
        .name   = "Kernel data",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_MEM,
+       .flags  = IORESOURCE_SYSTEM_RAM,
 };
 static struct resource __initdata kernel_code = {
        .name   = "Kernel code",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_MEM,
+       .flags  = IORESOURCE_SYSTEM_RAM,
        .sibling = &kernel_data,
 };
 
@@ -134,7 +134,7 @@ add_physical_memory(resource_size_t start, resource_size_t end)
        new->start = start;
        new->end = end;
        new->name = "System RAM";
-       new->flags = IORESOURCE_MEM;
+       new->flags = IORESOURCE_SYSTEM_RAM;
 
        *pprev = new;
 }
index f9c68fab0e2fc1d9eedc61c39c9ff84e1e68ab35..cb3991552f14b56fdd79351b6bfb539d84548d62 100644 (file)
@@ -124,3 +124,12 @@ __sys_process_vm_writev:
        call    sys_process_vm_writev
        sub     sp, -4
        popm    pc
+
+       .global __sys_copy_file_range
+       .type   __sys_copy_file_range,@function
+__sys_copy_file_range:
+       pushm   lr
+       st.w    --sp, ARG6
+       call    sys_copy_file_range
+       sub     sp, -4
+       popm    pc
index 1915a443b4914de8d27347688dc06f048ee22473..64d71a781fa88da2c687ee8bd102a49fee79ea22 100644 (file)
@@ -338,4 +338,5 @@ sys_call_table:
        .long   sys_userfaultfd
        .long   sys_membarrier
        .long   sys_mlock2
+       .long   __sys_copy_file_range   /* 325 */
        .long   sys_ni_syscall          /* r8 is saturated at nr_syscalls */
index af76634f8d9897fe61ae64a2b956d9ce07951c0c..a63c12259e77e03832c9d3c50da6ecbc9e62db18 100644 (file)
@@ -1233,8 +1233,6 @@ source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 menu "Executable file formats"
index 14efc0db1ade134eb41e8566a6e4be76b0f94e6b..11ea1cb35036e68a580613c7032f12c5b62a20ef 100644 (file)
@@ -4,7 +4,6 @@
 #define _ASM_BFIN_PCI_H
 
 #include <linux/scatterlist.h>
-#include <asm-generic/pci-dma-compat.h>
 #include <asm-generic/pci.h>
 
 #define PCIBIOS_MIN_IO 0x00001000
index b88a1558b0b9bf1d8a933fdd67383b1b66c95899..c1ee3d6533fbac890526fe9e7707eaa4afe1d01f 100644 (file)
@@ -97,6 +97,8 @@ extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long,
                                          unsigned long);
 #define HAVE_ARCH_FB_UNMAPPED_AREA
 
+#define pgprot_writecombine pgprot_noncached
+
 #include <asm-generic/pgtable.h>
 
 #endif                         /* _BLACKFIN_PGTABLE_H */
index 0030e21cfceb3b885e8365168ba91b74ddee4f75..23c4ef5f8bdced2fb30b461f94b53c56694db4a4 100644 (file)
@@ -333,7 +333,7 @@ void secondary_start_kernel(void)
 
        /* We are done with local CPU inits, unblock the boot CPU. */
        set_cpu_online(cpu, true);
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 void __init smp_prepare_boot_cpu(void)
index 72e17f7ebd6ff0fba193ac07190d42b41e106e76..786e36e2f61de91c8f446cc941cff895cdb91578 100644 (file)
@@ -281,8 +281,6 @@ notrace void __init machine_init(unsigned long dt_ptr)
         */
        set_ist(_vectors_start);
 
-       lockdep_init();
-
        /*
         * dtb is passed in from bootloader.
         * fdt is linked in blob.
index c15b4b4baafaa82295ebb1e637f7a242bce68a0b..b1b289df04c77f62575bd5be61968f1a784330fd 100644 (file)
@@ -48,9 +48,6 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 
 #endif /* __KERNEL__ */
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 /* generic pci stuff */
 #include <asm-generic/pci.h>
 
index e43d22c58ad52cc74d116291eef632508700460e..809cfc6707abf4f2402c0ae1e856cbca76ca211b 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
-#include <asm-generic/pci-dma-compat.h>
 #include <asm-generic/pci.h>
 
 struct pci_dev;
@@ -32,12 +31,6 @@ extern void consistent_sync_page(struct page *page, unsigned long offset,
                                 size_t size, int direction);
 #endif
 
-extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                                 dma_addr_t *dma_handle);
-
-extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                               void *vaddr, dma_addr_t dma_handle);
-
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)       (0)
 
index ff759f26b96aef8cbffbfc9c860aa7f2966ff27b..983bae7d2665cd6cc164e4584041b96f9e98f64e 100644 (file)
@@ -180,7 +180,7 @@ void start_secondary(void)
 
        local_irq_enable();
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 
index fb0515eb639b55295c59b25ef1ce83554f35d7b4..b534ebab36eac7397ca29119e1545fc9bbf7b611 100644 (file)
@@ -574,12 +574,8 @@ config PCI_DOMAINS
 config PCI_SYSCALL
        def_bool PCI
 
-source "drivers/pci/pcie/Kconfig"
-
 source "drivers/pci/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 source "drivers/pcmcia/Kconfig"
 
 endmenu
index 07039d168f37bfd14048e9e4a73d50bc4d20f35d..c0835b0dc72275adb47cae1dbcda19f098809320 100644 (file)
@@ -50,8 +50,6 @@ struct pci_dev;
 extern unsigned long ia64_max_iommu_merge_mask;
 #define PCI_DMA_BUS_IS_PHYS    (ia64_max_iommu_merge_mask == ~0UL)
 
-#include <asm-generic/pci-dma-compat.h>
-
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
                                enum pci_mmap_state mmap_state, int write_combine);
index caae3f4e4341a40d86f4014871c1ebe929a937ae..300dac3702f11a13460d1954843bfcbd1ddc2034 100644 (file)
@@ -1178,7 +1178,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
        efi_memory_desc_t *md;
        u64 efi_desc_size;
        char *name;
-       unsigned long flags;
+       unsigned long flags, desc;
 
        efi_map_start = __va(ia64_boot_param->efi_memmap);
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
@@ -1193,6 +1193,8 @@ efi_initialize_iomem_resources(struct resource *code_resource,
                        continue;
 
                flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               desc = IORES_DESC_NONE;
+
                switch (md->type) {
 
                        case EFI_MEMORY_MAPPED_IO:
@@ -1207,14 +1209,17 @@ efi_initialize_iomem_resources(struct resource *code_resource,
                                if (md->attribute & EFI_MEMORY_WP) {
                                        name = "System ROM";
                                        flags |= IORESOURCE_READONLY;
-                               } else if (md->attribute == EFI_MEMORY_UC)
+                               } else if (md->attribute == EFI_MEMORY_UC) {
                                        name = "Uncached RAM";
-                               else
+                               } else {
                                        name = "System RAM";
+                                       flags |= IORESOURCE_SYSRAM;
+                               }
                                break;
 
                        case EFI_ACPI_MEMORY_NVS:
                                name = "ACPI Non-volatile Storage";
+                               desc = IORES_DESC_ACPI_NV_STORAGE;
                                break;
 
                        case EFI_UNUSABLE_MEMORY:
@@ -1224,6 +1229,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
 
                        case EFI_PERSISTENT_MEMORY:
                                name = "Persistent Memory";
+                               desc = IORES_DESC_PERSISTENT_MEMORY;
                                break;
 
                        case EFI_RESERVED_TYPE:
@@ -1246,6 +1252,7 @@ efi_initialize_iomem_resources(struct resource *code_resource,
                res->start = md->phys_addr;
                res->end = md->phys_addr + efi_md_size(md) - 1;
                res->flags = flags;
+               res->desc = desc;
 
                if (insert_resource(&iomem_resource, res) < 0)
                        kfree(res);
index 4f118b0d30915f4f5927719522414a66efe17f08..2029a38a72aeee89793d53ee60418567586d67ff 100644 (file)
@@ -80,17 +80,17 @@ unsigned long vga_console_membase;
 
 static struct resource data_resource = {
        .name   = "Kernel data",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static struct resource code_resource = {
        .name   = "Kernel code",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static struct resource bss_resource = {
        .name   = "Kernel bss",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 unsigned long ia64_max_cacheline_size;
index 0e76fad27975db388776f61e0cf8afd4241f1112..74fe317477e6273b48d0b97f29d96aeda7ba7872 100644 (file)
@@ -454,7 +454,7 @@ start_secondary (void *unused)
        preempt_disable();
        smp_callin();
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
        return 0;
 }
 
index fc505d58f078ecfb55210cd3e802ed23c4b41a8e..41caa99add513964a638bda32eb725848b9e4d53 100644 (file)
  *
  * The standard boot ROM sequence for an x86 machine uses the BIOS
  * to select an initial video card for boot display. This boot video
- * card will have it's BIOS copied to C0000 in system RAM.
+ * card will have its BIOS copied to 0xC0000 in system RAM.
  * IORESOURCE_ROM_SHADOW is used to associate the boot video
  * card with this copy. On laptops this copy has to be used since
  * the main ROM may be compressed or combined with another image.
  * See pci_map_rom() for use of this flag. Before marking the device
  * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
- * by either arch cde or vga-arbitration, if so only apply the fixup to this
- * already determined primary video card.
+ * by either arch code or vga-arbitration; if so only apply the fixup to this
+ * already-determined primary video card.
  */
 
 static void pci_fixup_video(struct pci_dev *pdev)
@@ -32,6 +32,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
        struct pci_dev *bridge;
        struct pci_bus *bus;
        u16 config;
+       struct resource *res;
 
        if ((strcmp(ia64_platform_name, "dig") != 0)
            && (strcmp(ia64_platform_name, "hpzx1")  != 0))
@@ -61,8 +62,18 @@ static void pci_fixup_video(struct pci_dev *pdev)
        if (!vga_default_device() || pdev == vga_default_device()) {
                pci_read_config_word(pdev, PCI_COMMAND, &config);
                if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
-                       pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-                       dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
+                       res = &pdev->resource[PCI_ROM_RESOURCE];
+
+                       pci_disable_rom(pdev);
+                       if (res->parent)
+                               release_resource(res);
+
+                       res->start = 0xC0000;
+                       res->end = res->start + 0x20000 - 1;
+                       res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
+                                    IORESOURCE_PCI_FIXED;
+                       dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n",
+                                res);
                }
        }
 }
index 0640739cc20cf2895fca507babfe7de9096d8a41..231234c8d1133a8e593b2c5312cdb95141ecc4c6 100644 (file)
@@ -429,7 +429,8 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
        void __iomem *addr;
        struct pcidev_info *pcidev_info = NULL;
        struct sn_irq_info *sn_irq_info = NULL;
-       size_t image_size, size;
+       struct resource *res;
+       size_t size;
 
        if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
                panic("%s:  Failure obtaining pcidev_info for %s\n",
@@ -443,17 +444,20 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
                 * of the shadowed copy, and the actual length of the ROM image.
                 */
                size = pci_resource_len(dev, PCI_ROM_RESOURCE);
-               addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
-                              size);
-               image_size = pci_get_rom_size(dev, addr, size);
-               dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
-               dev->resource[PCI_ROM_RESOURCE].end =
-                                       (unsigned long) addr + image_size - 1;
-               dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
+
+               res = &dev->resource[PCI_ROM_RESOURCE];
+
+               pci_disable_rom(dev);
+               if (res->parent)
+                       release_resource(res);
+
+               res->start = pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE];
+               res->end = res->start + size - 1;
+               res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
+                            IORESOURCE_PCI_FIXED;
        }
        sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
 }
-
 EXPORT_SYMBOL(sn_acpi_slot_fixup);
 
 
index 1be65eb074ece698501600ee62fa8887b4f5c9a3..c15a41e2d1f2e85662fbfeaa811c7bb90d71e745 100644 (file)
@@ -150,7 +150,8 @@ void
 sn_io_slot_fixup(struct pci_dev *dev)
 {
        int idx;
-       unsigned long addr, end, size, start;
+       struct resource *res;
+       unsigned long addr, size;
        struct pcidev_info *pcidev_info;
        struct sn_irq_info *sn_irq_info;
        int status;
@@ -175,55 +176,41 @@ sn_io_slot_fixup(struct pci_dev *dev)
 
        /* Copy over PIO Mapped Addresses */
        for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
-
-               if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
+               if (!pcidev_info->pdi_pio_mapped_addr[idx])
                        continue;
-               }
 
-               start = dev->resource[idx].start;
-               end = dev->resource[idx].end;
-               size = end - start;
-               if (size == 0) {
+               res = &dev->resource[idx];
+
+               size = res->end - res->start;
+               if (size == 0)
                        continue;
-               }
-               addr = pcidev_info->pdi_pio_mapped_addr[idx];
-               addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET;
-               dev->resource[idx].start = addr;
-               dev->resource[idx].end = addr + size;
+
+               res->start = pcidev_info->pdi_pio_mapped_addr[idx];
+               res->end = addr + size;
 
                /*
                 * if it's already in the device structure, remove it before
                 * inserting
                 */
-               if (dev->resource[idx].parent && dev->resource[idx].parent->child)
-                       release_resource(&dev->resource[idx]);
+               if (res->parent && res->parent->child)
+                       release_resource(res);
 
-               if (dev->resource[idx].flags & IORESOURCE_IO)
-                       insert_resource(&ioport_resource, &dev->resource[idx]);
+               if (res->flags & IORESOURCE_IO)
+                       insert_resource(&ioport_resource, res);
                else
-                       insert_resource(&iomem_resource, &dev->resource[idx]);
+                       insert_resource(&iomem_resource, res);
                /*
-                * If ROM, set the actual ROM image size, and mark as
-                * shadowed in PROM.
+                * If ROM, mark as shadowed in PROM.
                 */
                if (idx == PCI_ROM_RESOURCE) {
-                       size_t image_size;
-                       void __iomem *rom;
-
-                       rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
-                                     size + 1);
-                       image_size = pci_get_rom_size(dev, rom, size + 1);
-                       dev->resource[PCI_ROM_RESOURCE].end =
-                               dev->resource[PCI_ROM_RESOURCE].start +
-                               image_size - 1;
-                       dev->resource[PCI_ROM_RESOURCE].flags |=
-                                                IORESOURCE_ROM_BIOS_COPY;
+                       pci_disable_rom(dev);
+                       res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
+                                    IORESOURCE_PCI_FIXED;
                }
        }
 
        sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
 }
-
 EXPORT_SYMBOL(sn_io_slot_fixup);
 
 /*
index 2841c0a3fd3bb201a4bed53d823858b32a0a009b..c82b2925399116e87128e0c187fde3d9e7aadb75 100644 (file)
@@ -387,8 +387,6 @@ config ISA
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 
index a5ecef7188baa39e6f21d7a5a7c5ed6cca8f040f..136c69f1fb8ab8b73c23e2a752ea371c6e484512 100644 (file)
@@ -70,14 +70,14 @@ static struct resource data_resource = {
        .name   = "Kernel data",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static struct resource code_resource = {
        .name   = "Kernel code",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 unsigned long memory_start;
index a468467542f453d170e2ded0ac2e339ad574198f..f98d2f6519d633c85f3979e103f5bf5c3438cd28 100644 (file)
@@ -432,7 +432,7 @@ int __init start_secondary(void *unused)
         */
        local_flush_tlb_all();
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
        return 0;
 }
 
index 0d4146f644dc01fe3323bb35b6f654e61016b671..11fa717d93b19f2858eec15acce07a9c82617ca7 100644 (file)
@@ -59,21 +59,24 @@ void free_initrd_mem(unsigned long, unsigned long);
 void __init zone_sizes_init(void)
 {
        unsigned long  zones_size[MAX_NR_ZONES] = {0, };
-       unsigned long  max_dma;
-       unsigned long  low;
        unsigned long  start_pfn;
 
 #ifdef CONFIG_MMU
-       start_pfn = START_PFN(0);
-       max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-       low = MAX_LOW_PFN(0);
-
-       if (low < max_dma){
-               zones_size[ZONE_DMA] = low - start_pfn;
-               zones_size[ZONE_NORMAL] = 0;
-       } else {
-               zones_size[ZONE_DMA] = low - start_pfn;
-               zones_size[ZONE_NORMAL] = low - max_dma;
+       {
+               unsigned long  low;
+               unsigned long  max_dma;
+
+               start_pfn = START_PFN(0);
+               max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+               low = MAX_LOW_PFN(0);
+
+               if (low < max_dma) {
+                       zones_size[ZONE_DMA] = low - start_pfn;
+                       zones_size[ZONE_NORMAL] = 0;
+               } else {
+                       zones_size[ZONE_DMA] = low - start_pfn;
+                       zones_size[ZONE_NORMAL] = low - max_dma;
+               }
        }
 #else
        zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT;
index 4ebf098b8a1fd58c9a222d864b9f4cea6f6c2171..1a8080c4cc402a9922ee873474c3c0010cf59655 100644 (file)
 
 /**********
  *
- * 0xFFFFF7xx -- Serial Periferial Interface Slave (SPIS)
+ * 0xFFFFF7xx -- Serial Peripheral Interface Slave (SPIS)
  *
  **********/
 
 
 /**********
  *
- * 0xFFFFF8xx -- Serial Periferial Interface Master (SPIM)
+ * 0xFFFFF8xx -- Serial Peripheral Interface Master (SPIM)
  *
  **********/
 
 
 #define UBAUD_PRESCALER_MASK   0x003f  /* Actual divisor is 65 - PRESCALER */
 #define UBAUD_PRESCALER_SHIFT  0
-#define UBAUD_DIVIDE_MASK      0x0700  /* Baud Rate freq. divizor */
+#define UBAUD_DIVIDE_MASK      0x0700  /* Baud Rate freq. divisor */
 #define UBAUD_DIVIDE_SHIFT     8
 #define UBAUD_BAUD_SRC         0x0800  /* Baud Rate Source */
 #define UBAUD_GPIOSRC          0x1000  /* GPIO source */
index d1bde58ab0ddbd63e75508cbcb691d11c925c222..fedac87c5d130858ad929118229b4680f588e568 100644 (file)
 
 /**********
  *
- * 0xFFFFF8xx -- Serial Periferial Interface Master (SPIM)
+ * 0xFFFFF8xx -- Serial Peripheral Interface Master (SPIM)
  *
  **********/
 
 
 #define UBAUD_PRESCALER_MASK   0x003f  /* Actual divisor is 65 - PRESCALER */
 #define UBAUD_PRESCALER_SHIFT  0
-#define UBAUD_DIVIDE_MASK      0x0700  /* Baud Rate freq. divizor */
+#define UBAUD_DIVIDE_MASK      0x0700  /* Baud Rate freq. divisor */
 #define UBAUD_DIVIDE_SHIFT     8
 #define UBAUD_BAUD_SRC         0x0800  /* Baud Rate Source */
 #define UBAUD_UCLKDIR          0x2000  /* UCLK Direction */
@@ -1160,7 +1160,7 @@ typedef volatile struct {
 #define DRAMMC_COL10           0x0080  /* Col address bit for MD10 PA11/PA0  */
 #define DRAMMC_COL9            0x0040  /* Col address bit for MD9  PA10/PA0  */
 #define DRAMMC_COL8            0x0020  /* Col address bit for MD8  PA9/PA0   */
-#define DRAMMC_REF_MASK                0x001f  /* Reresh Cycle */
+#define DRAMMC_REF_MASK                0x001f  /* Refresh Cycle */
 #define DRAMMC_REF_SHIFT       0
 
 /*
index 6bd1bf1f85ea23de0338e554a4609047b2db78aa..34a51b2c784fb96e74924947df9bbeef426ef2fb 100644 (file)
 
 /**********
  *
- * 0xFFFFF8xx -- Serial Periferial Interface Master (SPIM)
+ * 0xFFFFF8xx -- Serial Peripheral Interface Master (SPIM)
  *
  **********/
 
 
 #define UBAUD_PRESCALER_MASK   0x003f  /* Actual divisor is 65 - PRESCALER */
 #define UBAUD_PRESCALER_SHIFT  0
-#define UBAUD_DIVIDE_MASK      0x0700  /* Baud Rate freq. divizor */
+#define UBAUD_DIVIDE_MASK      0x0700  /* Baud Rate freq. divisor */
 #define UBAUD_DIVIDE_SHIFT     8
 #define UBAUD_BAUD_SRC         0x0800  /* Baud Rate Source */
 #define UBAUD_UCLKDIR          0x2000  /* UCLK Direction */
@@ -1256,7 +1256,7 @@ typedef struct {
 #define DRAMMC_COL10           0x0080  /* Col address bit for MD10 PA11/PA0  */
 #define DRAMMC_COL9            0x0040  /* Col address bit for MD9  PA10/PA0  */
 #define DRAMMC_COL8            0x0020  /* Col address bit for MD8  PA9/PA0   */
-#define DRAMMC_REF_MASK                0x001f  /* Reresh Cycle */
+#define DRAMMC_REF_MASK                0x001f  /* Refresh Cycle */
 #define DRAMMC_REF_SHIFT       0
 
 /*
index 6d13cae44af530240b99b83e4248288ee939ae69..59e171063c2f1f846dcac7c4fc07eab2b26093fc 100644 (file)
@@ -23,8 +23,8 @@
 #define CACR_IEC       0x00008000      /* Enable instruction cache */
 #define CACR_DNFB      0x00002000      /* Inhibited fill buffer */
 #define CACR_IDPI      0x00001000      /* Disable CPUSHL */
-#define CACR_IHLCK     0x00000800      /* Intruction cache half lock */
-#define CACR_IDCM      0x00000400      /* Intruction cache inhibit */
+#define CACR_IHLCK     0x00000800      /* Instruction cache half lock */
+#define CACR_IDCM      0x00000400      /* Instruction cache inhibit */
 #define CACR_ICINVA    0x00000100      /* Invalidate instr cache */
 #define CACR_EUSP      0x00000020      /* Enable separate user a7 */
 
index fde874a01e20fe001f78d5f4f5e440786f614d48..42566fd052bc0e091a4143f9fbd168c40752985c 100644 (file)
@@ -48,7 +48,7 @@
 
 /* IOP message status codes */
 
-#define IOP_MSGSTATUS_UNUSED   0       /* Unusued message structure       */
+#define IOP_MSGSTATUS_UNUSED   0       /* Unused message structure        */
 #define IOP_MSGSTATUS_WAITING  1       /* waiting for channel             */
 #define IOP_MSGSTATUS_SENT     2       /* message sent, awaiting reply    */
 #define IOP_MSGSTATUS_COMPLETE 3       /* message complete and reply rcvd */
index 089f0f150bbfc06169a720e2ddb9b9d3d563658c..1150e42c3f19db6c3241bee5156a60cdde79b434 100644 (file)
@@ -51,7 +51,7 @@
  *     Bit definitions for the Timer Event Registers (TER).
  */
 #define        MCFTIMER_TER_CAP        0x01            /* Capture event */
-#define        MCFTIMER_TER_REF        0x02            /* Refernece event */
+#define        MCFTIMER_TER_REF        0x02            /* Reference event */
 
 /****************************************************************************/
 #endif /* mcftimer_h */
index 848c3dfaad504a4748d907aae5caf4b37c90c5c0..3a3dbcf4051dbb5aca1a5841762c69426146b85b 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef _ASM_M68K_PCI_H
 #define _ASM_M68K_PCI_H
 
-#include <asm-generic/pci-dma-compat.h>
 #include <asm-generic/pci.h>
 
 /* The PCI address space does equal the physical memory
index b54ac7aba850eaf02ac995a857e673102039f3be..97cd3ea5f10b837949b124024951912d6973e8f6 100644 (file)
@@ -71,13 +71,19 @@ ENTRY(__sys_vfork)
 
 ENTRY(sys_sigreturn)
        SAVE_SWITCH_STACK
+       movel   %sp,%sp@-                 | switch_stack pointer
+       pea     %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer
        jbsr    do_sigreturn
+       addql   #8,%sp
        RESTORE_SWITCH_STACK
        rts
 
 ENTRY(sys_rt_sigreturn)
        SAVE_SWITCH_STACK
+       movel   %sp,%sp@-                 | switch_stack pointer
+       pea     %sp@(SWITCH_STACK_SIZE+4) | pt_regs pointer
        jbsr    do_rt_sigreturn
+       addql   #8,%sp
        RESTORE_SWITCH_STACK
        rts
 
index af1c4f330aefc67a025e5db896053a60b3847fa0..2dcee3a88867536b2186f01252f1bf1d842ec279 100644 (file)
@@ -737,10 +737,8 @@ badframe:
        return 1;
 }
 
-asmlinkage int do_sigreturn(unsigned long __unused)
+asmlinkage int do_sigreturn(struct pt_regs *regs, struct switch_stack *sw)
 {
-       struct switch_stack *sw = (struct switch_stack *) &__unused;
-       struct pt_regs *regs = (struct pt_regs *) (sw + 1);
        unsigned long usp = rdusp();
        struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
        sigset_t set;
@@ -764,10 +762,8 @@ badframe:
        return 0;
 }
 
-asmlinkage int do_rt_sigreturn(unsigned long __unused)
+asmlinkage int do_rt_sigreturn(struct pt_regs *regs, struct switch_stack *sw)
 {
-       struct switch_stack *sw = (struct switch_stack *) &__unused;
-       struct pt_regs *regs = (struct pt_regs *) (sw + 1);
        unsigned long usp = rdusp();
        struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
        sigset_t set;
index ce56e04386e707350568fd5850a4f44259f033b0..920ff63d4a81d77af96849d3e7c7f802da8be4a7 100644 (file)
@@ -68,7 +68,7 @@ static int gIER,gIFR,gBufA,gBufB;
  * interrupt. This limitation also seems to apply to VIA clone logic cores in
  * Quadra-like ASICs. (RBV and OSS machines don't have this limitation.)
  *
- * We used to fake it by configuring the relevent VIA pin as an output
+ * We used to fake it by configuring the relevant VIA pin as an output
  * (to mask the interrupt) or input (to unmask). That scheme did not work on
  * (at least) the Quadra 700. A NuBus card's /NMRQ signal is an open-collector
  * circuit (see Designing Cards and Drivers for Macintosh II and Macintosh SE,
index c3c6f086488169cc06e53b1eb6eb07ea6b2e68ee..bad13232de51897c4040fda12772ae31a4dbcc1c 100644 (file)
@@ -396,7 +396,7 @@ asmlinkage void secondary_start_kernel(void)
        /*
         * OK, it's off to the idle thread for us
         */
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 void __init smp_cpus_done(unsigned int max_cpus)
index 53b69deceb998820947e5136d668f334a4f9f1cd..3d793b55f60c04b3b18cdf01b20a1d7c6964e65a 100644 (file)
@@ -267,6 +267,9 @@ config PCI
 config PCI_DOMAINS
        def_bool PCI
 
+config PCI_DOMAINS_GENERIC
+       def_bool PCI_DOMAINS
+
 config PCI_SYSCALL
        def_bool PCI
 
index dc9eb6657e3a4a8e0763e3afabe0284bbd9bbbb2..fc3ecb55f1b23130efa35233e08ee77153e4a237 100644 (file)
@@ -22,8 +22,6 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 
-#include <asm-generic/pci-dma-compat.h>
-
 #define PCIBIOS_MIN_IO         0x1000
 #define PCIBIOS_MIN_MEM                0x10000000
 
index 89a2a93949274b16b3508b314d0cbdf6db5946e6..f31ebb5dc26c21922f240545d038f0d6b5699300 100644 (file)
@@ -130,8 +130,6 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
        memset(__bss_start, 0, __bss_stop-__bss_start);
        memset(_ssbss, 0, _esbss-_ssbss);
 
-       lockdep_init();
-
 /* initialize device tree for usage in early_printk */
        early_init_devtree(_fdt_start);
 
index ae838ed5fcf2535ca5c047a2837adadc434735cd..35654be3f1c03289bda596b184b64c2d734d7655 100644 (file)
@@ -123,17 +123,6 @@ unsigned long pci_address_to_pio(phys_addr_t address)
 }
 EXPORT_SYMBOL_GPL(pci_address_to_pio);
 
-/*
- * Return the domain number for this bus.
- */
-int pci_domain_nr(struct pci_bus *bus)
-{
-       struct pci_controller *hose = pci_bus_to_host(bus);
-
-       return hose->global_number;
-}
-EXPORT_SYMBOL(pci_domain_nr);
-
 /* This routine is meant to be used early during boot, when the
  * PCI bus numbers have not yet been assigned, and you need to
  * issue PCI config cycles to an OF device.
@@ -863,26 +852,10 @@ void pcibios_setup_bus_devices(struct pci_bus *bus)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       /* When called from the generic PCI probe, read PCI<->PCI bridge
-        * bases. This is -not- called when generating the PCI tree from
-        * the OF device-tree.
-        */
-       if (bus->self != NULL)
-               pci_read_bridge_bases(bus);
-
-       /* Now fixup the bus bus */
-       pcibios_setup_bus_self(bus);
-
-       /* Now fixup devices on that bus */
-       pcibios_setup_bus_devices(bus);
+       /* nothing to do */
 }
 EXPORT_SYMBOL(pcibios_fixup_bus);
 
-static int skip_isa_ioresource_align(struct pci_dev *dev)
-{
-       return 0;
-}
-
 /*
  * We need to avoid collisions with `mirrored' VGA ports
  * and other strange ISA hardware, so we always want the
@@ -899,20 +872,18 @@ static int skip_isa_ioresource_align(struct pci_dev *dev)
 resource_size_t pcibios_align_resource(void *data, const struct resource *res,
                                resource_size_t size, resource_size_t align)
 {
-       struct pci_dev *dev = data;
-       resource_size_t start = res->start;
-
-       if (res->flags & IORESOURCE_IO) {
-               if (skip_isa_ioresource_align(dev))
-                       return start;
-               if (start & 0x300)
-                       start = (start + 0x3ff) & ~0x3ff;
-       }
-
-       return start;
+       return res->start;
 }
 EXPORT_SYMBOL(pcibios_align_resource);
 
+int pcibios_add_device(struct pci_dev *dev)
+{
+       dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
+
+       return 0;
+}
+EXPORT_SYMBOL(pcibios_add_device);
+
 /*
  * Reparent resource children of pr that conflict with res
  * under res, and make res replace those children.
@@ -1333,13 +1304,6 @@ static void pcibios_setup_phb_resources(struct pci_controller *hose,
                 (unsigned long)hose->io_base_virt - _IO_BASE);
 }
 
-struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
-{
-       struct pci_controller *hose = bus->sysdata;
-
-       return of_node_get(hose->dn);
-}
-
 static void pcibios_scan_phb(struct pci_controller *hose)
 {
        LIST_HEAD(resources);
index 74a3db92da1b52edc15165ac06d3b1558b8b78c0..7c4a4ce356033c6a2aa05fe7fe306714c44689cb 100644 (file)
@@ -151,6 +151,7 @@ config BMIPS_GENERIC
        select CSRC_R4K
        select SYNC_R4K
        select COMMON_CLK
+       select BCM6345_L1_IRQ
        select BCM7038_L1_IRQ
        select BCM7120_L2_IRQ
        select BRCMSTB_L2_IRQ
@@ -2169,7 +2170,6 @@ config MIPS_MT_SMP
        select CPU_MIPSR2_IRQ_VI
        select CPU_MIPSR2_IRQ_EI
        select SYNC_R4K
-       select MIPS_GIC_IPI
        select MIPS_MT
        select SMP
        select SMP_UP
@@ -2267,7 +2267,6 @@ config MIPS_VPE_APSP_API_MT
 config MIPS_CMP
        bool "MIPS CMP framework support (DEPRECATED)"
        depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
-       select MIPS_GIC_IPI
        select SMP
        select SYNC_R4K
        select SYS_SUPPORTS_SMP
@@ -2287,7 +2286,6 @@ config MIPS_CPS
        select MIPS_CM
        select MIPS_CPC
        select MIPS_CPS_PM if HOTPLUG_CPU
-       select MIPS_GIC_IPI
        select SMP
        select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
        select SYS_SUPPORTS_HOTPLUG_CPU
@@ -2305,9 +2303,6 @@ config MIPS_CPS_PM
        select MIPS_CPC
        bool
 
-config MIPS_GIC_IPI
-       bool
-
 config MIPS_CM
        bool
 
@@ -2876,8 +2871,6 @@ config PCI_DOMAINS
 
 source "drivers/pci/Kconfig"
 
-source "drivers/pci/pcie/Kconfig"
-
 #
 # ISA support is now enabled via select.  Too many systems still have the one
 # or other ISA chip on the board that users don't know about so don't expect
@@ -2937,8 +2930,6 @@ config ZONE_DMA32
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 config RAPIDIO
        tristate "RapidIO support"
        depends on PCI
index 511c06560dc1f5a95866f832ec9ae2180048b9d5..2dfff1f19004326c06ec366033418e8152f76309 100644 (file)
 #include "common.h"
 #include "machtypes.h"
 
-static void __init ath79_misc_intc_domain_init(
-       struct device_node *node, int irq);
-
-static void ath79_misc_irq_handler(struct irq_desc *desc)
-{
-       struct irq_domain *domain = irq_desc_get_handler_data(desc);
-       void __iomem *base = domain->host_data;
-       u32 pending;
-
-       pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
-                 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
-
-       if (!pending) {
-               spurious_interrupt();
-               return;
-       }
-
-       while (pending) {
-               int bit = __ffs(pending);
-
-               generic_handle_irq(irq_linear_revmap(domain, bit));
-               pending &= ~BIT(bit);
-       }
-}
-
-static void ar71xx_misc_irq_unmask(struct irq_data *d)
-{
-       void __iomem *base = irq_data_get_irq_chip_data(d);
-       unsigned int irq = d->hwirq;
-       u32 t;
-
-       t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
-       __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
-
-       /* flush write */
-       __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
-}
-
-static void ar71xx_misc_irq_mask(struct irq_data *d)
-{
-       void __iomem *base = irq_data_get_irq_chip_data(d);
-       unsigned int irq = d->hwirq;
-       u32 t;
-
-       t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
-       __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
-
-       /* flush write */
-       __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
-}
-
-static void ar724x_misc_irq_ack(struct irq_data *d)
-{
-       void __iomem *base = irq_data_get_irq_chip_data(d);
-       unsigned int irq = d->hwirq;
-       u32 t;
-
-       t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
-       __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
-
-       /* flush write */
-       __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
-}
-
-static struct irq_chip ath79_misc_irq_chip = {
-       .name           = "MISC",
-       .irq_unmask     = ar71xx_misc_irq_unmask,
-       .irq_mask       = ar71xx_misc_irq_mask,
-};
-
-static void __init ath79_misc_irq_init(void)
-{
-       if (soc_is_ar71xx() || soc_is_ar913x())
-               ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
-       else if (soc_is_ar724x() ||
-                soc_is_ar933x() ||
-                soc_is_ar934x() ||
-                soc_is_qca955x())
-               ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
-       else
-               BUG();
-
-       ath79_misc_intc_domain_init(NULL, ATH79_CPU_IRQ(6));
-}
 
 static void ar934x_ip2_irq_dispatch(struct irq_desc *desc)
 {
@@ -212,142 +128,12 @@ static void qca955x_irq_init(void)
        irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch);
 }
 
-/*
- * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
- * these devices typically allocate coherent DMA memory, however the
- * DMA controller may still have some unsynchronized data in the FIFO.
- * Issue a flush in the handlers to ensure that the driver sees
- * the update.
- *
- * This array map the interrupt lines to the DDR write buffer channels.
- */
-
-static unsigned irq_wb_chan[8] = {
-       -1, -1, -1, -1, -1, -1, -1, -1,
-};
-
-asmlinkage void plat_irq_dispatch(void)
-{
-       unsigned long pending;
-       int irq;
-
-       pending = read_c0_status() & read_c0_cause() & ST0_IM;
-
-       if (!pending) {
-               spurious_interrupt();
-               return;
-       }
-
-       pending >>= CAUSEB_IP;
-       while (pending) {
-               irq = fls(pending) - 1;
-               if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1)
-                       ath79_ddr_wb_flush(irq_wb_chan[irq]);
-               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
-               pending &= ~BIT(irq);
-       }
-}
-
-static int misc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
-{
-       irq_set_chip_and_handler(irq, &ath79_misc_irq_chip, handle_level_irq);
-       irq_set_chip_data(irq, d->host_data);
-       return 0;
-}
-
-static const struct irq_domain_ops misc_irq_domain_ops = {
-       .xlate = irq_domain_xlate_onecell,
-       .map = misc_map,
-};
-
-static void __init ath79_misc_intc_domain_init(
-       struct device_node *node, int irq)
-{
-       void __iomem *base = ath79_reset_base;
-       struct irq_domain *domain;
-
-       domain = irq_domain_add_legacy(node, ATH79_MISC_IRQ_COUNT,
-                       ATH79_MISC_IRQ_BASE, 0, &misc_irq_domain_ops, base);
-       if (!domain)
-               panic("Failed to add MISC irqdomain");
-
-       /* Disable and clear all interrupts */
-       __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
-       __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
-
-       irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
-}
-
-static int __init ath79_misc_intc_of_init(
-       struct device_node *node, struct device_node *parent)
-{
-       int irq;
-
-       irq = irq_of_parse_and_map(node, 0);
-       if (!irq)
-               panic("Failed to get MISC IRQ");
-
-       ath79_misc_intc_domain_init(node, irq);
-       return 0;
-}
-
-static int __init ar7100_misc_intc_of_init(
-       struct device_node *node, struct device_node *parent)
-{
-       ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
-       return ath79_misc_intc_of_init(node, parent);
-}
-
-IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc",
-               ar7100_misc_intc_of_init);
-
-static int __init ar7240_misc_intc_of_init(
-       struct device_node *node, struct device_node *parent)
-{
-       ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
-       return ath79_misc_intc_of_init(node, parent);
-}
-
-IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc",
-               ar7240_misc_intc_of_init);
-
-static int __init ar79_cpu_intc_of_init(
-       struct device_node *node, struct device_node *parent)
-{
-       int err, i, count;
-
-       /* Fill the irq_wb_chan table */
-       count = of_count_phandle_with_args(
-               node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells");
-
-       for (i = 0; i < count; i++) {
-               struct of_phandle_args args;
-               u32 irq = i;
-
-               of_property_read_u32_index(
-                       node, "qca,ddr-wb-channel-interrupts", i, &irq);
-               if (irq >= ARRAY_SIZE(irq_wb_chan))
-                       continue;
-
-               err = of_parse_phandle_with_args(
-                       node, "qca,ddr-wb-channels",
-                       "#qca,ddr-wb-channel-cells",
-                       i, &args);
-               if (err)
-                       return err;
-
-               irq_wb_chan[irq] = args.args[0];
-               pr_info("IRQ: Set flush channel of IRQ%d to %d\n",
-                       irq, args.args[0]);
-       }
-
-       return mips_cpu_irq_of_init(node, parent);
-}
-IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc",
-               ar79_cpu_intc_of_init);
-
 void __init arch_init_irq(void)
 {
+       unsigned irq_wb_chan2 = -1;
+       unsigned irq_wb_chan3 = -1;
+       bool misc_is_ar71xx;
+
        if (mips_machtype == ATH79_MACH_GENERIC_OF) {
                irqchip_init();
                return;
@@ -355,14 +141,26 @@ void __init arch_init_irq(void)
 
        if (soc_is_ar71xx() || soc_is_ar724x() ||
            soc_is_ar913x() || soc_is_ar933x()) {
-               irq_wb_chan[2] = 3;
-               irq_wb_chan[3] = 2;
+               irq_wb_chan2 = 3;
+               irq_wb_chan3 = 2;
        } else if (soc_is_ar934x()) {
-               irq_wb_chan[3] = 2;
+               irq_wb_chan3 = 2;
        }
 
-       mips_cpu_irq_init();
-       ath79_misc_irq_init();
+       ath79_cpu_irq_init(irq_wb_chan2, irq_wb_chan3);
+
+       if (soc_is_ar71xx() || soc_is_ar913x())
+               misc_is_ar71xx = true;
+       else if (soc_is_ar724x() ||
+                soc_is_ar933x() ||
+                soc_is_ar934x() ||
+                soc_is_qca955x())
+               misc_is_ar71xx = false;
+       else
+               BUG();
+       ath79_misc_irq_init(
+               ath79_reset_base + AR71XX_RESET_REG_MISC_INT_STATUS,
+               ATH79_CPU_IRQ(6), ATH79_MISC_IRQ_BASE, misc_is_ar71xx);
 
        if (soc_is_ar934x())
                ar934x_ip2_irq_init();
index e7fc6f9348baa2e6bc06f881ced25aec7fb40b46..7efefcf440338c0e657733cdc2ae26e38aba9e35 100644 (file)
 #include <asm/irq_cpu.h>
 #include <asm/time.h>
 
+static const struct of_device_id smp_intc_dt_match[] = {
+       { .compatible = "brcm,bcm7038-l1-intc" },
+       { .compatible = "brcm,bcm6345-l1-intc" },
+       {}
+};
+
 unsigned int get_c0_compare_int(void)
 {
        return CP0_LEGACY_COMPARE_IRQ;
@@ -24,8 +30,8 @@ void __init arch_init_irq(void)
 {
        struct device_node *dn;
 
-       /* Only the STB (bcm7038) controller supports SMP IRQ affinity */
-       dn = of_find_compatible_node(NULL, NULL, "brcm,bcm7038-l1-intc");
+       /* Only these controllers support SMP IRQ affinity */
+       dn = of_find_matching_node(NULL, smp_intc_dt_match);
        if (dn)
                of_node_put(dn);
        else
index 408799a839b42f2d9d7d1232bd7ea4efda0cf2d4..f7521142deda55fb439fa0857a2383b4dad7cc83 100644 (file)
@@ -17,7 +17,7 @@
 #define PORT(offset) (CKSEG1ADDR(AR7_REGS_UART0) + (4 * offset))
 #endif
 
-#ifdef CONFIG_MACH_JZ4740
+#if defined(CONFIG_MACH_JZ4740) || defined(CONFIG_MACH_JZ4780)
 #include <asm/mach-jz4740/base.h>
 #define PORT(offset) (CKSEG1ADDR(JZ4740_UART0_BASE_ADDR) + (4 * offset))
 #endif
index d61b1616b604552be9a30f89eb42539de6838b14..9d19236f53e7b9a33c2a2cc2ccfd593322b04074 100644 (file)
@@ -74,7 +74,7 @@
                timer: timer@10000040 {
                        compatible = "syscon";
                        reg = <0x10000040 0x2c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index 9c8d3fe28b3114e51aaf128a640bde630d31a65b..1f6b9b5cddb4c0890b02cb37edb5c0c3331ba8dd 100644 (file)
@@ -54,7 +54,7 @@
                periph_cntl: syscon@10000000 {
                        compatible = "syscon";
                        reg = <0x10000000 0x14>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot: syscon-reboot@10000008 {
index 1a7efa883c5e3fd2e046b554485270036193b382..3ae16053a0c98763d8b8239eff18630105c2239a 100644 (file)
@@ -98,7 +98,7 @@
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7125-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x60c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index d4bf52cfcf170ee8ac84daa874495e0a6420e542..be7991917d2950f0d48d0c04dfd9b478856fcc35 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7346-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index 8e2501694d03fbd93827aeda79ef22f7cfd5d094..060805be619a23ac8812576a59a47fead67c98aa 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7358-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index 7e5f76040fb898b19a4bbc301c8a20f3b9368aa4..bcdb09bfe07ba3ed86369f9938ac50db678d250f 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7360-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index c739ea77acb0dfe17363ec52cf390cace407e54c..d3b1b762e6c3e21c3e129aea6127f071d4417845 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7362-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index 5f55d0a50a28622614ec6142eb0ff19746dfaade..3302a1b8a5c9b841b46b931ab501327aa2099b30 100644 (file)
@@ -99,7 +99,7 @@
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7420-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x60c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index e24d41ab4e30f9163605180d78605fc02a477db6..15b27aae15a9620e439de3e13162e16b2e8306b1 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index 8b9432cc062bc7e89898f2f1f2213926193389f8..adb33e3550430de99adb3b2e2c211310fabc65a9 100644 (file)
                sun_top_ctrl: syscon@404000 {
                        compatible = "brcm,bcm7425-sun-top-ctrl", "syscon";
                        reg = <0x404000 0x51c>;
-                       little-endian;
+                       native-endian;
                };
 
                reboot {
index 2b3487213d1e932247077d8b3f67ba28612f2683..441faa92c3cd488ac97685a1930597f7449a88f4 100644 (file)
@@ -144,4 +144,8 @@ static inline u32 ath79_reset_rr(unsigned reg)
 void ath79_device_reset_set(u32 mask);
 void ath79_device_reset_clear(u32 mask);
 
+void ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3);
+void ath79_misc_irq_init(void __iomem *regs, int irq,
+                       int irq_base, bool is_ar71xx);
+
 #endif /* __ASM_MACH_ATH79_H */
index 98c31e5d95793c68b50d594a5152bd0c2a730c82..8c16fb7b8fdbefd6fa9db170d4d1254bf44a9e4c 100644 (file)
@@ -102,7 +102,6 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
 #include <linux/scatterlist.h>
 #include <linux/string.h>
 #include <asm/io.h>
-#include <asm-generic/pci-bridge.h>
 
 struct pci_dev;
 
@@ -125,9 +124,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 
 #endif /* __KERNEL__ */
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 /* Do platform specific device initialization at pci_enable_device() time */
 extern int pcibios_plat_dev_init(struct pci_dev *dev);
 
index 6ba1fb8b11e225683cb32aafa959fdfcc73967c5..db7c322f057f936d9c658498a5e7d397303efb09 100644 (file)
@@ -44,8 +44,9 @@ static inline void plat_smp_setup(void)
        mp_ops->smp_setup();
 }
 
-extern void gic_send_ipi_single(int cpu, unsigned int action);
-extern void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action);
+extern void mips_smp_send_ipi_single(int cpu, unsigned int action);
+extern void mips_smp_send_ipi_mask(const struct cpumask *mask,
+                                     unsigned int action);
 
 #else /* !CONFIG_SMP */
 
index 8c6d76c9b2d69bf6603e32598e3b8d74cba15bf6..d9907e57e9b986f4d296c829c4cf0d5d8c995d38 100644 (file)
@@ -270,7 +270,7 @@ uint32_t jz_gpio_port_get_value(int port, uint32_t mask)
 }
 EXPORT_SYMBOL(jz_gpio_port_get_value);
 
-#define IRQ_TO_BIT(irq) BIT(irq_to_gpio(irq) & 0x1f)
+#define IRQ_TO_BIT(irq) BIT((irq - JZ4740_IRQ_GPIO(0)) & 0x1f)
 
 static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int irq)
 {
index 68e2b7db9348f1d168666411544a90bd080d0ae0..b0988fd62fcc3e6b6b296d3647cd9cdea39043f1 100644 (file)
@@ -52,7 +52,6 @@ obj-$(CONFIG_MIPS_MT_SMP)     += smp-mt.o
 obj-$(CONFIG_MIPS_CMP)         += smp-cmp.o
 obj-$(CONFIG_MIPS_CPS)         += smp-cps.o cps-vec.o
 obj-$(CONFIG_MIPS_CPS_NS16550) += cps-vec-ns16550.o
-obj-$(CONFIG_MIPS_GIC_IPI)     += smp-gic.o
 obj-$(CONFIG_MIPS_SPRAM)       += spram.o
 
 obj-$(CONFIG_MIPS_VPE_LOADER)  += vpe.o
index 5ce3b746cedc0bdea6e305cc72ef2121f0026053..b4ac6374a38f28e182b2558934ff979b88b33bb2 100644 (file)
@@ -125,7 +125,7 @@ LEAF(_restore_fp_context)
        END(_restore_fp_context)
        .set    reorder
 
-       .type   fault@function
+       .type   fault@function
        .ent    fault
 fault: li      v0, -EFAULT
        jr      ra
index f09546ee2cdc907dc02e4c391c103ba381e35a5e..17732f876eff1ad7e7e868f960304420e380db93 100644 (file)
@@ -358,7 +358,7 @@ LEAF(_restore_msa_all_upper)
 
        .set    reorder
 
-       .type   fault@function
+       .type   fault@function
        .ent    fault
 fault: li      v0, -EFAULT                             # failure
        jr      ra
index 5fdaf8bdcd2ebeed8e31eb7825edd958bfc1c251..4f607341a7938867efc6f0f0646c218bf168421b 100644 (file)
@@ -732,21 +732,23 @@ static void __init resource_init(void)
                        end = HIGHMEM_START - 1;
 
                res = alloc_bootmem(sizeof(struct resource));
+
+               res->start = start;
+               res->end = end;
+               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
                switch (boot_mem_map.map[i].type) {
                case BOOT_MEM_RAM:
                case BOOT_MEM_INIT_RAM:
                case BOOT_MEM_ROM_DATA:
                        res->name = "System RAM";
+                       res->flags |= IORESOURCE_SYSRAM;
                        break;
                case BOOT_MEM_RESERVED:
                default:
                        res->name = "reserved";
                }
 
-               res->start = start;
-               res->end = end;
-
-               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
                request_resource(&iomem_resource, res);
 
                /*
index d5e0f949dc480ba5659bc395e2cf5144b0832caf..76923349b4fe16135a97247734a9d803788ae5ca 100644 (file)
@@ -149,8 +149,8 @@ void __init cmp_prepare_cpus(unsigned int max_cpus)
 }
 
 struct plat_smp_ops cmp_smp_ops = {
-       .send_ipi_single        = gic_send_ipi_single,
-       .send_ipi_mask          = gic_send_ipi_mask,
+       .send_ipi_single        = mips_smp_send_ipi_single,
+       .send_ipi_mask          = mips_smp_send_ipi_mask,
        .init_secondary         = cmp_init_secondary,
        .smp_finish             = cmp_smp_finish,
        .boot_secondary         = cmp_boot_secondary,
index 2ad4e4c96d61cb02f8703d46efde1c596649a5df..253e1409338c146706ffb730952fb880c30e5b5d 100644 (file)
@@ -472,8 +472,8 @@ static struct plat_smp_ops cps_smp_ops = {
        .boot_secondary         = cps_boot_secondary,
        .init_secondary         = cps_init_secondary,
        .smp_finish             = cps_smp_finish,
-       .send_ipi_single        = gic_send_ipi_single,
-       .send_ipi_mask          = gic_send_ipi_mask,
+       .send_ipi_single        = mips_smp_send_ipi_single,
+       .send_ipi_mask          = mips_smp_send_ipi_mask,
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_disable            = cps_cpu_disable,
        .cpu_die                = cps_cpu_die,
index 86311a164ef1239487e6648e713d347432f750da..4f9570a57e8d8a354f48502f92d2d82b5907e3d3 100644 (file)
@@ -121,7 +121,7 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action)
 
 #ifdef CONFIG_MIPS_GIC
        if (gic_present) {
-               gic_send_ipi_single(cpu, action);
+               mips_smp_send_ipi_single(cpu, action);
                return;
        }
 #endif
index bd4385a8e6e86f7fbb9ca6d988f5eee155b9a8c7..37708d9af6381f8772c190569b5d64de40c7281d 100644 (file)
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/ftrace.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 
 #include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/idle.h>
 #include <asm/r4k-timer.h>
+#include <asm/mips-cpc.h>
 #include <asm/mmu_context.h>
 #include <asm/time.h>
 #include <asm/setup.h>
@@ -79,6 +83,11 @@ static cpumask_t cpu_core_setup_map;
 
 cpumask_t cpu_coherent_mask;
 
+#ifdef CONFIG_GENERIC_IRQ_IPI
+static struct irq_desc *call_desc;
+static struct irq_desc *sched_desc;
+#endif
+
 static inline void set_cpu_sibling_map(int cpu)
 {
        int i;
@@ -121,6 +130,7 @@ static inline void calculate_cpu_foreign_map(void)
        cpumask_t temp_foreign_map;
 
        /* Re-calculate the mask */
+       cpumask_clear(&temp_foreign_map);
        for_each_online_cpu(i) {
                core_present = 0;
                for_each_cpu(k, &temp_foreign_map)
@@ -145,6 +155,133 @@ void register_smp_ops(struct plat_smp_ops *ops)
        mp_ops = ops;
 }
 
+#ifdef CONFIG_GENERIC_IRQ_IPI
+void mips_smp_send_ipi_single(int cpu, unsigned int action)
+{
+       mips_smp_send_ipi_mask(cpumask_of(cpu), action);
+}
+
+void mips_smp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+       unsigned long flags;
+       unsigned int core;
+       int cpu;
+
+       local_irq_save(flags);
+
+       switch (action) {
+       case SMP_CALL_FUNCTION:
+               __ipi_send_mask(call_desc, mask);
+               break;
+
+       case SMP_RESCHEDULE_YOURSELF:
+               __ipi_send_mask(sched_desc, mask);
+               break;
+
+       default:
+               BUG();
+       }
+
+       if (mips_cpc_present()) {
+               for_each_cpu(cpu, mask) {
+                       core = cpu_data[cpu].core;
+
+                       if (core == current_cpu_data.core)
+                               continue;
+
+                       while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
+                               mips_cpc_lock_other(core);
+                               write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
+                               mips_cpc_unlock_other();
+                       }
+               }
+       }
+
+       local_irq_restore(flags);
+}
+
+
+static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
+{
+       scheduler_ipi();
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
+{
+       generic_smp_call_function_interrupt();
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction irq_resched = {
+       .handler        = ipi_resched_interrupt,
+       .flags          = IRQF_PERCPU,
+       .name           = "IPI resched"
+};
+
+static struct irqaction irq_call = {
+       .handler        = ipi_call_interrupt,
+       .flags          = IRQF_PERCPU,
+       .name           = "IPI call"
+};
+
+static __init void smp_ipi_init_one(unsigned int virq,
+                                   struct irqaction *action)
+{
+       int ret;
+
+       irq_set_handler(virq, handle_percpu_irq);
+       ret = setup_irq(virq, action);
+       BUG_ON(ret);
+}
+
+static int __init mips_smp_ipi_init(void)
+{
+       unsigned int call_virq, sched_virq;
+       struct irq_domain *ipidomain;
+       struct device_node *node;
+
+       node = of_irq_find_parent(of_root);
+       ipidomain = irq_find_matching_host(node, DOMAIN_BUS_IPI);
+
+       /*
+        * Some platforms have half DT setup. So if we found irq node but
+        * didn't find an ipidomain, try to search for one that is not in the
+        * DT.
+        */
+       if (node && !ipidomain)
+               ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI);
+
+       BUG_ON(!ipidomain);
+
+       call_virq = irq_reserve_ipi(ipidomain, cpu_possible_mask);
+       BUG_ON(!call_virq);
+
+       sched_virq = irq_reserve_ipi(ipidomain, cpu_possible_mask);
+       BUG_ON(!sched_virq);
+
+       if (irq_domain_is_ipi_per_cpu(ipidomain)) {
+               int cpu;
+
+               for_each_cpu(cpu, cpu_possible_mask) {
+                       smp_ipi_init_one(call_virq + cpu, &irq_call);
+                       smp_ipi_init_one(sched_virq + cpu, &irq_resched);
+               }
+       } else {
+               smp_ipi_init_one(call_virq, &irq_call);
+               smp_ipi_init_one(sched_virq, &irq_resched);
+       }
+
+       call_desc = irq_to_desc(call_virq);
+       sched_desc = irq_to_desc(sched_virq);
+
+       return 0;
+}
+early_initcall(mips_smp_ipi_init);
+#endif
+
 /*
  * First C code run on the secondary CPUs after being started up by
  * the master.
@@ -191,7 +328,7 @@ asmlinkage void start_secondary(void)
        WARN_ON_ONCE(!irqs_disabled());
        mp_ops->smp_finish();
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 static void stop_this_cpu(void *dummy)
index ae790c575d4fe2be7907714239e55f3b38e387cf..bf14da9f3e33b74473d2a23c3b3b388456c4bdc5 100644 (file)
@@ -690,15 +690,15 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
 asmlinkage void do_ov(struct pt_regs *regs)
 {
        enum ctx_state prev_state;
-       siginfo_t info;
+       siginfo_t info = {
+               .si_signo = SIGFPE,
+               .si_code = FPE_INTOVF,
+               .si_addr = (void __user *)regs->cp0_epc,
+       };
 
        prev_state = exception_enter();
        die_if_kernel("Integer overflow", regs);
 
-       info.si_code = FPE_INTOVF;
-       info.si_signo = SIGFPE;
-       info.si_errno = 0;
-       info.si_addr = (void __user *) regs->cp0_epc;
        force_sig_info(SIGFPE, &info, current);
        exception_exit(prev_state);
 }
@@ -874,7 +874,7 @@ out:
 void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
        const char *str)
 {
-       siginfo_t info;
+       siginfo_t info = { 0 };
        char b[40];
 
 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
@@ -903,7 +903,6 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code,
                else
                        info.si_code = FPE_INTOVF;
                info.si_signo = SIGFPE;
-               info.si_errno = 0;
                info.si_addr = (void __user *) regs->cp0_epc;
                force_sig_info(SIGFPE, &info, current);
                break;
index 8bc3977576e6af5f7b5c1a17f306da0f21b26937..70ef1a43c1148343101f2603a019fcefc1f90bce 100644 (file)
@@ -445,8 +445,8 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
 
        dvcpu->arch.wait = 0;
 
-       if (waitqueue_active(&dvcpu->wq))
-               wake_up_interruptible(&dvcpu->wq);
+       if (swait_active(&dvcpu->wq))
+               swake_up(&dvcpu->wq);
 
        return 0;
 }
@@ -702,7 +702,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
        } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
                void __user *uaddr = (void __user *)(long)reg->addr;
 
-               return copy_to_user(uaddr, vs, 16);
+               return copy_to_user(uaddr, vs, 16) ? -EFAULT : 0;
        } else {
                return -EINVAL;
        }
@@ -732,7 +732,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
        } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
                void __user *uaddr = (void __user *)(long)reg->addr;
 
-               return copy_from_user(vs, uaddr, 16);
+               return copy_from_user(vs, uaddr, 16) ? -EFAULT : 0;
        } else {
                return -EINVAL;
        }
@@ -1174,8 +1174,8 @@ static void kvm_mips_comparecount_func(unsigned long data)
        kvm_mips_callbacks->queue_timer_int(vcpu);
 
        vcpu->arch.wait = 0;
-       if (waitqueue_active(&vcpu->wq))
-               wake_up_interruptible(&vcpu->wq);
+       if (swait_active(&vcpu->wq))
+               swake_up(&vcpu->wq);
 }
 
 /* low level hrtimer wake routine */
index 5c81fdd032c3b1269549f27e27348e9606eb5424..353037699512ca5515b11ce8fb2c808eb6386c78 100644 (file)
@@ -146,7 +146,7 @@ unsigned long arch_mmap_rnd(void)
 {
        unsigned long rnd;
 
-       rnd = (unsigned long)get_random_int();
+       rnd = get_random_long();
        rnd <<= PAGE_SHIFT;
        if (TASK_IS_32BIT_ADDR)
                rnd &= 0xfffffful;
@@ -174,7 +174,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 static inline unsigned long brk_rnd(void)
 {
-       unsigned long rnd = get_random_int();
+       unsigned long rnd = get_random_long();
 
        rnd = rnd << PAGE_SHIFT;
        /* 8MB for 32bit, 256MB for 64bit */
index 249647578e587580eb1b528a5af7540ee13f19d2..91dec32c77b722a838ce9ca352d89ca3939fba2b 100644 (file)
@@ -164,11 +164,13 @@ static int __init mips_sc_probe_cm3(void)
 
        sets = cfg & CM_GCR_L2_CONFIG_SET_SIZE_MSK;
        sets >>= CM_GCR_L2_CONFIG_SET_SIZE_SHF;
-       c->scache.sets = 64 << sets;
+       if (sets)
+               c->scache.sets = 64 << sets;
 
        line_sz = cfg & CM_GCR_L2_CONFIG_LINE_SIZE_MSK;
        line_sz >>= CM_GCR_L2_CONFIG_LINE_SIZE_SHF;
-       c->scache.linesz = 2 << line_sz;
+       if (line_sz)
+               c->scache.linesz = 2 << line_sz;
 
        assoc = cfg & CM_GCR_L2_CONFIG_ASSOC_MSK;
        assoc >>= CM_GCR_L2_CONFIG_ASSOC_SHF;
@@ -176,9 +178,12 @@ static int __init mips_sc_probe_cm3(void)
        c->scache.waysize = c->scache.sets * c->scache.linesz;
        c->scache.waybit = __ffs(c->scache.waysize);
 
-       c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+       if (c->scache.linesz) {
+               c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
+               return 1;
+       }
 
-       return 1;
+       return 0;
 }
 
 static inline int __init mips_sc_probe(void)
index d708ae46d32532a38f5e3356ca291106524990a6..2b6d5e196f9990255eb5d35de3e6580a69f6003f 100644 (file)
@@ -40,20 +40,25 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 
 static void pci_fixup_radeon(struct pci_dev *pdev)
 {
-       if (pdev->resource[PCI_ROM_RESOURCE].start)
+       struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
+
+       if (res->start)
                return;
 
        if (!loongson_sysconf.vgabios_addr)
                return;
 
-       pdev->resource[PCI_ROM_RESOURCE].start =
-               loongson_sysconf.vgabios_addr;
-       pdev->resource[PCI_ROM_RESOURCE].end   =
-               loongson_sysconf.vgabios_addr + 256*1024 - 1;
-       pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_COPY;
+       pci_disable_rom(pdev);
+       if (res->parent)
+               release_resource(res);
+
+       res->start = virt_to_phys((void *) loongson_sysconf.vgabios_addr);
+       res->end   = res->start + 256*1024 - 1;
+       res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
+                    IORESOURCE_PCI_FIXED;
 
        dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n",
-                       PCI_ROM_RESOURCE, &pdev->resource[PCI_ROM_RESOURCE]);
+                PCI_ROM_RESOURCE, res);
 }
 
 DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
index be3debb8fc02b1a1befbe6230249a6733aa98cfb..51159fff025ab8fad129efdd6adba0f99c38db25 100644 (file)
@@ -80,9 +80,6 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 
 #endif /* __KERNEL__ */
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
        return channel ? 15 : 14;
index f984193718b1003f03861e79cd137b4a8c23badd..426173c4b0b900c0315431ef1104932aa5f867a7 100644 (file)
@@ -675,7 +675,7 @@ int __init start_secondary(void *unused)
 #ifdef CONFIG_GENERIC_CLOCKEVENTS
        init_clockevents();
 #endif
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
        return 0;
 }
 
index 3d0e17bcc8e905ece06053ae15b3ff5443e6b033..df0f52bd18b457f9efa1a0b9fc470b0803f50632 100644 (file)
@@ -22,6 +22,9 @@
 
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
+/* Read-only memory is marked before mark_rodata_ro() is called. */
+#define __ro_after_init        __read_mostly
+
 void parisc_cache_init(void);  /* initializes cache-flushing */
 void disable_sr_hashing_asm(int); /* low level support for above */
 void disable_sr_hashing(void);   /* turns off space register hashing */
index 845272ce9cc587222e835131bb5ed96be0be03d4..7bd69bd43a018577d099f373346383900b1f0121 100644 (file)
@@ -121,10 +121,6 @@ flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vma
        }
 }
 
-#ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
-#endif
-
 #include <asm/kmap_types.h>
 
 #define ARCH_HAS_KMAP
index f84ff12574b7375f0d08396047aca4f7fc22854f..6d8276cd25cad289b838bf20df02b6bcd8a06bb8 100644 (file)
@@ -33,7 +33,7 @@
  * floppy accesses go through the track buffer.
  */
 #define _CROSS_64KB(a,s,vdma) \
-(!vdma && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
+(!(vdma) && ((unsigned long)(a)/K_64 != ((unsigned long)(a) + (s) - 1) / K_64))
 
 #define CROSS_64KB(a,s) _CROSS_64KB(a,s,use_virtual_dma & 1)
 
index 89c53bfff05547641fa55e8035c8311d653658c2..defebd956585495bf4b33117989bf05dd8699685 100644 (file)
@@ -194,9 +194,6 @@ extern void pcibios_init_bridge(struct pci_dev *);
 #define PCIBIOS_MIN_IO          0x10
 #define PCIBIOS_MIN_MEM         0x1000 /* NBPG - but pci/setup-res.c dies */
 
-/* export the pci_ DMA API in terms of the dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
        return channel ? 15 : 14;
index 35bdccbb203622e116f288741ac4a9bc173034b0..b75039f9211645becb970599deeaafe257b86001 100644 (file)
 #define __NR_membarrier                (__NR_Linux + 343)
 #define __NR_userfaultfd       (__NR_Linux + 344)
 #define __NR_mlock2            (__NR_Linux + 345)
+#define __NR_copy_file_range   (__NR_Linux + 346)
 
-#define __NR_Linux_syscalls    (__NR_mlock2 + 1)
+#define __NR_Linux_syscalls    (__NR_copy_file_range + 1)
 
 
 #define __IGNORE_select                /* newselect */
index 9585c81f755fc667370ed850cba16ee1ff91024c..ce0b2b4075c704f9ee2006c263b1ba1cf3e9afd1 100644 (file)
@@ -269,14 +269,19 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 long do_syscall_trace_enter(struct pt_regs *regs)
 {
-       long ret = 0;
-
        /* Do the secure computing check first. */
        secure_computing_strict(regs->gr[20]);
 
        if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-           tracehook_report_syscall_entry(regs))
-               ret = -1L;
+           tracehook_report_syscall_entry(regs)) {
+               /*
+                * Tracing decided this syscall should not happen or the
+                * debugger stored an invalid system call number. Skip
+                * the system call and the system call restart handling.
+                */
+               regs->gr[20] = -1UL;
+               goto out;
+       }
 
 #ifdef CONFIG_64BIT
        if (!is_compat_task())
@@ -290,7 +295,8 @@ long do_syscall_trace_enter(struct pt_regs *regs)
                        regs->gr[24] & 0xffffffff,
                        regs->gr[23] & 0xffffffff);
 
-       return ret ? : regs->gr[20];
+out:
+       return regs->gr[20];
 }
 
 void do_syscall_trace_exit(struct pt_regs *regs)
index 52e85973a283c96dff805586a19fa066ade0573e..c2a9cc55a62f63709e1d1e1b78d9a086ac3a2bf7 100644 (file)
@@ -305,7 +305,7 @@ void __init smp_callin(void)
 
        local_irq_enable();  /* Interrupts have been off until now */
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 
        /* NOTREACHED */
        panic("smp_callin() AAAAaaaaahhhh....\n");
index 3fbd7252a4b27efd106250f5b21e98910f8af8bd..fbafa0d0e2bf865db726d15f9c4beb4817afe86c 100644 (file)
@@ -343,7 +343,7 @@ tracesys_next:
 #endif
 
        comiclr,>>=     __NR_Linux_syscalls, %r20, %r0
-       b,n     .Lsyscall_nosys
+       b,n     .Ltracesys_nosys
 
        LDREGX  %r20(%r19), %r19
 
@@ -359,6 +359,9 @@ tracesys_next:
        be      0(%sr7,%r19)
        ldo     R%tracesys_exit(%r2),%r2
 
+.Ltracesys_nosys:
+       ldo     -ENOSYS(%r0),%r28               /* set errno */
+
        /* Do *not* call this function on the gateway page, because it
        makes a direct call to syscall_trace. */
        
index d4ffcfbc98851e7c3f0707ec9d82470d918bed2e..585d50fc75c0f9776cf2bca74651387790ab6c22 100644 (file)
        ENTRY_SAME(membarrier)
        ENTRY_SAME(userfaultfd)
        ENTRY_SAME(mlock2)              /* 345 */
+       ENTRY_SAME(copy_file_range)
 
 
 .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b))
index 1b366c47768722081efe57a9db39eaba2a7dcde9..3c07d6b968772bc6de99bada8d83578ffe172c3d 100644 (file)
@@ -55,12 +55,12 @@ signed char pfnnid_map[PFNNID_MAP_MAX] __read_mostly;
 
 static struct resource data_resource = {
        .name   = "Kernel data",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
 };
 
 static struct resource code_resource = {
        .name   = "Kernel code",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
 };
 
 static struct resource pdcdata_resource = {
@@ -201,7 +201,7 @@ static void __init setup_bootmem(void)
                res->name = "System RAM";
                res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT;
                res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1;
-               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
                request_resource(&iomem_resource, res);
        }
 
index 9faa18c4f3f702adceb4f555b05b72bc8437cf6c..832cc461d0afab57046ef6b7e1b68b471a9ce69c 100644 (file)
@@ -828,14 +828,10 @@ config PCI_8260
        select PPC_INDIRECT_PCI
        default y
 
-source "drivers/pci/pcie/Kconfig"
-
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 config HAS_RAPIDIO
        bool
        default n
index 2aa79c864e91520ed563efd312c657f89696adc1..7529aab068f5968a8a093ba2ddb5f42e9ab5b61c 100644 (file)
@@ -33,8 +33,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
 }
 #endif
 
-#define SPAPR_TCE_SHIFT                12
-
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 #define KVM_DEFAULT_HPT_ORDER  24      /* 16MB HPT by default */
 #endif
index 9d08d8cbed1a1ec0e5893679c5e1fd9cb69dce09..d7b343170453df82b4f31429020c8680e1f949bf 100644 (file)
@@ -182,7 +182,10 @@ struct kvmppc_spapr_tce_table {
        struct list_head list;
        struct kvm *kvm;
        u64 liobn;
-       u32 window_size;
+       struct rcu_head rcu;
+       u32 page_shift;
+       u64 offset;             /* in pages */
+       u64 size;               /* window size in pages */
        struct page *pages[0];
 };
 
@@ -289,7 +292,7 @@ struct kvmppc_vcore {
        struct list_head runnable_threads;
        struct list_head preempt_list;
        spinlock_t lock;
-       wait_queue_head_t wq;
+       struct swait_queue_head wq;
        spinlock_t stoltb_lock; /* protects stolen_tb and preempt_tb */
        u64 stolen_tb;
        u64 preempt_tb;
@@ -629,7 +632,7 @@ struct kvm_vcpu_arch {
        u8 prodded;
        u32 last_inst;
 
-       wait_queue_head_t *wqp;
+       struct swait_queue_head *wqp;
        struct kvmppc_vcore *vcore;
        int ret;
        int trap;
index 2241d53571291a4ba24fcd40ab800d74aaa039ba..2544edabe7f392f1edb25fdf0c1c79a146b1c28b 100644 (file)
@@ -165,9 +165,25 @@ extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,
 extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
 
 extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
-                               struct kvm_create_spapr_tce *args);
+                               struct kvm_create_spapr_tce_64 *args);
+extern struct kvmppc_spapr_tce_table *kvmppc_find_table(
+               struct kvm_vcpu *vcpu, unsigned long liobn);
+extern long kvmppc_ioba_validate(struct kvmppc_spapr_tce_table *stt,
+               unsigned long ioba, unsigned long npages);
+extern long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *tt,
+               unsigned long tce);
+extern long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa,
+               unsigned long *ua, unsigned long **prmap);
+extern void kvmppc_tce_put(struct kvmppc_spapr_tce_table *tt,
+               unsigned long idx, unsigned long tce);
 extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
                             unsigned long ioba, unsigned long tce);
+extern long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+               unsigned long liobn, unsigned long ioba,
+               unsigned long tce_list, unsigned long npages);
+extern long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu,
+               unsigned long liobn, unsigned long ioba,
+               unsigned long tce_value, unsigned long npages);
 extern long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
                             unsigned long ioba);
 extern struct page *kvm_alloc_hpt(unsigned long nr_pages);
@@ -437,6 +453,8 @@ static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.irq_type == KVMPPC_IRQ_XICS;
 }
+extern void kvmppc_alloc_host_rm_ops(void);
+extern void kvmppc_free_host_rm_ops(void);
 extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu);
 extern int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu, unsigned long server);
 extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args);
@@ -445,7 +463,11 @@ extern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu);
 extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
 extern int kvmppc_xics_connect_vcpu(struct kvm_device *dev,
                        struct kvm_vcpu *vcpu, u32 cpu);
+extern void kvmppc_xics_ipi_action(void);
+extern int h_ipi_redirect;
 #else
+static inline void kvmppc_alloc_host_rm_ops(void) {};
+static inline void kvmppc_free_host_rm_ops(void) {};
 static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
        { return 0; }
 static inline void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { }
@@ -459,6 +481,33 @@ static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
        { return 0; }
 #endif
 
+/*
+ * Host-side operations we want to set up while running in real
+ * mode in the guest operating on the xics.
+ * Currently only VCPU wakeup is supported.
+ */
+
+union kvmppc_rm_state {
+       unsigned long raw;
+       struct {
+               u32 in_host;
+               u32 rm_action;
+       };
+};
+
+struct kvmppc_host_rm_core {
+       union kvmppc_rm_state rm_state;
+       void *rm_data;
+       char pad[112];
+};
+
+struct kvmppc_host_rm_ops {
+       struct kvmppc_host_rm_core      *rm_core;
+       void            (*vcpu_kick)(struct kvm_vcpu *vcpu);
+};
+
+extern struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv;
+
 static inline unsigned long kvmppc_get_epr(struct kvm_vcpu *vcpu)
 {
 #ifdef CONFIG_KVM_BOOKE_HV
index 54843ca5fa2bfa03871f28a3854b0d87f5685a76..78968c1ff931941d8244364cedd7f664f352e763 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/pci.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
-#include <asm-generic/pci-bridge.h>
 
 struct device_node;
 
index 6f8065a7d487f3e72609c98cfd8a348853ee87d8..a6f3ac0d4602fd8b0ecb2db73ea3d6b52ef46efe 100644 (file)
@@ -20,8 +20,6 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 
-#include <asm-generic/pci-dma-compat.h>
-
 /* Return values for pci_controller_ops.probe_mode function */
 #define PCI_PROBE_NONE         -1      /* Don't look at this bus at all */
 #define PCI_PROBE_NORMAL       0       /* Do normal PCI probing */
index ac9fb114e25d4301e439c212b469270edc7ce6d5..47897a30982d6aee476c5be51c7e81ada53158a5 100644 (file)
@@ -78,6 +78,9 @@ static inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
        }
        return __find_linux_pte_or_hugepte(pgdir, ea, is_thp, shift);
 }
+
+unsigned long vmalloc_to_phys(void *vmalloc_addr);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_PGTABLE_H */
index 825663c309450ea22c39d38a3d8fb9cd2b20736e..78083ed20792f63844ad82941168c1f9d005f1b5 100644 (file)
@@ -114,6 +114,9 @@ extern int cpu_to_core_id(int cpu);
 #define PPC_MSG_TICK_BROADCAST 2
 #define PPC_MSG_DEBUGGER_BREAK  3
 
+/* This is only used by the powernv kernel */
+#define PPC_MSG_RM_HOST_ACTION 4
+
 /* for irq controllers that have dedicated ipis per message (4) */
 extern int smp_request_message_ipi(int virq, int message);
 extern const char *smp_ipi_name[];
@@ -121,6 +124,7 @@ extern const char *smp_ipi_name[];
 /* for irq controllers with only a single ipi */
 extern void smp_muxed_ipi_set_data(int cpu, unsigned long data);
 extern void smp_muxed_ipi_message_pass(int cpu, int msg);
+extern void smp_muxed_ipi_set_message(int cpu, int msg);
 extern irqreturn_t smp_ipi_demux(void);
 
 void smp_init_pSeries(void);
index 0e25bdb190bbb8edd92376d7c6a55a730dc84a48..254604856e69e1cb1ced217b4191b21b664834ba 100644 (file)
@@ -30,6 +30,7 @@
 #ifdef CONFIG_PPC_ICP_NATIVE
 extern int icp_native_init(void);
 extern void icp_native_flush_interrupt(void);
+extern void icp_native_cause_ipi_rm(int cpu);
 #else
 static inline int icp_native_init(void) { return -ENODEV; }
 #endif
index ab4d4732c492ebc4dd9514733cbb8461af0dbf87..c93cf35ce379550e37bcfe1d127def78af7de11c 100644 (file)
@@ -333,6 +333,15 @@ struct kvm_create_spapr_tce {
        __u32 window_size;
 };
 
+/* for KVM_CAP_SPAPR_TCE_64 */
+struct kvm_create_spapr_tce_64 {
+       __u64 liobn;
+       __u32 page_shift;
+       __u32 flags;
+       __u64 offset;   /* in pages */
+       __u64 size;     /* in pages */
+};
+
 /* for KVM_ALLOCATE_RMA */
 struct kvm_allocate_rma {
        __u64 rma_size;
index 301be3126ae3e1bcbe6b3f8aabce07d2416c89e9..650cfb31ea3d9b3cee0301948bd85e54400cb951 100644 (file)
@@ -418,8 +418,7 @@ static void *eeh_rmv_device(void *data, void *userdata)
                eeh_pcid_put(dev);
                if (driver->err_handler &&
                    driver->err_handler->error_detected &&
-                   driver->err_handler->slot_reset &&
-                   driver->err_handler->resume)
+                   driver->err_handler->slot_reset)
                        return NULL;
        }
 
index 05e804cdecaa975dc6546ba251bbb61772f72219..aec9a1b1d25bc5a1d998b2a4f099176f9c48934d 100644 (file)
@@ -109,8 +109,9 @@ void arch_unregister_hw_breakpoint(struct perf_event *bp)
         * If the breakpoint is unregistered between a hw_breakpoint_handler()
         * and the single_step_dabr_instruction(), then cleanup the breakpoint
         * restoration variables to prevent dangling pointers.
+        * FIXME, this should not be using bp->ctx at all! Sayeth peterz.
         */
-       if (bp->ctx && bp->ctx->task)
+       if (bp->ctx && bp->ctx->task && bp->ctx->task != ((void *)-1L))
                bp->ctx->task->thread.last_hit_ubp = NULL;
 }
 
index dccc87e8fee5e6544de0d8fc732a97aa14f45907..3c5736e52a14b7d42dd0c28425e709b0a7147c3c 100644 (file)
@@ -1768,9 +1768,9 @@ static inline unsigned long brk_rnd(void)
 
        /* 8MB for 32bit, 1GB for 64bit */
        if (is_32bit_task())
-               rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
+               rnd = (get_random_long() % (1UL<<(23-PAGE_SHIFT)));
        else
-               rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
+               rnd = (get_random_long() % (1UL<<(30-PAGE_SHIFT)));
 
        return rnd << PAGE_SHIFT;
 }
index ad8c9db61237223c3b807e3a9afed1487c44af1e..d544fa31175766bf48790f75bcd5458d6a505080 100644 (file)
@@ -114,8 +114,6 @@ extern unsigned int memset_nocache_branch; /* Insn to be replaced by NOP */
 
 notrace void __init machine_init(u64 dt_ptr)
 {
-       lockdep_init();
-
        /* Enable early debugging if any specified (see udbg.h) */
        udbg_early_init();
 
index 5c03a6a9b0542fac3d042f2481f367aae9178d38..f98be8383a39994868ba41d0f8492e99f48eb1fe 100644 (file)
@@ -255,9 +255,6 @@ void __init early_setup(unsigned long dt_ptr)
        setup_paca(&boot_paca);
        fixup_boot_paca();
 
-       /* Initialize lockdep early or else spinlocks will blow */
-       lockdep_init();
-
        /* -------- printk is now safe to use ------- */
 
        /* Enable early debugging if any specified (see udbg.h) */
index ec9ec2058d2d3f3ec6db2dfbe25b35ab1f4cfb0b..b7dea05f07259558089205cebef69f40a7985a2f 100644 (file)
@@ -206,7 +206,7 @@ int smp_request_message_ipi(int virq, int msg)
 
 #ifdef CONFIG_PPC_SMP_MUXED_IPI
 struct cpu_messages {
-       int messages;                   /* current messages */
+       long messages;                  /* current messages */
        unsigned long data;             /* data for cause ipi */
 };
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_messages, ipi_message);
@@ -218,7 +218,7 @@ void smp_muxed_ipi_set_data(int cpu, unsigned long data)
        info->data = data;
 }
 
-void smp_muxed_ipi_message_pass(int cpu, int msg)
+void smp_muxed_ipi_set_message(int cpu, int msg)
 {
        struct cpu_messages *info = &per_cpu(ipi_message, cpu);
        char *message = (char *)&info->messages;
@@ -228,6 +228,13 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
         */
        smp_mb();
        message[msg] = 1;
+}
+
+void smp_muxed_ipi_message_pass(int cpu, int msg)
+{
+       struct cpu_messages *info = &per_cpu(ipi_message, cpu);
+
+       smp_muxed_ipi_set_message(cpu, msg);
        /*
         * cause_ipi functions are required to include a full barrier
         * before doing whatever causes the IPI.
@@ -236,20 +243,31 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
 }
 
 #ifdef __BIG_ENDIAN__
-#define IPI_MESSAGE(A) (1 << (24 - 8 * (A)))
+#define IPI_MESSAGE(A) (1uL << ((BITS_PER_LONG - 8) - 8 * (A)))
 #else
-#define IPI_MESSAGE(A) (1 << (8 * (A)))
+#define IPI_MESSAGE(A) (1uL << (8 * (A)))
 #endif
 
 irqreturn_t smp_ipi_demux(void)
 {
        struct cpu_messages *info = this_cpu_ptr(&ipi_message);
-       unsigned int all;
+       unsigned long all;
 
        mb();   /* order any irq clear */
 
        do {
                all = xchg(&info->messages, 0);
+#if defined(CONFIG_KVM_XICS) && defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)
+               /*
+                * Must check for PPC_MSG_RM_HOST_ACTION messages
+                * before PPC_MSG_CALL_FUNCTION messages because when
+                * a VM is destroyed, we call kick_all_cpus_sync()
+                * to ensure that any pending PPC_MSG_RM_HOST_ACTION
+                * messages have completed before we free any VCPUs.
+                */
+               if (all & IPI_MESSAGE(PPC_MSG_RM_HOST_ACTION))
+                       kvmppc_xics_ipi_action();
+#endif
                if (all & IPI_MESSAGE(PPC_MSG_CALL_FUNCTION))
                        generic_smp_call_function_interrupt();
                if (all & IPI_MESSAGE(PPC_MSG_RESCHEDULE))
@@ -727,7 +745,7 @@ void start_secondary(void *unused)
 
        local_irq_enable();
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 
        BUG();
 }
index 0570eef83fba59f2e1613c0db8571bd92e2da992..7f7b6d86ac731af7241e4ce343a4ed6a8e0542c8 100644 (file)
@@ -8,7 +8,7 @@ ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm
 KVM := ../../../virt/kvm
 
 common-objs-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
-               $(KVM)/eventfd.o
+               $(KVM)/eventfd.o $(KVM)/vfio.o
 
 CFLAGS_e500_mmu.o := -I.
 CFLAGS_e500_mmu_host.o := -I.
index 638c6d9be9e08bec96542312aaf18ce8e21900e6..b34220d2aa42c96380b8f2d8fcbe1de630f5c31e 100644 (file)
@@ -807,7 +807,7 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 {
 
 #ifdef CONFIG_PPC64
-       INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
+       INIT_LIST_HEAD_RCU(&kvm->arch.spapr_tce_tables);
        INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
 #endif
 
index 54cf9bc94dadfe3a1debf64f03cea511fc0aa97b..2c2d1030843acf5736e4ac0dd08c87b3522f2b17 100644 (file)
@@ -14,6 +14,7 @@
  *
  * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  * Copyright 2011 David Gibson, IBM Corporation <dwg@au1.ibm.com>
+ * Copyright 2016 Alexey Kardashevskiy, IBM Corporation <aik@au1.ibm.com>
  */
 
 #include <linux/types.h>
 #include <asm/ppc-opcode.h>
 #include <asm/kvm_host.h>
 #include <asm/udbg.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
 
-#define TCES_PER_PAGE  (PAGE_SIZE / sizeof(u64))
+static unsigned long kvmppc_tce_pages(unsigned long iommu_pages)
+{
+       return ALIGN(iommu_pages * sizeof(u64), PAGE_SIZE) / PAGE_SIZE;
+}
 
-static long kvmppc_stt_npages(unsigned long window_size)
+static unsigned long kvmppc_stt_pages(unsigned long tce_pages)
 {
-       return ALIGN((window_size >> SPAPR_TCE_SHIFT)
-                    * sizeof(u64), PAGE_SIZE) / PAGE_SIZE;
+       unsigned long stt_bytes = sizeof(struct kvmppc_spapr_tce_table) +
+                       (tce_pages * sizeof(struct page *));
+
+       return tce_pages + ALIGN(stt_bytes, PAGE_SIZE) / PAGE_SIZE;
 }
 
-static void release_spapr_tce_table(struct kvmppc_spapr_tce_table *stt)
+static long kvmppc_account_memlimit(unsigned long stt_pages, bool inc)
 {
-       struct kvm *kvm = stt->kvm;
-       int i;
+       long ret = 0;
 
-       mutex_lock(&kvm->lock);
-       list_del(&stt->list);
-       for (i = 0; i < kvmppc_stt_npages(stt->window_size); i++)
+       if (!current || !current->mm)
+               return ret; /* process exited */
+
+       down_write(&current->mm->mmap_sem);
+
+       if (inc) {
+               unsigned long locked, lock_limit;
+
+               locked = current->mm->locked_vm + stt_pages;
+               lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+               if (locked > lock_limit && !capable(CAP_IPC_LOCK))
+                       ret = -ENOMEM;
+               else
+                       current->mm->locked_vm += stt_pages;
+       } else {
+               if (WARN_ON_ONCE(stt_pages > current->mm->locked_vm))
+                       stt_pages = current->mm->locked_vm;
+
+               current->mm->locked_vm -= stt_pages;
+       }
+
+       pr_debug("[%d] RLIMIT_MEMLOCK KVM %c%ld %ld/%ld%s\n", current->pid,
+                       inc ? '+' : '-',
+                       stt_pages << PAGE_SHIFT,
+                       current->mm->locked_vm << PAGE_SHIFT,
+                       rlimit(RLIMIT_MEMLOCK),
+                       ret ? " - exceeded" : "");
+
+       up_write(&current->mm->mmap_sem);
+
+       return ret;
+}
+
+static void release_spapr_tce_table(struct rcu_head *head)
+{
+       struct kvmppc_spapr_tce_table *stt = container_of(head,
+                       struct kvmppc_spapr_tce_table, rcu);
+       unsigned long i, npages = kvmppc_tce_pages(stt->size);
+
+       for (i = 0; i < npages; i++)
                __free_page(stt->pages[i]);
-       kfree(stt);
-       mutex_unlock(&kvm->lock);
 
-       kvm_put_kvm(kvm);
+       kfree(stt);
 }
 
 static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -65,7 +107,7 @@ static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        struct kvmppc_spapr_tce_table *stt = vma->vm_file->private_data;
        struct page *page;
 
-       if (vmf->pgoff >= kvmppc_stt_npages(stt->window_size))
+       if (vmf->pgoff >= kvmppc_tce_pages(stt->size))
                return VM_FAULT_SIGBUS;
 
        page = stt->pages[vmf->pgoff];
@@ -88,7 +130,14 @@ static int kvm_spapr_tce_release(struct inode *inode, struct file *filp)
 {
        struct kvmppc_spapr_tce_table *stt = filp->private_data;
 
-       release_spapr_tce_table(stt);
+       list_del_rcu(&stt->list);
+
+       kvm_put_kvm(stt->kvm);
+
+       kvmppc_account_memlimit(
+               kvmppc_stt_pages(kvmppc_tce_pages(stt->size)), false);
+       call_rcu(&stt->rcu, release_spapr_tce_table);
+
        return 0;
 }
 
@@ -98,20 +147,29 @@ static const struct file_operations kvm_spapr_tce_fops = {
 };
 
 long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
-                                  struct kvm_create_spapr_tce *args)
+                                  struct kvm_create_spapr_tce_64 *args)
 {
        struct kvmppc_spapr_tce_table *stt = NULL;
-       long npages;
+       unsigned long npages, size;
        int ret = -ENOMEM;
        int i;
 
+       if (!args->size)
+               return -EINVAL;
+
        /* Check this LIOBN hasn't been previously allocated */
        list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
                if (stt->liobn == args->liobn)
                        return -EBUSY;
        }
 
-       npages = kvmppc_stt_npages(args->window_size);
+       size = args->size;
+       npages = kvmppc_tce_pages(size);
+       ret = kvmppc_account_memlimit(kvmppc_stt_pages(npages), true);
+       if (ret) {
+               stt = NULL;
+               goto fail;
+       }
 
        stt = kzalloc(sizeof(*stt) + npages * sizeof(struct page *),
                      GFP_KERNEL);
@@ -119,7 +177,9 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
                goto fail;
 
        stt->liobn = args->liobn;
-       stt->window_size = args->window_size;
+       stt->page_shift = args->page_shift;
+       stt->offset = args->offset;
+       stt->size = size;
        stt->kvm = kvm;
 
        for (i = 0; i < npages; i++) {
@@ -131,7 +191,7 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
        kvm_get_kvm(kvm);
 
        mutex_lock(&kvm->lock);
-       list_add(&stt->list, &kvm->arch.spapr_tce_tables);
+       list_add_rcu(&stt->list, &kvm->arch.spapr_tce_tables);
 
        mutex_unlock(&kvm->lock);
 
@@ -148,3 +208,59 @@ fail:
        }
        return ret;
 }
+
+long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+               unsigned long liobn, unsigned long ioba,
+               unsigned long tce_list, unsigned long npages)
+{
+       struct kvmppc_spapr_tce_table *stt;
+       long i, ret = H_SUCCESS, idx;
+       unsigned long entry, ua = 0;
+       u64 __user *tces, tce;
+
+       stt = kvmppc_find_table(vcpu, liobn);
+       if (!stt)
+               return H_TOO_HARD;
+
+       entry = ioba >> stt->page_shift;
+       /*
+        * SPAPR spec says that the maximum size of the list is 512 TCEs
+        * so the whole table fits in 4K page
+        */
+       if (npages > 512)
+               return H_PARAMETER;
+
+       if (tce_list & (SZ_4K - 1))
+               return H_PARAMETER;
+
+       ret = kvmppc_ioba_validate(stt, ioba, npages);
+       if (ret != H_SUCCESS)
+               return ret;
+
+       idx = srcu_read_lock(&vcpu->kvm->srcu);
+       if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, NULL)) {
+               ret = H_TOO_HARD;
+               goto unlock_exit;
+       }
+       tces = (u64 __user *) ua;
+
+       for (i = 0; i < npages; ++i) {
+               if (get_user(tce, tces + i)) {
+                       ret = H_TOO_HARD;
+                       goto unlock_exit;
+               }
+               tce = be64_to_cpu(tce);
+
+               ret = kvmppc_tce_validate(stt, tce);
+               if (ret != H_SUCCESS)
+                       goto unlock_exit;
+
+               kvmppc_tce_put(stt, entry + i, tce);
+       }
+
+unlock_exit:
+       srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(kvmppc_h_put_tce_indirect);
index 89e96b3e00398d0fb45bd841924a7f6b541f6718..44be73e6aa26b6563d1cc4cc91e1a332a84271c3 100644 (file)
@@ -14,6 +14,7 @@
  *
  * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  * Copyright 2011 David Gibson, IBM Corporation <dwg@au1.ibm.com>
+ * Copyright 2016 Alexey Kardashevskiy, IBM Corporation <aik@au1.ibm.com>
  */
 
 #include <linux/types.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
 #include <asm/mmu-hash64.h>
+#include <asm/mmu_context.h>
 #include <asm/hvcall.h>
 #include <asm/synch.h>
 #include <asm/ppc-opcode.h>
 #include <asm/kvm_host.h>
 #include <asm/udbg.h>
+#include <asm/iommu.h>
+#include <asm/tce.h>
+#include <asm/iommu.h>
 
 #define TCES_PER_PAGE  (PAGE_SIZE / sizeof(u64))
 
-/* WARNING: This will be called in real-mode on HV KVM and virtual
+/*
+ * Finds a TCE table descriptor by LIOBN.
+ *
+ * WARNING: This will be called in real or virtual mode on HV KVM and virtual
  *          mode on PR KVM
  */
-long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
-                     unsigned long ioba, unsigned long tce)
+struct kvmppc_spapr_tce_table *kvmppc_find_table(struct kvm_vcpu *vcpu,
+               unsigned long liobn)
 {
        struct kvm *kvm = vcpu->kvm;
        struct kvmppc_spapr_tce_table *stt;
 
+       list_for_each_entry_lockless(stt, &kvm->arch.spapr_tce_tables, list)
+               if (stt->liobn == liobn)
+                       return stt;
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(kvmppc_find_table);
+
+/*
+ * Validates IO address.
+ *
+ * WARNING: This will be called in real-mode on HV KVM and virtual
+ *          mode on PR KVM
+ */
+long kvmppc_ioba_validate(struct kvmppc_spapr_tce_table *stt,
+               unsigned long ioba, unsigned long npages)
+{
+       unsigned long mask = (1ULL << stt->page_shift) - 1;
+       unsigned long idx = ioba >> stt->page_shift;
+
+       if ((ioba & mask) || (idx < stt->offset) ||
+                       (idx - stt->offset + npages > stt->size) ||
+                       (idx + npages < idx))
+               return H_PARAMETER;
+
+       return H_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(kvmppc_ioba_validate);
+
+/*
+ * Validates TCE address.
+ * At the moment flags and page mask are validated.
+ * As the host kernel does not access those addresses (just puts them
+ * to the table and user space is supposed to process them), we can skip
+ * checking other things (such as TCE is a guest RAM address or the page
+ * was actually allocated).
+ *
+ * WARNING: This will be called in real-mode on HV KVM and virtual
+ *          mode on PR KVM
+ */
+long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt, unsigned long tce)
+{
+       unsigned long page_mask = ~((1ULL << stt->page_shift) - 1);
+       unsigned long mask = ~(page_mask | TCE_PCI_WRITE | TCE_PCI_READ);
+
+       if (tce & mask)
+               return H_PARAMETER;
+
+       return H_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(kvmppc_tce_validate);
+
+/* Note on the use of page_address() in real mode,
+ *
+ * It is safe to use page_address() in real mode on ppc64 because
+ * page_address() is always defined as lowmem_page_address()
+ * which returns __va(PFN_PHYS(page_to_pfn(page))) which is arithmetic
+ * operation and does not access page struct.
+ *
+ * Theoretically page_address() could be defined different
+ * but either WANT_PAGE_VIRTUAL or HASHED_PAGE_VIRTUAL
+ * would have to be enabled.
+ * WANT_PAGE_VIRTUAL is never enabled on ppc32/ppc64,
+ * HASHED_PAGE_VIRTUAL could be enabled for ppc32 only and only
+ * if CONFIG_HIGHMEM is defined. As CONFIG_SPARSEMEM_VMEMMAP
+ * is not expected to be enabled on ppc32, page_address()
+ * is safe for ppc32 as well.
+ *
+ * WARNING: This will be called in real-mode on HV KVM and virtual
+ *          mode on PR KVM
+ */
+static u64 *kvmppc_page_address(struct page *page)
+{
+#if defined(HASHED_PAGE_VIRTUAL) || defined(WANT_PAGE_VIRTUAL)
+#error TODO: fix to avoid page_address() here
+#endif
+       return (u64 *) page_address(page);
+}
+
+/*
+ * Handles TCE requests for emulated devices.
+ * Puts guest TCE values to the table and expects user space to convert them.
+ * Called in both real and virtual modes.
+ * Cannot fail so kvmppc_tce_validate must be called before it.
+ *
+ * WARNING: This will be called in real-mode on HV KVM and virtual
+ *          mode on PR KVM
+ */
+void kvmppc_tce_put(struct kvmppc_spapr_tce_table *stt,
+               unsigned long idx, unsigned long tce)
+{
+       struct page *page;
+       u64 *tbl;
+
+       idx -= stt->offset;
+       page = stt->pages[idx / TCES_PER_PAGE];
+       tbl = kvmppc_page_address(page);
+
+       tbl[idx % TCES_PER_PAGE] = tce;
+}
+EXPORT_SYMBOL_GPL(kvmppc_tce_put);
+
+long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa,
+               unsigned long *ua, unsigned long **prmap)
+{
+       unsigned long gfn = gpa >> PAGE_SHIFT;
+       struct kvm_memory_slot *memslot;
+
+       memslot = search_memslots(kvm_memslots(kvm), gfn);
+       if (!memslot)
+               return -EINVAL;
+
+       *ua = __gfn_to_hva_memslot(memslot, gfn) |
+               (gpa & ~(PAGE_MASK | TCE_PCI_READ | TCE_PCI_WRITE));
+
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+       if (prmap)
+               *prmap = &memslot->arch.rmap[gfn - memslot->base_gfn];
+#endif
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_gpa_to_ua);
+
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+                     unsigned long ioba, unsigned long tce)
+{
+       struct kvmppc_spapr_tce_table *stt = kvmppc_find_table(vcpu, liobn);
+       long ret;
+
        /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
        /*          liobn, ioba, tce); */
 
-       list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
-               if (stt->liobn == liobn) {
-                       unsigned long idx = ioba >> SPAPR_TCE_SHIFT;
-                       struct page *page;
-                       u64 *tbl;
-
-                       /* udbg_printf("H_PUT_TCE: liobn 0x%lx => stt=%p  window_size=0x%x\n", */
-                       /*          liobn, stt, stt->window_size); */
-                       if (ioba >= stt->window_size)
-                               return H_PARAMETER;
-
-                       page = stt->pages[idx / TCES_PER_PAGE];
-                       tbl = (u64 *)page_address(page);
-
-                       /* FIXME: Need to validate the TCE itself */
-                       /* udbg_printf("tce @ %p\n", &tbl[idx % TCES_PER_PAGE]); */
-                       tbl[idx % TCES_PER_PAGE] = tce;
-                       return H_SUCCESS;
-               }
-       }
+       if (!stt)
+               return H_TOO_HARD;
+
+       ret = kvmppc_ioba_validate(stt, ioba, 1);
+       if (ret != H_SUCCESS)
+               return ret;
 
-       /* Didn't find the liobn, punt it to userspace */
-       return H_TOO_HARD;
+       ret = kvmppc_tce_validate(stt, tce);
+       if (ret != H_SUCCESS)
+               return ret;
+
+       kvmppc_tce_put(stt, ioba >> stt->page_shift, tce);
+
+       return H_SUCCESS;
 }
 EXPORT_SYMBOL_GPL(kvmppc_h_put_tce);
 
-long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
-                     unsigned long ioba)
+static long kvmppc_rm_ua_to_hpa(struct kvm_vcpu *vcpu,
+               unsigned long ua, unsigned long *phpa)
+{
+       pte_t *ptep, pte;
+       unsigned shift = 0;
+
+       ptep = __find_linux_pte_or_hugepte(vcpu->arch.pgdir, ua, NULL, &shift);
+       if (!ptep || !pte_present(*ptep))
+               return -ENXIO;
+       pte = *ptep;
+
+       if (!shift)
+               shift = PAGE_SHIFT;
+
+       /* Avoid handling anything potentially complicated in realmode */
+       if (shift > PAGE_SHIFT)
+               return -EAGAIN;
+
+       if (!pte_young(pte))
+               return -EAGAIN;
+
+       *phpa = (pte_pfn(pte) << PAGE_SHIFT) | (ua & ((1ULL << shift) - 1)) |
+                       (ua & ~PAGE_MASK);
+
+       return 0;
+}
+
+long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+               unsigned long liobn, unsigned long ioba,
+               unsigned long tce_list, unsigned long npages)
 {
-       struct kvm *kvm = vcpu->kvm;
        struct kvmppc_spapr_tce_table *stt;
+       long i, ret = H_SUCCESS;
+       unsigned long tces, entry, ua = 0;
+       unsigned long *rmap = NULL;
+
+       stt = kvmppc_find_table(vcpu, liobn);
+       if (!stt)
+               return H_TOO_HARD;
+
+       entry = ioba >> stt->page_shift;
+       /*
+        * The spec says that the maximum size of the list is 512 TCEs
+        * so the whole table addressed resides in 4K page
+        */
+       if (npages > 512)
+               return H_PARAMETER;
+
+       if (tce_list & (SZ_4K - 1))
+               return H_PARAMETER;
+
+       ret = kvmppc_ioba_validate(stt, ioba, npages);
+       if (ret != H_SUCCESS)
+               return ret;
 
-       list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
-               if (stt->liobn == liobn) {
-                       unsigned long idx = ioba >> SPAPR_TCE_SHIFT;
-                       struct page *page;
-                       u64 *tbl;
+       if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, &rmap))
+               return H_TOO_HARD;
 
-                       if (ioba >= stt->window_size)
-                               return H_PARAMETER;
+       rmap = (void *) vmalloc_to_phys(rmap);
 
-                       page = stt->pages[idx / TCES_PER_PAGE];
-                       tbl = (u64 *)page_address(page);
+       /*
+        * Synchronize with the MMU notifier callbacks in
+        * book3s_64_mmu_hv.c (kvm_unmap_hva_hv etc.).
+        * While we have the rmap lock, code running on other CPUs
+        * cannot finish unmapping the host real page that backs
+        * this guest real page, so we are OK to access the host
+        * real page.
+        */
+       lock_rmap(rmap);
+       if (kvmppc_rm_ua_to_hpa(vcpu, ua, &tces)) {
+               ret = H_TOO_HARD;
+               goto unlock_exit;
+       }
+
+       for (i = 0; i < npages; ++i) {
+               unsigned long tce = be64_to_cpu(((u64 *)tces)[i]);
+
+               ret = kvmppc_tce_validate(stt, tce);
+               if (ret != H_SUCCESS)
+                       goto unlock_exit;
 
-                       vcpu->arch.gpr[4] = tbl[idx % TCES_PER_PAGE];
-                       return H_SUCCESS;
-               }
+               kvmppc_tce_put(stt, entry + i, tce);
        }
 
-       /* Didn't find the liobn, punt it to userspace */
-       return H_TOO_HARD;
+unlock_exit:
+       unlock_rmap(rmap);
+
+       return ret;
+}
+
+long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu,
+               unsigned long liobn, unsigned long ioba,
+               unsigned long tce_value, unsigned long npages)
+{
+       struct kvmppc_spapr_tce_table *stt;
+       long i, ret;
+
+       stt = kvmppc_find_table(vcpu, liobn);
+       if (!stt)
+               return H_TOO_HARD;
+
+       ret = kvmppc_ioba_validate(stt, ioba, npages);
+       if (ret != H_SUCCESS)
+               return ret;
+
+       /* Check permission bits only to allow userspace poison TCE for debug */
+       if (tce_value & (TCE_PCI_WRITE | TCE_PCI_READ))
+               return H_PARAMETER;
+
+       for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift))
+               kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value);
+
+       return H_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce);
+
+long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+                     unsigned long ioba)
+{
+       struct kvmppc_spapr_tce_table *stt = kvmppc_find_table(vcpu, liobn);
+       long ret;
+       unsigned long idx;
+       struct page *page;
+       u64 *tbl;
+
+       if (!stt)
+               return H_TOO_HARD;
+
+       ret = kvmppc_ioba_validate(stt, ioba, 1);
+       if (ret != H_SUCCESS)
+               return ret;
+
+       idx = (ioba >> stt->page_shift) - stt->offset;
+       page = stt->pages[idx / TCES_PER_PAGE];
+       tbl = (u64 *)page_address(page);
+
+       vcpu->arch.gpr[4] = tbl[idx % TCES_PER_PAGE];
+
+       return H_SUCCESS;
 }
 EXPORT_SYMBOL_GPL(kvmppc_h_get_tce);
+
+#endif /* KVM_BOOK3S_HV_POSSIBLE */
index baeddb06811d738a6ea8be4ce920e5ea39a9645a..84fb4fcfaa41b802a614515c67539b0d2d7ee3cf 100644 (file)
@@ -81,6 +81,17 @@ static int target_smt_mode;
 module_param(target_smt_mode, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(target_smt_mode, "Target threads per core (0 = max)");
 
+#ifdef CONFIG_KVM_XICS
+static struct kernel_param_ops module_param_ops = {
+       .set = param_set_int,
+       .get = param_get_int,
+};
+
+module_param_cb(h_ipi_redirect, &module_param_ops, &h_ipi_redirect,
+                                                       S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(h_ipi_redirect, "Redirect H_IPI wakeup to a free host core");
+#endif
+
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
 
@@ -114,11 +125,11 @@ static bool kvmppc_ipi_thread(int cpu)
 static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
 {
        int cpu;
-       wait_queue_head_t *wqp;
+       struct swait_queue_head *wqp;
 
        wqp = kvm_arch_vcpu_wq(vcpu);
-       if (waitqueue_active(wqp)) {
-               wake_up_interruptible(wqp);
+       if (swait_active(wqp)) {
+               swake_up(wqp);
                ++vcpu->stat.halt_wakeup;
        }
 
@@ -701,8 +712,8 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
                tvcpu->arch.prodded = 1;
                smp_mb();
                if (vcpu->arch.ceded) {
-                       if (waitqueue_active(&vcpu->wq)) {
-                               wake_up_interruptible(&vcpu->wq);
+                       if (swait_active(&vcpu->wq)) {
+                               swake_up(&vcpu->wq);
                                vcpu->stat.halt_wakeup++;
                        }
                }
@@ -768,7 +779,31 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
                if (kvmppc_xics_enabled(vcpu)) {
                        ret = kvmppc_xics_hcall(vcpu, req);
                        break;
-               } /* fallthrough */
+               }
+               return RESUME_HOST;
+       case H_PUT_TCE:
+               ret = kvmppc_h_put_tce(vcpu, kvmppc_get_gpr(vcpu, 4),
+                                               kvmppc_get_gpr(vcpu, 5),
+                                               kvmppc_get_gpr(vcpu, 6));
+               if (ret == H_TOO_HARD)
+                       return RESUME_HOST;
+               break;
+       case H_PUT_TCE_INDIRECT:
+               ret = kvmppc_h_put_tce_indirect(vcpu, kvmppc_get_gpr(vcpu, 4),
+                                               kvmppc_get_gpr(vcpu, 5),
+                                               kvmppc_get_gpr(vcpu, 6),
+                                               kvmppc_get_gpr(vcpu, 7));
+               if (ret == H_TOO_HARD)
+                       return RESUME_HOST;
+               break;
+       case H_STUFF_TCE:
+               ret = kvmppc_h_stuff_tce(vcpu, kvmppc_get_gpr(vcpu, 4),
+                                               kvmppc_get_gpr(vcpu, 5),
+                                               kvmppc_get_gpr(vcpu, 6),
+                                               kvmppc_get_gpr(vcpu, 7));
+               if (ret == H_TOO_HARD)
+                       return RESUME_HOST;
+               break;
        default:
                return RESUME_HOST;
        }
@@ -1459,7 +1494,7 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
        INIT_LIST_HEAD(&vcore->runnable_threads);
        spin_lock_init(&vcore->lock);
        spin_lock_init(&vcore->stoltb_lock);
-       init_waitqueue_head(&vcore->wq);
+       init_swait_queue_head(&vcore->wq);
        vcore->preempt_tb = TB_NIL;
        vcore->lpcr = kvm->arch.lpcr;
        vcore->first_vcpuid = core * threads_per_subcore;
@@ -2278,6 +2313,46 @@ static void post_guest_process(struct kvmppc_vcore *vc, bool is_master)
        spin_unlock(&vc->lock);
 }
 
+/*
+ * Clear core from the list of active host cores as we are about to
+ * enter the guest. Only do this if it is the primary thread of the
+ * core (not if a subcore) that is entering the guest.
+ */
+static inline void kvmppc_clear_host_core(int cpu)
+{
+       int core;
+
+       if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu))
+               return;
+       /*
+        * Memory barrier can be omitted here as we will do a smp_wmb()
+        * later in kvmppc_start_thread and we need ensure that state is
+        * visible to other CPUs only after we enter guest.
+        */
+       core = cpu >> threads_shift;
+       kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 0;
+}
+
+/*
+ * Advertise this core as an active host core since we exited the guest
+ * Only need to do this if it is the primary thread of the core that is
+ * exiting.
+ */
+static inline void kvmppc_set_host_core(int cpu)
+{
+       int core;
+
+       if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu))
+               return;
+
+       /*
+        * Memory barrier can be omitted here because we do a spin_unlock
+        * immediately after this which provides the memory barrier.
+        */
+       core = cpu >> threads_shift;
+       kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 1;
+}
+
 /*
  * Run a set of guest threads on a physical core.
  * Called with vc->lock held.
@@ -2390,6 +2465,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
                }
        }
 
+       kvmppc_clear_host_core(pcpu);
+
        /* Start all the threads */
        active = 0;
        for (sub = 0; sub < core_info.n_subcores; ++sub) {
@@ -2486,6 +2563,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
                        kvmppc_ipi_thread(pcpu + i);
        }
 
+       kvmppc_set_host_core(pcpu);
+
        spin_unlock(&vc->lock);
 
        /* make sure updates to secondary vcpu structs are visible now */
@@ -2531,10 +2610,9 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
 {
        struct kvm_vcpu *vcpu;
        int do_sleep = 1;
+       DECLARE_SWAITQUEUE(wait);
 
-       DEFINE_WAIT(wait);
-
-       prepare_to_wait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
+       prepare_to_swait(&vc->wq, &wait, TASK_INTERRUPTIBLE);
 
        /*
         * Check one last time for pending exceptions and ceded state after
@@ -2548,7 +2626,7 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
        }
 
        if (!do_sleep) {
-               finish_wait(&vc->wq, &wait);
+               finish_swait(&vc->wq, &wait);
                return;
        }
 
@@ -2556,7 +2634,7 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
        trace_kvmppc_vcore_blocked(vc, 0);
        spin_unlock(&vc->lock);
        schedule();
-       finish_wait(&vc->wq, &wait);
+       finish_swait(&vc->wq, &wait);
        spin_lock(&vc->lock);
        vc->vcore_state = VCORE_INACTIVE;
        trace_kvmppc_vcore_blocked(vc, 1);
@@ -2612,7 +2690,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
                        kvmppc_start_thread(vcpu, vc);
                        trace_kvm_guest_enter(vcpu);
                } else if (vc->vcore_state == VCORE_SLEEPING) {
-                       wake_up(&vc->wq);
+                       swake_up(&vc->wq);
                }
 
        }
@@ -2984,6 +3062,114 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
        goto out_srcu;
 }
 
+#ifdef CONFIG_KVM_XICS
+static int kvmppc_cpu_notify(struct notifier_block *self, unsigned long action,
+                       void *hcpu)
+{
+       unsigned long cpu = (long)hcpu;
+
+       switch (action) {
+       case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
+               kvmppc_set_host_core(cpu);
+               break;
+
+#ifdef CONFIG_HOTPLUG_CPU
+       case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
+       case CPU_UP_CANCELED:
+       case CPU_UP_CANCELED_FROZEN:
+               kvmppc_clear_host_core(cpu);
+               break;
+#endif
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block kvmppc_cpu_notifier = {
+           .notifier_call = kvmppc_cpu_notify,
+};
+
+/*
+ * Allocate a per-core structure for managing state about which cores are
+ * running in the host versus the guest and for exchanging data between
+ * real mode KVM and CPU running in the host.
+ * This is only done for the first VM.
+ * The allocated structure stays even if all VMs have stopped.
+ * It is only freed when the kvm-hv module is unloaded.
+ * It's OK for this routine to fail, we just don't support host
+ * core operations like redirecting H_IPI wakeups.
+ */
+void kvmppc_alloc_host_rm_ops(void)
+{
+       struct kvmppc_host_rm_ops *ops;
+       unsigned long l_ops;
+       int cpu, core;
+       int size;
+
+       /* Not the first time here ? */
+       if (kvmppc_host_rm_ops_hv != NULL)
+               return;
+
+       ops = kzalloc(sizeof(struct kvmppc_host_rm_ops), GFP_KERNEL);
+       if (!ops)
+               return;
+
+       size = cpu_nr_cores() * sizeof(struct kvmppc_host_rm_core);
+       ops->rm_core = kzalloc(size, GFP_KERNEL);
+
+       if (!ops->rm_core) {
+               kfree(ops);
+               return;
+       }
+
+       get_online_cpus();
+
+       for (cpu = 0; cpu < nr_cpu_ids; cpu += threads_per_core) {
+               if (!cpu_online(cpu))
+                       continue;
+
+               core = cpu >> threads_shift;
+               ops->rm_core[core].rm_state.in_host = 1;
+       }
+
+       ops->vcpu_kick = kvmppc_fast_vcpu_kick_hv;
+
+       /*
+        * Make the contents of the kvmppc_host_rm_ops structure visible
+        * to other CPUs before we assign it to the global variable.
+        * Do an atomic assignment (no locks used here), but if someone
+        * beats us to it, just free our copy and return.
+        */
+       smp_wmb();
+       l_ops = (unsigned long) ops;
+
+       if (cmpxchg64((unsigned long *)&kvmppc_host_rm_ops_hv, 0, l_ops)) {
+               put_online_cpus();
+               kfree(ops->rm_core);
+               kfree(ops);
+               return;
+       }
+
+       register_cpu_notifier(&kvmppc_cpu_notifier);
+
+       put_online_cpus();
+}
+
+void kvmppc_free_host_rm_ops(void)
+{
+       if (kvmppc_host_rm_ops_hv) {
+               unregister_cpu_notifier(&kvmppc_cpu_notifier);
+               kfree(kvmppc_host_rm_ops_hv->rm_core);
+               kfree(kvmppc_host_rm_ops_hv);
+               kvmppc_host_rm_ops_hv = NULL;
+       }
+}
+#endif
+
 static int kvmppc_core_init_vm_hv(struct kvm *kvm)
 {
        unsigned long lpcr, lpid;
@@ -2996,6 +3182,8 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
                return -ENOMEM;
        kvm->arch.lpid = lpid;
 
+       kvmppc_alloc_host_rm_ops();
+
        /*
         * Since we don't flush the TLB when tearing down a VM,
         * and this lpid might have previously been used,
@@ -3229,6 +3417,7 @@ static int kvmppc_book3s_init_hv(void)
 
 static void kvmppc_book3s_exit_hv(void)
 {
+       kvmppc_free_host_rm_ops();
        kvmppc_hv_ops = NULL;
 }
 
index fd7006bf6b1a1a59a86fe42efcbbb5c9b485e6a1..5f0380db3eabcf483a8ff98f68cad7d4b96f0c96 100644 (file)
@@ -283,3 +283,6 @@ void kvmhv_commence_exit(int trap)
                        kvmhv_interrupt_vcore(vc, ee);
        }
 }
+
+struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv;
+EXPORT_SYMBOL_GPL(kvmppc_host_rm_ops_hv);
index 24f58076d49e1eada68920615c8ce2c3b1166744..980d8a6f728427a0c58463bd3b3a594fe72fb6b5 100644 (file)
 #include <asm/xics.h>
 #include <asm/debug.h>
 #include <asm/synch.h>
+#include <asm/cputhreads.h>
 #include <asm/ppc-opcode.h>
 
 #include "book3s_xics.h"
 
 #define DEBUG_PASSUP
 
+int h_ipi_redirect = 1;
+EXPORT_SYMBOL(h_ipi_redirect);
+
 static void icp_rm_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
                            u32 new_irq);
 
@@ -50,11 +54,84 @@ static void ics_rm_check_resend(struct kvmppc_xics *xics,
 
 /* -- ICP routines -- */
 
+#ifdef CONFIG_SMP
+static inline void icp_send_hcore_msg(int hcore, struct kvm_vcpu *vcpu)
+{
+       int hcpu;
+
+       hcpu = hcore << threads_shift;
+       kvmppc_host_rm_ops_hv->rm_core[hcore].rm_data = vcpu;
+       smp_muxed_ipi_set_message(hcpu, PPC_MSG_RM_HOST_ACTION);
+       icp_native_cause_ipi_rm(hcpu);
+}
+#else
+static inline void icp_send_hcore_msg(int hcore, struct kvm_vcpu *vcpu) { }
+#endif
+
+/*
+ * We start the search from our current CPU Id in the core map
+ * and go in a circle until we get back to our ID looking for a
+ * core that is running in host context and that hasn't already
+ * been targeted for another rm_host_ops.
+ *
+ * In the future, could consider using a fairer algorithm (one
+ * that distributes the IPIs better)
+ *
+ * Returns -1, if no CPU could be found in the host
+ * Else, returns a CPU Id which has been reserved for use
+ */
+static inline int grab_next_hostcore(int start,
+               struct kvmppc_host_rm_core *rm_core, int max, int action)
+{
+       bool success;
+       int core;
+       union kvmppc_rm_state old, new;
+
+       for (core = start + 1; core < max; core++)  {
+               old = new = READ_ONCE(rm_core[core].rm_state);
+
+               if (!old.in_host || old.rm_action)
+                       continue;
+
+               /* Try to grab this host core if not taken already. */
+               new.rm_action = action;
+
+               success = cmpxchg64(&rm_core[core].rm_state.raw,
+                                               old.raw, new.raw) == old.raw;
+               if (success) {
+                       /*
+                        * Make sure that the store to the rm_action is made
+                        * visible before we return to caller (and the
+                        * subsequent store to rm_data) to synchronize with
+                        * the IPI handler.
+                        */
+                       smp_wmb();
+                       return core;
+               }
+       }
+
+       return -1;
+}
+
+static inline int find_available_hostcore(int action)
+{
+       int core;
+       int my_core = smp_processor_id() >> threads_shift;
+       struct kvmppc_host_rm_core *rm_core = kvmppc_host_rm_ops_hv->rm_core;
+
+       core = grab_next_hostcore(my_core, rm_core, cpu_nr_cores(), action);
+       if (core == -1)
+               core = grab_next_hostcore(core, rm_core, my_core, action);
+
+       return core;
+}
+
 static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu,
                                struct kvm_vcpu *this_vcpu)
 {
        struct kvmppc_icp *this_icp = this_vcpu->arch.icp;
        int cpu;
+       int hcore;
 
        /* Mark the target VCPU as having an interrupt pending */
        vcpu->stat.queue_intr++;
@@ -66,11 +143,22 @@ static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu,
                return;
        }
 
-       /* Check if the core is loaded, if not, too hard */
+       /*
+        * Check if the core is loaded,
+        * if not, find an available host core to post to wake the VCPU,
+        * if we can't find one, set up state to eventually return too hard.
+        */
        cpu = vcpu->arch.thread_cpu;
        if (cpu < 0 || cpu >= nr_cpu_ids) {
-               this_icp->rm_action |= XICS_RM_KICK_VCPU;
-               this_icp->rm_kick_target = vcpu;
+               hcore = -1;
+               if (kvmppc_host_rm_ops_hv && h_ipi_redirect)
+                       hcore = find_available_hostcore(XICS_RM_KICK_VCPU);
+               if (hcore != -1) {
+                       icp_send_hcore_msg(hcore, vcpu);
+               } else {
+                       this_icp->rm_action |= XICS_RM_KICK_VCPU;
+                       this_icp->rm_kick_target = vcpu;
+               }
                return;
        }
 
@@ -623,3 +711,40 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
  bail:
        return check_too_hard(xics, icp);
 }
+
+/*  --- Non-real mode XICS-related built-in routines ---  */
+
+/**
+ * Host Operations poked by RM KVM
+ */
+static void rm_host_ipi_action(int action, void *data)
+{
+       switch (action) {
+       case XICS_RM_KICK_VCPU:
+               kvmppc_host_rm_ops_hv->vcpu_kick(data);
+               break;
+       default:
+               WARN(1, "Unexpected rm_action=%d data=%p\n", action, data);
+               break;
+       }
+
+}
+
+void kvmppc_xics_ipi_action(void)
+{
+       int core;
+       unsigned int cpu = smp_processor_id();
+       struct kvmppc_host_rm_core *rm_corep;
+
+       core = cpu >> threads_shift;
+       rm_corep = &kvmppc_host_rm_ops_hv->rm_core[core];
+
+       if (rm_corep->rm_data) {
+               rm_host_ipi_action(rm_corep->rm_state.rm_action,
+                                                       rm_corep->rm_data);
+               /* Order these stores against the real mode KVM */
+               rm_corep->rm_data = NULL;
+               smp_wmb();
+               rm_corep->rm_state.rm_action = 0;
+       }
+}
index 6ee26de9a1ded02e0e08f376fd612049eedee0b4..85b32f16fa74e02a2fa753a62ecaf2c728e3eb2a 100644 (file)
@@ -1370,6 +1370,20 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
        std     r6, VCPU_ACOP(r9)
        stw     r7, VCPU_GUEST_PID(r9)
        std     r8, VCPU_WORT(r9)
+       /*
+        * Restore various registers to 0, where non-zero values
+        * set by the guest could disrupt the host.
+        */
+       li      r0, 0
+       mtspr   SPRN_IAMR, r0
+       mtspr   SPRN_CIABR, r0
+       mtspr   SPRN_DAWRX, r0
+       mtspr   SPRN_TCSCR, r0
+       mtspr   SPRN_WORT, r0
+       /* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
+       li      r0, 1
+       sldi    r0, r0, 31
+       mtspr   SPRN_MMCRS, r0
 8:
 
        /* Save and reset AMR and UAMOR before turning on the MMU */
@@ -2006,8 +2020,8 @@ hcall_real_table:
        .long   0               /* 0x12c */
        .long   0               /* 0x130 */
        .long   DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table
-       .long   0               /* 0x138 */
-       .long   0               /* 0x13c */
+       .long   DOTSYM(kvmppc_h_stuff_tce) - hcall_real_table
+       .long   DOTSYM(kvmppc_rm_h_put_tce_indirect) - hcall_real_table
        .long   0               /* 0x140 */
        .long   0               /* 0x144 */
        .long   0               /* 0x148 */
index f2c75a1e0536c7b13fdb329be3067691f3f2c284..02176fd52f84b85187f8a57a5e434bd56299a151 100644 (file)
@@ -280,6 +280,37 @@ static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
+static int kvmppc_h_pr_put_tce_indirect(struct kvm_vcpu *vcpu)
+{
+       unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
+       unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
+       unsigned long tce = kvmppc_get_gpr(vcpu, 6);
+       unsigned long npages = kvmppc_get_gpr(vcpu, 7);
+       long rc;
+
+       rc = kvmppc_h_put_tce_indirect(vcpu, liobn, ioba,
+                       tce, npages);
+       if (rc == H_TOO_HARD)
+               return EMULATE_FAIL;
+       kvmppc_set_gpr(vcpu, 3, rc);
+       return EMULATE_DONE;
+}
+
+static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu)
+{
+       unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
+       unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
+       unsigned long tce_value = kvmppc_get_gpr(vcpu, 6);
+       unsigned long npages = kvmppc_get_gpr(vcpu, 7);
+       long rc;
+
+       rc = kvmppc_h_stuff_tce(vcpu, liobn, ioba, tce_value, npages);
+       if (rc == H_TOO_HARD)
+               return EMULATE_FAIL;
+       kvmppc_set_gpr(vcpu, 3, rc);
+       return EMULATE_DONE;
+}
+
 static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
 {
        long rc = kvmppc_xics_hcall(vcpu, cmd);
@@ -306,6 +337,10 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd)
                return kvmppc_h_pr_bulk_remove(vcpu);
        case H_PUT_TCE:
                return kvmppc_h_pr_put_tce(vcpu);
+       case H_PUT_TCE_INDIRECT:
+               return kvmppc_h_pr_put_tce_indirect(vcpu);
+       case H_STUFF_TCE:
+               return kvmppc_h_pr_stuff_tce(vcpu);
        case H_CEDE:
                kvmppc_set_msr_fast(vcpu, kvmppc_get_msr(vcpu) | MSR_EE);
                kvm_vcpu_block(vcpu);
index a3b182dcb823640540fcaeac38bc7d89550fddd6..19aa59b0850cf73489d5f61623794da607a6fc41 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/tlbflush.h>
 #include <asm/cputhreads.h>
 #include <asm/irqflags.h>
+#include <asm/iommu.h>
 #include "timing.h"
 #include "irq.h"
 #include "../mm/mmu_decl.h"
@@ -437,6 +438,16 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
        unsigned int i;
        struct kvm_vcpu *vcpu;
 
+#ifdef CONFIG_KVM_XICS
+       /*
+        * We call kick_all_cpus_sync() to ensure that all
+        * CPUs have executed any pending IPIs before we
+        * continue and free VCPUs structures below.
+        */
+       if (is_kvmppc_hv_enabled(kvm))
+               kick_all_cpus_sync();
+#endif
+
        kvm_for_each_vcpu(i, vcpu, kvm)
                kvm_arch_vcpu_free(vcpu);
 
@@ -509,6 +520,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 
 #ifdef CONFIG_PPC_BOOK3S_64
        case KVM_CAP_SPAPR_TCE:
+       case KVM_CAP_SPAPR_TCE_64:
        case KVM_CAP_PPC_ALLOC_HTAB:
        case KVM_CAP_PPC_RTAS:
        case KVM_CAP_PPC_FIXUP_HCALL:
@@ -569,6 +581,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_PPC_GET_SMMU_INFO:
                r = 1;
                break;
+       case KVM_CAP_SPAPR_MULTITCE:
+               r = 1;
+               break;
 #endif
        default:
                r = 0;
@@ -1331,13 +1346,34 @@ long kvm_arch_vm_ioctl(struct file *filp,
                break;
        }
 #ifdef CONFIG_PPC_BOOK3S_64
+       case KVM_CREATE_SPAPR_TCE_64: {
+               struct kvm_create_spapr_tce_64 create_tce_64;
+
+               r = -EFAULT;
+               if (copy_from_user(&create_tce_64, argp, sizeof(create_tce_64)))
+                       goto out;
+               if (create_tce_64.flags) {
+                       r = -EINVAL;
+                       goto out;
+               }
+               r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce_64);
+               goto out;
+       }
        case KVM_CREATE_SPAPR_TCE: {
                struct kvm_create_spapr_tce create_tce;
+               struct kvm_create_spapr_tce_64 create_tce_64;
 
                r = -EFAULT;
                if (copy_from_user(&create_tce, argp, sizeof(create_tce)))
                        goto out;
-               r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce);
+
+               create_tce_64.liobn = create_tce.liobn;
+               create_tce_64.page_shift = IOMMU_PAGE_SHIFT_4K;
+               create_tce_64.offset = 0;
+               create_tce_64.size = create_tce.window_size >>
+                               IOMMU_PAGE_SHIFT_4K;
+               create_tce_64.flags = 0;
+               r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce_64);
                goto out;
        }
        case KVM_PPC_GET_SMMU_INFO: {
index 0762c1e08c88644f35cc8a3df5ba50c52c1801a2..edb09912f0c9b5ca316216bf3d912c7efe8d920a 100644 (file)
@@ -111,7 +111,13 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
         */
        if (!(old_pte & _PAGE_COMBO)) {
                flush_hash_page(vpn, rpte, MMU_PAGE_64K, ssize, flags);
-               old_pte &= ~_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND;
+               /*
+                * clear the old slot details from the old and new pte.
+                * On hash insert failure we use old pte value and we don't
+                * want slot information there if we have a insert failure.
+                */
+               old_pte &= ~(_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND);
+               new_pte &= ~(_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND);
                goto htab_insert_hpte;
        }
        /*
index 49b152b0f926289e1dcaa595988932a036df5325..eb2accdd76fd8bb70a762c4a57df8bc2c425ffad 100644 (file)
@@ -78,9 +78,19 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
                 * base page size. This is because demote_segment won't flush
                 * hash page table entries.
                 */
-               if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO))
+               if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) {
                        flush_hash_hugepage(vsid, ea, pmdp, MMU_PAGE_64K,
                                            ssize, flags);
+                       /*
+                        * With THP, we also clear the slot information with
+                        * respect to all the 64K hash pte mapping the 16MB
+                        * page. They are all invalid now. This make sure we
+                        * don't find the slot valid when we fault with 4k
+                        * base page size.
+                        *
+                        */
+                       memset(hpte_slot_array, 0, PTE_FRAG_SIZE);
+               }
        }
 
        valid = hpte_valid(hpte_slot_array, index);
index 7e6d0880813fe9e363a7e9edd2f5278ef10e4a9e..83a8be791e0646778ddf805d83b5a761bf0d62b1 100644 (file)
@@ -8,6 +8,8 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 
+#include <asm/mmu.h>
+
 #ifdef CONFIG_PPC_FSL_BOOK3E
 #ifdef CONFIG_PPC64
 static inline int tlb1_next(void)
@@ -60,6 +62,14 @@ static inline void book3e_tlb_lock(void)
        unsigned long tmp;
        int token = smp_processor_id() + 1;
 
+       /*
+        * Besides being unnecessary in the absence of SMT, this
+        * check prevents trying to do lbarx/stbcx. on e5500 which
+        * doesn't implement either feature.
+        */
+       if (!cpu_has_feature(CPU_FTR_SMT))
+               return;
+
        asm volatile("1: lbarx %0, 0, %1;"
                     "cmpwi %0, 0;"
                     "bne 2f;"
@@ -80,6 +90,9 @@ static inline void book3e_tlb_unlock(void)
 {
        struct paca_struct *paca = get_paca();
 
+       if (!cpu_has_feature(CPU_FTR_SMT))
+               return;
+
        isync();
        paca->tcd_ptr->lock = 0;
 }
index d0f0a514b04ed66da35d1ae6b27b964285ef2aec..f078a1f94fc267de0e4de530cd413608c2d93e5f 100644 (file)
@@ -541,7 +541,7 @@ static int __init add_system_ram_resources(void)
                        res->name = "System RAM";
                        res->start = base;
                        res->end = base + size - 1;
-                       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+                       res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
                        WARN_ON(request_resource(&iomem_resource, res) < 0);
                }
        }
index 0f0502e12f6c4c8accbe7fc28eb4db08158decfb..4087705ba90f34241200e2f30765794ea6b74b55 100644 (file)
@@ -59,9 +59,9 @@ unsigned long arch_mmap_rnd(void)
 
        /* 8MB for 32bit, 1GB for 64bit */
        if (is_32bit_task())
-               rnd = (unsigned long)get_random_int() % (1<<(23-PAGE_SHIFT));
+               rnd = get_random_long() % (1<<(23-PAGE_SHIFT));
        else
-               rnd = (unsigned long)get_random_int() % (1<<(30-PAGE_SHIFT));
+               rnd = get_random_long() % (1UL<<(30-PAGE_SHIFT));
 
        return rnd << PAGE_SHIFT;
 }
index 83dfd7925c72c95efa47766c1806ef3e4a39126c..de37ff445362a1215bb2e6d3956bf364f841671a 100644 (file)
@@ -243,3 +243,11 @@ void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
 }
 #endif /* CONFIG_DEBUG_VM */
 
+unsigned long vmalloc_to_phys(void *va)
+{
+       unsigned long pfn = vmalloc_to_pfn(va);
+
+       BUG_ON(!pfn);
+       return __pa(pfn_to_kaddr(pfn)) + offset_in_page(va);
+}
+EXPORT_SYMBOL_GPL(vmalloc_to_phys);
index 9f9dfda9ed2c13a927f6c863759a2e780a5e8941..3b09ecfd0aee20861ae7c2d5f48a19965a21953f 100644 (file)
@@ -493,14 +493,6 @@ static size_t event_to_attr_ct(struct hv_24x7_event_data *event)
        }
 }
 
-static unsigned long vmalloc_to_phys(void *v)
-{
-       struct page *p = vmalloc_to_page(v);
-
-       BUG_ON(!p);
-       return page_to_phys(p) + offset_in_page(v);
-}
-
 /* */
 struct event_uniq {
        struct rb_node node;
index eae32654bdf225c5a271b713bb70520395f43a56..afdf62f2a6950ae939029699c567f87223f4f87e 100644 (file)
@@ -159,6 +159,27 @@ static void icp_native_cause_ipi(int cpu, unsigned long data)
        icp_native_set_qirr(cpu, IPI_PRIORITY);
 }
 
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+void icp_native_cause_ipi_rm(int cpu)
+{
+       /*
+        * Currently not used to send IPIs to another CPU
+        * on the same core. Only caller is KVM real mode.
+        * Need the physical address of the XICS to be
+        * previously saved in kvm_hstate in the paca.
+        */
+       unsigned long xics_phys;
+
+       /*
+        * Just like the cause_ipi functions, it is required to
+        * include a full barrier (out8 includes a sync) before
+        * causing the IPI.
+        */
+       xics_phys = paca[cpu].kvm_hstate.xics_phys;
+       out_rm8((u8 *)(xics_phys + XICS_MFRR), IPI_PRIORITY);
+}
+#endif
+
 /*
  * Called when an interrupt is received on an off-line CPU to
  * clear the interrupt, so that the CPU can go back to nap mode.
index 3be9c832dec117a041378bd606f07df89ca44520..7e3e8a8338d6c5a3f45de1535d59bd64c91e1475 100644 (file)
@@ -254,12 +254,12 @@ config MARCH_ZEC12
          older machines.
 
 config MARCH_Z13
-       bool "IBM z13"
+       bool "IBM z13s and z13"
        select HAVE_MARCH_Z13_FEATURES
        help
-         Select this to enable optimizations for IBM z13 (2964 series).
-         The kernel will be slightly faster but will not work on older
-         machines.
+         Select this to enable optimizations for IBM z13s and z13 (2965 and
+         2964 series). The kernel will be slightly faster but will not work on
+         older machines.
 
 endchoice
 
@@ -605,8 +605,6 @@ config PCI_NR_MSI
          PCI devices.
 
 source "drivers/pci/Kconfig"
-source "drivers/pci/pcie/Kconfig"
-source "drivers/pci/hotplug/Kconfig"
 
 endif  # PCI
 
index a0e71a501f7cecbf41252c0c549864659bd0e5f4..5687d62fb0cb313e7562553da0ea320c0f8a0b22 100644 (file)
@@ -4,14 +4,23 @@
 /* CLP common request & response block size */
 #define CLP_BLK_SIZE                   PAGE_SIZE
 
+#define CLP_LPS_BASE   0
+#define CLP_LPS_PCI    2
+
 struct clp_req_hdr {
        u16 len;
        u16 cmd;
+       u32 fmt         : 4;
+       u32 reserved1   : 28;
+       u64 reserved2;
 } __packed;
 
 struct clp_rsp_hdr {
        u16 len;
        u16 rsp;
+       u32 fmt         : 4;
+       u32 reserved1   : 28;
+       u64 reserved2;
 } __packed;
 
 /* CLP Response Codes */
@@ -25,4 +34,22 @@ struct clp_rsp_hdr {
 #define CLP_RC_NODATA                  0x0080  /* No data available */
 #define CLP_RC_FC_UNKNOWN              0x0100  /* Function code not recognized */
 
+/* Store logical-processor characteristics request */
+struct clp_req_slpc {
+       struct clp_req_hdr hdr;
+} __packed;
+
+struct clp_rsp_slpc {
+       struct clp_rsp_hdr hdr;
+       u32 reserved2[4];
+       u32 lpif[8];
+       u32 reserved3[8];
+       u32 lpic[8];
+} __packed;
+
+struct clp_req_rsp_slpc {
+       struct clp_req_slpc request;
+       struct clp_rsp_slpc response;
+} __packed;
+
 #endif
index ea91ddfe54ebb901007bb625f833f7457eff0253..629c90865a073174f61fcc47268d3311db4f3a9e 100644 (file)
@@ -40,6 +40,7 @@ static inline void convert_fp_to_vx(__vector128 *vxrs, freg_t *fprs)
 static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
 {
        fpregs->pad = 0;
+       fpregs->fpc = fpu->fpc;
        if (MACHINE_HAS_VX)
                convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs);
        else
@@ -49,6 +50,7 @@ static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu)
 
 static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu)
 {
+       fpu->fpc = fpregs->fpc;
        if (MACHINE_HAS_VX)
                convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs);
        else
diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h
new file mode 100644 (file)
index 0000000..d054c1b
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  KVM guest address space mapping code
+ *
+ *    Copyright IBM Corp. 2007, 2016
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_GMAP_H
+#define _ASM_S390_GMAP_H
+
+/**
+ * struct gmap_struct - guest address space
+ * @crst_list: list of all crst tables used in the guest address space
+ * @mm: pointer to the parent mm_struct
+ * @guest_to_host: radix tree with guest to host address translation
+ * @host_to_guest: radix tree with pointer to segment table entries
+ * @guest_table_lock: spinlock to protect all entries in the guest page table
+ * @table: pointer to the page directory
+ * @asce: address space control element for gmap page table
+ * @pfault_enabled: defines if pfaults are applicable for the guest
+ */
+struct gmap {
+       struct list_head list;
+       struct list_head crst_list;
+       struct mm_struct *mm;
+       struct radix_tree_root guest_to_host;
+       struct radix_tree_root host_to_guest;
+       spinlock_t guest_table_lock;
+       unsigned long *table;
+       unsigned long asce;
+       unsigned long asce_end;
+       void *private;
+       bool pfault_enabled;
+};
+
+/**
+ * struct gmap_notifier - notify function block for page invalidation
+ * @notifier_call: address of callback function
+ */
+struct gmap_notifier {
+       struct list_head list;
+       void (*notifier_call)(struct gmap *gmap, unsigned long gaddr);
+};
+
+struct gmap *gmap_alloc(struct mm_struct *mm, unsigned long limit);
+void gmap_free(struct gmap *gmap);
+void gmap_enable(struct gmap *gmap);
+void gmap_disable(struct gmap *gmap);
+int gmap_map_segment(struct gmap *gmap, unsigned long from,
+                    unsigned long to, unsigned long len);
+int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
+unsigned long __gmap_translate(struct gmap *, unsigned long gaddr);
+unsigned long gmap_translate(struct gmap *, unsigned long gaddr);
+int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr);
+int gmap_fault(struct gmap *, unsigned long gaddr, unsigned int fault_flags);
+void gmap_discard(struct gmap *, unsigned long from, unsigned long to);
+void __gmap_zap(struct gmap *, unsigned long gaddr);
+void gmap_unlink(struct mm_struct *, unsigned long *table, unsigned long vmaddr);
+
+void gmap_register_ipte_notifier(struct gmap_notifier *);
+void gmap_unregister_ipte_notifier(struct gmap_notifier *);
+int gmap_ipte_notify(struct gmap *, unsigned long start, unsigned long len);
+
+#endif /* _ASM_S390_GMAP_H */
index 8959ebb6d2c9eb35538b835a39522585321f9af4..6da41fab70fbe951c957d1b5542101d22980839b 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/kvm_types.h>
 #include <linux/kvm_host.h>
 #include <linux/kvm.h>
+#include <linux/seqlock.h>
 #include <asm/debug.h>
 #include <asm/cpu.h>
 #include <asm/fpu/api.h>
@@ -229,17 +230,11 @@ struct kvm_s390_itdb {
        __u8    data[256];
 } __packed;
 
-struct kvm_s390_vregs {
-       __vector128 vrs[32];
-       __u8    reserved200[512];       /* for future vector expansion */
-} __packed;
-
 struct sie_page {
        struct kvm_s390_sie_block sie_block;
        __u8 reserved200[1024];         /* 0x0200 */
        struct kvm_s390_itdb itdb;      /* 0x0600 */
-       __u8 reserved700[1280];         /* 0x0700 */
-       struct kvm_s390_vregs vregs;    /* 0x0c00 */
+       __u8 reserved700[2304];         /* 0x0700 */
 } __packed;
 
 struct kvm_vcpu_stat {
@@ -467,7 +462,7 @@ struct kvm_s390_irq_payload {
 struct kvm_s390_local_interrupt {
        spinlock_t lock;
        struct kvm_s390_float_interrupt *float_int;
-       wait_queue_head_t *wq;
+       struct swait_queue_head *wq;
        atomic_t *cpuflags;
        DECLARE_BITMAP(sigp_emerg_pending, KVM_MAX_VCPUS);
        struct kvm_s390_irq_payload irq;
@@ -558,6 +553,15 @@ struct kvm_vcpu_arch {
        unsigned long pfault_token;
        unsigned long pfault_select;
        unsigned long pfault_compare;
+       bool cputm_enabled;
+       /*
+        * The seqcount protects updates to cputm_start and sie_block.cputm,
+        * this way we can have non-blocking reads with consistent values.
+        * Only the owning VCPU thread (vcpu->cpu) is allowed to change these
+        * values and to start/stop/enable/disable cpu timer accounting.
+        */
+       seqcount_t cputm_seqcount;
+       __u64 cputm_start;
 };
 
 struct kvm_vm_stat {
@@ -596,15 +600,11 @@ struct s390_io_adapter {
 #define S390_ARCH_FAC_MASK_SIZE_U64 \
        (S390_ARCH_FAC_MASK_SIZE_BYTE / sizeof(u64))
 
-struct kvm_s390_fac {
-       /* facility list requested by guest */
-       __u64 list[S390_ARCH_FAC_LIST_SIZE_U64];
-       /* facility mask supported by kvm & hosting machine */
-       __u64 mask[S390_ARCH_FAC_LIST_SIZE_U64];
-};
-
 struct kvm_s390_cpu_model {
-       struct kvm_s390_fac *fac;
+       /* facility mask supported by kvm & hosting machine */
+       __u64 fac_mask[S390_ARCH_FAC_LIST_SIZE_U64];
+       /* facility list requested by guest (in dma page) */
+       __u64 *fac_list;
        struct cpuid cpu_id;
        unsigned short ibc;
 };
@@ -623,6 +623,16 @@ struct kvm_s390_crypto_cb {
        __u8    reserved80[128];                /* 0x0080 */
 };
 
+/*
+ * sie_page2 has to be allocated as DMA because fac_list and crycb need
+ * 31bit addresses in the sie control block.
+ */
+struct sie_page2 {
+       __u64 fac_list[S390_ARCH_FAC_LIST_SIZE_U64];    /* 0x0000 */
+       struct kvm_s390_crypto_cb crycb;                /* 0x0800 */
+       u8 reserved900[0x1000 - 0x900];                 /* 0x0900 */
+} __packed;
+
 struct kvm_arch{
        void *sca;
        int use_esca;
@@ -643,6 +653,7 @@ struct kvm_arch{
        int ipte_lock_count;
        struct mutex ipte_mutex;
        spinlock_t start_stop_lock;
+       struct sie_page2 *sie_page2;
        struct kvm_s390_cpu_model model;
        struct kvm_s390_crypto crypto;
        u64 epoch;
index fb1b93ea3e3fead0efde9f30e819c55eecb88da9..e485817f7b1a97683e64ab04d1f7444e1aae2e1d 100644 (file)
 static inline int init_new_context(struct task_struct *tsk,
                                   struct mm_struct *mm)
 {
+       spin_lock_init(&mm->context.list_lock);
+       INIT_LIST_HEAD(&mm->context.pgtable_list);
+       INIT_LIST_HEAD(&mm->context.gmap_list);
        cpumask_clear(&mm->context.cpu_attach_mask);
        atomic_set(&mm->context.attach_count, 0);
        mm->context.flush_mm = 0;
-       mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
-       mm->context.asce_bits |= _ASCE_TYPE_REGION3;
 #ifdef CONFIG_PGSTE
        mm->context.alloc_pgste = page_table_allocate_pgste;
        mm->context.has_pgste = 0;
        mm->context.use_skey = 0;
 #endif
-       mm->context.asce_limit = STACK_TOP_MAX;
+       if (mm->context.asce_limit == 0) {
+               /* context created by exec, set asce limit to 4TB */
+               mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                       _ASCE_USER_BITS | _ASCE_TYPE_REGION3;
+               mm->context.asce_limit = STACK_TOP_MAX;
+       } else if (mm->context.asce_limit == (1UL << 31)) {
+               mm_inc_nr_pmds(mm);
+       }
        crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
        return 0;
 }
@@ -111,8 +119,6 @@ static inline void activate_mm(struct mm_struct *prev,
 static inline void arch_dup_mmap(struct mm_struct *oldmm,
                                 struct mm_struct *mm)
 {
-       if (oldmm->context.asce_limit < mm->context.asce_limit)
-               crst_table_downgrade(mm, oldmm->context.asce_limit);
 }
 
 static inline void arch_exit_mmap(struct mm_struct *mm)
index c873e682b67f8e4063628a1726a896a167a9d8c4..b6bfa169a002c051649a2909281fe8c203a00ee7 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <asm-generic/pci.h>
-#include <asm-generic/pci-dma-compat.h>
 #include <asm/pci_clp.h>
 #include <asm/pci_debug.h>
 
@@ -45,7 +44,7 @@ struct zpci_fmb {
        u64 rpcit_ops;
        u64 dma_rbytes;
        u64 dma_wbytes;
-} __packed __aligned(16);
+} __packed __aligned(64);
 
 enum zpci_state {
        ZPCI_FN_STATE_RESERVED,
@@ -66,7 +65,6 @@ struct s390_domain;
 
 /* Private data per function */
 struct zpci_dev {
-       struct pci_dev  *pdev;
        struct pci_bus  *bus;
        struct list_head entry;         /* list of all zpci_devices, needed for hotplug, etc. */
 
@@ -192,7 +190,7 @@ int zpci_fmb_disable_device(struct zpci_dev *);
 /* Debug */
 int zpci_debug_init(void);
 void zpci_debug_exit(void);
-void zpci_debug_init_device(struct zpci_dev *);
+void zpci_debug_init_device(struct zpci_dev *, const char *);
 void zpci_debug_exit_device(struct zpci_dev *);
 void zpci_debug_info(struct zpci_dev *, struct seq_file *);
 
index dd78f92f1cce5fc419e795e325800d1c78a155ac..e75c64cbcf080a260f5578d9b8383ed73d9617ba 100644 (file)
@@ -49,9 +49,6 @@ struct clp_fh_list_entry {
 /* List PCI functions request */
 struct clp_req_list_pci {
        struct clp_req_hdr hdr;
-       u32 fmt                 :  4;   /* cmd request block format */
-       u32                     : 28;
-       u64 reserved1;
        u64 resume_token;
        u64 reserved2;
 } __packed;
@@ -59,9 +56,6 @@ struct clp_req_list_pci {
 /* List PCI functions response */
 struct clp_rsp_list_pci {
        struct clp_rsp_hdr hdr;
-       u32 fmt                 :  4;   /* cmd request block format */
-       u32                     : 28;
-       u64 reserved1;
        u64 resume_token;
        u32 reserved2;
        u16 max_fn;
@@ -73,9 +67,6 @@ struct clp_rsp_list_pci {
 /* Query PCI function request */
 struct clp_req_query_pci {
        struct clp_req_hdr hdr;
-       u32 fmt                 :  4;   /* cmd request block format */
-       u32                     : 28;
-       u64 reserved1;
        u32 fh;                         /* function handle */
        u32 reserved2;
        u64 reserved3;
@@ -84,9 +75,6 @@ struct clp_req_query_pci {
 /* Query PCI function response */
 struct clp_rsp_query_pci {
        struct clp_rsp_hdr hdr;
-       u32 fmt                 :  4;   /* cmd request block format */
-       u32                     : 28;
-       u64                     : 64;
        u16 vfn;                        /* virtual fn number */
        u16                     :  7;
        u16 util_str_avail      :  1;   /* utility string available? */
@@ -108,21 +96,15 @@ struct clp_rsp_query_pci {
 /* Query PCI function group request */
 struct clp_req_query_pci_grp {
        struct clp_req_hdr hdr;
-       u32 fmt                 :  4;   /* cmd request block format */
-       u32                     : 28;
-       u64 reserved1;
-       u32                     : 24;
+       u32 reserved2           : 24;
        u32 pfgid               :  8;   /* function group id */
-       u32 reserved2;
-       u64 reserved3;
+       u32 reserved3;
+       u64 reserved4;
 } __packed;
 
 /* Query PCI function group response */
 struct clp_rsp_query_pci_grp {
        struct clp_rsp_hdr hdr;
-       u32 fmt                 :  4;   /* cmd request block format */
-       u32                     : 28;
-       u64 reserved1;
        u16                     :  4;
        u16 noi                 : 12;   /* number of interrupts */
        u8 version;
@@ -141,9 +123,6 @@ struct clp_rsp_query_pci_grp {
 /* Set PCI function request */
 struct clp_req_set_pci {
        struct clp_req_hdr hdr;
-       u32 fmt                 :  4;   /* cmd request block format */
-       u32                     : 28;
-       u64 reserved1;
        u32 fh;                         /* function handle */
        u16 reserved2;
        u8 oc;                          /* operation controls */
@@ -154,9 +133,6 @@ struct clp_req_set_pci {
 /* Set PCI function response */
 struct clp_rsp_set_pci {
        struct clp_rsp_hdr hdr;
-       u32 fmt                 :  4;   /* cmd request block format */
-       u32                     : 28;
-       u64 reserved1;
        u32 fh;                         /* function handle */
        u32 reserved3;
        u64 reserved4;
index 6d6556ca24aa2bd4cc2e8b1f566fa39da811fdc9..90240dfef76a1f95ab2b2a611f716af7b784eab8 100644 (file)
        ret__;                                                          \
 })
 
-#define this_cpu_cmpxchg_double_4 arch_this_cpu_cmpxchg_double
 #define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double
 
 #include <asm-generic/percpu.h>
index f897ec73dc8c9c02943a5c76254140bc951a6024..1f7ff85c5e4cc60d796ef5390a43b8ca85d47204 100644 (file)
@@ -21,7 +21,7 @@
 #define PMU_F_ERR_LSDA                 0x0200
 #define PMU_F_ERR_MASK                 (PMU_F_ERR_IBE|PMU_F_ERR_LSDA)
 
-/* Perf defintions for PMU event attributes in sysfs */
+/* Perf definitions for PMU event attributes in sysfs */
 extern __init const struct attribute_group **cpumf_cf_event_group(void);
 extern ssize_t cpumf_events_sysfs_show(struct device *dev,
                                       struct device_attribute *attr,
index 7b7858f158b4574b549ab99648f977a3e249068c..9b3d9b6099f2a8dd76a14f874dad8cc2715c2267 100644 (file)
@@ -23,10 +23,6 @@ void page_table_free(struct mm_struct *, unsigned long *);
 void page_table_free_rcu(struct mmu_gather *, unsigned long *, unsigned long);
 extern int page_table_allocate_pgste;
 
-int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
-                         unsigned long key, bool nq);
-unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr);
-
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 {
        typedef struct { char _[n]; } addrtype;
@@ -100,12 +96,26 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       spin_lock_init(&mm->context.list_lock);
-       INIT_LIST_HEAD(&mm->context.pgtable_list);
-       INIT_LIST_HEAD(&mm->context.gmap_list);
-       return (pgd_t *) crst_table_alloc(mm);
+       unsigned long *table = crst_table_alloc(mm);
+
+       if (!table)
+               return NULL;
+       if (mm->context.asce_limit == (1UL << 31)) {
+               /* Forking a compat process with 2 page table levels */
+               if (!pgtable_pmd_page_ctor(virt_to_page(table))) {
+                       crst_table_free(mm, table);
+                       return NULL;
+               }
+       }
+       return (pgd_t *) table;
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+       if (mm->context.asce_limit == (1UL << 31))
+               pgtable_pmd_page_dtor(virt_to_page(pgd));
+       crst_table_free(mm, (unsigned long *) pgd);
 }
-#define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
 
 static inline void pmd_populate(struct mm_struct *mm,
                                pmd_t *pmd, pgtable_t pte)
index 64ead80912488b476e19a004eaf01924dbdc6b4c..2f66645587a2a134d9d2a304ae6508fedfc1fd8a 100644 (file)
@@ -298,15 +298,15 @@ static inline int is_module_addr(void *addr)
 
 /*
  * Segment table entry encoding (R = read-only, I = invalid, y = young bit):
- *                             dy..R...I...wr
+ *                             dy..R...I...rw
  * prot-none, clean, old       00..1...1...00
  * prot-none, clean, young     01..1...1...00
  * prot-none, dirty, old       10..1...1...00
  * prot-none, dirty, young     11..1...1...00
- * read-only, clean, old       00..1...1...01
- * read-only, clean, young     01..1...0...01
- * read-only, dirty, old       10..1...1...01
- * read-only, dirty, young     11..1...0...01
+ * read-only, clean, old       00..1...1...10
+ * read-only, clean, young     01..1...0...10
+ * read-only, dirty, old       10..1...1...10
+ * read-only, dirty, young     11..1...0...10
  * read-write, clean, old      00..1...1...11
  * read-write, clean, young    01..1...0...11
  * read-write, dirty, old      10..0...1...11
@@ -520,15 +520,6 @@ static inline int pmd_bad(pmd_t pmd)
        return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0;
 }
 
-#define  __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
-extern int pmdp_set_access_flags(struct vm_area_struct *vma,
-                                unsigned long address, pmd_t *pmdp,
-                                pmd_t entry, int dirty);
-
-#define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH
-extern int pmdp_clear_flush_young(struct vm_area_struct *vma,
-                                 unsigned long address, pmd_t *pmdp);
-
 #define __HAVE_ARCH_PMD_WRITE
 static inline int pmd_write(pmd_t pmd)
 {
@@ -631,208 +622,6 @@ static inline pmd_t pmd_clear_soft_dirty(pmd_t pmd)
        return pmd;
 }
 
-static inline pgste_t pgste_get_lock(pte_t *ptep)
-{
-       unsigned long new = 0;
-#ifdef CONFIG_PGSTE
-       unsigned long old;
-
-       preempt_disable();
-       asm(
-               "       lg      %0,%2\n"
-               "0:     lgr     %1,%0\n"
-               "       nihh    %0,0xff7f\n"    /* clear PCL bit in old */
-               "       oihh    %1,0x0080\n"    /* set PCL bit in new */
-               "       csg     %0,%1,%2\n"
-               "       jl      0b\n"
-               : "=&d" (old), "=&d" (new), "=Q" (ptep[PTRS_PER_PTE])
-               : "Q" (ptep[PTRS_PER_PTE]) : "cc", "memory");
-#endif
-       return __pgste(new);
-}
-
-static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste)
-{
-#ifdef CONFIG_PGSTE
-       asm(
-               "       nihh    %1,0xff7f\n"    /* clear PCL bit */
-               "       stg     %1,%0\n"
-               : "=Q" (ptep[PTRS_PER_PTE])
-               : "d" (pgste_val(pgste)), "Q" (ptep[PTRS_PER_PTE])
-               : "cc", "memory");
-       preempt_enable();
-#endif
-}
-
-static inline pgste_t pgste_get(pte_t *ptep)
-{
-       unsigned long pgste = 0;
-#ifdef CONFIG_PGSTE
-       pgste = *(unsigned long *)(ptep + PTRS_PER_PTE);
-#endif
-       return __pgste(pgste);
-}
-
-static inline void pgste_set(pte_t *ptep, pgste_t pgste)
-{
-#ifdef CONFIG_PGSTE
-       *(pgste_t *)(ptep + PTRS_PER_PTE) = pgste;
-#endif
-}
-
-static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste,
-                                      struct mm_struct *mm)
-{
-#ifdef CONFIG_PGSTE
-       unsigned long address, bits, skey;
-
-       if (!mm_use_skey(mm) || pte_val(*ptep) & _PAGE_INVALID)
-               return pgste;
-       address = pte_val(*ptep) & PAGE_MASK;
-       skey = (unsigned long) page_get_storage_key(address);
-       bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
-       /* Transfer page changed & referenced bit to guest bits in pgste */
-       pgste_val(pgste) |= bits << 48;         /* GR bit & GC bit */
-       /* Copy page access key and fetch protection bit to pgste */
-       pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT);
-       pgste_val(pgste) |= (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56;
-#endif
-       return pgste;
-
-}
-
-static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry,
-                                struct mm_struct *mm)
-{
-#ifdef CONFIG_PGSTE
-       unsigned long address;
-       unsigned long nkey;
-
-       if (!mm_use_skey(mm) || pte_val(entry) & _PAGE_INVALID)
-               return;
-       VM_BUG_ON(!(pte_val(*ptep) & _PAGE_INVALID));
-       address = pte_val(entry) & PAGE_MASK;
-       /*
-        * Set page access key and fetch protection bit from pgste.
-        * The guest C/R information is still in the PGSTE, set real
-        * key C/R to 0.
-        */
-       nkey = (pgste_val(pgste) & (PGSTE_ACC_BITS | PGSTE_FP_BIT)) >> 56;
-       nkey |= (pgste_val(pgste) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 48;
-       page_set_storage_key(address, nkey, 0);
-#endif
-}
-
-static inline pgste_t pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
-{
-       if ((pte_val(entry) & _PAGE_PRESENT) &&
-           (pte_val(entry) & _PAGE_WRITE) &&
-           !(pte_val(entry) & _PAGE_INVALID)) {
-               if (!MACHINE_HAS_ESOP) {
-                       /*
-                        * Without enhanced suppression-on-protection force
-                        * the dirty bit on for all writable ptes.
-                        */
-                       pte_val(entry) |= _PAGE_DIRTY;
-                       pte_val(entry) &= ~_PAGE_PROTECT;
-               }
-               if (!(pte_val(entry) & _PAGE_PROTECT))
-                       /* This pte allows write access, set user-dirty */
-                       pgste_val(pgste) |= PGSTE_UC_BIT;
-       }
-       *ptep = entry;
-       return pgste;
-}
-
-/**
- * struct gmap_struct - guest address space
- * @crst_list: list of all crst tables used in the guest address space
- * @mm: pointer to the parent mm_struct
- * @guest_to_host: radix tree with guest to host address translation
- * @host_to_guest: radix tree with pointer to segment table entries
- * @guest_table_lock: spinlock to protect all entries in the guest page table
- * @table: pointer to the page directory
- * @asce: address space control element for gmap page table
- * @pfault_enabled: defines if pfaults are applicable for the guest
- */
-struct gmap {
-       struct list_head list;
-       struct list_head crst_list;
-       struct mm_struct *mm;
-       struct radix_tree_root guest_to_host;
-       struct radix_tree_root host_to_guest;
-       spinlock_t guest_table_lock;
-       unsigned long *table;
-       unsigned long asce;
-       unsigned long asce_end;
-       void *private;
-       bool pfault_enabled;
-};
-
-/**
- * struct gmap_notifier - notify function block for page invalidation
- * @notifier_call: address of callback function
- */
-struct gmap_notifier {
-       struct list_head list;
-       void (*notifier_call)(struct gmap *gmap, unsigned long gaddr);
-};
-
-struct gmap *gmap_alloc(struct mm_struct *mm, unsigned long limit);
-void gmap_free(struct gmap *gmap);
-void gmap_enable(struct gmap *gmap);
-void gmap_disable(struct gmap *gmap);
-int gmap_map_segment(struct gmap *gmap, unsigned long from,
-                    unsigned long to, unsigned long len);
-int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
-unsigned long __gmap_translate(struct gmap *, unsigned long gaddr);
-unsigned long gmap_translate(struct gmap *, unsigned long gaddr);
-int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr);
-int gmap_fault(struct gmap *, unsigned long gaddr, unsigned int fault_flags);
-void gmap_discard(struct gmap *, unsigned long from, unsigned long to);
-void __gmap_zap(struct gmap *, unsigned long gaddr);
-bool gmap_test_and_clear_dirty(unsigned long address, struct gmap *);
-
-
-void gmap_register_ipte_notifier(struct gmap_notifier *);
-void gmap_unregister_ipte_notifier(struct gmap_notifier *);
-int gmap_ipte_notify(struct gmap *, unsigned long start, unsigned long len);
-void gmap_do_ipte_notify(struct mm_struct *, unsigned long addr, pte_t *);
-
-static inline pgste_t pgste_ipte_notify(struct mm_struct *mm,
-                                       unsigned long addr,
-                                       pte_t *ptep, pgste_t pgste)
-{
-#ifdef CONFIG_PGSTE
-       if (pgste_val(pgste) & PGSTE_IN_BIT) {
-               pgste_val(pgste) &= ~PGSTE_IN_BIT;
-               gmap_do_ipte_notify(mm, addr, ptep);
-       }
-#endif
-       return pgste;
-}
-
-/*
- * Certain architectures need to do special things when PTEs
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
-                             pte_t *ptep, pte_t entry)
-{
-       pgste_t pgste;
-
-       if (mm_has_pgste(mm)) {
-               pgste = pgste_get_lock(ptep);
-               pgste_val(pgste) &= ~_PGSTE_GPS_ZERO;
-               pgste_set_key(ptep, pgste, entry, mm);
-               pgste = pgste_set_pte(ptep, pgste, entry);
-               pgste_set_unlock(ptep, pgste);
-       } else {
-               *ptep = entry;
-       }
-}
-
 /*
  * query functions pte_write/pte_dirty/pte_young only work if
  * pte_present() is true. Undefined behaviour if not..
@@ -998,96 +787,30 @@ static inline void __ptep_ipte_range(unsigned long address, int nr, pte_t *ptep)
        } while (nr != 255);
 }
 
-static inline void ptep_flush_direct(struct mm_struct *mm,
-                                    unsigned long address, pte_t *ptep)
-{
-       int active, count;
-
-       if (pte_val(*ptep) & _PAGE_INVALID)
-               return;
-       active = (mm == current->active_mm) ? 1 : 0;
-       count = atomic_add_return(0x10000, &mm->context.attach_count);
-       if (MACHINE_HAS_TLB_LC && (count & 0xffff) <= active &&
-           cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
-               __ptep_ipte_local(address, ptep);
-       else
-               __ptep_ipte(address, ptep);
-       atomic_sub(0x10000, &mm->context.attach_count);
-}
-
-static inline void ptep_flush_lazy(struct mm_struct *mm,
-                                  unsigned long address, pte_t *ptep)
-{
-       int active, count;
-
-       if (pte_val(*ptep) & _PAGE_INVALID)
-               return;
-       active = (mm == current->active_mm) ? 1 : 0;
-       count = atomic_add_return(0x10000, &mm->context.attach_count);
-       if ((count & 0xffff) <= active) {
-               pte_val(*ptep) |= _PAGE_INVALID;
-               mm->context.flush_mm = 1;
-       } else
-               __ptep_ipte(address, ptep);
-       atomic_sub(0x10000, &mm->context.attach_count);
-}
-
 /*
- * Get (and clear) the user dirty bit for a pte.
+ * This is hard to understand. ptep_get_and_clear and ptep_clear_flush
+ * both clear the TLB for the unmapped pte. The reason is that
+ * ptep_get_and_clear is used in common code (e.g. change_pte_range)
+ * to modify an active pte. The sequence is
+ *   1) ptep_get_and_clear
+ *   2) set_pte_at
+ *   3) flush_tlb_range
+ * On s390 the tlb needs to get flushed with the modification of the pte
+ * if the pte is active. The only way how this can be implemented is to
+ * have ptep_get_and_clear do the tlb flush. In exchange flush_tlb_range
+ * is a nop.
  */
-static inline int ptep_test_and_clear_user_dirty(struct mm_struct *mm,
-                                                unsigned long addr,
-                                                pte_t *ptep)
-{
-       pgste_t pgste;
-       pte_t pte;
-       int dirty;
-
-       if (!mm_has_pgste(mm))
-               return 0;
-       pgste = pgste_get_lock(ptep);
-       dirty = !!(pgste_val(pgste) & PGSTE_UC_BIT);
-       pgste_val(pgste) &= ~PGSTE_UC_BIT;
-       pte = *ptep;
-       if (dirty && (pte_val(pte) & _PAGE_PRESENT)) {
-               pgste = pgste_ipte_notify(mm, addr, ptep, pgste);
-               __ptep_ipte(addr, ptep);
-               if (MACHINE_HAS_ESOP || !(pte_val(pte) & _PAGE_WRITE))
-                       pte_val(pte) |= _PAGE_PROTECT;
-               else
-                       pte_val(pte) |= _PAGE_INVALID;
-               *ptep = pte;
-       }
-       pgste_set_unlock(ptep, pgste);
-       return dirty;
-}
+pte_t ptep_xchg_direct(struct mm_struct *, unsigned long, pte_t *, pte_t);
+pte_t ptep_xchg_lazy(struct mm_struct *, unsigned long, pte_t *, pte_t);
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
                                            unsigned long addr, pte_t *ptep)
 {
-       pgste_t pgste;
-       pte_t pte, oldpte;
-       int young;
-
-       if (mm_has_pgste(vma->vm_mm)) {
-               pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(vma->vm_mm, addr, ptep, pgste);
-       }
-
-       oldpte = pte = *ptep;
-       ptep_flush_direct(vma->vm_mm, addr, ptep);
-       young = pte_young(pte);
-       pte = pte_mkold(pte);
-
-       if (mm_has_pgste(vma->vm_mm)) {
-               pgste = pgste_update_all(&oldpte, pgste, vma->vm_mm);
-               pgste = pgste_set_pte(ptep, pgste, pte);
-               pgste_set_unlock(ptep, pgste);
-       } else
-               *ptep = pte;
+       pte_t pte = *ptep;
 
-       return young;
+       pte = ptep_xchg_direct(vma->vm_mm, addr, ptep, pte_mkold(pte));
+       return pte_young(pte);
 }
 
 #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
@@ -1097,104 +820,22 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
        return ptep_test_and_clear_young(vma, address, ptep);
 }
 
-/*
- * This is hard to understand. ptep_get_and_clear and ptep_clear_flush
- * both clear the TLB for the unmapped pte. The reason is that
- * ptep_get_and_clear is used in common code (e.g. change_pte_range)
- * to modify an active pte. The sequence is
- *   1) ptep_get_and_clear
- *   2) set_pte_at
- *   3) flush_tlb_range
- * On s390 the tlb needs to get flushed with the modification of the pte
- * if the pte is active. The only way how this can be implemented is to
- * have ptep_get_and_clear do the tlb flush. In exchange flush_tlb_range
- * is a nop.
- */
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
-                                      unsigned long address, pte_t *ptep)
+                                      unsigned long addr, pte_t *ptep)
 {
-       pgste_t pgste;
-       pte_t pte;
-
-       if (mm_has_pgste(mm)) {
-               pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(mm, address, ptep, pgste);
-       }
-
-       pte = *ptep;
-       ptep_flush_lazy(mm, address, ptep);
-       pte_val(*ptep) = _PAGE_INVALID;
-
-       if (mm_has_pgste(mm)) {
-               pgste = pgste_update_all(&pte, pgste, mm);
-               pgste_set_unlock(ptep, pgste);
-       }
-       return pte;
+       return ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
 }
 
 #define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
-static inline pte_t ptep_modify_prot_start(struct mm_struct *mm,
-                                          unsigned long address,
-                                          pte_t *ptep)
-{
-       pgste_t pgste;
-       pte_t pte;
-
-       if (mm_has_pgste(mm)) {
-               pgste = pgste_get_lock(ptep);
-               pgste_ipte_notify(mm, address, ptep, pgste);
-       }
-
-       pte = *ptep;
-       ptep_flush_lazy(mm, address, ptep);
-
-       if (mm_has_pgste(mm)) {
-               pgste = pgste_update_all(&pte, pgste, mm);
-               pgste_set(ptep, pgste);
-       }
-       return pte;
-}
-
-static inline void ptep_modify_prot_commit(struct mm_struct *mm,
-                                          unsigned long address,
-                                          pte_t *ptep, pte_t pte)
-{
-       pgste_t pgste;
-
-       if (mm_has_pgste(mm)) {
-               pgste = pgste_get(ptep);
-               pgste_set_key(ptep, pgste, pte, mm);
-               pgste = pgste_set_pte(ptep, pgste, pte);
-               pgste_set_unlock(ptep, pgste);
-       } else
-               *ptep = pte;
-}
+pte_t ptep_modify_prot_start(struct mm_struct *, unsigned long, pte_t *);
+void ptep_modify_prot_commit(struct mm_struct *, unsigned long, pte_t *, pte_t);
 
 #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
 static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
-                                    unsigned long address, pte_t *ptep)
+                                    unsigned long addr, pte_t *ptep)
 {
-       pgste_t pgste;
-       pte_t pte;
-
-       if (mm_has_pgste(vma->vm_mm)) {
-               pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(vma->vm_mm, address, ptep, pgste);
-       }
-
-       pte = *ptep;
-       ptep_flush_direct(vma->vm_mm, address, ptep);
-       pte_val(*ptep) = _PAGE_INVALID;
-
-       if (mm_has_pgste(vma->vm_mm)) {
-               if ((pgste_val(pgste) & _PGSTE_GPS_USAGE_MASK) ==
-                   _PGSTE_GPS_USAGE_UNUSED)
-                       pte_val(pte) |= _PAGE_UNUSED;
-               pgste = pgste_update_all(&pte, pgste, vma->vm_mm);
-               pgste_set_unlock(ptep, pgste);
-       }
-       return pte;
+       return ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID));
 }
 
 /*
@@ -1206,80 +847,66 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
  */
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
 static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
-                                           unsigned long address,
+                                           unsigned long addr,
                                            pte_t *ptep, int full)
 {
-       pgste_t pgste;
-       pte_t pte;
-
-       if (!full && mm_has_pgste(mm)) {
-               pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(mm, address, ptep, pgste);
-       }
-
-       pte = *ptep;
-       if (!full)
-               ptep_flush_lazy(mm, address, ptep);
-       pte_val(*ptep) = _PAGE_INVALID;
-
-       if (!full && mm_has_pgste(mm)) {
-               pgste = pgste_update_all(&pte, pgste, mm);
-               pgste_set_unlock(ptep, pgste);
+       if (full) {
+               pte_t pte = *ptep;
+               *ptep = __pte(_PAGE_INVALID);
+               return pte;
        }
-       return pte;
+       return ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
 }
 
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-static inline pte_t ptep_set_wrprotect(struct mm_struct *mm,
-                                      unsigned long address, pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm,
+                                     unsigned long addr, pte_t *ptep)
 {
-       pgste_t pgste;
        pte_t pte = *ptep;
 
-       if (pte_write(pte)) {
-               if (mm_has_pgste(mm)) {
-                       pgste = pgste_get_lock(ptep);
-                       pgste = pgste_ipte_notify(mm, address, ptep, pgste);
-               }
-
-               ptep_flush_lazy(mm, address, ptep);
-               pte = pte_wrprotect(pte);
-
-               if (mm_has_pgste(mm)) {
-                       pgste = pgste_set_pte(ptep, pgste, pte);
-                       pgste_set_unlock(ptep, pgste);
-               } else
-                       *ptep = pte;
-       }
-       return pte;
+       if (pte_write(pte))
+               ptep_xchg_lazy(mm, addr, ptep, pte_wrprotect(pte));
 }
 
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 static inline int ptep_set_access_flags(struct vm_area_struct *vma,
-                                       unsigned long address, pte_t *ptep,
+                                       unsigned long addr, pte_t *ptep,
                                        pte_t entry, int dirty)
 {
-       pgste_t pgste;
-       pte_t oldpte;
-
-       oldpte = *ptep;
-       if (pte_same(oldpte, entry))
+       if (pte_same(*ptep, entry))
                return 0;
-       if (mm_has_pgste(vma->vm_mm)) {
-               pgste = pgste_get_lock(ptep);
-               pgste = pgste_ipte_notify(vma->vm_mm, address, ptep, pgste);
-       }
+       ptep_xchg_direct(vma->vm_mm, addr, ptep, entry);
+       return 1;
+}
 
-       ptep_flush_direct(vma->vm_mm, address, ptep);
+/*
+ * Additional functions to handle KVM guest page tables
+ */
+void ptep_set_pte_at(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, pte_t entry);
+void ptep_set_notify(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+void ptep_notify(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+void ptep_zap_unused(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep , int reset);
+void ptep_zap_key(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
+
+bool test_and_clear_guest_dirty(struct mm_struct *mm, unsigned long address);
+int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
+                         unsigned char key, bool nq);
+unsigned char get_guest_storage_key(struct mm_struct *mm, unsigned long addr);
 
-       if (mm_has_pgste(vma->vm_mm)) {
-               if (pte_val(oldpte) & _PAGE_INVALID)
-                       pgste_set_key(ptep, pgste, entry, vma->vm_mm);
-               pgste = pgste_set_pte(ptep, pgste, entry);
-               pgste_set_unlock(ptep, pgste);
-       } else
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t entry)
+{
+       if (mm_has_pgste(mm))
+               ptep_set_pte_at(mm, addr, ptep, entry);
+       else
                *ptep = entry;
-       return 1;
 }
 
 /*
@@ -1476,54 +1103,51 @@ static inline void __pmdp_idte_local(unsigned long address, pmd_t *pmdp)
                : "cc" );
 }
 
-static inline void pmdp_flush_direct(struct mm_struct *mm,
-                                    unsigned long address, pmd_t *pmdp)
-{
-       int active, count;
+pmd_t pmdp_xchg_direct(struct mm_struct *, unsigned long, pmd_t *, pmd_t);
+pmd_t pmdp_xchg_lazy(struct mm_struct *, unsigned long, pmd_t *, pmd_t);
 
-       if (pmd_val(*pmdp) & _SEGMENT_ENTRY_INVALID)
-               return;
-       if (!MACHINE_HAS_IDTE) {
-               __pmdp_csp(pmdp);
-               return;
-       }
-       active = (mm == current->active_mm) ? 1 : 0;
-       count = atomic_add_return(0x10000, &mm->context.attach_count);
-       if (MACHINE_HAS_TLB_LC && (count & 0xffff) <= active &&
-           cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
-               __pmdp_idte_local(address, pmdp);
-       else
-               __pmdp_idte(address, pmdp);
-       atomic_sub(0x10000, &mm->context.attach_count);
-}
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 
-static inline void pmdp_flush_lazy(struct mm_struct *mm,
-                                  unsigned long address, pmd_t *pmdp)
+#define __HAVE_ARCH_PGTABLE_DEPOSIT
+void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+                               pgtable_t pgtable);
+
+#define __HAVE_ARCH_PGTABLE_WITHDRAW
+pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
+
+#define  __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
+static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
+                                       unsigned long addr, pmd_t *pmdp,
+                                       pmd_t entry, int dirty)
 {
-       int active, count;
+       VM_BUG_ON(addr & ~HPAGE_MASK);
 
-       if (pmd_val(*pmdp) & _SEGMENT_ENTRY_INVALID)
-               return;
-       active = (mm == current->active_mm) ? 1 : 0;
-       count = atomic_add_return(0x10000, &mm->context.attach_count);
-       if ((count & 0xffff) <= active) {
-               pmd_val(*pmdp) |= _SEGMENT_ENTRY_INVALID;
-               mm->context.flush_mm = 1;
-       } else if (MACHINE_HAS_IDTE)
-               __pmdp_idte(address, pmdp);
-       else
-               __pmdp_csp(pmdp);
-       atomic_sub(0x10000, &mm->context.attach_count);
+       entry = pmd_mkyoung(entry);
+       if (dirty)
+               entry = pmd_mkdirty(entry);
+       if (pmd_val(*pmdp) == pmd_val(entry))
+               return 0;
+       pmdp_xchg_direct(vma->vm_mm, addr, pmdp, entry);
+       return 1;
 }
 
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
+static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
+                                           unsigned long addr, pmd_t *pmdp)
+{
+       pmd_t pmd = *pmdp;
 
-#define __HAVE_ARCH_PGTABLE_DEPOSIT
-extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
-                                      pgtable_t pgtable);
+       pmd = pmdp_xchg_direct(vma->vm_mm, addr, pmdp, pmd_mkold(pmd));
+       return pmd_young(pmd);
+}
 
-#define __HAVE_ARCH_PGTABLE_WITHDRAW
-extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
+#define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH
+static inline int pmdp_clear_flush_young(struct vm_area_struct *vma,
+                                        unsigned long addr, pmd_t *pmdp)
+{
+       VM_BUG_ON(addr & ~HPAGE_MASK);
+       return pmdp_test_and_clear_young(vma, addr, pmdp);
+}
 
 static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
                              pmd_t *pmdp, pmd_t entry)
@@ -1539,66 +1163,48 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
        return pmd;
 }
 
-#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
-static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
-                                           unsigned long address, pmd_t *pmdp)
-{
-       pmd_t pmd;
-
-       pmd = *pmdp;
-       pmdp_flush_direct(vma->vm_mm, address, pmdp);
-       *pmdp = pmd_mkold(pmd);
-       return pmd_young(pmd);
-}
-
 #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
 static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
-                                           unsigned long address, pmd_t *pmdp)
+                                           unsigned long addr, pmd_t *pmdp)
 {
-       pmd_t pmd = *pmdp;
-
-       pmdp_flush_direct(mm, address, pmdp);
-       pmd_clear(pmdp);
-       return pmd;
+       return pmdp_xchg_direct(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_INVALID));
 }
 
 #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL
 static inline pmd_t pmdp_huge_get_and_clear_full(struct mm_struct *mm,
-                                                unsigned long address,
+                                                unsigned long addr,
                                                 pmd_t *pmdp, int full)
 {
-       pmd_t pmd = *pmdp;
-
-       if (!full)
-               pmdp_flush_lazy(mm, address, pmdp);
-       pmd_clear(pmdp);
-       return pmd;
+       if (full) {
+               pmd_t pmd = *pmdp;
+               *pmdp = __pmd(_SEGMENT_ENTRY_INVALID);
+               return pmd;
+       }
+       return pmdp_xchg_lazy(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_INVALID));
 }
 
 #define __HAVE_ARCH_PMDP_HUGE_CLEAR_FLUSH
 static inline pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma,
-                                         unsigned long address, pmd_t *pmdp)
+                                         unsigned long addr, pmd_t *pmdp)
 {
-       return pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp);
+       return pmdp_huge_get_and_clear(vma->vm_mm, addr, pmdp);
 }
 
 #define __HAVE_ARCH_PMDP_INVALIDATE
 static inline void pmdp_invalidate(struct vm_area_struct *vma,
-                                  unsigned long address, pmd_t *pmdp)
+                                  unsigned long addr, pmd_t *pmdp)
 {
-       pmdp_flush_direct(vma->vm_mm, address, pmdp);
+       pmdp_xchg_direct(vma->vm_mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_INVALID));
 }
 
 #define __HAVE_ARCH_PMDP_SET_WRPROTECT
 static inline void pmdp_set_wrprotect(struct mm_struct *mm,
-                                     unsigned long address, pmd_t *pmdp)
+                                     unsigned long addr, pmd_t *pmdp)
 {
        pmd_t pmd = *pmdp;
 
-       if (pmd_write(pmd)) {
-               pmdp_flush_direct(mm, address, pmdp);
-               set_pmd_at(mm, address, pmdp, pmd_wrprotect(pmd));
-       }
+       if (pmd_write(pmd))
+               pmd = pmdp_xchg_lazy(mm, addr, pmdp, pmd_wrprotect(pmd));
 }
 
 static inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
index 1c4fe129486d2e0a9282dc72a3735c4727277b52..d6fd22ea270db0e5446a41aaabc3d9ce1445e350 100644 (file)
@@ -184,6 +184,10 @@ struct task_struct;
 struct mm_struct;
 struct seq_file;
 
+typedef int (*dump_trace_func_t)(void *data, unsigned long address);
+void dump_trace(dump_trace_func_t func, void *data,
+               struct task_struct *task, unsigned long sp);
+
 void show_cacheinfo(struct seq_file *m);
 
 /* Free all resources held by a thread. */
@@ -203,6 +207,14 @@ unsigned long get_wchan(struct task_struct *p);
 /* Has task runtime instrumentation enabled ? */
 #define is_ri_task(tsk) (!!(tsk)->thread.ri_cb)
 
+static inline unsigned long current_stack_pointer(void)
+{
+       unsigned long sp;
+
+       asm volatile("la %0,0(15)" : "=a" (sp));
+       return sp;
+}
+
 static inline unsigned short stap(void)
 {
        unsigned short cpu_address;
index 4b43ee7e6776ca0ff98c2c2317cd4d25167b8409..fead491dfc28522017b1be01b1160ce788d052cb 100644 (file)
@@ -31,7 +31,7 @@
  * This should be totally fair - if anything is waiting, a process that wants a
  * lock will go to the back of the queue. When the currently active lock is
  * released, if there's a writer at the front of the queue, then that and only
- * that will be woken up; if there's a bunch of consequtive readers at the
+ * that will be woken up; if there's a bunch of consecutive readers at the
  * front, then they'll all be woken up, but no other readers will be.
  */
 
index 69837225119e675136edce82b65c9df6df5110a2..c0f0efbb6ab5b43c6d503d600c376b30a130c296 100644 (file)
@@ -101,6 +101,8 @@ extern void pfault_fini(void);
 #define pfault_fini()          do { } while (0)
 #endif /* CONFIG_PFAULT */
 
+void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault);
+
 extern void cmma_init(void);
 
 extern void (*_machine_restart)(char *command);
index c82eb12a5b1810e059e72db19b124e0078a3cbce..c988df744a70886d63b0ae3a50e7aa3d91c237c7 100644 (file)
@@ -1 +1,20 @@
-#include <asm-generic/xor.h>
+/*
+ * Optimited xor routines
+ *
+ * Copyright IBM Corp. 2016
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+#ifndef _ASM_S390_XOR_H
+#define _ASM_S390_XOR_H
+
+extern struct xor_block_template xor_block_xc;
+
+#undef XOR_TRY_TEMPLATES
+#define XOR_TRY_TEMPLATES                              \
+do {                                                   \
+       xor_speed(&xor_block_xc);                       \
+} while (0)
+
+#define XOR_SELECT_TEMPLATE(FASTEST)   (&xor_block_xc)
+
+#endif /* _ASM_S390_XOR_H */
diff --git a/arch/s390/include/uapi/asm/clp.h b/arch/s390/include/uapi/asm/clp.h
new file mode 100644 (file)
index 0000000..ab72d9d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * ioctl interface for /dev/clp
+ *
+ * Copyright IBM Corp. 2016
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef _ASM_CLP_H
+#define _ASM_CLP_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+struct clp_req {
+       unsigned int c : 1;
+       unsigned int r : 1;
+       unsigned int lps : 6;
+       unsigned int cmd : 8;
+       unsigned int : 16;
+       unsigned int reserved;
+       __u64 data_p;
+};
+
+#define CLP_IOCTL_MAGIC 'c'
+
+#define CLP_SYNC _IOWR(CLP_IOCTL_MAGIC, 0xC1, struct clp_req)
+
+#endif
index fe84bd5fe7ce05a44c4b75630a7f35405d075ec7..347fe5afa419c1cfb0051586009050f12b452c84 100644 (file)
@@ -154,6 +154,7 @@ struct kvm_guest_debug_arch {
 #define KVM_SYNC_PFAULT (1UL << 5)
 #define KVM_SYNC_VRS    (1UL << 6)
 #define KVM_SYNC_RICCB  (1UL << 7)
+#define KVM_SYNC_FPRS   (1UL << 8)
 /* definition of registers in kvm_run */
 struct kvm_sync_regs {
        __u64 prefix;   /* prefix register */
@@ -168,9 +169,12 @@ struct kvm_sync_regs {
        __u64 pft;      /* pfault token [PFAULT] */
        __u64 pfs;      /* pfault select [PFAULT] */
        __u64 pfc;      /* pfault compare [PFAULT] */
-       __u64 vrs[32][2];       /* vector registers */
+       union {
+               __u64 vrs[32][2];       /* vector registers (KVM_SYNC_VRS) */
+               __u64 fprs[16];         /* fp registers (KVM_SYNC_FPRS) */
+       };
        __u8  reserved[512];    /* for future vector expansion */
-       __u32 fpc;      /* only valid with vector registers */
+       __u32 fpc;              /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
        __u8 padding[52];       /* riccb needs to be 64byte aligned */
        __u8 riccb[64];         /* runtime instrumentation controls block */
 };
index ee69c0854c8891067b67a0d8920e7f3cf671f308..5dbaa72baa640dc397be0622960a874838e52218 100644 (file)
@@ -7,6 +7,7 @@
        { 0x9c, "DIAG (0x9c) time slice end directed" },        \
        { 0x204, "DIAG (0x204) logical-cpu utilization" },      \
        { 0x258, "DIAG (0x258) page-reference services" },      \
+       { 0x288, "DIAG (0x288) watchdog functions" },           \
        { 0x308, "DIAG (0x308) ipl functions" },                \
        { 0x500, "DIAG (0x500) KVM virtio functions" },         \
        { 0x501, "DIAG (0x501) KVM breakpoint" }
index 53bbc9e8b281fa9ae60f94ea81ce111d3249482d..1f95cc1faeb7624031b32c282953cc05cc001c3c 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/idle.h>
 #include <asm/vdso.h>
 #include <asm/pgtable.h>
+#include <asm/gmap.h>
 
 /*
  * Make sure that the compiler is new enough. We want a compiler that
index 66c94417c0ba09a471244a629c78d2457f38b17d..4af60374eba01fba89dc8b170a41428b094160b5 100644 (file)
@@ -271,7 +271,7 @@ static int restore_sigregs_ext32(struct pt_regs *regs,
 
        /* Restore high gprs from signal stack */
        if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high,
-                            sizeof(&sregs_ext->gprs_high)))
+                            sizeof(sregs_ext->gprs_high)))
                return -EFAULT;
        for (i = 0; i < NUM_GPRS; i++)
                *(__u32 *)&regs->gprs[i] = gprs_high[i];
index 7f768914fb4f94fb47fb9c99cac9e6077a3eca41..7f48e568ac644c884fbb182b396661fcf54a664e 100644 (file)
@@ -96,8 +96,7 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
                        (((unsigned long)response + rlen) >> 31)) {
                lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
                if (!lowbuf) {
-                       pr_warning("The cpcmd kernel function failed to "
-                                  "allocate a response buffer\n");
+                       pr_warn("The cpcmd kernel function failed to allocate a response buffer\n");
                        return -ENOMEM;
                }
                spin_lock_irqsave(&cpcmd_lock, flags);
index c890a5589e59583bb06b1d7dffe7226069e522a0..aa12de72fd47c9d9d8c13f1c4a1734eababe3891 100644 (file)
@@ -699,8 +699,7 @@ debug_info_t *debug_register_mode(const char *name, int pages_per_area,
        /* Since debugfs currently does not support uid/gid other than root, */
        /* we do not allow gid/uid != 0 until we get support for that. */
        if ((uid != 0) || (gid != 0))
-               pr_warning("Root becomes the owner of all s390dbf files "
-                          "in sysfs\n");
+               pr_warn("Root becomes the owner of all s390dbf files in sysfs\n");
        BUG_ON(!initialized);
        mutex_lock(&debug_mutex);
 
@@ -1307,8 +1306,7 @@ debug_input_level_fn(debug_info_t * id, struct debug_view *view,
                new_level = debug_get_uint(str);
        }
        if(new_level < 0) {
-               pr_warning("%s is not a valid level for a debug "
-                          "feature\n", str);
+               pr_warn("%s is not a valid level for a debug feature\n", str);
                rc = -EINVAL;
        } else {
                debug_set_level(id, new_level);
index 62973efd214a46f664f81cbf4f3f647391cacdd0..8cb9bfdd3ea8ad38e0eb6eda84d55cb7fc22bccb 100644 (file)
@@ -1920,23 +1920,16 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
                        }
                        if (separator)
                                ptr += sprintf(ptr, "%c", separator);
-                       /*
-                        * Use four '%' characters below because of the
-                        * following two conversions:
-                        *
-                        *  1) sprintf: %%%%r -> %%r
-                        *  2) printk : %%r   -> %r
-                        */
                        if (operand->flags & OPERAND_GPR)
-                               ptr += sprintf(ptr, "%%%%r%i", value);
+                               ptr += sprintf(ptr, "%%r%i", value);
                        else if (operand->flags & OPERAND_FPR)
-                               ptr += sprintf(ptr, "%%%%f%i", value);
+                               ptr += sprintf(ptr, "%%f%i", value);
                        else if (operand->flags & OPERAND_AR)
-                               ptr += sprintf(ptr, "%%%%a%i", value);
+                               ptr += sprintf(ptr, "%%a%i", value);
                        else if (operand->flags & OPERAND_CR)
-                               ptr += sprintf(ptr, "%%%%c%i", value);
+                               ptr += sprintf(ptr, "%%c%i", value);
                        else if (operand->flags & OPERAND_VR)
-                               ptr += sprintf(ptr, "%%%%v%i", value);
+                               ptr += sprintf(ptr, "%%v%i", value);
                        else if (operand->flags & OPERAND_PCREL)
                                ptr += sprintf(ptr, "%lx", (signed int) value
                                                                      + addr);
index 02bd02ff648b5ab570c5ffe920b27bbfbc3d5fd3..1b6081c0aff9238641f995c973560d2f8d33b686 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/export.h>
 #include <linux/kdebug.h>
 #include <linux/ptrace.h>
+#include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/processor.h>
 #include <asm/ipl.h>
 
 /*
- * For show_trace we have tree different stack to consider:
+ * For dump_trace we have tree different stack to consider:
  *   - the panic stack which is used if the kernel stack has overflown
  *   - the asynchronous interrupt stack (cpu related)
  *   - the synchronous kernel stack (process related)
- * The stack trace can start at any of the three stack and can potentially
+ * The stack trace can start at any of the three stacks and can potentially
  * touch all of them. The order is: panic stack, async stack, sync stack.
  */
 static unsigned long
-__show_trace(unsigned long sp, unsigned long low, unsigned long high)
+__dump_trace(dump_trace_func_t func, void *data, unsigned long sp,
+            unsigned long low, unsigned long high)
 {
        struct stack_frame *sf;
        struct pt_regs *regs;
-       unsigned long addr;
 
        while (1) {
                if (sp < low || sp > high - sizeof(*sf))
                        return sp;
                sf = (struct stack_frame *) sp;
-               addr = sf->gprs[8];
-               printk("([<%016lx>] %pSR)\n", addr, (void *)addr);
                /* Follow the backchain. */
                while (1) {
+                       if (func(data, sf->gprs[8]))
+                               return sp;
                        low = sp;
                        sp = sf->back_chain;
                        if (!sp)
@@ -48,46 +49,58 @@ __show_trace(unsigned long sp, unsigned long low, unsigned long high)
                        if (sp <= low || sp > high - sizeof(*sf))
                                return sp;
                        sf = (struct stack_frame *) sp;
-                       addr = sf->gprs[8];
-                       printk(" [<%016lx>] %pSR\n", addr, (void *)addr);
                }
                /* Zero backchain detected, check for interrupt frame. */
                sp = (unsigned long) (sf + 1);
                if (sp <= low || sp > high - sizeof(*regs))
                        return sp;
                regs = (struct pt_regs *) sp;
-               addr = regs->psw.addr;
-               printk(" [<%016lx>] %pSR\n", addr, (void *)addr);
+               if (!user_mode(regs)) {
+                       if (func(data, regs->psw.addr))
+                               return sp;
+               }
                low = sp;
                sp = regs->gprs[15];
        }
 }
 
-static void show_trace(struct task_struct *task, unsigned long *stack)
+void dump_trace(dump_trace_func_t func, void *data, struct task_struct *task,
+               unsigned long sp)
 {
-       const unsigned long frame_size =
-               STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
-       register unsigned long __r15 asm ("15");
-       unsigned long sp;
+       unsigned long frame_size;
 
-       sp = (unsigned long) stack;
-       if (!sp)
-               sp = task ? task->thread.ksp : __r15;
-       printk("Call Trace:\n");
+       frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
 #ifdef CONFIG_CHECK_STACK
-       sp = __show_trace(sp,
+       sp = __dump_trace(func, data, sp,
                          S390_lowcore.panic_stack + frame_size - 4096,
                          S390_lowcore.panic_stack + frame_size);
 #endif
-       sp = __show_trace(sp,
+       sp = __dump_trace(func, data, sp,
                          S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
                          S390_lowcore.async_stack + frame_size);
        if (task)
-               __show_trace(sp, (unsigned long) task_stack_page(task),
-                            (unsigned long) task_stack_page(task) + THREAD_SIZE);
+               __dump_trace(func, data, sp,
+                            (unsigned long)task_stack_page(task),
+                            (unsigned long)task_stack_page(task) + THREAD_SIZE);
        else
-               __show_trace(sp, S390_lowcore.thread_info,
+               __dump_trace(func, data, sp,
+                            S390_lowcore.thread_info,
                             S390_lowcore.thread_info + THREAD_SIZE);
+}
+EXPORT_SYMBOL_GPL(dump_trace);
+
+static int show_address(void *data, unsigned long address)
+{
+       printk("([<%016lx>] %pSR)\n", address, (void *)address);
+       return 0;
+}
+
+static void show_trace(struct task_struct *task, unsigned long sp)
+{
+       if (!sp)
+               sp = task ? task->thread.ksp : current_stack_pointer();
+       printk("Call Trace:\n");
+       dump_trace(show_address, NULL, task, sp);
        if (!task)
                task = current;
        debug_show_held_locks(task);
@@ -95,15 +108,16 @@ static void show_trace(struct task_struct *task, unsigned long *stack)
 
 void show_stack(struct task_struct *task, unsigned long *sp)
 {
-       register unsigned long *__r15 asm ("15");
        unsigned long *stack;
        int i;
 
-       if (!sp)
-               stack = task ? (unsigned long *) task->thread.ksp : __r15;
-       else
-               stack = sp;
-
+       stack = sp;
+       if (!stack) {
+               if (!task)
+                       stack = (unsigned long *)current_stack_pointer();
+               else
+                       stack = (unsigned long *)task->thread.ksp;
+       }
        for (i = 0; i < 20; i++) {
                if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
                        break;
@@ -112,7 +126,7 @@ void show_stack(struct task_struct *task, unsigned long *sp)
                printk("%016lx ", *stack++);
        }
        printk("\n");
-       show_trace(task, sp);
+       show_trace(task, (unsigned long)sp);
 }
 
 static void show_last_breaking_event(struct pt_regs *regs)
@@ -121,13 +135,9 @@ static void show_last_breaking_event(struct pt_regs *regs)
        printk(" [<%016lx>] %pSR\n", regs->args[0], (void *)regs->args[0]);
 }
 
-static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
-{
-       return (regs->psw.mask & bits) / ((~bits + 1) & bits);
-}
-
 void show_registers(struct pt_regs *regs)
 {
+       struct psw_bits *psw = &psw_bits(regs->psw);
        char *mode;
 
        mode = user_mode(regs) ? "User" : "Krnl";
@@ -136,13 +146,9 @@ void show_registers(struct pt_regs *regs)
                printk(" (%pSR)", (void *)regs->psw.addr);
        printk("\n");
        printk("           R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
-              "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
-              mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
-              mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
-              mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
-              mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
-              mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
-       printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
+              "P:%x AS:%x CC:%x PM:%x", psw->r, psw->t, psw->i, psw->e,
+              psw->key, psw->m, psw->w, psw->p, psw->as, psw->cc, psw->pm);
+       printk(" RI:%x EA:%x", psw->ri, psw->eaba);
        printk("\n%s GPRS: %016lx %016lx %016lx %016lx\n", mode,
               regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
        printk("           %016lx %016lx %016lx %016lx\n",
@@ -160,7 +166,7 @@ void show_regs(struct pt_regs *regs)
        show_registers(regs);
        /* Show stack backtrace if pt_regs is from kernel mode */
        if (!user_mode(regs))
-               show_trace(NULL, (unsigned long *) regs->gprs[15]);
+               show_trace(NULL, regs->gprs[15]);
        show_last_breaking_event(regs);
 }
 
@@ -184,9 +190,8 @@ void die(struct pt_regs *regs, const char *str)
 #ifdef CONFIG_SMP
        printk("SMP ");
 #endif
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       printk("DEBUG_PAGEALLOC");
-#endif
+       if (debug_pagealloc_enabled())
+               printk("DEBUG_PAGEALLOC");
        printk("\n");
        notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
        print_modules();
index c55576bbaa1f7555479994d6848c9aa5b60f189b..a0684de5a93b99ae199f9bf6906327f4513f662e 100644 (file)
@@ -448,7 +448,6 @@ void __init startup_init(void)
        rescue_initrd();
        clear_bss_section();
        init_kernel_storage_key();
-       lockdep_init();
        lockdep_off();
        setup_lowcore_early();
        setup_facility_list();
index cd5a191381b9438c2314294c350367ce9cabd062..2d47f9cfcb3613f32cf824748b0b8c9540d29e61 100644 (file)
@@ -186,6 +186,7 @@ ENTRY(__switch_to)
        stg     %r5,__LC_THREAD_INFO            # store thread info of next
        stg     %r15,__LC_KERNEL_STACK          # store end of kernel stack
        lg      %r15,__THREAD_ksp(%r1)          # load kernel stack of next
+       /* c4 is used in guest detection: arch/s390/kernel/perf_cpum_sf.c */
        lctl    %c4,%c4,__TASK_pid(%r3)         # load pid to control reg. 4
        mvc     __LC_CURRENT_PID(4,%r0),__TASK_pid(%r3) # store pid of next
        lmg     %r6,%r15,__SF_GPRS(%r15)        # load gprs of next task
@@ -1199,114 +1200,12 @@ cleanup_critical:
        .quad   .Lpsw_idle_lpsw
 
 .Lcleanup_save_fpu_regs:
-       TSTMSK  __LC_CPU_FLAGS,_CIF_FPU
-       bor     %r14
-       clg     %r9,BASED(.Lcleanup_save_fpu_regs_done)
-       jhe     5f
-       clg     %r9,BASED(.Lcleanup_save_fpu_regs_fp)
-       jhe     4f
-       clg     %r9,BASED(.Lcleanup_save_fpu_regs_vx_high)
-       jhe     3f
-       clg     %r9,BASED(.Lcleanup_save_fpu_regs_vx_low)
-       jhe     2f
-       clg     %r9,BASED(.Lcleanup_save_fpu_fpc_end)
-       jhe     1f
-       lg      %r2,__LC_CURRENT
-       aghi    %r2,__TASK_thread
-0:     # Store floating-point controls
-       stfpc   __THREAD_FPU_fpc(%r2)
-1:     # Load register save area and check if VX is active
-       lg      %r3,__THREAD_FPU_regs(%r2)
-       TSTMSK  __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
-       jz      4f                        # no VX -> store FP regs
-2:     # Store vector registers (V0-V15)
-       VSTM    %v0,%v15,0,%r3            # vstm 0,15,0(3)
-3:     # Store vector registers (V16-V31)
-       VSTM    %v16,%v31,256,%r3         # vstm 16,31,256(3)
-       j       5f                        # -> done, set CIF_FPU flag
-4:     # Store floating-point registers
-       std     0,0(%r3)
-       std     1,8(%r3)
-       std     2,16(%r3)
-       std     3,24(%r3)
-       std     4,32(%r3)
-       std     5,40(%r3)
-       std     6,48(%r3)
-       std     7,56(%r3)
-       std     8,64(%r3)
-       std     9,72(%r3)
-       std     10,80(%r3)
-       std     11,88(%r3)
-       std     12,96(%r3)
-       std     13,104(%r3)
-       std     14,112(%r3)
-       std     15,120(%r3)
-5:     # Set CIF_FPU flag
-       oi      __LC_CPU_FLAGS+7,_CIF_FPU
-       lg      %r9,48(%r11)            # return from save_fpu_regs
+       larl    %r9,save_fpu_regs
        br      %r14
-.Lcleanup_save_fpu_fpc_end:
-       .quad   .Lsave_fpu_regs_fpc_end
-.Lcleanup_save_fpu_regs_vx_low:
-       .quad   .Lsave_fpu_regs_vx_low
-.Lcleanup_save_fpu_regs_vx_high:
-       .quad   .Lsave_fpu_regs_vx_high
-.Lcleanup_save_fpu_regs_fp:
-       .quad   .Lsave_fpu_regs_fp
-.Lcleanup_save_fpu_regs_done:
-       .quad   .Lsave_fpu_regs_done
 
 .Lcleanup_load_fpu_regs:
-       TSTMSK  __LC_CPU_FLAGS,_CIF_FPU
-       bnor    %r14
-       clg     %r9,BASED(.Lcleanup_load_fpu_regs_done)
-       jhe     1f
-       clg     %r9,BASED(.Lcleanup_load_fpu_regs_fp)
-       jhe     2f
-       clg     %r9,BASED(.Lcleanup_load_fpu_regs_vx_high)
-       jhe     3f
-       clg     %r9,BASED(.Lcleanup_load_fpu_regs_vx)
-       jhe     4f
-       lg      %r4,__LC_CURRENT
-       aghi    %r4,__TASK_thread
-       lfpc    __THREAD_FPU_fpc(%r4)
-       TSTMSK  __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
-       lg      %r4,__THREAD_FPU_regs(%r4)      # %r4 <- reg save area
-       jz      2f                              # -> no VX, load FP regs
-4:     # Load V0 ..V15 registers
-       VLM     %v0,%v15,0,%r4
-3:     # Load V16..V31 registers
-       VLM     %v16,%v31,256,%r4
-       j       1f
-2:     # Load floating-point registers
-       ld      0,0(%r4)
-       ld      1,8(%r4)
-       ld      2,16(%r4)
-       ld      3,24(%r4)
-       ld      4,32(%r4)
-       ld      5,40(%r4)
-       ld      6,48(%r4)
-       ld      7,56(%r4)
-       ld      8,64(%r4)
-       ld      9,72(%r4)
-       ld      10,80(%r4)
-       ld      11,88(%r4)
-       ld      12,96(%r4)
-       ld      13,104(%r4)
-       ld      14,112(%r4)
-       ld      15,120(%r4)
-1:     # Clear CIF_FPU bit
-       ni      __LC_CPU_FLAGS+7,255-_CIF_FPU
-       lg      %r9,48(%r11)            # return from load_fpu_regs
+       larl    %r9,load_fpu_regs
        br      %r14
-.Lcleanup_load_fpu_regs_vx:
-       .quad   .Lload_fpu_regs_vx
-.Lcleanup_load_fpu_regs_vx_high:
-       .quad   .Lload_fpu_regs_vx_high
-.Lcleanup_load_fpu_regs_fp:
-       .quad   .Lload_fpu_regs_fp
-.Lcleanup_load_fpu_regs_done:
-       .quad   .Lload_fpu_regs_done
 
 /*
  * Integer constants
index c5febe84eba633385cd7a8c09bee87e484c2e05c..03c2b469c4725172e4c6750cb8bcb0fb4edea075 100644 (file)
@@ -16,7 +16,7 @@
 
 __HEAD
 ENTRY(startup_continue)
-       tm      __LC_STFLE_FAC_LIST+6,0x80      # LPP available ?
+       tm      __LC_STFLE_FAC_LIST+5,0x80      # LPP available ?
        jz      0f
        xc      __LC_LPP+1(7,0),__LC_LPP+1      # clear lpp and current_pid
        mvi     __LC_LPP,0x80                   #   and set LPP_MAGIC
index f41d5208aaf768bc7657a2e44e06f9f2b7e32f2b..c373a1d41d104157ce7ad7dc14ca1884a90ddc8d 100644 (file)
@@ -164,8 +164,7 @@ void do_softirq_own_stack(void)
 {
        unsigned long old, new;
 
-       /* Get current stack pointer. */
-       asm volatile("la %0,0(15)" : "=a" (old));
+       old = current_stack_pointer();
        /* Check against async. stack address range. */
        new = S390_lowcore.async_stack;
        if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) {
index 929c147e07b40c19370e621a4ba96e99c13a994e..58bf4572d457f09465abf82cc6e8e4cfda1b21ca 100644 (file)
@@ -383,7 +383,7 @@ static int __hw_perf_event_init(struct perf_event *event)
 
        /* Validate the counter that is assigned to this event.
         * Because the counter facility can use numerous counters at the
-        * same time without constraints, it is not necessary to explicity
+        * same time without constraints, it is not necessary to explicitly
         * validate event groups (event->group_leader != event).
         */
        err = validate_event(hwc);
index 3d8da1e742c2b72f7741b8e0a48b8e1b185b4530..1a43474df541a08008d011f0678211ab63eb19fa 100644 (file)
@@ -1022,10 +1022,13 @@ static int perf_push_sample(struct perf_event *event, struct sf_raw_sample *sfr)
        /*
         * A non-zero guest program parameter indicates a guest
         * sample.
-        * Note that some early samples might be misaccounted to
-        * the host.
+        * Note that some early samples or samples from guests without
+        * lpp usage would be misaccounted to the host. We use the asn
+        * value as a heuristic to detect most of these guest samples.
+        * If the value differs from the host hpp value, we assume
+        * it to be a KVM guest.
         */
-       if (sfr->basic.gpp)
+       if (sfr->basic.gpp || sfr->basic.prim_asn != (u16) sfr->basic.hpp)
                sde_regs->in_guest = 1;
 
        overflow = 0;
index 0943b11a2f6e22c088dc13d3b8a0de9b4e6ef92c..c3e4099b60a59da2452eddd333620a6f17acf9dd 100644 (file)
@@ -222,67 +222,23 @@ static int __init service_level_perf_register(void)
 }
 arch_initcall(service_level_perf_register);
 
-/* See also arch/s390/kernel/traps.c */
-static unsigned long __store_trace(struct perf_callchain_entry *entry,
-                                  unsigned long sp,
-                                  unsigned long low, unsigned long high)
+static int __perf_callchain_kernel(void *data, unsigned long address)
 {
-       struct stack_frame *sf;
-       struct pt_regs *regs;
-
-       while (1) {
-               if (sp < low || sp > high - sizeof(*sf))
-                       return sp;
-               sf = (struct stack_frame *) sp;
-               perf_callchain_store(entry, sf->gprs[8]);
-               /* Follow the backchain. */
-               while (1) {
-                       low = sp;
-                       sp = sf->back_chain;
-                       if (!sp)
-                               break;
-                       if (sp <= low || sp > high - sizeof(*sf))
-                               return sp;
-                       sf = (struct stack_frame *) sp;
-                       perf_callchain_store(entry, sf->gprs[8]);
-               }
-               /* Zero backchain detected, check for interrupt frame. */
-               sp = (unsigned long) (sf + 1);
-               if (sp <= low || sp > high - sizeof(*regs))
-                       return sp;
-               regs = (struct pt_regs *) sp;
-               perf_callchain_store(entry, sf->gprs[8]);
-               low = sp;
-               sp = regs->gprs[15];
-       }
+       struct perf_callchain_entry *entry = data;
+
+       perf_callchain_store(entry, address);
+       return 0;
 }
 
 void perf_callchain_kernel(struct perf_callchain_entry *entry,
                           struct pt_regs *regs)
 {
-       unsigned long head, frame_size;
-       struct stack_frame *head_sf;
-
        if (user_mode(regs))
                return;
-
-       frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
-       head = regs->gprs[15];
-       head_sf = (struct stack_frame *) head;
-
-       if (!head_sf || !head_sf->back_chain)
-               return;
-
-       head = head_sf->back_chain;
-       head = __store_trace(entry, head,
-                            S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
-                            S390_lowcore.async_stack + frame_size);
-
-       __store_trace(entry, head, S390_lowcore.thread_info,
-                     S390_lowcore.thread_info + THREAD_SIZE);
+       dump_trace(__perf_callchain_kernel, entry, NULL, regs->gprs[15]);
 }
 
-/* Perf defintions for PMU event attributes in sysfs */
+/* Perf definitions for PMU event attributes in sysfs */
 ssize_t cpumf_events_sysfs_show(struct device *dev,
                                struct device_attribute *attr, char *page)
 {
index 9220db5c996aa5250ca4d904361c51cec33d7827..d3f9688f26b5e7acead2bb9a420eb0e0597d27f6 100644 (file)
@@ -327,6 +327,7 @@ static void __init setup_lowcore(void)
                + PAGE_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
        lc->current_task = (unsigned long) init_thread_union.thread_info.task;
        lc->thread_info = (unsigned long) &init_thread_union;
+       lc->lpp = LPP_MAGIC;
        lc->machine_flags = S390_lowcore.machine_flags;
        lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
        memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
@@ -374,17 +375,17 @@ static void __init setup_lowcore(void)
 
 static struct resource code_resource = {
        .name  = "Kernel code",
-       .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+       .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
 };
 
 static struct resource data_resource = {
        .name = "Kernel data",
-       .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+       .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
 };
 
 static struct resource bss_resource = {
        .name = "Kernel bss",
-       .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+       .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
 };
 
 static struct resource __initdata *standard_resources[] = {
@@ -408,7 +409,7 @@ static void __init setup_resources(void)
 
        for_each_memblock(memory, reg) {
                res = alloc_bootmem_low(sizeof(*res));
-               res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+               res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
 
                res->name = "System RAM";
                res->start = reg->base;
@@ -779,6 +780,7 @@ static int __init setup_hwcaps(void)
                strcpy(elf_platform, "zEC12");
                break;
        case 0x2964:
+       case 0x2965:
                strcpy(elf_platform, "z13");
                break;
        }
index 3c65a8eae34d35b6a670066db2bc80c8fa3ccf67..40a6b4f9c36cedd5400898572f32173c90bf0240 100644 (file)
@@ -798,7 +798,7 @@ static void smp_start_secondary(void *cpuvoid)
        set_cpu_online(smp_processor_id(), true);
        inc_irq_stat(CPU_RST);
        local_irq_enable();
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 /* Upping and downing of CPUs */
index 8f64ebd63767c7a1a3e434b994b65110e890f741..44f84b23d4e5996f1ddc594ae3985d762e80aa36 100644 (file)
 #include <linux/kallsyms.h>
 #include <linux/module.h>
 
-static unsigned long save_context_stack(struct stack_trace *trace,
-                                       unsigned long sp,
-                                       unsigned long low,
-                                       unsigned long high,
-                                       int savesched)
+static int __save_address(void *data, unsigned long address, int nosched)
 {
-       struct stack_frame *sf;
-       struct pt_regs *regs;
-       unsigned long addr;
+       struct stack_trace *trace = data;
 
-       while(1) {
-               if (sp < low || sp > high)
-                       return sp;
-               sf = (struct stack_frame *)sp;
-               while(1) {
-                       addr = sf->gprs[8];
-                       if (!trace->skip)
-                               trace->entries[trace->nr_entries++] = addr;
-                       else
-                               trace->skip--;
-                       if (trace->nr_entries >= trace->max_entries)
-                               return sp;
-                       low = sp;
-                       sp = sf->back_chain;
-                       if (!sp)
-                               break;
-                       if (sp <= low || sp > high - sizeof(*sf))
-                               return sp;
-                       sf = (struct stack_frame *)sp;
-               }
-               /* Zero backchain detected, check for interrupt frame. */
-               sp = (unsigned long)(sf + 1);
-               if (sp <= low || sp > high - sizeof(*regs))
-                       return sp;
-               regs = (struct pt_regs *)sp;
-               addr = regs->psw.addr;
-               if (savesched || !in_sched_functions(addr)) {
-                       if (!trace->skip)
-                               trace->entries[trace->nr_entries++] = addr;
-                       else
-                               trace->skip--;
-               }
-               if (trace->nr_entries >= trace->max_entries)
-                       return sp;
-               low = sp;
-               sp = regs->gprs[15];
+       if (nosched && in_sched_functions(address))
+               return 0;
+       if (trace->skip > 0) {
+               trace->skip--;
+               return 0;
        }
+       if (trace->nr_entries < trace->max_entries) {
+               trace->entries[trace->nr_entries++] = address;
+               return 0;
+       }
+       return 1;
 }
 
-static void __save_stack_trace(struct stack_trace *trace, unsigned long sp)
+static int save_address(void *data, unsigned long address)
 {
-       unsigned long new_sp, frame_size;
+       return __save_address(data, address, 0);
+}
 
-       frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
-       new_sp = save_context_stack(trace, sp,
-                       S390_lowcore.panic_stack + frame_size - PAGE_SIZE,
-                       S390_lowcore.panic_stack + frame_size, 1);
-       new_sp = save_context_stack(trace, new_sp,
-                       S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
-                       S390_lowcore.async_stack + frame_size, 1);
-       save_context_stack(trace, new_sp,
-                          S390_lowcore.thread_info,
-                          S390_lowcore.thread_info + THREAD_SIZE, 1);
+static int save_address_nosched(void *data, unsigned long address)
+{
+       return __save_address(data, address, 1);
 }
 
 void save_stack_trace(struct stack_trace *trace)
 {
-       register unsigned long r15 asm ("15");
        unsigned long sp;
 
-       sp = r15;
-       __save_stack_trace(trace, sp);
+       sp = current_stack_pointer();
+       dump_trace(save_address, trace, NULL, sp);
        if (trace->nr_entries < trace->max_entries)
                trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
@@ -89,16 +50,12 @@ EXPORT_SYMBOL_GPL(save_stack_trace);
 
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
-       unsigned long sp, low, high;
+       unsigned long sp;
 
        sp = tsk->thread.ksp;
-       if (tsk == current) {
-               /* Get current stack pointer. */
-               asm volatile("la %0,0(15)" : "=a" (sp));
-       }
-       low = (unsigned long) task_stack_page(tsk);
-       high = (unsigned long) task_pt_regs(tsk);
-       save_context_stack(trace, sp, low, high, 0);
+       if (tsk == current)
+               sp = current_stack_pointer();
+       dump_trace(save_address_nosched, trace, tsk, sp);
        if (trace->nr_entries < trace->max_entries)
                trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
@@ -109,7 +66,7 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
        unsigned long sp;
 
        sp = kernel_stack_pointer(regs);
-       __save_stack_trace(trace, sp);
+       dump_trace(save_address, trace, NULL, sp);
        if (trace->nr_entries < trace->max_entries)
                trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
index 99f84ac31307962bfa803f60f754f7c187c7c5b4..c4e5f183f225d23519295f9f4900a2a3b2734367 100644 (file)
@@ -499,8 +499,7 @@ static void etr_reset(void)
                if (etr_port0_online && etr_port1_online)
                        set_bit(CLOCK_SYNC_ETR, &clock_sync_flags);
        } else if (etr_port0_online || etr_port1_online) {
-               pr_warning("The real or virtual hardware system does "
-                          "not provide an ETR interface\n");
+               pr_warn("The real or virtual hardware system does not provide an ETR interface\n");
                etr_port0_online = etr_port1_online = 0;
        }
 }
@@ -1464,8 +1463,7 @@ static void __init stp_reset(void)
        if (rc == 0)
                set_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags);
        else if (stp_online) {
-               pr_warning("The real or virtual hardware system does "
-                          "not provide an STP interface\n");
+               pr_warn("The real or virtual hardware system does not provide an STP interface\n");
                free_page((unsigned long) stp_page);
                stp_page = NULL;
                stp_online = 0;
index 017eb03daee2e724a603420f65b6e93dde98ac6a..dd97a3e8a34a8b3be07121f9ec4eb7be1bd7d971 100644 (file)
@@ -22,8 +22,6 @@
 #include <asm/fpu/api.h>
 #include "entry.h"
 
-int show_unhandled_signals = 1;
-
 static inline void __user *get_trap_ip(struct pt_regs *regs)
 {
        unsigned long address;
@@ -35,21 +33,6 @@ static inline void __user *get_trap_ip(struct pt_regs *regs)
        return (void __user *) (address - (regs->int_code >> 16));
 }
 
-static inline void report_user_fault(struct pt_regs *regs, int signr)
-{
-       if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
-               return;
-       if (!unhandled_signal(current, signr))
-               return;
-       if (!printk_ratelimit())
-               return;
-       printk("User process fault: interruption code %04x ilc:%d ",
-              regs->int_code & 0xffff, regs->int_code >> 17);
-       print_vma_addr("in ", regs->psw.addr);
-       printk("\n");
-       show_regs(regs);
-}
-
 int is_valid_bugaddr(unsigned long addr)
 {
        return 1;
@@ -65,7 +48,7 @@ void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str)
                info.si_code = si_code;
                info.si_addr = get_trap_ip(regs);
                force_sig_info(si_signo, &info, current);
-               report_user_fault(regs, si_signo);
+               report_user_fault(regs, si_signo, 0);
         } else {
                 const struct exception_table_entry *fixup;
                fixup = search_exception_tables(regs->psw.addr);
@@ -111,7 +94,7 @@ NOKPROBE_SYMBOL(do_per_trap);
 void default_trap_handler(struct pt_regs *regs)
 {
        if (user_mode(regs)) {
-               report_user_fault(regs, SIGSEGV);
+               report_user_fault(regs, SIGSEGV, 0);
                do_exit(SIGSEGV);
        } else
                die(regs, "Unknown program exception");
index 05f7de9869a9f1786a8b996edd10fcdb280bd7c0..1ea4095b67d729fb67c01b4be81ce8bb7efe4bcb 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <asm/pgalloc.h>
+#include <asm/gmap.h>
 #include <asm/virtio-ccw.h>
 #include "kvm-s390.h"
 #include "trace.h"
index d30db40437dc0d03943a1c98f79dbb7dfce8e863..66938d283b77094f694bccad132c749bb9c745af 100644 (file)
@@ -373,7 +373,7 @@ void ipte_unlock(struct kvm_vcpu *vcpu)
 }
 
 static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, ar_t ar,
-                         int write)
+                         enum gacc_mode mode)
 {
        union alet alet;
        struct ale ale;
@@ -454,7 +454,7 @@ static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, ar_t ar,
                }
        }
 
-       if (ale.fo == 1 && write)
+       if (ale.fo == 1 && mode == GACC_STORE)
                return PGM_PROTECTION;
 
        asce->val = aste.asce;
@@ -477,25 +477,28 @@ enum {
 };
 
 static int get_vcpu_asce(struct kvm_vcpu *vcpu, union asce *asce,
-                        ar_t ar, int write)
+                        ar_t ar, enum gacc_mode mode)
 {
        int rc;
-       psw_t *psw = &vcpu->arch.sie_block->gpsw;
+       struct psw_bits psw = psw_bits(vcpu->arch.sie_block->gpsw);
        struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
        struct trans_exc_code_bits *tec_bits;
 
        memset(pgm, 0, sizeof(*pgm));
        tec_bits = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
-       tec_bits->fsi = write ? FSI_STORE : FSI_FETCH;
-       tec_bits->as = psw_bits(*psw).as;
+       tec_bits->fsi = mode == GACC_STORE ? FSI_STORE : FSI_FETCH;
+       tec_bits->as = psw.as;
 
-       if (!psw_bits(*psw).t) {
+       if (!psw.t) {
                asce->val = 0;
                asce->r = 1;
                return 0;
        }
 
-       switch (psw_bits(vcpu->arch.sie_block->gpsw).as) {
+       if (mode == GACC_IFETCH)
+               psw.as = psw.as == PSW_AS_HOME ? PSW_AS_HOME : PSW_AS_PRIMARY;
+
+       switch (psw.as) {
        case PSW_AS_PRIMARY:
                asce->val = vcpu->arch.sie_block->gcr[1];
                return 0;
@@ -506,7 +509,7 @@ static int get_vcpu_asce(struct kvm_vcpu *vcpu, union asce *asce,
                asce->val = vcpu->arch.sie_block->gcr[13];
                return 0;
        case PSW_AS_ACCREG:
-               rc = ar_translation(vcpu, asce, ar, write);
+               rc = ar_translation(vcpu, asce, ar, mode);
                switch (rc) {
                case PGM_ALEN_TRANSLATION:
                case PGM_ALE_SEQUENCE:
@@ -538,7 +541,7 @@ static int deref_table(struct kvm *kvm, unsigned long gpa, unsigned long *val)
  * @gva: guest virtual address
  * @gpa: points to where guest physical (absolute) address should be stored
  * @asce: effective asce
- * @write: indicates if access is a write access
+ * @mode: indicates the access mode to be used
  *
  * Translate a guest virtual address into a guest absolute address by means
  * of dynamic address translation as specified by the architecture.
@@ -554,7 +557,7 @@ static int deref_table(struct kvm *kvm, unsigned long gpa, unsigned long *val)
  */
 static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
                                     unsigned long *gpa, const union asce asce,
-                                    int write)
+                                    enum gacc_mode mode)
 {
        union vaddress vaddr = {.addr = gva};
        union raddress raddr = {.addr = gva};
@@ -699,7 +702,7 @@ static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
 real_address:
        raddr.addr = kvm_s390_real_to_abs(vcpu, raddr.addr);
 absolute_address:
-       if (write && dat_protection)
+       if (mode == GACC_STORE && dat_protection)
                return PGM_PROTECTION;
        if (kvm_is_error_gpa(vcpu->kvm, raddr.addr))
                return PGM_ADDRESSING;
@@ -728,7 +731,7 @@ static int low_address_protection_enabled(struct kvm_vcpu *vcpu,
 
 static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga,
                            unsigned long *pages, unsigned long nr_pages,
-                           const union asce asce, int write)
+                           const union asce asce, enum gacc_mode mode)
 {
        struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
@@ -740,13 +743,13 @@ static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga,
        while (nr_pages) {
                ga = kvm_s390_logical_to_effective(vcpu, ga);
                tec_bits->addr = ga >> PAGE_SHIFT;
-               if (write && lap_enabled && is_low_address(ga)) {
+               if (mode == GACC_STORE && lap_enabled && is_low_address(ga)) {
                        pgm->code = PGM_PROTECTION;
                        return pgm->code;
                }
                ga &= PAGE_MASK;
                if (psw_bits(*psw).t) {
-                       rc = guest_translate(vcpu, ga, pages, asce, write);
+                       rc = guest_translate(vcpu, ga, pages, asce, mode);
                        if (rc < 0)
                                return rc;
                        if (rc == PGM_PROTECTION)
@@ -768,7 +771,7 @@ static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga,
 }
 
 int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
-                unsigned long len, int write)
+                unsigned long len, enum gacc_mode mode)
 {
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
        unsigned long _len, nr_pages, gpa, idx;
@@ -780,7 +783,7 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
 
        if (!len)
                return 0;
-       rc = get_vcpu_asce(vcpu, &asce, ar, write);
+       rc = get_vcpu_asce(vcpu, &asce, ar, mode);
        if (rc)
                return rc;
        nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1;
@@ -792,11 +795,11 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
        need_ipte_lock = psw_bits(*psw).t && !asce.r;
        if (need_ipte_lock)
                ipte_lock(vcpu);
-       rc = guest_page_range(vcpu, ga, pages, nr_pages, asce, write);
+       rc = guest_page_range(vcpu, ga, pages, nr_pages, asce, mode);
        for (idx = 0; idx < nr_pages && !rc; idx++) {
                gpa = *(pages + idx) + (ga & ~PAGE_MASK);
                _len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len);
-               if (write)
+               if (mode == GACC_STORE)
                        rc = kvm_write_guest(vcpu->kvm, gpa, data, _len);
                else
                        rc = kvm_read_guest(vcpu->kvm, gpa, data, _len);
@@ -812,7 +815,7 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
 }
 
 int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
-                     void *data, unsigned long len, int write)
+                     void *data, unsigned long len, enum gacc_mode mode)
 {
        unsigned long _len, gpa;
        int rc = 0;
@@ -820,7 +823,7 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
        while (len && !rc) {
                gpa = kvm_s390_real_to_abs(vcpu, gra);
                _len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len);
-               if (write)
+               if (mode)
                        rc = write_guest_abs(vcpu, gpa, data, _len);
                else
                        rc = read_guest_abs(vcpu, gpa, data, _len);
@@ -841,7 +844,7 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
  * has to take care of this.
  */
 int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
-                           unsigned long *gpa, int write)
+                           unsigned long *gpa, enum gacc_mode mode)
 {
        struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
@@ -851,19 +854,19 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
 
        gva = kvm_s390_logical_to_effective(vcpu, gva);
        tec = (struct trans_exc_code_bits *)&pgm->trans_exc_code;
-       rc = get_vcpu_asce(vcpu, &asce, ar, write);
+       rc = get_vcpu_asce(vcpu, &asce, ar, mode);
        tec->addr = gva >> PAGE_SHIFT;
        if (rc)
                return rc;
        if (is_low_address(gva) && low_address_protection_enabled(vcpu, asce)) {
-               if (write) {
+               if (mode == GACC_STORE) {
                        rc = pgm->code = PGM_PROTECTION;
                        return rc;
                }
        }
 
        if (psw_bits(*psw).t && !asce.r) {      /* Use DAT? */
-               rc = guest_translate(vcpu, gva, gpa, asce, write);
+               rc = guest_translate(vcpu, gva, gpa, asce, mode);
                if (rc > 0) {
                        if (rc == PGM_PROTECTION)
                                tec->b61 = 1;
@@ -883,7 +886,7 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
  * check_gva_range - test a range of guest virtual addresses for accessibility
  */
 int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
-                   unsigned long length, int is_write)
+                   unsigned long length, enum gacc_mode mode)
 {
        unsigned long gpa;
        unsigned long currlen;
@@ -892,7 +895,7 @@ int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
        ipte_lock(vcpu);
        while (length > 0 && !rc) {
                currlen = min(length, PAGE_SIZE - (gva % PAGE_SIZE));
-               rc = guest_translate_address(vcpu, gva, ar, &gpa, is_write);
+               rc = guest_translate_address(vcpu, gva, ar, &gpa, mode);
                gva += currlen;
                length -= currlen;
        }
index ef03726cc6611acd1e52fb6970e2e802a1730cbd..df0a79dd81595f43f815a8b671cb8dc6502e81e2 100644 (file)
@@ -155,16 +155,22 @@ int read_guest_lc(struct kvm_vcpu *vcpu, unsigned long gra, void *data,
        return kvm_read_guest(vcpu->kvm, gpa, data, len);
 }
 
+enum gacc_mode {
+       GACC_FETCH,
+       GACC_STORE,
+       GACC_IFETCH,
+};
+
 int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
-                           ar_t ar, unsigned long *gpa, int write);
+                           ar_t ar, unsigned long *gpa, enum gacc_mode mode);
 int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
-                   unsigned long length, int is_write);
+                   unsigned long length, enum gacc_mode mode);
 
 int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
-                unsigned long len, int write);
+                unsigned long len, enum gacc_mode mode);
 
 int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
-                     void *data, unsigned long len, int write);
+                     void *data, unsigned long len, enum gacc_mode mode);
 
 /**
  * write_guest - copy data from kernel space to guest space
@@ -215,7 +221,7 @@ static inline __must_check
 int write_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
                unsigned long len)
 {
-       return access_guest(vcpu, ga, ar, data, len, 1);
+       return access_guest(vcpu, ga, ar, data, len, GACC_STORE);
 }
 
 /**
@@ -235,7 +241,27 @@ static inline __must_check
 int read_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
               unsigned long len)
 {
-       return access_guest(vcpu, ga, ar, data, len, 0);
+       return access_guest(vcpu, ga, ar, data, len, GACC_FETCH);
+}
+
+/**
+ * read_guest_instr - copy instruction data from guest space to kernel space
+ * @vcpu: virtual cpu
+ * @data: destination address in kernel space
+ * @len: number of bytes to copy
+ *
+ * Copy @len bytes from the current psw address (guest space) to @data (kernel
+ * space).
+ *
+ * The behaviour of read_guest_instr is identical to read_guest, except that
+ * instruction data will be read from primary space when in home-space or
+ * address-space mode.
+ */
+static inline __must_check
+int read_guest_instr(struct kvm_vcpu *vcpu, void *data, unsigned long len)
+{
+       return access_guest(vcpu, vcpu->arch.sie_block->gpsw.addr, 0, data, len,
+                           GACC_IFETCH);
 }
 
 /**
index d697312ce9ee325571f25c74fb0d963f50943537..e8c6843b9600cd6ebf2e72e5cc9e75148dc1c780 100644 (file)
@@ -17,7 +17,7 @@
 /*
  * Extends the address range given by *start and *stop to include the address
  * range starting with estart and the length len. Takes care of overflowing
- * intervals and tries to minimize the overall intervall size.
+ * intervals and tries to minimize the overall interval size.
  */
 static void extend_address_range(u64 *start, u64 *stop, u64 estart, int len)
 {
@@ -72,7 +72,7 @@ static void enable_all_hw_bp(struct kvm_vcpu *vcpu)
                return;
 
        /*
-        * If the guest is not interrested in branching events, we can savely
+        * If the guest is not interested in branching events, we can safely
         * limit them to the PER address range.
         */
        if (!(*cr9 & PER_EVENT_BRANCH))
index d53c10753c466b47b6fcb4813ec9e3445ca47a04..2e6b54e4d3f955d1c7971fce4ad02551eeac3846 100644 (file)
@@ -38,17 +38,32 @@ static const intercept_handler_t instruction_handlers[256] = {
        [0xeb] = kvm_s390_handle_eb,
 };
 
-void kvm_s390_rewind_psw(struct kvm_vcpu *vcpu, int ilc)
+u8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu)
 {
        struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
+       u8 ilen = 0;
 
-       /* Use the length of the EXECUTE instruction if necessary */
-       if (sie_block->icptstatus & 1) {
-               ilc = (sie_block->icptstatus >> 4) & 0x6;
-               if (!ilc)
-                       ilc = 4;
+       switch (vcpu->arch.sie_block->icptcode) {
+       case ICPT_INST:
+       case ICPT_INSTPROGI:
+       case ICPT_OPEREXC:
+       case ICPT_PARTEXEC:
+       case ICPT_IOINST:
+               /* instruction only stored for these icptcodes */
+               ilen = insn_length(vcpu->arch.sie_block->ipa >> 8);
+               /* Use the length of the EXECUTE instruction if necessary */
+               if (sie_block->icptstatus & 1) {
+                       ilen = (sie_block->icptstatus >> 4) & 0x6;
+                       if (!ilen)
+                               ilen = 4;
+               }
+               break;
+       case ICPT_PROGI:
+               /* bit 1+2 of pgmilc are the ilc, so we directly get ilen */
+               ilen = vcpu->arch.sie_block->pgmilc & 0x6;
+               break;
        }
-       sie_block->gpsw.addr = __rewind_psw(sie_block->gpsw, ilc);
+       return ilen;
 }
 
 static int handle_noop(struct kvm_vcpu *vcpu)
@@ -121,11 +136,13 @@ static int handle_instruction(struct kvm_vcpu *vcpu)
        return -EOPNOTSUPP;
 }
 
-static void __extract_prog_irq(struct kvm_vcpu *vcpu,
-                              struct kvm_s390_pgm_info *pgm_info)
+static int inject_prog_on_prog_intercept(struct kvm_vcpu *vcpu)
 {
-       memset(pgm_info, 0, sizeof(struct kvm_s390_pgm_info));
-       pgm_info->code = vcpu->arch.sie_block->iprcc;
+       struct kvm_s390_pgm_info pgm_info = {
+               .code = vcpu->arch.sie_block->iprcc,
+               /* the PSW has already been rewound */
+               .flags = KVM_S390_PGM_FLAGS_NO_REWIND,
+       };
 
        switch (vcpu->arch.sie_block->iprcc & ~PGM_PER) {
        case PGM_AFX_TRANSLATION:
@@ -138,7 +155,7 @@ static void __extract_prog_irq(struct kvm_vcpu *vcpu,
        case PGM_PRIMARY_AUTHORITY:
        case PGM_SECONDARY_AUTHORITY:
        case PGM_SPACE_SWITCH:
-               pgm_info->trans_exc_code = vcpu->arch.sie_block->tecmc;
+               pgm_info.trans_exc_code = vcpu->arch.sie_block->tecmc;
                break;
        case PGM_ALEN_TRANSLATION:
        case PGM_ALE_SEQUENCE:
@@ -146,7 +163,7 @@ static void __extract_prog_irq(struct kvm_vcpu *vcpu,
        case PGM_ASTE_SEQUENCE:
        case PGM_ASTE_VALIDITY:
        case PGM_EXTENDED_AUTHORITY:
-               pgm_info->exc_access_id = vcpu->arch.sie_block->eai;
+               pgm_info.exc_access_id = vcpu->arch.sie_block->eai;
                break;
        case PGM_ASCE_TYPE:
        case PGM_PAGE_TRANSLATION:
@@ -154,32 +171,33 @@ static void __extract_prog_irq(struct kvm_vcpu *vcpu,
        case PGM_REGION_SECOND_TRANS:
        case PGM_REGION_THIRD_TRANS:
        case PGM_SEGMENT_TRANSLATION:
-               pgm_info->trans_exc_code = vcpu->arch.sie_block->tecmc;
-               pgm_info->exc_access_id  = vcpu->arch.sie_block->eai;
-               pgm_info->op_access_id  = vcpu->arch.sie_block->oai;
+               pgm_info.trans_exc_code = vcpu->arch.sie_block->tecmc;
+               pgm_info.exc_access_id  = vcpu->arch.sie_block->eai;
+               pgm_info.op_access_id  = vcpu->arch.sie_block->oai;
                break;
        case PGM_MONITOR:
-               pgm_info->mon_class_nr = vcpu->arch.sie_block->mcn;
-               pgm_info->mon_code = vcpu->arch.sie_block->tecmc;
+               pgm_info.mon_class_nr = vcpu->arch.sie_block->mcn;
+               pgm_info.mon_code = vcpu->arch.sie_block->tecmc;
                break;
        case PGM_VECTOR_PROCESSING:
        case PGM_DATA:
-               pgm_info->data_exc_code = vcpu->arch.sie_block->dxc;
+               pgm_info.data_exc_code = vcpu->arch.sie_block->dxc;
                break;
        case PGM_PROTECTION:
-               pgm_info->trans_exc_code = vcpu->arch.sie_block->tecmc;
-               pgm_info->exc_access_id  = vcpu->arch.sie_block->eai;
+               pgm_info.trans_exc_code = vcpu->arch.sie_block->tecmc;
+               pgm_info.exc_access_id  = vcpu->arch.sie_block->eai;
                break;
        default:
                break;
        }
 
        if (vcpu->arch.sie_block->iprcc & PGM_PER) {
-               pgm_info->per_code = vcpu->arch.sie_block->perc;
-               pgm_info->per_atmid = vcpu->arch.sie_block->peratmid;
-               pgm_info->per_address = vcpu->arch.sie_block->peraddr;
-               pgm_info->per_access_id = vcpu->arch.sie_block->peraid;
+               pgm_info.per_code = vcpu->arch.sie_block->perc;
+               pgm_info.per_atmid = vcpu->arch.sie_block->peratmid;
+               pgm_info.per_address = vcpu->arch.sie_block->peraddr;
+               pgm_info.per_access_id = vcpu->arch.sie_block->peraid;
        }
+       return kvm_s390_inject_prog_irq(vcpu, &pgm_info);
 }
 
 /*
@@ -208,7 +226,6 @@ static int handle_itdb(struct kvm_vcpu *vcpu)
 
 static int handle_prog(struct kvm_vcpu *vcpu)
 {
-       struct kvm_s390_pgm_info pgm_info;
        psw_t psw;
        int rc;
 
@@ -234,8 +251,7 @@ static int handle_prog(struct kvm_vcpu *vcpu)
        if (rc)
                return rc;
 
-       __extract_prog_irq(vcpu, &pgm_info);
-       return kvm_s390_inject_prog_irq(vcpu, &pgm_info);
+       return inject_prog_on_prog_intercept(vcpu);
 }
 
 /**
@@ -302,7 +318,7 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
 
        /* Make sure that the source is paged-in */
        rc = guest_translate_address(vcpu, vcpu->run->s.regs.gprs[reg2],
-                                    reg2, &srcaddr, 0);
+                                    reg2, &srcaddr, GACC_FETCH);
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        rc = kvm_arch_fault_in_page(vcpu, srcaddr, 0);
@@ -311,14 +327,14 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
 
        /* Make sure that the destination is paged-in */
        rc = guest_translate_address(vcpu, vcpu->run->s.regs.gprs[reg1],
-                                    reg1, &dstaddr, 1);
+                                    reg1, &dstaddr, GACC_STORE);
        if (rc)
                return kvm_s390_inject_prog_cond(vcpu, rc);
        rc = kvm_arch_fault_in_page(vcpu, dstaddr, 1);
        if (rc != 0)
                return rc;
 
-       kvm_s390_rewind_psw(vcpu, 4);
+       kvm_s390_retry_instr(vcpu);
 
        return 0;
 }
index f88ca72c3a77a52e05e65cfa79206cd8e41aa786..84efc2ba6a90555de35f6c3b78a47ab455b3beb6 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/uaccess.h>
 #include <asm/sclp.h>
 #include <asm/isc.h>
+#include <asm/gmap.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 #include "trace-s390.h"
@@ -182,8 +183,9 @@ static int cpu_timer_interrupts_enabled(struct kvm_vcpu *vcpu)
 
 static int cpu_timer_irq_pending(struct kvm_vcpu *vcpu)
 {
-       return (vcpu->arch.sie_block->cputm >> 63) &&
-              cpu_timer_interrupts_enabled(vcpu);
+       if (!cpu_timer_interrupts_enabled(vcpu))
+               return 0;
+       return kvm_s390_get_cpu_timer(vcpu) >> 63;
 }
 
 static inline int is_ioirq(unsigned long irq_type)
@@ -335,23 +337,6 @@ static void set_intercept_indicators(struct kvm_vcpu *vcpu)
        set_intercept_indicators_stop(vcpu);
 }
 
-static u16 get_ilc(struct kvm_vcpu *vcpu)
-{
-       switch (vcpu->arch.sie_block->icptcode) {
-       case ICPT_INST:
-       case ICPT_INSTPROGI:
-       case ICPT_OPEREXC:
-       case ICPT_PARTEXEC:
-       case ICPT_IOINST:
-               /* last instruction only stored for these icptcodes */
-               return insn_length(vcpu->arch.sie_block->ipa >> 8);
-       case ICPT_PROGI:
-               return vcpu->arch.sie_block->pgmilc;
-       default:
-               return 0;
-       }
-}
-
 static int __must_check __deliver_cpu_timer(struct kvm_vcpu *vcpu)
 {
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
@@ -588,7 +573,7 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
        struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
        struct kvm_s390_pgm_info pgm_info;
        int rc = 0, nullifying = false;
-       u16 ilc = get_ilc(vcpu);
+       u16 ilen;
 
        spin_lock(&li->lock);
        pgm_info = li->irq.pgm;
@@ -596,8 +581,9 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
        memset(&li->irq.pgm, 0, sizeof(pgm_info));
        spin_unlock(&li->lock);
 
-       VCPU_EVENT(vcpu, 3, "deliver: program irq code 0x%x, ilc:%d",
-                  pgm_info.code, ilc);
+       ilen = pgm_info.flags & KVM_S390_PGM_FLAGS_ILC_MASK;
+       VCPU_EVENT(vcpu, 3, "deliver: program irq code 0x%x, ilen:%d",
+                  pgm_info.code, ilen);
        vcpu->stat.deliver_program_int++;
        trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
                                         pgm_info.code, 0);
@@ -681,10 +667,11 @@ static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
                                   (u8 *) __LC_PER_ACCESS_ID);
        }
 
-       if (nullifying && vcpu->arch.sie_block->icptcode == ICPT_INST)
-               kvm_s390_rewind_psw(vcpu, ilc);
+       if (nullifying && !(pgm_info.flags & KVM_S390_PGM_FLAGS_NO_REWIND))
+               kvm_s390_rewind_psw(vcpu, ilen);
 
-       rc |= put_guest_lc(vcpu, ilc, (u16 *) __LC_PGM_ILC);
+       /* bit 1+2 of the target are the ilc, so we can directly use ilen */
+       rc |= put_guest_lc(vcpu, ilen, (u16 *) __LC_PGM_ILC);
        rc |= put_guest_lc(vcpu, vcpu->arch.sie_block->gbea,
                                 (u64 *) __LC_LAST_BREAK);
        rc |= put_guest_lc(vcpu, pgm_info.code,
@@ -923,9 +910,35 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
        return ckc_irq_pending(vcpu) || cpu_timer_irq_pending(vcpu);
 }
 
+static u64 __calculate_sltime(struct kvm_vcpu *vcpu)
+{
+       u64 now, cputm, sltime = 0;
+
+       if (ckc_interrupts_enabled(vcpu)) {
+               now = kvm_s390_get_tod_clock_fast(vcpu->kvm);
+               sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
+               /* already expired or overflow? */
+               if (!sltime || vcpu->arch.sie_block->ckc <= now)
+                       return 0;
+               if (cpu_timer_interrupts_enabled(vcpu)) {
+                       cputm = kvm_s390_get_cpu_timer(vcpu);
+                       /* already expired? */
+                       if (cputm >> 63)
+                               return 0;
+                       return min(sltime, tod_to_ns(cputm));
+               }
+       } else if (cpu_timer_interrupts_enabled(vcpu)) {
+               sltime = kvm_s390_get_cpu_timer(vcpu);
+               /* already expired? */
+               if (sltime >> 63)
+                       return 0;
+       }
+       return sltime;
+}
+
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
 {
-       u64 now, sltime;
+       u64 sltime;
 
        vcpu->stat.exit_wait_state++;
 
@@ -938,22 +951,20 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
                return -EOPNOTSUPP; /* disabled wait */
        }
 
-       if (!ckc_interrupts_enabled(vcpu)) {
+       if (!ckc_interrupts_enabled(vcpu) &&
+           !cpu_timer_interrupts_enabled(vcpu)) {
                VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer");
                __set_cpu_idle(vcpu);
                goto no_timer;
        }
 
-       now = kvm_s390_get_tod_clock_fast(vcpu->kvm);
-       sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
-
-       /* underflow */
-       if (vcpu->arch.sie_block->ckc < now)
+       sltime = __calculate_sltime(vcpu);
+       if (!sltime)
                return 0;
 
        __set_cpu_idle(vcpu);
        hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
-       VCPU_EVENT(vcpu, 4, "enabled wait via clock comparator: %llu ns", sltime);
+       VCPU_EVENT(vcpu, 4, "enabled wait: %llu ns", sltime);
 no_timer:
        srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
        kvm_vcpu_block(vcpu);
@@ -966,13 +977,13 @@ no_timer:
 
 void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
 {
-       if (waitqueue_active(&vcpu->wq)) {
+       if (swait_active(&vcpu->wq)) {
                /*
                 * The vcpu gave up the cpu voluntarily, mark it as a good
                 * yield-candidate.
                 */
                vcpu->preempted = true;
-               wake_up_interruptible(&vcpu->wq);
+               swake_up(&vcpu->wq);
                vcpu->stat.halt_wakeup++;
        }
 }
@@ -980,18 +991,16 @@ void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
 enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)
 {
        struct kvm_vcpu *vcpu;
-       u64 now, sltime;
+       u64 sltime;
 
        vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer);
-       now = kvm_s390_get_tod_clock_fast(vcpu->kvm);
-       sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
+       sltime = __calculate_sltime(vcpu);
 
        /*
         * If the monotonic clock runs faster than the tod clock we might be
         * woken up too early and have to go back to sleep to avoid deadlocks.
         */
-       if (vcpu->arch.sie_block->ckc > now &&
-           hrtimer_forward_now(timer, ns_to_ktime(sltime)))
+       if (sltime && hrtimer_forward_now(timer, ns_to_ktime(sltime)))
                return HRTIMER_RESTART;
        kvm_s390_vcpu_wakeup(vcpu);
        return HRTIMER_NORESTART;
@@ -1059,8 +1068,16 @@ static int __inject_prog(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
        trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
                                   irq->u.pgm.code, 0);
 
+       if (!(irq->u.pgm.flags & KVM_S390_PGM_FLAGS_ILC_VALID)) {
+               /* auto detection if no valid ILC was given */
+               irq->u.pgm.flags &= ~KVM_S390_PGM_FLAGS_ILC_MASK;
+               irq->u.pgm.flags |= kvm_s390_get_ilen(vcpu);
+               irq->u.pgm.flags |= KVM_S390_PGM_FLAGS_ILC_VALID;
+       }
+
        if (irq->u.pgm.code == PGM_PER) {
                li->irq.pgm.code |= PGM_PER;
+               li->irq.pgm.flags = irq->u.pgm.flags;
                /* only modify PER related information */
                li->irq.pgm.per_address = irq->u.pgm.per_address;
                li->irq.pgm.per_code = irq->u.pgm.per_code;
@@ -1069,6 +1086,7 @@ static int __inject_prog(struct kvm_vcpu *vcpu, struct kvm_s390_irq *irq)
        } else if (!(irq->u.pgm.code & PGM_PER)) {
                li->irq.pgm.code = (li->irq.pgm.code & PGM_PER) |
                                   irq->u.pgm.code;
+               li->irq.pgm.flags = irq->u.pgm.flags;
                /* only modify non-PER information */
                li->irq.pgm.trans_exc_code = irq->u.pgm.trans_exc_code;
                li->irq.pgm.mon_code = irq->u.pgm.mon_code;
index 4af21c771f9b3925bf860d0dc86cebcc803cf965..668c087513e597158a16b20d79beaf7d0cd694d0 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/lowcore.h>
 #include <asm/etr.h>
 #include <asm/pgtable.h>
+#include <asm/gmap.h>
 #include <asm/nmi.h>
 #include <asm/switch_to.h>
 #include <asm/isc.h>
@@ -158,6 +159,8 @@ static int kvm_clock_sync(struct notifier_block *notifier, unsigned long val,
                kvm->arch.epoch -= *delta;
                kvm_for_each_vcpu(i, vcpu, kvm) {
                        vcpu->arch.sie_block->epoch -= *delta;
+                       if (vcpu->arch.cputm_enabled)
+                               vcpu->arch.cputm_start += *delta;
                }
        }
        return NOTIFY_OK;
@@ -274,16 +277,17 @@ static void kvm_s390_sync_dirty_log(struct kvm *kvm,
        unsigned long address;
        struct gmap *gmap = kvm->arch.gmap;
 
-       down_read(&gmap->mm->mmap_sem);
        /* Loop over all guest pages */
        last_gfn = memslot->base_gfn + memslot->npages;
        for (cur_gfn = memslot->base_gfn; cur_gfn <= last_gfn; cur_gfn++) {
                address = gfn_to_hva_memslot(memslot, cur_gfn);
 
-               if (gmap_test_and_clear_dirty(address, gmap))
+               if (test_and_clear_guest_dirty(gmap->mm, address))
                        mark_page_dirty(kvm, cur_gfn);
+               if (fatal_signal_pending(current))
+                       return;
+               cond_resched();
        }
-       up_read(&gmap->mm->mmap_sem);
 }
 
 /* Section: vm related */
@@ -352,8 +356,8 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
                if (atomic_read(&kvm->online_vcpus)) {
                        r = -EBUSY;
                } else if (MACHINE_HAS_VX) {
-                       set_kvm_facility(kvm->arch.model.fac->mask, 129);
-                       set_kvm_facility(kvm->arch.model.fac->list, 129);
+                       set_kvm_facility(kvm->arch.model.fac_mask, 129);
+                       set_kvm_facility(kvm->arch.model.fac_list, 129);
                        r = 0;
                } else
                        r = -EINVAL;
@@ -367,8 +371,8 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
                if (atomic_read(&kvm->online_vcpus)) {
                        r = -EBUSY;
                } else if (test_facility(64)) {
-                       set_kvm_facility(kvm->arch.model.fac->mask, 64);
-                       set_kvm_facility(kvm->arch.model.fac->list, 64);
+                       set_kvm_facility(kvm->arch.model.fac_mask, 64);
+                       set_kvm_facility(kvm->arch.model.fac_list, 64);
                        r = 0;
                }
                mutex_unlock(&kvm->lock);
@@ -651,7 +655,7 @@ static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)
                memcpy(&kvm->arch.model.cpu_id, &proc->cpuid,
                       sizeof(struct cpuid));
                kvm->arch.model.ibc = proc->ibc;
-               memcpy(kvm->arch.model.fac->list, proc->fac_list,
+               memcpy(kvm->arch.model.fac_list, proc->fac_list,
                       S390_ARCH_FAC_LIST_SIZE_BYTE);
        } else
                ret = -EFAULT;
@@ -685,7 +689,8 @@ static int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr)
        }
        memcpy(&proc->cpuid, &kvm->arch.model.cpu_id, sizeof(struct cpuid));
        proc->ibc = kvm->arch.model.ibc;
-       memcpy(&proc->fac_list, kvm->arch.model.fac->list, S390_ARCH_FAC_LIST_SIZE_BYTE);
+       memcpy(&proc->fac_list, kvm->arch.model.fac_list,
+              S390_ARCH_FAC_LIST_SIZE_BYTE);
        if (copy_to_user((void __user *)attr->addr, proc, sizeof(*proc)))
                ret = -EFAULT;
        kfree(proc);
@@ -705,7 +710,7 @@ static int kvm_s390_get_machine(struct kvm *kvm, struct kvm_device_attr *attr)
        }
        get_cpu_id((struct cpuid *) &mach->cpuid);
        mach->ibc = sclp.ibc;
-       memcpy(&mach->fac_mask, kvm->arch.model.fac->mask,
+       memcpy(&mach->fac_mask, kvm->arch.model.fac_mask,
               S390_ARCH_FAC_LIST_SIZE_BYTE);
        memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list,
               S390_ARCH_FAC_LIST_SIZE_BYTE);
@@ -1082,16 +1087,12 @@ static void kvm_s390_get_cpu_id(struct cpuid *cpu_id)
        cpu_id->version = 0xff;
 }
 
-static int kvm_s390_crypto_init(struct kvm *kvm)
+static void kvm_s390_crypto_init(struct kvm *kvm)
 {
        if (!test_kvm_facility(kvm, 76))
-               return 0;
-
-       kvm->arch.crypto.crycb = kzalloc(sizeof(*kvm->arch.crypto.crycb),
-                                        GFP_KERNEL | GFP_DMA);
-       if (!kvm->arch.crypto.crycb)
-               return -ENOMEM;
+               return;
 
+       kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb;
        kvm_s390_set_crycb_format(kvm);
 
        /* Enable AES/DEA protected key functions by default */
@@ -1101,8 +1102,6 @@ static int kvm_s390_crypto_init(struct kvm *kvm)
                         sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
        get_random_bytes(kvm->arch.crypto.crycb->dea_wrapping_key_mask,
                         sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
-
-       return 0;
 }
 
 static void sca_dispose(struct kvm *kvm)
@@ -1156,37 +1155,30 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        if (!kvm->arch.dbf)
                goto out_err;
 
-       /*
-        * The architectural maximum amount of facilities is 16 kbit. To store
-        * this amount, 2 kbyte of memory is required. Thus we need a full
-        * page to hold the guest facility list (arch.model.fac->list) and the
-        * facility mask (arch.model.fac->mask). Its address size has to be
-        * 31 bits and word aligned.
-        */
-       kvm->arch.model.fac =
-               (struct kvm_s390_fac *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
-       if (!kvm->arch.model.fac)
+       kvm->arch.sie_page2 =
+            (struct sie_page2 *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+       if (!kvm->arch.sie_page2)
                goto out_err;
 
        /* Populate the facility mask initially. */
-       memcpy(kvm->arch.model.fac->mask, S390_lowcore.stfle_fac_list,
+       memcpy(kvm->arch.model.fac_mask, S390_lowcore.stfle_fac_list,
               S390_ARCH_FAC_LIST_SIZE_BYTE);
        for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) {
                if (i < kvm_s390_fac_list_mask_size())
-                       kvm->arch.model.fac->mask[i] &= kvm_s390_fac_list_mask[i];
+                       kvm->arch.model.fac_mask[i] &= kvm_s390_fac_list_mask[i];
                else
-                       kvm->arch.model.fac->mask[i] = 0UL;
+                       kvm->arch.model.fac_mask[i] = 0UL;
        }
 
        /* Populate the facility list initially. */
-       memcpy(kvm->arch.model.fac->list, kvm->arch.model.fac->mask,
+       kvm->arch.model.fac_list = kvm->arch.sie_page2->fac_list;
+       memcpy(kvm->arch.model.fac_list, kvm->arch.model.fac_mask,
               S390_ARCH_FAC_LIST_SIZE_BYTE);
 
        kvm_s390_get_cpu_id(&kvm->arch.model.cpu_id);
        kvm->arch.model.ibc = sclp.ibc & 0x0fff;
 
-       if (kvm_s390_crypto_init(kvm) < 0)
-               goto out_err;
+       kvm_s390_crypto_init(kvm);
 
        spin_lock_init(&kvm->arch.float_int.lock);
        for (i = 0; i < FIRQ_LIST_COUNT; i++)
@@ -1222,8 +1214,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 
        return 0;
 out_err:
-       kfree(kvm->arch.crypto.crycb);
-       free_page((unsigned long)kvm->arch.model.fac);
+       free_page((unsigned long)kvm->arch.sie_page2);
        debug_unregister(kvm->arch.dbf);
        sca_dispose(kvm);
        KVM_EVENT(3, "creation of vm failed: %d", rc);
@@ -1269,10 +1260,9 @@ static void kvm_free_vcpus(struct kvm *kvm)
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
        kvm_free_vcpus(kvm);
-       free_page((unsigned long)kvm->arch.model.fac);
        sca_dispose(kvm);
        debug_unregister(kvm->arch.dbf);
-       kfree(kvm->arch.crypto.crycb);
+       free_page((unsigned long)kvm->arch.sie_page2);
        if (!kvm_is_ucontrol(kvm))
                gmap_free(kvm->arch.gmap);
        kvm_s390_destroy_adapters(kvm);
@@ -1414,8 +1404,13 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
                                    KVM_SYNC_PFAULT;
        if (test_kvm_facility(vcpu->kvm, 64))
                vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
-       if (test_kvm_facility(vcpu->kvm, 129))
+       /* fprs can be synchronized via vrs, even if the guest has no vx. With
+        * MACHINE_HAS_VX, (load|store)_fpu_regs() will work with vrs format.
+        */
+       if (MACHINE_HAS_VX)
                vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS;
+       else
+               vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
 
        if (kvm_is_ucontrol(vcpu->kvm))
                return __kvm_ucontrol_vcpu_init(vcpu);
@@ -1423,6 +1418,93 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
+static void __start_cpu_timer_accounting(struct kvm_vcpu *vcpu)
+{
+       WARN_ON_ONCE(vcpu->arch.cputm_start != 0);
+       raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
+       vcpu->arch.cputm_start = get_tod_clock_fast();
+       raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
+}
+
+/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
+static void __stop_cpu_timer_accounting(struct kvm_vcpu *vcpu)
+{
+       WARN_ON_ONCE(vcpu->arch.cputm_start == 0);
+       raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
+       vcpu->arch.sie_block->cputm -= get_tod_clock_fast() - vcpu->arch.cputm_start;
+       vcpu->arch.cputm_start = 0;
+       raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
+}
+
+/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
+static void __enable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
+{
+       WARN_ON_ONCE(vcpu->arch.cputm_enabled);
+       vcpu->arch.cputm_enabled = true;
+       __start_cpu_timer_accounting(vcpu);
+}
+
+/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
+static void __disable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
+{
+       WARN_ON_ONCE(!vcpu->arch.cputm_enabled);
+       __stop_cpu_timer_accounting(vcpu);
+       vcpu->arch.cputm_enabled = false;
+}
+
+static void enable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
+{
+       preempt_disable(); /* protect from TOD sync and vcpu_load/put */
+       __enable_cpu_timer_accounting(vcpu);
+       preempt_enable();
+}
+
+static void disable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
+{
+       preempt_disable(); /* protect from TOD sync and vcpu_load/put */
+       __disable_cpu_timer_accounting(vcpu);
+       preempt_enable();
+}
+
+/* set the cpu timer - may only be called from the VCPU thread itself */
+void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm)
+{
+       preempt_disable(); /* protect from TOD sync and vcpu_load/put */
+       raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
+       if (vcpu->arch.cputm_enabled)
+               vcpu->arch.cputm_start = get_tod_clock_fast();
+       vcpu->arch.sie_block->cputm = cputm;
+       raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
+       preempt_enable();
+}
+
+/* update and get the cpu timer - can also be called from other VCPU threads */
+__u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu)
+{
+       unsigned int seq;
+       __u64 value;
+
+       if (unlikely(!vcpu->arch.cputm_enabled))
+               return vcpu->arch.sie_block->cputm;
+
+       preempt_disable(); /* protect from TOD sync and vcpu_load/put */
+       do {
+               seq = raw_read_seqcount(&vcpu->arch.cputm_seqcount);
+               /*
+                * If the writer would ever execute a read in the critical
+                * section, e.g. in irq context, we have a deadlock.
+                */
+               WARN_ON_ONCE((seq & 1) && smp_processor_id() == vcpu->cpu);
+               value = vcpu->arch.sie_block->cputm;
+               /* if cputm_start is 0, accounting is being started/stopped */
+               if (likely(vcpu->arch.cputm_start))
+                       value -= get_tod_clock_fast() - vcpu->arch.cputm_start;
+       } while (read_seqcount_retry(&vcpu->arch.cputm_seqcount, seq & ~1));
+       preempt_enable();
+       return value;
+}
+
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        /* Save host register state */
@@ -1430,10 +1512,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
        vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
 
-       /* Depending on MACHINE_HAS_VX, data stored to vrs either
-        * has vector register or floating point register format.
-        */
-       current->thread.fpu.regs = vcpu->run->s.regs.vrs;
+       if (MACHINE_HAS_VX)
+               current->thread.fpu.regs = vcpu->run->s.regs.vrs;
+       else
+               current->thread.fpu.regs = vcpu->run->s.regs.fprs;
        current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
        if (test_fp_ctl(current->thread.fpu.fpc))
                /* User space provided an invalid FPC, let's clear it */
@@ -1443,10 +1525,16 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        restore_access_regs(vcpu->run->s.regs.acrs);
        gmap_enable(vcpu->arch.gmap);
        atomic_or(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+       if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
+               __start_cpu_timer_accounting(vcpu);
+       vcpu->cpu = cpu;
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
+       vcpu->cpu = -1;
+       if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
+               __stop_cpu_timer_accounting(vcpu);
        atomic_andnot(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        gmap_disable(vcpu->arch.gmap);
 
@@ -1468,7 +1556,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
        vcpu->arch.sie_block->gpsw.mask = 0UL;
        vcpu->arch.sie_block->gpsw.addr = 0UL;
        kvm_s390_set_prefix(vcpu, 0);
-       vcpu->arch.sie_block->cputm     = 0UL;
+       kvm_s390_set_cpu_timer(vcpu, 0);
        vcpu->arch.sie_block->ckc       = 0UL;
        vcpu->arch.sie_block->todpr     = 0;
        memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
@@ -1538,7 +1626,8 @@ static void kvm_s390_vcpu_setup_model(struct kvm_vcpu *vcpu)
 
        vcpu->arch.cpu_id = model->cpu_id;
        vcpu->arch.sie_block->ibc = model->ibc;
-       vcpu->arch.sie_block->fac = (int) (long) model->fac->list;
+       if (test_kvm_facility(vcpu->kvm, 7))
+               vcpu->arch.sie_block->fac = (u32)(u64) model->fac_list;
 }
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
@@ -1616,6 +1705,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
        vcpu->arch.local_int.float_int = &kvm->arch.float_int;
        vcpu->arch.local_int.wq = &vcpu->wq;
        vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
+       seqcount_init(&vcpu->arch.cputm_seqcount);
 
        rc = kvm_vcpu_init(vcpu, kvm, id);
        if (rc)
@@ -1715,7 +1805,7 @@ static int kvm_arch_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu,
                             (u64 __user *)reg->addr);
                break;
        case KVM_REG_S390_CPU_TIMER:
-               r = put_user(vcpu->arch.sie_block->cputm,
+               r = put_user(kvm_s390_get_cpu_timer(vcpu),
                             (u64 __user *)reg->addr);
                break;
        case KVM_REG_S390_CLOCK_COMP:
@@ -1753,6 +1843,7 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
                                           struct kvm_one_reg *reg)
 {
        int r = -EINVAL;
+       __u64 val;
 
        switch (reg->id) {
        case KVM_REG_S390_TODPR:
@@ -1764,8 +1855,9 @@ static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
                             (u64 __user *)reg->addr);
                break;
        case KVM_REG_S390_CPU_TIMER:
-               r = get_user(vcpu->arch.sie_block->cputm,
-                            (u64 __user *)reg->addr);
+               r = get_user(val, (u64 __user *)reg->addr);
+               if (!r)
+                       kvm_s390_set_cpu_timer(vcpu, val);
                break;
        case KVM_REG_S390_CLOCK_COMP:
                r = get_user(vcpu->arch.sie_block->ckc,
@@ -2158,8 +2250,10 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
 
 static int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu)
 {
-       psw_t *psw = &vcpu->arch.sie_block->gpsw;
-       u8 opcode;
+       struct kvm_s390_pgm_info pgm_info = {
+               .code = PGM_ADDRESSING,
+       };
+       u8 opcode, ilen;
        int rc;
 
        VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
@@ -2173,12 +2267,21 @@ static int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu)
         * to look up the current opcode to get the length of the instruction
         * to be able to forward the PSW.
         */
-       rc = read_guest(vcpu, psw->addr, 0, &opcode, 1);
-       if (rc)
-               return kvm_s390_inject_prog_cond(vcpu, rc);
-       psw->addr = __rewind_psw(*psw, -insn_length(opcode));
-
-       return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+       rc = read_guest_instr(vcpu, &opcode, 1);
+       ilen = insn_length(opcode);
+       if (rc < 0) {
+               return rc;
+       } else if (rc) {
+               /* Instruction-Fetching Exceptions - we can't detect the ilen.
+                * Forward by arbitrary ilc, injection will take care of
+                * nullification if necessary.
+                */
+               pgm_info = vcpu->arch.pgm;
+               ilen = 4;
+       }
+       pgm_info.flags = ilen | KVM_S390_PGM_FLAGS_ILC_VALID;
+       kvm_s390_forward_psw(vcpu, ilen);
+       return kvm_s390_inject_prog_irq(vcpu, &pgm_info);
 }
 
 static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
@@ -2244,10 +2347,12 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
                 */
                local_irq_disable();
                __kvm_guest_enter();
+               __disable_cpu_timer_accounting(vcpu);
                local_irq_enable();
                exit_reason = sie64a(vcpu->arch.sie_block,
                                     vcpu->run->s.regs.gprs);
                local_irq_disable();
+               __enable_cpu_timer_accounting(vcpu);
                __kvm_guest_exit();
                local_irq_enable();
                vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
@@ -2271,7 +2376,7 @@ static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
        }
        if (kvm_run->kvm_dirty_regs & KVM_SYNC_ARCH0) {
-               vcpu->arch.sie_block->cputm = kvm_run->s.regs.cputm;
+               kvm_s390_set_cpu_timer(vcpu, kvm_run->s.regs.cputm);
                vcpu->arch.sie_block->ckc = kvm_run->s.regs.ckc;
                vcpu->arch.sie_block->todpr = kvm_run->s.regs.todpr;
                vcpu->arch.sie_block->pp = kvm_run->s.regs.pp;
@@ -2293,7 +2398,7 @@ static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
        kvm_run->s.regs.prefix = kvm_s390_get_prefix(vcpu);
        memcpy(&kvm_run->s.regs.crs, &vcpu->arch.sie_block->gcr, 128);
-       kvm_run->s.regs.cputm = vcpu->arch.sie_block->cputm;
+       kvm_run->s.regs.cputm = kvm_s390_get_cpu_timer(vcpu);
        kvm_run->s.regs.ckc = vcpu->arch.sie_block->ckc;
        kvm_run->s.regs.todpr = vcpu->arch.sie_block->todpr;
        kvm_run->s.regs.pp = vcpu->arch.sie_block->pp;
@@ -2325,6 +2430,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        }
 
        sync_regs(vcpu, kvm_run);
+       enable_cpu_timer_accounting(vcpu);
 
        might_fault();
        rc = __vcpu_run(vcpu);
@@ -2344,6 +2450,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                rc = 0;
        }
 
+       disable_cpu_timer_accounting(vcpu);
        store_regs(vcpu, kvm_run);
 
        if (vcpu->sigset_active)
@@ -2364,7 +2471,7 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
        unsigned char archmode = 1;
        freg_t fprs[NUM_FPRS];
        unsigned int px;
-       u64 clkcomp;
+       u64 clkcomp, cputm;
        int rc;
 
        px = kvm_s390_get_prefix(vcpu);
@@ -2381,12 +2488,12 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
 
        /* manually convert vector registers if necessary */
        if (MACHINE_HAS_VX) {
-               convert_vx_to_fp(fprs, current->thread.fpu.vxrs);
+               convert_vx_to_fp(fprs, (__vector128 *) vcpu->run->s.regs.vrs);
                rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
                                     fprs, 128);
        } else {
                rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
-                                    vcpu->run->s.regs.vrs, 128);
+                                    vcpu->run->s.regs.fprs, 128);
        }
        rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA,
                              vcpu->run->s.regs.gprs, 128);
@@ -2398,8 +2505,9 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
                              &vcpu->run->s.regs.fpc, 4);
        rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA,
                              &vcpu->arch.sie_block->todpr, 4);
+       cputm = kvm_s390_get_cpu_timer(vcpu);
        rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA,
-                             &vcpu->arch.sie_block->cputm, 8);
+                             &cputm, 8);
        clkcomp = vcpu->arch.sie_block->ckc >> 8;
        rc |= write_guest_abs(vcpu, gpa + __LC_CLOCK_COMP_SAVE_AREA,
                              &clkcomp, 8);
@@ -2605,7 +2713,8 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
        switch (mop->op) {
        case KVM_S390_MEMOP_LOGICAL_READ:
                if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
-                       r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size, false);
+                       r = check_gva_range(vcpu, mop->gaddr, mop->ar,
+                                           mop->size, GACC_FETCH);
                        break;
                }
                r = read_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size);
@@ -2616,7 +2725,8 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
                break;
        case KVM_S390_MEMOP_LOGICAL_WRITE:
                if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
-                       r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size, true);
+                       r = check_gva_range(vcpu, mop->gaddr, mop->ar,
+                                           mop->size, GACC_STORE);
                        break;
                }
                if (copy_from_user(tmpbuf, uaddr, mop->size)) {
index df1abada1f36dfc3579ab6ff2ef45c7db828490b..8621ab00ec8e19a6e7dabb20539da896bb38dcc5 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <asm/facility.h>
+#include <asm/processor.h>
 
 typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
 
@@ -53,6 +54,11 @@ static inline int is_vcpu_stopped(struct kvm_vcpu *vcpu)
        return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED;
 }
 
+static inline int is_vcpu_idle(struct kvm_vcpu *vcpu)
+{
+       return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_WAIT;
+}
+
 static inline int kvm_is_ucontrol(struct kvm *kvm)
 {
 #ifdef CONFIG_KVM_S390_UCONTROL
@@ -154,8 +160,8 @@ static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc)
 /* test availability of facility in a kvm instance */
 static inline int test_kvm_facility(struct kvm *kvm, unsigned long nr)
 {
-       return __test_facility(nr, kvm->arch.model.fac->mask) &&
-               __test_facility(nr, kvm->arch.model.fac->list);
+       return __test_facility(nr, kvm->arch.model.fac_mask) &&
+               __test_facility(nr, kvm->arch.model.fac_list);
 }
 
 static inline int set_kvm_facility(u64 *fac_list, unsigned long nr)
@@ -212,8 +218,22 @@ int kvm_s390_reinject_io_int(struct kvm *kvm,
 int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked);
 
 /* implemented in intercept.c */
-void kvm_s390_rewind_psw(struct kvm_vcpu *vcpu, int ilc);
+u8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu);
 int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
+static inline void kvm_s390_rewind_psw(struct kvm_vcpu *vcpu, int ilen)
+{
+       struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
+
+       sie_block->gpsw.addr = __rewind_psw(sie_block->gpsw, ilen);
+}
+static inline void kvm_s390_forward_psw(struct kvm_vcpu *vcpu, int ilen)
+{
+       kvm_s390_rewind_psw(vcpu, -ilen);
+}
+static inline void kvm_s390_retry_instr(struct kvm_vcpu *vcpu)
+{
+       kvm_s390_rewind_psw(vcpu, kvm_s390_get_ilen(vcpu));
+}
 
 /* implemented in priv.c */
 int is_valid_psw(psw_t *psw);
@@ -248,6 +268,8 @@ int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu);
 void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu);
 unsigned long kvm_s390_fac_list_mask_size(void);
 extern unsigned long kvm_s390_fac_list_mask[];
+void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm);
+__u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu);
 
 /* implemented in diag.c */
 int kvm_s390_handle_diag(struct kvm_vcpu *vcpu);
index ed74e86d9b9eb60c88b2f91e671c9d9b9c56f316..0a1591d3d25d07a6c2e98e406f77bb391ebb7c1a 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/sysinfo.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/gmap.h>
 #include <asm/io.h>
 #include <asm/ptrace.h>
 #include <asm/compat.h>
@@ -173,7 +174,7 @@ static int handle_skey(struct kvm_vcpu *vcpu)
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-       kvm_s390_rewind_psw(vcpu, 4);
+       kvm_s390_retry_instr(vcpu);
        VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation");
        return 0;
 }
@@ -184,7 +185,7 @@ static int handle_ipte_interlock(struct kvm_vcpu *vcpu)
        if (psw_bits(vcpu->arch.sie_block->gpsw).p)
                return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
        wait_event(vcpu->kvm->arch.ipte_wq, !ipte_lock_held(vcpu));
-       kvm_s390_rewind_psw(vcpu, 4);
+       kvm_s390_retry_instr(vcpu);
        VCPU_EVENT(vcpu, 4, "%s", "retrying ipte interlock operation");
        return 0;
 }
@@ -354,7 +355,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
         * We need to shift the lower 32 facility bits (bit 0-31) from a u64
         * into a u32 memory representation. They will remain bits 0-31.
         */
-       fac = *vcpu->kvm->arch.model.fac->list >> 32;
+       fac = *vcpu->kvm->arch.model.fac_list >> 32;
        rc = write_guest_lc(vcpu, offsetof(struct lowcore, stfl_fac_list),
                            &fac, sizeof(fac));
        if (rc)
@@ -759,8 +760,8 @@ static int handle_essa(struct kvm_vcpu *vcpu)
        if (((vcpu->arch.sie_block->ipb & 0xf0000000) >> 28) > 6)
                return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-       /* Rewind PSW to repeat the ESSA instruction */
-       kvm_s390_rewind_psw(vcpu, 4);
+       /* Retry the ESSA instruction */
+       kvm_s390_retry_instr(vcpu);
        vcpu->arch.sie_block->cbrlo &= PAGE_MASK;       /* reset nceo */
        cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo);
        down_read(&gmap->mm->mmap_sem);
@@ -981,11 +982,12 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
                return -EOPNOTSUPP;
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
                ipte_lock(vcpu);
-       ret = guest_translate_address(vcpu, address1, ar, &gpa, 1);
+       ret = guest_translate_address(vcpu, address1, ar, &gpa, GACC_STORE);
        if (ret == PGM_PROTECTION) {
                /* Write protected? Try again with read-only... */
                cc = 1;
-               ret = guest_translate_address(vcpu, address1, ar, &gpa, 0);
+               ret = guest_translate_address(vcpu, address1, ar, &gpa,
+                                             GACC_FETCH);
        }
        if (ret) {
                if (ret == PGM_ADDRESSING || ret == PGM_TRANSLATION_SPEC) {
index 0e8fefe5b0ce18a8a57739af8dd70e5f1174c05f..1d1af31e83546cb5609d52470f363302fd18ab35 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 lib-y += delay.o string.o uaccess.o find.o
-obj-y += mem.o
+obj-y += mem.o xor.o
 lib-$(CONFIG_SMP) += spinlock.o
 lib-$(CONFIG_KPROBES) += probes.o
 lib-$(CONFIG_UPROBES) += probes.o
diff --git a/arch/s390/lib/xor.c b/arch/s390/lib/xor.c
new file mode 100644 (file)
index 0000000..7d94e3e
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Optimized xor_block operation for RAID4/5
+ *
+ * Copyright IBM Corp. 2016
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/raid/xor.h>
+
+static void xor_xc_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
+{
+       asm volatile(
+               "       larl    1,2f\n"
+               "       aghi    %0,-1\n"
+               "       jm      3f\n"
+               "       srlg    0,%0,8\n"
+               "       ltgr    0,0\n"
+               "       jz      1f\n"
+               "0:     xc      0(256,%1),0(%2)\n"
+               "       la      %1,256(%1)\n"
+               "       la      %2,256(%2)\n"
+               "       brctg   0,0b\n"
+               "1:     ex      %0,0(1)\n"
+               "       j       3f\n"
+               "2:     xc      0(1,%1),0(%2)\n"
+               "3:\n"
+               : : "d" (bytes), "a" (p1), "a" (p2)
+               : "0", "1", "cc", "memory");
+}
+
+static void xor_xc_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+                    unsigned long *p3)
+{
+       asm volatile(
+               "       larl    1,2f\n"
+               "       aghi    %0,-1\n"
+               "       jm      3f\n"
+               "       srlg    0,%0,8\n"
+               "       ltgr    0,0\n"
+               "       jz      1f\n"
+               "0:     xc      0(256,%1),0(%2)\n"
+               "       xc      0(256,%1),0(%3)\n"
+               "       la      %1,256(%1)\n"
+               "       la      %2,256(%2)\n"
+               "       la      %3,256(%3)\n"
+               "       brctg   0,0b\n"
+               "1:     ex      %0,0(1)\n"
+               "       ex      %0,6(1)\n"
+               "       j       3f\n"
+               "2:     xc      0(1,%1),0(%2)\n"
+               "       xc      0(1,%1),0(%3)\n"
+               "3:\n"
+               : "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3)
+               : : "0", "1", "cc", "memory");
+}
+
+static void xor_xc_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+                    unsigned long *p3, unsigned long *p4)
+{
+       asm volatile(
+               "       larl    1,2f\n"
+               "       aghi    %0,-1\n"
+               "       jm      3f\n"
+               "       srlg    0,%0,8\n"
+               "       ltgr    0,0\n"
+               "       jz      1f\n"
+               "0:     xc      0(256,%1),0(%2)\n"
+               "       xc      0(256,%1),0(%3)\n"
+               "       xc      0(256,%1),0(%4)\n"
+               "       la      %1,256(%1)\n"
+               "       la      %2,256(%2)\n"
+               "       la      %3,256(%3)\n"
+               "       la      %4,256(%4)\n"
+               "       brctg   0,0b\n"
+               "1:     ex      %0,0(1)\n"
+               "       ex      %0,6(1)\n"
+               "       ex      %0,12(1)\n"
+               "       j       3f\n"
+               "2:     xc      0(1,%1),0(%2)\n"
+               "       xc      0(1,%1),0(%3)\n"
+               "       xc      0(1,%1),0(%4)\n"
+               "3:\n"
+               : "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4)
+               : : "0", "1", "cc", "memory");
+}
+
+static void xor_xc_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
+                    unsigned long *p3, unsigned long *p4, unsigned long *p5)
+{
+       /* Get around a gcc oddity */
+       register unsigned long *reg7 asm ("7") = p5;
+
+       asm volatile(
+               "       larl    1,2f\n"
+               "       aghi    %0,-1\n"
+               "       jm      3f\n"
+               "       srlg    0,%0,8\n"
+               "       ltgr    0,0\n"
+               "       jz      1f\n"
+               "0:     xc      0(256,%1),0(%2)\n"
+               "       xc      0(256,%1),0(%3)\n"
+               "       xc      0(256,%1),0(%4)\n"
+               "       xc      0(256,%1),0(%5)\n"
+               "       la      %1,256(%1)\n"
+               "       la      %2,256(%2)\n"
+               "       la      %3,256(%3)\n"
+               "       la      %4,256(%4)\n"
+               "       la      %5,256(%5)\n"
+               "       brctg   0,0b\n"
+               "1:     ex      %0,0(1)\n"
+               "       ex      %0,6(1)\n"
+               "       ex      %0,12(1)\n"
+               "       ex      %0,18(1)\n"
+               "       j       3f\n"
+               "2:     xc      0(1,%1),0(%2)\n"
+               "       xc      0(1,%1),0(%3)\n"
+               "       xc      0(1,%1),0(%4)\n"
+               "       xc      0(1,%1),0(%5)\n"
+               "3:\n"
+               : "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4),
+                 "+a" (reg7)
+               : : "0", "1", "cc", "memory");
+}
+
+struct xor_block_template xor_block_xc = {
+       .name = "xc",
+       .do_2 = xor_xc_2,
+       .do_3 = xor_xc_3,
+       .do_4 = xor_xc_4,
+       .do_5 = xor_xc_5,
+};
+EXPORT_SYMBOL(xor_block_xc);
index 839592ca265cdb620ddbe1c0505e9d9bbe4d428c..2ae54cad2b6ab2734f999694bbb968b940416d00 100644 (file)
@@ -2,9 +2,11 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y          := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o
+obj-y          := init.o fault.o extmem.o mmap.o vmem.o maccess.o
 obj-y          += page-states.o gup.o extable.o pageattr.o mem_detect.o
+obj-y          += pgtable.o pgalloc.o
 
 obj-$(CONFIG_CMM)              += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
 obj-$(CONFIG_S390_PTDUMP)      += dump_pagetables.o
+obj-$(CONFIG_PGSTE)            += gmap.o
index a1bf4ad8925de627fee30f14e94f4bbab6511b22..02042b6b66bfa52f2f1039aa017d85dcd0964c26 100644 (file)
@@ -265,7 +265,7 @@ query_segment_type (struct dcss_segment *seg)
                goto out_free;
        }
        if (diag_cc > 1) {
-               pr_warning("Querying a DCSS type failed with rc=%ld\n", vmrc);
+               pr_warn("Querying a DCSS type failed with rc=%ld\n", vmrc);
                rc = dcss_diag_translate_rc (vmrc);
                goto out_free;
        }
@@ -457,8 +457,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
                goto out_resource;
        }
        if (diag_cc > 1) {
-               pr_warning("Loading DCSS %s failed with rc=%ld\n", name,
-                          end_addr);
+               pr_warn("Loading DCSS %s failed with rc=%ld\n", name, end_addr);
                rc = dcss_diag_translate_rc(end_addr);
                dcss_diag(&purgeseg_scode, seg->dcss_name,
                                &dummy, &dummy);
@@ -574,8 +573,7 @@ segment_modify_shared (char *name, int do_nonshared)
                goto out_unlock;
        }
        if (atomic_read (&seg->ref_count) != 1) {
-               pr_warning("DCSS %s is in use and cannot be reloaded\n",
-                          name);
+               pr_warn("DCSS %s is in use and cannot be reloaded\n", name);
                rc = -EAGAIN;
                goto out_unlock;
        }
@@ -588,8 +586,8 @@ segment_modify_shared (char *name, int do_nonshared)
                        seg->res->flags |= IORESOURCE_READONLY;
 
        if (request_resource(&iomem_resource, seg->res)) {
-               pr_warning("DCSS %s overlaps with used memory resources "
-                          "and cannot be reloaded\n", name);
+               pr_warn("DCSS %s overlaps with used memory resources and cannot be reloaded\n",
+                       name);
                rc = -EBUSY;
                kfree(seg->res);
                goto out_del_mem;
@@ -607,8 +605,8 @@ segment_modify_shared (char *name, int do_nonshared)
                goto out_del_res;
        }
        if (diag_cc > 1) {
-               pr_warning("Reloading DCSS %s failed with rc=%ld\n", name,
-                          end_addr);
+               pr_warn("Reloading DCSS %s failed with rc=%ld\n",
+                       name, end_addr);
                rc = dcss_diag_translate_rc(end_addr);
                goto out_del_res;
        }
index 791a4146052c7a48fdb72a6ef3b9e0d1abc06eeb..cce577feab1e9998f5e1b29e6011e70e8db075fe 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/diag.h>
 #include <asm/pgtable.h>
+#include <asm/gmap.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
 #include <asm/facility.h>
@@ -183,6 +184,8 @@ static void dump_fault_info(struct pt_regs *regs)
 {
        unsigned long asce;
 
+       pr_alert("Failing address: %016lx TEID: %016lx\n",
+                regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
        pr_alert("Fault in ");
        switch (regs->int_parm_long & 3) {
        case 3:
@@ -218,7 +221,9 @@ static void dump_fault_info(struct pt_regs *regs)
        dump_pagetable(asce, regs->int_parm_long & __FAIL_ADDR_MASK);
 }
 
-static inline void report_user_fault(struct pt_regs *regs, long signr)
+int show_unhandled_signals = 1;
+
+void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault)
 {
        if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
                return;
@@ -230,9 +235,8 @@ static inline void report_user_fault(struct pt_regs *regs, long signr)
               regs->int_code & 0xffff, regs->int_code >> 17);
        print_vma_addr(KERN_CONT "in ", regs->psw.addr);
        printk(KERN_CONT "\n");
-       printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n",
-              regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
-       dump_fault_info(regs);
+       if (is_mm_fault)
+               dump_fault_info(regs);
        show_regs(regs);
 }
 
@@ -244,7 +248,7 @@ static noinline void do_sigsegv(struct pt_regs *regs, int si_code)
 {
        struct siginfo si;
 
-       report_user_fault(regs, SIGSEGV);
+       report_user_fault(regs, SIGSEGV, 1);
        si.si_signo = SIGSEGV;
        si.si_code = si_code;
        si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
@@ -272,8 +276,6 @@ static noinline void do_no_context(struct pt_regs *regs)
        else
                printk(KERN_ALERT "Unable to handle kernel paging request"
                       " in virtual user address space\n");
-       printk(KERN_ALERT "failing address: %016lx TEID: %016lx\n",
-              regs->int_parm_long & __FAIL_ADDR_MASK, regs->int_parm_long);
        dump_fault_info(regs);
        die(regs, "Oops");
        do_exit(SIGKILL);
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
new file mode 100644 (file)
index 0000000..69247b4
--- /dev/null
@@ -0,0 +1,774 @@
+/*
+ *  KVM guest address space mapping code
+ *
+ *    Copyright IBM Corp. 2007, 2016
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/swapops.h>
+#include <linux/ksm.h>
+#include <linux/mman.h>
+
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/gmap.h>
+#include <asm/tlb.h>
+
+/**
+ * gmap_alloc - allocate a guest address space
+ * @mm: pointer to the parent mm_struct
+ * @limit: maximum size of the gmap address space
+ *
+ * Returns a guest address space structure.
+ */
+struct gmap *gmap_alloc(struct mm_struct *mm, unsigned long limit)
+{
+       struct gmap *gmap;
+       struct page *page;
+       unsigned long *table;
+       unsigned long etype, atype;
+
+       if (limit < (1UL << 31)) {
+               limit = (1UL << 31) - 1;
+               atype = _ASCE_TYPE_SEGMENT;
+               etype = _SEGMENT_ENTRY_EMPTY;
+       } else if (limit < (1UL << 42)) {
+               limit = (1UL << 42) - 1;
+               atype = _ASCE_TYPE_REGION3;
+               etype = _REGION3_ENTRY_EMPTY;
+       } else if (limit < (1UL << 53)) {
+               limit = (1UL << 53) - 1;
+               atype = _ASCE_TYPE_REGION2;
+               etype = _REGION2_ENTRY_EMPTY;
+       } else {
+               limit = -1UL;
+               atype = _ASCE_TYPE_REGION1;
+               etype = _REGION1_ENTRY_EMPTY;
+       }
+       gmap = kzalloc(sizeof(struct gmap), GFP_KERNEL);
+       if (!gmap)
+               goto out;
+       INIT_LIST_HEAD(&gmap->crst_list);
+       INIT_RADIX_TREE(&gmap->guest_to_host, GFP_KERNEL);
+       INIT_RADIX_TREE(&gmap->host_to_guest, GFP_ATOMIC);
+       spin_lock_init(&gmap->guest_table_lock);
+       gmap->mm = mm;
+       page = alloc_pages(GFP_KERNEL, 2);
+       if (!page)
+               goto out_free;
+       page->index = 0;
+       list_add(&page->lru, &gmap->crst_list);
+       table = (unsigned long *) page_to_phys(page);
+       crst_table_init(table, etype);
+       gmap->table = table;
+       gmap->asce = atype | _ASCE_TABLE_LENGTH |
+               _ASCE_USER_BITS | __pa(table);
+       gmap->asce_end = limit;
+       down_write(&mm->mmap_sem);
+       list_add(&gmap->list, &mm->context.gmap_list);
+       up_write(&mm->mmap_sem);
+       return gmap;
+
+out_free:
+       kfree(gmap);
+out:
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(gmap_alloc);
+
+static void gmap_flush_tlb(struct gmap *gmap)
+{
+       if (MACHINE_HAS_IDTE)
+               __tlb_flush_asce(gmap->mm, gmap->asce);
+       else
+               __tlb_flush_global();
+}
+
+static void gmap_radix_tree_free(struct radix_tree_root *root)
+{
+       struct radix_tree_iter iter;
+       unsigned long indices[16];
+       unsigned long index;
+       void **slot;
+       int i, nr;
+
+       /* A radix tree is freed by deleting all of its entries */
+       index = 0;
+       do {
+               nr = 0;
+               radix_tree_for_each_slot(slot, root, &iter, index) {
+                       indices[nr] = iter.index;
+                       if (++nr == 16)
+                               break;
+               }
+               for (i = 0; i < nr; i++) {
+                       index = indices[i];
+                       radix_tree_delete(root, index);
+               }
+       } while (nr > 0);
+}
+
+/**
+ * gmap_free - free a guest address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_free(struct gmap *gmap)
+{
+       struct page *page, *next;
+
+       /* Flush tlb. */
+       if (MACHINE_HAS_IDTE)
+               __tlb_flush_asce(gmap->mm, gmap->asce);
+       else
+               __tlb_flush_global();
+
+       /* Free all segment & region tables. */
+       list_for_each_entry_safe(page, next, &gmap->crst_list, lru)
+               __free_pages(page, 2);
+       gmap_radix_tree_free(&gmap->guest_to_host);
+       gmap_radix_tree_free(&gmap->host_to_guest);
+       down_write(&gmap->mm->mmap_sem);
+       list_del(&gmap->list);
+       up_write(&gmap->mm->mmap_sem);
+       kfree(gmap);
+}
+EXPORT_SYMBOL_GPL(gmap_free);
+
+/**
+ * gmap_enable - switch primary space to the guest address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_enable(struct gmap *gmap)
+{
+       S390_lowcore.gmap = (unsigned long) gmap;
+}
+EXPORT_SYMBOL_GPL(gmap_enable);
+
+/**
+ * gmap_disable - switch back to the standard primary address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_disable(struct gmap *gmap)
+{
+       S390_lowcore.gmap = 0UL;
+}
+EXPORT_SYMBOL_GPL(gmap_disable);
+
+/*
+ * gmap_alloc_table is assumed to be called with mmap_sem held
+ */
+static int gmap_alloc_table(struct gmap *gmap, unsigned long *table,
+                           unsigned long init, unsigned long gaddr)
+{
+       struct page *page;
+       unsigned long *new;
+
+       /* since we dont free the gmap table until gmap_free we can unlock */
+       page = alloc_pages(GFP_KERNEL, 2);
+       if (!page)
+               return -ENOMEM;
+       new = (unsigned long *) page_to_phys(page);
+       crst_table_init(new, init);
+       spin_lock(&gmap->mm->page_table_lock);
+       if (*table & _REGION_ENTRY_INVALID) {
+               list_add(&page->lru, &gmap->crst_list);
+               *table = (unsigned long) new | _REGION_ENTRY_LENGTH |
+                       (*table & _REGION_ENTRY_TYPE_MASK);
+               page->index = gaddr;
+               page = NULL;
+       }
+       spin_unlock(&gmap->mm->page_table_lock);
+       if (page)
+               __free_pages(page, 2);
+       return 0;
+}
+
+/**
+ * __gmap_segment_gaddr - find virtual address from segment pointer
+ * @entry: pointer to a segment table entry in the guest address space
+ *
+ * Returns the virtual address in the guest address space for the segment
+ */
+static unsigned long __gmap_segment_gaddr(unsigned long *entry)
+{
+       struct page *page;
+       unsigned long offset, mask;
+
+       offset = (unsigned long) entry / sizeof(unsigned long);
+       offset = (offset & (PTRS_PER_PMD - 1)) * PMD_SIZE;
+       mask = ~(PTRS_PER_PMD * sizeof(pmd_t) - 1);
+       page = virt_to_page((void *)((unsigned long) entry & mask));
+       return page->index + offset;
+}
+
+/**
+ * __gmap_unlink_by_vmaddr - unlink a single segment via a host address
+ * @gmap: pointer to the guest address space structure
+ * @vmaddr: address in the host process address space
+ *
+ * Returns 1 if a TLB flush is required
+ */
+static int __gmap_unlink_by_vmaddr(struct gmap *gmap, unsigned long vmaddr)
+{
+       unsigned long *entry;
+       int flush = 0;
+
+       spin_lock(&gmap->guest_table_lock);
+       entry = radix_tree_delete(&gmap->host_to_guest, vmaddr >> PMD_SHIFT);
+       if (entry) {
+               flush = (*entry != _SEGMENT_ENTRY_INVALID);
+               *entry = _SEGMENT_ENTRY_INVALID;
+       }
+       spin_unlock(&gmap->guest_table_lock);
+       return flush;
+}
+
+/**
+ * __gmap_unmap_by_gaddr - unmap a single segment via a guest address
+ * @gmap: pointer to the guest address space structure
+ * @gaddr: address in the guest address space
+ *
+ * Returns 1 if a TLB flush is required
+ */
+static int __gmap_unmap_by_gaddr(struct gmap *gmap, unsigned long gaddr)
+{
+       unsigned long vmaddr;
+
+       vmaddr = (unsigned long) radix_tree_delete(&gmap->guest_to_host,
+                                                  gaddr >> PMD_SHIFT);
+       return vmaddr ? __gmap_unlink_by_vmaddr(gmap, vmaddr) : 0;
+}
+
+/**
+ * gmap_unmap_segment - unmap segment from the guest address space
+ * @gmap: pointer to the guest address space structure
+ * @to: address in the guest address space
+ * @len: length of the memory area to unmap
+ *
+ * Returns 0 if the unmap succeeded, -EINVAL if not.
+ */
+int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
+{
+       unsigned long off;
+       int flush;
+
+       if ((to | len) & (PMD_SIZE - 1))
+               return -EINVAL;
+       if (len == 0 || to + len < to)
+               return -EINVAL;
+
+       flush = 0;
+       down_write(&gmap->mm->mmap_sem);
+       for (off = 0; off < len; off += PMD_SIZE)
+               flush |= __gmap_unmap_by_gaddr(gmap, to + off);
+       up_write(&gmap->mm->mmap_sem);
+       if (flush)
+               gmap_flush_tlb(gmap);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(gmap_unmap_segment);
+
+/**
+ * gmap_map_segment - map a segment to the guest address space
+ * @gmap: pointer to the guest address space structure
+ * @from: source address in the parent address space
+ * @to: target address in the guest address space
+ * @len: length of the memory area to map
+ *
+ * Returns 0 if the mmap succeeded, -EINVAL or -ENOMEM if not.
+ */
+int gmap_map_segment(struct gmap *gmap, unsigned long from,
+                    unsigned long to, unsigned long len)
+{
+       unsigned long off;
+       int flush;
+
+       if ((from | to | len) & (PMD_SIZE - 1))
+               return -EINVAL;
+       if (len == 0 || from + len < from || to + len < to ||
+           from + len > TASK_MAX_SIZE || to + len > gmap->asce_end)
+               return -EINVAL;
+
+       flush = 0;
+       down_write(&gmap->mm->mmap_sem);
+       for (off = 0; off < len; off += PMD_SIZE) {
+               /* Remove old translation */
+               flush |= __gmap_unmap_by_gaddr(gmap, to + off);
+               /* Store new translation */
+               if (radix_tree_insert(&gmap->guest_to_host,
+                                     (to + off) >> PMD_SHIFT,
+                                     (void *) from + off))
+                       break;
+       }
+       up_write(&gmap->mm->mmap_sem);
+       if (flush)
+               gmap_flush_tlb(gmap);
+       if (off >= len)
+               return 0;
+       gmap_unmap_segment(gmap, to, len);
+       return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(gmap_map_segment);
+
+/**
+ * __gmap_translate - translate a guest address to a user space address
+ * @gmap: pointer to guest mapping meta data structure
+ * @gaddr: guest address
+ *
+ * Returns user space address which corresponds to the guest address or
+ * -EFAULT if no such mapping exists.
+ * This function does not establish potentially missing page table entries.
+ * The mmap_sem of the mm that belongs to the address space must be held
+ * when this function gets called.
+ */
+unsigned long __gmap_translate(struct gmap *gmap, unsigned long gaddr)
+{
+       unsigned long vmaddr;
+
+       vmaddr = (unsigned long)
+               radix_tree_lookup(&gmap->guest_to_host, gaddr >> PMD_SHIFT);
+       return vmaddr ? (vmaddr | (gaddr & ~PMD_MASK)) : -EFAULT;
+}
+EXPORT_SYMBOL_GPL(__gmap_translate);
+
+/**
+ * gmap_translate - translate a guest address to a user space address
+ * @gmap: pointer to guest mapping meta data structure
+ * @gaddr: guest address
+ *
+ * Returns user space address which corresponds to the guest address or
+ * -EFAULT if no such mapping exists.
+ * This function does not establish potentially missing page table entries.
+ */
+unsigned long gmap_translate(struct gmap *gmap, unsigned long gaddr)
+{
+       unsigned long rc;
+
+       down_read(&gmap->mm->mmap_sem);
+       rc = __gmap_translate(gmap, gaddr);
+       up_read(&gmap->mm->mmap_sem);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(gmap_translate);
+
+/**
+ * gmap_unlink - disconnect a page table from the gmap shadow tables
+ * @gmap: pointer to guest mapping meta data structure
+ * @table: pointer to the host page table
+ * @vmaddr: vm address associated with the host page table
+ */
+void gmap_unlink(struct mm_struct *mm, unsigned long *table,
+                unsigned long vmaddr)
+{
+       struct gmap *gmap;
+       int flush;
+
+       list_for_each_entry(gmap, &mm->context.gmap_list, list) {
+               flush = __gmap_unlink_by_vmaddr(gmap, vmaddr);
+               if (flush)
+                       gmap_flush_tlb(gmap);
+       }
+}
+
+/**
+ * gmap_link - set up shadow page tables to connect a host to a guest address
+ * @gmap: pointer to guest mapping meta data structure
+ * @gaddr: guest address
+ * @vmaddr: vm address
+ *
+ * Returns 0 on success, -ENOMEM for out of memory conditions, and -EFAULT
+ * if the vm address is already mapped to a different guest segment.
+ * The mmap_sem of the mm that belongs to the address space must be held
+ * when this function gets called.
+ */
+int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
+{
+       struct mm_struct *mm;
+       unsigned long *table;
+       spinlock_t *ptl;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       int rc;
+
+       /* Create higher level tables in the gmap page table */
+       table = gmap->table;
+       if ((gmap->asce & _ASCE_TYPE_MASK) >= _ASCE_TYPE_REGION1) {
+               table += (gaddr >> 53) & 0x7ff;
+               if ((*table & _REGION_ENTRY_INVALID) &&
+                   gmap_alloc_table(gmap, table, _REGION2_ENTRY_EMPTY,
+                                    gaddr & 0xffe0000000000000UL))
+                       return -ENOMEM;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       }
+       if ((gmap->asce & _ASCE_TYPE_MASK) >= _ASCE_TYPE_REGION2) {
+               table += (gaddr >> 42) & 0x7ff;
+               if ((*table & _REGION_ENTRY_INVALID) &&
+                   gmap_alloc_table(gmap, table, _REGION3_ENTRY_EMPTY,
+                                    gaddr & 0xfffffc0000000000UL))
+                       return -ENOMEM;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       }
+       if ((gmap->asce & _ASCE_TYPE_MASK) >= _ASCE_TYPE_REGION3) {
+               table += (gaddr >> 31) & 0x7ff;
+               if ((*table & _REGION_ENTRY_INVALID) &&
+                   gmap_alloc_table(gmap, table, _SEGMENT_ENTRY_EMPTY,
+                                    gaddr & 0xffffffff80000000UL))
+                       return -ENOMEM;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       }
+       table += (gaddr >> 20) & 0x7ff;
+       /* Walk the parent mm page table */
+       mm = gmap->mm;
+       pgd = pgd_offset(mm, vmaddr);
+       VM_BUG_ON(pgd_none(*pgd));
+       pud = pud_offset(pgd, vmaddr);
+       VM_BUG_ON(pud_none(*pud));
+       pmd = pmd_offset(pud, vmaddr);
+       VM_BUG_ON(pmd_none(*pmd));
+       /* large pmds cannot yet be handled */
+       if (pmd_large(*pmd))
+               return -EFAULT;
+       /* Link gmap segment table entry location to page table. */
+       rc = radix_tree_preload(GFP_KERNEL);
+       if (rc)
+               return rc;
+       ptl = pmd_lock(mm, pmd);
+       spin_lock(&gmap->guest_table_lock);
+       if (*table == _SEGMENT_ENTRY_INVALID) {
+               rc = radix_tree_insert(&gmap->host_to_guest,
+                                      vmaddr >> PMD_SHIFT, table);
+               if (!rc)
+                       *table = pmd_val(*pmd);
+       } else
+               rc = 0;
+       spin_unlock(&gmap->guest_table_lock);
+       spin_unlock(ptl);
+       radix_tree_preload_end();
+       return rc;
+}
+
+/**
+ * gmap_fault - resolve a fault on a guest address
+ * @gmap: pointer to guest mapping meta data structure
+ * @gaddr: guest address
+ * @fault_flags: flags to pass down to handle_mm_fault()
+ *
+ * Returns 0 on success, -ENOMEM for out of memory conditions, and -EFAULT
+ * if the vm address is already mapped to a different guest segment.
+ */
+int gmap_fault(struct gmap *gmap, unsigned long gaddr,
+              unsigned int fault_flags)
+{
+       unsigned long vmaddr;
+       int rc;
+       bool unlocked;
+
+       down_read(&gmap->mm->mmap_sem);
+
+retry:
+       unlocked = false;
+       vmaddr = __gmap_translate(gmap, gaddr);
+       if (IS_ERR_VALUE(vmaddr)) {
+               rc = vmaddr;
+               goto out_up;
+       }
+       if (fixup_user_fault(current, gmap->mm, vmaddr, fault_flags,
+                            &unlocked)) {
+               rc = -EFAULT;
+               goto out_up;
+       }
+       /*
+        * In the case that fixup_user_fault unlocked the mmap_sem during
+        * faultin redo __gmap_translate to not race with a map/unmap_segment.
+        */
+       if (unlocked)
+               goto retry;
+
+       rc = __gmap_link(gmap, gaddr, vmaddr);
+out_up:
+       up_read(&gmap->mm->mmap_sem);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(gmap_fault);
+
+/*
+ * this function is assumed to be called with mmap_sem held
+ */
+void __gmap_zap(struct gmap *gmap, unsigned long gaddr)
+{
+       unsigned long vmaddr;
+       spinlock_t *ptl;
+       pte_t *ptep;
+
+       /* Find the vm address for the guest address */
+       vmaddr = (unsigned long) radix_tree_lookup(&gmap->guest_to_host,
+                                                  gaddr >> PMD_SHIFT);
+       if (vmaddr) {
+               vmaddr |= gaddr & ~PMD_MASK;
+               /* Get pointer to the page table entry */
+               ptep = get_locked_pte(gmap->mm, vmaddr, &ptl);
+               if (likely(ptep))
+                       ptep_zap_unused(gmap->mm, vmaddr, ptep, 0);
+               pte_unmap_unlock(ptep, ptl);
+       }
+}
+EXPORT_SYMBOL_GPL(__gmap_zap);
+
+void gmap_discard(struct gmap *gmap, unsigned long from, unsigned long to)
+{
+       unsigned long gaddr, vmaddr, size;
+       struct vm_area_struct *vma;
+
+       down_read(&gmap->mm->mmap_sem);
+       for (gaddr = from; gaddr < to;
+            gaddr = (gaddr + PMD_SIZE) & PMD_MASK) {
+               /* Find the vm address for the guest address */
+               vmaddr = (unsigned long)
+                       radix_tree_lookup(&gmap->guest_to_host,
+                                         gaddr >> PMD_SHIFT);
+               if (!vmaddr)
+                       continue;
+               vmaddr |= gaddr & ~PMD_MASK;
+               /* Find vma in the parent mm */
+               vma = find_vma(gmap->mm, vmaddr);
+               size = min(to - gaddr, PMD_SIZE - (gaddr & ~PMD_MASK));
+               zap_page_range(vma, vmaddr, size, NULL);
+       }
+       up_read(&gmap->mm->mmap_sem);
+}
+EXPORT_SYMBOL_GPL(gmap_discard);
+
+static LIST_HEAD(gmap_notifier_list);
+static DEFINE_SPINLOCK(gmap_notifier_lock);
+
+/**
+ * gmap_register_ipte_notifier - register a pte invalidation callback
+ * @nb: pointer to the gmap notifier block
+ */
+void gmap_register_ipte_notifier(struct gmap_notifier *nb)
+{
+       spin_lock(&gmap_notifier_lock);
+       list_add(&nb->list, &gmap_notifier_list);
+       spin_unlock(&gmap_notifier_lock);
+}
+EXPORT_SYMBOL_GPL(gmap_register_ipte_notifier);
+
+/**
+ * gmap_unregister_ipte_notifier - remove a pte invalidation callback
+ * @nb: pointer to the gmap notifier block
+ */
+void gmap_unregister_ipte_notifier(struct gmap_notifier *nb)
+{
+       spin_lock(&gmap_notifier_lock);
+       list_del_init(&nb->list);
+       spin_unlock(&gmap_notifier_lock);
+}
+EXPORT_SYMBOL_GPL(gmap_unregister_ipte_notifier);
+
+/**
+ * gmap_ipte_notify - mark a range of ptes for invalidation notification
+ * @gmap: pointer to guest mapping meta data structure
+ * @gaddr: virtual address in the guest address space
+ * @len: size of area
+ *
+ * Returns 0 if for each page in the given range a gmap mapping exists and
+ * the invalidation notification could be set. If the gmap mapping is missing
+ * for one or more pages -EFAULT is returned. If no memory could be allocated
+ * -ENOMEM is returned. This function establishes missing page table entries.
+ */
+int gmap_ipte_notify(struct gmap *gmap, unsigned long gaddr, unsigned long len)
+{
+       unsigned long addr;
+       spinlock_t *ptl;
+       pte_t *ptep;
+       bool unlocked;
+       int rc = 0;
+
+       if ((gaddr & ~PAGE_MASK) || (len & ~PAGE_MASK))
+               return -EINVAL;
+       down_read(&gmap->mm->mmap_sem);
+       while (len) {
+               unlocked = false;
+               /* Convert gmap address and connect the page tables */
+               addr = __gmap_translate(gmap, gaddr);
+               if (IS_ERR_VALUE(addr)) {
+                       rc = addr;
+                       break;
+               }
+               /* Get the page mapped */
+               if (fixup_user_fault(current, gmap->mm, addr, FAULT_FLAG_WRITE,
+                                    &unlocked)) {
+                       rc = -EFAULT;
+                       break;
+               }
+               /* While trying to map mmap_sem got unlocked. Let us retry */
+               if (unlocked)
+                       continue;
+               rc = __gmap_link(gmap, gaddr, addr);
+               if (rc)
+                       break;
+               /* Walk the process page table, lock and get pte pointer */
+               ptep = get_locked_pte(gmap->mm, addr, &ptl);
+               VM_BUG_ON(!ptep);
+               /* Set notification bit in the pgste of the pte */
+               if ((pte_val(*ptep) & (_PAGE_INVALID | _PAGE_PROTECT)) == 0) {
+                       ptep_set_notify(gmap->mm, addr, ptep);
+                       gaddr += PAGE_SIZE;
+                       len -= PAGE_SIZE;
+               }
+               pte_unmap_unlock(ptep, ptl);
+       }
+       up_read(&gmap->mm->mmap_sem);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(gmap_ipte_notify);
+
+/**
+ * ptep_notify - call all invalidation callbacks for a specific pte.
+ * @mm: pointer to the process mm_struct
+ * @addr: virtual address in the process address space
+ * @pte: pointer to the page table entry
+ *
+ * This function is assumed to be called with the page table lock held
+ * for the pte to notify.
+ */
+void ptep_notify(struct mm_struct *mm, unsigned long vmaddr, pte_t *pte)
+{
+       unsigned long offset, gaddr;
+       unsigned long *table;
+       struct gmap_notifier *nb;
+       struct gmap *gmap;
+
+       offset = ((unsigned long) pte) & (255 * sizeof(pte_t));
+       offset = offset * (4096 / sizeof(pte_t));
+       spin_lock(&gmap_notifier_lock);
+       list_for_each_entry(gmap, &mm->context.gmap_list, list) {
+               table = radix_tree_lookup(&gmap->host_to_guest,
+                                         vmaddr >> PMD_SHIFT);
+               if (!table)
+                       continue;
+               gaddr = __gmap_segment_gaddr(table) + offset;
+               list_for_each_entry(nb, &gmap_notifier_list, list)
+                       nb->notifier_call(gmap, gaddr);
+       }
+       spin_unlock(&gmap_notifier_lock);
+}
+EXPORT_SYMBOL_GPL(ptep_notify);
+
+static inline void thp_split_mm(struct mm_struct *mm)
+{
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+       struct vm_area_struct *vma;
+       unsigned long addr;
+
+       for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
+               for (addr = vma->vm_start;
+                    addr < vma->vm_end;
+                    addr += PAGE_SIZE)
+                       follow_page(vma, addr, FOLL_SPLIT);
+               vma->vm_flags &= ~VM_HUGEPAGE;
+               vma->vm_flags |= VM_NOHUGEPAGE;
+       }
+       mm->def_flags |= VM_NOHUGEPAGE;
+#endif
+}
+
+/*
+ * switch on pgstes for its userspace process (for kvm)
+ */
+int s390_enable_sie(void)
+{
+       struct mm_struct *mm = current->mm;
+
+       /* Do we have pgstes? if yes, we are done */
+       if (mm_has_pgste(mm))
+               return 0;
+       /* Fail if the page tables are 2K */
+       if (!mm_alloc_pgste(mm))
+               return -EINVAL;
+       down_write(&mm->mmap_sem);
+       mm->context.has_pgste = 1;
+       /* split thp mappings and disable thp for future mappings */
+       thp_split_mm(mm);
+       up_write(&mm->mmap_sem);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(s390_enable_sie);
+
+/*
+ * Enable storage key handling from now on and initialize the storage
+ * keys with the default key.
+ */
+static int __s390_enable_skey(pte_t *pte, unsigned long addr,
+                             unsigned long next, struct mm_walk *walk)
+{
+       /*
+        * Remove all zero page mappings,
+        * after establishing a policy to forbid zero page mappings
+        * following faults for that page will get fresh anonymous pages
+        */
+       if (is_zero_pfn(pte_pfn(*pte)))
+               ptep_xchg_direct(walk->mm, addr, pte, __pte(_PAGE_INVALID));
+       /* Clear storage key */
+       ptep_zap_key(walk->mm, addr, pte);
+       return 0;
+}
+
+int s390_enable_skey(void)
+{
+       struct mm_walk walk = { .pte_entry = __s390_enable_skey };
+       struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma;
+       int rc = 0;
+
+       down_write(&mm->mmap_sem);
+       if (mm_use_skey(mm))
+               goto out_up;
+
+       mm->context.use_skey = 1;
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
+                               MADV_UNMERGEABLE, &vma->vm_flags)) {
+                       mm->context.use_skey = 0;
+                       rc = -ENOMEM;
+                       goto out_up;
+               }
+       }
+       mm->def_flags &= ~VM_MERGEABLE;
+
+       walk.mm = mm;
+       walk_page_range(0, TASK_SIZE, &walk);
+
+out_up:
+       up_write(&mm->mmap_sem);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(s390_enable_skey);
+
+/*
+ * Reset CMMA state, make all pages stable again.
+ */
+static int __s390_reset_cmma(pte_t *pte, unsigned long addr,
+                            unsigned long next, struct mm_walk *walk)
+{
+       ptep_zap_unused(walk->mm, addr, pte, 1);
+       return 0;
+}
+
+void s390_reset_cmma(struct mm_struct *mm)
+{
+       struct mm_walk walk = { .pte_entry = __s390_reset_cmma };
+
+       down_write(&mm->mmap_sem);
+       walk.mm = mm;
+       walk_page_range(0, TASK_SIZE, &walk);
+       up_write(&mm->mmap_sem);
+}
+EXPORT_SYMBOL_GPL(s390_reset_cmma);
index f81096b6940d7bd5532b1eced955d5543eb90228..1b5e8983f4f3840f5487caf50031a4bb7593fc8c 100644 (file)
@@ -105,11 +105,10 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
                              unsigned long addr, pte_t *ptep)
 {
        pmd_t *pmdp = (pmd_t *) ptep;
-       pte_t pte = huge_ptep_get(ptep);
+       pmd_t old;
 
-       pmdp_flush_direct(mm, addr, pmdp);
-       pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY;
-       return pte;
+       old = pmdp_xchg_direct(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY));
+       return __pmd_to_pte(old);
 }
 
 pte_t *huge_pte_alloc(struct mm_struct *mm,
index 749c98407b41f02e37e1aec174dcc2ca51674a35..f2a5c29a97e9f455fba6cc81bad7399a80354594 100644 (file)
@@ -65,19 +65,17 @@ static pte_t *walk_page_table(unsigned long addr)
 static void change_page_attr(unsigned long addr, int numpages,
                             pte_t (*set) (pte_t))
 {
-       pte_t *ptep, pte;
+       pte_t *ptep;
        int i;
 
        for (i = 0; i < numpages; i++) {
                ptep = walk_page_table(addr);
                if (WARN_ON_ONCE(!ptep))
                        break;
-               pte = *ptep;
-               pte = set(pte);
-               __ptep_ipte(addr, ptep);
-               *ptep = pte;
+               *ptep = set(*ptep);
                addr += PAGE_SIZE;
        }
+       __tlb_flush_kernel();
 }
 
 int set_memory_ro(unsigned long addr, int numpages)
diff --git a/arch/s390/mm/pgalloc.c b/arch/s390/mm/pgalloc.c
new file mode 100644 (file)
index 0000000..f6c3de2
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ *  Page table allocation functions
+ *
+ *    Copyright IBM Corp. 2016
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/gmap.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+#ifdef CONFIG_PGSTE
+
+static int page_table_allocate_pgste_min = 0;
+static int page_table_allocate_pgste_max = 1;
+int page_table_allocate_pgste = 0;
+EXPORT_SYMBOL(page_table_allocate_pgste);
+
+static struct ctl_table page_table_sysctl[] = {
+       {
+               .procname       = "allocate_pgste",
+               .data           = &page_table_allocate_pgste,
+               .maxlen         = sizeof(int),
+               .mode           = S_IRUGO | S_IWUSR,
+               .proc_handler   = proc_dointvec,
+               .extra1         = &page_table_allocate_pgste_min,
+               .extra2         = &page_table_allocate_pgste_max,
+       },
+       { }
+};
+
+static struct ctl_table page_table_sysctl_dir[] = {
+       {
+               .procname       = "vm",
+               .maxlen         = 0,
+               .mode           = 0555,
+               .child          = page_table_sysctl,
+       },
+       { }
+};
+
+static int __init page_table_register_sysctl(void)
+{
+       return register_sysctl_table(page_table_sysctl_dir) ? 0 : -ENOMEM;
+}
+__initcall(page_table_register_sysctl);
+
+#endif /* CONFIG_PGSTE */
+
+unsigned long *crst_table_alloc(struct mm_struct *mm)
+{
+       struct page *page = alloc_pages(GFP_KERNEL, 2);
+
+       if (!page)
+               return NULL;
+       return (unsigned long *) page_to_phys(page);
+}
+
+void crst_table_free(struct mm_struct *mm, unsigned long *table)
+{
+       free_pages((unsigned long) table, 2);
+}
+
+static void __crst_table_upgrade(void *arg)
+{
+       struct mm_struct *mm = arg;
+
+       if (current->active_mm == mm) {
+               clear_user_asce();
+               set_user_asce(mm);
+       }
+       __tlb_flush_local();
+}
+
+int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
+{
+       unsigned long *table, *pgd;
+       unsigned long entry;
+       int flush;
+
+       BUG_ON(limit > TASK_MAX_SIZE);
+       flush = 0;
+repeat:
+       table = crst_table_alloc(mm);
+       if (!table)
+               return -ENOMEM;
+       spin_lock_bh(&mm->page_table_lock);
+       if (mm->context.asce_limit < limit) {
+               pgd = (unsigned long *) mm->pgd;
+               if (mm->context.asce_limit <= (1UL << 31)) {
+                       entry = _REGION3_ENTRY_EMPTY;
+                       mm->context.asce_limit = 1UL << 42;
+                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                                               _ASCE_USER_BITS |
+                                               _ASCE_TYPE_REGION3;
+               } else {
+                       entry = _REGION2_ENTRY_EMPTY;
+                       mm->context.asce_limit = 1UL << 53;
+                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                                               _ASCE_USER_BITS |
+                                               _ASCE_TYPE_REGION2;
+               }
+               crst_table_init(table, entry);
+               pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
+               mm->pgd = (pgd_t *) table;
+               mm->task_size = mm->context.asce_limit;
+               table = NULL;
+               flush = 1;
+       }
+       spin_unlock_bh(&mm->page_table_lock);
+       if (table)
+               crst_table_free(mm, table);
+       if (mm->context.asce_limit < limit)
+               goto repeat;
+       if (flush)
+               on_each_cpu(__crst_table_upgrade, mm, 0);
+       return 0;
+}
+
+void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
+{
+       pgd_t *pgd;
+
+       if (current->active_mm == mm) {
+               clear_user_asce();
+               __tlb_flush_mm(mm);
+       }
+       while (mm->context.asce_limit > limit) {
+               pgd = mm->pgd;
+               switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
+               case _REGION_ENTRY_TYPE_R2:
+                       mm->context.asce_limit = 1UL << 42;
+                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                                               _ASCE_USER_BITS |
+                                               _ASCE_TYPE_REGION3;
+                       break;
+               case _REGION_ENTRY_TYPE_R3:
+                       mm->context.asce_limit = 1UL << 31;
+                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                                               _ASCE_USER_BITS |
+                                               _ASCE_TYPE_SEGMENT;
+                       break;
+               default:
+                       BUG();
+               }
+               mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
+               mm->task_size = mm->context.asce_limit;
+               crst_table_free(mm, (unsigned long *) pgd);
+       }
+       if (current->active_mm == mm)
+               set_user_asce(mm);
+}
+
+static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
+{
+       unsigned int old, new;
+
+       do {
+               old = atomic_read(v);
+               new = old ^ bits;
+       } while (atomic_cmpxchg(v, old, new) != old);
+       return new;
+}
+
+/*
+ * page table entry allocation/free routines.
+ */
+unsigned long *page_table_alloc(struct mm_struct *mm)
+{
+       unsigned long *table;
+       struct page *page;
+       unsigned int mask, bit;
+
+       /* Try to get a fragment of a 4K page as a 2K page table */
+       if (!mm_alloc_pgste(mm)) {
+               table = NULL;
+               spin_lock_bh(&mm->context.list_lock);
+               if (!list_empty(&mm->context.pgtable_list)) {
+                       page = list_first_entry(&mm->context.pgtable_list,
+                                               struct page, lru);
+                       mask = atomic_read(&page->_mapcount);
+                       mask = (mask | (mask >> 4)) & 3;
+                       if (mask != 3) {
+                               table = (unsigned long *) page_to_phys(page);
+                               bit = mask & 1;         /* =1 -> second 2K */
+                               if (bit)
+                                       table += PTRS_PER_PTE;
+                               atomic_xor_bits(&page->_mapcount, 1U << bit);
+                               list_del(&page->lru);
+                       }
+               }
+               spin_unlock_bh(&mm->context.list_lock);
+               if (table)
+                       return table;
+       }
+       /* Allocate a fresh page */
+       page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
+       if (!page)
+               return NULL;
+       if (!pgtable_page_ctor(page)) {
+               __free_page(page);
+               return NULL;
+       }
+       /* Initialize page table */
+       table = (unsigned long *) page_to_phys(page);
+       if (mm_alloc_pgste(mm)) {
+               /* Return 4K page table with PGSTEs */
+               atomic_set(&page->_mapcount, 3);
+               clear_table(table, _PAGE_INVALID, PAGE_SIZE/2);
+               clear_table(table + PTRS_PER_PTE, 0, PAGE_SIZE/2);
+       } else {
+               /* Return the first 2K fragment of the page */
+               atomic_set(&page->_mapcount, 1);
+               clear_table(table, _PAGE_INVALID, PAGE_SIZE);
+               spin_lock_bh(&mm->context.list_lock);
+               list_add(&page->lru, &mm->context.pgtable_list);
+               spin_unlock_bh(&mm->context.list_lock);
+       }
+       return table;
+}
+
+void page_table_free(struct mm_struct *mm, unsigned long *table)
+{
+       struct page *page;
+       unsigned int bit, mask;
+
+       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       if (!mm_alloc_pgste(mm)) {
+               /* Free 2K page table fragment of a 4K page */
+               bit = (__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
+               spin_lock_bh(&mm->context.list_lock);
+               mask = atomic_xor_bits(&page->_mapcount, 1U << bit);
+               if (mask & 3)
+                       list_add(&page->lru, &mm->context.pgtable_list);
+               else
+                       list_del(&page->lru);
+               spin_unlock_bh(&mm->context.list_lock);
+               if (mask != 0)
+                       return;
+       }
+
+       pgtable_page_dtor(page);
+       atomic_set(&page->_mapcount, -1);
+       __free_page(page);
+}
+
+void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
+                        unsigned long vmaddr)
+{
+       struct mm_struct *mm;
+       struct page *page;
+       unsigned int bit, mask;
+
+       mm = tlb->mm;
+       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       if (mm_alloc_pgste(mm)) {
+               gmap_unlink(mm, table, vmaddr);
+               table = (unsigned long *) (__pa(table) | 3);
+               tlb_remove_table(tlb, table);
+               return;
+       }
+       bit = (__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t));
+       spin_lock_bh(&mm->context.list_lock);
+       mask = atomic_xor_bits(&page->_mapcount, 0x11U << bit);
+       if (mask & 3)
+               list_add_tail(&page->lru, &mm->context.pgtable_list);
+       else
+               list_del(&page->lru);
+       spin_unlock_bh(&mm->context.list_lock);
+       table = (unsigned long *) (__pa(table) | (1U << bit));
+       tlb_remove_table(tlb, table);
+}
+
+static void __tlb_remove_table(void *_table)
+{
+       unsigned int mask = (unsigned long) _table & 3;
+       void *table = (void *)((unsigned long) _table ^ mask);
+       struct page *page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+
+       switch (mask) {
+       case 0:         /* pmd or pud */
+               free_pages((unsigned long) table, 2);
+               break;
+       case 1:         /* lower 2K of a 4K page table */
+       case 2:         /* higher 2K of a 4K page table */
+               if (atomic_xor_bits(&page->_mapcount, mask << 4) != 0)
+                       break;
+               /* fallthrough */
+       case 3:         /* 4K page table with pgstes */
+               pgtable_page_dtor(page);
+               atomic_set(&page->_mapcount, -1);
+               __free_page(page);
+               break;
+       }
+}
+
+static void tlb_remove_table_smp_sync(void *arg)
+{
+       /* Simply deliver the interrupt */
+}
+
+static void tlb_remove_table_one(void *table)
+{
+       /*
+        * This isn't an RCU grace period and hence the page-tables cannot be
+        * assumed to be actually RCU-freed.
+        *
+        * It is however sufficient for software page-table walkers that rely
+        * on IRQ disabling. See the comment near struct mmu_table_batch.
+        */
+       smp_call_function(tlb_remove_table_smp_sync, NULL, 1);
+       __tlb_remove_table(table);
+}
+
+static void tlb_remove_table_rcu(struct rcu_head *head)
+{
+       struct mmu_table_batch *batch;
+       int i;
+
+       batch = container_of(head, struct mmu_table_batch, rcu);
+
+       for (i = 0; i < batch->nr; i++)
+               __tlb_remove_table(batch->tables[i]);
+
+       free_page((unsigned long)batch);
+}
+
+void tlb_table_flush(struct mmu_gather *tlb)
+{
+       struct mmu_table_batch **batch = &tlb->batch;
+
+       if (*batch) {
+               call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu);
+               *batch = NULL;
+       }
+}
+
+void tlb_remove_table(struct mmu_gather *tlb, void *table)
+{
+       struct mmu_table_batch **batch = &tlb->batch;
+
+       tlb->mm->context.flush_mm = 1;
+       if (*batch == NULL) {
+               *batch = (struct mmu_table_batch *)
+                       __get_free_page(GFP_NOWAIT | __GFP_NOWARN);
+               if (*batch == NULL) {
+                       __tlb_flush_mm_lazy(tlb->mm);
+                       tlb_remove_table_one(table);
+                       return;
+               }
+               (*batch)->nr = 0;
+       }
+       (*batch)->tables[(*batch)->nr++] = table;
+       if ((*batch)->nr == MAX_TABLE_BATCH)
+               tlb_flush_mmu(tlb);
+}
index 5109827883acaefc6afc0ac913956fcb79f8f8a0..4324b87f93982f08552ecb86bb9c893431507427 100644 (file)
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 
-unsigned long *crst_table_alloc(struct mm_struct *mm)
-{
-       struct page *page = alloc_pages(GFP_KERNEL, 2);
-
-       if (!page)
-               return NULL;
-       return (unsigned long *) page_to_phys(page);
+static inline pte_t ptep_flush_direct(struct mm_struct *mm,
+                                     unsigned long addr, pte_t *ptep)
+{
+       int active, count;
+       pte_t old;
+
+       old = *ptep;
+       if (unlikely(pte_val(old) & _PAGE_INVALID))
+               return old;
+       active = (mm == current->active_mm) ? 1 : 0;
+       count = atomic_add_return(0x10000, &mm->context.attach_count);
+       if (MACHINE_HAS_TLB_LC && (count & 0xffff) <= active &&
+           cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
+               __ptep_ipte_local(addr, ptep);
+       else
+               __ptep_ipte(addr, ptep);
+       atomic_sub(0x10000, &mm->context.attach_count);
+       return old;
 }
 
-void crst_table_free(struct mm_struct *mm, unsigned long *table)
+static inline pte_t ptep_flush_lazy(struct mm_struct *mm,
+                                   unsigned long addr, pte_t *ptep)
 {
-       free_pages((unsigned long) table, 2);
+       int active, count;
+       pte_t old;
+
+       old = *ptep;
+       if (unlikely(pte_val(old) & _PAGE_INVALID))
+               return old;
+       active = (mm == current->active_mm) ? 1 : 0;
+       count = atomic_add_return(0x10000, &mm->context.attach_count);
+       if ((count & 0xffff) <= active) {
+               pte_val(*ptep) |= _PAGE_INVALID;
+               mm->context.flush_mm = 1;
+       } else
+               __ptep_ipte(addr, ptep);
+       atomic_sub(0x10000, &mm->context.attach_count);
+       return old;
 }
 
-static void __crst_table_upgrade(void *arg)
+static inline pgste_t pgste_get_lock(pte_t *ptep)
 {
-       struct mm_struct *mm = arg;
+       unsigned long new = 0;
+#ifdef CONFIG_PGSTE
+       unsigned long old;
 
-       if (current->active_mm == mm) {
-               clear_user_asce();
-               set_user_asce(mm);
-       }
-       __tlb_flush_local();
+       preempt_disable();
+       asm(
+               "       lg      %0,%2\n"
+               "0:     lgr     %1,%0\n"
+               "       nihh    %0,0xff7f\n"    /* clear PCL bit in old */
+               "       oihh    %1,0x0080\n"    /* set PCL bit in new */
+               "       csg     %0,%1,%2\n"
+               "       jl      0b\n"
+               : "=&d" (old), "=&d" (new), "=Q" (ptep[PTRS_PER_PTE])
+               : "Q" (ptep[PTRS_PER_PTE]) : "cc", "memory");
+#endif
+       return __pgste(new);
 }
 
-int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
+static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste)
 {
-       unsigned long *table, *pgd;
-       unsigned long entry;
-       int flush;
-
-       BUG_ON(limit > TASK_MAX_SIZE);
-       flush = 0;
-repeat:
-       table = crst_table_alloc(mm);
-       if (!table)
-               return -ENOMEM;
-       spin_lock_bh(&mm->page_table_lock);
-       if (mm->context.asce_limit < limit) {
-               pgd = (unsigned long *) mm->pgd;
-               if (mm->context.asce_limit <= (1UL << 31)) {
-                       entry = _REGION3_ENTRY_EMPTY;
-                       mm->context.asce_limit = 1UL << 42;
-                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-                                               _ASCE_USER_BITS |
-                                               _ASCE_TYPE_REGION3;
-               } else {
-                       entry = _REGION2_ENTRY_EMPTY;
-                       mm->context.asce_limit = 1UL << 53;
-                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-                                               _ASCE_USER_BITS |
-                                               _ASCE_TYPE_REGION2;
-               }
-               crst_table_init(table, entry);
-               pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
-               mm->pgd = (pgd_t *) table;
-               mm->task_size = mm->context.asce_limit;
-               table = NULL;
-               flush = 1;
-       }
-       spin_unlock_bh(&mm->page_table_lock);
-       if (table)
-               crst_table_free(mm, table);
-       if (mm->context.asce_limit < limit)
-               goto repeat;
-       if (flush)
-               on_each_cpu(__crst_table_upgrade, mm, 0);
-       return 0;
+#ifdef CONFIG_PGSTE
+       asm(
+               "       nihh    %1,0xff7f\n"    /* clear PCL bit */
+               "       stg     %1,%0\n"
+               : "=Q" (ptep[PTRS_PER_PTE])
+               : "d" (pgste_val(pgste)), "Q" (ptep[PTRS_PER_PTE])
+               : "cc", "memory");
+       preempt_enable();
+#endif
 }
 
-void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
+static inline pgste_t pgste_get(pte_t *ptep)
 {
-       pgd_t *pgd;
-
-       if (current->active_mm == mm) {
-               clear_user_asce();
-               __tlb_flush_mm(mm);
-       }
-       while (mm->context.asce_limit > limit) {
-               pgd = mm->pgd;
-               switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
-               case _REGION_ENTRY_TYPE_R2:
-                       mm->context.asce_limit = 1UL << 42;
-                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-                                               _ASCE_USER_BITS |
-                                               _ASCE_TYPE_REGION3;
-                       break;
-               case _REGION_ENTRY_TYPE_R3:
-                       mm->context.asce_limit = 1UL << 31;
-                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
-                                               _ASCE_USER_BITS |
-                                               _ASCE_TYPE_SEGMENT;
-                       break;
-               default:
-                       BUG();
-               }
-               mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
-               mm->task_size = mm->context.asce_limit;
-               crst_table_free(mm, (unsigned long *) pgd);
-       }
-       if (current->active_mm == mm)
-               set_user_asce(mm);
+       unsigned long pgste = 0;
+#ifdef CONFIG_PGSTE
+       pgste = *(unsigned long *)(ptep + PTRS_PER_PTE);
+#endif
+       return __pgste(pgste);
 }
 
+static inline void pgste_set(pte_t *ptep, pgste_t pgste)
+{
 #ifdef CONFIG_PGSTE
+       *(pgste_t *)(ptep + PTRS_PER_PTE) = pgste;
+#endif
+}
 
-/**
- * gmap_alloc - allocate a guest address space
- * @mm: pointer to the parent mm_struct
- * @limit: maximum address of the gmap address space
- *
- * Returns a guest address space structure.
- */
-struct gmap *gmap_alloc(struct mm_struct *mm, unsigned long limit)
+static inline pgste_t pgste_update_all(pte_t pte, pgste_t pgste,
+                                      struct mm_struct *mm)
 {
-       struct gmap *gmap;
-       struct page *page;
-       unsigned long *table;
-       unsigned long etype, atype;
-
-       if (limit < (1UL << 31)) {
-               limit = (1UL << 31) - 1;
-               atype = _ASCE_TYPE_SEGMENT;
-               etype = _SEGMENT_ENTRY_EMPTY;
-       } else if (limit < (1UL << 42)) {
-               limit = (1UL << 42) - 1;
-               atype = _ASCE_TYPE_REGION3;
-               etype = _REGION3_ENTRY_EMPTY;
-       } else if (limit < (1UL << 53)) {
-               limit = (1UL << 53) - 1;
-               atype = _ASCE_TYPE_REGION2;
-               etype = _REGION2_ENTRY_EMPTY;
-       } else {
-               limit = -1UL;
-               atype = _ASCE_TYPE_REGION1;
-               etype = _REGION1_ENTRY_EMPTY;
-       }
-       gmap = kzalloc(sizeof(struct gmap), GFP_KERNEL);
-       if (!gmap)
-               goto out;
-       INIT_LIST_HEAD(&gmap->crst_list);
-       INIT_RADIX_TREE(&gmap->guest_to_host, GFP_KERNEL);
-       INIT_RADIX_TREE(&gmap->host_to_guest, GFP_ATOMIC);
-       spin_lock_init(&gmap->guest_table_lock);
-       gmap->mm = mm;
-       page = alloc_pages(GFP_KERNEL, 2);
-       if (!page)
-               goto out_free;
-       page->index = 0;
-       list_add(&page->lru, &gmap->crst_list);
-       table = (unsigned long *) page_to_phys(page);
-       crst_table_init(table, etype);
-       gmap->table = table;
-       gmap->asce = atype | _ASCE_TABLE_LENGTH |
-               _ASCE_USER_BITS | __pa(table);
-       gmap->asce_end = limit;
-       down_write(&mm->mmap_sem);
-       list_add(&gmap->list, &mm->context.gmap_list);
-       up_write(&mm->mmap_sem);
-       return gmap;
-
-out_free:
-       kfree(gmap);
-out:
-       return NULL;
+#ifdef CONFIG_PGSTE
+       unsigned long address, bits, skey;
+
+       if (!mm_use_skey(mm) || pte_val(pte) & _PAGE_INVALID)
+               return pgste;
+       address = pte_val(pte) & PAGE_MASK;
+       skey = (unsigned long) page_get_storage_key(address);
+       bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
+       /* Transfer page changed & referenced bit to guest bits in pgste */
+       pgste_val(pgste) |= bits << 48;         /* GR bit & GC bit */
+       /* Copy page access key and fetch protection bit to pgste */
+       pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT);
+       pgste_val(pgste) |= (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56;
+#endif
+       return pgste;
+
 }
-EXPORT_SYMBOL_GPL(gmap_alloc);
 
-static void gmap_flush_tlb(struct gmap *gmap)
+static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry,
+                                struct mm_struct *mm)
 {
-       if (MACHINE_HAS_IDTE)
-               __tlb_flush_asce(gmap->mm, gmap->asce);
-       else
-               __tlb_flush_global();
+#ifdef CONFIG_PGSTE
+       unsigned long address;
+       unsigned long nkey;
+
+       if (!mm_use_skey(mm) || pte_val(entry) & _PAGE_INVALID)
+               return;
+       VM_BUG_ON(!(pte_val(*ptep) & _PAGE_INVALID));
+       address = pte_val(entry) & PAGE_MASK;
+       /*
+        * Set page access key and fetch protection bit from pgste.
+        * The guest C/R information is still in the PGSTE, set real
+        * key C/R to 0.
+        */
+       nkey = (pgste_val(pgste) & (PGSTE_ACC_BITS | PGSTE_FP_BIT)) >> 56;
+       nkey |= (pgste_val(pgste) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 48;
+       page_set_storage_key(address, nkey, 0);
+#endif
 }
 
-static void gmap_radix_tree_free(struct radix_tree_root *root)
+static inline pgste_t pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
 {
-       struct radix_tree_iter iter;
-       unsigned long indices[16];
-       unsigned long index;
-       void **slot;
-       int i, nr;
-
-       /* A radix tree is freed by deleting all of its entries */
-       index = 0;
-       do {
-               nr = 0;
-               radix_tree_for_each_slot(slot, root, &iter, index) {
-                       indices[nr] = iter.index;
-                       if (++nr == 16)
-                               break;
-               }
-               for (i = 0; i < nr; i++) {
-                       index = indices[i];
-                       radix_tree_delete(root, index);
+#ifdef CONFIG_PGSTE
+       if ((pte_val(entry) & _PAGE_PRESENT) &&
+           (pte_val(entry) & _PAGE_WRITE) &&
+           !(pte_val(entry) & _PAGE_INVALID)) {
+               if (!MACHINE_HAS_ESOP) {
+                       /*
+                        * Without enhanced suppression-on-protection force
+                        * the dirty bit on for all writable ptes.
+                        */
+                       pte_val(entry) |= _PAGE_DIRTY;
+                       pte_val(entry) &= ~_PAGE_PROTECT;
                }
-       } while (nr > 0);
+               if (!(pte_val(entry) & _PAGE_PROTECT))
+                       /* This pte allows write access, set user-dirty */
+                       pgste_val(pgste) |= PGSTE_UC_BIT;
+       }
+#endif
+       *ptep = entry;
+       return pgste;
 }
 
-/**
- * gmap_free - free a guest address space
- * @gmap: pointer to the guest address space structure
- */
-void gmap_free(struct gmap *gmap)
+static inline pgste_t pgste_ipte_notify(struct mm_struct *mm,
+                                       unsigned long addr,
+                                       pte_t *ptep, pgste_t pgste)
 {
-       struct page *page, *next;
-
-       /* Flush tlb. */
-       if (MACHINE_HAS_IDTE)
-               __tlb_flush_asce(gmap->mm, gmap->asce);
-       else
-               __tlb_flush_global();
-
-       /* Free all segment & region tables. */
-       list_for_each_entry_safe(page, next, &gmap->crst_list, lru)
-               __free_pages(page, 2);
-       gmap_radix_tree_free(&gmap->guest_to_host);
-       gmap_radix_tree_free(&gmap->host_to_guest);
-       down_write(&gmap->mm->mmap_sem);
-       list_del(&gmap->list);
-       up_write(&gmap->mm->mmap_sem);
-       kfree(gmap);
+#ifdef CONFIG_PGSTE
+       if (pgste_val(pgste) & PGSTE_IN_BIT) {
+               pgste_val(pgste) &= ~PGSTE_IN_BIT;
+               ptep_notify(mm, addr, ptep);
+       }
+#endif
+       return pgste;
 }
-EXPORT_SYMBOL_GPL(gmap_free);
 
-/**
- * gmap_enable - switch primary space to the guest address space
- * @gmap: pointer to the guest address space structure
- */
-void gmap_enable(struct gmap *gmap)
+static inline pgste_t ptep_xchg_start(struct mm_struct *mm,
+                                     unsigned long addr, pte_t *ptep)
 {
-       S390_lowcore.gmap = (unsigned long) gmap;
+       pgste_t pgste = __pgste(0);
+
+       if (mm_has_pgste(mm)) {
+               pgste = pgste_get_lock(ptep);
+               pgste = pgste_ipte_notify(mm, addr, ptep, pgste);
+       }
+       return pgste;
 }
-EXPORT_SYMBOL_GPL(gmap_enable);
 
-/**
- * gmap_disable - switch back to the standard primary address space
- * @gmap: pointer to the guest address space structure
- */
-void gmap_disable(struct gmap *gmap)
+static inline void ptep_xchg_commit(struct mm_struct *mm,
+                                   unsigned long addr, pte_t *ptep,
+                                   pgste_t pgste, pte_t old, pte_t new)
 {
-       S390_lowcore.gmap = 0UL;
+       if (mm_has_pgste(mm)) {
+               if (pte_val(old) & _PAGE_INVALID)
+                       pgste_set_key(ptep, pgste, new, mm);
+               if (pte_val(new) & _PAGE_INVALID) {
+                       pgste = pgste_update_all(old, pgste, mm);
+                       if ((pgste_val(pgste) & _PGSTE_GPS_USAGE_MASK) ==
+                           _PGSTE_GPS_USAGE_UNUSED)
+                               pte_val(old) |= _PAGE_UNUSED;
+               }
+               pgste = pgste_set_pte(ptep, pgste, new);
+               pgste_set_unlock(ptep, pgste);
+       } else {
+               *ptep = new;
+       }
 }
-EXPORT_SYMBOL_GPL(gmap_disable);
 
-/*
- * gmap_alloc_table is assumed to be called with mmap_sem held
- */
-static int gmap_alloc_table(struct gmap *gmap, unsigned long *table,
-                           unsigned long init, unsigned long gaddr)
+pte_t ptep_xchg_direct(struct mm_struct *mm, unsigned long addr,
+                      pte_t *ptep, pte_t new)
 {
-       struct page *page;
-       unsigned long *new;
-
-       /* since we dont free the gmap table until gmap_free we can unlock */
-       page = alloc_pages(GFP_KERNEL, 2);
-       if (!page)
-               return -ENOMEM;
-       new = (unsigned long *) page_to_phys(page);
-       crst_table_init(new, init);
-       spin_lock(&gmap->mm->page_table_lock);
-       if (*table & _REGION_ENTRY_INVALID) {
-               list_add(&page->lru, &gmap->crst_list);
-               *table = (unsigned long) new | _REGION_ENTRY_LENGTH |
-                       (*table & _REGION_ENTRY_TYPE_MASK);
-               page->index = gaddr;
-               page = NULL;
-       }
-       spin_unlock(&gmap->mm->page_table_lock);
-       if (page)
-               __free_pages(page, 2);
-       return 0;
+       pgste_t pgste;
+       pte_t old;
+
+       pgste = ptep_xchg_start(mm, addr, ptep);
+       old = ptep_flush_direct(mm, addr, ptep);
+       ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
+       return old;
 }
+EXPORT_SYMBOL(ptep_xchg_direct);
 
-/**
- * __gmap_segment_gaddr - find virtual address from segment pointer
- * @entry: pointer to a segment table entry in the guest address space
- *
- * Returns the virtual address in the guest address space for the segment
- */
-static unsigned long __gmap_segment_gaddr(unsigned long *entry)
+pte_t ptep_xchg_lazy(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, pte_t new)
 {
-       struct page *page;
-       unsigned long offset, mask;
-
-       offset = (unsigned long) entry / sizeof(unsigned long);
-       offset = (offset & (PTRS_PER_PMD - 1)) * PMD_SIZE;
-       mask = ~(PTRS_PER_PMD * sizeof(pmd_t) - 1);
-       page = virt_to_page((void *)((unsigned long) entry & mask));
-       return page->index + offset;
+       pgste_t pgste;
+       pte_t old;
+
+       pgste = ptep_xchg_start(mm, addr, ptep);
+       old = ptep_flush_lazy(mm, addr, ptep);
+       ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
+       return old;
 }
+EXPORT_SYMBOL(ptep_xchg_lazy);
 
-/**
- * __gmap_unlink_by_vmaddr - unlink a single segment via a host address
- * @gmap: pointer to the guest address space structure
- * @vmaddr: address in the host process address space
- *
- * Returns 1 if a TLB flush is required
- */
-static int __gmap_unlink_by_vmaddr(struct gmap *gmap, unsigned long vmaddr)
+pte_t ptep_modify_prot_start(struct mm_struct *mm, unsigned long addr,
+                            pte_t *ptep)
 {
-       unsigned long *entry;
-       int flush = 0;
-
-       spin_lock(&gmap->guest_table_lock);
-       entry = radix_tree_delete(&gmap->host_to_guest, vmaddr >> PMD_SHIFT);
-       if (entry) {
-               flush = (*entry != _SEGMENT_ENTRY_INVALID);
-               *entry = _SEGMENT_ENTRY_INVALID;
+       pgste_t pgste;
+       pte_t old;
+
+       pgste = ptep_xchg_start(mm, addr, ptep);
+       old = ptep_flush_lazy(mm, addr, ptep);
+       if (mm_has_pgste(mm)) {
+               pgste = pgste_update_all(old, pgste, mm);
+               pgste_set(ptep, pgste);
        }
-       spin_unlock(&gmap->guest_table_lock);
-       return flush;
+       return old;
 }
+EXPORT_SYMBOL(ptep_modify_prot_start);
 
-/**
- * __gmap_unmap_by_gaddr - unmap a single segment via a guest address
- * @gmap: pointer to the guest address space structure
- * @gaddr: address in the guest address space
- *
- * Returns 1 if a TLB flush is required
- */
-static int __gmap_unmap_by_gaddr(struct gmap *gmap, unsigned long gaddr)
+void ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
+                            pte_t *ptep, pte_t pte)
 {
-       unsigned long vmaddr;
+       pgste_t pgste;
 
-       vmaddr = (unsigned long) radix_tree_delete(&gmap->guest_to_host,
-                                                  gaddr >> PMD_SHIFT);
-       return vmaddr ? __gmap_unlink_by_vmaddr(gmap, vmaddr) : 0;
+       if (mm_has_pgste(mm)) {
+               pgste = pgste_get(ptep);
+               pgste_set_key(ptep, pgste, pte, mm);
+               pgste = pgste_set_pte(ptep, pgste, pte);
+               pgste_set_unlock(ptep, pgste);
+       } else {
+               *ptep = pte;
+       }
 }
+EXPORT_SYMBOL(ptep_modify_prot_commit);
 
-/**
- * gmap_unmap_segment - unmap segment from the guest address space
- * @gmap: pointer to the guest address space structure
- * @to: address in the guest address space
- * @len: length of the memory area to unmap
- *
- * Returns 0 if the unmap succeeded, -EINVAL if not.
- */
-int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
+static inline pmd_t pmdp_flush_direct(struct mm_struct *mm,
+                                     unsigned long addr, pmd_t *pmdp)
 {
-       unsigned long off;
-       int flush;
-
-       if ((to | len) & (PMD_SIZE - 1))
-               return -EINVAL;
-       if (len == 0 || to + len < to)
-               return -EINVAL;
-
-       flush = 0;
-       down_write(&gmap->mm->mmap_sem);
-       for (off = 0; off < len; off += PMD_SIZE)
-               flush |= __gmap_unmap_by_gaddr(gmap, to + off);
-       up_write(&gmap->mm->mmap_sem);
-       if (flush)
-               gmap_flush_tlb(gmap);
-       return 0;
+       int active, count;
+       pmd_t old;
+
+       old = *pmdp;
+       if (pmd_val(old) & _SEGMENT_ENTRY_INVALID)
+               return old;
+       if (!MACHINE_HAS_IDTE) {
+               __pmdp_csp(pmdp);
+               return old;
+       }
+       active = (mm == current->active_mm) ? 1 : 0;
+       count = atomic_add_return(0x10000, &mm->context.attach_count);
+       if (MACHINE_HAS_TLB_LC && (count & 0xffff) <= active &&
+           cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id())))
+               __pmdp_idte_local(addr, pmdp);
+       else
+               __pmdp_idte(addr, pmdp);
+       atomic_sub(0x10000, &mm->context.attach_count);
+       return old;
+}
+
+static inline pmd_t pmdp_flush_lazy(struct mm_struct *mm,
+                                   unsigned long addr, pmd_t *pmdp)
+{
+       int active, count;
+       pmd_t old;
+
+       old = *pmdp;
+       if (pmd_val(old) & _SEGMENT_ENTRY_INVALID)
+               return old;
+       active = (mm == current->active_mm) ? 1 : 0;
+       count = atomic_add_return(0x10000, &mm->context.attach_count);
+       if ((count & 0xffff) <= active) {
+               pmd_val(*pmdp) |= _SEGMENT_ENTRY_INVALID;
+               mm->context.flush_mm = 1;
+       } else if (MACHINE_HAS_IDTE)
+               __pmdp_idte(addr, pmdp);
+       else
+               __pmdp_csp(pmdp);
+       atomic_sub(0x10000, &mm->context.attach_count);
+       return old;
 }
-EXPORT_SYMBOL_GPL(gmap_unmap_segment);
-
-/**
- * gmap_mmap_segment - map a segment to the guest address space
- * @gmap: pointer to the guest address space structure
- * @from: source address in the parent address space
- * @to: target address in the guest address space
- * @len: length of the memory area to map
- *
- * Returns 0 if the mmap succeeded, -EINVAL or -ENOMEM if not.
- */
-int gmap_map_segment(struct gmap *gmap, unsigned long from,
-                    unsigned long to, unsigned long len)
+
+pmd_t pmdp_xchg_direct(struct mm_struct *mm, unsigned long addr,
+                      pmd_t *pmdp, pmd_t new)
 {
-       unsigned long off;
-       int flush;
-
-       if ((from | to | len) & (PMD_SIZE - 1))
-               return -EINVAL;
-       if (len == 0 || from + len < from || to + len < to ||
-           from + len - 1 > TASK_MAX_SIZE || to + len - 1 > gmap->asce_end)
-               return -EINVAL;
-
-       flush = 0;
-       down_write(&gmap->mm->mmap_sem);
-       for (off = 0; off < len; off += PMD_SIZE) {
-               /* Remove old translation */
-               flush |= __gmap_unmap_by_gaddr(gmap, to + off);
-               /* Store new translation */
-               if (radix_tree_insert(&gmap->guest_to_host,
-                                     (to + off) >> PMD_SHIFT,
-                                     (void *) from + off))
-                       break;
-       }
-       up_write(&gmap->mm->mmap_sem);
-       if (flush)
-               gmap_flush_tlb(gmap);
-       if (off >= len)
-               return 0;
-       gmap_unmap_segment(gmap, to, len);
-       return -ENOMEM;
+       pmd_t old;
+
+       old = pmdp_flush_direct(mm, addr, pmdp);
+       *pmdp = new;
+       return old;
 }
-EXPORT_SYMBOL_GPL(gmap_map_segment);
-
-/**
- * __gmap_translate - translate a guest address to a user space address
- * @gmap: pointer to guest mapping meta data structure
- * @gaddr: guest address
- *
- * Returns user space address which corresponds to the guest address or
- * -EFAULT if no such mapping exists.
- * This function does not establish potentially missing page table entries.
- * The mmap_sem of the mm that belongs to the address space must be held
- * when this function gets called.
- */
-unsigned long __gmap_translate(struct gmap *gmap, unsigned long gaddr)
+EXPORT_SYMBOL(pmdp_xchg_direct);
+
+pmd_t pmdp_xchg_lazy(struct mm_struct *mm, unsigned long addr,
+                    pmd_t *pmdp, pmd_t new)
 {
-       unsigned long vmaddr;
+       pmd_t old;
 
-       vmaddr = (unsigned long)
-               radix_tree_lookup(&gmap->guest_to_host, gaddr >> PMD_SHIFT);
-       return vmaddr ? (vmaddr | (gaddr & ~PMD_MASK)) : -EFAULT;
+       old = pmdp_flush_lazy(mm, addr, pmdp);
+       *pmdp = new;
+       return old;
 }
-EXPORT_SYMBOL_GPL(__gmap_translate);
-
-/**
- * gmap_translate - translate a guest address to a user space address
- * @gmap: pointer to guest mapping meta data structure
- * @gaddr: guest address
- *
- * Returns user space address which corresponds to the guest address or
- * -EFAULT if no such mapping exists.
- * This function does not establish potentially missing page table entries.
- */
-unsigned long gmap_translate(struct gmap *gmap, unsigned long gaddr)
+EXPORT_SYMBOL(pmdp_xchg_lazy);
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+                               pgtable_t pgtable)
 {
-       unsigned long rc;
+       struct list_head *lh = (struct list_head *) pgtable;
 
-       down_read(&gmap->mm->mmap_sem);
-       rc = __gmap_translate(gmap, gaddr);
-       up_read(&gmap->mm->mmap_sem);
-       return rc;
+       assert_spin_locked(pmd_lockptr(mm, pmdp));
+
+       /* FIFO */
+       if (!pmd_huge_pte(mm, pmdp))
+               INIT_LIST_HEAD(lh);
+       else
+               list_add(lh, (struct list_head *) pmd_huge_pte(mm, pmdp));
+       pmd_huge_pte(mm, pmdp) = pgtable;
 }
-EXPORT_SYMBOL_GPL(gmap_translate);
 
-/**
- * gmap_unlink - disconnect a page table from the gmap shadow tables
- * @gmap: pointer to guest mapping meta data structure
- * @table: pointer to the host page table
- * @vmaddr: vm address associated with the host page table
- */
-static void gmap_unlink(struct mm_struct *mm, unsigned long *table,
-                       unsigned long vmaddr)
+pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
 {
-       struct gmap *gmap;
-       int flush;
+       struct list_head *lh;
+       pgtable_t pgtable;
+       pte_t *ptep;
+
+       assert_spin_locked(pmd_lockptr(mm, pmdp));
 
-       list_for_each_entry(gmap, &mm->context.gmap_list, list) {
-               flush = __gmap_unlink_by_vmaddr(gmap, vmaddr);
-               if (flush)
-                       gmap_flush_tlb(gmap);
+       /* FIFO */
+       pgtable = pmd_huge_pte(mm, pmdp);
+       lh = (struct list_head *) pgtable;
+       if (list_empty(lh))
+               pmd_huge_pte(mm, pmdp) = NULL;
+       else {
+               pmd_huge_pte(mm, pmdp) = (pgtable_t) lh->next;
+               list_del(lh);
        }
+       ptep = (pte_t *) pgtable;
+       pte_val(*ptep) = _PAGE_INVALID;
+       ptep++;
+       pte_val(*ptep) = _PAGE_INVALID;
+       return pgtable;
 }
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
-/**
- * gmap_link - set up shadow page tables to connect a host to a guest address
- * @gmap: pointer to guest mapping meta data structure
- * @gaddr: guest address
- * @vmaddr: vm address
- *
- * Returns 0 on success, -ENOMEM for out of memory conditions, and -EFAULT
- * if the vm address is already mapped to a different guest segment.
- * The mmap_sem of the mm that belongs to the address space must be held
- * when this function gets called.
- */
-int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
+#ifdef CONFIG_PGSTE
+void ptep_set_pte_at(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, pte_t entry)
 {
-       struct mm_struct *mm;
-       unsigned long *table;
-       spinlock_t *ptl;
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       int rc;
-
-       /* Create higher level tables in the gmap page table */
-       table = gmap->table;
-       if ((gmap->asce & _ASCE_TYPE_MASK) >= _ASCE_TYPE_REGION1) {
-               table += (gaddr >> 53) & 0x7ff;
-               if ((*table & _REGION_ENTRY_INVALID) &&
-                   gmap_alloc_table(gmap, table, _REGION2_ENTRY_EMPTY,
-                                    gaddr & 0xffe0000000000000UL))
-                       return -ENOMEM;
-               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
-       }
-       if ((gmap->asce & _ASCE_TYPE_MASK) >= _ASCE_TYPE_REGION2) {
-               table += (gaddr >> 42) & 0x7ff;
-               if ((*table & _REGION_ENTRY_INVALID) &&
-                   gmap_alloc_table(gmap, table, _REGION3_ENTRY_EMPTY,
-                                    gaddr & 0xfffffc0000000000UL))
-                       return -ENOMEM;
-               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
-       }
-       if ((gmap->asce & _ASCE_TYPE_MASK) >= _ASCE_TYPE_REGION3) {
-               table += (gaddr >> 31) & 0x7ff;
-               if ((*table & _REGION_ENTRY_INVALID) &&
-                   gmap_alloc_table(gmap, table, _SEGMENT_ENTRY_EMPTY,
-                                    gaddr & 0xffffffff80000000UL))
-                       return -ENOMEM;
-               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
-       }
-       table += (gaddr >> 20) & 0x7ff;
-       /* Walk the parent mm page table */
-       mm = gmap->mm;
-       pgd = pgd_offset(mm, vmaddr);
-       VM_BUG_ON(pgd_none(*pgd));
-       pud = pud_offset(pgd, vmaddr);
-       VM_BUG_ON(pud_none(*pud));
-       pmd = pmd_offset(pud, vmaddr);
-       VM_BUG_ON(pmd_none(*pmd));
-       /* large pmds cannot yet be handled */
-       if (pmd_large(*pmd))
-               return -EFAULT;
-       /* Link gmap segment table entry location to page table. */
-       rc = radix_tree_preload(GFP_KERNEL);
-       if (rc)
-               return rc;
-       ptl = pmd_lock(mm, pmd);
-       spin_lock(&gmap->guest_table_lock);
-       if (*table == _SEGMENT_ENTRY_INVALID) {
-               rc = radix_tree_insert(&gmap->host_to_guest,
-                                      vmaddr >> PMD_SHIFT, table);
-               if (!rc)
-                       *table = pmd_val(*pmd);
-       } else
-               rc = 0;
-       spin_unlock(&gmap->guest_table_lock);
-       spin_unlock(ptl);
-       radix_tree_preload_end();
-       return rc;
+       pgste_t pgste;
+
+       /* the mm_has_pgste() check is done in set_pte_at() */
+       pgste = pgste_get_lock(ptep);
+       pgste_val(pgste) &= ~_PGSTE_GPS_ZERO;
+       pgste_set_key(ptep, pgste, entry, mm);
+       pgste = pgste_set_pte(ptep, pgste, entry);
+       pgste_set_unlock(ptep, pgste);
 }
 
-/**
- * gmap_fault - resolve a fault on a guest address
- * @gmap: pointer to guest mapping meta data structure
- * @gaddr: guest address
- * @fault_flags: flags to pass down to handle_mm_fault()
- *
- * Returns 0 on success, -ENOMEM for out of memory conditions, and -EFAULT
- * if the vm address is already mapped to a different guest segment.
- */
-int gmap_fault(struct gmap *gmap, unsigned long gaddr,
-              unsigned int fault_flags)
+void ptep_set_notify(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
-       unsigned long vmaddr;
-       int rc;
-       bool unlocked;
-
-       down_read(&gmap->mm->mmap_sem);
-
-retry:
-       unlocked = false;
-       vmaddr = __gmap_translate(gmap, gaddr);
-       if (IS_ERR_VALUE(vmaddr)) {
-               rc = vmaddr;
-               goto out_up;
-       }
-       if (fixup_user_fault(current, gmap->mm, vmaddr, fault_flags,
-                            &unlocked)) {
-               rc = -EFAULT;
-               goto out_up;
-       }
-       /*
-        * In the case that fixup_user_fault unlocked the mmap_sem during
-        * faultin redo __gmap_translate to not race with a map/unmap_segment.
-        */
-       if (unlocked)
-               goto retry;
+       pgste_t pgste;
 
-       rc = __gmap_link(gmap, gaddr, vmaddr);
-out_up:
-       up_read(&gmap->mm->mmap_sem);
-       return rc;
+       pgste = pgste_get_lock(ptep);
+       pgste_val(pgste) |= PGSTE_IN_BIT;
+       pgste_set_unlock(ptep, pgste);
 }
-EXPORT_SYMBOL_GPL(gmap_fault);
 
-static void gmap_zap_swap_entry(swp_entry_t entry, struct mm_struct *mm)
+static void ptep_zap_swap_entry(struct mm_struct *mm, swp_entry_t entry)
 {
        if (!non_swap_entry(entry))
                dec_mm_counter(mm, MM_SWAPENTS);
@@ -620,225 +426,99 @@ static void gmap_zap_swap_entry(swp_entry_t entry, struct mm_struct *mm)
        free_swap_and_cache(entry);
 }
 
-/*
- * this function is assumed to be called with mmap_sem held
- */
-void __gmap_zap(struct gmap *gmap, unsigned long gaddr)
+void ptep_zap_unused(struct mm_struct *mm, unsigned long addr,
+                    pte_t *ptep, int reset)
 {
-       unsigned long vmaddr, ptev, pgstev;
-       pte_t *ptep, pte;
-       spinlock_t *ptl;
+       unsigned long pgstev;
        pgste_t pgste;
+       pte_t pte;
 
-       /* Find the vm address for the guest address */
-       vmaddr = (unsigned long) radix_tree_lookup(&gmap->guest_to_host,
-                                                  gaddr >> PMD_SHIFT);
-       if (!vmaddr)
-               return;
-       vmaddr |= gaddr & ~PMD_MASK;
-       /* Get pointer to the page table entry */
-       ptep = get_locked_pte(gmap->mm, vmaddr, &ptl);
-       if (unlikely(!ptep))
-               return;
-       pte = *ptep;
-       if (!pte_swap(pte))
-               goto out_pte;
        /* Zap unused and logically-zero pages */
        pgste = pgste_get_lock(ptep);
        pgstev = pgste_val(pgste);
-       ptev = pte_val(pte);
-       if (((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED) ||
-           ((pgstev & _PGSTE_GPS_ZERO) && (ptev & _PAGE_INVALID))) {
-               gmap_zap_swap_entry(pte_to_swp_entry(pte), gmap->mm);
-               pte_clear(gmap->mm, vmaddr, ptep);
-       }
+       pte = *ptep;
+       if (pte_swap(pte) &&
+           ((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED ||
+            (pgstev & _PGSTE_GPS_ZERO))) {
+               ptep_zap_swap_entry(mm, pte_to_swp_entry(pte));
+               pte_clear(mm, addr, ptep);
+       }
+       if (reset)
+               pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
        pgste_set_unlock(ptep, pgste);
-out_pte:
-       pte_unmap_unlock(ptep, ptl);
 }
-EXPORT_SYMBOL_GPL(__gmap_zap);
 
-void gmap_discard(struct gmap *gmap, unsigned long from, unsigned long to)
+void ptep_zap_key(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
-       unsigned long gaddr, vmaddr, size;
-       struct vm_area_struct *vma;
-
-       down_read(&gmap->mm->mmap_sem);
-       for (gaddr = from; gaddr < to;
-            gaddr = (gaddr + PMD_SIZE) & PMD_MASK) {
-               /* Find the vm address for the guest address */
-               vmaddr = (unsigned long)
-                       radix_tree_lookup(&gmap->guest_to_host,
-                                         gaddr >> PMD_SHIFT);
-               if (!vmaddr)
-                       continue;
-               vmaddr |= gaddr & ~PMD_MASK;
-               /* Find vma in the parent mm */
-               vma = find_vma(gmap->mm, vmaddr);
-               size = min(to - gaddr, PMD_SIZE - (gaddr & ~PMD_MASK));
-               zap_page_range(vma, vmaddr, size, NULL);
-       }
-       up_read(&gmap->mm->mmap_sem);
-}
-EXPORT_SYMBOL_GPL(gmap_discard);
-
-static LIST_HEAD(gmap_notifier_list);
-static DEFINE_SPINLOCK(gmap_notifier_lock);
+       unsigned long ptev;
+       pgste_t pgste;
 
-/**
- * gmap_register_ipte_notifier - register a pte invalidation callback
- * @nb: pointer to the gmap notifier block
- */
-void gmap_register_ipte_notifier(struct gmap_notifier *nb)
-{
-       spin_lock(&gmap_notifier_lock);
-       list_add(&nb->list, &gmap_notifier_list);
-       spin_unlock(&gmap_notifier_lock);
+       /* Clear storage key */
+       pgste = pgste_get_lock(ptep);
+       pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT |
+                             PGSTE_GR_BIT | PGSTE_GC_BIT);
+       ptev = pte_val(*ptep);
+       if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE))
+               page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 1);
+       pgste_set_unlock(ptep, pgste);
 }
-EXPORT_SYMBOL_GPL(gmap_register_ipte_notifier);
 
-/**
- * gmap_unregister_ipte_notifier - remove a pte invalidation callback
- * @nb: pointer to the gmap notifier block
- */
-void gmap_unregister_ipte_notifier(struct gmap_notifier *nb)
-{
-       spin_lock(&gmap_notifier_lock);
-       list_del_init(&nb->list);
-       spin_unlock(&gmap_notifier_lock);
-}
-EXPORT_SYMBOL_GPL(gmap_unregister_ipte_notifier);
-
-/**
- * gmap_ipte_notify - mark a range of ptes for invalidation notification
- * @gmap: pointer to guest mapping meta data structure
- * @gaddr: virtual address in the guest address space
- * @len: size of area
- *
- * Returns 0 if for each page in the given range a gmap mapping exists and
- * the invalidation notification could be set. If the gmap mapping is missing
- * for one or more pages -EFAULT is returned. If no memory could be allocated
- * -ENOMEM is returned. This function establishes missing page table entries.
+/*
+ * Test and reset if a guest page is dirty
  */
-int gmap_ipte_notify(struct gmap *gmap, unsigned long gaddr, unsigned long len)
+bool test_and_clear_guest_dirty(struct mm_struct *mm, unsigned long addr)
 {
-       unsigned long addr;
        spinlock_t *ptl;
-       pte_t *ptep, entry;
        pgste_t pgste;
-       bool unlocked;
-       int rc = 0;
-
-       if ((gaddr & ~PAGE_MASK) || (len & ~PAGE_MASK))
-               return -EINVAL;
-       down_read(&gmap->mm->mmap_sem);
-       while (len) {
-               unlocked = false;
-               /* Convert gmap address and connect the page tables */
-               addr = __gmap_translate(gmap, gaddr);
-               if (IS_ERR_VALUE(addr)) {
-                       rc = addr;
-                       break;
-               }
-               /* Get the page mapped */
-               if (fixup_user_fault(current, gmap->mm, addr, FAULT_FLAG_WRITE,
-                                    &unlocked)) {
-                       rc = -EFAULT;
-                       break;
-               }
-               /* While trying to map mmap_sem got unlocked. Let us retry */
-               if (unlocked)
-                       continue;
-               rc = __gmap_link(gmap, gaddr, addr);
-               if (rc)
-                       break;
-               /* Walk the process page table, lock and get pte pointer */
-               ptep = get_locked_pte(gmap->mm, addr, &ptl);
-               VM_BUG_ON(!ptep);
-               /* Set notification bit in the pgste of the pte */
-               entry = *ptep;
-               if ((pte_val(entry) & (_PAGE_INVALID | _PAGE_PROTECT)) == 0) {
-                       pgste = pgste_get_lock(ptep);
-                       pgste_val(pgste) |= PGSTE_IN_BIT;
-                       pgste_set_unlock(ptep, pgste);
-                       gaddr += PAGE_SIZE;
-                       len -= PAGE_SIZE;
-               }
-               pte_unmap_unlock(ptep, ptl);
-       }
-       up_read(&gmap->mm->mmap_sem);
-       return rc;
-}
-EXPORT_SYMBOL_GPL(gmap_ipte_notify);
-
-/**
- * gmap_do_ipte_notify - call all invalidation callbacks for a specific pte.
- * @mm: pointer to the process mm_struct
- * @addr: virtual address in the process address space
- * @pte: pointer to the page table entry
- *
- * This function is assumed to be called with the page table lock held
- * for the pte to notify.
- */
-void gmap_do_ipte_notify(struct mm_struct *mm, unsigned long vmaddr, pte_t *pte)
-{
-       unsigned long offset, gaddr;
-       unsigned long *table;
-       struct gmap_notifier *nb;
-       struct gmap *gmap;
-
-       offset = ((unsigned long) pte) & (255 * sizeof(pte_t));
-       offset = offset * (4096 / sizeof(pte_t));
-       spin_lock(&gmap_notifier_lock);
-       list_for_each_entry(gmap, &mm->context.gmap_list, list) {
-               table = radix_tree_lookup(&gmap->host_to_guest,
-                                         vmaddr >> PMD_SHIFT);
-               if (!table)
-                       continue;
-               gaddr = __gmap_segment_gaddr(table) + offset;
-               list_for_each_entry(nb, &gmap_notifier_list, list)
-                       nb->notifier_call(gmap, gaddr);
+       pte_t *ptep;
+       pte_t pte;
+       bool dirty;
+
+       ptep = get_locked_pte(mm, addr, &ptl);
+       if (unlikely(!ptep))
+               return false;
+
+       pgste = pgste_get_lock(ptep);
+       dirty = !!(pgste_val(pgste) & PGSTE_UC_BIT);
+       pgste_val(pgste) &= ~PGSTE_UC_BIT;
+       pte = *ptep;
+       if (dirty && (pte_val(pte) & _PAGE_PRESENT)) {
+               pgste = pgste_ipte_notify(mm, addr, ptep, pgste);
+               __ptep_ipte(addr, ptep);
+               if (MACHINE_HAS_ESOP || !(pte_val(pte) & _PAGE_WRITE))
+                       pte_val(pte) |= _PAGE_PROTECT;
+               else
+                       pte_val(pte) |= _PAGE_INVALID;
+               *ptep = pte;
        }
-       spin_unlock(&gmap_notifier_lock);
+       pgste_set_unlock(ptep, pgste);
+
+       spin_unlock(ptl);
+       return dirty;
 }
-EXPORT_SYMBOL_GPL(gmap_do_ipte_notify);
+EXPORT_SYMBOL_GPL(test_and_clear_guest_dirty);
 
 int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
-                         unsigned long key, bool nq)
+                         unsigned char key, bool nq)
 {
+       unsigned long keyul;
        spinlock_t *ptl;
        pgste_t old, new;
        pte_t *ptep;
-       bool unlocked;
 
        down_read(&mm->mmap_sem);
-retry:
-       unlocked = false;
        ptep = get_locked_pte(mm, addr, &ptl);
        if (unlikely(!ptep)) {
                up_read(&mm->mmap_sem);
                return -EFAULT;
        }
-       if (!(pte_val(*ptep) & _PAGE_INVALID) &&
-            (pte_val(*ptep) & _PAGE_PROTECT)) {
-               pte_unmap_unlock(ptep, ptl);
-               /*
-                * We do not really care about unlocked. We will retry either
-                * way. But this allows fixup_user_fault to enable userfaultfd.
-                */
-               if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE,
-                                    &unlocked)) {
-                       up_read(&mm->mmap_sem);
-                       return -EFAULT;
-               }
-               goto retry;
-       }
 
        new = old = pgste_get_lock(ptep);
        pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT |
                            PGSTE_ACC_BITS | PGSTE_FP_BIT);
-       pgste_val(new) |= (key & (_PAGE_CHANGED | _PAGE_REFERENCED)) << 48;
-       pgste_val(new) |= (key & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56;
+       keyul = (unsigned long) key;
+       pgste_val(new) |= (keyul & (_PAGE_CHANGED | _PAGE_REFERENCED)) << 48;
+       pgste_val(new) |= (keyul & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56;
        if (!(pte_val(*ptep) & _PAGE_INVALID)) {
                unsigned long address, bits, skey;
 
@@ -863,13 +543,12 @@ retry:
 }
 EXPORT_SYMBOL(set_guest_storage_key);
 
-unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
+unsigned char get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
 {
+       unsigned char key;
        spinlock_t *ptl;
        pgste_t pgste;
        pte_t *ptep;
-       uint64_t physaddr;
-       unsigned long key = 0;
 
        down_read(&mm->mmap_sem);
        ptep = get_locked_pte(mm, addr, &ptl);
@@ -880,13 +559,12 @@ unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
        pgste = pgste_get_lock(ptep);
 
        if (pte_val(*ptep) & _PAGE_INVALID) {
-               key |= (pgste_val(pgste) & PGSTE_ACC_BITS) >> 56;
+               key  = (pgste_val(pgste) & PGSTE_ACC_BITS) >> 56;
                key |= (pgste_val(pgste) & PGSTE_FP_BIT) >> 56;
                key |= (pgste_val(pgste) & PGSTE_GR_BIT) >> 48;
                key |= (pgste_val(pgste) & PGSTE_GC_BIT) >> 48;
        } else {
-               physaddr = pte_val(*ptep) & PAGE_MASK;
-               key = page_get_storage_key(physaddr);
+               key = page_get_storage_key(pte_val(*ptep) & PAGE_MASK);
 
                /* Reflect guest's logical view, not physical */
                if (pgste_val(pgste) & PGSTE_GR_BIT)
@@ -901,471 +579,4 @@ unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
        return key;
 }
 EXPORT_SYMBOL(get_guest_storage_key);
-
-static int page_table_allocate_pgste_min = 0;
-static int page_table_allocate_pgste_max = 1;
-int page_table_allocate_pgste = 0;
-EXPORT_SYMBOL(page_table_allocate_pgste);
-
-static struct ctl_table page_table_sysctl[] = {
-       {
-               .procname       = "allocate_pgste",
-               .data           = &page_table_allocate_pgste,
-               .maxlen         = sizeof(int),
-               .mode           = S_IRUGO | S_IWUSR,
-               .proc_handler   = proc_dointvec,
-               .extra1         = &page_table_allocate_pgste_min,
-               .extra2         = &page_table_allocate_pgste_max,
-       },
-       { }
-};
-
-static struct ctl_table page_table_sysctl_dir[] = {
-       {
-               .procname       = "vm",
-               .maxlen         = 0,
-               .mode           = 0555,
-               .child          = page_table_sysctl,
-       },
-       { }
-};
-
-static int __init page_table_register_sysctl(void)
-{
-       return register_sysctl_table(page_table_sysctl_dir) ? 0 : -ENOMEM;
-}
-__initcall(page_table_register_sysctl);
-
-#else /* CONFIG_PGSTE */
-
-static inline void gmap_unlink(struct mm_struct *mm, unsigned long *table,
-                       unsigned long vmaddr)
-{
-}
-
-#endif /* CONFIG_PGSTE */
-
-static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
-{
-       unsigned int old, new;
-
-       do {
-               old = atomic_read(v);
-               new = old ^ bits;
-       } while (atomic_cmpxchg(v, old, new) != old);
-       return new;
-}
-
-/*
- * page table entry allocation/free routines.
- */
-unsigned long *page_table_alloc(struct mm_struct *mm)
-{
-       unsigned long *table;
-       struct page *page;
-       unsigned int mask, bit;
-
-       /* Try to get a fragment of a 4K page as a 2K page table */
-       if (!mm_alloc_pgste(mm)) {
-               table = NULL;
-               spin_lock_bh(&mm->context.list_lock);
-               if (!list_empty(&mm->context.pgtable_list)) {
-                       page = list_first_entry(&mm->context.pgtable_list,
-                                               struct page, lru);
-                       mask = atomic_read(&page->_mapcount);
-                       mask = (mask | (mask >> 4)) & 3;
-                       if (mask != 3) {
-                               table = (unsigned long *) page_to_phys(page);
-                               bit = mask & 1;         /* =1 -> second 2K */
-                               if (bit)
-                                       table += PTRS_PER_PTE;
-                               atomic_xor_bits(&page->_mapcount, 1U << bit);
-                               list_del(&page->lru);
-                       }
-               }
-               spin_unlock_bh(&mm->context.list_lock);
-               if (table)
-                       return table;
-       }
-       /* Allocate a fresh page */
-       page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
-       if (!page)
-               return NULL;
-       if (!pgtable_page_ctor(page)) {
-               __free_page(page);
-               return NULL;
-       }
-       /* Initialize page table */
-       table = (unsigned long *) page_to_phys(page);
-       if (mm_alloc_pgste(mm)) {
-               /* Return 4K page table with PGSTEs */
-               atomic_set(&page->_mapcount, 3);
-               clear_table(table, _PAGE_INVALID, PAGE_SIZE/2);
-               clear_table(table + PTRS_PER_PTE, 0, PAGE_SIZE/2);
-       } else {
-               /* Return the first 2K fragment of the page */
-               atomic_set(&page->_mapcount, 1);
-               clear_table(table, _PAGE_INVALID, PAGE_SIZE);
-               spin_lock_bh(&mm->context.list_lock);
-               list_add(&page->lru, &mm->context.pgtable_list);
-               spin_unlock_bh(&mm->context.list_lock);
-       }
-       return table;
-}
-
-void page_table_free(struct mm_struct *mm, unsigned long *table)
-{
-       struct page *page;
-       unsigned int bit, mask;
-
-       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       if (!mm_alloc_pgste(mm)) {
-               /* Free 2K page table fragment of a 4K page */
-               bit = (__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
-               spin_lock_bh(&mm->context.list_lock);
-               mask = atomic_xor_bits(&page->_mapcount, 1U << bit);
-               if (mask & 3)
-                       list_add(&page->lru, &mm->context.pgtable_list);
-               else
-                       list_del(&page->lru);
-               spin_unlock_bh(&mm->context.list_lock);
-               if (mask != 0)
-                       return;
-       }
-
-       pgtable_page_dtor(page);
-       atomic_set(&page->_mapcount, -1);
-       __free_page(page);
-}
-
-void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table,
-                        unsigned long vmaddr)
-{
-       struct mm_struct *mm;
-       struct page *page;
-       unsigned int bit, mask;
-
-       mm = tlb->mm;
-       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-       if (mm_alloc_pgste(mm)) {
-               gmap_unlink(mm, table, vmaddr);
-               table = (unsigned long *) (__pa(table) | 3);
-               tlb_remove_table(tlb, table);
-               return;
-       }
-       bit = (__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t));
-       spin_lock_bh(&mm->context.list_lock);
-       mask = atomic_xor_bits(&page->_mapcount, 0x11U << bit);
-       if (mask & 3)
-               list_add_tail(&page->lru, &mm->context.pgtable_list);
-       else
-               list_del(&page->lru);
-       spin_unlock_bh(&mm->context.list_lock);
-       table = (unsigned long *) (__pa(table) | (1U << bit));
-       tlb_remove_table(tlb, table);
-}
-
-static void __tlb_remove_table(void *_table)
-{
-       unsigned int mask = (unsigned long) _table & 3;
-       void *table = (void *)((unsigned long) _table ^ mask);
-       struct page *page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
-
-       switch (mask) {
-       case 0:         /* pmd or pud */
-               free_pages((unsigned long) table, 2);
-               break;
-       case 1:         /* lower 2K of a 4K page table */
-       case 2:         /* higher 2K of a 4K page table */
-               if (atomic_xor_bits(&page->_mapcount, mask << 4) != 0)
-                       break;
-               /* fallthrough */
-       case 3:         /* 4K page table with pgstes */
-               pgtable_page_dtor(page);
-               atomic_set(&page->_mapcount, -1);
-               __free_page(page);
-               break;
-       }
-}
-
-static void tlb_remove_table_smp_sync(void *arg)
-{
-       /* Simply deliver the interrupt */
-}
-
-static void tlb_remove_table_one(void *table)
-{
-       /*
-        * This isn't an RCU grace period and hence the page-tables cannot be
-        * assumed to be actually RCU-freed.
-        *
-        * It is however sufficient for software page-table walkers that rely
-        * on IRQ disabling. See the comment near struct mmu_table_batch.
-        */
-       smp_call_function(tlb_remove_table_smp_sync, NULL, 1);
-       __tlb_remove_table(table);
-}
-
-static void tlb_remove_table_rcu(struct rcu_head *head)
-{
-       struct mmu_table_batch *batch;
-       int i;
-
-       batch = container_of(head, struct mmu_table_batch, rcu);
-
-       for (i = 0; i < batch->nr; i++)
-               __tlb_remove_table(batch->tables[i]);
-
-       free_page((unsigned long)batch);
-}
-
-void tlb_table_flush(struct mmu_gather *tlb)
-{
-       struct mmu_table_batch **batch = &tlb->batch;
-
-       if (*batch) {
-               call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu);
-               *batch = NULL;
-       }
-}
-
-void tlb_remove_table(struct mmu_gather *tlb, void *table)
-{
-       struct mmu_table_batch **batch = &tlb->batch;
-
-       tlb->mm->context.flush_mm = 1;
-       if (*batch == NULL) {
-               *batch = (struct mmu_table_batch *)
-                       __get_free_page(GFP_NOWAIT | __GFP_NOWARN);
-               if (*batch == NULL) {
-                       __tlb_flush_mm_lazy(tlb->mm);
-                       tlb_remove_table_one(table);
-                       return;
-               }
-               (*batch)->nr = 0;
-       }
-       (*batch)->tables[(*batch)->nr++] = table;
-       if ((*batch)->nr == MAX_TABLE_BATCH)
-               tlb_flush_mmu(tlb);
-}
-
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static inline void thp_split_vma(struct vm_area_struct *vma)
-{
-       unsigned long addr;
-
-       for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE)
-               follow_page(vma, addr, FOLL_SPLIT);
-}
-
-static inline void thp_split_mm(struct mm_struct *mm)
-{
-       struct vm_area_struct *vma;
-
-       for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
-               thp_split_vma(vma);
-               vma->vm_flags &= ~VM_HUGEPAGE;
-               vma->vm_flags |= VM_NOHUGEPAGE;
-       }
-       mm->def_flags |= VM_NOHUGEPAGE;
-}
-#else
-static inline void thp_split_mm(struct mm_struct *mm)
-{
-}
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
-
-/*
- * switch on pgstes for its userspace process (for kvm)
- */
-int s390_enable_sie(void)
-{
-       struct mm_struct *mm = current->mm;
-
-       /* Do we have pgstes? if yes, we are done */
-       if (mm_has_pgste(mm))
-               return 0;
-       /* Fail if the page tables are 2K */
-       if (!mm_alloc_pgste(mm))
-               return -EINVAL;
-       down_write(&mm->mmap_sem);
-       mm->context.has_pgste = 1;
-       /* split thp mappings and disable thp for future mappings */
-       thp_split_mm(mm);
-       up_write(&mm->mmap_sem);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(s390_enable_sie);
-
-/*
- * Enable storage key handling from now on and initialize the storage
- * keys with the default key.
- */
-static int __s390_enable_skey(pte_t *pte, unsigned long addr,
-                             unsigned long next, struct mm_walk *walk)
-{
-       unsigned long ptev;
-       pgste_t pgste;
-
-       pgste = pgste_get_lock(pte);
-       /*
-        * Remove all zero page mappings,
-        * after establishing a policy to forbid zero page mappings
-        * following faults for that page will get fresh anonymous pages
-        */
-       if (is_zero_pfn(pte_pfn(*pte))) {
-               ptep_flush_direct(walk->mm, addr, pte);
-               pte_val(*pte) = _PAGE_INVALID;
-       }
-       /* Clear storage key */
-       pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT |
-                             PGSTE_GR_BIT | PGSTE_GC_BIT);
-       ptev = pte_val(*pte);
-       if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE))
-               page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 1);
-       pgste_set_unlock(pte, pgste);
-       return 0;
-}
-
-int s390_enable_skey(void)
-{
-       struct mm_walk walk = { .pte_entry = __s390_enable_skey };
-       struct mm_struct *mm = current->mm;
-       struct vm_area_struct *vma;
-       int rc = 0;
-
-       down_write(&mm->mmap_sem);
-       if (mm_use_skey(mm))
-               goto out_up;
-
-       mm->context.use_skey = 1;
-       for (vma = mm->mmap; vma; vma = vma->vm_next) {
-               if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
-                               MADV_UNMERGEABLE, &vma->vm_flags)) {
-                       mm->context.use_skey = 0;
-                       rc = -ENOMEM;
-                       goto out_up;
-               }
-       }
-       mm->def_flags &= ~VM_MERGEABLE;
-
-       walk.mm = mm;
-       walk_page_range(0, TASK_SIZE, &walk);
-
-out_up:
-       up_write(&mm->mmap_sem);
-       return rc;
-}
-EXPORT_SYMBOL_GPL(s390_enable_skey);
-
-/*
- * Reset CMMA state, make all pages stable again.
- */
-static int __s390_reset_cmma(pte_t *pte, unsigned long addr,
-                            unsigned long next, struct mm_walk *walk)
-{
-       pgste_t pgste;
-
-       pgste = pgste_get_lock(pte);
-       pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
-       pgste_set_unlock(pte, pgste);
-       return 0;
-}
-
-void s390_reset_cmma(struct mm_struct *mm)
-{
-       struct mm_walk walk = { .pte_entry = __s390_reset_cmma };
-
-       down_write(&mm->mmap_sem);
-       walk.mm = mm;
-       walk_page_range(0, TASK_SIZE, &walk);
-       up_write(&mm->mmap_sem);
-}
-EXPORT_SYMBOL_GPL(s390_reset_cmma);
-
-/*
- * Test and reset if a guest page is dirty
- */
-bool gmap_test_and_clear_dirty(unsigned long address, struct gmap *gmap)
-{
-       pte_t *pte;
-       spinlock_t *ptl;
-       bool dirty = false;
-
-       pte = get_locked_pte(gmap->mm, address, &ptl);
-       if (unlikely(!pte))
-               return false;
-
-       if (ptep_test_and_clear_user_dirty(gmap->mm, address, pte))
-               dirty = true;
-
-       spin_unlock(ptl);
-       return dirty;
-}
-EXPORT_SYMBOL_GPL(gmap_test_and_clear_dirty);
-
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-int pmdp_clear_flush_young(struct vm_area_struct *vma, unsigned long address,
-                          pmd_t *pmdp)
-{
-       VM_BUG_ON(address & ~HPAGE_PMD_MASK);
-       /* No need to flush TLB
-        * On s390 reference bits are in storage key and never in TLB */
-       return pmdp_test_and_clear_young(vma, address, pmdp);
-}
-
-int pmdp_set_access_flags(struct vm_area_struct *vma,
-                         unsigned long address, pmd_t *pmdp,
-                         pmd_t entry, int dirty)
-{
-       VM_BUG_ON(address & ~HPAGE_PMD_MASK);
-
-       entry = pmd_mkyoung(entry);
-       if (dirty)
-               entry = pmd_mkdirty(entry);
-       if (pmd_same(*pmdp, entry))
-               return 0;
-       pmdp_invalidate(vma, address, pmdp);
-       set_pmd_at(vma->vm_mm, address, pmdp, entry);
-       return 1;
-}
-
-void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
-                               pgtable_t pgtable)
-{
-       struct list_head *lh = (struct list_head *) pgtable;
-
-       assert_spin_locked(pmd_lockptr(mm, pmdp));
-
-       /* FIFO */
-       if (!pmd_huge_pte(mm, pmdp))
-               INIT_LIST_HEAD(lh);
-       else
-               list_add(lh, (struct list_head *) pmd_huge_pte(mm, pmdp));
-       pmd_huge_pte(mm, pmdp) = pgtable;
-}
-
-pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
-{
-       struct list_head *lh;
-       pgtable_t pgtable;
-       pte_t *ptep;
-
-       assert_spin_locked(pmd_lockptr(mm, pmdp));
-
-       /* FIFO */
-       pgtable = pmd_huge_pte(mm, pmdp);
-       lh = (struct list_head *) pgtable;
-       if (list_empty(lh))
-               pmd_huge_pte(mm, pmdp) = NULL;
-       else {
-               pmd_huge_pte(mm, pmdp) = (pgtable_t) lh->next;
-               list_del(lh);
-       }
-       ptep = (pte_t *) pgtable;
-       pte_val(*ptep) = _PAGE_INVALID;
-       ptep++;
-       pte_val(*ptep) = _PAGE_INVALID;
-       return pgtable;
-}
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+#endif
index ef7d6c8fea66ea62eeddbe43420081d837c44274..d27fccbad7c1e6a67af2d355c486c3b7016958e9 100644 (file)
@@ -94,16 +94,15 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                        pgd_populate(&init_mm, pg_dir, pu_dir);
                }
                pu_dir = pud_offset(pg_dir, address);
-#ifndef CONFIG_DEBUG_PAGEALLOC
                if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address &&
-                   !(address & ~PUD_MASK) && (address + PUD_SIZE <= end)) {
+                   !(address & ~PUD_MASK) && (address + PUD_SIZE <= end) &&
+                    !debug_pagealloc_enabled()) {
                        pud_val(*pu_dir) = __pa(address) |
                                _REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE |
                                (ro ? _REGION_ENTRY_PROTECT : 0);
                        address += PUD_SIZE;
                        continue;
                }
-#endif
                if (pud_none(*pu_dir)) {
                        pm_dir = vmem_pmd_alloc();
                        if (!pm_dir)
@@ -111,9 +110,9 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                        pud_populate(&init_mm, pu_dir, pm_dir);
                }
                pm_dir = pmd_offset(pu_dir, address);
-#ifndef CONFIG_DEBUG_PAGEALLOC
                if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
-                   !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
+                   !(address & ~PMD_MASK) && (address + PMD_SIZE <= end) &&
+                   !debug_pagealloc_enabled()) {
                        pmd_val(*pm_dir) = __pa(address) |
                                _SEGMENT_ENTRY | _SEGMENT_ENTRY_LARGE |
                                _SEGMENT_ENTRY_YOUNG |
@@ -121,7 +120,6 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                        address += PMD_SIZE;
                        continue;
                }
-#endif
                if (pmd_none(*pm_dir)) {
                        pt_dir = vmem_pte_alloc(address);
                        if (!pt_dir)
index 1bd23017191e86fb528257d30cbc3e60e8339a5b..496e4a7ee00eb99a7d885acd4b7aff2c97eb4058 100644 (file)
@@ -6,5 +6,5 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
                oprofilefs.o oprofile_stats.o  \
                timer_int.o )
 
-oprofile-y :=  $(DRIVER_OBJS) init.o backtrace.o
+oprofile-y :=  $(DRIVER_OBJS) init.o
 oprofile-y +=  hwsampler.o
diff --git a/arch/s390/oprofile/backtrace.c b/arch/s390/oprofile/backtrace.c
deleted file mode 100644 (file)
index 1884e17..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * S390 Version
- *   Copyright IBM Corp. 2005
- *   Author(s): Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
- */
-
-#include <linux/oprofile.h>
-
-#include <asm/processor.h> /* for struct stack_frame */
-
-static unsigned long
-__show_trace(unsigned int *depth, unsigned long sp,
-            unsigned long low, unsigned long high)
-{
-       struct stack_frame *sf;
-       struct pt_regs *regs;
-
-       while (*depth) {
-               if (sp < low || sp > high - sizeof(*sf))
-                       return sp;
-               sf = (struct stack_frame *) sp;
-               (*depth)--;
-               oprofile_add_trace(sf->gprs[8]);
-
-               /* Follow the backchain.  */
-               while (*depth) {
-                       low = sp;
-                       sp = sf->back_chain;
-                       if (!sp)
-                               break;
-                       if (sp <= low || sp > high - sizeof(*sf))
-                               return sp;
-                       sf = (struct stack_frame *) sp;
-                       (*depth)--;
-                       oprofile_add_trace(sf->gprs[8]);
-
-               }
-
-               if (*depth == 0)
-                       break;
-
-               /* Zero backchain detected, check for interrupt frame.  */
-               sp = (unsigned long) (sf + 1);
-               if (sp <= low || sp > high - sizeof(*regs))
-                       return sp;
-               regs = (struct pt_regs *) sp;
-               (*depth)--;
-               oprofile_add_trace(sf->gprs[8]);
-               low = sp;
-               sp = regs->gprs[15];
-       }
-       return sp;
-}
-
-void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
-{
-       unsigned long head, frame_size;
-       struct stack_frame* head_sf;
-
-       if (user_mode(regs))
-               return;
-
-       frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
-       head = regs->gprs[15];
-       head_sf = (struct stack_frame*)head;
-
-       if (!head_sf->back_chain)
-               return;
-
-       head = head_sf->back_chain;
-
-       head = __show_trace(&depth, head,
-                           S390_lowcore.async_stack + frame_size - ASYNC_SIZE,
-                           S390_lowcore.async_stack + frame_size);
-
-       __show_trace(&depth, head, S390_lowcore.thread_info,
-                    S390_lowcore.thread_info + THREAD_SIZE);
-}
index 9cfa2ffaa9d6bb02dd29cb01d895a0feaf63bdb0..791935a658008f6b3b7efd51ba2d4c6fe3d9bc4f 100644 (file)
@@ -20,8 +20,6 @@
 
 #include "../../../drivers/oprofile/oprof.h"
 
-extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth);
-
 #include "hwsampler.h"
 #include "op_counter.h"
 
@@ -456,6 +454,7 @@ static int oprofile_hwsampler_init(struct oprofile_operations *ops)
                case 0x2097: case 0x2098: ops->cpu_type = "s390/z10"; break;
                case 0x2817: case 0x2818: ops->cpu_type = "s390/z196"; break;
                case 0x2827: case 0x2828: ops->cpu_type = "s390/zEC12"; break;
+               case 0x2964: case 0x2965: ops->cpu_type = "s390/z13"; break;
                default: return -ENODEV;
                }
        }
@@ -494,6 +493,24 @@ static void oprofile_hwsampler_exit(void)
        hwsampler_shutdown();
 }
 
+static int __s390_backtrace(void *data, unsigned long address)
+{
+       unsigned int *depth = data;
+
+       if (*depth == 0)
+               return 1;
+       (*depth)--;
+       oprofile_add_trace(address);
+       return 0;
+}
+
+static void s390_backtrace(struct pt_regs *regs, unsigned int depth)
+{
+       if (user_mode(regs))
+               return;
+       dump_trace(__s390_backtrace, &depth, NULL, regs->gprs[15]);
+}
+
 int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
        ops->backtrace = s390_backtrace;
index 8f19c8f9d660570839a69f60477f855181ba4e7c..9fd59a7cfcd3c31133bac69b6e62ffbf0a9654ed 100644 (file)
@@ -637,11 +637,9 @@ static void zpci_cleanup_bus_resources(struct zpci_dev *zdev)
 
 int pcibios_add_device(struct pci_dev *pdev)
 {
-       struct zpci_dev *zdev = to_zpci(pdev);
        struct resource *res;
        int i;
 
-       zdev->pdev = pdev;
        pdev->dev.groups = zpci_attr_groups;
        zpci_map_resources(pdev);
 
@@ -664,8 +662,7 @@ int pcibios_enable_device(struct pci_dev *pdev, int mask)
 {
        struct zpci_dev *zdev = to_zpci(pdev);
 
-       zdev->pdev = pdev;
-       zpci_debug_init_device(zdev);
+       zpci_debug_init_device(zdev, dev_name(&pdev->dev));
        zpci_fmb_enable_device(zdev);
 
        return pci_enable_resources(pdev, mask);
@@ -677,7 +674,6 @@ void pcibios_disable_device(struct pci_dev *pdev)
 
        zpci_fmb_disable_device(zdev);
        zpci_debug_exit_device(zdev);
-       zdev->pdev = NULL;
 }
 
 #ifdef CONFIG_HIBERNATE_CALLBACKS
@@ -864,8 +860,11 @@ static inline int barsize(u8 size)
 
 static int zpci_mem_init(void)
 {
+       BUILD_BUG_ON(!is_power_of_2(__alignof__(struct zpci_fmb)) ||
+                    __alignof__(struct zpci_fmb) < sizeof(struct zpci_fmb));
+
        zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
-                               16, 0, NULL);
+                                          __alignof__(struct zpci_fmb), 0, NULL);
        if (!zdev_fmb_cache)
                goto error_fmb;
 
index d6e411ed8b1f9017a62b68b6c3fbaab4ce4a0f18..21591ddb4c1fddcd59aeb1d990f484040e57aeae 100644 (file)
@@ -8,13 +8,19 @@
 #define KMSG_COMPONENT "zpci"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/compat.h>
 #include <linux/kernel.h>
+#include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/uaccess.h>
 #include <asm/pci_debug.h>
 #include <asm/pci_clp.h>
+#include <asm/compat.h>
+#include <asm/clp.h>
+#include <uapi/asm/clp.h>
 
 static inline void zpci_err_clp(unsigned int rsp, int rc)
 {
@@ -27,21 +33,43 @@ static inline void zpci_err_clp(unsigned int rsp, int rc)
 }
 
 /*
- * Call Logical Processor
- * Retry logic is handled by the caller.
+ * Call Logical Processor with c=1, lps=0 and command 1
+ * to get the bit mask of installed logical processors
  */
-static inline u8 clp_instr(void *data)
+static inline int clp_get_ilp(unsigned long *ilp)
+{
+       unsigned long mask;
+       int cc = 3;
+
+       asm volatile (
+               "       .insn   rrf,0xb9a00000,%[mask],%[cmd],8,0\n"
+               "0:     ipm     %[cc]\n"
+               "       srl     %[cc],28\n"
+               "1:\n"
+               EX_TABLE(0b, 1b)
+               : [cc] "+d" (cc), [mask] "=d" (mask) : [cmd] "a" (1)
+               : "cc");
+       *ilp = mask;
+       return cc;
+}
+
+/*
+ * Call Logical Processor with c=0, the give constant lps and an lpcb request.
+ */
+static inline int clp_req(void *data, unsigned int lps)
 {
        struct { u8 _[CLP_BLK_SIZE]; } *req = data;
        u64 ignored;
-       u8 cc;
+       int cc = 3;
 
        asm volatile (
-               "       .insn   rrf,0xb9a00000,%[ign],%[req],0x0,0x2\n"
-               "       ipm     %[cc]\n"
+               "       .insn   rrf,0xb9a00000,%[ign],%[req],0,%[lps]\n"
+               "0:     ipm     %[cc]\n"
                "       srl     %[cc],28\n"
-               : [cc] "=d" (cc), [ign] "=d" (ignored), "+m" (*req)
-               : [req] "a" (req)
+               "1:\n"
+               EX_TABLE(0b, 1b)
+               : [cc] "+d" (cc), [ign] "=d" (ignored), "+m" (*req)
+               : [req] "a" (req), [lps] "i" (lps)
                : "cc");
        return cc;
 }
@@ -90,7 +118,7 @@ static int clp_query_pci_fngrp(struct zpci_dev *zdev, u8 pfgid)
        rrb->response.hdr.len = sizeof(rrb->response);
        rrb->request.pfgid = pfgid;
 
-       rc = clp_instr(rrb);
+       rc = clp_req(rrb, CLP_LPS_PCI);
        if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
                clp_store_query_pci_fngrp(zdev, &rrb->response);
        else {
@@ -143,7 +171,7 @@ static int clp_query_pci_fn(struct zpci_dev *zdev, u32 fh)
        rrb->response.hdr.len = sizeof(rrb->response);
        rrb->request.fh = fh;
 
-       rc = clp_instr(rrb);
+       rc = clp_req(rrb, CLP_LPS_PCI);
        if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
                rc = clp_store_query_pci_fn(zdev, &rrb->response);
                if (rc)
@@ -214,7 +242,7 @@ static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
                rrb->request.oc = command;
                rrb->request.ndas = nr_dma_as;
 
-               rc = clp_instr(rrb);
+               rc = clp_req(rrb, CLP_LPS_PCI);
                if (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY) {
                        retries--;
                        if (retries < 0)
@@ -280,7 +308,7 @@ static int clp_list_pci(struct clp_req_rsp_list_pci *rrb,
                rrb->request.resume_token = resume_token;
 
                /* Get PCI function handle list */
-               rc = clp_instr(rrb);
+               rc = clp_req(rrb, CLP_LPS_PCI);
                if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
                        zpci_err("List PCI FN:\n");
                        zpci_err_clp(rrb->response.hdr.rsp, rc);
@@ -391,3 +419,198 @@ int clp_rescan_pci_devices_simple(void)
        clp_free_block(rrb);
        return rc;
 }
+
+static int clp_base_slpc(struct clp_req *req, struct clp_req_rsp_slpc *lpcb)
+{
+       unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
+
+       if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
+           lpcb->response.hdr.len > limit)
+               return -EINVAL;
+       return clp_req(lpcb, CLP_LPS_BASE) ? -EOPNOTSUPP : 0;
+}
+
+static int clp_base_command(struct clp_req *req, struct clp_req_hdr *lpcb)
+{
+       switch (lpcb->cmd) {
+       case 0x0001: /* store logical-processor characteristics */
+               return clp_base_slpc(req, (void *) lpcb);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int clp_pci_slpc(struct clp_req *req, struct clp_req_rsp_slpc *lpcb)
+{
+       unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
+
+       if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
+           lpcb->response.hdr.len > limit)
+               return -EINVAL;
+       return clp_req(lpcb, CLP_LPS_PCI) ? -EOPNOTSUPP : 0;
+}
+
+static int clp_pci_list(struct clp_req *req, struct clp_req_rsp_list_pci *lpcb)
+{
+       unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
+
+       if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
+           lpcb->response.hdr.len > limit)
+               return -EINVAL;
+       if (lpcb->request.reserved2 != 0)
+               return -EINVAL;
+       return clp_req(lpcb, CLP_LPS_PCI) ? -EOPNOTSUPP : 0;
+}
+
+static int clp_pci_query(struct clp_req *req,
+                        struct clp_req_rsp_query_pci *lpcb)
+{
+       unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
+
+       if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
+           lpcb->response.hdr.len > limit)
+               return -EINVAL;
+       if (lpcb->request.reserved2 != 0 || lpcb->request.reserved3 != 0)
+               return -EINVAL;
+       return clp_req(lpcb, CLP_LPS_PCI) ? -EOPNOTSUPP : 0;
+}
+
+static int clp_pci_query_grp(struct clp_req *req,
+                            struct clp_req_rsp_query_pci_grp *lpcb)
+{
+       unsigned long limit = PAGE_SIZE - sizeof(lpcb->request);
+
+       if (lpcb->request.hdr.len != sizeof(lpcb->request) ||
+           lpcb->response.hdr.len > limit)
+               return -EINVAL;
+       if (lpcb->request.reserved2 != 0 || lpcb->request.reserved3 != 0 ||
+           lpcb->request.reserved4 != 0)
+               return -EINVAL;
+       return clp_req(lpcb, CLP_LPS_PCI) ? -EOPNOTSUPP : 0;
+}
+
+static int clp_pci_command(struct clp_req *req, struct clp_req_hdr *lpcb)
+{
+       switch (lpcb->cmd) {
+       case 0x0001: /* store logical-processor characteristics */
+               return clp_pci_slpc(req, (void *) lpcb);
+       case 0x0002: /* list PCI functions */
+               return clp_pci_list(req, (void *) lpcb);
+       case 0x0003: /* query PCI function */
+               return clp_pci_query(req, (void *) lpcb);
+       case 0x0004: /* query PCI function group */
+               return clp_pci_query_grp(req, (void *) lpcb);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int clp_normal_command(struct clp_req *req)
+{
+       struct clp_req_hdr *lpcb;
+       void __user *uptr;
+       int rc;
+
+       rc = -EINVAL;
+       if (req->lps != 0 && req->lps != 2)
+               goto out;
+
+       rc = -ENOMEM;
+       lpcb = clp_alloc_block(GFP_KERNEL);
+       if (!lpcb)
+               goto out;
+
+       rc = -EFAULT;
+       uptr = (void __force __user *)(unsigned long) req->data_p;
+       if (copy_from_user(lpcb, uptr, PAGE_SIZE) != 0)
+               goto out_free;
+
+       rc = -EINVAL;
+       if (lpcb->fmt != 0 || lpcb->reserved1 != 0 || lpcb->reserved2 != 0)
+               goto out_free;
+
+       switch (req->lps) {
+       case 0:
+               rc = clp_base_command(req, lpcb);
+               break;
+       case 2:
+               rc = clp_pci_command(req, lpcb);
+               break;
+       }
+       if (rc)
+               goto out_free;
+
+       rc = -EFAULT;
+       if (copy_to_user(uptr, lpcb, PAGE_SIZE) != 0)
+               goto out_free;
+
+       rc = 0;
+
+out_free:
+       clp_free_block(lpcb);
+out:
+       return rc;
+}
+
+static int clp_immediate_command(struct clp_req *req)
+{
+       void __user *uptr;
+       unsigned long ilp;
+       int exists;
+
+       if (req->cmd > 1 || clp_get_ilp(&ilp) != 0)
+               return -EINVAL;
+
+       uptr = (void __force __user *)(unsigned long) req->data_p;
+       if (req->cmd == 0) {
+               /* Command code 0: test for a specific processor */
+               exists = test_bit_inv(req->lps, &ilp);
+               return put_user(exists, (int __user *) uptr);
+       }
+       /* Command code 1: return bit mask of installed processors */
+       return put_user(ilp, (unsigned long __user *) uptr);
+}
+
+static long clp_misc_ioctl(struct file *filp, unsigned int cmd,
+                          unsigned long arg)
+{
+       struct clp_req req;
+       void __user *argp;
+
+       if (cmd != CLP_SYNC)
+               return -EINVAL;
+
+       argp = is_compat_task() ? compat_ptr(arg) : (void __user *) arg;
+       if (copy_from_user(&req, argp, sizeof(req)))
+               return -EFAULT;
+       if (req.r != 0)
+               return -EINVAL;
+       return req.c ? clp_immediate_command(&req) : clp_normal_command(&req);
+}
+
+static int clp_misc_release(struct inode *inode, struct file *filp)
+{
+       return 0;
+}
+
+static const struct file_operations clp_misc_fops = {
+       .owner = THIS_MODULE,
+       .open = nonseekable_open,
+       .release = clp_misc_release,
+       .unlocked_ioctl = clp_misc_ioctl,
+       .compat_ioctl = clp_misc_ioctl,
+       .llseek = no_llseek,
+};
+
+static struct miscdevice clp_misc_device = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "clp",
+       .fops = &clp_misc_fops,
+};
+
+static int __init clp_misc_init(void)
+{
+       return misc_register(&clp_misc_device);
+}
+
+device_initcall(clp_misc_init);
index 4129b0a5fd780f1f1b74260ee6be656ff93d91c1..c555de3d12d6b987842a31f77f201c53f779a368 100644 (file)
@@ -128,10 +128,9 @@ static const struct file_operations debugfs_pci_perf_fops = {
        .release = single_release,
 };
 
-void zpci_debug_init_device(struct zpci_dev *zdev)
+void zpci_debug_init_device(struct zpci_dev *zdev, const char *name)
 {
-       zdev->debugfs_dev = debugfs_create_dir(dev_name(&zdev->pdev->dev),
-                                              debugfs_root);
+       zdev->debugfs_dev = debugfs_create_dir(name, debugfs_root);
        if (IS_ERR(zdev->debugfs_dev))
                zdev->debugfs_dev = NULL;
 
index 4638b93c763243908ae8bfe61816aed2c8761816..a06ce8037cec0257f805dd211d7ea4cfecbb5fd2 100644 (file)
@@ -217,27 +217,29 @@ void dma_cleanup_tables(unsigned long *table)
        dma_free_cpu_table(table);
 }
 
-static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev,
+static unsigned long __dma_alloc_iommu(struct device *dev,
                                       unsigned long start, int size)
 {
+       struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
        unsigned long boundary_size;
 
-       boundary_size = ALIGN(dma_get_seg_boundary(&zdev->pdev->dev) + 1,
+       boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
                              PAGE_SIZE) >> PAGE_SHIFT;
        return iommu_area_alloc(zdev->iommu_bitmap, zdev->iommu_pages,
                                start, size, 0, boundary_size, 0);
 }
 
-static unsigned long dma_alloc_iommu(struct zpci_dev *zdev, int size)
+static unsigned long dma_alloc_iommu(struct device *dev, int size)
 {
+       struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
        unsigned long offset, flags;
        int wrap = 0;
 
        spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
-       offset = __dma_alloc_iommu(zdev, zdev->next_bit, size);
+       offset = __dma_alloc_iommu(dev, zdev->next_bit, size);
        if (offset == -1) {
                /* wrap-around */
-               offset = __dma_alloc_iommu(zdev, 0, size);
+               offset = __dma_alloc_iommu(dev, 0, size);
                wrap = 1;
        }
 
@@ -251,8 +253,9 @@ static unsigned long dma_alloc_iommu(struct zpci_dev *zdev, int size)
        return offset;
 }
 
-static void dma_free_iommu(struct zpci_dev *zdev, unsigned long offset, int size)
+static void dma_free_iommu(struct device *dev, unsigned long offset, int size)
 {
+       struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
        unsigned long flags;
 
        spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
@@ -293,7 +296,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
 
        /* This rounds up number of pages based on size and offset */
        nr_pages = iommu_num_pages(pa, size, PAGE_SIZE);
-       iommu_page_index = dma_alloc_iommu(zdev, nr_pages);
+       iommu_page_index = dma_alloc_iommu(dev, nr_pages);
        if (iommu_page_index == -1) {
                ret = -ENOSPC;
                goto out_err;
@@ -319,7 +322,7 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
        return dma_addr + (offset & ~PAGE_MASK);
 
 out_free:
-       dma_free_iommu(zdev, iommu_page_index, nr_pages);
+       dma_free_iommu(dev, iommu_page_index, nr_pages);
 out_err:
        zpci_err("map error:\n");
        zpci_err_dma(ret, pa);
@@ -346,7 +349,7 @@ static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
 
        atomic64_add(npages, &zdev->unmapped_pages);
        iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT;
-       dma_free_iommu(zdev, iommu_page_index, npages);
+       dma_free_iommu(dev, iommu_page_index, npages);
 }
 
 static void *s390_dma_alloc(struct device *dev, size_t size,
index b0e04751c5d599fbdbb4bdb68fdbed5dcb4039d5..fb2a9a560fdcfc1e414e823563d436a4ebdc90af 100644 (file)
@@ -46,11 +46,14 @@ struct zpci_ccdf_avail {
 static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
 {
        struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
-       struct pci_dev *pdev = zdev ? zdev->pdev : NULL;
+       struct pci_dev *pdev = NULL;
 
        zpci_err("error CCDF:\n");
        zpci_err_hex(ccdf, sizeof(*ccdf));
 
+       if (zdev)
+               pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);
+
        pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
               pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
 
@@ -58,6 +61,7 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
                return;
 
        pdev->error_state = pci_channel_io_perm_failure;
+       pci_dev_put(pdev);
 }
 
 void zpci_event_error(void *data)
@@ -69,9 +73,12 @@ void zpci_event_error(void *data)
 static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
 {
        struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
-       struct pci_dev *pdev = zdev ? zdev->pdev : NULL;
+       struct pci_dev *pdev = NULL;
        int ret;
 
+       if (zdev)
+               pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);
+
        pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n",
                pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
        zpci_err("avail CCDF:\n");
@@ -138,6 +145,8 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
        default:
                break;
        }
+       if (pdev)
+               pci_dev_put(pdev);
 }
 
 void zpci_event_availability(void *data)
index b48459afefddb835582e548f5b8d7b4ffd026e0d..f3a0649ab5217ac5f87b83580723dfda40fff3de 100644 (file)
@@ -101,7 +101,7 @@ static void __init resource_init(void)
        res->name = "System RAM";
        res->start = MEMORY_START;
        res->end = MEMORY_START + MEMORY_SIZE - 1;
-       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
        request_resource(&iomem_resource, res);
 
        request_resource(res, &code_resource);
index e13da05505dcebc9501e97a34ec26057b1ffab90..17a4f1593d6564bcfb2f09e4c677f31931725516 100644 (file)
@@ -847,14 +847,10 @@ config PCI
 config PCI_DOMAINS
        bool
 
-source "drivers/pci/pcie/Kconfig"
-
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 menu "Executable file formats"
index e343dbd02e416d3ea1891374242b75781f546f73..644314f2b1ef0ba94e22bb1707f68036ac3968cc 100644 (file)
@@ -105,9 +105,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
        return channel ? 15 : 14;
 }
 
-/* generic DMA-mapping stuff */
-#include <asm-generic/pci-dma-compat.h>
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PCI_H */
 
index de19cfa768f208708406e3350b5e9aecc92a6266..3f1c18b28e8af5fc414c13ebeb29ccbf04cd63a5 100644 (file)
@@ -78,17 +78,17 @@ static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, };
 
 static struct resource code_resource = {
        .name = "Kernel code",
-       .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+       .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
 };
 
 static struct resource data_resource = {
        .name = "Kernel data",
-       .flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+       .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
 };
 
 static struct resource bss_resource = {
        .name   = "Kernel bss",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM,
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
 };
 
 unsigned long memory_start;
@@ -202,7 +202,7 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
        res->name = "System RAM";
        res->start = start;
        res->end = end - 1;
-       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
        if (request_resource(&iomem_resource, res)) {
                pr_err("unable to request memory_resource 0x%lx 0x%lx\n",
index de6be008fc0140ff7086bd4c153619f7213fc8cd..13f633add29ac46f21850400d63e6dafdc3d63c8 100644 (file)
@@ -203,7 +203,7 @@ asmlinkage void start_secondary(void)
        set_cpu_online(cpu, true);
        per_cpu(cpu_state, cpu) = CPU_ONLINE;
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 extern struct {
index eaee14637d93ec5db5f95931b52cc31d5a8c2108..8496a074bd0eb74548ce1e38709b8a8dfe7dfb31 100644 (file)
@@ -24,7 +24,13 @@ LDFLAGS        := -m elf32_sparc
 export BITS    := 32
 UTS_MACHINE    := sparc
 
+# We are adding -Wa,-Av8 to KBUILD_CFLAGS to deal with a specs bug in some
+# versions of gcc.  Some gcc versions won't pass -Av8 to binutils when you
+# give -mcpu=v8.  This silently worked with older bintutils versions but
+# does not any more.
 KBUILD_CFLAGS  += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+KBUILD_CFLAGS  += -Wa,-Av8
+
 KBUILD_AFLAGS  += -m32 -Wa,-Av8
 
 else
index d9c031f9910f89bcc7ca1ba41115435cdf9a8534..6e14fd179335d0a24d05cc71293589b63331607f 100644 (file)
@@ -5,7 +5,4 @@
 #else
 #include <asm/pci_32.h>
 #endif
-
-#include <asm-generic/pci-dma-compat.h>
-
 #endif
index 1c26d440d288dfb8d28579fda55e2a76ccf4c139..b6de8b10a55b8b8f09eedb2c90d86906d5445686 100644 (file)
 #define __NR_listen            354
 #define __NR_setsockopt                355
 #define __NR_mlock2            356
+#define __NR_copy_file_range   357
 
-#define NR_syscalls            357
+#define NR_syscalls            358
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
index 33c02b15f47859a8262677d08635fcfdbb8872cb..a83707c83be803b78b3019cac6dde9dba2cfabd6 100644 (file)
@@ -948,7 +948,24 @@ linux_syscall_trace:
        cmp     %o0, 0
        bne     3f
         mov    -ENOSYS, %o0
+
+       /* Syscall tracing can modify the registers.  */
+       ld      [%sp + STACKFRAME_SZ + PT_G1], %g1
+       sethi   %hi(sys_call_table), %l7
+       ld      [%sp + STACKFRAME_SZ + PT_I0], %i0
+       or      %l7, %lo(sys_call_table), %l7
+       ld      [%sp + STACKFRAME_SZ + PT_I1], %i1
+       ld      [%sp + STACKFRAME_SZ + PT_I2], %i2
+       ld      [%sp + STACKFRAME_SZ + PT_I3], %i3
+       ld      [%sp + STACKFRAME_SZ + PT_I4], %i4
+       ld      [%sp + STACKFRAME_SZ + PT_I5], %i5
+       cmp     %g1, NR_syscalls
+       bgeu    3f
+        mov    -ENOSYS, %o0
+
+       sll     %g1, 2, %l4
        mov     %i0, %o0
+       ld      [%l7 + %l4], %l7
        mov     %i1, %o1
        mov     %i2, %o2
        mov     %i3, %o3
index f2d30cab5b3f388fa9b446cf5b12afda92fa0a9d..cd1f592cd3479f8c94c599bfc589087184d4d180 100644 (file)
@@ -696,14 +696,6 @@ tlb_fixup_done:
        call    __bzero
         sub    %o1, %o0, %o1
 
-#ifdef CONFIG_LOCKDEP
-       /* We have this call this super early, as even prom_init can grab
-        * spinlocks and thus call into the lockdep code.
-        */
-       call    lockdep_init
-        nop
-#endif
-
        call    prom_init
         mov    %l7, %o0                        ! OpenPROM cif handler
 
index afbaba52d2f16cb30daf092f5cd3986e7ca9c299..d127130bf4246032d39cf923248fce7eebf92867 100644 (file)
@@ -338,8 +338,9 @@ ENTRY(sun4v_mach_set_watchdog)
        mov     %o1, %o4
        mov     HV_FAST_MACH_SET_WATCHDOG, %o5
        ta      HV_FAST_TRAP
+       brnz,a,pn %o4, 0f
        stx     %o1, [%o4]
-       retl
+0:     retl
         nop
 ENDPROC(sun4v_mach_set_watchdog)
 
index d88beff47bab3eb74fece39e282f7c701ab84868..39aaec173f66ebce88fe7953c99b412f5b07cc3d 100644 (file)
@@ -52,7 +52,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
        unsigned char fenab;
        int err;
 
-       flush_user_windows();
+       synchronize_user_stack();
        if (get_thread_wsaved()                                 ||
            (((unsigned long)ucp) & (sizeof(unsigned long)-1))  ||
            (!__access_ok(ucp, sizeof(*ucp))))
index b3a5d81b20f0f7c4fcaf669d11c90f733b2db4f2..fb30e7c6a5b15bac54e052010784327f62290589 100644 (file)
@@ -364,7 +364,7 @@ static void sparc_start_secondary(void *arg)
        local_irq_enable();
 
        wmb();
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 
        /* We should never reach here! */
        BUG();
index 19cd08d1867285f059f768402e4df14c64d7871d..8a6151a628ce9bd6b5de8a3b60f8c7e3911d6aa7 100644 (file)
@@ -134,7 +134,7 @@ void smp_callin(void)
 
        local_irq_enable();
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 void cpu_panic(void)
index a92d5d2c46a3a6553bf13a57f95f65c6d61c334c..9e034f29dcc52208ca98a648e028f955f7c8f882 100644 (file)
@@ -37,6 +37,7 @@ EXPORT_SYMBOL(sun4v_niagara_getperf);
 EXPORT_SYMBOL(sun4v_niagara_setperf);
 EXPORT_SYMBOL(sun4v_niagara2_getperf);
 EXPORT_SYMBOL(sun4v_niagara2_setperf);
+EXPORT_SYMBOL(sun4v_mach_set_watchdog);
 
 /* from hweight.S */
 EXPORT_SYMBOL(__arch_hweight8);
index c690c8e16a96ef2758fca4e9af8080ec7af6c17a..b489e9759518182b6a3884935e5a1c22b1af3524 100644 (file)
@@ -264,7 +264,7 @@ static unsigned long mmap_rnd(void)
        unsigned long rnd = 0UL;
 
        if (current->flags & PF_RANDOMIZE) {
-               unsigned long val = get_random_int();
+               unsigned long val = get_random_long();
                if (test_thread_flag(TIF_32BIT))
                        rnd = (val % (1UL << (23UL-PAGE_SHIFT)));
                else
index bb0008927598b1f7bbeeccdf30c6fa154219a4ce..c4a1b5c40e4efc7ed17bcc0d67d1f058ea4f09f8 100644 (file)
@@ -158,7 +158,25 @@ linux_syscall_trace32:
         add    %sp, PTREGS_OFF, %o0
        brnz,pn %o0, 3f
         mov    -ENOSYS, %o0
+
+       /* Syscall tracing can modify the registers.  */
+       ldx     [%sp + PTREGS_OFF + PT_V9_G1], %g1
+       sethi   %hi(sys_call_table32), %l7
+       ldx     [%sp + PTREGS_OFF + PT_V9_I0], %i0
+       or      %l7, %lo(sys_call_table32), %l7
+       ldx     [%sp + PTREGS_OFF + PT_V9_I1], %i1
+       ldx     [%sp + PTREGS_OFF + PT_V9_I2], %i2
+       ldx     [%sp + PTREGS_OFF + PT_V9_I3], %i3
+       ldx     [%sp + PTREGS_OFF + PT_V9_I4], %i4
+       ldx     [%sp + PTREGS_OFF + PT_V9_I5], %i5
+
+       cmp     %g1, NR_syscalls
+       bgeu,pn %xcc, 3f
+        mov    -ENOSYS, %o0
+
+       sll     %g1, 2, %l4
        srl     %i0, 0, %o0
+       lduw    [%l7 + %l4], %l7
        srl     %i4, 0, %o4
        srl     %i1, 0, %o1
        srl     %i2, 0, %o2
@@ -170,7 +188,25 @@ linux_syscall_trace:
         add    %sp, PTREGS_OFF, %o0
        brnz,pn %o0, 3f
         mov    -ENOSYS, %o0
+
+       /* Syscall tracing can modify the registers.  */
+       ldx     [%sp + PTREGS_OFF + PT_V9_G1], %g1
+       sethi   %hi(sys_call_table64), %l7
+       ldx     [%sp + PTREGS_OFF + PT_V9_I0], %i0
+       or      %l7, %lo(sys_call_table64), %l7
+       ldx     [%sp + PTREGS_OFF + PT_V9_I1], %i1
+       ldx     [%sp + PTREGS_OFF + PT_V9_I2], %i2
+       ldx     [%sp + PTREGS_OFF + PT_V9_I3], %i3
+       ldx     [%sp + PTREGS_OFF + PT_V9_I4], %i4
+       ldx     [%sp + PTREGS_OFF + PT_V9_I5], %i5
+
+       cmp     %g1, NR_syscalls
+       bgeu,pn %xcc, 3f
+        mov    -ENOSYS, %o0
+
+       sll     %g1, 2, %l4
        mov     %i0, %o0
+       lduw    [%l7 + %l4], %l7
        mov     %i1, %o1
        mov     %i2, %o2
        mov     %i3, %o3
index e663b6c78de2e6498a5a458f1129504cae3ab2a8..6c3dd6c52f8bd09135e81f1d56704602d10c4f4e 100644 (file)
@@ -88,4 +88,4 @@ sys_call_table:
 /*340*/        .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
 /*345*/        .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
 /*350*/        .long sys_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
-/*355*/        .long sys_setsockopt, sys_mlock2
+/*355*/        .long sys_setsockopt, sys_mlock2, sys_copy_file_range
index 1557121f4cdce8a6ae21c31fb33e9aa2d7cbc443..12b524cfcfa0120caabdf7aa5b8606ecc3978c96 100644 (file)
@@ -89,7 +89,7 @@ sys_call_table32:
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
        .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
 /*350*/        .word sys32_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
-       .word compat_sys_setsockopt, sys_mlock2
+       .word compat_sys_setsockopt, sys_mlock2, sys_copy_file_range
 
 #endif /* CONFIG_COMPAT */
 
@@ -170,4 +170,4 @@ sys_call_table:
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
        .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
 /*350*/        .word sys64_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
-       .word sys_setsockopt, sys_mlock2
+       .word sys_setsockopt, sys_mlock2, sys_copy_file_range
index 6f216853f2724f8395bdd36ab18c4eadbeae0366..1cfe6aab7a11572d54f6848fe4656b7b40af8cf2 100644 (file)
@@ -2863,17 +2863,17 @@ void hugetlb_setup(struct pt_regs *regs)
 
 static struct resource code_resource = {
        .name   = "Kernel code",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static struct resource data_resource = {
        .name   = "Kernel data",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static struct resource bss_resource = {
        .name   = "Kernel bss",
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static inline resource_size_t compute_kern_paddr(void *addr)
@@ -2909,7 +2909,7 @@ static int __init report_memory(void)
                res->name = "System RAM";
                res->start = pavail[i].phys_addr;
                res->end = pavail[i].phys_addr + pavail[i].reg_size - 1;
-               res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+               res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
 
                if (insert_resource(&iomem_resource, res) < 0) {
                        pr_warn("Resource insertion failed.\n");
index de4a4fff93237a1a9d14c6520f905a67c8ef7aad..81719302b056e095dda4c5cfd15e8a5efa18a70f 100644 (file)
@@ -455,8 +455,6 @@ config TILE_PCI_IO
 
 source "drivers/pci/Kconfig"
 
-source "drivers/pci/pcie/Kconfig"
-
 config TILE_USB
        tristate "Tilera USB host adapter support"
        default y
@@ -467,8 +465,6 @@ config TILE_USB
          Provides USB host adapter support for the built-in EHCI and OHCI
          interfaces on TILE-Gx chips.
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 menu "Executable file formats"
index dfedd7ac7298dc93424a7862ef20b2c8ce73da1f..fe3de505b02477206af012a12fe938defc172be0 100644 (file)
@@ -226,7 +226,4 @@ static inline int pcibios_assign_all_busses(void)
 /* Use any cpu for PCI. */
 #define cpumask_of_pcibus(bus) cpu_online_mask
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 #endif /* _ASM_TILE_PCI_H */
index bbb855de6569841200c991bf610b090c4e94c47b..a992238e9b58260fdfa067c4cc2c0d348ceda41f 100644 (file)
@@ -1632,14 +1632,14 @@ static struct resource data_resource = {
        .name   = "Kernel data",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static struct resource code_resource = {
        .name   = "Kernel code",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 /*
@@ -1673,10 +1673,15 @@ insert_ram_resource(u64 start_pfn, u64 end_pfn, bool reserved)
                kzalloc(sizeof(struct resource), GFP_ATOMIC);
        if (!res)
                return NULL;
-       res->name = reserved ? "Reserved" : "System RAM";
        res->start = start_pfn << PAGE_SHIFT;
        res->end = (end_pfn << PAGE_SHIFT) - 1;
        res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+       if (reserved) {
+               res->name = "Reserved";
+       } else {
+               res->name = "System RAM";
+               res->flags |= IORESOURCE_SYSRAM;
+       }
        if (insert_resource(&iomem_resource, res)) {
                kfree(res);
                return NULL;
index 20d52a98e1716be9a2ea5a58353ec78d6a44a6b9..6c0abaacec335be522041bd4634dc0561f708375 100644 (file)
@@ -208,7 +208,7 @@ void online_secondary(void)
        /* Set up tile-timer clock-event device on this cpu */
        setup_tile_timer();
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 int __cpu_up(unsigned int cpu, struct task_struct *tidle)
index 9bdf67a092a53bc9b9f68939abce7cc872e2a8b6..b60a9f8cda7550729a571c1eb6433eb83dcbd858 100644 (file)
@@ -12,6 +12,7 @@
 #include <skas.h>
 
 void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
 
 static void kill_off_processes(void)
 {
index fc8be0e3a4ff879a2cf9fddc8e017dfa974ffc95..57acbd67d85dbd4051cd3c534ceff2a300ce9906 100644 (file)
@@ -69,7 +69,7 @@ void do_signal(struct pt_regs *regs)
        struct ksignal ksig;
        int handled_sig = 0;
 
-       if (get_signal(&ksig)) {
+       while (get_signal(&ksig)) {
                handled_sig = 1;
                /* Whee!  Actually deliver the signal.  */
                handle_signal(&ksig, regs);
index 38b3f3785c3c82c6c55a98192d67bc60bd1f45a9..37e55d018de5f979051ec6526f32f5722af87bb5 100644 (file)
@@ -13,8 +13,6 @@
 #define __UNICORE_PCI_H__
 
 #ifdef __KERNEL__
-#include <asm-generic/pci-dma-compat.h>
-#include <asm-generic/pci-bridge.h>
 #include <asm-generic/pci.h>
 #include <mach/hardware.h> /* for PCIBIOS_MIN_* */
 
@@ -23,5 +21,4 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        enum pci_mmap_state mmap_state, int write_combine);
 
 #endif /* __KERNEL__ */
-
 #endif
index 9e20b5d9ed5061fb91f1b56270dbd8239992aa8d..25146232c7cf19da2b1b87ac0837363cd29f7fb1 100644 (file)
 #define PCIBIOS_MIN_IO                 0x4000 /* should lower than 64KB */
 #define PCIBIOS_MIN_MEM                        io_v2p(PKUNITY_PCIMEM_BASE)
 
-/*
- * We override the standard dma-mask routines for bouncing.
- */
-#define        HAVE_ARCH_PCI_SET_DMA_MASK
-
 #define pcibios_assign_all_busses()    1
 
 #endif  /* __MACH_PUV3_HARDWARE_H__ */
index 3fa317f96122130d30cfc7be41d4e1450fc56a02..c2bffa5614a48102a1d66a60865a2e3474a49597 100644 (file)
@@ -72,13 +72,13 @@ static struct resource mem_res[] = {
                .name = "Kernel code",
                .start = 0,
                .end = 0,
-               .flags = IORESOURCE_MEM
+               .flags = IORESOURCE_SYSTEM_RAM
        },
        {
                .name = "Kernel data",
                .start = 0,
                .end = 0,
-               .flags = IORESOURCE_MEM
+               .flags = IORESOURCE_SYSTEM_RAM
        }
 };
 
@@ -211,7 +211,7 @@ request_standard_resources(struct meminfo *mi)
                res->name  = "System RAM";
                res->start = mi->bank[i].start;
                res->end   = mi->bank[i].start + mi->bank[i].size - 1;
-               res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
                request_resource(&iomem_resource, res);
 
index 1538562cc720e78132d0eb31c38116b029d56ce0..eb3abf8ac44eb33f333ed29727dfd49ba6bfbf38 100644 (file)
@@ -1,6 +1,7 @@
-
 obj-y += entry/
 
+obj-$(CONFIG_PERF_EVENTS) += events/
+
 obj-$(CONFIG_KVM) += kvm/
 
 # Xen paravirtualization support
index c46662f64c392050d1c45b722e3de7c01f87e250..3c74b549ea9a3bbb5e3962a7d202cb8079cb1f63 100644 (file)
@@ -303,6 +303,9 @@ config ARCH_SUPPORTS_UPROBES
 config FIX_EARLYCON_MEM
        def_bool y
 
+config DEBUG_RODATA
+       def_bool y
+
 config PGTABLE_LEVELS
        int
        default 4 if X86_64
@@ -1160,22 +1163,23 @@ config MICROCODE
        bool "CPU microcode loading support"
        default y
        depends on CPU_SUP_AMD || CPU_SUP_INTEL
-       depends on BLK_DEV_INITRD
        select FW_LOADER
        ---help---
-
          If you say Y here, you will be able to update the microcode on
-         certain Intel and AMD processors. The Intel support is for the
-         IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4,
-         Xeon etc. The AMD support is for families 0x10 and later. You will
-         obviously need the actual microcode binary data itself which is not
-         shipped with the Linux kernel.
+         Intel and AMD processors. The Intel support is for the IA32 family,
+         e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, Xeon etc. The
+         AMD support is for families 0x10 and later. You will obviously need
+         the actual microcode binary data itself which is not shipped with
+         the Linux kernel.
 
-         This option selects the general module only, you need to select
-         at least one vendor specific module as well.
+         The preferred method to load microcode from a detached initrd is described
+         in Documentation/x86/early-microcode.txt. For that you need to enable
+         CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the
+         initrd for microcode blobs.
 
-         To compile this driver as a module, choose M here: the module
-         will be called microcode.
+         In addition, you can build-in the microcode into the kernel. For that you
+         need to enable FIRMWARE_IN_KERNEL and add the vendor-supplied microcode
+         to the CONFIG_EXTRA_FIRMWARE config option.
 
 config MICROCODE_INTEL
        bool "Intel microcode loading support"
@@ -2431,8 +2435,6 @@ config PCI_CNB20LE_QUIRK
 
          You should say N unless you know you need this.
 
-source "drivers/pci/pcie/Kconfig"
-
 source "drivers/pci/Kconfig"
 
 # x86_64 have no ISA slots, but can have ISA-style DMA.
@@ -2588,8 +2590,6 @@ config AMD_NB
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 config RAPIDIO
        tristate "RapidIO support"
        depends on PCI
index 9b18ed97a8a2968b7b293bc83484d8311d830e83..67eec55093a5dc97634aea899c4be86ff9f18f00 100644 (file)
@@ -74,28 +74,16 @@ config EFI_PGT_DUMP
          issues with the mapping of the EFI runtime regions into that
          table.
 
-config DEBUG_RODATA
-       bool "Write protect kernel read-only data structures"
-       default y
-       depends on DEBUG_KERNEL
-       ---help---
-         Mark the kernel read-only data as write-protected in the pagetables,
-         in order to catch accidental (and incorrect) writes to such const
-         data. This is recommended so that we can catch kernel bugs sooner.
-         If in doubt, say "Y".
-
 config DEBUG_RODATA_TEST
-       bool "Testcase for the DEBUG_RODATA feature"
-       depends on DEBUG_RODATA
+       bool "Testcase for the marking rodata read-only"
        default y
        ---help---
-         This option enables a testcase for the DEBUG_RODATA
-         feature as well as for the change_page_attr() infrastructure.
+         This option enables a testcase for the setting rodata read-only
+         as well as for the change_page_attr() infrastructure.
          If in doubt, say "N"
 
 config DEBUG_WX
        bool "Warn on W+X mappings at boot"
-       depends on DEBUG_RODATA
        select X86_PTDUMP_CORE
        ---help---
          Generate a warning if any W+X mappings are found at boot.
@@ -350,16 +338,6 @@ config DEBUG_IMR_SELFTEST
 
          If unsure say N here.
 
-config X86_DEBUG_STATIC_CPU_HAS
-       bool "Debug alternatives"
-       depends on DEBUG_KERNEL
-       ---help---
-         This option causes additional code to be generated which
-         fails if static_cpu_has() is used before alternatives have
-         run.
-
-         If unsure, say N.
-
 config X86_DEBUG_FPU
        bool "Debug the x86 FPU code"
        depends on DEBUG_KERNEL
index ea97697e51e40fd2ff232caa5e3147ff0f6e725c..4cb404fd45ceaa0e89f9e669d6a59de4ce378449 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef BOOT_CPUFLAGS_H
 #define BOOT_CPUFLAGS_H
 
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/processor-flags.h>
 
 struct cpu_features {
index 637097e66a62a675de99040bdcf4f8fc011e2af0..f72498dc90d2376f5f0ffafbc4305be959344343 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "../include/asm/required-features.h"
 #include "../include/asm/disabled-features.h"
-#include "../include/asm/cpufeature.h"
+#include "../include/asm/cpufeatures.h"
 #include "../kernel/cpu/capflags.c"
 
 int main(void)
index a7661c430cd98d28795ddee61bf5506c5ef3a1e5..0702d2531bc7f441364adca7ebc2d0e1a227f0bd 100644 (file)
@@ -49,7 +49,6 @@ typedef unsigned int   u32;
 
 /* This must be large enough to hold the entire setup */
 u8 buf[SETUP_SECT_MAX*512];
-int is_big_kernel;
 
 #define PECOFF_RELOC_RESERVE 0x20
 
index 028be48c883974058e877494764dcbca8c0af48d..e25a1630320cc47b3112b8082eaba3cb66cc0cee 100644 (file)
@@ -288,7 +288,7 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=y
 CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
-CONFIG_FRAME_WARN=2048
+CONFIG_FRAME_WARN=1024
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
index 07d2c6c86a5483216684970489fcba3b4478007d..27226df3f7d8aa16a647a051d8ac19ef02ef5aa2 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/crc32.h>
 #include <crypto/internal/hash.h>
 
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/cpu_device_id.h>
 #include <asm/fpu/api.h>
 
index 0e9871693f2469d3106f57ab6dc94d85a3f16146..0857b1a1de3bdc411b3fea94517a9db6c9b9952c 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/kernel.h>
 #include <crypto/internal/hash.h>
 
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/cpu_device_id.h>
 #include <asm/fpu/internal.h>
 
index a3fcfc97a311d5b660e0dcda3be489038f231dce..cd4df93225014b6fc64e3020bf07c0600647fd7c 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <asm/fpu/api.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/cpu_device_id.h>
 
 asmlinkage __u16 crc_t10dif_pcl(__u16 crc, const unsigned char *buf,
index e32206e0986828390e769604ec6cd510b1f2296e..9a9e5884066c6581878b56cde27e75f542b21249 100644 (file)
@@ -201,37 +201,6 @@ For 32-bit we have the following conventions - kernel is built with
        .byte 0xf1
        .endm
 
-#else /* CONFIG_X86_64 */
-
-/*
- * For 32bit only simplified versions of SAVE_ALL/RESTORE_ALL. These
- * are different from the entry_32.S versions in not changing the segment
- * registers. So only suitable for in kernel use, not when transitioning
- * from or to user space. The resulting stack frame is not a standard
- * pt_regs frame. The main use case is calling C code from assembler
- * when all the registers need to be preserved.
- */
-
-       .macro SAVE_ALL
-       pushl %eax
-       pushl %ebp
-       pushl %edi
-       pushl %esi
-       pushl %edx
-       pushl %ecx
-       pushl %ebx
-       .endm
-
-       .macro RESTORE_ALL
-       popl %ebx
-       popl %ecx
-       popl %edx
-       popl %esi
-       popl %edi
-       popl %ebp
-       popl %eax
-       .endm
-
 #endif /* CONFIG_X86_64 */
 
 /*
index 03663740c86655cabf21504578e97d73d98595be..e79d93d44ecd9c66b1e29078a11aa1ee405c0fa2 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/traps.h>
 #include <asm/vdso.h>
 #include <asm/uaccess.h>
+#include <asm/cpufeature.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
@@ -44,6 +45,8 @@ __visible void enter_from_user_mode(void)
        CT_WARN_ON(ct_state() != CONTEXT_USER);
        user_exit();
 }
+#else
+static inline void enter_from_user_mode(void) {}
 #endif
 
 static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
@@ -84,17 +87,6 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
 
        work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY;
 
-#ifdef CONFIG_CONTEXT_TRACKING
-       /*
-        * If TIF_NOHZ is set, we are required to call user_exit() before
-        * doing anything that could touch RCU.
-        */
-       if (work & _TIF_NOHZ) {
-               enter_from_user_mode();
-               work &= ~_TIF_NOHZ;
-       }
-#endif
-
 #ifdef CONFIG_SECCOMP
        /*
         * Do seccomp first -- it should minimize exposure of other
@@ -171,16 +163,6 @@ long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
        if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
                BUG_ON(regs != task_pt_regs(current));
 
-       /*
-        * If we stepped into a sysenter/syscall insn, it trapped in
-        * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP.
-        * If user-mode had set TF itself, then it's still clear from
-        * do_debug() and we need to set it again to restore the user
-        * state.  If we entered on the slow path, TF was already set.
-        */
-       if (work & _TIF_SINGLESTEP)
-               regs->flags |= X86_EFLAGS_TF;
-
 #ifdef CONFIG_SECCOMP
        /*
         * Call seccomp_phase2 before running the other hooks so that
@@ -268,6 +250,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
 /* Called with IRQs disabled. */
 __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
 {
+       struct thread_info *ti = pt_regs_to_thread_info(regs);
        u32 cached_flags;
 
        if (IS_ENABLED(CONFIG_PROVE_LOCKING) && WARN_ON(!irqs_disabled()))
@@ -275,12 +258,22 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
 
        lockdep_sys_exit();
 
-       cached_flags =
-               READ_ONCE(pt_regs_to_thread_info(regs)->flags);
+       cached_flags = READ_ONCE(ti->flags);
 
        if (unlikely(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS))
                exit_to_usermode_loop(regs, cached_flags);
 
+#ifdef CONFIG_COMPAT
+       /*
+        * Compat syscalls set TS_COMPAT.  Make sure we clear it before
+        * returning to user mode.  We need to clear it *after* signal
+        * handling, because syscall restart has a fixup for compat
+        * syscalls.  The fixup is exercised by the ptrace_syscall_32
+        * selftest.
+        */
+       ti->status &= ~TS_COMPAT;
+#endif
+
        user_enter();
 }
 
@@ -332,33 +325,45 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs)
        if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS))
                syscall_slow_exit_work(regs, cached_flags);
 
-#ifdef CONFIG_COMPAT
+       local_irq_disable();
+       prepare_exit_to_usermode(regs);
+}
+
+#ifdef CONFIG_X86_64
+__visible void do_syscall_64(struct pt_regs *regs)
+{
+       struct thread_info *ti = pt_regs_to_thread_info(regs);
+       unsigned long nr = regs->orig_ax;
+
+       enter_from_user_mode();
+       local_irq_enable();
+
+       if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY)
+               nr = syscall_trace_enter(regs);
+
        /*
-        * Compat syscalls set TS_COMPAT.  Make sure we clear it before
-        * returning to user mode.
+        * NB: Native and x32 syscalls are dispatched from the same
+        * table.  The only functional difference is the x32 bit in
+        * regs->orig_ax, which changes the behavior of some syscalls.
         */
-       ti->status &= ~TS_COMPAT;
-#endif
+       if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) {
+               regs->ax = sys_call_table[nr & __SYSCALL_MASK](
+                       regs->di, regs->si, regs->dx,
+                       regs->r10, regs->r8, regs->r9);
+       }
 
-       local_irq_disable();
-       prepare_exit_to_usermode(regs);
+       syscall_return_slowpath(regs);
 }
+#endif
 
 #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
 /*
- * Does a 32-bit syscall.  Called with IRQs on and does all entry and
- * exit work and returns with IRQs off.  This function is extremely hot
- * in workloads that use it, and it's usually called from
+ * Does a 32-bit syscall.  Called with IRQs on in CONTEXT_KERNEL.  Does
+ * all entry and exit work and returns with IRQs off.  This function is
+ * extremely hot in workloads that use it, and it's usually called from
  * do_fast_syscall_32, so forcibly inline it to improve performance.
  */
-#ifdef CONFIG_X86_32
-/* 32-bit kernels use a trap gate for INT80, and the asm code calls here. */
-__visible
-#else
-/* 64-bit kernels use do_syscall_32_irqs_off() instead. */
-static
-#endif
-__always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
+static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
 {
        struct thread_info *ti = pt_regs_to_thread_info(regs);
        unsigned int nr = (unsigned int)regs->orig_ax;
@@ -393,14 +398,13 @@ __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
        syscall_return_slowpath(regs);
 }
 
-#ifdef CONFIG_X86_64
-/* Handles INT80 on 64-bit kernels */
-__visible void do_syscall_32_irqs_off(struct pt_regs *regs)
+/* Handles int $0x80 */
+__visible void do_int80_syscall_32(struct pt_regs *regs)
 {
+       enter_from_user_mode();
        local_irq_enable();
        do_syscall_32_irqs_on(regs);
 }
-#endif
 
 /* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
 __visible long do_fast_syscall_32(struct pt_regs *regs)
@@ -420,12 +424,11 @@ __visible long do_fast_syscall_32(struct pt_regs *regs)
         */
        regs->ip = landing_pad;
 
-       /*
-        * Fetch EBP from where the vDSO stashed it.
-        *
-        * WARNING: We are in CONTEXT_USER and RCU isn't paying attention!
-        */
+       enter_from_user_mode();
+
        local_irq_enable();
+
+       /* Fetch EBP from where the vDSO stashed it. */
        if (
 #ifdef CONFIG_X86_64
                /*
@@ -443,9 +446,6 @@ __visible long do_fast_syscall_32(struct pt_regs *regs)
                /* User code screwed up. */
                local_irq_disable();
                regs->ax = -EFAULT;
-#ifdef CONFIG_CONTEXT_TRACKING
-               enter_from_user_mode();
-#endif
                prepare_exit_to_usermode(regs);
                return 0;       /* Keep it simple: use IRET. */
        }
index 77d8c5112900e0edb73741af9c7cc4a60b0bb8f5..10868aa734dc07e9a438bcdd3d4c7b4aae0106d3 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/processor-flags.h>
 #include <asm/ftrace.h>
 #include <asm/irq_vectors.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
 #include <asm/asm.h>
 #include <asm/smap.h>
@@ -287,7 +287,58 @@ need_resched:
 END(resume_kernel)
 #endif
 
-       # SYSENTER  call handler stub
+GLOBAL(__begin_SYSENTER_singlestep_region)
+/*
+ * All code from here through __end_SYSENTER_singlestep_region is subject
+ * to being single-stepped if a user program sets TF and executes SYSENTER.
+ * There is absolutely nothing that we can do to prevent this from happening
+ * (thanks Intel!).  To keep our handling of this situation as simple as
+ * possible, we handle TF just like AC and NT, except that our #DB handler
+ * will ignore all of the single-step traps generated in this range.
+ */
+
+#ifdef CONFIG_XEN
+/*
+ * Xen doesn't set %esp to be precisely what the normal SYSENTER
+ * entry point expects, so fix it up before using the normal path.
+ */
+ENTRY(xen_sysenter_target)
+       addl    $5*4, %esp                      /* remove xen-provided frame */
+       jmp     sysenter_past_esp
+#endif
+
+/*
+ * 32-bit SYSENTER entry.
+ *
+ * 32-bit system calls through the vDSO's __kernel_vsyscall enter here
+ * if X86_FEATURE_SEP is available.  This is the preferred system call
+ * entry on 32-bit systems.
+ *
+ * The SYSENTER instruction, in principle, should *only* occur in the
+ * vDSO.  In practice, a small number of Android devices were shipped
+ * with a copy of Bionic that inlined a SYSENTER instruction.  This
+ * never happened in any of Google's Bionic versions -- it only happened
+ * in a narrow range of Intel-provided versions.
+ *
+ * SYSENTER loads SS, ESP, CS, and EIP from previously programmed MSRs.
+ * IF and VM in RFLAGS are cleared (IOW: interrupts are off).
+ * SYSENTER does not save anything on the stack,
+ * and does not save old EIP (!!!), ESP, or EFLAGS.
+ *
+ * To avoid losing track of EFLAGS.VM (and thus potentially corrupting
+ * user and/or vm86 state), we explicitly disable the SYSENTER
+ * instruction in vm86 mode by reprogramming the MSRs.
+ *
+ * Arguments:
+ * eax  system call number
+ * ebx  arg1
+ * ecx  arg2
+ * edx  arg3
+ * esi  arg4
+ * edi  arg5
+ * ebp  user stack
+ * 0(%ebp) arg6
+ */
 ENTRY(entry_SYSENTER_32)
        movl    TSS_sysenter_sp0(%esp), %esp
 sysenter_past_esp:
@@ -300,6 +351,29 @@ sysenter_past_esp:
        pushl   %eax                    /* pt_regs->orig_ax */
        SAVE_ALL pt_regs_ax=$-ENOSYS    /* save rest */
 
+       /*
+        * SYSENTER doesn't filter flags, so we need to clear NT, AC
+        * and TF ourselves.  To save a few cycles, we can check whether
+        * either was set instead of doing an unconditional popfq.
+        * This needs to happen before enabling interrupts so that
+        * we don't get preempted with NT set.
+        *
+        * If TF is set, we will single-step all the way to here -- do_debug
+        * will ignore all the traps.  (Yes, this is slow, but so is
+        * single-stepping in general.  This allows us to avoid having
+        * a more complicated code to handle the case where a user program
+        * forces us to single-step through the SYSENTER entry code.)
+        *
+        * NB.: .Lsysenter_fix_flags is a label with the code under it moved
+        * out-of-line as an optimization: NT is unlikely to be set in the
+        * majority of the cases and instead of polluting the I$ unnecessarily,
+        * we're keeping that code behind a branch which will predict as
+        * not-taken and therefore its instructions won't be fetched.
+        */
+       testl   $X86_EFLAGS_NT|X86_EFLAGS_AC|X86_EFLAGS_TF, PT_EFLAGS(%esp)
+       jnz     .Lsysenter_fix_flags
+.Lsysenter_flags_fixed:
+
        /*
         * User mode is traced as though IRQs are on, and SYSENTER
         * turned them off.
@@ -325,6 +399,15 @@ sysenter_past_esp:
        popl    %ebp                    /* pt_regs->bp */
        popl    %eax                    /* pt_regs->ax */
 
+       /*
+        * Restore all flags except IF. (We restore IF separately because
+        * STI gives a one-instruction window in which we won't be interrupted,
+        * whereas POPF does not.)
+        */
+       addl    $PT_EFLAGS-PT_DS, %esp  /* point esp at pt_regs->flags */
+       btr     $X86_EFLAGS_IF_BIT, (%esp)
+       popfl
+
        /*
         * Return back to the vDSO, which will pop ecx and edx.
         * Don't bother with DS and ES (they already contain __USER_DS).
@@ -338,28 +421,63 @@ sysenter_past_esp:
 .popsection
        _ASM_EXTABLE(1b, 2b)
        PTGS_TO_GS_EX
+
+.Lsysenter_fix_flags:
+       pushl   $X86_EFLAGS_FIXED
+       popfl
+       jmp     .Lsysenter_flags_fixed
+GLOBAL(__end_SYSENTER_singlestep_region)
 ENDPROC(entry_SYSENTER_32)
 
-       # system call handler stub
+/*
+ * 32-bit legacy system call entry.
+ *
+ * 32-bit x86 Linux system calls traditionally used the INT $0x80
+ * instruction.  INT $0x80 lands here.
+ *
+ * This entry point can be used by any 32-bit perform system calls.
+ * Instances of INT $0x80 can be found inline in various programs and
+ * libraries.  It is also used by the vDSO's __kernel_vsyscall
+ * fallback for hardware that doesn't support a faster entry method.
+ * Restarted 32-bit system calls also fall back to INT $0x80
+ * regardless of what instruction was originally used to do the system
+ * call.  (64-bit programs can use INT $0x80 as well, but they can
+ * only run on 64-bit kernels and therefore land in
+ * entry_INT80_compat.)
+ *
+ * This is considered a slow path.  It is not used by most libc
+ * implementations on modern hardware except during process startup.
+ *
+ * Arguments:
+ * eax  system call number
+ * ebx  arg1
+ * ecx  arg2
+ * edx  arg3
+ * esi  arg4
+ * edi  arg5
+ * ebp  arg6
+ */
 ENTRY(entry_INT80_32)
        ASM_CLAC
        pushl   %eax                    /* pt_regs->orig_ax */
        SAVE_ALL pt_regs_ax=$-ENOSYS    /* save rest */
 
        /*
-        * User mode is traced as though IRQs are on.  Unlike the 64-bit
-        * case, INT80 is a trap gate on 32-bit kernels, so interrupts
-        * are already on (unless user code is messing around with iopl).
+        * User mode is traced as though IRQs are on, and the interrupt gate
+        * turned them off.
         */
+       TRACE_IRQS_OFF
 
        movl    %esp, %eax
-       call    do_syscall_32_irqs_on
+       call    do_int80_syscall_32
 .Lsyscall_32_done:
 
 restore_all:
        TRACE_IRQS_IRET
 restore_all_notrace:
 #ifdef CONFIG_X86_ESPFIX32
+       ALTERNATIVE     "jmp restore_nocheck", "", X86_BUG_ESPFIX
+
        movl    PT_EFLAGS(%esp), %eax           # mix EFLAGS, SS and CS
        /*
         * Warning: PT_OLDSS(%esp) contains the wrong/random values if we
@@ -386,19 +504,6 @@ ENTRY(iret_exc     )
 
 #ifdef CONFIG_X86_ESPFIX32
 ldt_ss:
-#ifdef CONFIG_PARAVIRT
-       /*
-        * The kernel can't run on a non-flat stack if paravirt mode
-        * is active.  Rather than try to fixup the high bits of
-        * ESP, bypass this code entirely.  This may break DOSemu
-        * and/or Wine support in a paravirt VM, although the option
-        * is still available to implement the setting of the high
-        * 16-bits in the INTERRUPT_RETURN paravirt-op.
-        */
-       cmpl    $0, pv_info+PARAVIRT_enabled
-       jne     restore_nocheck
-#endif
-
 /*
  * Setup and switch to ESPFIX stack
  *
@@ -631,14 +736,6 @@ ENTRY(spurious_interrupt_bug)
 END(spurious_interrupt_bug)
 
 #ifdef CONFIG_XEN
-/*
- * Xen doesn't set %esp to be precisely what the normal SYSENTER
- * entry point expects, so fix it up before using the normal path.
- */
-ENTRY(xen_sysenter_target)
-       addl    $5*4, %esp                      /* remove xen-provided frame */
-       jmp     sysenter_past_esp
-
 ENTRY(xen_hypervisor_callback)
        pushl   $-1                             /* orig_ax = -1 => not a system call */
        SAVE_ALL
@@ -938,51 +1035,48 @@ error_code:
        jmp     ret_from_exception
 END(page_fault)
 
-/*
- * Debug traps and NMI can happen at the one SYSENTER instruction
- * that sets up the real kernel stack. Check here, since we can't
- * allow the wrong stack to be used.
- *
- * "TSS_sysenter_sp0+12" is because the NMI/debug handler will have
- * already pushed 3 words if it hits on the sysenter instruction:
- * eflags, cs and eip.
- *
- * We just load the right stack, and push the three (known) values
- * by hand onto the new stack - while updating the return eip past
- * the instruction that would have done it for sysenter.
- */
-.macro FIX_STACK offset ok label
-       cmpw    $__KERNEL_CS, 4(%esp)
-       jne     \ok
-\label:
-       movl    TSS_sysenter_sp0 + \offset(%esp), %esp
-       pushfl
-       pushl   $__KERNEL_CS
-       pushl   $sysenter_past_esp
-.endm
-
 ENTRY(debug)
+       /*
+        * #DB can happen at the first instruction of
+        * entry_SYSENTER_32 or in Xen's SYSENTER prologue.  If this
+        * happens, then we will be running on a very small stack.  We
+        * need to detect this condition and switch to the thread
+        * stack before calling any C code at all.
+        *
+        * If you edit this code, keep in mind that NMIs can happen in here.
+        */
        ASM_CLAC
-       cmpl    $entry_SYSENTER_32, (%esp)
-       jne     debug_stack_correct
-       FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn
-debug_stack_correct:
        pushl   $-1                             # mark this as an int
        SAVE_ALL
-       TRACE_IRQS_OFF
        xorl    %edx, %edx                      # error code 0
        movl    %esp, %eax                      # pt_regs pointer
+
+       /* Are we currently on the SYSENTER stack? */
+       PER_CPU(cpu_tss + CPU_TSS_SYSENTER_stack + SIZEOF_SYSENTER_stack, %ecx)
+       subl    %eax, %ecx      /* ecx = (end of SYSENTER_stack) - esp */
+       cmpl    $SIZEOF_SYSENTER_stack, %ecx
+       jb      .Ldebug_from_sysenter_stack
+
+       TRACE_IRQS_OFF
+       call    do_debug
+       jmp     ret_from_exception
+
+.Ldebug_from_sysenter_stack:
+       /* We're on the SYSENTER stack.  Switch off. */
+       movl    %esp, %ebp
+       movl    PER_CPU_VAR(cpu_current_top_of_stack), %esp
+       TRACE_IRQS_OFF
        call    do_debug
+       movl    %ebp, %esp
        jmp     ret_from_exception
 END(debug)
 
 /*
- * NMI is doubly nasty. It can happen _while_ we're handling
- * a debug fault, and the debug fault hasn't yet been able to
- * clear up the stack. So we first check whether we got  an
- * NMI on the sysenter entry path, but after that we need to
- * check whether we got an NMI on the debug path where the debug
- * fault happened on the sysenter path.
+ * NMI is doubly nasty.  It can happen on the first instruction of
+ * entry_SYSENTER_32 (just like #DB), but it can also interrupt the beginning
+ * of the #DB handler even if that #DB in turn hit before entry_SYSENTER_32
+ * switched stacks.  We handle both conditions by simply checking whether we
+ * interrupted kernel code running on the SYSENTER stack.
  */
 ENTRY(nmi)
        ASM_CLAC
@@ -993,41 +1087,32 @@ ENTRY(nmi)
        popl    %eax
        je      nmi_espfix_stack
 #endif
-       cmpl    $entry_SYSENTER_32, (%esp)
-       je      nmi_stack_fixup
-       pushl   %eax
-       movl    %esp, %eax
-       /*
-        * Do not access memory above the end of our stack page,
-        * it might not exist.
-        */
-       andl    $(THREAD_SIZE-1), %eax
-       cmpl    $(THREAD_SIZE-20), %eax
-       popl    %eax
-       jae     nmi_stack_correct
-       cmpl    $entry_SYSENTER_32, 12(%esp)
-       je      nmi_debug_stack_check
-nmi_stack_correct:
-       pushl   %eax
+
+       pushl   %eax                            # pt_regs->orig_ax
        SAVE_ALL
        xorl    %edx, %edx                      # zero error code
        movl    %esp, %eax                      # pt_regs pointer
+
+       /* Are we currently on the SYSENTER stack? */
+       PER_CPU(cpu_tss + CPU_TSS_SYSENTER_stack + SIZEOF_SYSENTER_stack, %ecx)
+       subl    %eax, %ecx      /* ecx = (end of SYSENTER_stack) - esp */
+       cmpl    $SIZEOF_SYSENTER_stack, %ecx
+       jb      .Lnmi_from_sysenter_stack
+
+       /* Not on SYSENTER stack. */
        call    do_nmi
        jmp     restore_all_notrace
 
-nmi_stack_fixup:
-       FIX_STACK 12, nmi_stack_correct, 1
-       jmp     nmi_stack_correct
-
-nmi_debug_stack_check:
-       cmpw    $__KERNEL_CS, 16(%esp)
-       jne     nmi_stack_correct
-       cmpl    $debug, (%esp)
-       jb      nmi_stack_correct
-       cmpl    $debug_esp_fix_insn, (%esp)
-       ja      nmi_stack_correct
-       FIX_STACK 24, nmi_stack_correct, 1
-       jmp     nmi_stack_correct
+.Lnmi_from_sysenter_stack:
+       /*
+        * We're on the SYSENTER stack.  Switch off.  No one (not even debug)
+        * is using the thread stack right now, so it's safe for us to use it.
+        */
+       movl    %esp, %ebp
+       movl    PER_CPU_VAR(cpu_current_top_of_stack), %esp
+       call    do_nmi
+       movl    %ebp, %esp
+       jmp     restore_all_notrace
 
 #ifdef CONFIG_X86_ESPFIX32
 nmi_espfix_stack:
index 9d34d3cfceb61c1073c507f5a0f90e939eb146a3..858b555e274b8d763d97d9b9cf14998125bce563 100644 (file)
@@ -103,6 +103,16 @@ ENDPROC(native_usergs_sysret64)
 /*
  * 64-bit SYSCALL instruction entry. Up to 6 arguments in registers.
  *
+ * This is the only entry point used for 64-bit system calls.  The
+ * hardware interface is reasonably well designed and the register to
+ * argument mapping Linux uses fits well with the registers that are
+ * available when SYSCALL is used.
+ *
+ * SYSCALL instructions can be found inlined in libc implementations as
+ * well as some other programs and libraries.  There are also a handful
+ * of SYSCALL instructions in the vDSO used, for example, as a
+ * clock_gettimeofday fallback.
+ *
  * 64-bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
  * then loads new ss, cs, and rip from previously programmed MSRs.
  * rflags gets masked by a value from another MSR (so CLD and CLAC
@@ -145,17 +155,11 @@ GLOBAL(entry_SYSCALL_64_after_swapgs)
        movq    %rsp, PER_CPU_VAR(rsp_scratch)
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 
+       TRACE_IRQS_OFF
+
        /* Construct struct pt_regs on stack */
        pushq   $__USER_DS                      /* pt_regs->ss */
        pushq   PER_CPU_VAR(rsp_scratch)        /* pt_regs->sp */
-       /*
-        * Re-enable interrupts.
-        * We use 'rsp_scratch' as a scratch space, hence irq-off block above
-        * must execute atomically in the face of possible interrupt-driven
-        * task preemption. We must enable interrupts only after we're done
-        * with using rsp_scratch:
-        */
-       ENABLE_INTERRUPTS(CLBR_NONE)
        pushq   %r11                            /* pt_regs->flags */
        pushq   $__USER_CS                      /* pt_regs->cs */
        pushq   %rcx                            /* pt_regs->ip */
@@ -171,9 +175,21 @@ GLOBAL(entry_SYSCALL_64_after_swapgs)
        pushq   %r11                            /* pt_regs->r11 */
        sub     $(6*8), %rsp                    /* pt_regs->bp, bx, r12-15 not saved */
 
-       testl   $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
-       jnz     tracesys
+       /*
+        * If we need to do entry work or if we guess we'll need to do
+        * exit work, go straight to the slow path.
+        */
+       testl   $_TIF_WORK_SYSCALL_ENTRY|_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
+       jnz     entry_SYSCALL64_slow_path
+
 entry_SYSCALL_64_fastpath:
+       /*
+        * Easy case: enable interrupts and issue the syscall.  If the syscall
+        * needs pt_regs, we'll call a stub that disables interrupts again
+        * and jumps to the slow path.
+        */
+       TRACE_IRQS_ON
+       ENABLE_INTERRUPTS(CLBR_NONE)
 #if __SYSCALL_MASK == ~0
        cmpq    $__NR_syscall_max, %rax
 #else
@@ -182,103 +198,56 @@ entry_SYSCALL_64_fastpath:
 #endif
        ja      1f                              /* return -ENOSYS (already in pt_regs->ax) */
        movq    %r10, %rcx
+
+       /*
+        * This call instruction is handled specially in stub_ptregs_64.
+        * It might end up jumping to the slow path.  If it jumps, RAX
+        * and all argument registers are clobbered.
+        */
        call    *sys_call_table(, %rax, 8)
+.Lentry_SYSCALL_64_after_fastpath_call:
+
        movq    %rax, RAX(%rsp)
 1:
-/*
- * Syscall return path ending with SYSRET (fast path).
- * Has incompletely filled pt_regs.
- */
-       LOCKDEP_SYS_EXIT
-       /*
-        * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
-        * it is too small to ever cause noticeable irq latency.
-        */
-       DISABLE_INTERRUPTS(CLBR_NONE)
 
        /*
-        * We must check ti flags with interrupts (or at least preemption)
-        * off because we must *never* return to userspace without
-        * processing exit work that is enqueued if we're preempted here.
-        * In particular, returning to userspace with any of the one-shot
-        * flags (TIF_NOTIFY_RESUME, TIF_USER_RETURN_NOTIFY, etc) set is
-        * very bad.
+        * If we get here, then we know that pt_regs is clean for SYSRET64.
+        * If we see that no exit work is required (which we are required
+        * to check with IRQs off), then we can go straight to SYSRET64.
         */
+       DISABLE_INTERRUPTS(CLBR_NONE)
+       TRACE_IRQS_OFF
        testl   $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
-       jnz     int_ret_from_sys_call_irqs_off  /* Go to the slow path */
+       jnz     1f
 
-       RESTORE_C_REGS_EXCEPT_RCX_R11
+       LOCKDEP_SYS_EXIT
+       TRACE_IRQS_ON           /* user mode is traced as IRQs on */
        movq    RIP(%rsp), %rcx
        movq    EFLAGS(%rsp), %r11
+       RESTORE_C_REGS_EXCEPT_RCX_R11
        movq    RSP(%rsp), %rsp
-       /*
-        * 64-bit SYSRET restores rip from rcx,
-        * rflags from r11 (but RF and VM bits are forced to 0),
-        * cs and ss are loaded from MSRs.
-        * Restoration of rflags re-enables interrupts.
-        *
-        * NB: On AMD CPUs with the X86_BUG_SYSRET_SS_ATTRS bug, the ss
-        * descriptor is not reinitialized.  This means that we should
-        * avoid SYSRET with SS == NULL, which could happen if we schedule,
-        * exit the kernel, and re-enter using an interrupt vector.  (All
-        * interrupt entries on x86_64 set SS to NULL.)  We prevent that
-        * from happening by reloading SS in __switch_to.  (Actually
-        * detecting the failure in 64-bit userspace is tricky but can be
-        * done.)
-        */
        USERGS_SYSRET64
 
-GLOBAL(int_ret_from_sys_call_irqs_off)
+1:
+       /*
+        * The fast path looked good when we started, but something changed
+        * along the way and we need to switch to the slow path.  Calling
+        * raise(3) will trigger this, for example.  IRQs are off.
+        */
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-       jmp int_ret_from_sys_call
-
-       /* Do syscall entry tracing */
-tracesys:
-       movq    %rsp, %rdi
-       movl    $AUDIT_ARCH_X86_64, %esi
-       call    syscall_trace_enter_phase1
-       test    %rax, %rax
-       jnz     tracesys_phase2                 /* if needed, run the slow path */
-       RESTORE_C_REGS_EXCEPT_RAX               /* else restore clobbered regs */
-       movq    ORIG_RAX(%rsp), %rax
-       jmp     entry_SYSCALL_64_fastpath       /* and return to the fast path */
-
-tracesys_phase2:
        SAVE_EXTRA_REGS
        movq    %rsp, %rdi
-       movl    $AUDIT_ARCH_X86_64, %esi
-       movq    %rax, %rdx
-       call    syscall_trace_enter_phase2
-
-       /*
-        * Reload registers from stack in case ptrace changed them.
-        * We don't reload %rax because syscall_trace_entry_phase2() returned
-        * the value it wants us to use in the table lookup.
-        */
-       RESTORE_C_REGS_EXCEPT_RAX
-       RESTORE_EXTRA_REGS
-#if __SYSCALL_MASK == ~0
-       cmpq    $__NR_syscall_max, %rax
-#else
-       andl    $__SYSCALL_MASK, %eax
-       cmpl    $__NR_syscall_max, %eax
-#endif
-       ja      1f                              /* return -ENOSYS (already in pt_regs->ax) */
-       movq    %r10, %rcx                      /* fixup for C */
-       call    *sys_call_table(, %rax, 8)
-       movq    %rax, RAX(%rsp)
-1:
-       /* Use IRET because user could have changed pt_regs->foo */
+       call    syscall_return_slowpath /* returns with IRQs disabled */
+       jmp     return_from_SYSCALL_64
 
-/*
- * Syscall return path ending with IRET.
- * Has correct iret frame.
- */
-GLOBAL(int_ret_from_sys_call)
+entry_SYSCALL64_slow_path:
+       /* IRQs are off. */
        SAVE_EXTRA_REGS
        movq    %rsp, %rdi
-       call    syscall_return_slowpath /* returns with IRQs disabled */
+       call    do_syscall_64           /* returns with IRQs disabled */
+
+return_from_SYSCALL_64:
        RESTORE_EXTRA_REGS
        TRACE_IRQS_IRETQ                /* we're about to change IF */
 
@@ -355,83 +324,45 @@ opportunistic_sysret_failed:
        jmp     restore_c_regs_and_iret
 END(entry_SYSCALL_64)
 
+ENTRY(stub_ptregs_64)
+       /*
+        * Syscalls marked as needing ptregs land here.
+        * If we are on the fast path, we need to save the extra regs,
+        * which we achieve by trying again on the slow path.  If we are on
+        * the slow path, the extra regs are already saved.
+        *
+        * RAX stores a pointer to the C function implementing the syscall.
+        * IRQs are on.
+        */
+       cmpq    $.Lentry_SYSCALL_64_after_fastpath_call, (%rsp)
+       jne     1f
 
-       .macro FORK_LIKE func
-ENTRY(stub_\func)
-       SAVE_EXTRA_REGS 8
-       jmp     sys_\func
-END(stub_\func)
-       .endm
-
-       FORK_LIKE  clone
-       FORK_LIKE  fork
-       FORK_LIKE  vfork
-
-ENTRY(stub_execve)
-       call    sys_execve
-return_from_execve:
-       testl   %eax, %eax
-       jz      1f
-       /* exec failed, can use fast SYSRET code path in this case */
-       ret
-1:
-       /* must use IRET code path (pt_regs->cs may have changed) */
-       addq    $8, %rsp
-       ZERO_EXTRA_REGS
-       movq    %rax, RAX(%rsp)
-       jmp     int_ret_from_sys_call
-END(stub_execve)
-/*
- * Remaining execve stubs are only 7 bytes long.
- * ENTRY() often aligns to 16 bytes, which in this case has no benefits.
- */
-       .align  8
-GLOBAL(stub_execveat)
-       call    sys_execveat
-       jmp     return_from_execve
-END(stub_execveat)
-
-#if defined(CONFIG_X86_X32_ABI)
-       .align  8
-GLOBAL(stub_x32_execve)
-       call    compat_sys_execve
-       jmp     return_from_execve
-END(stub_x32_execve)
-       .align  8
-GLOBAL(stub_x32_execveat)
-       call    compat_sys_execveat
-       jmp     return_from_execve
-END(stub_x32_execveat)
-#endif
-
-/*
- * sigreturn is special because it needs to restore all registers on return.
- * This cannot be done with SYSRET, so use the IRET return path instead.
- */
-ENTRY(stub_rt_sigreturn)
        /*
-        * SAVE_EXTRA_REGS result is not normally needed:
-        * sigreturn overwrites all pt_regs->GPREGS.
-        * But sigreturn can fail (!), and there is no easy way to detect that.
-        * To make sure RESTORE_EXTRA_REGS doesn't restore garbage on error,
-        * we SAVE_EXTRA_REGS here.
+        * Called from fast path -- disable IRQs again, pop return address
+        * and jump to slow path
         */
-       SAVE_EXTRA_REGS 8
-       call    sys_rt_sigreturn
-return_from_stub:
-       addq    $8, %rsp
-       RESTORE_EXTRA_REGS
-       movq    %rax, RAX(%rsp)
-       jmp     int_ret_from_sys_call
-END(stub_rt_sigreturn)
+       DISABLE_INTERRUPTS(CLBR_NONE)
+       TRACE_IRQS_OFF
+       popq    %rax
+       jmp     entry_SYSCALL64_slow_path
 
-#ifdef CONFIG_X86_X32_ABI
-ENTRY(stub_x32_rt_sigreturn)
-       SAVE_EXTRA_REGS 8
-       call    sys32_x32_rt_sigreturn
-       jmp     return_from_stub
-END(stub_x32_rt_sigreturn)
-#endif
+1:
+       /* Called from C */
+       jmp     *%rax                           /* called from C */
+END(stub_ptregs_64)
+
+.macro ptregs_stub func
+ENTRY(ptregs_\func)
+       leaq    \func(%rip), %rax
+       jmp     stub_ptregs_64
+END(ptregs_\func)
+.endm
+
+/* Instantiate ptregs_stub for each ptregs-using syscall */
+#define __SYSCALL_64_QUAL_(sym)
+#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_stub sym
+#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(sym)
+#include <asm/syscalls_64.h>
 
 /*
  * A newly forked process directly context switches into this address.
@@ -439,7 +370,6 @@ END(stub_x32_rt_sigreturn)
  * rdi: prev task we switched from
  */
 ENTRY(ret_from_fork)
-
        LOCK ; btr $TIF_FORK, TI_flags(%r8)
 
        pushq   $0x0002
@@ -447,28 +377,32 @@ ENTRY(ret_from_fork)
 
        call    schedule_tail                   /* rdi: 'prev' task parameter */
 
-       RESTORE_EXTRA_REGS
-
        testb   $3, CS(%rsp)                    /* from kernel_thread? */
+       jnz     1f
 
        /*
-        * By the time we get here, we have no idea whether our pt_regs,
-        * ti flags, and ti status came from the 64-bit SYSCALL fast path,
-        * the slow path, or one of the 32-bit compat paths.
-        * Use IRET code path to return, since it can safely handle
-        * all of the above.
+        * We came from kernel_thread.  This code path is quite twisted, and
+        * someone should clean it up.
+        *
+        * copy_thread_tls stashes the function pointer in RBX and the
+        * parameter to be passed in RBP.  The called function is permitted
+        * to call do_execve and thereby jump to user mode.
         */
-       jnz     int_ret_from_sys_call
+       movq    RBP(%rsp), %rdi
+       call    *RBX(%rsp)
+       movl    $0, RAX(%rsp)
 
        /*
-        * We came from kernel_thread
-        * nb: we depend on RESTORE_EXTRA_REGS above
+        * Fall through as though we're exiting a syscall.  This makes a
+        * twisted sort of sense if we just called do_execve.
         */
-       movq    %rbp, %rdi
-       call    *%rbx
-       movl    $0, RAX(%rsp)
-       RESTORE_EXTRA_REGS
-       jmp     int_ret_from_sys_call
+
+1:
+       movq    %rsp, %rdi
+       call    syscall_return_slowpath /* returns with IRQs disabled */
+       TRACE_IRQS_ON                   /* user mode is traced as IRQS on */
+       SWAPGS
+       jmp     restore_regs_and_iret
 END(ret_from_fork)
 
 /*
index ff1c6d61f332d22e6f95f54a782b150b39bf75dc..847f2f0c31e50d1029a2e39600ed86e772ef8847 100644 (file)
        .section .entry.text, "ax"
 
 /*
- * 32-bit SYSENTER instruction entry.
+ * 32-bit SYSENTER entry.
  *
- * SYSENTER loads ss, rsp, cs, and rip from previously programmed MSRs.
- * IF and VM in rflags are cleared (IOW: interrupts are off).
+ * 32-bit system calls through the vDSO's __kernel_vsyscall enter here
+ * on 64-bit kernels running on Intel CPUs.
+ *
+ * The SYSENTER instruction, in principle, should *only* occur in the
+ * vDSO.  In practice, a small number of Android devices were shipped
+ * with a copy of Bionic that inlined a SYSENTER instruction.  This
+ * never happened in any of Google's Bionic versions -- it only happened
+ * in a narrow range of Intel-provided versions.
+ *
+ * SYSENTER loads SS, RSP, CS, and RIP from previously programmed MSRs.
+ * IF and VM in RFLAGS are cleared (IOW: interrupts are off).
  * SYSENTER does not save anything on the stack,
- * and does not save old rip (!!!) and rflags.
+ * and does not save old RIP (!!!), RSP, or RFLAGS.
  *
  * Arguments:
  * eax  system call number
  * edi  arg5
  * ebp  user stack
  * 0(%ebp) arg6
- *
- * This is purely a fast path. For anything complicated we use the int 0x80
- * path below. We set up a complete hardware stack frame to share code
- * with the int 0x80 path.
  */
 ENTRY(entry_SYSENTER_compat)
        /* Interrupts are off on entry. */
@@ -66,8 +71,6 @@ ENTRY(entry_SYSENTER_compat)
         */
        pushfq                          /* pt_regs->flags (except IF = 0) */
        orl     $X86_EFLAGS_IF, (%rsp)  /* Fix saved flags */
-       ASM_CLAC                        /* Clear AC after saving FLAGS */
-
        pushq   $__USER32_CS            /* pt_regs->cs */
        xorq    %r8,%r8
        pushq   %r8                     /* pt_regs->ip = 0 (placeholder) */
@@ -90,19 +93,25 @@ ENTRY(entry_SYSENTER_compat)
        cld
 
        /*
-        * Sysenter doesn't filter flags, so we need to clear NT
+        * SYSENTER doesn't filter flags, so we need to clear NT and AC
         * ourselves.  To save a few cycles, we can check whether
-        * NT was set instead of doing an unconditional popfq.
+        * either was set instead of doing an unconditional popfq.
         * This needs to happen before enabling interrupts so that
         * we don't get preempted with NT set.
         *
+        * If TF is set, we will single-step all the way to here -- do_debug
+        * will ignore all the traps.  (Yes, this is slow, but so is
+        * single-stepping in general.  This allows us to avoid having
+        * a more complicated code to handle the case where a user program
+        * forces us to single-step through the SYSENTER entry code.)
+        *
         * NB.: .Lsysenter_fix_flags is a label with the code under it moved
         * out-of-line as an optimization: NT is unlikely to be set in the
         * majority of the cases and instead of polluting the I$ unnecessarily,
         * we're keeping that code behind a branch which will predict as
         * not-taken and therefore its instructions won't be fetched.
         */
-       testl   $X86_EFLAGS_NT, EFLAGS(%rsp)
+       testl   $X86_EFLAGS_NT|X86_EFLAGS_AC|X86_EFLAGS_TF, EFLAGS(%rsp)
        jnz     .Lsysenter_fix_flags
 .Lsysenter_flags_fixed:
 
@@ -123,20 +132,42 @@ ENTRY(entry_SYSENTER_compat)
        pushq   $X86_EFLAGS_FIXED
        popfq
        jmp     .Lsysenter_flags_fixed
+GLOBAL(__end_entry_SYSENTER_compat)
 ENDPROC(entry_SYSENTER_compat)
 
 /*
- * 32-bit SYSCALL instruction entry.
+ * 32-bit SYSCALL entry.
+ *
+ * 32-bit system calls through the vDSO's __kernel_vsyscall enter here
+ * on 64-bit kernels running on AMD CPUs.
+ *
+ * The SYSCALL instruction, in principle, should *only* occur in the
+ * vDSO.  In practice, it appears that this really is the case.
+ * As evidence:
+ *
+ *  - The calling convention for SYSCALL has changed several times without
+ *    anyone noticing.
  *
- * 32-bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
- * then loads new ss, cs, and rip from previously programmed MSRs.
- * rflags gets masked by a value from another MSR (so CLD and CLAC
- * are not needed). SYSCALL does not save anything on the stack
- * and does not change rsp.
+ *  - Prior to the in-kernel X86_BUG_SYSRET_SS_ATTRS fixup, anything
+ *    user task that did SYSCALL without immediately reloading SS
+ *    would randomly crash.
  *
- * Note: rflags saving+masking-with-MSR happens only in Long mode
+ *  - Most programmers do not directly target AMD CPUs, and the 32-bit
+ *    SYSCALL instruction does not exist on Intel CPUs.  Even on AMD
+ *    CPUs, Linux disables the SYSCALL instruction on 32-bit kernels
+ *    because the SYSCALL instruction in legacy/native 32-bit mode (as
+ *    opposed to compat mode) is sufficiently poorly designed as to be
+ *    essentially unusable.
+ *
+ * 32-bit SYSCALL saves RIP to RCX, clears RFLAGS.RF, then saves
+ * RFLAGS to R11, then loads new SS, CS, and RIP from previously
+ * programmed MSRs.  RFLAGS gets masked by a value from another MSR
+ * (so CLD and CLAC are not needed).  SYSCALL does not save anything on
+ * the stack and does not change RSP.
+ *
+ * Note: RFLAGS saving+masking-with-MSR happens only in Long mode
  * (in legacy 32-bit mode, IF, RF and VM bits are cleared and that's it).
- * Don't get confused: rflags saving+masking depends on Long Mode Active bit
+ * Don't get confused: RFLAGS saving+masking depends on Long Mode Active bit
  * (EFER.LMA=1), NOT on bitness of userspace where SYSCALL executes
  * or target CS descriptor's L bit (SYSCALL does not read segment descriptors).
  *
@@ -236,7 +267,21 @@ sysret32_from_system_call:
 END(entry_SYSCALL_compat)
 
 /*
- * Emulated IA32 system calls via int 0x80.
+ * 32-bit legacy system call entry.
+ *
+ * 32-bit x86 Linux system calls traditionally used the INT $0x80
+ * instruction.  INT $0x80 lands here.
+ *
+ * This entry point can be used by 32-bit and 64-bit programs to perform
+ * 32-bit system calls.  Instances of INT $0x80 can be found inline in
+ * various programs and libraries.  It is also used by the vDSO's
+ * __kernel_vsyscall fallback for hardware that doesn't support a faster
+ * entry method.  Restarted 32-bit system calls also fall back to INT
+ * $0x80 regardless of what instruction was originally used to do the
+ * system call.
+ *
+ * This is considered a slow path.  It is not used by most libc
+ * implementations on modern hardware except during process startup.
  *
  * Arguments:
  * eax  system call number
@@ -245,22 +290,14 @@ END(entry_SYSCALL_compat)
  * edx  arg3
  * esi  arg4
  * edi  arg5
- * ebp  arg6   (note: not saved in the stack frame, should not be touched)
- *
- * Notes:
- * Uses the same stack frame as the x86-64 version.
- * All registers except eax must be saved (but ptrace may violate that).
- * Arguments are zero extended. For system calls that want sign extension and
- * take long arguments a wrapper is needed. Most calls can just be called
- * directly.
- * Assumes it is only called from user space and entered with interrupts off.
+ * ebp  arg6
  */
-
 ENTRY(entry_INT80_compat)
        /*
         * Interrupts are off on entry.
         */
        PARAVIRT_ADJUST_EXCEPTION_FRAME
+       ASM_CLAC                        /* Do this early to minimize exposure */
        SWAPGS
 
        /*
@@ -299,7 +336,7 @@ ENTRY(entry_INT80_compat)
        TRACE_IRQS_OFF
 
        movq    %rsp, %rdi
-       call    do_syscall_32_irqs_off
+       call    do_int80_syscall_32
 .Lsyscall_32_done:
 
        /* Go back to user mode. */
index 9a6649857106a0e0bc6bfe8ad0074562e394a5d1..8f895ee13a1cbfa1f1666a251471d29d2db01ea2 100644 (file)
@@ -6,17 +6,11 @@
 #include <asm/asm-offsets.h>
 #include <asm/syscall.h>
 
-#ifdef CONFIG_IA32_EMULATION
-#define SYM(sym, compat) compat
-#else
-#define SYM(sym, compat) sym
-#endif
-
-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage long SYM(sym, compat)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
+#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
 #include <asm/syscalls_32.h>
 #undef __SYSCALL_I386
 
-#define __SYSCALL_I386(nr, sym, compat) [nr] = SYM(sym, compat),
+#define __SYSCALL_I386(nr, sym, qual) [nr] = sym,
 
 extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 
index 41283d22be7a92db23e46fb427593a2e878ee37d..9dbc5abb6162fa20581069499667a8c49b254868 100644 (file)
@@ -6,19 +6,14 @@
 #include <asm/asm-offsets.h>
 #include <asm/syscall.h>
 
-#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
+#define __SYSCALL_64_QUAL_(sym) sym
+#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_##sym
 
-#ifdef CONFIG_X86_X32_ABI
-# define __SYSCALL_X32(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
-#else
-# define __SYSCALL_X32(nr, sym, compat) /* nothing */
-#endif
-
-#define __SYSCALL_64(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
+#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long __SYSCALL_64_QUAL_##qual(sym)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 #include <asm/syscalls_64.h>
 #undef __SYSCALL_64
 
-#define __SYSCALL_64(nr, sym, compat) [nr] = sym,
+#define __SYSCALL_64(nr, sym, qual) [nr] = __SYSCALL_64_QUAL_##qual(sym),
 
 extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 
index dc1040a50bdc21594317f9f9dc4c59196a25ae63..2e5b565adacc542415854612ad752e04cfc5df95 100644 (file)
@@ -21,7 +21,7 @@
 12     common  brk                     sys_brk
 13     64      rt_sigaction            sys_rt_sigaction
 14     common  rt_sigprocmask          sys_rt_sigprocmask
-15     64      rt_sigreturn            stub_rt_sigreturn
+15     64      rt_sigreturn            sys_rt_sigreturn/ptregs
 16     64      ioctl                   sys_ioctl
 17     common  pread64                 sys_pread64
 18     common  pwrite64                sys_pwrite64
 53     common  socketpair              sys_socketpair
 54     64      setsockopt              sys_setsockopt
 55     64      getsockopt              sys_getsockopt
-56     common  clone                   stub_clone
-57     common  fork                    stub_fork
-58     common  vfork                   stub_vfork
-59     64      execve                  stub_execve
+56     common  clone                   sys_clone/ptregs
+57     common  fork                    sys_fork/ptregs
+58     common  vfork                   sys_vfork/ptregs
+59     64      execve                  sys_execve/ptregs
 60     common  exit                    sys_exit
 61     common  wait4                   sys_wait4
 62     common  kill                    sys_kill
 169    common  reboot                  sys_reboot
 170    common  sethostname             sys_sethostname
 171    common  setdomainname           sys_setdomainname
-172    common  iopl                    sys_iopl
+172    common  iopl                    sys_iopl/ptregs
 173    common  ioperm                  sys_ioperm
 174    64      create_module
 175    common  init_module             sys_init_module
 319    common  memfd_create            sys_memfd_create
 320    common  kexec_file_load         sys_kexec_file_load
 321    common  bpf                     sys_bpf
-322    64      execveat                stub_execveat
+322    64      execveat                sys_execveat/ptregs
 323    common  userfaultfd             sys_userfaultfd
 324    common  membarrier              sys_membarrier
 325    common  mlock2                  sys_mlock2
 # for native 64-bit operation.
 #
 512    x32     rt_sigaction            compat_sys_rt_sigaction
-513    x32     rt_sigreturn            stub_x32_rt_sigreturn
+513    x32     rt_sigreturn            sys32_x32_rt_sigreturn
 514    x32     ioctl                   compat_sys_ioctl
 515    x32     readv                   compat_sys_readv
 516    x32     writev                  compat_sys_writev
 517    x32     recvfrom                compat_sys_recvfrom
 518    x32     sendmsg                 compat_sys_sendmsg
 519    x32     recvmsg                 compat_sys_recvmsg
-520    x32     execve                  stub_x32_execve
+520    x32     execve                  compat_sys_execve/ptregs
 521    x32     ptrace                  compat_sys_ptrace
 522    x32     rt_sigpending           compat_sys_rt_sigpending
 523    x32     rt_sigtimedwait         compat_sys_rt_sigtimedwait
 542    x32     getsockopt              compat_sys_getsockopt
 543    x32     io_setup                compat_sys_io_setup
 544    x32     io_submit               compat_sys_io_submit
-545    x32     execveat                stub_x32_execveat
+545    x32     execveat                compat_sys_execveat/ptregs
index 0e7f8ec071e76217a6cee34bc90d0ca7b997443e..cd3d3015d7df87ed79f469c7be0ce6549c62433f 100644 (file)
@@ -3,13 +3,63 @@
 in="$1"
 out="$2"
 
+syscall_macro() {
+    abi="$1"
+    nr="$2"
+    entry="$3"
+
+    # Entry can be either just a function name or "function/qualifier"
+    real_entry="${entry%%/*}"
+    qualifier="${entry:${#real_entry}}"                # Strip the function name
+    qualifier="${qualifier:1}"                 # Strip the slash, if any
+
+    echo "__SYSCALL_${abi}($nr, $real_entry, $qualifier)"
+}
+
+emit() {
+    abi="$1"
+    nr="$2"
+    entry="$3"
+    compat="$4"
+
+    if [ "$abi" == "64" -a -n "$compat" ]; then
+       echo "a compat entry for a 64-bit syscall makes no sense" >&2
+       exit 1
+    fi
+
+    if [ -z "$compat" ]; then
+       if [ -n "$entry" ]; then
+           syscall_macro "$abi" "$nr" "$entry"
+       fi
+    else
+       echo "#ifdef CONFIG_X86_32"
+       if [ -n "$entry" ]; then
+           syscall_macro "$abi" "$nr" "$entry"
+       fi
+       echo "#else"
+       syscall_macro "$abi" "$nr" "$compat"
+       echo "#endif"
+    fi
+}
+
 grep '^[0-9]' "$in" | sort -n | (
     while read nr abi name entry compat; do
        abi=`echo "$abi" | tr '[a-z]' '[A-Z]'`
-       if [ -n "$compat" ]; then
-           echo "__SYSCALL_${abi}($nr, $entry, $compat)"
-       elif [ -n "$entry" ]; then
-           echo "__SYSCALL_${abi}($nr, $entry, $entry)"
+       if [ "$abi" == "COMMON" -o "$abi" == "64" ]; then
+           # COMMON is the same as 64, except that we don't expect X32
+           # programs to use it.  Our expectation has nothing to do with
+           # any generated code, so treat them the same.
+           emit 64 "$nr" "$entry" "$compat"
+       elif [ "$abi" == "X32" ]; then
+           # X32 is equivalent to 64 on an X32-compatible kernel.
+           echo "#ifdef CONFIG_X86_X32_ABI"
+           emit 64 "$nr" "$entry" "$compat"
+           echo "#endif"
+       elif [ "$abi" == "I386" ]; then
+           emit "$abi" "$nr" "$entry" "$compat"
+       else
+           echo "Unknown abi $abi" >&2
+           exit 1
        fi
     done
 ) > "$out"
index 0224987556ce80bd606063b56ef124b0857a3f44..63a03bb91497e63d56e1ba329f9da7b80e751e1d 100644 (file)
@@ -140,7 +140,7 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
        fprintf(outfile, "#include <asm/vdso.h>\n");
        fprintf(outfile, "\n");
        fprintf(outfile,
-               "static unsigned char raw_data[%lu] __page_aligned_data = {",
+               "static unsigned char raw_data[%lu] __ro_after_init __aligned(PAGE_SIZE) = {",
                mapping_size);
        for (j = 0; j < stripped_len; j++) {
                if (j % 10 == 0)
@@ -150,16 +150,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
        }
        fprintf(outfile, "\n};\n\n");
 
-       fprintf(outfile, "static struct page *pages[%lu];\n\n",
-               mapping_size / 4096);
-
        fprintf(outfile, "const struct vdso_image %s = {\n", name);
        fprintf(outfile, "\t.data = raw_data,\n");
        fprintf(outfile, "\t.size = %lu,\n", mapping_size);
-       fprintf(outfile, "\t.text_mapping = {\n");
-       fprintf(outfile, "\t\t.name = \"[vdso]\",\n");
-       fprintf(outfile, "\t\t.pages = pages,\n");
-       fprintf(outfile, "\t},\n");
        if (alt_sec) {
                fprintf(outfile, "\t.alt = %lu,\n",
                        (unsigned long)GET_LE(&alt_sec->sh_offset));
index 08a317a9ae4b582974ec4af4842461bddb762121..7853b53959cd35a8d555a5ddebfbb4af1f40562a 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/kernel.h>
 #include <linux/mm_types.h>
 
-#include <asm/cpufeature.h>
 #include <asm/processor.h>
 #include <asm/vdso.h>
 
index 3a1d9297074bc5e1d2e559735bb5247acffa6164..0109ac6cb79cc73a5d74c99bc2c97705a9ca5c7d 100644 (file)
@@ -3,7 +3,7 @@
 */
 
 #include <asm/dwarf2.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
 
 /*
index b8f69e264ac4148afbdaeedc69e24132980117a9..10f704584922653fd208646cac11c4f8a9cd776b 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/page.h>
 #include <asm/hpet.h>
 #include <asm/desc.h>
+#include <asm/cpufeature.h>
 
 #if defined(CONFIG_X86_64)
 unsigned int __read_mostly vdso64_enabled = 1;
@@ -27,13 +28,7 @@ unsigned int __read_mostly vdso64_enabled = 1;
 
 void __init init_vdso_image(const struct vdso_image *image)
 {
-       int i;
-       int npages = (image->size) / PAGE_SIZE;
-
        BUG_ON(image->size % PAGE_SIZE != 0);
-       for (i = 0; i < npages; i++)
-               image->text_mapping.pages[i] =
-                       virt_to_page(image->data + i*PAGE_SIZE);
 
        apply_alternatives((struct alt_instr *)(image->data + image->alt),
                           (struct alt_instr *)(image->data + image->alt +
@@ -90,18 +85,87 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
 #endif
 }
 
+static int vdso_fault(const struct vm_special_mapping *sm,
+                     struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       const struct vdso_image *image = vma->vm_mm->context.vdso_image;
+
+       if (!image || (vmf->pgoff << PAGE_SHIFT) >= image->size)
+               return VM_FAULT_SIGBUS;
+
+       vmf->page = virt_to_page(image->data + (vmf->pgoff << PAGE_SHIFT));
+       get_page(vmf->page);
+       return 0;
+}
+
+static const struct vm_special_mapping text_mapping = {
+       .name = "[vdso]",
+       .fault = vdso_fault,
+};
+
+static int vvar_fault(const struct vm_special_mapping *sm,
+                     struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       const struct vdso_image *image = vma->vm_mm->context.vdso_image;
+       long sym_offset;
+       int ret = -EFAULT;
+
+       if (!image)
+               return VM_FAULT_SIGBUS;
+
+       sym_offset = (long)(vmf->pgoff << PAGE_SHIFT) +
+               image->sym_vvar_start;
+
+       /*
+        * Sanity check: a symbol offset of zero means that the page
+        * does not exist for this vdso image, not that the page is at
+        * offset zero relative to the text mapping.  This should be
+        * impossible here, because sym_offset should only be zero for
+        * the page past the end of the vvar mapping.
+        */
+       if (sym_offset == 0)
+               return VM_FAULT_SIGBUS;
+
+       if (sym_offset == image->sym_vvar_page) {
+               ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address,
+                                   __pa_symbol(&__vvar_page) >> PAGE_SHIFT);
+       } else if (sym_offset == image->sym_hpet_page) {
+#ifdef CONFIG_HPET_TIMER
+               if (hpet_address && vclock_was_used(VCLOCK_HPET)) {
+                       ret = vm_insert_pfn_prot(
+                               vma,
+                               (unsigned long)vmf->virtual_address,
+                               hpet_address >> PAGE_SHIFT,
+                               pgprot_noncached(PAGE_READONLY));
+               }
+#endif
+       } else if (sym_offset == image->sym_pvclock_page) {
+               struct pvclock_vsyscall_time_info *pvti =
+                       pvclock_pvti_cpu0_va();
+               if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) {
+                       ret = vm_insert_pfn(
+                               vma,
+                               (unsigned long)vmf->virtual_address,
+                               __pa(pvti) >> PAGE_SHIFT);
+               }
+       }
+
+       if (ret == 0 || ret == -EBUSY)
+               return VM_FAULT_NOPAGE;
+
+       return VM_FAULT_SIGBUS;
+}
+
 static int map_vdso(const struct vdso_image *image, bool calculate_addr)
 {
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        unsigned long addr, text_start;
        int ret = 0;
-       static struct page *no_pages[] = {NULL};
-       static struct vm_special_mapping vvar_mapping = {
+       static const struct vm_special_mapping vvar_mapping = {
                .name = "[vvar]",
-               .pages = no_pages,
+               .fault = vvar_fault,
        };
-       struct pvclock_vsyscall_time_info *pvti;
 
        if (calculate_addr) {
                addr = vdso_addr(current->mm->start_stack,
@@ -121,6 +185,7 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
 
        text_start = addr - image->sym_vvar_start;
        current->mm->context.vdso = (void __user *)text_start;
+       current->mm->context.vdso_image = image;
 
        /*
         * MAYWRITE to allow gdb to COW and set breakpoints
@@ -130,7 +195,7 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
                                       image->size,
                                       VM_READ|VM_EXEC|
                                       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
-                                      &image->text_mapping);
+                                      &text_mapping);
 
        if (IS_ERR(vma)) {
                ret = PTR_ERR(vma);
@@ -140,7 +205,8 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
        vma = _install_special_mapping(mm,
                                       addr,
                                       -image->sym_vvar_start,
-                                      VM_READ|VM_MAYREAD,
+                                      VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP|
+                                      VM_PFNMAP,
                                       &vvar_mapping);
 
        if (IS_ERR(vma)) {
@@ -148,41 +214,6 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr)
                goto up_fail;
        }
 
-       if (image->sym_vvar_page)
-               ret = remap_pfn_range(vma,
-                                     text_start + image->sym_vvar_page,
-                                     __pa_symbol(&__vvar_page) >> PAGE_SHIFT,
-                                     PAGE_SIZE,
-                                     PAGE_READONLY);
-
-       if (ret)
-               goto up_fail;
-
-#ifdef CONFIG_HPET_TIMER
-       if (hpet_address && image->sym_hpet_page) {
-               ret = io_remap_pfn_range(vma,
-                       text_start + image->sym_hpet_page,
-                       hpet_address >> PAGE_SHIFT,
-                       PAGE_SIZE,
-                       pgprot_noncached(PAGE_READONLY));
-
-               if (ret)
-                       goto up_fail;
-       }
-#endif
-
-       pvti = pvclock_pvti_cpu0_va();
-       if (pvti && image->sym_pvclock_page) {
-               ret = remap_pfn_range(vma,
-                                     text_start + image->sym_pvclock_page,
-                                     __pa(pvti) >> PAGE_SHIFT,
-                                     PAGE_SIZE,
-                                     PAGE_READONLY);
-
-               if (ret)
-                       goto up_fail;
-       }
-
 up_fail:
        if (ret)
                current->mm->context.vdso = NULL;
@@ -254,7 +285,7 @@ static void vgetcpu_cpu_init(void *arg)
 #ifdef CONFIG_NUMA
        node = cpu_to_node(cpu);
 #endif
-       if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP))
+       if (static_cpu_has(X86_FEATURE_RDTSCP))
                write_rdtscp_aux((node << 12) | cpu);
 
        /*
index 51e3304169951619362ea4a1494716e4f20696bf..0fb3a104ac626b07e0a4e604a8ebf36764bea2cf 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm/vgtod.h>
 #include <asm/vvar.h>
 
+int vclocks_used __read_mostly;
+
 DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data);
 
 void update_vsyscall_tz(void)
@@ -26,12 +28,17 @@ void update_vsyscall_tz(void)
 
 void update_vsyscall(struct timekeeper *tk)
 {
+       int vclock_mode = tk->tkr_mono.clock->archdata.vclock_mode;
        struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
 
+       /* Mark the new vclock used. */
+       BUILD_BUG_ON(VCLOCK_MAX >= 32);
+       WRITE_ONCE(vclocks_used, READ_ONCE(vclocks_used) | (1 << vclock_mode));
+
        gtod_write_begin(vdata);
 
        /* copy vsyscall data */
-       vdata->vclock_mode      = tk->tkr_mono.clock->archdata.vclock_mode;
+       vdata->vclock_mode      = vclock_mode;
        vdata->cycle_last       = tk->tkr_mono.cycle_last;
        vdata->mask             = tk->tkr_mono.mask;
        vdata->mult             = tk->tkr_mono.mult;
diff --git a/arch/x86/events/Makefile b/arch/x86/events/Makefile
new file mode 100644 (file)
index 0000000..fdfea15
--- /dev/null
@@ -0,0 +1,13 @@
+obj-y                  += core.o
+
+obj-$(CONFIG_CPU_SUP_AMD)               += amd/core.o amd/uncore.o
+obj-$(CONFIG_X86_LOCAL_APIC)            += amd/ibs.o msr.o
+ifdef CONFIG_AMD_IOMMU
+obj-$(CONFIG_CPU_SUP_AMD)               += amd/iommu.o
+endif
+obj-$(CONFIG_CPU_SUP_INTEL)            += intel/core.o intel/bts.o intel/cqm.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += intel/cstate.o intel/ds.o intel/knc.o 
+obj-$(CONFIG_CPU_SUP_INTEL)            += intel/lbr.o intel/p4.o intel/p6.o intel/pt.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += intel/rapl.o msr.o
+obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel/uncore.o intel/uncore_nhmex.o
+obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel/uncore_snb.o intel/uncore_snbep.o
diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
new file mode 100644 (file)
index 0000000..049ada8
--- /dev/null
@@ -0,0 +1,731 @@
+#include <linux/perf_event.h>
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/apicdef.h>
+
+#include "../perf_event.h"
+
+static __initconst const u64 amd_hw_cache_event_ids
+                               [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) ] = 0x0040, /* Data Cache Accesses        */
+               [ C(RESULT_MISS)   ] = 0x0141, /* Data Cache Misses          */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0267, /* Data Prefetcher :attempts  */
+               [ C(RESULT_MISS)   ] = 0x0167, /* Data Prefetcher :cancelled */
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction cache fetches  */
+               [ C(RESULT_MISS)   ] = 0x0081, /* Instruction cache misses   */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x014B, /* Prefetch Instructions :Load */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x037D, /* Requests to L2 Cache :IC+DC */
+               [ C(RESULT_MISS)   ] = 0x037E, /* L2 Cache Misses : IC+DC     */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x017F, /* L2 Fill/Writeback           */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
+               [ C(RESULT_MISS)   ] = 0x0746, /* L1_DTLB_AND_L2_DLTB_MISS.ALL */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes        */
+               [ C(RESULT_MISS)   ] = 0x0385, /* L1_ITLB_AND_L2_ITLB_MISS.ALL */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c2, /* Retired Branch Instr.      */
+               [ C(RESULT_MISS)   ] = 0x00c3, /* Retired Mispredicted BI    */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0xb8e9, /* CPU Request to Memory, l+r */
+               [ C(RESULT_MISS)   ] = 0x98e9, /* CPU Request to Memory, r   */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+};
+
+/*
+ * AMD Performance Monitor K7 and later.
+ */
+static const u64 amd_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]                   = 0x0076,
+  [PERF_COUNT_HW_INSTRUCTIONS]                 = 0x00c0,
+  [PERF_COUNT_HW_CACHE_REFERENCES]             = 0x0080,
+  [PERF_COUNT_HW_CACHE_MISSES]                 = 0x0081,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]          = 0x00c2,
+  [PERF_COUNT_HW_BRANCH_MISSES]                        = 0x00c3,
+  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]      = 0x00d0, /* "Decoder empty" event */
+  [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]       = 0x00d1, /* "Dispatch stalls" event */
+};
+
+static u64 amd_pmu_event_map(int hw_event)
+{
+       return amd_perfmon_event_map[hw_event];
+}
+
+/*
+ * Previously calculated offsets
+ */
+static unsigned int event_offsets[X86_PMC_IDX_MAX] __read_mostly;
+static unsigned int count_offsets[X86_PMC_IDX_MAX] __read_mostly;
+
+/*
+ * Legacy CPUs:
+ *   4 counters starting at 0xc0010000 each offset by 1
+ *
+ * CPUs with core performance counter extensions:
+ *   6 counters starting at 0xc0010200 each offset by 2
+ */
+static inline int amd_pmu_addr_offset(int index, bool eventsel)
+{
+       int offset;
+
+       if (!index)
+               return index;
+
+       if (eventsel)
+               offset = event_offsets[index];
+       else
+               offset = count_offsets[index];
+
+       if (offset)
+               return offset;
+
+       if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
+               offset = index;
+       else
+               offset = index << 1;
+
+       if (eventsel)
+               event_offsets[index] = offset;
+       else
+               count_offsets[index] = offset;
+
+       return offset;
+}
+
+static int amd_core_hw_config(struct perf_event *event)
+{
+       if (event->attr.exclude_host && event->attr.exclude_guest)
+               /*
+                * When HO == GO == 1 the hardware treats that as GO == HO == 0
+                * and will count in both modes. We don't want to count in that
+                * case so we emulate no-counting by setting US = OS = 0.
+                */
+               event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR |
+                                     ARCH_PERFMON_EVENTSEL_OS);
+       else if (event->attr.exclude_host)
+               event->hw.config |= AMD64_EVENTSEL_GUESTONLY;
+       else if (event->attr.exclude_guest)
+               event->hw.config |= AMD64_EVENTSEL_HOSTONLY;
+
+       return 0;
+}
+
+/*
+ * AMD64 events are detected based on their event codes.
+ */
+static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
+{
+       return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
+}
+
+static inline int amd_is_nb_event(struct hw_perf_event *hwc)
+{
+       return (hwc->config & 0xe0) == 0xe0;
+}
+
+static inline int amd_has_nb(struct cpu_hw_events *cpuc)
+{
+       struct amd_nb *nb = cpuc->amd_nb;
+
+       return nb && nb->nb_id != -1;
+}
+
+static int amd_pmu_hw_config(struct perf_event *event)
+{
+       int ret;
+
+       /* pass precise event sampling to ibs: */
+       if (event->attr.precise_ip && get_ibs_caps())
+               return -ENOENT;
+
+       if (has_branch_stack(event))
+               return -EOPNOTSUPP;
+
+       ret = x86_pmu_hw_config(event);
+       if (ret)
+               return ret;
+
+       if (event->attr.type == PERF_TYPE_RAW)
+               event->hw.config |= event->attr.config & AMD64_RAW_EVENT_MASK;
+
+       return amd_core_hw_config(event);
+}
+
+static void __amd_put_nb_event_constraints(struct cpu_hw_events *cpuc,
+                                          struct perf_event *event)
+{
+       struct amd_nb *nb = cpuc->amd_nb;
+       int i;
+
+       /*
+        * need to scan whole list because event may not have
+        * been assigned during scheduling
+        *
+        * no race condition possible because event can only
+        * be removed on one CPU at a time AND PMU is disabled
+        * when we come here
+        */
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+               if (cmpxchg(nb->owners + i, event, NULL) == event)
+                       break;
+       }
+}
+
+ /*
+  * AMD64 NorthBridge events need special treatment because
+  * counter access needs to be synchronized across all cores
+  * of a package. Refer to BKDG section 3.12
+  *
+  * NB events are events measuring L3 cache, Hypertransport
+  * traffic. They are identified by an event code >= 0xe00.
+  * They measure events on the NorthBride which is shared
+  * by all cores on a package. NB events are counted on a
+  * shared set of counters. When a NB event is programmed
+  * in a counter, the data actually comes from a shared
+  * counter. Thus, access to those counters needs to be
+  * synchronized.
+  *
+  * We implement the synchronization such that no two cores
+  * can be measuring NB events using the same counters. Thus,
+  * we maintain a per-NB allocation table. The available slot
+  * is propagated using the event_constraint structure.
+  *
+  * We provide only one choice for each NB event based on
+  * the fact that only NB events have restrictions. Consequently,
+  * if a counter is available, there is a guarantee the NB event
+  * will be assigned to it. If no slot is available, an empty
+  * constraint is returned and scheduling will eventually fail
+  * for this event.
+  *
+  * Note that all cores attached the same NB compete for the same
+  * counters to host NB events, this is why we use atomic ops. Some
+  * multi-chip CPUs may have more than one NB.
+  *
+  * Given that resources are allocated (cmpxchg), they must be
+  * eventually freed for others to use. This is accomplished by
+  * calling __amd_put_nb_event_constraints()
+  *
+  * Non NB events are not impacted by this restriction.
+  */
+static struct event_constraint *
+__amd_get_nb_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
+                              struct event_constraint *c)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct amd_nb *nb = cpuc->amd_nb;
+       struct perf_event *old;
+       int idx, new = -1;
+
+       if (!c)
+               c = &unconstrained;
+
+       if (cpuc->is_fake)
+               return c;
+
+       /*
+        * detect if already present, if so reuse
+        *
+        * cannot merge with actual allocation
+        * because of possible holes
+        *
+        * event can already be present yet not assigned (in hwc->idx)
+        * because of successive calls to x86_schedule_events() from
+        * hw_perf_group_sched_in() without hw_perf_enable()
+        */
+       for_each_set_bit(idx, c->idxmsk, x86_pmu.num_counters) {
+               if (new == -1 || hwc->idx == idx)
+                       /* assign free slot, prefer hwc->idx */
+                       old = cmpxchg(nb->owners + idx, NULL, event);
+               else if (nb->owners[idx] == event)
+                       /* event already present */
+                       old = event;
+               else
+                       continue;
+
+               if (old && old != event)
+                       continue;
+
+               /* reassign to this slot */
+               if (new != -1)
+                       cmpxchg(nb->owners + new, event, NULL);
+               new = idx;
+
+               /* already present, reuse */
+               if (old == event)
+                       break;
+       }
+
+       if (new == -1)
+               return &emptyconstraint;
+
+       return &nb->event_constraints[new];
+}
+
+static struct amd_nb *amd_alloc_nb(int cpu)
+{
+       struct amd_nb *nb;
+       int i;
+
+       nb = kzalloc_node(sizeof(struct amd_nb), GFP_KERNEL, cpu_to_node(cpu));
+       if (!nb)
+               return NULL;
+
+       nb->nb_id = -1;
+
+       /*
+        * initialize all possible NB constraints
+        */
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+               __set_bit(i, nb->event_constraints[i].idxmsk);
+               nb->event_constraints[i].weight = 1;
+       }
+       return nb;
+}
+
+static int amd_pmu_cpu_prepare(int cpu)
+{
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+
+       WARN_ON_ONCE(cpuc->amd_nb);
+
+       if (boot_cpu_data.x86_max_cores < 2)
+               return NOTIFY_OK;
+
+       cpuc->amd_nb = amd_alloc_nb(cpu);
+       if (!cpuc->amd_nb)
+               return NOTIFY_BAD;
+
+       return NOTIFY_OK;
+}
+
+static void amd_pmu_cpu_starting(int cpu)
+{
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+       void **onln = &cpuc->kfree_on_online[X86_PERF_KFREE_SHARED];
+       struct amd_nb *nb;
+       int i, nb_id;
+
+       cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY;
+
+       if (boot_cpu_data.x86_max_cores < 2)
+               return;
+
+       nb_id = amd_get_nb_id(cpu);
+       WARN_ON_ONCE(nb_id == BAD_APICID);
+
+       for_each_online_cpu(i) {
+               nb = per_cpu(cpu_hw_events, i).amd_nb;
+               if (WARN_ON_ONCE(!nb))
+                       continue;
+
+               if (nb->nb_id == nb_id) {
+                       *onln = cpuc->amd_nb;
+                       cpuc->amd_nb = nb;
+                       break;
+               }
+       }
+
+       cpuc->amd_nb->nb_id = nb_id;
+       cpuc->amd_nb->refcnt++;
+}
+
+static void amd_pmu_cpu_dead(int cpu)
+{
+       struct cpu_hw_events *cpuhw;
+
+       if (boot_cpu_data.x86_max_cores < 2)
+               return;
+
+       cpuhw = &per_cpu(cpu_hw_events, cpu);
+
+       if (cpuhw->amd_nb) {
+               struct amd_nb *nb = cpuhw->amd_nb;
+
+               if (nb->nb_id == -1 || --nb->refcnt == 0)
+                       kfree(nb);
+
+               cpuhw->amd_nb = NULL;
+       }
+}
+
+static struct event_constraint *
+amd_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event)
+{
+       /*
+        * if not NB event or no NB, then no constraints
+        */
+       if (!(amd_has_nb(cpuc) && amd_is_nb_event(&event->hw)))
+               return &unconstrained;
+
+       return __amd_get_nb_event_constraints(cpuc, event, NULL);
+}
+
+static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
+                                     struct perf_event *event)
+{
+       if (amd_has_nb(cpuc) && amd_is_nb_event(&event->hw))
+               __amd_put_nb_event_constraints(cpuc, event);
+}
+
+PMU_FORMAT_ATTR(event, "config:0-7,32-35");
+PMU_FORMAT_ATTR(umask, "config:8-15"   );
+PMU_FORMAT_ATTR(edge,  "config:18"     );
+PMU_FORMAT_ATTR(inv,   "config:23"     );
+PMU_FORMAT_ATTR(cmask, "config:24-31"  );
+
+static struct attribute *amd_format_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask.attr,
+       NULL,
+};
+
+/* AMD Family 15h */
+
+#define AMD_EVENT_TYPE_MASK    0x000000F0ULL
+
+#define AMD_EVENT_FP           0x00000000ULL ... 0x00000010ULL
+#define AMD_EVENT_LS           0x00000020ULL ... 0x00000030ULL
+#define AMD_EVENT_DC           0x00000040ULL ... 0x00000050ULL
+#define AMD_EVENT_CU           0x00000060ULL ... 0x00000070ULL
+#define AMD_EVENT_IC_DE                0x00000080ULL ... 0x00000090ULL
+#define AMD_EVENT_EX_LS                0x000000C0ULL
+#define AMD_EVENT_DE           0x000000D0ULL
+#define AMD_EVENT_NB           0x000000E0ULL ... 0x000000F0ULL
+
+/*
+ * AMD family 15h event code/PMC mappings:
+ *
+ * type = event_code & 0x0F0:
+ *
+ * 0x000       FP      PERF_CTL[5:3]
+ * 0x010       FP      PERF_CTL[5:3]
+ * 0x020       LS      PERF_CTL[5:0]
+ * 0x030       LS      PERF_CTL[5:0]
+ * 0x040       DC      PERF_CTL[5:0]
+ * 0x050       DC      PERF_CTL[5:0]
+ * 0x060       CU      PERF_CTL[2:0]
+ * 0x070       CU      PERF_CTL[2:0]
+ * 0x080       IC/DE   PERF_CTL[2:0]
+ * 0x090       IC/DE   PERF_CTL[2:0]
+ * 0x0A0       ---
+ * 0x0B0       ---
+ * 0x0C0       EX/LS   PERF_CTL[5:0]
+ * 0x0D0       DE      PERF_CTL[2:0]
+ * 0x0E0       NB      NB_PERF_CTL[3:0]
+ * 0x0F0       NB      NB_PERF_CTL[3:0]
+ *
+ * Exceptions:
+ *
+ * 0x000       FP      PERF_CTL[3], PERF_CTL[5:3] (*)
+ * 0x003       FP      PERF_CTL[3]
+ * 0x004       FP      PERF_CTL[3], PERF_CTL[5:3] (*)
+ * 0x00B       FP      PERF_CTL[3]
+ * 0x00D       FP      PERF_CTL[3]
+ * 0x023       DE      PERF_CTL[2:0]
+ * 0x02D       LS      PERF_CTL[3]
+ * 0x02E       LS      PERF_CTL[3,0]
+ * 0x031       LS      PERF_CTL[2:0] (**)
+ * 0x043       CU      PERF_CTL[2:0]
+ * 0x045       CU      PERF_CTL[2:0]
+ * 0x046       CU      PERF_CTL[2:0]
+ * 0x054       CU      PERF_CTL[2:0]
+ * 0x055       CU      PERF_CTL[2:0]
+ * 0x08F       IC      PERF_CTL[0]
+ * 0x187       DE      PERF_CTL[0]
+ * 0x188       DE      PERF_CTL[0]
+ * 0x0DB       EX      PERF_CTL[5:0]
+ * 0x0DC       LS      PERF_CTL[5:0]
+ * 0x0DD       LS      PERF_CTL[5:0]
+ * 0x0DE       LS      PERF_CTL[5:0]
+ * 0x0DF       LS      PERF_CTL[5:0]
+ * 0x1C0       EX      PERF_CTL[5:3]
+ * 0x1D6       EX      PERF_CTL[5:0]
+ * 0x1D8       EX      PERF_CTL[5:0]
+ *
+ * (*)  depending on the umask all FPU counters may be used
+ * (**) only one unitmask enabled at a time
+ */
+
+static struct event_constraint amd_f15_PMC0  = EVENT_CONSTRAINT(0, 0x01, 0);
+static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0);
+static struct event_constraint amd_f15_PMC3  = EVENT_CONSTRAINT(0, 0x08, 0);
+static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT_OVERLAP(0, 0x09, 0);
+static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
+static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
+
+static struct event_constraint *
+amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, int idx,
+                              struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned int event_code = amd_get_event_code(hwc);
+
+       switch (event_code & AMD_EVENT_TYPE_MASK) {
+       case AMD_EVENT_FP:
+               switch (event_code) {
+               case 0x000:
+                       if (!(hwc->config & 0x0000F000ULL))
+                               break;
+                       if (!(hwc->config & 0x00000F00ULL))
+                               break;
+                       return &amd_f15_PMC3;
+               case 0x004:
+                       if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
+                               break;
+                       return &amd_f15_PMC3;
+               case 0x003:
+               case 0x00B:
+               case 0x00D:
+                       return &amd_f15_PMC3;
+               }
+               return &amd_f15_PMC53;
+       case AMD_EVENT_LS:
+       case AMD_EVENT_DC:
+       case AMD_EVENT_EX_LS:
+               switch (event_code) {
+               case 0x023:
+               case 0x043:
+               case 0x045:
+               case 0x046:
+               case 0x054:
+               case 0x055:
+                       return &amd_f15_PMC20;
+               case 0x02D:
+                       return &amd_f15_PMC3;
+               case 0x02E:
+                       return &amd_f15_PMC30;
+               case 0x031:
+                       if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
+                               return &amd_f15_PMC20;
+                       return &emptyconstraint;
+               case 0x1C0:
+                       return &amd_f15_PMC53;
+               default:
+                       return &amd_f15_PMC50;
+               }
+       case AMD_EVENT_CU:
+       case AMD_EVENT_IC_DE:
+       case AMD_EVENT_DE:
+               switch (event_code) {
+               case 0x08F:
+               case 0x187:
+               case 0x188:
+                       return &amd_f15_PMC0;
+               case 0x0DB ... 0x0DF:
+               case 0x1D6:
+               case 0x1D8:
+                       return &amd_f15_PMC50;
+               default:
+                       return &amd_f15_PMC20;
+               }
+       case AMD_EVENT_NB:
+               /* moved to perf_event_amd_uncore.c */
+               return &emptyconstraint;
+       default:
+               return &emptyconstraint;
+       }
+}
+
+static ssize_t amd_event_sysfs_show(char *page, u64 config)
+{
+       u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
+                   (config & AMD64_EVENTSEL_EVENT) >> 24;
+
+       return x86_event_sysfs_show(page, config, event);
+}
+
+static __initconst const struct x86_pmu amd_pmu = {
+       .name                   = "AMD",
+       .handle_irq             = x86_pmu_handle_irq,
+       .disable_all            = x86_pmu_disable_all,
+       .enable_all             = x86_pmu_enable_all,
+       .enable                 = x86_pmu_enable_event,
+       .disable                = x86_pmu_disable_event,
+       .hw_config              = amd_pmu_hw_config,
+       .schedule_events        = x86_schedule_events,
+       .eventsel               = MSR_K7_EVNTSEL0,
+       .perfctr                = MSR_K7_PERFCTR0,
+       .addr_offset            = amd_pmu_addr_offset,
+       .event_map              = amd_pmu_event_map,
+       .max_events             = ARRAY_SIZE(amd_perfmon_event_map),
+       .num_counters           = AMD64_NUM_COUNTERS,
+       .cntval_bits            = 48,
+       .cntval_mask            = (1ULL << 48) - 1,
+       .apic                   = 1,
+       /* use highest bit to detect overflow */
+       .max_period             = (1ULL << 47) - 1,
+       .get_event_constraints  = amd_get_event_constraints,
+       .put_event_constraints  = amd_put_event_constraints,
+
+       .format_attrs           = amd_format_attr,
+       .events_sysfs_show      = amd_event_sysfs_show,
+
+       .cpu_prepare            = amd_pmu_cpu_prepare,
+       .cpu_starting           = amd_pmu_cpu_starting,
+       .cpu_dead               = amd_pmu_cpu_dead,
+};
+
+static int __init amd_core_pmu_init(void)
+{
+       if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
+               return 0;
+
+       switch (boot_cpu_data.x86) {
+       case 0x15:
+               pr_cont("Fam15h ");
+               x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
+               break;
+
+       default:
+               pr_err("core perfctr but no constraints; unknown hardware!\n");
+               return -ENODEV;
+       }
+
+       /*
+        * If core performance counter extensions exists, we must use
+        * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
+        * amd_pmu_addr_offset().
+        */
+       x86_pmu.eventsel        = MSR_F15H_PERF_CTL;
+       x86_pmu.perfctr         = MSR_F15H_PERF_CTR;
+       x86_pmu.num_counters    = AMD64_NUM_COUNTERS_CORE;
+
+       pr_cont("core perfctr, ");
+       return 0;
+}
+
+__init int amd_pmu_init(void)
+{
+       int ret;
+
+       /* Performance-monitoring supported from K7 and later: */
+       if (boot_cpu_data.x86 < 6)
+               return -ENODEV;
+
+       x86_pmu = amd_pmu;
+
+       ret = amd_core_pmu_init();
+       if (ret)
+               return ret;
+
+       /* Events are common for all AMDs */
+       memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
+              sizeof(hw_cache_event_ids));
+
+       return 0;
+}
+
+void amd_pmu_enable_virt(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       cpuc->perf_ctr_virt_mask = 0;
+
+       /* Reload all events */
+       x86_pmu_disable_all();
+       x86_pmu_enable_all(0);
+}
+EXPORT_SYMBOL_GPL(amd_pmu_enable_virt);
+
+void amd_pmu_disable_virt(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       /*
+        * We only mask out the Host-only bit so that host-only counting works
+        * when SVM is disabled. If someone sets up a guest-only counter when
+        * SVM is disabled the Guest-only bits still gets set and the counter
+        * will not count anything.
+        */
+       cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY;
+
+       /* Reload all events */
+       x86_pmu_disable_all();
+       x86_pmu_enable_all(0);
+}
+EXPORT_SYMBOL_GPL(amd_pmu_disable_virt);
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
new file mode 100644 (file)
index 0000000..51087c2
--- /dev/null
@@ -0,0 +1,959 @@
+/*
+ * Performance events - AMD IBS
+ *
+ *  Copyright (C) 2011 Advanced Micro Devices, Inc., Robert Richter
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/syscore_ops.h>
+
+#include <asm/apic.h>
+
+#include "../perf_event.h"
+
+static u32 ibs_caps;
+
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
+
+#include <linux/kprobes.h>
+#include <linux/hardirq.h>
+
+#include <asm/nmi.h>
+
+#define IBS_FETCH_CONFIG_MASK  (IBS_FETCH_RAND_EN | IBS_FETCH_MAX_CNT)
+#define IBS_OP_CONFIG_MASK     IBS_OP_MAX_CNT
+
+enum ibs_states {
+       IBS_ENABLED     = 0,
+       IBS_STARTED     = 1,
+       IBS_STOPPING    = 2,
+
+       IBS_MAX_STATES,
+};
+
+struct cpu_perf_ibs {
+       struct perf_event       *event;
+       unsigned long           state[BITS_TO_LONGS(IBS_MAX_STATES)];
+};
+
+struct perf_ibs {
+       struct pmu                      pmu;
+       unsigned int                    msr;
+       u64                             config_mask;
+       u64                             cnt_mask;
+       u64                             enable_mask;
+       u64                             valid_mask;
+       u64                             max_period;
+       unsigned long                   offset_mask[1];
+       int                             offset_max;
+       struct cpu_perf_ibs __percpu    *pcpu;
+
+       struct attribute                **format_attrs;
+       struct attribute_group          format_group;
+       const struct attribute_group    *attr_groups[2];
+
+       u64                             (*get_count)(u64 config);
+};
+
+struct perf_ibs_data {
+       u32             size;
+       union {
+               u32     data[0];        /* data buffer starts here */
+               u32     caps;
+       };
+       u64             regs[MSR_AMD64_IBS_REG_COUNT_MAX];
+};
+
+static int
+perf_event_set_period(struct hw_perf_event *hwc, u64 min, u64 max, u64 *hw_period)
+{
+       s64 left = local64_read(&hwc->period_left);
+       s64 period = hwc->sample_period;
+       int overflow = 0;
+
+       /*
+        * If we are way outside a reasonable range then just skip forward:
+        */
+       if (unlikely(left <= -period)) {
+               left = period;
+               local64_set(&hwc->period_left, left);
+               hwc->last_period = period;
+               overflow = 1;
+       }
+
+       if (unlikely(left < (s64)min)) {
+               left += period;
+               local64_set(&hwc->period_left, left);
+               hwc->last_period = period;
+               overflow = 1;
+       }
+
+       /*
+        * If the hw period that triggers the sw overflow is too short
+        * we might hit the irq handler. This biases the results.
+        * Thus we shorten the next-to-last period and set the last
+        * period to the max period.
+        */
+       if (left > max) {
+               left -= max;
+               if (left > max)
+                       left = max;
+               else if (left < min)
+                       left = min;
+       }
+
+       *hw_period = (u64)left;
+
+       return overflow;
+}
+
+static  int
+perf_event_try_update(struct perf_event *event, u64 new_raw_count, int width)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       int shift = 64 - width;
+       u64 prev_raw_count;
+       u64 delta;
+
+       /*
+        * Careful: an NMI might modify the previous event value.
+        *
+        * Our tactic to handle this is to first atomically read and
+        * exchange a new raw count - then add that new-prev delta
+        * count to the generic event atomically:
+        */
+       prev_raw_count = local64_read(&hwc->prev_count);
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                                       new_raw_count) != prev_raw_count)
+               return 0;
+
+       /*
+        * Now we have the new raw value and have updated the prev
+        * timestamp already. We can now calculate the elapsed delta
+        * (event-)time and add that to the generic event.
+        *
+        * Careful, not all hw sign-extends above the physical width
+        * of the count.
+        */
+       delta = (new_raw_count << shift) - (prev_raw_count << shift);
+       delta >>= shift;
+
+       local64_add(delta, &event->count);
+       local64_sub(delta, &hwc->period_left);
+
+       return 1;
+}
+
+static struct perf_ibs perf_ibs_fetch;
+static struct perf_ibs perf_ibs_op;
+
+static struct perf_ibs *get_ibs_pmu(int type)
+{
+       if (perf_ibs_fetch.pmu.type == type)
+               return &perf_ibs_fetch;
+       if (perf_ibs_op.pmu.type == type)
+               return &perf_ibs_op;
+       return NULL;
+}
+
+/*
+ * Use IBS for precise event sampling:
+ *
+ *  perf record -a -e cpu-cycles:p ...    # use ibs op counting cycle count
+ *  perf record -a -e r076:p ...          # same as -e cpu-cycles:p
+ *  perf record -a -e r0C1:p ...          # use ibs op counting micro-ops
+ *
+ * IbsOpCntCtl (bit 19) of IBS Execution Control Register (IbsOpCtl,
+ * MSRC001_1033) is used to select either cycle or micro-ops counting
+ * mode.
+ *
+ * The rip of IBS samples has skid 0. Thus, IBS supports precise
+ * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the
+ * rip is invalid when IBS was not able to record the rip correctly.
+ * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then.
+ *
+ */
+static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
+{
+       switch (event->attr.precise_ip) {
+       case 0:
+               return -ENOENT;
+       case 1:
+       case 2:
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       switch (event->attr.type) {
+       case PERF_TYPE_HARDWARE:
+               switch (event->attr.config) {
+               case PERF_COUNT_HW_CPU_CYCLES:
+                       *config = 0;
+                       return 0;
+               }
+               break;
+       case PERF_TYPE_RAW:
+               switch (event->attr.config) {
+               case 0x0076:
+                       *config = 0;
+                       return 0;
+               case 0x00C1:
+                       *config = IBS_OP_CNT_CTL;
+                       return 0;
+               }
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return -EOPNOTSUPP;
+}
+
+static const struct perf_event_attr ibs_notsupp = {
+       .exclude_user   = 1,
+       .exclude_kernel = 1,
+       .exclude_hv     = 1,
+       .exclude_idle   = 1,
+       .exclude_host   = 1,
+       .exclude_guest  = 1,
+};
+
+static int perf_ibs_init(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct perf_ibs *perf_ibs;
+       u64 max_cnt, config;
+       int ret;
+
+       perf_ibs = get_ibs_pmu(event->attr.type);
+       if (perf_ibs) {
+               config = event->attr.config;
+       } else {
+               perf_ibs = &perf_ibs_op;
+               ret = perf_ibs_precise_event(event, &config);
+               if (ret)
+                       return ret;
+       }
+
+       if (event->pmu != &perf_ibs->pmu)
+               return -ENOENT;
+
+       if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp))
+               return -EINVAL;
+
+       if (config & ~perf_ibs->config_mask)
+               return -EINVAL;
+
+       if (hwc->sample_period) {
+               if (config & perf_ibs->cnt_mask)
+                       /* raw max_cnt may not be set */
+                       return -EINVAL;
+               if (!event->attr.sample_freq && hwc->sample_period & 0x0f)
+                       /*
+                        * lower 4 bits can not be set in ibs max cnt,
+                        * but allowing it in case we adjust the
+                        * sample period to set a frequency.
+                        */
+                       return -EINVAL;
+               hwc->sample_period &= ~0x0FULL;
+               if (!hwc->sample_period)
+                       hwc->sample_period = 0x10;
+       } else {
+               max_cnt = config & perf_ibs->cnt_mask;
+               config &= ~perf_ibs->cnt_mask;
+               event->attr.sample_period = max_cnt << 4;
+               hwc->sample_period = event->attr.sample_period;
+       }
+
+       if (!hwc->sample_period)
+               return -EINVAL;
+
+       /*
+        * If we modify hwc->sample_period, we also need to update
+        * hwc->last_period and hwc->period_left.
+        */
+       hwc->last_period = hwc->sample_period;
+       local64_set(&hwc->period_left, hwc->sample_period);
+
+       hwc->config_base = perf_ibs->msr;
+       hwc->config = config;
+
+       return 0;
+}
+
+static int perf_ibs_set_period(struct perf_ibs *perf_ibs,
+                              struct hw_perf_event *hwc, u64 *period)
+{
+       int overflow;
+
+       /* ignore lower 4 bits in min count: */
+       overflow = perf_event_set_period(hwc, 1<<4, perf_ibs->max_period, period);
+       local64_set(&hwc->prev_count, 0);
+
+       return overflow;
+}
+
+static u64 get_ibs_fetch_count(u64 config)
+{
+       return (config & IBS_FETCH_CNT) >> 12;
+}
+
+static u64 get_ibs_op_count(u64 config)
+{
+       u64 count = 0;
+
+       if (config & IBS_OP_VAL)
+               count += (config & IBS_OP_MAX_CNT) << 4; /* cnt rolled over */
+
+       if (ibs_caps & IBS_CAPS_RDWROPCNT)
+               count += (config & IBS_OP_CUR_CNT) >> 32;
+
+       return count;
+}
+
+static void
+perf_ibs_event_update(struct perf_ibs *perf_ibs, struct perf_event *event,
+                     u64 *config)
+{
+       u64 count = perf_ibs->get_count(*config);
+
+       /*
+        * Set width to 64 since we do not overflow on max width but
+        * instead on max count. In perf_ibs_set_period() we clear
+        * prev count manually on overflow.
+        */
+       while (!perf_event_try_update(event, count, 64)) {
+               rdmsrl(event->hw.config_base, *config);
+               count = perf_ibs->get_count(*config);
+       }
+}
+
+static inline void perf_ibs_enable_event(struct perf_ibs *perf_ibs,
+                                        struct hw_perf_event *hwc, u64 config)
+{
+       wrmsrl(hwc->config_base, hwc->config | config | perf_ibs->enable_mask);
+}
+
+/*
+ * Erratum #420 Instruction-Based Sampling Engine May Generate
+ * Interrupt that Cannot Be Cleared:
+ *
+ * Must clear counter mask first, then clear the enable bit. See
+ * Revision Guide for AMD Family 10h Processors, Publication #41322.
+ */
+static inline void perf_ibs_disable_event(struct perf_ibs *perf_ibs,
+                                         struct hw_perf_event *hwc, u64 config)
+{
+       config &= ~perf_ibs->cnt_mask;
+       wrmsrl(hwc->config_base, config);
+       config &= ~perf_ibs->enable_mask;
+       wrmsrl(hwc->config_base, config);
+}
+
+/*
+ * We cannot restore the ibs pmu state, so we always needs to update
+ * the event while stopping it and then reset the state when starting
+ * again. Thus, ignoring PERF_EF_RELOAD and PERF_EF_UPDATE flags in
+ * perf_ibs_start()/perf_ibs_stop() and instead always do it.
+ */
+static void perf_ibs_start(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+       u64 period;
+
+       if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
+               return;
+
+       WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+       hwc->state = 0;
+
+       perf_ibs_set_period(perf_ibs, hwc, &period);
+       set_bit(IBS_STARTED, pcpu->state);
+       perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
+
+       perf_event_update_userpage(event);
+}
+
+static void perf_ibs_stop(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+       u64 config;
+       int stopping;
+
+       stopping = test_and_clear_bit(IBS_STARTED, pcpu->state);
+
+       if (!stopping && (hwc->state & PERF_HES_UPTODATE))
+               return;
+
+       rdmsrl(hwc->config_base, config);
+
+       if (stopping) {
+               set_bit(IBS_STOPPING, pcpu->state);
+               perf_ibs_disable_event(perf_ibs, hwc, config);
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+       }
+
+       if (hwc->state & PERF_HES_UPTODATE)
+               return;
+
+       /*
+        * Clear valid bit to not count rollovers on update, rollovers
+        * are only updated in the irq handler.
+        */
+       config &= ~perf_ibs->valid_mask;
+
+       perf_ibs_event_update(perf_ibs, event, &config);
+       hwc->state |= PERF_HES_UPTODATE;
+}
+
+static int perf_ibs_add(struct perf_event *event, int flags)
+{
+       struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+
+       if (test_and_set_bit(IBS_ENABLED, pcpu->state))
+               return -ENOSPC;
+
+       event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+       pcpu->event = event;
+
+       if (flags & PERF_EF_START)
+               perf_ibs_start(event, PERF_EF_RELOAD);
+
+       return 0;
+}
+
+static void perf_ibs_del(struct perf_event *event, int flags)
+{
+       struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+
+       if (!test_and_clear_bit(IBS_ENABLED, pcpu->state))
+               return;
+
+       perf_ibs_stop(event, PERF_EF_UPDATE);
+
+       pcpu->event = NULL;
+
+       perf_event_update_userpage(event);
+}
+
+static void perf_ibs_read(struct perf_event *event) { }
+
+PMU_FORMAT_ATTR(rand_en,       "config:57");
+PMU_FORMAT_ATTR(cnt_ctl,       "config:19");
+
+static struct attribute *ibs_fetch_format_attrs[] = {
+       &format_attr_rand_en.attr,
+       NULL,
+};
+
+static struct attribute *ibs_op_format_attrs[] = {
+       NULL,   /* &format_attr_cnt_ctl.attr if IBS_CAPS_OPCNT */
+       NULL,
+};
+
+static struct perf_ibs perf_ibs_fetch = {
+       .pmu = {
+               .task_ctx_nr    = perf_invalid_context,
+
+               .event_init     = perf_ibs_init,
+               .add            = perf_ibs_add,
+               .del            = perf_ibs_del,
+               .start          = perf_ibs_start,
+               .stop           = perf_ibs_stop,
+               .read           = perf_ibs_read,
+       },
+       .msr                    = MSR_AMD64_IBSFETCHCTL,
+       .config_mask            = IBS_FETCH_CONFIG_MASK,
+       .cnt_mask               = IBS_FETCH_MAX_CNT,
+       .enable_mask            = IBS_FETCH_ENABLE,
+       .valid_mask             = IBS_FETCH_VAL,
+       .max_period             = IBS_FETCH_MAX_CNT << 4,
+       .offset_mask            = { MSR_AMD64_IBSFETCH_REG_MASK },
+       .offset_max             = MSR_AMD64_IBSFETCH_REG_COUNT,
+       .format_attrs           = ibs_fetch_format_attrs,
+
+       .get_count              = get_ibs_fetch_count,
+};
+
+static struct perf_ibs perf_ibs_op = {
+       .pmu = {
+               .task_ctx_nr    = perf_invalid_context,
+
+               .event_init     = perf_ibs_init,
+               .add            = perf_ibs_add,
+               .del            = perf_ibs_del,
+               .start          = perf_ibs_start,
+               .stop           = perf_ibs_stop,
+               .read           = perf_ibs_read,
+       },
+       .msr                    = MSR_AMD64_IBSOPCTL,
+       .config_mask            = IBS_OP_CONFIG_MASK,
+       .cnt_mask               = IBS_OP_MAX_CNT,
+       .enable_mask            = IBS_OP_ENABLE,
+       .valid_mask             = IBS_OP_VAL,
+       .max_period             = IBS_OP_MAX_CNT << 4,
+       .offset_mask            = { MSR_AMD64_IBSOP_REG_MASK },
+       .offset_max             = MSR_AMD64_IBSOP_REG_COUNT,
+       .format_attrs           = ibs_op_format_attrs,
+
+       .get_count              = get_ibs_op_count,
+};
+
+static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
+{
+       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+       struct perf_event *event = pcpu->event;
+       struct hw_perf_event *hwc = &event->hw;
+       struct perf_sample_data data;
+       struct perf_raw_record raw;
+       struct pt_regs regs;
+       struct perf_ibs_data ibs_data;
+       int offset, size, check_rip, offset_max, throttle = 0;
+       unsigned int msr;
+       u64 *buf, *config, period;
+
+       if (!test_bit(IBS_STARTED, pcpu->state)) {
+               /*
+                * Catch spurious interrupts after stopping IBS: After
+                * disabling IBS there could be still incoming NMIs
+                * with samples that even have the valid bit cleared.
+                * Mark all this NMIs as handled.
+                */
+               return test_and_clear_bit(IBS_STOPPING, pcpu->state) ? 1 : 0;
+       }
+
+       msr = hwc->config_base;
+       buf = ibs_data.regs;
+       rdmsrl(msr, *buf);
+       if (!(*buf++ & perf_ibs->valid_mask))
+               return 0;
+
+       config = &ibs_data.regs[0];
+       perf_ibs_event_update(perf_ibs, event, config);
+       perf_sample_data_init(&data, 0, hwc->last_period);
+       if (!perf_ibs_set_period(perf_ibs, hwc, &period))
+               goto out;       /* no sw counter overflow */
+
+       ibs_data.caps = ibs_caps;
+       size = 1;
+       offset = 1;
+       check_rip = (perf_ibs == &perf_ibs_op && (ibs_caps & IBS_CAPS_RIPINVALIDCHK));
+       if (event->attr.sample_type & PERF_SAMPLE_RAW)
+               offset_max = perf_ibs->offset_max;
+       else if (check_rip)
+               offset_max = 2;
+       else
+               offset_max = 1;
+       do {
+               rdmsrl(msr + offset, *buf++);
+               size++;
+               offset = find_next_bit(perf_ibs->offset_mask,
+                                      perf_ibs->offset_max,
+                                      offset + 1);
+       } while (offset < offset_max);
+       if (event->attr.sample_type & PERF_SAMPLE_RAW) {
+               /*
+                * Read IbsBrTarget and IbsOpData4 separately
+                * depending on their availability.
+                * Can't add to offset_max as they are staggered
+                */
+               if (ibs_caps & IBS_CAPS_BRNTRGT) {
+                       rdmsrl(MSR_AMD64_IBSBRTARGET, *buf++);
+                       size++;
+               }
+               if (ibs_caps & IBS_CAPS_OPDATA4) {
+                       rdmsrl(MSR_AMD64_IBSOPDATA4, *buf++);
+                       size++;
+               }
+       }
+       ibs_data.size = sizeof(u64) * size;
+
+       regs = *iregs;
+       if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) {
+               regs.flags &= ~PERF_EFLAGS_EXACT;
+       } else {
+               set_linear_ip(&regs, ibs_data.regs[1]);
+               regs.flags |= PERF_EFLAGS_EXACT;
+       }
+
+       if (event->attr.sample_type & PERF_SAMPLE_RAW) {
+               raw.size = sizeof(u32) + ibs_data.size;
+               raw.data = ibs_data.data;
+               data.raw = &raw;
+       }
+
+       throttle = perf_event_overflow(event, &data, &regs);
+out:
+       if (throttle)
+               perf_ibs_disable_event(perf_ibs, hwc, *config);
+       else
+               perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
+
+       perf_event_update_userpage(event);
+
+       return 1;
+}
+
+static int
+perf_ibs_nmi_handler(unsigned int cmd, struct pt_regs *regs)
+{
+       int handled = 0;
+
+       handled += perf_ibs_handle_irq(&perf_ibs_fetch, regs);
+       handled += perf_ibs_handle_irq(&perf_ibs_op, regs);
+
+       if (handled)
+               inc_irq_stat(apic_perf_irqs);
+
+       return handled;
+}
+NOKPROBE_SYMBOL(perf_ibs_nmi_handler);
+
+static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name)
+{
+       struct cpu_perf_ibs __percpu *pcpu;
+       int ret;
+
+       pcpu = alloc_percpu(struct cpu_perf_ibs);
+       if (!pcpu)
+               return -ENOMEM;
+
+       perf_ibs->pcpu = pcpu;
+
+       /* register attributes */
+       if (perf_ibs->format_attrs[0]) {
+               memset(&perf_ibs->format_group, 0, sizeof(perf_ibs->format_group));
+               perf_ibs->format_group.name     = "format";
+               perf_ibs->format_group.attrs    = perf_ibs->format_attrs;
+
+               memset(&perf_ibs->attr_groups, 0, sizeof(perf_ibs->attr_groups));
+               perf_ibs->attr_groups[0]        = &perf_ibs->format_group;
+               perf_ibs->pmu.attr_groups       = perf_ibs->attr_groups;
+       }
+
+       ret = perf_pmu_register(&perf_ibs->pmu, name, -1);
+       if (ret) {
+               perf_ibs->pcpu = NULL;
+               free_percpu(pcpu);
+       }
+
+       return ret;
+}
+
+static __init int perf_event_ibs_init(void)
+{
+       struct attribute **attr = ibs_op_format_attrs;
+
+       if (!ibs_caps)
+               return -ENODEV; /* ibs not supported by the cpu */
+
+       perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
+
+       if (ibs_caps & IBS_CAPS_OPCNT) {
+               perf_ibs_op.config_mask |= IBS_OP_CNT_CTL;
+               *attr++ = &format_attr_cnt_ctl.attr;
+       }
+       perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");
+
+       register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs");
+       pr_info("perf: AMD IBS detected (0x%08x)\n", ibs_caps);
+
+       return 0;
+}
+
+#else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */
+
+static __init int perf_event_ibs_init(void) { return 0; }
+
+#endif
+
+/* IBS - apic initialization, for perf and oprofile */
+
+static __init u32 __get_ibs_caps(void)
+{
+       u32 caps;
+       unsigned int max_level;
+
+       if (!boot_cpu_has(X86_FEATURE_IBS))
+               return 0;
+
+       /* check IBS cpuid feature flags */
+       max_level = cpuid_eax(0x80000000);
+       if (max_level < IBS_CPUID_FEATURES)
+               return IBS_CAPS_DEFAULT;
+
+       caps = cpuid_eax(IBS_CPUID_FEATURES);
+       if (!(caps & IBS_CAPS_AVAIL))
+               /* cpuid flags not valid */
+               return IBS_CAPS_DEFAULT;
+
+       return caps;
+}
+
+u32 get_ibs_caps(void)
+{
+       return ibs_caps;
+}
+
+EXPORT_SYMBOL(get_ibs_caps);
+
+static inline int get_eilvt(int offset)
+{
+       return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+}
+
+static inline int put_eilvt(int offset)
+{
+       return !setup_APIC_eilvt(offset, 0, 0, 1);
+}
+
+/*
+ * Check and reserve APIC extended interrupt LVT offset for IBS if available.
+ */
+static inline int ibs_eilvt_valid(void)
+{
+       int offset;
+       u64 val;
+       int valid = 0;
+
+       preempt_disable();
+
+       rdmsrl(MSR_AMD64_IBSCTL, val);
+       offset = val & IBSCTL_LVT_OFFSET_MASK;
+
+       if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+               pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
+                      smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+               goto out;
+       }
+
+       if (!get_eilvt(offset)) {
+               pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
+                      smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+               goto out;
+       }
+
+       valid = 1;
+out:
+       preempt_enable();
+
+       return valid;
+}
+
+static int setup_ibs_ctl(int ibs_eilvt_off)
+{
+       struct pci_dev *cpu_cfg;
+       int nodes;
+       u32 value = 0;
+
+       nodes = 0;
+       cpu_cfg = NULL;
+       do {
+               cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
+                                        PCI_DEVICE_ID_AMD_10H_NB_MISC,
+                                        cpu_cfg);
+               if (!cpu_cfg)
+                       break;
+               ++nodes;
+               pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
+                                      | IBSCTL_LVT_OFFSET_VALID);
+               pci_read_config_dword(cpu_cfg, IBSCTL, &value);
+               if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
+                       pci_dev_put(cpu_cfg);
+                       pr_debug("Failed to setup IBS LVT offset, IBSCTL = 0x%08x\n",
+                                value);
+                       return -EINVAL;
+               }
+       } while (1);
+
+       if (!nodes) {
+               pr_debug("No CPU node configured for IBS\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/*
+ * This runs only on the current cpu. We try to find an LVT offset and
+ * setup the local APIC. For this we must disable preemption. On
+ * success we initialize all nodes with this offset. This updates then
+ * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
+ * the IBS interrupt vector is handled by perf_ibs_cpu_notifier that
+ * is using the new offset.
+ */
+static void force_ibs_eilvt_setup(void)
+{
+       int offset;
+       int ret;
+
+       preempt_disable();
+       /* find the next free available EILVT entry, skip offset 0 */
+       for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
+               if (get_eilvt(offset))
+                       break;
+       }
+       preempt_enable();
+
+       if (offset == APIC_EILVT_NR_MAX) {
+               pr_debug("No EILVT entry available\n");
+               return;
+       }
+
+       ret = setup_ibs_ctl(offset);
+       if (ret)
+               goto out;
+
+       if (!ibs_eilvt_valid())
+               goto out;
+
+       pr_info("IBS: LVT offset %d assigned\n", offset);
+
+       return;
+out:
+       preempt_disable();
+       put_eilvt(offset);
+       preempt_enable();
+       return;
+}
+
+static void ibs_eilvt_setup(void)
+{
+       /*
+        * Force LVT offset assignment for family 10h: The offsets are
+        * not assigned by the BIOS for this family, so the OS is
+        * responsible for doing it. If the OS assignment fails, fall
+        * back to BIOS settings and try to setup this.
+        */
+       if (boot_cpu_data.x86 == 0x10)
+               force_ibs_eilvt_setup();
+}
+
+static inline int get_ibs_lvt_offset(void)
+{
+       u64 val;
+
+       rdmsrl(MSR_AMD64_IBSCTL, val);
+       if (!(val & IBSCTL_LVT_OFFSET_VALID))
+               return -EINVAL;
+
+       return val & IBSCTL_LVT_OFFSET_MASK;
+}
+
+static void setup_APIC_ibs(void *dummy)
+{
+       int offset;
+
+       offset = get_ibs_lvt_offset();
+       if (offset < 0)
+               goto failed;
+
+       if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
+               return;
+failed:
+       pr_warn("perf: IBS APIC setup failed on cpu #%d\n",
+               smp_processor_id());
+}
+
+static void clear_APIC_ibs(void *dummy)
+{
+       int offset;
+
+       offset = get_ibs_lvt_offset();
+       if (offset >= 0)
+               setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
+}
+
+#ifdef CONFIG_PM
+
+static int perf_ibs_suspend(void)
+{
+       clear_APIC_ibs(NULL);
+       return 0;
+}
+
+static void perf_ibs_resume(void)
+{
+       ibs_eilvt_setup();
+       setup_APIC_ibs(NULL);
+}
+
+static struct syscore_ops perf_ibs_syscore_ops = {
+       .resume         = perf_ibs_resume,
+       .suspend        = perf_ibs_suspend,
+};
+
+static void perf_ibs_pm_init(void)
+{
+       register_syscore_ops(&perf_ibs_syscore_ops);
+}
+
+#else
+
+static inline void perf_ibs_pm_init(void) { }
+
+#endif
+
+static int
+perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
+{
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_STARTING:
+               setup_APIC_ibs(NULL);
+               break;
+       case CPU_DYING:
+               clear_APIC_ibs(NULL);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static __init int amd_ibs_init(void)
+{
+       u32 caps;
+       int ret = -EINVAL;
+
+       caps = __get_ibs_caps();
+       if (!caps)
+               return -ENODEV; /* ibs not supported by the cpu */
+
+       ibs_eilvt_setup();
+
+       if (!ibs_eilvt_valid())
+               goto out;
+
+       perf_ibs_pm_init();
+       cpu_notifier_register_begin();
+       ibs_caps = caps;
+       /* make ibs_caps visible to other cpus: */
+       smp_mb();
+       smp_call_function(setup_APIC_ibs, NULL, 1);
+       __perf_cpu_notifier(perf_ibs_cpu_notifier);
+       cpu_notifier_register_done();
+
+       ret = perf_event_ibs_init();
+out:
+       if (ret)
+               pr_err("Failed to setup IBS, %d\n", ret);
+       return ret;
+}
+
+/* Since we need the pci subsystem to init ibs we can't do this earlier: */
+device_initcall(amd_ibs_init);
diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c
new file mode 100644 (file)
index 0000000..635e5eb
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Steven Kinney <Steven.Kinney@amd.com>
+ * Author: Suravee Suthikulpanit <Suraveee.Suthikulpanit@amd.com>
+ *
+ * Perf: amd_iommu - AMD IOMMU Performance Counter PMU implementation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/perf_event.h>
+#include <linux/module.h>
+#include <linux/cpumask.h>
+#include <linux/slab.h>
+
+#include "../perf_event.h"
+#include "iommu.h"
+
+#define COUNTER_SHIFT          16
+
+#define _GET_BANK(ev)       ((u8)(ev->hw.extra_reg.reg >> 8))
+#define _GET_CNTR(ev)       ((u8)(ev->hw.extra_reg.reg))
+
+/* iommu pmu config masks */
+#define _GET_CSOURCE(ev)    ((ev->hw.config & 0xFFULL))
+#define _GET_DEVID(ev)      ((ev->hw.config >> 8)  & 0xFFFFULL)
+#define _GET_PASID(ev)      ((ev->hw.config >> 24) & 0xFFFFULL)
+#define _GET_DOMID(ev)      ((ev->hw.config >> 40) & 0xFFFFULL)
+#define _GET_DEVID_MASK(ev) ((ev->hw.extra_reg.config)  & 0xFFFFULL)
+#define _GET_PASID_MASK(ev) ((ev->hw.extra_reg.config >> 16) & 0xFFFFULL)
+#define _GET_DOMID_MASK(ev) ((ev->hw.extra_reg.config >> 32) & 0xFFFFULL)
+
+static struct perf_amd_iommu __perf_iommu;
+
+struct perf_amd_iommu {
+       struct pmu pmu;
+       u8 max_banks;
+       u8 max_counters;
+       u64 cntr_assign_mask;
+       raw_spinlock_t lock;
+       const struct attribute_group *attr_groups[4];
+};
+
+#define format_group   attr_groups[0]
+#define cpumask_group  attr_groups[1]
+#define events_group   attr_groups[2]
+#define null_group     attr_groups[3]
+
+/*---------------------------------------------
+ * sysfs format attributes
+ *---------------------------------------------*/
+PMU_FORMAT_ATTR(csource,    "config:0-7");
+PMU_FORMAT_ATTR(devid,      "config:8-23");
+PMU_FORMAT_ATTR(pasid,      "config:24-39");
+PMU_FORMAT_ATTR(domid,      "config:40-55");
+PMU_FORMAT_ATTR(devid_mask, "config1:0-15");
+PMU_FORMAT_ATTR(pasid_mask, "config1:16-31");
+PMU_FORMAT_ATTR(domid_mask, "config1:32-47");
+
+static struct attribute *iommu_format_attrs[] = {
+       &format_attr_csource.attr,
+       &format_attr_devid.attr,
+       &format_attr_pasid.attr,
+       &format_attr_domid.attr,
+       &format_attr_devid_mask.attr,
+       &format_attr_pasid_mask.attr,
+       &format_attr_domid_mask.attr,
+       NULL,
+};
+
+static struct attribute_group amd_iommu_format_group = {
+       .name = "format",
+       .attrs = iommu_format_attrs,
+};
+
+/*---------------------------------------------
+ * sysfs events attributes
+ *---------------------------------------------*/
+struct amd_iommu_event_desc {
+       struct kobj_attribute attr;
+       const char *event;
+};
+
+static ssize_t _iommu_event_show(struct kobject *kobj,
+                               struct kobj_attribute *attr, char *buf)
+{
+       struct amd_iommu_event_desc *event =
+               container_of(attr, struct amd_iommu_event_desc, attr);
+       return sprintf(buf, "%s\n", event->event);
+}
+
+#define AMD_IOMMU_EVENT_DESC(_name, _event)                    \
+{                                                              \
+       .attr  = __ATTR(_name, 0444, _iommu_event_show, NULL),  \
+       .event = _event,                                        \
+}
+
+static struct amd_iommu_event_desc amd_iommu_v2_event_descs[] = {
+       AMD_IOMMU_EVENT_DESC(mem_pass_untrans,        "csource=0x01"),
+       AMD_IOMMU_EVENT_DESC(mem_pass_pretrans,       "csource=0x02"),
+       AMD_IOMMU_EVENT_DESC(mem_pass_excl,           "csource=0x03"),
+       AMD_IOMMU_EVENT_DESC(mem_target_abort,        "csource=0x04"),
+       AMD_IOMMU_EVENT_DESC(mem_trans_total,         "csource=0x05"),
+       AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pte_hit,   "csource=0x06"),
+       AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pte_mis,   "csource=0x07"),
+       AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pde_hit,   "csource=0x08"),
+       AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pde_mis,   "csource=0x09"),
+       AMD_IOMMU_EVENT_DESC(mem_dte_hit,             "csource=0x0a"),
+       AMD_IOMMU_EVENT_DESC(mem_dte_mis,             "csource=0x0b"),
+       AMD_IOMMU_EVENT_DESC(page_tbl_read_tot,       "csource=0x0c"),
+       AMD_IOMMU_EVENT_DESC(page_tbl_read_nst,       "csource=0x0d"),
+       AMD_IOMMU_EVENT_DESC(page_tbl_read_gst,       "csource=0x0e"),
+       AMD_IOMMU_EVENT_DESC(int_dte_hit,             "csource=0x0f"),
+       AMD_IOMMU_EVENT_DESC(int_dte_mis,             "csource=0x10"),
+       AMD_IOMMU_EVENT_DESC(cmd_processed,           "csource=0x11"),
+       AMD_IOMMU_EVENT_DESC(cmd_processed_inv,       "csource=0x12"),
+       AMD_IOMMU_EVENT_DESC(tlb_inv,                 "csource=0x13"),
+       { /* end: all zeroes */ },
+};
+
+/*---------------------------------------------
+ * sysfs cpumask attributes
+ *---------------------------------------------*/
+static cpumask_t iommu_cpumask;
+
+static ssize_t _iommu_cpumask_show(struct device *dev,
+                                  struct device_attribute *attr,
+                                  char *buf)
+{
+       return cpumap_print_to_pagebuf(true, buf, &iommu_cpumask);
+}
+static DEVICE_ATTR(cpumask, S_IRUGO, _iommu_cpumask_show, NULL);
+
+static struct attribute *iommu_cpumask_attrs[] = {
+       &dev_attr_cpumask.attr,
+       NULL,
+};
+
+static struct attribute_group amd_iommu_cpumask_group = {
+       .attrs = iommu_cpumask_attrs,
+};
+
+/*---------------------------------------------*/
+
+static int get_next_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu)
+{
+       unsigned long flags;
+       int shift, bank, cntr, retval;
+       int max_banks = perf_iommu->max_banks;
+       int max_cntrs = perf_iommu->max_counters;
+
+       raw_spin_lock_irqsave(&perf_iommu->lock, flags);
+
+       for (bank = 0, shift = 0; bank < max_banks; bank++) {
+               for (cntr = 0; cntr < max_cntrs; cntr++) {
+                       shift = bank + (bank*3) + cntr;
+                       if (perf_iommu->cntr_assign_mask & (1ULL<<shift)) {
+                               continue;
+                       } else {
+                               perf_iommu->cntr_assign_mask |= (1ULL<<shift);
+                               retval = ((u16)((u16)bank<<8) | (u8)(cntr));
+                               goto out;
+                       }
+               }
+       }
+       retval = -ENOSPC;
+out:
+       raw_spin_unlock_irqrestore(&perf_iommu->lock, flags);
+       return retval;
+}
+
+static int clear_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu,
+                                       u8 bank, u8 cntr)
+{
+       unsigned long flags;
+       int max_banks, max_cntrs;
+       int shift = 0;
+
+       max_banks = perf_iommu->max_banks;
+       max_cntrs = perf_iommu->max_counters;
+
+       if ((bank > max_banks) || (cntr > max_cntrs))
+               return -EINVAL;
+
+       shift = bank + cntr + (bank*3);
+
+       raw_spin_lock_irqsave(&perf_iommu->lock, flags);
+       perf_iommu->cntr_assign_mask &= ~(1ULL<<shift);
+       raw_spin_unlock_irqrestore(&perf_iommu->lock, flags);
+
+       return 0;
+}
+
+static int perf_iommu_event_init(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct perf_amd_iommu *perf_iommu;
+       u64 config, config1;
+
+       /* test the event attr type check for PMU enumeration */
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       /*
+        * IOMMU counters are shared across all cores.
+        * Therefore, it does not support per-process mode.
+        * Also, it does not support event sampling mode.
+        */
+       if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+               return -EINVAL;
+
+       /* IOMMU counters do not have usr/os/guest/host bits */
+       if (event->attr.exclude_user || event->attr.exclude_kernel ||
+           event->attr.exclude_host || event->attr.exclude_guest)
+               return -EINVAL;
+
+       if (event->cpu < 0)
+               return -EINVAL;
+
+       perf_iommu = &__perf_iommu;
+
+       if (event->pmu != &perf_iommu->pmu)
+               return -ENOENT;
+
+       if (perf_iommu) {
+               config = event->attr.config;
+               config1 = event->attr.config1;
+       } else {
+               return -EINVAL;
+       }
+
+       /* integrate with iommu base devid (0000), assume one iommu */
+       perf_iommu->max_banks =
+               amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID);
+       perf_iommu->max_counters =
+               amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID);
+       if ((perf_iommu->max_banks == 0) || (perf_iommu->max_counters == 0))
+               return -EINVAL;
+
+       /* update the hw_perf_event struct with the iommu config data */
+       hwc->config = config;
+       hwc->extra_reg.config = config1;
+
+       return 0;
+}
+
+static void perf_iommu_enable_event(struct perf_event *ev)
+{
+       u8 csource = _GET_CSOURCE(ev);
+       u16 devid = _GET_DEVID(ev);
+       u64 reg = 0ULL;
+
+       reg = csource;
+       amd_iommu_pc_get_set_reg_val(devid,
+                       _GET_BANK(ev), _GET_CNTR(ev) ,
+                        IOMMU_PC_COUNTER_SRC_REG, &reg, true);
+
+       reg = 0ULL | devid | (_GET_DEVID_MASK(ev) << 32);
+       if (reg)
+               reg |= (1UL << 31);
+       amd_iommu_pc_get_set_reg_val(devid,
+                       _GET_BANK(ev), _GET_CNTR(ev) ,
+                        IOMMU_PC_DEVID_MATCH_REG, &reg, true);
+
+       reg = 0ULL | _GET_PASID(ev) | (_GET_PASID_MASK(ev) << 32);
+       if (reg)
+               reg |= (1UL << 31);
+       amd_iommu_pc_get_set_reg_val(devid,
+                       _GET_BANK(ev), _GET_CNTR(ev) ,
+                        IOMMU_PC_PASID_MATCH_REG, &reg, true);
+
+       reg = 0ULL | _GET_DOMID(ev) | (_GET_DOMID_MASK(ev) << 32);
+       if (reg)
+               reg |= (1UL << 31);
+       amd_iommu_pc_get_set_reg_val(devid,
+                       _GET_BANK(ev), _GET_CNTR(ev) ,
+                        IOMMU_PC_DOMID_MATCH_REG, &reg, true);
+}
+
+static void perf_iommu_disable_event(struct perf_event *event)
+{
+       u64 reg = 0ULL;
+
+       amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
+                       _GET_BANK(event), _GET_CNTR(event),
+                       IOMMU_PC_COUNTER_SRC_REG, &reg, true);
+}
+
+static void perf_iommu_start(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       pr_debug("perf: amd_iommu:perf_iommu_start\n");
+       if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
+               return;
+
+       WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+       hwc->state = 0;
+
+       if (flags & PERF_EF_RELOAD) {
+               u64 prev_raw_count =  local64_read(&hwc->prev_count);
+               amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
+                               _GET_BANK(event), _GET_CNTR(event),
+                               IOMMU_PC_COUNTER_REG, &prev_raw_count, true);
+       }
+
+       perf_iommu_enable_event(event);
+       perf_event_update_userpage(event);
+
+}
+
+static void perf_iommu_read(struct perf_event *event)
+{
+       u64 count = 0ULL;
+       u64 prev_raw_count = 0ULL;
+       u64 delta = 0ULL;
+       struct hw_perf_event *hwc = &event->hw;
+       pr_debug("perf: amd_iommu:perf_iommu_read\n");
+
+       amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
+                               _GET_BANK(event), _GET_CNTR(event),
+                               IOMMU_PC_COUNTER_REG, &count, false);
+
+       /* IOMMU pc counter register is only 48 bits */
+       count &= 0xFFFFFFFFFFFFULL;
+
+       prev_raw_count =  local64_read(&hwc->prev_count);
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                                       count) != prev_raw_count)
+               return;
+
+       /* Handling 48-bit counter overflowing */
+       delta = (count << COUNTER_SHIFT) - (prev_raw_count << COUNTER_SHIFT);
+       delta >>= COUNTER_SHIFT;
+       local64_add(delta, &event->count);
+
+}
+
+static void perf_iommu_stop(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 config;
+
+       pr_debug("perf: amd_iommu:perf_iommu_stop\n");
+
+       if (hwc->state & PERF_HES_UPTODATE)
+               return;
+
+       perf_iommu_disable_event(event);
+       WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+       hwc->state |= PERF_HES_STOPPED;
+
+       if (hwc->state & PERF_HES_UPTODATE)
+               return;
+
+       config = hwc->config;
+       perf_iommu_read(event);
+       hwc->state |= PERF_HES_UPTODATE;
+}
+
+static int perf_iommu_add(struct perf_event *event, int flags)
+{
+       int retval;
+       struct perf_amd_iommu *perf_iommu =
+                       container_of(event->pmu, struct perf_amd_iommu, pmu);
+
+       pr_debug("perf: amd_iommu:perf_iommu_add\n");
+       event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+       /* request an iommu bank/counter */
+       retval = get_next_avail_iommu_bnk_cntr(perf_iommu);
+       if (retval != -ENOSPC)
+               event->hw.extra_reg.reg = (u16)retval;
+       else
+               return retval;
+
+       if (flags & PERF_EF_START)
+               perf_iommu_start(event, PERF_EF_RELOAD);
+
+       return 0;
+}
+
+static void perf_iommu_del(struct perf_event *event, int flags)
+{
+       struct perf_amd_iommu *perf_iommu =
+                       container_of(event->pmu, struct perf_amd_iommu, pmu);
+
+       pr_debug("perf: amd_iommu:perf_iommu_del\n");
+       perf_iommu_stop(event, PERF_EF_UPDATE);
+
+       /* clear the assigned iommu bank/counter */
+       clear_avail_iommu_bnk_cntr(perf_iommu,
+                                    _GET_BANK(event),
+                                    _GET_CNTR(event));
+
+       perf_event_update_userpage(event);
+}
+
+static __init int _init_events_attrs(struct perf_amd_iommu *perf_iommu)
+{
+       struct attribute **attrs;
+       struct attribute_group *attr_group;
+       int i = 0, j;
+
+       while (amd_iommu_v2_event_descs[i].attr.attr.name)
+               i++;
+
+       attr_group = kzalloc(sizeof(struct attribute *)
+               * (i + 1) + sizeof(*attr_group), GFP_KERNEL);
+       if (!attr_group)
+               return -ENOMEM;
+
+       attrs = (struct attribute **)(attr_group + 1);
+       for (j = 0; j < i; j++)
+               attrs[j] = &amd_iommu_v2_event_descs[j].attr.attr;
+
+       attr_group->name = "events";
+       attr_group->attrs = attrs;
+       perf_iommu->events_group = attr_group;
+
+       return 0;
+}
+
+static __init void amd_iommu_pc_exit(void)
+{
+       if (__perf_iommu.events_group != NULL) {
+               kfree(__perf_iommu.events_group);
+               __perf_iommu.events_group = NULL;
+       }
+}
+
+static __init int _init_perf_amd_iommu(
+       struct perf_amd_iommu *perf_iommu, char *name)
+{
+       int ret;
+
+       raw_spin_lock_init(&perf_iommu->lock);
+
+       /* Init format attributes */
+       perf_iommu->format_group = &amd_iommu_format_group;
+
+       /* Init cpumask attributes to only core 0 */
+       cpumask_set_cpu(0, &iommu_cpumask);
+       perf_iommu->cpumask_group = &amd_iommu_cpumask_group;
+
+       /* Init events attributes */
+       if (_init_events_attrs(perf_iommu) != 0)
+               pr_err("perf: amd_iommu: Only support raw events.\n");
+
+       /* Init null attributes */
+       perf_iommu->null_group = NULL;
+       perf_iommu->pmu.attr_groups = perf_iommu->attr_groups;
+
+       ret = perf_pmu_register(&perf_iommu->pmu, name, -1);
+       if (ret) {
+               pr_err("perf: amd_iommu: Failed to initialized.\n");
+               amd_iommu_pc_exit();
+       } else {
+               pr_info("perf: amd_iommu: Detected. (%d banks, %d counters/bank)\n",
+                       amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID),
+                       amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID));
+       }
+
+       return ret;
+}
+
+static struct perf_amd_iommu __perf_iommu = {
+       .pmu = {
+               .event_init     = perf_iommu_event_init,
+               .add            = perf_iommu_add,
+               .del            = perf_iommu_del,
+               .start          = perf_iommu_start,
+               .stop           = perf_iommu_stop,
+               .read           = perf_iommu_read,
+       },
+       .max_banks              = 0x00,
+       .max_counters           = 0x00,
+       .cntr_assign_mask       = 0ULL,
+       .format_group           = NULL,
+       .cpumask_group          = NULL,
+       .events_group           = NULL,
+       .null_group             = NULL,
+};
+
+static __init int amd_iommu_pc_init(void)
+{
+       /* Make sure the IOMMU PC resource is available */
+       if (!amd_iommu_pc_supported())
+               return -ENODEV;
+
+       _init_perf_amd_iommu(&__perf_iommu, "amd_iommu");
+
+       return 0;
+}
+
+device_initcall(amd_iommu_pc_init);
diff --git a/arch/x86/events/amd/iommu.h b/arch/x86/events/amd/iommu.h
new file mode 100644 (file)
index 0000000..845d173
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Steven Kinney <Steven.Kinney@amd.com>
+ * Author: Suravee Suthikulpanit <Suraveee.Suthikulpanit@amd.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 _PERF_EVENT_AMD_IOMMU_H_
+#define _PERF_EVENT_AMD_IOMMU_H_
+
+/* iommu pc mmio region register indexes */
+#define IOMMU_PC_COUNTER_REG                   0x00
+#define IOMMU_PC_COUNTER_SRC_REG               0x08
+#define IOMMU_PC_PASID_MATCH_REG               0x10
+#define IOMMU_PC_DOMID_MATCH_REG               0x18
+#define IOMMU_PC_DEVID_MATCH_REG               0x20
+#define IOMMU_PC_COUNTER_REPORT_REG            0x28
+
+/* maximun specified bank/counters */
+#define PC_MAX_SPEC_BNKS                       64
+#define PC_MAX_SPEC_CNTRS                      16
+
+/* iommu pc reg masks*/
+#define IOMMU_BASE_DEVID                       0x0000
+
+/* amd_iommu_init.c external support functions */
+extern bool amd_iommu_pc_supported(void);
+
+extern u8 amd_iommu_pc_get_max_banks(u16 devid);
+
+extern u8 amd_iommu_pc_get_max_counters(u16 devid);
+
+extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr,
+                       u8 fxn, u64 *value, bool is_write);
+
+#endif /*_PERF_EVENT_AMD_IOMMU_H_*/
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
new file mode 100644 (file)
index 0000000..3db9569
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Jacob Shin <jacob.shin@amd.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.
+ */
+
+#include <linux/perf_event.h>
+#include <linux/percpu.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+
+#include <asm/cpufeature.h>
+#include <asm/perf_event.h>
+#include <asm/msr.h>
+
+#define NUM_COUNTERS_NB                4
+#define NUM_COUNTERS_L2                4
+#define MAX_COUNTERS           NUM_COUNTERS_NB
+
+#define RDPMC_BASE_NB          6
+#define RDPMC_BASE_L2          10
+
+#define COUNTER_SHIFT          16
+
+struct amd_uncore {
+       int id;
+       int refcnt;
+       int cpu;
+       int num_counters;
+       int rdpmc_base;
+       u32 msr_base;
+       cpumask_t *active_mask;
+       struct pmu *pmu;
+       struct perf_event *events[MAX_COUNTERS];
+       struct amd_uncore *free_when_cpu_online;
+};
+
+static struct amd_uncore * __percpu *amd_uncore_nb;
+static struct amd_uncore * __percpu *amd_uncore_l2;
+
+static struct pmu amd_nb_pmu;
+static struct pmu amd_l2_pmu;
+
+static cpumask_t amd_nb_active_mask;
+static cpumask_t amd_l2_active_mask;
+
+static bool is_nb_event(struct perf_event *event)
+{
+       return event->pmu->type == amd_nb_pmu.type;
+}
+
+static bool is_l2_event(struct perf_event *event)
+{
+       return event->pmu->type == amd_l2_pmu.type;
+}
+
+static struct amd_uncore *event_to_amd_uncore(struct perf_event *event)
+{
+       if (is_nb_event(event) && amd_uncore_nb)
+               return *per_cpu_ptr(amd_uncore_nb, event->cpu);
+       else if (is_l2_event(event) && amd_uncore_l2)
+               return *per_cpu_ptr(amd_uncore_l2, event->cpu);
+
+       return NULL;
+}
+
+static void amd_uncore_read(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 prev, new;
+       s64 delta;
+
+       /*
+        * since we do not enable counter overflow interrupts,
+        * we do not have to worry about prev_count changing on us
+        */
+
+       prev = local64_read(&hwc->prev_count);
+       rdpmcl(hwc->event_base_rdpmc, new);
+       local64_set(&hwc->prev_count, new);
+       delta = (new << COUNTER_SHIFT) - (prev << COUNTER_SHIFT);
+       delta >>= COUNTER_SHIFT;
+       local64_add(delta, &event->count);
+}
+
+static void amd_uncore_start(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (flags & PERF_EF_RELOAD)
+               wrmsrl(hwc->event_base, (u64)local64_read(&hwc->prev_count));
+
+       hwc->state = 0;
+       wrmsrl(hwc->config_base, (hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE));
+       perf_event_update_userpage(event);
+}
+
+static void amd_uncore_stop(struct perf_event *event, int flags)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       wrmsrl(hwc->config_base, hwc->config);
+       hwc->state |= PERF_HES_STOPPED;
+
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               amd_uncore_read(event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+}
+
+static int amd_uncore_add(struct perf_event *event, int flags)
+{
+       int i;
+       struct amd_uncore *uncore = event_to_amd_uncore(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       /* are we already assigned? */
+       if (hwc->idx != -1 && uncore->events[hwc->idx] == event)
+               goto out;
+
+       for (i = 0; i < uncore->num_counters; i++) {
+               if (uncore->events[i] == event) {
+                       hwc->idx = i;
+                       goto out;
+               }
+       }
+
+       /* if not, take the first available counter */
+       hwc->idx = -1;
+       for (i = 0; i < uncore->num_counters; i++) {
+               if (cmpxchg(&uncore->events[i], NULL, event) == NULL) {
+                       hwc->idx = i;
+                       break;
+               }
+       }
+
+out:
+       if (hwc->idx == -1)
+               return -EBUSY;
+
+       hwc->config_base = uncore->msr_base + (2 * hwc->idx);
+       hwc->event_base = uncore->msr_base + 1 + (2 * hwc->idx);
+       hwc->event_base_rdpmc = uncore->rdpmc_base + hwc->idx;
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+       if (flags & PERF_EF_START)
+               amd_uncore_start(event, PERF_EF_RELOAD);
+
+       return 0;
+}
+
+static void amd_uncore_del(struct perf_event *event, int flags)
+{
+       int i;
+       struct amd_uncore *uncore = event_to_amd_uncore(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       amd_uncore_stop(event, PERF_EF_UPDATE);
+
+       for (i = 0; i < uncore->num_counters; i++) {
+               if (cmpxchg(&uncore->events[i], event, NULL) == event)
+                       break;
+       }
+
+       hwc->idx = -1;
+}
+
+static int amd_uncore_event_init(struct perf_event *event)
+{
+       struct amd_uncore *uncore;
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       /*
+        * NB and L2 counters (MSRs) are shared across all cores that share the
+        * same NB / L2 cache. Interrupts can be directed to a single target
+        * core, however, event counts generated by processes running on other
+        * cores cannot be masked out. So we do not support sampling and
+        * per-thread events.
+        */
+       if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+               return -EINVAL;
+
+       /* NB and L2 counters do not have usr/os/guest/host bits */
+       if (event->attr.exclude_user || event->attr.exclude_kernel ||
+           event->attr.exclude_host || event->attr.exclude_guest)
+               return -EINVAL;
+
+       /* and we do not enable counter overflow interrupts */
+       hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB;
+       hwc->idx = -1;
+
+       if (event->cpu < 0)
+               return -EINVAL;
+
+       uncore = event_to_amd_uncore(event);
+       if (!uncore)
+               return -ENODEV;
+
+       /*
+        * since request can come in to any of the shared cores, we will remap
+        * to a single common cpu.
+        */
+       event->cpu = uncore->cpu;
+
+       return 0;
+}
+
+static ssize_t amd_uncore_attr_show_cpumask(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       cpumask_t *active_mask;
+       struct pmu *pmu = dev_get_drvdata(dev);
+
+       if (pmu->type == amd_nb_pmu.type)
+               active_mask = &amd_nb_active_mask;
+       else if (pmu->type == amd_l2_pmu.type)
+               active_mask = &amd_l2_active_mask;
+       else
+               return 0;
+
+       return cpumap_print_to_pagebuf(true, buf, active_mask);
+}
+static DEVICE_ATTR(cpumask, S_IRUGO, amd_uncore_attr_show_cpumask, NULL);
+
+static struct attribute *amd_uncore_attrs[] = {
+       &dev_attr_cpumask.attr,
+       NULL,
+};
+
+static struct attribute_group amd_uncore_attr_group = {
+       .attrs = amd_uncore_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-7,32-35");
+PMU_FORMAT_ATTR(umask, "config:8-15");
+
+static struct attribute *amd_uncore_format_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       NULL,
+};
+
+static struct attribute_group amd_uncore_format_group = {
+       .name = "format",
+       .attrs = amd_uncore_format_attr,
+};
+
+static const struct attribute_group *amd_uncore_attr_groups[] = {
+       &amd_uncore_attr_group,
+       &amd_uncore_format_group,
+       NULL,
+};
+
+static struct pmu amd_nb_pmu = {
+       .attr_groups    = amd_uncore_attr_groups,
+       .name           = "amd_nb",
+       .event_init     = amd_uncore_event_init,
+       .add            = amd_uncore_add,
+       .del            = amd_uncore_del,
+       .start          = amd_uncore_start,
+       .stop           = amd_uncore_stop,
+       .read           = amd_uncore_read,
+};
+
+static struct pmu amd_l2_pmu = {
+       .attr_groups    = amd_uncore_attr_groups,
+       .name           = "amd_l2",
+       .event_init     = amd_uncore_event_init,
+       .add            = amd_uncore_add,
+       .del            = amd_uncore_del,
+       .start          = amd_uncore_start,
+       .stop           = amd_uncore_stop,
+       .read           = amd_uncore_read,
+};
+
+static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
+{
+       return kzalloc_node(sizeof(struct amd_uncore), GFP_KERNEL,
+                       cpu_to_node(cpu));
+}
+
+static int amd_uncore_cpu_up_prepare(unsigned int cpu)
+{
+       struct amd_uncore *uncore_nb = NULL, *uncore_l2;
+
+       if (amd_uncore_nb) {
+               uncore_nb = amd_uncore_alloc(cpu);
+               if (!uncore_nb)
+                       goto fail;
+               uncore_nb->cpu = cpu;
+               uncore_nb->num_counters = NUM_COUNTERS_NB;
+               uncore_nb->rdpmc_base = RDPMC_BASE_NB;
+               uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL;
+               uncore_nb->active_mask = &amd_nb_active_mask;
+               uncore_nb->pmu = &amd_nb_pmu;
+               *per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb;
+       }
+
+       if (amd_uncore_l2) {
+               uncore_l2 = amd_uncore_alloc(cpu);
+               if (!uncore_l2)
+                       goto fail;
+               uncore_l2->cpu = cpu;
+               uncore_l2->num_counters = NUM_COUNTERS_L2;
+               uncore_l2->rdpmc_base = RDPMC_BASE_L2;
+               uncore_l2->msr_base = MSR_F16H_L2I_PERF_CTL;
+               uncore_l2->active_mask = &amd_l2_active_mask;
+               uncore_l2->pmu = &amd_l2_pmu;
+               *per_cpu_ptr(amd_uncore_l2, cpu) = uncore_l2;
+       }
+
+       return 0;
+
+fail:
+       if (amd_uncore_nb)
+               *per_cpu_ptr(amd_uncore_nb, cpu) = NULL;
+       kfree(uncore_nb);
+       return -ENOMEM;
+}
+
+static struct amd_uncore *
+amd_uncore_find_online_sibling(struct amd_uncore *this,
+                              struct amd_uncore * __percpu *uncores)
+{
+       unsigned int cpu;
+       struct amd_uncore *that;
+
+       for_each_online_cpu(cpu) {
+               that = *per_cpu_ptr(uncores, cpu);
+
+               if (!that)
+                       continue;
+
+               if (this == that)
+                       continue;
+
+               if (this->id == that->id) {
+                       that->free_when_cpu_online = this;
+                       this = that;
+                       break;
+               }
+       }
+
+       this->refcnt++;
+       return this;
+}
+
+static void amd_uncore_cpu_starting(unsigned int cpu)
+{
+       unsigned int eax, ebx, ecx, edx;
+       struct amd_uncore *uncore;
+
+       if (amd_uncore_nb) {
+               uncore = *per_cpu_ptr(amd_uncore_nb, cpu);
+               cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
+               uncore->id = ecx & 0xff;
+
+               uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_nb);
+               *per_cpu_ptr(amd_uncore_nb, cpu) = uncore;
+       }
+
+       if (amd_uncore_l2) {
+               unsigned int apicid = cpu_data(cpu).apicid;
+               unsigned int nshared;
+
+               uncore = *per_cpu_ptr(amd_uncore_l2, cpu);
+               cpuid_count(0x8000001d, 2, &eax, &ebx, &ecx, &edx);
+               nshared = ((eax >> 14) & 0xfff) + 1;
+               uncore->id = apicid - (apicid % nshared);
+
+               uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_l2);
+               *per_cpu_ptr(amd_uncore_l2, cpu) = uncore;
+       }
+}
+
+static void uncore_online(unsigned int cpu,
+                         struct amd_uncore * __percpu *uncores)
+{
+       struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu);
+
+       kfree(uncore->free_when_cpu_online);
+       uncore->free_when_cpu_online = NULL;
+
+       if (cpu == uncore->cpu)
+               cpumask_set_cpu(cpu, uncore->active_mask);
+}
+
+static void amd_uncore_cpu_online(unsigned int cpu)
+{
+       if (amd_uncore_nb)
+               uncore_online(cpu, amd_uncore_nb);
+
+       if (amd_uncore_l2)
+               uncore_online(cpu, amd_uncore_l2);
+}
+
+static void uncore_down_prepare(unsigned int cpu,
+                               struct amd_uncore * __percpu *uncores)
+{
+       unsigned int i;
+       struct amd_uncore *this = *per_cpu_ptr(uncores, cpu);
+
+       if (this->cpu != cpu)
+               return;
+
+       /* this cpu is going down, migrate to a shared sibling if possible */
+       for_each_online_cpu(i) {
+               struct amd_uncore *that = *per_cpu_ptr(uncores, i);
+
+               if (cpu == i)
+                       continue;
+
+               if (this == that) {
+                       perf_pmu_migrate_context(this->pmu, cpu, i);
+                       cpumask_clear_cpu(cpu, that->active_mask);
+                       cpumask_set_cpu(i, that->active_mask);
+                       that->cpu = i;
+                       break;
+               }
+       }
+}
+
+static void amd_uncore_cpu_down_prepare(unsigned int cpu)
+{
+       if (amd_uncore_nb)
+               uncore_down_prepare(cpu, amd_uncore_nb);
+
+       if (amd_uncore_l2)
+               uncore_down_prepare(cpu, amd_uncore_l2);
+}
+
+static void uncore_dead(unsigned int cpu, struct amd_uncore * __percpu *uncores)
+{
+       struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu);
+
+       if (cpu == uncore->cpu)
+               cpumask_clear_cpu(cpu, uncore->active_mask);
+
+       if (!--uncore->refcnt)
+               kfree(uncore);
+       *per_cpu_ptr(uncores, cpu) = NULL;
+}
+
+static void amd_uncore_cpu_dead(unsigned int cpu)
+{
+       if (amd_uncore_nb)
+               uncore_dead(cpu, amd_uncore_nb);
+
+       if (amd_uncore_l2)
+               uncore_dead(cpu, amd_uncore_l2);
+}
+
+static int
+amd_uncore_cpu_notifier(struct notifier_block *self, unsigned long action,
+                       void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               if (amd_uncore_cpu_up_prepare(cpu))
+                       return notifier_from_errno(-ENOMEM);
+               break;
+
+       case CPU_STARTING:
+               amd_uncore_cpu_starting(cpu);
+               break;
+
+       case CPU_ONLINE:
+               amd_uncore_cpu_online(cpu);
+               break;
+
+       case CPU_DOWN_PREPARE:
+               amd_uncore_cpu_down_prepare(cpu);
+               break;
+
+       case CPU_UP_CANCELED:
+       case CPU_DEAD:
+               amd_uncore_cpu_dead(cpu);
+               break;
+
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block amd_uncore_cpu_notifier_block = {
+       .notifier_call  = amd_uncore_cpu_notifier,
+       .priority       = CPU_PRI_PERF + 1,
+};
+
+static void __init init_cpu_already_online(void *dummy)
+{
+       unsigned int cpu = smp_processor_id();
+
+       amd_uncore_cpu_starting(cpu);
+       amd_uncore_cpu_online(cpu);
+}
+
+static void cleanup_cpu_online(void *dummy)
+{
+       unsigned int cpu = smp_processor_id();
+
+       amd_uncore_cpu_dead(cpu);
+}
+
+static int __init amd_uncore_init(void)
+{
+       unsigned int cpu, cpu2;
+       int ret = -ENODEV;
+
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+               goto fail_nodev;
+
+       if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
+               goto fail_nodev;
+
+       if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) {
+               amd_uncore_nb = alloc_percpu(struct amd_uncore *);
+               if (!amd_uncore_nb) {
+                       ret = -ENOMEM;
+                       goto fail_nb;
+               }
+               ret = perf_pmu_register(&amd_nb_pmu, amd_nb_pmu.name, -1);
+               if (ret)
+                       goto fail_nb;
+
+               pr_info("perf: AMD NB counters detected\n");
+               ret = 0;
+       }
+
+       if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) {
+               amd_uncore_l2 = alloc_percpu(struct amd_uncore *);
+               if (!amd_uncore_l2) {
+                       ret = -ENOMEM;
+                       goto fail_l2;
+               }
+               ret = perf_pmu_register(&amd_l2_pmu, amd_l2_pmu.name, -1);
+               if (ret)
+                       goto fail_l2;
+
+               pr_info("perf: AMD L2I counters detected\n");
+               ret = 0;
+       }
+
+       if (ret)
+               goto fail_nodev;
+
+       cpu_notifier_register_begin();
+
+       /* init cpus already online before registering for hotplug notifier */
+       for_each_online_cpu(cpu) {
+               ret = amd_uncore_cpu_up_prepare(cpu);
+               if (ret)
+                       goto fail_online;
+               smp_call_function_single(cpu, init_cpu_already_online, NULL, 1);
+       }
+
+       __register_cpu_notifier(&amd_uncore_cpu_notifier_block);
+       cpu_notifier_register_done();
+
+       return 0;
+
+
+fail_online:
+       for_each_online_cpu(cpu2) {
+               if (cpu2 == cpu)
+                       break;
+               smp_call_function_single(cpu, cleanup_cpu_online, NULL, 1);
+       }
+       cpu_notifier_register_done();
+
+       /* amd_uncore_nb/l2 should have been freed by cleanup_cpu_online */
+       amd_uncore_nb = amd_uncore_l2 = NULL;
+
+       if (boot_cpu_has(X86_FEATURE_PERFCTR_L2))
+               perf_pmu_unregister(&amd_l2_pmu);
+fail_l2:
+       if (boot_cpu_has(X86_FEATURE_PERFCTR_NB))
+               perf_pmu_unregister(&amd_nb_pmu);
+       if (amd_uncore_l2)
+               free_percpu(amd_uncore_l2);
+fail_nb:
+       if (amd_uncore_nb)
+               free_percpu(amd_uncore_nb);
+
+fail_nodev:
+       return ret;
+}
+device_initcall(amd_uncore_init);
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
new file mode 100644 (file)
index 0000000..5e830d0
--- /dev/null
@@ -0,0 +1,2442 @@
+/*
+ * Performance events x86 architecture code
+ *
+ *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
+ *  Copyright (C) 2009 Jaswinder Singh Rajput
+ *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
+ *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
+ *  Copyright (C) 2009 Google, Inc., Stephane Eranian
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+#include <linux/capability.h>
+#include <linux/notifier.h>
+#include <linux/hardirq.h>
+#include <linux/kprobes.h>
+#include <linux/module.h>
+#include <linux/kdebug.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+
+#include <asm/apic.h>
+#include <asm/stacktrace.h>
+#include <asm/nmi.h>
+#include <asm/smp.h>
+#include <asm/alternative.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+#include <asm/timer.h>
+#include <asm/desc.h>
+#include <asm/ldt.h>
+
+#include "perf_event.h"
+
+struct x86_pmu x86_pmu __read_mostly;
+
+DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
+       .enabled = 1,
+};
+
+struct static_key rdpmc_always_available = STATIC_KEY_INIT_FALSE;
+
+u64 __read_mostly hw_cache_event_ids
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
+u64 __read_mostly hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
+
+/*
+ * Propagate event elapsed time into the generic event.
+ * Can only be executed on the CPU where the event is active.
+ * Returns the delta events processed.
+ */
+u64 x86_perf_event_update(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       int shift = 64 - x86_pmu.cntval_bits;
+       u64 prev_raw_count, new_raw_count;
+       int idx = hwc->idx;
+       s64 delta;
+
+       if (idx == INTEL_PMC_IDX_FIXED_BTS)
+               return 0;
+
+       /*
+        * Careful: an NMI might modify the previous event value.
+        *
+        * Our tactic to handle this is to first atomically read and
+        * exchange a new raw count - then add that new-prev delta
+        * count to the generic event atomically:
+        */
+again:
+       prev_raw_count = local64_read(&hwc->prev_count);
+       rdpmcl(hwc->event_base_rdpmc, new_raw_count);
+
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                                       new_raw_count) != prev_raw_count)
+               goto again;
+
+       /*
+        * Now we have the new raw value and have updated the prev
+        * timestamp already. We can now calculate the elapsed delta
+        * (event-)time and add that to the generic event.
+        *
+        * Careful, not all hw sign-extends above the physical width
+        * of the count.
+        */
+       delta = (new_raw_count << shift) - (prev_raw_count << shift);
+       delta >>= shift;
+
+       local64_add(delta, &event->count);
+       local64_sub(delta, &hwc->period_left);
+
+       return new_raw_count;
+}
+
+/*
+ * Find and validate any extra registers to set up.
+ */
+static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg;
+       struct extra_reg *er;
+
+       reg = &event->hw.extra_reg;
+
+       if (!x86_pmu.extra_regs)
+               return 0;
+
+       for (er = x86_pmu.extra_regs; er->msr; er++) {
+               if (er->event != (config & er->config_mask))
+                       continue;
+               if (event->attr.config1 & ~er->valid_mask)
+                       return -EINVAL;
+               /* Check if the extra msrs can be safely accessed*/
+               if (!er->extra_msr_access)
+                       return -ENXIO;
+
+               reg->idx = er->idx;
+               reg->config = event->attr.config1;
+               reg->reg = er->msr;
+               break;
+       }
+       return 0;
+}
+
+static atomic_t active_events;
+static atomic_t pmc_refcount;
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+static bool reserve_pmc_hardware(void)
+{
+       int i;
+
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+               if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
+                       goto perfctr_fail;
+       }
+
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+               if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
+                       goto eventsel_fail;
+       }
+
+       return true;
+
+eventsel_fail:
+       for (i--; i >= 0; i--)
+               release_evntsel_nmi(x86_pmu_config_addr(i));
+
+       i = x86_pmu.num_counters;
+
+perfctr_fail:
+       for (i--; i >= 0; i--)
+               release_perfctr_nmi(x86_pmu_event_addr(i));
+
+       return false;
+}
+
+static void release_pmc_hardware(void)
+{
+       int i;
+
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+               release_perfctr_nmi(x86_pmu_event_addr(i));
+               release_evntsel_nmi(x86_pmu_config_addr(i));
+       }
+}
+
+#else
+
+static bool reserve_pmc_hardware(void) { return true; }
+static void release_pmc_hardware(void) {}
+
+#endif
+
+static bool check_hw_exists(void)
+{
+       u64 val, val_fail, val_new= ~0;
+       int i, reg, reg_fail, ret = 0;
+       int bios_fail = 0;
+       int reg_safe = -1;
+
+       /*
+        * Check to see if the BIOS enabled any of the counters, if so
+        * complain and bail.
+        */
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+               reg = x86_pmu_config_addr(i);
+               ret = rdmsrl_safe(reg, &val);
+               if (ret)
+                       goto msr_fail;
+               if (val & ARCH_PERFMON_EVENTSEL_ENABLE) {
+                       bios_fail = 1;
+                       val_fail = val;
+                       reg_fail = reg;
+               } else {
+                       reg_safe = i;
+               }
+       }
+
+       if (x86_pmu.num_counters_fixed) {
+               reg = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
+               ret = rdmsrl_safe(reg, &val);
+               if (ret)
+                       goto msr_fail;
+               for (i = 0; i < x86_pmu.num_counters_fixed; i++) {
+                       if (val & (0x03 << i*4)) {
+                               bios_fail = 1;
+                               val_fail = val;
+                               reg_fail = reg;
+                       }
+               }
+       }
+
+       /*
+        * If all the counters are enabled, the below test will always
+        * fail.  The tools will also become useless in this scenario.
+        * Just fail and disable the hardware counters.
+        */
+
+       if (reg_safe == -1) {
+               reg = reg_safe;
+               goto msr_fail;
+       }
+
+       /*
+        * Read the current value, change it and read it back to see if it
+        * matches, this is needed to detect certain hardware emulators
+        * (qemu/kvm) that don't trap on the MSR access and always return 0s.
+        */
+       reg = x86_pmu_event_addr(reg_safe);
+       if (rdmsrl_safe(reg, &val))
+               goto msr_fail;
+       val ^= 0xffffUL;
+       ret = wrmsrl_safe(reg, val);
+       ret |= rdmsrl_safe(reg, &val_new);
+       if (ret || val != val_new)
+               goto msr_fail;
+
+       /*
+        * We still allow the PMU driver to operate:
+        */
+       if (bios_fail) {
+               pr_cont("Broken BIOS detected, complain to your hardware vendor.\n");
+               pr_err(FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n",
+                             reg_fail, val_fail);
+       }
+
+       return true;
+
+msr_fail:
+       pr_cont("Broken PMU hardware detected, using software events only.\n");
+       pr_info("%sFailed to access perfctr msr (MSR %x is %Lx)\n",
+               boot_cpu_has(X86_FEATURE_HYPERVISOR) ? KERN_INFO : KERN_ERR,
+               reg, val_new);
+
+       return false;
+}
+
+static void hw_perf_event_destroy(struct perf_event *event)
+{
+       x86_release_hardware();
+       atomic_dec(&active_events);
+}
+
+void hw_perf_lbr_event_destroy(struct perf_event *event)
+{
+       hw_perf_event_destroy(event);
+
+       /* undo the lbr/bts event accounting */
+       x86_del_exclusive(x86_lbr_exclusive_lbr);
+}
+
+static inline int x86_pmu_initialized(void)
+{
+       return x86_pmu.handle_irq != NULL;
+}
+
+static inline int
+set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
+{
+       struct perf_event_attr *attr = &event->attr;
+       unsigned int cache_type, cache_op, cache_result;
+       u64 config, val;
+
+       config = attr->config;
+
+       cache_type = (config >>  0) & 0xff;
+       if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
+               return -EINVAL;
+
+       cache_op = (config >>  8) & 0xff;
+       if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
+               return -EINVAL;
+
+       cache_result = (config >> 16) & 0xff;
+       if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+               return -EINVAL;
+
+       val = hw_cache_event_ids[cache_type][cache_op][cache_result];
+
+       if (val == 0)
+               return -ENOENT;
+
+       if (val == -1)
+               return -EINVAL;
+
+       hwc->config |= val;
+       attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
+       return x86_pmu_extra_regs(val, event);
+}
+
+int x86_reserve_hardware(void)
+{
+       int err = 0;
+
+       if (!atomic_inc_not_zero(&pmc_refcount)) {
+               mutex_lock(&pmc_reserve_mutex);
+               if (atomic_read(&pmc_refcount) == 0) {
+                       if (!reserve_pmc_hardware())
+                               err = -EBUSY;
+                       else
+                               reserve_ds_buffers();
+               }
+               if (!err)
+                       atomic_inc(&pmc_refcount);
+               mutex_unlock(&pmc_reserve_mutex);
+       }
+
+       return err;
+}
+
+void x86_release_hardware(void)
+{
+       if (atomic_dec_and_mutex_lock(&pmc_refcount, &pmc_reserve_mutex)) {
+               release_pmc_hardware();
+               release_ds_buffers();
+               mutex_unlock(&pmc_reserve_mutex);
+       }
+}
+
+/*
+ * Check if we can create event of a certain type (that no conflicting events
+ * are present).
+ */
+int x86_add_exclusive(unsigned int what)
+{
+       int i;
+
+       if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
+               mutex_lock(&pmc_reserve_mutex);
+               for (i = 0; i < ARRAY_SIZE(x86_pmu.lbr_exclusive); i++) {
+                       if (i != what && atomic_read(&x86_pmu.lbr_exclusive[i]))
+                               goto fail_unlock;
+               }
+               atomic_inc(&x86_pmu.lbr_exclusive[what]);
+               mutex_unlock(&pmc_reserve_mutex);
+       }
+
+       atomic_inc(&active_events);
+       return 0;
+
+fail_unlock:
+       mutex_unlock(&pmc_reserve_mutex);
+       return -EBUSY;
+}
+
+void x86_del_exclusive(unsigned int what)
+{
+       atomic_dec(&x86_pmu.lbr_exclusive[what]);
+       atomic_dec(&active_events);
+}
+
+int x86_setup_perfctr(struct perf_event *event)
+{
+       struct perf_event_attr *attr = &event->attr;
+       struct hw_perf_event *hwc = &event->hw;
+       u64 config;
+
+       if (!is_sampling_event(event)) {
+               hwc->sample_period = x86_pmu.max_period;
+               hwc->last_period = hwc->sample_period;
+               local64_set(&hwc->period_left, hwc->sample_period);
+       }
+
+       if (attr->type == PERF_TYPE_RAW)
+               return x86_pmu_extra_regs(event->attr.config, event);
+
+       if (attr->type == PERF_TYPE_HW_CACHE)
+               return set_ext_hw_attr(hwc, event);
+
+       if (attr->config >= x86_pmu.max_events)
+               return -EINVAL;
+
+       /*
+        * The generic map:
+        */
+       config = x86_pmu.event_map(attr->config);
+
+       if (config == 0)
+               return -ENOENT;
+
+       if (config == -1LL)
+               return -EINVAL;
+
+       /*
+        * Branch tracing:
+        */
+       if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
+           !attr->freq && hwc->sample_period == 1) {
+               /* BTS is not supported by this architecture. */
+               if (!x86_pmu.bts_active)
+                       return -EOPNOTSUPP;
+
+               /* BTS is currently only allowed for user-mode. */
+               if (!attr->exclude_kernel)
+                       return -EOPNOTSUPP;
+
+               /* disallow bts if conflicting events are present */
+               if (x86_add_exclusive(x86_lbr_exclusive_lbr))
+                       return -EBUSY;
+
+               event->destroy = hw_perf_lbr_event_destroy;
+       }
+
+       hwc->config |= config;
+
+       return 0;
+}
+
+/*
+ * check that branch_sample_type is compatible with
+ * settings needed for precise_ip > 1 which implies
+ * using the LBR to capture ALL taken branches at the
+ * priv levels of the measurement
+ */
+static inline int precise_br_compat(struct perf_event *event)
+{
+       u64 m = event->attr.branch_sample_type;
+       u64 b = 0;
+
+       /* must capture all branches */
+       if (!(m & PERF_SAMPLE_BRANCH_ANY))
+               return 0;
+
+       m &= PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_USER;
+
+       if (!event->attr.exclude_user)
+               b |= PERF_SAMPLE_BRANCH_USER;
+
+       if (!event->attr.exclude_kernel)
+               b |= PERF_SAMPLE_BRANCH_KERNEL;
+
+       /*
+        * ignore PERF_SAMPLE_BRANCH_HV, not supported on x86
+        */
+
+       return m == b;
+}
+
+int x86_pmu_hw_config(struct perf_event *event)
+{
+       if (event->attr.precise_ip) {
+               int precise = 0;
+
+               /* Support for constant skid */
+               if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
+                       precise++;
+
+                       /* Support for IP fixup */
+                       if (x86_pmu.lbr_nr || x86_pmu.intel_cap.pebs_format >= 2)
+                               precise++;
+
+                       if (x86_pmu.pebs_prec_dist)
+                               precise++;
+               }
+
+               if (event->attr.precise_ip > precise)
+                       return -EOPNOTSUPP;
+       }
+       /*
+        * check that PEBS LBR correction does not conflict with
+        * whatever the user is asking with attr->branch_sample_type
+        */
+       if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format < 2) {
+               u64 *br_type = &event->attr.branch_sample_type;
+
+               if (has_branch_stack(event)) {
+                       if (!precise_br_compat(event))
+                               return -EOPNOTSUPP;
+
+                       /* branch_sample_type is compatible */
+
+               } else {
+                       /*
+                        * user did not specify  branch_sample_type
+                        *
+                        * For PEBS fixups, we capture all
+                        * the branches at the priv level of the
+                        * event.
+                        */
+                       *br_type = PERF_SAMPLE_BRANCH_ANY;
+
+                       if (!event->attr.exclude_user)
+                               *br_type |= PERF_SAMPLE_BRANCH_USER;
+
+                       if (!event->attr.exclude_kernel)
+                               *br_type |= PERF_SAMPLE_BRANCH_KERNEL;
+               }
+       }
+
+       if (event->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK)
+               event->attach_state |= PERF_ATTACH_TASK_DATA;
+
+       /*
+        * Generate PMC IRQs:
+        * (keep 'enabled' bit clear for now)
+        */
+       event->hw.config = ARCH_PERFMON_EVENTSEL_INT;
+
+       /*
+        * Count user and OS events unless requested not to
+        */
+       if (!event->attr.exclude_user)
+               event->hw.config |= ARCH_PERFMON_EVENTSEL_USR;
+       if (!event->attr.exclude_kernel)
+               event->hw.config |= ARCH_PERFMON_EVENTSEL_OS;
+
+       if (event->attr.type == PERF_TYPE_RAW)
+               event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK;
+
+       if (event->attr.sample_period && x86_pmu.limit_period) {
+               if (x86_pmu.limit_period(event, event->attr.sample_period) >
+                               event->attr.sample_period)
+                       return -EINVAL;
+       }
+
+       return x86_setup_perfctr(event);
+}
+
+/*
+ * Setup the hardware configuration for a given attr_type
+ */
+static int __x86_pmu_event_init(struct perf_event *event)
+{
+       int err;
+
+       if (!x86_pmu_initialized())
+               return -ENODEV;
+
+       err = x86_reserve_hardware();
+       if (err)
+               return err;
+
+       atomic_inc(&active_events);
+       event->destroy = hw_perf_event_destroy;
+
+       event->hw.idx = -1;
+       event->hw.last_cpu = -1;
+       event->hw.last_tag = ~0ULL;
+
+       /* mark unused */
+       event->hw.extra_reg.idx = EXTRA_REG_NONE;
+       event->hw.branch_reg.idx = EXTRA_REG_NONE;
+
+       return x86_pmu.hw_config(event);
+}
+
+void x86_pmu_disable_all(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               u64 val;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+               rdmsrl(x86_pmu_config_addr(idx), val);
+               if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
+                       continue;
+               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+               wrmsrl(x86_pmu_config_addr(idx), val);
+       }
+}
+
+/*
+ * There may be PMI landing after enabled=0. The PMI hitting could be before or
+ * after disable_all.
+ *
+ * If PMI hits before disable_all, the PMU will be disabled in the NMI handler.
+ * It will not be re-enabled in the NMI handler again, because enabled=0. After
+ * handling the NMI, disable_all will be called, which will not change the
+ * state either. If PMI hits after disable_all, the PMU is already disabled
+ * before entering NMI handler. The NMI handler will not change the state
+ * either.
+ *
+ * So either situation is harmless.
+ */
+static void x86_pmu_disable(struct pmu *pmu)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       if (!x86_pmu_initialized())
+               return;
+
+       if (!cpuc->enabled)
+               return;
+
+       cpuc->n_added = 0;
+       cpuc->enabled = 0;
+       barrier();
+
+       x86_pmu.disable_all();
+}
+
+void x86_pmu_enable_all(int added)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
+       }
+}
+
+static struct pmu pmu;
+
+static inline int is_x86_event(struct perf_event *event)
+{
+       return event->pmu == &pmu;
+}
+
+/*
+ * Event scheduler state:
+ *
+ * Assign events iterating over all events and counters, beginning
+ * with events with least weights first. Keep the current iterator
+ * state in struct sched_state.
+ */
+struct sched_state {
+       int     weight;
+       int     event;          /* event index */
+       int     counter;        /* counter index */
+       int     unassigned;     /* number of events to be assigned left */
+       int     nr_gp;          /* number of GP counters used */
+       unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+};
+
+/* Total max is X86_PMC_IDX_MAX, but we are O(n!) limited */
+#define        SCHED_STATES_MAX        2
+
+struct perf_sched {
+       int                     max_weight;
+       int                     max_events;
+       int                     max_gp;
+       int                     saved_states;
+       struct event_constraint **constraints;
+       struct sched_state      state;
+       struct sched_state      saved[SCHED_STATES_MAX];
+};
+
+/*
+ * Initialize interator that runs through all events and counters.
+ */
+static void perf_sched_init(struct perf_sched *sched, struct event_constraint **constraints,
+                           int num, int wmin, int wmax, int gpmax)
+{
+       int idx;
+
+       memset(sched, 0, sizeof(*sched));
+       sched->max_events       = num;
+       sched->max_weight       = wmax;
+       sched->max_gp           = gpmax;
+       sched->constraints      = constraints;
+
+       for (idx = 0; idx < num; idx++) {
+               if (constraints[idx]->weight == wmin)
+                       break;
+       }
+
+       sched->state.event      = idx;          /* start with min weight */
+       sched->state.weight     = wmin;
+       sched->state.unassigned = num;
+}
+
+static void perf_sched_save_state(struct perf_sched *sched)
+{
+       if (WARN_ON_ONCE(sched->saved_states >= SCHED_STATES_MAX))
+               return;
+
+       sched->saved[sched->saved_states] = sched->state;
+       sched->saved_states++;
+}
+
+static bool perf_sched_restore_state(struct perf_sched *sched)
+{
+       if (!sched->saved_states)
+               return false;
+
+       sched->saved_states--;
+       sched->state = sched->saved[sched->saved_states];
+
+       /* continue with next counter: */
+       clear_bit(sched->state.counter++, sched->state.used);
+
+       return true;
+}
+
+/*
+ * Select a counter for the current event to schedule. Return true on
+ * success.
+ */
+static bool __perf_sched_find_counter(struct perf_sched *sched)
+{
+       struct event_constraint *c;
+       int idx;
+
+       if (!sched->state.unassigned)
+               return false;
+
+       if (sched->state.event >= sched->max_events)
+               return false;
+
+       c = sched->constraints[sched->state.event];
+       /* Prefer fixed purpose counters */
+       if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
+               idx = INTEL_PMC_IDX_FIXED;
+               for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) {
+                       if (!__test_and_set_bit(idx, sched->state.used))
+                               goto done;
+               }
+       }
+
+       /* Grab the first unused counter starting with idx */
+       idx = sched->state.counter;
+       for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
+               if (!__test_and_set_bit(idx, sched->state.used)) {
+                       if (sched->state.nr_gp++ >= sched->max_gp)
+                               return false;
+
+                       goto done;
+               }
+       }
+
+       return false;
+
+done:
+       sched->state.counter = idx;
+
+       if (c->overlap)
+               perf_sched_save_state(sched);
+
+       return true;
+}
+
+static bool perf_sched_find_counter(struct perf_sched *sched)
+{
+       while (!__perf_sched_find_counter(sched)) {
+               if (!perf_sched_restore_state(sched))
+                       return false;
+       }
+
+       return true;
+}
+
+/*
+ * Go through all unassigned events and find the next one to schedule.
+ * Take events with the least weight first. Return true on success.
+ */
+static bool perf_sched_next_event(struct perf_sched *sched)
+{
+       struct event_constraint *c;
+
+       if (!sched->state.unassigned || !--sched->state.unassigned)
+               return false;
+
+       do {
+               /* next event */
+               sched->state.event++;
+               if (sched->state.event >= sched->max_events) {
+                       /* next weight */
+                       sched->state.event = 0;
+                       sched->state.weight++;
+                       if (sched->state.weight > sched->max_weight)
+                               return false;
+               }
+               c = sched->constraints[sched->state.event];
+       } while (c->weight != sched->state.weight);
+
+       sched->state.counter = 0;       /* start with first counter */
+
+       return true;
+}
+
+/*
+ * Assign a counter for each event.
+ */
+int perf_assign_events(struct event_constraint **constraints, int n,
+                       int wmin, int wmax, int gpmax, int *assign)
+{
+       struct perf_sched sched;
+
+       perf_sched_init(&sched, constraints, n, wmin, wmax, gpmax);
+
+       do {
+               if (!perf_sched_find_counter(&sched))
+                       break;  /* failed */
+               if (assign)
+                       assign[sched.state.event] = sched.state.counter;
+       } while (perf_sched_next_event(&sched));
+
+       return sched.state.unassigned;
+}
+EXPORT_SYMBOL_GPL(perf_assign_events);
+
+int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+{
+       struct event_constraint *c;
+       unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+       struct perf_event *e;
+       int i, wmin, wmax, unsched = 0;
+       struct hw_perf_event *hwc;
+
+       bitmap_zero(used_mask, X86_PMC_IDX_MAX);
+
+       if (x86_pmu.start_scheduling)
+               x86_pmu.start_scheduling(cpuc);
+
+       for (i = 0, wmin = X86_PMC_IDX_MAX, wmax = 0; i < n; i++) {
+               cpuc->event_constraint[i] = NULL;
+               c = x86_pmu.get_event_constraints(cpuc, i, cpuc->event_list[i]);
+               cpuc->event_constraint[i] = c;
+
+               wmin = min(wmin, c->weight);
+               wmax = max(wmax, c->weight);
+       }
+
+       /*
+        * fastpath, try to reuse previous register
+        */
+       for (i = 0; i < n; i++) {
+               hwc = &cpuc->event_list[i]->hw;
+               c = cpuc->event_constraint[i];
+
+               /* never assigned */
+               if (hwc->idx == -1)
+                       break;
+
+               /* constraint still honored */
+               if (!test_bit(hwc->idx, c->idxmsk))
+                       break;
+
+               /* not already used */
+               if (test_bit(hwc->idx, used_mask))
+                       break;
+
+               __set_bit(hwc->idx, used_mask);
+               if (assign)
+                       assign[i] = hwc->idx;
+       }
+
+       /* slow path */
+       if (i != n) {
+               int gpmax = x86_pmu.num_counters;
+
+               /*
+                * Do not allow scheduling of more than half the available
+                * generic counters.
+                *
+                * This helps avoid counter starvation of sibling thread by
+                * ensuring at most half the counters cannot be in exclusive
+                * mode. There is no designated counters for the limits. Any
+                * N/2 counters can be used. This helps with events with
+                * specific counter constraints.
+                */
+               if (is_ht_workaround_enabled() && !cpuc->is_fake &&
+                   READ_ONCE(cpuc->excl_cntrs->exclusive_present))
+                       gpmax /= 2;
+
+               unsched = perf_assign_events(cpuc->event_constraint, n, wmin,
+                                            wmax, gpmax, assign);
+       }
+
+       /*
+        * In case of success (unsched = 0), mark events as committed,
+        * so we do not put_constraint() in case new events are added
+        * and fail to be scheduled
+        *
+        * We invoke the lower level commit callback to lock the resource
+        *
+        * We do not need to do all of this in case we are called to
+        * validate an event group (assign == NULL)
+        */
+       if (!unsched && assign) {
+               for (i = 0; i < n; i++) {
+                       e = cpuc->event_list[i];
+                       e->hw.flags |= PERF_X86_EVENT_COMMITTED;
+                       if (x86_pmu.commit_scheduling)
+                               x86_pmu.commit_scheduling(cpuc, i, assign[i]);
+               }
+       } else {
+               for (i = 0; i < n; i++) {
+                       e = cpuc->event_list[i];
+                       /*
+                        * do not put_constraint() on comitted events,
+                        * because they are good to go
+                        */
+                       if ((e->hw.flags & PERF_X86_EVENT_COMMITTED))
+                               continue;
+
+                       /*
+                        * release events that failed scheduling
+                        */
+                       if (x86_pmu.put_event_constraints)
+                               x86_pmu.put_event_constraints(cpuc, e);
+               }
+       }
+
+       if (x86_pmu.stop_scheduling)
+               x86_pmu.stop_scheduling(cpuc);
+
+       return unsched ? -EINVAL : 0;
+}
+
+/*
+ * dogrp: true if must collect siblings events (group)
+ * returns total number of events and error code
+ */
+static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, bool dogrp)
+{
+       struct perf_event *event;
+       int n, max_count;
+
+       max_count = x86_pmu.num_counters + x86_pmu.num_counters_fixed;
+
+       /* current number of events already accepted */
+       n = cpuc->n_events;
+
+       if (is_x86_event(leader)) {
+               if (n >= max_count)
+                       return -EINVAL;
+               cpuc->event_list[n] = leader;
+               n++;
+       }
+       if (!dogrp)
+               return n;
+
+       list_for_each_entry(event, &leader->sibling_list, group_entry) {
+               if (!is_x86_event(event) ||
+                   event->state <= PERF_EVENT_STATE_OFF)
+                       continue;
+
+               if (n >= max_count)
+                       return -EINVAL;
+
+               cpuc->event_list[n] = event;
+               n++;
+       }
+       return n;
+}
+
+static inline void x86_assign_hw_event(struct perf_event *event,
+                               struct cpu_hw_events *cpuc, int i)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       hwc->idx = cpuc->assign[i];
+       hwc->last_cpu = smp_processor_id();
+       hwc->last_tag = ++cpuc->tags[i];
+
+       if (hwc->idx == INTEL_PMC_IDX_FIXED_BTS) {
+               hwc->config_base = 0;
+               hwc->event_base = 0;
+       } else if (hwc->idx >= INTEL_PMC_IDX_FIXED) {
+               hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
+               hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - INTEL_PMC_IDX_FIXED);
+               hwc->event_base_rdpmc = (hwc->idx - INTEL_PMC_IDX_FIXED) | 1<<30;
+       } else {
+               hwc->config_base = x86_pmu_config_addr(hwc->idx);
+               hwc->event_base  = x86_pmu_event_addr(hwc->idx);
+               hwc->event_base_rdpmc = x86_pmu_rdpmc_index(hwc->idx);
+       }
+}
+
+static inline int match_prev_assignment(struct hw_perf_event *hwc,
+                                       struct cpu_hw_events *cpuc,
+                                       int i)
+{
+       return hwc->idx == cpuc->assign[i] &&
+               hwc->last_cpu == smp_processor_id() &&
+               hwc->last_tag == cpuc->tags[i];
+}
+
+static void x86_pmu_start(struct perf_event *event, int flags);
+
+static void x86_pmu_enable(struct pmu *pmu)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct perf_event *event;
+       struct hw_perf_event *hwc;
+       int i, added = cpuc->n_added;
+
+       if (!x86_pmu_initialized())
+               return;
+
+       if (cpuc->enabled)
+               return;
+
+       if (cpuc->n_added) {
+               int n_running = cpuc->n_events - cpuc->n_added;
+               /*
+                * apply assignment obtained either from
+                * hw_perf_group_sched_in() or x86_pmu_enable()
+                *
+                * step1: save events moving to new counters
+                */
+               for (i = 0; i < n_running; i++) {
+                       event = cpuc->event_list[i];
+                       hwc = &event->hw;
+
+                       /*
+                        * we can avoid reprogramming counter if:
+                        * - assigned same counter as last time
+                        * - running on same CPU as last time
+                        * - no other event has used the counter since
+                        */
+                       if (hwc->idx == -1 ||
+                           match_prev_assignment(hwc, cpuc, i))
+                               continue;
+
+                       /*
+                        * Ensure we don't accidentally enable a stopped
+                        * counter simply because we rescheduled.
+                        */
+                       if (hwc->state & PERF_HES_STOPPED)
+                               hwc->state |= PERF_HES_ARCH;
+
+                       x86_pmu_stop(event, PERF_EF_UPDATE);
+               }
+
+               /*
+                * step2: reprogram moved events into new counters
+                */
+               for (i = 0; i < cpuc->n_events; i++) {
+                       event = cpuc->event_list[i];
+                       hwc = &event->hw;
+
+                       if (!match_prev_assignment(hwc, cpuc, i))
+                               x86_assign_hw_event(event, cpuc, i);
+                       else if (i < n_running)
+                               continue;
+
+                       if (hwc->state & PERF_HES_ARCH)
+                               continue;
+
+                       x86_pmu_start(event, PERF_EF_RELOAD);
+               }
+               cpuc->n_added = 0;
+               perf_events_lapic_init();
+       }
+
+       cpuc->enabled = 1;
+       barrier();
+
+       x86_pmu.enable_all(added);
+}
+
+static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
+
+/*
+ * Set the next IRQ period, based on the hwc->period_left value.
+ * To be called with the event disabled in hw:
+ */
+int x86_perf_event_set_period(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       s64 left = local64_read(&hwc->period_left);
+       s64 period = hwc->sample_period;
+       int ret = 0, idx = hwc->idx;
+
+       if (idx == INTEL_PMC_IDX_FIXED_BTS)
+               return 0;
+
+       /*
+        * If we are way outside a reasonable range then just skip forward:
+        */
+       if (unlikely(left <= -period)) {
+               left = period;
+               local64_set(&hwc->period_left, left);
+               hwc->last_period = period;
+               ret = 1;
+       }
+
+       if (unlikely(left <= 0)) {
+               left += period;
+               local64_set(&hwc->period_left, left);
+               hwc->last_period = period;
+               ret = 1;
+       }
+       /*
+        * Quirk: certain CPUs dont like it if just 1 hw_event is left:
+        */
+       if (unlikely(left < 2))
+               left = 2;
+
+       if (left > x86_pmu.max_period)
+               left = x86_pmu.max_period;
+
+       if (x86_pmu.limit_period)
+               left = x86_pmu.limit_period(event, left);
+
+       per_cpu(pmc_prev_left[idx], smp_processor_id()) = left;
+
+       if (!(hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) ||
+           local64_read(&hwc->prev_count) != (u64)-left) {
+               /*
+                * The hw event starts counting from this event offset,
+                * mark it to be able to extra future deltas:
+                */
+               local64_set(&hwc->prev_count, (u64)-left);
+
+               wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
+       }
+
+       /*
+        * Due to erratum on certan cpu we need
+        * a second write to be sure the register
+        * is updated properly
+        */
+       if (x86_pmu.perfctr_second_write) {
+               wrmsrl(hwc->event_base,
+                       (u64)(-left) & x86_pmu.cntval_mask);
+       }
+
+       perf_event_update_userpage(event);
+
+       return ret;
+}
+
+void x86_pmu_enable_event(struct perf_event *event)
+{
+       if (__this_cpu_read(cpu_hw_events.enabled))
+               __x86_pmu_enable_event(&event->hw,
+                                      ARCH_PERFMON_EVENTSEL_ENABLE);
+}
+
+/*
+ * Add a single event to the PMU.
+ *
+ * The event is added to the group of enabled events
+ * but only if it can be scehduled with existing events.
+ */
+static int x86_pmu_add(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct hw_perf_event *hwc;
+       int assign[X86_PMC_IDX_MAX];
+       int n, n0, ret;
+
+       hwc = &event->hw;
+
+       n0 = cpuc->n_events;
+       ret = n = collect_events(cpuc, event, false);
+       if (ret < 0)
+               goto out;
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+       if (!(flags & PERF_EF_START))
+               hwc->state |= PERF_HES_ARCH;
+
+       /*
+        * If group events scheduling transaction was started,
+        * skip the schedulability test here, it will be performed
+        * at commit time (->commit_txn) as a whole.
+        */
+       if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
+               goto done_collect;
+
+       ret = x86_pmu.schedule_events(cpuc, n, assign);
+       if (ret)
+               goto out;
+       /*
+        * copy new assignment, now we know it is possible
+        * will be used by hw_perf_enable()
+        */
+       memcpy(cpuc->assign, assign, n*sizeof(int));
+
+done_collect:
+       /*
+        * Commit the collect_events() state. See x86_pmu_del() and
+        * x86_pmu_*_txn().
+        */
+       cpuc->n_events = n;
+       cpuc->n_added += n - n0;
+       cpuc->n_txn += n - n0;
+
+       ret = 0;
+out:
+       return ret;
+}
+
+static void x86_pmu_start(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx = event->hw.idx;
+
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       if (WARN_ON_ONCE(idx == -1))
+               return;
+
+       if (flags & PERF_EF_RELOAD) {
+               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+               x86_perf_event_set_period(event);
+       }
+
+       event->hw.state = 0;
+
+       cpuc->events[idx] = event;
+       __set_bit(idx, cpuc->active_mask);
+       __set_bit(idx, cpuc->running);
+       x86_pmu.enable(event);
+       perf_event_update_userpage(event);
+}
+
+void perf_event_print_debug(void)
+{
+       u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
+       u64 pebs, debugctl;
+       struct cpu_hw_events *cpuc;
+       unsigned long flags;
+       int cpu, idx;
+
+       if (!x86_pmu.num_counters)
+               return;
+
+       local_irq_save(flags);
+
+       cpu = smp_processor_id();
+       cpuc = &per_cpu(cpu_hw_events, cpu);
+
+       if (x86_pmu.version >= 2) {
+               rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
+               rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
+               rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
+               rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
+
+               pr_info("\n");
+               pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
+               pr_info("CPU#%d: status:     %016llx\n", cpu, status);
+               pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
+               pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
+               if (x86_pmu.pebs_constraints) {
+                       rdmsrl(MSR_IA32_PEBS_ENABLE, pebs);
+                       pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);
+               }
+               if (x86_pmu.lbr_nr) {
+                       rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+                       pr_info("CPU#%d: debugctl:   %016llx\n", cpu, debugctl);
+               }
+       }
+       pr_info("CPU#%d: active:     %016llx\n", cpu, *(u64 *)cpuc->active_mask);
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               rdmsrl(x86_pmu_config_addr(idx), pmc_ctrl);
+               rdmsrl(x86_pmu_event_addr(idx), pmc_count);
+
+               prev_left = per_cpu(pmc_prev_left[idx], cpu);
+
+               pr_info("CPU#%d:   gen-PMC%d ctrl:  %016llx\n",
+                       cpu, idx, pmc_ctrl);
+               pr_info("CPU#%d:   gen-PMC%d count: %016llx\n",
+                       cpu, idx, pmc_count);
+               pr_info("CPU#%d:   gen-PMC%d left:  %016llx\n",
+                       cpu, idx, prev_left);
+       }
+       for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) {
+               rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count);
+
+               pr_info("CPU#%d: fixed-PMC%d count: %016llx\n",
+                       cpu, idx, pmc_count);
+       }
+       local_irq_restore(flags);
+}
+
+void x86_pmu_stop(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (__test_and_clear_bit(hwc->idx, cpuc->active_mask)) {
+               x86_pmu.disable(event);
+               cpuc->events[hwc->idx] = NULL;
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+       }
+
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               x86_perf_event_update(event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+}
+
+static void x86_pmu_del(struct perf_event *event, int flags)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int i;
+
+       /*
+        * event is descheduled
+        */
+       event->hw.flags &= ~PERF_X86_EVENT_COMMITTED;
+
+       /*
+        * If we're called during a txn, we don't need to do anything.
+        * The events never got scheduled and ->cancel_txn will truncate
+        * the event_list.
+        *
+        * XXX assumes any ->del() called during a TXN will only be on
+        * an event added during that same TXN.
+        */
+       if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
+               return;
+
+       /*
+        * Not a TXN, therefore cleanup properly.
+        */
+       x86_pmu_stop(event, PERF_EF_UPDATE);
+
+       for (i = 0; i < cpuc->n_events; i++) {
+               if (event == cpuc->event_list[i])
+                       break;
+       }
+
+       if (WARN_ON_ONCE(i == cpuc->n_events)) /* called ->del() without ->add() ? */
+               return;
+
+       /* If we have a newly added event; make sure to decrease n_added. */
+       if (i >= cpuc->n_events - cpuc->n_added)
+               --cpuc->n_added;
+
+       if (x86_pmu.put_event_constraints)
+               x86_pmu.put_event_constraints(cpuc, event);
+
+       /* Delete the array entry. */
+       while (++i < cpuc->n_events) {
+               cpuc->event_list[i-1] = cpuc->event_list[i];
+               cpuc->event_constraint[i-1] = cpuc->event_constraint[i];
+       }
+       --cpuc->n_events;
+
+       perf_event_update_userpage(event);
+}
+
+int x86_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       struct perf_event *event;
+       int idx, handled = 0;
+       u64 val;
+
+       cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       /*
+        * Some chipsets need to unmask the LVTPC in a particular spot
+        * inside the nmi handler.  As a result, the unmasking was pushed
+        * into all the nmi handlers.
+        *
+        * This generic handler doesn't seem to have any issues where the
+        * unmasking occurs so it was left at the top.
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               if (!test_bit(idx, cpuc->active_mask)) {
+                       /*
+                        * Though we deactivated the counter some cpus
+                        * might still deliver spurious interrupts still
+                        * in flight. Catch them:
+                        */
+                       if (__test_and_clear_bit(idx, cpuc->running))
+                               handled++;
+                       continue;
+               }
+
+               event = cpuc->events[idx];
+
+               val = x86_perf_event_update(event);
+               if (val & (1ULL << (x86_pmu.cntval_bits - 1)))
+                       continue;
+
+               /*
+                * event overflow
+                */
+               handled++;
+               perf_sample_data_init(&data, 0, event->hw.last_period);
+
+               if (!x86_perf_event_set_period(event))
+                       continue;
+
+               if (perf_event_overflow(event, &data, regs))
+                       x86_pmu_stop(event, 0);
+       }
+
+       if (handled)
+               inc_irq_stat(apic_perf_irqs);
+
+       return handled;
+}
+
+void perf_events_lapic_init(void)
+{
+       if (!x86_pmu.apic || !x86_pmu_initialized())
+               return;
+
+       /*
+        * Always use NMI for PMU
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+}
+
+static int
+perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs)
+{
+       u64 start_clock;
+       u64 finish_clock;
+       int ret;
+
+       /*
+        * All PMUs/events that share this PMI handler should make sure to
+        * increment active_events for their events.
+        */
+       if (!atomic_read(&active_events))
+               return NMI_DONE;
+
+       start_clock = sched_clock();
+       ret = x86_pmu.handle_irq(regs);
+       finish_clock = sched_clock();
+
+       perf_sample_event_took(finish_clock - start_clock);
+
+       return ret;
+}
+NOKPROBE_SYMBOL(perf_event_nmi_handler);
+
+struct event_constraint emptyconstraint;
+struct event_constraint unconstrained;
+
+static int
+x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+       int i, ret = NOTIFY_OK;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               for (i = 0 ; i < X86_PERF_KFREE_MAX; i++)
+                       cpuc->kfree_on_online[i] = NULL;
+               if (x86_pmu.cpu_prepare)
+                       ret = x86_pmu.cpu_prepare(cpu);
+               break;
+
+       case CPU_STARTING:
+               if (x86_pmu.cpu_starting)
+                       x86_pmu.cpu_starting(cpu);
+               break;
+
+       case CPU_ONLINE:
+               for (i = 0 ; i < X86_PERF_KFREE_MAX; i++) {
+                       kfree(cpuc->kfree_on_online[i]);
+                       cpuc->kfree_on_online[i] = NULL;
+               }
+               break;
+
+       case CPU_DYING:
+               if (x86_pmu.cpu_dying)
+                       x86_pmu.cpu_dying(cpu);
+               break;
+
+       case CPU_UP_CANCELED:
+       case CPU_DEAD:
+               if (x86_pmu.cpu_dead)
+                       x86_pmu.cpu_dead(cpu);
+               break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static void __init pmu_check_apic(void)
+{
+       if (cpu_has_apic)
+               return;
+
+       x86_pmu.apic = 0;
+       pr_info("no APIC, boot with the \"lapic\" boot parameter to force-enable it.\n");
+       pr_info("no hardware sampling interrupt available.\n");
+
+       /*
+        * If we have a PMU initialized but no APIC
+        * interrupts, we cannot sample hardware
+        * events (user-space has to fall back and
+        * sample via a hrtimer based software event):
+        */
+       pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+
+}
+
+static struct attribute_group x86_pmu_format_group = {
+       .name = "format",
+       .attrs = NULL,
+};
+
+/*
+ * Remove all undefined events (x86_pmu.event_map(id) == 0)
+ * out of events_attr attributes.
+ */
+static void __init filter_events(struct attribute **attrs)
+{
+       struct device_attribute *d;
+       struct perf_pmu_events_attr *pmu_attr;
+       int offset = 0;
+       int i, j;
+
+       for (i = 0; attrs[i]; i++) {
+               d = (struct device_attribute *)attrs[i];
+               pmu_attr = container_of(d, struct perf_pmu_events_attr, attr);
+               /* str trumps id */
+               if (pmu_attr->event_str)
+                       continue;
+               if (x86_pmu.event_map(i + offset))
+                       continue;
+
+               for (j = i; attrs[j]; j++)
+                       attrs[j] = attrs[j + 1];
+
+               /* Check the shifted attr. */
+               i--;
+
+               /*
+                * event_map() is index based, the attrs array is organized
+                * by increasing event index. If we shift the events, then
+                * we need to compensate for the event_map(), otherwise
+                * we are looking up the wrong event in the map
+                */
+               offset++;
+       }
+}
+
+/* Merge two pointer arrays */
+__init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
+{
+       struct attribute **new;
+       int j, i;
+
+       for (j = 0; a[j]; j++)
+               ;
+       for (i = 0; b[i]; i++)
+               j++;
+       j++;
+
+       new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL);
+       if (!new)
+               return NULL;
+
+       j = 0;
+       for (i = 0; a[i]; i++)
+               new[j++] = a[i];
+       for (i = 0; b[i]; i++)
+               new[j++] = b[i];
+       new[j] = NULL;
+
+       return new;
+}
+
+ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
+                         char *page)
+{
+       struct perf_pmu_events_attr *pmu_attr = \
+               container_of(attr, struct perf_pmu_events_attr, attr);
+       u64 config = x86_pmu.event_map(pmu_attr->id);
+
+       /* string trumps id */
+       if (pmu_attr->event_str)
+               return sprintf(page, "%s", pmu_attr->event_str);
+
+       return x86_pmu.events_sysfs_show(page, config);
+}
+
+EVENT_ATTR(cpu-cycles,                 CPU_CYCLES              );
+EVENT_ATTR(instructions,               INSTRUCTIONS            );
+EVENT_ATTR(cache-references,           CACHE_REFERENCES        );
+EVENT_ATTR(cache-misses,               CACHE_MISSES            );
+EVENT_ATTR(branch-instructions,                BRANCH_INSTRUCTIONS     );
+EVENT_ATTR(branch-misses,              BRANCH_MISSES           );
+EVENT_ATTR(bus-cycles,                 BUS_CYCLES              );
+EVENT_ATTR(stalled-cycles-frontend,    STALLED_CYCLES_FRONTEND );
+EVENT_ATTR(stalled-cycles-backend,     STALLED_CYCLES_BACKEND  );
+EVENT_ATTR(ref-cycles,                 REF_CPU_CYCLES          );
+
+static struct attribute *empty_attrs;
+
+static struct attribute *events_attr[] = {
+       EVENT_PTR(CPU_CYCLES),
+       EVENT_PTR(INSTRUCTIONS),
+       EVENT_PTR(CACHE_REFERENCES),
+       EVENT_PTR(CACHE_MISSES),
+       EVENT_PTR(BRANCH_INSTRUCTIONS),
+       EVENT_PTR(BRANCH_MISSES),
+       EVENT_PTR(BUS_CYCLES),
+       EVENT_PTR(STALLED_CYCLES_FRONTEND),
+       EVENT_PTR(STALLED_CYCLES_BACKEND),
+       EVENT_PTR(REF_CPU_CYCLES),
+       NULL,
+};
+
+static struct attribute_group x86_pmu_events_group = {
+       .name = "events",
+       .attrs = events_attr,
+};
+
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
+{
+       u64 umask  = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
+       u64 cmask  = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24;
+       bool edge  = (config & ARCH_PERFMON_EVENTSEL_EDGE);
+       bool pc    = (config & ARCH_PERFMON_EVENTSEL_PIN_CONTROL);
+       bool any   = (config & ARCH_PERFMON_EVENTSEL_ANY);
+       bool inv   = (config & ARCH_PERFMON_EVENTSEL_INV);
+       ssize_t ret;
+
+       /*
+       * We have whole page size to spend and just little data
+       * to write, so we can safely use sprintf.
+       */
+       ret = sprintf(page, "event=0x%02llx", event);
+
+       if (umask)
+               ret += sprintf(page + ret, ",umask=0x%02llx", umask);
+
+       if (edge)
+               ret += sprintf(page + ret, ",edge");
+
+       if (pc)
+               ret += sprintf(page + ret, ",pc");
+
+       if (any)
+               ret += sprintf(page + ret, ",any");
+
+       if (inv)
+               ret += sprintf(page + ret, ",inv");
+
+       if (cmask)
+               ret += sprintf(page + ret, ",cmask=0x%02llx", cmask);
+
+       ret += sprintf(page + ret, "\n");
+
+       return ret;
+}
+
+static int __init init_hw_perf_events(void)
+{
+       struct x86_pmu_quirk *quirk;
+       int err;
+
+       pr_info("Performance Events: ");
+
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_INTEL:
+               err = intel_pmu_init();
+               break;
+       case X86_VENDOR_AMD:
+               err = amd_pmu_init();
+               break;
+       default:
+               err = -ENOTSUPP;
+       }
+       if (err != 0) {
+               pr_cont("no PMU driver, software events only.\n");
+               return 0;
+       }
+
+       pmu_check_apic();
+
+       /* sanity check that the hardware exists or is emulated */
+       if (!check_hw_exists())
+               return 0;
+
+       pr_cont("%s PMU driver.\n", x86_pmu.name);
+
+       x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
+
+       for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next)
+               quirk->func();
+
+       if (!x86_pmu.intel_ctrl)
+               x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
+
+       perf_events_lapic_init();
+       register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
+
+       unconstrained = (struct event_constraint)
+               __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
+                                  0, x86_pmu.num_counters, 0, 0);
+
+       x86_pmu_format_group.attrs = x86_pmu.format_attrs;
+
+       if (x86_pmu.event_attrs)
+               x86_pmu_events_group.attrs = x86_pmu.event_attrs;
+
+       if (!x86_pmu.events_sysfs_show)
+               x86_pmu_events_group.attrs = &empty_attrs;
+       else
+               filter_events(x86_pmu_events_group.attrs);
+
+       if (x86_pmu.cpu_events) {
+               struct attribute **tmp;
+
+               tmp = merge_attr(x86_pmu_events_group.attrs, x86_pmu.cpu_events);
+               if (!WARN_ON(!tmp))
+                       x86_pmu_events_group.attrs = tmp;
+       }
+
+       pr_info("... version:                %d\n",     x86_pmu.version);
+       pr_info("... bit width:              %d\n",     x86_pmu.cntval_bits);
+       pr_info("... generic registers:      %d\n",     x86_pmu.num_counters);
+       pr_info("... value mask:             %016Lx\n", x86_pmu.cntval_mask);
+       pr_info("... max period:             %016Lx\n", x86_pmu.max_period);
+       pr_info("... fixed-purpose events:   %d\n",     x86_pmu.num_counters_fixed);
+       pr_info("... event mask:             %016Lx\n", x86_pmu.intel_ctrl);
+
+       perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
+       perf_cpu_notifier(x86_pmu_notifier);
+
+       return 0;
+}
+early_initcall(init_hw_perf_events);
+
+static inline void x86_pmu_read(struct perf_event *event)
+{
+       x86_perf_event_update(event);
+}
+
+/*
+ * Start group events scheduling transaction
+ * Set the flag to make pmu::enable() not perform the
+ * schedulability test, it will be performed at commit time
+ *
+ * We only support PERF_PMU_TXN_ADD transactions. Save the
+ * transaction flags but otherwise ignore non-PERF_PMU_TXN_ADD
+ * transactions.
+ */
+static void x86_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       WARN_ON_ONCE(cpuc->txn_flags);          /* txn already in flight */
+
+       cpuc->txn_flags = txn_flags;
+       if (txn_flags & ~PERF_PMU_TXN_ADD)
+               return;
+
+       perf_pmu_disable(pmu);
+       __this_cpu_write(cpu_hw_events.n_txn, 0);
+}
+
+/*
+ * Stop group events scheduling transaction
+ * Clear the flag and pmu::enable() will perform the
+ * schedulability test.
+ */
+static void x86_pmu_cancel_txn(struct pmu *pmu)
+{
+       unsigned int txn_flags;
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */
+
+       txn_flags = cpuc->txn_flags;
+       cpuc->txn_flags = 0;
+       if (txn_flags & ~PERF_PMU_TXN_ADD)
+               return;
+
+       /*
+        * Truncate collected array by the number of events added in this
+        * transaction. See x86_pmu_add() and x86_pmu_*_txn().
+        */
+       __this_cpu_sub(cpu_hw_events.n_added, __this_cpu_read(cpu_hw_events.n_txn));
+       __this_cpu_sub(cpu_hw_events.n_events, __this_cpu_read(cpu_hw_events.n_txn));
+       perf_pmu_enable(pmu);
+}
+
+/*
+ * Commit group events scheduling transaction
+ * Perform the group schedulability test as a whole
+ * Return 0 if success
+ *
+ * Does not cancel the transaction on failure; expects the caller to do this.
+ */
+static int x86_pmu_commit_txn(struct pmu *pmu)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int assign[X86_PMC_IDX_MAX];
+       int n, ret;
+
+       WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */
+
+       if (cpuc->txn_flags & ~PERF_PMU_TXN_ADD) {
+               cpuc->txn_flags = 0;
+               return 0;
+       }
+
+       n = cpuc->n_events;
+
+       if (!x86_pmu_initialized())
+               return -EAGAIN;
+
+       ret = x86_pmu.schedule_events(cpuc, n, assign);
+       if (ret)
+               return ret;
+
+       /*
+        * copy new assignment, now we know it is possible
+        * will be used by hw_perf_enable()
+        */
+       memcpy(cpuc->assign, assign, n*sizeof(int));
+
+       cpuc->txn_flags = 0;
+       perf_pmu_enable(pmu);
+       return 0;
+}
+/*
+ * a fake_cpuc is used to validate event groups. Due to
+ * the extra reg logic, we need to also allocate a fake
+ * per_core and per_cpu structure. Otherwise, group events
+ * using extra reg may conflict without the kernel being
+ * able to catch this when the last event gets added to
+ * the group.
+ */
+static void free_fake_cpuc(struct cpu_hw_events *cpuc)
+{
+       kfree(cpuc->shared_regs);
+       kfree(cpuc);
+}
+
+static struct cpu_hw_events *allocate_fake_cpuc(void)
+{
+       struct cpu_hw_events *cpuc;
+       int cpu = raw_smp_processor_id();
+
+       cpuc = kzalloc(sizeof(*cpuc), GFP_KERNEL);
+       if (!cpuc)
+               return ERR_PTR(-ENOMEM);
+
+       /* only needed, if we have extra_regs */
+       if (x86_pmu.extra_regs) {
+               cpuc->shared_regs = allocate_shared_regs(cpu);
+               if (!cpuc->shared_regs)
+                       goto error;
+       }
+       cpuc->is_fake = 1;
+       return cpuc;
+error:
+       free_fake_cpuc(cpuc);
+       return ERR_PTR(-ENOMEM);
+}
+
+/*
+ * validate that we can schedule this event
+ */
+static int validate_event(struct perf_event *event)
+{
+       struct cpu_hw_events *fake_cpuc;
+       struct event_constraint *c;
+       int ret = 0;
+
+       fake_cpuc = allocate_fake_cpuc();
+       if (IS_ERR(fake_cpuc))
+               return PTR_ERR(fake_cpuc);
+
+       c = x86_pmu.get_event_constraints(fake_cpuc, -1, event);
+
+       if (!c || !c->weight)
+               ret = -EINVAL;
+
+       if (x86_pmu.put_event_constraints)
+               x86_pmu.put_event_constraints(fake_cpuc, event);
+
+       free_fake_cpuc(fake_cpuc);
+
+       return ret;
+}
+
+/*
+ * validate a single event group
+ *
+ * validation include:
+ *     - check events are compatible which each other
+ *     - events do not compete for the same counter
+ *     - number of events <= number of counters
+ *
+ * validation ensures the group can be loaded onto the
+ * PMU if it was the only group available.
+ */
+static int validate_group(struct perf_event *event)
+{
+       struct perf_event *leader = event->group_leader;
+       struct cpu_hw_events *fake_cpuc;
+       int ret = -EINVAL, n;
+
+       fake_cpuc = allocate_fake_cpuc();
+       if (IS_ERR(fake_cpuc))
+               return PTR_ERR(fake_cpuc);
+       /*
+        * the event is not yet connected with its
+        * siblings therefore we must first collect
+        * existing siblings, then add the new event
+        * before we can simulate the scheduling
+        */
+       n = collect_events(fake_cpuc, leader, true);
+       if (n < 0)
+               goto out;
+
+       fake_cpuc->n_events = n;
+       n = collect_events(fake_cpuc, event, false);
+       if (n < 0)
+               goto out;
+
+       fake_cpuc->n_events = n;
+
+       ret = x86_pmu.schedule_events(fake_cpuc, n, NULL);
+
+out:
+       free_fake_cpuc(fake_cpuc);
+       return ret;
+}
+
+static int x86_pmu_event_init(struct perf_event *event)
+{
+       struct pmu *tmp;
+       int err;
+
+       switch (event->attr.type) {
+       case PERF_TYPE_RAW:
+       case PERF_TYPE_HARDWARE:
+       case PERF_TYPE_HW_CACHE:
+               break;
+
+       default:
+               return -ENOENT;
+       }
+
+       err = __x86_pmu_event_init(event);
+       if (!err) {
+               /*
+                * we temporarily connect event to its pmu
+                * such that validate_group() can classify
+                * it as an x86 event using is_x86_event()
+                */
+               tmp = event->pmu;
+               event->pmu = &pmu;
+
+               if (event->group_leader != event)
+                       err = validate_group(event);
+               else
+                       err = validate_event(event);
+
+               event->pmu = tmp;
+       }
+       if (err) {
+               if (event->destroy)
+                       event->destroy(event);
+       }
+
+       if (ACCESS_ONCE(x86_pmu.attr_rdpmc))
+               event->hw.flags |= PERF_X86_EVENT_RDPMC_ALLOWED;
+
+       return err;
+}
+
+static void refresh_pce(void *ignored)
+{
+       if (current->mm)
+               load_mm_cr4(current->mm);
+}
+
+static void x86_pmu_event_mapped(struct perf_event *event)
+{
+       if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
+               return;
+
+       if (atomic_inc_return(&current->mm->context.perf_rdpmc_allowed) == 1)
+               on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1);
+}
+
+static void x86_pmu_event_unmapped(struct perf_event *event)
+{
+       if (!current->mm)
+               return;
+
+       if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
+               return;
+
+       if (atomic_dec_and_test(&current->mm->context.perf_rdpmc_allowed))
+               on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1);
+}
+
+static int x86_pmu_event_idx(struct perf_event *event)
+{
+       int idx = event->hw.idx;
+
+       if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
+               return 0;
+
+       if (x86_pmu.num_counters_fixed && idx >= INTEL_PMC_IDX_FIXED) {
+               idx -= INTEL_PMC_IDX_FIXED;
+               idx |= 1 << 30;
+       }
+
+       return idx + 1;
+}
+
+static ssize_t get_attr_rdpmc(struct device *cdev,
+                             struct device_attribute *attr,
+                             char *buf)
+{
+       return snprintf(buf, 40, "%d\n", x86_pmu.attr_rdpmc);
+}
+
+static ssize_t set_attr_rdpmc(struct device *cdev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       unsigned long val;
+       ssize_t ret;
+
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       if (val > 2)
+               return -EINVAL;
+
+       if (x86_pmu.attr_rdpmc_broken)
+               return -ENOTSUPP;
+
+       if ((val == 2) != (x86_pmu.attr_rdpmc == 2)) {
+               /*
+                * Changing into or out of always available, aka
+                * perf-event-bypassing mode.  This path is extremely slow,
+                * but only root can trigger it, so it's okay.
+                */
+               if (val == 2)
+                       static_key_slow_inc(&rdpmc_always_available);
+               else
+                       static_key_slow_dec(&rdpmc_always_available);
+               on_each_cpu(refresh_pce, NULL, 1);
+       }
+
+       x86_pmu.attr_rdpmc = val;
+
+       return count;
+}
+
+static DEVICE_ATTR(rdpmc, S_IRUSR | S_IWUSR, get_attr_rdpmc, set_attr_rdpmc);
+
+static struct attribute *x86_pmu_attrs[] = {
+       &dev_attr_rdpmc.attr,
+       NULL,
+};
+
+static struct attribute_group x86_pmu_attr_group = {
+       .attrs = x86_pmu_attrs,
+};
+
+static const struct attribute_group *x86_pmu_attr_groups[] = {
+       &x86_pmu_attr_group,
+       &x86_pmu_format_group,
+       &x86_pmu_events_group,
+       NULL,
+};
+
+static void x86_pmu_sched_task(struct perf_event_context *ctx, bool sched_in)
+{
+       if (x86_pmu.sched_task)
+               x86_pmu.sched_task(ctx, sched_in);
+}
+
+void perf_check_microcode(void)
+{
+       if (x86_pmu.check_microcode)
+               x86_pmu.check_microcode();
+}
+EXPORT_SYMBOL_GPL(perf_check_microcode);
+
+static struct pmu pmu = {
+       .pmu_enable             = x86_pmu_enable,
+       .pmu_disable            = x86_pmu_disable,
+
+       .attr_groups            = x86_pmu_attr_groups,
+
+       .event_init             = x86_pmu_event_init,
+
+       .event_mapped           = x86_pmu_event_mapped,
+       .event_unmapped         = x86_pmu_event_unmapped,
+
+       .add                    = x86_pmu_add,
+       .del                    = x86_pmu_del,
+       .start                  = x86_pmu_start,
+       .stop                   = x86_pmu_stop,
+       .read                   = x86_pmu_read,
+
+       .start_txn              = x86_pmu_start_txn,
+       .cancel_txn             = x86_pmu_cancel_txn,
+       .commit_txn             = x86_pmu_commit_txn,
+
+       .event_idx              = x86_pmu_event_idx,
+       .sched_task             = x86_pmu_sched_task,
+       .task_ctx_size          = sizeof(struct x86_perf_task_context),
+};
+
+void arch_perf_update_userpage(struct perf_event *event,
+                              struct perf_event_mmap_page *userpg, u64 now)
+{
+       struct cyc2ns_data *data;
+
+       userpg->cap_user_time = 0;
+       userpg->cap_user_time_zero = 0;
+       userpg->cap_user_rdpmc =
+               !!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED);
+       userpg->pmc_width = x86_pmu.cntval_bits;
+
+       if (!sched_clock_stable())
+               return;
+
+       data = cyc2ns_read_begin();
+
+       /*
+        * Internal timekeeping for enabled/running/stopped times
+        * is always in the local_clock domain.
+        */
+       userpg->cap_user_time = 1;
+       userpg->time_mult = data->cyc2ns_mul;
+       userpg->time_shift = data->cyc2ns_shift;
+       userpg->time_offset = data->cyc2ns_offset - now;
+
+       /*
+        * cap_user_time_zero doesn't make sense when we're using a different
+        * time base for the records.
+        */
+       if (event->clock == &local_clock) {
+               userpg->cap_user_time_zero = 1;
+               userpg->time_zero = data->cyc2ns_offset;
+       }
+
+       cyc2ns_read_end(data);
+}
+
+/*
+ * callchain support
+ */
+
+static int backtrace_stack(void *data, char *name)
+{
+       return 0;
+}
+
+static void backtrace_address(void *data, unsigned long addr, int reliable)
+{
+       struct perf_callchain_entry *entry = data;
+
+       perf_callchain_store(entry, addr);
+}
+
+static const struct stacktrace_ops backtrace_ops = {
+       .stack                  = backtrace_stack,
+       .address                = backtrace_address,
+       .walk_stack             = print_context_stack_bp,
+};
+
+void
+perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+{
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               /* TODO: We don't support guest os callchain now */
+               return;
+       }
+
+       perf_callchain_store(entry, regs->ip);
+
+       dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry);
+}
+
+static inline int
+valid_user_frame(const void __user *fp, unsigned long size)
+{
+       return (__range_not_ok(fp, size, TASK_SIZE) == 0);
+}
+
+static unsigned long get_segment_base(unsigned int segment)
+{
+       struct desc_struct *desc;
+       int idx = segment >> 3;
+
+       if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
+#ifdef CONFIG_MODIFY_LDT_SYSCALL
+               struct ldt_struct *ldt;
+
+               if (idx > LDT_ENTRIES)
+                       return 0;
+
+               /* IRQs are off, so this synchronizes with smp_store_release */
+               ldt = lockless_dereference(current->active_mm->context.ldt);
+               if (!ldt || idx > ldt->size)
+                       return 0;
+
+               desc = &ldt->entries[idx];
+#else
+               return 0;
+#endif
+       } else {
+               if (idx > GDT_ENTRIES)
+                       return 0;
+
+               desc = raw_cpu_ptr(gdt_page.gdt) + idx;
+       }
+
+       return get_desc_base(desc);
+}
+
+#ifdef CONFIG_IA32_EMULATION
+
+#include <asm/compat.h>
+
+static inline int
+perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
+{
+       /* 32-bit process in 64-bit kernel. */
+       unsigned long ss_base, cs_base;
+       struct stack_frame_ia32 frame;
+       const void __user *fp;
+
+       if (!test_thread_flag(TIF_IA32))
+               return 0;
+
+       cs_base = get_segment_base(regs->cs);
+       ss_base = get_segment_base(regs->ss);
+
+       fp = compat_ptr(ss_base + regs->bp);
+       pagefault_disable();
+       while (entry->nr < PERF_MAX_STACK_DEPTH) {
+               unsigned long bytes;
+               frame.next_frame     = 0;
+               frame.return_address = 0;
+
+               if (!access_ok(VERIFY_READ, fp, 8))
+                       break;
+
+               bytes = __copy_from_user_nmi(&frame.next_frame, fp, 4);
+               if (bytes != 0)
+                       break;
+               bytes = __copy_from_user_nmi(&frame.return_address, fp+4, 4);
+               if (bytes != 0)
+                       break;
+
+               if (!valid_user_frame(fp, sizeof(frame)))
+                       break;
+
+               perf_callchain_store(entry, cs_base + frame.return_address);
+               fp = compat_ptr(ss_base + frame.next_frame);
+       }
+       pagefault_enable();
+       return 1;
+}
+#else
+static inline int
+perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
+{
+    return 0;
+}
+#endif
+
+void
+perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+{
+       struct stack_frame frame;
+       const void __user *fp;
+
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               /* TODO: We don't support guest os callchain now */
+               return;
+       }
+
+       /*
+        * We don't know what to do with VM86 stacks.. ignore them for now.
+        */
+       if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM))
+               return;
+
+       fp = (void __user *)regs->bp;
+
+       perf_callchain_store(entry, regs->ip);
+
+       if (!current->mm)
+               return;
+
+       if (perf_callchain_user32(regs, entry))
+               return;
+
+       pagefault_disable();
+       while (entry->nr < PERF_MAX_STACK_DEPTH) {
+               unsigned long bytes;
+               frame.next_frame             = NULL;
+               frame.return_address = 0;
+
+               if (!access_ok(VERIFY_READ, fp, 16))
+                       break;
+
+               bytes = __copy_from_user_nmi(&frame.next_frame, fp, 8);
+               if (bytes != 0)
+                       break;
+               bytes = __copy_from_user_nmi(&frame.return_address, fp+8, 8);
+               if (bytes != 0)
+                       break;
+
+               if (!valid_user_frame(fp, sizeof(frame)))
+                       break;
+
+               perf_callchain_store(entry, frame.return_address);
+               fp = (void __user *)frame.next_frame;
+       }
+       pagefault_enable();
+}
+
+/*
+ * Deal with code segment offsets for the various execution modes:
+ *
+ *   VM86 - the good olde 16 bit days, where the linear address is
+ *          20 bits and we use regs->ip + 0x10 * regs->cs.
+ *
+ *   IA32 - Where we need to look at GDT/LDT segment descriptor tables
+ *          to figure out what the 32bit base address is.
+ *
+ *    X32 - has TIF_X32 set, but is running in x86_64
+ *
+ * X86_64 - CS,DS,SS,ES are all zero based.
+ */
+static unsigned long code_segment_base(struct pt_regs *regs)
+{
+       /*
+        * For IA32 we look at the GDT/LDT segment base to convert the
+        * effective IP to a linear address.
+        */
+
+#ifdef CONFIG_X86_32
+       /*
+        * If we are in VM86 mode, add the segment offset to convert to a
+        * linear address.
+        */
+       if (regs->flags & X86_VM_MASK)
+               return 0x10 * regs->cs;
+
+       if (user_mode(regs) && regs->cs != __USER_CS)
+               return get_segment_base(regs->cs);
+#else
+       if (user_mode(regs) && !user_64bit_mode(regs) &&
+           regs->cs != __USER32_CS)
+               return get_segment_base(regs->cs);
+#endif
+       return 0;
+}
+
+unsigned long perf_instruction_pointer(struct pt_regs *regs)
+{
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
+               return perf_guest_cbs->get_guest_ip();
+
+       return regs->ip + code_segment_base(regs);
+}
+
+unsigned long perf_misc_flags(struct pt_regs *regs)
+{
+       int misc = 0;
+
+       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+               if (perf_guest_cbs->is_user_mode())
+                       misc |= PERF_RECORD_MISC_GUEST_USER;
+               else
+                       misc |= PERF_RECORD_MISC_GUEST_KERNEL;
+       } else {
+               if (user_mode(regs))
+                       misc |= PERF_RECORD_MISC_USER;
+               else
+                       misc |= PERF_RECORD_MISC_KERNEL;
+       }
+
+       if (regs->flags & PERF_EFLAGS_EXACT)
+               misc |= PERF_RECORD_MISC_EXACT_IP;
+
+       return misc;
+}
+
+void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
+{
+       cap->version            = x86_pmu.version;
+       cap->num_counters_gp    = x86_pmu.num_counters;
+       cap->num_counters_fixed = x86_pmu.num_counters_fixed;
+       cap->bit_width_gp       = x86_pmu.cntval_bits;
+       cap->bit_width_fixed    = x86_pmu.cntval_bits;
+       cap->events_mask        = (unsigned int)x86_pmu.events_maskl;
+       cap->events_mask_len    = x86_pmu.events_mask_len;
+}
+EXPORT_SYMBOL_GPL(perf_get_x86_pmu_capability);
diff --git a/arch/x86/events/intel/bts.c b/arch/x86/events/intel/bts.c
new file mode 100644 (file)
index 0000000..b99dc92
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * BTS PMU driver for perf
+ * Copyright (c) 2013-2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#undef DEBUG
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/coredump.h>
+
+#include <asm-generic/sizes.h>
+#include <asm/perf_event.h>
+
+#include "../perf_event.h"
+
+struct bts_ctx {
+       struct perf_output_handle       handle;
+       struct debug_store              ds_back;
+       int                             started;
+};
+
+static DEFINE_PER_CPU(struct bts_ctx, bts_ctx);
+
+#define BTS_RECORD_SIZE                24
+#define BTS_SAFETY_MARGIN      4080
+
+struct bts_phys {
+       struct page     *page;
+       unsigned long   size;
+       unsigned long   offset;
+       unsigned long   displacement;
+};
+
+struct bts_buffer {
+       size_t          real_size;      /* multiple of BTS_RECORD_SIZE */
+       unsigned int    nr_pages;
+       unsigned int    nr_bufs;
+       unsigned int    cur_buf;
+       bool            snapshot;
+       local_t         data_size;
+       local_t         lost;
+       local_t         head;
+       unsigned long   end;
+       void            **data_pages;
+       struct bts_phys buf[0];
+};
+
+struct pmu bts_pmu;
+
+static size_t buf_size(struct page *page)
+{
+       return 1 << (PAGE_SHIFT + page_private(page));
+}
+
+static void *
+bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
+{
+       struct bts_buffer *buf;
+       struct page *page;
+       int node = (cpu == -1) ? cpu : cpu_to_node(cpu);
+       unsigned long offset;
+       size_t size = nr_pages << PAGE_SHIFT;
+       int pg, nbuf, pad;
+
+       /* count all the high order buffers */
+       for (pg = 0, nbuf = 0; pg < nr_pages;) {
+               page = virt_to_page(pages[pg]);
+               if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1))
+                       return NULL;
+               pg += 1 << page_private(page);
+               nbuf++;
+       }
+
+       /*
+        * to avoid interrupts in overwrite mode, only allow one physical
+        */
+       if (overwrite && nbuf > 1)
+               return NULL;
+
+       buf = kzalloc_node(offsetof(struct bts_buffer, buf[nbuf]), GFP_KERNEL, node);
+       if (!buf)
+               return NULL;
+
+       buf->nr_pages = nr_pages;
+       buf->nr_bufs = nbuf;
+       buf->snapshot = overwrite;
+       buf->data_pages = pages;
+       buf->real_size = size - size % BTS_RECORD_SIZE;
+
+       for (pg = 0, nbuf = 0, offset = 0, pad = 0; nbuf < buf->nr_bufs; nbuf++) {
+               unsigned int __nr_pages;
+
+               page = virt_to_page(pages[pg]);
+               __nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
+               buf->buf[nbuf].page = page;
+               buf->buf[nbuf].offset = offset;
+               buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
+               buf->buf[nbuf].size = buf_size(page) - buf->buf[nbuf].displacement;
+               pad = buf->buf[nbuf].size % BTS_RECORD_SIZE;
+               buf->buf[nbuf].size -= pad;
+
+               pg += __nr_pages;
+               offset += __nr_pages << PAGE_SHIFT;
+       }
+
+       return buf;
+}
+
+static void bts_buffer_free_aux(void *data)
+{
+       kfree(data);
+}
+
+static unsigned long bts_buffer_offset(struct bts_buffer *buf, unsigned int idx)
+{
+       return buf->buf[idx].offset + buf->buf[idx].displacement;
+}
+
+static void
+bts_config_buffer(struct bts_buffer *buf)
+{
+       int cpu = raw_smp_processor_id();
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+       struct bts_phys *phys = &buf->buf[buf->cur_buf];
+       unsigned long index, thresh = 0, end = phys->size;
+       struct page *page = phys->page;
+
+       index = local_read(&buf->head);
+
+       if (!buf->snapshot) {
+               if (buf->end < phys->offset + buf_size(page))
+                       end = buf->end - phys->offset - phys->displacement;
+
+               index -= phys->offset + phys->displacement;
+
+               if (end - index > BTS_SAFETY_MARGIN)
+                       thresh = end - BTS_SAFETY_MARGIN;
+               else if (end - index > BTS_RECORD_SIZE)
+                       thresh = end - BTS_RECORD_SIZE;
+               else
+                       thresh = end;
+       }
+
+       ds->bts_buffer_base = (u64)(long)page_address(page) + phys->displacement;
+       ds->bts_index = ds->bts_buffer_base + index;
+       ds->bts_absolute_maximum = ds->bts_buffer_base + end;
+       ds->bts_interrupt_threshold = !buf->snapshot
+               ? ds->bts_buffer_base + thresh
+               : ds->bts_absolute_maximum + BTS_RECORD_SIZE;
+}
+
+static void bts_buffer_pad_out(struct bts_phys *phys, unsigned long head)
+{
+       unsigned long index = head - phys->offset;
+
+       memset(page_address(phys->page) + index, 0, phys->size - index);
+}
+
+static bool bts_buffer_is_full(struct bts_buffer *buf, struct bts_ctx *bts)
+{
+       if (buf->snapshot)
+               return false;
+
+       if (local_read(&buf->data_size) >= bts->handle.size ||
+           bts->handle.size - local_read(&buf->data_size) < BTS_RECORD_SIZE)
+               return true;
+
+       return false;
+}
+
+static void bts_update(struct bts_ctx *bts)
+{
+       int cpu = raw_smp_processor_id();
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+       struct bts_buffer *buf = perf_get_aux(&bts->handle);
+       unsigned long index = ds->bts_index - ds->bts_buffer_base, old, head;
+
+       if (!buf)
+               return;
+
+       head = index + bts_buffer_offset(buf, buf->cur_buf);
+       old = local_xchg(&buf->head, head);
+
+       if (!buf->snapshot) {
+               if (old == head)
+                       return;
+
+               if (ds->bts_index >= ds->bts_absolute_maximum)
+                       local_inc(&buf->lost);
+
+               /*
+                * old and head are always in the same physical buffer, so we
+                * can subtract them to get the data size.
+                */
+               local_add(head - old, &buf->data_size);
+       } else {
+               local_set(&buf->data_size, head);
+       }
+}
+
+static void __bts_event_start(struct perf_event *event)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+       struct bts_buffer *buf = perf_get_aux(&bts->handle);
+       u64 config = 0;
+
+       if (!buf || bts_buffer_is_full(buf, bts))
+               return;
+
+       event->hw.itrace_started = 1;
+       event->hw.state = 0;
+
+       if (!buf->snapshot)
+               config |= ARCH_PERFMON_EVENTSEL_INT;
+       if (!event->attr.exclude_kernel)
+               config |= ARCH_PERFMON_EVENTSEL_OS;
+       if (!event->attr.exclude_user)
+               config |= ARCH_PERFMON_EVENTSEL_USR;
+
+       bts_config_buffer(buf);
+
+       /*
+        * local barrier to make sure that ds configuration made it
+        * before we enable BTS
+        */
+       wmb();
+
+       intel_pmu_enable_bts(config);
+}
+
+static void bts_event_start(struct perf_event *event, int flags)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+
+       __bts_event_start(event);
+
+       /* PMI handler: this counter is running and likely generating PMIs */
+       ACCESS_ONCE(bts->started) = 1;
+}
+
+static void __bts_event_stop(struct perf_event *event)
+{
+       /*
+        * No extra synchronization is mandated by the documentation to have
+        * BTS data stores globally visible.
+        */
+       intel_pmu_disable_bts();
+
+       if (event->hw.state & PERF_HES_STOPPED)
+               return;
+
+       ACCESS_ONCE(event->hw.state) |= PERF_HES_STOPPED;
+}
+
+static void bts_event_stop(struct perf_event *event, int flags)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+
+       /* PMI handler: don't restart this counter */
+       ACCESS_ONCE(bts->started) = 0;
+
+       __bts_event_stop(event);
+
+       if (flags & PERF_EF_UPDATE)
+               bts_update(bts);
+}
+
+void intel_bts_enable_local(void)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+
+       if (bts->handle.event && bts->started)
+               __bts_event_start(bts->handle.event);
+}
+
+void intel_bts_disable_local(void)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+
+       if (bts->handle.event)
+               __bts_event_stop(bts->handle.event);
+}
+
+static int
+bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle)
+{
+       unsigned long head, space, next_space, pad, gap, skip, wakeup;
+       unsigned int next_buf;
+       struct bts_phys *phys, *next_phys;
+       int ret;
+
+       if (buf->snapshot)
+               return 0;
+
+       head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
+       if (WARN_ON_ONCE(head != local_read(&buf->head)))
+               return -EINVAL;
+
+       phys = &buf->buf[buf->cur_buf];
+       space = phys->offset + phys->displacement + phys->size - head;
+       pad = space;
+       if (space > handle->size) {
+               space = handle->size;
+               space -= space % BTS_RECORD_SIZE;
+       }
+       if (space <= BTS_SAFETY_MARGIN) {
+               /* See if next phys buffer has more space */
+               next_buf = buf->cur_buf + 1;
+               if (next_buf >= buf->nr_bufs)
+                       next_buf = 0;
+               next_phys = &buf->buf[next_buf];
+               gap = buf_size(phys->page) - phys->displacement - phys->size +
+                     next_phys->displacement;
+               skip = pad + gap;
+               if (handle->size >= skip) {
+                       next_space = next_phys->size;
+                       if (next_space + skip > handle->size) {
+                               next_space = handle->size - skip;
+                               next_space -= next_space % BTS_RECORD_SIZE;
+                       }
+                       if (next_space > space || !space) {
+                               if (pad)
+                                       bts_buffer_pad_out(phys, head);
+                               ret = perf_aux_output_skip(handle, skip);
+                               if (ret)
+                                       return ret;
+                               /* Advance to next phys buffer */
+                               phys = next_phys;
+                               space = next_space;
+                               head = phys->offset + phys->displacement;
+                               /*
+                                * After this, cur_buf and head won't match ds
+                                * anymore, so we must not be racing with
+                                * bts_update().
+                                */
+                               buf->cur_buf = next_buf;
+                               local_set(&buf->head, head);
+                       }
+               }
+       }
+
+       /* Don't go far beyond wakeup watermark */
+       wakeup = BTS_SAFETY_MARGIN + BTS_RECORD_SIZE + handle->wakeup -
+                handle->head;
+       if (space > wakeup) {
+               space = wakeup;
+               space -= space % BTS_RECORD_SIZE;
+       }
+
+       buf->end = head + space;
+
+       /*
+        * If we have no space, the lost notification would have been sent when
+        * we hit absolute_maximum - see bts_update()
+        */
+       if (!space)
+               return -ENOSPC;
+
+       return 0;
+}
+
+int intel_bts_interrupt(void)
+{
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+       struct perf_event *event = bts->handle.event;
+       struct bts_buffer *buf;
+       s64 old_head;
+       int err;
+
+       if (!event || !bts->started)
+               return 0;
+
+       buf = perf_get_aux(&bts->handle);
+       /*
+        * Skip snapshot counters: they don't use the interrupt, but
+        * there's no other way of telling, because the pointer will
+        * keep moving
+        */
+       if (!buf || buf->snapshot)
+               return 0;
+
+       old_head = local_read(&buf->head);
+       bts_update(bts);
+
+       /* no new data */
+       if (old_head == local_read(&buf->head))
+               return 0;
+
+       perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
+                           !!local_xchg(&buf->lost, 0));
+
+       buf = perf_aux_output_begin(&bts->handle, event);
+       if (!buf)
+               return 1;
+
+       err = bts_buffer_reset(buf, &bts->handle);
+       if (err)
+               perf_aux_output_end(&bts->handle, 0, false);
+
+       return 1;
+}
+
+static void bts_event_del(struct perf_event *event, int mode)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+       struct bts_buffer *buf = perf_get_aux(&bts->handle);
+
+       bts_event_stop(event, PERF_EF_UPDATE);
+
+       if (buf) {
+               if (buf->snapshot)
+                       bts->handle.head =
+                               local_xchg(&buf->data_size,
+                                          buf->nr_pages << PAGE_SHIFT);
+               perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
+                                   !!local_xchg(&buf->lost, 0));
+       }
+
+       cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
+       cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base;
+       cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum;
+       cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold;
+}
+
+static int bts_event_add(struct perf_event *event, int mode)
+{
+       struct bts_buffer *buf;
+       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       int ret = -EBUSY;
+
+       event->hw.state = PERF_HES_STOPPED;
+
+       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
+               return -EBUSY;
+
+       if (bts->handle.event)
+               return -EBUSY;
+
+       buf = perf_aux_output_begin(&bts->handle, event);
+       if (!buf)
+               return -EINVAL;
+
+       ret = bts_buffer_reset(buf, &bts->handle);
+       if (ret) {
+               perf_aux_output_end(&bts->handle, 0, false);
+               return ret;
+       }
+
+       bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base;
+       bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
+       bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
+
+       if (mode & PERF_EF_START) {
+               bts_event_start(event, 0);
+               if (hwc->state & PERF_HES_STOPPED) {
+                       bts_event_del(event, 0);
+                       return -EBUSY;
+               }
+       }
+
+       return 0;
+}
+
+static void bts_event_destroy(struct perf_event *event)
+{
+       x86_release_hardware();
+       x86_del_exclusive(x86_lbr_exclusive_bts);
+}
+
+static int bts_event_init(struct perf_event *event)
+{
+       int ret;
+
+       if (event->attr.type != bts_pmu.type)
+               return -ENOENT;
+
+       if (x86_add_exclusive(x86_lbr_exclusive_bts))
+               return -EBUSY;
+
+       /*
+        * BTS leaks kernel addresses even when CPL0 tracing is
+        * disabled, so disallow intel_bts driver for unprivileged
+        * users on paranoid systems since it provides trace data
+        * to the user in a zero-copy fashion.
+        *
+        * Note that the default paranoia setting permits unprivileged
+        * users to profile the kernel.
+        */
+       if (event->attr.exclude_kernel && perf_paranoid_kernel() &&
+           !capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       ret = x86_reserve_hardware();
+       if (ret) {
+               x86_del_exclusive(x86_lbr_exclusive_bts);
+               return ret;
+       }
+
+       event->destroy = bts_event_destroy;
+
+       return 0;
+}
+
+static void bts_event_read(struct perf_event *event)
+{
+}
+
+static __init int bts_init(void)
+{
+       if (!boot_cpu_has(X86_FEATURE_DTES64) || !x86_pmu.bts)
+               return -ENODEV;
+
+       bts_pmu.capabilities    = PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_ITRACE;
+       bts_pmu.task_ctx_nr     = perf_sw_context;
+       bts_pmu.event_init      = bts_event_init;
+       bts_pmu.add             = bts_event_add;
+       bts_pmu.del             = bts_event_del;
+       bts_pmu.start           = bts_event_start;
+       bts_pmu.stop            = bts_event_stop;
+       bts_pmu.read            = bts_event_read;
+       bts_pmu.setup_aux       = bts_buffer_setup_aux;
+       bts_pmu.free_aux        = bts_buffer_free_aux;
+
+       return perf_pmu_register(&bts_pmu, "intel_bts", -1);
+}
+arch_initcall(bts_init);
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
new file mode 100644 (file)
index 0000000..68fa55b
--- /dev/null
@@ -0,0 +1,3796 @@
+/*
+ * Per core/cpu state
+ *
+ * Used to coordinate shared registers between HT threads or
+ * among events on a single PMU.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/nmi.h>
+
+#include <asm/cpufeature.h>
+#include <asm/hardirq.h>
+#include <asm/apic.h>
+
+#include "../perf_event.h"
+
+/*
+ * Intel PerfMon, used on Core and later.
+ */
+static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
+{
+       [PERF_COUNT_HW_CPU_CYCLES]              = 0x003c,
+       [PERF_COUNT_HW_INSTRUCTIONS]            = 0x00c0,
+       [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x4f2e,
+       [PERF_COUNT_HW_CACHE_MISSES]            = 0x412e,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0x00c4,
+       [PERF_COUNT_HW_BRANCH_MISSES]           = 0x00c5,
+       [PERF_COUNT_HW_BUS_CYCLES]              = 0x013c,
+       [PERF_COUNT_HW_REF_CPU_CYCLES]          = 0x0300, /* pseudo-encoding */
+};
+
+static struct event_constraint intel_core_event_constraints[] __read_mostly =
+{
+       INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
+       INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
+       INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
+       INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
+       INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
+       INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FP_COMP_INSTR_RET */
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_core2_event_constraints[] __read_mostly =
+{
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+       INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
+       INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
+       INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
+       INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
+       INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
+       INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */
+       INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
+       INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */
+       INTEL_EVENT_CONSTRAINT(0xc9, 0x1), /* ITLB_MISS_RETIRED (T30-9) */
+       INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_nehalem_event_constraints[] __read_mostly =
+{
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+       INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */
+       INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */
+       INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */
+       INTEL_EVENT_CONSTRAINT(0x43, 0x3), /* L1D_ALL_REF */
+       INTEL_EVENT_CONSTRAINT(0x48, 0x3), /* L1D_PEND_MISS */
+       INTEL_EVENT_CONSTRAINT(0x4e, 0x3), /* L1D_PREFETCH */
+       INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
+       INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
+       EVENT_CONSTRAINT_END
+};
+
+static struct extra_reg intel_nehalem_extra_regs[] __read_mostly =
+{
+       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
+       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0),
+       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x100b),
+       EVENT_EXTRA_END
+};
+
+static struct event_constraint intel_westmere_event_constraints[] __read_mostly =
+{
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+       INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
+       INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */
+       INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
+       INTEL_EVENT_CONSTRAINT(0xb3, 0x1), /* SNOOPQ_REQUEST_OUTSTANDING */
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_snb_event_constraints[] __read_mostly =
+{
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_DISPATCH */
+       INTEL_UEVENT_CONSTRAINT(0x05a3, 0xf), /* CYCLE_ACTIVITY.STALLS_L2_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x02a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x06a3, 0x4), /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
+       INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
+       INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
+       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_DISPATCH */
+       INTEL_UEVENT_CONSTRAINT(0x02a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
+
+       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_ivb_event_constraints[] __read_mostly =
+{
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+       INTEL_UEVENT_CONSTRAINT(0x0148, 0x4), /* L1D_PEND_MISS.PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x0279, 0xf), /* IDQ.EMTPY */
+       INTEL_UEVENT_CONSTRAINT(0x019c, 0xf), /* IDQ_UOPS_NOT_DELIVERED.CORE */
+       INTEL_UEVENT_CONSTRAINT(0x02a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_LDM_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */
+       INTEL_UEVENT_CONSTRAINT(0x05a3, 0xf), /* CYCLE_ACTIVITY.STALLS_L2_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x06a3, 0xf), /* CYCLE_ACTIVITY.STALLS_LDM_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x08a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x0ca3, 0x4), /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
+
+       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+
+       EVENT_CONSTRAINT_END
+};
+
+static struct extra_reg intel_westmere_extra_regs[] __read_mostly =
+{
+       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
+       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0),
+       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0xffff, RSP_1),
+       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x100b),
+       EVENT_EXTRA_END
+};
+
+static struct event_constraint intel_v1_event_constraints[] __read_mostly =
+{
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_gen_event_constraints[] __read_mostly =
+{
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_slm_event_constraints[] __read_mostly =
+{
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* pseudo CPU_CLK_UNHALTED.REF */
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_skl_event_constraints[] = {
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0),      /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1),      /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2),      /* CPU_CLK_UNHALTED.REF */
+       INTEL_UEVENT_CONSTRAINT(0x1c0, 0x2),    /* INST_RETIRED.PREC_DIST */
+       EVENT_CONSTRAINT_END
+};
+
+static struct extra_reg intel_knl_extra_regs[] __read_mostly = {
+       INTEL_UEVENT_EXTRA_REG(0x01b7,
+                              MSR_OFFCORE_RSP_0, 0x7f9ffbffffull, RSP_0),
+       INTEL_UEVENT_EXTRA_REG(0x02b7,
+                              MSR_OFFCORE_RSP_1, 0x3f9ffbffffull, RSP_1),
+       EVENT_EXTRA_END
+};
+
+static struct extra_reg intel_snb_extra_regs[] __read_mostly = {
+       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
+       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0),
+       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3f807f8fffull, RSP_1),
+       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
+       EVENT_EXTRA_END
+};
+
+static struct extra_reg intel_snbep_extra_regs[] __read_mostly = {
+       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
+       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
+       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
+       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
+       EVENT_EXTRA_END
+};
+
+static struct extra_reg intel_skl_extra_regs[] __read_mostly = {
+       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
+       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
+       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
+       /*
+        * Note the low 8 bits eventsel code is not a continuous field, containing
+        * some #GPing bits. These are masked out.
+        */
+       INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff17, FE),
+       EVENT_EXTRA_END
+};
+
+EVENT_ATTR_STR(mem-loads,      mem_ld_nhm,     "event=0x0b,umask=0x10,ldlat=3");
+EVENT_ATTR_STR(mem-loads,      mem_ld_snb,     "event=0xcd,umask=0x1,ldlat=3");
+EVENT_ATTR_STR(mem-stores,     mem_st_snb,     "event=0xcd,umask=0x2");
+
+struct attribute *nhm_events_attrs[] = {
+       EVENT_PTR(mem_ld_nhm),
+       NULL,
+};
+
+struct attribute *snb_events_attrs[] = {
+       EVENT_PTR(mem_ld_snb),
+       EVENT_PTR(mem_st_snb),
+       NULL,
+};
+
+static struct event_constraint intel_hsw_event_constraints[] = {
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+       INTEL_UEVENT_CONSTRAINT(0x148, 0x4),    /* L1D_PEND_MISS.PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
+       INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
+       /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x08a3, 0x4),
+       /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x0ca3, 0x4),
+       /* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */
+       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf),
+
+       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_bdw_event_constraints[] = {
+       FIXED_EVENT_CONSTRAINT(0x00c0, 0),      /* INST_RETIRED.ANY */
+       FIXED_EVENT_CONSTRAINT(0x003c, 1),      /* CPU_CLK_UNHALTED.CORE */
+       FIXED_EVENT_CONSTRAINT(0x0300, 2),      /* CPU_CLK_UNHALTED.REF */
+       INTEL_UEVENT_CONSTRAINT(0x148, 0x4),    /* L1D_PEND_MISS.PENDING */
+       INTEL_UBIT_EVENT_CONSTRAINT(0x8a3, 0x4),        /* CYCLE_ACTIVITY.CYCLES_L1D_MISS */
+       EVENT_CONSTRAINT_END
+};
+
+static u64 intel_pmu_event_map(int hw_event)
+{
+       return intel_perfmon_event_map[hw_event];
+}
+
+/*
+ * Notes on the events:
+ * - data reads do not include code reads (comparable to earlier tables)
+ * - data counts include speculative execution (except L1 write, dtlb, bpu)
+ * - remote node access includes remote memory, remote cache, remote mmio.
+ * - prefetches are not included in the counts.
+ * - icache miss does not include decoded icache
+ */
+
+#define SKL_DEMAND_DATA_RD             BIT_ULL(0)
+#define SKL_DEMAND_RFO                 BIT_ULL(1)
+#define SKL_ANY_RESPONSE               BIT_ULL(16)
+#define SKL_SUPPLIER_NONE              BIT_ULL(17)
+#define SKL_L3_MISS_LOCAL_DRAM         BIT_ULL(26)
+#define SKL_L3_MISS_REMOTE_HOP0_DRAM   BIT_ULL(27)
+#define SKL_L3_MISS_REMOTE_HOP1_DRAM   BIT_ULL(28)
+#define SKL_L3_MISS_REMOTE_HOP2P_DRAM  BIT_ULL(29)
+#define SKL_L3_MISS                    (SKL_L3_MISS_LOCAL_DRAM| \
+                                        SKL_L3_MISS_REMOTE_HOP0_DRAM| \
+                                        SKL_L3_MISS_REMOTE_HOP1_DRAM| \
+                                        SKL_L3_MISS_REMOTE_HOP2P_DRAM)
+#define SKL_SPL_HIT                    BIT_ULL(30)
+#define SKL_SNOOP_NONE                 BIT_ULL(31)
+#define SKL_SNOOP_NOT_NEEDED           BIT_ULL(32)
+#define SKL_SNOOP_MISS                 BIT_ULL(33)
+#define SKL_SNOOP_HIT_NO_FWD           BIT_ULL(34)
+#define SKL_SNOOP_HIT_WITH_FWD         BIT_ULL(35)
+#define SKL_SNOOP_HITM                 BIT_ULL(36)
+#define SKL_SNOOP_NON_DRAM             BIT_ULL(37)
+#define SKL_ANY_SNOOP                  (SKL_SPL_HIT|SKL_SNOOP_NONE| \
+                                        SKL_SNOOP_NOT_NEEDED|SKL_SNOOP_MISS| \
+                                        SKL_SNOOP_HIT_NO_FWD|SKL_SNOOP_HIT_WITH_FWD| \
+                                        SKL_SNOOP_HITM|SKL_SNOOP_NON_DRAM)
+#define SKL_DEMAND_READ                        SKL_DEMAND_DATA_RD
+#define SKL_SNOOP_DRAM                 (SKL_SNOOP_NONE| \
+                                        SKL_SNOOP_NOT_NEEDED|SKL_SNOOP_MISS| \
+                                        SKL_SNOOP_HIT_NO_FWD|SKL_SNOOP_HIT_WITH_FWD| \
+                                        SKL_SNOOP_HITM|SKL_SPL_HIT)
+#define SKL_DEMAND_WRITE               SKL_DEMAND_RFO
+#define SKL_LLC_ACCESS                 SKL_ANY_RESPONSE
+#define SKL_L3_MISS_REMOTE             (SKL_L3_MISS_REMOTE_HOP0_DRAM| \
+                                        SKL_L3_MISS_REMOTE_HOP1_DRAM| \
+                                        SKL_L3_MISS_REMOTE_HOP2P_DRAM)
+
+static __initconst const u64 skl_hw_cache_event_ids
+                               [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) ] = 0x81d0,  /* MEM_INST_RETIRED.ALL_LOADS */
+               [ C(RESULT_MISS)   ] = 0x151,   /* L1D.REPLACEMENT */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_INST_RETIRED.ALL_STORES */
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x283,   /* ICACHE_64B.MISS */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_INST_RETIRED.ALL_LOADS */
+               [ C(RESULT_MISS)   ] = 0x608,   /* DTLB_LOAD_MISSES.WALK_COMPLETED */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_INST_RETIRED.ALL_STORES */
+               [ C(RESULT_MISS)   ] = 0x649,   /* DTLB_STORE_MISSES.WALK_COMPLETED */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x2085,  /* ITLB_MISSES.STLB_HIT */
+               [ C(RESULT_MISS)   ] = 0xe85,   /* ITLB_MISSES.WALK_COMPLETED */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0xc4,    /* BR_INST_RETIRED.ALL_BRANCHES */
+               [ C(RESULT_MISS)   ] = 0xc5,    /* BR_MISP_RETIRED.ALL_BRANCHES */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+};
+
+static __initconst const u64 skl_hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = SKL_DEMAND_READ|
+                                      SKL_LLC_ACCESS|SKL_ANY_SNOOP,
+               [ C(RESULT_MISS)   ] = SKL_DEMAND_READ|
+                                      SKL_L3_MISS|SKL_ANY_SNOOP|
+                                      SKL_SUPPLIER_NONE,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = SKL_DEMAND_WRITE|
+                                      SKL_LLC_ACCESS|SKL_ANY_SNOOP,
+               [ C(RESULT_MISS)   ] = SKL_DEMAND_WRITE|
+                                      SKL_L3_MISS|SKL_ANY_SNOOP|
+                                      SKL_SUPPLIER_NONE,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = SKL_DEMAND_READ|
+                                      SKL_L3_MISS_LOCAL_DRAM|SKL_SNOOP_DRAM,
+               [ C(RESULT_MISS)   ] = SKL_DEMAND_READ|
+                                      SKL_L3_MISS_REMOTE|SKL_SNOOP_DRAM,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = SKL_DEMAND_WRITE|
+                                      SKL_L3_MISS_LOCAL_DRAM|SKL_SNOOP_DRAM,
+               [ C(RESULT_MISS)   ] = SKL_DEMAND_WRITE|
+                                      SKL_L3_MISS_REMOTE|SKL_SNOOP_DRAM,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+};
+
+#define SNB_DMND_DATA_RD       (1ULL << 0)
+#define SNB_DMND_RFO           (1ULL << 1)
+#define SNB_DMND_IFETCH                (1ULL << 2)
+#define SNB_DMND_WB            (1ULL << 3)
+#define SNB_PF_DATA_RD         (1ULL << 4)
+#define SNB_PF_RFO             (1ULL << 5)
+#define SNB_PF_IFETCH          (1ULL << 6)
+#define SNB_LLC_DATA_RD                (1ULL << 7)
+#define SNB_LLC_RFO            (1ULL << 8)
+#define SNB_LLC_IFETCH         (1ULL << 9)
+#define SNB_BUS_LOCKS          (1ULL << 10)
+#define SNB_STRM_ST            (1ULL << 11)
+#define SNB_OTHER              (1ULL << 15)
+#define SNB_RESP_ANY           (1ULL << 16)
+#define SNB_NO_SUPP            (1ULL << 17)
+#define SNB_LLC_HITM           (1ULL << 18)
+#define SNB_LLC_HITE           (1ULL << 19)
+#define SNB_LLC_HITS           (1ULL << 20)
+#define SNB_LLC_HITF           (1ULL << 21)
+#define SNB_LOCAL              (1ULL << 22)
+#define SNB_REMOTE             (0xffULL << 23)
+#define SNB_SNP_NONE           (1ULL << 31)
+#define SNB_SNP_NOT_NEEDED     (1ULL << 32)
+#define SNB_SNP_MISS           (1ULL << 33)
+#define SNB_NO_FWD             (1ULL << 34)
+#define SNB_SNP_FWD            (1ULL << 35)
+#define SNB_HITM               (1ULL << 36)
+#define SNB_NON_DRAM           (1ULL << 37)
+
+#define SNB_DMND_READ          (SNB_DMND_DATA_RD|SNB_LLC_DATA_RD)
+#define SNB_DMND_WRITE         (SNB_DMND_RFO|SNB_LLC_RFO)
+#define SNB_DMND_PREFETCH      (SNB_PF_DATA_RD|SNB_PF_RFO)
+
+#define SNB_SNP_ANY            (SNB_SNP_NONE|SNB_SNP_NOT_NEEDED| \
+                                SNB_SNP_MISS|SNB_NO_FWD|SNB_SNP_FWD| \
+                                SNB_HITM)
+
+#define SNB_DRAM_ANY           (SNB_LOCAL|SNB_REMOTE|SNB_SNP_ANY)
+#define SNB_DRAM_REMOTE                (SNB_REMOTE|SNB_SNP_ANY)
+
+#define SNB_L3_ACCESS          SNB_RESP_ANY
+#define SNB_L3_MISS            (SNB_DRAM_ANY|SNB_NON_DRAM)
+
+static __initconst const u64 snb_hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = SNB_DMND_READ|SNB_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = SNB_DMND_READ|SNB_L3_MISS,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = SNB_DMND_WRITE|SNB_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = SNB_DMND_WRITE|SNB_L3_MISS,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = SNB_DMND_PREFETCH|SNB_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = SNB_DMND_PREFETCH|SNB_L3_MISS,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = SNB_DMND_READ|SNB_DRAM_ANY,
+               [ C(RESULT_MISS)   ] = SNB_DMND_READ|SNB_DRAM_REMOTE,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = SNB_DMND_WRITE|SNB_DRAM_ANY,
+               [ C(RESULT_MISS)   ] = SNB_DMND_WRITE|SNB_DRAM_REMOTE,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = SNB_DMND_PREFETCH|SNB_DRAM_ANY,
+               [ C(RESULT_MISS)   ] = SNB_DMND_PREFETCH|SNB_DRAM_REMOTE,
+       },
+ },
+};
+
+static __initconst const u64 snb_hw_cache_event_ids
+                               [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) ] = 0xf1d0, /* MEM_UOP_RETIRED.LOADS        */
+               [ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPLACEMENT              */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0xf2d0, /* MEM_UOP_RETIRED.STORES       */
+               [ C(RESULT_MISS)   ] = 0x0851, /* L1D.ALL_M_REPLACEMENT        */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x024e, /* HW_PRE_REQ.DL1_MISS          */
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0280, /* ICACHE.MISSES */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_WRITE) ] = {
+               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_PREFETCH) ] = {
+               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x81d0, /* MEM_UOP_RETIRED.ALL_LOADS */
+               [ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.CAUSES_A_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x82d0, /* MEM_UOP_RETIRED.ALL_STORES */
+               [ C(RESULT_MISS)   ] = 0x0149, /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1085, /* ITLB_MISSES.STLB_HIT         */
+               [ C(RESULT_MISS)   ] = 0x0185, /* ITLB_MISSES.CAUSES_A_WALK    */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
+               [ C(RESULT_MISS)   ] = 0x00c5, /* BR_MISP_RETIRED.ALL_BRANCHES */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+ },
+
+};
+
+/*
+ * Notes on the events:
+ * - data reads do not include code reads (comparable to earlier tables)
+ * - data counts include speculative execution (except L1 write, dtlb, bpu)
+ * - remote node access includes remote memory, remote cache, remote mmio.
+ * - prefetches are not included in the counts because they are not
+ *   reliably counted.
+ */
+
+#define HSW_DEMAND_DATA_RD             BIT_ULL(0)
+#define HSW_DEMAND_RFO                 BIT_ULL(1)
+#define HSW_ANY_RESPONSE               BIT_ULL(16)
+#define HSW_SUPPLIER_NONE              BIT_ULL(17)
+#define HSW_L3_MISS_LOCAL_DRAM         BIT_ULL(22)
+#define HSW_L3_MISS_REMOTE_HOP0                BIT_ULL(27)
+#define HSW_L3_MISS_REMOTE_HOP1                BIT_ULL(28)
+#define HSW_L3_MISS_REMOTE_HOP2P       BIT_ULL(29)
+#define HSW_L3_MISS                    (HSW_L3_MISS_LOCAL_DRAM| \
+                                        HSW_L3_MISS_REMOTE_HOP0|HSW_L3_MISS_REMOTE_HOP1| \
+                                        HSW_L3_MISS_REMOTE_HOP2P)
+#define HSW_SNOOP_NONE                 BIT_ULL(31)
+#define HSW_SNOOP_NOT_NEEDED           BIT_ULL(32)
+#define HSW_SNOOP_MISS                 BIT_ULL(33)
+#define HSW_SNOOP_HIT_NO_FWD           BIT_ULL(34)
+#define HSW_SNOOP_HIT_WITH_FWD         BIT_ULL(35)
+#define HSW_SNOOP_HITM                 BIT_ULL(36)
+#define HSW_SNOOP_NON_DRAM             BIT_ULL(37)
+#define HSW_ANY_SNOOP                  (HSW_SNOOP_NONE| \
+                                        HSW_SNOOP_NOT_NEEDED|HSW_SNOOP_MISS| \
+                                        HSW_SNOOP_HIT_NO_FWD|HSW_SNOOP_HIT_WITH_FWD| \
+                                        HSW_SNOOP_HITM|HSW_SNOOP_NON_DRAM)
+#define HSW_SNOOP_DRAM                 (HSW_ANY_SNOOP & ~HSW_SNOOP_NON_DRAM)
+#define HSW_DEMAND_READ                        HSW_DEMAND_DATA_RD
+#define HSW_DEMAND_WRITE               HSW_DEMAND_RFO
+#define HSW_L3_MISS_REMOTE             (HSW_L3_MISS_REMOTE_HOP0|\
+                                        HSW_L3_MISS_REMOTE_HOP1|HSW_L3_MISS_REMOTE_HOP2P)
+#define HSW_LLC_ACCESS                 HSW_ANY_RESPONSE
+
+#define BDW_L3_MISS_LOCAL              BIT(26)
+#define BDW_L3_MISS                    (BDW_L3_MISS_LOCAL| \
+                                        HSW_L3_MISS_REMOTE_HOP0|HSW_L3_MISS_REMOTE_HOP1| \
+                                        HSW_L3_MISS_REMOTE_HOP2P)
+
+
+static __initconst const u64 hsw_hw_cache_event_ids
+                               [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) ] = 0x81d0,  /* MEM_UOPS_RETIRED.ALL_LOADS */
+               [ C(RESULT_MISS)   ] = 0x151,   /* L1D.REPLACEMENT */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_UOPS_RETIRED.ALL_STORES */
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x280,   /* ICACHE.MISSES */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_UOPS_RETIRED.ALL_LOADS */
+               [ C(RESULT_MISS)   ] = 0x108,   /* DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_UOPS_RETIRED.ALL_STORES */
+               [ C(RESULT_MISS)   ] = 0x149,   /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x6085,  /* ITLB_MISSES.STLB_HIT */
+               [ C(RESULT_MISS)   ] = 0x185,   /* ITLB_MISSES.MISS_CAUSES_A_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0xc4,    /* BR_INST_RETIRED.ALL_BRANCHES */
+               [ C(RESULT_MISS)   ] = 0xc5,    /* BR_MISP_RETIRED.ALL_BRANCHES */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
+               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+};
+
+static __initconst const u64 hsw_hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = HSW_DEMAND_READ|
+                                      HSW_LLC_ACCESS,
+               [ C(RESULT_MISS)   ] = HSW_DEMAND_READ|
+                                      HSW_L3_MISS|HSW_ANY_SNOOP,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = HSW_DEMAND_WRITE|
+                                      HSW_LLC_ACCESS,
+               [ C(RESULT_MISS)   ] = HSW_DEMAND_WRITE|
+                                      HSW_L3_MISS|HSW_ANY_SNOOP,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = HSW_DEMAND_READ|
+                                      HSW_L3_MISS_LOCAL_DRAM|
+                                      HSW_SNOOP_DRAM,
+               [ C(RESULT_MISS)   ] = HSW_DEMAND_READ|
+                                      HSW_L3_MISS_REMOTE|
+                                      HSW_SNOOP_DRAM,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = HSW_DEMAND_WRITE|
+                                      HSW_L3_MISS_LOCAL_DRAM|
+                                      HSW_SNOOP_DRAM,
+               [ C(RESULT_MISS)   ] = HSW_DEMAND_WRITE|
+                                      HSW_L3_MISS_REMOTE|
+                                      HSW_SNOOP_DRAM,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+};
+
+static __initconst const u64 westmere_hw_cache_event_ids
+                               [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) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
+               [ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPL                     */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
+               [ C(RESULT_MISS)   ] = 0x0251, /* L1D.M_REPL                   */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS        */
+               [ C(RESULT_MISS)   ] = 0x024e, /* L1D_PREFETCH.MISS            */
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                    */
+               [ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                   */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       /*
+        * Use RFO, not WRITEBACK, because a write miss would typically occur
+        * on RFO.
+        */
+       [ C(OP_WRITE) ] = {
+               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_PREFETCH) ] = {
+               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
+               [ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.ANY         */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
+               [ C(RESULT_MISS)   ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS  */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P           */
+               [ C(RESULT_MISS)   ] = 0x0185, /* ITLB_MISSES.ANY              */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
+               [ C(RESULT_MISS)   ] = 0x03e8, /* BPU_CLEARS.ANY               */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+ },
+};
+
+/*
+ * Nehalem/Westmere MSR_OFFCORE_RESPONSE bits;
+ * See IA32 SDM Vol 3B 30.6.1.3
+ */
+
+#define NHM_DMND_DATA_RD       (1 << 0)
+#define NHM_DMND_RFO           (1 << 1)
+#define NHM_DMND_IFETCH                (1 << 2)
+#define NHM_DMND_WB            (1 << 3)
+#define NHM_PF_DATA_RD         (1 << 4)
+#define NHM_PF_DATA_RFO                (1 << 5)
+#define NHM_PF_IFETCH          (1 << 6)
+#define NHM_OFFCORE_OTHER      (1 << 7)
+#define NHM_UNCORE_HIT         (1 << 8)
+#define NHM_OTHER_CORE_HIT_SNP (1 << 9)
+#define NHM_OTHER_CORE_HITM    (1 << 10)
+                               /* reserved */
+#define NHM_REMOTE_CACHE_FWD   (1 << 12)
+#define NHM_REMOTE_DRAM                (1 << 13)
+#define NHM_LOCAL_DRAM         (1 << 14)
+#define NHM_NON_DRAM           (1 << 15)
+
+#define NHM_LOCAL              (NHM_LOCAL_DRAM|NHM_REMOTE_CACHE_FWD)
+#define NHM_REMOTE             (NHM_REMOTE_DRAM)
+
+#define NHM_DMND_READ          (NHM_DMND_DATA_RD)
+#define NHM_DMND_WRITE         (NHM_DMND_RFO|NHM_DMND_WB)
+#define NHM_DMND_PREFETCH      (NHM_PF_DATA_RD|NHM_PF_DATA_RFO)
+
+#define NHM_L3_HIT     (NHM_UNCORE_HIT|NHM_OTHER_CORE_HIT_SNP|NHM_OTHER_CORE_HITM)
+#define NHM_L3_MISS    (NHM_NON_DRAM|NHM_LOCAL_DRAM|NHM_REMOTE_DRAM|NHM_REMOTE_CACHE_FWD)
+#define NHM_L3_ACCESS  (NHM_L3_HIT|NHM_L3_MISS)
+
+static __initconst const u64 nehalem_hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = NHM_DMND_READ|NHM_L3_MISS,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = NHM_DMND_WRITE|NHM_L3_MISS,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_L3_ACCESS,
+               [ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_L3_MISS,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_LOCAL|NHM_REMOTE,
+               [ C(RESULT_MISS)   ] = NHM_DMND_READ|NHM_REMOTE,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_LOCAL|NHM_REMOTE,
+               [ C(RESULT_MISS)   ] = NHM_DMND_WRITE|NHM_REMOTE,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_LOCAL|NHM_REMOTE,
+               [ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_REMOTE,
+       },
+ },
+};
+
+static __initconst const u64 nehalem_hw_cache_event_ids
+                               [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) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
+               [ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPL                     */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
+               [ C(RESULT_MISS)   ] = 0x0251, /* L1D.M_REPL                   */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS        */
+               [ C(RESULT_MISS)   ] = 0x024e, /* L1D_PREFETCH.MISS            */
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                    */
+               [ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                   */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       /*
+        * Use RFO, not WRITEBACK, because a write miss would typically occur
+        * on RFO.
+        */
+       [ C(OP_WRITE) ] = {
+               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_PREFETCH) ] = {
+               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI   (alias)  */
+               [ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.ANY         */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI   (alias)  */
+               [ C(RESULT_MISS)   ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS  */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P           */
+               [ C(RESULT_MISS)   ] = 0x20c8, /* ITLB_MISS_RETIRED            */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
+               [ C(RESULT_MISS)   ] = 0x03e8, /* BPU_CLEARS.ANY               */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+ },
+};
+
+static __initconst const u64 core2_hw_cache_event_ids
+                               [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) ] = 0x0f40, /* L1D_CACHE_LD.MESI          */
+               [ C(RESULT_MISS)   ] = 0x0140, /* L1D_CACHE_LD.I_STATE       */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI          */
+               [ C(RESULT_MISS)   ] = 0x0141, /* L1D_CACHE_ST.I_STATE       */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x104e, /* L1D_PREFETCH.REQUESTS      */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080, /* L1I.READS                  */
+               [ C(RESULT_MISS)   ] = 0x0081, /* L1I.MISSES                 */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI                 */
+               [ C(RESULT_MISS)   ] = 0x4129, /* L2_LD.ISTATE               */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI                 */
+               [ C(RESULT_MISS)   ] = 0x412A, /* L2_ST.ISTATE               */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI  (alias) */
+               [ C(RESULT_MISS)   ] = 0x0208, /* DTLB_MISSES.MISS_LD        */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI  (alias) */
+               [ C(RESULT_MISS)   ] = 0x0808, /* DTLB_MISSES.MISS_ST        */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P         */
+               [ C(RESULT_MISS)   ] = 0x1282, /* ITLBMISSES                 */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY        */
+               [ C(RESULT_MISS)   ] = 0x00c5, /* BP_INST_RETIRED.MISPRED    */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+};
+
+static __initconst const u64 atom_hw_cache_event_ids
+                               [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) ] = 0x2140, /* L1D_CACHE.LD               */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE.ST               */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                  */
+               [ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                 */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI                 */
+               [ C(RESULT_MISS)   ] = 0x4129, /* L2_LD.ISTATE               */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI                 */
+               [ C(RESULT_MISS)   ] = 0x412A, /* L2_ST.ISTATE               */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE_LD.MESI  (alias) */
+               [ C(RESULT_MISS)   ] = 0x0508, /* DTLB_MISSES.MISS_LD        */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE_ST.MESI  (alias) */
+               [ C(RESULT_MISS)   ] = 0x0608, /* DTLB_MISSES.MISS_ST        */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P         */
+               [ C(RESULT_MISS)   ] = 0x0282, /* ITLB.MISSES                */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY        */
+               [ C(RESULT_MISS)   ] = 0x00c5, /* BP_INST_RETIRED.MISPRED    */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+};
+
+static struct extra_reg intel_slm_extra_regs[] __read_mostly =
+{
+       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
+       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x768005ffffull, RSP_0),
+       INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0x368005ffffull, RSP_1),
+       EVENT_EXTRA_END
+};
+
+#define SLM_DMND_READ          SNB_DMND_DATA_RD
+#define SLM_DMND_WRITE         SNB_DMND_RFO
+#define SLM_DMND_PREFETCH      (SNB_PF_DATA_RD|SNB_PF_RFO)
+
+#define SLM_SNP_ANY            (SNB_SNP_NONE|SNB_SNP_MISS|SNB_NO_FWD|SNB_HITM)
+#define SLM_LLC_ACCESS         SNB_RESP_ANY
+#define SLM_LLC_MISS           (SLM_SNP_ANY|SNB_NON_DRAM)
+
+static __initconst const u64 slm_hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = SLM_DMND_READ|SLM_LLC_ACCESS,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = SLM_DMND_WRITE|SLM_LLC_ACCESS,
+               [ C(RESULT_MISS)   ] = SLM_DMND_WRITE|SLM_LLC_MISS,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = SLM_DMND_PREFETCH|SLM_LLC_ACCESS,
+               [ C(RESULT_MISS)   ] = SLM_DMND_PREFETCH|SLM_LLC_MISS,
+       },
+ },
+};
+
+static __initconst const u64 slm_hw_cache_event_ids
+                               [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) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0104, /* LD_DCU_MISS */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0380, /* ICACHE.ACCESSES */
+               [ C(RESULT_MISS)   ] = 0x0280, /* ICACGE.MISSES */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+       [ C(OP_PREFETCH) ] = {
+               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
+               [ C(RESULT_ACCESS) ] = 0x01b7,
+               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+               [ C(RESULT_MISS)   ] = 0x01b7,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0804, /* LD_DTLB_MISS */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */
+               [ C(RESULT_MISS)   ] = 0x40205, /* PAGE_WALKS.I_SIDE_WALKS */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */
+               [ C(RESULT_MISS)   ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+};
+
+#define KNL_OT_L2_HITE         BIT_ULL(19) /* Other Tile L2 Hit */
+#define KNL_OT_L2_HITF         BIT_ULL(20) /* Other Tile L2 Hit */
+#define KNL_MCDRAM_LOCAL       BIT_ULL(21)
+#define KNL_MCDRAM_FAR         BIT_ULL(22)
+#define KNL_DDR_LOCAL          BIT_ULL(23)
+#define KNL_DDR_FAR            BIT_ULL(24)
+#define KNL_DRAM_ANY           (KNL_MCDRAM_LOCAL | KNL_MCDRAM_FAR | \
+                                   KNL_DDR_LOCAL | KNL_DDR_FAR)
+#define KNL_L2_READ            SLM_DMND_READ
+#define KNL_L2_WRITE           SLM_DMND_WRITE
+#define KNL_L2_PREFETCH                SLM_DMND_PREFETCH
+#define KNL_L2_ACCESS          SLM_LLC_ACCESS
+#define KNL_L2_MISS            (KNL_OT_L2_HITE | KNL_OT_L2_HITF | \
+                                  KNL_DRAM_ANY | SNB_SNP_ANY | \
+                                                 SNB_NON_DRAM)
+
+static __initconst const u64 knl_hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)] = KNL_L2_READ | KNL_L2_ACCESS,
+                       [C(RESULT_MISS)]   = 0,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)] = KNL_L2_WRITE | KNL_L2_ACCESS,
+                       [C(RESULT_MISS)]   = KNL_L2_WRITE | KNL_L2_MISS,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)] = KNL_L2_PREFETCH | KNL_L2_ACCESS,
+                       [C(RESULT_MISS)]   = KNL_L2_PREFETCH | KNL_L2_MISS,
+               },
+       },
+};
+
+/*
+ * Used from PMIs where the LBRs are already disabled.
+ *
+ * This function could be called consecutively. It is required to remain in
+ * disabled state if called consecutively.
+ *
+ * During consecutive calls, the same disable value will be written to related
+ * registers, so the PMU state remains unchanged. hw.state in
+ * intel_bts_disable_local will remain PERF_HES_STOPPED too in consecutive
+ * calls.
+ */
+static void __intel_pmu_disable_all(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
+
+       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
+               intel_pmu_disable_bts();
+       else
+               intel_bts_disable_local();
+
+       intel_pmu_pebs_disable_all();
+}
+
+static void intel_pmu_disable_all(void)
+{
+       __intel_pmu_disable_all();
+       intel_pmu_lbr_disable_all();
+}
+
+static void __intel_pmu_enable_all(int added, bool pmi)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       intel_pmu_pebs_enable_all();
+       intel_pmu_lbr_enable_all(pmi);
+       wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL,
+                       x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask);
+
+       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
+               struct perf_event *event =
+                       cpuc->events[INTEL_PMC_IDX_FIXED_BTS];
+
+               if (WARN_ON_ONCE(!event))
+                       return;
+
+               intel_pmu_enable_bts(event->hw.config);
+       } else
+               intel_bts_enable_local();
+}
+
+static void intel_pmu_enable_all(int added)
+{
+       __intel_pmu_enable_all(added, false);
+}
+
+/*
+ * Workaround for:
+ *   Intel Errata AAK100 (model 26)
+ *   Intel Errata AAP53  (model 30)
+ *   Intel Errata BD53   (model 44)
+ *
+ * The official story:
+ *   These chips need to be 'reset' when adding counters by programming the
+ *   magic three (non-counting) events 0x4300B5, 0x4300D2, and 0x4300B1 either
+ *   in sequence on the same PMC or on different PMCs.
+ *
+ * In practise it appears some of these events do in fact count, and
+ * we need to programm all 4 events.
+ */
+static void intel_pmu_nhm_workaround(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       static const unsigned long nhm_magic[4] = {
+               0x4300B5,
+               0x4300D2,
+               0x4300B1,
+               0x4300B1
+       };
+       struct perf_event *event;
+       int i;
+
+       /*
+        * The Errata requires below steps:
+        * 1) Clear MSR_IA32_PEBS_ENABLE and MSR_CORE_PERF_GLOBAL_CTRL;
+        * 2) Configure 4 PERFEVTSELx with the magic events and clear
+        *    the corresponding PMCx;
+        * 3) set bit0~bit3 of MSR_CORE_PERF_GLOBAL_CTRL;
+        * 4) Clear MSR_CORE_PERF_GLOBAL_CTRL;
+        * 5) Clear 4 pairs of ERFEVTSELx and PMCx;
+        */
+
+       /*
+        * The real steps we choose are a little different from above.
+        * A) To reduce MSR operations, we don't run step 1) as they
+        *    are already cleared before this function is called;
+        * B) Call x86_perf_event_update to save PMCx before configuring
+        *    PERFEVTSELx with magic number;
+        * C) With step 5), we do clear only when the PERFEVTSELx is
+        *    not used currently.
+        * D) Call x86_perf_event_set_period to restore PMCx;
+        */
+
+       /* We always operate 4 pairs of PERF Counters */
+       for (i = 0; i < 4; i++) {
+               event = cpuc->events[i];
+               if (event)
+                       x86_perf_event_update(event);
+       }
+
+       for (i = 0; i < 4; i++) {
+               wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + i, nhm_magic[i]);
+               wrmsrl(MSR_ARCH_PERFMON_PERFCTR0 + i, 0x0);
+       }
+
+       wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0xf);
+       wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x0);
+
+       for (i = 0; i < 4; i++) {
+               event = cpuc->events[i];
+
+               if (event) {
+                       x86_perf_event_set_period(event);
+                       __x86_pmu_enable_event(&event->hw,
+                                       ARCH_PERFMON_EVENTSEL_ENABLE);
+               } else
+                       wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + i, 0x0);
+       }
+}
+
+static void intel_pmu_nhm_enable_all(int added)
+{
+       if (added)
+               intel_pmu_nhm_workaround();
+       intel_pmu_enable_all(added);
+}
+
+static inline u64 intel_pmu_get_status(void)
+{
+       u64 status;
+
+       rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
+
+       return status;
+}
+
+static inline void intel_pmu_ack_status(u64 ack)
+{
+       wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack);
+}
+
+static void intel_pmu_disable_fixed(struct hw_perf_event *hwc)
+{
+       int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
+       u64 ctrl_val, mask;
+
+       mask = 0xfULL << (idx * 4);
+
+       rdmsrl(hwc->config_base, ctrl_val);
+       ctrl_val &= ~mask;
+       wrmsrl(hwc->config_base, ctrl_val);
+}
+
+static inline bool event_is_checkpointed(struct perf_event *event)
+{
+       return (event->hw.config & HSW_IN_TX_CHECKPOINTED) != 0;
+}
+
+static void intel_pmu_disable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       if (unlikely(hwc->idx == INTEL_PMC_IDX_FIXED_BTS)) {
+               intel_pmu_disable_bts();
+               intel_pmu_drain_bts_buffer();
+               return;
+       }
+
+       cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx);
+       cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
+       cpuc->intel_cp_status &= ~(1ull << hwc->idx);
+
+       /*
+        * must disable before any actual event
+        * because any event may be combined with LBR
+        */
+       if (needs_branch_stack(event))
+               intel_pmu_lbr_disable(event);
+
+       if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
+               intel_pmu_disable_fixed(hwc);
+               return;
+       }
+
+       x86_pmu_disable_event(event);
+
+       if (unlikely(event->attr.precise_ip))
+               intel_pmu_pebs_disable(event);
+}
+
+static void intel_pmu_enable_fixed(struct hw_perf_event *hwc)
+{
+       int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
+       u64 ctrl_val, bits, mask;
+
+       /*
+        * Enable IRQ generation (0x8),
+        * and enable ring-3 counting (0x2) and ring-0 counting (0x1)
+        * if requested:
+        */
+       bits = 0x8ULL;
+       if (hwc->config & ARCH_PERFMON_EVENTSEL_USR)
+               bits |= 0x2;
+       if (hwc->config & ARCH_PERFMON_EVENTSEL_OS)
+               bits |= 0x1;
+
+       /*
+        * ANY bit is supported in v3 and up
+        */
+       if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY)
+               bits |= 0x4;
+
+       bits <<= (idx * 4);
+       mask = 0xfULL << (idx * 4);
+
+       rdmsrl(hwc->config_base, ctrl_val);
+       ctrl_val &= ~mask;
+       ctrl_val |= bits;
+       wrmsrl(hwc->config_base, ctrl_val);
+}
+
+static void intel_pmu_enable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       if (unlikely(hwc->idx == INTEL_PMC_IDX_FIXED_BTS)) {
+               if (!__this_cpu_read(cpu_hw_events.enabled))
+                       return;
+
+               intel_pmu_enable_bts(hwc->config);
+               return;
+       }
+       /*
+        * must enabled before any actual event
+        * because any event may be combined with LBR
+        */
+       if (needs_branch_stack(event))
+               intel_pmu_lbr_enable(event);
+
+       if (event->attr.exclude_host)
+               cpuc->intel_ctrl_guest_mask |= (1ull << hwc->idx);
+       if (event->attr.exclude_guest)
+               cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx);
+
+       if (unlikely(event_is_checkpointed(event)))
+               cpuc->intel_cp_status |= (1ull << hwc->idx);
+
+       if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
+               intel_pmu_enable_fixed(hwc);
+               return;
+       }
+
+       if (unlikely(event->attr.precise_ip))
+               intel_pmu_pebs_enable(event);
+
+       __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
+}
+
+/*
+ * Save and restart an expired event. Called by NMI contexts,
+ * so it has to be careful about preempting normal event ops:
+ */
+int intel_pmu_save_and_restart(struct perf_event *event)
+{
+       x86_perf_event_update(event);
+       /*
+        * For a checkpointed counter always reset back to 0.  This
+        * avoids a situation where the counter overflows, aborts the
+        * transaction and is then set back to shortly before the
+        * overflow, and overflows and aborts again.
+        */
+       if (unlikely(event_is_checkpointed(event))) {
+               /* No race with NMIs because the counter should not be armed */
+               wrmsrl(event->hw.event_base, 0);
+               local64_set(&event->hw.prev_count, 0);
+       }
+       return x86_perf_event_set_period(event);
+}
+
+static void intel_pmu_reset(void)
+{
+       struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
+       unsigned long flags;
+       int idx;
+
+       if (!x86_pmu.num_counters)
+               return;
+
+       local_irq_save(flags);
+
+       pr_info("clearing PMU state on CPU#%d\n", smp_processor_id());
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               wrmsrl_safe(x86_pmu_config_addr(idx), 0ull);
+               wrmsrl_safe(x86_pmu_event_addr(idx),  0ull);
+       }
+       for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++)
+               wrmsrl_safe(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
+
+       if (ds)
+               ds->bts_index = ds->bts_buffer_base;
+
+       /* Ack all overflows and disable fixed counters */
+       if (x86_pmu.version >= 2) {
+               intel_pmu_ack_status(intel_pmu_get_status());
+               wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
+       }
+
+       /* Reset LBRs and LBR freezing */
+       if (x86_pmu.lbr_nr) {
+               update_debugctlmsr(get_debugctlmsr() &
+                       ~(DEBUGCTLMSR_FREEZE_LBRS_ON_PMI|DEBUGCTLMSR_LBR));
+       }
+
+       local_irq_restore(flags);
+}
+
+/*
+ * This handler is triggered by the local APIC, so the APIC IRQ handling
+ * rules apply:
+ */
+static int intel_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       int bit, loops;
+       u64 status;
+       int handled;
+
+       cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       /*
+        * No known reason to not always do late ACK,
+        * but just in case do it opt-in.
+        */
+       if (!x86_pmu.late_ack)
+               apic_write(APIC_LVTPC, APIC_DM_NMI);
+       __intel_pmu_disable_all();
+       handled = intel_pmu_drain_bts_buffer();
+       handled += intel_bts_interrupt();
+       status = intel_pmu_get_status();
+       if (!status)
+               goto done;
+
+       loops = 0;
+again:
+       intel_pmu_lbr_read();
+       intel_pmu_ack_status(status);
+       if (++loops > 100) {
+               static bool warned = false;
+               if (!warned) {
+                       WARN(1, "perfevents: irq loop stuck!\n");
+                       perf_event_print_debug();
+                       warned = true;
+               }
+               intel_pmu_reset();
+               goto done;
+       }
+
+       inc_irq_stat(apic_perf_irqs);
+
+
+       /*
+        * Ignore a range of extra bits in status that do not indicate
+        * overflow by themselves.
+        */
+       status &= ~(GLOBAL_STATUS_COND_CHG |
+                   GLOBAL_STATUS_ASIF |
+                   GLOBAL_STATUS_LBRS_FROZEN);
+       if (!status)
+               goto done;
+
+       /*
+        * PEBS overflow sets bit 62 in the global status register
+        */
+       if (__test_and_clear_bit(62, (unsigned long *)&status)) {
+               handled++;
+               x86_pmu.drain_pebs(regs);
+               /*
+                * There are cases where, even though, the PEBS ovfl bit is set
+                * in GLOBAL_OVF_STATUS, the PEBS events may also have their
+                * overflow bits set for their counters. We must clear them
+                * here because they have been processed as exact samples in
+                * the drain_pebs() routine. They must not be processed again
+                * in the for_each_bit_set() loop for regular samples below.
+                */
+               status &= ~cpuc->pebs_enabled;
+               status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
+       }
+
+       /*
+        * Intel PT
+        */
+       if (__test_and_clear_bit(55, (unsigned long *)&status)) {
+               handled++;
+               intel_pt_interrupt();
+       }
+
+       /*
+        * Checkpointed counters can lead to 'spurious' PMIs because the
+        * rollback caused by the PMI will have cleared the overflow status
+        * bit. Therefore always force probe these counters.
+        */
+       status |= cpuc->intel_cp_status;
+
+       for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[bit];
+
+               handled++;
+
+               if (!test_bit(bit, cpuc->active_mask))
+                       continue;
+
+               if (!intel_pmu_save_and_restart(event))
+                       continue;
+
+               perf_sample_data_init(&data, 0, event->hw.last_period);
+
+               if (has_branch_stack(event))
+                       data.br_stack = &cpuc->lbr_stack;
+
+               if (perf_event_overflow(event, &data, regs))
+                       x86_pmu_stop(event, 0);
+       }
+
+       /*
+        * Repeat if there is more work to be done:
+        */
+       status = intel_pmu_get_status();
+       if (status)
+               goto again;
+
+done:
+       /* Only restore PMU state when it's active. See x86_pmu_disable(). */
+       if (cpuc->enabled)
+               __intel_pmu_enable_all(0, true);
+
+       /*
+        * Only unmask the NMI after the overflow counters
+        * have been reset. This avoids spurious NMIs on
+        * Haswell CPUs.
+        */
+       if (x86_pmu.late_ack)
+               apic_write(APIC_LVTPC, APIC_DM_NMI);
+       return handled;
+}
+
+static struct event_constraint *
+intel_bts_constraints(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned int hw_event, bts_event;
+
+       if (event->attr.freq)
+               return NULL;
+
+       hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
+       bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
+
+       if (unlikely(hw_event == bts_event && hwc->sample_period == 1))
+               return &bts_constraint;
+
+       return NULL;
+}
+
+static int intel_alt_er(int idx, u64 config)
+{
+       int alt_idx = idx;
+
+       if (!(x86_pmu.flags & PMU_FL_HAS_RSP_1))
+               return idx;
+
+       if (idx == EXTRA_REG_RSP_0)
+               alt_idx = EXTRA_REG_RSP_1;
+
+       if (idx == EXTRA_REG_RSP_1)
+               alt_idx = EXTRA_REG_RSP_0;
+
+       if (config & ~x86_pmu.extra_regs[alt_idx].valid_mask)
+               return idx;
+
+       return alt_idx;
+}
+
+static void intel_fixup_er(struct perf_event *event, int idx)
+{
+       event->hw.extra_reg.idx = idx;
+
+       if (idx == EXTRA_REG_RSP_0) {
+               event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
+               event->hw.config |= x86_pmu.extra_regs[EXTRA_REG_RSP_0].event;
+               event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0;
+       } else if (idx == EXTRA_REG_RSP_1) {
+               event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
+               event->hw.config |= x86_pmu.extra_regs[EXTRA_REG_RSP_1].event;
+               event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1;
+       }
+}
+
+/*
+ * manage allocation of shared extra msr for certain events
+ *
+ * sharing can be:
+ * per-cpu: to be shared between the various events on a single PMU
+ * per-core: per-cpu + shared by HT threads
+ */
+static struct event_constraint *
+__intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc,
+                                  struct perf_event *event,
+                                  struct hw_perf_event_extra *reg)
+{
+       struct event_constraint *c = &emptyconstraint;
+       struct er_account *era;
+       unsigned long flags;
+       int idx = reg->idx;
+
+       /*
+        * reg->alloc can be set due to existing state, so for fake cpuc we
+        * need to ignore this, otherwise we might fail to allocate proper fake
+        * state for this extra reg constraint. Also see the comment below.
+        */
+       if (reg->alloc && !cpuc->is_fake)
+               return NULL; /* call x86_get_event_constraint() */
+
+again:
+       era = &cpuc->shared_regs->regs[idx];
+       /*
+        * we use spin_lock_irqsave() to avoid lockdep issues when
+        * passing a fake cpuc
+        */
+       raw_spin_lock_irqsave(&era->lock, flags);
+
+       if (!atomic_read(&era->ref) || era->config == reg->config) {
+
+               /*
+                * If its a fake cpuc -- as per validate_{group,event}() we
+                * shouldn't touch event state and we can avoid doing so
+                * since both will only call get_event_constraints() once
+                * on each event, this avoids the need for reg->alloc.
+                *
+                * Not doing the ER fixup will only result in era->reg being
+                * wrong, but since we won't actually try and program hardware
+                * this isn't a problem either.
+                */
+               if (!cpuc->is_fake) {
+                       if (idx != reg->idx)
+                               intel_fixup_er(event, idx);
+
+                       /*
+                        * x86_schedule_events() can call get_event_constraints()
+                        * multiple times on events in the case of incremental
+                        * scheduling(). reg->alloc ensures we only do the ER
+                        * allocation once.
+                        */
+                       reg->alloc = 1;
+               }
+
+               /* lock in msr value */
+               era->config = reg->config;
+               era->reg = reg->reg;
+
+               /* one more user */
+               atomic_inc(&era->ref);
+
+               /*
+                * need to call x86_get_event_constraint()
+                * to check if associated event has constraints
+                */
+               c = NULL;
+       } else {
+               idx = intel_alt_er(idx, reg->config);
+               if (idx != reg->idx) {
+                       raw_spin_unlock_irqrestore(&era->lock, flags);
+                       goto again;
+               }
+       }
+       raw_spin_unlock_irqrestore(&era->lock, flags);
+
+       return c;
+}
+
+static void
+__intel_shared_reg_put_constraints(struct cpu_hw_events *cpuc,
+                                  struct hw_perf_event_extra *reg)
+{
+       struct er_account *era;
+
+       /*
+        * Only put constraint if extra reg was actually allocated. Also takes
+        * care of event which do not use an extra shared reg.
+        *
+        * Also, if this is a fake cpuc we shouldn't touch any event state
+        * (reg->alloc) and we don't care about leaving inconsistent cpuc state
+        * either since it'll be thrown out.
+        */
+       if (!reg->alloc || cpuc->is_fake)
+               return;
+
+       era = &cpuc->shared_regs->regs[reg->idx];
+
+       /* one fewer user */
+       atomic_dec(&era->ref);
+
+       /* allocate again next time */
+       reg->alloc = 0;
+}
+
+static struct event_constraint *
+intel_shared_regs_constraints(struct cpu_hw_events *cpuc,
+                             struct perf_event *event)
+{
+       struct event_constraint *c = NULL, *d;
+       struct hw_perf_event_extra *xreg, *breg;
+
+       xreg = &event->hw.extra_reg;
+       if (xreg->idx != EXTRA_REG_NONE) {
+               c = __intel_shared_reg_get_constraints(cpuc, event, xreg);
+               if (c == &emptyconstraint)
+                       return c;
+       }
+       breg = &event->hw.branch_reg;
+       if (breg->idx != EXTRA_REG_NONE) {
+               d = __intel_shared_reg_get_constraints(cpuc, event, breg);
+               if (d == &emptyconstraint) {
+                       __intel_shared_reg_put_constraints(cpuc, xreg);
+                       c = d;
+               }
+       }
+       return c;
+}
+
+struct event_constraint *
+x86_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event)
+{
+       struct event_constraint *c;
+
+       if (x86_pmu.event_constraints) {
+               for_each_event_constraint(c, x86_pmu.event_constraints) {
+                       if ((event->hw.config & c->cmask) == c->code) {
+                               event->hw.flags |= c->flags;
+                               return c;
+                       }
+               }
+       }
+
+       return &unconstrained;
+}
+
+static struct event_constraint *
+__intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                           struct perf_event *event)
+{
+       struct event_constraint *c;
+
+       c = intel_bts_constraints(event);
+       if (c)
+               return c;
+
+       c = intel_shared_regs_constraints(cpuc, event);
+       if (c)
+               return c;
+
+       c = intel_pebs_constraints(event);
+       if (c)
+               return c;
+
+       return x86_get_event_constraints(cpuc, idx, event);
+}
+
+static void
+intel_start_scheduling(struct cpu_hw_events *cpuc)
+{
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct intel_excl_states *xl;
+       int tid = cpuc->excl_thread_id;
+
+       /*
+        * nothing needed if in group validation mode
+        */
+       if (cpuc->is_fake || !is_ht_workaround_enabled())
+               return;
+
+       /*
+        * no exclusion needed
+        */
+       if (WARN_ON_ONCE(!excl_cntrs))
+               return;
+
+       xl = &excl_cntrs->states[tid];
+
+       xl->sched_started = true;
+       /*
+        * lock shared state until we are done scheduling
+        * in stop_event_scheduling()
+        * makes scheduling appear as a transaction
+        */
+       raw_spin_lock(&excl_cntrs->lock);
+}
+
+static void intel_commit_scheduling(struct cpu_hw_events *cpuc, int idx, int cntr)
+{
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct event_constraint *c = cpuc->event_constraint[idx];
+       struct intel_excl_states *xl;
+       int tid = cpuc->excl_thread_id;
+
+       if (cpuc->is_fake || !is_ht_workaround_enabled())
+               return;
+
+       if (WARN_ON_ONCE(!excl_cntrs))
+               return;
+
+       if (!(c->flags & PERF_X86_EVENT_DYNAMIC))
+               return;
+
+       xl = &excl_cntrs->states[tid];
+
+       lockdep_assert_held(&excl_cntrs->lock);
+
+       if (c->flags & PERF_X86_EVENT_EXCL)
+               xl->state[cntr] = INTEL_EXCL_EXCLUSIVE;
+       else
+               xl->state[cntr] = INTEL_EXCL_SHARED;
+}
+
+static void
+intel_stop_scheduling(struct cpu_hw_events *cpuc)
+{
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct intel_excl_states *xl;
+       int tid = cpuc->excl_thread_id;
+
+       /*
+        * nothing needed if in group validation mode
+        */
+       if (cpuc->is_fake || !is_ht_workaround_enabled())
+               return;
+       /*
+        * no exclusion needed
+        */
+       if (WARN_ON_ONCE(!excl_cntrs))
+               return;
+
+       xl = &excl_cntrs->states[tid];
+
+       xl->sched_started = false;
+       /*
+        * release shared state lock (acquired in intel_start_scheduling())
+        */
+       raw_spin_unlock(&excl_cntrs->lock);
+}
+
+static struct event_constraint *
+intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
+                          int idx, struct event_constraint *c)
+{
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       struct intel_excl_states *xlo;
+       int tid = cpuc->excl_thread_id;
+       int is_excl, i;
+
+       /*
+        * validating a group does not require
+        * enforcing cross-thread  exclusion
+        */
+       if (cpuc->is_fake || !is_ht_workaround_enabled())
+               return c;
+
+       /*
+        * no exclusion needed
+        */
+       if (WARN_ON_ONCE(!excl_cntrs))
+               return c;
+
+       /*
+        * because we modify the constraint, we need
+        * to make a copy. Static constraints come
+        * from static const tables.
+        *
+        * only needed when constraint has not yet
+        * been cloned (marked dynamic)
+        */
+       if (!(c->flags & PERF_X86_EVENT_DYNAMIC)) {
+               struct event_constraint *cx;
+
+               /*
+                * grab pre-allocated constraint entry
+                */
+               cx = &cpuc->constraint_list[idx];
+
+               /*
+                * initialize dynamic constraint
+                * with static constraint
+                */
+               *cx = *c;
+
+               /*
+                * mark constraint as dynamic, so we
+                * can free it later on
+                */
+               cx->flags |= PERF_X86_EVENT_DYNAMIC;
+               c = cx;
+       }
+
+       /*
+        * From here on, the constraint is dynamic.
+        * Either it was just allocated above, or it
+        * was allocated during a earlier invocation
+        * of this function
+        */
+
+       /*
+        * state of sibling HT
+        */
+       xlo = &excl_cntrs->states[tid ^ 1];
+
+       /*
+        * event requires exclusive counter access
+        * across HT threads
+        */
+       is_excl = c->flags & PERF_X86_EVENT_EXCL;
+       if (is_excl && !(event->hw.flags & PERF_X86_EVENT_EXCL_ACCT)) {
+               event->hw.flags |= PERF_X86_EVENT_EXCL_ACCT;
+               if (!cpuc->n_excl++)
+                       WRITE_ONCE(excl_cntrs->has_exclusive[tid], 1);
+       }
+
+       /*
+        * Modify static constraint with current dynamic
+        * state of thread
+        *
+        * EXCLUSIVE: sibling counter measuring exclusive event
+        * SHARED   : sibling counter measuring non-exclusive event
+        * UNUSED   : sibling counter unused
+        */
+       for_each_set_bit(i, c->idxmsk, X86_PMC_IDX_MAX) {
+               /*
+                * exclusive event in sibling counter
+                * our corresponding counter cannot be used
+                * regardless of our event
+                */
+               if (xlo->state[i] == INTEL_EXCL_EXCLUSIVE)
+                       __clear_bit(i, c->idxmsk);
+               /*
+                * if measuring an exclusive event, sibling
+                * measuring non-exclusive, then counter cannot
+                * be used
+                */
+               if (is_excl && xlo->state[i] == INTEL_EXCL_SHARED)
+                       __clear_bit(i, c->idxmsk);
+       }
+
+       /*
+        * recompute actual bit weight for scheduling algorithm
+        */
+       c->weight = hweight64(c->idxmsk64);
+
+       /*
+        * if we return an empty mask, then switch
+        * back to static empty constraint to avoid
+        * the cost of freeing later on
+        */
+       if (c->weight == 0)
+               c = &emptyconstraint;
+
+       return c;
+}
+
+static struct event_constraint *
+intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                           struct perf_event *event)
+{
+       struct event_constraint *c1 = NULL;
+       struct event_constraint *c2;
+
+       if (idx >= 0) /* fake does < 0 */
+               c1 = cpuc->event_constraint[idx];
+
+       /*
+        * first time only
+        * - static constraint: no change across incremental scheduling calls
+        * - dynamic constraint: handled by intel_get_excl_constraints()
+        */
+       c2 = __intel_get_event_constraints(cpuc, idx, event);
+       if (c1 && (c1->flags & PERF_X86_EVENT_DYNAMIC)) {
+               bitmap_copy(c1->idxmsk, c2->idxmsk, X86_PMC_IDX_MAX);
+               c1->weight = c2->weight;
+               c2 = c1;
+       }
+
+       if (cpuc->excl_cntrs)
+               return intel_get_excl_constraints(cpuc, event, idx, c2);
+
+       return c2;
+}
+
+static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
+               struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
+       int tid = cpuc->excl_thread_id;
+       struct intel_excl_states *xl;
+
+       /*
+        * nothing needed if in group validation mode
+        */
+       if (cpuc->is_fake)
+               return;
+
+       if (WARN_ON_ONCE(!excl_cntrs))
+               return;
+
+       if (hwc->flags & PERF_X86_EVENT_EXCL_ACCT) {
+               hwc->flags &= ~PERF_X86_EVENT_EXCL_ACCT;
+               if (!--cpuc->n_excl)
+                       WRITE_ONCE(excl_cntrs->has_exclusive[tid], 0);
+       }
+
+       /*
+        * If event was actually assigned, then mark the counter state as
+        * unused now.
+        */
+       if (hwc->idx >= 0) {
+               xl = &excl_cntrs->states[tid];
+
+               /*
+                * put_constraint may be called from x86_schedule_events()
+                * which already has the lock held so here make locking
+                * conditional.
+                */
+               if (!xl->sched_started)
+                       raw_spin_lock(&excl_cntrs->lock);
+
+               xl->state[hwc->idx] = INTEL_EXCL_UNUSED;
+
+               if (!xl->sched_started)
+                       raw_spin_unlock(&excl_cntrs->lock);
+       }
+}
+
+static void
+intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg;
+
+       reg = &event->hw.extra_reg;
+       if (reg->idx != EXTRA_REG_NONE)
+               __intel_shared_reg_put_constraints(cpuc, reg);
+
+       reg = &event->hw.branch_reg;
+       if (reg->idx != EXTRA_REG_NONE)
+               __intel_shared_reg_put_constraints(cpuc, reg);
+}
+
+static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
+                                       struct perf_event *event)
+{
+       intel_put_shared_regs_event_constraints(cpuc, event);
+
+       /*
+        * is PMU has exclusive counter restrictions, then
+        * all events are subject to and must call the
+        * put_excl_constraints() routine
+        */
+       if (cpuc->excl_cntrs)
+               intel_put_excl_constraints(cpuc, event);
+}
+
+static void intel_pebs_aliases_core2(struct perf_event *event)
+{
+       if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
+               /*
+                * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P
+                * (0x003c) so that we can use it with PEBS.
+                *
+                * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't
+                * PEBS capable. However we can use INST_RETIRED.ANY_P
+                * (0x00c0), which is a PEBS capable event, to get the same
+                * count.
+                *
+                * INST_RETIRED.ANY_P counts the number of cycles that retires
+                * CNTMASK instructions. By setting CNTMASK to a value (16)
+                * larger than the maximum number of instructions that can be
+                * retired per cycle (4) and then inverting the condition, we
+                * count all cycles that retire 16 or less instructions, which
+                * is every cycle.
+                *
+                * Thereby we gain a PEBS capable cycle counter.
+                */
+               u64 alt_config = X86_CONFIG(.event=0xc0, .inv=1, .cmask=16);
+
+               alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK);
+               event->hw.config = alt_config;
+       }
+}
+
+static void intel_pebs_aliases_snb(struct perf_event *event)
+{
+       if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
+               /*
+                * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P
+                * (0x003c) so that we can use it with PEBS.
+                *
+                * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't
+                * PEBS capable. However we can use UOPS_RETIRED.ALL
+                * (0x01c2), which is a PEBS capable event, to get the same
+                * count.
+                *
+                * UOPS_RETIRED.ALL counts the number of cycles that retires
+                * CNTMASK micro-ops. By setting CNTMASK to a value (16)
+                * larger than the maximum number of micro-ops that can be
+                * retired per cycle (4) and then inverting the condition, we
+                * count all cycles that retire 16 or less micro-ops, which
+                * is every cycle.
+                *
+                * Thereby we gain a PEBS capable cycle counter.
+                */
+               u64 alt_config = X86_CONFIG(.event=0xc2, .umask=0x01, .inv=1, .cmask=16);
+
+               alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK);
+               event->hw.config = alt_config;
+       }
+}
+
+static void intel_pebs_aliases_precdist(struct perf_event *event)
+{
+       if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
+               /*
+                * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P
+                * (0x003c) so that we can use it with PEBS.
+                *
+                * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't
+                * PEBS capable. However we can use INST_RETIRED.PREC_DIST
+                * (0x01c0), which is a PEBS capable event, to get the same
+                * count.
+                *
+                * The PREC_DIST event has special support to minimize sample
+                * shadowing effects. One drawback is that it can be
+                * only programmed on counter 1, but that seems like an
+                * acceptable trade off.
+                */
+               u64 alt_config = X86_CONFIG(.event=0xc0, .umask=0x01, .inv=1, .cmask=16);
+
+               alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK);
+               event->hw.config = alt_config;
+       }
+}
+
+static void intel_pebs_aliases_ivb(struct perf_event *event)
+{
+       if (event->attr.precise_ip < 3)
+               return intel_pebs_aliases_snb(event);
+       return intel_pebs_aliases_precdist(event);
+}
+
+static void intel_pebs_aliases_skl(struct perf_event *event)
+{
+       if (event->attr.precise_ip < 3)
+               return intel_pebs_aliases_core2(event);
+       return intel_pebs_aliases_precdist(event);
+}
+
+static unsigned long intel_pmu_free_running_flags(struct perf_event *event)
+{
+       unsigned long flags = x86_pmu.free_running_flags;
+
+       if (event->attr.use_clockid)
+               flags &= ~PERF_SAMPLE_TIME;
+       return flags;
+}
+
+static int intel_pmu_hw_config(struct perf_event *event)
+{
+       int ret = x86_pmu_hw_config(event);
+
+       if (ret)
+               return ret;
+
+       if (event->attr.precise_ip) {
+               if (!event->attr.freq) {
+                       event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD;
+                       if (!(event->attr.sample_type &
+                             ~intel_pmu_free_running_flags(event)))
+                               event->hw.flags |= PERF_X86_EVENT_FREERUNNING;
+               }
+               if (x86_pmu.pebs_aliases)
+                       x86_pmu.pebs_aliases(event);
+       }
+
+       if (needs_branch_stack(event)) {
+               ret = intel_pmu_setup_lbr_filter(event);
+               if (ret)
+                       return ret;
+
+               /*
+                * BTS is set up earlier in this path, so don't account twice
+                */
+               if (!intel_pmu_has_bts(event)) {
+                       /* disallow lbr if conflicting events are present */
+                       if (x86_add_exclusive(x86_lbr_exclusive_lbr))
+                               return -EBUSY;
+
+                       event->destroy = hw_perf_lbr_event_destroy;
+               }
+       }
+
+       if (event->attr.type != PERF_TYPE_RAW)
+               return 0;
+
+       if (!(event->attr.config & ARCH_PERFMON_EVENTSEL_ANY))
+               return 0;
+
+       if (x86_pmu.version < 3)
+               return -EINVAL;
+
+       if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       event->hw.config |= ARCH_PERFMON_EVENTSEL_ANY;
+
+       return 0;
+}
+
+struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
+{
+       if (x86_pmu.guest_get_msrs)
+               return x86_pmu.guest_get_msrs(nr);
+       *nr = 0;
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(perf_guest_get_msrs);
+
+static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+
+       arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;
+       arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;
+       arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask;
+       /*
+        * If PMU counter has PEBS enabled it is not enough to disable counter
+        * on a guest entry since PEBS memory write can overshoot guest entry
+        * and corrupt guest memory. Disabling PEBS solves the problem.
+        */
+       arr[1].msr = MSR_IA32_PEBS_ENABLE;
+       arr[1].host = cpuc->pebs_enabled;
+       arr[1].guest = 0;
+
+       *nr = 2;
+       return arr;
+}
+
+static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
+       int idx;
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++)  {
+               struct perf_event *event = cpuc->events[idx];
+
+               arr[idx].msr = x86_pmu_config_addr(idx);
+               arr[idx].host = arr[idx].guest = 0;
+
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               arr[idx].host = arr[idx].guest =
+                       event->hw.config | ARCH_PERFMON_EVENTSEL_ENABLE;
+
+               if (event->attr.exclude_host)
+                       arr[idx].host &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+               else if (event->attr.exclude_guest)
+                       arr[idx].guest &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+       }
+
+       *nr = x86_pmu.num_counters;
+       return arr;
+}
+
+static void core_pmu_enable_event(struct perf_event *event)
+{
+       if (!event->attr.exclude_host)
+               x86_pmu_enable_event(event);
+}
+
+static void core_pmu_enable_all(int added)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
+
+               if (!test_bit(idx, cpuc->active_mask) ||
+                               cpuc->events[idx]->attr.exclude_host)
+                       continue;
+
+               __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
+       }
+}
+
+static int hsw_hw_config(struct perf_event *event)
+{
+       int ret = intel_pmu_hw_config(event);
+
+       if (ret)
+               return ret;
+       if (!boot_cpu_has(X86_FEATURE_RTM) && !boot_cpu_has(X86_FEATURE_HLE))
+               return 0;
+       event->hw.config |= event->attr.config & (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED);
+
+       /*
+        * IN_TX/IN_TX-CP filters are not supported by the Haswell PMU with
+        * PEBS or in ANY thread mode. Since the results are non-sensical forbid
+        * this combination.
+        */
+       if ((event->hw.config & (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED)) &&
+            ((event->hw.config & ARCH_PERFMON_EVENTSEL_ANY) ||
+             event->attr.precise_ip > 0))
+               return -EOPNOTSUPP;
+
+       if (event_is_checkpointed(event)) {
+               /*
+                * Sampling of checkpointed events can cause situations where
+                * the CPU constantly aborts because of a overflow, which is
+                * then checkpointed back and ignored. Forbid checkpointing
+                * for sampling.
+                *
+                * But still allow a long sampling period, so that perf stat
+                * from KVM works.
+                */
+               if (event->attr.sample_period > 0 &&
+                   event->attr.sample_period < 0x7fffffff)
+                       return -EOPNOTSUPP;
+       }
+       return 0;
+}
+
+static struct event_constraint counter2_constraint =
+                       EVENT_CONSTRAINT(0, 0x4, 0);
+
+static struct event_constraint *
+hsw_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event)
+{
+       struct event_constraint *c;
+
+       c = intel_get_event_constraints(cpuc, idx, event);
+
+       /* Handle special quirk on in_tx_checkpointed only in counter 2 */
+       if (event->hw.config & HSW_IN_TX_CHECKPOINTED) {
+               if (c->idxmsk64 & (1U << 2))
+                       return &counter2_constraint;
+               return &emptyconstraint;
+       }
+
+       return c;
+}
+
+/*
+ * Broadwell:
+ *
+ * The INST_RETIRED.ALL period always needs to have lowest 6 bits cleared
+ * (BDM55) and it must not use a period smaller than 100 (BDM11). We combine
+ * the two to enforce a minimum period of 128 (the smallest value that has bits
+ * 0-5 cleared and >= 100).
+ *
+ * Because of how the code in x86_perf_event_set_period() works, the truncation
+ * of the lower 6 bits is 'harmless' as we'll occasionally add a longer period
+ * to make up for the 'lost' events due to carrying the 'error' in period_left.
+ *
+ * Therefore the effective (average) period matches the requested period,
+ * despite coarser hardware granularity.
+ */
+static unsigned bdw_limit_period(struct perf_event *event, unsigned left)
+{
+       if ((event->hw.config & INTEL_ARCH_EVENT_MASK) ==
+                       X86_CONFIG(.event=0xc0, .umask=0x01)) {
+               if (left < 128)
+                       left = 128;
+               left &= ~0x3fu;
+       }
+       return left;
+}
+
+PMU_FORMAT_ATTR(event, "config:0-7"    );
+PMU_FORMAT_ATTR(umask, "config:8-15"   );
+PMU_FORMAT_ATTR(edge,  "config:18"     );
+PMU_FORMAT_ATTR(pc,    "config:19"     );
+PMU_FORMAT_ATTR(any,   "config:21"     ); /* v3 + */
+PMU_FORMAT_ATTR(inv,   "config:23"     );
+PMU_FORMAT_ATTR(cmask, "config:24-31"  );
+PMU_FORMAT_ATTR(in_tx,  "config:32");
+PMU_FORMAT_ATTR(in_tx_cp, "config:33");
+
+static struct attribute *intel_arch_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_pc.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask.attr,
+       NULL,
+};
+
+ssize_t intel_event_sysfs_show(char *page, u64 config)
+{
+       u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
+
+       return x86_event_sysfs_show(page, config, event);
+}
+
+struct intel_shared_regs *allocate_shared_regs(int cpu)
+{
+       struct intel_shared_regs *regs;
+       int i;
+
+       regs = kzalloc_node(sizeof(struct intel_shared_regs),
+                           GFP_KERNEL, cpu_to_node(cpu));
+       if (regs) {
+               /*
+                * initialize the locks to keep lockdep happy
+                */
+               for (i = 0; i < EXTRA_REG_MAX; i++)
+                       raw_spin_lock_init(&regs->regs[i].lock);
+
+               regs->core_id = -1;
+       }
+       return regs;
+}
+
+static struct intel_excl_cntrs *allocate_excl_cntrs(int cpu)
+{
+       struct intel_excl_cntrs *c;
+
+       c = kzalloc_node(sizeof(struct intel_excl_cntrs),
+                        GFP_KERNEL, cpu_to_node(cpu));
+       if (c) {
+               raw_spin_lock_init(&c->lock);
+               c->core_id = -1;
+       }
+       return c;
+}
+
+static int intel_pmu_cpu_prepare(int cpu)
+{
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+
+       if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
+               cpuc->shared_regs = allocate_shared_regs(cpu);
+               if (!cpuc->shared_regs)
+                       goto err;
+       }
+
+       if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
+               size_t sz = X86_PMC_IDX_MAX * sizeof(struct event_constraint);
+
+               cpuc->constraint_list = kzalloc(sz, GFP_KERNEL);
+               if (!cpuc->constraint_list)
+                       goto err_shared_regs;
+
+               cpuc->excl_cntrs = allocate_excl_cntrs(cpu);
+               if (!cpuc->excl_cntrs)
+                       goto err_constraint_list;
+
+               cpuc->excl_thread_id = 0;
+       }
+
+       return NOTIFY_OK;
+
+err_constraint_list:
+       kfree(cpuc->constraint_list);
+       cpuc->constraint_list = NULL;
+
+err_shared_regs:
+       kfree(cpuc->shared_regs);
+       cpuc->shared_regs = NULL;
+
+err:
+       return NOTIFY_BAD;
+}
+
+static void intel_pmu_cpu_starting(int cpu)
+{
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+       int core_id = topology_core_id(cpu);
+       int i;
+
+       init_debug_store_on_cpu(cpu);
+       /*
+        * Deal with CPUs that don't clear their LBRs on power-up.
+        */
+       intel_pmu_lbr_reset();
+
+       cpuc->lbr_sel = NULL;
+
+       if (!cpuc->shared_regs)
+               return;
+
+       if (!(x86_pmu.flags & PMU_FL_NO_HT_SHARING)) {
+               for_each_cpu(i, topology_sibling_cpumask(cpu)) {
+                       struct intel_shared_regs *pc;
+
+                       pc = per_cpu(cpu_hw_events, i).shared_regs;
+                       if (pc && pc->core_id == core_id) {
+                               cpuc->kfree_on_online[0] = cpuc->shared_regs;
+                               cpuc->shared_regs = pc;
+                               break;
+                       }
+               }
+               cpuc->shared_regs->core_id = core_id;
+               cpuc->shared_regs->refcnt++;
+       }
+
+       if (x86_pmu.lbr_sel_map)
+               cpuc->lbr_sel = &cpuc->shared_regs->regs[EXTRA_REG_LBR];
+
+       if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
+               for_each_cpu(i, topology_sibling_cpumask(cpu)) {
+                       struct intel_excl_cntrs *c;
+
+                       c = per_cpu(cpu_hw_events, i).excl_cntrs;
+                       if (c && c->core_id == core_id) {
+                               cpuc->kfree_on_online[1] = cpuc->excl_cntrs;
+                               cpuc->excl_cntrs = c;
+                               cpuc->excl_thread_id = 1;
+                               break;
+                       }
+               }
+               cpuc->excl_cntrs->core_id = core_id;
+               cpuc->excl_cntrs->refcnt++;
+       }
+}
+
+static void free_excl_cntrs(int cpu)
+{
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+       struct intel_excl_cntrs *c;
+
+       c = cpuc->excl_cntrs;
+       if (c) {
+               if (c->core_id == -1 || --c->refcnt == 0)
+                       kfree(c);
+               cpuc->excl_cntrs = NULL;
+               kfree(cpuc->constraint_list);
+               cpuc->constraint_list = NULL;
+       }
+}
+
+static void intel_pmu_cpu_dying(int cpu)
+{
+       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+       struct intel_shared_regs *pc;
+
+       pc = cpuc->shared_regs;
+       if (pc) {
+               if (pc->core_id == -1 || --pc->refcnt == 0)
+                       kfree(pc);
+               cpuc->shared_regs = NULL;
+       }
+
+       free_excl_cntrs(cpu);
+
+       fini_debug_store_on_cpu(cpu);
+}
+
+static void intel_pmu_sched_task(struct perf_event_context *ctx,
+                                bool sched_in)
+{
+       if (x86_pmu.pebs_active)
+               intel_pmu_pebs_sched_task(ctx, sched_in);
+       if (x86_pmu.lbr_nr)
+               intel_pmu_lbr_sched_task(ctx, sched_in);
+}
+
+PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
+
+PMU_FORMAT_ATTR(ldlat, "config1:0-15");
+
+PMU_FORMAT_ATTR(frontend, "config1:0-23");
+
+static struct attribute *intel_arch3_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_pc.attr,
+       &format_attr_any.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask.attr,
+       &format_attr_in_tx.attr,
+       &format_attr_in_tx_cp.attr,
+
+       &format_attr_offcore_rsp.attr, /* XXX do NHM/WSM + SNB breakout */
+       &format_attr_ldlat.attr, /* PEBS load latency */
+       NULL,
+};
+
+static struct attribute *skl_format_attr[] = {
+       &format_attr_frontend.attr,
+       NULL,
+};
+
+static __initconst const struct x86_pmu core_pmu = {
+       .name                   = "core",
+       .handle_irq             = x86_pmu_handle_irq,
+       .disable_all            = x86_pmu_disable_all,
+       .enable_all             = core_pmu_enable_all,
+       .enable                 = core_pmu_enable_event,
+       .disable                = x86_pmu_disable_event,
+       .hw_config              = x86_pmu_hw_config,
+       .schedule_events        = x86_schedule_events,
+       .eventsel               = MSR_ARCH_PERFMON_EVENTSEL0,
+       .perfctr                = MSR_ARCH_PERFMON_PERFCTR0,
+       .event_map              = intel_pmu_event_map,
+       .max_events             = ARRAY_SIZE(intel_perfmon_event_map),
+       .apic                   = 1,
+       .free_running_flags     = PEBS_FREERUNNING_FLAGS,
+
+       /*
+        * Intel PMCs cannot be accessed sanely above 32-bit width,
+        * so we install an artificial 1<<31 period regardless of
+        * the generic event period:
+        */
+       .max_period             = (1ULL<<31) - 1,
+       .get_event_constraints  = intel_get_event_constraints,
+       .put_event_constraints  = intel_put_event_constraints,
+       .event_constraints      = intel_core_event_constraints,
+       .guest_get_msrs         = core_guest_get_msrs,
+       .format_attrs           = intel_arch_formats_attr,
+       .events_sysfs_show      = intel_event_sysfs_show,
+
+       /*
+        * Virtual (or funny metal) CPU can define x86_pmu.extra_regs
+        * together with PMU version 1 and thus be using core_pmu with
+        * shared_regs. We need following callbacks here to allocate
+        * it properly.
+        */
+       .cpu_prepare            = intel_pmu_cpu_prepare,
+       .cpu_starting           = intel_pmu_cpu_starting,
+       .cpu_dying              = intel_pmu_cpu_dying,
+};
+
+static __initconst const struct x86_pmu intel_pmu = {
+       .name                   = "Intel",
+       .handle_irq             = intel_pmu_handle_irq,
+       .disable_all            = intel_pmu_disable_all,
+       .enable_all             = intel_pmu_enable_all,
+       .enable                 = intel_pmu_enable_event,
+       .disable                = intel_pmu_disable_event,
+       .hw_config              = intel_pmu_hw_config,
+       .schedule_events        = x86_schedule_events,
+       .eventsel               = MSR_ARCH_PERFMON_EVENTSEL0,
+       .perfctr                = MSR_ARCH_PERFMON_PERFCTR0,
+       .event_map              = intel_pmu_event_map,
+       .max_events             = ARRAY_SIZE(intel_perfmon_event_map),
+       .apic                   = 1,
+       .free_running_flags     = PEBS_FREERUNNING_FLAGS,
+       /*
+        * Intel PMCs cannot be accessed sanely above 32 bit width,
+        * so we install an artificial 1<<31 period regardless of
+        * the generic event period:
+        */
+       .max_period             = (1ULL << 31) - 1,
+       .get_event_constraints  = intel_get_event_constraints,
+       .put_event_constraints  = intel_put_event_constraints,
+       .pebs_aliases           = intel_pebs_aliases_core2,
+
+       .format_attrs           = intel_arch3_formats_attr,
+       .events_sysfs_show      = intel_event_sysfs_show,
+
+       .cpu_prepare            = intel_pmu_cpu_prepare,
+       .cpu_starting           = intel_pmu_cpu_starting,
+       .cpu_dying              = intel_pmu_cpu_dying,
+       .guest_get_msrs         = intel_guest_get_msrs,
+       .sched_task             = intel_pmu_sched_task,
+};
+
+static __init void intel_clovertown_quirk(void)
+{
+       /*
+        * PEBS is unreliable due to:
+        *
+        *   AJ67  - PEBS may experience CPL leaks
+        *   AJ68  - PEBS PMI may be delayed by one event
+        *   AJ69  - GLOBAL_STATUS[62] will only be set when DEBUGCTL[12]
+        *   AJ106 - FREEZE_LBRS_ON_PMI doesn't work in combination with PEBS
+        *
+        * AJ67 could be worked around by restricting the OS/USR flags.
+        * AJ69 could be worked around by setting PMU_FREEZE_ON_PMI.
+        *
+        * AJ106 could possibly be worked around by not allowing LBR
+        *       usage from PEBS, including the fixup.
+        * AJ68  could possibly be worked around by always programming
+        *       a pebs_event_reset[0] value and coping with the lost events.
+        *
+        * But taken together it might just make sense to not enable PEBS on
+        * these chips.
+        */
+       pr_warn("PEBS disabled due to CPU errata\n");
+       x86_pmu.pebs = 0;
+       x86_pmu.pebs_constraints = NULL;
+}
+
+static int intel_snb_pebs_broken(int cpu)
+{
+       u32 rev = UINT_MAX; /* default to broken for unknown models */
+
+       switch (cpu_data(cpu).x86_model) {
+       case 42: /* SNB */
+               rev = 0x28;
+               break;
+
+       case 45: /* SNB-EP */
+               switch (cpu_data(cpu).x86_mask) {
+               case 6: rev = 0x618; break;
+               case 7: rev = 0x70c; break;
+               }
+       }
+
+       return (cpu_data(cpu).microcode < rev);
+}
+
+static void intel_snb_check_microcode(void)
+{
+       int pebs_broken = 0;
+       int cpu;
+
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
+               if ((pebs_broken = intel_snb_pebs_broken(cpu)))
+                       break;
+       }
+       put_online_cpus();
+
+       if (pebs_broken == x86_pmu.pebs_broken)
+               return;
+
+       /*
+        * Serialized by the microcode lock..
+        */
+       if (x86_pmu.pebs_broken) {
+               pr_info("PEBS enabled due to microcode update\n");
+               x86_pmu.pebs_broken = 0;
+       } else {
+               pr_info("PEBS disabled due to CPU errata, please upgrade microcode\n");
+               x86_pmu.pebs_broken = 1;
+       }
+}
+
+/*
+ * Under certain circumstances, access certain MSR may cause #GP.
+ * The function tests if the input MSR can be safely accessed.
+ */
+static bool check_msr(unsigned long msr, u64 mask)
+{
+       u64 val_old, val_new, val_tmp;
+
+       /*
+        * Read the current value, change it and read it back to see if it
+        * matches, this is needed to detect certain hardware emulators
+        * (qemu/kvm) that don't trap on the MSR access and always return 0s.
+        */
+       if (rdmsrl_safe(msr, &val_old))
+               return false;
+
+       /*
+        * Only change the bits which can be updated by wrmsrl.
+        */
+       val_tmp = val_old ^ mask;
+       if (wrmsrl_safe(msr, val_tmp) ||
+           rdmsrl_safe(msr, &val_new))
+               return false;
+
+       if (val_new != val_tmp)
+               return false;
+
+       /* Here it's sure that the MSR can be safely accessed.
+        * Restore the old value and return.
+        */
+       wrmsrl(msr, val_old);
+
+       return true;
+}
+
+static __init void intel_sandybridge_quirk(void)
+{
+       x86_pmu.check_microcode = intel_snb_check_microcode;
+       intel_snb_check_microcode();
+}
+
+static const struct { int id; char *name; } intel_arch_events_map[] __initconst = {
+       { PERF_COUNT_HW_CPU_CYCLES, "cpu cycles" },
+       { PERF_COUNT_HW_INSTRUCTIONS, "instructions" },
+       { PERF_COUNT_HW_BUS_CYCLES, "bus cycles" },
+       { PERF_COUNT_HW_CACHE_REFERENCES, "cache references" },
+       { PERF_COUNT_HW_CACHE_MISSES, "cache misses" },
+       { PERF_COUNT_HW_BRANCH_INSTRUCTIONS, "branch instructions" },
+       { PERF_COUNT_HW_BRANCH_MISSES, "branch misses" },
+};
+
+static __init void intel_arch_events_quirk(void)
+{
+       int bit;
+
+       /* disable event that reported as not presend by cpuid */
+       for_each_set_bit(bit, x86_pmu.events_mask, ARRAY_SIZE(intel_arch_events_map)) {
+               intel_perfmon_event_map[intel_arch_events_map[bit].id] = 0;
+               pr_warn("CPUID marked event: \'%s\' unavailable\n",
+                       intel_arch_events_map[bit].name);
+       }
+}
+
+static __init void intel_nehalem_quirk(void)
+{
+       union cpuid10_ebx ebx;
+
+       ebx.full = x86_pmu.events_maskl;
+       if (ebx.split.no_branch_misses_retired) {
+               /*
+                * Erratum AAJ80 detected, we work it around by using
+                * the BR_MISP_EXEC.ANY event. This will over-count
+                * branch-misses, but it's still much better than the
+                * architectural event which is often completely bogus:
+                */
+               intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
+               ebx.split.no_branch_misses_retired = 0;
+               x86_pmu.events_maskl = ebx.full;
+               pr_info("CPU erratum AAJ80 worked around\n");
+       }
+}
+
+/*
+ * enable software workaround for errata:
+ * SNB: BJ122
+ * IVB: BV98
+ * HSW: HSD29
+ *
+ * Only needed when HT is enabled. However detecting
+ * if HT is enabled is difficult (model specific). So instead,
+ * we enable the workaround in the early boot, and verify if
+ * it is needed in a later initcall phase once we have valid
+ * topology information to check if HT is actually enabled
+ */
+static __init void intel_ht_bug(void)
+{
+       x86_pmu.flags |= PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED;
+
+       x86_pmu.start_scheduling = intel_start_scheduling;
+       x86_pmu.commit_scheduling = intel_commit_scheduling;
+       x86_pmu.stop_scheduling = intel_stop_scheduling;
+}
+
+EVENT_ATTR_STR(mem-loads,      mem_ld_hsw,     "event=0xcd,umask=0x1,ldlat=3");
+EVENT_ATTR_STR(mem-stores,     mem_st_hsw,     "event=0xd0,umask=0x82")
+
+/* Haswell special events */
+EVENT_ATTR_STR(tx-start,       tx_start,       "event=0xc9,umask=0x1");
+EVENT_ATTR_STR(tx-commit,      tx_commit,      "event=0xc9,umask=0x2");
+EVENT_ATTR_STR(tx-abort,       tx_abort,       "event=0xc9,umask=0x4");
+EVENT_ATTR_STR(tx-capacity,    tx_capacity,    "event=0x54,umask=0x2");
+EVENT_ATTR_STR(tx-conflict,    tx_conflict,    "event=0x54,umask=0x1");
+EVENT_ATTR_STR(el-start,       el_start,       "event=0xc8,umask=0x1");
+EVENT_ATTR_STR(el-commit,      el_commit,      "event=0xc8,umask=0x2");
+EVENT_ATTR_STR(el-abort,       el_abort,       "event=0xc8,umask=0x4");
+EVENT_ATTR_STR(el-capacity,    el_capacity,    "event=0x54,umask=0x2");
+EVENT_ATTR_STR(el-conflict,    el_conflict,    "event=0x54,umask=0x1");
+EVENT_ATTR_STR(cycles-t,       cycles_t,       "event=0x3c,in_tx=1");
+EVENT_ATTR_STR(cycles-ct,      cycles_ct,      "event=0x3c,in_tx=1,in_tx_cp=1");
+
+static struct attribute *hsw_events_attrs[] = {
+       EVENT_PTR(tx_start),
+       EVENT_PTR(tx_commit),
+       EVENT_PTR(tx_abort),
+       EVENT_PTR(tx_capacity),
+       EVENT_PTR(tx_conflict),
+       EVENT_PTR(el_start),
+       EVENT_PTR(el_commit),
+       EVENT_PTR(el_abort),
+       EVENT_PTR(el_capacity),
+       EVENT_PTR(el_conflict),
+       EVENT_PTR(cycles_t),
+       EVENT_PTR(cycles_ct),
+       EVENT_PTR(mem_ld_hsw),
+       EVENT_PTR(mem_st_hsw),
+       NULL
+};
+
+__init int intel_pmu_init(void)
+{
+       union cpuid10_edx edx;
+       union cpuid10_eax eax;
+       union cpuid10_ebx ebx;
+       struct event_constraint *c;
+       unsigned int unused;
+       struct extra_reg *er;
+       int version, i;
+
+       if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+               switch (boot_cpu_data.x86) {
+               case 0x6:
+                       return p6_pmu_init();
+               case 0xb:
+                       return knc_pmu_init();
+               case 0xf:
+                       return p4_pmu_init();
+               }
+               return -ENODEV;
+       }
+
+       /*
+        * Check whether the Architectural PerfMon supports
+        * Branch Misses Retired hw_event or not.
+        */
+       cpuid(10, &eax.full, &ebx.full, &unused, &edx.full);
+       if (eax.split.mask_length < ARCH_PERFMON_EVENTS_COUNT)
+               return -ENODEV;
+
+       version = eax.split.version_id;
+       if (version < 2)
+               x86_pmu = core_pmu;
+       else
+               x86_pmu = intel_pmu;
+
+       x86_pmu.version                 = version;
+       x86_pmu.num_counters            = eax.split.num_counters;
+       x86_pmu.cntval_bits             = eax.split.bit_width;
+       x86_pmu.cntval_mask             = (1ULL << eax.split.bit_width) - 1;
+
+       x86_pmu.events_maskl            = ebx.full;
+       x86_pmu.events_mask_len         = eax.split.mask_length;
+
+       x86_pmu.max_pebs_events         = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters);
+
+       /*
+        * Quirk: v2 perfmon does not report fixed-purpose events, so
+        * assume at least 3 events:
+        */
+       if (version > 1)
+               x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3);
+
+       if (boot_cpu_has(X86_FEATURE_PDCM)) {
+               u64 capabilities;
+
+               rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities);
+               x86_pmu.intel_cap.capabilities = capabilities;
+       }
+
+       intel_ds_init();
+
+       x86_add_quirk(intel_arch_events_quirk); /* Install first, so it runs last */
+
+       /*
+        * Install the hw-cache-events table:
+        */
+       switch (boot_cpu_data.x86_model) {
+       case 14: /* 65nm Core "Yonah" */
+               pr_cont("Core events, ");
+               break;
+
+       case 15: /* 65nm Core2 "Merom"          */
+               x86_add_quirk(intel_clovertown_quirk);
+       case 22: /* 65nm Core2 "Merom-L"        */
+       case 23: /* 45nm Core2 "Penryn"         */
+       case 29: /* 45nm Core2 "Dunnington (MP) */
+               memcpy(hw_cache_event_ids, core2_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
+
+               intel_pmu_lbr_init_core();
+
+               x86_pmu.event_constraints = intel_core2_event_constraints;
+               x86_pmu.pebs_constraints = intel_core2_pebs_event_constraints;
+               pr_cont("Core2 events, ");
+               break;
+
+       case 30: /* 45nm Nehalem    */
+       case 26: /* 45nm Nehalem-EP */
+       case 46: /* 45nm Nehalem-EX */
+               memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
+                      sizeof(hw_cache_extra_regs));
+
+               intel_pmu_lbr_init_nhm();
+
+               x86_pmu.event_constraints = intel_nehalem_event_constraints;
+               x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
+               x86_pmu.enable_all = intel_pmu_nhm_enable_all;
+               x86_pmu.extra_regs = intel_nehalem_extra_regs;
+
+               x86_pmu.cpu_events = nhm_events_attrs;
+
+               /* UOPS_ISSUED.STALLED_CYCLES */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
+                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
+               /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
+                       X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
+
+               intel_pmu_pebs_data_source_nhm();
+               x86_add_quirk(intel_nehalem_quirk);
+
+               pr_cont("Nehalem events, ");
+               break;
+
+       case 28: /* 45nm Atom "Pineview"   */
+       case 38: /* 45nm Atom "Lincroft"   */
+       case 39: /* 32nm Atom "Penwell"    */
+       case 53: /* 32nm Atom "Cloverview" */
+       case 54: /* 32nm Atom "Cedarview"  */
+               memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
+
+               intel_pmu_lbr_init_atom();
+
+               x86_pmu.event_constraints = intel_gen_event_constraints;
+               x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints;
+               x86_pmu.pebs_aliases = intel_pebs_aliases_core2;
+               pr_cont("Atom events, ");
+               break;
+
+       case 55: /* 22nm Atom "Silvermont"                */
+       case 76: /* 14nm Atom "Airmont"                   */
+       case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
+               memcpy(hw_cache_event_ids, slm_hw_cache_event_ids,
+                       sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
+                      sizeof(hw_cache_extra_regs));
+
+               intel_pmu_lbr_init_atom();
+
+               x86_pmu.event_constraints = intel_slm_event_constraints;
+               x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
+               x86_pmu.extra_regs = intel_slm_extra_regs;
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               pr_cont("Silvermont events, ");
+               break;
+
+       case 37: /* 32nm Westmere    */
+       case 44: /* 32nm Westmere-EP */
+       case 47: /* 32nm Westmere-EX */
+               memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
+                      sizeof(hw_cache_extra_regs));
+
+               intel_pmu_lbr_init_nhm();
+
+               x86_pmu.event_constraints = intel_westmere_event_constraints;
+               x86_pmu.enable_all = intel_pmu_nhm_enable_all;
+               x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
+               x86_pmu.extra_regs = intel_westmere_extra_regs;
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+
+               x86_pmu.cpu_events = nhm_events_attrs;
+
+               /* UOPS_ISSUED.STALLED_CYCLES */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
+                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
+               /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
+                       X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
+
+               intel_pmu_pebs_data_source_nhm();
+               pr_cont("Westmere events, ");
+               break;
+
+       case 42: /* 32nm SandyBridge         */
+       case 45: /* 32nm SandyBridge-E/EN/EP */
+               x86_add_quirk(intel_sandybridge_quirk);
+               x86_add_quirk(intel_ht_bug);
+               memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
+                      sizeof(hw_cache_extra_regs));
+
+               intel_pmu_lbr_init_snb();
+
+               x86_pmu.event_constraints = intel_snb_event_constraints;
+               x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
+               x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
+               if (boot_cpu_data.x86_model == 45)
+                       x86_pmu.extra_regs = intel_snbep_extra_regs;
+               else
+                       x86_pmu.extra_regs = intel_snb_extra_regs;
+
+
+               /* all extra regs are per-cpu when HT is on */
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
+
+               x86_pmu.cpu_events = snb_events_attrs;
+
+               /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
+                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
+               /* UOPS_DISPATCHED.THREAD,c=1,i=1 to count stall cycles*/
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
+                       X86_CONFIG(.event=0xb1, .umask=0x01, .inv=1, .cmask=1);
+
+               pr_cont("SandyBridge events, ");
+               break;
+
+       case 58: /* 22nm IvyBridge       */
+       case 62: /* 22nm IvyBridge-EP/EX */
+               x86_add_quirk(intel_ht_bug);
+               memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
+               /* dTLB-load-misses on IVB is different than SNB */
+               hw_cache_event_ids[C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = 0x8108; /* DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK */
+
+               memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
+                      sizeof(hw_cache_extra_regs));
+
+               intel_pmu_lbr_init_snb();
+
+               x86_pmu.event_constraints = intel_ivb_event_constraints;
+               x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
+               x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
+               x86_pmu.pebs_prec_dist = true;
+               if (boot_cpu_data.x86_model == 62)
+                       x86_pmu.extra_regs = intel_snbep_extra_regs;
+               else
+                       x86_pmu.extra_regs = intel_snb_extra_regs;
+               /* all extra regs are per-cpu when HT is on */
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
+
+               x86_pmu.cpu_events = snb_events_attrs;
+
+               /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
+                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
+
+               pr_cont("IvyBridge events, ");
+               break;
+
+
+       case 60: /* 22nm Haswell Core */
+       case 63: /* 22nm Haswell Server */
+       case 69: /* 22nm Haswell ULT */
+       case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
+               x86_add_quirk(intel_ht_bug);
+               x86_pmu.late_ack = true;
+               memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+
+               intel_pmu_lbr_init_hsw();
+
+               x86_pmu.event_constraints = intel_hsw_event_constraints;
+               x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
+               x86_pmu.extra_regs = intel_snbep_extra_regs;
+               x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
+               x86_pmu.pebs_prec_dist = true;
+               /* all extra regs are per-cpu when HT is on */
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
+
+               x86_pmu.hw_config = hsw_hw_config;
+               x86_pmu.get_event_constraints = hsw_get_event_constraints;
+               x86_pmu.cpu_events = hsw_events_attrs;
+               x86_pmu.lbr_double_abort = true;
+               pr_cont("Haswell events, ");
+               break;
+
+       case 61: /* 14nm Broadwell Core-M */
+       case 86: /* 14nm Broadwell Xeon D */
+       case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
+       case 79: /* 14nm Broadwell Server */
+               x86_pmu.late_ack = true;
+               memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+
+               /* L3_MISS_LOCAL_DRAM is BIT(26) in Broadwell */
+               hw_cache_extra_regs[C(LL)][C(OP_READ)][C(RESULT_MISS)] = HSW_DEMAND_READ |
+                                                                        BDW_L3_MISS|HSW_SNOOP_DRAM;
+               hw_cache_extra_regs[C(LL)][C(OP_WRITE)][C(RESULT_MISS)] = HSW_DEMAND_WRITE|BDW_L3_MISS|
+                                                                         HSW_SNOOP_DRAM;
+               hw_cache_extra_regs[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = HSW_DEMAND_READ|
+                                                                            BDW_L3_MISS_LOCAL|HSW_SNOOP_DRAM;
+               hw_cache_extra_regs[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = HSW_DEMAND_WRITE|
+                                                                             BDW_L3_MISS_LOCAL|HSW_SNOOP_DRAM;
+
+               intel_pmu_lbr_init_hsw();
+
+               x86_pmu.event_constraints = intel_bdw_event_constraints;
+               x86_pmu.pebs_constraints = intel_bdw_pebs_event_constraints;
+               x86_pmu.extra_regs = intel_snbep_extra_regs;
+               x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
+               x86_pmu.pebs_prec_dist = true;
+               /* all extra regs are per-cpu when HT is on */
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
+
+               x86_pmu.hw_config = hsw_hw_config;
+               x86_pmu.get_event_constraints = hsw_get_event_constraints;
+               x86_pmu.cpu_events = hsw_events_attrs;
+               x86_pmu.limit_period = bdw_limit_period;
+               pr_cont("Broadwell events, ");
+               break;
+
+       case 87: /* Knights Landing Xeon Phi */
+               memcpy(hw_cache_event_ids,
+                      slm_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs,
+                      knl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+               intel_pmu_lbr_init_knl();
+
+               x86_pmu.event_constraints = intel_slm_event_constraints;
+               x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
+               x86_pmu.extra_regs = intel_knl_extra_regs;
+
+               /* all extra regs are per-cpu when HT is on */
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
+
+               pr_cont("Knights Landing events, ");
+               break;
+
+       case 78: /* 14nm Skylake Mobile */
+       case 94: /* 14nm Skylake Desktop */
+               x86_pmu.late_ack = true;
+               memcpy(hw_cache_event_ids, skl_hw_cache_event_ids, sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, skl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
+               intel_pmu_lbr_init_skl();
+
+               x86_pmu.event_constraints = intel_skl_event_constraints;
+               x86_pmu.pebs_constraints = intel_skl_pebs_event_constraints;
+               x86_pmu.extra_regs = intel_skl_extra_regs;
+               x86_pmu.pebs_aliases = intel_pebs_aliases_skl;
+               x86_pmu.pebs_prec_dist = true;
+               /* all extra regs are per-cpu when HT is on */
+               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
+
+               x86_pmu.hw_config = hsw_hw_config;
+               x86_pmu.get_event_constraints = hsw_get_event_constraints;
+               x86_pmu.format_attrs = merge_attr(intel_arch3_formats_attr,
+                                                 skl_format_attr);
+               WARN_ON(!x86_pmu.format_attrs);
+               x86_pmu.cpu_events = hsw_events_attrs;
+               pr_cont("Skylake events, ");
+               break;
+
+       default:
+               switch (x86_pmu.version) {
+               case 1:
+                       x86_pmu.event_constraints = intel_v1_event_constraints;
+                       pr_cont("generic architected perfmon v1, ");
+                       break;
+               default:
+                       /*
+                        * default constraints for v2 and up
+                        */
+                       x86_pmu.event_constraints = intel_gen_event_constraints;
+                       pr_cont("generic architected perfmon, ");
+                       break;
+               }
+       }
+
+       if (x86_pmu.num_counters > INTEL_PMC_MAX_GENERIC) {
+               WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
+                    x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
+               x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
+       }
+       x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
+
+       if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
+               WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
+                    x86_pmu.num_counters_fixed, INTEL_PMC_MAX_FIXED);
+               x86_pmu.num_counters_fixed = INTEL_PMC_MAX_FIXED;
+       }
+
+       x86_pmu.intel_ctrl |=
+               ((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
+
+       if (x86_pmu.event_constraints) {
+               /*
+                * event on fixed counter2 (REF_CYCLES) only works on this
+                * counter, so do not extend mask to generic counters
+                */
+               for_each_event_constraint(c, x86_pmu.event_constraints) {
+                       if (c->cmask == FIXED_EVENT_FLAGS
+                           && c->idxmsk64 != INTEL_PMC_MSK_FIXED_REF_CYCLES) {
+                               c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
+                       }
+                       c->idxmsk64 &=
+                               ~(~0UL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed));
+                       c->weight = hweight64(c->idxmsk64);
+               }
+       }
+
+       /*
+        * Access LBR MSR may cause #GP under certain circumstances.
+        * E.g. KVM doesn't support LBR MSR
+        * Check all LBT MSR here.
+        * Disable LBR access if any LBR MSRs can not be accessed.
+        */
+       if (x86_pmu.lbr_nr && !check_msr(x86_pmu.lbr_tos, 0x3UL))
+               x86_pmu.lbr_nr = 0;
+       for (i = 0; i < x86_pmu.lbr_nr; i++) {
+               if (!(check_msr(x86_pmu.lbr_from + i, 0xffffUL) &&
+                     check_msr(x86_pmu.lbr_to + i, 0xffffUL)))
+                       x86_pmu.lbr_nr = 0;
+       }
+
+       /*
+        * Access extra MSR may cause #GP under certain circumstances.
+        * E.g. KVM doesn't support offcore event
+        * Check all extra_regs here.
+        */
+       if (x86_pmu.extra_regs) {
+               for (er = x86_pmu.extra_regs; er->msr; er++) {
+                       er->extra_msr_access = check_msr(er->msr, 0x11UL);
+                       /* Disable LBR select mapping */
+                       if ((er->idx == EXTRA_REG_LBR) && !er->extra_msr_access)
+                               x86_pmu.lbr_sel_map = NULL;
+               }
+       }
+
+       /* Support full width counters using alternative MSR range */
+       if (x86_pmu.intel_cap.full_width_write) {
+               x86_pmu.max_period = x86_pmu.cntval_mask;
+               x86_pmu.perfctr = MSR_IA32_PMC0;
+               pr_cont("full-width counters, ");
+       }
+
+       return 0;
+}
+
+/*
+ * HT bug: phase 2 init
+ * Called once we have valid topology information to check
+ * whether or not HT is enabled
+ * If HT is off, then we disable the workaround
+ */
+static __init int fixup_ht_bug(void)
+{
+       int cpu = smp_processor_id();
+       int w, c;
+       /*
+        * problem not present on this CPU model, nothing to do
+        */
+       if (!(x86_pmu.flags & PMU_FL_EXCL_ENABLED))
+               return 0;
+
+       w = cpumask_weight(topology_sibling_cpumask(cpu));
+       if (w > 1) {
+               pr_info("PMU erratum BJ122, BV98, HSD29 worked around, HT is on\n");
+               return 0;
+       }
+
+       if (lockup_detector_suspend() != 0) {
+               pr_debug("failed to disable PMU erratum BJ122, BV98, HSD29 workaround\n");
+               return 0;
+       }
+
+       x86_pmu.flags &= ~(PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED);
+
+       x86_pmu.start_scheduling = NULL;
+       x86_pmu.commit_scheduling = NULL;
+       x86_pmu.stop_scheduling = NULL;
+
+       lockup_detector_resume();
+
+       get_online_cpus();
+
+       for_each_online_cpu(c) {
+               free_excl_cntrs(c);
+       }
+
+       put_online_cpus();
+       pr_info("PMU erratum BJ122, BV98, HSD29 workaround disabled, HT off\n");
+       return 0;
+}
+subsys_initcall(fixup_ht_bug)
diff --git a/arch/x86/events/intel/cqm.c b/arch/x86/events/intel/cqm.c
new file mode 100644 (file)
index 0000000..93cb412
--- /dev/null
@@ -0,0 +1,1381 @@
+/*
+ * Intel Cache Quality-of-Service Monitoring (CQM) support.
+ *
+ * Based very, very heavily on work by Peter Zijlstra.
+ */
+
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+#include <asm/cpu_device_id.h>
+#include "../perf_event.h"
+
+#define MSR_IA32_PQR_ASSOC     0x0c8f
+#define MSR_IA32_QM_CTR                0x0c8e
+#define MSR_IA32_QM_EVTSEL     0x0c8d
+
+static u32 cqm_max_rmid = -1;
+static unsigned int cqm_l3_scale; /* supposedly cacheline size */
+
+/**
+ * struct intel_pqr_state - State cache for the PQR MSR
+ * @rmid:              The cached Resource Monitoring ID
+ * @closid:            The cached Class Of Service ID
+ * @rmid_usecnt:       The usage counter for rmid
+ *
+ * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
+ * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
+ * contains both parts, so we need to cache them.
+ *
+ * The cache also helps to avoid pointless updates if the value does
+ * not change.
+ */
+struct intel_pqr_state {
+       u32                     rmid;
+       u32                     closid;
+       int                     rmid_usecnt;
+};
+
+/*
+ * The cached intel_pqr_state is strictly per CPU and can never be
+ * updated from a remote CPU. Both functions which modify the state
+ * (intel_cqm_event_start and intel_cqm_event_stop) are called with
+ * interrupts disabled, which is sufficient for the protection.
+ */
+static DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
+
+/*
+ * Protects cache_cgroups and cqm_rmid_free_lru and cqm_rmid_limbo_lru.
+ * Also protects event->hw.cqm_rmid
+ *
+ * Hold either for stability, both for modification of ->hw.cqm_rmid.
+ */
+static DEFINE_MUTEX(cache_mutex);
+static DEFINE_RAW_SPINLOCK(cache_lock);
+
+/*
+ * Groups of events that have the same target(s), one RMID per group.
+ */
+static LIST_HEAD(cache_groups);
+
+/*
+ * Mask of CPUs for reading CQM values. We only need one per-socket.
+ */
+static cpumask_t cqm_cpumask;
+
+#define RMID_VAL_ERROR         (1ULL << 63)
+#define RMID_VAL_UNAVAIL       (1ULL << 62)
+
+#define QOS_L3_OCCUP_EVENT_ID  (1 << 0)
+
+#define QOS_EVENT_MASK QOS_L3_OCCUP_EVENT_ID
+
+/*
+ * This is central to the rotation algorithm in __intel_cqm_rmid_rotate().
+ *
+ * This rmid is always free and is guaranteed to have an associated
+ * near-zero occupancy value, i.e. no cachelines are tagged with this
+ * RMID, once __intel_cqm_rmid_rotate() returns.
+ */
+static u32 intel_cqm_rotation_rmid;
+
+#define INVALID_RMID           (-1)
+
+/*
+ * Is @rmid valid for programming the hardware?
+ *
+ * rmid 0 is reserved by the hardware for all non-monitored tasks, which
+ * means that we should never come across an rmid with that value.
+ * Likewise, an rmid value of -1 is used to indicate "no rmid currently
+ * assigned" and is used as part of the rotation code.
+ */
+static inline bool __rmid_valid(u32 rmid)
+{
+       if (!rmid || rmid == INVALID_RMID)
+               return false;
+
+       return true;
+}
+
+static u64 __rmid_read(u32 rmid)
+{
+       u64 val;
+
+       /*
+        * Ignore the SDM, this thing is _NOTHING_ like a regular perfcnt,
+        * it just says that to increase confusion.
+        */
+       wrmsr(MSR_IA32_QM_EVTSEL, QOS_L3_OCCUP_EVENT_ID, rmid);
+       rdmsrl(MSR_IA32_QM_CTR, val);
+
+       /*
+        * Aside from the ERROR and UNAVAIL bits, assume this thing returns
+        * the number of cachelines tagged with @rmid.
+        */
+       return val;
+}
+
+enum rmid_recycle_state {
+       RMID_YOUNG = 0,
+       RMID_AVAILABLE,
+       RMID_DIRTY,
+};
+
+struct cqm_rmid_entry {
+       u32 rmid;
+       enum rmid_recycle_state state;
+       struct list_head list;
+       unsigned long queue_time;
+};
+
+/*
+ * cqm_rmid_free_lru - A least recently used list of RMIDs.
+ *
+ * Oldest entry at the head, newest (most recently used) entry at the
+ * tail. This list is never traversed, it's only used to keep track of
+ * the lru order. That is, we only pick entries of the head or insert
+ * them on the tail.
+ *
+ * All entries on the list are 'free', and their RMIDs are not currently
+ * in use. To mark an RMID as in use, remove its entry from the lru
+ * list.
+ *
+ *
+ * cqm_rmid_limbo_lru - list of currently unused but (potentially) dirty RMIDs.
+ *
+ * This list is contains RMIDs that no one is currently using but that
+ * may have a non-zero occupancy value associated with them. The
+ * rotation worker moves RMIDs from the limbo list to the free list once
+ * the occupancy value drops below __intel_cqm_threshold.
+ *
+ * Both lists are protected by cache_mutex.
+ */
+static LIST_HEAD(cqm_rmid_free_lru);
+static LIST_HEAD(cqm_rmid_limbo_lru);
+
+/*
+ * We use a simple array of pointers so that we can lookup a struct
+ * cqm_rmid_entry in O(1). This alleviates the callers of __get_rmid()
+ * and __put_rmid() from having to worry about dealing with struct
+ * cqm_rmid_entry - they just deal with rmids, i.e. integers.
+ *
+ * Once this array is initialized it is read-only. No locks are required
+ * to access it.
+ *
+ * All entries for all RMIDs can be looked up in the this array at all
+ * times.
+ */
+static struct cqm_rmid_entry **cqm_rmid_ptrs;
+
+static inline struct cqm_rmid_entry *__rmid_entry(u32 rmid)
+{
+       struct cqm_rmid_entry *entry;
+
+       entry = cqm_rmid_ptrs[rmid];
+       WARN_ON(entry->rmid != rmid);
+
+       return entry;
+}
+
+/*
+ * Returns < 0 on fail.
+ *
+ * We expect to be called with cache_mutex held.
+ */
+static u32 __get_rmid(void)
+{
+       struct cqm_rmid_entry *entry;
+
+       lockdep_assert_held(&cache_mutex);
+
+       if (list_empty(&cqm_rmid_free_lru))
+               return INVALID_RMID;
+
+       entry = list_first_entry(&cqm_rmid_free_lru, struct cqm_rmid_entry, list);
+       list_del(&entry->list);
+
+       return entry->rmid;
+}
+
+static void __put_rmid(u32 rmid)
+{
+       struct cqm_rmid_entry *entry;
+
+       lockdep_assert_held(&cache_mutex);
+
+       WARN_ON(!__rmid_valid(rmid));
+       entry = __rmid_entry(rmid);
+
+       entry->queue_time = jiffies;
+       entry->state = RMID_YOUNG;
+
+       list_add_tail(&entry->list, &cqm_rmid_limbo_lru);
+}
+
+static int intel_cqm_setup_rmid_cache(void)
+{
+       struct cqm_rmid_entry *entry;
+       unsigned int nr_rmids;
+       int r = 0;
+
+       nr_rmids = cqm_max_rmid + 1;
+       cqm_rmid_ptrs = kmalloc(sizeof(struct cqm_rmid_entry *) *
+                               nr_rmids, GFP_KERNEL);
+       if (!cqm_rmid_ptrs)
+               return -ENOMEM;
+
+       for (; r <= cqm_max_rmid; r++) {
+               struct cqm_rmid_entry *entry;
+
+               entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+               if (!entry)
+                       goto fail;
+
+               INIT_LIST_HEAD(&entry->list);
+               entry->rmid = r;
+               cqm_rmid_ptrs[r] = entry;
+
+               list_add_tail(&entry->list, &cqm_rmid_free_lru);
+       }
+
+       /*
+        * RMID 0 is special and is always allocated. It's used for all
+        * tasks that are not monitored.
+        */
+       entry = __rmid_entry(0);
+       list_del(&entry->list);
+
+       mutex_lock(&cache_mutex);
+       intel_cqm_rotation_rmid = __get_rmid();
+       mutex_unlock(&cache_mutex);
+
+       return 0;
+fail:
+       while (r--)
+               kfree(cqm_rmid_ptrs[r]);
+
+       kfree(cqm_rmid_ptrs);
+       return -ENOMEM;
+}
+
+/*
+ * Determine if @a and @b measure the same set of tasks.
+ *
+ * If @a and @b measure the same set of tasks then we want to share a
+ * single RMID.
+ */
+static bool __match_event(struct perf_event *a, struct perf_event *b)
+{
+       /* Per-cpu and task events don't mix */
+       if ((a->attach_state & PERF_ATTACH_TASK) !=
+           (b->attach_state & PERF_ATTACH_TASK))
+               return false;
+
+#ifdef CONFIG_CGROUP_PERF
+       if (a->cgrp != b->cgrp)
+               return false;
+#endif
+
+       /* If not task event, we're machine wide */
+       if (!(b->attach_state & PERF_ATTACH_TASK))
+               return true;
+
+       /*
+        * Events that target same task are placed into the same cache group.
+        */
+       if (a->hw.target == b->hw.target)
+               return true;
+
+       /*
+        * Are we an inherited event?
+        */
+       if (b->parent == a)
+               return true;
+
+       return false;
+}
+
+#ifdef CONFIG_CGROUP_PERF
+static inline struct perf_cgroup *event_to_cgroup(struct perf_event *event)
+{
+       if (event->attach_state & PERF_ATTACH_TASK)
+               return perf_cgroup_from_task(event->hw.target, event->ctx);
+
+       return event->cgrp;
+}
+#endif
+
+/*
+ * Determine if @a's tasks intersect with @b's tasks
+ *
+ * There are combinations of events that we explicitly prohibit,
+ *
+ *                PROHIBITS
+ *     system-wide    ->       cgroup and task
+ *     cgroup        ->        system-wide
+ *                           ->        task in cgroup
+ *     task          ->        system-wide
+ *                           ->        task in cgroup
+ *
+ * Call this function before allocating an RMID.
+ */
+static bool __conflict_event(struct perf_event *a, struct perf_event *b)
+{
+#ifdef CONFIG_CGROUP_PERF
+       /*
+        * We can have any number of cgroups but only one system-wide
+        * event at a time.
+        */
+       if (a->cgrp && b->cgrp) {
+               struct perf_cgroup *ac = a->cgrp;
+               struct perf_cgroup *bc = b->cgrp;
+
+               /*
+                * This condition should have been caught in
+                * __match_event() and we should be sharing an RMID.
+                */
+               WARN_ON_ONCE(ac == bc);
+
+               if (cgroup_is_descendant(ac->css.cgroup, bc->css.cgroup) ||
+                   cgroup_is_descendant(bc->css.cgroup, ac->css.cgroup))
+                       return true;
+
+               return false;
+       }
+
+       if (a->cgrp || b->cgrp) {
+               struct perf_cgroup *ac, *bc;
+
+               /*
+                * cgroup and system-wide events are mutually exclusive
+                */
+               if ((a->cgrp && !(b->attach_state & PERF_ATTACH_TASK)) ||
+                   (b->cgrp && !(a->attach_state & PERF_ATTACH_TASK)))
+                       return true;
+
+               /*
+                * Ensure neither event is part of the other's cgroup
+                */
+               ac = event_to_cgroup(a);
+               bc = event_to_cgroup(b);
+               if (ac == bc)
+                       return true;
+
+               /*
+                * Must have cgroup and non-intersecting task events.
+                */
+               if (!ac || !bc)
+                       return false;
+
+               /*
+                * We have cgroup and task events, and the task belongs
+                * to a cgroup. Check for for overlap.
+                */
+               if (cgroup_is_descendant(ac->css.cgroup, bc->css.cgroup) ||
+                   cgroup_is_descendant(bc->css.cgroup, ac->css.cgroup))
+                       return true;
+
+               return false;
+       }
+#endif
+       /*
+        * If one of them is not a task, same story as above with cgroups.
+        */
+       if (!(a->attach_state & PERF_ATTACH_TASK) ||
+           !(b->attach_state & PERF_ATTACH_TASK))
+               return true;
+
+       /*
+        * Must be non-overlapping.
+        */
+       return false;
+}
+
+struct rmid_read {
+       u32 rmid;
+       atomic64_t value;
+};
+
+static void __intel_cqm_event_count(void *info);
+
+/*
+ * Exchange the RMID of a group of events.
+ */
+static u32 intel_cqm_xchg_rmid(struct perf_event *group, u32 rmid)
+{
+       struct perf_event *event;
+       struct list_head *head = &group->hw.cqm_group_entry;
+       u32 old_rmid = group->hw.cqm_rmid;
+
+       lockdep_assert_held(&cache_mutex);
+
+       /*
+        * If our RMID is being deallocated, perform a read now.
+        */
+       if (__rmid_valid(old_rmid) && !__rmid_valid(rmid)) {
+               struct rmid_read rr = {
+                       .value = ATOMIC64_INIT(0),
+                       .rmid = old_rmid,
+               };
+
+               on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count,
+                                &rr, 1);
+               local64_set(&group->count, atomic64_read(&rr.value));
+       }
+
+       raw_spin_lock_irq(&cache_lock);
+
+       group->hw.cqm_rmid = rmid;
+       list_for_each_entry(event, head, hw.cqm_group_entry)
+               event->hw.cqm_rmid = rmid;
+
+       raw_spin_unlock_irq(&cache_lock);
+
+       return old_rmid;
+}
+
+/*
+ * If we fail to assign a new RMID for intel_cqm_rotation_rmid because
+ * cachelines are still tagged with RMIDs in limbo, we progressively
+ * increment the threshold until we find an RMID in limbo with <=
+ * __intel_cqm_threshold lines tagged. This is designed to mitigate the
+ * problem where cachelines tagged with an RMID are not steadily being
+ * evicted.
+ *
+ * On successful rotations we decrease the threshold back towards zero.
+ *
+ * __intel_cqm_max_threshold provides an upper bound on the threshold,
+ * and is measured in bytes because it's exposed to userland.
+ */
+static unsigned int __intel_cqm_threshold;
+static unsigned int __intel_cqm_max_threshold;
+
+/*
+ * Test whether an RMID has a zero occupancy value on this cpu.
+ */
+static void intel_cqm_stable(void *arg)
+{
+       struct cqm_rmid_entry *entry;
+
+       list_for_each_entry(entry, &cqm_rmid_limbo_lru, list) {
+               if (entry->state != RMID_AVAILABLE)
+                       break;
+
+               if (__rmid_read(entry->rmid) > __intel_cqm_threshold)
+                       entry->state = RMID_DIRTY;
+       }
+}
+
+/*
+ * If we have group events waiting for an RMID that don't conflict with
+ * events already running, assign @rmid.
+ */
+static bool intel_cqm_sched_in_event(u32 rmid)
+{
+       struct perf_event *leader, *event;
+
+       lockdep_assert_held(&cache_mutex);
+
+       leader = list_first_entry(&cache_groups, struct perf_event,
+                                 hw.cqm_groups_entry);
+       event = leader;
+
+       list_for_each_entry_continue(event, &cache_groups,
+                                    hw.cqm_groups_entry) {
+               if (__rmid_valid(event->hw.cqm_rmid))
+                       continue;
+
+               if (__conflict_event(event, leader))
+                       continue;
+
+               intel_cqm_xchg_rmid(event, rmid);
+               return true;
+       }
+
+       return false;
+}
+
+/*
+ * Initially use this constant for both the limbo queue time and the
+ * rotation timer interval, pmu::hrtimer_interval_ms.
+ *
+ * They don't need to be the same, but the two are related since if you
+ * rotate faster than you recycle RMIDs, you may run out of available
+ * RMIDs.
+ */
+#define RMID_DEFAULT_QUEUE_TIME 250    /* ms */
+
+static unsigned int __rmid_queue_time_ms = RMID_DEFAULT_QUEUE_TIME;
+
+/*
+ * intel_cqm_rmid_stabilize - move RMIDs from limbo to free list
+ * @nr_available: number of freeable RMIDs on the limbo list
+ *
+ * Quiescent state; wait for all 'freed' RMIDs to become unused, i.e. no
+ * cachelines are tagged with those RMIDs. After this we can reuse them
+ * and know that the current set of active RMIDs is stable.
+ *
+ * Return %true or %false depending on whether stabilization needs to be
+ * reattempted.
+ *
+ * If we return %true then @nr_available is updated to indicate the
+ * number of RMIDs on the limbo list that have been queued for the
+ * minimum queue time (RMID_AVAILABLE), but whose data occupancy values
+ * are above __intel_cqm_threshold.
+ */
+static bool intel_cqm_rmid_stabilize(unsigned int *available)
+{
+       struct cqm_rmid_entry *entry, *tmp;
+
+       lockdep_assert_held(&cache_mutex);
+
+       *available = 0;
+       list_for_each_entry(entry, &cqm_rmid_limbo_lru, list) {
+               unsigned long min_queue_time;
+               unsigned long now = jiffies;
+
+               /*
+                * We hold RMIDs placed into limbo for a minimum queue
+                * time. Before the minimum queue time has elapsed we do
+                * not recycle RMIDs.
+                *
+                * The reasoning is that until a sufficient time has
+                * passed since we stopped using an RMID, any RMID
+                * placed onto the limbo list will likely still have
+                * data tagged in the cache, which means we'll probably
+                * fail to recycle it anyway.
+                *
+                * We can save ourselves an expensive IPI by skipping
+                * any RMIDs that have not been queued for the minimum
+                * time.
+                */
+               min_queue_time = entry->queue_time +
+                       msecs_to_jiffies(__rmid_queue_time_ms);
+
+               if (time_after(min_queue_time, now))
+                       break;
+
+               entry->state = RMID_AVAILABLE;
+               (*available)++;
+       }
+
+       /*
+        * Fast return if none of the RMIDs on the limbo list have been
+        * sitting on the queue for the minimum queue time.
+        */
+       if (!*available)
+               return false;
+
+       /*
+        * Test whether an RMID is free for each package.
+        */
+       on_each_cpu_mask(&cqm_cpumask, intel_cqm_stable, NULL, true);
+
+       list_for_each_entry_safe(entry, tmp, &cqm_rmid_limbo_lru, list) {
+               /*
+                * Exhausted all RMIDs that have waited min queue time.
+                */
+               if (entry->state == RMID_YOUNG)
+                       break;
+
+               if (entry->state == RMID_DIRTY)
+                       continue;
+
+               list_del(&entry->list); /* remove from limbo */
+
+               /*
+                * The rotation RMID gets priority if it's
+                * currently invalid. In which case, skip adding
+                * the RMID to the the free lru.
+                */
+               if (!__rmid_valid(intel_cqm_rotation_rmid)) {
+                       intel_cqm_rotation_rmid = entry->rmid;
+                       continue;
+               }
+
+               /*
+                * If we have groups waiting for RMIDs, hand
+                * them one now provided they don't conflict.
+                */
+               if (intel_cqm_sched_in_event(entry->rmid))
+                       continue;
+
+               /*
+                * Otherwise place it onto the free list.
+                */
+               list_add_tail(&entry->list, &cqm_rmid_free_lru);
+       }
+
+
+       return __rmid_valid(intel_cqm_rotation_rmid);
+}
+
+/*
+ * Pick a victim group and move it to the tail of the group list.
+ * @next: The first group without an RMID
+ */
+static void __intel_cqm_pick_and_rotate(struct perf_event *next)
+{
+       struct perf_event *rotor;
+       u32 rmid;
+
+       lockdep_assert_held(&cache_mutex);
+
+       rotor = list_first_entry(&cache_groups, struct perf_event,
+                                hw.cqm_groups_entry);
+
+       /*
+        * The group at the front of the list should always have a valid
+        * RMID. If it doesn't then no groups have RMIDs assigned and we
+        * don't need to rotate the list.
+        */
+       if (next == rotor)
+               return;
+
+       rmid = intel_cqm_xchg_rmid(rotor, INVALID_RMID);
+       __put_rmid(rmid);
+
+       list_rotate_left(&cache_groups);
+}
+
+/*
+ * Deallocate the RMIDs from any events that conflict with @event, and
+ * place them on the back of the group list.
+ */
+static void intel_cqm_sched_out_conflicting_events(struct perf_event *event)
+{
+       struct perf_event *group, *g;
+       u32 rmid;
+
+       lockdep_assert_held(&cache_mutex);
+
+       list_for_each_entry_safe(group, g, &cache_groups, hw.cqm_groups_entry) {
+               if (group == event)
+                       continue;
+
+               rmid = group->hw.cqm_rmid;
+
+               /*
+                * Skip events that don't have a valid RMID.
+                */
+               if (!__rmid_valid(rmid))
+                       continue;
+
+               /*
+                * No conflict? No problem! Leave the event alone.
+                */
+               if (!__conflict_event(group, event))
+                       continue;
+
+               intel_cqm_xchg_rmid(group, INVALID_RMID);
+               __put_rmid(rmid);
+       }
+}
+
+/*
+ * Attempt to rotate the groups and assign new RMIDs.
+ *
+ * We rotate for two reasons,
+ *   1. To handle the scheduling of conflicting events
+ *   2. To recycle RMIDs
+ *
+ * Rotating RMIDs is complicated because the hardware doesn't give us
+ * any clues.
+ *
+ * There's problems with the hardware interface; when you change the
+ * task:RMID map cachelines retain their 'old' tags, giving a skewed
+ * picture. In order to work around this, we must always keep one free
+ * RMID - intel_cqm_rotation_rmid.
+ *
+ * Rotation works by taking away an RMID from a group (the old RMID),
+ * and assigning the free RMID to another group (the new RMID). We must
+ * then wait for the old RMID to not be used (no cachelines tagged).
+ * This ensure that all cachelines are tagged with 'active' RMIDs. At
+ * this point we can start reading values for the new RMID and treat the
+ * old RMID as the free RMID for the next rotation.
+ *
+ * Return %true or %false depending on whether we did any rotating.
+ */
+static bool __intel_cqm_rmid_rotate(void)
+{
+       struct perf_event *group, *start = NULL;
+       unsigned int threshold_limit;
+       unsigned int nr_needed = 0;
+       unsigned int nr_available;
+       bool rotated = false;
+
+       mutex_lock(&cache_mutex);
+
+again:
+       /*
+        * Fast path through this function if there are no groups and no
+        * RMIDs that need cleaning.
+        */
+       if (list_empty(&cache_groups) && list_empty(&cqm_rmid_limbo_lru))
+               goto out;
+
+       list_for_each_entry(group, &cache_groups, hw.cqm_groups_entry) {
+               if (!__rmid_valid(group->hw.cqm_rmid)) {
+                       if (!start)
+                               start = group;
+                       nr_needed++;
+               }
+       }
+
+       /*
+        * We have some event groups, but they all have RMIDs assigned
+        * and no RMIDs need cleaning.
+        */
+       if (!nr_needed && list_empty(&cqm_rmid_limbo_lru))
+               goto out;
+
+       if (!nr_needed)
+               goto stabilize;
+
+       /*
+        * We have more event groups without RMIDs than available RMIDs,
+        * or we have event groups that conflict with the ones currently
+        * scheduled.
+        *
+        * We force deallocate the rmid of the group at the head of
+        * cache_groups. The first event group without an RMID then gets
+        * assigned intel_cqm_rotation_rmid. This ensures we always make
+        * forward progress.
+        *
+        * Rotate the cache_groups list so the previous head is now the
+        * tail.
+        */
+       __intel_cqm_pick_and_rotate(start);
+
+       /*
+        * If the rotation is going to succeed, reduce the threshold so
+        * that we don't needlessly reuse dirty RMIDs.
+        */
+       if (__rmid_valid(intel_cqm_rotation_rmid)) {
+               intel_cqm_xchg_rmid(start, intel_cqm_rotation_rmid);
+               intel_cqm_rotation_rmid = __get_rmid();
+
+               intel_cqm_sched_out_conflicting_events(start);
+
+               if (__intel_cqm_threshold)
+                       __intel_cqm_threshold--;
+       }
+
+       rotated = true;
+
+stabilize:
+       /*
+        * We now need to stablize the RMID we freed above (if any) to
+        * ensure that the next time we rotate we have an RMID with zero
+        * occupancy value.
+        *
+        * Alternatively, if we didn't need to perform any rotation,
+        * we'll have a bunch of RMIDs in limbo that need stabilizing.
+        */
+       threshold_limit = __intel_cqm_max_threshold / cqm_l3_scale;
+
+       while (intel_cqm_rmid_stabilize(&nr_available) &&
+              __intel_cqm_threshold < threshold_limit) {
+               unsigned int steal_limit;
+
+               /*
+                * Don't spin if nobody is actively waiting for an RMID,
+                * the rotation worker will be kicked as soon as an
+                * event needs an RMID anyway.
+                */
+               if (!nr_needed)
+                       break;
+
+               /* Allow max 25% of RMIDs to be in limbo. */
+               steal_limit = (cqm_max_rmid + 1) / 4;
+
+               /*
+                * We failed to stabilize any RMIDs so our rotation
+                * logic is now stuck. In order to make forward progress
+                * we have a few options:
+                *
+                *   1. rotate ("steal") another RMID
+                *   2. increase the threshold
+                *   3. do nothing
+                *
+                * We do both of 1. and 2. until we hit the steal limit.
+                *
+                * The steal limit prevents all RMIDs ending up on the
+                * limbo list. This can happen if every RMID has a
+                * non-zero occupancy above threshold_limit, and the
+                * occupancy values aren't dropping fast enough.
+                *
+                * Note that there is prioritisation at work here - we'd
+                * rather increase the number of RMIDs on the limbo list
+                * than increase the threshold, because increasing the
+                * threshold skews the event data (because we reuse
+                * dirty RMIDs) - threshold bumps are a last resort.
+                */
+               if (nr_available < steal_limit)
+                       goto again;
+
+               __intel_cqm_threshold++;
+       }
+
+out:
+       mutex_unlock(&cache_mutex);
+       return rotated;
+}
+
+static void intel_cqm_rmid_rotate(struct work_struct *work);
+
+static DECLARE_DELAYED_WORK(intel_cqm_rmid_work, intel_cqm_rmid_rotate);
+
+static struct pmu intel_cqm_pmu;
+
+static void intel_cqm_rmid_rotate(struct work_struct *work)
+{
+       unsigned long delay;
+
+       __intel_cqm_rmid_rotate();
+
+       delay = msecs_to_jiffies(intel_cqm_pmu.hrtimer_interval_ms);
+       schedule_delayed_work(&intel_cqm_rmid_work, delay);
+}
+
+/*
+ * Find a group and setup RMID.
+ *
+ * If we're part of a group, we use the group's RMID.
+ */
+static void intel_cqm_setup_event(struct perf_event *event,
+                                 struct perf_event **group)
+{
+       struct perf_event *iter;
+       bool conflict = false;
+       u32 rmid;
+
+       list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) {
+               rmid = iter->hw.cqm_rmid;
+
+               if (__match_event(iter, event)) {
+                       /* All tasks in a group share an RMID */
+                       event->hw.cqm_rmid = rmid;
+                       *group = iter;
+                       return;
+               }
+
+               /*
+                * We only care about conflicts for events that are
+                * actually scheduled in (and hence have a valid RMID).
+                */
+               if (__conflict_event(iter, event) && __rmid_valid(rmid))
+                       conflict = true;
+       }
+
+       if (conflict)
+               rmid = INVALID_RMID;
+       else
+               rmid = __get_rmid();
+
+       event->hw.cqm_rmid = rmid;
+}
+
+static void intel_cqm_event_read(struct perf_event *event)
+{
+       unsigned long flags;
+       u32 rmid;
+       u64 val;
+
+       /*
+        * Task events are handled by intel_cqm_event_count().
+        */
+       if (event->cpu == -1)
+               return;
+
+       raw_spin_lock_irqsave(&cache_lock, flags);
+       rmid = event->hw.cqm_rmid;
+
+       if (!__rmid_valid(rmid))
+               goto out;
+
+       val = __rmid_read(rmid);
+
+       /*
+        * Ignore this reading on error states and do not update the value.
+        */
+       if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
+               goto out;
+
+       local64_set(&event->count, val);
+out:
+       raw_spin_unlock_irqrestore(&cache_lock, flags);
+}
+
+static void __intel_cqm_event_count(void *info)
+{
+       struct rmid_read *rr = info;
+       u64 val;
+
+       val = __rmid_read(rr->rmid);
+
+       if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
+               return;
+
+       atomic64_add(val, &rr->value);
+}
+
+static inline bool cqm_group_leader(struct perf_event *event)
+{
+       return !list_empty(&event->hw.cqm_groups_entry);
+}
+
+static u64 intel_cqm_event_count(struct perf_event *event)
+{
+       unsigned long flags;
+       struct rmid_read rr = {
+               .value = ATOMIC64_INIT(0),
+       };
+
+       /*
+        * We only need to worry about task events. System-wide events
+        * are handled like usual, i.e. entirely with
+        * intel_cqm_event_read().
+        */
+       if (event->cpu != -1)
+               return __perf_event_count(event);
+
+       /*
+        * Only the group leader gets to report values. This stops us
+        * reporting duplicate values to userspace, and gives us a clear
+        * rule for which task gets to report the values.
+        *
+        * Note that it is impossible to attribute these values to
+        * specific packages - we forfeit that ability when we create
+        * task events.
+        */
+       if (!cqm_group_leader(event))
+               return 0;
+
+       /*
+        * Getting up-to-date values requires an SMP IPI which is not
+        * possible if we're being called in interrupt context. Return
+        * the cached values instead.
+        */
+       if (unlikely(in_interrupt()))
+               goto out;
+
+       /*
+        * Notice that we don't perform the reading of an RMID
+        * atomically, because we can't hold a spin lock across the
+        * IPIs.
+        *
+        * Speculatively perform the read, since @event might be
+        * assigned a different (possibly invalid) RMID while we're
+        * busying performing the IPI calls. It's therefore necessary to
+        * check @event's RMID afterwards, and if it has changed,
+        * discard the result of the read.
+        */
+       rr.rmid = ACCESS_ONCE(event->hw.cqm_rmid);
+
+       if (!__rmid_valid(rr.rmid))
+               goto out;
+
+       on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count, &rr, 1);
+
+       raw_spin_lock_irqsave(&cache_lock, flags);
+       if (event->hw.cqm_rmid == rr.rmid)
+               local64_set(&event->count, atomic64_read(&rr.value));
+       raw_spin_unlock_irqrestore(&cache_lock, flags);
+out:
+       return __perf_event_count(event);
+}
+
+static void intel_cqm_event_start(struct perf_event *event, int mode)
+{
+       struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
+       u32 rmid = event->hw.cqm_rmid;
+
+       if (!(event->hw.cqm_state & PERF_HES_STOPPED))
+               return;
+
+       event->hw.cqm_state &= ~PERF_HES_STOPPED;
+
+       if (state->rmid_usecnt++) {
+               if (!WARN_ON_ONCE(state->rmid != rmid))
+                       return;
+       } else {
+               WARN_ON_ONCE(state->rmid);
+       }
+
+       state->rmid = rmid;
+       wrmsr(MSR_IA32_PQR_ASSOC, rmid, state->closid);
+}
+
+static void intel_cqm_event_stop(struct perf_event *event, int mode)
+{
+       struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
+
+       if (event->hw.cqm_state & PERF_HES_STOPPED)
+               return;
+
+       event->hw.cqm_state |= PERF_HES_STOPPED;
+
+       intel_cqm_event_read(event);
+
+       if (!--state->rmid_usecnt) {
+               state->rmid = 0;
+               wrmsr(MSR_IA32_PQR_ASSOC, 0, state->closid);
+       } else {
+               WARN_ON_ONCE(!state->rmid);
+       }
+}
+
+static int intel_cqm_event_add(struct perf_event *event, int mode)
+{
+       unsigned long flags;
+       u32 rmid;
+
+       raw_spin_lock_irqsave(&cache_lock, flags);
+
+       event->hw.cqm_state = PERF_HES_STOPPED;
+       rmid = event->hw.cqm_rmid;
+
+       if (__rmid_valid(rmid) && (mode & PERF_EF_START))
+               intel_cqm_event_start(event, mode);
+
+       raw_spin_unlock_irqrestore(&cache_lock, flags);
+
+       return 0;
+}
+
+static void intel_cqm_event_destroy(struct perf_event *event)
+{
+       struct perf_event *group_other = NULL;
+
+       mutex_lock(&cache_mutex);
+
+       /*
+        * If there's another event in this group...
+        */
+       if (!list_empty(&event->hw.cqm_group_entry)) {
+               group_other = list_first_entry(&event->hw.cqm_group_entry,
+                                              struct perf_event,
+                                              hw.cqm_group_entry);
+               list_del(&event->hw.cqm_group_entry);
+       }
+
+       /*
+        * And we're the group leader..
+        */
+       if (cqm_group_leader(event)) {
+               /*
+                * If there was a group_other, make that leader, otherwise
+                * destroy the group and return the RMID.
+                */
+               if (group_other) {
+                       list_replace(&event->hw.cqm_groups_entry,
+                                    &group_other->hw.cqm_groups_entry);
+               } else {
+                       u32 rmid = event->hw.cqm_rmid;
+
+                       if (__rmid_valid(rmid))
+                               __put_rmid(rmid);
+                       list_del(&event->hw.cqm_groups_entry);
+               }
+       }
+
+       mutex_unlock(&cache_mutex);
+}
+
+static int intel_cqm_event_init(struct perf_event *event)
+{
+       struct perf_event *group = NULL;
+       bool rotate = false;
+
+       if (event->attr.type != intel_cqm_pmu.type)
+               return -ENOENT;
+
+       if (event->attr.config & ~QOS_EVENT_MASK)
+               return -EINVAL;
+
+       /* unsupported modes and filters */
+       if (event->attr.exclude_user   ||
+           event->attr.exclude_kernel ||
+           event->attr.exclude_hv     ||
+           event->attr.exclude_idle   ||
+           event->attr.exclude_host   ||
+           event->attr.exclude_guest  ||
+           event->attr.sample_period) /* no sampling */
+               return -EINVAL;
+
+       INIT_LIST_HEAD(&event->hw.cqm_group_entry);
+       INIT_LIST_HEAD(&event->hw.cqm_groups_entry);
+
+       event->destroy = intel_cqm_event_destroy;
+
+       mutex_lock(&cache_mutex);
+
+       /* Will also set rmid */
+       intel_cqm_setup_event(event, &group);
+
+       if (group) {
+               list_add_tail(&event->hw.cqm_group_entry,
+                             &group->hw.cqm_group_entry);
+       } else {
+               list_add_tail(&event->hw.cqm_groups_entry,
+                             &cache_groups);
+
+               /*
+                * All RMIDs are either in use or have recently been
+                * used. Kick the rotation worker to clean/free some.
+                *
+                * We only do this for the group leader, rather than for
+                * every event in a group to save on needless work.
+                */
+               if (!__rmid_valid(event->hw.cqm_rmid))
+                       rotate = true;
+       }
+
+       mutex_unlock(&cache_mutex);
+
+       if (rotate)
+               schedule_delayed_work(&intel_cqm_rmid_work, 0);
+
+       return 0;
+}
+
+EVENT_ATTR_STR(llc_occupancy, intel_cqm_llc, "event=0x01");
+EVENT_ATTR_STR(llc_occupancy.per-pkg, intel_cqm_llc_pkg, "1");
+EVENT_ATTR_STR(llc_occupancy.unit, intel_cqm_llc_unit, "Bytes");
+EVENT_ATTR_STR(llc_occupancy.scale, intel_cqm_llc_scale, NULL);
+EVENT_ATTR_STR(llc_occupancy.snapshot, intel_cqm_llc_snapshot, "1");
+
+static struct attribute *intel_cqm_events_attr[] = {
+       EVENT_PTR(intel_cqm_llc),
+       EVENT_PTR(intel_cqm_llc_pkg),
+       EVENT_PTR(intel_cqm_llc_unit),
+       EVENT_PTR(intel_cqm_llc_scale),
+       EVENT_PTR(intel_cqm_llc_snapshot),
+       NULL,
+};
+
+static struct attribute_group intel_cqm_events_group = {
+       .name = "events",
+       .attrs = intel_cqm_events_attr,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-7");
+static struct attribute *intel_cqm_formats_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group intel_cqm_format_group = {
+       .name = "format",
+       .attrs = intel_cqm_formats_attr,
+};
+
+static ssize_t
+max_recycle_threshold_show(struct device *dev, struct device_attribute *attr,
+                          char *page)
+{
+       ssize_t rv;
+
+       mutex_lock(&cache_mutex);
+       rv = snprintf(page, PAGE_SIZE-1, "%u\n", __intel_cqm_max_threshold);
+       mutex_unlock(&cache_mutex);
+
+       return rv;
+}
+
+static ssize_t
+max_recycle_threshold_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       unsigned int bytes, cachelines;
+       int ret;
+
+       ret = kstrtouint(buf, 0, &bytes);
+       if (ret)
+               return ret;
+
+       mutex_lock(&cache_mutex);
+
+       __intel_cqm_max_threshold = bytes;
+       cachelines = bytes / cqm_l3_scale;
+
+       /*
+        * The new maximum takes effect immediately.
+        */
+       if (__intel_cqm_threshold > cachelines)
+               __intel_cqm_threshold = cachelines;
+
+       mutex_unlock(&cache_mutex);
+
+       return count;
+}
+
+static DEVICE_ATTR_RW(max_recycle_threshold);
+
+static struct attribute *intel_cqm_attrs[] = {
+       &dev_attr_max_recycle_threshold.attr,
+       NULL,
+};
+
+static const struct attribute_group intel_cqm_group = {
+       .attrs = intel_cqm_attrs,
+};
+
+static const struct attribute_group *intel_cqm_attr_groups[] = {
+       &intel_cqm_events_group,
+       &intel_cqm_format_group,
+       &intel_cqm_group,
+       NULL,
+};
+
+static struct pmu intel_cqm_pmu = {
+       .hrtimer_interval_ms = RMID_DEFAULT_QUEUE_TIME,
+       .attr_groups         = intel_cqm_attr_groups,
+       .task_ctx_nr         = perf_sw_context,
+       .event_init          = intel_cqm_event_init,
+       .add                 = intel_cqm_event_add,
+       .del                 = intel_cqm_event_stop,
+       .start               = intel_cqm_event_start,
+       .stop                = intel_cqm_event_stop,
+       .read                = intel_cqm_event_read,
+       .count               = intel_cqm_event_count,
+};
+
+static inline void cqm_pick_event_reader(int cpu)
+{
+       int reader;
+
+       /* First online cpu in package becomes the reader */
+       reader = cpumask_any_and(&cqm_cpumask, topology_core_cpumask(cpu));
+       if (reader >= nr_cpu_ids)
+               cpumask_set_cpu(cpu, &cqm_cpumask);
+}
+
+static void intel_cqm_cpu_starting(unsigned int cpu)
+{
+       struct intel_pqr_state *state = &per_cpu(pqr_state, cpu);
+       struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+       state->rmid = 0;
+       state->closid = 0;
+       state->rmid_usecnt = 0;
+
+       WARN_ON(c->x86_cache_max_rmid != cqm_max_rmid);
+       WARN_ON(c->x86_cache_occ_scale != cqm_l3_scale);
+}
+
+static void intel_cqm_cpu_exit(unsigned int cpu)
+{
+       int target;
+
+       /* Is @cpu the current cqm reader for this package ? */
+       if (!cpumask_test_and_clear_cpu(cpu, &cqm_cpumask))
+               return;
+
+       /* Find another online reader in this package */
+       target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+
+       if (target < nr_cpu_ids)
+               cpumask_set_cpu(target, &cqm_cpumask);
+}
+
+static int intel_cqm_cpu_notifier(struct notifier_block *nb,
+                                 unsigned long action, void *hcpu)
+{
+       unsigned int cpu  = (unsigned long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DOWN_PREPARE:
+               intel_cqm_cpu_exit(cpu);
+               break;
+       case CPU_STARTING:
+               intel_cqm_cpu_starting(cpu);
+               cqm_pick_event_reader(cpu);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static const struct x86_cpu_id intel_cqm_match[] = {
+       { .vendor = X86_VENDOR_INTEL, .feature = X86_FEATURE_CQM_OCCUP_LLC },
+       {}
+};
+
+static int __init intel_cqm_init(void)
+{
+       char *str, scale[20];
+       int i, cpu, ret;
+
+       if (!x86_match_cpu(intel_cqm_match))
+               return -ENODEV;
+
+       cqm_l3_scale = boot_cpu_data.x86_cache_occ_scale;
+
+       /*
+        * It's possible that not all resources support the same number
+        * of RMIDs. Instead of making scheduling much more complicated
+        * (where we have to match a task's RMID to a cpu that supports
+        * that many RMIDs) just find the minimum RMIDs supported across
+        * all cpus.
+        *
+        * Also, check that the scales match on all cpus.
+        */
+       cpu_notifier_register_begin();
+
+       for_each_online_cpu(cpu) {
+               struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+               if (c->x86_cache_max_rmid < cqm_max_rmid)
+                       cqm_max_rmid = c->x86_cache_max_rmid;
+
+               if (c->x86_cache_occ_scale != cqm_l3_scale) {
+                       pr_err("Multiple LLC scale values, disabling\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+       }
+
+       /*
+        * A reasonable upper limit on the max threshold is the number
+        * of lines tagged per RMID if all RMIDs have the same number of
+        * lines tagged in the LLC.
+        *
+        * For a 35MB LLC and 56 RMIDs, this is ~1.8% of the LLC.
+        */
+       __intel_cqm_max_threshold =
+               boot_cpu_data.x86_cache_size * 1024 / (cqm_max_rmid + 1);
+
+       snprintf(scale, sizeof(scale), "%u", cqm_l3_scale);
+       str = kstrdup(scale, GFP_KERNEL);
+       if (!str) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       event_attr_intel_cqm_llc_scale.event_str = str;
+
+       ret = intel_cqm_setup_rmid_cache();
+       if (ret)
+               goto out;
+
+       for_each_online_cpu(i) {
+               intel_cqm_cpu_starting(i);
+               cqm_pick_event_reader(i);
+       }
+
+       __perf_cpu_notifier(intel_cqm_cpu_notifier);
+
+       ret = perf_pmu_register(&intel_cqm_pmu, "intel_cqm", -1);
+       if (ret)
+               pr_err("Intel CQM perf registration failed: %d\n", ret);
+       else
+               pr_info("Intel CQM monitoring enabled\n");
+
+out:
+       cpu_notifier_register_done();
+
+       return ret;
+}
+device_initcall(intel_cqm_init);
diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c
new file mode 100644 (file)
index 0000000..7946c42
--- /dev/null
@@ -0,0 +1,694 @@
+/*
+ * perf_event_intel_cstate.c: support cstate residency counters
+ *
+ * Copyright (C) 2015, Intel Corp.
+ * Author: Kan Liang (kan.liang@intel.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ */
+
+/*
+ * This file export cstate related free running (read-only) counters
+ * for perf. These counters may be use simultaneously by other tools,
+ * such as turbostat. However, it still make sense to implement them
+ * in perf. Because we can conveniently collect them together with
+ * other events, and allow to use them from tools without special MSR
+ * access code.
+ *
+ * The events only support system-wide mode counting. There is no
+ * sampling support because it is not supported by the hardware.
+ *
+ * According to counters' scope and category, two PMUs are registered
+ * with the perf_event core subsystem.
+ *  - 'cstate_core': The counter is available for each physical core.
+ *    The counters include CORE_C*_RESIDENCY.
+ *  - 'cstate_pkg': The counter is available for each physical package.
+ *    The counters include PKG_C*_RESIDENCY.
+ *
+ * All of these counters are specified in the Intel® 64 and IA-32
+ * Architectures Software Developer.s Manual Vol3b.
+ *
+ * Model specific counters:
+ *     MSR_CORE_C1_RES: CORE C1 Residency Counter
+ *                      perf code: 0x00
+ *                      Available model: SLM,AMT
+ *                      Scope: Core (each processor core has a MSR)
+ *     MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
+ *                            perf code: 0x01
+ *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Scope: Core
+ *     MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter
+ *                            perf code: 0x02
+ *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Scope: Core
+ *     MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
+ *                            perf code: 0x03
+ *                            Available model: SNB,IVB,HSW,BDW,SKL
+ *                            Scope: Core
+ *     MSR_PKG_C2_RESIDENCY:  Package C2 Residency Counter.
+ *                            perf code: 0x00
+ *                            Available model: SNB,IVB,HSW,BDW,SKL
+ *                            Scope: Package (physical package)
+ *     MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
+ *                            perf code: 0x01
+ *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Scope: Package (physical package)
+ *     MSR_PKG_C6_RESIDENCY:  Package C6 Residency Counter.
+ *                            perf code: 0x02
+ *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Scope: Package (physical package)
+ *     MSR_PKG_C7_RESIDENCY:  Package C7 Residency Counter.
+ *                            perf code: 0x03
+ *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL
+ *                            Scope: Package (physical package)
+ *     MSR_PKG_C8_RESIDENCY:  Package C8 Residency Counter.
+ *                            perf code: 0x04
+ *                            Available model: HSW ULT only
+ *                            Scope: Package (physical package)
+ *     MSR_PKG_C9_RESIDENCY:  Package C9 Residency Counter.
+ *                            perf code: 0x05
+ *                            Available model: HSW ULT only
+ *                            Scope: Package (physical package)
+ *     MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
+ *                            perf code: 0x06
+ *                            Available model: HSW ULT only
+ *                            Scope: Package (physical package)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/perf_event.h>
+#include <asm/cpu_device_id.h>
+#include "../perf_event.h"
+
+#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format)                \
+static ssize_t __cstate_##_var##_show(struct kobject *kobj,    \
+                               struct kobj_attribute *attr,    \
+                               char *page)                     \
+{                                                              \
+       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);             \
+       return sprintf(page, _format "\n");                     \
+}                                                              \
+static struct kobj_attribute format_attr_##_var =              \
+       __ATTR(_name, 0444, __cstate_##_var##_show, NULL)
+
+static ssize_t cstate_get_attr_cpumask(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf);
+
+struct perf_cstate_msr {
+       u64     msr;
+       struct  perf_pmu_events_attr *attr;
+       bool    (*test)(int idx);
+};
+
+
+/* cstate_core PMU */
+
+static struct pmu cstate_core_pmu;
+static bool has_cstate_core;
+
+enum perf_cstate_core_id {
+       /*
+        * cstate_core events
+        */
+       PERF_CSTATE_CORE_C1_RES = 0,
+       PERF_CSTATE_CORE_C3_RES,
+       PERF_CSTATE_CORE_C6_RES,
+       PERF_CSTATE_CORE_C7_RES,
+
+       PERF_CSTATE_CORE_EVENT_MAX,
+};
+
+bool test_core(int idx)
+{
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
+           boot_cpu_data.x86 != 6)
+               return false;
+
+       switch (boot_cpu_data.x86_model) {
+       case 30: /* 45nm Nehalem    */
+       case 26: /* 45nm Nehalem-EP */
+       case 46: /* 45nm Nehalem-EX */
+
+       case 37: /* 32nm Westmere    */
+       case 44: /* 32nm Westmere-EP */
+       case 47: /* 32nm Westmere-EX */
+               if (idx == PERF_CSTATE_CORE_C3_RES ||
+                   idx == PERF_CSTATE_CORE_C6_RES)
+                       return true;
+               break;
+       case 42: /* 32nm SandyBridge         */
+       case 45: /* 32nm SandyBridge-E/EN/EP */
+
+       case 58: /* 22nm IvyBridge       */
+       case 62: /* 22nm IvyBridge-EP/EX */
+
+       case 60: /* 22nm Haswell Core */
+       case 63: /* 22nm Haswell Server */
+       case 69: /* 22nm Haswell ULT */
+       case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
+
+       case 61: /* 14nm Broadwell Core-M */
+       case 86: /* 14nm Broadwell Xeon D */
+       case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
+       case 79: /* 14nm Broadwell Server */
+
+       case 78: /* 14nm Skylake Mobile */
+       case 94: /* 14nm Skylake Desktop */
+               if (idx == PERF_CSTATE_CORE_C3_RES ||
+                   idx == PERF_CSTATE_CORE_C6_RES ||
+                   idx == PERF_CSTATE_CORE_C7_RES)
+                       return true;
+               break;
+       case 55: /* 22nm Atom "Silvermont"                */
+       case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
+       case 76: /* 14nm Atom "Airmont"                   */
+               if (idx == PERF_CSTATE_CORE_C1_RES ||
+                   idx == PERF_CSTATE_CORE_C6_RES)
+                       return true;
+               break;
+       }
+
+       return false;
+}
+
+PMU_EVENT_ATTR_STRING(c1-residency, evattr_cstate_core_c1, "event=0x00");
+PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_core_c3, "event=0x01");
+PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_core_c6, "event=0x02");
+PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_core_c7, "event=0x03");
+
+static struct perf_cstate_msr core_msr[] = {
+       [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES,          &evattr_cstate_core_c1, test_core, },
+       [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY,    &evattr_cstate_core_c3, test_core, },
+       [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY,    &evattr_cstate_core_c6, test_core, },
+       [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY,    &evattr_cstate_core_c7, test_core, },
+};
+
+static struct attribute *core_events_attrs[PERF_CSTATE_CORE_EVENT_MAX + 1] = {
+       NULL,
+};
+
+static struct attribute_group core_events_attr_group = {
+       .name = "events",
+       .attrs = core_events_attrs,
+};
+
+DEFINE_CSTATE_FORMAT_ATTR(core_event, event, "config:0-63");
+static struct attribute *core_format_attrs[] = {
+       &format_attr_core_event.attr,
+       NULL,
+};
+
+static struct attribute_group core_format_attr_group = {
+       .name = "format",
+       .attrs = core_format_attrs,
+};
+
+static cpumask_t cstate_core_cpu_mask;
+static DEVICE_ATTR(cpumask, S_IRUGO, cstate_get_attr_cpumask, NULL);
+
+static struct attribute *cstate_cpumask_attrs[] = {
+       &dev_attr_cpumask.attr,
+       NULL,
+};
+
+static struct attribute_group cpumask_attr_group = {
+       .attrs = cstate_cpumask_attrs,
+};
+
+static const struct attribute_group *core_attr_groups[] = {
+       &core_events_attr_group,
+       &core_format_attr_group,
+       &cpumask_attr_group,
+       NULL,
+};
+
+/* cstate_core PMU end */
+
+
+/* cstate_pkg PMU */
+
+static struct pmu cstate_pkg_pmu;
+static bool has_cstate_pkg;
+
+enum perf_cstate_pkg_id {
+       /*
+        * cstate_pkg events
+        */
+       PERF_CSTATE_PKG_C2_RES = 0,
+       PERF_CSTATE_PKG_C3_RES,
+       PERF_CSTATE_PKG_C6_RES,
+       PERF_CSTATE_PKG_C7_RES,
+       PERF_CSTATE_PKG_C8_RES,
+       PERF_CSTATE_PKG_C9_RES,
+       PERF_CSTATE_PKG_C10_RES,
+
+       PERF_CSTATE_PKG_EVENT_MAX,
+};
+
+bool test_pkg(int idx)
+{
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
+           boot_cpu_data.x86 != 6)
+               return false;
+
+       switch (boot_cpu_data.x86_model) {
+       case 30: /* 45nm Nehalem    */
+       case 26: /* 45nm Nehalem-EP */
+       case 46: /* 45nm Nehalem-EX */
+
+       case 37: /* 32nm Westmere    */
+       case 44: /* 32nm Westmere-EP */
+       case 47: /* 32nm Westmere-EX */
+               if (idx == PERF_CSTATE_CORE_C3_RES ||
+                   idx == PERF_CSTATE_CORE_C6_RES ||
+                   idx == PERF_CSTATE_CORE_C7_RES)
+                       return true;
+               break;
+       case 42: /* 32nm SandyBridge         */
+       case 45: /* 32nm SandyBridge-E/EN/EP */
+
+       case 58: /* 22nm IvyBridge       */
+       case 62: /* 22nm IvyBridge-EP/EX */
+
+       case 60: /* 22nm Haswell Core */
+       case 63: /* 22nm Haswell Server */
+       case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
+
+       case 61: /* 14nm Broadwell Core-M */
+       case 86: /* 14nm Broadwell Xeon D */
+       case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
+       case 79: /* 14nm Broadwell Server */
+
+       case 78: /* 14nm Skylake Mobile */
+       case 94: /* 14nm Skylake Desktop */
+               if (idx == PERF_CSTATE_PKG_C2_RES ||
+                   idx == PERF_CSTATE_PKG_C3_RES ||
+                   idx == PERF_CSTATE_PKG_C6_RES ||
+                   idx == PERF_CSTATE_PKG_C7_RES)
+                       return true;
+               break;
+       case 55: /* 22nm Atom "Silvermont"                */
+       case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
+       case 76: /* 14nm Atom "Airmont"                   */
+               if (idx == PERF_CSTATE_CORE_C6_RES)
+                       return true;
+               break;
+       case 69: /* 22nm Haswell ULT */
+               if (idx == PERF_CSTATE_PKG_C2_RES ||
+                   idx == PERF_CSTATE_PKG_C3_RES ||
+                   idx == PERF_CSTATE_PKG_C6_RES ||
+                   idx == PERF_CSTATE_PKG_C7_RES ||
+                   idx == PERF_CSTATE_PKG_C8_RES ||
+                   idx == PERF_CSTATE_PKG_C9_RES ||
+                   idx == PERF_CSTATE_PKG_C10_RES)
+                       return true;
+               break;
+       }
+
+       return false;
+}
+
+PMU_EVENT_ATTR_STRING(c2-residency, evattr_cstate_pkg_c2, "event=0x00");
+PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_pkg_c3, "event=0x01");
+PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_pkg_c6, "event=0x02");
+PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_pkg_c7, "event=0x03");
+PMU_EVENT_ATTR_STRING(c8-residency, evattr_cstate_pkg_c8, "event=0x04");
+PMU_EVENT_ATTR_STRING(c9-residency, evattr_cstate_pkg_c9, "event=0x05");
+PMU_EVENT_ATTR_STRING(c10-residency, evattr_cstate_pkg_c10, "event=0x06");
+
+static struct perf_cstate_msr pkg_msr[] = {
+       [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY,      &evattr_cstate_pkg_c2,  test_pkg, },
+       [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY,      &evattr_cstate_pkg_c3,  test_pkg, },
+       [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY,      &evattr_cstate_pkg_c6,  test_pkg, },
+       [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY,      &evattr_cstate_pkg_c7,  test_pkg, },
+       [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY,      &evattr_cstate_pkg_c8,  test_pkg, },
+       [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY,      &evattr_cstate_pkg_c9,  test_pkg, },
+       [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY,    &evattr_cstate_pkg_c10, test_pkg, },
+};
+
+static struct attribute *pkg_events_attrs[PERF_CSTATE_PKG_EVENT_MAX + 1] = {
+       NULL,
+};
+
+static struct attribute_group pkg_events_attr_group = {
+       .name = "events",
+       .attrs = pkg_events_attrs,
+};
+
+DEFINE_CSTATE_FORMAT_ATTR(pkg_event, event, "config:0-63");
+static struct attribute *pkg_format_attrs[] = {
+       &format_attr_pkg_event.attr,
+       NULL,
+};
+static struct attribute_group pkg_format_attr_group = {
+       .name = "format",
+       .attrs = pkg_format_attrs,
+};
+
+static cpumask_t cstate_pkg_cpu_mask;
+
+static const struct attribute_group *pkg_attr_groups[] = {
+       &pkg_events_attr_group,
+       &pkg_format_attr_group,
+       &cpumask_attr_group,
+       NULL,
+};
+
+/* cstate_pkg PMU end*/
+
+static ssize_t cstate_get_attr_cpumask(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       struct pmu *pmu = dev_get_drvdata(dev);
+
+       if (pmu == &cstate_core_pmu)
+               return cpumap_print_to_pagebuf(true, buf, &cstate_core_cpu_mask);
+       else if (pmu == &cstate_pkg_pmu)
+               return cpumap_print_to_pagebuf(true, buf, &cstate_pkg_cpu_mask);
+       else
+               return 0;
+}
+
+static int cstate_pmu_event_init(struct perf_event *event)
+{
+       u64 cfg = event->attr.config;
+       int ret = 0;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       /* unsupported modes and filters */
+       if (event->attr.exclude_user   ||
+           event->attr.exclude_kernel ||
+           event->attr.exclude_hv     ||
+           event->attr.exclude_idle   ||
+           event->attr.exclude_host   ||
+           event->attr.exclude_guest  ||
+           event->attr.sample_period) /* no sampling */
+               return -EINVAL;
+
+       if (event->pmu == &cstate_core_pmu) {
+               if (cfg >= PERF_CSTATE_CORE_EVENT_MAX)
+                       return -EINVAL;
+               if (!core_msr[cfg].attr)
+                       return -EINVAL;
+               event->hw.event_base = core_msr[cfg].msr;
+       } else if (event->pmu == &cstate_pkg_pmu) {
+               if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)
+                       return -EINVAL;
+               if (!pkg_msr[cfg].attr)
+                       return -EINVAL;
+               event->hw.event_base = pkg_msr[cfg].msr;
+       } else
+               return -ENOENT;
+
+       /* must be done before validate_group */
+       event->hw.config = cfg;
+       event->hw.idx = -1;
+
+       return ret;
+}
+
+static inline u64 cstate_pmu_read_counter(struct perf_event *event)
+{
+       u64 val;
+
+       rdmsrl(event->hw.event_base, val);
+       return val;
+}
+
+static void cstate_pmu_event_update(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 prev_raw_count, new_raw_count;
+
+again:
+       prev_raw_count = local64_read(&hwc->prev_count);
+       new_raw_count = cstate_pmu_read_counter(event);
+
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                           new_raw_count) != prev_raw_count)
+               goto again;
+
+       local64_add(new_raw_count - prev_raw_count, &event->count);
+}
+
+static void cstate_pmu_event_start(struct perf_event *event, int mode)
+{
+       local64_set(&event->hw.prev_count, cstate_pmu_read_counter(event));
+}
+
+static void cstate_pmu_event_stop(struct perf_event *event, int mode)
+{
+       cstate_pmu_event_update(event);
+}
+
+static void cstate_pmu_event_del(struct perf_event *event, int mode)
+{
+       cstate_pmu_event_stop(event, PERF_EF_UPDATE);
+}
+
+static int cstate_pmu_event_add(struct perf_event *event, int mode)
+{
+       if (mode & PERF_EF_START)
+               cstate_pmu_event_start(event, mode);
+
+       return 0;
+}
+
+static void cstate_cpu_exit(int cpu)
+{
+       int i, id, target;
+
+       /* cpu exit for cstate core */
+       if (has_cstate_core) {
+               id = topology_core_id(cpu);
+               target = -1;
+
+               for_each_online_cpu(i) {
+                       if (i == cpu)
+                               continue;
+                       if (id == topology_core_id(i)) {
+                               target = i;
+                               break;
+                       }
+               }
+               if (cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask) && target >= 0)
+                       cpumask_set_cpu(target, &cstate_core_cpu_mask);
+               WARN_ON(cpumask_empty(&cstate_core_cpu_mask));
+               if (target >= 0)
+                       perf_pmu_migrate_context(&cstate_core_pmu, cpu, target);
+       }
+
+       /* cpu exit for cstate pkg */
+       if (has_cstate_pkg) {
+               id = topology_physical_package_id(cpu);
+               target = -1;
+
+               for_each_online_cpu(i) {
+                       if (i == cpu)
+                               continue;
+                       if (id == topology_physical_package_id(i)) {
+                               target = i;
+                               break;
+                       }
+               }
+               if (cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask) && target >= 0)
+                       cpumask_set_cpu(target, &cstate_pkg_cpu_mask);
+               WARN_ON(cpumask_empty(&cstate_pkg_cpu_mask));
+               if (target >= 0)
+                       perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target);
+       }
+}
+
+static void cstate_cpu_init(int cpu)
+{
+       int i, id;
+
+       /* cpu init for cstate core */
+       if (has_cstate_core) {
+               id = topology_core_id(cpu);
+               for_each_cpu(i, &cstate_core_cpu_mask) {
+                       if (id == topology_core_id(i))
+                               break;
+               }
+               if (i >= nr_cpu_ids)
+                       cpumask_set_cpu(cpu, &cstate_core_cpu_mask);
+       }
+
+       /* cpu init for cstate pkg */
+       if (has_cstate_pkg) {
+               id = topology_physical_package_id(cpu);
+               for_each_cpu(i, &cstate_pkg_cpu_mask) {
+                       if (id == topology_physical_package_id(i))
+                               break;
+               }
+               if (i >= nr_cpu_ids)
+                       cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
+       }
+}
+
+static int cstate_cpu_notifier(struct notifier_block *self,
+                                 unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               break;
+       case CPU_STARTING:
+               cstate_cpu_init(cpu);
+               break;
+       case CPU_UP_CANCELED:
+       case CPU_DYING:
+               break;
+       case CPU_ONLINE:
+       case CPU_DEAD:
+               break;
+       case CPU_DOWN_PREPARE:
+               cstate_cpu_exit(cpu);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+/*
+ * Probe the cstate events and insert the available one into sysfs attrs
+ * Return false if there is no available events.
+ */
+static bool cstate_probe_msr(struct perf_cstate_msr *msr,
+                            struct attribute   **events_attrs,
+                            int max_event_nr)
+{
+       int i, j = 0;
+       u64 val;
+
+       /* Probe the cstate events. */
+       for (i = 0; i < max_event_nr; i++) {
+               if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
+                       msr[i].attr = NULL;
+       }
+
+       /* List remaining events in the sysfs attrs. */
+       for (i = 0; i < max_event_nr; i++) {
+               if (msr[i].attr)
+                       events_attrs[j++] = &msr[i].attr->attr.attr;
+       }
+       events_attrs[j] = NULL;
+
+       return (j > 0) ? true : false;
+}
+
+static int __init cstate_init(void)
+{
+       /* SLM has different MSR for PKG C6 */
+       switch (boot_cpu_data.x86_model) {
+       case 55:
+       case 76:
+       case 77:
+               pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
+       }
+
+       if (cstate_probe_msr(core_msr, core_events_attrs, PERF_CSTATE_CORE_EVENT_MAX))
+               has_cstate_core = true;
+
+       if (cstate_probe_msr(pkg_msr, pkg_events_attrs, PERF_CSTATE_PKG_EVENT_MAX))
+               has_cstate_pkg = true;
+
+       return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV;
+}
+
+static void __init cstate_cpumask_init(void)
+{
+       int cpu;
+
+       cpu_notifier_register_begin();
+
+       for_each_online_cpu(cpu)
+               cstate_cpu_init(cpu);
+
+       __perf_cpu_notifier(cstate_cpu_notifier);
+
+       cpu_notifier_register_done();
+}
+
+static struct pmu cstate_core_pmu = {
+       .attr_groups    = core_attr_groups,
+       .name           = "cstate_core",
+       .task_ctx_nr    = perf_invalid_context,
+       .event_init     = cstate_pmu_event_init,
+       .add            = cstate_pmu_event_add, /* must have */
+       .del            = cstate_pmu_event_del, /* must have */
+       .start          = cstate_pmu_event_start,
+       .stop           = cstate_pmu_event_stop,
+       .read           = cstate_pmu_event_update,
+       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
+};
+
+static struct pmu cstate_pkg_pmu = {
+       .attr_groups    = pkg_attr_groups,
+       .name           = "cstate_pkg",
+       .task_ctx_nr    = perf_invalid_context,
+       .event_init     = cstate_pmu_event_init,
+       .add            = cstate_pmu_event_add, /* must have */
+       .del            = cstate_pmu_event_del, /* must have */
+       .start          = cstate_pmu_event_start,
+       .stop           = cstate_pmu_event_stop,
+       .read           = cstate_pmu_event_update,
+       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
+};
+
+static void __init cstate_pmus_register(void)
+{
+       int err;
+
+       if (has_cstate_core) {
+               err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1);
+               if (WARN_ON(err))
+                       pr_info("Failed to register PMU %s error %d\n",
+                               cstate_core_pmu.name, err);
+       }
+
+       if (has_cstate_pkg) {
+               err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1);
+               if (WARN_ON(err))
+                       pr_info("Failed to register PMU %s error %d\n",
+                               cstate_pkg_pmu.name, err);
+       }
+}
+
+static int __init cstate_pmu_init(void)
+{
+       int err;
+
+       if (cpu_has_hypervisor)
+               return -ENODEV;
+
+       err = cstate_init();
+       if (err)
+               return err;
+
+       cstate_cpumask_init();
+
+       cstate_pmus_register();
+
+       return 0;
+}
+
+device_initcall(cstate_pmu_init);
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
new file mode 100644 (file)
index 0000000..ce7211a
--- /dev/null
@@ -0,0 +1,1410 @@
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+
+#include <asm/perf_event.h>
+#include <asm/insn.h>
+
+#include "../perf_event.h"
+
+/* The size of a BTS record in bytes: */
+#define BTS_RECORD_SIZE                24
+
+#define BTS_BUFFER_SIZE                (PAGE_SIZE << 4)
+#define PEBS_BUFFER_SIZE       (PAGE_SIZE << 4)
+#define PEBS_FIXUP_SIZE                PAGE_SIZE
+
+/*
+ * pebs_record_32 for p4 and core not supported
+
+struct pebs_record_32 {
+       u32 flags, ip;
+       u32 ax, bc, cx, dx;
+       u32 si, di, bp, sp;
+};
+
+ */
+
+union intel_x86_pebs_dse {
+       u64 val;
+       struct {
+               unsigned int ld_dse:4;
+               unsigned int ld_stlb_miss:1;
+               unsigned int ld_locked:1;
+               unsigned int ld_reserved:26;
+       };
+       struct {
+               unsigned int st_l1d_hit:1;
+               unsigned int st_reserved1:3;
+               unsigned int st_stlb_miss:1;
+               unsigned int st_locked:1;
+               unsigned int st_reserved2:26;
+       };
+};
+
+
+/*
+ * Map PEBS Load Latency Data Source encodings to generic
+ * memory data source information
+ */
+#define P(a, b) PERF_MEM_S(a, b)
+#define OP_LH (P(OP, LOAD) | P(LVL, HIT))
+#define SNOOP_NONE_MISS (P(SNOOP, NONE) | P(SNOOP, MISS))
+
+/* Version for Sandy Bridge and later */
+static u64 pebs_data_source[] = {
+       P(OP, LOAD) | P(LVL, MISS) | P(LVL, L3) | P(SNOOP, NA),/* 0x00:ukn L3 */
+       OP_LH | P(LVL, L1)  | P(SNOOP, NONE),   /* 0x01: L1 local */
+       OP_LH | P(LVL, LFB) | P(SNOOP, NONE),   /* 0x02: LFB hit */
+       OP_LH | P(LVL, L2)  | P(SNOOP, NONE),   /* 0x03: L2 hit */
+       OP_LH | P(LVL, L3)  | P(SNOOP, NONE),   /* 0x04: L3 hit */
+       OP_LH | P(LVL, L3)  | P(SNOOP, MISS),   /* 0x05: L3 hit, snoop miss */
+       OP_LH | P(LVL, L3)  | P(SNOOP, HIT),    /* 0x06: L3 hit, snoop hit */
+       OP_LH | P(LVL, L3)  | P(SNOOP, HITM),   /* 0x07: L3 hit, snoop hitm */
+       OP_LH | P(LVL, REM_CCE1) | P(SNOOP, HIT),  /* 0x08: L3 miss snoop hit */
+       OP_LH | P(LVL, REM_CCE1) | P(SNOOP, HITM), /* 0x09: L3 miss snoop hitm*/
+       OP_LH | P(LVL, LOC_RAM)  | P(SNOOP, HIT),  /* 0x0a: L3 miss, shared */
+       OP_LH | P(LVL, REM_RAM1) | P(SNOOP, HIT),  /* 0x0b: L3 miss, shared */
+       OP_LH | P(LVL, LOC_RAM)  | SNOOP_NONE_MISS,/* 0x0c: L3 miss, excl */
+       OP_LH | P(LVL, REM_RAM1) | SNOOP_NONE_MISS,/* 0x0d: L3 miss, excl */
+       OP_LH | P(LVL, IO)  | P(SNOOP, NONE), /* 0x0e: I/O */
+       OP_LH | P(LVL, UNC) | P(SNOOP, NONE), /* 0x0f: uncached */
+};
+
+/* Patch up minor differences in the bits */
+void __init intel_pmu_pebs_data_source_nhm(void)
+{
+       pebs_data_source[0x05] = OP_LH | P(LVL, L3)  | P(SNOOP, HIT);
+       pebs_data_source[0x06] = OP_LH | P(LVL, L3)  | P(SNOOP, HITM);
+       pebs_data_source[0x07] = OP_LH | P(LVL, L3)  | P(SNOOP, HITM);
+}
+
+static u64 precise_store_data(u64 status)
+{
+       union intel_x86_pebs_dse dse;
+       u64 val = P(OP, STORE) | P(SNOOP, NA) | P(LVL, L1) | P(TLB, L2);
+
+       dse.val = status;
+
+       /*
+        * bit 4: TLB access
+        * 1 = stored missed 2nd level TLB
+        *
+        * so it either hit the walker or the OS
+        * otherwise hit 2nd level TLB
+        */
+       if (dse.st_stlb_miss)
+               val |= P(TLB, MISS);
+       else
+               val |= P(TLB, HIT);
+
+       /*
+        * bit 0: hit L1 data cache
+        * if not set, then all we know is that
+        * it missed L1D
+        */
+       if (dse.st_l1d_hit)
+               val |= P(LVL, HIT);
+       else
+               val |= P(LVL, MISS);
+
+       /*
+        * bit 5: Locked prefix
+        */
+       if (dse.st_locked)
+               val |= P(LOCK, LOCKED);
+
+       return val;
+}
+
+static u64 precise_datala_hsw(struct perf_event *event, u64 status)
+{
+       union perf_mem_data_src dse;
+
+       dse.val = PERF_MEM_NA;
+
+       if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW)
+               dse.mem_op = PERF_MEM_OP_STORE;
+       else if (event->hw.flags & PERF_X86_EVENT_PEBS_LD_HSW)
+               dse.mem_op = PERF_MEM_OP_LOAD;
+
+       /*
+        * L1 info only valid for following events:
+        *
+        * MEM_UOPS_RETIRED.STLB_MISS_STORES
+        * MEM_UOPS_RETIRED.LOCK_STORES
+        * MEM_UOPS_RETIRED.SPLIT_STORES
+        * MEM_UOPS_RETIRED.ALL_STORES
+        */
+       if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW) {
+               if (status & 1)
+                       dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT;
+               else
+                       dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_MISS;
+       }
+       return dse.val;
+}
+
+static u64 load_latency_data(u64 status)
+{
+       union intel_x86_pebs_dse dse;
+       u64 val;
+       int model = boot_cpu_data.x86_model;
+       int fam = boot_cpu_data.x86;
+
+       dse.val = status;
+
+       /*
+        * use the mapping table for bit 0-3
+        */
+       val = pebs_data_source[dse.ld_dse];
+
+       /*
+        * Nehalem models do not support TLB, Lock infos
+        */
+       if (fam == 0x6 && (model == 26 || model == 30
+           || model == 31 || model == 46)) {
+               val |= P(TLB, NA) | P(LOCK, NA);
+               return val;
+       }
+       /*
+        * bit 4: TLB access
+        * 0 = did not miss 2nd level TLB
+        * 1 = missed 2nd level TLB
+        */
+       if (dse.ld_stlb_miss)
+               val |= P(TLB, MISS) | P(TLB, L2);
+       else
+               val |= P(TLB, HIT) | P(TLB, L1) | P(TLB, L2);
+
+       /*
+        * bit 5: locked prefix
+        */
+       if (dse.ld_locked)
+               val |= P(LOCK, LOCKED);
+
+       return val;
+}
+
+struct pebs_record_core {
+       u64 flags, ip;
+       u64 ax, bx, cx, dx;
+       u64 si, di, bp, sp;
+       u64 r8,  r9,  r10, r11;
+       u64 r12, r13, r14, r15;
+};
+
+struct pebs_record_nhm {
+       u64 flags, ip;
+       u64 ax, bx, cx, dx;
+       u64 si, di, bp, sp;
+       u64 r8,  r9,  r10, r11;
+       u64 r12, r13, r14, r15;
+       u64 status, dla, dse, lat;
+};
+
+/*
+ * Same as pebs_record_nhm, with two additional fields.
+ */
+struct pebs_record_hsw {
+       u64 flags, ip;
+       u64 ax, bx, cx, dx;
+       u64 si, di, bp, sp;
+       u64 r8,  r9,  r10, r11;
+       u64 r12, r13, r14, r15;
+       u64 status, dla, dse, lat;
+       u64 real_ip, tsx_tuning;
+};
+
+union hsw_tsx_tuning {
+       struct {
+               u32 cycles_last_block     : 32,
+                   hle_abort             : 1,
+                   rtm_abort             : 1,
+                   instruction_abort     : 1,
+                   non_instruction_abort : 1,
+                   retry                 : 1,
+                   data_conflict         : 1,
+                   capacity_writes       : 1,
+                   capacity_reads        : 1;
+       };
+       u64         value;
+};
+
+#define PEBS_HSW_TSX_FLAGS     0xff00000000ULL
+
+/* Same as HSW, plus TSC */
+
+struct pebs_record_skl {
+       u64 flags, ip;
+       u64 ax, bx, cx, dx;
+       u64 si, di, bp, sp;
+       u64 r8,  r9,  r10, r11;
+       u64 r12, r13, r14, r15;
+       u64 status, dla, dse, lat;
+       u64 real_ip, tsx_tuning;
+       u64 tsc;
+};
+
+void init_debug_store_on_cpu(int cpu)
+{
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+
+       if (!ds)
+               return;
+
+       wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA,
+                    (u32)((u64)(unsigned long)ds),
+                    (u32)((u64)(unsigned long)ds >> 32));
+}
+
+void fini_debug_store_on_cpu(int cpu)
+{
+       if (!per_cpu(cpu_hw_events, cpu).ds)
+               return;
+
+       wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0);
+}
+
+static DEFINE_PER_CPU(void *, insn_buffer);
+
+static int alloc_pebs_buffer(int cpu)
+{
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+       int node = cpu_to_node(cpu);
+       int max;
+       void *buffer, *ibuffer;
+
+       if (!x86_pmu.pebs)
+               return 0;
+
+       buffer = kzalloc_node(x86_pmu.pebs_buffer_size, GFP_KERNEL, node);
+       if (unlikely(!buffer))
+               return -ENOMEM;
+
+       /*
+        * HSW+ already provides us the eventing ip; no need to allocate this
+        * buffer then.
+        */
+       if (x86_pmu.intel_cap.pebs_format < 2) {
+               ibuffer = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node);
+               if (!ibuffer) {
+                       kfree(buffer);
+                       return -ENOMEM;
+               }
+               per_cpu(insn_buffer, cpu) = ibuffer;
+       }
+
+       max = x86_pmu.pebs_buffer_size / x86_pmu.pebs_record_size;
+
+       ds->pebs_buffer_base = (u64)(unsigned long)buffer;
+       ds->pebs_index = ds->pebs_buffer_base;
+       ds->pebs_absolute_maximum = ds->pebs_buffer_base +
+               max * x86_pmu.pebs_record_size;
+
+       return 0;
+}
+
+static void release_pebs_buffer(int cpu)
+{
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+
+       if (!ds || !x86_pmu.pebs)
+               return;
+
+       kfree(per_cpu(insn_buffer, cpu));
+       per_cpu(insn_buffer, cpu) = NULL;
+
+       kfree((void *)(unsigned long)ds->pebs_buffer_base);
+       ds->pebs_buffer_base = 0;
+}
+
+static int alloc_bts_buffer(int cpu)
+{
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+       int node = cpu_to_node(cpu);
+       int max, thresh;
+       void *buffer;
+
+       if (!x86_pmu.bts)
+               return 0;
+
+       buffer = kzalloc_node(BTS_BUFFER_SIZE, GFP_KERNEL | __GFP_NOWARN, node);
+       if (unlikely(!buffer)) {
+               WARN_ONCE(1, "%s: BTS buffer allocation failure\n", __func__);
+               return -ENOMEM;
+       }
+
+       max = BTS_BUFFER_SIZE / BTS_RECORD_SIZE;
+       thresh = max / 16;
+
+       ds->bts_buffer_base = (u64)(unsigned long)buffer;
+       ds->bts_index = ds->bts_buffer_base;
+       ds->bts_absolute_maximum = ds->bts_buffer_base +
+               max * BTS_RECORD_SIZE;
+       ds->bts_interrupt_threshold = ds->bts_absolute_maximum -
+               thresh * BTS_RECORD_SIZE;
+
+       return 0;
+}
+
+static void release_bts_buffer(int cpu)
+{
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+
+       if (!ds || !x86_pmu.bts)
+               return;
+
+       kfree((void *)(unsigned long)ds->bts_buffer_base);
+       ds->bts_buffer_base = 0;
+}
+
+static int alloc_ds_buffer(int cpu)
+{
+       int node = cpu_to_node(cpu);
+       struct debug_store *ds;
+
+       ds = kzalloc_node(sizeof(*ds), GFP_KERNEL, node);
+       if (unlikely(!ds))
+               return -ENOMEM;
+
+       per_cpu(cpu_hw_events, cpu).ds = ds;
+
+       return 0;
+}
+
+static void release_ds_buffer(int cpu)
+{
+       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
+
+       if (!ds)
+               return;
+
+       per_cpu(cpu_hw_events, cpu).ds = NULL;
+       kfree(ds);
+}
+
+void release_ds_buffers(void)
+{
+       int cpu;
+
+       if (!x86_pmu.bts && !x86_pmu.pebs)
+               return;
+
+       get_online_cpus();
+       for_each_online_cpu(cpu)
+               fini_debug_store_on_cpu(cpu);
+
+       for_each_possible_cpu(cpu) {
+               release_pebs_buffer(cpu);
+               release_bts_buffer(cpu);
+               release_ds_buffer(cpu);
+       }
+       put_online_cpus();
+}
+
+void reserve_ds_buffers(void)
+{
+       int bts_err = 0, pebs_err = 0;
+       int cpu;
+
+       x86_pmu.bts_active = 0;
+       x86_pmu.pebs_active = 0;
+
+       if (!x86_pmu.bts && !x86_pmu.pebs)
+               return;
+
+       if (!x86_pmu.bts)
+               bts_err = 1;
+
+       if (!x86_pmu.pebs)
+               pebs_err = 1;
+
+       get_online_cpus();
+
+       for_each_possible_cpu(cpu) {
+               if (alloc_ds_buffer(cpu)) {
+                       bts_err = 1;
+                       pebs_err = 1;
+               }
+
+               if (!bts_err && alloc_bts_buffer(cpu))
+                       bts_err = 1;
+
+               if (!pebs_err && alloc_pebs_buffer(cpu))
+                       pebs_err = 1;
+
+               if (bts_err && pebs_err)
+                       break;
+       }
+
+       if (bts_err) {
+               for_each_possible_cpu(cpu)
+                       release_bts_buffer(cpu);
+       }
+
+       if (pebs_err) {
+               for_each_possible_cpu(cpu)
+                       release_pebs_buffer(cpu);
+       }
+
+       if (bts_err && pebs_err) {
+               for_each_possible_cpu(cpu)
+                       release_ds_buffer(cpu);
+       } else {
+               if (x86_pmu.bts && !bts_err)
+                       x86_pmu.bts_active = 1;
+
+               if (x86_pmu.pebs && !pebs_err)
+                       x86_pmu.pebs_active = 1;
+
+               for_each_online_cpu(cpu)
+                       init_debug_store_on_cpu(cpu);
+       }
+
+       put_online_cpus();
+}
+
+/*
+ * BTS
+ */
+
+struct event_constraint bts_constraint =
+       EVENT_CONSTRAINT(0, 1ULL << INTEL_PMC_IDX_FIXED_BTS, 0);
+
+void intel_pmu_enable_bts(u64 config)
+{
+       unsigned long debugctlmsr;
+
+       debugctlmsr = get_debugctlmsr();
+
+       debugctlmsr |= DEBUGCTLMSR_TR;
+       debugctlmsr |= DEBUGCTLMSR_BTS;
+       if (config & ARCH_PERFMON_EVENTSEL_INT)
+               debugctlmsr |= DEBUGCTLMSR_BTINT;
+
+       if (!(config & ARCH_PERFMON_EVENTSEL_OS))
+               debugctlmsr |= DEBUGCTLMSR_BTS_OFF_OS;
+
+       if (!(config & ARCH_PERFMON_EVENTSEL_USR))
+               debugctlmsr |= DEBUGCTLMSR_BTS_OFF_USR;
+
+       update_debugctlmsr(debugctlmsr);
+}
+
+void intel_pmu_disable_bts(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       unsigned long debugctlmsr;
+
+       if (!cpuc->ds)
+               return;
+
+       debugctlmsr = get_debugctlmsr();
+
+       debugctlmsr &=
+               ~(DEBUGCTLMSR_TR | DEBUGCTLMSR_BTS | DEBUGCTLMSR_BTINT |
+                 DEBUGCTLMSR_BTS_OFF_OS | DEBUGCTLMSR_BTS_OFF_USR);
+
+       update_debugctlmsr(debugctlmsr);
+}
+
+int intel_pmu_drain_bts_buffer(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct debug_store *ds = cpuc->ds;
+       struct bts_record {
+               u64     from;
+               u64     to;
+               u64     flags;
+       };
+       struct perf_event *event = cpuc->events[INTEL_PMC_IDX_FIXED_BTS];
+       struct bts_record *at, *base, *top;
+       struct perf_output_handle handle;
+       struct perf_event_header header;
+       struct perf_sample_data data;
+       unsigned long skip = 0;
+       struct pt_regs regs;
+
+       if (!event)
+               return 0;
+
+       if (!x86_pmu.bts_active)
+               return 0;
+
+       base = (struct bts_record *)(unsigned long)ds->bts_buffer_base;
+       top  = (struct bts_record *)(unsigned long)ds->bts_index;
+
+       if (top <= base)
+               return 0;
+
+       memset(&regs, 0, sizeof(regs));
+
+       ds->bts_index = ds->bts_buffer_base;
+
+       perf_sample_data_init(&data, 0, event->hw.last_period);
+
+       /*
+        * BTS leaks kernel addresses in branches across the cpl boundary,
+        * such as traps or system calls, so unless the user is asking for
+        * kernel tracing (and right now it's not possible), we'd need to
+        * filter them out. But first we need to count how many of those we
+        * have in the current batch. This is an extra O(n) pass, however,
+        * it's much faster than the other one especially considering that
+        * n <= 2560 (BTS_BUFFER_SIZE / BTS_RECORD_SIZE * 15/16; see the
+        * alloc_bts_buffer()).
+        */
+       for (at = base; at < top; at++) {
+               /*
+                * Note that right now *this* BTS code only works if
+                * attr::exclude_kernel is set, but let's keep this extra
+                * check here in case that changes.
+                */
+               if (event->attr.exclude_kernel &&
+                   (kernel_ip(at->from) || kernel_ip(at->to)))
+                       skip++;
+       }
+
+       /*
+        * Prepare a generic sample, i.e. fill in the invariant fields.
+        * We will overwrite the from and to address before we output
+        * the sample.
+        */
+       perf_prepare_sample(&header, &data, event, &regs);
+
+       if (perf_output_begin(&handle, event, header.size *
+                             (top - base - skip)))
+               return 1;
+
+       for (at = base; at < top; at++) {
+               /* Filter out any records that contain kernel addresses. */
+               if (event->attr.exclude_kernel &&
+                   (kernel_ip(at->from) || kernel_ip(at->to)))
+                       continue;
+
+               data.ip         = at->from;
+               data.addr       = at->to;
+
+               perf_output_sample(&handle, &header, &data, event);
+       }
+
+       perf_output_end(&handle);
+
+       /* There's new data available. */
+       event->hw.interrupts++;
+       event->pending_kill = POLL_IN;
+       return 1;
+}
+
+static inline void intel_pmu_drain_pebs_buffer(void)
+{
+       struct pt_regs regs;
+
+       x86_pmu.drain_pebs(&regs);
+}
+
+void intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in)
+{
+       if (!sched_in)
+               intel_pmu_drain_pebs_buffer();
+}
+
+/*
+ * PEBS
+ */
+struct event_constraint intel_core2_pebs_event_constraints[] = {
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
+       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01),
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_atom_pebs_event_constraints[] = {
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
+       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01),
+       /* Allow all events as PEBS with no flags */
+       INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_slm_pebs_event_constraints[] = {
+       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x1),
+       /* Allow all events as PEBS with no flags */
+       INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_nehalem_pebs_event_constraints[] = {
+       INTEL_PLD_CONSTRAINT(0x100b, 0xf),      /* MEM_INST_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xf),    /* INST_RETIRED.ANY */
+       INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
+       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f),
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_westmere_pebs_event_constraints[] = {
+       INTEL_PLD_CONSTRAINT(0x100b, 0xf),      /* MEM_INST_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xf),    /* INSTR_RETIRED.* */
+       INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
+       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f),
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_snb_pebs_event_constraints[] = {
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+       INTEL_PLD_CONSTRAINT(0x01cd, 0x8),    /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */
+       INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */
+       /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
+        INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */
+        INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+        INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+        INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf),    /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+       /* Allow all events as PEBS with no flags */
+       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_ivb_pebs_event_constraints[] = {
+        INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+        INTEL_PLD_CONSTRAINT(0x01cd, 0x8),    /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */
+       INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */
+       /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
+       /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
+       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf),    /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+       /* Allow all events as PEBS with no flags */
+       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
+        EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_hsw_pebs_event_constraints[] = {
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+       INTEL_PLD_CONSTRAINT(0x01cd, 0xf),    /* MEM_TRANS_RETIRED.* */
+       /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
+       /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x12d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x42d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd2, 0xf),    /* MEM_LOAD_UOPS_L3_HIT_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd3, 0xf),    /* MEM_LOAD_UOPS_L3_MISS_RETIRED.* */
+       /* Allow all events as PEBS with no flags */
+       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint intel_bdw_pebs_event_constraints[] = {
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+       INTEL_PLD_CONSTRAINT(0x01cd, 0xf),    /* MEM_TRANS_RETIRED.* */
+       /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
+       /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd2, 0xf),    /* MEM_LOAD_UOPS_L3_HIT_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd3, 0xf),    /* MEM_LOAD_UOPS_L3_MISS_RETIRED.* */
+       /* Allow all events as PEBS with no flags */
+       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
+       EVENT_CONSTRAINT_END
+};
+
+
+struct event_constraint intel_skl_pebs_event_constraints[] = {
+       INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x2),      /* INST_RETIRED.PREC_DIST */
+       /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
+       /* INST_RETIRED.TOTAL_CYCLES_PS (inv=1, cmask=16) (cycles:p). */
+       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f),
+       INTEL_PLD_CONSTRAINT(0x1cd, 0xf),                     /* MEM_TRANS_RETIRED.* */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_INST_RETIRED.LOCK_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x22d0, 0xf), /* MEM_INST_RETIRED.LOCK_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_INST_RETIRED.SPLIT_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_INST_RETIRED.SPLIT_STORES */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_INST_RETIRED.ALL_LOADS */
+       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_INST_RETIRED.ALL_STORES */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd1, 0xf),    /* MEM_LOAD_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd2, 0xf),    /* MEM_LOAD_L3_HIT_RETIRED.* */
+       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd3, 0xf),    /* MEM_LOAD_L3_MISS_RETIRED.* */
+       /* Allow all events as PEBS with no flags */
+       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
+       EVENT_CONSTRAINT_END
+};
+
+struct event_constraint *intel_pebs_constraints(struct perf_event *event)
+{
+       struct event_constraint *c;
+
+       if (!event->attr.precise_ip)
+               return NULL;
+
+       if (x86_pmu.pebs_constraints) {
+               for_each_event_constraint(c, x86_pmu.pebs_constraints) {
+                       if ((event->hw.config & c->cmask) == c->code) {
+                               event->hw.flags |= c->flags;
+                               return c;
+                       }
+               }
+       }
+
+       return &emptyconstraint;
+}
+
+static inline bool pebs_is_enabled(struct cpu_hw_events *cpuc)
+{
+       return (cpuc->pebs_enabled & ((1ULL << MAX_PEBS_EVENTS) - 1));
+}
+
+void intel_pmu_pebs_enable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       struct debug_store *ds = cpuc->ds;
+       bool first_pebs;
+       u64 threshold;
+
+       hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
+
+       first_pebs = !pebs_is_enabled(cpuc);
+       cpuc->pebs_enabled |= 1ULL << hwc->idx;
+
+       if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
+               cpuc->pebs_enabled |= 1ULL << (hwc->idx + 32);
+       else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
+               cpuc->pebs_enabled |= 1ULL << 63;
+
+       /*
+        * When the event is constrained enough we can use a larger
+        * threshold and run the event with less frequent PMI.
+        */
+       if (hwc->flags & PERF_X86_EVENT_FREERUNNING) {
+               threshold = ds->pebs_absolute_maximum -
+                       x86_pmu.max_pebs_events * x86_pmu.pebs_record_size;
+
+               if (first_pebs)
+                       perf_sched_cb_inc(event->ctx->pmu);
+       } else {
+               threshold = ds->pebs_buffer_base + x86_pmu.pebs_record_size;
+
+               /*
+                * If not all events can use larger buffer,
+                * roll back to threshold = 1
+                */
+               if (!first_pebs &&
+                   (ds->pebs_interrupt_threshold > threshold))
+                       perf_sched_cb_dec(event->ctx->pmu);
+       }
+
+       /* Use auto-reload if possible to save a MSR write in the PMI */
+       if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) {
+               ds->pebs_event_reset[hwc->idx] =
+                       (u64)(-hwc->sample_period) & x86_pmu.cntval_mask;
+       }
+
+       if (first_pebs || ds->pebs_interrupt_threshold > threshold)
+               ds->pebs_interrupt_threshold = threshold;
+}
+
+void intel_pmu_pebs_disable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct hw_perf_event *hwc = &event->hw;
+       struct debug_store *ds = cpuc->ds;
+       bool large_pebs = ds->pebs_interrupt_threshold >
+               ds->pebs_buffer_base + x86_pmu.pebs_record_size;
+
+       if (large_pebs)
+               intel_pmu_drain_pebs_buffer();
+
+       cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
+
+       if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
+               cpuc->pebs_enabled &= ~(1ULL << (hwc->idx + 32));
+       else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
+               cpuc->pebs_enabled &= ~(1ULL << 63);
+
+       if (large_pebs && !pebs_is_enabled(cpuc))
+               perf_sched_cb_dec(event->ctx->pmu);
+
+       if (cpuc->enabled)
+               wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
+
+       hwc->config |= ARCH_PERFMON_EVENTSEL_INT;
+}
+
+void intel_pmu_pebs_enable_all(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       if (cpuc->pebs_enabled)
+               wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
+}
+
+void intel_pmu_pebs_disable_all(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       if (cpuc->pebs_enabled)
+               wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
+}
+
+static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       unsigned long from = cpuc->lbr_entries[0].from;
+       unsigned long old_to, to = cpuc->lbr_entries[0].to;
+       unsigned long ip = regs->ip;
+       int is_64bit = 0;
+       void *kaddr;
+       int size;
+
+       /*
+        * We don't need to fixup if the PEBS assist is fault like
+        */
+       if (!x86_pmu.intel_cap.pebs_trap)
+               return 1;
+
+       /*
+        * No LBR entry, no basic block, no rewinding
+        */
+       if (!cpuc->lbr_stack.nr || !from || !to)
+               return 0;
+
+       /*
+        * Basic blocks should never cross user/kernel boundaries
+        */
+       if (kernel_ip(ip) != kernel_ip(to))
+               return 0;
+
+       /*
+        * unsigned math, either ip is before the start (impossible) or
+        * the basic block is larger than 1 page (sanity)
+        */
+       if ((ip - to) > PEBS_FIXUP_SIZE)
+               return 0;
+
+       /*
+        * We sampled a branch insn, rewind using the LBR stack
+        */
+       if (ip == to) {
+               set_linear_ip(regs, from);
+               return 1;
+       }
+
+       size = ip - to;
+       if (!kernel_ip(ip)) {
+               int bytes;
+               u8 *buf = this_cpu_read(insn_buffer);
+
+               /* 'size' must fit our buffer, see above */
+               bytes = copy_from_user_nmi(buf, (void __user *)to, size);
+               if (bytes != 0)
+                       return 0;
+
+               kaddr = buf;
+       } else {
+               kaddr = (void *)to;
+       }
+
+       do {
+               struct insn insn;
+
+               old_to = to;
+
+#ifdef CONFIG_X86_64
+               is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
+#endif
+               insn_init(&insn, kaddr, size, is_64bit);
+               insn_get_length(&insn);
+               /*
+                * Make sure there was not a problem decoding the
+                * instruction and getting the length.  This is
+                * doubly important because we have an infinite
+                * loop if insn.length=0.
+                */
+               if (!insn.length)
+                       break;
+
+               to += insn.length;
+               kaddr += insn.length;
+               size -= insn.length;
+       } while (to < ip);
+
+       if (to == ip) {
+               set_linear_ip(regs, old_to);
+               return 1;
+       }
+
+       /*
+        * Even though we decoded the basic block, the instruction stream
+        * never matched the given IP, either the TO or the IP got corrupted.
+        */
+       return 0;
+}
+
+static inline u64 intel_hsw_weight(struct pebs_record_skl *pebs)
+{
+       if (pebs->tsx_tuning) {
+               union hsw_tsx_tuning tsx = { .value = pebs->tsx_tuning };
+               return tsx.cycles_last_block;
+       }
+       return 0;
+}
+
+static inline u64 intel_hsw_transaction(struct pebs_record_skl *pebs)
+{
+       u64 txn = (pebs->tsx_tuning & PEBS_HSW_TSX_FLAGS) >> 32;
+
+       /* For RTM XABORTs also log the abort code from AX */
+       if ((txn & PERF_TXN_TRANSACTION) && (pebs->ax & 1))
+               txn |= ((pebs->ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT;
+       return txn;
+}
+
+static void setup_pebs_sample_data(struct perf_event *event,
+                                  struct pt_regs *iregs, void *__pebs,
+                                  struct perf_sample_data *data,
+                                  struct pt_regs *regs)
+{
+#define PERF_X86_EVENT_PEBS_HSW_PREC \
+               (PERF_X86_EVENT_PEBS_ST_HSW | \
+                PERF_X86_EVENT_PEBS_LD_HSW | \
+                PERF_X86_EVENT_PEBS_NA_HSW)
+       /*
+        * We cast to the biggest pebs_record but are careful not to
+        * unconditionally access the 'extra' entries.
+        */
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct pebs_record_skl *pebs = __pebs;
+       u64 sample_type;
+       int fll, fst, dsrc;
+       int fl = event->hw.flags;
+
+       if (pebs == NULL)
+               return;
+
+       sample_type = event->attr.sample_type;
+       dsrc = sample_type & PERF_SAMPLE_DATA_SRC;
+
+       fll = fl & PERF_X86_EVENT_PEBS_LDLAT;
+       fst = fl & (PERF_X86_EVENT_PEBS_ST | PERF_X86_EVENT_PEBS_HSW_PREC);
+
+       perf_sample_data_init(data, 0, event->hw.last_period);
+
+       data->period = event->hw.last_period;
+
+       /*
+        * Use latency for weight (only avail with PEBS-LL)
+        */
+       if (fll && (sample_type & PERF_SAMPLE_WEIGHT))
+               data->weight = pebs->lat;
+
+       /*
+        * data.data_src encodes the data source
+        */
+       if (dsrc) {
+               u64 val = PERF_MEM_NA;
+               if (fll)
+                       val = load_latency_data(pebs->dse);
+               else if (fst && (fl & PERF_X86_EVENT_PEBS_HSW_PREC))
+                       val = precise_datala_hsw(event, pebs->dse);
+               else if (fst)
+                       val = precise_store_data(pebs->dse);
+               data->data_src.val = val;
+       }
+
+       /*
+        * We use the interrupt regs as a base because the PEBS record
+        * does not contain a full regs set, specifically it seems to
+        * lack segment descriptors, which get used by things like
+        * user_mode().
+        *
+        * In the simple case fix up only the IP and BP,SP regs, for
+        * PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly.
+        * A possible PERF_SAMPLE_REGS will have to transfer all regs.
+        */
+       *regs = *iregs;
+       regs->flags = pebs->flags;
+       set_linear_ip(regs, pebs->ip);
+       regs->bp = pebs->bp;
+       regs->sp = pebs->sp;
+
+       if (sample_type & PERF_SAMPLE_REGS_INTR) {
+               regs->ax = pebs->ax;
+               regs->bx = pebs->bx;
+               regs->cx = pebs->cx;
+               regs->dx = pebs->dx;
+               regs->si = pebs->si;
+               regs->di = pebs->di;
+               regs->bp = pebs->bp;
+               regs->sp = pebs->sp;
+
+               regs->flags = pebs->flags;
+#ifndef CONFIG_X86_32
+               regs->r8 = pebs->r8;
+               regs->r9 = pebs->r9;
+               regs->r10 = pebs->r10;
+               regs->r11 = pebs->r11;
+               regs->r12 = pebs->r12;
+               regs->r13 = pebs->r13;
+               regs->r14 = pebs->r14;
+               regs->r15 = pebs->r15;
+#endif
+       }
+
+       if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) {
+               regs->ip = pebs->real_ip;
+               regs->flags |= PERF_EFLAGS_EXACT;
+       } else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(regs))
+               regs->flags |= PERF_EFLAGS_EXACT;
+       else
+               regs->flags &= ~PERF_EFLAGS_EXACT;
+
+       if ((sample_type & PERF_SAMPLE_ADDR) &&
+           x86_pmu.intel_cap.pebs_format >= 1)
+               data->addr = pebs->dla;
+
+       if (x86_pmu.intel_cap.pebs_format >= 2) {
+               /* Only set the TSX weight when no memory weight. */
+               if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)
+                       data->weight = intel_hsw_weight(pebs);
+
+               if (sample_type & PERF_SAMPLE_TRANSACTION)
+                       data->txn = intel_hsw_transaction(pebs);
+       }
+
+       /*
+        * v3 supplies an accurate time stamp, so we use that
+        * for the time stamp.
+        *
+        * We can only do this for the default trace clock.
+        */
+       if (x86_pmu.intel_cap.pebs_format >= 3 &&
+               event->attr.use_clockid == 0)
+               data->time = native_sched_clock_from_tsc(pebs->tsc);
+
+       if (has_branch_stack(event))
+               data->br_stack = &cpuc->lbr_stack;
+}
+
+static inline void *
+get_next_pebs_record_by_bit(void *base, void *top, int bit)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       void *at;
+       u64 pebs_status;
+
+       /*
+        * fmt0 does not have a status bitfield (does not use
+        * perf_record_nhm format)
+        */
+       if (x86_pmu.intel_cap.pebs_format < 1)
+               return base;
+
+       if (base == NULL)
+               return NULL;
+
+       for (at = base; at < top; at += x86_pmu.pebs_record_size) {
+               struct pebs_record_nhm *p = at;
+
+               if (test_bit(bit, (unsigned long *)&p->status)) {
+                       /* PEBS v3 has accurate status bits */
+                       if (x86_pmu.intel_cap.pebs_format >= 3)
+                               return at;
+
+                       if (p->status == (1 << bit))
+                               return at;
+
+                       /* clear non-PEBS bit and re-check */
+                       pebs_status = p->status & cpuc->pebs_enabled;
+                       pebs_status &= (1ULL << MAX_PEBS_EVENTS) - 1;
+                       if (pebs_status == (1 << bit))
+                               return at;
+               }
+       }
+       return NULL;
+}
+
+static void __intel_pmu_pebs_event(struct perf_event *event,
+                                  struct pt_regs *iregs,
+                                  void *base, void *top,
+                                  int bit, int count)
+{
+       struct perf_sample_data data;
+       struct pt_regs regs;
+       void *at = get_next_pebs_record_by_bit(base, top, bit);
+
+       if (!intel_pmu_save_and_restart(event) &&
+           !(event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD))
+               return;
+
+       while (count > 1) {
+               setup_pebs_sample_data(event, iregs, at, &data, &regs);
+               perf_event_output(event, &data, &regs);
+               at += x86_pmu.pebs_record_size;
+               at = get_next_pebs_record_by_bit(at, top, bit);
+               count--;
+       }
+
+       setup_pebs_sample_data(event, iregs, at, &data, &regs);
+
+       /*
+        * All but the last records are processed.
+        * The last one is left to be able to call the overflow handler.
+        */
+       if (perf_event_overflow(event, &data, &regs)) {
+               x86_pmu_stop(event, 0);
+               return;
+       }
+
+}
+
+static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct debug_store *ds = cpuc->ds;
+       struct perf_event *event = cpuc->events[0]; /* PMC0 only */
+       struct pebs_record_core *at, *top;
+       int n;
+
+       if (!x86_pmu.pebs_active)
+               return;
+
+       at  = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base;
+       top = (struct pebs_record_core *)(unsigned long)ds->pebs_index;
+
+       /*
+        * Whatever else happens, drain the thing
+        */
+       ds->pebs_index = ds->pebs_buffer_base;
+
+       if (!test_bit(0, cpuc->active_mask))
+               return;
+
+       WARN_ON_ONCE(!event);
+
+       if (!event->attr.precise_ip)
+               return;
+
+       n = top - at;
+       if (n <= 0)
+               return;
+
+       __intel_pmu_pebs_event(event, iregs, at, top, 0, n);
+}
+
+static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct debug_store *ds = cpuc->ds;
+       struct perf_event *event;
+       void *base, *at, *top;
+       short counts[MAX_PEBS_EVENTS] = {};
+       short error[MAX_PEBS_EVENTS] = {};
+       int bit, i;
+
+       if (!x86_pmu.pebs_active)
+               return;
+
+       base = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
+       top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
+
+       ds->pebs_index = ds->pebs_buffer_base;
+
+       if (unlikely(base >= top))
+               return;
+
+       for (at = base; at < top; at += x86_pmu.pebs_record_size) {
+               struct pebs_record_nhm *p = at;
+               u64 pebs_status;
+
+               /* PEBS v3 has accurate status bits */
+               if (x86_pmu.intel_cap.pebs_format >= 3) {
+                       for_each_set_bit(bit, (unsigned long *)&p->status,
+                                        MAX_PEBS_EVENTS)
+                               counts[bit]++;
+
+                       continue;
+               }
+
+               pebs_status = p->status & cpuc->pebs_enabled;
+               pebs_status &= (1ULL << x86_pmu.max_pebs_events) - 1;
+
+               /*
+                * On some CPUs the PEBS status can be zero when PEBS is
+                * racing with clearing of GLOBAL_STATUS.
+                *
+                * Normally we would drop that record, but in the
+                * case when there is only a single active PEBS event
+                * we can assume it's for that event.
+                */
+               if (!pebs_status && cpuc->pebs_enabled &&
+                       !(cpuc->pebs_enabled & (cpuc->pebs_enabled-1)))
+                       pebs_status = cpuc->pebs_enabled;
+
+               bit = find_first_bit((unsigned long *)&pebs_status,
+                                       x86_pmu.max_pebs_events);
+               if (bit >= x86_pmu.max_pebs_events)
+                       continue;
+
+               /*
+                * The PEBS hardware does not deal well with the situation
+                * when events happen near to each other and multiple bits
+                * are set. But it should happen rarely.
+                *
+                * If these events include one PEBS and multiple non-PEBS
+                * events, it doesn't impact PEBS record. The record will
+                * be handled normally. (slow path)
+                *
+                * If these events include two or more PEBS events, the
+                * records for the events can be collapsed into a single
+                * one, and it's not possible to reconstruct all events
+                * that caused the PEBS record. It's called collision.
+                * If collision happened, the record will be dropped.
+                */
+               if (p->status != (1ULL << bit)) {
+                       for_each_set_bit(i, (unsigned long *)&pebs_status,
+                                        x86_pmu.max_pebs_events)
+                               error[i]++;
+                       continue;
+               }
+
+               counts[bit]++;
+       }
+
+       for (bit = 0; bit < x86_pmu.max_pebs_events; bit++) {
+               if ((counts[bit] == 0) && (error[bit] == 0))
+                       continue;
+
+               event = cpuc->events[bit];
+               WARN_ON_ONCE(!event);
+               WARN_ON_ONCE(!event->attr.precise_ip);
+
+               /* log dropped samples number */
+               if (error[bit])
+                       perf_log_lost_samples(event, error[bit]);
+
+               if (counts[bit]) {
+                       __intel_pmu_pebs_event(event, iregs, base,
+                                              top, bit, counts[bit]);
+               }
+       }
+}
+
+/*
+ * BTS, PEBS probe and setup
+ */
+
+void __init intel_ds_init(void)
+{
+       /*
+        * No support for 32bit formats
+        */
+       if (!boot_cpu_has(X86_FEATURE_DTES64))
+               return;
+
+       x86_pmu.bts  = boot_cpu_has(X86_FEATURE_BTS);
+       x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS);
+       x86_pmu.pebs_buffer_size = PEBS_BUFFER_SIZE;
+       if (x86_pmu.pebs) {
+               char pebs_type = x86_pmu.intel_cap.pebs_trap ?  '+' : '-';
+               int format = x86_pmu.intel_cap.pebs_format;
+
+               switch (format) {
+               case 0:
+                       pr_cont("PEBS fmt0%c, ", pebs_type);
+                       x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
+                       /*
+                        * Using >PAGE_SIZE buffers makes the WRMSR to
+                        * PERF_GLOBAL_CTRL in intel_pmu_enable_all()
+                        * mysteriously hang on Core2.
+                        *
+                        * As a workaround, we don't do this.
+                        */
+                       x86_pmu.pebs_buffer_size = PAGE_SIZE;
+                       x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
+                       break;
+
+               case 1:
+                       pr_cont("PEBS fmt1%c, ", pebs_type);
+                       x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm);
+                       x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
+                       break;
+
+               case 2:
+                       pr_cont("PEBS fmt2%c, ", pebs_type);
+                       x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw);
+                       x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
+                       break;
+
+               case 3:
+                       pr_cont("PEBS fmt3%c, ", pebs_type);
+                       x86_pmu.pebs_record_size =
+                                               sizeof(struct pebs_record_skl);
+                       x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
+                       x86_pmu.free_running_flags |= PERF_SAMPLE_TIME;
+                       break;
+
+               default:
+                       pr_cont("no PEBS fmt%d%c, ", format, pebs_type);
+                       x86_pmu.pebs = 0;
+               }
+       }
+}
+
+void perf_restore_debug_store(void)
+{
+       struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
+
+       if (!x86_pmu.bts && !x86_pmu.pebs)
+               return;
+
+       wrmsrl(MSR_IA32_DS_AREA, (unsigned long)ds);
+}
diff --git a/arch/x86/events/intel/knc.c b/arch/x86/events/intel/knc.c
new file mode 100644 (file)
index 0000000..548d5f7
--- /dev/null
@@ -0,0 +1,321 @@
+/* Driver for Intel Xeon Phi "Knights Corner" PMU */
+
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include <asm/hardirq.h>
+
+#include "../perf_event.h"
+
+static const u64 knc_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x002a,
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x0016,
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0028,
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x0029,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x0012,
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x002b,
+};
+
+static const u64 __initconst knc_hw_cache_event_ids
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+       [ C(OP_READ) ] = {
+               /* On Xeon Phi event "0" is a valid DATA_READ          */
+               /*   (L1 Data Cache Reads) Instruction.                */
+               /* We code this as ARCH_PERFMON_EVENTSEL_INT as this   */
+               /* bit will always be set in x86_pmu_hw_config().      */
+               [ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
+                                               /* DATA_READ           */
+               [ C(RESULT_MISS)   ] = 0x0003,  /* DATA_READ_MISS      */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0001,  /* DATA_WRITE          */
+               [ C(RESULT_MISS)   ] = 0x0004,  /* DATA_WRITE_MISS     */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0011,  /* L1_DATA_PF1         */
+               [ C(RESULT_MISS)   ] = 0x001c,  /* L1_DATA_PF1_MISS    */
+       },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x000c,  /* CODE_READ          */
+               [ C(RESULT_MISS)   ] = 0x000e,  /* CODE_CACHE_MISS    */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x10cb,  /* L2_READ_MISS */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x10cc,  /* L2_WRITE_HIT */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x10fc,  /* L2_DATA_PF2      */
+               [ C(RESULT_MISS)   ] = 0x10fe,  /* L2_DATA_PF2_MISS */
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
+                                               /* DATA_READ */
+                                               /* see note on L1 OP_READ */
+               [ C(RESULT_MISS)   ] = 0x0002,  /* DATA_PAGE_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0001,  /* DATA_WRITE */
+               [ C(RESULT_MISS)   ] = 0x0002,  /* DATA_PAGE_WALK */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = 0x0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x000c,  /* CODE_READ */
+               [ C(RESULT_MISS)   ] = 0x000d,  /* CODE_PAGE_WALK */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0012,  /* BRANCHES */
+               [ C(RESULT_MISS)   ] = 0x002b,  /* BRANCHES_MISPREDICTED */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+};
+
+
+static u64 knc_pmu_event_map(int hw_event)
+{
+       return knc_perfmon_event_map[hw_event];
+}
+
+static struct event_constraint knc_event_constraints[] =
+{
+       INTEL_EVENT_CONSTRAINT(0xc3, 0x1),      /* HWP_L2HIT */
+       INTEL_EVENT_CONSTRAINT(0xc4, 0x1),      /* HWP_L2MISS */
+       INTEL_EVENT_CONSTRAINT(0xc8, 0x1),      /* L2_READ_HIT_E */
+       INTEL_EVENT_CONSTRAINT(0xc9, 0x1),      /* L2_READ_HIT_M */
+       INTEL_EVENT_CONSTRAINT(0xca, 0x1),      /* L2_READ_HIT_S */
+       INTEL_EVENT_CONSTRAINT(0xcb, 0x1),      /* L2_READ_MISS */
+       INTEL_EVENT_CONSTRAINT(0xcc, 0x1),      /* L2_WRITE_HIT */
+       INTEL_EVENT_CONSTRAINT(0xce, 0x1),      /* L2_STRONGLY_ORDERED_STREAMING_VSTORES_MISS */
+       INTEL_EVENT_CONSTRAINT(0xcf, 0x1),      /* L2_WEAKLY_ORDERED_STREAMING_VSTORE_MISS */
+       INTEL_EVENT_CONSTRAINT(0xd7, 0x1),      /* L2_VICTIM_REQ_WITH_DATA */
+       INTEL_EVENT_CONSTRAINT(0xe3, 0x1),      /* SNP_HITM_BUNIT */
+       INTEL_EVENT_CONSTRAINT(0xe6, 0x1),      /* SNP_HIT_L2 */
+       INTEL_EVENT_CONSTRAINT(0xe7, 0x1),      /* SNP_HITM_L2 */
+       INTEL_EVENT_CONSTRAINT(0xf1, 0x1),      /* L2_DATA_READ_MISS_CACHE_FILL */
+       INTEL_EVENT_CONSTRAINT(0xf2, 0x1),      /* L2_DATA_WRITE_MISS_CACHE_FILL */
+       INTEL_EVENT_CONSTRAINT(0xf6, 0x1),      /* L2_DATA_READ_MISS_MEM_FILL */
+       INTEL_EVENT_CONSTRAINT(0xf7, 0x1),      /* L2_DATA_WRITE_MISS_MEM_FILL */
+       INTEL_EVENT_CONSTRAINT(0xfc, 0x1),      /* L2_DATA_PF2 */
+       INTEL_EVENT_CONSTRAINT(0xfd, 0x1),      /* L2_DATA_PF2_DROP */
+       INTEL_EVENT_CONSTRAINT(0xfe, 0x1),      /* L2_DATA_PF2_MISS */
+       INTEL_EVENT_CONSTRAINT(0xff, 0x1),      /* L2_DATA_HIT_INFLIGHT_PF2 */
+       EVENT_CONSTRAINT_END
+};
+
+#define MSR_KNC_IA32_PERF_GLOBAL_STATUS                0x0000002d
+#define MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL   0x0000002e
+#define MSR_KNC_IA32_PERF_GLOBAL_CTRL          0x0000002f
+
+#define KNC_ENABLE_COUNTER0                    0x00000001
+#define KNC_ENABLE_COUNTER1                    0x00000002
+
+static void knc_pmu_disable_all(void)
+{
+       u64 val;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
+       val &= ~(KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
+}
+
+static void knc_pmu_enable_all(int added)
+{
+       u64 val;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
+       val |= (KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
+}
+
+static inline void
+knc_pmu_disable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 val;
+
+       val = hwc->config;
+       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+
+       (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
+}
+
+static void knc_pmu_enable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 val;
+
+       val = hwc->config;
+       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+
+       (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
+}
+
+static inline u64 knc_pmu_get_status(void)
+{
+       u64 status;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
+
+       return status;
+}
+
+static inline void knc_pmu_ack_status(u64 ack)
+{
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
+}
+
+static int knc_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       int handled = 0;
+       int bit, loops;
+       u64 status;
+
+       cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       knc_pmu_disable_all();
+
+       status = knc_pmu_get_status();
+       if (!status) {
+               knc_pmu_enable_all(0);
+               return handled;
+       }
+
+       loops = 0;
+again:
+       knc_pmu_ack_status(status);
+       if (++loops > 100) {
+               WARN_ONCE(1, "perf: irq loop stuck!\n");
+               perf_event_print_debug();
+               goto done;
+       }
+
+       inc_irq_stat(apic_perf_irqs);
+
+       for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[bit];
+
+               handled++;
+
+               if (!test_bit(bit, cpuc->active_mask))
+                       continue;
+
+               if (!intel_pmu_save_and_restart(event))
+                       continue;
+
+               perf_sample_data_init(&data, 0, event->hw.last_period);
+
+               if (perf_event_overflow(event, &data, regs))
+                       x86_pmu_stop(event, 0);
+       }
+
+       /*
+        * Repeat if there is more work to be done:
+        */
+       status = knc_pmu_get_status();
+       if (status)
+               goto again;
+
+done:
+       /* Only restore PMU state when it's active. See x86_pmu_disable(). */
+       if (cpuc->enabled)
+               knc_pmu_enable_all(0);
+
+       return handled;
+}
+
+
+PMU_FORMAT_ATTR(event, "config:0-7"    );
+PMU_FORMAT_ATTR(umask, "config:8-15"   );
+PMU_FORMAT_ATTR(edge,  "config:18"     );
+PMU_FORMAT_ATTR(inv,   "config:23"     );
+PMU_FORMAT_ATTR(cmask, "config:24-31"  );
+
+static struct attribute *intel_knc_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask.attr,
+       NULL,
+};
+
+static const struct x86_pmu knc_pmu __initconst = {
+       .name                   = "knc",
+       .handle_irq             = knc_pmu_handle_irq,
+       .disable_all            = knc_pmu_disable_all,
+       .enable_all             = knc_pmu_enable_all,
+       .enable                 = knc_pmu_enable_event,
+       .disable                = knc_pmu_disable_event,
+       .hw_config              = x86_pmu_hw_config,
+       .schedule_events        = x86_schedule_events,
+       .eventsel               = MSR_KNC_EVNTSEL0,
+       .perfctr                = MSR_KNC_PERFCTR0,
+       .event_map              = knc_pmu_event_map,
+       .max_events             = ARRAY_SIZE(knc_perfmon_event_map),
+       .apic                   = 1,
+       .max_period             = (1ULL << 39) - 1,
+       .version                = 0,
+       .num_counters           = 2,
+       .cntval_bits            = 40,
+       .cntval_mask            = (1ULL << 40) - 1,
+       .get_event_constraints  = x86_get_event_constraints,
+       .event_constraints      = knc_event_constraints,
+       .format_attrs           = intel_knc_formats_attr,
+};
+
+__init int knc_pmu_init(void)
+{
+       x86_pmu = knc_pmu;
+
+       memcpy(hw_cache_event_ids, knc_hw_cache_event_ids, 
+               sizeof(hw_cache_event_ids));
+
+       return 0;
+}
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
new file mode 100644 (file)
index 0000000..69dd118
--- /dev/null
@@ -0,0 +1,1062 @@
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include <asm/perf_event.h>
+#include <asm/msr.h>
+#include <asm/insn.h>
+
+#include "../perf_event.h"
+
+enum {
+       LBR_FORMAT_32           = 0x00,
+       LBR_FORMAT_LIP          = 0x01,
+       LBR_FORMAT_EIP          = 0x02,
+       LBR_FORMAT_EIP_FLAGS    = 0x03,
+       LBR_FORMAT_EIP_FLAGS2   = 0x04,
+       LBR_FORMAT_INFO         = 0x05,
+       LBR_FORMAT_MAX_KNOWN    = LBR_FORMAT_INFO,
+};
+
+static enum {
+       LBR_EIP_FLAGS           = 1,
+       LBR_TSX                 = 2,
+} lbr_desc[LBR_FORMAT_MAX_KNOWN + 1] = {
+       [LBR_FORMAT_EIP_FLAGS]  = LBR_EIP_FLAGS,
+       [LBR_FORMAT_EIP_FLAGS2] = LBR_EIP_FLAGS | LBR_TSX,
+};
+
+/*
+ * Intel LBR_SELECT bits
+ * Intel Vol3a, April 2011, Section 16.7 Table 16-10
+ *
+ * Hardware branch filter (not available on all CPUs)
+ */
+#define LBR_KERNEL_BIT         0 /* do not capture at ring0 */
+#define LBR_USER_BIT           1 /* do not capture at ring > 0 */
+#define LBR_JCC_BIT            2 /* do not capture conditional branches */
+#define LBR_REL_CALL_BIT       3 /* do not capture relative calls */
+#define LBR_IND_CALL_BIT       4 /* do not capture indirect calls */
+#define LBR_RETURN_BIT         5 /* do not capture near returns */
+#define LBR_IND_JMP_BIT                6 /* do not capture indirect jumps */
+#define LBR_REL_JMP_BIT                7 /* do not capture relative jumps */
+#define LBR_FAR_BIT            8 /* do not capture far branches */
+#define LBR_CALL_STACK_BIT     9 /* enable call stack */
+
+/*
+ * Following bit only exists in Linux; we mask it out before writing it to
+ * the actual MSR. But it helps the constraint perf code to understand
+ * that this is a separate configuration.
+ */
+#define LBR_NO_INFO_BIT               63 /* don't read LBR_INFO. */
+
+#define LBR_KERNEL     (1 << LBR_KERNEL_BIT)
+#define LBR_USER       (1 << LBR_USER_BIT)
+#define LBR_JCC                (1 << LBR_JCC_BIT)
+#define LBR_REL_CALL   (1 << LBR_REL_CALL_BIT)
+#define LBR_IND_CALL   (1 << LBR_IND_CALL_BIT)
+#define LBR_RETURN     (1 << LBR_RETURN_BIT)
+#define LBR_REL_JMP    (1 << LBR_REL_JMP_BIT)
+#define LBR_IND_JMP    (1 << LBR_IND_JMP_BIT)
+#define LBR_FAR                (1 << LBR_FAR_BIT)
+#define LBR_CALL_STACK (1 << LBR_CALL_STACK_BIT)
+#define LBR_NO_INFO    (1ULL << LBR_NO_INFO_BIT)
+
+#define LBR_PLM (LBR_KERNEL | LBR_USER)
+
+#define LBR_SEL_MASK   0x1ff   /* valid bits in LBR_SELECT */
+#define LBR_NOT_SUPP   -1      /* LBR filter not supported */
+#define LBR_IGN                0       /* ignored */
+
+#define LBR_ANY                 \
+       (LBR_JCC        |\
+        LBR_REL_CALL   |\
+        LBR_IND_CALL   |\
+        LBR_RETURN     |\
+        LBR_REL_JMP    |\
+        LBR_IND_JMP    |\
+        LBR_FAR)
+
+#define LBR_FROM_FLAG_MISPRED  (1ULL << 63)
+#define LBR_FROM_FLAG_IN_TX    (1ULL << 62)
+#define LBR_FROM_FLAG_ABORT    (1ULL << 61)
+
+/*
+ * x86control flow change classification
+ * x86control flow changes include branches, interrupts, traps, faults
+ */
+enum {
+       X86_BR_NONE             = 0,      /* unknown */
+
+       X86_BR_USER             = 1 << 0, /* branch target is user */
+       X86_BR_KERNEL           = 1 << 1, /* branch target is kernel */
+
+       X86_BR_CALL             = 1 << 2, /* call */
+       X86_BR_RET              = 1 << 3, /* return */
+       X86_BR_SYSCALL          = 1 << 4, /* syscall */
+       X86_BR_SYSRET           = 1 << 5, /* syscall return */
+       X86_BR_INT              = 1 << 6, /* sw interrupt */
+       X86_BR_IRET             = 1 << 7, /* return from interrupt */
+       X86_BR_JCC              = 1 << 8, /* conditional */
+       X86_BR_JMP              = 1 << 9, /* jump */
+       X86_BR_IRQ              = 1 << 10,/* hw interrupt or trap or fault */
+       X86_BR_IND_CALL         = 1 << 11,/* indirect calls */
+       X86_BR_ABORT            = 1 << 12,/* transaction abort */
+       X86_BR_IN_TX            = 1 << 13,/* in transaction */
+       X86_BR_NO_TX            = 1 << 14,/* not in transaction */
+       X86_BR_ZERO_CALL        = 1 << 15,/* zero length call */
+       X86_BR_CALL_STACK       = 1 << 16,/* call stack */
+       X86_BR_IND_JMP          = 1 << 17,/* indirect jump */
+};
+
+#define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL)
+#define X86_BR_ANYTX (X86_BR_NO_TX | X86_BR_IN_TX)
+
+#define X86_BR_ANY       \
+       (X86_BR_CALL    |\
+        X86_BR_RET     |\
+        X86_BR_SYSCALL |\
+        X86_BR_SYSRET  |\
+        X86_BR_INT     |\
+        X86_BR_IRET    |\
+        X86_BR_JCC     |\
+        X86_BR_JMP      |\
+        X86_BR_IRQ      |\
+        X86_BR_ABORT    |\
+        X86_BR_IND_CALL |\
+        X86_BR_IND_JMP  |\
+        X86_BR_ZERO_CALL)
+
+#define X86_BR_ALL (X86_BR_PLM | X86_BR_ANY)
+
+#define X86_BR_ANY_CALL                 \
+       (X86_BR_CALL            |\
+        X86_BR_IND_CALL        |\
+        X86_BR_ZERO_CALL       |\
+        X86_BR_SYSCALL         |\
+        X86_BR_IRQ             |\
+        X86_BR_INT)
+
+static void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc);
+
+/*
+ * We only support LBR implementations that have FREEZE_LBRS_ON_PMI
+ * otherwise it becomes near impossible to get a reliable stack.
+ */
+
+static void __intel_pmu_lbr_enable(bool pmi)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       u64 debugctl, lbr_select = 0, orig_debugctl;
+
+       /*
+        * No need to unfreeze manually, as v4 can do that as part
+        * of the GLOBAL_STATUS ack.
+        */
+       if (pmi && x86_pmu.version >= 4)
+               return;
+
+       /*
+        * No need to reprogram LBR_SELECT in a PMI, as it
+        * did not change.
+        */
+       if (cpuc->lbr_sel)
+               lbr_select = cpuc->lbr_sel->config & x86_pmu.lbr_sel_mask;
+       if (!pmi && cpuc->lbr_sel)
+               wrmsrl(MSR_LBR_SELECT, lbr_select);
+
+       rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+       orig_debugctl = debugctl;
+       debugctl |= DEBUGCTLMSR_LBR;
+       /*
+        * LBR callstack does not work well with FREEZE_LBRS_ON_PMI.
+        * If FREEZE_LBRS_ON_PMI is set, PMI near call/return instructions
+        * may cause superfluous increase/decrease of LBR_TOS.
+        */
+       if (!(lbr_select & LBR_CALL_STACK))
+               debugctl |= DEBUGCTLMSR_FREEZE_LBRS_ON_PMI;
+       if (orig_debugctl != debugctl)
+               wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+}
+
+static void __intel_pmu_lbr_disable(void)
+{
+       u64 debugctl;
+
+       rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+       debugctl &= ~(DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI);
+       wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+}
+
+static void intel_pmu_lbr_reset_32(void)
+{
+       int i;
+
+       for (i = 0; i < x86_pmu.lbr_nr; i++)
+               wrmsrl(x86_pmu.lbr_from + i, 0);
+}
+
+static void intel_pmu_lbr_reset_64(void)
+{
+       int i;
+
+       for (i = 0; i < x86_pmu.lbr_nr; i++) {
+               wrmsrl(x86_pmu.lbr_from + i, 0);
+               wrmsrl(x86_pmu.lbr_to   + i, 0);
+               if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
+                       wrmsrl(MSR_LBR_INFO_0 + i, 0);
+       }
+}
+
+void intel_pmu_lbr_reset(void)
+{
+       if (!x86_pmu.lbr_nr)
+               return;
+
+       if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
+               intel_pmu_lbr_reset_32();
+       else
+               intel_pmu_lbr_reset_64();
+}
+
+/*
+ * TOS = most recently recorded branch
+ */
+static inline u64 intel_pmu_lbr_tos(void)
+{
+       u64 tos;
+
+       rdmsrl(x86_pmu.lbr_tos, tos);
+       return tos;
+}
+
+enum {
+       LBR_NONE,
+       LBR_VALID,
+};
+
+static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
+{
+       int i;
+       unsigned lbr_idx, mask;
+       u64 tos;
+
+       if (task_ctx->lbr_callstack_users == 0 ||
+           task_ctx->lbr_stack_state == LBR_NONE) {
+               intel_pmu_lbr_reset();
+               return;
+       }
+
+       mask = x86_pmu.lbr_nr - 1;
+       tos = task_ctx->tos;
+       for (i = 0; i < tos; i++) {
+               lbr_idx = (tos - i) & mask;
+               wrmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
+               wrmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
+               if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
+                       wrmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
+       }
+       wrmsrl(x86_pmu.lbr_tos, tos);
+       task_ctx->lbr_stack_state = LBR_NONE;
+}
+
+static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
+{
+       int i;
+       unsigned lbr_idx, mask;
+       u64 tos;
+
+       if (task_ctx->lbr_callstack_users == 0) {
+               task_ctx->lbr_stack_state = LBR_NONE;
+               return;
+       }
+
+       mask = x86_pmu.lbr_nr - 1;
+       tos = intel_pmu_lbr_tos();
+       for (i = 0; i < tos; i++) {
+               lbr_idx = (tos - i) & mask;
+               rdmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
+               rdmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
+               if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
+                       rdmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
+       }
+       task_ctx->tos = tos;
+       task_ctx->lbr_stack_state = LBR_VALID;
+}
+
+void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct x86_perf_task_context *task_ctx;
+
+       /*
+        * If LBR callstack feature is enabled and the stack was saved when
+        * the task was scheduled out, restore the stack. Otherwise flush
+        * the LBR stack.
+        */
+       task_ctx = ctx ? ctx->task_ctx_data : NULL;
+       if (task_ctx) {
+               if (sched_in) {
+                       __intel_pmu_lbr_restore(task_ctx);
+                       cpuc->lbr_context = ctx;
+               } else {
+                       __intel_pmu_lbr_save(task_ctx);
+               }
+               return;
+       }
+
+       /*
+        * When sampling the branck stack in system-wide, it may be
+        * necessary to flush the stack on context switch. This happens
+        * when the branch stack does not tag its entries with the pid
+        * of the current task. Otherwise it becomes impossible to
+        * associate a branch entry with a task. This ambiguity is more
+        * likely to appear when the branch stack supports priv level
+        * filtering and the user sets it to monitor only at the user
+        * level (which could be a useful measurement in system-wide
+        * mode). In that case, the risk is high of having a branch
+        * stack with branch from multiple tasks.
+        */
+       if (sched_in) {
+               intel_pmu_lbr_reset();
+               cpuc->lbr_context = ctx;
+       }
+}
+
+static inline bool branch_user_callstack(unsigned br_sel)
+{
+       return (br_sel & X86_BR_USER) && (br_sel & X86_BR_CALL_STACK);
+}
+
+void intel_pmu_lbr_enable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct x86_perf_task_context *task_ctx;
+
+       if (!x86_pmu.lbr_nr)
+               return;
+
+       /*
+        * Reset the LBR stack if we changed task context to
+        * avoid data leaks.
+        */
+       if (event->ctx->task && cpuc->lbr_context != event->ctx) {
+               intel_pmu_lbr_reset();
+               cpuc->lbr_context = event->ctx;
+       }
+       cpuc->br_sel = event->hw.branch_reg.reg;
+
+       if (branch_user_callstack(cpuc->br_sel) && event->ctx &&
+                                       event->ctx->task_ctx_data) {
+               task_ctx = event->ctx->task_ctx_data;
+               task_ctx->lbr_callstack_users++;
+       }
+
+       cpuc->lbr_users++;
+       perf_sched_cb_inc(event->ctx->pmu);
+}
+
+void intel_pmu_lbr_disable(struct perf_event *event)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       struct x86_perf_task_context *task_ctx;
+
+       if (!x86_pmu.lbr_nr)
+               return;
+
+       if (branch_user_callstack(cpuc->br_sel) && event->ctx &&
+                                       event->ctx->task_ctx_data) {
+               task_ctx = event->ctx->task_ctx_data;
+               task_ctx->lbr_callstack_users--;
+       }
+
+       cpuc->lbr_users--;
+       WARN_ON_ONCE(cpuc->lbr_users < 0);
+       perf_sched_cb_dec(event->ctx->pmu);
+
+       if (cpuc->enabled && !cpuc->lbr_users) {
+               __intel_pmu_lbr_disable();
+               /* avoid stale pointer */
+               cpuc->lbr_context = NULL;
+       }
+}
+
+void intel_pmu_lbr_enable_all(bool pmi)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       if (cpuc->lbr_users)
+               __intel_pmu_lbr_enable(pmi);
+}
+
+void intel_pmu_lbr_disable_all(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       if (cpuc->lbr_users)
+               __intel_pmu_lbr_disable();
+}
+
+static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
+{
+       unsigned long mask = x86_pmu.lbr_nr - 1;
+       u64 tos = intel_pmu_lbr_tos();
+       int i;
+
+       for (i = 0; i < x86_pmu.lbr_nr; i++) {
+               unsigned long lbr_idx = (tos - i) & mask;
+               union {
+                       struct {
+                               u32 from;
+                               u32 to;
+                       };
+                       u64     lbr;
+               } msr_lastbranch;
+
+               rdmsrl(x86_pmu.lbr_from + lbr_idx, msr_lastbranch.lbr);
+
+               cpuc->lbr_entries[i].from       = msr_lastbranch.from;
+               cpuc->lbr_entries[i].to         = msr_lastbranch.to;
+               cpuc->lbr_entries[i].mispred    = 0;
+               cpuc->lbr_entries[i].predicted  = 0;
+               cpuc->lbr_entries[i].reserved   = 0;
+       }
+       cpuc->lbr_stack.nr = i;
+}
+
+/*
+ * Due to lack of segmentation in Linux the effective address (offset)
+ * is the same as the linear address, allowing us to merge the LIP and EIP
+ * LBR formats.
+ */
+static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
+{
+       bool need_info = false;
+       unsigned long mask = x86_pmu.lbr_nr - 1;
+       int lbr_format = x86_pmu.intel_cap.lbr_format;
+       u64 tos = intel_pmu_lbr_tos();
+       int i;
+       int out = 0;
+       int num = x86_pmu.lbr_nr;
+
+       if (cpuc->lbr_sel) {
+               need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO);
+               if (cpuc->lbr_sel->config & LBR_CALL_STACK)
+                       num = tos;
+       }
+
+       for (i = 0; i < num; i++) {
+               unsigned long lbr_idx = (tos - i) & mask;
+               u64 from, to, mis = 0, pred = 0, in_tx = 0, abort = 0;
+               int skip = 0;
+               u16 cycles = 0;
+               int lbr_flags = lbr_desc[lbr_format];
+
+               rdmsrl(x86_pmu.lbr_from + lbr_idx, from);
+               rdmsrl(x86_pmu.lbr_to   + lbr_idx, to);
+
+               if (lbr_format == LBR_FORMAT_INFO && need_info) {
+                       u64 info;
+
+                       rdmsrl(MSR_LBR_INFO_0 + lbr_idx, info);
+                       mis = !!(info & LBR_INFO_MISPRED);
+                       pred = !mis;
+                       in_tx = !!(info & LBR_INFO_IN_TX);
+                       abort = !!(info & LBR_INFO_ABORT);
+                       cycles = (info & LBR_INFO_CYCLES);
+               }
+               if (lbr_flags & LBR_EIP_FLAGS) {
+                       mis = !!(from & LBR_FROM_FLAG_MISPRED);
+                       pred = !mis;
+                       skip = 1;
+               }
+               if (lbr_flags & LBR_TSX) {
+                       in_tx = !!(from & LBR_FROM_FLAG_IN_TX);
+                       abort = !!(from & LBR_FROM_FLAG_ABORT);
+                       skip = 3;
+               }
+               from = (u64)((((s64)from) << skip) >> skip);
+
+               /*
+                * Some CPUs report duplicated abort records,
+                * with the second entry not having an abort bit set.
+                * Skip them here. This loop runs backwards,
+                * so we need to undo the previous record.
+                * If the abort just happened outside the window
+                * the extra entry cannot be removed.
+                */
+               if (abort && x86_pmu.lbr_double_abort && out > 0)
+                       out--;
+
+               cpuc->lbr_entries[out].from      = from;
+               cpuc->lbr_entries[out].to        = to;
+               cpuc->lbr_entries[out].mispred   = mis;
+               cpuc->lbr_entries[out].predicted = pred;
+               cpuc->lbr_entries[out].in_tx     = in_tx;
+               cpuc->lbr_entries[out].abort     = abort;
+               cpuc->lbr_entries[out].cycles    = cycles;
+               cpuc->lbr_entries[out].reserved  = 0;
+               out++;
+       }
+       cpuc->lbr_stack.nr = out;
+}
+
+void intel_pmu_lbr_read(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       if (!cpuc->lbr_users)
+               return;
+
+       if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
+               intel_pmu_lbr_read_32(cpuc);
+       else
+               intel_pmu_lbr_read_64(cpuc);
+
+       intel_pmu_lbr_filter(cpuc);
+}
+
+/*
+ * SW filter is used:
+ * - in case there is no HW filter
+ * - in case the HW filter has errata or limitations
+ */
+static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
+{
+       u64 br_type = event->attr.branch_sample_type;
+       int mask = 0;
+
+       if (br_type & PERF_SAMPLE_BRANCH_USER)
+               mask |= X86_BR_USER;
+
+       if (br_type & PERF_SAMPLE_BRANCH_KERNEL)
+               mask |= X86_BR_KERNEL;
+
+       /* we ignore BRANCH_HV here */
+
+       if (br_type & PERF_SAMPLE_BRANCH_ANY)
+               mask |= X86_BR_ANY;
+
+       if (br_type & PERF_SAMPLE_BRANCH_ANY_CALL)
+               mask |= X86_BR_ANY_CALL;
+
+       if (br_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
+               mask |= X86_BR_RET | X86_BR_IRET | X86_BR_SYSRET;
+
+       if (br_type & PERF_SAMPLE_BRANCH_IND_CALL)
+               mask |= X86_BR_IND_CALL;
+
+       if (br_type & PERF_SAMPLE_BRANCH_ABORT_TX)
+               mask |= X86_BR_ABORT;
+
+       if (br_type & PERF_SAMPLE_BRANCH_IN_TX)
+               mask |= X86_BR_IN_TX;
+
+       if (br_type & PERF_SAMPLE_BRANCH_NO_TX)
+               mask |= X86_BR_NO_TX;
+
+       if (br_type & PERF_SAMPLE_BRANCH_COND)
+               mask |= X86_BR_JCC;
+
+       if (br_type & PERF_SAMPLE_BRANCH_CALL_STACK) {
+               if (!x86_pmu_has_lbr_callstack())
+                       return -EOPNOTSUPP;
+               if (mask & ~(X86_BR_USER | X86_BR_KERNEL))
+                       return -EINVAL;
+               mask |= X86_BR_CALL | X86_BR_IND_CALL | X86_BR_RET |
+                       X86_BR_CALL_STACK;
+       }
+
+       if (br_type & PERF_SAMPLE_BRANCH_IND_JUMP)
+               mask |= X86_BR_IND_JMP;
+
+       if (br_type & PERF_SAMPLE_BRANCH_CALL)
+               mask |= X86_BR_CALL | X86_BR_ZERO_CALL;
+       /*
+        * stash actual user request into reg, it may
+        * be used by fixup code for some CPU
+        */
+       event->hw.branch_reg.reg = mask;
+       return 0;
+}
+
+/*
+ * setup the HW LBR filter
+ * Used only when available, may not be enough to disambiguate
+ * all branches, may need the help of the SW filter
+ */
+static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg;
+       u64 br_type = event->attr.branch_sample_type;
+       u64 mask = 0, v;
+       int i;
+
+       for (i = 0; i < PERF_SAMPLE_BRANCH_MAX_SHIFT; i++) {
+               if (!(br_type & (1ULL << i)))
+                       continue;
+
+               v = x86_pmu.lbr_sel_map[i];
+               if (v == LBR_NOT_SUPP)
+                       return -EOPNOTSUPP;
+
+               if (v != LBR_IGN)
+                       mask |= v;
+       }
+
+       reg = &event->hw.branch_reg;
+       reg->idx = EXTRA_REG_LBR;
+
+       /*
+        * The first 9 bits (LBR_SEL_MASK) in LBR_SELECT operate
+        * in suppress mode. So LBR_SELECT should be set to
+        * (~mask & LBR_SEL_MASK) | (mask & ~LBR_SEL_MASK)
+        */
+       reg->config = mask ^ x86_pmu.lbr_sel_mask;
+
+       if ((br_type & PERF_SAMPLE_BRANCH_NO_CYCLES) &&
+           (br_type & PERF_SAMPLE_BRANCH_NO_FLAGS) &&
+           (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO))
+               reg->config |= LBR_NO_INFO;
+
+       return 0;
+}
+
+int intel_pmu_setup_lbr_filter(struct perf_event *event)
+{
+       int ret = 0;
+
+       /*
+        * no LBR on this PMU
+        */
+       if (!x86_pmu.lbr_nr)
+               return -EOPNOTSUPP;
+
+       /*
+        * setup SW LBR filter
+        */
+       ret = intel_pmu_setup_sw_lbr_filter(event);
+       if (ret)
+               return ret;
+
+       /*
+        * setup HW LBR filter, if any
+        */
+       if (x86_pmu.lbr_sel_map)
+               ret = intel_pmu_setup_hw_lbr_filter(event);
+
+       return ret;
+}
+
+/*
+ * return the type of control flow change at address "from"
+ * intruction is not necessarily a branch (in case of interrupt).
+ *
+ * The branch type returned also includes the priv level of the
+ * target of the control flow change (X86_BR_USER, X86_BR_KERNEL).
+ *
+ * If a branch type is unknown OR the instruction cannot be
+ * decoded (e.g., text page not present), then X86_BR_NONE is
+ * returned.
+ */
+static int branch_type(unsigned long from, unsigned long to, int abort)
+{
+       struct insn insn;
+       void *addr;
+       int bytes_read, bytes_left;
+       int ret = X86_BR_NONE;
+       int ext, to_plm, from_plm;
+       u8 buf[MAX_INSN_SIZE];
+       int is64 = 0;
+
+       to_plm = kernel_ip(to) ? X86_BR_KERNEL : X86_BR_USER;
+       from_plm = kernel_ip(from) ? X86_BR_KERNEL : X86_BR_USER;
+
+       /*
+        * maybe zero if lbr did not fill up after a reset by the time
+        * we get a PMU interrupt
+        */
+       if (from == 0 || to == 0)
+               return X86_BR_NONE;
+
+       if (abort)
+               return X86_BR_ABORT | to_plm;
+
+       if (from_plm == X86_BR_USER) {
+               /*
+                * can happen if measuring at the user level only
+                * and we interrupt in a kernel thread, e.g., idle.
+                */
+               if (!current->mm)
+                       return X86_BR_NONE;
+
+               /* may fail if text not present */
+               bytes_left = copy_from_user_nmi(buf, (void __user *)from,
+                                               MAX_INSN_SIZE);
+               bytes_read = MAX_INSN_SIZE - bytes_left;
+               if (!bytes_read)
+                       return X86_BR_NONE;
+
+               addr = buf;
+       } else {
+               /*
+                * The LBR logs any address in the IP, even if the IP just
+                * faulted. This means userspace can control the from address.
+                * Ensure we don't blindy read any address by validating it is
+                * a known text address.
+                */
+               if (kernel_text_address(from)) {
+                       addr = (void *)from;
+                       /*
+                        * Assume we can get the maximum possible size
+                        * when grabbing kernel data.  This is not
+                        * _strictly_ true since we could possibly be
+                        * executing up next to a memory hole, but
+                        * it is very unlikely to be a problem.
+                        */
+                       bytes_read = MAX_INSN_SIZE;
+               } else {
+                       return X86_BR_NONE;
+               }
+       }
+
+       /*
+        * decoder needs to know the ABI especially
+        * on 64-bit systems running 32-bit apps
+        */
+#ifdef CONFIG_X86_64
+       is64 = kernel_ip((unsigned long)addr) || !test_thread_flag(TIF_IA32);
+#endif
+       insn_init(&insn, addr, bytes_read, is64);
+       insn_get_opcode(&insn);
+       if (!insn.opcode.got)
+               return X86_BR_ABORT;
+
+       switch (insn.opcode.bytes[0]) {
+       case 0xf:
+               switch (insn.opcode.bytes[1]) {
+               case 0x05: /* syscall */
+               case 0x34: /* sysenter */
+                       ret = X86_BR_SYSCALL;
+                       break;
+               case 0x07: /* sysret */
+               case 0x35: /* sysexit */
+                       ret = X86_BR_SYSRET;
+                       break;
+               case 0x80 ... 0x8f: /* conditional */
+                       ret = X86_BR_JCC;
+                       break;
+               default:
+                       ret = X86_BR_NONE;
+               }
+               break;
+       case 0x70 ... 0x7f: /* conditional */
+               ret = X86_BR_JCC;
+               break;
+       case 0xc2: /* near ret */
+       case 0xc3: /* near ret */
+       case 0xca: /* far ret */
+       case 0xcb: /* far ret */
+               ret = X86_BR_RET;
+               break;
+       case 0xcf: /* iret */
+               ret = X86_BR_IRET;
+               break;
+       case 0xcc ... 0xce: /* int */
+               ret = X86_BR_INT;
+               break;
+       case 0xe8: /* call near rel */
+               insn_get_immediate(&insn);
+               if (insn.immediate1.value == 0) {
+                       /* zero length call */
+                       ret = X86_BR_ZERO_CALL;
+                       break;
+               }
+       case 0x9a: /* call far absolute */
+               ret = X86_BR_CALL;
+               break;
+       case 0xe0 ... 0xe3: /* loop jmp */
+               ret = X86_BR_JCC;
+               break;
+       case 0xe9 ... 0xeb: /* jmp */
+               ret = X86_BR_JMP;
+               break;
+       case 0xff: /* call near absolute, call far absolute ind */
+               insn_get_modrm(&insn);
+               ext = (insn.modrm.bytes[0] >> 3) & 0x7;
+               switch (ext) {
+               case 2: /* near ind call */
+               case 3: /* far ind call */
+                       ret = X86_BR_IND_CALL;
+                       break;
+               case 4:
+               case 5:
+                       ret = X86_BR_IND_JMP;
+                       break;
+               }
+               break;
+       default:
+               ret = X86_BR_NONE;
+       }
+       /*
+        * interrupts, traps, faults (and thus ring transition) may
+        * occur on any instructions. Thus, to classify them correctly,
+        * we need to first look at the from and to priv levels. If they
+        * are different and to is in the kernel, then it indicates
+        * a ring transition. If the from instruction is not a ring
+        * transition instr (syscall, systenter, int), then it means
+        * it was a irq, trap or fault.
+        *
+        * we have no way of detecting kernel to kernel faults.
+        */
+       if (from_plm == X86_BR_USER && to_plm == X86_BR_KERNEL
+           && ret != X86_BR_SYSCALL && ret != X86_BR_INT)
+               ret = X86_BR_IRQ;
+
+       /*
+        * branch priv level determined by target as
+        * is done by HW when LBR_SELECT is implemented
+        */
+       if (ret != X86_BR_NONE)
+               ret |= to_plm;
+
+       return ret;
+}
+
+/*
+ * implement actual branch filter based on user demand.
+ * Hardware may not exactly satisfy that request, thus
+ * we need to inspect opcodes. Mismatched branches are
+ * discarded. Therefore, the number of branches returned
+ * in PERF_SAMPLE_BRANCH_STACK sample may vary.
+ */
+static void
+intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
+{
+       u64 from, to;
+       int br_sel = cpuc->br_sel;
+       int i, j, type;
+       bool compress = false;
+
+       /* if sampling all branches, then nothing to filter */
+       if ((br_sel & X86_BR_ALL) == X86_BR_ALL)
+               return;
+
+       for (i = 0; i < cpuc->lbr_stack.nr; i++) {
+
+               from = cpuc->lbr_entries[i].from;
+               to = cpuc->lbr_entries[i].to;
+
+               type = branch_type(from, to, cpuc->lbr_entries[i].abort);
+               if (type != X86_BR_NONE && (br_sel & X86_BR_ANYTX)) {
+                       if (cpuc->lbr_entries[i].in_tx)
+                               type |= X86_BR_IN_TX;
+                       else
+                               type |= X86_BR_NO_TX;
+               }
+
+               /* if type does not correspond, then discard */
+               if (type == X86_BR_NONE || (br_sel & type) != type) {
+                       cpuc->lbr_entries[i].from = 0;
+                       compress = true;
+               }
+       }
+
+       if (!compress)
+               return;
+
+       /* remove all entries with from=0 */
+       for (i = 0; i < cpuc->lbr_stack.nr; ) {
+               if (!cpuc->lbr_entries[i].from) {
+                       j = i;
+                       while (++j < cpuc->lbr_stack.nr)
+                               cpuc->lbr_entries[j-1] = cpuc->lbr_entries[j];
+                       cpuc->lbr_stack.nr--;
+                       if (!cpuc->lbr_entries[i].from)
+                               continue;
+               }
+               i++;
+       }
+}
+
+/*
+ * Map interface branch filters onto LBR filters
+ */
+static const int nhm_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
+       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
+       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
+       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
+       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
+       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_REL_JMP
+                                               | LBR_IND_JMP | LBR_FAR,
+       /*
+        * NHM/WSM erratum: must include REL_JMP+IND_JMP to get CALL branches
+        */
+       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT] =
+        LBR_REL_CALL | LBR_IND_CALL | LBR_REL_JMP | LBR_IND_JMP | LBR_FAR,
+       /*
+        * NHM/WSM erratum: must include IND_JMP to capture IND_CALL
+        */
+       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_IND_CALL | LBR_IND_JMP,
+       [PERF_SAMPLE_BRANCH_COND_SHIFT]     = LBR_JCC,
+       [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT] = LBR_IND_JMP,
+};
+
+static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
+       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
+       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
+       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
+       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
+       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_FAR,
+       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]     = LBR_REL_CALL | LBR_IND_CALL
+                                               | LBR_FAR,
+       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]     = LBR_IND_CALL,
+       [PERF_SAMPLE_BRANCH_COND_SHIFT]         = LBR_JCC,
+       [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT]     = LBR_IND_JMP,
+       [PERF_SAMPLE_BRANCH_CALL_SHIFT]         = LBR_REL_CALL,
+};
+
+static const int hsw_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
+       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
+       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
+       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
+       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
+       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_FAR,
+       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]     = LBR_REL_CALL | LBR_IND_CALL
+                                               | LBR_FAR,
+       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]     = LBR_IND_CALL,
+       [PERF_SAMPLE_BRANCH_COND_SHIFT]         = LBR_JCC,
+       [PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT]   = LBR_REL_CALL | LBR_IND_CALL
+                                               | LBR_RETURN | LBR_CALL_STACK,
+       [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT]     = LBR_IND_JMP,
+       [PERF_SAMPLE_BRANCH_CALL_SHIFT]         = LBR_REL_CALL,
+};
+
+/* core */
+void __init intel_pmu_lbr_init_core(void)
+{
+       x86_pmu.lbr_nr     = 4;
+       x86_pmu.lbr_tos    = MSR_LBR_TOS;
+       x86_pmu.lbr_from   = MSR_LBR_CORE_FROM;
+       x86_pmu.lbr_to     = MSR_LBR_CORE_TO;
+
+       /*
+        * SW branch filter usage:
+        * - compensate for lack of HW filter
+        */
+       pr_cont("4-deep LBR, ");
+}
+
+/* nehalem/westmere */
+void __init intel_pmu_lbr_init_nhm(void)
+{
+       x86_pmu.lbr_nr     = 16;
+       x86_pmu.lbr_tos    = MSR_LBR_TOS;
+       x86_pmu.lbr_from   = MSR_LBR_NHM_FROM;
+       x86_pmu.lbr_to     = MSR_LBR_NHM_TO;
+
+       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
+       x86_pmu.lbr_sel_map  = nhm_lbr_sel_map;
+
+       /*
+        * SW branch filter usage:
+        * - workaround LBR_SEL errata (see above)
+        * - support syscall, sysret capture.
+        *   That requires LBR_FAR but that means far
+        *   jmp need to be filtered out
+        */
+       pr_cont("16-deep LBR, ");
+}
+
+/* sandy bridge */
+void __init intel_pmu_lbr_init_snb(void)
+{
+       x86_pmu.lbr_nr   = 16;
+       x86_pmu.lbr_tos  = MSR_LBR_TOS;
+       x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
+       x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
+
+       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
+       x86_pmu.lbr_sel_map  = snb_lbr_sel_map;
+
+       /*
+        * SW branch filter usage:
+        * - support syscall, sysret capture.
+        *   That requires LBR_FAR but that means far
+        *   jmp need to be filtered out
+        */
+       pr_cont("16-deep LBR, ");
+}
+
+/* haswell */
+void intel_pmu_lbr_init_hsw(void)
+{
+       x86_pmu.lbr_nr   = 16;
+       x86_pmu.lbr_tos  = MSR_LBR_TOS;
+       x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
+       x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
+
+       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
+       x86_pmu.lbr_sel_map  = hsw_lbr_sel_map;
+
+       pr_cont("16-deep LBR, ");
+}
+
+/* skylake */
+__init void intel_pmu_lbr_init_skl(void)
+{
+       x86_pmu.lbr_nr   = 32;
+       x86_pmu.lbr_tos  = MSR_LBR_TOS;
+       x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
+       x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
+
+       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
+       x86_pmu.lbr_sel_map  = hsw_lbr_sel_map;
+
+       /*
+        * SW branch filter usage:
+        * - support syscall, sysret capture.
+        *   That requires LBR_FAR but that means far
+        *   jmp need to be filtered out
+        */
+       pr_cont("32-deep LBR, ");
+}
+
+/* atom */
+void __init intel_pmu_lbr_init_atom(void)
+{
+       /*
+        * only models starting at stepping 10 seems
+        * to have an operational LBR which can freeze
+        * on PMU interrupt
+        */
+       if (boot_cpu_data.x86_model == 28
+           && boot_cpu_data.x86_mask < 10) {
+               pr_cont("LBR disabled due to erratum");
+               return;
+       }
+
+       x86_pmu.lbr_nr     = 8;
+       x86_pmu.lbr_tos    = MSR_LBR_TOS;
+       x86_pmu.lbr_from   = MSR_LBR_CORE_FROM;
+       x86_pmu.lbr_to     = MSR_LBR_CORE_TO;
+
+       /*
+        * SW branch filter usage:
+        * - compensate for lack of HW filter
+        */
+       pr_cont("8-deep LBR, ");
+}
+
+/* Knights Landing */
+void intel_pmu_lbr_init_knl(void)
+{
+       x86_pmu.lbr_nr     = 8;
+       x86_pmu.lbr_tos    = MSR_LBR_TOS;
+       x86_pmu.lbr_from   = MSR_LBR_NHM_FROM;
+       x86_pmu.lbr_to     = MSR_LBR_NHM_TO;
+
+       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
+       x86_pmu.lbr_sel_map  = snb_lbr_sel_map;
+
+       pr_cont("8-deep LBR, ");
+}
diff --git a/arch/x86/events/intel/p4.c b/arch/x86/events/intel/p4.c
new file mode 100644 (file)
index 0000000..0a5ede1
--- /dev/null
@@ -0,0 +1,1376 @@
+/*
+ * Netburst Performance Events (P4, old Xeon)
+ *
+ *  Copyright (C) 2010 Parallels, Inc., Cyrill Gorcunov <gorcunov@openvz.org>
+ *  Copyright (C) 2010 Intel Corporation, Lin Ming <ming.m.lin@intel.com>
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+
+#include <asm/perf_event_p4.h>
+#include <asm/hardirq.h>
+#include <asm/apic.h>
+
+#include "../perf_event.h"
+
+#define P4_CNTR_LIMIT 3
+/*
+ * array indices: 0,1 - HT threads, used with HT enabled cpu
+ */
+struct p4_event_bind {
+       unsigned int opcode;                    /* Event code and ESCR selector */
+       unsigned int escr_msr[2];               /* ESCR MSR for this event */
+       unsigned int escr_emask;                /* valid ESCR EventMask bits */
+       unsigned int shared;                    /* event is shared across threads */
+       char cntr[2][P4_CNTR_LIMIT];            /* counter index (offset), -1 on abscence */
+};
+
+struct p4_pebs_bind {
+       unsigned int metric_pebs;
+       unsigned int metric_vert;
+};
+
+/* it sets P4_PEBS_ENABLE_UOP_TAG as well */
+#define P4_GEN_PEBS_BIND(name, pebs, vert)                     \
+       [P4_PEBS_METRIC__##name] = {                            \
+               .metric_pebs = pebs | P4_PEBS_ENABLE_UOP_TAG,   \
+               .metric_vert = vert,                            \
+       }
+
+/*
+ * note we have P4_PEBS_ENABLE_UOP_TAG always set here
+ *
+ * it's needed for mapping P4_PEBS_CONFIG_METRIC_MASK bits of
+ * event configuration to find out which values are to be
+ * written into MSR_IA32_PEBS_ENABLE and MSR_P4_PEBS_MATRIX_VERT
+ * resgisters
+ */
+static struct p4_pebs_bind p4_pebs_bind_map[] = {
+       P4_GEN_PEBS_BIND(1stl_cache_load_miss_retired,  0x0000001, 0x0000001),
+       P4_GEN_PEBS_BIND(2ndl_cache_load_miss_retired,  0x0000002, 0x0000001),
+       P4_GEN_PEBS_BIND(dtlb_load_miss_retired,        0x0000004, 0x0000001),
+       P4_GEN_PEBS_BIND(dtlb_store_miss_retired,       0x0000004, 0x0000002),
+       P4_GEN_PEBS_BIND(dtlb_all_miss_retired,         0x0000004, 0x0000003),
+       P4_GEN_PEBS_BIND(tagged_mispred_branch,         0x0018000, 0x0000010),
+       P4_GEN_PEBS_BIND(mob_load_replay_retired,       0x0000200, 0x0000001),
+       P4_GEN_PEBS_BIND(split_load_retired,            0x0000400, 0x0000001),
+       P4_GEN_PEBS_BIND(split_store_retired,           0x0000400, 0x0000002),
+};
+
+/*
+ * Note that we don't use CCCR1 here, there is an
+ * exception for P4_BSQ_ALLOCATION but we just have
+ * no workaround
+ *
+ * consider this binding as resources which particular
+ * event may borrow, it doesn't contain EventMask,
+ * Tags and friends -- they are left to a caller
+ */
+static struct p4_event_bind p4_event_bind_map[] = {
+       [P4_EVENT_TC_DELIVER_MODE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_TC_DELIVER_MODE),
+               .escr_msr       = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DD)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DB)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DI)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BD)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BB)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BI)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, ID),
+               .shared         = 1,
+               .cntr           = { {4, 5, -1}, {6, 7, -1} },
+       },
+       [P4_EVENT_BPU_FETCH_REQUEST] = {
+               .opcode         = P4_OPCODE(P4_EVENT_BPU_FETCH_REQUEST),
+               .escr_msr       = { MSR_P4_BPU_ESCR0, MSR_P4_BPU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BPU_FETCH_REQUEST, TCMISS),
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_ITLB_REFERENCE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_ITLB_REFERENCE),
+               .escr_msr       = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, MISS)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT_UK),
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_MEMORY_CANCEL] = {
+               .opcode         = P4_OPCODE(P4_EVENT_MEMORY_CANCEL),
+               .escr_msr       = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, ST_RB_FULL)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, 64K_CONF),
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_MEMORY_COMPLETE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_MEMORY_COMPLETE),
+               .escr_msr       = { MSR_P4_SAAT_ESCR0 , MSR_P4_SAAT_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, LSC)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, SSC),
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_LOAD_PORT_REPLAY] = {
+               .opcode         = P4_OPCODE(P4_EVENT_LOAD_PORT_REPLAY),
+               .escr_msr       = { MSR_P4_SAAT_ESCR0, MSR_P4_SAAT_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_LOAD_PORT_REPLAY, SPLIT_LD),
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_STORE_PORT_REPLAY] = {
+               .opcode         = P4_OPCODE(P4_EVENT_STORE_PORT_REPLAY),
+               .escr_msr       = { MSR_P4_SAAT_ESCR0 ,  MSR_P4_SAAT_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_STORE_PORT_REPLAY, SPLIT_ST),
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_MOB_LOAD_REPLAY] = {
+               .opcode         = P4_OPCODE(P4_EVENT_MOB_LOAD_REPLAY),
+               .escr_msr       = { MSR_P4_MOB_ESCR0, MSR_P4_MOB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STA)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STD)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, PARTIAL_DATA)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, UNALGN_ADDR),
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_PAGE_WALK_TYPE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_PAGE_WALK_TYPE),
+               .escr_msr       = { MSR_P4_PMH_ESCR0, MSR_P4_PMH_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, DTMISS)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, ITMISS),
+               .shared         = 1,
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_BSQ_CACHE_REFERENCE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_BSQ_CACHE_REFERENCE),
+               .escr_msr       = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS),
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_IOQ_ALLOCATION] = {
+               .opcode         = P4_OPCODE(P4_EVENT_IOQ_ALLOCATION),
+               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, DEFAULT)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_READ)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_WRITE)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_UC)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WC)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WT)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WP)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WB)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OWN)                 |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OTHER)               |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, PREFETCH),
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_IOQ_ACTIVE_ENTRIES] = {       /* shared ESCR */
+               .opcode         = P4_OPCODE(P4_EVENT_IOQ_ACTIVE_ENTRIES),
+               .escr_msr       = { MSR_P4_FSB_ESCR1,  MSR_P4_FSB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, DEFAULT)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_READ)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_WRITE)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_UC)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WC)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WT)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WP)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WB)          |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OWN)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OTHER)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, PREFETCH),
+               .cntr           = { {2, -1, -1}, {3, -1, -1} },
+       },
+       [P4_EVENT_FSB_DATA_ACTIVITY] = {
+               .opcode         = P4_OPCODE(P4_EVENT_FSB_DATA_ACTIVITY),
+               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OTHER)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_DRV)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OWN)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OTHER),
+               .shared         = 1,
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_BSQ_ALLOCATION] = {           /* shared ESCR, broken CCCR1 */
+               .opcode         = P4_OPCODE(P4_EVENT_BSQ_ALLOCATION),
+               .escr_msr       = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR0 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE0)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE1)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN0)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN1)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_IO_TYPE)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LOCK_TYPE)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_CACHE_TYPE)      |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_SPLIT_TYPE)      |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_DEM_TYPE)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_ORD_TYPE)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE0)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE1)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE2),
+               .cntr           = { {0, -1, -1}, {1, -1, -1} },
+       },
+       [P4_EVENT_BSQ_ACTIVE_ENTRIES] = {       /* shared ESCR */
+               .opcode         = P4_OPCODE(P4_EVENT_BSQ_ACTIVE_ENTRIES),
+               .escr_msr       = { MSR_P4_BSU_ESCR1 , MSR_P4_BSU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE0)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE1)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN0)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN1)        |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_IO_TYPE)     |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LOCK_TYPE)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_CACHE_TYPE)  |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_SPLIT_TYPE)  |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_DEM_TYPE)    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_ORD_TYPE)    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE0)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE1)       |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE2),
+               .cntr           = { {2, -1, -1}, {3, -1, -1} },
+       },
+       [P4_EVENT_SSE_INPUT_ASSIST] = {
+               .opcode         = P4_OPCODE(P4_EVENT_SSE_INPUT_ASSIST),
+               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_SSE_INPUT_ASSIST, ALL),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_PACKED_SP_UOP] = {
+               .opcode         = P4_OPCODE(P4_EVENT_PACKED_SP_UOP),
+               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_SP_UOP, ALL),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_PACKED_DP_UOP] = {
+               .opcode         = P4_OPCODE(P4_EVENT_PACKED_DP_UOP),
+               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_DP_UOP, ALL),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_SCALAR_SP_UOP] = {
+               .opcode         = P4_OPCODE(P4_EVENT_SCALAR_SP_UOP),
+               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_SP_UOP, ALL),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_SCALAR_DP_UOP] = {
+               .opcode         = P4_OPCODE(P4_EVENT_SCALAR_DP_UOP),
+               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_DP_UOP, ALL),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_64BIT_MMX_UOP] = {
+               .opcode         = P4_OPCODE(P4_EVENT_64BIT_MMX_UOP),
+               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_64BIT_MMX_UOP, ALL),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_128BIT_MMX_UOP] = {
+               .opcode         = P4_OPCODE(P4_EVENT_128BIT_MMX_UOP),
+               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_128BIT_MMX_UOP, ALL),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_X87_FP_UOP] = {
+               .opcode         = P4_OPCODE(P4_EVENT_X87_FP_UOP),
+               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_FP_UOP, ALL),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_TC_MISC] = {
+               .opcode         = P4_OPCODE(P4_EVENT_TC_MISC),
+               .escr_msr       = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_MISC, FLUSH),
+               .cntr           = { {4, 5, -1}, {6, 7, -1} },
+       },
+       [P4_EVENT_GLOBAL_POWER_EVENTS] = {
+               .opcode         = P4_OPCODE(P4_EVENT_GLOBAL_POWER_EVENTS),
+               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING),
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_TC_MS_XFER] = {
+               .opcode         = P4_OPCODE(P4_EVENT_TC_MS_XFER),
+               .escr_msr       = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_MS_XFER, CISC),
+               .cntr           = { {4, 5, -1}, {6, 7, -1} },
+       },
+       [P4_EVENT_UOP_QUEUE_WRITES] = {
+               .opcode         = P4_OPCODE(P4_EVENT_UOP_QUEUE_WRITES),
+               .escr_msr       = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_BUILD)     |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_DELIVER)   |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_ROM),
+               .cntr           = { {4, 5, -1}, {6, 7, -1} },
+       },
+       [P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE),
+               .escr_msr       = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR0 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CONDITIONAL)    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CALL)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, RETURN)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, INDIRECT),
+               .cntr           = { {4, 5, -1}, {6, 7, -1} },
+       },
+       [P4_EVENT_RETIRED_BRANCH_TYPE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_RETIRED_BRANCH_TYPE),
+               .escr_msr       = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL)    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CALL)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN)         |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT),
+               .cntr           = { {4, 5, -1}, {6, 7, -1} },
+       },
+       [P4_EVENT_RESOURCE_STALL] = {
+               .opcode         = P4_OPCODE(P4_EVENT_RESOURCE_STALL),
+               .escr_msr       = { MSR_P4_ALF_ESCR0, MSR_P4_ALF_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_RESOURCE_STALL, SBFULL),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_WC_BUFFER] = {
+               .opcode         = P4_OPCODE(P4_EVENT_WC_BUFFER),
+               .escr_msr       = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_EVICTS)               |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_FULL_EVICTS),
+               .shared         = 1,
+               .cntr           = { {8, 9, -1}, {10, 11, -1} },
+       },
+       [P4_EVENT_B2B_CYCLES] = {
+               .opcode         = P4_OPCODE(P4_EVENT_B2B_CYCLES),
+               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     = 0,
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_BNR] = {
+               .opcode         = P4_OPCODE(P4_EVENT_BNR),
+               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     = 0,
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_SNOOP] = {
+               .opcode         = P4_OPCODE(P4_EVENT_SNOOP),
+               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     = 0,
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_RESPONSE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_RESPONSE),
+               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
+               .escr_emask     = 0,
+               .cntr           = { {0, -1, -1}, {2, -1, -1} },
+       },
+       [P4_EVENT_FRONT_END_EVENT] = {
+               .opcode         = P4_OPCODE(P4_EVENT_FRONT_END_EVENT),
+               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, NBOGUS)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, BOGUS),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_EXECUTION_EVENT] = {
+               .opcode         = P4_OPCODE(P4_EVENT_EXECUTION_EVENT),
+               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_REPLAY_EVENT] = {
+               .opcode         = P4_OPCODE(P4_EVENT_REPLAY_EVENT),
+               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, NBOGUS)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, BOGUS),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_INSTR_RETIRED] = {
+               .opcode         = P4_OPCODE(P4_EVENT_INSTR_RETIRED),
+               .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG)           |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSTAG)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSNTAG)            |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSTAG),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_UOPS_RETIRED] = {
+               .opcode         = P4_OPCODE(P4_EVENT_UOPS_RETIRED),
+               .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, NBOGUS)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, BOGUS),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_UOP_TYPE] = {
+               .opcode         = P4_OPCODE(P4_EVENT_UOP_TYPE),
+               .escr_msr       = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGLOADS)                  |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGSTORES),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_BRANCH_RETIRED] = {
+               .opcode         = P4_OPCODE(P4_EVENT_BRANCH_RETIRED),
+               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNP)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNM)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTP)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTM),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_MISPRED_BRANCH_RETIRED] = {
+               .opcode         = P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED),
+               .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_X87_ASSIST] = {
+               .opcode         = P4_OPCODE(P4_EVENT_X87_ASSIST),
+               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSU)                    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSO)                    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAO)                    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAU)                    |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, PREA),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_MACHINE_CLEAR] = {
+               .opcode         = P4_OPCODE(P4_EVENT_MACHINE_CLEAR),
+               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, CLEAR)                |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, MOCLEAR)              |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, SMCLEAR),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+       [P4_EVENT_INSTR_COMPLETED] = {
+               .opcode         = P4_OPCODE(P4_EVENT_INSTR_COMPLETED),
+               .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
+               .escr_emask     =
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, NBOGUS)             |
+                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, BOGUS),
+               .cntr           = { {12, 13, 16}, {14, 15, 17} },
+       },
+};
+
+#define P4_GEN_CACHE_EVENT(event, bit, metric)                           \
+       p4_config_pack_escr(P4_ESCR_EVENT(event)                        | \
+                           P4_ESCR_EMASK_BIT(event, bit))              | \
+       p4_config_pack_cccr(metric                                      | \
+                           P4_CCCR_ESEL(P4_OPCODE_ESEL(P4_OPCODE(event))))
+
+static __initconst const u64 p4_hw_cache_event_ids
+                               [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) ] = 0x0,
+               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS,
+                                               P4_PEBS_METRIC__1stl_cache_load_miss_retired),
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS,
+                                               P4_PEBS_METRIC__2ndl_cache_load_miss_retired),
+       },
+},
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS,
+                                               P4_PEBS_METRIC__dtlb_load_miss_retired),
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0,
+               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS,
+                                               P4_PEBS_METRIC__dtlb_store_miss_retired),
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, HIT,
+                                               P4_PEBS_METRIC__none),
+               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, MISS,
+                                               P4_PEBS_METRIC__none),
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(NODE) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+};
+
+/*
+ * Because of Netburst being quite restricted in how many
+ * identical events may run simultaneously, we introduce event aliases,
+ * ie the different events which have the same functionality but
+ * utilize non-intersected resources (ESCR/CCCR/counter registers).
+ *
+ * This allow us to relax restrictions a bit and run two or more
+ * identical events together.
+ *
+ * Never set any custom internal bits such as P4_CONFIG_HT,
+ * P4_CONFIG_ALIASABLE or bits for P4_PEBS_METRIC, they are
+ * either up to date automatically or not applicable at all.
+ */
+struct p4_event_alias {
+       u64 original;
+       u64 alternative;
+} p4_event_aliases[] = {
+       {
+               /*
+                * Non-halted cycles can be substituted with non-sleeping cycles (see
+                * Intel SDM Vol3b for details). We need this alias to be able
+                * to run nmi-watchdog and 'perf top' (or any other user space tool
+                * which is interested in running PERF_COUNT_HW_CPU_CYCLES)
+                * simultaneously.
+                */
+       .original       =
+               p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS)         |
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)),
+       .alternative    =
+               p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_EXECUTION_EVENT)             |
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)|
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)|
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)|
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)|
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0) |
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1) |
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2) |
+                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3))|
+               p4_config_pack_cccr(P4_CCCR_THRESHOLD(15) | P4_CCCR_COMPLEMENT          |
+                                   P4_CCCR_COMPARE),
+       },
+};
+
+static u64 p4_get_alias_event(u64 config)
+{
+       u64 config_match;
+       int i;
+
+       /*
+        * Only event with special mark is allowed,
+        * we're to be sure it didn't come as malformed
+        * RAW event.
+        */
+       if (!(config & P4_CONFIG_ALIASABLE))
+               return 0;
+
+       config_match = config & P4_CONFIG_EVENT_ALIAS_MASK;
+
+       for (i = 0; i < ARRAY_SIZE(p4_event_aliases); i++) {
+               if (config_match == p4_event_aliases[i].original) {
+                       config_match = p4_event_aliases[i].alternative;
+                       break;
+               } else if (config_match == p4_event_aliases[i].alternative) {
+                       config_match = p4_event_aliases[i].original;
+                       break;
+               }
+       }
+
+       if (i >= ARRAY_SIZE(p4_event_aliases))
+               return 0;
+
+       return config_match | (config & P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS);
+}
+
+static u64 p4_general_events[PERF_COUNT_HW_MAX] = {
+  /* non-halted CPU clocks */
+  [PERF_COUNT_HW_CPU_CYCLES] =
+       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS)         |
+               P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING))       |
+               P4_CONFIG_ALIASABLE,
+
+  /*
+   * retired instructions
+   * in a sake of simplicity we don't use the FSB tagging
+   */
+  [PERF_COUNT_HW_INSTRUCTIONS] =
+       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_INSTR_RETIRED)               |
+               P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG)           |
+               P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSNTAG)),
+
+  /* cache hits */
+  [PERF_COUNT_HW_CACHE_REFERENCES] =
+       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_BSQ_CACHE_REFERENCE)         |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS)   |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE)   |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM)   |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS)   |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE)   |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM)),
+
+  /* cache misses */
+  [PERF_COUNT_HW_CACHE_MISSES] =
+       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_BSQ_CACHE_REFERENCE)         |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS)   |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS)   |
+               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS)),
+
+  /* branch instructions retired */
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =
+       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_RETIRED_BRANCH_TYPE)         |
+               P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL)    |
+               P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CALL)           |
+               P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN)         |
+               P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT)),
+
+  /* mispredicted branches retired */
+  [PERF_COUNT_HW_BRANCH_MISSES]        =
+       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_MISPRED_BRANCH_RETIRED)      |
+               P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS)),
+
+  /* bus ready clocks (cpu is driving #DRDY_DRV\#DRDY_OWN):  */
+  [PERF_COUNT_HW_BUS_CYCLES] =
+       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_FSB_DATA_ACTIVITY)           |
+               P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV)         |
+               P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN))        |
+       p4_config_pack_cccr(P4_CCCR_EDGE | P4_CCCR_COMPARE),
+};
+
+static struct p4_event_bind *p4_config_get_bind(u64 config)
+{
+       unsigned int evnt = p4_config_unpack_event(config);
+       struct p4_event_bind *bind = NULL;
+
+       if (evnt < ARRAY_SIZE(p4_event_bind_map))
+               bind = &p4_event_bind_map[evnt];
+
+       return bind;
+}
+
+static u64 p4_pmu_event_map(int hw_event)
+{
+       struct p4_event_bind *bind;
+       unsigned int esel;
+       u64 config;
+
+       config = p4_general_events[hw_event];
+       bind = p4_config_get_bind(config);
+       esel = P4_OPCODE_ESEL(bind->opcode);
+       config |= p4_config_pack_cccr(P4_CCCR_ESEL(esel));
+
+       return config;
+}
+
+/* check cpu model specifics */
+static bool p4_event_match_cpu_model(unsigned int event_idx)
+{
+       /* INSTR_COMPLETED event only exist for model 3, 4, 6 (Prescott) */
+       if (event_idx == P4_EVENT_INSTR_COMPLETED) {
+               if (boot_cpu_data.x86_model != 3 &&
+                       boot_cpu_data.x86_model != 4 &&
+                       boot_cpu_data.x86_model != 6)
+                       return false;
+       }
+
+       /*
+        * For info
+        * - IQ_ESCR0, IQ_ESCR1 only for models 1 and 2
+        */
+
+       return true;
+}
+
+static int p4_validate_raw_event(struct perf_event *event)
+{
+       unsigned int v, emask;
+
+       /* User data may have out-of-bound event index */
+       v = p4_config_unpack_event(event->attr.config);
+       if (v >= ARRAY_SIZE(p4_event_bind_map))
+               return -EINVAL;
+
+       /* It may be unsupported: */
+       if (!p4_event_match_cpu_model(v))
+               return -EINVAL;
+
+       /*
+        * NOTE: P4_CCCR_THREAD_ANY has not the same meaning as
+        * in Architectural Performance Monitoring, it means not
+        * on _which_ logical cpu to count but rather _when_, ie it
+        * depends on logical cpu state -- count event if one cpu active,
+        * none, both or any, so we just allow user to pass any value
+        * desired.
+        *
+        * In turn we always set Tx_OS/Tx_USR bits bound to logical
+        * cpu without their propagation to another cpu
+        */
+
+       /*
+        * if an event is shared across the logical threads
+        * the user needs special permissions to be able to use it
+        */
+       if (p4_ht_active() && p4_event_bind_map[v].shared) {
+               if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
+                       return -EACCES;
+       }
+
+       /* ESCR EventMask bits may be invalid */
+       emask = p4_config_unpack_escr(event->attr.config) & P4_ESCR_EVENTMASK_MASK;
+       if (emask & ~p4_event_bind_map[v].escr_emask)
+               return -EINVAL;
+
+       /*
+        * it may have some invalid PEBS bits
+        */
+       if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE))
+               return -EINVAL;
+
+       v = p4_config_unpack_metric(event->attr.config);
+       if (v >= ARRAY_SIZE(p4_pebs_bind_map))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int p4_hw_config(struct perf_event *event)
+{
+       int cpu = get_cpu();
+       int rc = 0;
+       u32 escr, cccr;
+
+       /*
+        * the reason we use cpu that early is that: if we get scheduled
+        * first time on the same cpu -- we will not need swap thread
+        * specific flags in config (and will save some cpu cycles)
+        */
+
+       cccr = p4_default_cccr_conf(cpu);
+       escr = p4_default_escr_conf(cpu, event->attr.exclude_kernel,
+                                        event->attr.exclude_user);
+       event->hw.config = p4_config_pack_escr(escr) |
+                          p4_config_pack_cccr(cccr);
+
+       if (p4_ht_active() && p4_ht_thread(cpu))
+               event->hw.config = p4_set_ht_bit(event->hw.config);
+
+       if (event->attr.type == PERF_TYPE_RAW) {
+               struct p4_event_bind *bind;
+               unsigned int esel;
+               /*
+                * Clear bits we reserve to be managed by kernel itself
+                * and never allowed from a user space
+                */
+                event->attr.config &= P4_CONFIG_MASK;
+
+               rc = p4_validate_raw_event(event);
+               if (rc)
+                       goto out;
+
+               /*
+                * Note that for RAW events we allow user to use P4_CCCR_RESERVED
+                * bits since we keep additional info here (for cache events and etc)
+                */
+               event->hw.config |= event->attr.config;
+               bind = p4_config_get_bind(event->attr.config);
+               if (!bind) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+               esel = P4_OPCODE_ESEL(bind->opcode);
+               event->hw.config |= p4_config_pack_cccr(P4_CCCR_ESEL(esel));
+       }
+
+       rc = x86_setup_perfctr(event);
+out:
+       put_cpu();
+       return rc;
+}
+
+static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
+{
+       u64 v;
+
+       /* an official way for overflow indication */
+       rdmsrl(hwc->config_base, v);
+       if (v & P4_CCCR_OVF) {
+               wrmsrl(hwc->config_base, v & ~P4_CCCR_OVF);
+               return 1;
+       }
+
+       /*
+        * In some circumstances the overflow might issue an NMI but did
+        * not set P4_CCCR_OVF bit. Because a counter holds a negative value
+        * we simply check for high bit being set, if it's cleared it means
+        * the counter has reached zero value and continued counting before
+        * real NMI signal was received:
+        */
+       rdmsrl(hwc->event_base, v);
+       if (!(v & ARCH_P4_UNFLAGGED_BIT))
+               return 1;
+
+       return 0;
+}
+
+static void p4_pmu_disable_pebs(void)
+{
+       /*
+        * FIXME
+        *
+        * It's still allowed that two threads setup same cache
+        * events so we can't simply clear metrics until we knew
+        * no one is depending on us, so we need kind of counter
+        * for "ReplayEvent" users.
+        *
+        * What is more complex -- RAW events, if user (for some
+        * reason) will pass some cache event metric with improper
+        * event opcode -- it's fine from hardware point of view
+        * but completely nonsense from "meaning" of such action.
+        *
+        * So at moment let leave metrics turned on forever -- it's
+        * ok for now but need to be revisited!
+        *
+        * (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, 0);
+        * (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT, 0);
+        */
+}
+
+static inline void p4_pmu_disable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       /*
+        * If event gets disabled while counter is in overflowed
+        * state we need to clear P4_CCCR_OVF, otherwise interrupt get
+        * asserted again and again
+        */
+       (void)wrmsrl_safe(hwc->config_base,
+               p4_config_unpack_cccr(hwc->config) & ~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED);
+}
+
+static void p4_pmu_disable_all(void)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               struct perf_event *event = cpuc->events[idx];
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+               p4_pmu_disable_event(event);
+       }
+
+       p4_pmu_disable_pebs();
+}
+
+/* configuration must be valid */
+static void p4_pmu_enable_pebs(u64 config)
+{
+       struct p4_pebs_bind *bind;
+       unsigned int idx;
+
+       BUILD_BUG_ON(P4_PEBS_METRIC__max > P4_PEBS_CONFIG_METRIC_MASK);
+
+       idx = p4_config_unpack_metric(config);
+       if (idx == P4_PEBS_METRIC__none)
+               return;
+
+       bind = &p4_pebs_bind_map[idx];
+
+       (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, (u64)bind->metric_pebs);
+       (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT,      (u64)bind->metric_vert);
+}
+
+static void p4_pmu_enable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       int thread = p4_ht_config_thread(hwc->config);
+       u64 escr_conf = p4_config_unpack_escr(p4_clear_ht_bit(hwc->config));
+       unsigned int idx = p4_config_unpack_event(hwc->config);
+       struct p4_event_bind *bind;
+       u64 escr_addr, cccr;
+
+       bind = &p4_event_bind_map[idx];
+       escr_addr = bind->escr_msr[thread];
+
+       /*
+        * - we dont support cascaded counters yet
+        * - and counter 1 is broken (erratum)
+        */
+       WARN_ON_ONCE(p4_is_event_cascaded(hwc->config));
+       WARN_ON_ONCE(hwc->idx == 1);
+
+       /* we need a real Event value */
+       escr_conf &= ~P4_ESCR_EVENT_MASK;
+       escr_conf |= P4_ESCR_EVENT(P4_OPCODE_EVNT(bind->opcode));
+
+       cccr = p4_config_unpack_cccr(hwc->config);
+
+       /*
+        * it could be Cache event so we need to write metrics
+        * into additional MSRs
+        */
+       p4_pmu_enable_pebs(hwc->config);
+
+       (void)wrmsrl_safe(escr_addr, escr_conf);
+       (void)wrmsrl_safe(hwc->config_base,
+                               (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
+}
+
+static void p4_pmu_enable_all(int added)
+{
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       int idx;
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               struct perf_event *event = cpuc->events[idx];
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+               p4_pmu_enable_event(event);
+       }
+}
+
+static int p4_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       struct perf_event *event;
+       struct hw_perf_event *hwc;
+       int idx, handled = 0;
+       u64 val;
+
+       cpuc = this_cpu_ptr(&cpu_hw_events);
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               int overflow;
+
+               if (!test_bit(idx, cpuc->active_mask)) {
+                       /* catch in-flight IRQs */
+                       if (__test_and_clear_bit(idx, cpuc->running))
+                               handled++;
+                       continue;
+               }
+
+               event = cpuc->events[idx];
+               hwc = &event->hw;
+
+               WARN_ON_ONCE(hwc->idx != idx);
+
+               /* it might be unflagged overflow */
+               overflow = p4_pmu_clear_cccr_ovf(hwc);
+
+               val = x86_perf_event_update(event);
+               if (!overflow && (val & (1ULL << (x86_pmu.cntval_bits - 1))))
+                       continue;
+
+               handled += overflow;
+
+               /* event overflow for sure */
+               perf_sample_data_init(&data, 0, hwc->last_period);
+
+               if (!x86_perf_event_set_period(event))
+                       continue;
+
+
+               if (perf_event_overflow(event, &data, regs))
+                       x86_pmu_stop(event, 0);
+       }
+
+       if (handled)
+               inc_irq_stat(apic_perf_irqs);
+
+       /*
+        * When dealing with the unmasking of the LVTPC on P4 perf hw, it has
+        * been observed that the OVF bit flag has to be cleared first _before_
+        * the LVTPC can be unmasked.
+        *
+        * The reason is the NMI line will continue to be asserted while the OVF
+        * bit is set.  This causes a second NMI to generate if the LVTPC is
+        * unmasked before the OVF bit is cleared, leading to unknown NMI
+        * messages.
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+
+       return handled;
+}
+
+/*
+ * swap thread specific fields according to a thread
+ * we are going to run on
+ */
+static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu)
+{
+       u32 escr, cccr;
+
+       /*
+        * we either lucky and continue on same cpu or no HT support
+        */
+       if (!p4_should_swap_ts(hwc->config, cpu))
+               return;
+
+       /*
+        * the event is migrated from an another logical
+        * cpu, so we need to swap thread specific flags
+        */
+
+       escr = p4_config_unpack_escr(hwc->config);
+       cccr = p4_config_unpack_cccr(hwc->config);
+
+       if (p4_ht_thread(cpu)) {
+               cccr &= ~P4_CCCR_OVF_PMI_T0;
+               cccr |= P4_CCCR_OVF_PMI_T1;
+               if (escr & P4_ESCR_T0_OS) {
+                       escr &= ~P4_ESCR_T0_OS;
+                       escr |= P4_ESCR_T1_OS;
+               }
+               if (escr & P4_ESCR_T0_USR) {
+                       escr &= ~P4_ESCR_T0_USR;
+                       escr |= P4_ESCR_T1_USR;
+               }
+               hwc->config  = p4_config_pack_escr(escr);
+               hwc->config |= p4_config_pack_cccr(cccr);
+               hwc->config |= P4_CONFIG_HT;
+       } else {
+               cccr &= ~P4_CCCR_OVF_PMI_T1;
+               cccr |= P4_CCCR_OVF_PMI_T0;
+               if (escr & P4_ESCR_T1_OS) {
+                       escr &= ~P4_ESCR_T1_OS;
+                       escr |= P4_ESCR_T0_OS;
+               }
+               if (escr & P4_ESCR_T1_USR) {
+                       escr &= ~P4_ESCR_T1_USR;
+                       escr |= P4_ESCR_T0_USR;
+               }
+               hwc->config  = p4_config_pack_escr(escr);
+               hwc->config |= p4_config_pack_cccr(cccr);
+               hwc->config &= ~P4_CONFIG_HT;
+       }
+}
+
+/*
+ * ESCR address hashing is tricky, ESCRs are not sequential
+ * in memory but all starts from MSR_P4_BSU_ESCR0 (0x03a0) and
+ * the metric between any ESCRs is laid in range [0xa0,0xe1]
+ *
+ * so we make ~70% filled hashtable
+ */
+
+#define P4_ESCR_MSR_BASE               0x000003a0
+#define P4_ESCR_MSR_MAX                        0x000003e1
+#define P4_ESCR_MSR_TABLE_SIZE         (P4_ESCR_MSR_MAX - P4_ESCR_MSR_BASE + 1)
+#define P4_ESCR_MSR_IDX(msr)           (msr - P4_ESCR_MSR_BASE)
+#define P4_ESCR_MSR_TABLE_ENTRY(msr)   [P4_ESCR_MSR_IDX(msr)] = msr
+
+static const unsigned int p4_escr_table[P4_ESCR_MSR_TABLE_SIZE] = {
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ALF_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ALF_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BPU_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BPU_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BSU_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BSU_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR2),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR3),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR4),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR5),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_DAC_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_DAC_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FIRM_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FIRM_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FLAME_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FLAME_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FSB_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FSB_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IQ_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IQ_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IS_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IS_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ITLB_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ITLB_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IX_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IX_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MOB_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MOB_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MS_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MS_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_PMH_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_PMH_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_RAT_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_RAT_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SAAT_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SAAT_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SSU_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SSU_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TBPU_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TBPU_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TC_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TC_ESCR1),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_U2L_ESCR0),
+       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_U2L_ESCR1),
+};
+
+static int p4_get_escr_idx(unsigned int addr)
+{
+       unsigned int idx = P4_ESCR_MSR_IDX(addr);
+
+       if (unlikely(idx >= P4_ESCR_MSR_TABLE_SIZE      ||
+                       !p4_escr_table[idx]             ||
+                       p4_escr_table[idx] != addr)) {
+               WARN_ONCE(1, "P4 PMU: Wrong address passed: %x\n", addr);
+               return -1;
+       }
+
+       return idx;
+}
+
+static int p4_next_cntr(int thread, unsigned long *used_mask,
+                       struct p4_event_bind *bind)
+{
+       int i, j;
+
+       for (i = 0; i < P4_CNTR_LIMIT; i++) {
+               j = bind->cntr[thread][i];
+               if (j != -1 && !test_bit(j, used_mask))
+                       return j;
+       }
+
+       return -1;
+}
+
+static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
+{
+       unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+       unsigned long escr_mask[BITS_TO_LONGS(P4_ESCR_MSR_TABLE_SIZE)];
+       int cpu = smp_processor_id();
+       struct hw_perf_event *hwc;
+       struct p4_event_bind *bind;
+       unsigned int i, thread, num;
+       int cntr_idx, escr_idx;
+       u64 config_alias;
+       int pass;
+
+       bitmap_zero(used_mask, X86_PMC_IDX_MAX);
+       bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE);
+
+       for (i = 0, num = n; i < n; i++, num--) {
+
+               hwc = &cpuc->event_list[i]->hw;
+               thread = p4_ht_thread(cpu);
+               pass = 0;
+
+again:
+               /*
+                * It's possible to hit a circular lock
+                * between original and alternative events
+                * if both are scheduled already.
+                */
+               if (pass > 2)
+                       goto done;
+
+               bind = p4_config_get_bind(hwc->config);
+               escr_idx = p4_get_escr_idx(bind->escr_msr[thread]);
+               if (unlikely(escr_idx == -1))
+                       goto done;
+
+               if (hwc->idx != -1 && !p4_should_swap_ts(hwc->config, cpu)) {
+                       cntr_idx = hwc->idx;
+                       if (assign)
+                               assign[i] = hwc->idx;
+                       goto reserve;
+               }
+
+               cntr_idx = p4_next_cntr(thread, used_mask, bind);
+               if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) {
+                       /*
+                        * Check whether an event alias is still available.
+                        */
+                       config_alias = p4_get_alias_event(hwc->config);
+                       if (!config_alias)
+                               goto done;
+                       hwc->config = config_alias;
+                       pass++;
+                       goto again;
+               }
+               /*
+                * Perf does test runs to see if a whole group can be assigned
+                * together succesfully.  There can be multiple rounds of this.
+                * Unfortunately, p4_pmu_swap_config_ts touches the hwc->config
+                * bits, such that the next round of group assignments will
+                * cause the above p4_should_swap_ts to pass instead of fail.
+                * This leads to counters exclusive to thread0 being used by
+                * thread1.
+                *
+                * Solve this with a cheap hack, reset the idx back to -1 to
+                * force a new lookup (p4_next_cntr) to get the right counter
+                * for the right thread.
+                *
+                * This probably doesn't comply with the general spirit of how
+                * perf wants to work, but P4 is special. :-(
+                */
+               if (p4_should_swap_ts(hwc->config, cpu))
+                       hwc->idx = -1;
+               p4_pmu_swap_config_ts(hwc, cpu);
+               if (assign)
+                       assign[i] = cntr_idx;
+reserve:
+               set_bit(cntr_idx, used_mask);
+               set_bit(escr_idx, escr_mask);
+       }
+
+done:
+       return num ? -EINVAL : 0;
+}
+
+PMU_FORMAT_ATTR(cccr, "config:0-31" );
+PMU_FORMAT_ATTR(escr, "config:32-62");
+PMU_FORMAT_ATTR(ht,   "config:63"   );
+
+static struct attribute *intel_p4_formats_attr[] = {
+       &format_attr_cccr.attr,
+       &format_attr_escr.attr,
+       &format_attr_ht.attr,
+       NULL,
+};
+
+static __initconst const struct x86_pmu p4_pmu = {
+       .name                   = "Netburst P4/Xeon",
+       .handle_irq             = p4_pmu_handle_irq,
+       .disable_all            = p4_pmu_disable_all,
+       .enable_all             = p4_pmu_enable_all,
+       .enable                 = p4_pmu_enable_event,
+       .disable                = p4_pmu_disable_event,
+       .eventsel               = MSR_P4_BPU_CCCR0,
+       .perfctr                = MSR_P4_BPU_PERFCTR0,
+       .event_map              = p4_pmu_event_map,
+       .max_events             = ARRAY_SIZE(p4_general_events),
+       .get_event_constraints  = x86_get_event_constraints,
+       /*
+        * IF HT disabled we may need to use all
+        * ARCH_P4_MAX_CCCR counters simulaneously
+        * though leave it restricted at moment assuming
+        * HT is on
+        */
+       .num_counters           = ARCH_P4_MAX_CCCR,
+       .apic                   = 1,
+       .cntval_bits            = ARCH_P4_CNTRVAL_BITS,
+       .cntval_mask            = ARCH_P4_CNTRVAL_MASK,
+       .max_period             = (1ULL << (ARCH_P4_CNTRVAL_BITS - 1)) - 1,
+       .hw_config              = p4_hw_config,
+       .schedule_events        = p4_pmu_schedule_events,
+       /*
+        * This handles erratum N15 in intel doc 249199-029,
+        * the counter may not be updated correctly on write
+        * so we need a second write operation to do the trick
+        * (the official workaround didn't work)
+        *
+        * the former idea is taken from OProfile code
+        */
+       .perfctr_second_write   = 1,
+
+       .format_attrs           = intel_p4_formats_attr,
+};
+
+__init int p4_pmu_init(void)
+{
+       unsigned int low, high;
+       int i, reg;
+
+       /* If we get stripped -- indexing fails */
+       BUILD_BUG_ON(ARCH_P4_MAX_CCCR > INTEL_PMC_MAX_GENERIC);
+
+       rdmsr(MSR_IA32_MISC_ENABLE, low, high);
+       if (!(low & (1 << 7))) {
+               pr_cont("unsupported Netburst CPU model %d ",
+                       boot_cpu_data.x86_model);
+               return -ENODEV;
+       }
+
+       memcpy(hw_cache_event_ids, p4_hw_cache_event_ids,
+               sizeof(hw_cache_event_ids));
+
+       pr_cont("Netburst events, ");
+
+       x86_pmu = p4_pmu;
+
+       /*
+        * Even though the counters are configured to interrupt a particular
+        * logical processor when an overflow happens, testing has shown that
+        * on kdump kernels (which uses a single cpu), thread1's counter
+        * continues to run and will report an NMI on thread0.  Due to the
+        * overflow bug, this leads to a stream of unknown NMIs.
+        *
+        * Solve this by zero'ing out the registers to mimic a reset.
+        */
+       for (i = 0; i < x86_pmu.num_counters; i++) {
+               reg = x86_pmu_config_addr(i);
+               wrmsrl_safe(reg, 0ULL);
+       }
+
+       return 0;
+}
diff --git a/arch/x86/events/intel/p6.c b/arch/x86/events/intel/p6.c
new file mode 100644 (file)
index 0000000..1f5c47a
--- /dev/null
@@ -0,0 +1,279 @@
+#include <linux/perf_event.h>
+#include <linux/types.h>
+
+#include "../perf_event.h"
+
+/*
+ * Not sure about some of these
+ */
+static const u64 p6_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,       /* CPU_CLK_UNHALTED */
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,       /* INST_RETIRED     */
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,       /* L2_RQSTS:M:E:S:I */
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,       /* L2_RQSTS:I       */
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,       /* BR_INST_RETIRED  */
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,       /* BR_MISS_PRED_RETIRED */
+  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,       /* BUS_DRDY_CLOCKS  */
+  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,    /* RESOURCE_STALLS  */
+
+};
+
+static const u64 __initconst p6_hw_cache_event_ids
+                               [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) ] = 0x0043,  /* DATA_MEM_REFS       */
+                [ C(RESULT_MISS)   ] = 0x0045, /* DCU_LINES_IN        */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0f29,  /* L2_LD:M:E:S:I       */
+       },
+        [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+        },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0f28,  /* L2_IFETCH:M:E:S:I  */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0025,  /* L2_M_LINES_INM     */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS      */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0085,  /* ITLB_MISS          */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4,  /* BR_INST_RETIRED      */
+               [ C(RESULT_MISS)   ] = 0x00c5,  /* BR_MISS_PRED_RETIRED */
+        },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+};
+
+static u64 p6_pmu_event_map(int hw_event)
+{
+       return p6_perfmon_event_map[hw_event];
+}
+
+/*
+ * Event setting that is specified not to count anything.
+ * We use this to effectively disable a counter.
+ *
+ * L2_RQSTS with 0 MESI unit mask.
+ */
+#define P6_NOP_EVENT                   0x0000002EULL
+
+static struct event_constraint p6_event_constraints[] =
+{
+       INTEL_EVENT_CONSTRAINT(0xc1, 0x1),      /* FLOPS */
+       INTEL_EVENT_CONSTRAINT(0x10, 0x1),      /* FP_COMP_OPS_EXE */
+       INTEL_EVENT_CONSTRAINT(0x11, 0x2),      /* FP_ASSIST */
+       INTEL_EVENT_CONSTRAINT(0x12, 0x2),      /* MUL */
+       INTEL_EVENT_CONSTRAINT(0x13, 0x2),      /* DIV */
+       INTEL_EVENT_CONSTRAINT(0x14, 0x1),      /* CYCLES_DIV_BUSY */
+       EVENT_CONSTRAINT_END
+};
+
+static void p6_pmu_disable_all(void)
+{
+       u64 val;
+
+       /* p6 only has one enable register */
+       rdmsrl(MSR_P6_EVNTSEL0, val);
+       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+       wrmsrl(MSR_P6_EVNTSEL0, val);
+}
+
+static void p6_pmu_enable_all(int added)
+{
+       unsigned long val;
+
+       /* p6 only has one enable register */
+       rdmsrl(MSR_P6_EVNTSEL0, val);
+       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+       wrmsrl(MSR_P6_EVNTSEL0, val);
+}
+
+static inline void
+p6_pmu_disable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 val = P6_NOP_EVENT;
+
+       (void)wrmsrl_safe(hwc->config_base, val);
+}
+
+static void p6_pmu_enable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 val;
+
+       val = hwc->config;
+
+       /*
+        * p6 only has a global event enable, set on PerfEvtSel0
+        * We "disable" events by programming P6_NOP_EVENT
+        * and we rely on p6_pmu_enable_all() being called
+        * to actually enable the events.
+        */
+
+       (void)wrmsrl_safe(hwc->config_base, val);
+}
+
+PMU_FORMAT_ATTR(event, "config:0-7"    );
+PMU_FORMAT_ATTR(umask, "config:8-15"   );
+PMU_FORMAT_ATTR(edge,  "config:18"     );
+PMU_FORMAT_ATTR(pc,    "config:19"     );
+PMU_FORMAT_ATTR(inv,   "config:23"     );
+PMU_FORMAT_ATTR(cmask, "config:24-31"  );
+
+static struct attribute *intel_p6_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_pc.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask.attr,
+       NULL,
+};
+
+static __initconst const struct x86_pmu p6_pmu = {
+       .name                   = "p6",
+       .handle_irq             = x86_pmu_handle_irq,
+       .disable_all            = p6_pmu_disable_all,
+       .enable_all             = p6_pmu_enable_all,
+       .enable                 = p6_pmu_enable_event,
+       .disable                = p6_pmu_disable_event,
+       .hw_config              = x86_pmu_hw_config,
+       .schedule_events        = x86_schedule_events,
+       .eventsel               = MSR_P6_EVNTSEL0,
+       .perfctr                = MSR_P6_PERFCTR0,
+       .event_map              = p6_pmu_event_map,
+       .max_events             = ARRAY_SIZE(p6_perfmon_event_map),
+       .apic                   = 1,
+       .max_period             = (1ULL << 31) - 1,
+       .version                = 0,
+       .num_counters           = 2,
+       /*
+        * Events have 40 bits implemented. However they are designed such
+        * that bits [32-39] are sign extensions of bit 31. As such the
+        * effective width of a event for P6-like PMU is 32 bits only.
+        *
+        * See IA-32 Intel Architecture Software developer manual Vol 3B
+        */
+       .cntval_bits            = 32,
+       .cntval_mask            = (1ULL << 32) - 1,
+       .get_event_constraints  = x86_get_event_constraints,
+       .event_constraints      = p6_event_constraints,
+
+       .format_attrs           = intel_p6_formats_attr,
+       .events_sysfs_show      = intel_event_sysfs_show,
+
+};
+
+static __init void p6_pmu_rdpmc_quirk(void)
+{
+       if (boot_cpu_data.x86_mask < 9) {
+               /*
+                * PPro erratum 26; fixed in stepping 9 and above.
+                */
+               pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n");
+               x86_pmu.attr_rdpmc_broken = 1;
+               x86_pmu.attr_rdpmc = 0;
+       }
+}
+
+__init int p6_pmu_init(void)
+{
+       x86_pmu = p6_pmu;
+
+       switch (boot_cpu_data.x86_model) {
+       case  1: /* Pentium Pro */
+               x86_add_quirk(p6_pmu_rdpmc_quirk);
+               break;
+
+       case  3: /* Pentium II - Klamath */
+       case  5: /* Pentium II - Deschutes */
+       case  6: /* Pentium II - Mendocino */
+               break;
+
+       case  7: /* Pentium III - Katmai */
+       case  8: /* Pentium III - Coppermine */
+       case 10: /* Pentium III Xeon */
+       case 11: /* Pentium III - Tualatin */
+               break;
+
+       case  9: /* Pentium M - Banias */
+       case 13: /* Pentium M - Dothan */
+               break;
+
+       default:
+               pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model);
+               return -ENODEV;
+       }
+
+       memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
+               sizeof(hw_cache_event_ids));
+
+       return 0;
+}
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
new file mode 100644 (file)
index 0000000..6af7cf7
--- /dev/null
@@ -0,0 +1,1188 @@
+/*
+ * Intel(R) Processor Trace PMU driver for perf
+ * Copyright (c) 2013-2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Intel PT is specified in the Intel Architecture Instruction Set Extensions
+ * Programming Reference:
+ * http://software.intel.com/en-us/intel-isa-extensions
+ */
+
+#undef DEBUG
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+#include <asm/perf_event.h>
+#include <asm/insn.h>
+#include <asm/io.h>
+#include <asm/intel_pt.h>
+
+#include "../perf_event.h"
+#include "pt.h"
+
+static DEFINE_PER_CPU(struct pt, pt_ctx);
+
+static struct pt_pmu pt_pmu;
+
+enum cpuid_regs {
+       CR_EAX = 0,
+       CR_ECX,
+       CR_EDX,
+       CR_EBX
+};
+
+/*
+ * Capabilities of Intel PT hardware, such as number of address bits or
+ * supported output schemes, are cached and exported to userspace as "caps"
+ * attribute group of pt pmu device
+ * (/sys/bus/event_source/devices/intel_pt/caps/) so that userspace can store
+ * relevant bits together with intel_pt traces.
+ *
+ * These are necessary for both trace decoding (payloads_lip, contains address
+ * width encoded in IP-related packets), and event configuration (bitmasks with
+ * permitted values for certain bit fields).
+ */
+#define PT_CAP(_n, _l, _r, _m)                                         \
+       [PT_CAP_ ## _n] = { .name = __stringify(_n), .leaf = _l,        \
+                           .reg = _r, .mask = _m }
+
+static struct pt_cap_desc {
+       const char      *name;
+       u32             leaf;
+       u8              reg;
+       u32             mask;
+} pt_caps[] = {
+       PT_CAP(max_subleaf,             0, CR_EAX, 0xffffffff),
+       PT_CAP(cr3_filtering,           0, CR_EBX, BIT(0)),
+       PT_CAP(psb_cyc,                 0, CR_EBX, BIT(1)),
+       PT_CAP(mtc,                     0, CR_EBX, BIT(3)),
+       PT_CAP(topa_output,             0, CR_ECX, BIT(0)),
+       PT_CAP(topa_multiple_entries,   0, CR_ECX, BIT(1)),
+       PT_CAP(single_range_output,     0, CR_ECX, BIT(2)),
+       PT_CAP(payloads_lip,            0, CR_ECX, BIT(31)),
+       PT_CAP(mtc_periods,             1, CR_EAX, 0xffff0000),
+       PT_CAP(cycle_thresholds,        1, CR_EBX, 0xffff),
+       PT_CAP(psb_periods,             1, CR_EBX, 0xffff0000),
+};
+
+static u32 pt_cap_get(enum pt_capabilities cap)
+{
+       struct pt_cap_desc *cd = &pt_caps[cap];
+       u32 c = pt_pmu.caps[cd->leaf * PT_CPUID_REGS_NUM + cd->reg];
+       unsigned int shift = __ffs(cd->mask);
+
+       return (c & cd->mask) >> shift;
+}
+
+static ssize_t pt_cap_show(struct device *cdev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       struct dev_ext_attribute *ea =
+               container_of(attr, struct dev_ext_attribute, attr);
+       enum pt_capabilities cap = (long)ea->var;
+
+       return snprintf(buf, PAGE_SIZE, "%x\n", pt_cap_get(cap));
+}
+
+static struct attribute_group pt_cap_group = {
+       .name   = "caps",
+};
+
+PMU_FORMAT_ATTR(cyc,           "config:1"      );
+PMU_FORMAT_ATTR(mtc,           "config:9"      );
+PMU_FORMAT_ATTR(tsc,           "config:10"     );
+PMU_FORMAT_ATTR(noretcomp,     "config:11"     );
+PMU_FORMAT_ATTR(mtc_period,    "config:14-17"  );
+PMU_FORMAT_ATTR(cyc_thresh,    "config:19-22"  );
+PMU_FORMAT_ATTR(psb_period,    "config:24-27"  );
+
+static struct attribute *pt_formats_attr[] = {
+       &format_attr_cyc.attr,
+       &format_attr_mtc.attr,
+       &format_attr_tsc.attr,
+       &format_attr_noretcomp.attr,
+       &format_attr_mtc_period.attr,
+       &format_attr_cyc_thresh.attr,
+       &format_attr_psb_period.attr,
+       NULL,
+};
+
+static struct attribute_group pt_format_group = {
+       .name   = "format",
+       .attrs  = pt_formats_attr,
+};
+
+static const struct attribute_group *pt_attr_groups[] = {
+       &pt_cap_group,
+       &pt_format_group,
+       NULL,
+};
+
+static int __init pt_pmu_hw_init(void)
+{
+       struct dev_ext_attribute *de_attrs;
+       struct attribute **attrs;
+       size_t size;
+       int ret;
+       long i;
+
+       attrs = NULL;
+
+       for (i = 0; i < PT_CPUID_LEAVES; i++) {
+               cpuid_count(20, i,
+                           &pt_pmu.caps[CR_EAX + i*PT_CPUID_REGS_NUM],
+                           &pt_pmu.caps[CR_EBX + i*PT_CPUID_REGS_NUM],
+                           &pt_pmu.caps[CR_ECX + i*PT_CPUID_REGS_NUM],
+                           &pt_pmu.caps[CR_EDX + i*PT_CPUID_REGS_NUM]);
+       }
+
+       ret = -ENOMEM;
+       size = sizeof(struct attribute *) * (ARRAY_SIZE(pt_caps)+1);
+       attrs = kzalloc(size, GFP_KERNEL);
+       if (!attrs)
+               goto fail;
+
+       size = sizeof(struct dev_ext_attribute) * (ARRAY_SIZE(pt_caps)+1);
+       de_attrs = kzalloc(size, GFP_KERNEL);
+       if (!de_attrs)
+               goto fail;
+
+       for (i = 0; i < ARRAY_SIZE(pt_caps); i++) {
+               struct dev_ext_attribute *de_attr = de_attrs + i;
+
+               de_attr->attr.attr.name = pt_caps[i].name;
+
+               sysfs_attr_init(&de_attr->attr.attr);
+
+               de_attr->attr.attr.mode         = S_IRUGO;
+               de_attr->attr.show              = pt_cap_show;
+               de_attr->var                    = (void *)i;
+
+               attrs[i] = &de_attr->attr.attr;
+       }
+
+       pt_cap_group.attrs = attrs;
+
+       return 0;
+
+fail:
+       kfree(attrs);
+
+       return ret;
+}
+
+#define RTIT_CTL_CYC_PSB (RTIT_CTL_CYCLEACC    | \
+                         RTIT_CTL_CYC_THRESH   | \
+                         RTIT_CTL_PSB_FREQ)
+
+#define RTIT_CTL_MTC   (RTIT_CTL_MTC_EN        | \
+                        RTIT_CTL_MTC_RANGE)
+
+#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN                | \
+                       RTIT_CTL_DISRETC        | \
+                       RTIT_CTL_CYC_PSB        | \
+                       RTIT_CTL_MTC)
+
+static bool pt_event_valid(struct perf_event *event)
+{
+       u64 config = event->attr.config;
+       u64 allowed, requested;
+
+       if ((config & PT_CONFIG_MASK) != config)
+               return false;
+
+       if (config & RTIT_CTL_CYC_PSB) {
+               if (!pt_cap_get(PT_CAP_psb_cyc))
+                       return false;
+
+               allowed = pt_cap_get(PT_CAP_psb_periods);
+               requested = (config & RTIT_CTL_PSB_FREQ) >>
+                       RTIT_CTL_PSB_FREQ_OFFSET;
+               if (requested && (!(allowed & BIT(requested))))
+                       return false;
+
+               allowed = pt_cap_get(PT_CAP_cycle_thresholds);
+               requested = (config & RTIT_CTL_CYC_THRESH) >>
+                       RTIT_CTL_CYC_THRESH_OFFSET;
+               if (requested && (!(allowed & BIT(requested))))
+                       return false;
+       }
+
+       if (config & RTIT_CTL_MTC) {
+               /*
+                * In the unlikely case that CPUID lists valid mtc periods,
+                * but not the mtc capability, drop out here.
+                *
+                * Spec says that setting mtc period bits while mtc bit in
+                * CPUID is 0 will #GP, so better safe than sorry.
+                */
+               if (!pt_cap_get(PT_CAP_mtc))
+                       return false;
+
+               allowed = pt_cap_get(PT_CAP_mtc_periods);
+               if (!allowed)
+                       return false;
+
+               requested = (config & RTIT_CTL_MTC_RANGE) >>
+                       RTIT_CTL_MTC_RANGE_OFFSET;
+
+               if (!(allowed & BIT(requested)))
+                       return false;
+       }
+
+       return true;
+}
+
+/*
+ * PT configuration helpers
+ * These all are cpu affine and operate on a local PT
+ */
+
+static void pt_config(struct perf_event *event)
+{
+       u64 reg;
+
+       if (!event->hw.itrace_started) {
+               event->hw.itrace_started = 1;
+               wrmsrl(MSR_IA32_RTIT_STATUS, 0);
+       }
+
+       reg = RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN;
+
+       if (!event->attr.exclude_kernel)
+               reg |= RTIT_CTL_OS;
+       if (!event->attr.exclude_user)
+               reg |= RTIT_CTL_USR;
+
+       reg |= (event->attr.config & PT_CONFIG_MASK);
+
+       wrmsrl(MSR_IA32_RTIT_CTL, reg);
+}
+
+static void pt_config_start(bool start)
+{
+       u64 ctl;
+
+       rdmsrl(MSR_IA32_RTIT_CTL, ctl);
+       if (start)
+               ctl |= RTIT_CTL_TRACEEN;
+       else
+               ctl &= ~RTIT_CTL_TRACEEN;
+       wrmsrl(MSR_IA32_RTIT_CTL, ctl);
+
+       /*
+        * A wrmsr that disables trace generation serializes other PT
+        * registers and causes all data packets to be written to memory,
+        * but a fence is required for the data to become globally visible.
+        *
+        * The below WMB, separating data store and aux_head store matches
+        * the consumer's RMB that separates aux_head load and data load.
+        */
+       if (!start)
+               wmb();
+}
+
+static void pt_config_buffer(void *buf, unsigned int topa_idx,
+                            unsigned int output_off)
+{
+       u64 reg;
+
+       wrmsrl(MSR_IA32_RTIT_OUTPUT_BASE, virt_to_phys(buf));
+
+       reg = 0x7f | ((u64)topa_idx << 7) | ((u64)output_off << 32);
+
+       wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, reg);
+}
+
+/*
+ * Keep ToPA table-related metadata on the same page as the actual table,
+ * taking up a few words from the top
+ */
+
+#define TENTS_PER_PAGE (((PAGE_SIZE - 40) / sizeof(struct topa_entry)) - 1)
+
+/**
+ * struct topa - page-sized ToPA table with metadata at the top
+ * @table:     actual ToPA table entries, as understood by PT hardware
+ * @list:      linkage to struct pt_buffer's list of tables
+ * @phys:      physical address of this page
+ * @offset:    offset of the first entry in this table in the buffer
+ * @size:      total size of all entries in this table
+ * @last:      index of the last initialized entry in this table
+ */
+struct topa {
+       struct topa_entry       table[TENTS_PER_PAGE];
+       struct list_head        list;
+       u64                     phys;
+       u64                     offset;
+       size_t                  size;
+       int                     last;
+};
+
+/* make -1 stand for the last table entry */
+#define TOPA_ENTRY(t, i) ((i) == -1 ? &(t)->table[(t)->last] : &(t)->table[(i)])
+
+/**
+ * topa_alloc() - allocate page-sized ToPA table
+ * @cpu:       CPU on which to allocate.
+ * @gfp:       Allocation flags.
+ *
+ * Return:     On success, return the pointer to ToPA table page.
+ */
+static struct topa *topa_alloc(int cpu, gfp_t gfp)
+{
+       int node = cpu_to_node(cpu);
+       struct topa *topa;
+       struct page *p;
+
+       p = alloc_pages_node(node, gfp | __GFP_ZERO, 0);
+       if (!p)
+               return NULL;
+
+       topa = page_address(p);
+       topa->last = 0;
+       topa->phys = page_to_phys(p);
+
+       /*
+        * In case of singe-entry ToPA, always put the self-referencing END
+        * link as the 2nd entry in the table
+        */
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries)) {
+               TOPA_ENTRY(topa, 1)->base = topa->phys >> TOPA_SHIFT;
+               TOPA_ENTRY(topa, 1)->end = 1;
+       }
+
+       return topa;
+}
+
+/**
+ * topa_free() - free a page-sized ToPA table
+ * @topa:      Table to deallocate.
+ */
+static void topa_free(struct topa *topa)
+{
+       free_page((unsigned long)topa);
+}
+
+/**
+ * topa_insert_table() - insert a ToPA table into a buffer
+ * @buf:        PT buffer that's being extended.
+ * @topa:       New topa table to be inserted.
+ *
+ * If it's the first table in this buffer, set up buffer's pointers
+ * accordingly; otherwise, add a END=1 link entry to @topa to the current
+ * "last" table and adjust the last table pointer to @topa.
+ */
+static void topa_insert_table(struct pt_buffer *buf, struct topa *topa)
+{
+       struct topa *last = buf->last;
+
+       list_add_tail(&topa->list, &buf->tables);
+
+       if (!buf->first) {
+               buf->first = buf->last = buf->cur = topa;
+               return;
+       }
+
+       topa->offset = last->offset + last->size;
+       buf->last = topa;
+
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
+               return;
+
+       BUG_ON(last->last != TENTS_PER_PAGE - 1);
+
+       TOPA_ENTRY(last, -1)->base = topa->phys >> TOPA_SHIFT;
+       TOPA_ENTRY(last, -1)->end = 1;
+}
+
+/**
+ * topa_table_full() - check if a ToPA table is filled up
+ * @topa:      ToPA table.
+ */
+static bool topa_table_full(struct topa *topa)
+{
+       /* single-entry ToPA is a special case */
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
+               return !!topa->last;
+
+       return topa->last == TENTS_PER_PAGE - 1;
+}
+
+/**
+ * topa_insert_pages() - create a list of ToPA tables
+ * @buf:       PT buffer being initialized.
+ * @gfp:       Allocation flags.
+ *
+ * This initializes a list of ToPA tables with entries from
+ * the data_pages provided by rb_alloc_aux().
+ *
+ * Return:     0 on success or error code.
+ */
+static int topa_insert_pages(struct pt_buffer *buf, gfp_t gfp)
+{
+       struct topa *topa = buf->last;
+       int order = 0;
+       struct page *p;
+
+       p = virt_to_page(buf->data_pages[buf->nr_pages]);
+       if (PagePrivate(p))
+               order = page_private(p);
+
+       if (topa_table_full(topa)) {
+               topa = topa_alloc(buf->cpu, gfp);
+               if (!topa)
+                       return -ENOMEM;
+
+               topa_insert_table(buf, topa);
+       }
+
+       TOPA_ENTRY(topa, -1)->base = page_to_phys(p) >> TOPA_SHIFT;
+       TOPA_ENTRY(topa, -1)->size = order;
+       if (!buf->snapshot && !pt_cap_get(PT_CAP_topa_multiple_entries)) {
+               TOPA_ENTRY(topa, -1)->intr = 1;
+               TOPA_ENTRY(topa, -1)->stop = 1;
+       }
+
+       topa->last++;
+       topa->size += sizes(order);
+
+       buf->nr_pages += 1ul << order;
+
+       return 0;
+}
+
+/**
+ * pt_topa_dump() - print ToPA tables and their entries
+ * @buf:       PT buffer.
+ */
+static void pt_topa_dump(struct pt_buffer *buf)
+{
+       struct topa *topa;
+
+       list_for_each_entry(topa, &buf->tables, list) {
+               int i;
+
+               pr_debug("# table @%p (%016Lx), off %llx size %zx\n", topa->table,
+                        topa->phys, topa->offset, topa->size);
+               for (i = 0; i < TENTS_PER_PAGE; i++) {
+                       pr_debug("# entry @%p (%lx sz %u %c%c%c) raw=%16llx\n",
+                                &topa->table[i],
+                                (unsigned long)topa->table[i].base << TOPA_SHIFT,
+                                sizes(topa->table[i].size),
+                                topa->table[i].end ?  'E' : ' ',
+                                topa->table[i].intr ? 'I' : ' ',
+                                topa->table[i].stop ? 'S' : ' ',
+                                *(u64 *)&topa->table[i]);
+                       if ((pt_cap_get(PT_CAP_topa_multiple_entries) &&
+                            topa->table[i].stop) ||
+                           topa->table[i].end)
+                               break;
+               }
+       }
+}
+
+/**
+ * pt_buffer_advance() - advance to the next output region
+ * @buf:       PT buffer.
+ *
+ * Advance the current pointers in the buffer to the next ToPA entry.
+ */
+static void pt_buffer_advance(struct pt_buffer *buf)
+{
+       buf->output_off = 0;
+       buf->cur_idx++;
+
+       if (buf->cur_idx == buf->cur->last) {
+               if (buf->cur == buf->last)
+                       buf->cur = buf->first;
+               else
+                       buf->cur = list_entry(buf->cur->list.next, struct topa,
+                                             list);
+               buf->cur_idx = 0;
+       }
+}
+
+/**
+ * pt_update_head() - calculate current offsets and sizes
+ * @pt:                Per-cpu pt context.
+ *
+ * Update buffer's current write pointer position and data size.
+ */
+static void pt_update_head(struct pt *pt)
+{
+       struct pt_buffer *buf = perf_get_aux(&pt->handle);
+       u64 topa_idx, base, old;
+
+       /* offset of the first region in this table from the beginning of buf */
+       base = buf->cur->offset + buf->output_off;
+
+       /* offset of the current output region within this table */
+       for (topa_idx = 0; topa_idx < buf->cur_idx; topa_idx++)
+               base += sizes(buf->cur->table[topa_idx].size);
+
+       if (buf->snapshot) {
+               local_set(&buf->data_size, base);
+       } else {
+               old = (local64_xchg(&buf->head, base) &
+                      ((buf->nr_pages << PAGE_SHIFT) - 1));
+               if (base < old)
+                       base += buf->nr_pages << PAGE_SHIFT;
+
+               local_add(base - old, &buf->data_size);
+       }
+}
+
+/**
+ * pt_buffer_region() - obtain current output region's address
+ * @buf:       PT buffer.
+ */
+static void *pt_buffer_region(struct pt_buffer *buf)
+{
+       return phys_to_virt(buf->cur->table[buf->cur_idx].base << TOPA_SHIFT);
+}
+
+/**
+ * pt_buffer_region_size() - obtain current output region's size
+ * @buf:       PT buffer.
+ */
+static size_t pt_buffer_region_size(struct pt_buffer *buf)
+{
+       return sizes(buf->cur->table[buf->cur_idx].size);
+}
+
+/**
+ * pt_handle_status() - take care of possible status conditions
+ * @pt:                Per-cpu pt context.
+ */
+static void pt_handle_status(struct pt *pt)
+{
+       struct pt_buffer *buf = perf_get_aux(&pt->handle);
+       int advance = 0;
+       u64 status;
+
+       rdmsrl(MSR_IA32_RTIT_STATUS, status);
+
+       if (status & RTIT_STATUS_ERROR) {
+               pr_err_ratelimited("ToPA ERROR encountered, trying to recover\n");
+               pt_topa_dump(buf);
+               status &= ~RTIT_STATUS_ERROR;
+       }
+
+       if (status & RTIT_STATUS_STOPPED) {
+               status &= ~RTIT_STATUS_STOPPED;
+
+               /*
+                * On systems that only do single-entry ToPA, hitting STOP
+                * means we are already losing data; need to let the decoder
+                * know.
+                */
+               if (!pt_cap_get(PT_CAP_topa_multiple_entries) ||
+                   buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
+                       local_inc(&buf->lost);
+                       advance++;
+               }
+       }
+
+       /*
+        * Also on single-entry ToPA implementations, interrupt will come
+        * before the output reaches its output region's boundary.
+        */
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries) && !buf->snapshot &&
+           pt_buffer_region_size(buf) - buf->output_off <= TOPA_PMI_MARGIN) {
+               void *head = pt_buffer_region(buf);
+
+               /* everything within this margin needs to be zeroed out */
+               memset(head + buf->output_off, 0,
+                      pt_buffer_region_size(buf) -
+                      buf->output_off);
+               advance++;
+       }
+
+       if (advance)
+               pt_buffer_advance(buf);
+
+       wrmsrl(MSR_IA32_RTIT_STATUS, status);
+}
+
+/**
+ * pt_read_offset() - translate registers into buffer pointers
+ * @buf:       PT buffer.
+ *
+ * Set buffer's output pointers from MSR values.
+ */
+static void pt_read_offset(struct pt_buffer *buf)
+{
+       u64 offset, base_topa;
+
+       rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, base_topa);
+       buf->cur = phys_to_virt(base_topa);
+
+       rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, offset);
+       /* offset within current output region */
+       buf->output_off = offset >> 32;
+       /* index of current output region within this table */
+       buf->cur_idx = (offset & 0xffffff80) >> 7;
+}
+
+/**
+ * pt_topa_next_entry() - obtain index of the first page in the next ToPA entry
+ * @buf:       PT buffer.
+ * @pg:                Page offset in the buffer.
+ *
+ * When advancing to the next output region (ToPA entry), given a page offset
+ * into the buffer, we need to find the offset of the first page in the next
+ * region.
+ */
+static unsigned int pt_topa_next_entry(struct pt_buffer *buf, unsigned int pg)
+{
+       struct topa_entry *te = buf->topa_index[pg];
+
+       /* one region */
+       if (buf->first == buf->last && buf->first->last == 1)
+               return pg;
+
+       do {
+               pg++;
+               pg &= buf->nr_pages - 1;
+       } while (buf->topa_index[pg] == te);
+
+       return pg;
+}
+
+/**
+ * pt_buffer_reset_markers() - place interrupt and stop bits in the buffer
+ * @buf:       PT buffer.
+ * @handle:    Current output handle.
+ *
+ * Place INT and STOP marks to prevent overwriting old data that the consumer
+ * hasn't yet collected and waking up the consumer after a certain fraction of
+ * the buffer has filled up. Only needed and sensible for non-snapshot counters.
+ *
+ * This obviously relies on buf::head to figure out buffer markers, so it has
+ * to be called after pt_buffer_reset_offsets() and before the hardware tracing
+ * is enabled.
+ */
+static int pt_buffer_reset_markers(struct pt_buffer *buf,
+                                  struct perf_output_handle *handle)
+
+{
+       unsigned long head = local64_read(&buf->head);
+       unsigned long idx, npages, wakeup;
+
+       /* can't stop in the middle of an output region */
+       if (buf->output_off + handle->size + 1 <
+           sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size))
+               return -EINVAL;
+
+
+       /* single entry ToPA is handled by marking all regions STOP=1 INT=1 */
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
+               return 0;
+
+       /* clear STOP and INT from current entry */
+       buf->topa_index[buf->stop_pos]->stop = 0;
+       buf->topa_index[buf->intr_pos]->intr = 0;
+
+       /* how many pages till the STOP marker */
+       npages = handle->size >> PAGE_SHIFT;
+
+       /* if it's on a page boundary, fill up one more page */
+       if (!offset_in_page(head + handle->size + 1))
+               npages++;
+
+       idx = (head >> PAGE_SHIFT) + npages;
+       idx &= buf->nr_pages - 1;
+       buf->stop_pos = idx;
+
+       wakeup = handle->wakeup >> PAGE_SHIFT;
+
+       /* in the worst case, wake up the consumer one page before hard stop */
+       idx = (head >> PAGE_SHIFT) + npages - 1;
+       if (idx > wakeup)
+               idx = wakeup;
+
+       idx &= buf->nr_pages - 1;
+       buf->intr_pos = idx;
+
+       buf->topa_index[buf->stop_pos]->stop = 1;
+       buf->topa_index[buf->intr_pos]->intr = 1;
+
+       return 0;
+}
+
+/**
+ * pt_buffer_setup_topa_index() - build topa_index[] table of regions
+ * @buf:       PT buffer.
+ *
+ * topa_index[] references output regions indexed by offset into the
+ * buffer for purposes of quick reverse lookup.
+ */
+static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
+{
+       struct topa *cur = buf->first, *prev = buf->last;
+       struct topa_entry *te_cur = TOPA_ENTRY(cur, 0),
+               *te_prev = TOPA_ENTRY(prev, prev->last - 1);
+       int pg = 0, idx = 0;
+
+       while (pg < buf->nr_pages) {
+               int tidx;
+
+               /* pages within one topa entry */
+               for (tidx = 0; tidx < 1 << te_cur->size; tidx++, pg++)
+                       buf->topa_index[pg] = te_prev;
+
+               te_prev = te_cur;
+
+               if (idx == cur->last - 1) {
+                       /* advance to next topa table */
+                       idx = 0;
+                       cur = list_entry(cur->list.next, struct topa, list);
+               } else {
+                       idx++;
+               }
+               te_cur = TOPA_ENTRY(cur, idx);
+       }
+
+}
+
+/**
+ * pt_buffer_reset_offsets() - adjust buffer's write pointers from aux_head
+ * @buf:       PT buffer.
+ * @head:      Write pointer (aux_head) from AUX buffer.
+ *
+ * Find the ToPA table and entry corresponding to given @head and set buffer's
+ * "current" pointers accordingly. This is done after we have obtained the
+ * current aux_head position from a successful call to perf_aux_output_begin()
+ * to make sure the hardware is writing to the right place.
+ *
+ * This function modifies buf::{cur,cur_idx,output_off} that will be programmed
+ * into PT msrs when the tracing is enabled and buf::head and buf::data_size,
+ * which are used to determine INT and STOP markers' locations by a subsequent
+ * call to pt_buffer_reset_markers().
+ */
+static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head)
+{
+       int pg;
+
+       if (buf->snapshot)
+               head &= (buf->nr_pages << PAGE_SHIFT) - 1;
+
+       pg = (head >> PAGE_SHIFT) & (buf->nr_pages - 1);
+       pg = pt_topa_next_entry(buf, pg);
+
+       buf->cur = (struct topa *)((unsigned long)buf->topa_index[pg] & PAGE_MASK);
+       buf->cur_idx = ((unsigned long)buf->topa_index[pg] -
+                       (unsigned long)buf->cur) / sizeof(struct topa_entry);
+       buf->output_off = head & (sizes(buf->cur->table[buf->cur_idx].size) - 1);
+
+       local64_set(&buf->head, head);
+       local_set(&buf->data_size, 0);
+}
+
+/**
+ * pt_buffer_fini_topa() - deallocate ToPA structure of a buffer
+ * @buf:       PT buffer.
+ */
+static void pt_buffer_fini_topa(struct pt_buffer *buf)
+{
+       struct topa *topa, *iter;
+
+       list_for_each_entry_safe(topa, iter, &buf->tables, list) {
+               /*
+                * right now, this is in free_aux() path only, so
+                * no need to unlink this table from the list
+                */
+               topa_free(topa);
+       }
+}
+
+/**
+ * pt_buffer_init_topa() - initialize ToPA table for pt buffer
+ * @buf:       PT buffer.
+ * @size:      Total size of all regions within this ToPA.
+ * @gfp:       Allocation flags.
+ */
+static int pt_buffer_init_topa(struct pt_buffer *buf, unsigned long nr_pages,
+                              gfp_t gfp)
+{
+       struct topa *topa;
+       int err;
+
+       topa = topa_alloc(buf->cpu, gfp);
+       if (!topa)
+               return -ENOMEM;
+
+       topa_insert_table(buf, topa);
+
+       while (buf->nr_pages < nr_pages) {
+               err = topa_insert_pages(buf, gfp);
+               if (err) {
+                       pt_buffer_fini_topa(buf);
+                       return -ENOMEM;
+               }
+       }
+
+       pt_buffer_setup_topa_index(buf);
+
+       /* link last table to the first one, unless we're double buffering */
+       if (pt_cap_get(PT_CAP_topa_multiple_entries)) {
+               TOPA_ENTRY(buf->last, -1)->base = buf->first->phys >> TOPA_SHIFT;
+               TOPA_ENTRY(buf->last, -1)->end = 1;
+       }
+
+       pt_topa_dump(buf);
+       return 0;
+}
+
+/**
+ * pt_buffer_setup_aux() - set up topa tables for a PT buffer
+ * @cpu:       Cpu on which to allocate, -1 means current.
+ * @pages:     Array of pointers to buffer pages passed from perf core.
+ * @nr_pages:  Number of pages in the buffer.
+ * @snapshot:  If this is a snapshot/overwrite counter.
+ *
+ * This is a pmu::setup_aux callback that sets up ToPA tables and all the
+ * bookkeeping for an AUX buffer.
+ *
+ * Return:     Our private PT buffer structure.
+ */
+static void *
+pt_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool snapshot)
+{
+       struct pt_buffer *buf;
+       int node, ret;
+
+       if (!nr_pages)
+               return NULL;
+
+       if (cpu == -1)
+               cpu = raw_smp_processor_id();
+       node = cpu_to_node(cpu);
+
+       buf = kzalloc_node(offsetof(struct pt_buffer, topa_index[nr_pages]),
+                          GFP_KERNEL, node);
+       if (!buf)
+               return NULL;
+
+       buf->cpu = cpu;
+       buf->snapshot = snapshot;
+       buf->data_pages = pages;
+
+       INIT_LIST_HEAD(&buf->tables);
+
+       ret = pt_buffer_init_topa(buf, nr_pages, GFP_KERNEL);
+       if (ret) {
+               kfree(buf);
+               return NULL;
+       }
+
+       return buf;
+}
+
+/**
+ * pt_buffer_free_aux() - perf AUX deallocation path callback
+ * @data:      PT buffer.
+ */
+static void pt_buffer_free_aux(void *data)
+{
+       struct pt_buffer *buf = data;
+
+       pt_buffer_fini_topa(buf);
+       kfree(buf);
+}
+
+/**
+ * pt_buffer_is_full() - check if the buffer is full
+ * @buf:       PT buffer.
+ * @pt:                Per-cpu pt handle.
+ *
+ * If the user hasn't read data from the output region that aux_head
+ * points to, the buffer is considered full: the user needs to read at
+ * least this region and update aux_tail to point past it.
+ */
+static bool pt_buffer_is_full(struct pt_buffer *buf, struct pt *pt)
+{
+       if (buf->snapshot)
+               return false;
+
+       if (local_read(&buf->data_size) >= pt->handle.size)
+               return true;
+
+       return false;
+}
+
+/**
+ * intel_pt_interrupt() - PT PMI handler
+ */
+void intel_pt_interrupt(void)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+       struct pt_buffer *buf;
+       struct perf_event *event = pt->handle.event;
+
+       /*
+        * There may be a dangling PT bit in the interrupt status register
+        * after PT has been disabled by pt_event_stop(). Make sure we don't
+        * do anything (particularly, re-enable) for this event here.
+        */
+       if (!ACCESS_ONCE(pt->handle_nmi))
+               return;
+
+       pt_config_start(false);
+
+       if (!event)
+               return;
+
+       buf = perf_get_aux(&pt->handle);
+       if (!buf)
+               return;
+
+       pt_read_offset(buf);
+
+       pt_handle_status(pt);
+
+       pt_update_head(pt);
+
+       perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0),
+                           local_xchg(&buf->lost, 0));
+
+       if (!event->hw.state) {
+               int ret;
+
+               buf = perf_aux_output_begin(&pt->handle, event);
+               if (!buf) {
+                       event->hw.state = PERF_HES_STOPPED;
+                       return;
+               }
+
+               pt_buffer_reset_offsets(buf, pt->handle.head);
+               /* snapshot counters don't use PMI, so it's safe */
+               ret = pt_buffer_reset_markers(buf, &pt->handle);
+               if (ret) {
+                       perf_aux_output_end(&pt->handle, 0, true);
+                       return;
+               }
+
+               pt_config_buffer(buf->cur->table, buf->cur_idx,
+                                buf->output_off);
+               pt_config(event);
+       }
+}
+
+/*
+ * PMU callbacks
+ */
+
+static void pt_event_start(struct perf_event *event, int mode)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+       struct pt_buffer *buf = perf_get_aux(&pt->handle);
+
+       if (!buf || pt_buffer_is_full(buf, pt)) {
+               event->hw.state = PERF_HES_STOPPED;
+               return;
+       }
+
+       ACCESS_ONCE(pt->handle_nmi) = 1;
+       event->hw.state = 0;
+
+       pt_config_buffer(buf->cur->table, buf->cur_idx,
+                        buf->output_off);
+       pt_config(event);
+}
+
+static void pt_event_stop(struct perf_event *event, int mode)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+
+       /*
+        * Protect against the PMI racing with disabling wrmsr,
+        * see comment in intel_pt_interrupt().
+        */
+       ACCESS_ONCE(pt->handle_nmi) = 0;
+       pt_config_start(false);
+
+       if (event->hw.state == PERF_HES_STOPPED)
+               return;
+
+       event->hw.state = PERF_HES_STOPPED;
+
+       if (mode & PERF_EF_UPDATE) {
+               struct pt_buffer *buf = perf_get_aux(&pt->handle);
+
+               if (!buf)
+                       return;
+
+               if (WARN_ON_ONCE(pt->handle.event != event))
+                       return;
+
+               pt_read_offset(buf);
+
+               pt_handle_status(pt);
+
+               pt_update_head(pt);
+       }
+}
+
+static void pt_event_del(struct perf_event *event, int mode)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+       struct pt_buffer *buf;
+
+       pt_event_stop(event, PERF_EF_UPDATE);
+
+       buf = perf_get_aux(&pt->handle);
+
+       if (buf) {
+               if (buf->snapshot)
+                       pt->handle.head =
+                               local_xchg(&buf->data_size,
+                                          buf->nr_pages << PAGE_SHIFT);
+               perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0),
+                                   local_xchg(&buf->lost, 0));
+       }
+}
+
+static int pt_event_add(struct perf_event *event, int mode)
+{
+       struct pt_buffer *buf;
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+       struct hw_perf_event *hwc = &event->hw;
+       int ret = -EBUSY;
+
+       if (pt->handle.event)
+               goto fail;
+
+       buf = perf_aux_output_begin(&pt->handle, event);
+       ret = -EINVAL;
+       if (!buf)
+               goto fail_stop;
+
+       pt_buffer_reset_offsets(buf, pt->handle.head);
+       if (!buf->snapshot) {
+               ret = pt_buffer_reset_markers(buf, &pt->handle);
+               if (ret)
+                       goto fail_end_stop;
+       }
+
+       if (mode & PERF_EF_START) {
+               pt_event_start(event, 0);
+               ret = -EBUSY;
+               if (hwc->state == PERF_HES_STOPPED)
+                       goto fail_end_stop;
+       } else {
+               hwc->state = PERF_HES_STOPPED;
+       }
+
+       return 0;
+
+fail_end_stop:
+       perf_aux_output_end(&pt->handle, 0, true);
+fail_stop:
+       hwc->state = PERF_HES_STOPPED;
+fail:
+       return ret;
+}
+
+static void pt_event_read(struct perf_event *event)
+{
+}
+
+static void pt_event_destroy(struct perf_event *event)
+{
+       x86_del_exclusive(x86_lbr_exclusive_pt);
+}
+
+static int pt_event_init(struct perf_event *event)
+{
+       if (event->attr.type != pt_pmu.pmu.type)
+               return -ENOENT;
+
+       if (!pt_event_valid(event))
+               return -EINVAL;
+
+       if (x86_add_exclusive(x86_lbr_exclusive_pt))
+               return -EBUSY;
+
+       event->destroy = pt_event_destroy;
+
+       return 0;
+}
+
+void cpu_emergency_stop_pt(void)
+{
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
+
+       if (pt->handle.event)
+               pt_event_stop(pt->handle.event, PERF_EF_UPDATE);
+}
+
+static __init int pt_init(void)
+{
+       int ret, cpu, prior_warn = 0;
+
+       BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE);
+
+       if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_INTEL_PT))
+               return -ENODEV;
+
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
+               u64 ctl;
+
+               ret = rdmsrl_safe_on_cpu(cpu, MSR_IA32_RTIT_CTL, &ctl);
+               if (!ret && (ctl & RTIT_CTL_TRACEEN))
+                       prior_warn++;
+       }
+       put_online_cpus();
+
+       if (prior_warn) {
+               x86_add_exclusive(x86_lbr_exclusive_pt);
+               pr_warn("PT is enabled at boot time, doing nothing\n");
+
+               return -EBUSY;
+       }
+
+       ret = pt_pmu_hw_init();
+       if (ret)
+               return ret;
+
+       if (!pt_cap_get(PT_CAP_topa_output)) {
+               pr_warn("ToPA output is not supported on this CPU\n");
+               return -ENODEV;
+       }
+
+       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
+               pt_pmu.pmu.capabilities =
+                       PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF;
+
+       pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE;
+       pt_pmu.pmu.attr_groups  = pt_attr_groups;
+       pt_pmu.pmu.task_ctx_nr  = perf_sw_context;
+       pt_pmu.pmu.event_init   = pt_event_init;
+       pt_pmu.pmu.add          = pt_event_add;
+       pt_pmu.pmu.del          = pt_event_del;
+       pt_pmu.pmu.start        = pt_event_start;
+       pt_pmu.pmu.stop         = pt_event_stop;
+       pt_pmu.pmu.read         = pt_event_read;
+       pt_pmu.pmu.setup_aux    = pt_buffer_setup_aux;
+       pt_pmu.pmu.free_aux     = pt_buffer_free_aux;
+       ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1);
+
+       return ret;
+}
+arch_initcall(pt_init);
diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h
new file mode 100644 (file)
index 0000000..336878a
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Intel(R) Processor Trace PMU driver for perf
+ * Copyright (c) 2013-2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Intel PT is specified in the Intel Architecture Instruction Set Extensions
+ * Programming Reference:
+ * http://software.intel.com/en-us/intel-isa-extensions
+ */
+
+#ifndef __INTEL_PT_H__
+#define __INTEL_PT_H__
+
+/*
+ * Single-entry ToPA: when this close to region boundary, switch
+ * buffers to avoid losing data.
+ */
+#define TOPA_PMI_MARGIN 512
+
+#define TOPA_SHIFT 12
+
+static inline unsigned int sizes(unsigned int tsz)
+{
+       return 1 << (tsz + TOPA_SHIFT);
+};
+
+struct topa_entry {
+       u64     end     : 1;
+       u64     rsvd0   : 1;
+       u64     intr    : 1;
+       u64     rsvd1   : 1;
+       u64     stop    : 1;
+       u64     rsvd2   : 1;
+       u64     size    : 4;
+       u64     rsvd3   : 2;
+       u64     base    : 36;
+       u64     rsvd4   : 16;
+};
+
+#define PT_CPUID_LEAVES                2
+#define PT_CPUID_REGS_NUM      4 /* number of regsters (eax, ebx, ecx, edx) */
+
+enum pt_capabilities {
+       PT_CAP_max_subleaf = 0,
+       PT_CAP_cr3_filtering,
+       PT_CAP_psb_cyc,
+       PT_CAP_mtc,
+       PT_CAP_topa_output,
+       PT_CAP_topa_multiple_entries,
+       PT_CAP_single_range_output,
+       PT_CAP_payloads_lip,
+       PT_CAP_mtc_periods,
+       PT_CAP_cycle_thresholds,
+       PT_CAP_psb_periods,
+};
+
+struct pt_pmu {
+       struct pmu              pmu;
+       u32                     caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
+};
+
+/**
+ * struct pt_buffer - buffer configuration; one buffer per task_struct or
+ *             cpu, depending on perf event configuration
+ * @cpu:       cpu for per-cpu allocation
+ * @tables:    list of ToPA tables in this buffer
+ * @first:     shorthand for first topa table
+ * @last:      shorthand for last topa table
+ * @cur:       current topa table
+ * @nr_pages:  buffer size in pages
+ * @cur_idx:   current output region's index within @cur table
+ * @output_off:        offset within the current output region
+ * @data_size: running total of the amount of data in this buffer
+ * @lost:      if data was lost/truncated
+ * @head:      logical write offset inside the buffer
+ * @snapshot:  if this is for a snapshot/overwrite counter
+ * @stop_pos:  STOP topa entry in the buffer
+ * @intr_pos:  INT topa entry in the buffer
+ * @data_pages:        array of pages from perf
+ * @topa_index:        table of topa entries indexed by page offset
+ */
+struct pt_buffer {
+       int                     cpu;
+       struct list_head        tables;
+       struct topa             *first, *last, *cur;
+       unsigned int            cur_idx;
+       size_t                  output_off;
+       unsigned long           nr_pages;
+       local_t                 data_size;
+       local_t                 lost;
+       local64_t               head;
+       bool                    snapshot;
+       unsigned long           stop_pos, intr_pos;
+       void                    **data_pages;
+       struct topa_entry       *topa_index[0];
+};
+
+/**
+ * struct pt - per-cpu pt context
+ * @handle:    perf output handle
+ * @handle_nmi:        do handle PT PMI on this cpu, there's an active event
+ */
+struct pt {
+       struct perf_output_handle handle;
+       int                     handle_nmi;
+};
+
+#endif /* __INTEL_PT_H__ */
diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
new file mode 100644 (file)
index 0000000..b834a3f
--- /dev/null
@@ -0,0 +1,767 @@
+/*
+ * perf_event_intel_rapl.c: support Intel RAPL energy consumption counters
+ * Copyright (C) 2013 Google, Inc., Stephane Eranian
+ *
+ * Intel RAPL interface is specified in the IA-32 Manual Vol3b
+ * section 14.7.1 (September 2013)
+ *
+ * RAPL provides more controls than just reporting energy consumption
+ * however here we only expose the 3 energy consumption free running
+ * counters (pp0, pkg, dram).
+ *
+ * Each of those counters increments in a power unit defined by the
+ * RAPL_POWER_UNIT MSR. On SandyBridge, this unit is 1/(2^16) Joules
+ * but it can vary.
+ *
+ * Counter to rapl events mappings:
+ *
+ *  pp0 counter: consumption of all physical cores (power plane 0)
+ *       event: rapl_energy_cores
+ *    perf code: 0x1
+ *
+ *  pkg counter: consumption of the whole processor package
+ *       event: rapl_energy_pkg
+ *    perf code: 0x2
+ *
+ * dram counter: consumption of the dram domain (servers only)
+ *       event: rapl_energy_dram
+ *    perf code: 0x3
+ *
+ * dram counter: consumption of the builtin-gpu domain (client only)
+ *       event: rapl_energy_gpu
+ *    perf code: 0x4
+ *
+ * We manage those counters as free running (read-only). They may be
+ * use simultaneously by other tools, such as turbostat.
+ *
+ * The events only support system-wide mode counting. There is no
+ * sampling support because it does not make sense and is not
+ * supported by the RAPL hardware.
+ *
+ * Because we want to avoid floating-point operations in the kernel,
+ * the events are all reported in fixed point arithmetic (32.32).
+ * Tools must adjust the counts to convert them to Watts using
+ * the duration of the measurement. Tools may use a function such as
+ * ldexp(raw_count, -32);
+ */
+
+#define pr_fmt(fmt) "RAPL PMU: " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/perf_event.h>
+#include <asm/cpu_device_id.h>
+#include "../perf_event.h"
+
+/*
+ * RAPL energy status counters
+ */
+#define RAPL_IDX_PP0_NRG_STAT  0       /* all cores */
+#define INTEL_RAPL_PP0         0x1     /* pseudo-encoding */
+#define RAPL_IDX_PKG_NRG_STAT  1       /* entire package */
+#define INTEL_RAPL_PKG         0x2     /* pseudo-encoding */
+#define RAPL_IDX_RAM_NRG_STAT  2       /* DRAM */
+#define INTEL_RAPL_RAM         0x3     /* pseudo-encoding */
+#define RAPL_IDX_PP1_NRG_STAT  3       /* gpu */
+#define INTEL_RAPL_PP1         0x4     /* pseudo-encoding */
+
+#define NR_RAPL_DOMAINS         0x4
+static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = {
+       "pp0-core",
+       "package",
+       "dram",
+       "pp1-gpu",
+};
+
+/* Clients have PP0, PKG */
+#define RAPL_IDX_CLN   (1<<RAPL_IDX_PP0_NRG_STAT|\
+                        1<<RAPL_IDX_PKG_NRG_STAT|\
+                        1<<RAPL_IDX_PP1_NRG_STAT)
+
+/* Servers have PP0, PKG, RAM */
+#define RAPL_IDX_SRV   (1<<RAPL_IDX_PP0_NRG_STAT|\
+                        1<<RAPL_IDX_PKG_NRG_STAT|\
+                        1<<RAPL_IDX_RAM_NRG_STAT)
+
+/* Servers have PP0, PKG, RAM, PP1 */
+#define RAPL_IDX_HSW   (1<<RAPL_IDX_PP0_NRG_STAT|\
+                        1<<RAPL_IDX_PKG_NRG_STAT|\
+                        1<<RAPL_IDX_RAM_NRG_STAT|\
+                        1<<RAPL_IDX_PP1_NRG_STAT)
+
+/* Knights Landing has PKG, RAM */
+#define RAPL_IDX_KNL   (1<<RAPL_IDX_PKG_NRG_STAT|\
+                        1<<RAPL_IDX_RAM_NRG_STAT)
+
+/*
+ * event code: LSB 8 bits, passed in attr->config
+ * any other bit is reserved
+ */
+#define RAPL_EVENT_MASK        0xFFULL
+
+#define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format)          \
+static ssize_t __rapl_##_var##_show(struct kobject *kobj,      \
+                               struct kobj_attribute *attr,    \
+                               char *page)                     \
+{                                                              \
+       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);             \
+       return sprintf(page, _format "\n");                     \
+}                                                              \
+static struct kobj_attribute format_attr_##_var =              \
+       __ATTR(_name, 0444, __rapl_##_var##_show, NULL)
+
+#define RAPL_CNTR_WIDTH 32
+
+#define RAPL_EVENT_ATTR_STR(_name, v, str)                                     \
+static struct perf_pmu_events_attr event_attr_##v = {                          \
+       .attr           = __ATTR(_name, 0444, perf_event_sysfs_show, NULL),     \
+       .id             = 0,                                                    \
+       .event_str      = str,                                                  \
+};
+
+struct rapl_pmu {
+       raw_spinlock_t          lock;
+       int                     n_active;
+       int                     cpu;
+       struct list_head        active_list;
+       struct pmu              *pmu;
+       ktime_t                 timer_interval;
+       struct hrtimer          hrtimer;
+};
+
+struct rapl_pmus {
+       struct pmu              pmu;
+       unsigned int            maxpkg;
+       struct rapl_pmu         *pmus[];
+};
+
+ /* 1/2^hw_unit Joule */
+static int rapl_hw_unit[NR_RAPL_DOMAINS] __read_mostly;
+static struct rapl_pmus *rapl_pmus;
+static cpumask_t rapl_cpu_mask;
+static unsigned int rapl_cntr_mask;
+static u64 rapl_timer_ms;
+
+static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
+{
+       return rapl_pmus->pmus[topology_logical_package_id(cpu)];
+}
+
+static inline u64 rapl_read_counter(struct perf_event *event)
+{
+       u64 raw;
+       rdmsrl(event->hw.event_base, raw);
+       return raw;
+}
+
+static inline u64 rapl_scale(u64 v, int cfg)
+{
+       if (cfg > NR_RAPL_DOMAINS) {
+               pr_warn("Invalid domain %d, failed to scale data\n", cfg);
+               return v;
+       }
+       /*
+        * scale delta to smallest unit (1/2^32)
+        * users must then scale back: count * 1/(1e9*2^32) to get Joules
+        * or use ldexp(count, -32).
+        * Watts = Joules/Time delta
+        */
+       return v << (32 - rapl_hw_unit[cfg - 1]);
+}
+
+static u64 rapl_event_update(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 prev_raw_count, new_raw_count;
+       s64 delta, sdelta;
+       int shift = RAPL_CNTR_WIDTH;
+
+again:
+       prev_raw_count = local64_read(&hwc->prev_count);
+       rdmsrl(event->hw.event_base, new_raw_count);
+
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+                           new_raw_count) != prev_raw_count) {
+               cpu_relax();
+               goto again;
+       }
+
+       /*
+        * Now we have the new raw value and have updated the prev
+        * timestamp already. We can now calculate the elapsed delta
+        * (event-)time and add that to the generic event.
+        *
+        * Careful, not all hw sign-extends above the physical width
+        * of the count.
+        */
+       delta = (new_raw_count << shift) - (prev_raw_count << shift);
+       delta >>= shift;
+
+       sdelta = rapl_scale(delta, event->hw.config);
+
+       local64_add(sdelta, &event->count);
+
+       return new_raw_count;
+}
+
+static void rapl_start_hrtimer(struct rapl_pmu *pmu)
+{
+       hrtimer_start(&pmu->hrtimer, pmu->timer_interval,
+                    HRTIMER_MODE_REL_PINNED);
+}
+
+static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer)
+{
+       struct rapl_pmu *pmu = container_of(hrtimer, struct rapl_pmu, hrtimer);
+       struct perf_event *event;
+       unsigned long flags;
+
+       if (!pmu->n_active)
+               return HRTIMER_NORESTART;
+
+       raw_spin_lock_irqsave(&pmu->lock, flags);
+
+       list_for_each_entry(event, &pmu->active_list, active_entry)
+               rapl_event_update(event);
+
+       raw_spin_unlock_irqrestore(&pmu->lock, flags);
+
+       hrtimer_forward_now(hrtimer, pmu->timer_interval);
+
+       return HRTIMER_RESTART;
+}
+
+static void rapl_hrtimer_init(struct rapl_pmu *pmu)
+{
+       struct hrtimer *hr = &pmu->hrtimer;
+
+       hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       hr->function = rapl_hrtimer_handle;
+}
+
+static void __rapl_pmu_event_start(struct rapl_pmu *pmu,
+                                  struct perf_event *event)
+{
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       event->hw.state = 0;
+
+       list_add_tail(&event->active_entry, &pmu->active_list);
+
+       local64_set(&event->hw.prev_count, rapl_read_counter(event));
+
+       pmu->n_active++;
+       if (pmu->n_active == 1)
+               rapl_start_hrtimer(pmu);
+}
+
+static void rapl_pmu_event_start(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = event->pmu_private;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pmu->lock, flags);
+       __rapl_pmu_event_start(pmu, event);
+       raw_spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static void rapl_pmu_event_stop(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = event->pmu_private;
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pmu->lock, flags);
+
+       /* mark event as deactivated and stopped */
+       if (!(hwc->state & PERF_HES_STOPPED)) {
+               WARN_ON_ONCE(pmu->n_active <= 0);
+               pmu->n_active--;
+               if (pmu->n_active == 0)
+                       hrtimer_cancel(&pmu->hrtimer);
+
+               list_del(&event->active_entry);
+
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+       }
+
+       /* check if update of sw counter is necessary */
+       if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               rapl_event_update(event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+
+       raw_spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static int rapl_pmu_event_add(struct perf_event *event, int mode)
+{
+       struct rapl_pmu *pmu = event->pmu_private;
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pmu->lock, flags);
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+       if (mode & PERF_EF_START)
+               __rapl_pmu_event_start(pmu, event);
+
+       raw_spin_unlock_irqrestore(&pmu->lock, flags);
+
+       return 0;
+}
+
+static void rapl_pmu_event_del(struct perf_event *event, int flags)
+{
+       rapl_pmu_event_stop(event, PERF_EF_UPDATE);
+}
+
+static int rapl_pmu_event_init(struct perf_event *event)
+{
+       u64 cfg = event->attr.config & RAPL_EVENT_MASK;
+       int bit, msr, ret = 0;
+       struct rapl_pmu *pmu;
+
+       /* only look at RAPL events */
+       if (event->attr.type != rapl_pmus->pmu.type)
+               return -ENOENT;
+
+       /* check only supported bits are set */
+       if (event->attr.config & ~RAPL_EVENT_MASK)
+               return -EINVAL;
+
+       if (event->cpu < 0)
+               return -EINVAL;
+
+       /*
+        * check event is known (determines counter)
+        */
+       switch (cfg) {
+       case INTEL_RAPL_PP0:
+               bit = RAPL_IDX_PP0_NRG_STAT;
+               msr = MSR_PP0_ENERGY_STATUS;
+               break;
+       case INTEL_RAPL_PKG:
+               bit = RAPL_IDX_PKG_NRG_STAT;
+               msr = MSR_PKG_ENERGY_STATUS;
+               break;
+       case INTEL_RAPL_RAM:
+               bit = RAPL_IDX_RAM_NRG_STAT;
+               msr = MSR_DRAM_ENERGY_STATUS;
+               break;
+       case INTEL_RAPL_PP1:
+               bit = RAPL_IDX_PP1_NRG_STAT;
+               msr = MSR_PP1_ENERGY_STATUS;
+               break;
+       default:
+               return -EINVAL;
+       }
+       /* check event supported */
+       if (!(rapl_cntr_mask & (1 << bit)))
+               return -EINVAL;
+
+       /* unsupported modes and filters */
+       if (event->attr.exclude_user   ||
+           event->attr.exclude_kernel ||
+           event->attr.exclude_hv     ||
+           event->attr.exclude_idle   ||
+           event->attr.exclude_host   ||
+           event->attr.exclude_guest  ||
+           event->attr.sample_period) /* no sampling */
+               return -EINVAL;
+
+       /* must be done before validate_group */
+       pmu = cpu_to_rapl_pmu(event->cpu);
+       event->cpu = pmu->cpu;
+       event->pmu_private = pmu;
+       event->hw.event_base = msr;
+       event->hw.config = cfg;
+       event->hw.idx = bit;
+
+       return ret;
+}
+
+static void rapl_pmu_event_read(struct perf_event *event)
+{
+       rapl_event_update(event);
+}
+
+static ssize_t rapl_get_attr_cpumask(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       return cpumap_print_to_pagebuf(true, buf, &rapl_cpu_mask);
+}
+
+static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL);
+
+static struct attribute *rapl_pmu_attrs[] = {
+       &dev_attr_cpumask.attr,
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_attr_group = {
+       .attrs = rapl_pmu_attrs,
+};
+
+RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
+RAPL_EVENT_ATTR_STR(energy-pkg  ,   rapl_pkg, "event=0x02");
+RAPL_EVENT_ATTR_STR(energy-ram  ,   rapl_ram, "event=0x03");
+RAPL_EVENT_ATTR_STR(energy-gpu  ,   rapl_gpu, "event=0x04");
+
+RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
+RAPL_EVENT_ATTR_STR(energy-pkg.unit  ,   rapl_pkg_unit, "Joules");
+RAPL_EVENT_ATTR_STR(energy-ram.unit  ,   rapl_ram_unit, "Joules");
+RAPL_EVENT_ATTR_STR(energy-gpu.unit  ,   rapl_gpu_unit, "Joules");
+
+/*
+ * we compute in 0.23 nJ increments regardless of MSR
+ */
+RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
+RAPL_EVENT_ATTR_STR(energy-pkg.scale,     rapl_pkg_scale, "2.3283064365386962890625e-10");
+RAPL_EVENT_ATTR_STR(energy-ram.scale,     rapl_ram_scale, "2.3283064365386962890625e-10");
+RAPL_EVENT_ATTR_STR(energy-gpu.scale,     rapl_gpu_scale, "2.3283064365386962890625e-10");
+
+static struct attribute *rapl_events_srv_attr[] = {
+       EVENT_PTR(rapl_cores),
+       EVENT_PTR(rapl_pkg),
+       EVENT_PTR(rapl_ram),
+
+       EVENT_PTR(rapl_cores_unit),
+       EVENT_PTR(rapl_pkg_unit),
+       EVENT_PTR(rapl_ram_unit),
+
+       EVENT_PTR(rapl_cores_scale),
+       EVENT_PTR(rapl_pkg_scale),
+       EVENT_PTR(rapl_ram_scale),
+       NULL,
+};
+
+static struct attribute *rapl_events_cln_attr[] = {
+       EVENT_PTR(rapl_cores),
+       EVENT_PTR(rapl_pkg),
+       EVENT_PTR(rapl_gpu),
+
+       EVENT_PTR(rapl_cores_unit),
+       EVENT_PTR(rapl_pkg_unit),
+       EVENT_PTR(rapl_gpu_unit),
+
+       EVENT_PTR(rapl_cores_scale),
+       EVENT_PTR(rapl_pkg_scale),
+       EVENT_PTR(rapl_gpu_scale),
+       NULL,
+};
+
+static struct attribute *rapl_events_hsw_attr[] = {
+       EVENT_PTR(rapl_cores),
+       EVENT_PTR(rapl_pkg),
+       EVENT_PTR(rapl_gpu),
+       EVENT_PTR(rapl_ram),
+
+       EVENT_PTR(rapl_cores_unit),
+       EVENT_PTR(rapl_pkg_unit),
+       EVENT_PTR(rapl_gpu_unit),
+       EVENT_PTR(rapl_ram_unit),
+
+       EVENT_PTR(rapl_cores_scale),
+       EVENT_PTR(rapl_pkg_scale),
+       EVENT_PTR(rapl_gpu_scale),
+       EVENT_PTR(rapl_ram_scale),
+       NULL,
+};
+
+static struct attribute *rapl_events_knl_attr[] = {
+       EVENT_PTR(rapl_pkg),
+       EVENT_PTR(rapl_ram),
+
+       EVENT_PTR(rapl_pkg_unit),
+       EVENT_PTR(rapl_ram_unit),
+
+       EVENT_PTR(rapl_pkg_scale),
+       EVENT_PTR(rapl_ram_scale),
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_events_group = {
+       .name = "events",
+       .attrs = NULL, /* patched at runtime */
+};
+
+DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7");
+static struct attribute *rapl_formats_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group rapl_pmu_format_group = {
+       .name = "format",
+       .attrs = rapl_formats_attr,
+};
+
+const struct attribute_group *rapl_attr_groups[] = {
+       &rapl_pmu_attr_group,
+       &rapl_pmu_format_group,
+       &rapl_pmu_events_group,
+       NULL,
+};
+
+static void rapl_cpu_exit(int cpu)
+{
+       struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
+       int target;
+
+       /* Check if exiting cpu is used for collecting rapl events */
+       if (!cpumask_test_and_clear_cpu(cpu, &rapl_cpu_mask))
+               return;
+
+       pmu->cpu = -1;
+       /* Find a new cpu to collect rapl events */
+       target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+
+       /* Migrate rapl events to the new target */
+       if (target < nr_cpu_ids) {
+               cpumask_set_cpu(target, &rapl_cpu_mask);
+               pmu->cpu = target;
+               perf_pmu_migrate_context(pmu->pmu, cpu, target);
+       }
+}
+
+static void rapl_cpu_init(int cpu)
+{
+       struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
+       int target;
+
+       /*
+        * Check if there is an online cpu in the package which collects rapl
+        * events already.
+        */
+       target = cpumask_any_and(&rapl_cpu_mask, topology_core_cpumask(cpu));
+       if (target < nr_cpu_ids)
+               return;
+
+       cpumask_set_cpu(cpu, &rapl_cpu_mask);
+       pmu->cpu = cpu;
+}
+
+static int rapl_cpu_prepare(int cpu)
+{
+       struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
+
+       if (pmu)
+               return 0;
+
+       pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
+       if (!pmu)
+               return -ENOMEM;
+
+       raw_spin_lock_init(&pmu->lock);
+       INIT_LIST_HEAD(&pmu->active_list);
+       pmu->pmu = &rapl_pmus->pmu;
+       pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
+       pmu->cpu = -1;
+       rapl_hrtimer_init(pmu);
+       rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
+       return 0;
+}
+
+static int rapl_cpu_notifier(struct notifier_block *self,
+                            unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               rapl_cpu_prepare(cpu);
+               break;
+
+       case CPU_DOWN_FAILED:
+       case CPU_ONLINE:
+               rapl_cpu_init(cpu);
+               break;
+
+       case CPU_DOWN_PREPARE:
+               rapl_cpu_exit(cpu);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static int rapl_check_hw_unit(bool apply_quirk)
+{
+       u64 msr_rapl_power_unit_bits;
+       int i;
+
+       /* protect rdmsrl() to handle virtualization */
+       if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &msr_rapl_power_unit_bits))
+               return -1;
+       for (i = 0; i < NR_RAPL_DOMAINS; i++)
+               rapl_hw_unit[i] = (msr_rapl_power_unit_bits >> 8) & 0x1FULL;
+
+       /*
+        * DRAM domain on HSW server and KNL has fixed energy unit which can be
+        * different than the unit from power unit MSR. See
+        * "Intel Xeon Processor E5-1600 and E5-2600 v3 Product Families, V2
+        * of 2. Datasheet, September 2014, Reference Number: 330784-001 "
+        */
+       if (apply_quirk)
+               rapl_hw_unit[RAPL_IDX_RAM_NRG_STAT] = 16;
+
+       /*
+        * Calculate the timer rate:
+        * Use reference of 200W for scaling the timeout to avoid counter
+        * overflows. 200W = 200 Joules/sec
+        * Divide interval by 2 to avoid lockstep (2 * 100)
+        * if hw unit is 32, then we use 2 ms 1/200/2
+        */
+       rapl_timer_ms = 2;
+       if (rapl_hw_unit[0] < 32) {
+               rapl_timer_ms = (1000 / (2 * 100));
+               rapl_timer_ms *= (1ULL << (32 - rapl_hw_unit[0] - 1));
+       }
+       return 0;
+}
+
+static void __init rapl_advertise(void)
+{
+       int i;
+
+       pr_info("API unit is 2^-32 Joules, %d fixed counters, %llu ms ovfl timer\n",
+               hweight32(rapl_cntr_mask), rapl_timer_ms);
+
+       for (i = 0; i < NR_RAPL_DOMAINS; i++) {
+               if (rapl_cntr_mask & (1 << i)) {
+                       pr_info("hw unit of domain %s 2^-%d Joules\n",
+                               rapl_domain_names[i], rapl_hw_unit[i]);
+               }
+       }
+}
+
+static int __init rapl_prepare_cpus(void)
+{
+       unsigned int cpu, pkg;
+       int ret;
+
+       for_each_online_cpu(cpu) {
+               pkg = topology_logical_package_id(cpu);
+               if (rapl_pmus->pmus[pkg])
+                       continue;
+
+               ret = rapl_cpu_prepare(cpu);
+               if (ret)
+                       return ret;
+               rapl_cpu_init(cpu);
+       }
+       return 0;
+}
+
+static void __init cleanup_rapl_pmus(void)
+{
+       int i;
+
+       for (i = 0; i < rapl_pmus->maxpkg; i++)
+               kfree(rapl_pmus->pmus + i);
+       kfree(rapl_pmus);
+}
+
+static int __init init_rapl_pmus(void)
+{
+       int maxpkg = topology_max_packages();
+       size_t size;
+
+       size = sizeof(*rapl_pmus) + maxpkg * sizeof(struct rapl_pmu *);
+       rapl_pmus = kzalloc(size, GFP_KERNEL);
+       if (!rapl_pmus)
+               return -ENOMEM;
+
+       rapl_pmus->maxpkg               = maxpkg;
+       rapl_pmus->pmu.attr_groups      = rapl_attr_groups;
+       rapl_pmus->pmu.task_ctx_nr      = perf_invalid_context;
+       rapl_pmus->pmu.event_init       = rapl_pmu_event_init;
+       rapl_pmus->pmu.add              = rapl_pmu_event_add;
+       rapl_pmus->pmu.del              = rapl_pmu_event_del;
+       rapl_pmus->pmu.start            = rapl_pmu_event_start;
+       rapl_pmus->pmu.stop             = rapl_pmu_event_stop;
+       rapl_pmus->pmu.read             = rapl_pmu_event_read;
+       return 0;
+}
+
+static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
+       [0] = { .vendor = X86_VENDOR_INTEL, .family = 6 },
+       [1] = {},
+};
+
+static int __init rapl_pmu_init(void)
+{
+       bool apply_quirk = false;
+       int ret;
+
+       if (!x86_match_cpu(rapl_cpu_match))
+               return -ENODEV;
+
+       switch (boot_cpu_data.x86_model) {
+       case 42: /* Sandy Bridge */
+       case 58: /* Ivy Bridge */
+               rapl_cntr_mask = RAPL_IDX_CLN;
+               rapl_pmu_events_group.attrs = rapl_events_cln_attr;
+               break;
+       case 63: /* Haswell-Server */
+               apply_quirk = true;
+               rapl_cntr_mask = RAPL_IDX_SRV;
+               rapl_pmu_events_group.attrs = rapl_events_srv_attr;
+               break;
+       case 60: /* Haswell */
+       case 69: /* Haswell-Celeron */
+       case 61: /* Broadwell */
+               rapl_cntr_mask = RAPL_IDX_HSW;
+               rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
+               break;
+       case 45: /* Sandy Bridge-EP */
+       case 62: /* IvyTown */
+               rapl_cntr_mask = RAPL_IDX_SRV;
+               rapl_pmu_events_group.attrs = rapl_events_srv_attr;
+               break;
+       case 87: /* Knights Landing */
+               apply_quirk = true;
+               rapl_cntr_mask = RAPL_IDX_KNL;
+               rapl_pmu_events_group.attrs = rapl_events_knl_attr;
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       ret = rapl_check_hw_unit(apply_quirk);
+       if (ret)
+               return ret;
+
+       ret = init_rapl_pmus();
+       if (ret)
+               return ret;
+
+       cpu_notifier_register_begin();
+
+       ret = rapl_prepare_cpus();
+       if (ret)
+               goto out;
+
+       ret = perf_pmu_register(&rapl_pmus->pmu, "power", -1);
+       if (ret)
+               goto out;
+
+       __perf_cpu_notifier(rapl_cpu_notifier);
+       cpu_notifier_register_done();
+       rapl_advertise();
+       return 0;
+
+out:
+       pr_warn("Initialization failed (%d), disabled\n", ret);
+       cleanup_rapl_pmus();
+       cpu_notifier_register_done();
+       return ret;
+}
+device_initcall(rapl_pmu_init);
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
new file mode 100644 (file)
index 0000000..7012d18
--- /dev/null
@@ -0,0 +1,1412 @@
+#include "uncore.h"
+
+static struct intel_uncore_type *empty_uncore[] = { NULL, };
+struct intel_uncore_type **uncore_msr_uncores = empty_uncore;
+struct intel_uncore_type **uncore_pci_uncores = empty_uncore;
+
+static bool pcidrv_registered;
+struct pci_driver *uncore_pci_driver;
+/* pci bus to socket mapping */
+DEFINE_RAW_SPINLOCK(pci2phy_map_lock);
+struct list_head pci2phy_map_head = LIST_HEAD_INIT(pci2phy_map_head);
+struct pci_extra_dev *uncore_extra_pci_dev;
+static int max_packages;
+
+/* mask of cpus that collect uncore events */
+static cpumask_t uncore_cpu_mask;
+
+/* constraint for the fixed counter */
+static struct event_constraint uncore_constraint_fixed =
+       EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL);
+struct event_constraint uncore_constraint_empty =
+       EVENT_CONSTRAINT(0, 0, 0);
+
+static int uncore_pcibus_to_physid(struct pci_bus *bus)
+{
+       struct pci2phy_map *map;
+       int phys_id = -1;
+
+       raw_spin_lock(&pci2phy_map_lock);
+       list_for_each_entry(map, &pci2phy_map_head, list) {
+               if (map->segment == pci_domain_nr(bus)) {
+                       phys_id = map->pbus_to_physid[bus->number];
+                       break;
+               }
+       }
+       raw_spin_unlock(&pci2phy_map_lock);
+
+       return phys_id;
+}
+
+static void uncore_free_pcibus_map(void)
+{
+       struct pci2phy_map *map, *tmp;
+
+       list_for_each_entry_safe(map, tmp, &pci2phy_map_head, list) {
+               list_del(&map->list);
+               kfree(map);
+       }
+}
+
+struct pci2phy_map *__find_pci2phy_map(int segment)
+{
+       struct pci2phy_map *map, *alloc = NULL;
+       int i;
+
+       lockdep_assert_held(&pci2phy_map_lock);
+
+lookup:
+       list_for_each_entry(map, &pci2phy_map_head, list) {
+               if (map->segment == segment)
+                       goto end;
+       }
+
+       if (!alloc) {
+               raw_spin_unlock(&pci2phy_map_lock);
+               alloc = kmalloc(sizeof(struct pci2phy_map), GFP_KERNEL);
+               raw_spin_lock(&pci2phy_map_lock);
+
+               if (!alloc)
+                       return NULL;
+
+               goto lookup;
+       }
+
+       map = alloc;
+       alloc = NULL;
+       map->segment = segment;
+       for (i = 0; i < 256; i++)
+               map->pbus_to_physid[i] = -1;
+       list_add_tail(&map->list, &pci2phy_map_head);
+
+end:
+       kfree(alloc);
+       return map;
+}
+
+ssize_t uncore_event_show(struct kobject *kobj,
+                         struct kobj_attribute *attr, char *buf)
+{
+       struct uncore_event_desc *event =
+               container_of(attr, struct uncore_event_desc, attr);
+       return sprintf(buf, "%s", event->config);
+}
+
+struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
+{
+       return pmu->boxes[topology_logical_package_id(cpu)];
+}
+
+u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       u64 count;
+
+       rdmsrl(event->hw.event_base, count);
+
+       return count;
+}
+
+/*
+ * generic get constraint function for shared match/mask registers.
+ */
+struct event_constraint *
+uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct intel_uncore_extra_reg *er;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
+       unsigned long flags;
+       bool ok = false;
+
+       /*
+        * reg->alloc can be set due to existing state, so for fake box we
+        * need to ignore this, otherwise we might fail to allocate proper
+        * fake state for this extra reg constraint.
+        */
+       if (reg1->idx == EXTRA_REG_NONE ||
+           (!uncore_box_is_fake(box) && reg1->alloc))
+               return NULL;
+
+       er = &box->shared_regs[reg1->idx];
+       raw_spin_lock_irqsave(&er->lock, flags);
+       if (!atomic_read(&er->ref) ||
+           (er->config1 == reg1->config && er->config2 == reg2->config)) {
+               atomic_inc(&er->ref);
+               er->config1 = reg1->config;
+               er->config2 = reg2->config;
+               ok = true;
+       }
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+
+       if (ok) {
+               if (!uncore_box_is_fake(box))
+                       reg1->alloc = 1;
+               return NULL;
+       }
+
+       return &uncore_constraint_empty;
+}
+
+void uncore_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct intel_uncore_extra_reg *er;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+
+       /*
+        * Only put constraint if extra reg was actually allocated. Also
+        * takes care of event which do not use an extra shared reg.
+        *
+        * Also, if this is a fake box we shouldn't touch any event state
+        * (reg->alloc) and we don't care about leaving inconsistent box
+        * state either since it will be thrown out.
+        */
+       if (uncore_box_is_fake(box) || !reg1->alloc)
+               return;
+
+       er = &box->shared_regs[reg1->idx];
+       atomic_dec(&er->ref);
+       reg1->alloc = 0;
+}
+
+u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx)
+{
+       struct intel_uncore_extra_reg *er;
+       unsigned long flags;
+       u64 config;
+
+       er = &box->shared_regs[idx];
+
+       raw_spin_lock_irqsave(&er->lock, flags);
+       config = er->config;
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+
+       return config;
+}
+
+static void uncore_assign_hw_event(struct intel_uncore_box *box,
+                                  struct perf_event *event, int idx)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       hwc->idx = idx;
+       hwc->last_tag = ++box->tags[idx];
+
+       if (hwc->idx == UNCORE_PMC_IDX_FIXED) {
+               hwc->event_base = uncore_fixed_ctr(box);
+               hwc->config_base = uncore_fixed_ctl(box);
+               return;
+       }
+
+       hwc->config_base = uncore_event_ctl(box, hwc->idx);
+       hwc->event_base  = uncore_perf_ctr(box, hwc->idx);
+}
+
+void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event)
+{
+       u64 prev_count, new_count, delta;
+       int shift;
+
+       if (event->hw.idx >= UNCORE_PMC_IDX_FIXED)
+               shift = 64 - uncore_fixed_ctr_bits(box);
+       else
+               shift = 64 - uncore_perf_ctr_bits(box);
+
+       /* the hrtimer might modify the previous event value */
+again:
+       prev_count = local64_read(&event->hw.prev_count);
+       new_count = uncore_read_counter(box, event);
+       if (local64_xchg(&event->hw.prev_count, new_count) != prev_count)
+               goto again;
+
+       delta = (new_count << shift) - (prev_count << shift);
+       delta >>= shift;
+
+       local64_add(delta, &event->count);
+}
+
+/*
+ * The overflow interrupt is unavailable for SandyBridge-EP, is broken
+ * for SandyBridge. So we use hrtimer to periodically poll the counter
+ * to avoid overflow.
+ */
+static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
+{
+       struct intel_uncore_box *box;
+       struct perf_event *event;
+       unsigned long flags;
+       int bit;
+
+       box = container_of(hrtimer, struct intel_uncore_box, hrtimer);
+       if (!box->n_active || box->cpu != smp_processor_id())
+               return HRTIMER_NORESTART;
+       /*
+        * disable local interrupt to prevent uncore_pmu_event_start/stop
+        * to interrupt the update process
+        */
+       local_irq_save(flags);
+
+       /*
+        * handle boxes with an active event list as opposed to active
+        * counters
+        */
+       list_for_each_entry(event, &box->active_list, active_entry) {
+               uncore_perf_event_update(box, event);
+       }
+
+       for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX)
+               uncore_perf_event_update(box, box->events[bit]);
+
+       local_irq_restore(flags);
+
+       hrtimer_forward_now(hrtimer, ns_to_ktime(box->hrtimer_duration));
+       return HRTIMER_RESTART;
+}
+
+void uncore_pmu_start_hrtimer(struct intel_uncore_box *box)
+{
+       hrtimer_start(&box->hrtimer, ns_to_ktime(box->hrtimer_duration),
+                     HRTIMER_MODE_REL_PINNED);
+}
+
+void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box)
+{
+       hrtimer_cancel(&box->hrtimer);
+}
+
+static void uncore_pmu_init_hrtimer(struct intel_uncore_box *box)
+{
+       hrtimer_init(&box->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       box->hrtimer.function = uncore_pmu_hrtimer;
+}
+
+static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
+                                                int node)
+{
+       int i, size, numshared = type->num_shared_regs ;
+       struct intel_uncore_box *box;
+
+       size = sizeof(*box) + numshared * sizeof(struct intel_uncore_extra_reg);
+
+       box = kzalloc_node(size, GFP_KERNEL, node);
+       if (!box)
+               return NULL;
+
+       for (i = 0; i < numshared; i++)
+               raw_spin_lock_init(&box->shared_regs[i].lock);
+
+       uncore_pmu_init_hrtimer(box);
+       box->cpu = -1;
+       box->pci_phys_id = -1;
+       box->pkgid = -1;
+
+       /* set default hrtimer timeout */
+       box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL;
+
+       INIT_LIST_HEAD(&box->active_list);
+
+       return box;
+}
+
+/*
+ * Using uncore_pmu_event_init pmu event_init callback
+ * as a detection point for uncore events.
+ */
+static int uncore_pmu_event_init(struct perf_event *event);
+
+static bool is_uncore_event(struct perf_event *event)
+{
+       return event->pmu->event_init == uncore_pmu_event_init;
+}
+
+static int
+uncore_collect_events(struct intel_uncore_box *box, struct perf_event *leader,
+                     bool dogrp)
+{
+       struct perf_event *event;
+       int n, max_count;
+
+       max_count = box->pmu->type->num_counters;
+       if (box->pmu->type->fixed_ctl)
+               max_count++;
+
+       if (box->n_events >= max_count)
+               return -EINVAL;
+
+       n = box->n_events;
+
+       if (is_uncore_event(leader)) {
+               box->event_list[n] = leader;
+               n++;
+       }
+
+       if (!dogrp)
+               return n;
+
+       list_for_each_entry(event, &leader->sibling_list, group_entry) {
+               if (!is_uncore_event(event) ||
+                   event->state <= PERF_EVENT_STATE_OFF)
+                       continue;
+
+               if (n >= max_count)
+                       return -EINVAL;
+
+               box->event_list[n] = event;
+               n++;
+       }
+       return n;
+}
+
+static struct event_constraint *
+uncore_get_event_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct intel_uncore_type *type = box->pmu->type;
+       struct event_constraint *c;
+
+       if (type->ops->get_constraint) {
+               c = type->ops->get_constraint(box, event);
+               if (c)
+                       return c;
+       }
+
+       if (event->attr.config == UNCORE_FIXED_EVENT)
+               return &uncore_constraint_fixed;
+
+       if (type->constraints) {
+               for_each_event_constraint(c, type->constraints) {
+                       if ((event->hw.config & c->cmask) == c->code)
+                               return c;
+               }
+       }
+
+       return &type->unconstrainted;
+}
+
+static void uncore_put_event_constraint(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       if (box->pmu->type->ops->put_constraint)
+               box->pmu->type->ops->put_constraint(box, event);
+}
+
+static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int n)
+{
+       unsigned long used_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
+       struct event_constraint *c;
+       int i, wmin, wmax, ret = 0;
+       struct hw_perf_event *hwc;
+
+       bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX);
+
+       for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) {
+               c = uncore_get_event_constraint(box, box->event_list[i]);
+               box->event_constraint[i] = c;
+               wmin = min(wmin, c->weight);
+               wmax = max(wmax, c->weight);
+       }
+
+       /* fastpath, try to reuse previous register */
+       for (i = 0; i < n; i++) {
+               hwc = &box->event_list[i]->hw;
+               c = box->event_constraint[i];
+
+               /* never assigned */
+               if (hwc->idx == -1)
+                       break;
+
+               /* constraint still honored */
+               if (!test_bit(hwc->idx, c->idxmsk))
+                       break;
+
+               /* not already used */
+               if (test_bit(hwc->idx, used_mask))
+                       break;
+
+               __set_bit(hwc->idx, used_mask);
+               if (assign)
+                       assign[i] = hwc->idx;
+       }
+       /* slow path */
+       if (i != n)
+               ret = perf_assign_events(box->event_constraint, n,
+                                        wmin, wmax, n, assign);
+
+       if (!assign || ret) {
+               for (i = 0; i < n; i++)
+                       uncore_put_event_constraint(box, box->event_list[i]);
+       }
+       return ret ? -EINVAL : 0;
+}
+
+static void uncore_pmu_event_start(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       int idx = event->hw.idx;
+
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       if (WARN_ON_ONCE(idx == -1 || idx >= UNCORE_PMC_IDX_MAX))
+               return;
+
+       event->hw.state = 0;
+       box->events[idx] = event;
+       box->n_active++;
+       __set_bit(idx, box->active_mask);
+
+       local64_set(&event->hw.prev_count, uncore_read_counter(box, event));
+       uncore_enable_event(box, event);
+
+       if (box->n_active == 1) {
+               uncore_enable_box(box);
+               uncore_pmu_start_hrtimer(box);
+       }
+}
+
+static void uncore_pmu_event_stop(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (__test_and_clear_bit(hwc->idx, box->active_mask)) {
+               uncore_disable_event(box, event);
+               box->n_active--;
+               box->events[hwc->idx] = NULL;
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+
+               if (box->n_active == 0) {
+                       uncore_disable_box(box);
+                       uncore_pmu_cancel_hrtimer(box);
+               }
+       }
+
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               uncore_perf_event_update(box, event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+}
+
+static int uncore_pmu_event_add(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+       int assign[UNCORE_PMC_IDX_MAX];
+       int i, n, ret;
+
+       if (!box)
+               return -ENODEV;
+
+       ret = n = uncore_collect_events(box, event, false);
+       if (ret < 0)
+               return ret;
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+       if (!(flags & PERF_EF_START))
+               hwc->state |= PERF_HES_ARCH;
+
+       ret = uncore_assign_events(box, assign, n);
+       if (ret)
+               return ret;
+
+       /* save events moving to new counters */
+       for (i = 0; i < box->n_events; i++) {
+               event = box->event_list[i];
+               hwc = &event->hw;
+
+               if (hwc->idx == assign[i] &&
+                       hwc->last_tag == box->tags[assign[i]])
+                       continue;
+               /*
+                * Ensure we don't accidentally enable a stopped
+                * counter simply because we rescheduled.
+                */
+               if (hwc->state & PERF_HES_STOPPED)
+                       hwc->state |= PERF_HES_ARCH;
+
+               uncore_pmu_event_stop(event, PERF_EF_UPDATE);
+       }
+
+       /* reprogram moved events into new counters */
+       for (i = 0; i < n; i++) {
+               event = box->event_list[i];
+               hwc = &event->hw;
+
+               if (hwc->idx != assign[i] ||
+                       hwc->last_tag != box->tags[assign[i]])
+                       uncore_assign_hw_event(box, event, assign[i]);
+               else if (i < box->n_events)
+                       continue;
+
+               if (hwc->state & PERF_HES_ARCH)
+                       continue;
+
+               uncore_pmu_event_start(event, 0);
+       }
+       box->n_events = n;
+
+       return 0;
+}
+
+static void uncore_pmu_event_del(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       int i;
+
+       uncore_pmu_event_stop(event, PERF_EF_UPDATE);
+
+       for (i = 0; i < box->n_events; i++) {
+               if (event == box->event_list[i]) {
+                       uncore_put_event_constraint(box, event);
+
+                       for (++i; i < box->n_events; i++)
+                               box->event_list[i - 1] = box->event_list[i];
+
+                       --box->n_events;
+                       break;
+               }
+       }
+
+       event->hw.idx = -1;
+       event->hw.last_tag = ~0ULL;
+}
+
+void uncore_pmu_event_read(struct perf_event *event)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       uncore_perf_event_update(box, event);
+}
+
+/*
+ * validation ensures the group can be loaded onto the
+ * PMU if it was the only group available.
+ */
+static int uncore_validate_group(struct intel_uncore_pmu *pmu,
+                               struct perf_event *event)
+{
+       struct perf_event *leader = event->group_leader;
+       struct intel_uncore_box *fake_box;
+       int ret = -EINVAL, n;
+
+       fake_box = uncore_alloc_box(pmu->type, NUMA_NO_NODE);
+       if (!fake_box)
+               return -ENOMEM;
+
+       fake_box->pmu = pmu;
+       /*
+        * the event is not yet connected with its
+        * siblings therefore we must first collect
+        * existing siblings, then add the new event
+        * before we can simulate the scheduling
+        */
+       n = uncore_collect_events(fake_box, leader, true);
+       if (n < 0)
+               goto out;
+
+       fake_box->n_events = n;
+       n = uncore_collect_events(fake_box, event, false);
+       if (n < 0)
+               goto out;
+
+       fake_box->n_events = n;
+
+       ret = uncore_assign_events(fake_box, NULL, n);
+out:
+       kfree(fake_box);
+       return ret;
+}
+
+static int uncore_pmu_event_init(struct perf_event *event)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       struct hw_perf_event *hwc = &event->hw;
+       int ret;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       pmu = uncore_event_to_pmu(event);
+       /* no device found for this pmu */
+       if (pmu->func_id < 0)
+               return -ENOENT;
+
+       /*
+        * Uncore PMU does measure at all privilege level all the time.
+        * So it doesn't make sense to specify any exclude bits.
+        */
+       if (event->attr.exclude_user || event->attr.exclude_kernel ||
+                       event->attr.exclude_hv || event->attr.exclude_idle)
+               return -EINVAL;
+
+       /* Sampling not supported yet */
+       if (hwc->sample_period)
+               return -EINVAL;
+
+       /*
+        * Place all uncore events for a particular physical package
+        * onto a single cpu
+        */
+       if (event->cpu < 0)
+               return -EINVAL;
+       box = uncore_pmu_to_box(pmu, event->cpu);
+       if (!box || box->cpu < 0)
+               return -EINVAL;
+       event->cpu = box->cpu;
+       event->pmu_private = box;
+
+       event->hw.idx = -1;
+       event->hw.last_tag = ~0ULL;
+       event->hw.extra_reg.idx = EXTRA_REG_NONE;
+       event->hw.branch_reg.idx = EXTRA_REG_NONE;
+
+       if (event->attr.config == UNCORE_FIXED_EVENT) {
+               /* no fixed counter */
+               if (!pmu->type->fixed_ctl)
+                       return -EINVAL;
+               /*
+                * if there is only one fixed counter, only the first pmu
+                * can access the fixed counter
+                */
+               if (pmu->type->single_fixed && pmu->pmu_idx > 0)
+                       return -EINVAL;
+
+               /* fixed counters have event field hardcoded to zero */
+               hwc->config = 0ULL;
+       } else {
+               hwc->config = event->attr.config & pmu->type->event_mask;
+               if (pmu->type->ops->hw_config) {
+                       ret = pmu->type->ops->hw_config(box, event);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       if (event->group_leader != event)
+               ret = uncore_validate_group(pmu, event);
+       else
+               ret = 0;
+
+       return ret;
+}
+
+static ssize_t uncore_get_attr_cpumask(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       return cpumap_print_to_pagebuf(true, buf, &uncore_cpu_mask);
+}
+
+static DEVICE_ATTR(cpumask, S_IRUGO, uncore_get_attr_cpumask, NULL);
+
+static struct attribute *uncore_pmu_attrs[] = {
+       &dev_attr_cpumask.attr,
+       NULL,
+};
+
+static struct attribute_group uncore_pmu_attr_group = {
+       .attrs = uncore_pmu_attrs,
+};
+
+static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
+{
+       int ret;
+
+       if (!pmu->type->pmu) {
+               pmu->pmu = (struct pmu) {
+                       .attr_groups    = pmu->type->attr_groups,
+                       .task_ctx_nr    = perf_invalid_context,
+                       .event_init     = uncore_pmu_event_init,
+                       .add            = uncore_pmu_event_add,
+                       .del            = uncore_pmu_event_del,
+                       .start          = uncore_pmu_event_start,
+                       .stop           = uncore_pmu_event_stop,
+                       .read           = uncore_pmu_event_read,
+               };
+       } else {
+               pmu->pmu = *pmu->type->pmu;
+               pmu->pmu.attr_groups = pmu->type->attr_groups;
+       }
+
+       if (pmu->type->num_boxes == 1) {
+               if (strlen(pmu->type->name) > 0)
+                       sprintf(pmu->name, "uncore_%s", pmu->type->name);
+               else
+                       sprintf(pmu->name, "uncore");
+       } else {
+               sprintf(pmu->name, "uncore_%s_%d", pmu->type->name,
+                       pmu->pmu_idx);
+       }
+
+       ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
+       if (!ret)
+               pmu->registered = true;
+       return ret;
+}
+
+static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu)
+{
+       if (!pmu->registered)
+               return;
+       perf_pmu_unregister(&pmu->pmu);
+       pmu->registered = false;
+}
+
+static void __init __uncore_exit_boxes(struct intel_uncore_type *type, int cpu)
+{
+       struct intel_uncore_pmu *pmu = type->pmus;
+       struct intel_uncore_box *box;
+       int i, pkg;
+
+       if (pmu) {
+               pkg = topology_physical_package_id(cpu);
+               for (i = 0; i < type->num_boxes; i++, pmu++) {
+                       box = pmu->boxes[pkg];
+                       if (box)
+                               uncore_box_exit(box);
+               }
+       }
+}
+
+static void __init uncore_exit_boxes(void *dummy)
+{
+       struct intel_uncore_type **types;
+
+       for (types = uncore_msr_uncores; *types; types++)
+               __uncore_exit_boxes(*types++, smp_processor_id());
+}
+
+static void uncore_free_boxes(struct intel_uncore_pmu *pmu)
+{
+       int pkg;
+
+       for (pkg = 0; pkg < max_packages; pkg++)
+               kfree(pmu->boxes[pkg]);
+       kfree(pmu->boxes);
+}
+
+static void __init uncore_type_exit(struct intel_uncore_type *type)
+{
+       struct intel_uncore_pmu *pmu = type->pmus;
+       int i;
+
+       if (pmu) {
+               for (i = 0; i < type->num_boxes; i++, pmu++) {
+                       uncore_pmu_unregister(pmu);
+                       uncore_free_boxes(pmu);
+               }
+               kfree(type->pmus);
+               type->pmus = NULL;
+       }
+       kfree(type->events_group);
+       type->events_group = NULL;
+}
+
+static void __init uncore_types_exit(struct intel_uncore_type **types)
+{
+       for (; *types; types++)
+               uncore_type_exit(*types);
+}
+
+static int __init uncore_type_init(struct intel_uncore_type *type, bool setid)
+{
+       struct intel_uncore_pmu *pmus;
+       struct attribute_group *attr_group;
+       struct attribute **attrs;
+       size_t size;
+       int i, j;
+
+       pmus = kzalloc(sizeof(*pmus) * type->num_boxes, GFP_KERNEL);
+       if (!pmus)
+               return -ENOMEM;
+
+       size = max_packages * sizeof(struct intel_uncore_box *);
+
+       for (i = 0; i < type->num_boxes; i++) {
+               pmus[i].func_id = setid ? i : -1;
+               pmus[i].pmu_idx = i;
+               pmus[i].type    = type;
+               pmus[i].boxes   = kzalloc(size, GFP_KERNEL);
+               if (!pmus[i].boxes)
+                       return -ENOMEM;
+       }
+
+       type->pmus = pmus;
+       type->unconstrainted = (struct event_constraint)
+               __EVENT_CONSTRAINT(0, (1ULL << type->num_counters) - 1,
+                               0, type->num_counters, 0, 0);
+
+       if (type->event_descs) {
+               for (i = 0; type->event_descs[i].attr.attr.name; i++);
+
+               attr_group = kzalloc(sizeof(struct attribute *) * (i + 1) +
+                                       sizeof(*attr_group), GFP_KERNEL);
+               if (!attr_group)
+                       return -ENOMEM;
+
+               attrs = (struct attribute **)(attr_group + 1);
+               attr_group->name = "events";
+               attr_group->attrs = attrs;
+
+               for (j = 0; j < i; j++)
+                       attrs[j] = &type->event_descs[j].attr.attr;
+
+               type->events_group = attr_group;
+       }
+
+       type->pmu_group = &uncore_pmu_attr_group;
+       return 0;
+}
+
+static int __init
+uncore_types_init(struct intel_uncore_type **types, bool setid)
+{
+       int ret;
+
+       for (; *types; types++) {
+               ret = uncore_type_init(*types, setid);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/*
+ * add a pci uncore device
+ */
+static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int phys_id, pkg, ret;
+
+       phys_id = uncore_pcibus_to_physid(pdev->bus);
+       if (phys_id < 0)
+               return -ENODEV;
+
+       pkg = topology_phys_to_logical_pkg(phys_id);
+       if (WARN_ON_ONCE(pkg < 0))
+               return -EINVAL;
+
+       if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) {
+               int idx = UNCORE_PCI_DEV_IDX(id->driver_data);
+
+               uncore_extra_pci_dev[pkg].dev[idx] = pdev;
+               pci_set_drvdata(pdev, NULL);
+               return 0;
+       }
+
+       type = uncore_pci_uncores[UNCORE_PCI_DEV_TYPE(id->driver_data)];
+       /*
+        * for performance monitoring unit with multiple boxes,
+        * each box has a different function id.
+        */
+       pmu = &type->pmus[UNCORE_PCI_DEV_IDX(id->driver_data)];
+       /* Knights Landing uses a common PCI device ID for multiple instances of
+        * an uncore PMU device type. There is only one entry per device type in
+        * the knl_uncore_pci_ids table inspite of multiple devices present for
+        * some device types. Hence PCI device idx would be 0 for all devices.
+        * So increment pmu pointer to point to an unused array element.
+        */
+       if (boot_cpu_data.x86_model == 87) {
+               while (pmu->func_id >= 0)
+                       pmu++;
+       }
+
+       if (WARN_ON_ONCE(pmu->boxes[pkg] != NULL))
+               return -EINVAL;
+
+       box = uncore_alloc_box(type, NUMA_NO_NODE);
+       if (!box)
+               return -ENOMEM;
+
+       if (pmu->func_id < 0)
+               pmu->func_id = pdev->devfn;
+       else
+               WARN_ON_ONCE(pmu->func_id != pdev->devfn);
+
+       atomic_inc(&box->refcnt);
+       box->pci_phys_id = phys_id;
+       box->pkgid = pkg;
+       box->pci_dev = pdev;
+       box->pmu = pmu;
+       uncore_box_init(box);
+       pci_set_drvdata(pdev, box);
+
+       pmu->boxes[pkg] = box;
+       if (atomic_inc_return(&pmu->activeboxes) > 1)
+               return 0;
+
+       /* First active box registers the pmu */
+       ret = uncore_pmu_register(pmu);
+       if (ret) {
+               pci_set_drvdata(pdev, NULL);
+               pmu->boxes[pkg] = NULL;
+               uncore_box_exit(box);
+               kfree(box);
+       }
+       return ret;
+}
+
+static void uncore_pci_remove(struct pci_dev *pdev)
+{
+       struct intel_uncore_box *box = pci_get_drvdata(pdev);
+       struct intel_uncore_pmu *pmu;
+       int i, phys_id, pkg;
+
+       phys_id = uncore_pcibus_to_physid(pdev->bus);
+       pkg = topology_phys_to_logical_pkg(phys_id);
+
+       box = pci_get_drvdata(pdev);
+       if (!box) {
+               for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) {
+                       if (uncore_extra_pci_dev[pkg].dev[i] == pdev) {
+                               uncore_extra_pci_dev[pkg].dev[i] = NULL;
+                               break;
+                       }
+               }
+               WARN_ON_ONCE(i >= UNCORE_EXTRA_PCI_DEV_MAX);
+               return;
+       }
+
+       pmu = box->pmu;
+       if (WARN_ON_ONCE(phys_id != box->pci_phys_id))
+               return;
+
+       pci_set_drvdata(pdev, NULL);
+       pmu->boxes[pkg] = NULL;
+       if (atomic_dec_return(&pmu->activeboxes) == 0)
+               uncore_pmu_unregister(pmu);
+       uncore_box_exit(box);
+       kfree(box);
+}
+
+static int __init uncore_pci_init(void)
+{
+       size_t size;
+       int ret;
+
+       switch (boot_cpu_data.x86_model) {
+       case 45: /* Sandy Bridge-EP */
+               ret = snbep_uncore_pci_init();
+               break;
+       case 62: /* Ivy Bridge-EP */
+               ret = ivbep_uncore_pci_init();
+               break;
+       case 63: /* Haswell-EP */
+               ret = hswep_uncore_pci_init();
+               break;
+       case 79: /* BDX-EP */
+       case 86: /* BDX-DE */
+               ret = bdx_uncore_pci_init();
+               break;
+       case 42: /* Sandy Bridge */
+               ret = snb_uncore_pci_init();
+               break;
+       case 58: /* Ivy Bridge */
+               ret = ivb_uncore_pci_init();
+               break;
+       case 60: /* Haswell */
+       case 69: /* Haswell Celeron */
+               ret = hsw_uncore_pci_init();
+               break;
+       case 61: /* Broadwell */
+               ret = bdw_uncore_pci_init();
+               break;
+       case 87: /* Knights Landing */
+               ret = knl_uncore_pci_init();
+               break;
+       case 94: /* SkyLake */
+               ret = skl_uncore_pci_init();
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       if (ret)
+               return ret;
+
+       size = max_packages * sizeof(struct pci_extra_dev);
+       uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL);
+       if (!uncore_extra_pci_dev) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       ret = uncore_types_init(uncore_pci_uncores, false);
+       if (ret)
+               goto errtype;
+
+       uncore_pci_driver->probe = uncore_pci_probe;
+       uncore_pci_driver->remove = uncore_pci_remove;
+
+       ret = pci_register_driver(uncore_pci_driver);
+       if (ret)
+               goto errtype;
+
+       pcidrv_registered = true;
+       return 0;
+
+errtype:
+       uncore_types_exit(uncore_pci_uncores);
+       kfree(uncore_extra_pci_dev);
+       uncore_extra_pci_dev = NULL;
+       uncore_free_pcibus_map();
+err:
+       uncore_pci_uncores = empty_uncore;
+       return ret;
+}
+
+static void __init uncore_pci_exit(void)
+{
+       if (pcidrv_registered) {
+               pcidrv_registered = false;
+               pci_unregister_driver(uncore_pci_driver);
+               uncore_types_exit(uncore_pci_uncores);
+               kfree(uncore_extra_pci_dev);
+               uncore_free_pcibus_map();
+       }
+}
+
+static void uncore_cpu_dying(int cpu)
+{
+       struct intel_uncore_type *type, **types = uncore_msr_uncores;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, pkg;
+
+       pkg = topology_logical_package_id(cpu);
+       for (; *types; types++) {
+               type = *types;
+               pmu = type->pmus;
+               for (i = 0; i < type->num_boxes; i++, pmu++) {
+                       box = pmu->boxes[pkg];
+                       if (box && atomic_dec_return(&box->refcnt) == 0)
+                               uncore_box_exit(box);
+               }
+       }
+}
+
+static void uncore_cpu_starting(int cpu, bool init)
+{
+       struct intel_uncore_type *type, **types = uncore_msr_uncores;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, pkg, ncpus = 1;
+
+       if (init) {
+               /*
+                * On init we get the number of online cpus in the package
+                * and set refcount for all of them.
+                */
+               ncpus = cpumask_weight(topology_core_cpumask(cpu));
+       }
+
+       pkg = topology_logical_package_id(cpu);
+       for (; *types; types++) {
+               type = *types;
+               pmu = type->pmus;
+               for (i = 0; i < type->num_boxes; i++, pmu++) {
+                       box = pmu->boxes[pkg];
+                       if (!box)
+                               continue;
+                       /* The first cpu on a package activates the box */
+                       if (atomic_add_return(ncpus, &box->refcnt) == ncpus)
+                               uncore_box_init(box);
+               }
+       }
+}
+
+static int uncore_cpu_prepare(int cpu)
+{
+       struct intel_uncore_type *type, **types = uncore_msr_uncores;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, pkg;
+
+       pkg = topology_logical_package_id(cpu);
+       for (; *types; types++) {
+               type = *types;
+               pmu = type->pmus;
+               for (i = 0; i < type->num_boxes; i++, pmu++) {
+                       if (pmu->boxes[pkg])
+                               continue;
+                       /* First cpu of a package allocates the box */
+                       box = uncore_alloc_box(type, cpu_to_node(cpu));
+                       if (!box)
+                               return -ENOMEM;
+                       box->pmu = pmu;
+                       box->pkgid = pkg;
+                       pmu->boxes[pkg] = box;
+               }
+       }
+       return 0;
+}
+
+static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_cpu,
+                                  int new_cpu)
+{
+       struct intel_uncore_pmu *pmu = type->pmus;
+       struct intel_uncore_box *box;
+       int i, pkg;
+
+       pkg = topology_logical_package_id(old_cpu < 0 ? new_cpu : old_cpu);
+       for (i = 0; i < type->num_boxes; i++, pmu++) {
+               box = pmu->boxes[pkg];
+               if (!box)
+                       continue;
+
+               if (old_cpu < 0) {
+                       WARN_ON_ONCE(box->cpu != -1);
+                       box->cpu = new_cpu;
+                       continue;
+               }
+
+               WARN_ON_ONCE(box->cpu != old_cpu);
+               box->cpu = -1;
+               if (new_cpu < 0)
+                       continue;
+
+               uncore_pmu_cancel_hrtimer(box);
+               perf_pmu_migrate_context(&pmu->pmu, old_cpu, new_cpu);
+               box->cpu = new_cpu;
+       }
+}
+
+static void uncore_change_context(struct intel_uncore_type **uncores,
+                                 int old_cpu, int new_cpu)
+{
+       for (; *uncores; uncores++)
+               uncore_change_type_ctx(*uncores, old_cpu, new_cpu);
+}
+
+static void uncore_event_exit_cpu(int cpu)
+{
+       int target;
+
+       /* Check if exiting cpu is used for collecting uncore events */
+       if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
+               return;
+
+       /* Find a new cpu to collect uncore events */
+       target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+
+       /* Migrate uncore events to the new target */
+       if (target < nr_cpu_ids)
+               cpumask_set_cpu(target, &uncore_cpu_mask);
+       else
+               target = -1;
+
+       uncore_change_context(uncore_msr_uncores, cpu, target);
+       uncore_change_context(uncore_pci_uncores, cpu, target);
+}
+
+static void uncore_event_init_cpu(int cpu)
+{
+       int target;
+
+       /*
+        * Check if there is an online cpu in the package
+        * which collects uncore events already.
+        */
+       target = cpumask_any_and(&uncore_cpu_mask, topology_core_cpumask(cpu));
+       if (target < nr_cpu_ids)
+               return;
+
+       cpumask_set_cpu(cpu, &uncore_cpu_mask);
+
+       uncore_change_context(uncore_msr_uncores, -1, cpu);
+       uncore_change_context(uncore_pci_uncores, -1, cpu);
+}
+
+static int uncore_cpu_notifier(struct notifier_block *self,
+                              unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               return notifier_from_errno(uncore_cpu_prepare(cpu));
+
+       case CPU_STARTING:
+               uncore_cpu_starting(cpu, false);
+       case CPU_DOWN_FAILED:
+               uncore_event_init_cpu(cpu);
+               break;
+
+       case CPU_UP_CANCELED:
+       case CPU_DYING:
+               uncore_cpu_dying(cpu);
+               break;
+
+       case CPU_DOWN_PREPARE:
+               uncore_event_exit_cpu(cpu);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block uncore_cpu_nb = {
+       .notifier_call  = uncore_cpu_notifier,
+       /*
+        * to migrate uncore events, our notifier should be executed
+        * before perf core's notifier.
+        */
+       .priority       = CPU_PRI_PERF + 1,
+};
+
+static int __init type_pmu_register(struct intel_uncore_type *type)
+{
+       int i, ret;
+
+       for (i = 0; i < type->num_boxes; i++) {
+               ret = uncore_pmu_register(&type->pmus[i]);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static int __init uncore_msr_pmus_register(void)
+{
+       struct intel_uncore_type **types = uncore_msr_uncores;
+       int ret;
+
+       for (; *types; types++) {
+               ret = type_pmu_register(*types);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static int __init uncore_cpu_init(void)
+{
+       int ret;
+
+       switch (boot_cpu_data.x86_model) {
+       case 26: /* Nehalem */
+       case 30:
+       case 37: /* Westmere */
+       case 44:
+               nhm_uncore_cpu_init();
+               break;
+       case 42: /* Sandy Bridge */
+       case 58: /* Ivy Bridge */
+       case 60: /* Haswell */
+       case 69: /* Haswell */
+       case 70: /* Haswell */
+       case 61: /* Broadwell */
+       case 71: /* Broadwell */
+               snb_uncore_cpu_init();
+               break;
+       case 45: /* Sandy Bridge-EP */
+               snbep_uncore_cpu_init();
+               break;
+       case 46: /* Nehalem-EX */
+       case 47: /* Westmere-EX aka. Xeon E7 */
+               nhmex_uncore_cpu_init();
+               break;
+       case 62: /* Ivy Bridge-EP */
+               ivbep_uncore_cpu_init();
+               break;
+       case 63: /* Haswell-EP */
+               hswep_uncore_cpu_init();
+               break;
+       case 79: /* BDX-EP */
+       case 86: /* BDX-DE */
+               bdx_uncore_cpu_init();
+               break;
+       case 87: /* Knights Landing */
+               knl_uncore_cpu_init();
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       ret = uncore_types_init(uncore_msr_uncores, true);
+       if (ret)
+               goto err;
+
+       ret = uncore_msr_pmus_register();
+       if (ret)
+               goto err;
+       return 0;
+err:
+       uncore_types_exit(uncore_msr_uncores);
+       uncore_msr_uncores = empty_uncore;
+       return ret;
+}
+
+static void __init uncore_cpu_setup(void *dummy)
+{
+       uncore_cpu_starting(smp_processor_id(), true);
+}
+
+/* Lazy to avoid allocation of a few bytes for the normal case */
+static __initdata DECLARE_BITMAP(packages, MAX_LOCAL_APIC);
+
+static int __init uncore_cpumask_init(bool msr)
+{
+       unsigned int cpu;
+
+       for_each_online_cpu(cpu) {
+               unsigned int pkg = topology_logical_package_id(cpu);
+               int ret;
+
+               if (test_and_set_bit(pkg, packages))
+                       continue;
+               /*
+                * The first online cpu of each package allocates and takes
+                * the refcounts for all other online cpus in that package.
+                * If msrs are not enabled no allocation is required.
+                */
+               if (msr) {
+                       ret = uncore_cpu_prepare(cpu);
+                       if (ret)
+                               return ret;
+               }
+               uncore_event_init_cpu(cpu);
+               smp_call_function_single(cpu, uncore_cpu_setup, NULL, 1);
+       }
+       __register_cpu_notifier(&uncore_cpu_nb);
+       return 0;
+}
+
+static int __init intel_uncore_init(void)
+{
+       int pret, cret, ret;
+
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+               return -ENODEV;
+
+       if (cpu_has_hypervisor)
+               return -ENODEV;
+
+       max_packages = topology_max_packages();
+
+       pret = uncore_pci_init();
+       cret = uncore_cpu_init();
+
+       if (cret && pret)
+               return -ENODEV;
+
+       cpu_notifier_register_begin();
+       ret = uncore_cpumask_init(!cret);
+       if (ret)
+               goto err;
+       cpu_notifier_register_done();
+       return 0;
+
+err:
+       /* Undo box->init_box() */
+       on_each_cpu_mask(&uncore_cpu_mask, uncore_exit_boxes, NULL, 1);
+       uncore_types_exit(uncore_msr_uncores);
+       uncore_pci_exit();
+       cpu_notifier_register_done();
+       return ret;
+}
+device_initcall(intel_uncore_init);
diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
new file mode 100644 (file)
index 0000000..79766b9
--- /dev/null
@@ -0,0 +1,378 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <asm/apicdef.h>
+
+#include <linux/perf_event.h>
+#include "../perf_event.h"
+
+#define UNCORE_PMU_NAME_LEN            32
+#define UNCORE_PMU_HRTIMER_INTERVAL    (60LL * NSEC_PER_SEC)
+#define UNCORE_SNB_IMC_HRTIMER_INTERVAL (5ULL * NSEC_PER_SEC)
+
+#define UNCORE_FIXED_EVENT             0xff
+#define UNCORE_PMC_IDX_MAX_GENERIC     8
+#define UNCORE_PMC_IDX_FIXED           UNCORE_PMC_IDX_MAX_GENERIC
+#define UNCORE_PMC_IDX_MAX             (UNCORE_PMC_IDX_FIXED + 1)
+
+#define UNCORE_PCI_DEV_DATA(type, idx) ((type << 8) | idx)
+#define UNCORE_PCI_DEV_TYPE(data)      ((data >> 8) & 0xff)
+#define UNCORE_PCI_DEV_IDX(data)       (data & 0xff)
+#define UNCORE_EXTRA_PCI_DEV           0xff
+#define UNCORE_EXTRA_PCI_DEV_MAX       3
+
+#define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff)
+
+struct pci_extra_dev {
+       struct pci_dev *dev[UNCORE_EXTRA_PCI_DEV_MAX];
+};
+
+struct intel_uncore_ops;
+struct intel_uncore_pmu;
+struct intel_uncore_box;
+struct uncore_event_desc;
+
+struct intel_uncore_type {
+       const char *name;
+       int num_counters;
+       int num_boxes;
+       int perf_ctr_bits;
+       int fixed_ctr_bits;
+       unsigned perf_ctr;
+       unsigned event_ctl;
+       unsigned event_mask;
+       unsigned fixed_ctr;
+       unsigned fixed_ctl;
+       unsigned box_ctl;
+       unsigned msr_offset;
+       unsigned num_shared_regs:8;
+       unsigned single_fixed:1;
+       unsigned pair_ctr_ctl:1;
+       unsigned *msr_offsets;
+       struct event_constraint unconstrainted;
+       struct event_constraint *constraints;
+       struct intel_uncore_pmu *pmus;
+       struct intel_uncore_ops *ops;
+       struct uncore_event_desc *event_descs;
+       const struct attribute_group *attr_groups[4];
+       struct pmu *pmu; /* for custom pmu ops */
+};
+
+#define pmu_group attr_groups[0]
+#define format_group attr_groups[1]
+#define events_group attr_groups[2]
+
+struct intel_uncore_ops {
+       void (*init_box)(struct intel_uncore_box *);
+       void (*exit_box)(struct intel_uncore_box *);
+       void (*disable_box)(struct intel_uncore_box *);
+       void (*enable_box)(struct intel_uncore_box *);
+       void (*disable_event)(struct intel_uncore_box *, struct perf_event *);
+       void (*enable_event)(struct intel_uncore_box *, struct perf_event *);
+       u64 (*read_counter)(struct intel_uncore_box *, struct perf_event *);
+       int (*hw_config)(struct intel_uncore_box *, struct perf_event *);
+       struct event_constraint *(*get_constraint)(struct intel_uncore_box *,
+                                                  struct perf_event *);
+       void (*put_constraint)(struct intel_uncore_box *, struct perf_event *);
+};
+
+struct intel_uncore_pmu {
+       struct pmu                      pmu;
+       char                            name[UNCORE_PMU_NAME_LEN];
+       int                             pmu_idx;
+       int                             func_id;
+       bool                            registered;
+       atomic_t                        activeboxes;
+       struct intel_uncore_type        *type;
+       struct intel_uncore_box         **boxes;
+};
+
+struct intel_uncore_extra_reg {
+       raw_spinlock_t lock;
+       u64 config, config1, config2;
+       atomic_t ref;
+};
+
+struct intel_uncore_box {
+       int pci_phys_id;
+       int pkgid;
+       int n_active;   /* number of active events */
+       int n_events;
+       int cpu;        /* cpu to collect events */
+       unsigned long flags;
+       atomic_t refcnt;
+       struct perf_event *events[UNCORE_PMC_IDX_MAX];
+       struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
+       struct event_constraint *event_constraint[UNCORE_PMC_IDX_MAX];
+       unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
+       u64 tags[UNCORE_PMC_IDX_MAX];
+       struct pci_dev *pci_dev;
+       struct intel_uncore_pmu *pmu;
+       u64 hrtimer_duration; /* hrtimer timeout for this box */
+       struct hrtimer hrtimer;
+       struct list_head list;
+       struct list_head active_list;
+       void *io_addr;
+       struct intel_uncore_extra_reg shared_regs[0];
+};
+
+#define UNCORE_BOX_FLAG_INITIATED      0
+
+struct uncore_event_desc {
+       struct kobj_attribute attr;
+       const char *config;
+};
+
+struct pci2phy_map {
+       struct list_head list;
+       int segment;
+       int pbus_to_physid[256];
+};
+
+struct pci2phy_map *__find_pci2phy_map(int segment);
+
+ssize_t uncore_event_show(struct kobject *kobj,
+                         struct kobj_attribute *attr, char *buf);
+
+#define INTEL_UNCORE_EVENT_DESC(_name, _config)                        \
+{                                                              \
+       .attr   = __ATTR(_name, 0444, uncore_event_show, NULL), \
+       .config = _config,                                      \
+}
+
+#define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format)                        \
+static ssize_t __uncore_##_var##_show(struct kobject *kobj,            \
+                               struct kobj_attribute *attr,            \
+                               char *page)                             \
+{                                                                      \
+       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);                     \
+       return sprintf(page, _format "\n");                             \
+}                                                                      \
+static struct kobj_attribute format_attr_##_var =                      \
+       __ATTR(_name, 0444, __uncore_##_var##_show, NULL)
+
+static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box)
+{
+       return box->pmu->type->box_ctl;
+}
+
+static inline unsigned uncore_pci_fixed_ctl(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctl;
+}
+
+static inline unsigned uncore_pci_fixed_ctr(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr;
+}
+
+static inline
+unsigned uncore_pci_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       return idx * 4 + box->pmu->type->event_ctl;
+}
+
+static inline
+unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       return idx * 8 + box->pmu->type->perf_ctr;
+}
+
+static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box)
+{
+       struct intel_uncore_pmu *pmu = box->pmu;
+       return pmu->type->msr_offsets ?
+               pmu->type->msr_offsets[pmu->pmu_idx] :
+               pmu->type->msr_offset * pmu->pmu_idx;
+}
+
+static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)
+{
+       if (!box->pmu->type->box_ctl)
+               return 0;
+       return box->pmu->type->box_ctl + uncore_msr_box_offset(box);
+}
+
+static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box)
+{
+       if (!box->pmu->type->fixed_ctl)
+               return 0;
+       return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box);
+}
+
+static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box);
+}
+
+static inline
+unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       return box->pmu->type->event_ctl +
+               (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
+               uncore_msr_box_offset(box);
+}
+
+static inline
+unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       return box->pmu->type->perf_ctr +
+               (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
+               uncore_msr_box_offset(box);
+}
+
+static inline
+unsigned uncore_fixed_ctl(struct intel_uncore_box *box)
+{
+       if (box->pci_dev)
+               return uncore_pci_fixed_ctl(box);
+       else
+               return uncore_msr_fixed_ctl(box);
+}
+
+static inline
+unsigned uncore_fixed_ctr(struct intel_uncore_box *box)
+{
+       if (box->pci_dev)
+               return uncore_pci_fixed_ctr(box);
+       else
+               return uncore_msr_fixed_ctr(box);
+}
+
+static inline
+unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       if (box->pci_dev)
+               return uncore_pci_event_ctl(box, idx);
+       else
+               return uncore_msr_event_ctl(box, idx);
+}
+
+static inline
+unsigned uncore_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       if (box->pci_dev)
+               return uncore_pci_perf_ctr(box, idx);
+       else
+               return uncore_msr_perf_ctr(box, idx);
+}
+
+static inline int uncore_perf_ctr_bits(struct intel_uncore_box *box)
+{
+       return box->pmu->type->perf_ctr_bits;
+}
+
+static inline int uncore_fixed_ctr_bits(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr_bits;
+}
+
+static inline int uncore_num_counters(struct intel_uncore_box *box)
+{
+       return box->pmu->type->num_counters;
+}
+
+static inline void uncore_disable_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->type->ops->disable_box)
+               box->pmu->type->ops->disable_box(box);
+}
+
+static inline void uncore_enable_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->type->ops->enable_box)
+               box->pmu->type->ops->enable_box(box);
+}
+
+static inline void uncore_disable_event(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       box->pmu->type->ops->disable_event(box, event);
+}
+
+static inline void uncore_enable_event(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       box->pmu->type->ops->enable_event(box, event);
+}
+
+static inline u64 uncore_read_counter(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       return box->pmu->type->ops->read_counter(box, event);
+}
+
+static inline void uncore_box_init(struct intel_uncore_box *box)
+{
+       if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) {
+               if (box->pmu->type->ops->init_box)
+                       box->pmu->type->ops->init_box(box);
+       }
+}
+
+static inline void uncore_box_exit(struct intel_uncore_box *box)
+{
+       if (test_and_clear_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) {
+               if (box->pmu->type->ops->exit_box)
+                       box->pmu->type->ops->exit_box(box);
+       }
+}
+
+static inline bool uncore_box_is_fake(struct intel_uncore_box *box)
+{
+       return (box->pkgid < 0);
+}
+
+static inline struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
+{
+       return container_of(event->pmu, struct intel_uncore_pmu, pmu);
+}
+
+static inline struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
+{
+       return event->pmu_private;
+}
+
+struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu);
+u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event);
+void uncore_pmu_start_hrtimer(struct intel_uncore_box *box);
+void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box);
+void uncore_pmu_event_read(struct perf_event *event);
+void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event);
+struct event_constraint *
+uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event);
+void uncore_put_constraint(struct intel_uncore_box *box, struct perf_event *event);
+u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx);
+
+extern struct intel_uncore_type **uncore_msr_uncores;
+extern struct intel_uncore_type **uncore_pci_uncores;
+extern struct pci_driver *uncore_pci_driver;
+extern raw_spinlock_t pci2phy_map_lock;
+extern struct list_head pci2phy_map_head;
+extern struct pci_extra_dev *uncore_extra_pci_dev;
+extern struct event_constraint uncore_constraint_empty;
+
+/* perf_event_intel_uncore_snb.c */
+int snb_uncore_pci_init(void);
+int ivb_uncore_pci_init(void);
+int hsw_uncore_pci_init(void);
+int bdw_uncore_pci_init(void);
+int skl_uncore_pci_init(void);
+void snb_uncore_cpu_init(void);
+void nhm_uncore_cpu_init(void);
+int snb_pci2phy_map_init(int devid);
+
+/* perf_event_intel_uncore_snbep.c */
+int snbep_uncore_pci_init(void);
+void snbep_uncore_cpu_init(void);
+int ivbep_uncore_pci_init(void);
+void ivbep_uncore_cpu_init(void);
+int hswep_uncore_pci_init(void);
+void hswep_uncore_cpu_init(void);
+int bdx_uncore_pci_init(void);
+void bdx_uncore_cpu_init(void);
+int knl_uncore_pci_init(void);
+void knl_uncore_cpu_init(void);
+
+/* perf_event_intel_uncore_nhmex.c */
+void nhmex_uncore_cpu_init(void);
diff --git a/arch/x86/events/intel/uncore_nhmex.c b/arch/x86/events/intel/uncore_nhmex.c
new file mode 100644 (file)
index 0000000..cda5693
--- /dev/null
@@ -0,0 +1,1227 @@
+/* Nehalem-EX/Westmere-EX uncore support */
+#include "uncore.h"
+
+/* NHM-EX event control */
+#define NHMEX_PMON_CTL_EV_SEL_MASK     0x000000ff
+#define NHMEX_PMON_CTL_UMASK_MASK      0x0000ff00
+#define NHMEX_PMON_CTL_EN_BIT0         (1 << 0)
+#define NHMEX_PMON_CTL_EDGE_DET                (1 << 18)
+#define NHMEX_PMON_CTL_PMI_EN          (1 << 20)
+#define NHMEX_PMON_CTL_EN_BIT22                (1 << 22)
+#define NHMEX_PMON_CTL_INVERT          (1 << 23)
+#define NHMEX_PMON_CTL_TRESH_MASK      0xff000000
+#define NHMEX_PMON_RAW_EVENT_MASK      (NHMEX_PMON_CTL_EV_SEL_MASK | \
+                                        NHMEX_PMON_CTL_UMASK_MASK | \
+                                        NHMEX_PMON_CTL_EDGE_DET | \
+                                        NHMEX_PMON_CTL_INVERT | \
+                                        NHMEX_PMON_CTL_TRESH_MASK)
+
+/* NHM-EX Ubox */
+#define NHMEX_U_MSR_PMON_GLOBAL_CTL            0xc00
+#define NHMEX_U_MSR_PMON_CTR                   0xc11
+#define NHMEX_U_MSR_PMON_EV_SEL                        0xc10
+
+#define NHMEX_U_PMON_GLOBAL_EN                 (1 << 0)
+#define NHMEX_U_PMON_GLOBAL_PMI_CORE_SEL       0x0000001e
+#define NHMEX_U_PMON_GLOBAL_EN_ALL             (1 << 28)
+#define NHMEX_U_PMON_GLOBAL_RST_ALL            (1 << 29)
+#define NHMEX_U_PMON_GLOBAL_FRZ_ALL            (1 << 31)
+
+#define NHMEX_U_PMON_RAW_EVENT_MASK            \
+               (NHMEX_PMON_CTL_EV_SEL_MASK |   \
+                NHMEX_PMON_CTL_EDGE_DET)
+
+/* NHM-EX Cbox */
+#define NHMEX_C0_MSR_PMON_GLOBAL_CTL           0xd00
+#define NHMEX_C0_MSR_PMON_CTR0                 0xd11
+#define NHMEX_C0_MSR_PMON_EV_SEL0              0xd10
+#define NHMEX_C_MSR_OFFSET                     0x20
+
+/* NHM-EX Bbox */
+#define NHMEX_B0_MSR_PMON_GLOBAL_CTL           0xc20
+#define NHMEX_B0_MSR_PMON_CTR0                 0xc31
+#define NHMEX_B0_MSR_PMON_CTL0                 0xc30
+#define NHMEX_B_MSR_OFFSET                     0x40
+#define NHMEX_B0_MSR_MATCH                     0xe45
+#define NHMEX_B0_MSR_MASK                      0xe46
+#define NHMEX_B1_MSR_MATCH                     0xe4d
+#define NHMEX_B1_MSR_MASK                      0xe4e
+
+#define NHMEX_B_PMON_CTL_EN                    (1 << 0)
+#define NHMEX_B_PMON_CTL_EV_SEL_SHIFT          1
+#define NHMEX_B_PMON_CTL_EV_SEL_MASK           \
+               (0x1f << NHMEX_B_PMON_CTL_EV_SEL_SHIFT)
+#define NHMEX_B_PMON_CTR_SHIFT         6
+#define NHMEX_B_PMON_CTR_MASK          \
+               (0x3 << NHMEX_B_PMON_CTR_SHIFT)
+#define NHMEX_B_PMON_RAW_EVENT_MASK            \
+               (NHMEX_B_PMON_CTL_EV_SEL_MASK | \
+                NHMEX_B_PMON_CTR_MASK)
+
+/* NHM-EX Sbox */
+#define NHMEX_S0_MSR_PMON_GLOBAL_CTL           0xc40
+#define NHMEX_S0_MSR_PMON_CTR0                 0xc51
+#define NHMEX_S0_MSR_PMON_CTL0                 0xc50
+#define NHMEX_S_MSR_OFFSET                     0x80
+#define NHMEX_S0_MSR_MM_CFG                    0xe48
+#define NHMEX_S0_MSR_MATCH                     0xe49
+#define NHMEX_S0_MSR_MASK                      0xe4a
+#define NHMEX_S1_MSR_MM_CFG                    0xe58
+#define NHMEX_S1_MSR_MATCH                     0xe59
+#define NHMEX_S1_MSR_MASK                      0xe5a
+
+#define NHMEX_S_PMON_MM_CFG_EN                 (0x1ULL << 63)
+#define NHMEX_S_EVENT_TO_R_PROG_EV             0
+
+/* NHM-EX Mbox */
+#define NHMEX_M0_MSR_GLOBAL_CTL                        0xca0
+#define NHMEX_M0_MSR_PMU_DSP                   0xca5
+#define NHMEX_M0_MSR_PMU_ISS                   0xca6
+#define NHMEX_M0_MSR_PMU_MAP                   0xca7
+#define NHMEX_M0_MSR_PMU_MSC_THR               0xca8
+#define NHMEX_M0_MSR_PMU_PGT                   0xca9
+#define NHMEX_M0_MSR_PMU_PLD                   0xcaa
+#define NHMEX_M0_MSR_PMU_ZDP_CTL_FVC           0xcab
+#define NHMEX_M0_MSR_PMU_CTL0                  0xcb0
+#define NHMEX_M0_MSR_PMU_CNT0                  0xcb1
+#define NHMEX_M_MSR_OFFSET                     0x40
+#define NHMEX_M0_MSR_PMU_MM_CFG                        0xe54
+#define NHMEX_M1_MSR_PMU_MM_CFG                        0xe5c
+
+#define NHMEX_M_PMON_MM_CFG_EN                 (1ULL << 63)
+#define NHMEX_M_PMON_ADDR_MATCH_MASK           0x3ffffffffULL
+#define NHMEX_M_PMON_ADDR_MASK_MASK            0x7ffffffULL
+#define NHMEX_M_PMON_ADDR_MASK_SHIFT           34
+
+#define NHMEX_M_PMON_CTL_EN                    (1 << 0)
+#define NHMEX_M_PMON_CTL_PMI_EN                        (1 << 1)
+#define NHMEX_M_PMON_CTL_COUNT_MODE_SHIFT      2
+#define NHMEX_M_PMON_CTL_COUNT_MODE_MASK       \
+       (0x3 << NHMEX_M_PMON_CTL_COUNT_MODE_SHIFT)
+#define NHMEX_M_PMON_CTL_STORAGE_MODE_SHIFT    4
+#define NHMEX_M_PMON_CTL_STORAGE_MODE_MASK     \
+       (0x3 << NHMEX_M_PMON_CTL_STORAGE_MODE_SHIFT)
+#define NHMEX_M_PMON_CTL_WRAP_MODE             (1 << 6)
+#define NHMEX_M_PMON_CTL_FLAG_MODE             (1 << 7)
+#define NHMEX_M_PMON_CTL_INC_SEL_SHIFT         9
+#define NHMEX_M_PMON_CTL_INC_SEL_MASK          \
+       (0x1f << NHMEX_M_PMON_CTL_INC_SEL_SHIFT)
+#define NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT    19
+#define NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK     \
+       (0x7 << NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT)
+#define NHMEX_M_PMON_RAW_EVENT_MASK                    \
+               (NHMEX_M_PMON_CTL_COUNT_MODE_MASK |     \
+                NHMEX_M_PMON_CTL_STORAGE_MODE_MASK |   \
+                NHMEX_M_PMON_CTL_WRAP_MODE |           \
+                NHMEX_M_PMON_CTL_FLAG_MODE |           \
+                NHMEX_M_PMON_CTL_INC_SEL_MASK |        \
+                NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK)
+
+#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK          (((1 << 11) - 1) | (1 << 23))
+#define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7ULL << (11 + 3 * (n)))
+
+#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK          (((1 << 12) - 1) | (1 << 24))
+#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7ULL << (12 + 3 * (n)))
+
+/*
+ * use the 9~13 bits to select event If the 7th bit is not set,
+ * otherwise use the 19~21 bits to select event.
+ */
+#define MBOX_INC_SEL(x) ((x) << NHMEX_M_PMON_CTL_INC_SEL_SHIFT)
+#define MBOX_SET_FLAG_SEL(x) (((x) << NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT) | \
+                               NHMEX_M_PMON_CTL_FLAG_MODE)
+#define MBOX_INC_SEL_MASK (NHMEX_M_PMON_CTL_INC_SEL_MASK | \
+                          NHMEX_M_PMON_CTL_FLAG_MODE)
+#define MBOX_SET_FLAG_SEL_MASK (NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK | \
+                               NHMEX_M_PMON_CTL_FLAG_MODE)
+#define MBOX_INC_SEL_EXTAR_REG(c, r) \
+               EVENT_EXTRA_REG(MBOX_INC_SEL(c), NHMEX_M0_MSR_PMU_##r, \
+                               MBOX_INC_SEL_MASK, (u64)-1, NHMEX_M_##r)
+#define MBOX_SET_FLAG_SEL_EXTRA_REG(c, r) \
+               EVENT_EXTRA_REG(MBOX_SET_FLAG_SEL(c), NHMEX_M0_MSR_PMU_##r, \
+                               MBOX_SET_FLAG_SEL_MASK, \
+                               (u64)-1, NHMEX_M_##r)
+
+/* NHM-EX Rbox */
+#define NHMEX_R_MSR_GLOBAL_CTL                 0xe00
+#define NHMEX_R_MSR_PMON_CTL0                  0xe10
+#define NHMEX_R_MSR_PMON_CNT0                  0xe11
+#define NHMEX_R_MSR_OFFSET                     0x20
+
+#define NHMEX_R_MSR_PORTN_QLX_CFG(n)           \
+               ((n) < 4 ? (0xe0c + (n)) : (0xe2c + (n) - 4))
+#define NHMEX_R_MSR_PORTN_IPERF_CFG0(n)                (0xe04 + (n))
+#define NHMEX_R_MSR_PORTN_IPERF_CFG1(n)                (0xe24 + (n))
+#define NHMEX_R_MSR_PORTN_XBR_OFFSET(n)                \
+               (((n) < 4 ? 0 : 0x10) + (n) * 4)
+#define NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n)   \
+               (0xe60 + NHMEX_R_MSR_PORTN_XBR_OFFSET(n))
+#define NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(n)    \
+               (NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) + 1)
+#define NHMEX_R_MSR_PORTN_XBR_SET1_MASK(n)     \
+               (NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) + 2)
+#define NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n)   \
+               (0xe70 + NHMEX_R_MSR_PORTN_XBR_OFFSET(n))
+#define NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(n)    \
+               (NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) + 1)
+#define NHMEX_R_MSR_PORTN_XBR_SET2_MASK(n)     \
+               (NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) + 2)
+
+#define NHMEX_R_PMON_CTL_EN                    (1 << 0)
+#define NHMEX_R_PMON_CTL_EV_SEL_SHIFT          1
+#define NHMEX_R_PMON_CTL_EV_SEL_MASK           \
+               (0x1f << NHMEX_R_PMON_CTL_EV_SEL_SHIFT)
+#define NHMEX_R_PMON_CTL_PMI_EN                        (1 << 6)
+#define NHMEX_R_PMON_RAW_EVENT_MASK            NHMEX_R_PMON_CTL_EV_SEL_MASK
+
+/* NHM-EX Wbox */
+#define NHMEX_W_MSR_GLOBAL_CTL                 0xc80
+#define NHMEX_W_MSR_PMON_CNT0                  0xc90
+#define NHMEX_W_MSR_PMON_EVT_SEL0              0xc91
+#define NHMEX_W_MSR_PMON_FIXED_CTR             0x394
+#define NHMEX_W_MSR_PMON_FIXED_CTL             0x395
+
+#define NHMEX_W_PMON_GLOBAL_FIXED_EN           (1ULL << 31)
+
+#define __BITS_VALUE(x, i, n)  ((typeof(x))(((x) >> ((i) * (n))) & \
+                               ((1ULL << (n)) - 1)))
+
+DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
+DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5");
+DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
+DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
+DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
+DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
+DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7");
+DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63");
+DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63");
+
+static void nhmex_uncore_msr_init_box(struct intel_uncore_box *box)
+{
+       wrmsrl(NHMEX_U_MSR_PMON_GLOBAL_CTL, NHMEX_U_PMON_GLOBAL_EN_ALL);
+}
+
+static void nhmex_uncore_msr_exit_box(struct intel_uncore_box *box)
+{
+       wrmsrl(NHMEX_U_MSR_PMON_GLOBAL_CTL, 0);
+}
+
+static void nhmex_uncore_msr_disable_box(struct intel_uncore_box *box)
+{
+       unsigned msr = uncore_msr_box_ctl(box);
+       u64 config;
+
+       if (msr) {
+               rdmsrl(msr, config);
+               config &= ~((1ULL << uncore_num_counters(box)) - 1);
+               /* WBox has a fixed counter */
+               if (uncore_msr_fixed_ctl(box))
+                       config &= ~NHMEX_W_PMON_GLOBAL_FIXED_EN;
+               wrmsrl(msr, config);
+       }
+}
+
+static void nhmex_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+       unsigned msr = uncore_msr_box_ctl(box);
+       u64 config;
+
+       if (msr) {
+               rdmsrl(msr, config);
+               config |= (1ULL << uncore_num_counters(box)) - 1;
+               /* WBox has a fixed counter */
+               if (uncore_msr_fixed_ctl(box))
+                       config |= NHMEX_W_PMON_GLOBAL_FIXED_EN;
+               wrmsrl(msr, config);
+       }
+}
+
+static void nhmex_uncore_msr_disable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       wrmsrl(event->hw.config_base, 0);
+}
+
+static void nhmex_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->idx >= UNCORE_PMC_IDX_FIXED)
+               wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0);
+       else if (box->pmu->type->event_mask & NHMEX_PMON_CTL_EN_BIT0)
+               wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
+       else
+               wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);
+}
+
+#define NHMEX_UNCORE_OPS_COMMON_INIT()                         \
+       .init_box       = nhmex_uncore_msr_init_box,            \
+       .exit_box       = nhmex_uncore_msr_exit_box,            \
+       .disable_box    = nhmex_uncore_msr_disable_box,         \
+       .enable_box     = nhmex_uncore_msr_enable_box,          \
+       .disable_event  = nhmex_uncore_msr_disable_event,       \
+       .read_counter   = uncore_msr_read_counter
+
+static struct intel_uncore_ops nhmex_uncore_ops = {
+       NHMEX_UNCORE_OPS_COMMON_INIT(),
+       .enable_event   = nhmex_uncore_msr_enable_event,
+};
+
+static struct attribute *nhmex_uncore_ubox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_edge.attr,
+       NULL,
+};
+
+static struct attribute_group nhmex_uncore_ubox_format_group = {
+       .name           = "format",
+       .attrs          = nhmex_uncore_ubox_formats_attr,
+};
+
+static struct intel_uncore_type nhmex_uncore_ubox = {
+       .name           = "ubox",
+       .num_counters   = 1,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       .event_ctl      = NHMEX_U_MSR_PMON_EV_SEL,
+       .perf_ctr       = NHMEX_U_MSR_PMON_CTR,
+       .event_mask     = NHMEX_U_PMON_RAW_EVENT_MASK,
+       .box_ctl        = NHMEX_U_MSR_PMON_GLOBAL_CTL,
+       .ops            = &nhmex_uncore_ops,
+       .format_group   = &nhmex_uncore_ubox_format_group
+};
+
+static struct attribute *nhmex_uncore_cbox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       NULL,
+};
+
+static struct attribute_group nhmex_uncore_cbox_format_group = {
+       .name = "format",
+       .attrs = nhmex_uncore_cbox_formats_attr,
+};
+
+/* msr offset for each instance of cbox */
+static unsigned nhmex_cbox_msr_offsets[] = {
+       0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0,
+};
+
+static struct intel_uncore_type nhmex_uncore_cbox = {
+       .name                   = "cbox",
+       .num_counters           = 6,
+       .num_boxes              = 10,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = NHMEX_C0_MSR_PMON_EV_SEL0,
+       .perf_ctr               = NHMEX_C0_MSR_PMON_CTR0,
+       .event_mask             = NHMEX_PMON_RAW_EVENT_MASK,
+       .box_ctl                = NHMEX_C0_MSR_PMON_GLOBAL_CTL,
+       .msr_offsets            = nhmex_cbox_msr_offsets,
+       .pair_ctr_ctl           = 1,
+       .ops                    = &nhmex_uncore_ops,
+       .format_group           = &nhmex_uncore_cbox_format_group
+};
+
+static struct uncore_event_desc nhmex_uncore_wbox_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0"),
+       { /* end: all zeroes */ },
+};
+
+static struct intel_uncore_type nhmex_uncore_wbox = {
+       .name                   = "wbox",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = NHMEX_W_MSR_PMON_CNT0,
+       .perf_ctr               = NHMEX_W_MSR_PMON_EVT_SEL0,
+       .fixed_ctr              = NHMEX_W_MSR_PMON_FIXED_CTR,
+       .fixed_ctl              = NHMEX_W_MSR_PMON_FIXED_CTL,
+       .event_mask             = NHMEX_PMON_RAW_EVENT_MASK,
+       .box_ctl                = NHMEX_W_MSR_GLOBAL_CTL,
+       .pair_ctr_ctl           = 1,
+       .event_descs            = nhmex_uncore_wbox_events,
+       .ops                    = &nhmex_uncore_ops,
+       .format_group           = &nhmex_uncore_cbox_format_group
+};
+
+static int nhmex_bbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+       int ctr, ev_sel;
+
+       ctr = (hwc->config & NHMEX_B_PMON_CTR_MASK) >>
+               NHMEX_B_PMON_CTR_SHIFT;
+       ev_sel = (hwc->config & NHMEX_B_PMON_CTL_EV_SEL_MASK) >>
+                 NHMEX_B_PMON_CTL_EV_SEL_SHIFT;
+
+       /* events that do not use the match/mask registers */
+       if ((ctr == 0 && ev_sel > 0x3) || (ctr == 1 && ev_sel > 0x6) ||
+           (ctr == 2 && ev_sel != 0x4) || ctr == 3)
+               return 0;
+
+       if (box->pmu->pmu_idx == 0)
+               reg1->reg = NHMEX_B0_MSR_MATCH;
+       else
+               reg1->reg = NHMEX_B1_MSR_MATCH;
+       reg1->idx = 0;
+       reg1->config = event->attr.config1;
+       reg2->config = event->attr.config2;
+       return 0;
+}
+
+static void nhmex_bbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+
+       if (reg1->idx != EXTRA_REG_NONE) {
+               wrmsrl(reg1->reg, reg1->config);
+               wrmsrl(reg1->reg + 1, reg2->config);
+       }
+       wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0 |
+               (hwc->config & NHMEX_B_PMON_CTL_EV_SEL_MASK));
+}
+
+/*
+ * The Bbox has 4 counters, but each counter monitors different events.
+ * Use bits 6-7 in the event config to select counter.
+ */
+static struct event_constraint nhmex_uncore_bbox_constraints[] = {
+       EVENT_CONSTRAINT(0 , 1, 0xc0),
+       EVENT_CONSTRAINT(0x40, 2, 0xc0),
+       EVENT_CONSTRAINT(0x80, 4, 0xc0),
+       EVENT_CONSTRAINT(0xc0, 8, 0xc0),
+       EVENT_CONSTRAINT_END,
+};
+
+static struct attribute *nhmex_uncore_bbox_formats_attr[] = {
+       &format_attr_event5.attr,
+       &format_attr_counter.attr,
+       &format_attr_match.attr,
+       &format_attr_mask.attr,
+       NULL,
+};
+
+static struct attribute_group nhmex_uncore_bbox_format_group = {
+       .name = "format",
+       .attrs = nhmex_uncore_bbox_formats_attr,
+};
+
+static struct intel_uncore_ops nhmex_uncore_bbox_ops = {
+       NHMEX_UNCORE_OPS_COMMON_INIT(),
+       .enable_event           = nhmex_bbox_msr_enable_event,
+       .hw_config              = nhmex_bbox_hw_config,
+       .get_constraint         = uncore_get_constraint,
+       .put_constraint         = uncore_put_constraint,
+};
+
+static struct intel_uncore_type nhmex_uncore_bbox = {
+       .name                   = "bbox",
+       .num_counters           = 4,
+       .num_boxes              = 2,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = NHMEX_B0_MSR_PMON_CTL0,
+       .perf_ctr               = NHMEX_B0_MSR_PMON_CTR0,
+       .event_mask             = NHMEX_B_PMON_RAW_EVENT_MASK,
+       .box_ctl                = NHMEX_B0_MSR_PMON_GLOBAL_CTL,
+       .msr_offset             = NHMEX_B_MSR_OFFSET,
+       .pair_ctr_ctl           = 1,
+       .num_shared_regs        = 1,
+       .constraints            = nhmex_uncore_bbox_constraints,
+       .ops                    = &nhmex_uncore_bbox_ops,
+       .format_group           = &nhmex_uncore_bbox_format_group
+};
+
+static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+
+       /* only TO_R_PROG_EV event uses the match/mask register */
+       if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) !=
+           NHMEX_S_EVENT_TO_R_PROG_EV)
+               return 0;
+
+       if (box->pmu->pmu_idx == 0)
+               reg1->reg = NHMEX_S0_MSR_MM_CFG;
+       else
+               reg1->reg = NHMEX_S1_MSR_MM_CFG;
+       reg1->idx = 0;
+       reg1->config = event->attr.config1;
+       reg2->config = event->attr.config2;
+       return 0;
+}
+
+static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+
+       if (reg1->idx != EXTRA_REG_NONE) {
+               wrmsrl(reg1->reg, 0);
+               wrmsrl(reg1->reg + 1, reg1->config);
+               wrmsrl(reg1->reg + 2, reg2->config);
+               wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN);
+       }
+       wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
+}
+
+static struct attribute *nhmex_uncore_sbox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_match.attr,
+       &format_attr_mask.attr,
+       NULL,
+};
+
+static struct attribute_group nhmex_uncore_sbox_format_group = {
+       .name                   = "format",
+       .attrs                  = nhmex_uncore_sbox_formats_attr,
+};
+
+static struct intel_uncore_ops nhmex_uncore_sbox_ops = {
+       NHMEX_UNCORE_OPS_COMMON_INIT(),
+       .enable_event           = nhmex_sbox_msr_enable_event,
+       .hw_config              = nhmex_sbox_hw_config,
+       .get_constraint         = uncore_get_constraint,
+       .put_constraint         = uncore_put_constraint,
+};
+
+static struct intel_uncore_type nhmex_uncore_sbox = {
+       .name                   = "sbox",
+       .num_counters           = 4,
+       .num_boxes              = 2,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = NHMEX_S0_MSR_PMON_CTL0,
+       .perf_ctr               = NHMEX_S0_MSR_PMON_CTR0,
+       .event_mask             = NHMEX_PMON_RAW_EVENT_MASK,
+       .box_ctl                = NHMEX_S0_MSR_PMON_GLOBAL_CTL,
+       .msr_offset             = NHMEX_S_MSR_OFFSET,
+       .pair_ctr_ctl           = 1,
+       .num_shared_regs        = 1,
+       .ops                    = &nhmex_uncore_sbox_ops,
+       .format_group           = &nhmex_uncore_sbox_format_group
+};
+
+enum {
+       EXTRA_REG_NHMEX_M_FILTER,
+       EXTRA_REG_NHMEX_M_DSP,
+       EXTRA_REG_NHMEX_M_ISS,
+       EXTRA_REG_NHMEX_M_MAP,
+       EXTRA_REG_NHMEX_M_MSC_THR,
+       EXTRA_REG_NHMEX_M_PGT,
+       EXTRA_REG_NHMEX_M_PLD,
+       EXTRA_REG_NHMEX_M_ZDP_CTL_FVC,
+};
+
+static struct extra_reg nhmex_uncore_mbox_extra_regs[] = {
+       MBOX_INC_SEL_EXTAR_REG(0x0, DSP),
+       MBOX_INC_SEL_EXTAR_REG(0x4, MSC_THR),
+       MBOX_INC_SEL_EXTAR_REG(0x5, MSC_THR),
+       MBOX_INC_SEL_EXTAR_REG(0x9, ISS),
+       /* event 0xa uses two extra registers */
+       MBOX_INC_SEL_EXTAR_REG(0xa, ISS),
+       MBOX_INC_SEL_EXTAR_REG(0xa, PLD),
+       MBOX_INC_SEL_EXTAR_REG(0xb, PLD),
+       /* events 0xd ~ 0x10 use the same extra register */
+       MBOX_INC_SEL_EXTAR_REG(0xd, ZDP_CTL_FVC),
+       MBOX_INC_SEL_EXTAR_REG(0xe, ZDP_CTL_FVC),
+       MBOX_INC_SEL_EXTAR_REG(0xf, ZDP_CTL_FVC),
+       MBOX_INC_SEL_EXTAR_REG(0x10, ZDP_CTL_FVC),
+       MBOX_INC_SEL_EXTAR_REG(0x16, PGT),
+       MBOX_SET_FLAG_SEL_EXTRA_REG(0x0, DSP),
+       MBOX_SET_FLAG_SEL_EXTRA_REG(0x1, ISS),
+       MBOX_SET_FLAG_SEL_EXTRA_REG(0x5, PGT),
+       MBOX_SET_FLAG_SEL_EXTRA_REG(0x6, MAP),
+       EVENT_EXTRA_END
+};
+
+/* Nehalem-EX or Westmere-EX ? */
+static bool uncore_nhmex;
+
+static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config)
+{
+       struct intel_uncore_extra_reg *er;
+       unsigned long flags;
+       bool ret = false;
+       u64 mask;
+
+       if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
+               er = &box->shared_regs[idx];
+               raw_spin_lock_irqsave(&er->lock, flags);
+               if (!atomic_read(&er->ref) || er->config == config) {
+                       atomic_inc(&er->ref);
+                       er->config = config;
+                       ret = true;
+               }
+               raw_spin_unlock_irqrestore(&er->lock, flags);
+
+               return ret;
+       }
+       /*
+        * The ZDP_CTL_FVC MSR has 4 fields which are used to control
+        * events 0xd ~ 0x10. Besides these 4 fields, there are additional
+        * fields which are shared.
+        */
+       idx -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
+       if (WARN_ON_ONCE(idx >= 4))
+               return false;
+
+       /* mask of the shared fields */
+       if (uncore_nhmex)
+               mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK;
+       else
+               mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK;
+       er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
+
+       raw_spin_lock_irqsave(&er->lock, flags);
+       /* add mask of the non-shared field if it's in use */
+       if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) {
+               if (uncore_nhmex)
+                       mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
+               else
+                       mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
+       }
+
+       if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) {
+               atomic_add(1 << (idx * 8), &er->ref);
+               if (uncore_nhmex)
+                       mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK |
+                               NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
+               else
+                       mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK |
+                               WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
+               er->config &= ~mask;
+               er->config |= (config & mask);
+               ret = true;
+       }
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+
+       return ret;
+}
+
+static void nhmex_mbox_put_shared_reg(struct intel_uncore_box *box, int idx)
+{
+       struct intel_uncore_extra_reg *er;
+
+       if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
+               er = &box->shared_regs[idx];
+               atomic_dec(&er->ref);
+               return;
+       }
+
+       idx -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
+       er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
+       atomic_sub(1 << (idx * 8), &er->ref);
+}
+
+static u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       u64 idx, orig_idx = __BITS_VALUE(reg1->idx, 0, 8);
+       u64 config = reg1->config;
+
+       /* get the non-shared control bits and shift them */
+       idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
+       if (uncore_nhmex)
+               config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
+       else
+               config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
+       if (new_idx > orig_idx) {
+               idx = new_idx - orig_idx;
+               config <<= 3 * idx;
+       } else {
+               idx = orig_idx - new_idx;
+               config >>= 3 * idx;
+       }
+
+       /* add the shared control bits back */
+       if (uncore_nhmex)
+               config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
+       else
+               config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
+       config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
+       if (modify) {
+               /* adjust the main event selector */
+               if (new_idx > orig_idx)
+                       hwc->config += idx << NHMEX_M_PMON_CTL_INC_SEL_SHIFT;
+               else
+                       hwc->config -= idx << NHMEX_M_PMON_CTL_INC_SEL_SHIFT;
+               reg1->config = config;
+               reg1->idx = ~0xff | new_idx;
+       }
+       return config;
+}
+
+static struct event_constraint *
+nhmex_mbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
+       int i, idx[2], alloc = 0;
+       u64 config1 = reg1->config;
+
+       idx[0] = __BITS_VALUE(reg1->idx, 0, 8);
+       idx[1] = __BITS_VALUE(reg1->idx, 1, 8);
+again:
+       for (i = 0; i < 2; i++) {
+               if (!uncore_box_is_fake(box) && (reg1->alloc & (0x1 << i)))
+                       idx[i] = 0xff;
+
+               if (idx[i] == 0xff)
+                       continue;
+
+               if (!nhmex_mbox_get_shared_reg(box, idx[i],
+                               __BITS_VALUE(config1, i, 32)))
+                       goto fail;
+               alloc |= (0x1 << i);
+       }
+
+       /* for the match/mask registers */
+       if (reg2->idx != EXTRA_REG_NONE &&
+           (uncore_box_is_fake(box) || !reg2->alloc) &&
+           !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config))
+               goto fail;
+
+       /*
+        * If it's a fake box -- as per validate_{group,event}() we
+        * shouldn't touch event state and we can avoid doing so
+        * since both will only call get_event_constraints() once
+        * on each event, this avoids the need for reg->alloc.
+        */
+       if (!uncore_box_is_fake(box)) {
+               if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8))
+                       nhmex_mbox_alter_er(event, idx[0], true);
+               reg1->alloc |= alloc;
+               if (reg2->idx != EXTRA_REG_NONE)
+                       reg2->alloc = 1;
+       }
+       return NULL;
+fail:
+       if (idx[0] != 0xff && !(alloc & 0x1) &&
+           idx[0] >= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
+               /*
+                * events 0xd ~ 0x10 are functional identical, but are
+                * controlled by different fields in the ZDP_CTL_FVC
+                * register. If we failed to take one field, try the
+                * rest 3 choices.
+                */
+               BUG_ON(__BITS_VALUE(reg1->idx, 1, 8) != 0xff);
+               idx[0] -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
+               idx[0] = (idx[0] + 1) % 4;
+               idx[0] += EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
+               if (idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) {
+                       config1 = nhmex_mbox_alter_er(event, idx[0], false);
+                       goto again;
+               }
+       }
+
+       if (alloc & 0x1)
+               nhmex_mbox_put_shared_reg(box, idx[0]);
+       if (alloc & 0x2)
+               nhmex_mbox_put_shared_reg(box, idx[1]);
+       return &uncore_constraint_empty;
+}
+
+static void nhmex_mbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
+
+       if (uncore_box_is_fake(box))
+               return;
+
+       if (reg1->alloc & 0x1)
+               nhmex_mbox_put_shared_reg(box, __BITS_VALUE(reg1->idx, 0, 8));
+       if (reg1->alloc & 0x2)
+               nhmex_mbox_put_shared_reg(box, __BITS_VALUE(reg1->idx, 1, 8));
+       reg1->alloc = 0;
+
+       if (reg2->alloc) {
+               nhmex_mbox_put_shared_reg(box, reg2->idx);
+               reg2->alloc = 0;
+       }
+}
+
+static int nhmex_mbox_extra_reg_idx(struct extra_reg *er)
+{
+       if (er->idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC)
+               return er->idx;
+       return er->idx + (er->event >> NHMEX_M_PMON_CTL_INC_SEL_SHIFT) - 0xd;
+}
+
+static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct intel_uncore_type *type = box->pmu->type;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
+       struct extra_reg *er;
+       unsigned msr;
+       int reg_idx = 0;
+       /*
+        * The mbox events may require 2 extra MSRs at the most. But only
+        * the lower 32 bits in these MSRs are significant, so we can use
+        * config1 to pass two MSRs' config.
+        */
+       for (er = nhmex_uncore_mbox_extra_regs; er->msr; er++) {
+               if (er->event != (event->hw.config & er->config_mask))
+                       continue;
+               if (event->attr.config1 & ~er->valid_mask)
+                       return -EINVAL;
+
+               msr = er->msr + type->msr_offset * box->pmu->pmu_idx;
+               if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff))
+                       return -EINVAL;
+
+               /* always use the 32~63 bits to pass the PLD config */
+               if (er->idx == EXTRA_REG_NHMEX_M_PLD)
+                       reg_idx = 1;
+               else if (WARN_ON_ONCE(reg_idx > 0))
+                       return -EINVAL;
+
+               reg1->idx &= ~(0xff << (reg_idx * 8));
+               reg1->reg &= ~(0xffff << (reg_idx * 16));
+               reg1->idx |= nhmex_mbox_extra_reg_idx(er) << (reg_idx * 8);
+               reg1->reg |= msr << (reg_idx * 16);
+               reg1->config = event->attr.config1;
+               reg_idx++;
+       }
+       /*
+        * The mbox only provides ability to perform address matching
+        * for the PLD events.
+        */
+       if (reg_idx == 2) {
+               reg2->idx = EXTRA_REG_NHMEX_M_FILTER;
+               if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN)
+                       reg2->config = event->attr.config2;
+               else
+                       reg2->config = ~0ULL;
+               if (box->pmu->pmu_idx == 0)
+                       reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG;
+               else
+                       reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG;
+       }
+       return 0;
+}
+
+static u64 nhmex_mbox_shared_reg_config(struct intel_uncore_box *box, int idx)
+{
+       struct intel_uncore_extra_reg *er;
+       unsigned long flags;
+       u64 config;
+
+       if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC)
+               return box->shared_regs[idx].config;
+
+       er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
+       raw_spin_lock_irqsave(&er->lock, flags);
+       config = er->config;
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+       return config;
+}
+
+static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+       int idx;
+
+       idx = __BITS_VALUE(reg1->idx, 0, 8);
+       if (idx != 0xff)
+               wrmsrl(__BITS_VALUE(reg1->reg, 0, 16),
+                       nhmex_mbox_shared_reg_config(box, idx));
+       idx = __BITS_VALUE(reg1->idx, 1, 8);
+       if (idx != 0xff)
+               wrmsrl(__BITS_VALUE(reg1->reg, 1, 16),
+                       nhmex_mbox_shared_reg_config(box, idx));
+
+       if (reg2->idx != EXTRA_REG_NONE) {
+               wrmsrl(reg2->reg, 0);
+               if (reg2->config != ~0ULL) {
+                       wrmsrl(reg2->reg + 1,
+                               reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK);
+                       wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK &
+                               (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT));
+                       wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN);
+               }
+       }
+
+       wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);
+}
+
+DEFINE_UNCORE_FORMAT_ATTR(count_mode,          count_mode,     "config:2-3");
+DEFINE_UNCORE_FORMAT_ATTR(storage_mode,                storage_mode,   "config:4-5");
+DEFINE_UNCORE_FORMAT_ATTR(wrap_mode,           wrap_mode,      "config:6");
+DEFINE_UNCORE_FORMAT_ATTR(flag_mode,           flag_mode,      "config:7");
+DEFINE_UNCORE_FORMAT_ATTR(inc_sel,             inc_sel,        "config:9-13");
+DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel,                set_flag_sel,   "config:19-21");
+DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en,       filter_cfg_en,  "config2:63");
+DEFINE_UNCORE_FORMAT_ATTR(filter_match,                filter_match,   "config2:0-33");
+DEFINE_UNCORE_FORMAT_ATTR(filter_mask,         filter_mask,    "config2:34-61");
+DEFINE_UNCORE_FORMAT_ATTR(dsp,                 dsp,            "config1:0-31");
+DEFINE_UNCORE_FORMAT_ATTR(thr,                 thr,            "config1:0-31");
+DEFINE_UNCORE_FORMAT_ATTR(fvc,                 fvc,            "config1:0-31");
+DEFINE_UNCORE_FORMAT_ATTR(pgt,                 pgt,            "config1:0-31");
+DEFINE_UNCORE_FORMAT_ATTR(map,                 map,            "config1:0-31");
+DEFINE_UNCORE_FORMAT_ATTR(iss,                 iss,            "config1:0-31");
+DEFINE_UNCORE_FORMAT_ATTR(pld,                 pld,            "config1:32-63");
+
+static struct attribute *nhmex_uncore_mbox_formats_attr[] = {
+       &format_attr_count_mode.attr,
+       &format_attr_storage_mode.attr,
+       &format_attr_wrap_mode.attr,
+       &format_attr_flag_mode.attr,
+       &format_attr_inc_sel.attr,
+       &format_attr_set_flag_sel.attr,
+       &format_attr_filter_cfg_en.attr,
+       &format_attr_filter_match.attr,
+       &format_attr_filter_mask.attr,
+       &format_attr_dsp.attr,
+       &format_attr_thr.attr,
+       &format_attr_fvc.attr,
+       &format_attr_pgt.attr,
+       &format_attr_map.attr,
+       &format_attr_iss.attr,
+       &format_attr_pld.attr,
+       NULL,
+};
+
+static struct attribute_group nhmex_uncore_mbox_format_group = {
+       .name           = "format",
+       .attrs          = nhmex_uncore_mbox_formats_attr,
+};
+
+static struct uncore_event_desc nhmex_uncore_mbox_events[] = {
+       INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x2800"),
+       INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x2820"),
+       { /* end: all zeroes */ },
+};
+
+static struct uncore_event_desc wsmex_uncore_mbox_events[] = {
+       INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"),
+       INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"),
+       { /* end: all zeroes */ },
+};
+
+static struct intel_uncore_ops nhmex_uncore_mbox_ops = {
+       NHMEX_UNCORE_OPS_COMMON_INIT(),
+       .enable_event   = nhmex_mbox_msr_enable_event,
+       .hw_config      = nhmex_mbox_hw_config,
+       .get_constraint = nhmex_mbox_get_constraint,
+       .put_constraint = nhmex_mbox_put_constraint,
+};
+
+static struct intel_uncore_type nhmex_uncore_mbox = {
+       .name                   = "mbox",
+       .num_counters           = 6,
+       .num_boxes              = 2,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = NHMEX_M0_MSR_PMU_CTL0,
+       .perf_ctr               = NHMEX_M0_MSR_PMU_CNT0,
+       .event_mask             = NHMEX_M_PMON_RAW_EVENT_MASK,
+       .box_ctl                = NHMEX_M0_MSR_GLOBAL_CTL,
+       .msr_offset             = NHMEX_M_MSR_OFFSET,
+       .pair_ctr_ctl           = 1,
+       .num_shared_regs        = 8,
+       .event_descs            = nhmex_uncore_mbox_events,
+       .ops                    = &nhmex_uncore_mbox_ops,
+       .format_group           = &nhmex_uncore_mbox_format_group,
+};
+
+static void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+
+       /* adjust the main event selector and extra register index */
+       if (reg1->idx % 2) {
+               reg1->idx--;
+               hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
+       } else {
+               reg1->idx++;
+               hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
+       }
+
+       /* adjust extra register config */
+       switch (reg1->idx % 6) {
+       case 2:
+               /* shift the 8~15 bits to the 0~7 bits */
+               reg1->config >>= 8;
+               break;
+       case 3:
+               /* shift the 0~7 bits to the 8~15 bits */
+               reg1->config <<= 8;
+               break;
+       }
+}
+
+/*
+ * Each rbox has 4 event set which monitor PQI port 0~3 or 4~7.
+ * An event set consists of 6 events, the 3rd and 4th events in
+ * an event set use the same extra register. So an event set uses
+ * 5 extra registers.
+ */
+static struct event_constraint *
+nhmex_rbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+       struct intel_uncore_extra_reg *er;
+       unsigned long flags;
+       int idx, er_idx;
+       u64 config1;
+       bool ok = false;
+
+       if (!uncore_box_is_fake(box) && reg1->alloc)
+               return NULL;
+
+       idx = reg1->idx % 6;
+       config1 = reg1->config;
+again:
+       er_idx = idx;
+       /* the 3rd and 4th events use the same extra register */
+       if (er_idx > 2)
+               er_idx--;
+       er_idx += (reg1->idx / 6) * 5;
+
+       er = &box->shared_regs[er_idx];
+       raw_spin_lock_irqsave(&er->lock, flags);
+       if (idx < 2) {
+               if (!atomic_read(&er->ref) || er->config == reg1->config) {
+                       atomic_inc(&er->ref);
+                       er->config = reg1->config;
+                       ok = true;
+               }
+       } else if (idx == 2 || idx == 3) {
+               /*
+                * these two events use different fields in a extra register,
+                * the 0~7 bits and the 8~15 bits respectively.
+                */
+               u64 mask = 0xff << ((idx - 2) * 8);
+               if (!__BITS_VALUE(atomic_read(&er->ref), idx - 2, 8) ||
+                               !((er->config ^ config1) & mask)) {
+                       atomic_add(1 << ((idx - 2) * 8), &er->ref);
+                       er->config &= ~mask;
+                       er->config |= config1 & mask;
+                       ok = true;
+               }
+       } else {
+               if (!atomic_read(&er->ref) ||
+                               (er->config == (hwc->config >> 32) &&
+                                er->config1 == reg1->config &&
+                                er->config2 == reg2->config)) {
+                       atomic_inc(&er->ref);
+                       er->config = (hwc->config >> 32);
+                       er->config1 = reg1->config;
+                       er->config2 = reg2->config;
+                       ok = true;
+               }
+       }
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+
+       if (!ok) {
+               /*
+                * The Rbox events are always in pairs. The paired
+                * events are functional identical, but use different
+                * extra registers. If we failed to take an extra
+                * register, try the alternative.
+                */
+               idx ^= 1;
+               if (idx != reg1->idx % 6) {
+                       if (idx == 2)
+                               config1 >>= 8;
+                       else if (idx == 3)
+                               config1 <<= 8;
+                       goto again;
+               }
+       } else {
+               if (!uncore_box_is_fake(box)) {
+                       if (idx != reg1->idx % 6)
+                               nhmex_rbox_alter_er(box, event);
+                       reg1->alloc = 1;
+               }
+               return NULL;
+       }
+       return &uncore_constraint_empty;
+}
+
+static void nhmex_rbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct intel_uncore_extra_reg *er;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       int idx, er_idx;
+
+       if (uncore_box_is_fake(box) || !reg1->alloc)
+               return;
+
+       idx = reg1->idx % 6;
+       er_idx = idx;
+       if (er_idx > 2)
+               er_idx--;
+       er_idx += (reg1->idx / 6) * 5;
+
+       er = &box->shared_regs[er_idx];
+       if (idx == 2 || idx == 3)
+               atomic_sub(1 << ((idx - 2) * 8), &er->ref);
+       else
+               atomic_dec(&er->ref);
+
+       reg1->alloc = 0;
+}
+
+static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
+       int idx;
+
+       idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >>
+               NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
+       if (idx >= 0x18)
+               return -EINVAL;
+
+       reg1->idx = idx;
+       reg1->config = event->attr.config1;
+
+       switch (idx % 6) {
+       case 4:
+       case 5:
+               hwc->config |= event->attr.config & (~0ULL << 32);
+               reg2->config = event->attr.config2;
+               break;
+       }
+       return 0;
+}
+
+static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+       int idx, port;
+
+       idx = reg1->idx;
+       port = idx / 6 + box->pmu->pmu_idx * 4;
+
+       switch (idx % 6) {
+       case 0:
+               wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config);
+               break;
+       case 1:
+               wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config);
+               break;
+       case 2:
+       case 3:
+               wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port),
+                       uncore_shared_reg_config(box, 2 + (idx / 6) * 5));
+               break;
+       case 4:
+               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port),
+                       hwc->config >> 32);
+               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config);
+               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config);
+               break;
+       case 5:
+               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port),
+                       hwc->config >> 32);
+               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config);
+               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config);
+               break;
+       }
+
+       wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0 |
+               (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK));
+}
+
+DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63");
+DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63");
+DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63");
+DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15");
+DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31");
+
+static struct attribute *nhmex_uncore_rbox_formats_attr[] = {
+       &format_attr_event5.attr,
+       &format_attr_xbr_mm_cfg.attr,
+       &format_attr_xbr_match.attr,
+       &format_attr_xbr_mask.attr,
+       &format_attr_qlx_cfg.attr,
+       &format_attr_iperf_cfg.attr,
+       NULL,
+};
+
+static struct attribute_group nhmex_uncore_rbox_format_group = {
+       .name = "format",
+       .attrs = nhmex_uncore_rbox_formats_attr,
+};
+
+static struct uncore_event_desc nhmex_uncore_rbox_events[] = {
+       INTEL_UNCORE_EVENT_DESC(qpi0_flit_send,         "event=0x0,iperf_cfg=0x80000000"),
+       INTEL_UNCORE_EVENT_DESC(qpi1_filt_send,         "event=0x6,iperf_cfg=0x80000000"),
+       INTEL_UNCORE_EVENT_DESC(qpi0_idle_filt,         "event=0x0,iperf_cfg=0x40000000"),
+       INTEL_UNCORE_EVENT_DESC(qpi1_idle_filt,         "event=0x6,iperf_cfg=0x40000000"),
+       INTEL_UNCORE_EVENT_DESC(qpi0_date_response,     "event=0x0,iperf_cfg=0xc4"),
+       INTEL_UNCORE_EVENT_DESC(qpi1_date_response,     "event=0x6,iperf_cfg=0xc4"),
+       { /* end: all zeroes */ },
+};
+
+static struct intel_uncore_ops nhmex_uncore_rbox_ops = {
+       NHMEX_UNCORE_OPS_COMMON_INIT(),
+       .enable_event           = nhmex_rbox_msr_enable_event,
+       .hw_config              = nhmex_rbox_hw_config,
+       .get_constraint         = nhmex_rbox_get_constraint,
+       .put_constraint         = nhmex_rbox_put_constraint,
+};
+
+static struct intel_uncore_type nhmex_uncore_rbox = {
+       .name                   = "rbox",
+       .num_counters           = 8,
+       .num_boxes              = 2,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = NHMEX_R_MSR_PMON_CTL0,
+       .perf_ctr               = NHMEX_R_MSR_PMON_CNT0,
+       .event_mask             = NHMEX_R_PMON_RAW_EVENT_MASK,
+       .box_ctl                = NHMEX_R_MSR_GLOBAL_CTL,
+       .msr_offset             = NHMEX_R_MSR_OFFSET,
+       .pair_ctr_ctl           = 1,
+       .num_shared_regs        = 20,
+       .event_descs            = nhmex_uncore_rbox_events,
+       .ops                    = &nhmex_uncore_rbox_ops,
+       .format_group           = &nhmex_uncore_rbox_format_group
+};
+
+static struct intel_uncore_type *nhmex_msr_uncores[] = {
+       &nhmex_uncore_ubox,
+       &nhmex_uncore_cbox,
+       &nhmex_uncore_bbox,
+       &nhmex_uncore_sbox,
+       &nhmex_uncore_mbox,
+       &nhmex_uncore_rbox,
+       &nhmex_uncore_wbox,
+       NULL,
+};
+
+void nhmex_uncore_cpu_init(void)
+{
+       if (boot_cpu_data.x86_model == 46)
+               uncore_nhmex = true;
+       else
+               nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events;
+       if (nhmex_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
+               nhmex_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
+       uncore_msr_uncores = nhmex_msr_uncores;
+}
+/* end of Nehalem-EX uncore support */
diff --git a/arch/x86/events/intel/uncore_snb.c b/arch/x86/events/intel/uncore_snb.c
new file mode 100644 (file)
index 0000000..96531d2
--- /dev/null
@@ -0,0 +1,731 @@
+/* Nehalem/SandBridge/Haswell uncore support */
+#include "uncore.h"
+
+/* Uncore IMC PCI IDs */
+#define PCI_DEVICE_ID_INTEL_SNB_IMC    0x0100
+#define PCI_DEVICE_ID_INTEL_IVB_IMC    0x0154
+#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
+#define PCI_DEVICE_ID_INTEL_HSW_IMC    0x0c00
+#define PCI_DEVICE_ID_INTEL_HSW_U_IMC  0x0a04
+#define PCI_DEVICE_ID_INTEL_BDW_IMC    0x1604
+#define PCI_DEVICE_ID_INTEL_SKL_IMC    0x191f
+
+/* SNB event control */
+#define SNB_UNC_CTL_EV_SEL_MASK                        0x000000ff
+#define SNB_UNC_CTL_UMASK_MASK                 0x0000ff00
+#define SNB_UNC_CTL_EDGE_DET                   (1 << 18)
+#define SNB_UNC_CTL_EN                         (1 << 22)
+#define SNB_UNC_CTL_INVERT                     (1 << 23)
+#define SNB_UNC_CTL_CMASK_MASK                 0x1f000000
+#define NHM_UNC_CTL_CMASK_MASK                 0xff000000
+#define NHM_UNC_FIXED_CTR_CTL_EN               (1 << 0)
+
+#define SNB_UNC_RAW_EVENT_MASK                 (SNB_UNC_CTL_EV_SEL_MASK | \
+                                                SNB_UNC_CTL_UMASK_MASK | \
+                                                SNB_UNC_CTL_EDGE_DET | \
+                                                SNB_UNC_CTL_INVERT | \
+                                                SNB_UNC_CTL_CMASK_MASK)
+
+#define NHM_UNC_RAW_EVENT_MASK                 (SNB_UNC_CTL_EV_SEL_MASK | \
+                                                SNB_UNC_CTL_UMASK_MASK | \
+                                                SNB_UNC_CTL_EDGE_DET | \
+                                                SNB_UNC_CTL_INVERT | \
+                                                NHM_UNC_CTL_CMASK_MASK)
+
+/* SNB global control register */
+#define SNB_UNC_PERF_GLOBAL_CTL                 0x391
+#define SNB_UNC_FIXED_CTR_CTRL                  0x394
+#define SNB_UNC_FIXED_CTR                       0x395
+
+/* SNB uncore global control */
+#define SNB_UNC_GLOBAL_CTL_CORE_ALL             ((1 << 4) - 1)
+#define SNB_UNC_GLOBAL_CTL_EN                   (1 << 29)
+
+/* SNB Cbo register */
+#define SNB_UNC_CBO_0_PERFEVTSEL0               0x700
+#define SNB_UNC_CBO_0_PER_CTR0                  0x706
+#define SNB_UNC_CBO_MSR_OFFSET                  0x10
+
+/* SNB ARB register */
+#define SNB_UNC_ARB_PER_CTR0                   0x3b0
+#define SNB_UNC_ARB_PERFEVTSEL0                        0x3b2
+#define SNB_UNC_ARB_MSR_OFFSET                 0x10
+
+/* NHM global control register */
+#define NHM_UNC_PERF_GLOBAL_CTL                 0x391
+#define NHM_UNC_FIXED_CTR                       0x394
+#define NHM_UNC_FIXED_CTR_CTRL                  0x395
+
+/* NHM uncore global control */
+#define NHM_UNC_GLOBAL_CTL_EN_PC_ALL            ((1ULL << 8) - 1)
+#define NHM_UNC_GLOBAL_CTL_EN_FC                (1ULL << 32)
+
+/* NHM uncore register */
+#define NHM_UNC_PERFEVTSEL0                     0x3c0
+#define NHM_UNC_UNCORE_PMC0                     0x3b0
+
+DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
+DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
+DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
+DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
+DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28");
+DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31");
+
+/* Sandy Bridge uncore support */
+static void snb_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->idx < UNCORE_PMC_IDX_FIXED)
+               wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
+       else
+               wrmsrl(hwc->config_base, SNB_UNC_CTL_EN);
+}
+
+static void snb_uncore_msr_disable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       wrmsrl(event->hw.config_base, 0);
+}
+
+static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->pmu_idx == 0) {
+               wrmsrl(SNB_UNC_PERF_GLOBAL_CTL,
+                       SNB_UNC_GLOBAL_CTL_EN | SNB_UNC_GLOBAL_CTL_CORE_ALL);
+       }
+}
+
+static void snb_uncore_msr_exit_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->pmu_idx == 0)
+               wrmsrl(SNB_UNC_PERF_GLOBAL_CTL, 0);
+}
+
+static struct uncore_event_desc snb_uncore_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
+       { /* end: all zeroes */ },
+};
+
+static struct attribute *snb_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask5.attr,
+       NULL,
+};
+
+static struct attribute_group snb_uncore_format_group = {
+       .name           = "format",
+       .attrs          = snb_uncore_formats_attr,
+};
+
+static struct intel_uncore_ops snb_uncore_msr_ops = {
+       .init_box       = snb_uncore_msr_init_box,
+       .exit_box       = snb_uncore_msr_exit_box,
+       .disable_event  = snb_uncore_msr_disable_event,
+       .enable_event   = snb_uncore_msr_enable_event,
+       .read_counter   = uncore_msr_read_counter,
+};
+
+static struct event_constraint snb_uncore_arb_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x80, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x83, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type snb_uncore_cbox = {
+       .name           = "cbox",
+       .num_counters   = 2,
+       .num_boxes      = 4,
+       .perf_ctr_bits  = 44,
+       .fixed_ctr_bits = 48,
+       .perf_ctr       = SNB_UNC_CBO_0_PER_CTR0,
+       .event_ctl      = SNB_UNC_CBO_0_PERFEVTSEL0,
+       .fixed_ctr      = SNB_UNC_FIXED_CTR,
+       .fixed_ctl      = SNB_UNC_FIXED_CTR_CTRL,
+       .single_fixed   = 1,
+       .event_mask     = SNB_UNC_RAW_EVENT_MASK,
+       .msr_offset     = SNB_UNC_CBO_MSR_OFFSET,
+       .ops            = &snb_uncore_msr_ops,
+       .format_group   = &snb_uncore_format_group,
+       .event_descs    = snb_uncore_events,
+};
+
+static struct intel_uncore_type snb_uncore_arb = {
+       .name           = "arb",
+       .num_counters   = 2,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .perf_ctr       = SNB_UNC_ARB_PER_CTR0,
+       .event_ctl      = SNB_UNC_ARB_PERFEVTSEL0,
+       .event_mask     = SNB_UNC_RAW_EVENT_MASK,
+       .msr_offset     = SNB_UNC_ARB_MSR_OFFSET,
+       .constraints    = snb_uncore_arb_constraints,
+       .ops            = &snb_uncore_msr_ops,
+       .format_group   = &snb_uncore_format_group,
+};
+
+static struct intel_uncore_type *snb_msr_uncores[] = {
+       &snb_uncore_cbox,
+       &snb_uncore_arb,
+       NULL,
+};
+
+void snb_uncore_cpu_init(void)
+{
+       uncore_msr_uncores = snb_msr_uncores;
+       if (snb_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
+               snb_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
+}
+
+enum {
+       SNB_PCI_UNCORE_IMC,
+};
+
+static struct uncore_event_desc snb_uncore_imc_events[] = {
+       INTEL_UNCORE_EVENT_DESC(data_reads,  "event=0x01"),
+       INTEL_UNCORE_EVENT_DESC(data_reads.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(data_reads.unit, "MiB"),
+
+       INTEL_UNCORE_EVENT_DESC(data_writes, "event=0x02"),
+       INTEL_UNCORE_EVENT_DESC(data_writes.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(data_writes.unit, "MiB"),
+
+       { /* end: all zeroes */ },
+};
+
+#define SNB_UNCORE_PCI_IMC_EVENT_MASK          0xff
+#define SNB_UNCORE_PCI_IMC_BAR_OFFSET          0x48
+
+/* page size multiple covering all config regs */
+#define SNB_UNCORE_PCI_IMC_MAP_SIZE            0x6000
+
+#define SNB_UNCORE_PCI_IMC_DATA_READS          0x1
+#define SNB_UNCORE_PCI_IMC_DATA_READS_BASE     0x5050
+#define SNB_UNCORE_PCI_IMC_DATA_WRITES         0x2
+#define SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE    0x5054
+#define SNB_UNCORE_PCI_IMC_CTR_BASE            SNB_UNCORE_PCI_IMC_DATA_READS_BASE
+
+static struct attribute *snb_uncore_imc_formats_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group snb_uncore_imc_format_group = {
+       .name = "format",
+       .attrs = snb_uncore_imc_formats_attr,
+};
+
+static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int where = SNB_UNCORE_PCI_IMC_BAR_OFFSET;
+       resource_size_t addr;
+       u32 pci_dword;
+
+       pci_read_config_dword(pdev, where, &pci_dword);
+       addr = pci_dword;
+
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+       pci_read_config_dword(pdev, where + 4, &pci_dword);
+       addr |= ((resource_size_t)pci_dword << 32);
+#endif
+
+       addr &= ~(PAGE_SIZE - 1);
+
+       box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE);
+       box->hrtimer_duration = UNCORE_SNB_IMC_HRTIMER_INTERVAL;
+}
+
+static void snb_uncore_imc_exit_box(struct intel_uncore_box *box)
+{
+       iounmap(box->io_addr);
+}
+
+static void snb_uncore_imc_enable_box(struct intel_uncore_box *box)
+{}
+
+static void snb_uncore_imc_disable_box(struct intel_uncore_box *box)
+{}
+
+static void snb_uncore_imc_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{}
+
+static void snb_uncore_imc_disable_event(struct intel_uncore_box *box, struct perf_event *event)
+{}
+
+static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       return (u64)*(unsigned int *)(box->io_addr + hwc->event_base);
+}
+
+/*
+ * custom event_init() function because we define our own fixed, free
+ * running counters, so we do not want to conflict with generic uncore
+ * logic. Also simplifies processing
+ */
+static int snb_uncore_imc_event_init(struct perf_event *event)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       struct hw_perf_event *hwc = &event->hw;
+       u64 cfg = event->attr.config & SNB_UNCORE_PCI_IMC_EVENT_MASK;
+       int idx, base;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       pmu = uncore_event_to_pmu(event);
+       /* no device found for this pmu */
+       if (pmu->func_id < 0)
+               return -ENOENT;
+
+       /* Sampling not supported yet */
+       if (hwc->sample_period)
+               return -EINVAL;
+
+       /* unsupported modes and filters */
+       if (event->attr.exclude_user   ||
+           event->attr.exclude_kernel ||
+           event->attr.exclude_hv     ||
+           event->attr.exclude_idle   ||
+           event->attr.exclude_host   ||
+           event->attr.exclude_guest  ||
+           event->attr.sample_period) /* no sampling */
+               return -EINVAL;
+
+       /*
+        * Place all uncore events for a particular physical package
+        * onto a single cpu
+        */
+       if (event->cpu < 0)
+               return -EINVAL;
+
+       /* check only supported bits are set */
+       if (event->attr.config & ~SNB_UNCORE_PCI_IMC_EVENT_MASK)
+               return -EINVAL;
+
+       box = uncore_pmu_to_box(pmu, event->cpu);
+       if (!box || box->cpu < 0)
+               return -EINVAL;
+
+       event->cpu = box->cpu;
+       event->pmu_private = box;
+
+       event->hw.idx = -1;
+       event->hw.last_tag = ~0ULL;
+       event->hw.extra_reg.idx = EXTRA_REG_NONE;
+       event->hw.branch_reg.idx = EXTRA_REG_NONE;
+       /*
+        * check event is known (whitelist, determines counter)
+        */
+       switch (cfg) {
+       case SNB_UNCORE_PCI_IMC_DATA_READS:
+               base = SNB_UNCORE_PCI_IMC_DATA_READS_BASE;
+               idx = UNCORE_PMC_IDX_FIXED;
+               break;
+       case SNB_UNCORE_PCI_IMC_DATA_WRITES:
+               base = SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE;
+               idx = UNCORE_PMC_IDX_FIXED + 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* must be done before validate_group */
+       event->hw.event_base = base;
+       event->hw.config = cfg;
+       event->hw.idx = idx;
+
+       /* no group validation needed, we have free running counters */
+
+       return 0;
+}
+
+static int snb_uncore_imc_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       return 0;
+}
+
+static void snb_uncore_imc_event_start(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       u64 count;
+
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       event->hw.state = 0;
+       box->n_active++;
+
+       list_add_tail(&event->active_entry, &box->active_list);
+
+       count = snb_uncore_imc_read_counter(box, event);
+       local64_set(&event->hw.prev_count, count);
+
+       if (box->n_active == 1)
+               uncore_pmu_start_hrtimer(box);
+}
+
+static void snb_uncore_imc_event_stop(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (!(hwc->state & PERF_HES_STOPPED)) {
+               box->n_active--;
+
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+
+               list_del(&event->active_entry);
+
+               if (box->n_active == 0)
+                       uncore_pmu_cancel_hrtimer(box);
+       }
+
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               uncore_perf_event_update(box, event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+}
+
+static int snb_uncore_imc_event_add(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (!box)
+               return -ENODEV;
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+       if (!(flags & PERF_EF_START))
+               hwc->state |= PERF_HES_ARCH;
+
+       snb_uncore_imc_event_start(event, 0);
+
+       box->n_events++;
+
+       return 0;
+}
+
+static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       int i;
+
+       snb_uncore_imc_event_stop(event, PERF_EF_UPDATE);
+
+       for (i = 0; i < box->n_events; i++) {
+               if (event == box->event_list[i]) {
+                       --box->n_events;
+                       break;
+               }
+       }
+}
+
+int snb_pci2phy_map_init(int devid)
+{
+       struct pci_dev *dev = NULL;
+       struct pci2phy_map *map;
+       int bus, segment;
+
+       dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, dev);
+       if (!dev)
+               return -ENOTTY;
+
+       bus = dev->bus->number;
+       segment = pci_domain_nr(dev->bus);
+
+       raw_spin_lock(&pci2phy_map_lock);
+       map = __find_pci2phy_map(segment);
+       if (!map) {
+               raw_spin_unlock(&pci2phy_map_lock);
+               pci_dev_put(dev);
+               return -ENOMEM;
+       }
+       map->pbus_to_physid[bus] = 0;
+       raw_spin_unlock(&pci2phy_map_lock);
+
+       pci_dev_put(dev);
+
+       return 0;
+}
+
+static struct pmu snb_uncore_imc_pmu = {
+       .task_ctx_nr    = perf_invalid_context,
+       .event_init     = snb_uncore_imc_event_init,
+       .add            = snb_uncore_imc_event_add,
+       .del            = snb_uncore_imc_event_del,
+       .start          = snb_uncore_imc_event_start,
+       .stop           = snb_uncore_imc_event_stop,
+       .read           = uncore_pmu_event_read,
+};
+
+static struct intel_uncore_ops snb_uncore_imc_ops = {
+       .init_box       = snb_uncore_imc_init_box,
+       .exit_box       = snb_uncore_imc_exit_box,
+       .enable_box     = snb_uncore_imc_enable_box,
+       .disable_box    = snb_uncore_imc_disable_box,
+       .disable_event  = snb_uncore_imc_disable_event,
+       .enable_event   = snb_uncore_imc_enable_event,
+       .hw_config      = snb_uncore_imc_hw_config,
+       .read_counter   = snb_uncore_imc_read_counter,
+};
+
+static struct intel_uncore_type snb_uncore_imc = {
+       .name           = "imc",
+       .num_counters   = 2,
+       .num_boxes      = 1,
+       .fixed_ctr_bits = 32,
+       .fixed_ctr      = SNB_UNCORE_PCI_IMC_CTR_BASE,
+       .event_descs    = snb_uncore_imc_events,
+       .format_group   = &snb_uncore_imc_format_group,
+       .perf_ctr       = SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
+       .event_mask     = SNB_UNCORE_PCI_IMC_EVENT_MASK,
+       .ops            = &snb_uncore_imc_ops,
+       .pmu            = &snb_uncore_imc_pmu,
+};
+
+static struct intel_uncore_type *snb_pci_uncores[] = {
+       [SNB_PCI_UNCORE_IMC]    = &snb_uncore_imc,
+       NULL,
+};
+
+static const struct pci_device_id snb_uncore_pci_ids[] = {
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* end: all zeroes */ },
+};
+
+static const struct pci_device_id ivb_uncore_pci_ids[] = {
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_E3_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* end: all zeroes */ },
+};
+
+static const struct pci_device_id hsw_uncore_pci_ids[] = {
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_U_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* end: all zeroes */ },
+};
+
+static const struct pci_device_id bdw_uncore_pci_ids[] = {
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* end: all zeroes */ },
+};
+
+static const struct pci_device_id skl_uncore_pci_ids[] = {
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* end: all zeroes */ },
+};
+
+static struct pci_driver snb_uncore_pci_driver = {
+       .name           = "snb_uncore",
+       .id_table       = snb_uncore_pci_ids,
+};
+
+static struct pci_driver ivb_uncore_pci_driver = {
+       .name           = "ivb_uncore",
+       .id_table       = ivb_uncore_pci_ids,
+};
+
+static struct pci_driver hsw_uncore_pci_driver = {
+       .name           = "hsw_uncore",
+       .id_table       = hsw_uncore_pci_ids,
+};
+
+static struct pci_driver bdw_uncore_pci_driver = {
+       .name           = "bdw_uncore",
+       .id_table       = bdw_uncore_pci_ids,
+};
+
+static struct pci_driver skl_uncore_pci_driver = {
+       .name           = "skl_uncore",
+       .id_table       = skl_uncore_pci_ids,
+};
+
+struct imc_uncore_pci_dev {
+       __u32 pci_id;
+       struct pci_driver *driver;
+};
+#define IMC_DEV(a, d) \
+       { .pci_id = PCI_DEVICE_ID_INTEL_##a, .driver = (d) }
+
+static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
+       IMC_DEV(SNB_IMC, &snb_uncore_pci_driver),
+       IMC_DEV(IVB_IMC, &ivb_uncore_pci_driver),    /* 3rd Gen Core processor */
+       IMC_DEV(IVB_E3_IMC, &ivb_uncore_pci_driver), /* Xeon E3-1200 v2/3rd Gen Core processor */
+       IMC_DEV(HSW_IMC, &hsw_uncore_pci_driver),    /* 4th Gen Core Processor */
+       IMC_DEV(HSW_U_IMC, &hsw_uncore_pci_driver),  /* 4th Gen Core ULT Mobile Processor */
+       IMC_DEV(BDW_IMC, &bdw_uncore_pci_driver),    /* 5th Gen Core U */
+       IMC_DEV(SKL_IMC, &skl_uncore_pci_driver),    /* 6th Gen Core */
+       {  /* end marker */ }
+};
+
+
+#define for_each_imc_pci_id(x, t) \
+       for (x = (t); (x)->pci_id; x++)
+
+static struct pci_driver *imc_uncore_find_dev(void)
+{
+       const struct imc_uncore_pci_dev *p;
+       int ret;
+
+       for_each_imc_pci_id(p, desktop_imc_pci_ids) {
+               ret = snb_pci2phy_map_init(p->pci_id);
+               if (ret == 0)
+                       return p->driver;
+       }
+       return NULL;
+}
+
+static int imc_uncore_pci_init(void)
+{
+       struct pci_driver *imc_drv = imc_uncore_find_dev();
+
+       if (!imc_drv)
+               return -ENODEV;
+
+       uncore_pci_uncores = snb_pci_uncores;
+       uncore_pci_driver = imc_drv;
+
+       return 0;
+}
+
+int snb_uncore_pci_init(void)
+{
+       return imc_uncore_pci_init();
+}
+
+int ivb_uncore_pci_init(void)
+{
+       return imc_uncore_pci_init();
+}
+int hsw_uncore_pci_init(void)
+{
+       return imc_uncore_pci_init();
+}
+
+int bdw_uncore_pci_init(void)
+{
+       return imc_uncore_pci_init();
+}
+
+int skl_uncore_pci_init(void)
+{
+       return imc_uncore_pci_init();
+}
+
+/* end of Sandy Bridge uncore support */
+
+/* Nehalem uncore support */
+static void nhm_uncore_msr_disable_box(struct intel_uncore_box *box)
+{
+       wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, 0);
+}
+
+static void nhm_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+       wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, NHM_UNC_GLOBAL_CTL_EN_PC_ALL | NHM_UNC_GLOBAL_CTL_EN_FC);
+}
+
+static void nhm_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->idx < UNCORE_PMC_IDX_FIXED)
+               wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
+       else
+               wrmsrl(hwc->config_base, NHM_UNC_FIXED_CTR_CTL_EN);
+}
+
+static struct attribute *nhm_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask8.attr,
+       NULL,
+};
+
+static struct attribute_group nhm_uncore_format_group = {
+       .name = "format",
+       .attrs = nhm_uncore_formats_attr,
+};
+
+static struct uncore_event_desc nhm_uncore_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,                "event=0xff,umask=0x00"),
+       INTEL_UNCORE_EVENT_DESC(qmc_writes_full_any,       "event=0x2f,umask=0x0f"),
+       INTEL_UNCORE_EVENT_DESC(qmc_normal_reads_any,      "event=0x2c,umask=0x0f"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_reads,     "event=0x20,umask=0x01"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_writes,    "event=0x20,umask=0x02"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_remote_reads,  "event=0x20,umask=0x04"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_remote_writes, "event=0x20,umask=0x08"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_local_reads,   "event=0x20,umask=0x10"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_local_writes,  "event=0x20,umask=0x20"),
+       { /* end: all zeroes */ },
+};
+
+static struct intel_uncore_ops nhm_uncore_msr_ops = {
+       .disable_box    = nhm_uncore_msr_disable_box,
+       .enable_box     = nhm_uncore_msr_enable_box,
+       .disable_event  = snb_uncore_msr_disable_event,
+       .enable_event   = nhm_uncore_msr_enable_event,
+       .read_counter   = uncore_msr_read_counter,
+};
+
+static struct intel_uncore_type nhm_uncore = {
+       .name           = "",
+       .num_counters   = 8,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .event_ctl      = NHM_UNC_PERFEVTSEL0,
+       .perf_ctr       = NHM_UNC_UNCORE_PMC0,
+       .fixed_ctr      = NHM_UNC_FIXED_CTR,
+       .fixed_ctl      = NHM_UNC_FIXED_CTR_CTRL,
+       .event_mask     = NHM_UNC_RAW_EVENT_MASK,
+       .event_descs    = nhm_uncore_events,
+       .ops            = &nhm_uncore_msr_ops,
+       .format_group   = &nhm_uncore_format_group,
+};
+
+static struct intel_uncore_type *nhm_msr_uncores[] = {
+       &nhm_uncore,
+       NULL,
+};
+
+void nhm_uncore_cpu_init(void)
+{
+       uncore_msr_uncores = nhm_msr_uncores;
+}
+
+/* end of Nehalem uncore support */
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
new file mode 100644 (file)
index 0000000..93f6bd9
--- /dev/null
@@ -0,0 +1,3135 @@
+/* SandyBridge-EP/IvyTown uncore support */
+#include "uncore.h"
+
+/* SNB-EP Box level control */
+#define SNBEP_PMON_BOX_CTL_RST_CTRL    (1 << 0)
+#define SNBEP_PMON_BOX_CTL_RST_CTRS    (1 << 1)
+#define SNBEP_PMON_BOX_CTL_FRZ         (1 << 8)
+#define SNBEP_PMON_BOX_CTL_FRZ_EN      (1 << 16)
+#define SNBEP_PMON_BOX_CTL_INT         (SNBEP_PMON_BOX_CTL_RST_CTRL | \
+                                        SNBEP_PMON_BOX_CTL_RST_CTRS | \
+                                        SNBEP_PMON_BOX_CTL_FRZ_EN)
+/* SNB-EP event control */
+#define SNBEP_PMON_CTL_EV_SEL_MASK     0x000000ff
+#define SNBEP_PMON_CTL_UMASK_MASK      0x0000ff00
+#define SNBEP_PMON_CTL_RST             (1 << 17)
+#define SNBEP_PMON_CTL_EDGE_DET                (1 << 18)
+#define SNBEP_PMON_CTL_EV_SEL_EXT      (1 << 21)
+#define SNBEP_PMON_CTL_EN              (1 << 22)
+#define SNBEP_PMON_CTL_INVERT          (1 << 23)
+#define SNBEP_PMON_CTL_TRESH_MASK      0xff000000
+#define SNBEP_PMON_RAW_EVENT_MASK      (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                        SNBEP_PMON_CTL_UMASK_MASK | \
+                                        SNBEP_PMON_CTL_EDGE_DET | \
+                                        SNBEP_PMON_CTL_INVERT | \
+                                        SNBEP_PMON_CTL_TRESH_MASK)
+
+/* SNB-EP Ubox event control */
+#define SNBEP_U_MSR_PMON_CTL_TRESH_MASK                0x1f000000
+#define SNBEP_U_MSR_PMON_RAW_EVENT_MASK                \
+                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                SNBEP_PMON_CTL_UMASK_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_PMON_CTL_INVERT | \
+                                SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
+
+#define SNBEP_CBO_PMON_CTL_TID_EN              (1 << 19)
+#define SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK      (SNBEP_PMON_RAW_EVENT_MASK | \
+                                                SNBEP_CBO_PMON_CTL_TID_EN)
+
+/* SNB-EP PCU event control */
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK    0x0000c000
+#define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK      0x1f000000
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT      (1 << 30)
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET    (1 << 31)
+#define SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK      \
+                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_PMON_CTL_EV_SEL_EXT | \
+                                SNBEP_PMON_CTL_INVERT | \
+                                SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
+
+#define SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK      \
+                               (SNBEP_PMON_RAW_EVENT_MASK | \
+                                SNBEP_PMON_CTL_EV_SEL_EXT)
+
+/* SNB-EP pci control register */
+#define SNBEP_PCI_PMON_BOX_CTL                 0xf4
+#define SNBEP_PCI_PMON_CTL0                    0xd8
+/* SNB-EP pci counter register */
+#define SNBEP_PCI_PMON_CTR0                    0xa0
+
+/* SNB-EP home agent register */
+#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH0       0x40
+#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH1       0x44
+#define SNBEP_HA_PCI_PMON_BOX_OPCODEMATCH      0x48
+/* SNB-EP memory controller register */
+#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTL                0xf0
+#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTR                0xd0
+/* SNB-EP QPI register */
+#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH0         0x228
+#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH1         0x22c
+#define SNBEP_Q_Py_PCI_PMON_PKT_MASK0          0x238
+#define SNBEP_Q_Py_PCI_PMON_PKT_MASK1          0x23c
+
+/* SNB-EP Ubox register */
+#define SNBEP_U_MSR_PMON_CTR0                  0xc16
+#define SNBEP_U_MSR_PMON_CTL0                  0xc10
+
+#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTL                0xc08
+#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTR                0xc09
+
+/* SNB-EP Cbo register */
+#define SNBEP_C0_MSR_PMON_CTR0                 0xd16
+#define SNBEP_C0_MSR_PMON_CTL0                 0xd10
+#define SNBEP_C0_MSR_PMON_BOX_CTL              0xd04
+#define SNBEP_C0_MSR_PMON_BOX_FILTER           0xd14
+#define SNBEP_CBO_MSR_OFFSET                   0x20
+
+#define SNBEP_CB0_MSR_PMON_BOX_FILTER_TID      0x1f
+#define SNBEP_CB0_MSR_PMON_BOX_FILTER_NID      0x3fc00
+#define SNBEP_CB0_MSR_PMON_BOX_FILTER_STATE    0x7c0000
+#define SNBEP_CB0_MSR_PMON_BOX_FILTER_OPC      0xff800000
+
+#define SNBEP_CBO_EVENT_EXTRA_REG(e, m, i) {   \
+       .event = (e),                           \
+       .msr = SNBEP_C0_MSR_PMON_BOX_FILTER,    \
+       .config_mask = (m),                     \
+       .idx = (i)                              \
+}
+
+/* SNB-EP PCU register */
+#define SNBEP_PCU_MSR_PMON_CTR0                        0xc36
+#define SNBEP_PCU_MSR_PMON_CTL0                        0xc30
+#define SNBEP_PCU_MSR_PMON_BOX_CTL             0xc24
+#define SNBEP_PCU_MSR_PMON_BOX_FILTER          0xc34
+#define SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK     0xffffffff
+#define SNBEP_PCU_MSR_CORE_C3_CTR              0x3fc
+#define SNBEP_PCU_MSR_CORE_C6_CTR              0x3fd
+
+/* IVBEP event control */
+#define IVBEP_PMON_BOX_CTL_INT         (SNBEP_PMON_BOX_CTL_RST_CTRL | \
+                                        SNBEP_PMON_BOX_CTL_RST_CTRS)
+#define IVBEP_PMON_RAW_EVENT_MASK              (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                        SNBEP_PMON_CTL_UMASK_MASK | \
+                                        SNBEP_PMON_CTL_EDGE_DET | \
+                                        SNBEP_PMON_CTL_TRESH_MASK)
+/* IVBEP Ubox */
+#define IVBEP_U_MSR_PMON_GLOBAL_CTL            0xc00
+#define IVBEP_U_PMON_GLOBAL_FRZ_ALL            (1 << 31)
+#define IVBEP_U_PMON_GLOBAL_UNFRZ_ALL          (1 << 29)
+
+#define IVBEP_U_MSR_PMON_RAW_EVENT_MASK        \
+                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                SNBEP_PMON_CTL_UMASK_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
+/* IVBEP Cbo */
+#define IVBEP_CBO_MSR_PMON_RAW_EVENT_MASK              (IVBEP_PMON_RAW_EVENT_MASK | \
+                                                SNBEP_CBO_PMON_CTL_TID_EN)
+
+#define IVBEP_CB0_MSR_PMON_BOX_FILTER_TID              (0x1fULL << 0)
+#define IVBEP_CB0_MSR_PMON_BOX_FILTER_LINK     (0xfULL << 5)
+#define IVBEP_CB0_MSR_PMON_BOX_FILTER_STATE    (0x3fULL << 17)
+#define IVBEP_CB0_MSR_PMON_BOX_FILTER_NID              (0xffffULL << 32)
+#define IVBEP_CB0_MSR_PMON_BOX_FILTER_OPC              (0x1ffULL << 52)
+#define IVBEP_CB0_MSR_PMON_BOX_FILTER_C6               (0x1ULL << 61)
+#define IVBEP_CB0_MSR_PMON_BOX_FILTER_NC               (0x1ULL << 62)
+#define IVBEP_CB0_MSR_PMON_BOX_FILTER_ISOC     (0x1ULL << 63)
+
+/* IVBEP home agent */
+#define IVBEP_HA_PCI_PMON_CTL_Q_OCC_RST                (1 << 16)
+#define IVBEP_HA_PCI_PMON_RAW_EVENT_MASK               \
+                               (IVBEP_PMON_RAW_EVENT_MASK | \
+                                IVBEP_HA_PCI_PMON_CTL_Q_OCC_RST)
+/* IVBEP PCU */
+#define IVBEP_PCU_MSR_PMON_RAW_EVENT_MASK      \
+                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                SNBEP_PMON_CTL_EV_SEL_EXT | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
+/* IVBEP QPI */
+#define IVBEP_QPI_PCI_PMON_RAW_EVENT_MASK      \
+                               (IVBEP_PMON_RAW_EVENT_MASK | \
+                                SNBEP_PMON_CTL_EV_SEL_EXT)
+
+#define __BITS_VALUE(x, i, n)  ((typeof(x))(((x) >> ((i) * (n))) & \
+                               ((1ULL << (n)) - 1)))
+
+/* Haswell-EP Ubox */
+#define HSWEP_U_MSR_PMON_CTR0                  0x709
+#define HSWEP_U_MSR_PMON_CTL0                  0x705
+#define HSWEP_U_MSR_PMON_FILTER                        0x707
+
+#define HSWEP_U_MSR_PMON_UCLK_FIXED_CTL                0x703
+#define HSWEP_U_MSR_PMON_UCLK_FIXED_CTR                0x704
+
+#define HSWEP_U_MSR_PMON_BOX_FILTER_TID                (0x1 << 0)
+#define HSWEP_U_MSR_PMON_BOX_FILTER_CID                (0x1fULL << 1)
+#define HSWEP_U_MSR_PMON_BOX_FILTER_MASK \
+                                       (HSWEP_U_MSR_PMON_BOX_FILTER_TID | \
+                                        HSWEP_U_MSR_PMON_BOX_FILTER_CID)
+
+/* Haswell-EP CBo */
+#define HSWEP_C0_MSR_PMON_CTR0                 0xe08
+#define HSWEP_C0_MSR_PMON_CTL0                 0xe01
+#define HSWEP_C0_MSR_PMON_BOX_CTL                      0xe00
+#define HSWEP_C0_MSR_PMON_BOX_FILTER0          0xe05
+#define HSWEP_CBO_MSR_OFFSET                   0x10
+
+
+#define HSWEP_CB0_MSR_PMON_BOX_FILTER_TID              (0x3fULL << 0)
+#define HSWEP_CB0_MSR_PMON_BOX_FILTER_LINK     (0xfULL << 6)
+#define HSWEP_CB0_MSR_PMON_BOX_FILTER_STATE    (0x7fULL << 17)
+#define HSWEP_CB0_MSR_PMON_BOX_FILTER_NID              (0xffffULL << 32)
+#define HSWEP_CB0_MSR_PMON_BOX_FILTER_OPC              (0x1ffULL << 52)
+#define HSWEP_CB0_MSR_PMON_BOX_FILTER_C6               (0x1ULL << 61)
+#define HSWEP_CB0_MSR_PMON_BOX_FILTER_NC               (0x1ULL << 62)
+#define HSWEP_CB0_MSR_PMON_BOX_FILTER_ISOC     (0x1ULL << 63)
+
+
+/* Haswell-EP Sbox */
+#define HSWEP_S0_MSR_PMON_CTR0                 0x726
+#define HSWEP_S0_MSR_PMON_CTL0                 0x721
+#define HSWEP_S0_MSR_PMON_BOX_CTL                      0x720
+#define HSWEP_SBOX_MSR_OFFSET                  0xa
+#define HSWEP_S_MSR_PMON_RAW_EVENT_MASK                (SNBEP_PMON_RAW_EVENT_MASK | \
+                                                SNBEP_CBO_PMON_CTL_TID_EN)
+
+/* Haswell-EP PCU */
+#define HSWEP_PCU_MSR_PMON_CTR0                        0x717
+#define HSWEP_PCU_MSR_PMON_CTL0                        0x711
+#define HSWEP_PCU_MSR_PMON_BOX_CTL             0x710
+#define HSWEP_PCU_MSR_PMON_BOX_FILTER          0x715
+
+/* KNL Ubox */
+#define KNL_U_MSR_PMON_RAW_EVENT_MASK \
+                                       (SNBEP_U_MSR_PMON_RAW_EVENT_MASK | \
+                                               SNBEP_CBO_PMON_CTL_TID_EN)
+/* KNL CHA */
+#define KNL_CHA_MSR_OFFSET                     0xc
+#define KNL_CHA_MSR_PMON_CTL_QOR               (1 << 16)
+#define KNL_CHA_MSR_PMON_RAW_EVENT_MASK \
+                                       (SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK | \
+                                        KNL_CHA_MSR_PMON_CTL_QOR)
+#define KNL_CHA_MSR_PMON_BOX_FILTER_TID                0x1ff
+#define KNL_CHA_MSR_PMON_BOX_FILTER_STATE      (7 << 18)
+#define KNL_CHA_MSR_PMON_BOX_FILTER_OP         (0xfffffe2aULL << 32)
+
+/* KNL EDC/MC UCLK */
+#define KNL_UCLK_MSR_PMON_CTR0_LOW             0x400
+#define KNL_UCLK_MSR_PMON_CTL0                 0x420
+#define KNL_UCLK_MSR_PMON_BOX_CTL              0x430
+#define KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW       0x44c
+#define KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL       0x454
+#define KNL_PMON_FIXED_CTL_EN                  0x1
+
+/* KNL EDC */
+#define KNL_EDC0_ECLK_MSR_PMON_CTR0_LOW                0xa00
+#define KNL_EDC0_ECLK_MSR_PMON_CTL0            0xa20
+#define KNL_EDC0_ECLK_MSR_PMON_BOX_CTL         0xa30
+#define KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_LOW  0xa3c
+#define KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_CTL  0xa44
+
+/* KNL MC */
+#define KNL_MC0_CH0_MSR_PMON_CTR0_LOW          0xb00
+#define KNL_MC0_CH0_MSR_PMON_CTL0              0xb20
+#define KNL_MC0_CH0_MSR_PMON_BOX_CTL           0xb30
+#define KNL_MC0_CH0_MSR_PMON_FIXED_LOW         0xb3c
+#define KNL_MC0_CH0_MSR_PMON_FIXED_CTL         0xb44
+
+/* KNL IRP */
+#define KNL_IRP_PCI_PMON_BOX_CTL               0xf0
+#define KNL_IRP_PCI_PMON_RAW_EVENT_MASK                (SNBEP_PMON_RAW_EVENT_MASK | \
+                                                KNL_CHA_MSR_PMON_CTL_QOR)
+/* KNL PCU */
+#define KNL_PCU_PMON_CTL_EV_SEL_MASK           0x0000007f
+#define KNL_PCU_PMON_CTL_USE_OCC_CTR           (1 << 7)
+#define KNL_PCU_MSR_PMON_CTL_TRESH_MASK                0x3f000000
+#define KNL_PCU_MSR_PMON_RAW_EVENT_MASK        \
+                               (KNL_PCU_PMON_CTL_EV_SEL_MASK | \
+                                KNL_PCU_PMON_CTL_USE_OCC_CTR | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_CBO_PMON_CTL_TID_EN | \
+                                SNBEP_PMON_CTL_EV_SEL_EXT | \
+                                SNBEP_PMON_CTL_INVERT | \
+                                KNL_PCU_MSR_PMON_CTL_TRESH_MASK | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
+
+DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
+DEFINE_UNCORE_FORMAT_ATTR(event2, event, "config:0-6");
+DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21");
+DEFINE_UNCORE_FORMAT_ATTR(use_occ_ctr, use_occ_ctr, "config:7");
+DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
+DEFINE_UNCORE_FORMAT_ATTR(qor, qor, "config:16");
+DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
+DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19");
+DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
+DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
+DEFINE_UNCORE_FORMAT_ATTR(thresh6, thresh, "config:24-29");
+DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28");
+DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15");
+DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30");
+DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51");
+DEFINE_UNCORE_FORMAT_ATTR(occ_edge_det, occ_edge_det, "config:31");
+DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4");
+DEFINE_UNCORE_FORMAT_ATTR(filter_tid2, filter_tid, "config1:0");
+DEFINE_UNCORE_FORMAT_ATTR(filter_tid3, filter_tid, "config1:0-5");
+DEFINE_UNCORE_FORMAT_ATTR(filter_tid4, filter_tid, "config1:0-8");
+DEFINE_UNCORE_FORMAT_ATTR(filter_cid, filter_cid, "config1:5");
+DEFINE_UNCORE_FORMAT_ATTR(filter_link, filter_link, "config1:5-8");
+DEFINE_UNCORE_FORMAT_ATTR(filter_link2, filter_link, "config1:6-8");
+DEFINE_UNCORE_FORMAT_ATTR(filter_link3, filter_link, "config1:12");
+DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17");
+DEFINE_UNCORE_FORMAT_ATTR(filter_nid2, filter_nid, "config1:32-47");
+DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22");
+DEFINE_UNCORE_FORMAT_ATTR(filter_state2, filter_state, "config1:17-22");
+DEFINE_UNCORE_FORMAT_ATTR(filter_state3, filter_state, "config1:17-23");
+DEFINE_UNCORE_FORMAT_ATTR(filter_state4, filter_state, "config1:18-20");
+DEFINE_UNCORE_FORMAT_ATTR(filter_local, filter_local, "config1:33");
+DEFINE_UNCORE_FORMAT_ATTR(filter_all_op, filter_all_op, "config1:35");
+DEFINE_UNCORE_FORMAT_ATTR(filter_nnm, filter_nnm, "config1:37");
+DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31");
+DEFINE_UNCORE_FORMAT_ATTR(filter_opc2, filter_opc, "config1:52-60");
+DEFINE_UNCORE_FORMAT_ATTR(filter_opc3, filter_opc, "config1:41-60");
+DEFINE_UNCORE_FORMAT_ATTR(filter_nc, filter_nc, "config1:62");
+DEFINE_UNCORE_FORMAT_ATTR(filter_c6, filter_c6, "config1:61");
+DEFINE_UNCORE_FORMAT_ATTR(filter_isoc, filter_isoc, "config1:63");
+DEFINE_UNCORE_FORMAT_ATTR(filter_band0, filter_band0, "config1:0-7");
+DEFINE_UNCORE_FORMAT_ATTR(filter_band1, filter_band1, "config1:8-15");
+DEFINE_UNCORE_FORMAT_ATTR(filter_band2, filter_band2, "config1:16-23");
+DEFINE_UNCORE_FORMAT_ATTR(filter_band3, filter_band3, "config1:24-31");
+DEFINE_UNCORE_FORMAT_ATTR(match_rds, match_rds, "config1:48-51");
+DEFINE_UNCORE_FORMAT_ATTR(match_rnid30, match_rnid30, "config1:32-35");
+DEFINE_UNCORE_FORMAT_ATTR(match_rnid4, match_rnid4, "config1:31");
+DEFINE_UNCORE_FORMAT_ATTR(match_dnid, match_dnid, "config1:13-17");
+DEFINE_UNCORE_FORMAT_ATTR(match_mc, match_mc, "config1:9-12");
+DEFINE_UNCORE_FORMAT_ATTR(match_opc, match_opc, "config1:5-8");
+DEFINE_UNCORE_FORMAT_ATTR(match_vnw, match_vnw, "config1:3-4");
+DEFINE_UNCORE_FORMAT_ATTR(match0, match0, "config1:0-31");
+DEFINE_UNCORE_FORMAT_ATTR(match1, match1, "config1:32-63");
+DEFINE_UNCORE_FORMAT_ATTR(mask_rds, mask_rds, "config2:48-51");
+DEFINE_UNCORE_FORMAT_ATTR(mask_rnid30, mask_rnid30, "config2:32-35");
+DEFINE_UNCORE_FORMAT_ATTR(mask_rnid4, mask_rnid4, "config2:31");
+DEFINE_UNCORE_FORMAT_ATTR(mask_dnid, mask_dnid, "config2:13-17");
+DEFINE_UNCORE_FORMAT_ATTR(mask_mc, mask_mc, "config2:9-12");
+DEFINE_UNCORE_FORMAT_ATTR(mask_opc, mask_opc, "config2:5-8");
+DEFINE_UNCORE_FORMAT_ATTR(mask_vnw, mask_vnw, "config2:3-4");
+DEFINE_UNCORE_FORMAT_ATTR(mask0, mask0, "config2:0-31");
+DEFINE_UNCORE_FORMAT_ATTR(mask1, mask1, "config2:32-63");
+
+static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int box_ctl = uncore_pci_box_ctl(box);
+       u32 config = 0;
+
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config |= SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
+}
+
+static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int box_ctl = uncore_pci_box_ctl(box);
+       u32 config = 0;
+
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
+}
+
+static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       pci_write_config_dword(pdev, hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static void snbep_uncore_pci_disable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       pci_write_config_dword(pdev, hwc->config_base, hwc->config);
+}
+
+static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+       u64 count = 0;
+
+       pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
+       pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
+
+       return count;
+}
+
+static void snbep_uncore_pci_init_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int box_ctl = uncore_pci_box_ctl(box);
+
+       pci_write_config_dword(pdev, box_ctl, SNBEP_PMON_BOX_CTL_INT);
+}
+
+static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box)
+{
+       u64 config;
+       unsigned msr;
+
+       msr = uncore_msr_box_ctl(box);
+       if (msr) {
+               rdmsrl(msr, config);
+               config |= SNBEP_PMON_BOX_CTL_FRZ;
+               wrmsrl(msr, config);
+       }
+}
+
+static void snbep_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+       u64 config;
+       unsigned msr;
+
+       msr = uncore_msr_box_ctl(box);
+       if (msr) {
+               rdmsrl(msr, config);
+               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+               wrmsrl(msr, config);
+       }
+}
+
+static void snbep_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+
+       if (reg1->idx != EXTRA_REG_NONE)
+               wrmsrl(reg1->reg, uncore_shared_reg_config(box, 0));
+
+       wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static void snbep_uncore_msr_disable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       wrmsrl(hwc->config_base, hwc->config);
+}
+
+static void snbep_uncore_msr_init_box(struct intel_uncore_box *box)
+{
+       unsigned msr = uncore_msr_box_ctl(box);
+
+       if (msr)
+               wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT);
+}
+
+static struct attribute *snbep_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_ubox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_cbox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_filter_tid.attr,
+       &format_attr_filter_nid.attr,
+       &format_attr_filter_state.attr,
+       &format_attr_filter_opc.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_pcu_formats_attr[] = {
+       &format_attr_event_ext.attr,
+       &format_attr_occ_sel.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       &format_attr_occ_invert.attr,
+       &format_attr_occ_edge.attr,
+       &format_attr_filter_band0.attr,
+       &format_attr_filter_band1.attr,
+       &format_attr_filter_band2.attr,
+       &format_attr_filter_band3.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_qpi_formats_attr[] = {
+       &format_attr_event_ext.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_match_rds.attr,
+       &format_attr_match_rnid30.attr,
+       &format_attr_match_rnid4.attr,
+       &format_attr_match_dnid.attr,
+       &format_attr_match_mc.attr,
+       &format_attr_match_opc.attr,
+       &format_attr_match_vnw.attr,
+       &format_attr_match0.attr,
+       &format_attr_match1.attr,
+       &format_attr_mask_rds.attr,
+       &format_attr_mask_rnid30.attr,
+       &format_attr_mask_rnid4.attr,
+       &format_attr_mask_dnid.attr,
+       &format_attr_mask_mc.attr,
+       &format_attr_mask_opc.attr,
+       &format_attr_mask_vnw.attr,
+       &format_attr_mask0.attr,
+       &format_attr_mask1.attr,
+       NULL,
+};
+
+static struct uncore_event_desc snbep_uncore_imc_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,      "event=0xff,umask=0x00"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read,  "event=0x04,umask=0x03"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read.unit, "MiB"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write.unit, "MiB"),
+       { /* end: all zeroes */ },
+};
+
+static struct uncore_event_desc snbep_uncore_qpi_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,       "event=0x14"),
+       INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
+       INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x102,umask=0x08"),
+       INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x103,umask=0x04"),
+       { /* end: all zeroes */ },
+};
+
+static struct attribute_group snbep_uncore_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_ubox_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_ubox_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_cbox_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_cbox_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_pcu_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_pcu_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_qpi_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_qpi_formats_attr,
+};
+
+#define __SNBEP_UNCORE_MSR_OPS_COMMON_INIT()                   \
+       .disable_box    = snbep_uncore_msr_disable_box,         \
+       .enable_box     = snbep_uncore_msr_enable_box,          \
+       .disable_event  = snbep_uncore_msr_disable_event,       \
+       .enable_event   = snbep_uncore_msr_enable_event,        \
+       .read_counter   = uncore_msr_read_counter
+
+#define SNBEP_UNCORE_MSR_OPS_COMMON_INIT()                     \
+       __SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),                   \
+       .init_box       = snbep_uncore_msr_init_box             \
+
+static struct intel_uncore_ops snbep_uncore_msr_ops = {
+       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+};
+
+#define SNBEP_UNCORE_PCI_OPS_COMMON_INIT()                     \
+       .init_box       = snbep_uncore_pci_init_box,            \
+       .disable_box    = snbep_uncore_pci_disable_box,         \
+       .enable_box     = snbep_uncore_pci_enable_box,          \
+       .disable_event  = snbep_uncore_pci_disable_event,       \
+       .read_counter   = snbep_uncore_pci_read_counter
+
+static struct intel_uncore_ops snbep_uncore_pci_ops = {
+       SNBEP_UNCORE_PCI_OPS_COMMON_INIT(),
+       .enable_event   = snbep_uncore_pci_enable_event,        \
+};
+
+static struct event_constraint snbep_uncore_cbox_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x02, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x04, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x05, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x07, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x09, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x1b, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1c, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1d, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1e, 0xc),
+       EVENT_CONSTRAINT_OVERLAP(0x1f, 0xe, 0xff),
+       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint snbep_uncore_r2pcie_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint snbep_uncore_r3qpi_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2a, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2b, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x30, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type snbep_uncore_ubox = {
+       .name           = "ubox",
+       .num_counters   = 2,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .fixed_ctr_bits = 48,
+       .perf_ctr       = SNBEP_U_MSR_PMON_CTR0,
+       .event_ctl      = SNBEP_U_MSR_PMON_CTL0,
+       .event_mask     = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
+       .fixed_ctr      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
+       .fixed_ctl      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
+       .ops            = &snbep_uncore_msr_ops,
+       .format_group   = &snbep_uncore_ubox_format_group,
+};
+
+static struct extra_reg snbep_uncore_cbox_extra_regs[] = {
+       SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
+                                 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0xa),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0xa),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0xa),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0xa),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x2),
+       EVENT_EXTRA_END
+};
+
+static void snbep_cbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct intel_uncore_extra_reg *er = &box->shared_regs[0];
+       int i;
+
+       if (uncore_box_is_fake(box))
+               return;
+
+       for (i = 0; i < 5; i++) {
+               if (reg1->alloc & (0x1 << i))
+                       atomic_sub(1 << (i * 6), &er->ref);
+       }
+       reg1->alloc = 0;
+}
+
+static struct event_constraint *
+__snbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event,
+                           u64 (*cbox_filter_mask)(int fields))
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct intel_uncore_extra_reg *er = &box->shared_regs[0];
+       int i, alloc = 0;
+       unsigned long flags;
+       u64 mask;
+
+       if (reg1->idx == EXTRA_REG_NONE)
+               return NULL;
+
+       raw_spin_lock_irqsave(&er->lock, flags);
+       for (i = 0; i < 5; i++) {
+               if (!(reg1->idx & (0x1 << i)))
+                       continue;
+               if (!uncore_box_is_fake(box) && (reg1->alloc & (0x1 << i)))
+                       continue;
+
+               mask = cbox_filter_mask(0x1 << i);
+               if (!__BITS_VALUE(atomic_read(&er->ref), i, 6) ||
+                   !((reg1->config ^ er->config) & mask)) {
+                       atomic_add(1 << (i * 6), &er->ref);
+                       er->config &= ~mask;
+                       er->config |= reg1->config & mask;
+                       alloc |= (0x1 << i);
+               } else {
+                       break;
+               }
+       }
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+       if (i < 5)
+               goto fail;
+
+       if (!uncore_box_is_fake(box))
+               reg1->alloc |= alloc;
+
+       return NULL;
+fail:
+       for (; i >= 0; i--) {
+               if (alloc & (0x1 << i))
+                       atomic_sub(1 << (i * 6), &er->ref);
+       }
+       return &uncore_constraint_empty;
+}
+
+static u64 snbep_cbox_filter_mask(int fields)
+{
+       u64 mask = 0;
+
+       if (fields & 0x1)
+               mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_TID;
+       if (fields & 0x2)
+               mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_NID;
+       if (fields & 0x4)
+               mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_STATE;
+       if (fields & 0x8)
+               mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_OPC;
+
+       return mask;
+}
+
+static struct event_constraint *
+snbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       return __snbep_cbox_get_constraint(box, event, snbep_cbox_filter_mask);
+}
+
+static int snbep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct extra_reg *er;
+       int idx = 0;
+
+       for (er = snbep_uncore_cbox_extra_regs; er->msr; er++) {
+               if (er->event != (event->hw.config & er->config_mask))
+                       continue;
+               idx |= er->idx;
+       }
+
+       if (idx) {
+               reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
+                       SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
+               reg1->config = event->attr.config1 & snbep_cbox_filter_mask(idx);
+               reg1->idx = idx;
+       }
+       return 0;
+}
+
+static struct intel_uncore_ops snbep_uncore_cbox_ops = {
+       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+       .hw_config              = snbep_cbox_hw_config,
+       .get_constraint         = snbep_cbox_get_constraint,
+       .put_constraint         = snbep_cbox_put_constraint,
+};
+
+static struct intel_uncore_type snbep_uncore_cbox = {
+       .name                   = "cbox",
+       .num_counters           = 4,
+       .num_boxes              = 8,
+       .perf_ctr_bits          = 44,
+       .event_ctl              = SNBEP_C0_MSR_PMON_CTL0,
+       .perf_ctr               = SNBEP_C0_MSR_PMON_CTR0,
+       .event_mask             = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_C0_MSR_PMON_BOX_CTL,
+       .msr_offset             = SNBEP_CBO_MSR_OFFSET,
+       .num_shared_regs        = 1,
+       .constraints            = snbep_uncore_cbox_constraints,
+       .ops                    = &snbep_uncore_cbox_ops,
+       .format_group           = &snbep_uncore_cbox_format_group,
+};
+
+static u64 snbep_pcu_alter_er(struct perf_event *event, int new_idx, bool modify)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       u64 config = reg1->config;
+
+       if (new_idx > reg1->idx)
+               config <<= 8 * (new_idx - reg1->idx);
+       else
+               config >>= 8 * (reg1->idx - new_idx);
+
+       if (modify) {
+               hwc->config += new_idx - reg1->idx;
+               reg1->config = config;
+               reg1->idx = new_idx;
+       }
+       return config;
+}
+
+static struct event_constraint *
+snbep_pcu_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct intel_uncore_extra_reg *er = &box->shared_regs[0];
+       unsigned long flags;
+       int idx = reg1->idx;
+       u64 mask, config1 = reg1->config;
+       bool ok = false;
+
+       if (reg1->idx == EXTRA_REG_NONE ||
+           (!uncore_box_is_fake(box) && reg1->alloc))
+               return NULL;
+again:
+       mask = 0xffULL << (idx * 8);
+       raw_spin_lock_irqsave(&er->lock, flags);
+       if (!__BITS_VALUE(atomic_read(&er->ref), idx, 8) ||
+           !((config1 ^ er->config) & mask)) {
+               atomic_add(1 << (idx * 8), &er->ref);
+               er->config &= ~mask;
+               er->config |= config1 & mask;
+               ok = true;
+       }
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+
+       if (!ok) {
+               idx = (idx + 1) % 4;
+               if (idx != reg1->idx) {
+                       config1 = snbep_pcu_alter_er(event, idx, false);
+                       goto again;
+               }
+               return &uncore_constraint_empty;
+       }
+
+       if (!uncore_box_is_fake(box)) {
+               if (idx != reg1->idx)
+                       snbep_pcu_alter_er(event, idx, true);
+               reg1->alloc = 1;
+       }
+       return NULL;
+}
+
+static void snbep_pcu_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct intel_uncore_extra_reg *er = &box->shared_regs[0];
+
+       if (uncore_box_is_fake(box) || !reg1->alloc)
+               return;
+
+       atomic_sub(1 << (reg1->idx * 8), &er->ref);
+       reg1->alloc = 0;
+}
+
+static int snbep_pcu_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       int ev_sel = hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK;
+
+       if (ev_sel >= 0xb && ev_sel <= 0xe) {
+               reg1->reg = SNBEP_PCU_MSR_PMON_BOX_FILTER;
+               reg1->idx = ev_sel - 0xb;
+               reg1->config = event->attr.config1 & (0xff << (reg1->idx * 8));
+       }
+       return 0;
+}
+
+static struct intel_uncore_ops snbep_uncore_pcu_ops = {
+       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+       .hw_config              = snbep_pcu_hw_config,
+       .get_constraint         = snbep_pcu_get_constraint,
+       .put_constraint         = snbep_pcu_put_constraint,
+};
+
+static struct intel_uncore_type snbep_uncore_pcu = {
+       .name                   = "pcu",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCU_MSR_PMON_CTR0,
+       .event_ctl              = SNBEP_PCU_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCU_MSR_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &snbep_uncore_pcu_ops,
+       .format_group           = &snbep_uncore_pcu_format_group,
+};
+
+static struct intel_uncore_type *snbep_msr_uncores[] = {
+       &snbep_uncore_ubox,
+       &snbep_uncore_cbox,
+       &snbep_uncore_pcu,
+       NULL,
+};
+
+void snbep_uncore_cpu_init(void)
+{
+       if (snbep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
+               snbep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
+       uncore_msr_uncores = snbep_msr_uncores;
+}
+
+enum {
+       SNBEP_PCI_QPI_PORT0_FILTER,
+       SNBEP_PCI_QPI_PORT1_FILTER,
+       HSWEP_PCI_PCU_3,
+};
+
+static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+
+       if ((hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK) == 0x38) {
+               reg1->idx = 0;
+               reg1->reg = SNBEP_Q_Py_PCI_PMON_PKT_MATCH0;
+               reg1->config = event->attr.config1;
+               reg2->reg = SNBEP_Q_Py_PCI_PMON_PKT_MASK0;
+               reg2->config = event->attr.config2;
+       }
+       return 0;
+}
+
+static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
+
+       if (reg1->idx != EXTRA_REG_NONE) {
+               int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER;
+               int pkg = topology_phys_to_logical_pkg(box->pci_phys_id);
+               struct pci_dev *filter_pdev = uncore_extra_pci_dev[pkg].dev[idx];
+
+               if (filter_pdev) {
+                       pci_write_config_dword(filter_pdev, reg1->reg,
+                                               (u32)reg1->config);
+                       pci_write_config_dword(filter_pdev, reg1->reg + 4,
+                                               (u32)(reg1->config >> 32));
+                       pci_write_config_dword(filter_pdev, reg2->reg,
+                                               (u32)reg2->config);
+                       pci_write_config_dword(filter_pdev, reg2->reg + 4,
+                                               (u32)(reg2->config >> 32));
+               }
+       }
+
+       pci_write_config_dword(pdev, hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static struct intel_uncore_ops snbep_uncore_qpi_ops = {
+       SNBEP_UNCORE_PCI_OPS_COMMON_INIT(),
+       .enable_event           = snbep_qpi_enable_event,
+       .hw_config              = snbep_qpi_hw_config,
+       .get_constraint         = uncore_get_constraint,
+       .put_constraint         = uncore_put_constraint,
+};
+
+#define SNBEP_UNCORE_PCI_COMMON_INIT()                         \
+       .perf_ctr       = SNBEP_PCI_PMON_CTR0,                  \
+       .event_ctl      = SNBEP_PCI_PMON_CTL0,                  \
+       .event_mask     = SNBEP_PMON_RAW_EVENT_MASK,            \
+       .box_ctl        = SNBEP_PCI_PMON_BOX_CTL,               \
+       .ops            = &snbep_uncore_pci_ops,                \
+       .format_group   = &snbep_uncore_format_group
+
+static struct intel_uncore_type snbep_uncore_ha = {
+       .name           = "ha",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_imc = {
+       .name           = "imc",
+       .num_counters   = 4,
+       .num_boxes      = 4,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
+       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
+       .event_descs    = snbep_uncore_imc_events,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_qpi = {
+       .name                   = "qpi",
+       .num_counters           = 4,
+       .num_boxes              = 2,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
+       .event_ctl              = SNBEP_PCI_PMON_CTL0,
+       .event_mask             = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &snbep_uncore_qpi_ops,
+       .event_descs            = snbep_uncore_qpi_events,
+       .format_group           = &snbep_uncore_qpi_format_group,
+};
+
+
+static struct intel_uncore_type snbep_uncore_r2pcie = {
+       .name           = "r2pcie",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .constraints    = snbep_uncore_r2pcie_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_r3qpi = {
+       .name           = "r3qpi",
+       .num_counters   = 3,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 44,
+       .constraints    = snbep_uncore_r3qpi_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+enum {
+       SNBEP_PCI_UNCORE_HA,
+       SNBEP_PCI_UNCORE_IMC,
+       SNBEP_PCI_UNCORE_QPI,
+       SNBEP_PCI_UNCORE_R2PCIE,
+       SNBEP_PCI_UNCORE_R3QPI,
+};
+
+static struct intel_uncore_type *snbep_pci_uncores[] = {
+       [SNBEP_PCI_UNCORE_HA]           = &snbep_uncore_ha,
+       [SNBEP_PCI_UNCORE_IMC]          = &snbep_uncore_imc,
+       [SNBEP_PCI_UNCORE_QPI]          = &snbep_uncore_qpi,
+       [SNBEP_PCI_UNCORE_R2PCIE]       = &snbep_uncore_r2pcie,
+       [SNBEP_PCI_UNCORE_R3QPI]        = &snbep_uncore_r3qpi,
+       NULL,
+};
+
+static const struct pci_device_id snbep_uncore_pci_ids[] = {
+       { /* Home Agent */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_HA, 0),
+       },
+       { /* MC Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC0),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 0),
+       },
+       { /* MC Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC1),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 1),
+       },
+       { /* MC Channel 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC2),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 2),
+       },
+       { /* MC Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC3),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 3),
+       },
+       { /* QPI Port 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI0),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_QPI, 0),
+       },
+       { /* QPI Port 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI1),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_QPI, 1),
+       },
+       { /* R2PCIe */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R2PCIE),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R2PCIE, 0),
+       },
+       { /* R3QPI Link 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI0),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R3QPI, 0),
+       },
+       { /* R3QPI Link 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI1),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R3QPI, 1),
+       },
+       { /* QPI Port 0 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3c86),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+                                                  SNBEP_PCI_QPI_PORT0_FILTER),
+       },
+       { /* QPI Port 0 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3c96),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+                                                  SNBEP_PCI_QPI_PORT1_FILTER),
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_driver snbep_uncore_pci_driver = {
+       .name           = "snbep_uncore",
+       .id_table       = snbep_uncore_pci_ids,
+};
+
+/*
+ * build pci bus to socket mapping
+ */
+static int snbep_pci2phy_map_init(int devid)
+{
+       struct pci_dev *ubox_dev = NULL;
+       int i, bus, nodeid, segment;
+       struct pci2phy_map *map;
+       int err = 0;
+       u32 config = 0;
+
+       while (1) {
+               /* find the UBOX device */
+               ubox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, ubox_dev);
+               if (!ubox_dev)
+                       break;
+               bus = ubox_dev->bus->number;
+               /* get the Node ID of the local register */
+               err = pci_read_config_dword(ubox_dev, 0x40, &config);
+               if (err)
+                       break;
+               nodeid = config;
+               /* get the Node ID mapping */
+               err = pci_read_config_dword(ubox_dev, 0x54, &config);
+               if (err)
+                       break;
+
+               segment = pci_domain_nr(ubox_dev->bus);
+               raw_spin_lock(&pci2phy_map_lock);
+               map = __find_pci2phy_map(segment);
+               if (!map) {
+                       raw_spin_unlock(&pci2phy_map_lock);
+                       err = -ENOMEM;
+                       break;
+               }
+
+               /*
+                * every three bits in the Node ID mapping register maps
+                * to a particular node.
+                */
+               for (i = 0; i < 8; i++) {
+                       if (nodeid == ((config >> (3 * i)) & 0x7)) {
+                               map->pbus_to_physid[bus] = i;
+                               break;
+                       }
+               }
+               raw_spin_unlock(&pci2phy_map_lock);
+       }
+
+       if (!err) {
+               /*
+                * For PCI bus with no UBOX device, find the next bus
+                * that has UBOX device and use its mapping.
+                */
+               raw_spin_lock(&pci2phy_map_lock);
+               list_for_each_entry(map, &pci2phy_map_head, list) {
+                       i = -1;
+                       for (bus = 255; bus >= 0; bus--) {
+                               if (map->pbus_to_physid[bus] >= 0)
+                                       i = map->pbus_to_physid[bus];
+                               else
+                                       map->pbus_to_physid[bus] = i;
+                       }
+               }
+               raw_spin_unlock(&pci2phy_map_lock);
+       }
+
+       pci_dev_put(ubox_dev);
+
+       return err ? pcibios_err_to_errno(err) : 0;
+}
+
+int snbep_uncore_pci_init(void)
+{
+       int ret = snbep_pci2phy_map_init(0x3ce0);
+       if (ret)
+               return ret;
+       uncore_pci_uncores = snbep_pci_uncores;
+       uncore_pci_driver = &snbep_uncore_pci_driver;
+       return 0;
+}
+/* end of Sandy Bridge-EP uncore support */
+
+/* IvyTown uncore support */
+static void ivbep_uncore_msr_init_box(struct intel_uncore_box *box)
+{
+       unsigned msr = uncore_msr_box_ctl(box);
+       if (msr)
+               wrmsrl(msr, IVBEP_PMON_BOX_CTL_INT);
+}
+
+static void ivbep_uncore_pci_init_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+
+       pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL, IVBEP_PMON_BOX_CTL_INT);
+}
+
+#define IVBEP_UNCORE_MSR_OPS_COMMON_INIT()                     \
+       .init_box       = ivbep_uncore_msr_init_box,            \
+       .disable_box    = snbep_uncore_msr_disable_box,         \
+       .enable_box     = snbep_uncore_msr_enable_box,          \
+       .disable_event  = snbep_uncore_msr_disable_event,       \
+       .enable_event   = snbep_uncore_msr_enable_event,        \
+       .read_counter   = uncore_msr_read_counter
+
+static struct intel_uncore_ops ivbep_uncore_msr_ops = {
+       IVBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+};
+
+static struct intel_uncore_ops ivbep_uncore_pci_ops = {
+       .init_box       = ivbep_uncore_pci_init_box,
+       .disable_box    = snbep_uncore_pci_disable_box,
+       .enable_box     = snbep_uncore_pci_enable_box,
+       .disable_event  = snbep_uncore_pci_disable_event,
+       .enable_event   = snbep_uncore_pci_enable_event,
+       .read_counter   = snbep_uncore_pci_read_counter,
+};
+
+#define IVBEP_UNCORE_PCI_COMMON_INIT()                         \
+       .perf_ctr       = SNBEP_PCI_PMON_CTR0,                  \
+       .event_ctl      = SNBEP_PCI_PMON_CTL0,                  \
+       .event_mask     = IVBEP_PMON_RAW_EVENT_MASK,            \
+       .box_ctl        = SNBEP_PCI_PMON_BOX_CTL,               \
+       .ops            = &ivbep_uncore_pci_ops,                        \
+       .format_group   = &ivbep_uncore_format_group
+
+static struct attribute *ivbep_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       NULL,
+};
+
+static struct attribute *ivbep_uncore_ubox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       NULL,
+};
+
+static struct attribute *ivbep_uncore_cbox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_filter_tid.attr,
+       &format_attr_filter_link.attr,
+       &format_attr_filter_state2.attr,
+       &format_attr_filter_nid2.attr,
+       &format_attr_filter_opc2.attr,
+       &format_attr_filter_nc.attr,
+       &format_attr_filter_c6.attr,
+       &format_attr_filter_isoc.attr,
+       NULL,
+};
+
+static struct attribute *ivbep_uncore_pcu_formats_attr[] = {
+       &format_attr_event_ext.attr,
+       &format_attr_occ_sel.attr,
+       &format_attr_edge.attr,
+       &format_attr_thresh5.attr,
+       &format_attr_occ_invert.attr,
+       &format_attr_occ_edge.attr,
+       &format_attr_filter_band0.attr,
+       &format_attr_filter_band1.attr,
+       &format_attr_filter_band2.attr,
+       &format_attr_filter_band3.attr,
+       NULL,
+};
+
+static struct attribute *ivbep_uncore_qpi_formats_attr[] = {
+       &format_attr_event_ext.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_match_rds.attr,
+       &format_attr_match_rnid30.attr,
+       &format_attr_match_rnid4.attr,
+       &format_attr_match_dnid.attr,
+       &format_attr_match_mc.attr,
+       &format_attr_match_opc.attr,
+       &format_attr_match_vnw.attr,
+       &format_attr_match0.attr,
+       &format_attr_match1.attr,
+       &format_attr_mask_rds.attr,
+       &format_attr_mask_rnid30.attr,
+       &format_attr_mask_rnid4.attr,
+       &format_attr_mask_dnid.attr,
+       &format_attr_mask_mc.attr,
+       &format_attr_mask_opc.attr,
+       &format_attr_mask_vnw.attr,
+       &format_attr_mask0.attr,
+       &format_attr_mask1.attr,
+       NULL,
+};
+
+static struct attribute_group ivbep_uncore_format_group = {
+       .name = "format",
+       .attrs = ivbep_uncore_formats_attr,
+};
+
+static struct attribute_group ivbep_uncore_ubox_format_group = {
+       .name = "format",
+       .attrs = ivbep_uncore_ubox_formats_attr,
+};
+
+static struct attribute_group ivbep_uncore_cbox_format_group = {
+       .name = "format",
+       .attrs = ivbep_uncore_cbox_formats_attr,
+};
+
+static struct attribute_group ivbep_uncore_pcu_format_group = {
+       .name = "format",
+       .attrs = ivbep_uncore_pcu_formats_attr,
+};
+
+static struct attribute_group ivbep_uncore_qpi_format_group = {
+       .name = "format",
+       .attrs = ivbep_uncore_qpi_formats_attr,
+};
+
+static struct intel_uncore_type ivbep_uncore_ubox = {
+       .name           = "ubox",
+       .num_counters   = 2,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .fixed_ctr_bits = 48,
+       .perf_ctr       = SNBEP_U_MSR_PMON_CTR0,
+       .event_ctl      = SNBEP_U_MSR_PMON_CTL0,
+       .event_mask     = IVBEP_U_MSR_PMON_RAW_EVENT_MASK,
+       .fixed_ctr      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
+       .fixed_ctl      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
+       .ops            = &ivbep_uncore_msr_ops,
+       .format_group   = &ivbep_uncore_ubox_format_group,
+};
+
+static struct extra_reg ivbep_uncore_cbox_extra_regs[] = {
+       SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
+                                 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2335, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0x18),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0x18),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x8135, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x8335, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2136, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2336, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0x18),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0x18),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x5036, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x8136, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x8336, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x8),
+       EVENT_EXTRA_END
+};
+
+static u64 ivbep_cbox_filter_mask(int fields)
+{
+       u64 mask = 0;
+
+       if (fields & 0x1)
+               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_TID;
+       if (fields & 0x2)
+               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_LINK;
+       if (fields & 0x4)
+               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_STATE;
+       if (fields & 0x8)
+               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_NID;
+       if (fields & 0x10) {
+               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_OPC;
+               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_NC;
+               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_C6;
+               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_ISOC;
+       }
+
+       return mask;
+}
+
+static struct event_constraint *
+ivbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       return __snbep_cbox_get_constraint(box, event, ivbep_cbox_filter_mask);
+}
+
+static int ivbep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct extra_reg *er;
+       int idx = 0;
+
+       for (er = ivbep_uncore_cbox_extra_regs; er->msr; er++) {
+               if (er->event != (event->hw.config & er->config_mask))
+                       continue;
+               idx |= er->idx;
+       }
+
+       if (idx) {
+               reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
+                       SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
+               reg1->config = event->attr.config1 & ivbep_cbox_filter_mask(idx);
+               reg1->idx = idx;
+       }
+       return 0;
+}
+
+static void ivbep_cbox_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+
+       if (reg1->idx != EXTRA_REG_NONE) {
+               u64 filter = uncore_shared_reg_config(box, 0);
+               wrmsrl(reg1->reg, filter & 0xffffffff);
+               wrmsrl(reg1->reg + 6, filter >> 32);
+       }
+
+       wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static struct intel_uncore_ops ivbep_uncore_cbox_ops = {
+       .init_box               = ivbep_uncore_msr_init_box,
+       .disable_box            = snbep_uncore_msr_disable_box,
+       .enable_box             = snbep_uncore_msr_enable_box,
+       .disable_event          = snbep_uncore_msr_disable_event,
+       .enable_event           = ivbep_cbox_enable_event,
+       .read_counter           = uncore_msr_read_counter,
+       .hw_config              = ivbep_cbox_hw_config,
+       .get_constraint         = ivbep_cbox_get_constraint,
+       .put_constraint         = snbep_cbox_put_constraint,
+};
+
+static struct intel_uncore_type ivbep_uncore_cbox = {
+       .name                   = "cbox",
+       .num_counters           = 4,
+       .num_boxes              = 15,
+       .perf_ctr_bits          = 44,
+       .event_ctl              = SNBEP_C0_MSR_PMON_CTL0,
+       .perf_ctr               = SNBEP_C0_MSR_PMON_CTR0,
+       .event_mask             = IVBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_C0_MSR_PMON_BOX_CTL,
+       .msr_offset             = SNBEP_CBO_MSR_OFFSET,
+       .num_shared_regs        = 1,
+       .constraints            = snbep_uncore_cbox_constraints,
+       .ops                    = &ivbep_uncore_cbox_ops,
+       .format_group           = &ivbep_uncore_cbox_format_group,
+};
+
+static struct intel_uncore_ops ivbep_uncore_pcu_ops = {
+       IVBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+       .hw_config              = snbep_pcu_hw_config,
+       .get_constraint         = snbep_pcu_get_constraint,
+       .put_constraint         = snbep_pcu_put_constraint,
+};
+
+static struct intel_uncore_type ivbep_uncore_pcu = {
+       .name                   = "pcu",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCU_MSR_PMON_CTR0,
+       .event_ctl              = SNBEP_PCU_MSR_PMON_CTL0,
+       .event_mask             = IVBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCU_MSR_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &ivbep_uncore_pcu_ops,
+       .format_group           = &ivbep_uncore_pcu_format_group,
+};
+
+static struct intel_uncore_type *ivbep_msr_uncores[] = {
+       &ivbep_uncore_ubox,
+       &ivbep_uncore_cbox,
+       &ivbep_uncore_pcu,
+       NULL,
+};
+
+void ivbep_uncore_cpu_init(void)
+{
+       if (ivbep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
+               ivbep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
+       uncore_msr_uncores = ivbep_msr_uncores;
+}
+
+static struct intel_uncore_type ivbep_uncore_ha = {
+       .name           = "ha",
+       .num_counters   = 4,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 48,
+       IVBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type ivbep_uncore_imc = {
+       .name           = "imc",
+       .num_counters   = 4,
+       .num_boxes      = 8,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
+       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
+       .event_descs    = snbep_uncore_imc_events,
+       IVBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+/* registers in IRP boxes are not properly aligned */
+static unsigned ivbep_uncore_irp_ctls[] = {0xd8, 0xdc, 0xe0, 0xe4};
+static unsigned ivbep_uncore_irp_ctrs[] = {0xa0, 0xb0, 0xb8, 0xc0};
+
+static void ivbep_uncore_irp_enable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       pci_write_config_dword(pdev, ivbep_uncore_irp_ctls[hwc->idx],
+                              hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static void ivbep_uncore_irp_disable_event(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       pci_write_config_dword(pdev, ivbep_uncore_irp_ctls[hwc->idx], hwc->config);
+}
+
+static u64 ivbep_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+       u64 count = 0;
+
+       pci_read_config_dword(pdev, ivbep_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
+       pci_read_config_dword(pdev, ivbep_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
+
+       return count;
+}
+
+static struct intel_uncore_ops ivbep_uncore_irp_ops = {
+       .init_box       = ivbep_uncore_pci_init_box,
+       .disable_box    = snbep_uncore_pci_disable_box,
+       .enable_box     = snbep_uncore_pci_enable_box,
+       .disable_event  = ivbep_uncore_irp_disable_event,
+       .enable_event   = ivbep_uncore_irp_enable_event,
+       .read_counter   = ivbep_uncore_irp_read_counter,
+};
+
+static struct intel_uncore_type ivbep_uncore_irp = {
+       .name                   = "irp",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .event_mask             = IVBEP_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
+       .ops                    = &ivbep_uncore_irp_ops,
+       .format_group           = &ivbep_uncore_format_group,
+};
+
+static struct intel_uncore_ops ivbep_uncore_qpi_ops = {
+       .init_box       = ivbep_uncore_pci_init_box,
+       .disable_box    = snbep_uncore_pci_disable_box,
+       .enable_box     = snbep_uncore_pci_enable_box,
+       .disable_event  = snbep_uncore_pci_disable_event,
+       .enable_event   = snbep_qpi_enable_event,
+       .read_counter   = snbep_uncore_pci_read_counter,
+       .hw_config      = snbep_qpi_hw_config,
+       .get_constraint = uncore_get_constraint,
+       .put_constraint = uncore_put_constraint,
+};
+
+static struct intel_uncore_type ivbep_uncore_qpi = {
+       .name                   = "qpi",
+       .num_counters           = 4,
+       .num_boxes              = 3,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
+       .event_ctl              = SNBEP_PCI_PMON_CTL0,
+       .event_mask             = IVBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &ivbep_uncore_qpi_ops,
+       .format_group           = &ivbep_uncore_qpi_format_group,
+};
+
+static struct intel_uncore_type ivbep_uncore_r2pcie = {
+       .name           = "r2pcie",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .constraints    = snbep_uncore_r2pcie_constraints,
+       IVBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type ivbep_uncore_r3qpi = {
+       .name           = "r3qpi",
+       .num_counters   = 3,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 44,
+       .constraints    = snbep_uncore_r3qpi_constraints,
+       IVBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+enum {
+       IVBEP_PCI_UNCORE_HA,
+       IVBEP_PCI_UNCORE_IMC,
+       IVBEP_PCI_UNCORE_IRP,
+       IVBEP_PCI_UNCORE_QPI,
+       IVBEP_PCI_UNCORE_R2PCIE,
+       IVBEP_PCI_UNCORE_R3QPI,
+};
+
+static struct intel_uncore_type *ivbep_pci_uncores[] = {
+       [IVBEP_PCI_UNCORE_HA]   = &ivbep_uncore_ha,
+       [IVBEP_PCI_UNCORE_IMC]  = &ivbep_uncore_imc,
+       [IVBEP_PCI_UNCORE_IRP]  = &ivbep_uncore_irp,
+       [IVBEP_PCI_UNCORE_QPI]  = &ivbep_uncore_qpi,
+       [IVBEP_PCI_UNCORE_R2PCIE]       = &ivbep_uncore_r2pcie,
+       [IVBEP_PCI_UNCORE_R3QPI]        = &ivbep_uncore_r3qpi,
+       NULL,
+};
+
+static const struct pci_device_id ivbep_uncore_pci_ids[] = {
+       { /* Home Agent 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe30),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_HA, 0),
+       },
+       { /* Home Agent 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe38),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_HA, 1),
+       },
+       { /* MC0 Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb4),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 0),
+       },
+       { /* MC0 Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb5),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 1),
+       },
+       { /* MC0 Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb0),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 2),
+       },
+       { /* MC0 Channel 4 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb1),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 3),
+       },
+       { /* MC1 Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef4),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 4),
+       },
+       { /* MC1 Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef5),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 5),
+       },
+       { /* MC1 Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef0),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 6),
+       },
+       { /* MC1 Channel 4 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 7),
+       },
+       { /* IRP */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe39),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IRP, 0),
+       },
+       { /* QPI0 Port 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 0),
+       },
+       { /* QPI0 Port 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe33),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 1),
+       },
+       { /* QPI1 Port 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3a),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 2),
+       },
+       { /* R2PCIe */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe34),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R2PCIE, 0),
+       },
+       { /* R3QPI0 Link 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe36),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 0),
+       },
+       { /* R3QPI0 Link 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe37),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 1),
+       },
+       { /* R3QPI1 Link 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e),
+               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 2),
+       },
+       { /* QPI Port 0 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe86),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+                                                  SNBEP_PCI_QPI_PORT0_FILTER),
+       },
+       { /* QPI Port 0 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe96),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+                                                  SNBEP_PCI_QPI_PORT1_FILTER),
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_driver ivbep_uncore_pci_driver = {
+       .name           = "ivbep_uncore",
+       .id_table       = ivbep_uncore_pci_ids,
+};
+
+int ivbep_uncore_pci_init(void)
+{
+       int ret = snbep_pci2phy_map_init(0x0e1e);
+       if (ret)
+               return ret;
+       uncore_pci_uncores = ivbep_pci_uncores;
+       uncore_pci_driver = &ivbep_uncore_pci_driver;
+       return 0;
+}
+/* end of IvyTown uncore support */
+
+/* KNL uncore support */
+static struct attribute *knl_uncore_ubox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       NULL,
+};
+
+static struct attribute_group knl_uncore_ubox_format_group = {
+       .name = "format",
+       .attrs = knl_uncore_ubox_formats_attr,
+};
+
+static struct intel_uncore_type knl_uncore_ubox = {
+       .name                   = "ubox",
+       .num_counters           = 2,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .fixed_ctr_bits         = 48,
+       .perf_ctr               = HSWEP_U_MSR_PMON_CTR0,
+       .event_ctl              = HSWEP_U_MSR_PMON_CTL0,
+       .event_mask             = KNL_U_MSR_PMON_RAW_EVENT_MASK,
+       .fixed_ctr              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
+       .fixed_ctl              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
+       .ops                    = &snbep_uncore_msr_ops,
+       .format_group           = &knl_uncore_ubox_format_group,
+};
+
+static struct attribute *knl_uncore_cha_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_qor.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_filter_tid4.attr,
+       &format_attr_filter_link3.attr,
+       &format_attr_filter_state4.attr,
+       &format_attr_filter_local.attr,
+       &format_attr_filter_all_op.attr,
+       &format_attr_filter_nnm.attr,
+       &format_attr_filter_opc3.attr,
+       &format_attr_filter_nc.attr,
+       &format_attr_filter_isoc.attr,
+       NULL,
+};
+
+static struct attribute_group knl_uncore_cha_format_group = {
+       .name = "format",
+       .attrs = knl_uncore_cha_formats_attr,
+};
+
+static struct event_constraint knl_uncore_cha_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x1f, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct extra_reg knl_uncore_cha_extra_regs[] = {
+       SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
+                                 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x3d, 0xff, 0x2),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x35, 0xff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x36, 0xff, 0x4),
+       EVENT_EXTRA_END
+};
+
+static u64 knl_cha_filter_mask(int fields)
+{
+       u64 mask = 0;
+
+       if (fields & 0x1)
+               mask |= KNL_CHA_MSR_PMON_BOX_FILTER_TID;
+       if (fields & 0x2)
+               mask |= KNL_CHA_MSR_PMON_BOX_FILTER_STATE;
+       if (fields & 0x4)
+               mask |= KNL_CHA_MSR_PMON_BOX_FILTER_OP;
+       return mask;
+}
+
+static struct event_constraint *
+knl_cha_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       return __snbep_cbox_get_constraint(box, event, knl_cha_filter_mask);
+}
+
+static int knl_cha_hw_config(struct intel_uncore_box *box,
+                            struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct extra_reg *er;
+       int idx = 0;
+
+       for (er = knl_uncore_cha_extra_regs; er->msr; er++) {
+               if (er->event != (event->hw.config & er->config_mask))
+                       continue;
+               idx |= er->idx;
+       }
+
+       if (idx) {
+               reg1->reg = HSWEP_C0_MSR_PMON_BOX_FILTER0 +
+                           KNL_CHA_MSR_OFFSET * box->pmu->pmu_idx;
+               reg1->config = event->attr.config1 & knl_cha_filter_mask(idx);
+               reg1->idx = idx;
+       }
+       return 0;
+}
+
+static void hswep_cbox_enable_event(struct intel_uncore_box *box,
+                                   struct perf_event *event);
+
+static struct intel_uncore_ops knl_uncore_cha_ops = {
+       .init_box               = snbep_uncore_msr_init_box,
+       .disable_box            = snbep_uncore_msr_disable_box,
+       .enable_box             = snbep_uncore_msr_enable_box,
+       .disable_event          = snbep_uncore_msr_disable_event,
+       .enable_event           = hswep_cbox_enable_event,
+       .read_counter           = uncore_msr_read_counter,
+       .hw_config              = knl_cha_hw_config,
+       .get_constraint         = knl_cha_get_constraint,
+       .put_constraint         = snbep_cbox_put_constraint,
+};
+
+static struct intel_uncore_type knl_uncore_cha = {
+       .name                   = "cha",
+       .num_counters           = 4,
+       .num_boxes              = 38,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = HSWEP_C0_MSR_PMON_CTL0,
+       .perf_ctr               = HSWEP_C0_MSR_PMON_CTR0,
+       .event_mask             = KNL_CHA_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = HSWEP_C0_MSR_PMON_BOX_CTL,
+       .msr_offset             = KNL_CHA_MSR_OFFSET,
+       .num_shared_regs        = 1,
+       .constraints            = knl_uncore_cha_constraints,
+       .ops                    = &knl_uncore_cha_ops,
+       .format_group           = &knl_uncore_cha_format_group,
+};
+
+static struct attribute *knl_uncore_pcu_formats_attr[] = {
+       &format_attr_event2.attr,
+       &format_attr_use_occ_ctr.attr,
+       &format_attr_occ_sel.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh6.attr,
+       &format_attr_occ_invert.attr,
+       &format_attr_occ_edge_det.attr,
+       NULL,
+};
+
+static struct attribute_group knl_uncore_pcu_format_group = {
+       .name = "format",
+       .attrs = knl_uncore_pcu_formats_attr,
+};
+
+static struct intel_uncore_type knl_uncore_pcu = {
+       .name                   = "pcu",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = HSWEP_PCU_MSR_PMON_CTR0,
+       .event_ctl              = HSWEP_PCU_MSR_PMON_CTL0,
+       .event_mask             = KNL_PCU_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = HSWEP_PCU_MSR_PMON_BOX_CTL,
+       .ops                    = &snbep_uncore_msr_ops,
+       .format_group           = &knl_uncore_pcu_format_group,
+};
+
+static struct intel_uncore_type *knl_msr_uncores[] = {
+       &knl_uncore_ubox,
+       &knl_uncore_cha,
+       &knl_uncore_pcu,
+       NULL,
+};
+
+void knl_uncore_cpu_init(void)
+{
+       uncore_msr_uncores = knl_msr_uncores;
+}
+
+static void knl_uncore_imc_enable_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int box_ctl = uncore_pci_box_ctl(box);
+
+       pci_write_config_dword(pdev, box_ctl, 0);
+}
+
+static void knl_uncore_imc_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       if ((event->attr.config & SNBEP_PMON_CTL_EV_SEL_MASK)
+                                                       == UNCORE_FIXED_EVENT)
+               pci_write_config_dword(pdev, hwc->config_base,
+                                      hwc->config | KNL_PMON_FIXED_CTL_EN);
+       else
+               pci_write_config_dword(pdev, hwc->config_base,
+                                      hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static struct intel_uncore_ops knl_uncore_imc_ops = {
+       .init_box       = snbep_uncore_pci_init_box,
+       .disable_box    = snbep_uncore_pci_disable_box,
+       .enable_box     = knl_uncore_imc_enable_box,
+       .read_counter   = snbep_uncore_pci_read_counter,
+       .enable_event   = knl_uncore_imc_enable_event,
+       .disable_event  = snbep_uncore_pci_disable_event,
+};
+
+static struct intel_uncore_type knl_uncore_imc_uclk = {
+       .name                   = "imc_uclk",
+       .num_counters           = 4,
+       .num_boxes              = 2,
+       .perf_ctr_bits          = 48,
+       .fixed_ctr_bits         = 48,
+       .perf_ctr               = KNL_UCLK_MSR_PMON_CTR0_LOW,
+       .event_ctl              = KNL_UCLK_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
+       .fixed_ctr              = KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW,
+       .fixed_ctl              = KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL,
+       .box_ctl                = KNL_UCLK_MSR_PMON_BOX_CTL,
+       .ops                    = &knl_uncore_imc_ops,
+       .format_group           = &snbep_uncore_format_group,
+};
+
+static struct intel_uncore_type knl_uncore_imc_dclk = {
+       .name                   = "imc",
+       .num_counters           = 4,
+       .num_boxes              = 6,
+       .perf_ctr_bits          = 48,
+       .fixed_ctr_bits         = 48,
+       .perf_ctr               = KNL_MC0_CH0_MSR_PMON_CTR0_LOW,
+       .event_ctl              = KNL_MC0_CH0_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
+       .fixed_ctr              = KNL_MC0_CH0_MSR_PMON_FIXED_LOW,
+       .fixed_ctl              = KNL_MC0_CH0_MSR_PMON_FIXED_CTL,
+       .box_ctl                = KNL_MC0_CH0_MSR_PMON_BOX_CTL,
+       .ops                    = &knl_uncore_imc_ops,
+       .format_group           = &snbep_uncore_format_group,
+};
+
+static struct intel_uncore_type knl_uncore_edc_uclk = {
+       .name                   = "edc_uclk",
+       .num_counters           = 4,
+       .num_boxes              = 8,
+       .perf_ctr_bits          = 48,
+       .fixed_ctr_bits         = 48,
+       .perf_ctr               = KNL_UCLK_MSR_PMON_CTR0_LOW,
+       .event_ctl              = KNL_UCLK_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
+       .fixed_ctr              = KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW,
+       .fixed_ctl              = KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL,
+       .box_ctl                = KNL_UCLK_MSR_PMON_BOX_CTL,
+       .ops                    = &knl_uncore_imc_ops,
+       .format_group           = &snbep_uncore_format_group,
+};
+
+static struct intel_uncore_type knl_uncore_edc_eclk = {
+       .name                   = "edc_eclk",
+       .num_counters           = 4,
+       .num_boxes              = 8,
+       .perf_ctr_bits          = 48,
+       .fixed_ctr_bits         = 48,
+       .perf_ctr               = KNL_EDC0_ECLK_MSR_PMON_CTR0_LOW,
+       .event_ctl              = KNL_EDC0_ECLK_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
+       .fixed_ctr              = KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_LOW,
+       .fixed_ctl              = KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_CTL,
+       .box_ctl                = KNL_EDC0_ECLK_MSR_PMON_BOX_CTL,
+       .ops                    = &knl_uncore_imc_ops,
+       .format_group           = &snbep_uncore_format_group,
+};
+
+static struct event_constraint knl_uncore_m2pcie_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type knl_uncore_m2pcie = {
+       .name           = "m2pcie",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       .constraints    = knl_uncore_m2pcie_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct attribute *knl_uncore_irp_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_qor.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       NULL,
+};
+
+static struct attribute_group knl_uncore_irp_format_group = {
+       .name = "format",
+       .attrs = knl_uncore_irp_formats_attr,
+};
+
+static struct intel_uncore_type knl_uncore_irp = {
+       .name                   = "irp",
+       .num_counters           = 2,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
+       .event_ctl              = SNBEP_PCI_PMON_CTL0,
+       .event_mask             = KNL_IRP_PCI_PMON_RAW_EVENT_MASK,
+       .box_ctl                = KNL_IRP_PCI_PMON_BOX_CTL,
+       .ops                    = &snbep_uncore_pci_ops,
+       .format_group           = &knl_uncore_irp_format_group,
+};
+
+enum {
+       KNL_PCI_UNCORE_MC_UCLK,
+       KNL_PCI_UNCORE_MC_DCLK,
+       KNL_PCI_UNCORE_EDC_UCLK,
+       KNL_PCI_UNCORE_EDC_ECLK,
+       KNL_PCI_UNCORE_M2PCIE,
+       KNL_PCI_UNCORE_IRP,
+};
+
+static struct intel_uncore_type *knl_pci_uncores[] = {
+       [KNL_PCI_UNCORE_MC_UCLK]        = &knl_uncore_imc_uclk,
+       [KNL_PCI_UNCORE_MC_DCLK]        = &knl_uncore_imc_dclk,
+       [KNL_PCI_UNCORE_EDC_UCLK]       = &knl_uncore_edc_uclk,
+       [KNL_PCI_UNCORE_EDC_ECLK]       = &knl_uncore_edc_eclk,
+       [KNL_PCI_UNCORE_M2PCIE]         = &knl_uncore_m2pcie,
+       [KNL_PCI_UNCORE_IRP]            = &knl_uncore_irp,
+       NULL,
+};
+
+/*
+ * KNL uses a common PCI device ID for multiple instances of an Uncore PMU
+ * device type. prior to KNL, each instance of a PMU device type had a unique
+ * device ID.
+ *
+ *     PCI Device ID   Uncore PMU Devices
+ *     ----------------------------------
+ *     0x7841          MC0 UClk, MC1 UClk
+ *     0x7843          MC0 DClk CH 0, MC0 DClk CH 1, MC0 DClk CH 2,
+ *                     MC1 DClk CH 0, MC1 DClk CH 1, MC1 DClk CH 2
+ *     0x7833          EDC0 UClk, EDC1 UClk, EDC2 UClk, EDC3 UClk,
+ *                     EDC4 UClk, EDC5 UClk, EDC6 UClk, EDC7 UClk
+ *     0x7835          EDC0 EClk, EDC1 EClk, EDC2 EClk, EDC3 EClk,
+ *                     EDC4 EClk, EDC5 EClk, EDC6 EClk, EDC7 EClk
+ *     0x7817          M2PCIe
+ *     0x7814          IRP
+*/
+
+static const struct pci_device_id knl_uncore_pci_ids[] = {
+       { /* MC UClk */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7841),
+               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_MC_UCLK, 0),
+       },
+       { /* MC DClk Channel */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7843),
+               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_MC_DCLK, 0),
+       },
+       { /* EDC UClk */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7833),
+               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_EDC_UCLK, 0),
+       },
+       { /* EDC EClk */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7835),
+               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_EDC_ECLK, 0),
+       },
+       { /* M2PCIe */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7817),
+               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_M2PCIE, 0),
+       },
+       { /* IRP */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7814),
+               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_IRP, 0),
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_driver knl_uncore_pci_driver = {
+       .name           = "knl_uncore",
+       .id_table       = knl_uncore_pci_ids,
+};
+
+int knl_uncore_pci_init(void)
+{
+       int ret;
+
+       /* All KNL PCI based PMON units are on the same PCI bus except IRP */
+       ret = snb_pci2phy_map_init(0x7814); /* IRP */
+       if (ret)
+               return ret;
+       ret = snb_pci2phy_map_init(0x7817); /* M2PCIe */
+       if (ret)
+               return ret;
+       uncore_pci_uncores = knl_pci_uncores;
+       uncore_pci_driver = &knl_uncore_pci_driver;
+       return 0;
+}
+
+/* end of KNL uncore support */
+
+/* Haswell-EP uncore support */
+static struct attribute *hswep_uncore_ubox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       &format_attr_filter_tid2.attr,
+       &format_attr_filter_cid.attr,
+       NULL,
+};
+
+static struct attribute_group hswep_uncore_ubox_format_group = {
+       .name = "format",
+       .attrs = hswep_uncore_ubox_formats_attr,
+};
+
+static int hswep_ubox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       reg1->reg = HSWEP_U_MSR_PMON_FILTER;
+       reg1->config = event->attr.config1 & HSWEP_U_MSR_PMON_BOX_FILTER_MASK;
+       reg1->idx = 0;
+       return 0;
+}
+
+static struct intel_uncore_ops hswep_uncore_ubox_ops = {
+       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+       .hw_config              = hswep_ubox_hw_config,
+       .get_constraint         = uncore_get_constraint,
+       .put_constraint         = uncore_put_constraint,
+};
+
+static struct intel_uncore_type hswep_uncore_ubox = {
+       .name                   = "ubox",
+       .num_counters           = 2,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 44,
+       .fixed_ctr_bits         = 48,
+       .perf_ctr               = HSWEP_U_MSR_PMON_CTR0,
+       .event_ctl              = HSWEP_U_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
+       .fixed_ctr              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
+       .fixed_ctl              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &hswep_uncore_ubox_ops,
+       .format_group           = &hswep_uncore_ubox_format_group,
+};
+
+static struct attribute *hswep_uncore_cbox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_filter_tid3.attr,
+       &format_attr_filter_link2.attr,
+       &format_attr_filter_state3.attr,
+       &format_attr_filter_nid2.attr,
+       &format_attr_filter_opc2.attr,
+       &format_attr_filter_nc.attr,
+       &format_attr_filter_c6.attr,
+       &format_attr_filter_isoc.attr,
+       NULL,
+};
+
+static struct attribute_group hswep_uncore_cbox_format_group = {
+       .name = "format",
+       .attrs = hswep_uncore_cbox_formats_attr,
+};
+
+static struct event_constraint hswep_uncore_cbox_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x09, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x3e, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct extra_reg hswep_uncore_cbox_extra_regs[] = {
+       SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
+                                 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2134, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x4),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4028, 0x40ff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4032, 0x40ff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4029, 0x40ff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4033, 0x40ff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x402A, 0x40ff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x12),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0x18),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0x18),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2335, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x8335, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x8135, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0x18),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0x18),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x8),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2336, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x8336, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x2136, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x8136, 0xffff, 0x10),
+       SNBEP_CBO_EVENT_EXTRA_REG(0x5036, 0xffff, 0x8),
+       EVENT_EXTRA_END
+};
+
+static u64 hswep_cbox_filter_mask(int fields)
+{
+       u64 mask = 0;
+       if (fields & 0x1)
+               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_TID;
+       if (fields & 0x2)
+               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_LINK;
+       if (fields & 0x4)
+               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_STATE;
+       if (fields & 0x8)
+               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_NID;
+       if (fields & 0x10) {
+               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_OPC;
+               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_NC;
+               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_C6;
+               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_ISOC;
+       }
+       return mask;
+}
+
+static struct event_constraint *
+hswep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
+{
+       return __snbep_cbox_get_constraint(box, event, hswep_cbox_filter_mask);
+}
+
+static int hswep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       struct extra_reg *er;
+       int idx = 0;
+
+       for (er = hswep_uncore_cbox_extra_regs; er->msr; er++) {
+               if (er->event != (event->hw.config & er->config_mask))
+                       continue;
+               idx |= er->idx;
+       }
+
+       if (idx) {
+               reg1->reg = HSWEP_C0_MSR_PMON_BOX_FILTER0 +
+                           HSWEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
+               reg1->config = event->attr.config1 & hswep_cbox_filter_mask(idx);
+               reg1->idx = idx;
+       }
+       return 0;
+}
+
+static void hswep_cbox_enable_event(struct intel_uncore_box *box,
+                                 struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+
+       if (reg1->idx != EXTRA_REG_NONE) {
+               u64 filter = uncore_shared_reg_config(box, 0);
+               wrmsrl(reg1->reg, filter & 0xffffffff);
+               wrmsrl(reg1->reg + 1, filter >> 32);
+       }
+
+       wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static struct intel_uncore_ops hswep_uncore_cbox_ops = {
+       .init_box               = snbep_uncore_msr_init_box,
+       .disable_box            = snbep_uncore_msr_disable_box,
+       .enable_box             = snbep_uncore_msr_enable_box,
+       .disable_event          = snbep_uncore_msr_disable_event,
+       .enable_event           = hswep_cbox_enable_event,
+       .read_counter           = uncore_msr_read_counter,
+       .hw_config              = hswep_cbox_hw_config,
+       .get_constraint         = hswep_cbox_get_constraint,
+       .put_constraint         = snbep_cbox_put_constraint,
+};
+
+static struct intel_uncore_type hswep_uncore_cbox = {
+       .name                   = "cbox",
+       .num_counters           = 4,
+       .num_boxes              = 18,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = HSWEP_C0_MSR_PMON_CTL0,
+       .perf_ctr               = HSWEP_C0_MSR_PMON_CTR0,
+       .event_mask             = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = HSWEP_C0_MSR_PMON_BOX_CTL,
+       .msr_offset             = HSWEP_CBO_MSR_OFFSET,
+       .num_shared_regs        = 1,
+       .constraints            = hswep_uncore_cbox_constraints,
+       .ops                    = &hswep_uncore_cbox_ops,
+       .format_group           = &hswep_uncore_cbox_format_group,
+};
+
+/*
+ * Write SBOX Initialization register bit by bit to avoid spurious #GPs
+ */
+static void hswep_uncore_sbox_msr_init_box(struct intel_uncore_box *box)
+{
+       unsigned msr = uncore_msr_box_ctl(box);
+
+       if (msr) {
+               u64 init = SNBEP_PMON_BOX_CTL_INT;
+               u64 flags = 0;
+               int i;
+
+               for_each_set_bit(i, (unsigned long *)&init, 64) {
+                       flags |= (1ULL << i);
+                       wrmsrl(msr, flags);
+               }
+       }
+}
+
+static struct intel_uncore_ops hswep_uncore_sbox_msr_ops = {
+       __SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+       .init_box               = hswep_uncore_sbox_msr_init_box
+};
+
+static struct attribute *hswep_uncore_sbox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       NULL,
+};
+
+static struct attribute_group hswep_uncore_sbox_format_group = {
+       .name = "format",
+       .attrs = hswep_uncore_sbox_formats_attr,
+};
+
+static struct intel_uncore_type hswep_uncore_sbox = {
+       .name                   = "sbox",
+       .num_counters           = 4,
+       .num_boxes              = 4,
+       .perf_ctr_bits          = 44,
+       .event_ctl              = HSWEP_S0_MSR_PMON_CTL0,
+       .perf_ctr               = HSWEP_S0_MSR_PMON_CTR0,
+       .event_mask             = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = HSWEP_S0_MSR_PMON_BOX_CTL,
+       .msr_offset             = HSWEP_SBOX_MSR_OFFSET,
+       .ops                    = &hswep_uncore_sbox_msr_ops,
+       .format_group           = &hswep_uncore_sbox_format_group,
+};
+
+static int hswep_pcu_hw_config(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+       int ev_sel = hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK;
+
+       if (ev_sel >= 0xb && ev_sel <= 0xe) {
+               reg1->reg = HSWEP_PCU_MSR_PMON_BOX_FILTER;
+               reg1->idx = ev_sel - 0xb;
+               reg1->config = event->attr.config1 & (0xff << reg1->idx);
+       }
+       return 0;
+}
+
+static struct intel_uncore_ops hswep_uncore_pcu_ops = {
+       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
+       .hw_config              = hswep_pcu_hw_config,
+       .get_constraint         = snbep_pcu_get_constraint,
+       .put_constraint         = snbep_pcu_put_constraint,
+};
+
+static struct intel_uncore_type hswep_uncore_pcu = {
+       .name                   = "pcu",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = HSWEP_PCU_MSR_PMON_CTR0,
+       .event_ctl              = HSWEP_PCU_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = HSWEP_PCU_MSR_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &hswep_uncore_pcu_ops,
+       .format_group           = &snbep_uncore_pcu_format_group,
+};
+
+static struct intel_uncore_type *hswep_msr_uncores[] = {
+       &hswep_uncore_ubox,
+       &hswep_uncore_cbox,
+       &hswep_uncore_sbox,
+       &hswep_uncore_pcu,
+       NULL,
+};
+
+void hswep_uncore_cpu_init(void)
+{
+       int pkg = topology_phys_to_logical_pkg(0);
+
+       if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
+               hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
+
+       /* Detect 6-8 core systems with only two SBOXes */
+       if (uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]) {
+               u32 capid4;
+
+               pci_read_config_dword(uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3],
+                                     0x94, &capid4);
+               if (((capid4 >> 6) & 0x3) == 0)
+                       hswep_uncore_sbox.num_boxes = 2;
+       }
+
+       uncore_msr_uncores = hswep_msr_uncores;
+}
+
+static struct intel_uncore_type hswep_uncore_ha = {
+       .name           = "ha",
+       .num_counters   = 5,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 48,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct uncore_event_desc hswep_uncore_imc_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,      "event=0x00,umask=0x00"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read,  "event=0x04,umask=0x03"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read.unit, "MiB"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write.scale, "6.103515625e-5"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write.unit, "MiB"),
+       { /* end: all zeroes */ },
+};
+
+static struct intel_uncore_type hswep_uncore_imc = {
+       .name           = "imc",
+       .num_counters   = 5,
+       .num_boxes      = 8,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
+       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
+       .event_descs    = hswep_uncore_imc_events,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static unsigned hswep_uncore_irp_ctrs[] = {0xa0, 0xa8, 0xb0, 0xb8};
+
+static u64 hswep_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+       u64 count = 0;
+
+       pci_read_config_dword(pdev, hswep_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
+       pci_read_config_dword(pdev, hswep_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
+
+       return count;
+}
+
+static struct intel_uncore_ops hswep_uncore_irp_ops = {
+       .init_box       = snbep_uncore_pci_init_box,
+       .disable_box    = snbep_uncore_pci_disable_box,
+       .enable_box     = snbep_uncore_pci_enable_box,
+       .disable_event  = ivbep_uncore_irp_disable_event,
+       .enable_event   = ivbep_uncore_irp_enable_event,
+       .read_counter   = hswep_uncore_irp_read_counter,
+};
+
+static struct intel_uncore_type hswep_uncore_irp = {
+       .name                   = "irp",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
+       .ops                    = &hswep_uncore_irp_ops,
+       .format_group           = &snbep_uncore_format_group,
+};
+
+static struct intel_uncore_type hswep_uncore_qpi = {
+       .name                   = "qpi",
+       .num_counters           = 5,
+       .num_boxes              = 3,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
+       .event_ctl              = SNBEP_PCI_PMON_CTL0,
+       .event_mask             = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &snbep_uncore_qpi_ops,
+       .format_group           = &snbep_uncore_qpi_format_group,
+};
+
+static struct event_constraint hswep_uncore_r2pcie_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x24, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x27, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2a, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x2b, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type hswep_uncore_r2pcie = {
+       .name           = "r2pcie",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       .constraints    = hswep_uncore_r2pcie_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct event_constraint hswep_uncore_r3qpi_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x01, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x07, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x08, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x09, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x0a, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x0e, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x14, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x15, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x1f, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type hswep_uncore_r3qpi = {
+       .name           = "r3qpi",
+       .num_counters   = 4,
+       .num_boxes      = 3,
+       .perf_ctr_bits  = 44,
+       .constraints    = hswep_uncore_r3qpi_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+enum {
+       HSWEP_PCI_UNCORE_HA,
+       HSWEP_PCI_UNCORE_IMC,
+       HSWEP_PCI_UNCORE_IRP,
+       HSWEP_PCI_UNCORE_QPI,
+       HSWEP_PCI_UNCORE_R2PCIE,
+       HSWEP_PCI_UNCORE_R3QPI,
+};
+
+static struct intel_uncore_type *hswep_pci_uncores[] = {
+       [HSWEP_PCI_UNCORE_HA]   = &hswep_uncore_ha,
+       [HSWEP_PCI_UNCORE_IMC]  = &hswep_uncore_imc,
+       [HSWEP_PCI_UNCORE_IRP]  = &hswep_uncore_irp,
+       [HSWEP_PCI_UNCORE_QPI]  = &hswep_uncore_qpi,
+       [HSWEP_PCI_UNCORE_R2PCIE]       = &hswep_uncore_r2pcie,
+       [HSWEP_PCI_UNCORE_R3QPI]        = &hswep_uncore_r3qpi,
+       NULL,
+};
+
+static const struct pci_device_id hswep_uncore_pci_ids[] = {
+       { /* Home Agent 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f30),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_HA, 0),
+       },
+       { /* Home Agent 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f38),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_HA, 1),
+       },
+       { /* MC0 Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb0),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 0),
+       },
+       { /* MC0 Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb1),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 1),
+       },
+       { /* MC0 Channel 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb4),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 2),
+       },
+       { /* MC0 Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb5),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 3),
+       },
+       { /* MC1 Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd0),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 4),
+       },
+       { /* MC1 Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd1),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 5),
+       },
+       { /* MC1 Channel 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd4),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 6),
+       },
+       { /* MC1 Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd5),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 7),
+       },
+       { /* IRP */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f39),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IRP, 0),
+       },
+       { /* QPI0 Port 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f32),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 0),
+       },
+       { /* QPI0 Port 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f33),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 1),
+       },
+       { /* QPI1 Port 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f3a),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 2),
+       },
+       { /* R2PCIe */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f34),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R2PCIE, 0),
+       },
+       { /* R3QPI0 Link 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f36),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 0),
+       },
+       { /* R3QPI0 Link 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f37),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 1),
+       },
+       { /* R3QPI1 Link 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f3e),
+               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 2),
+       },
+       { /* QPI Port 0 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f86),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+                                                  SNBEP_PCI_QPI_PORT0_FILTER),
+       },
+       { /* QPI Port 1 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f96),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+                                                  SNBEP_PCI_QPI_PORT1_FILTER),
+       },
+       { /* PCU.3 (for Capability registers) */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fc0),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
+                                                  HSWEP_PCI_PCU_3),
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_driver hswep_uncore_pci_driver = {
+       .name           = "hswep_uncore",
+       .id_table       = hswep_uncore_pci_ids,
+};
+
+int hswep_uncore_pci_init(void)
+{
+       int ret = snbep_pci2phy_map_init(0x2f1e);
+       if (ret)
+               return ret;
+       uncore_pci_uncores = hswep_pci_uncores;
+       uncore_pci_driver = &hswep_uncore_pci_driver;
+       return 0;
+}
+/* end of Haswell-EP uncore support */
+
+/* BDX uncore support */
+
+static struct intel_uncore_type bdx_uncore_ubox = {
+       .name                   = "ubox",
+       .num_counters           = 2,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .fixed_ctr_bits         = 48,
+       .perf_ctr               = HSWEP_U_MSR_PMON_CTR0,
+       .event_ctl              = HSWEP_U_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
+       .fixed_ctr              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
+       .fixed_ctl              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &ivbep_uncore_msr_ops,
+       .format_group           = &ivbep_uncore_ubox_format_group,
+};
+
+static struct event_constraint bdx_uncore_cbox_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x09, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x3e, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type bdx_uncore_cbox = {
+       .name                   = "cbox",
+       .num_counters           = 4,
+       .num_boxes              = 24,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = HSWEP_C0_MSR_PMON_CTL0,
+       .perf_ctr               = HSWEP_C0_MSR_PMON_CTR0,
+       .event_mask             = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = HSWEP_C0_MSR_PMON_BOX_CTL,
+       .msr_offset             = HSWEP_CBO_MSR_OFFSET,
+       .num_shared_regs        = 1,
+       .constraints            = bdx_uncore_cbox_constraints,
+       .ops                    = &hswep_uncore_cbox_ops,
+       .format_group           = &hswep_uncore_cbox_format_group,
+};
+
+static struct intel_uncore_type bdx_uncore_sbox = {
+       .name                   = "sbox",
+       .num_counters           = 4,
+       .num_boxes              = 4,
+       .perf_ctr_bits          = 48,
+       .event_ctl              = HSWEP_S0_MSR_PMON_CTL0,
+       .perf_ctr               = HSWEP_S0_MSR_PMON_CTR0,
+       .event_mask             = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = HSWEP_S0_MSR_PMON_BOX_CTL,
+       .msr_offset             = HSWEP_SBOX_MSR_OFFSET,
+       .ops                    = &hswep_uncore_sbox_msr_ops,
+       .format_group           = &hswep_uncore_sbox_format_group,
+};
+
+#define BDX_MSR_UNCORE_SBOX    3
+
+static struct intel_uncore_type *bdx_msr_uncores[] = {
+       &bdx_uncore_ubox,
+       &bdx_uncore_cbox,
+       &hswep_uncore_pcu,
+       &bdx_uncore_sbox,
+       NULL,
+};
+
+void bdx_uncore_cpu_init(void)
+{
+       if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
+               bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
+       uncore_msr_uncores = bdx_msr_uncores;
+
+       /* BDX-DE doesn't have SBOX */
+       if (boot_cpu_data.x86_model == 86)
+               uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
+}
+
+static struct intel_uncore_type bdx_uncore_ha = {
+       .name           = "ha",
+       .num_counters   = 4,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 48,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type bdx_uncore_imc = {
+       .name           = "imc",
+       .num_counters   = 5,
+       .num_boxes      = 8,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
+       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
+       .event_descs    = hswep_uncore_imc_events,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type bdx_uncore_irp = {
+       .name                   = "irp",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
+       .ops                    = &hswep_uncore_irp_ops,
+       .format_group           = &snbep_uncore_format_group,
+};
+
+static struct intel_uncore_type bdx_uncore_qpi = {
+       .name                   = "qpi",
+       .num_counters           = 4,
+       .num_boxes              = 3,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
+       .event_ctl              = SNBEP_PCI_PMON_CTL0,
+       .event_mask             = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &snbep_uncore_qpi_ops,
+       .format_group           = &snbep_uncore_qpi_format_group,
+};
+
+static struct event_constraint bdx_uncore_r2pcie_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type bdx_uncore_r2pcie = {
+       .name           = "r2pcie",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       .constraints    = bdx_uncore_r2pcie_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct event_constraint bdx_uncore_r3qpi_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x01, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x07, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x08, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x09, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x0a, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x0e, 0x7),
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x14, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x15, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x1f, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type bdx_uncore_r3qpi = {
+       .name           = "r3qpi",
+       .num_counters   = 3,
+       .num_boxes      = 3,
+       .perf_ctr_bits  = 48,
+       .constraints    = bdx_uncore_r3qpi_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+enum {
+       BDX_PCI_UNCORE_HA,
+       BDX_PCI_UNCORE_IMC,
+       BDX_PCI_UNCORE_IRP,
+       BDX_PCI_UNCORE_QPI,
+       BDX_PCI_UNCORE_R2PCIE,
+       BDX_PCI_UNCORE_R3QPI,
+};
+
+static struct intel_uncore_type *bdx_pci_uncores[] = {
+       [BDX_PCI_UNCORE_HA]     = &bdx_uncore_ha,
+       [BDX_PCI_UNCORE_IMC]    = &bdx_uncore_imc,
+       [BDX_PCI_UNCORE_IRP]    = &bdx_uncore_irp,
+       [BDX_PCI_UNCORE_QPI]    = &bdx_uncore_qpi,
+       [BDX_PCI_UNCORE_R2PCIE] = &bdx_uncore_r2pcie,
+       [BDX_PCI_UNCORE_R3QPI]  = &bdx_uncore_r3qpi,
+       NULL,
+};
+
+static const struct pci_device_id bdx_uncore_pci_ids[] = {
+       { /* Home Agent 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f30),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_HA, 0),
+       },
+       { /* Home Agent 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f38),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_HA, 1),
+       },
+       { /* MC0 Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb0),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 0),
+       },
+       { /* MC0 Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb1),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 1),
+       },
+       { /* MC0 Channel 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb4),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 2),
+       },
+       { /* MC0 Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb5),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 3),
+       },
+       { /* MC1 Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd0),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 4),
+       },
+       { /* MC1 Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd1),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 5),
+       },
+       { /* MC1 Channel 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd4),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 6),
+       },
+       { /* MC1 Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd5),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 7),
+       },
+       { /* IRP */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f39),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IRP, 0),
+       },
+       { /* QPI0 Port 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f32),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 0),
+       },
+       { /* QPI0 Port 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f33),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 1),
+       },
+       { /* QPI1 Port 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f3a),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 2),
+       },
+       { /* R2PCIe */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f34),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R2PCIE, 0),
+       },
+       { /* R3QPI0 Link 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f36),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 0),
+       },
+       { /* R3QPI0 Link 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f37),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 1),
+       },
+       { /* R3QPI1 Link 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f3e),
+               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 2),
+       },
+       { /* QPI Port 0 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f86),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 0),
+       },
+       { /* QPI Port 1 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f96),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 1),
+       },
+       { /* QPI Port 2 filter  */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f46),
+               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 2),
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_driver bdx_uncore_pci_driver = {
+       .name           = "bdx_uncore",
+       .id_table       = bdx_uncore_pci_ids,
+};
+
+int bdx_uncore_pci_init(void)
+{
+       int ret = snbep_pci2phy_map_init(0x6f1e);
+
+       if (ret)
+               return ret;
+       uncore_pci_uncores = bdx_pci_uncores;
+       uncore_pci_driver = &bdx_uncore_pci_driver;
+       return 0;
+}
+
+/* end of BDX uncore support */
diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c
new file mode 100644 (file)
index 0000000..ec863b9
--- /dev/null
@@ -0,0 +1,241 @@
+#include <linux/perf_event.h>
+
+enum perf_msr_id {
+       PERF_MSR_TSC                    = 0,
+       PERF_MSR_APERF                  = 1,
+       PERF_MSR_MPERF                  = 2,
+       PERF_MSR_PPERF                  = 3,
+       PERF_MSR_SMI                    = 4,
+
+       PERF_MSR_EVENT_MAX,
+};
+
+static bool test_aperfmperf(int idx)
+{
+       return boot_cpu_has(X86_FEATURE_APERFMPERF);
+}
+
+static bool test_intel(int idx)
+{
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
+           boot_cpu_data.x86 != 6)
+               return false;
+
+       switch (boot_cpu_data.x86_model) {
+       case 30: /* 45nm Nehalem    */
+       case 26: /* 45nm Nehalem-EP */
+       case 46: /* 45nm Nehalem-EX */
+
+       case 37: /* 32nm Westmere    */
+       case 44: /* 32nm Westmere-EP */
+       case 47: /* 32nm Westmere-EX */
+
+       case 42: /* 32nm SandyBridge         */
+       case 45: /* 32nm SandyBridge-E/EN/EP */
+
+       case 58: /* 22nm IvyBridge       */
+       case 62: /* 22nm IvyBridge-EP/EX */
+
+       case 60: /* 22nm Haswell Core */
+       case 63: /* 22nm Haswell Server */
+       case 69: /* 22nm Haswell ULT */
+       case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
+
+       case 61: /* 14nm Broadwell Core-M */
+       case 86: /* 14nm Broadwell Xeon D */
+       case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
+       case 79: /* 14nm Broadwell Server */
+
+       case 55: /* 22nm Atom "Silvermont"                */
+       case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
+       case 76: /* 14nm Atom "Airmont"                   */
+               if (idx == PERF_MSR_SMI)
+                       return true;
+               break;
+
+       case 78: /* 14nm Skylake Mobile */
+       case 94: /* 14nm Skylake Desktop */
+               if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
+                       return true;
+               break;
+       }
+
+       return false;
+}
+
+struct perf_msr {
+       u64     msr;
+       struct  perf_pmu_events_attr *attr;
+       bool    (*test)(int idx);
+};
+
+PMU_EVENT_ATTR_STRING(tsc,   evattr_tsc,   "event=0x00");
+PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01");
+PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02");
+PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03");
+PMU_EVENT_ATTR_STRING(smi,   evattr_smi,   "event=0x04");
+
+static struct perf_msr msr[] = {
+       [PERF_MSR_TSC]   = { 0,                 &evattr_tsc,    NULL,            },
+       [PERF_MSR_APERF] = { MSR_IA32_APERF,    &evattr_aperf,  test_aperfmperf, },
+       [PERF_MSR_MPERF] = { MSR_IA32_MPERF,    &evattr_mperf,  test_aperfmperf, },
+       [PERF_MSR_PPERF] = { MSR_PPERF,         &evattr_pperf,  test_intel,      },
+       [PERF_MSR_SMI]   = { MSR_SMI_COUNT,     &evattr_smi,    test_intel,      },
+};
+
+static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
+       NULL,
+};
+
+static struct attribute_group events_attr_group = {
+       .name = "events",
+       .attrs = events_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-63");
+static struct attribute *format_attrs[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+static struct attribute_group format_attr_group = {
+       .name = "format",
+       .attrs = format_attrs,
+};
+
+static const struct attribute_group *attr_groups[] = {
+       &events_attr_group,
+       &format_attr_group,
+       NULL,
+};
+
+static int msr_event_init(struct perf_event *event)
+{
+       u64 cfg = event->attr.config;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       if (cfg >= PERF_MSR_EVENT_MAX)
+               return -EINVAL;
+
+       /* unsupported modes and filters */
+       if (event->attr.exclude_user   ||
+           event->attr.exclude_kernel ||
+           event->attr.exclude_hv     ||
+           event->attr.exclude_idle   ||
+           event->attr.exclude_host   ||
+           event->attr.exclude_guest  ||
+           event->attr.sample_period) /* no sampling */
+               return -EINVAL;
+
+       if (!msr[cfg].attr)
+               return -EINVAL;
+
+       event->hw.idx = -1;
+       event->hw.event_base = msr[cfg].msr;
+       event->hw.config = cfg;
+
+       return 0;
+}
+
+static inline u64 msr_read_counter(struct perf_event *event)
+{
+       u64 now;
+
+       if (event->hw.event_base)
+               rdmsrl(event->hw.event_base, now);
+       else
+               rdtscll(now);
+
+       return now;
+}
+static void msr_event_update(struct perf_event *event)
+{
+       u64 prev, now;
+       s64 delta;
+
+       /* Careful, an NMI might modify the previous event value. */
+again:
+       prev = local64_read(&event->hw.prev_count);
+       now = msr_read_counter(event);
+
+       if (local64_cmpxchg(&event->hw.prev_count, prev, now) != prev)
+               goto again;
+
+       delta = now - prev;
+       if (unlikely(event->hw.event_base == MSR_SMI_COUNT))
+               delta = sign_extend64(delta, 31);
+
+       local64_add(now - prev, &event->count);
+}
+
+static void msr_event_start(struct perf_event *event, int flags)
+{
+       u64 now;
+
+       now = msr_read_counter(event);
+       local64_set(&event->hw.prev_count, now);
+}
+
+static void msr_event_stop(struct perf_event *event, int flags)
+{
+       msr_event_update(event);
+}
+
+static void msr_event_del(struct perf_event *event, int flags)
+{
+       msr_event_stop(event, PERF_EF_UPDATE);
+}
+
+static int msr_event_add(struct perf_event *event, int flags)
+{
+       if (flags & PERF_EF_START)
+               msr_event_start(event, flags);
+
+       return 0;
+}
+
+static struct pmu pmu_msr = {
+       .task_ctx_nr    = perf_sw_context,
+       .attr_groups    = attr_groups,
+       .event_init     = msr_event_init,
+       .add            = msr_event_add,
+       .del            = msr_event_del,
+       .start          = msr_event_start,
+       .stop           = msr_event_stop,
+       .read           = msr_event_update,
+       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
+};
+
+static int __init msr_init(void)
+{
+       int i, j = 0;
+
+       if (!boot_cpu_has(X86_FEATURE_TSC)) {
+               pr_cont("no MSR PMU driver.\n");
+               return 0;
+       }
+
+       /* Probe the MSRs. */
+       for (i = PERF_MSR_TSC + 1; i < PERF_MSR_EVENT_MAX; i++) {
+               u64 val;
+
+               /*
+                * Virt sucks arse; you cannot tell if a R/O MSR is present :/
+                */
+               if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
+                       msr[i].attr = NULL;
+       }
+
+       /* List remaining MSRs in the sysfs attrs. */
+       for (i = 0; i < PERF_MSR_EVENT_MAX; i++) {
+               if (msr[i].attr)
+                       events_attrs[j++] = &msr[i].attr->attr.attr;
+       }
+       events_attrs[j] = NULL;
+
+       perf_pmu_register(&pmu_msr, "msr", -1);
+
+       return 0;
+}
+device_initcall(msr_init);
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
new file mode 100644 (file)
index 0000000..68155ca
--- /dev/null
@@ -0,0 +1,960 @@
+/*
+ * Performance events x86 architecture header
+ *
+ *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
+ *  Copyright (C) 2009 Jaswinder Singh Rajput
+ *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
+ *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
+ *  Copyright (C) 2009 Google, Inc., Stephane Eranian
+ *
+ *  For licencing details see kernel-base/COPYING
+ */
+
+#include <linux/perf_event.h>
+
+/* To enable MSR tracing please use the generic trace points. */
+
+/*
+ *          |   NHM/WSM    |      SNB     |
+ * register -------------------------------
+ *          |  HT  | no HT |  HT  | no HT |
+ *-----------------------------------------
+ * offcore  | core | core  | cpu  | core  |
+ * lbr_sel  | core | core  | cpu  | core  |
+ * ld_lat   | cpu  | core  | cpu  | core  |
+ *-----------------------------------------
+ *
+ * Given that there is a small number of shared regs,
+ * we can pre-allocate their slot in the per-cpu
+ * per-core reg tables.
+ */
+enum extra_reg_type {
+       EXTRA_REG_NONE  = -1,   /* not used */
+
+       EXTRA_REG_RSP_0 = 0,    /* offcore_response_0 */
+       EXTRA_REG_RSP_1 = 1,    /* offcore_response_1 */
+       EXTRA_REG_LBR   = 2,    /* lbr_select */
+       EXTRA_REG_LDLAT = 3,    /* ld_lat_threshold */
+       EXTRA_REG_FE    = 4,    /* fe_* */
+
+       EXTRA_REG_MAX           /* number of entries needed */
+};
+
+struct event_constraint {
+       union {
+               unsigned long   idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+               u64             idxmsk64;
+       };
+       u64     code;
+       u64     cmask;
+       int     weight;
+       int     overlap;
+       int     flags;
+};
+/*
+ * struct hw_perf_event.flags flags
+ */
+#define PERF_X86_EVENT_PEBS_LDLAT      0x0001 /* ld+ldlat data address sampling */
+#define PERF_X86_EVENT_PEBS_ST         0x0002 /* st data address sampling */
+#define PERF_X86_EVENT_PEBS_ST_HSW     0x0004 /* haswell style datala, store */
+#define PERF_X86_EVENT_COMMITTED       0x0008 /* event passed commit_txn */
+#define PERF_X86_EVENT_PEBS_LD_HSW     0x0010 /* haswell style datala, load */
+#define PERF_X86_EVENT_PEBS_NA_HSW     0x0020 /* haswell style datala, unknown */
+#define PERF_X86_EVENT_EXCL            0x0040 /* HT exclusivity on counter */
+#define PERF_X86_EVENT_DYNAMIC         0x0080 /* dynamic alloc'd constraint */
+#define PERF_X86_EVENT_RDPMC_ALLOWED   0x0100 /* grant rdpmc permission */
+#define PERF_X86_EVENT_EXCL_ACCT       0x0200 /* accounted EXCL event */
+#define PERF_X86_EVENT_AUTO_RELOAD     0x0400 /* use PEBS auto-reload */
+#define PERF_X86_EVENT_FREERUNNING     0x0800 /* use freerunning PEBS */
+
+
+struct amd_nb {
+       int nb_id;  /* NorthBridge id */
+       int refcnt; /* reference count */
+       struct perf_event *owners[X86_PMC_IDX_MAX];
+       struct event_constraint event_constraints[X86_PMC_IDX_MAX];
+};
+
+/* The maximal number of PEBS events: */
+#define MAX_PEBS_EVENTS                8
+
+/*
+ * Flags PEBS can handle without an PMI.
+ *
+ * TID can only be handled by flushing at context switch.
+ *
+ */
+#define PEBS_FREERUNNING_FLAGS \
+       (PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_ADDR | \
+       PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_STREAM_ID | \
+       PERF_SAMPLE_DATA_SRC | PERF_SAMPLE_IDENTIFIER | \
+       PERF_SAMPLE_TRANSACTION)
+
+/*
+ * A debug store configuration.
+ *
+ * We only support architectures that use 64bit fields.
+ */
+struct debug_store {
+       u64     bts_buffer_base;
+       u64     bts_index;
+       u64     bts_absolute_maximum;
+       u64     bts_interrupt_threshold;
+       u64     pebs_buffer_base;
+       u64     pebs_index;
+       u64     pebs_absolute_maximum;
+       u64     pebs_interrupt_threshold;
+       u64     pebs_event_reset[MAX_PEBS_EVENTS];
+};
+
+/*
+ * Per register state.
+ */
+struct er_account {
+       raw_spinlock_t          lock;   /* per-core: protect structure */
+       u64                 config;     /* extra MSR config */
+       u64                 reg;        /* extra MSR number */
+       atomic_t            ref;        /* reference count */
+};
+
+/*
+ * Per core/cpu state
+ *
+ * Used to coordinate shared registers between HT threads or
+ * among events on a single PMU.
+ */
+struct intel_shared_regs {
+       struct er_account       regs[EXTRA_REG_MAX];
+       int                     refcnt;         /* per-core: #HT threads */
+       unsigned                core_id;        /* per-core: core id */
+};
+
+enum intel_excl_state_type {
+       INTEL_EXCL_UNUSED    = 0, /* counter is unused */
+       INTEL_EXCL_SHARED    = 1, /* counter can be used by both threads */
+       INTEL_EXCL_EXCLUSIVE = 2, /* counter can be used by one thread only */
+};
+
+struct intel_excl_states {
+       enum intel_excl_state_type state[X86_PMC_IDX_MAX];
+       bool sched_started; /* true if scheduling has started */
+};
+
+struct intel_excl_cntrs {
+       raw_spinlock_t  lock;
+
+       struct intel_excl_states states[2];
+
+       union {
+               u16     has_exclusive[2];
+               u32     exclusive_present;
+       };
+
+       int             refcnt;         /* per-core: #HT threads */
+       unsigned        core_id;        /* per-core: core id */
+};
+
+#define MAX_LBR_ENTRIES                32
+
+enum {
+       X86_PERF_KFREE_SHARED = 0,
+       X86_PERF_KFREE_EXCL   = 1,
+       X86_PERF_KFREE_MAX
+};
+
+struct cpu_hw_events {
+       /*
+        * Generic x86 PMC bits
+        */
+       struct perf_event       *events[X86_PMC_IDX_MAX]; /* in counter order */
+       unsigned long           active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+       unsigned long           running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+       int                     enabled;
+
+       int                     n_events; /* the # of events in the below arrays */
+       int                     n_added;  /* the # last events in the below arrays;
+                                            they've never been enabled yet */
+       int                     n_txn;    /* the # last events in the below arrays;
+                                            added in the current transaction */
+       int                     assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
+       u64                     tags[X86_PMC_IDX_MAX];
+
+       struct perf_event       *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
+       struct event_constraint *event_constraint[X86_PMC_IDX_MAX];
+
+       int                     n_excl; /* the number of exclusive events */
+
+       unsigned int            txn_flags;
+       int                     is_fake;
+
+       /*
+        * Intel DebugStore bits
+        */
+       struct debug_store      *ds;
+       u64                     pebs_enabled;
+
+       /*
+        * Intel LBR bits
+        */
+       int                             lbr_users;
+       void                            *lbr_context;
+       struct perf_branch_stack        lbr_stack;
+       struct perf_branch_entry        lbr_entries[MAX_LBR_ENTRIES];
+       struct er_account               *lbr_sel;
+       u64                             br_sel;
+
+       /*
+        * Intel host/guest exclude bits
+        */
+       u64                             intel_ctrl_guest_mask;
+       u64                             intel_ctrl_host_mask;
+       struct perf_guest_switch_msr    guest_switch_msrs[X86_PMC_IDX_MAX];
+
+       /*
+        * Intel checkpoint mask
+        */
+       u64                             intel_cp_status;
+
+       /*
+        * manage shared (per-core, per-cpu) registers
+        * used on Intel NHM/WSM/SNB
+        */
+       struct intel_shared_regs        *shared_regs;
+       /*
+        * manage exclusive counter access between hyperthread
+        */
+       struct event_constraint *constraint_list; /* in enable order */
+       struct intel_excl_cntrs         *excl_cntrs;
+       int excl_thread_id; /* 0 or 1 */
+
+       /*
+        * AMD specific bits
+        */
+       struct amd_nb                   *amd_nb;
+       /* Inverted mask of bits to clear in the perf_ctr ctrl registers */
+       u64                             perf_ctr_virt_mask;
+
+       void                            *kfree_on_online[X86_PERF_KFREE_MAX];
+};
+
+#define __EVENT_CONSTRAINT(c, n, m, w, o, f) {\
+       { .idxmsk64 = (n) },            \
+       .code = (c),                    \
+       .cmask = (m),                   \
+       .weight = (w),                  \
+       .overlap = (o),                 \
+       .flags = f,                     \
+}
+
+#define EVENT_CONSTRAINT(c, n, m)      \
+       __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n), 0, 0)
+
+#define INTEL_EXCLEVT_CONSTRAINT(c, n) \
+       __EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT, HWEIGHT(n),\
+                          0, PERF_X86_EVENT_EXCL)
+
+/*
+ * The overlap flag marks event constraints with overlapping counter
+ * masks. This is the case if the counter mask of such an event is not
+ * a subset of any other counter mask of a constraint with an equal or
+ * higher weight, e.g.:
+ *
+ *  c_overlaps = EVENT_CONSTRAINT_OVERLAP(0, 0x09, 0);
+ *  c_another1 = EVENT_CONSTRAINT(0, 0x07, 0);
+ *  c_another2 = EVENT_CONSTRAINT(0, 0x38, 0);
+ *
+ * The event scheduler may not select the correct counter in the first
+ * cycle because it needs to know which subsequent events will be
+ * scheduled. It may fail to schedule the events then. So we set the
+ * overlap flag for such constraints to give the scheduler a hint which
+ * events to select for counter rescheduling.
+ *
+ * Care must be taken as the rescheduling algorithm is O(n!) which
+ * will increase scheduling cycles for an over-commited system
+ * dramatically.  The number of such EVENT_CONSTRAINT_OVERLAP() macros
+ * and its counter masks must be kept at a minimum.
+ */
+#define EVENT_CONSTRAINT_OVERLAP(c, n, m)      \
+       __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n), 1, 0)
+
+/*
+ * Constraint on the Event code.
+ */
+#define INTEL_EVENT_CONSTRAINT(c, n)   \
+       EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT)
+
+/*
+ * Constraint on the Event code + UMask + fixed-mask
+ *
+ * filter mask to validate fixed counter events.
+ * the following filters disqualify for fixed counters:
+ *  - inv
+ *  - edge
+ *  - cnt-mask
+ *  - in_tx
+ *  - in_tx_checkpointed
+ *  The other filters are supported by fixed counters.
+ *  The any-thread option is supported starting with v3.
+ */
+#define FIXED_EVENT_FLAGS (X86_RAW_EVENT_MASK|HSW_IN_TX|HSW_IN_TX_CHECKPOINTED)
+#define FIXED_EVENT_CONSTRAINT(c, n)   \
+       EVENT_CONSTRAINT(c, (1ULL << (32+n)), FIXED_EVENT_FLAGS)
+
+/*
+ * Constraint on the Event code + UMask
+ */
+#define INTEL_UEVENT_CONSTRAINT(c, n)  \
+       EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
+
+/* Constraint on specific umask bit only + event */
+#define INTEL_UBIT_EVENT_CONSTRAINT(c, n)      \
+       EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT|(c))
+
+/* Like UEVENT_CONSTRAINT, but match flags too */
+#define INTEL_FLAGS_UEVENT_CONSTRAINT(c, n)    \
+       EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
+
+#define INTEL_EXCLUEVT_CONSTRAINT(c, n)        \
+       __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \
+                          HWEIGHT(n), 0, PERF_X86_EVENT_EXCL)
+
+#define INTEL_PLD_CONSTRAINT(c, n)     \
+       __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LDLAT)
+
+#define INTEL_PST_CONSTRAINT(c, n)     \
+       __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST)
+
+/* Event constraint, but match on all event flags too. */
+#define INTEL_FLAGS_EVENT_CONSTRAINT(c, n) \
+       EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
+
+/* Check only flags, but allow all event/umask */
+#define INTEL_ALL_EVENT_CONSTRAINT(code, n)    \
+       EVENT_CONSTRAINT(code, n, X86_ALL_EVENT_FLAGS)
+
+/* Check flags and event code, and set the HSW store flag */
+#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_ST(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
+
+/* Check flags and event code, and set the HSW load flag */
+#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LD_HSW)
+
+#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, \
+                         PERF_X86_EVENT_PEBS_LD_HSW|PERF_X86_EVENT_EXCL)
+
+/* Check flags and event code/umask, and set the HSW store flag */
+#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
+
+#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, \
+                         PERF_X86_EVENT_PEBS_ST_HSW|PERF_X86_EVENT_EXCL)
+
+/* Check flags and event code/umask, and set the HSW load flag */
+#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LD_HSW)
+
+#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, \
+                         PERF_X86_EVENT_PEBS_LD_HSW|PERF_X86_EVENT_EXCL)
+
+/* Check flags and event code/umask, and set the HSW N/A flag */
+#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(code, n) \
+       __EVENT_CONSTRAINT(code, n,                     \
+                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
+                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_NA_HSW)
+
+
+/*
+ * We define the end marker as having a weight of -1
+ * to enable blacklisting of events using a counter bitmask
+ * of zero and thus a weight of zero.
+ * The end marker has a weight that cannot possibly be
+ * obtained from counting the bits in the bitmask.
+ */
+#define EVENT_CONSTRAINT_END { .weight = -1 }
+
+/*
+ * Check for end marker with weight == -1
+ */
+#define for_each_event_constraint(e, c)        \
+       for ((e) = (c); (e)->weight != -1; (e)++)
+
+/*
+ * Extra registers for specific events.
+ *
+ * Some events need large masks and require external MSRs.
+ * Those extra MSRs end up being shared for all events on
+ * a PMU and sometimes between PMU of sibling HT threads.
+ * In either case, the kernel needs to handle conflicting
+ * accesses to those extra, shared, regs. The data structure
+ * to manage those registers is stored in cpu_hw_event.
+ */
+struct extra_reg {
+       unsigned int            event;
+       unsigned int            msr;
+       u64                     config_mask;
+       u64                     valid_mask;
+       int                     idx;  /* per_xxx->regs[] reg index */
+       bool                    extra_msr_access;
+};
+
+#define EVENT_EXTRA_REG(e, ms, m, vm, i) {     \
+       .event = (e),                   \
+       .msr = (ms),                    \
+       .config_mask = (m),             \
+       .valid_mask = (vm),             \
+       .idx = EXTRA_REG_##i,           \
+       .extra_msr_access = true,       \
+       }
+
+#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx)     \
+       EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
+
+#define INTEL_UEVENT_EXTRA_REG(event, msr, vm, idx) \
+       EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT | \
+                       ARCH_PERFMON_EVENTSEL_UMASK, vm, idx)
+
+#define INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(c) \
+       INTEL_UEVENT_EXTRA_REG(c, \
+                              MSR_PEBS_LD_LAT_THRESHOLD, \
+                              0xffff, \
+                              LDLAT)
+
+#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
+
+union perf_capabilities {
+       struct {
+               u64     lbr_format:6;
+               u64     pebs_trap:1;
+               u64     pebs_arch_reg:1;
+               u64     pebs_format:4;
+               u64     smm_freeze:1;
+               /*
+                * PMU supports separate counter range for writing
+                * values > 32bit.
+                */
+               u64     full_width_write:1;
+       };
+       u64     capabilities;
+};
+
+struct x86_pmu_quirk {
+       struct x86_pmu_quirk *next;
+       void (*func)(void);
+};
+
+union x86_pmu_config {
+       struct {
+               u64 event:8,
+                   umask:8,
+                   usr:1,
+                   os:1,
+                   edge:1,
+                   pc:1,
+                   interrupt:1,
+                   __reserved1:1,
+                   en:1,
+                   inv:1,
+                   cmask:8,
+                   event2:4,
+                   __reserved2:4,
+                   go:1,
+                   ho:1;
+       } bits;
+       u64 value;
+};
+
+#define X86_CONFIG(args...) ((union x86_pmu_config){.bits = {args}}).value
+
+enum {
+       x86_lbr_exclusive_lbr,
+       x86_lbr_exclusive_bts,
+       x86_lbr_exclusive_pt,
+       x86_lbr_exclusive_max,
+};
+
+/*
+ * struct x86_pmu - generic x86 pmu
+ */
+struct x86_pmu {
+       /*
+        * Generic x86 PMC bits
+        */
+       const char      *name;
+       int             version;
+       int             (*handle_irq)(struct pt_regs *);
+       void            (*disable_all)(void);
+       void            (*enable_all)(int added);
+       void            (*enable)(struct perf_event *);
+       void            (*disable)(struct perf_event *);
+       int             (*hw_config)(struct perf_event *event);
+       int             (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
+       unsigned        eventsel;
+       unsigned        perfctr;
+       int             (*addr_offset)(int index, bool eventsel);
+       int             (*rdpmc_index)(int index);
+       u64             (*event_map)(int);
+       int             max_events;
+       int             num_counters;
+       int             num_counters_fixed;
+       int             cntval_bits;
+       u64             cntval_mask;
+       union {
+                       unsigned long events_maskl;
+                       unsigned long events_mask[BITS_TO_LONGS(ARCH_PERFMON_EVENTS_COUNT)];
+       };
+       int             events_mask_len;
+       int             apic;
+       u64             max_period;
+       struct event_constraint *
+                       (*get_event_constraints)(struct cpu_hw_events *cpuc,
+                                                int idx,
+                                                struct perf_event *event);
+
+       void            (*put_event_constraints)(struct cpu_hw_events *cpuc,
+                                                struct perf_event *event);
+
+       void            (*start_scheduling)(struct cpu_hw_events *cpuc);
+
+       void            (*commit_scheduling)(struct cpu_hw_events *cpuc, int idx, int cntr);
+
+       void            (*stop_scheduling)(struct cpu_hw_events *cpuc);
+
+       struct event_constraint *event_constraints;
+       struct x86_pmu_quirk *quirks;
+       int             perfctr_second_write;
+       bool            late_ack;
+       unsigned        (*limit_period)(struct perf_event *event, unsigned l);
+
+       /*
+        * sysfs attrs
+        */
+       int             attr_rdpmc_broken;
+       int             attr_rdpmc;
+       struct attribute **format_attrs;
+       struct attribute **event_attrs;
+
+       ssize_t         (*events_sysfs_show)(char *page, u64 config);
+       struct attribute **cpu_events;
+
+       /*
+        * CPU Hotplug hooks
+        */
+       int             (*cpu_prepare)(int cpu);
+       void            (*cpu_starting)(int cpu);
+       void            (*cpu_dying)(int cpu);
+       void            (*cpu_dead)(int cpu);
+
+       void            (*check_microcode)(void);
+       void            (*sched_task)(struct perf_event_context *ctx,
+                                     bool sched_in);
+
+       /*
+        * Intel Arch Perfmon v2+
+        */
+       u64                     intel_ctrl;
+       union perf_capabilities intel_cap;
+
+       /*
+        * Intel DebugStore bits
+        */
+       unsigned int    bts             :1,
+                       bts_active      :1,
+                       pebs            :1,
+                       pebs_active     :1,
+                       pebs_broken     :1,
+                       pebs_prec_dist  :1;
+       int             pebs_record_size;
+       int             pebs_buffer_size;
+       void            (*drain_pebs)(struct pt_regs *regs);
+       struct event_constraint *pebs_constraints;
+       void            (*pebs_aliases)(struct perf_event *event);
+       int             max_pebs_events;
+       unsigned long   free_running_flags;
+
+       /*
+        * Intel LBR
+        */
+       unsigned long   lbr_tos, lbr_from, lbr_to; /* MSR base regs       */
+       int             lbr_nr;                    /* hardware stack size */
+       u64             lbr_sel_mask;              /* LBR_SELECT valid bits */
+       const int       *lbr_sel_map;              /* lbr_select mappings */
+       bool            lbr_double_abort;          /* duplicated lbr aborts */
+
+       /*
+        * Intel PT/LBR/BTS are exclusive
+        */
+       atomic_t        lbr_exclusive[x86_lbr_exclusive_max];
+
+       /*
+        * Extra registers for events
+        */
+       struct extra_reg *extra_regs;
+       unsigned int flags;
+
+       /*
+        * Intel host/guest support (KVM)
+        */
+       struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
+};
+
+struct x86_perf_task_context {
+       u64 lbr_from[MAX_LBR_ENTRIES];
+       u64 lbr_to[MAX_LBR_ENTRIES];
+       u64 lbr_info[MAX_LBR_ENTRIES];
+       int tos;
+       int lbr_callstack_users;
+       int lbr_stack_state;
+};
+
+#define x86_add_quirk(func_)                                           \
+do {                                                                   \
+       static struct x86_pmu_quirk __quirk __initdata = {              \
+               .func = func_,                                          \
+       };                                                              \
+       __quirk.next = x86_pmu.quirks;                                  \
+       x86_pmu.quirks = &__quirk;                                      \
+} while (0)
+
+/*
+ * x86_pmu flags
+ */
+#define PMU_FL_NO_HT_SHARING   0x1 /* no hyper-threading resource sharing */
+#define PMU_FL_HAS_RSP_1       0x2 /* has 2 equivalent offcore_rsp regs   */
+#define PMU_FL_EXCL_CNTRS      0x4 /* has exclusive counter requirements  */
+#define PMU_FL_EXCL_ENABLED    0x8 /* exclusive counter active */
+
+#define EVENT_VAR(_id)  event_attr_##_id
+#define EVENT_PTR(_id) &event_attr_##_id.attr.attr
+
+#define EVENT_ATTR(_name, _id)                                         \
+static struct perf_pmu_events_attr EVENT_VAR(_id) = {                  \
+       .attr           = __ATTR(_name, 0444, events_sysfs_show, NULL), \
+       .id             = PERF_COUNT_HW_##_id,                          \
+       .event_str      = NULL,                                         \
+};
+
+#define EVENT_ATTR_STR(_name, v, str)                                  \
+static struct perf_pmu_events_attr event_attr_##v = {                  \
+       .attr           = __ATTR(_name, 0444, events_sysfs_show, NULL), \
+       .id             = 0,                                            \
+       .event_str      = str,                                          \
+};
+
+extern struct x86_pmu x86_pmu __read_mostly;
+
+static inline bool x86_pmu_has_lbr_callstack(void)
+{
+       return  x86_pmu.lbr_sel_map &&
+               x86_pmu.lbr_sel_map[PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT] > 0;
+}
+
+DECLARE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+int x86_perf_event_set_period(struct perf_event *event);
+
+/*
+ * Generalized hw caching related hw_event table, filled
+ * in on a per model basis. A value of 0 means
+ * 'not supported', -1 means 'hw_event makes no sense on
+ * this CPU', any other value means the raw hw_event
+ * ID.
+ */
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+extern u64 __read_mostly hw_cache_event_ids
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
+extern u64 __read_mostly hw_cache_extra_regs
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
+
+u64 x86_perf_event_update(struct perf_event *event);
+
+static inline unsigned int x86_pmu_config_addr(int index)
+{
+       return x86_pmu.eventsel + (x86_pmu.addr_offset ?
+                                  x86_pmu.addr_offset(index, true) : index);
+}
+
+static inline unsigned int x86_pmu_event_addr(int index)
+{
+       return x86_pmu.perfctr + (x86_pmu.addr_offset ?
+                                 x86_pmu.addr_offset(index, false) : index);
+}
+
+static inline int x86_pmu_rdpmc_index(int index)
+{
+       return x86_pmu.rdpmc_index ? x86_pmu.rdpmc_index(index) : index;
+}
+
+int x86_add_exclusive(unsigned int what);
+
+void x86_del_exclusive(unsigned int what);
+
+int x86_reserve_hardware(void);
+
+void x86_release_hardware(void);
+
+void hw_perf_lbr_event_destroy(struct perf_event *event);
+
+int x86_setup_perfctr(struct perf_event *event);
+
+int x86_pmu_hw_config(struct perf_event *event);
+
+void x86_pmu_disable_all(void);
+
+static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
+                                         u64 enable_mask)
+{
+       u64 disable_mask = __this_cpu_read(cpu_hw_events.perf_ctr_virt_mask);
+
+       if (hwc->extra_reg.reg)
+               wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
+       wrmsrl(hwc->config_base, (hwc->config | enable_mask) & ~disable_mask);
+}
+
+void x86_pmu_enable_all(int added);
+
+int perf_assign_events(struct event_constraint **constraints, int n,
+                       int wmin, int wmax, int gpmax, int *assign);
+int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
+
+void x86_pmu_stop(struct perf_event *event, int flags);
+
+static inline void x86_pmu_disable_event(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       wrmsrl(hwc->config_base, hwc->config);
+}
+
+void x86_pmu_enable_event(struct perf_event *event);
+
+int x86_pmu_handle_irq(struct pt_regs *regs);
+
+extern struct event_constraint emptyconstraint;
+
+extern struct event_constraint unconstrained;
+
+static inline bool kernel_ip(unsigned long ip)
+{
+#ifdef CONFIG_X86_32
+       return ip > PAGE_OFFSET;
+#else
+       return (long)ip < 0;
+#endif
+}
+
+/*
+ * Not all PMUs provide the right context information to place the reported IP
+ * into full context. Specifically segment registers are typically not
+ * supplied.
+ *
+ * Assuming the address is a linear address (it is for IBS), we fake the CS and
+ * vm86 mode using the known zero-based code segment and 'fix up' the registers
+ * to reflect this.
+ *
+ * Intel PEBS/LBR appear to typically provide the effective address, nothing
+ * much we can do about that but pray and treat it like a linear address.
+ */
+static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip)
+{
+       regs->cs = kernel_ip(ip) ? __KERNEL_CS : __USER_CS;
+       if (regs->flags & X86_VM_MASK)
+               regs->flags ^= (PERF_EFLAGS_VM | X86_VM_MASK);
+       regs->ip = ip;
+}
+
+ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);
+ssize_t intel_event_sysfs_show(char *page, u64 config);
+
+struct attribute **merge_attr(struct attribute **a, struct attribute **b);
+
+#ifdef CONFIG_CPU_SUP_AMD
+
+int amd_pmu_init(void);
+
+#else /* CONFIG_CPU_SUP_AMD */
+
+static inline int amd_pmu_init(void)
+{
+       return 0;
+}
+
+#endif /* CONFIG_CPU_SUP_AMD */
+
+#ifdef CONFIG_CPU_SUP_INTEL
+
+static inline bool intel_pmu_has_bts(struct perf_event *event)
+{
+       if (event->attr.config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
+           !event->attr.freq && event->hw.sample_period == 1)
+               return true;
+
+       return false;
+}
+
+int intel_pmu_save_and_restart(struct perf_event *event);
+
+struct event_constraint *
+x86_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event);
+
+struct intel_shared_regs *allocate_shared_regs(int cpu);
+
+int intel_pmu_init(void);
+
+void init_debug_store_on_cpu(int cpu);
+
+void fini_debug_store_on_cpu(int cpu);
+
+void release_ds_buffers(void);
+
+void reserve_ds_buffers(void);
+
+extern struct event_constraint bts_constraint;
+
+void intel_pmu_enable_bts(u64 config);
+
+void intel_pmu_disable_bts(void);
+
+int intel_pmu_drain_bts_buffer(void);
+
+extern struct event_constraint intel_core2_pebs_event_constraints[];
+
+extern struct event_constraint intel_atom_pebs_event_constraints[];
+
+extern struct event_constraint intel_slm_pebs_event_constraints[];
+
+extern struct event_constraint intel_nehalem_pebs_event_constraints[];
+
+extern struct event_constraint intel_westmere_pebs_event_constraints[];
+
+extern struct event_constraint intel_snb_pebs_event_constraints[];
+
+extern struct event_constraint intel_ivb_pebs_event_constraints[];
+
+extern struct event_constraint intel_hsw_pebs_event_constraints[];
+
+extern struct event_constraint intel_bdw_pebs_event_constraints[];
+
+extern struct event_constraint intel_skl_pebs_event_constraints[];
+
+struct event_constraint *intel_pebs_constraints(struct perf_event *event);
+
+void intel_pmu_pebs_enable(struct perf_event *event);
+
+void intel_pmu_pebs_disable(struct perf_event *event);
+
+void intel_pmu_pebs_enable_all(void);
+
+void intel_pmu_pebs_disable_all(void);
+
+void intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in);
+
+void intel_ds_init(void);
+
+void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in);
+
+void intel_pmu_lbr_reset(void);
+
+void intel_pmu_lbr_enable(struct perf_event *event);
+
+void intel_pmu_lbr_disable(struct perf_event *event);
+
+void intel_pmu_lbr_enable_all(bool pmi);
+
+void intel_pmu_lbr_disable_all(void);
+
+void intel_pmu_lbr_read(void);
+
+void intel_pmu_lbr_init_core(void);
+
+void intel_pmu_lbr_init_nhm(void);
+
+void intel_pmu_lbr_init_atom(void);
+
+void intel_pmu_lbr_init_snb(void);
+
+void intel_pmu_lbr_init_hsw(void);
+
+void intel_pmu_lbr_init_skl(void);
+
+void intel_pmu_lbr_init_knl(void);
+
+void intel_pmu_pebs_data_source_nhm(void);
+
+int intel_pmu_setup_lbr_filter(struct perf_event *event);
+
+void intel_pt_interrupt(void);
+
+int intel_bts_interrupt(void);
+
+void intel_bts_enable_local(void);
+
+void intel_bts_disable_local(void);
+
+int p4_pmu_init(void);
+
+int p6_pmu_init(void);
+
+int knc_pmu_init(void);
+
+ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
+                         char *page);
+
+static inline int is_ht_workaround_enabled(void)
+{
+       return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED);
+}
+
+#else /* CONFIG_CPU_SUP_INTEL */
+
+static inline void reserve_ds_buffers(void)
+{
+}
+
+static inline void release_ds_buffers(void)
+{
+}
+
+static inline int intel_pmu_init(void)
+{
+       return 0;
+}
+
+static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
+{
+       return NULL;
+}
+
+static inline int is_ht_workaround_enabled(void)
+{
+       return 0;
+}
+#endif /* CONFIG_CPU_SUP_INTEL */
index 7bfc85bbb8ffc0578011ceac2c08548bd140ade3..99afb665a004cb8ea82c1751f6ef29b12d116cc6 100644 (file)
@@ -151,12 +151,6 @@ static inline int alternatives_text_reserved(void *start, void *end)
        ALTINSTR_REPLACEMENT(newinstr2, feature2, 2)                    \
        ".popsection"
 
-/*
- * This must be included *after* the definition of ALTERNATIVE due to
- * <asm/arch_hweight.h>
- */
-#include <asm/cpufeature.h>
-
 /*
  * Alternative instructions for different CPU types or capabilities.
  *
index 3c56ef1ae068e8c52b829bab6719d47fba0ef8bd..5e828da2e18f6e9b4ee05e0abab7997b2fe9c6d3 100644 (file)
@@ -27,15 +27,23 @@ struct amd_l3_cache {
 };
 
 struct threshold_block {
-       unsigned int            block;
-       unsigned int            bank;
-       unsigned int            cpu;
-       u32                     address;
-       u16                     interrupt_enable;
-       bool                    interrupt_capable;
-       u16                     threshold_limit;
-       struct kobject          kobj;
-       struct list_head        miscj;
+       unsigned int     block;                 /* Number within bank */
+       unsigned int     bank;                  /* MCA bank the block belongs to */
+       unsigned int     cpu;                   /* CPU which controls MCA bank */
+       u32              address;               /* MSR address for the block */
+       u16              interrupt_enable;      /* Enable/Disable APIC interrupt */
+       bool             interrupt_capable;     /* Bank can generate an interrupt. */
+
+       u16              threshold_limit;       /*
+                                                * Value upon which threshold
+                                                * interrupt is generated.
+                                                */
+
+       struct kobject   kobj;                  /* sysfs object */
+       struct list_head miscj;                 /*
+                                                * List of threshold blocks
+                                                * within a bank.
+                                                */
 };
 
 struct threshold_bank {
index c80f6b6f3da222dc86dc00747429b618589502eb..0899cfc8dfe8f84f98edc6a0c19e7ff40225ae74 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
-#include <asm/processor.h>
 #include <asm/apicdef.h>
 #include <linux/atomic.h>
 #include <asm/fixmap.h>
index 259a7c1ef7099bc89b30cdb0ebbd3a311fa88e18..02e799fa43d1b19c878290f6424e1b2f7293074d 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_HWEIGHT_H
 #define _ASM_X86_HWEIGHT_H
 
+#include <asm/cpufeatures.h>
+
 #ifdef CONFIG_64BIT
 /* popcnt %edi, %eax -- redundant REX prefix for alignment */
 #define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
index 189679aba703537393b87d699a4e11cbfe94e23c..f5063b6659eb37f1a835bc5e614cf251ac48e032 100644 (file)
 
 /* Exception table entry */
 #ifdef __ASSEMBLY__
-# define _ASM_EXTABLE(from,to)                                 \
+# define _ASM_EXTABLE_HANDLE(from, to, handler)                        \
        .pushsection "__ex_table","a" ;                         \
-       .balign 8 ;                                             \
+       .balign 4 ;                                             \
        .long (from) - . ;                                      \
        .long (to) - . ;                                        \
+       .long (handler) - . ;                                   \
        .popsection
 
-# define _ASM_EXTABLE_EX(from,to)                              \
-       .pushsection "__ex_table","a" ;                         \
-       .balign 8 ;                                             \
-       .long (from) - . ;                                      \
-       .long (to) - . + 0x7ffffff0 ;                           \
-       .popsection
+# define _ASM_EXTABLE(from, to)                                        \
+       _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
+
+# define _ASM_EXTABLE_FAULT(from, to)                          \
+       _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
+
+# define _ASM_EXTABLE_EX(from, to)                             \
+       _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)                                  \
        .pushsection "_kprobe_blacklist","aw" ;                 \
        .endm
 
 #else
-# define _ASM_EXTABLE(from,to)                                 \
+# define _EXPAND_EXTABLE_HANDLE(x) #x
+# define _ASM_EXTABLE_HANDLE(from, to, handler)                        \
        " .pushsection \"__ex_table\",\"a\"\n"                  \
-       " .balign 8\n"                                          \
+       " .balign 4\n"                                          \
        " .long (" #from ") - .\n"                              \
        " .long (" #to ") - .\n"                                \
+       " .long (" _EXPAND_EXTABLE_HANDLE(handler) ") - .\n"    \
        " .popsection\n"
 
-# define _ASM_EXTABLE_EX(from,to)                              \
-       " .pushsection \"__ex_table\",\"a\"\n"                  \
-       " .balign 8\n"                                          \
-       " .long (" #from ") - .\n"                              \
-       " .long (" #to ") - . + 0x7ffffff0\n"                   \
-       " .popsection\n"
+# define _ASM_EXTABLE(from, to)                                        \
+       _ASM_EXTABLE_HANDLE(from, to, ex_handler_default)
+
+# define _ASM_EXTABLE_FAULT(from, to)                          \
+       _ASM_EXTABLE_HANDLE(from, to, ex_handler_fault)
+
+# define _ASM_EXTABLE_EX(from, to)                             \
+       _ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
+
 /* For C file, we already have NOKPROBE_SYMBOL macro */
 #endif
 
index a584e1c50918406a0398cf4a013432e47abf143e..bfb28caf97b1be1f2d6aa8893bd905a39030e310 100644 (file)
@@ -6,18 +6,17 @@
 
 /*
  * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
+ * And yes, this might be required on UP too when we're talking
  * to devices.
  */
 
 #ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+#define mb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "mfence", \
+                                     X86_FEATURE_XMM2) ::: "memory", "cc")
+#define rmb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "lfence", \
+                                      X86_FEATURE_XMM2) ::: "memory", "cc")
+#define wmb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "sfence", \
+                                      X86_FEATURE_XMM2) ::: "memory", "cc")
 #else
 #define mb()   asm volatile("mfence":::"memory")
 #define rmb()  asm volatile("lfence":::"memory")
index cfe3b954d5e41cbd96be1fdb147c164b63581814..7766d1cf096e80d56562d63876f8ca65df869199 100644 (file)
@@ -91,7 +91,7 @@ set_bit(long nr, volatile unsigned long *addr)
  * If it's called on the same region of memory simultaneously, the effect
  * may be that only one operation succeeds.
  */
-static inline void __set_bit(long nr, volatile unsigned long *addr)
+static __always_inline void __set_bit(long nr, volatile unsigned long *addr)
 {
        asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory");
 }
@@ -128,13 +128,13 @@ clear_bit(long nr, volatile unsigned long *addr)
  * clear_bit() is atomic and implies release semantics before the memory
  * operation. It can be used for an unlock.
  */
-static inline void clear_bit_unlock(long nr, volatile unsigned long *addr)
+static __always_inline void clear_bit_unlock(long nr, volatile unsigned long *addr)
 {
        barrier();
        clear_bit(nr, addr);
 }
 
-static inline void __clear_bit(long nr, volatile unsigned long *addr)
+static __always_inline void __clear_bit(long nr, volatile unsigned long *addr)
 {
        asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
 }
@@ -151,7 +151,7 @@ static inline void __clear_bit(long nr, volatile unsigned long *addr)
  * No memory barrier is required here, because x86 cannot reorder stores past
  * older loads. Same principle as spin_unlock.
  */
-static inline void __clear_bit_unlock(long nr, volatile unsigned long *addr)
+static __always_inline void __clear_bit_unlock(long nr, volatile unsigned long *addr)
 {
        barrier();
        __clear_bit(nr, addr);
@@ -166,7 +166,7 @@ static inline void __clear_bit_unlock(long nr, volatile unsigned long *addr)
  * If it's called on the same region of memory simultaneously, the effect
  * may be that only one operation succeeds.
  */
-static inline void __change_bit(long nr, volatile unsigned long *addr)
+static __always_inline void __change_bit(long nr, volatile unsigned long *addr)
 {
        asm volatile("btc %1,%0" : ADDR : "Ir" (nr));
 }
@@ -180,7 +180,7 @@ static inline void __change_bit(long nr, volatile unsigned long *addr)
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
-static inline void change_bit(long nr, volatile unsigned long *addr)
+static __always_inline void change_bit(long nr, volatile unsigned long *addr)
 {
        if (IS_IMMEDIATE(nr)) {
                asm volatile(LOCK_PREFIX "xorb %1,%0"
@@ -201,7 +201,7 @@ static inline void change_bit(long nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int test_and_set_bit(long nr, volatile unsigned long *addr)
+static __always_inline int test_and_set_bit(long nr, volatile unsigned long *addr)
 {
        GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, "Ir", nr, "%0", "c");
 }
@@ -228,7 +228,7 @@ test_and_set_bit_lock(long nr, volatile unsigned long *addr)
  * If two examples of this operation race, one can appear to succeed
  * but actually fail.  You must protect multiple accesses with a lock.
  */
-static inline int __test_and_set_bit(long nr, volatile unsigned long *addr)
+static __always_inline int __test_and_set_bit(long nr, volatile unsigned long *addr)
 {
        int oldbit;
 
@@ -247,7 +247,7 @@ static inline int __test_and_set_bit(long nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int test_and_clear_bit(long nr, volatile unsigned long *addr)
+static __always_inline int test_and_clear_bit(long nr, volatile unsigned long *addr)
 {
        GEN_BINARY_RMWcc(LOCK_PREFIX "btr", *addr, "Ir", nr, "%0", "c");
 }
@@ -268,7 +268,7 @@ static inline int test_and_clear_bit(long nr, volatile unsigned long *addr)
  * accessed from a hypervisor on the same CPU if running in a VM: don't change
  * this without also updating arch/x86/kernel/kvm.c
  */
-static inline int __test_and_clear_bit(long nr, volatile unsigned long *addr)
+static __always_inline int __test_and_clear_bit(long nr, volatile unsigned long *addr)
 {
        int oldbit;
 
@@ -280,7 +280,7 @@ static inline int __test_and_clear_bit(long nr, volatile unsigned long *addr)
 }
 
 /* WARNING: non atomic and it can be reordered! */
-static inline int __test_and_change_bit(long nr, volatile unsigned long *addr)
+static __always_inline int __test_and_change_bit(long nr, volatile unsigned long *addr)
 {
        int oldbit;
 
@@ -300,7 +300,7 @@ static inline int __test_and_change_bit(long nr, volatile unsigned long *addr)
  * This operation is atomic and cannot be reordered.
  * It also implies a memory barrier.
  */
-static inline int test_and_change_bit(long nr, volatile unsigned long *addr)
+static __always_inline int test_and_change_bit(long nr, volatile unsigned long *addr)
 {
        GEN_BINARY_RMWcc(LOCK_PREFIX "btc", *addr, "Ir", nr, "%0", "c");
 }
@@ -311,7 +311,7 @@ static __always_inline int constant_test_bit(long nr, const volatile unsigned lo
                (addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
 }
 
-static inline int variable_test_bit(long nr, volatile const unsigned long *addr)
+static __always_inline int variable_test_bit(long nr, volatile const unsigned long *addr)
 {
        int oldbit;
 
@@ -343,7 +343,7 @@ static int test_bit(int nr, const volatile unsigned long *addr);
  *
  * Undefined if no bit exists, so code should check against 0 first.
  */
-static inline unsigned long __ffs(unsigned long word)
+static __always_inline unsigned long __ffs(unsigned long word)
 {
        asm("rep; bsf %1,%0"
                : "=r" (word)
@@ -357,7 +357,7 @@ static inline unsigned long __ffs(unsigned long word)
  *
  * Undefined if no zero exists, so code should check against ~0UL first.
  */
-static inline unsigned long ffz(unsigned long word)
+static __always_inline unsigned long ffz(unsigned long word)
 {
        asm("rep; bsf %1,%0"
                : "=r" (word)
@@ -371,7 +371,7 @@ static inline unsigned long ffz(unsigned long word)
  *
  * Undefined if no set bit exists, so code should check against 0 first.
  */
-static inline unsigned long __fls(unsigned long word)
+static __always_inline unsigned long __fls(unsigned long word)
 {
        asm("bsr %1,%0"
            : "=r" (word)
@@ -393,7 +393,7 @@ static inline unsigned long __fls(unsigned long word)
  * set bit if value is nonzero. The first (least significant) bit
  * is at position 1.
  */
-static inline int ffs(int x)
+static __always_inline int ffs(int x)
 {
        int r;
 
@@ -434,7 +434,7 @@ static inline int ffs(int x)
  * set bit if value is nonzero. The last (most significant) bit is
  * at position 32.
  */
-static inline int fls(int x)
+static __always_inline int fls(int x)
 {
        int r;
 
index e63aa38e85fb23375ecefa40efe8cd9d76da6c43..61518cf79437679788bd41a1ee1c942aea29a8cb 100644 (file)
@@ -91,16 +91,10 @@ void clflush_cache_range(void *addr, unsigned int size);
 
 #define mmio_flush_range(addr, size) clflush_cache_range(addr, size)
 
-#ifdef CONFIG_DEBUG_RODATA
-void mark_rodata_ro(void);
 extern const int rodata_test_data;
 extern int kernel_set_to_readonly;
 void set_kernel_text_rw(void);
 void set_kernel_text_ro(void);
-#else
-static inline void set_kernel_text_rw(void) { }
-static inline void set_kernel_text_ro(void) { }
-#endif
 
 #ifdef CONFIG_DEBUG_RODATA_TEST
 int rodata_test(void);
index eda81dc0f4ae091c5ff085450ff277f68aa933a9..d194266acb28e52d237c19c21291633c15d99c9e 100644 (file)
@@ -3,10 +3,11 @@
 #ifndef _ASM_X86_CLOCKSOURCE_H
 #define _ASM_X86_CLOCKSOURCE_H
 
-#define VCLOCK_NONE 0  /* No vDSO clock available.     */
-#define VCLOCK_TSC  1  /* vDSO should use vread_tsc.   */
-#define VCLOCK_HPET 2  /* vDSO should use vread_hpet.  */
-#define VCLOCK_PVCLOCK 3 /* vDSO should use vread_pvclock. */
+#define VCLOCK_NONE    0  /* No vDSO clock available.  */
+#define VCLOCK_TSC     1  /* vDSO should use vread_tsc.        */
+#define VCLOCK_HPET    2  /* vDSO should use vread_hpet.       */
+#define VCLOCK_PVCLOCK 3 /* vDSO should use vread_pvclock. */
+#define VCLOCK_MAX     3
 
 struct arch_clocksource_data {
        int vclock_mode;
index ad19841eddfe142fec6b2b27dc329059d8fb7296..9733361fed6f4f7368d92f98d21b0d0edfbf6261 100644 (file)
@@ -2,6 +2,7 @@
 #define ASM_X86_CMPXCHG_H
 
 #include <linux/compiler.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative.h> /* Provides LOCK_PREFIX */
 
 /*
index 7ad8c946429776b6dad30238e9d5e2d65a1a3c87..68e4e8258b84126d59094ea1023568a8272dcdbd 100644 (file)
@@ -1,288 +1,7 @@
-/*
- * Defines x86 CPU feature bits
- */
 #ifndef _ASM_X86_CPUFEATURE_H
 #define _ASM_X86_CPUFEATURE_H
 
-#ifndef _ASM_X86_REQUIRED_FEATURES_H
-#include <asm/required-features.h>
-#endif
-
-#ifndef _ASM_X86_DISABLED_FEATURES_H
-#include <asm/disabled-features.h>
-#endif
-
-#define NCAPINTS       16      /* N 32-bit words worth of info */
-#define NBUGINTS       1       /* N 32-bit bug flags */
-
-/*
- * Note: If the comment begins with a quoted string, that string is used
- * in /proc/cpuinfo instead of the macro name.  If the string is "",
- * this feature bit is not displayed in /proc/cpuinfo at all.
- */
-
-/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
-#define X86_FEATURE_FPU                ( 0*32+ 0) /* Onboard FPU */
-#define X86_FEATURE_VME                ( 0*32+ 1) /* Virtual Mode Extensions */
-#define X86_FEATURE_DE         ( 0*32+ 2) /* Debugging Extensions */
-#define X86_FEATURE_PSE                ( 0*32+ 3) /* Page Size Extensions */
-#define X86_FEATURE_TSC                ( 0*32+ 4) /* Time Stamp Counter */
-#define X86_FEATURE_MSR                ( 0*32+ 5) /* Model-Specific Registers */
-#define X86_FEATURE_PAE                ( 0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE                ( 0*32+ 7) /* Machine Check Exception */
-#define X86_FEATURE_CX8                ( 0*32+ 8) /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC       ( 0*32+ 9) /* Onboard APIC */
-#define X86_FEATURE_SEP                ( 0*32+11) /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR       ( 0*32+12) /* Memory Type Range Registers */
-#define X86_FEATURE_PGE                ( 0*32+13) /* Page Global Enable */
-#define X86_FEATURE_MCA                ( 0*32+14) /* Machine Check Architecture */
-#define X86_FEATURE_CMOV       ( 0*32+15) /* CMOV instructions */
-                                         /* (plus FCMOVcc, FCOMI with FPU) */
-#define X86_FEATURE_PAT                ( 0*32+16) /* Page Attribute Table */
-#define X86_FEATURE_PSE36      ( 0*32+17) /* 36-bit PSEs */
-#define X86_FEATURE_PN         ( 0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLUSH    ( 0*32+19) /* CLFLUSH instruction */
-#define X86_FEATURE_DS         ( 0*32+21) /* "dts" Debug Store */
-#define X86_FEATURE_ACPI       ( 0*32+22) /* ACPI via MSR */
-#define X86_FEATURE_MMX                ( 0*32+23) /* Multimedia Extensions */
-#define X86_FEATURE_FXSR       ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
-#define X86_FEATURE_XMM                ( 0*32+25) /* "sse" */
-#define X86_FEATURE_XMM2       ( 0*32+26) /* "sse2" */
-#define X86_FEATURE_SELFSNOOP  ( 0*32+27) /* "ss" CPU self snoop */
-#define X86_FEATURE_HT         ( 0*32+28) /* Hyper-Threading */
-#define X86_FEATURE_ACC                ( 0*32+29) /* "tm" Automatic clock control */
-#define X86_FEATURE_IA64       ( 0*32+30) /* IA-64 processor */
-#define X86_FEATURE_PBE                ( 0*32+31) /* Pending Break Enable */
-
-/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
-/* Don't duplicate feature flags which are redundant with Intel! */
-#define X86_FEATURE_SYSCALL    ( 1*32+11) /* SYSCALL/SYSRET */
-#define X86_FEATURE_MP         ( 1*32+19) /* MP Capable. */
-#define X86_FEATURE_NX         ( 1*32+20) /* Execute Disable */
-#define X86_FEATURE_MMXEXT     ( 1*32+22) /* AMD MMX extensions */
-#define X86_FEATURE_FXSR_OPT   ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */
-#define X86_FEATURE_GBPAGES    ( 1*32+26) /* "pdpe1gb" GB pages */
-#define X86_FEATURE_RDTSCP     ( 1*32+27) /* RDTSCP */
-#define X86_FEATURE_LM         ( 1*32+29) /* Long Mode (x86-64) */
-#define X86_FEATURE_3DNOWEXT   ( 1*32+30) /* AMD 3DNow! extensions */
-#define X86_FEATURE_3DNOW      ( 1*32+31) /* 3DNow! */
-
-/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY   ( 2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN    ( 2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI       ( 2*32+ 3) /* LongRun table interface */
-
-/* Other features, Linux-defined mapping, word 3 */
-/* This range is used for feature bits which conflict or are synthesized */
-#define X86_FEATURE_CXMMX      ( 3*32+ 0) /* Cyrix MMX extensions */
-#define X86_FEATURE_K6_MTRR    ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */
-#define X86_FEATURE_CYRIX_ARR  ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */
-#define X86_FEATURE_CENTAUR_MCR        ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */
-/* cpu types for specific tunings: */
-#define X86_FEATURE_K8         ( 3*32+ 4) /* "" Opteron, Athlon64 */
-#define X86_FEATURE_K7         ( 3*32+ 5) /* "" Athlon */
-#define X86_FEATURE_P3         ( 3*32+ 6) /* "" P3 */
-#define X86_FEATURE_P4         ( 3*32+ 7) /* "" P4 */
-#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */
-#define X86_FEATURE_UP         ( 3*32+ 9) /* smp kernel running on up */
-/* free, was #define X86_FEATURE_FXSAVE_LEAK ( 3*32+10) * "" FXSAVE leaks FOP/FIP/FOP */
-#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS       ( 3*32+12) /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS                ( 3*32+13) /* Branch Trace Store */
-#define X86_FEATURE_SYSCALL32  ( 3*32+14) /* "" syscall in ia32 userspace */
-#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in ia32 userspace */
-#define X86_FEATURE_REP_GOOD   ( 3*32+16) /* rep microcode works well */
-#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */
-#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */
-/* free, was #define X86_FEATURE_11AP  ( 3*32+19) * "" Bad local APIC aka 11AP */
-#define X86_FEATURE_NOPL       ( 3*32+20) /* The NOPL (0F 1F) instructions */
-#define X86_FEATURE_ALWAYS     ( 3*32+21) /* "" Always-present feature */
-#define X86_FEATURE_XTOPOLOGY  ( 3*32+22) /* cpu topology enum extensions */
-#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
-#define X86_FEATURE_NONSTOP_TSC        ( 3*32+24) /* TSC does not stop in C states */
-/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
-#define X86_FEATURE_EXTD_APICID        ( 3*32+26) /* has extended APICID (8 bits) */
-#define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
-#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
-#define X86_FEATURE_EAGER_FPU  ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */
-#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
-
-/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_XMM3       ( 4*32+ 0) /* "pni" SSE-3 */
-#define X86_FEATURE_PCLMULQDQ  ( 4*32+ 1) /* PCLMULQDQ instruction */
-#define X86_FEATURE_DTES64     ( 4*32+ 2) /* 64-bit Debug Store */
-#define X86_FEATURE_MWAIT      ( 4*32+ 3) /* "monitor" Monitor/Mwait support */
-#define X86_FEATURE_DSCPL      ( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */
-#define X86_FEATURE_VMX                ( 4*32+ 5) /* Hardware virtualization */
-#define X86_FEATURE_SMX                ( 4*32+ 6) /* Safer mode */
-#define X86_FEATURE_EST                ( 4*32+ 7) /* Enhanced SpeedStep */
-#define X86_FEATURE_TM2                ( 4*32+ 8) /* Thermal Monitor 2 */
-#define X86_FEATURE_SSSE3      ( 4*32+ 9) /* Supplemental SSE-3 */
-#define X86_FEATURE_CID                ( 4*32+10) /* Context ID */
-#define X86_FEATURE_SDBG       ( 4*32+11) /* Silicon Debug */
-#define X86_FEATURE_FMA                ( 4*32+12) /* Fused multiply-add */
-#define X86_FEATURE_CX16       ( 4*32+13) /* CMPXCHG16B */
-#define X86_FEATURE_XTPR       ( 4*32+14) /* Send Task Priority Messages */
-#define X86_FEATURE_PDCM       ( 4*32+15) /* Performance Capabilities */
-#define X86_FEATURE_PCID       ( 4*32+17) /* Process Context Identifiers */
-#define X86_FEATURE_DCA                ( 4*32+18) /* Direct Cache Access */
-#define X86_FEATURE_XMM4_1     ( 4*32+19) /* "sse4_1" SSE-4.1 */
-#define X86_FEATURE_XMM4_2     ( 4*32+20) /* "sse4_2" SSE-4.2 */
-#define X86_FEATURE_X2APIC     ( 4*32+21) /* x2APIC */
-#define X86_FEATURE_MOVBE      ( 4*32+22) /* MOVBE instruction */
-#define X86_FEATURE_POPCNT      ( 4*32+23) /* POPCNT instruction */
-#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* Tsc deadline timer */
-#define X86_FEATURE_AES                ( 4*32+25) /* AES instructions */
-#define X86_FEATURE_XSAVE      ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
-#define X86_FEATURE_OSXSAVE    ( 4*32+27) /* "" XSAVE enabled in the OS */
-#define X86_FEATURE_AVX                ( 4*32+28) /* Advanced Vector Extensions */
-#define X86_FEATURE_F16C       ( 4*32+29) /* 16-bit fp conversions */
-#define X86_FEATURE_RDRAND     ( 4*32+30) /* The RDRAND instruction */
-#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */
-
-/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
-#define X86_FEATURE_XSTORE     ( 5*32+ 2) /* "rng" RNG present (xstore) */
-#define X86_FEATURE_XSTORE_EN  ( 5*32+ 3) /* "rng_en" RNG enabled */
-#define X86_FEATURE_XCRYPT     ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
-#define X86_FEATURE_XCRYPT_EN  ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */
-#define X86_FEATURE_ACE2       ( 5*32+ 8) /* Advanced Cryptography Engine v2 */
-#define X86_FEATURE_ACE2_EN    ( 5*32+ 9) /* ACE v2 enabled */
-#define X86_FEATURE_PHE                ( 5*32+10) /* PadLock Hash Engine */
-#define X86_FEATURE_PHE_EN     ( 5*32+11) /* PHE enabled */
-#define X86_FEATURE_PMM                ( 5*32+12) /* PadLock Montgomery Multiplier */
-#define X86_FEATURE_PMM_EN     ( 5*32+13) /* PMM enabled */
-
-/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
-#define X86_FEATURE_LAHF_LM    ( 6*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */
-#define X86_FEATURE_SVM                ( 6*32+ 2) /* Secure virtual machine */
-#define X86_FEATURE_EXTAPIC    ( 6*32+ 3) /* Extended APIC space */
-#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */
-#define X86_FEATURE_ABM                ( 6*32+ 5) /* Advanced bit manipulation */
-#define X86_FEATURE_SSE4A      ( 6*32+ 6) /* SSE-4A */
-#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */
-#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */
-#define X86_FEATURE_OSVW       ( 6*32+ 9) /* OS Visible Workaround */
-#define X86_FEATURE_IBS                ( 6*32+10) /* Instruction Based Sampling */
-#define X86_FEATURE_XOP                ( 6*32+11) /* extended AVX instructions */
-#define X86_FEATURE_SKINIT     ( 6*32+12) /* SKINIT/STGI instructions */
-#define X86_FEATURE_WDT                ( 6*32+13) /* Watchdog timer */
-#define X86_FEATURE_LWP                ( 6*32+15) /* Light Weight Profiling */
-#define X86_FEATURE_FMA4       ( 6*32+16) /* 4 operands MAC instructions */
-#define X86_FEATURE_TCE                ( 6*32+17) /* translation cache extension */
-#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */
-#define X86_FEATURE_TBM                ( 6*32+21) /* trailing bit manipulations */
-#define X86_FEATURE_TOPOEXT    ( 6*32+22) /* topology extensions CPUID leafs */
-#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */
-#define X86_FEATURE_PERFCTR_NB  ( 6*32+24) /* NB performance counter extensions */
-#define X86_FEATURE_BPEXT      (6*32+26) /* data breakpoint extension */
-#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */
-#define X86_FEATURE_MWAITX     ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
-
-/*
- * Auxiliary flags: Linux defined - For features scattered in various
- * CPUID levels like 0x6, 0xA etc, word 7.
- *
- * Reuse free bits when adding new feature flags!
- */
-
-#define X86_FEATURE_CPB                ( 7*32+ 2) /* AMD Core Performance Boost */
-#define X86_FEATURE_EPB                ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
-
-#define X86_FEATURE_HW_PSTATE  ( 7*32+ 8) /* AMD HW-PState */
-#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
-
-#define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
-
-/* Virtualization flags: Linux defined, word 8 */
-#define X86_FEATURE_TPR_SHADOW  ( 8*32+ 0) /* Intel TPR Shadow */
-#define X86_FEATURE_VNMI        ( 8*32+ 1) /* Intel Virtual NMI */
-#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */
-#define X86_FEATURE_EPT         ( 8*32+ 3) /* Intel Extended Page Table */
-#define X86_FEATURE_VPID        ( 8*32+ 4) /* Intel Virtual Processor ID */
-
-#define X86_FEATURE_VMMCALL     ( 8*32+15) /* Prefer vmmcall to vmcall */
-#define X86_FEATURE_XENPV       ( 8*32+16) /* "" Xen paravirtual guest */
-
-
-/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
-#define X86_FEATURE_FSGSBASE   ( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
-#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3b */
-#define X86_FEATURE_BMI1       ( 9*32+ 3) /* 1st group bit manipulation extensions */
-#define X86_FEATURE_HLE                ( 9*32+ 4) /* Hardware Lock Elision */
-#define X86_FEATURE_AVX2       ( 9*32+ 5) /* AVX2 instructions */
-#define X86_FEATURE_SMEP       ( 9*32+ 7) /* Supervisor Mode Execution Protection */
-#define X86_FEATURE_BMI2       ( 9*32+ 8) /* 2nd group bit manipulation extensions */
-#define X86_FEATURE_ERMS       ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */
-#define X86_FEATURE_INVPCID    ( 9*32+10) /* Invalidate Processor Context ID */
-#define X86_FEATURE_RTM                ( 9*32+11) /* Restricted Transactional Memory */
-#define X86_FEATURE_CQM                ( 9*32+12) /* Cache QoS Monitoring */
-#define X86_FEATURE_MPX                ( 9*32+14) /* Memory Protection Extension */
-#define X86_FEATURE_AVX512F    ( 9*32+16) /* AVX-512 Foundation */
-#define X86_FEATURE_RDSEED     ( 9*32+18) /* The RDSEED instruction */
-#define X86_FEATURE_ADX                ( 9*32+19) /* The ADCX and ADOX instructions */
-#define X86_FEATURE_SMAP       ( 9*32+20) /* Supervisor Mode Access Prevention */
-#define X86_FEATURE_PCOMMIT    ( 9*32+22) /* PCOMMIT instruction */
-#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
-#define X86_FEATURE_CLWB       ( 9*32+24) /* CLWB instruction */
-#define X86_FEATURE_AVX512PF   ( 9*32+26) /* AVX-512 Prefetch */
-#define X86_FEATURE_AVX512ER   ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
-#define X86_FEATURE_AVX512CD   ( 9*32+28) /* AVX-512 Conflict Detection */
-#define X86_FEATURE_SHA_NI     ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */
-
-/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */
-#define X86_FEATURE_XSAVEOPT   (10*32+ 0) /* XSAVEOPT */
-#define X86_FEATURE_XSAVEC     (10*32+ 1) /* XSAVEC */
-#define X86_FEATURE_XGETBV1    (10*32+ 2) /* XGETBV with ECX = 1 */
-#define X86_FEATURE_XSAVES     (10*32+ 3) /* XSAVES/XRSTORS */
-
-/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11 */
-#define X86_FEATURE_CQM_LLC    (11*32+ 1) /* LLC QoS if 1 */
-
-/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */
-#define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */
-
-/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */
-#define X86_FEATURE_CLZERO     (13*32+0) /* CLZERO instruction */
-
-/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */
-#define X86_FEATURE_DTHERM     (14*32+ 0) /* Digital Thermal Sensor */
-#define X86_FEATURE_IDA                (14*32+ 1) /* Intel Dynamic Acceleration */
-#define X86_FEATURE_ARAT       (14*32+ 2) /* Always Running APIC Timer */
-#define X86_FEATURE_PLN                (14*32+ 4) /* Intel Power Limit Notification */
-#define X86_FEATURE_PTS                (14*32+ 6) /* Intel Package Thermal Status */
-#define X86_FEATURE_HWP                (14*32+ 7) /* Intel Hardware P-states */
-#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */
-#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */
-#define X86_FEATURE_HWP_EPP    (14*32+10) /* HWP Energy Perf. Preference */
-#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */
-
-/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */
-#define X86_FEATURE_NPT                (15*32+ 0) /* Nested Page Table support */
-#define X86_FEATURE_LBRV       (15*32+ 1) /* LBR Virtualization support */
-#define X86_FEATURE_SVML       (15*32+ 2) /* "svm_lock" SVM locking MSR */
-#define X86_FEATURE_NRIPS      (15*32+ 3) /* "nrip_save" SVM next_rip save */
-#define X86_FEATURE_TSCRATEMSR  (15*32+ 4) /* "tsc_scale" TSC scaling support */
-#define X86_FEATURE_VMCBCLEAN   (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */
-#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */
-#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */
-#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */
-#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
-
-/*
- * BUG word(s)
- */
-#define X86_BUG(x)             (NCAPINTS*32 + (x))
-
-#define X86_BUG_F00F           X86_BUG(0) /* Intel F00F */
-#define X86_BUG_FDIV           X86_BUG(1) /* FPU FDIV */
-#define X86_BUG_COMA           X86_BUG(2) /* Cyrix 6x86 coma */
-#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */
-#define X86_BUG_AMD_APIC_C1E   X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */
-#define X86_BUG_11AP           X86_BUG(5) /* Bad local APIC aka 11AP */
-#define X86_BUG_FXSAVE_LEAK    X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
-#define X86_BUG_CLFLUSH_MONITOR        X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
-#define X86_BUG_SYSRET_SS_ATTRS        X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
+#include <asm/processor.h>
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 
@@ -369,8 +88,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
  * is not relevant.
  */
 #define cpu_feature_enabled(bit)       \
-       (__builtin_constant_p(bit) && DISABLED_MASK_BIT_SET(bit) ? 0 :  \
-        cpu_has(&boot_cpu_data, bit))
+       (__builtin_constant_p(bit) && DISABLED_MASK_BIT_SET(bit) ? 0 : static_cpu_has(bit))
 
 #define boot_cpu_has(bit)      cpu_has(&boot_cpu_data, bit)
 
@@ -406,106 +124,19 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
 #define cpu_has_osxsave                boot_cpu_has(X86_FEATURE_OSXSAVE)
 #define cpu_has_hypervisor     boot_cpu_has(X86_FEATURE_HYPERVISOR)
 /*
- * Do not add any more of those clumsy macros - use static_cpu_has_safe() for
+ * Do not add any more of those clumsy macros - use static_cpu_has() for
  * fast paths and boot_cpu_has() otherwise!
  */
 
-#if __GNUC__ >= 4 && defined(CONFIG_X86_FAST_FEATURE_TESTS)
-extern void warn_pre_alternatives(void);
-extern bool __static_cpu_has_safe(u16 bit);
-
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_X86_FAST_FEATURE_TESTS)
 /*
  * Static testing of CPU features.  Used the same as boot_cpu_has().
- * These are only valid after alternatives have run, but will statically
- * patch the target code for additional performance.
+ * These will statically patch the target code for additional
+ * performance.
  */
-static __always_inline __pure bool __static_cpu_has(u16 bit)
-{
-#ifdef CC_HAVE_ASM_GOTO
-
-#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS
-
-               /*
-                * Catch too early usage of this before alternatives
-                * have run.
-                */
-               asm_volatile_goto("1: jmp %l[t_warn]\n"
-                        "2:\n"
-                        ".section .altinstructions,\"a\"\n"
-                        " .long 1b - .\n"
-                        " .long 0\n"           /* no replacement */
-                        " .word %P0\n"         /* 1: do replace */
-                        " .byte 2b - 1b\n"     /* source len */
-                        " .byte 0\n"           /* replacement len */
-                        " .byte 0\n"           /* pad len */
-                        ".previous\n"
-                        /* skipping size check since replacement size = 0 */
-                        : : "i" (X86_FEATURE_ALWAYS) : : t_warn);
-
-#endif
-
-               asm_volatile_goto("1: jmp %l[t_no]\n"
-                        "2:\n"
-                        ".section .altinstructions,\"a\"\n"
-                        " .long 1b - .\n"
-                        " .long 0\n"           /* no replacement */
-                        " .word %P0\n"         /* feature bit */
-                        " .byte 2b - 1b\n"     /* source len */
-                        " .byte 0\n"           /* replacement len */
-                        " .byte 0\n"           /* pad len */
-                        ".previous\n"
-                        /* skipping size check since replacement size = 0 */
-                        : : "i" (bit) : : t_no);
-               return true;
-       t_no:
-               return false;
-
-#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS
-       t_warn:
-               warn_pre_alternatives();
-               return false;
-#endif
-
-#else /* CC_HAVE_ASM_GOTO */
-
-               u8 flag;
-               /* Open-coded due to __stringify() in ALTERNATIVE() */
-               asm volatile("1: movb $0,%0\n"
-                            "2:\n"
-                            ".section .altinstructions,\"a\"\n"
-                            " .long 1b - .\n"
-                            " .long 3f - .\n"
-                            " .word %P1\n"             /* feature bit */
-                            " .byte 2b - 1b\n"         /* source len */
-                            " .byte 4f - 3f\n"         /* replacement len */
-                            " .byte 0\n"               /* pad len */
-                            ".previous\n"
-                            ".section .discard,\"aw\",@progbits\n"
-                            " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */
-                            ".previous\n"
-                            ".section .altinstr_replacement,\"ax\"\n"
-                            "3: movb $1,%0\n"
-                            "4:\n"
-                            ".previous\n"
-                            : "=qm" (flag) : "i" (bit));
-               return flag;
-
-#endif /* CC_HAVE_ASM_GOTO */
-}
-
-#define static_cpu_has(bit)                                    \
-(                                                              \
-       __builtin_constant_p(boot_cpu_has(bit)) ?               \
-               boot_cpu_has(bit) :                             \
-       __builtin_constant_p(bit) ?                             \
-               __static_cpu_has(bit) :                         \
-               boot_cpu_has(bit)                               \
-)
-
-static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
+static __always_inline __pure bool _static_cpu_has(u16 bit)
 {
-#ifdef CC_HAVE_ASM_GOTO
-               asm_volatile_goto("1: jmp %l[t_dynamic]\n"
+               asm_volatile_goto("1: jmp 6f\n"
                         "2:\n"
                         ".skip -(((5f-4f) - (2b-1b)) > 0) * "
                                 "((5f-4f) - (2b-1b)),0x90\n"
@@ -530,66 +161,34 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
                         " .byte 0\n"                   /* repl len */
                         " .byte 0\n"                   /* pad len */
                         ".previous\n"
-                        : : "i" (bit), "i" (X86_FEATURE_ALWAYS)
-                        : : t_dynamic, t_no);
+                        ".section .altinstr_aux,\"ax\"\n"
+                        "6:\n"
+                        " testb %[bitnum],%[cap_byte]\n"
+                        " jnz %l[t_yes]\n"
+                        " jmp %l[t_no]\n"
+                        ".previous\n"
+                        : : "i" (bit), "i" (X86_FEATURE_ALWAYS),
+                            [bitnum] "i" (1 << (bit & 7)),
+                            [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3])
+                        : : t_yes, t_no);
+       t_yes:
                return true;
        t_no:
                return false;
-       t_dynamic:
-               return __static_cpu_has_safe(bit);
-#else
-               u8 flag;
-               /* Open-coded due to __stringify() in ALTERNATIVE() */
-               asm volatile("1: movb $2,%0\n"
-                            "2:\n"
-                            ".section .altinstructions,\"a\"\n"
-                            " .long 1b - .\n"          /* src offset */
-                            " .long 3f - .\n"          /* repl offset */
-                            " .word %P2\n"             /* always replace */
-                            " .byte 2b - 1b\n"         /* source len */
-                            " .byte 4f - 3f\n"         /* replacement len */
-                            " .byte 0\n"               /* pad len */
-                            ".previous\n"
-                            ".section .discard,\"aw\",@progbits\n"
-                            " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */
-                            ".previous\n"
-                            ".section .altinstr_replacement,\"ax\"\n"
-                            "3: movb $0,%0\n"
-                            "4:\n"
-                            ".previous\n"
-                            ".section .altinstructions,\"a\"\n"
-                            " .long 1b - .\n"          /* src offset */
-                            " .long 5f - .\n"          /* repl offset */
-                            " .word %P1\n"             /* feature bit */
-                            " .byte 4b - 3b\n"         /* src len */
-                            " .byte 6f - 5f\n"         /* repl len */
-                            " .byte 0\n"               /* pad len */
-                            ".previous\n"
-                            ".section .discard,\"aw\",@progbits\n"
-                            " .byte 0xff + (6f-5f) - (4b-3b)\n" /* size check */
-                            ".previous\n"
-                            ".section .altinstr_replacement,\"ax\"\n"
-                            "5: movb $1,%0\n"
-                            "6:\n"
-                            ".previous\n"
-                            : "=qm" (flag)
-                            : "i" (bit), "i" (X86_FEATURE_ALWAYS));
-               return (flag == 2 ? __static_cpu_has_safe(bit) : flag);
-#endif /* CC_HAVE_ASM_GOTO */
 }
 
-#define static_cpu_has_safe(bit)                               \
+#define static_cpu_has(bit)                                    \
 (                                                              \
        __builtin_constant_p(boot_cpu_has(bit)) ?               \
                boot_cpu_has(bit) :                             \
-               _static_cpu_has_safe(bit)                       \
+               _static_cpu_has(bit)                            \
 )
 #else
 /*
- * gcc 3.x is too stupid to do the static test; fall back to dynamic.
+ * Fall back to dynamic for gcc versions which don't support asm goto. Should be
+ * a minority now anyway.
  */
 #define static_cpu_has(bit)            boot_cpu_has(bit)
-#define static_cpu_has_safe(bit)       boot_cpu_has(bit)
 #endif
 
 #define cpu_has_bug(c, bit)            cpu_has(c, (bit))
@@ -597,7 +196,6 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)
 #define clear_cpu_bug(c, bit)          clear_cpu_cap(c, (bit))
 
 #define static_cpu_has_bug(bit)                static_cpu_has((bit))
-#define static_cpu_has_bug_safe(bit)   static_cpu_has_safe((bit))
 #define boot_cpu_has_bug(bit)          cpu_has_bug(&boot_cpu_data, (bit))
 
 #define MAX_CPU_FEATURES               (NCAPINTS * 32)
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
new file mode 100644 (file)
index 0000000..074b760
--- /dev/null
@@ -0,0 +1,300 @@
+#ifndef _ASM_X86_CPUFEATURES_H
+#define _ASM_X86_CPUFEATURES_H
+
+#ifndef _ASM_X86_REQUIRED_FEATURES_H
+#include <asm/required-features.h>
+#endif
+
+#ifndef _ASM_X86_DISABLED_FEATURES_H
+#include <asm/disabled-features.h>
+#endif
+
+/*
+ * Defines x86 CPU feature bits
+ */
+#define NCAPINTS       16      /* N 32-bit words worth of info */
+#define NBUGINTS       1       /* N 32-bit bug flags */
+
+/*
+ * Note: If the comment begins with a quoted string, that string is used
+ * in /proc/cpuinfo instead of the macro name.  If the string is "",
+ * this feature bit is not displayed in /proc/cpuinfo at all.
+ */
+
+/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
+#define X86_FEATURE_FPU                ( 0*32+ 0) /* Onboard FPU */
+#define X86_FEATURE_VME                ( 0*32+ 1) /* Virtual Mode Extensions */
+#define X86_FEATURE_DE         ( 0*32+ 2) /* Debugging Extensions */
+#define X86_FEATURE_PSE                ( 0*32+ 3) /* Page Size Extensions */
+#define X86_FEATURE_TSC                ( 0*32+ 4) /* Time Stamp Counter */
+#define X86_FEATURE_MSR                ( 0*32+ 5) /* Model-Specific Registers */
+#define X86_FEATURE_PAE                ( 0*32+ 6) /* Physical Address Extensions */
+#define X86_FEATURE_MCE                ( 0*32+ 7) /* Machine Check Exception */
+#define X86_FEATURE_CX8                ( 0*32+ 8) /* CMPXCHG8 instruction */
+#define X86_FEATURE_APIC       ( 0*32+ 9) /* Onboard APIC */
+#define X86_FEATURE_SEP                ( 0*32+11) /* SYSENTER/SYSEXIT */
+#define X86_FEATURE_MTRR       ( 0*32+12) /* Memory Type Range Registers */
+#define X86_FEATURE_PGE                ( 0*32+13) /* Page Global Enable */
+#define X86_FEATURE_MCA                ( 0*32+14) /* Machine Check Architecture */
+#define X86_FEATURE_CMOV       ( 0*32+15) /* CMOV instructions */
+                                         /* (plus FCMOVcc, FCOMI with FPU) */
+#define X86_FEATURE_PAT                ( 0*32+16) /* Page Attribute Table */
+#define X86_FEATURE_PSE36      ( 0*32+17) /* 36-bit PSEs */
+#define X86_FEATURE_PN         ( 0*32+18) /* Processor serial number */
+#define X86_FEATURE_CLFLUSH    ( 0*32+19) /* CLFLUSH instruction */
+#define X86_FEATURE_DS         ( 0*32+21) /* "dts" Debug Store */
+#define X86_FEATURE_ACPI       ( 0*32+22) /* ACPI via MSR */
+#define X86_FEATURE_MMX                ( 0*32+23) /* Multimedia Extensions */
+#define X86_FEATURE_FXSR       ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
+#define X86_FEATURE_XMM                ( 0*32+25) /* "sse" */
+#define X86_FEATURE_XMM2       ( 0*32+26) /* "sse2" */
+#define X86_FEATURE_SELFSNOOP  ( 0*32+27) /* "ss" CPU self snoop */
+#define X86_FEATURE_HT         ( 0*32+28) /* Hyper-Threading */
+#define X86_FEATURE_ACC                ( 0*32+29) /* "tm" Automatic clock control */
+#define X86_FEATURE_IA64       ( 0*32+30) /* IA-64 processor */
+#define X86_FEATURE_PBE                ( 0*32+31) /* Pending Break Enable */
+
+/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
+/* Don't duplicate feature flags which are redundant with Intel! */
+#define X86_FEATURE_SYSCALL    ( 1*32+11) /* SYSCALL/SYSRET */
+#define X86_FEATURE_MP         ( 1*32+19) /* MP Capable. */
+#define X86_FEATURE_NX         ( 1*32+20) /* Execute Disable */
+#define X86_FEATURE_MMXEXT     ( 1*32+22) /* AMD MMX extensions */
+#define X86_FEATURE_FXSR_OPT   ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */
+#define X86_FEATURE_GBPAGES    ( 1*32+26) /* "pdpe1gb" GB pages */
+#define X86_FEATURE_RDTSCP     ( 1*32+27) /* RDTSCP */
+#define X86_FEATURE_LM         ( 1*32+29) /* Long Mode (x86-64) */
+#define X86_FEATURE_3DNOWEXT   ( 1*32+30) /* AMD 3DNow! extensions */
+#define X86_FEATURE_3DNOW      ( 1*32+31) /* 3DNow! */
+
+/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
+#define X86_FEATURE_RECOVERY   ( 2*32+ 0) /* CPU in recovery mode */
+#define X86_FEATURE_LONGRUN    ( 2*32+ 1) /* Longrun power control */
+#define X86_FEATURE_LRTI       ( 2*32+ 3) /* LongRun table interface */
+
+/* Other features, Linux-defined mapping, word 3 */
+/* This range is used for feature bits which conflict or are synthesized */
+#define X86_FEATURE_CXMMX      ( 3*32+ 0) /* Cyrix MMX extensions */
+#define X86_FEATURE_K6_MTRR    ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */
+#define X86_FEATURE_CYRIX_ARR  ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */
+#define X86_FEATURE_CENTAUR_MCR        ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */
+/* cpu types for specific tunings: */
+#define X86_FEATURE_K8         ( 3*32+ 4) /* "" Opteron, Athlon64 */
+#define X86_FEATURE_K7         ( 3*32+ 5) /* "" Athlon */
+#define X86_FEATURE_P3         ( 3*32+ 6) /* "" P3 */
+#define X86_FEATURE_P4         ( 3*32+ 7) /* "" P4 */
+#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */
+#define X86_FEATURE_UP         ( 3*32+ 9) /* smp kernel running on up */
+#define X86_FEATURE_ART                ( 3*32+10) /* Platform has always running timer (ART) */
+#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */
+#define X86_FEATURE_PEBS       ( 3*32+12) /* Precise-Event Based Sampling */
+#define X86_FEATURE_BTS                ( 3*32+13) /* Branch Trace Store */
+#define X86_FEATURE_SYSCALL32  ( 3*32+14) /* "" syscall in ia32 userspace */
+#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in ia32 userspace */
+#define X86_FEATURE_REP_GOOD   ( 3*32+16) /* rep microcode works well */
+#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */
+#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */
+/* free, was #define X86_FEATURE_11AP  ( 3*32+19) * "" Bad local APIC aka 11AP */
+#define X86_FEATURE_NOPL       ( 3*32+20) /* The NOPL (0F 1F) instructions */
+#define X86_FEATURE_ALWAYS     ( 3*32+21) /* "" Always-present feature */
+#define X86_FEATURE_XTOPOLOGY  ( 3*32+22) /* cpu topology enum extensions */
+#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
+#define X86_FEATURE_NONSTOP_TSC        ( 3*32+24) /* TSC does not stop in C states */
+/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
+#define X86_FEATURE_EXTD_APICID        ( 3*32+26) /* has extended APICID (8 bits) */
+#define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
+#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
+#define X86_FEATURE_EAGER_FPU  ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */
+#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
+#define X86_FEATURE_MCE_RECOVERY ( 3*32+31) /* cpu has recoverable machine checks */
+
+/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
+#define X86_FEATURE_XMM3       ( 4*32+ 0) /* "pni" SSE-3 */
+#define X86_FEATURE_PCLMULQDQ  ( 4*32+ 1) /* PCLMULQDQ instruction */
+#define X86_FEATURE_DTES64     ( 4*32+ 2) /* 64-bit Debug Store */
+#define X86_FEATURE_MWAIT      ( 4*32+ 3) /* "monitor" Monitor/Mwait support */
+#define X86_FEATURE_DSCPL      ( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */
+#define X86_FEATURE_VMX                ( 4*32+ 5) /* Hardware virtualization */
+#define X86_FEATURE_SMX                ( 4*32+ 6) /* Safer mode */
+#define X86_FEATURE_EST                ( 4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2                ( 4*32+ 8) /* Thermal Monitor 2 */
+#define X86_FEATURE_SSSE3      ( 4*32+ 9) /* Supplemental SSE-3 */
+#define X86_FEATURE_CID                ( 4*32+10) /* Context ID */
+#define X86_FEATURE_SDBG       ( 4*32+11) /* Silicon Debug */
+#define X86_FEATURE_FMA                ( 4*32+12) /* Fused multiply-add */
+#define X86_FEATURE_CX16       ( 4*32+13) /* CMPXCHG16B */
+#define X86_FEATURE_XTPR       ( 4*32+14) /* Send Task Priority Messages */
+#define X86_FEATURE_PDCM       ( 4*32+15) /* Performance Capabilities */
+#define X86_FEATURE_PCID       ( 4*32+17) /* Process Context Identifiers */
+#define X86_FEATURE_DCA                ( 4*32+18) /* Direct Cache Access */
+#define X86_FEATURE_XMM4_1     ( 4*32+19) /* "sse4_1" SSE-4.1 */
+#define X86_FEATURE_XMM4_2     ( 4*32+20) /* "sse4_2" SSE-4.2 */
+#define X86_FEATURE_X2APIC     ( 4*32+21) /* x2APIC */
+#define X86_FEATURE_MOVBE      ( 4*32+22) /* MOVBE instruction */
+#define X86_FEATURE_POPCNT      ( 4*32+23) /* POPCNT instruction */
+#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* Tsc deadline timer */
+#define X86_FEATURE_AES                ( 4*32+25) /* AES instructions */
+#define X86_FEATURE_XSAVE      ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
+#define X86_FEATURE_OSXSAVE    ( 4*32+27) /* "" XSAVE enabled in the OS */
+#define X86_FEATURE_AVX                ( 4*32+28) /* Advanced Vector Extensions */
+#define X86_FEATURE_F16C       ( 4*32+29) /* 16-bit fp conversions */
+#define X86_FEATURE_RDRAND     ( 4*32+30) /* The RDRAND instruction */
+#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */
+
+/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
+#define X86_FEATURE_XSTORE     ( 5*32+ 2) /* "rng" RNG present (xstore) */
+#define X86_FEATURE_XSTORE_EN  ( 5*32+ 3) /* "rng_en" RNG enabled */
+#define X86_FEATURE_XCRYPT     ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
+#define X86_FEATURE_XCRYPT_EN  ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */
+#define X86_FEATURE_ACE2       ( 5*32+ 8) /* Advanced Cryptography Engine v2 */
+#define X86_FEATURE_ACE2_EN    ( 5*32+ 9) /* ACE v2 enabled */
+#define X86_FEATURE_PHE                ( 5*32+10) /* PadLock Hash Engine */
+#define X86_FEATURE_PHE_EN     ( 5*32+11) /* PHE enabled */
+#define X86_FEATURE_PMM                ( 5*32+12) /* PadLock Montgomery Multiplier */
+#define X86_FEATURE_PMM_EN     ( 5*32+13) /* PMM enabled */
+
+/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
+#define X86_FEATURE_LAHF_LM    ( 6*32+ 0) /* LAHF/SAHF in long mode */
+#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */
+#define X86_FEATURE_SVM                ( 6*32+ 2) /* Secure virtual machine */
+#define X86_FEATURE_EXTAPIC    ( 6*32+ 3) /* Extended APIC space */
+#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */
+#define X86_FEATURE_ABM                ( 6*32+ 5) /* Advanced bit manipulation */
+#define X86_FEATURE_SSE4A      ( 6*32+ 6) /* SSE-4A */
+#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */
+#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */
+#define X86_FEATURE_OSVW       ( 6*32+ 9) /* OS Visible Workaround */
+#define X86_FEATURE_IBS                ( 6*32+10) /* Instruction Based Sampling */
+#define X86_FEATURE_XOP                ( 6*32+11) /* extended AVX instructions */
+#define X86_FEATURE_SKINIT     ( 6*32+12) /* SKINIT/STGI instructions */
+#define X86_FEATURE_WDT                ( 6*32+13) /* Watchdog timer */
+#define X86_FEATURE_LWP                ( 6*32+15) /* Light Weight Profiling */
+#define X86_FEATURE_FMA4       ( 6*32+16) /* 4 operands MAC instructions */
+#define X86_FEATURE_TCE                ( 6*32+17) /* translation cache extension */
+#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */
+#define X86_FEATURE_TBM                ( 6*32+21) /* trailing bit manipulations */
+#define X86_FEATURE_TOPOEXT    ( 6*32+22) /* topology extensions CPUID leafs */
+#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */
+#define X86_FEATURE_PERFCTR_NB  ( 6*32+24) /* NB performance counter extensions */
+#define X86_FEATURE_BPEXT      (6*32+26) /* data breakpoint extension */
+#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */
+#define X86_FEATURE_MWAITX     ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
+
+/*
+ * Auxiliary flags: Linux defined - For features scattered in various
+ * CPUID levels like 0x6, 0xA etc, word 7.
+ *
+ * Reuse free bits when adding new feature flags!
+ */
+
+#define X86_FEATURE_CPB                ( 7*32+ 2) /* AMD Core Performance Boost */
+#define X86_FEATURE_EPB                ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
+
+#define X86_FEATURE_HW_PSTATE  ( 7*32+ 8) /* AMD HW-PState */
+#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
+
+#define X86_FEATURE_INTEL_PT   ( 7*32+15) /* Intel Processor Trace */
+
+/* Virtualization flags: Linux defined, word 8 */
+#define X86_FEATURE_TPR_SHADOW  ( 8*32+ 0) /* Intel TPR Shadow */
+#define X86_FEATURE_VNMI        ( 8*32+ 1) /* Intel Virtual NMI */
+#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */
+#define X86_FEATURE_EPT         ( 8*32+ 3) /* Intel Extended Page Table */
+#define X86_FEATURE_VPID        ( 8*32+ 4) /* Intel Virtual Processor ID */
+
+#define X86_FEATURE_VMMCALL     ( 8*32+15) /* Prefer vmmcall to vmcall */
+#define X86_FEATURE_XENPV       ( 8*32+16) /* "" Xen paravirtual guest */
+
+
+/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
+#define X86_FEATURE_FSGSBASE   ( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
+#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3b */
+#define X86_FEATURE_BMI1       ( 9*32+ 3) /* 1st group bit manipulation extensions */
+#define X86_FEATURE_HLE                ( 9*32+ 4) /* Hardware Lock Elision */
+#define X86_FEATURE_AVX2       ( 9*32+ 5) /* AVX2 instructions */
+#define X86_FEATURE_SMEP       ( 9*32+ 7) /* Supervisor Mode Execution Protection */
+#define X86_FEATURE_BMI2       ( 9*32+ 8) /* 2nd group bit manipulation extensions */
+#define X86_FEATURE_ERMS       ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */
+#define X86_FEATURE_INVPCID    ( 9*32+10) /* Invalidate Processor Context ID */
+#define X86_FEATURE_RTM                ( 9*32+11) /* Restricted Transactional Memory */
+#define X86_FEATURE_CQM                ( 9*32+12) /* Cache QoS Monitoring */
+#define X86_FEATURE_MPX                ( 9*32+14) /* Memory Protection Extension */
+#define X86_FEATURE_AVX512F    ( 9*32+16) /* AVX-512 Foundation */
+#define X86_FEATURE_AVX512DQ   ( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */
+#define X86_FEATURE_RDSEED     ( 9*32+18) /* The RDSEED instruction */
+#define X86_FEATURE_ADX                ( 9*32+19) /* The ADCX and ADOX instructions */
+#define X86_FEATURE_SMAP       ( 9*32+20) /* Supervisor Mode Access Prevention */
+#define X86_FEATURE_PCOMMIT    ( 9*32+22) /* PCOMMIT instruction */
+#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
+#define X86_FEATURE_CLWB       ( 9*32+24) /* CLWB instruction */
+#define X86_FEATURE_AVX512PF   ( 9*32+26) /* AVX-512 Prefetch */
+#define X86_FEATURE_AVX512ER   ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
+#define X86_FEATURE_AVX512CD   ( 9*32+28) /* AVX-512 Conflict Detection */
+#define X86_FEATURE_SHA_NI     ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */
+#define X86_FEATURE_AVX512BW   ( 9*32+30) /* AVX-512 BW (Byte/Word granular) Instructions */
+#define X86_FEATURE_AVX512VL   ( 9*32+31) /* AVX-512 VL (128/256 Vector Length) Extensions */
+
+/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */
+#define X86_FEATURE_XSAVEOPT   (10*32+ 0) /* XSAVEOPT */
+#define X86_FEATURE_XSAVEC     (10*32+ 1) /* XSAVEC */
+#define X86_FEATURE_XGETBV1    (10*32+ 2) /* XGETBV with ECX = 1 */
+#define X86_FEATURE_XSAVES     (10*32+ 3) /* XSAVES/XRSTORS */
+
+/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11 */
+#define X86_FEATURE_CQM_LLC    (11*32+ 1) /* LLC QoS if 1 */
+
+/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */
+#define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */
+
+/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */
+#define X86_FEATURE_CLZERO     (13*32+0) /* CLZERO instruction */
+
+/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */
+#define X86_FEATURE_DTHERM     (14*32+ 0) /* Digital Thermal Sensor */
+#define X86_FEATURE_IDA                (14*32+ 1) /* Intel Dynamic Acceleration */
+#define X86_FEATURE_ARAT       (14*32+ 2) /* Always Running APIC Timer */
+#define X86_FEATURE_PLN                (14*32+ 4) /* Intel Power Limit Notification */
+#define X86_FEATURE_PTS                (14*32+ 6) /* Intel Package Thermal Status */
+#define X86_FEATURE_HWP                (14*32+ 7) /* Intel Hardware P-states */
+#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */
+#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */
+#define X86_FEATURE_HWP_EPP    (14*32+10) /* HWP Energy Perf. Preference */
+#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */
+
+/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */
+#define X86_FEATURE_NPT                (15*32+ 0) /* Nested Page Table support */
+#define X86_FEATURE_LBRV       (15*32+ 1) /* LBR Virtualization support */
+#define X86_FEATURE_SVML       (15*32+ 2) /* "svm_lock" SVM locking MSR */
+#define X86_FEATURE_NRIPS      (15*32+ 3) /* "nrip_save" SVM next_rip save */
+#define X86_FEATURE_TSCRATEMSR  (15*32+ 4) /* "tsc_scale" TSC scaling support */
+#define X86_FEATURE_VMCBCLEAN   (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */
+#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */
+#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */
+#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */
+#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
+#define X86_FEATURE_AVIC       (15*32+13) /* Virtual Interrupt Controller */
+
+/*
+ * BUG word(s)
+ */
+#define X86_BUG(x)             (NCAPINTS*32 + (x))
+
+#define X86_BUG_F00F           X86_BUG(0) /* Intel F00F */
+#define X86_BUG_FDIV           X86_BUG(1) /* FPU FDIV */
+#define X86_BUG_COMA           X86_BUG(2) /* Cyrix 6x86 coma */
+#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */
+#define X86_BUG_AMD_APIC_C1E   X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */
+#define X86_BUG_11AP           X86_BUG(5) /* Bad local APIC aka 11AP */
+#define X86_BUG_FXSAVE_LEAK    X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
+#define X86_BUG_CLFLUSH_MONITOR        X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
+#define X86_BUG_SYSRET_SS_ATTRS        X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
+
+#ifdef CONFIG_X86_32
+/*
+ * 64-bit kernels don't use X86_BUG_ESPFIX.  Make the define conditional
+ * to avoid confusion.
+ */
+#define X86_BUG_ESPFIX         X86_BUG(9) /* "" IRET to 16-bit SS corrupts ESP/RSP high bits */
+#endif
+
+#endif /* _ASM_X86_CPUFEATURES_H */
index 278441f39856edf31edca4f5391479c356b19a61..eb5deb42484d5e283adeaa191c004d1566f11a7f 100644 (file)
@@ -98,4 +98,27 @@ struct desc_ptr {
 
 #endif /* !__ASSEMBLY__ */
 
+/* Access rights as returned by LAR */
+#define AR_TYPE_RODATA         (0 * (1 << 9))
+#define AR_TYPE_RWDATA         (1 * (1 << 9))
+#define AR_TYPE_RODATA_EXPDOWN (2 * (1 << 9))
+#define AR_TYPE_RWDATA_EXPDOWN (3 * (1 << 9))
+#define AR_TYPE_XOCODE         (4 * (1 << 9))
+#define AR_TYPE_XRCODE         (5 * (1 << 9))
+#define AR_TYPE_XOCODE_CONF    (6 * (1 << 9))
+#define AR_TYPE_XRCODE_CONF    (7 * (1 << 9))
+#define AR_TYPE_MASK           (7 * (1 << 9))
+
+#define AR_DPL0                        (0 * (1 << 13))
+#define AR_DPL3                        (3 * (1 << 13))
+#define AR_DPL_MASK            (3 * (1 << 13))
+
+#define AR_A                   (1 << 8)   /* "Accessed" */
+#define AR_S                   (1 << 12)  /* If clear, "System" segment */
+#define AR_P                   (1 << 15)  /* "Present" */
+#define AR_AVL                 (1 << 20)  /* "AVaiLable" (no HW effect) */
+#define AR_L                   (1 << 21)  /* "Long mode" for code segments */
+#define AR_DB                  (1 << 22)  /* D/B, effect depends on type */
+#define AR_G                   (1 << 23)  /* "Granularity" (limit in pages) */
+
 #endif /* _ASM_X86_DESC_DEFS_H */
index 535192f6bfad8d67c27235377e1e549b8ba89276..3c69fed215c56c3203e59d97a6c7e11381c97cf8 100644 (file)
@@ -15,7 +15,7 @@ static __always_inline __init void *dmi_alloc(unsigned len)
 /* Use early IO mappings for DMI because it's initialized early */
 #define dmi_early_remap                early_ioremap
 #define dmi_early_unmap                early_iounmap
-#define dmi_remap              ioremap
+#define dmi_remap              ioremap_cache
 #define dmi_unmap              iounmap
 
 #endif /* _ASM_X86_DMI_H */
index 1514753fd43553e079696712b48a8d08b6966e98..15340e36ddcb3364e16eb63cd61c61a42676d756 100644 (file)
@@ -256,7 +256,7 @@ extern int force_personality32;
    instruction set this CPU supports.  This could be done in user space,
    but it's not easy, and we've already done it here.  */
 
-#define ELF_HWCAP              (boot_cpu_data.x86_capability[0])
+#define ELF_HWCAP              (boot_cpu_data.x86_capability[CPUID_1_EDX])
 
 /* This yields a string that ld.so will use to load implementation
    specific libraries for optimization.  This is more specific in
index 6d7d0e52ed5a5388b87e834083d90307a6a250ba..8554f960e21b7ce0d05dfb67fa36f6cff974650e 100644 (file)
@@ -138,7 +138,7 @@ extern void reserve_top_address(unsigned long reserve);
 extern int fixmaps_set;
 
 extern pte_t *kmap_pte;
-extern pgprot_t kmap_prot;
+#define kmap_prot PAGE_KERNEL
 extern pte_t *pkmap_page_table;
 
 void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
index 0fd440df63f18d77c040f8683f34018ed426b4b2..a2124343edf5448fa06eece0015729505cf93412 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/user.h>
 #include <asm/fpu/api.h>
 #include <asm/fpu/xstate.h>
+#include <asm/cpufeature.h>
 
 /*
  * High level FPU state handling functions:
@@ -58,22 +59,22 @@ extern u64 fpu__get_supported_xfeatures_mask(void);
  */
 static __always_inline __pure bool use_eager_fpu(void)
 {
-       return static_cpu_has_safe(X86_FEATURE_EAGER_FPU);
+       return static_cpu_has(X86_FEATURE_EAGER_FPU);
 }
 
 static __always_inline __pure bool use_xsaveopt(void)
 {
-       return static_cpu_has_safe(X86_FEATURE_XSAVEOPT);
+       return static_cpu_has(X86_FEATURE_XSAVEOPT);
 }
 
 static __always_inline __pure bool use_xsave(void)
 {
-       return static_cpu_has_safe(X86_FEATURE_XSAVE);
+       return static_cpu_has(X86_FEATURE_XSAVE);
 }
 
 static __always_inline __pure bool use_fxsr(void)
 {
-       return static_cpu_has_safe(X86_FEATURE_FXSR);
+       return static_cpu_has(X86_FEATURE_FXSR);
 }
 
 /*
@@ -300,7 +301,7 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate)
 
        WARN_ON(system_state != SYSTEM_BOOTING);
 
-       if (static_cpu_has_safe(X86_FEATURE_XSAVES))
+       if (static_cpu_has(X86_FEATURE_XSAVES))
                XSTATE_OP(XSAVES, xstate, lmask, hmask, err);
        else
                XSTATE_OP(XSAVE, xstate, lmask, hmask, err);
@@ -322,7 +323,7 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)
 
        WARN_ON(system_state != SYSTEM_BOOTING);
 
-       if (static_cpu_has_safe(X86_FEATURE_XSAVES))
+       if (static_cpu_has(X86_FEATURE_XSAVES))
                XSTATE_OP(XRSTORS, xstate, lmask, hmask, err);
        else
                XSTATE_OP(XRSTOR, xstate, lmask, hmask, err);
@@ -460,7 +461,7 @@ static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate)
         * pending. Clear the x87 state here by setting it to fixed values.
         * "m" is a random variable that should be in L1.
         */
-       if (unlikely(static_cpu_has_bug_safe(X86_BUG_FXSAVE_LEAK))) {
+       if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) {
                asm volatile(
                        "fnclex\n\t"
                        "emms\n\t"
@@ -589,7 +590,8 @@ switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)
         * If the task has used the math, pre-load the FPU on xsave processors
         * or if the past 5 consecutive context-switches used math.
         */
-       fpu.preload = new_fpu->fpstate_active &&
+       fpu.preload = static_cpu_has(X86_FEATURE_FPU) &&
+                     new_fpu->fpstate_active &&
                      (use_eager_fpu() || new_fpu->counter > 5);
 
        if (old_fpu->fpregs_active) {
index af30fdeb140da75691e91c52446f7f1bb7fe2e93..f23cd8c80b1c818057053e831ec704ab4006fba4 100644 (file)
 
 /* Supported features which support lazy state saving */
 #define XFEATURE_MASK_LAZY     (XFEATURE_MASK_FP | \
-                                XFEATURE_MASK_SSE)
-
-/* Supported features which require eager state saving */
-#define XFEATURE_MASK_EAGER    (XFEATURE_MASK_BNDREGS | \
-                                XFEATURE_MASK_BNDCSR | \
+                                XFEATURE_MASK_SSE | \
                                 XFEATURE_MASK_YMM | \
                                 XFEATURE_MASK_OPMASK | \
                                 XFEATURE_MASK_ZMM_Hi256 | \
                                 XFEATURE_MASK_Hi16_ZMM)
 
+/* Supported features which require eager state saving */
+#define XFEATURE_MASK_EAGER    (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR)
+
 /* All currently supported features */
 #define XCNTXT_MASK    (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER)
 
index 793179cf8e21aa89636f869fc3a9e2fe0b4a29e0..6e4d170726b758a75a46777f416d07bc7ada01e7 100644 (file)
@@ -1,23 +1,44 @@
-#ifdef __ASSEMBLY__
+#ifndef _ASM_X86_FRAME_H
+#define _ASM_X86_FRAME_H
 
 #include <asm/asm.h>
 
-/* The annotation hides the frame from the unwinder and makes it look
-   like a ordinary ebp save/restore. This avoids some special cases for
-   frame pointer later */
+/*
+ * These are stack frame creation macros.  They should be used by every
+ * callable non-leaf asm function to make kernel stack traces more reliable.
+ */
+
 #ifdef CONFIG_FRAME_POINTER
-       .macro FRAME
-       __ASM_SIZE(push,)       %__ASM_REG(bp)
-       __ASM_SIZE(mov)         %__ASM_REG(sp), %__ASM_REG(bp)
-       .endm
-       .macro ENDFRAME
-       __ASM_SIZE(pop,)        %__ASM_REG(bp)
-       .endm
-#else
-       .macro FRAME
-       .endm
-       .macro ENDFRAME
-       .endm
-#endif
-
-#endif  /*  __ASSEMBLY__  */
+
+#ifdef __ASSEMBLY__
+
+.macro FRAME_BEGIN
+       push %_ASM_BP
+       _ASM_MOV %_ASM_SP, %_ASM_BP
+.endm
+
+.macro FRAME_END
+       pop %_ASM_BP
+.endm
+
+#else /* !__ASSEMBLY__ */
+
+#define FRAME_BEGIN                            \
+       "push %" _ASM_BP "\n"                   \
+       _ASM_MOV "%" _ASM_SP ", %" _ASM_BP "\n"
+
+#define FRAME_END "pop %" _ASM_BP "\n"
+
+#endif /* __ASSEMBLY__ */
+
+#define FRAME_OFFSET __ASM_SEL(4, 8)
+
+#else /* !CONFIG_FRAME_POINTER */
+
+#define FRAME_BEGIN
+#define FRAME_END
+#define FRAME_OFFSET 0
+
+#endif /* CONFIG_FRAME_POINTER */
+
+#endif /* _ASM_X86_FRAME_H */
index cd2ce4068441b7e938fa93f49ef6b16213866d18..ebea2c9d2cdc05940c95ee0b42e93fb70c593a89 100644 (file)
@@ -53,7 +53,7 @@
 #define IMR_MASK               (IMR_ALIGN - 1)
 
 int imr_add_range(phys_addr_t base, size_t size,
-                 unsigned int rmask, unsigned int wmask, bool lock);
+                 unsigned int rmask, unsigned int wmask);
 
 int imr_remove_range(phys_addr_t base, size_t size);
 
index cfc9a0d2d07ce4b6d2bf2a3dc1aa623114eb11bb..a4fe16e42b7b268a736431cccccd5b73ac632fa1 100644 (file)
@@ -57,67 +57,13 @@ static inline void __xapic_wait_icr_idle(void)
                cpu_relax();
 }
 
-static inline void
-__default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
-{
-       /*
-        * Subtle. In the case of the 'never do double writes' workaround
-        * we have to lock out interrupts to be safe.  As we don't care
-        * of the value read we use an atomic rmw access to avoid costly
-        * cli/sti.  Otherwise we use an even cheaper single atomic write
-        * to the APIC.
-        */
-       unsigned int cfg;
-
-       /*
-        * Wait for idle.
-        */
-       __xapic_wait_icr_idle();
-
-       /*
-        * No need to touch the target chip field
-        */
-       cfg = __prepare_ICR(shortcut, vector, dest);
-
-       /*
-        * Send the IPI. The write to APIC_ICR fires this off.
-        */
-       native_apic_mem_write(APIC_ICR, cfg);
-}
+void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest);
 
 /*
  * This is used to send an IPI with no shorthand notation (the destination is
  * specified in bits 56 to 63 of the ICR).
  */
-static inline void
- __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
-{
-       unsigned long cfg;
-
-       /*
-        * Wait for idle.
-        */
-       if (unlikely(vector == NMI_VECTOR))
-               safe_apic_wait_icr_idle();
-       else
-               __xapic_wait_icr_idle();
-
-       /*
-        * prepare target chip field
-        */
-       cfg = __prepare_ICR2(mask);
-       native_apic_mem_write(APIC_ICR2, cfg);
-
-       /*
-        * program the ICR
-        */
-       cfg = __prepare_ICR(0, vector, dest);
-
-       /*
-        * Send the IPI. The write to APIC_ICR fires this off.
-        */
-       native_apic_mem_write(APIC_ICR, cfg);
-}
+void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest);
 
 extern void default_send_IPI_single(int cpu, int vector);
 extern void default_send_IPI_single_phys(int cpu, int vector);
index 78162f8e248bdc77c2625238f821791d837d24d4..d0afb05c84fc1ffd434e85f6267326b9091d2595 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _ASM_IRQ_WORK_H
 #define _ASM_IRQ_WORK_H
 
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 
 static inline bool arch_irq_work_has_interrupt(void)
 {
index 44adbb81904184da0cbbab08807075a24918ba28..01c8b501cb6d5afbdd5eb1c5dfaba366ea158cf8 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/mtrr.h>
 #include <asm/msr-index.h>
 #include <asm/asm.h>
+#include <asm/kvm_page_track.h>
 
 #define KVM_MAX_VCPUS 255
 #define KVM_SOFT_MAX_VCPUS 160
@@ -214,6 +215,14 @@ struct kvm_mmu_memory_cache {
        void *objects[KVM_NR_MEM_OBJS];
 };
 
+/*
+ * the pages used as guest page table on soft mmu are tracked by
+ * kvm_memory_slot.arch.gfn_track which is 16 bits, so the role bits used
+ * by indirect shadow page can not be more than 15 bits.
+ *
+ * Currently, we used 14 bits that are @level, @cr4_pae, @quadrant, @access,
+ * @nxe, @cr0_wp, @smep_andnot_wp and @smap_andnot_wp.
+ */
 union kvm_mmu_page_role {
        unsigned word;
        struct {
@@ -276,7 +285,7 @@ struct kvm_mmu_page {
 #endif
 
        /* Number of writes since the last time traversal visited this page.  */
-       int write_flooding_count;
+       atomic_t write_flooding_count;
 };
 
 struct kvm_pio_request {
@@ -338,12 +347,8 @@ struct kvm_mmu {
 
        struct rsvd_bits_validate guest_rsvd_check;
 
-       /*
-        * Bitmap: bit set = last pte in walk
-        * index[0:1]: level (zero-based)
-        * index[2]: pte.ps
-        */
-       u8 last_pte_bitmap;
+       /* Can have large pages at levels 2..last_nonleaf_level-1. */
+       u8 last_nonleaf_level;
 
        bool nx;
 
@@ -498,7 +503,6 @@ struct kvm_vcpu_arch {
        struct kvm_mmu_memory_cache mmu_page_header_cache;
 
        struct fpu guest_fpu;
-       bool eager_fpu;
        u64 xcr0;
        u64 guest_supported_xcr0;
        u32 guest_xstate_size;
@@ -644,12 +648,13 @@ struct kvm_vcpu_arch {
 };
 
 struct kvm_lpage_info {
-       int write_count;
+       int disallow_lpage;
 };
 
 struct kvm_arch_memory_slot {
        struct kvm_rmap_head *rmap[KVM_NR_PAGE_SIZES];
        struct kvm_lpage_info *lpage_info[KVM_NR_PAGE_SIZES - 1];
+       unsigned short *gfn_track[KVM_PAGE_TRACK_MAX];
 };
 
 /*
@@ -694,6 +699,8 @@ struct kvm_arch {
         */
        struct list_head active_mmu_pages;
        struct list_head zapped_obsolete_pages;
+       struct kvm_page_track_notifier_node mmu_sp_tracker;
+       struct kvm_page_track_notifier_head track_notifier_head;
 
        struct list_head assigned_dev_head;
        struct iommu_domain *iommu_domain;
@@ -754,6 +761,8 @@ struct kvm_arch {
 
        bool irqchip_split;
        u8 nr_reserved_ioapic_pins;
+
+       bool disabled_lapic_found;
 };
 
 struct kvm_vm_stat {
@@ -988,6 +997,8 @@ void kvm_mmu_module_exit(void);
 void kvm_mmu_destroy(struct kvm_vcpu *vcpu);
 int kvm_mmu_create(struct kvm_vcpu *vcpu);
 void kvm_mmu_setup(struct kvm_vcpu *vcpu);
+void kvm_mmu_init_vm(struct kvm *kvm);
+void kvm_mmu_uninit_vm(struct kvm *kvm);
 void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
                u64 dirty_mask, u64 nx_mask, u64 x_mask);
 
@@ -1127,8 +1138,6 @@ void kvm_pic_clear_all(struct kvm_pic *pic, int irq_source_id);
 
 void kvm_inject_nmi(struct kvm_vcpu *vcpu);
 
-void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-                      const u8 *new, int bytes);
 int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn);
 int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
 void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h
new file mode 100644 (file)
index 0000000..c2b8d24
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _ASM_X86_KVM_PAGE_TRACK_H
+#define _ASM_X86_KVM_PAGE_TRACK_H
+
+enum kvm_page_track_mode {
+       KVM_PAGE_TRACK_WRITE,
+       KVM_PAGE_TRACK_MAX,
+};
+
+/*
+ * The notifier represented by @kvm_page_track_notifier_node is linked into
+ * the head which will be notified when guest is triggering the track event.
+ *
+ * Write access on the head is protected by kvm->mmu_lock, read access
+ * is protected by track_srcu.
+ */
+struct kvm_page_track_notifier_head {
+       struct srcu_struct track_srcu;
+       struct hlist_head track_notifier_list;
+};
+
+struct kvm_page_track_notifier_node {
+       struct hlist_node node;
+
+       /*
+        * It is called when guest is writing the write-tracked page
+        * and write emulation is finished at that time.
+        *
+        * @vcpu: the vcpu where the write access happened.
+        * @gpa: the physical address written by guest.
+        * @new: the data was written to the address.
+        * @bytes: the written length.
+        */
+       void (*track_write)(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
+                           int bytes);
+};
+
+void kvm_page_track_init(struct kvm *kvm);
+
+void kvm_page_track_free_memslot(struct kvm_memory_slot *free,
+                                struct kvm_memory_slot *dont);
+int kvm_page_track_create_memslot(struct kvm_memory_slot *slot,
+                                 unsigned long npages);
+
+void kvm_slot_page_track_add_page(struct kvm *kvm,
+                                 struct kvm_memory_slot *slot, gfn_t gfn,
+                                 enum kvm_page_track_mode mode);
+void kvm_slot_page_track_remove_page(struct kvm *kvm,
+                                    struct kvm_memory_slot *slot, gfn_t gfn,
+                                    enum kvm_page_track_mode mode);
+bool kvm_page_track_is_active(struct kvm_vcpu *vcpu, gfn_t gfn,
+                             enum kvm_page_track_mode mode);
+
+void
+kvm_page_track_register_notifier(struct kvm *kvm,
+                                struct kvm_page_track_notifier_node *n);
+void
+kvm_page_track_unregister_notifier(struct kvm *kvm,
+                                  struct kvm_page_track_notifier_node *n);
+void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
+                         int bytes);
+#endif
index c1adf33fdd0d6f70f055b9a056bc7787bda7635e..bc62e7cbf1b1f883fc9acb0a145305384a3bf062 100644 (file)
@@ -17,15 +17,8 @@ static inline bool kvm_check_and_clear_guest_paused(void)
 }
 #endif /* CONFIG_KVM_GUEST */
 
-#ifdef CONFIG_DEBUG_RODATA
 #define KVM_HYPERCALL \
         ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL)
-#else
-/* On AMD processors, vmcall will generate a trap that we will
- * then rewrite to the appropriate instruction.
- */
-#define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1"
-#endif
 
 /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall
  * instruction.  The hypervisor may replace it with something else but only the
index 2ea4527e462f133398f178a885a4b920892cd3f5..92b6f651fa4fcc7e58d5764f317f9db8b0a5616b 100644 (file)
 #define MCI_STATUS_AR   (1ULL<<55)  /* Action required */
 
 /* AMD-specific bits */
-#define MCI_STATUS_DEFERRED    (1ULL<<44)  /* declare an uncorrected error */
+#define MCI_STATUS_DEFERRED    (1ULL<<44)  /* uncorrected error, deferred exception */
 #define MCI_STATUS_POISON      (1ULL<<43)  /* access poisonous data */
+#define MCI_STATUS_TCC         (1ULL<<55)  /* Task context corrupt */
+
+/*
+ * McaX field if set indicates a given bank supports MCA extensions:
+ *  - Deferred error interrupt type is specifiable by bank.
+ *  - MCx_MISC0[BlkPtr] field indicates presence of extended MISC registers,
+ *    But should not be used to determine MSR numbers.
+ *  - TCC bit is present in MCx_STATUS.
+ */
+#define MCI_CONFIG_MCAX                0x1
+#define MCI_IPID_MCATYPE       0xFFFF0000
+#define MCI_IPID_HWID          0xFFF
 
 /*
  * Note that the full MCACOD field of IA32_MCi_STATUS MSR is
 #define MCE_LOG_LEN 32
 #define MCE_LOG_SIGNATURE      "MACHINECHECK"
 
+/* AMD Scalable MCA */
+#define MSR_AMD64_SMCA_MC0_MISC0       0xc0002003
+#define MSR_AMD64_SMCA_MC0_CONFIG      0xc0002004
+#define MSR_AMD64_SMCA_MC0_IPID                0xc0002005
+#define MSR_AMD64_SMCA_MC0_MISC1       0xc000200a
+#define MSR_AMD64_SMCA_MCx_MISC(x)     (MSR_AMD64_SMCA_MC0_MISC0 + 0x10*(x))
+#define MSR_AMD64_SMCA_MCx_CONFIG(x)   (MSR_AMD64_SMCA_MC0_CONFIG + 0x10*(x))
+#define MSR_AMD64_SMCA_MCx_IPID(x)     (MSR_AMD64_SMCA_MC0_IPID + 0x10*(x))
+#define MSR_AMD64_SMCA_MCx_MISCy(x, y) ((MSR_AMD64_SMCA_MC0_MISC1 + y) + (0x10*(x)))
+
 /*
  * This structure contains all data related to the MCE log.  Also
  * carries a signature to make it easier to find from external
@@ -113,6 +135,7 @@ struct mca_config {
        bool ignore_ce;
        bool disabled;
        bool ser;
+       bool recovery;
        bool bios_cmci_threshold;
        u8 banks;
        s8 bootlog;
@@ -287,4 +310,49 @@ struct cper_sec_mem_err;
 extern void apei_mce_report_mem_error(int corrected,
                                      struct cper_sec_mem_err *mem_err);
 
+/*
+ * Enumerate new IP types and HWID values in AMD processors which support
+ * Scalable MCA.
+ */
+#ifdef CONFIG_X86_MCE_AMD
+enum amd_ip_types {
+       SMCA_F17H_CORE = 0,     /* Core errors */
+       SMCA_DF,                /* Data Fabric */
+       SMCA_UMC,               /* Unified Memory Controller */
+       SMCA_PB,                /* Parameter Block */
+       SMCA_PSP,               /* Platform Security Processor */
+       SMCA_SMU,               /* System Management Unit */
+       N_AMD_IP_TYPES
+};
+
+struct amd_hwid {
+       const char *name;
+       unsigned int hwid;
+};
+
+extern struct amd_hwid amd_hwids[N_AMD_IP_TYPES];
+
+enum amd_core_mca_blocks {
+       SMCA_LS = 0,    /* Load Store */
+       SMCA_IF,        /* Instruction Fetch */
+       SMCA_L2_CACHE,  /* L2 cache */
+       SMCA_DE,        /* Decoder unit */
+       RES,            /* Reserved */
+       SMCA_EX,        /* Execution unit */
+       SMCA_FP,        /* Floating Point */
+       SMCA_L3_CACHE,  /* L3 cache */
+       N_CORE_MCA_BLOCKS
+};
+
+extern const char * const amd_core_mcablock_names[N_CORE_MCA_BLOCKS];
+
+enum amd_df_mca_blocks {
+       SMCA_CS = 0,    /* Coherent Slave */
+       SMCA_PIE,       /* Power management, Interrupts, etc */
+       N_DF_BLOCKS
+};
+
+extern const char * const amd_df_mcablock_names[N_DF_BLOCKS];
+#endif
+
 #endif /* _ASM_X86_MCE_H */
index 1e1b07a5a7388d45eaaf46e032efd8ee14569662..9d3a96c4da789230f9aeb523e6af35e4fe4a8db3 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm/cpu.h>
 #include <linux/earlycpio.h>
+#include <linux/initrd.h>
 
 #define native_rdmsr(msr, val1, val2)                  \
 do {                                                   \
@@ -143,4 +144,29 @@ static inline void reload_early_microcode(void)                    { }
 static inline bool
 get_builtin_firmware(struct cpio_data *cd, const char *name)   { return false; }
 #endif
+
+static inline unsigned long get_initrd_start(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+       return initrd_start;
+#else
+       return 0;
+#endif
+}
+
+static inline unsigned long get_initrd_start_addr(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+#ifdef CONFIG_X86_32
+       unsigned long *initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
+
+       return (unsigned long)__pa_nodebug(*initrd_start_p);
+#else
+       return get_initrd_start();
+#endif
+#else /* CONFIG_BLK_DEV_INITRD */
+       return 0;
+#endif
+}
+
 #endif /* _ASM_X86_MICROCODE_H */
index 8559b0102ea1f14dfc840c28df6e1fcc0f813965..603417f8dd6cfcf3424ff410f820bab254209c9d 100644 (file)
@@ -40,7 +40,6 @@ struct extended_sigtable {
 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
 #define EXT_HEADER_SIZE                (sizeof(struct extended_sigtable))
 #define EXT_SIGNATURE_SIZE     (sizeof(struct extended_signature))
-#define DWSIZE                 (sizeof(u32))
 
 #define get_totalsize(mc) \
        (((struct microcode_intel *)mc)->hdr.datasize ? \
index 55234d5e7160db83bd9854a40c87b8e70593b3c7..1ea0baef1175c407e9097e125a84b226be28266c 100644 (file)
@@ -19,7 +19,8 @@ typedef struct {
 #endif
 
        struct mutex lock;
-       void __user *vdso;
+       void __user *vdso;                      /* vdso base address */
+       const struct vdso_image *vdso_image;    /* vdso image in use */
 
        atomic_t perf_rdpmc_allowed;    /* nonzero if rdpmc is allowed */
 } mm_context_t;
index b05402ef3b842203f97def484806bec3c2320b9c..2da46ac16e3750441294d983d82f359fdccdb0a4 100644 (file)
@@ -1,7 +1,12 @@
 #ifndef _ASM_X86_MSR_INDEX_H
 #define _ASM_X86_MSR_INDEX_H
 
-/* CPU model specific register (MSR) numbers */
+/*
+ * CPU model specific register (MSR) numbers.
+ *
+ * Do not add new entries to this file unless the definitions are shared
+ * between multiple compilation units.
+ */
 
 /* x86-64 specific MSRs */
 #define MSR_EFER               0xc0000080 /* extended feature register */
 #define HWP_PACKAGE_LEVEL_REQUEST_BIT  (1<<11)
 
 /* IA32_HWP_CAPABILITIES */
-#define HWP_HIGHEST_PERF(x)            (x & 0xff)
-#define HWP_GUARANTEED_PERF(x)         ((x & (0xff << 8)) >>8)
-#define HWP_MOSTEFFICIENT_PERF(x)      ((x & (0xff << 16)) >>16)
-#define HWP_LOWEST_PERF(x)             ((x & (0xff << 24)) >>24)
+#define HWP_HIGHEST_PERF(x)            (((x) >> 0) & 0xff)
+#define HWP_GUARANTEED_PERF(x)         (((x) >> 8) & 0xff)
+#define HWP_MOSTEFFICIENT_PERF(x)      (((x) >> 16) & 0xff)
+#define HWP_LOWEST_PERF(x)             (((x) >> 24) & 0xff)
 
 /* IA32_HWP_REQUEST */
 #define HWP_MIN_PERF(x)                (x & 0xff)
index c70689b5e5aa4c07f06aabd4edd3d344df207c3e..0deeb2d26df7cd7510e831d04d4f80ed297acaf0 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <linux/sched.h>
 
+#include <asm/cpufeature.h>
+
 #define MWAIT_SUBSTATE_MASK            0xf
 #define MWAIT_CSTATE_MASK              0xf
 #define MWAIT_SUBSTATE_SIZE            4
index 462594320d39a93b835dde080d1b7ae9f9e9819a..9ab7507ca1c2ce785291525d42fc14f58a92c79e 100644 (file)
@@ -20,6 +20,9 @@ struct pci_sysdata {
 #ifdef CONFIG_X86_64
        void            *iommu;         /* IOMMU private data */
 #endif
+#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+       void            *fwnode;        /* IRQ domain for MSI assignment */
+#endif
 };
 
 extern int pci_routeirq;
@@ -32,6 +35,7 @@ extern int noioapicreroute;
 static inline int pci_domain_nr(struct pci_bus *bus)
 {
        struct pci_sysdata *sd = bus->sysdata;
+
        return sd->domain;
 }
 
@@ -41,6 +45,17 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 }
 #endif
 
+#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+static inline void *_pci_root_bus_fwnode(struct pci_bus *bus)
+{
+       struct pci_sysdata *sd = bus->sysdata;
+
+       return sd->fwnode;
+}
+
+#define pci_root_bus_fwnode    _pci_root_bus_fwnode
+#endif
+
 /* Can be used to override the logic in pci_scan_bus for skipping
    already-configured bus numbers - to be used for buggy BIOSes
    or architectures with incomplete PCI setup by the loader */
@@ -105,9 +120,6 @@ void native_restore_msi_irqs(struct pci_dev *dev);
 #include <asm/pci_64.h>
 #endif
 
-/* implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 /* generic pci stuff */
 #include <asm-generic/pci.h>
 
index 46873fbd44e1b522b5d40ad5ebf963714df566a1..d08eacd298c2f4b2436b9841203dd5c90f295697 100644 (file)
@@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
 extern void (*pcibios_disable_irq)(struct pci_dev *dev);
 
+extern bool mp_should_keep_irq(struct device *dev);
+
 struct pci_raw_ops {
        int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
                                                int reg, int len, u32 *val);
index 7bcb861a04e5cf5b32c2c26919756fa29353cb07..5a2ed3ed2f261893d5de08022ea3259198c8c0fe 100644 (file)
@@ -165,6 +165,7 @@ struct x86_pmu_capability {
 #define GLOBAL_STATUS_ASIF                             BIT_ULL(60)
 #define GLOBAL_STATUS_COUNTERS_FROZEN                  BIT_ULL(59)
 #define GLOBAL_STATUS_LBRS_FROZEN                      BIT_ULL(58)
+#define GLOBAL_STATUS_TRACE_TOPAPMI                    BIT_ULL(55)
 
 /*
  * IBS cpuid feature detection
index 20c11d1aa4ccce11b0709c3fe56092a5505151cf..983738ac014c6508f499b26650d44b6f5b3b1b2b 100644 (file)
@@ -13,7 +13,7 @@ struct vm86;
 #include <asm/types.h>
 #include <uapi/asm/sigcontext.h>
 #include <asm/current.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/page.h>
 #include <asm/pgtable_types.h>
 #include <asm/percpu.h>
@@ -24,7 +24,6 @@ struct vm86;
 #include <asm/fpu/types.h>
 
 #include <linux/personality.h>
-#include <linux/cpumask.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <linux/math64.h>
@@ -129,6 +128,8 @@ struct cpuinfo_x86 {
        u16                     booted_cores;
        /* Physical processor id: */
        u16                     phys_proc_id;
+       /* Logical processor id: */
+       u16                     logical_proc_id;
        /* Core id: */
        u16                     cpu_core_id;
        /* Compute unit id */
@@ -298,10 +299,13 @@ struct tss_struct {
         */
        unsigned long           io_bitmap[IO_BITMAP_LONGS + 1];
 
+#ifdef CONFIG_X86_32
        /*
-        * Space for the temporary SYSENTER stack:
+        * Space for the temporary SYSENTER stack.
         */
+       unsigned long           SYSENTER_stack_canary;
        unsigned long           SYSENTER_stack[64];
+#endif
 
 } ____cacheline_aligned;
 
index a4a77286cb1ddf68b466e934e9f69cb1785f3062..9b9b30b1944187c8c3de3ed5c4ef1d82ea7c422d 100644 (file)
@@ -7,12 +7,23 @@
 
 void syscall_init(void);
 
+#ifdef CONFIG_X86_64
 void entry_SYSCALL_64(void);
-void entry_SYSCALL_compat(void);
+#endif
+
+#ifdef CONFIG_X86_32
 void entry_INT80_32(void);
-void entry_INT80_compat(void);
 void entry_SYSENTER_32(void);
+void __begin_SYSENTER_singlestep_region(void);
+void __end_SYSENTER_singlestep_region(void);
+#endif
+
+#ifdef CONFIG_IA32_EMULATION
 void entry_SYSENTER_compat(void);
+void __end_entry_SYSENTER_compat(void);
+void entry_SYSCALL_compat(void);
+void entry_INT80_compat(void);
+#endif
 
 void x86_configure_nx(void);
 void x86_report_nx(void);
index 0a5242428659045cfb439d3045593cc1c63aad96..13b6cdd0af57049468e47ef884e6eccba49dca0e 100644 (file)
@@ -7,7 +7,7 @@
 extern char __brk_base[], __brk_limit[];
 extern struct exception_table_entry __stop___ex_table[];
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
+#if defined(CONFIG_X86_64)
 extern char __end_rodata_hpage_align[];
 #endif
 
index 89db46752a8f0e1c78c9403ef4b40a805b488999..452c88b8ad0691cc4d22ae4289d9f0cfa6b5c332 100644 (file)
@@ -13,7 +13,6 @@
                         X86_EFLAGS_CF | X86_EFLAGS_RF)
 
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
-int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc);
 int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
                     struct pt_regs *regs, unsigned long mask);
 
index ba665ebd17bb8f22a39712dbf2a8c398b9e9207f..db333300bd4be17205daf3b2e820c0af101ccc2d 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/stringify.h>
 #include <asm/nops.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 
 /* "Raw" instruction opcodes */
 #define __ASM_CLAC     .byte 0x0f,0x01,0xca
index dfcf0727623b3f89d53374ea504f243e802be149..20a3de5cb3b0dd5e3362833baebd752c1142ae4e 100644 (file)
@@ -16,7 +16,6 @@
 #endif
 #include <asm/thread_info.h>
 #include <asm/cpumask.h>
-#include <asm/cpufeature.h>
 
 extern int smp_num_siblings;
 extern unsigned int num_processors;
index ff8b9a17dc4b2d354971fb52b60b69e6fbb0e903..ca6ba36077054605580e8b8a6236eab7aa65733f 100644 (file)
@@ -78,6 +78,19 @@ int strcmp(const char *cs, const char *ct);
 #define memset(s, c, n) __memset(s, c, n)
 #endif
 
+/**
+ * memcpy_mcsafe - copy memory with indication if a machine check happened
+ *
+ * @dst:       destination address
+ * @src:       source address
+ * @cnt:       number of bytes to copy
+ *
+ * Low level memory copy function that catches machine checks
+ *
+ * Return true for success, false for fail
+ */
+bool memcpy_mcsafe(void *dst, const void *src, size_t cnt);
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_X86_STRING_64_H */
index c7b551028740f18a5360070a6ccb5dc9ad714c5e..82866697fcf186ac7f63f1f6b5f1f77385dc8ab4 100644 (file)
@@ -49,7 +49,7 @@
  */
 #ifndef __ASSEMBLY__
 struct task_struct;
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <linux/atomic.h>
 
 struct thread_info {
@@ -134,10 +134,13 @@ struct thread_info {
 #define _TIF_ADDR32            (1 << TIF_ADDR32)
 #define _TIF_X32               (1 << TIF_X32)
 
-/* work to do in syscall_trace_enter() */
+/*
+ * work to do in syscall_trace_enter().  Also includes TIF_NOHZ for
+ * enter_from_user_mode()
+ */
 #define _TIF_WORK_SYSCALL_ENTRY        \
        (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | _TIF_SYSCALL_AUDIT |   \
-        _TIF_SECCOMP | _TIF_SINGLESTEP | _TIF_SYSCALL_TRACEPOINT |     \
+        _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT |       \
         _TIF_NOHZ)
 
 /* work to do on any return to user space */
index 6df2029405a3ae55df8b9718dd320b55dde5c1ad..c24b4224d439267051d85af645a026a54fd67f84 100644 (file)
@@ -5,8 +5,57 @@
 #include <linux/sched.h>
 
 #include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <asm/special_insns.h>
 
+static inline void __invpcid(unsigned long pcid, unsigned long addr,
+                            unsigned long type)
+{
+       struct { u64 d[2]; } desc = { { pcid, addr } };
+
+       /*
+        * The memory clobber is because the whole point is to invalidate
+        * stale TLB entries and, especially if we're flushing global
+        * mappings, we don't want the compiler to reorder any subsequent
+        * memory accesses before the TLB flush.
+        *
+        * The hex opcode is invpcid (%ecx), %eax in 32-bit mode and
+        * invpcid (%rcx), %rax in long mode.
+        */
+       asm volatile (".byte 0x66, 0x0f, 0x38, 0x82, 0x01"
+                     : : "m" (desc), "a" (type), "c" (&desc) : "memory");
+}
+
+#define INVPCID_TYPE_INDIV_ADDR                0
+#define INVPCID_TYPE_SINGLE_CTXT       1
+#define INVPCID_TYPE_ALL_INCL_GLOBAL   2
+#define INVPCID_TYPE_ALL_NON_GLOBAL    3
+
+/* Flush all mappings for a given pcid and addr, not including globals. */
+static inline void invpcid_flush_one(unsigned long pcid,
+                                    unsigned long addr)
+{
+       __invpcid(pcid, addr, INVPCID_TYPE_INDIV_ADDR);
+}
+
+/* Flush all mappings for a given PCID, not including globals. */
+static inline void invpcid_flush_single_context(unsigned long pcid)
+{
+       __invpcid(pcid, 0, INVPCID_TYPE_SINGLE_CTXT);
+}
+
+/* Flush all mappings, including globals, for all PCIDs. */
+static inline void invpcid_flush_all(void)
+{
+       __invpcid(0, 0, INVPCID_TYPE_ALL_INCL_GLOBAL);
+}
+
+/* Flush all mappings for all PCIDs except globals. */
+static inline void invpcid_flush_all_nonglobals(void)
+{
+       __invpcid(0, 0, INVPCID_TYPE_ALL_NON_GLOBAL);
+}
+
 #ifdef CONFIG_PARAVIRT
 #include <asm/paravirt.h>
 #else
@@ -104,6 +153,15 @@ static inline void __native_flush_tlb_global(void)
 {
        unsigned long flags;
 
+       if (static_cpu_has(X86_FEATURE_INVPCID)) {
+               /*
+                * Using INVPCID is considerably faster than a pair of writes
+                * to CR4 sandwiched inside an IRQ flag save/restore.
+                */
+               invpcid_flush_all();
+               return;
+       }
+
        /*
         * Read-modify-write to CR4 - protect it from preemption and
         * from interrupts. (Use the raw variant because this code can
index 0fb46482dfde160b9dcfad6ef57841e07c3830e2..7f991bd5031b24947e0773265023ab70b934a7b8 100644 (file)
@@ -119,12 +119,23 @@ static inline void setup_node_to_cpumask_map(void) { }
 
 extern const struct cpumask *cpu_coregroup_mask(int cpu);
 
+#define topology_logical_package_id(cpu)       (cpu_data(cpu).logical_proc_id)
 #define topology_physical_package_id(cpu)      (cpu_data(cpu).phys_proc_id)
 #define topology_core_id(cpu)                  (cpu_data(cpu).cpu_core_id)
 
 #ifdef ENABLE_TOPO_DEFINES
 #define topology_core_cpumask(cpu)             (per_cpu(cpu_core_map, cpu))
 #define topology_sibling_cpumask(cpu)          (per_cpu(cpu_sibling_map, cpu))
+
+extern unsigned int __max_logical_packages;
+#define topology_max_packages()                        (__max_logical_packages)
+int topology_update_package_map(unsigned int apicid, unsigned int cpu);
+extern int topology_phys_to_logical_pkg(unsigned int pkg);
+#else
+#define topology_max_packages()                        (1)
+static inline int
+topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; }
+static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
 #endif
 
 static inline void arch_fix_phys_package_id(int num, u32 slot)
index 6d7c5479bceae12cca3f306ef3067ce8d8067483..174c4212780afde12200fd23a1dbc17a08f40309 100644 (file)
@@ -29,6 +29,8 @@ static inline cycles_t get_cycles(void)
        return rdtsc();
 }
 
+extern struct system_counterval_t convert_art_to_tsc(cycle_t art);
+
 extern void tsc_init(void);
 extern void mark_tsc_unstable(char *reason);
 extern int unsynchronized_tsc(void);
index a4a30e4b2d34321d96ddd02413d037d3f6cb95d9..c0f27d7ea7ff95eaea44987bd94417fabe68ca98 100644 (file)
@@ -90,12 +90,11 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
        likely(!__range_not_ok(addr, size, user_addr_max()))
 
 /*
- * The exception table consists of pairs of addresses relative to the
- * exception table enty itself: the first is the address of an
- * instruction that is allowed to fault, and the second is the address
- * at which the program should continue.  No registers are modified,
- * so it is entirely up to the continuation code to figure out what to
- * do.
+ * The exception table consists of triples of addresses relative to the
+ * exception table entry itself. The first address is of an instruction
+ * that is allowed to fault, the second is the target at which the program
+ * should continue. The third is a handler function to deal with the fault
+ * caused by the instruction in the first field.
  *
  * All the routines below use bits of fixup code that are out of line
  * with the main instruction path.  This means when everything is well,
@@ -104,13 +103,14 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
  */
 
 struct exception_table_entry {
-       int insn, fixup;
+       int insn, fixup, handler;
 };
 /* This is not the generic standard exception_table_entry format */
 #define ARCH_HAS_SORT_EXTABLE
 #define ARCH_HAS_SEARCH_EXTABLE
 
-extern int fixup_exception(struct pt_regs *regs);
+extern int fixup_exception(struct pt_regs *regs, int trapnr);
+extern bool ex_has_fault_handler(unsigned long ip);
 extern int early_fixup_exception(unsigned long *ip);
 
 /*
index b89c34c4019b5818da47434dcd711235a65baa40..307698688fa1cfde037e9d9f96426269b7cd61e9 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/errno.h>
 #include <linux/lockdep.h>
 #include <asm/alternative.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/page.h>
 
 /*
index deabaf9759b640d5cd93f50f9db67ef2dc60a807..43dc55be524e7fdc8e5150f87b02a8639b20b3f3 100644 (file)
@@ -13,9 +13,6 @@ struct vdso_image {
        void *data;
        unsigned long size;   /* Always a multiple of PAGE_SIZE */
 
-       /* text_mapping.pages is big enough for data/size page pointers */
-       struct vm_special_mapping text_mapping;
-
        unsigned long alt, alt_len;
 
        long sym_vvar_start;  /* Negative offset to the vvar area */
index f556c4843aa18af74359dfeb2a41d39d9a2c3bb9..e728699db7741f0282441a79635a88afd23259c8 100644 (file)
@@ -37,6 +37,12 @@ struct vsyscall_gtod_data {
 };
 extern struct vsyscall_gtod_data vsyscall_gtod_data;
 
+extern int vclocks_used;
+static inline bool vclock_was_used(int vclock)
+{
+       return READ_ONCE(vclocks_used) & (1 << vclock);
+}
+
 static inline unsigned gtod_read_begin(const struct vsyscall_gtod_data *s)
 {
        unsigned ret;
index 7956412d09bd8b340a41660d41aed4fac3947a6e..9b1a91834ac8062ce19f3bab02449ced5978fc99 100644 (file)
                (~((1ull << HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT) - 1))
 
 /* Declare the various hypercall operations. */
-#define HV_X64_HV_NOTIFY_LONG_SPIN_WAIT                0x0008
+#define HVCALL_NOTIFY_LONG_SPIN_WAIT           0x0008
+#define HVCALL_POST_MESSAGE                    0x005c
+#define HVCALL_SIGNAL_EVENT                    0x005d
 
 #define HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE             0x00000001
 #define HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT      12
index d485232f1e9f9a1b0f0ba4d44bf8382c39175757..62d4111c1c549a8f1cc70636e708934a83605cde 100644 (file)
@@ -256,7 +256,7 @@ struct sigcontext_64 {
        __u16                           cs;
        __u16                           gs;
        __u16                           fs;
-       __u16                           __pad0;
+       __u16                           ss;
        __u64                           err;
        __u64                           trapno;
        __u64                           oldmask;
@@ -341,9 +341,37 @@ struct sigcontext {
        __u64                           rip;
        __u64                           eflags;         /* RFLAGS */
        __u16                           cs;
+
+       /*
+        * Prior to 2.5.64 ("[PATCH] x86-64 updates for 2.5.64-bk3"),
+        * Linux saved and restored fs and gs in these slots.  This
+        * was counterproductive, as fsbase and gsbase were never
+        * saved, so arch_prctl was presumably unreliable.
+        *
+        * These slots should never be reused without extreme caution:
+        *
+        *  - Some DOSEMU versions stash fs and gs in these slots manually,
+        *    thus overwriting anything the kernel expects to be preserved
+        *    in these slots.
+        *
+        *  - If these slots are ever needed for any other purpose,
+        *    there is some risk that very old 64-bit binaries could get
+        *    confused.  I doubt that many such binaries still work,
+        *    though, since the same patch in 2.5.64 also removed the
+        *    64-bit set_thread_area syscall, so it appears that there
+        *    is no TLS API beyond modify_ldt that works in both pre-
+        *    and post-2.5.64 kernels.
+        *
+        * If the kernel ever adds explicit fs, gs, fsbase, and gsbase
+        * save/restore, it will most likely need to be opt-in and use
+        * different context slots.
+        */
        __u16                           gs;
        __u16                           fs;
-       __u16                           __pad0;
+       union {
+               __u16                   ss;     /* If UC_SIGCONTEXT_SS */
+               __u16                   __pad0; /* Alias name for old (!UC_SIGCONTEXT_SS) user-space */
+       };
        __u64                           err;
        __u64                           trapno;
        __u64                           oldmask;
index b7c29c8017f280ba4cdf58e08557dd94221991fb..e3d1ec90616ed39fcdc259fae324530c5d0477d5 100644 (file)
@@ -1,11 +1,54 @@
 #ifndef _ASM_X86_UCONTEXT_H
 #define _ASM_X86_UCONTEXT_H
 
-#define UC_FP_XSTATE   0x1     /* indicates the presence of extended state
-                                * information in the memory layout pointed
-                                * by the fpstate pointer in the ucontext's
-                                * sigcontext struct (uc_mcontext).
-                                */
+/*
+ * Indicates the presence of extended state information in the memory
+ * layout pointed by the fpstate pointer in the ucontext's sigcontext
+ * struct (uc_mcontext).
+ */
+#define UC_FP_XSTATE   0x1
+
+#ifdef __x86_64__
+/*
+ * UC_SIGCONTEXT_SS will be set when delivering 64-bit or x32 signals on
+ * kernels that save SS in the sigcontext.  All kernels that set
+ * UC_SIGCONTEXT_SS will correctly restore at least the low 32 bits of esp
+ * regardless of SS (i.e. they implement espfix).
+ *
+ * Kernels that set UC_SIGCONTEXT_SS will also set UC_STRICT_RESTORE_SS
+ * when delivering a signal that came from 64-bit code.
+ *
+ * Sigreturn restores SS as follows:
+ *
+ * if (saved SS is valid || UC_STRICT_RESTORE_SS is set ||
+ *     saved CS is not 64-bit)
+ *         new SS = saved SS  (will fail IRET and signal if invalid)
+ * else
+ *         new SS = a flat 32-bit data segment
+ *
+ * This behavior serves three purposes:
+ *
+ * - Legacy programs that construct a 64-bit sigcontext from scratch
+ *   with zero or garbage in the SS slot (e.g. old CRIU) and call
+ *   sigreturn will still work.
+ *
+ * - Old DOSEMU versions sometimes catch a signal from a segmented
+ *   context, delete the old SS segment (with modify_ldt), and change
+ *   the saved CS to a 64-bit segment.  These DOSEMU versions expect
+ *   sigreturn to send them back to 64-bit mode without killing them,
+ *   despite the fact that the SS selector when the signal was raised is
+ *   no longer valid.  UC_STRICT_RESTORE_SS will be clear, so the kernel
+ *   will fix up SS for these DOSEMU versions.
+ *
+ * - Old and new programs that catch a signal and return without
+ *   modifying the saved context will end up in exactly the state they
+ *   started in, even if they were running in a segmented context when
+ *   the signal was raised..  Old kernels would lose track of the
+ *   previous SS value.
+ */
+#define UC_SIGCONTEXT_SS       0x2
+#define UC_STRICT_RESTORE_SS   0x4
+#endif
 
 #include <asm-generic/ucontext.h>
 
index d1daead5fcddd57ab4cd0675315420bf52608584..adb3eaf8fe2a5e038c2444bd8f75b55716faf607 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/realmode.h>
 
+#include <linux/ftrace.h>
 #include "../../realmode/rm/wakeup.h"
 #include "sleep.h"
 
@@ -107,7 +108,13 @@ int x86_acpi_suspend_lowlevel(void)
        saved_magic = 0x123456789abcdef0L;
 #endif /* CONFIG_64BIT */
 
+       /*
+        * Pause/unpause graph tracing around do_suspend_lowlevel as it has
+        * inconsistent call/return info after it jumps to the wakeup vector.
+        */
+       pause_graph_tracing();
        do_suspend_lowlevel();
+       unpause_graph_tracing();
        return 0;
 }
 
index 8a5cddac7d444084c223e95948944b5099d15003..531b9611c51d5d4b42f721f45609a5f4ecd3cce2 100644 (file)
@@ -2077,6 +2077,20 @@ int generic_processor_info(int apicid, int version)
        } else
                cpu = cpumask_next_zero(-1, cpu_present_mask);
 
+       /*
+        * This can happen on physical hotplug. The sanity check at boot time
+        * is done from native_smp_prepare_cpus() after num_possible_cpus() is
+        * established.
+        */
+       if (topology_update_package_map(apicid, cpu) < 0) {
+               int thiscpu = max + disabled_cpus;
+
+               pr_warning("ACPI: Package limit reached. Processor %d/0x%x ignored.\n",
+                          thiscpu, apicid);
+               disabled_cpus++;
+               return -ENOSPC;
+       }
+
        /*
         * Validate version
         */
index 9968f30cca3e187d28acf2d7631609c29cb1bcf6..76f89e2b245afbb1a22550301e39479a8959b04d 100644 (file)
@@ -53,7 +53,7 @@ void flat_init_apic_ldr(void)
        apic_write(APIC_LDR, val);
 }
 
-static inline void _flat_send_IPI_mask(unsigned long mask, int vector)
+static void _flat_send_IPI_mask(unsigned long mask, int vector)
 {
        unsigned long flags;
 
index c80c02c6ec4944a85715f4438443e5987df4f612..ab5c2c685a3ce908c3677262a35fd402ba77a445 100644 (file)
@@ -30,7 +30,7 @@ static unsigned int numachip1_get_apic_id(unsigned long x)
        unsigned long value;
        unsigned int id = (x >> 24) & 0xff;
 
-       if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) {
+       if (static_cpu_has(X86_FEATURE_NODEID_MSR)) {
                rdmsrl(MSR_FAM10H_NODE_ID, value);
                id |= (value << 2) & 0xff00;
        }
@@ -178,7 +178,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
        this_cpu_write(cpu_llc_id, node);
 
        /* Account for nodes per socket in multi-core-module processors */
-       if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) {
+       if (static_cpu_has(X86_FEATURE_NODEID_MSR)) {
                rdmsrl(MSR_FAM10H_NODE_ID, val);
                nodes = ((val >> 3) & 7) + 1;
        }
index eb45fc9b61248e9c9e819c974741c2652f56e644..28bde88b0085d2284947016aae114574958428ed 100644 (file)
 #include <asm/proto.h>
 #include <asm/ipi.h>
 
+void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
+{
+       /*
+        * Subtle. In the case of the 'never do double writes' workaround
+        * we have to lock out interrupts to be safe.  As we don't care
+        * of the value read we use an atomic rmw access to avoid costly
+        * cli/sti.  Otherwise we use an even cheaper single atomic write
+        * to the APIC.
+        */
+       unsigned int cfg;
+
+       /*
+        * Wait for idle.
+        */
+       __xapic_wait_icr_idle();
+
+       /*
+        * No need to touch the target chip field
+        */
+       cfg = __prepare_ICR(shortcut, vector, dest);
+
+       /*
+        * Send the IPI. The write to APIC_ICR fires this off.
+        */
+       native_apic_mem_write(APIC_ICR, cfg);
+}
+
+/*
+ * This is used to send an IPI with no shorthand notation (the destination is
+ * specified in bits 56 to 63 of the ICR).
+ */
+void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
+{
+       unsigned long cfg;
+
+       /*
+        * Wait for idle.
+        */
+       if (unlikely(vector == NMI_VECTOR))
+               safe_apic_wait_icr_idle();
+       else
+               __xapic_wait_icr_idle();
+
+       /*
+        * prepare target chip field
+        */
+       cfg = __prepare_ICR2(mask);
+       native_apic_mem_write(APIC_ICR2, cfg);
+
+       /*
+        * program the ICR
+        */
+       cfg = __prepare_ICR(0, vector, dest);
+
+       /*
+        * Send the IPI. The write to APIC_ICR fires this off.
+        */
+       native_apic_mem_write(APIC_ICR, cfg);
+}
+
 void default_send_IPI_single_phys(int cpu, int vector)
 {
        unsigned long flags;
index 84a7524b202cad58509a68db5e6d229f7765b6aa..5c042466f274d0f79dac84bba1c6835953565c84 100644 (file)
@@ -59,7 +59,6 @@ void common(void) {
 
 #ifdef CONFIG_PARAVIRT
        BLANK();
-       OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
        OFFSET(PARAVIRT_PATCH_pv_cpu_ops, paravirt_patch_template, pv_cpu_ops);
        OFFSET(PARAVIRT_PATCH_pv_irq_ops, paravirt_patch_template, pv_irq_ops);
        OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
index 6ce39025f467fb060ce68c8b8ebfaf8f87258d09..ecdc1d217dc0f50a7b760c25cec8bee586643336 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/lguest.h>
 #include "../../../drivers/lguest/lg.h"
 
-#define __SYSCALL_I386(nr, sym, compat) [nr] = 1,
+#define __SYSCALL_I386(nr, sym, qual) [nr] = 1,
 static char syscalls[] = {
 #include <asm/syscalls_32.h>
 };
@@ -52,6 +52,11 @@ void foo(void)
        DEFINE(TSS_sysenter_sp0, offsetof(struct tss_struct, x86_tss.sp0) -
               offsetofend(struct tss_struct, SYSENTER_stack));
 
+       /* Offset from cpu_tss to SYSENTER_stack */
+       OFFSET(CPU_TSS_SYSENTER_stack, tss_struct, SYSENTER_stack);
+       /* Size of SYSENTER_stack */
+       DEFINE(SIZEOF_SYSENTER_stack, sizeof(((struct tss_struct *)0)->SYSENTER_stack));
+
 #if defined(CONFIG_LGUEST) || defined(CONFIG_LGUEST_GUEST) || defined(CONFIG_LGUEST_MODULE)
        BLANK();
        OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
index f2edafb5f24eb2034ee54751292af3fa9bd70fb9..d875f97d4e0ba0477c648e1244ff238bfd48be03 100644 (file)
@@ -4,17 +4,11 @@
 
 #include <asm/ia32.h>
 
-#define __SYSCALL_64(nr, sym, compat) [nr] = 1,
-#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1,
-#ifdef CONFIG_X86_X32_ABI
-# define __SYSCALL_X32(nr, sym, compat) [nr] = 1,
-#else
-# define __SYSCALL_X32(nr, sym, compat) /* nothing */
-#endif
+#define __SYSCALL_64(nr, sym, qual) [nr] = 1,
 static char syscalls_64[] = {
 #include <asm/syscalls_64.h>
 };
-#define __SYSCALL_I386(nr, sym, compat) [nr] = 1,
+#define __SYSCALL_I386(nr, sym, qual) [nr] = 1,
 static char syscalls_ia32[] = {
 #include <asm/syscalls_32.h>
 };
index 58031303e30488c540d609f95d0693918c09fa64..0d373d7affc8d48d1039f6c6d759a3b9cc191c38 100644 (file)
@@ -30,33 +30,11 @@ obj-$(CONFIG_CPU_SUP_CENTAUR)               += centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)     += transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)           += umc.o
 
-obj-$(CONFIG_PERF_EVENTS)              += perf_event.o
-
-ifdef CONFIG_PERF_EVENTS
-obj-$(CONFIG_CPU_SUP_AMD)              += perf_event_amd.o perf_event_amd_uncore.o
-ifdef CONFIG_AMD_IOMMU
-obj-$(CONFIG_CPU_SUP_AMD)              += perf_event_amd_iommu.o
-endif
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_knc.o perf_event_p4.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_rapl.o perf_event_intel_cqm.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_pt.o perf_event_intel_bts.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_cstate.o
-
-obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += perf_event_intel_uncore.o \
-                                          perf_event_intel_uncore_snb.o \
-                                          perf_event_intel_uncore_snbep.o \
-                                          perf_event_intel_uncore_nhmex.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_msr.o
-obj-$(CONFIG_CPU_SUP_AMD)              += perf_event_msr.o
-endif
-
-
 obj-$(CONFIG_X86_MCE)                  += mcheck/
 obj-$(CONFIG_MTRR)                     += mtrr/
 obj-$(CONFIG_MICROCODE)                        += microcode/
 
-obj-$(CONFIG_X86_LOCAL_APIC)           += perfctr-watchdog.o perf_event_amd_ibs.o
+obj-$(CONFIG_X86_LOCAL_APIC)           += perfctr-watchdog.o
 
 obj-$(CONFIG_HYPERVISOR_GUEST)         += vmware.o hypervisor.o mshyperv.o
 
@@ -64,7 +42,7 @@ ifdef CONFIG_X86_FEATURE_NAMES
 quiet_cmd_mkcapflags = MKCAP   $@
       cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $< $@
 
-cpufeature = $(src)/../../include/asm/cpufeature.h
+cpufeature = $(src)/../../include/asm/cpufeatures.h
 
 targets += capflags.c
 $(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE
index a07956a08936e8ea56c1a73075d700d281895577..97c59fd60702f4ceacad7c4d46a3c8d5de7dacbf 100644 (file)
@@ -117,7 +117,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
                void (*f_vide)(void);
                u64 d, d2;
 
-               printk(KERN_INFO "AMD K6 stepping B detected - ");
+               pr_info("AMD K6 stepping B detected - ");
 
                /*
                 * It looks like AMD fixed the 2.6.2 bug and improved indirect
@@ -133,10 +133,9 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
                d = d2-d;
 
                if (d > 20*K6_BUG_LOOP)
-                       printk(KERN_CONT
-                               "system stability may be impaired when more than 32 MB are used.\n");
+                       pr_cont("system stability may be impaired when more than 32 MB are used.\n");
                else
-                       printk(KERN_CONT "probably OK (after B9730xxxx).\n");
+                       pr_cont("probably OK (after B9730xxxx).\n");
        }
 
        /* K6 with old style WHCR */
@@ -154,7 +153,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
                        wbinvd();
                        wrmsr(MSR_K6_WHCR, l, h);
                        local_irq_restore(flags);
-                       printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n",
+                       pr_info("Enabling old style K6 write allocation for %d Mb\n",
                                mbytes);
                }
                return;
@@ -175,7 +174,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
                        wbinvd();
                        wrmsr(MSR_K6_WHCR, l, h);
                        local_irq_restore(flags);
-                       printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n",
+                       pr_info("Enabling new style K6 write allocation for %d Mb\n",
                                mbytes);
                }
 
@@ -202,7 +201,7 @@ static void init_amd_k7(struct cpuinfo_x86 *c)
         */
        if (c->x86_model >= 6 && c->x86_model <= 10) {
                if (!cpu_has(c, X86_FEATURE_XMM)) {
-                       printk(KERN_INFO "Enabling disabled K7/SSE Support.\n");
+                       pr_info("Enabling disabled K7/SSE Support.\n");
                        msr_clear_bit(MSR_K7_HWCR, 15);
                        set_cpu_cap(c, X86_FEATURE_XMM);
                }
@@ -216,9 +215,8 @@ static void init_amd_k7(struct cpuinfo_x86 *c)
        if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) {
                rdmsr(MSR_K7_CLK_CTL, l, h);
                if ((l & 0xfff00000) != 0x20000000) {
-                       printk(KERN_INFO
-                           "CPU: CLK_CTL MSR was %x. Reprogramming to %x\n",
-                                       l, ((l & 0x000fffff)|0x20000000));
+                       pr_info("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n",
+                               l, ((l & 0x000fffff)|0x20000000));
                        wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h);
                }
        }
@@ -485,7 +483,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
                if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) {
                        unsigned long pfn = tseg >> PAGE_SHIFT;
 
-                       printk(KERN_DEBUG "tseg: %010llx\n", tseg);
+                       pr_debug("tseg: %010llx\n", tseg);
                        if (pfn_range_is_mapped(pfn, pfn + 1))
                                set_memory_4k((unsigned long)__va(tseg), 1);
                }
@@ -500,8 +498,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
 
                        rdmsrl(MSR_K7_HWCR, val);
                        if (!(val & BIT(24)))
-                               printk(KERN_WARNING FW_BUG "TSC doesn't count "
-                                       "with P0 frequency!\n");
+                               pr_warn(FW_BUG "TSC doesn't count with P0 frequency!\n");
                }
        }
 
index 04f0fe5af83ec34bb4fd6ec09fd3cc8db1c7ee07..a972ac4c7e7df05238e78b08e093cded47640fcd 100644 (file)
@@ -15,7 +15,7 @@ void __init check_bugs(void)
 {
        identify_boot_cpu();
 #if !defined(CONFIG_SMP)
-       printk(KERN_INFO "CPU: ");
+       pr_info("CPU: ");
        print_cpu_info(&boot_cpu_data);
 #endif
        alternative_instructions();
index ae20be6e483c77703413cf36e9db065134da01f3..1661d8ec92805191cd4581c365db68ea5acfdf02 100644 (file)
@@ -1,7 +1,7 @@
 #include <linux/bitops.h>
 #include <linux/kernel.h>
 
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <asm/e820.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
@@ -29,7 +29,7 @@ static void init_c3(struct cpuinfo_x86 *c)
                        rdmsr(MSR_VIA_FCR, lo, hi);
                        lo |= ACE_FCR;          /* enable ACE unit */
                        wrmsr(MSR_VIA_FCR, lo, hi);
-                       printk(KERN_INFO "CPU: Enabled ACE h/w crypto\n");
+                       pr_info("CPU: Enabled ACE h/w crypto\n");
                }
 
                /* enable RNG unit, if present and disabled */
@@ -37,7 +37,7 @@ static void init_c3(struct cpuinfo_x86 *c)
                        rdmsr(MSR_VIA_RNG, lo, hi);
                        lo |= RNG_ENABLE;       /* enable RNG unit */
                        wrmsr(MSR_VIA_RNG, lo, hi);
-                       printk(KERN_INFO "CPU: Enabled h/w RNG\n");
+                       pr_info("CPU: Enabled h/w RNG\n");
                }
 
                /* store Centaur Extended Feature Flags as
@@ -130,7 +130,7 @@ static void init_centaur(struct cpuinfo_x86 *c)
                        name = "C6";
                        fcr_set = ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
                        fcr_clr = DPDC;
-                       printk(KERN_NOTICE "Disabling bugged TSC.\n");
+                       pr_notice("Disabling bugged TSC.\n");
                        clear_cpu_cap(c, X86_FEATURE_TSC);
                        break;
                case 8:
@@ -163,11 +163,11 @@ static void init_centaur(struct cpuinfo_x86 *c)
                newlo = (lo|fcr_set) & (~fcr_clr);
 
                if (newlo != lo) {
-                       printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n",
+                       pr_info("Centaur FCR was 0x%X now 0x%X\n",
                                lo, newlo);
                        wrmsr(MSR_IDT_FCR1, newlo, hi);
                } else {
-                       printk(KERN_INFO "Centaur FCR is 0x%X\n", lo);
+                       pr_info("Centaur FCR is 0x%X\n", lo);
                }
                /* Emulate MTRRs using Centaur's MCR. */
                set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR);
index 37830de8f60a8f0d8f8da27d409da72ce1f13551..249461f958516a5a281af53532e771c9d55e8189 100644 (file)
@@ -162,6 +162,22 @@ static int __init x86_mpx_setup(char *s)
 }
 __setup("nompx", x86_mpx_setup);
 
+static int __init x86_noinvpcid_setup(char *s)
+{
+       /* noinvpcid doesn't accept parameters */
+       if (s)
+               return -EINVAL;
+
+       /* do not emit a message if the feature is not present */
+       if (!boot_cpu_has(X86_FEATURE_INVPCID))
+               return 0;
+
+       setup_clear_cpu_cap(X86_FEATURE_INVPCID);
+       pr_info("noinvpcid: INVPCID feature disabled\n");
+       return 0;
+}
+early_param("noinvpcid", x86_noinvpcid_setup);
+
 #ifdef CONFIG_X86_32
 static int cachesize_override = -1;
 static int disable_x86_serial_nr = 1;
@@ -228,7 +244,7 @@ static void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
        lo |= 0x200000;
        wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi);
 
-       printk(KERN_NOTICE "CPU serial number disabled.\n");
+       pr_notice("CPU serial number disabled.\n");
        clear_cpu_cap(c, X86_FEATURE_PN);
 
        /* Disabling the serial number may affect the cpuid level */
@@ -329,9 +345,8 @@ static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
                if (!warn)
                        continue;
 
-               printk(KERN_WARNING
-                      "CPU: CPU feature " X86_CAP_FMT " disabled, no CPUID level 0x%x\n",
-                               x86_cap_flag(df->feature), df->level);
+               pr_warn("CPU: CPU feature " X86_CAP_FMT " disabled, no CPUID level 0x%x\n",
+                       x86_cap_flag(df->feature), df->level);
        }
 }
 
@@ -510,7 +525,7 @@ void detect_ht(struct cpuinfo_x86 *c)
        smp_num_siblings = (ebx & 0xff0000) >> 16;
 
        if (smp_num_siblings == 1) {
-               printk_once(KERN_INFO "CPU0: Hyper-Threading is disabled\n");
+               pr_info_once("CPU0: Hyper-Threading is disabled\n");
                goto out;
        }
 
@@ -531,10 +546,10 @@ void detect_ht(struct cpuinfo_x86 *c)
 
 out:
        if (!printed && (c->x86_max_cores * smp_num_siblings) > 1) {
-               printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
-                      c->phys_proc_id);
-               printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
-                      c->cpu_core_id);
+               pr_info("CPU: Physical Processor ID: %d\n",
+                       c->phys_proc_id);
+               pr_info("CPU: Processor Core ID: %d\n",
+                       c->cpu_core_id);
                printed = 1;
        }
 #endif
@@ -559,9 +574,8 @@ static void get_cpu_vendor(struct cpuinfo_x86 *c)
                }
        }
 
-       printk_once(KERN_ERR
-                       "CPU: vendor_id '%s' unknown, using generic init.\n" \
-                       "CPU: Your system may be unstable.\n", v);
+       pr_err_once("CPU: vendor_id '%s' unknown, using generic init.\n" \
+                   "CPU: Your system may be unstable.\n", v);
 
        c->x86_vendor = X86_VENDOR_UNKNOWN;
        this_cpu = &default_cpu;
@@ -760,7 +774,7 @@ void __init early_cpu_init(void)
        int count = 0;
 
 #ifdef CONFIG_PROCESSOR_SELECT
-       printk(KERN_INFO "KERNEL supported cpus:\n");
+       pr_info("KERNEL supported cpus:\n");
 #endif
 
        for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
@@ -778,7 +792,7 @@ void __init early_cpu_init(void)
                        for (j = 0; j < 2; j++) {
                                if (!cpudev->c_ident[j])
                                        continue;
-                               printk(KERN_INFO "  %s %s\n", cpudev->c_vendor,
+                               pr_info("  %s %s\n", cpudev->c_vendor,
                                        cpudev->c_ident[j]);
                        }
                }
@@ -802,6 +816,31 @@ static void detect_nopl(struct cpuinfo_x86 *c)
        clear_cpu_cap(c, X86_FEATURE_NOPL);
 #else
        set_cpu_cap(c, X86_FEATURE_NOPL);
+#endif
+
+       /*
+        * ESPFIX is a strange bug.  All real CPUs have it.  Paravirt
+        * systems that run Linux at CPL > 0 may or may not have the
+        * issue, but, even if they have the issue, there's absolutely
+        * nothing we can do about it because we can't use the real IRET
+        * instruction.
+        *
+        * NB: For the time being, only 32-bit kernels support
+        * X86_BUG_ESPFIX as such.  64-bit kernels directly choose
+        * whether to apply espfix using paravirt hooks.  If any
+        * non-paravirt system ever shows up that does *not* have the
+        * ESPFIX issue, we can change this.
+        */
+#ifdef CONFIG_X86_32
+#ifdef CONFIG_PARAVIRT
+       do {
+               extern void native_iret(void);
+               if (pv_cpu_ops.iret == native_iret)
+                       set_cpu_bug(c, X86_BUG_ESPFIX);
+       } while (0);
+#else
+       set_cpu_bug(c, X86_BUG_ESPFIX);
+#endif
 #endif
 }
 
@@ -977,6 +1016,8 @@ static void identify_cpu(struct cpuinfo_x86 *c)
 #ifdef CONFIG_NUMA
        numa_add_cpu(smp_processor_id());
 #endif
+       /* The boot/hotplug time assigment got cleared, restore it */
+       c->logical_proc_id = topology_phys_to_logical_pkg(c->phys_proc_id);
 }
 
 /*
@@ -1061,7 +1102,7 @@ static void __print_cpu_msr(void)
                for (index = index_min; index < index_max; index++) {
                        if (rdmsrl_safe(index, &val))
                                continue;
-                       printk(KERN_INFO " MSR%08x: %016llx\n", index, val);
+                       pr_info(" MSR%08x: %016llx\n", index, val);
                }
        }
 }
@@ -1100,19 +1141,19 @@ void print_cpu_info(struct cpuinfo_x86 *c)
        }
 
        if (vendor && !strstr(c->x86_model_id, vendor))
-               printk(KERN_CONT "%s ", vendor);
+               pr_cont("%s ", vendor);
 
        if (c->x86_model_id[0])
-               printk(KERN_CONT "%s", c->x86_model_id);
+               pr_cont("%s", c->x86_model_id);
        else
-               printk(KERN_CONT "%d86", c->x86);
+               pr_cont("%d86", c->x86);
 
-       printk(KERN_CONT " (family: 0x%x, model: 0x%x", c->x86, c->x86_model);
+       pr_cont(" (family: 0x%x, model: 0x%x", c->x86, c->x86_model);
 
        if (c->x86_mask || c->cpuid_level >= 0)
-               printk(KERN_CONT ", stepping: 0x%x)\n", c->x86_mask);
+               pr_cont(", stepping: 0x%x)\n", c->x86_mask);
        else
-               printk(KERN_CONT ")\n");
+               pr_cont(")\n");
 
        print_cpu_msr(c);
 }
@@ -1438,7 +1479,7 @@ void cpu_init(void)
 
        show_ucode_info_early();
 
-       printk(KERN_INFO "Initializing CPU#%d\n", cpu);
+       pr_info("Initializing CPU#%d\n", cpu);
 
        if (cpu_feature_enabled(X86_FEATURE_VME) ||
            cpu_has_tsc ||
@@ -1475,20 +1516,6 @@ void cpu_init(void)
 }
 #endif
 
-#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS
-void warn_pre_alternatives(void)
-{
-       WARN(1, "You're using static_cpu_has before alternatives have run!\n");
-}
-EXPORT_SYMBOL_GPL(warn_pre_alternatives);
-#endif
-
-inline bool __static_cpu_has_safe(u16 bit)
-{
-       return boot_cpu_has(bit);
-}
-EXPORT_SYMBOL_GPL(__static_cpu_has_safe);
-
 static void bsp_resume(void)
 {
        if (this_cpu->c_bsp_resume)
index aaf152e79637384781d264afbff76a58da9489cc..6adef9cac23ee99c96924e2789abeb2d1ad123f3 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/timer.h>
 #include <asm/pci-direct.h>
 #include <asm/tsc.h>
+#include <asm/cpufeature.h>
 
 #include "cpu.h"
 
@@ -103,7 +104,7 @@ static void check_cx686_slop(struct cpuinfo_x86 *c)
                local_irq_restore(flags);
 
                if (ccr5 & 2) { /* possible wrong calibration done */
-                       printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n");
+                       pr_info("Recalibrating delay loop with SLOP bit reset\n");
                        calibrate_delay();
                        c->loops_per_jiffy = loops_per_jiffy;
                }
@@ -115,7 +116,7 @@ static void set_cx86_reorder(void)
 {
        u8 ccr3;
 
-       printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n");
+       pr_info("Enable Memory access reorder on Cyrix/NSC processor.\n");
        ccr3 = getCx86(CX86_CCR3);
        setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
 
@@ -128,7 +129,7 @@ static void set_cx86_reorder(void)
 
 static void set_cx86_memwb(void)
 {
-       printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n");
+       pr_info("Enable Memory-Write-back mode on Cyrix/NSC processor.\n");
 
        /* CCR2 bit 2: unlock NW bit */
        setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) & ~0x04);
@@ -268,7 +269,7 @@ static void init_cyrix(struct cpuinfo_x86 *c)
                 *  VSA1 we work around however.
                 */
 
-               printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
+               pr_info("Working around Cyrix MediaGX virtual DMA bugs.\n");
                isa_dma_bridge_buggy = 2;
 
                /* We do this before the PCI layer is running. However we
@@ -426,7 +427,7 @@ static void cyrix_identify(struct cpuinfo_x86 *c)
                if (dir0 == 5 || dir0 == 3) {
                        unsigned char ccr3;
                        unsigned long flags;
-                       printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
+                       pr_info("Enabling CPUID on Cyrix processor.\n");
                        local_irq_save(flags);
                        ccr3 = getCx86(CX86_CCR3);
                        /* enable MAPEN  */
index d820d8eae96be0b3daa0ec01d9f4a22bf1ad930e..73d391ae452f82a7bfeca4be2276eed628dcd452 100644 (file)
@@ -56,7 +56,7 @@ detect_hypervisor_vendor(void)
        }
 
        if (max_pri)
-               printk(KERN_INFO "Hypervisor detected: %s\n", x86_hyper->name);
+               pr_info("Hypervisor detected: %s\n", x86_hyper->name);
 }
 
 void init_hypervisor(struct cpuinfo_x86 *c)
index 565648bc1a0aef6c3cf60da92ec9fb60a2408c90..1f7fdb91a818bc10d4b975a070d6b2c1a947b15b 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/module.h>
 #include <linux/uaccess.h>
 
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <asm/pgtable.h>
 #include <asm/msr.h>
 #include <asm/bugs.h>
@@ -61,7 +61,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
         */
        if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 &&
            c->microcode < 0x20e) {
-               printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n");
+               pr_warn("Atom PSE erratum detected, BIOS microcode update recommended\n");
                clear_cpu_cap(c, X86_FEATURE_PSE);
        }
 
@@ -140,7 +140,7 @@ static void early_init_intel(struct cpuinfo_x86 *c)
        if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) {
                rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable);
                if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) {
-                       printk(KERN_INFO "Disabled fast string operations\n");
+                       pr_info("Disabled fast string operations\n");
                        setup_clear_cpu_cap(X86_FEATURE_REP_GOOD);
                        setup_clear_cpu_cap(X86_FEATURE_ERMS);
                }
@@ -160,6 +160,19 @@ static void early_init_intel(struct cpuinfo_x86 *c)
                pr_info("Disabling PGE capability bit\n");
                setup_clear_cpu_cap(X86_FEATURE_PGE);
        }
+
+       if (c->cpuid_level >= 0x00000001) {
+               u32 eax, ebx, ecx, edx;
+
+               cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
+               /*
+                * If HTT (EDX[28]) is set EBX[16:23] contain the number of
+                * apicids which are reserved per package. Store the resulting
+                * shift value for the package management code.
+                */
+               if (edx & (1U << 28))
+                       c->x86_coreid_bits = get_count_order((ebx >> 16) & 0xff);
+       }
 }
 
 #ifdef CONFIG_X86_32
@@ -176,7 +189,7 @@ int ppro_with_ram_bug(void)
            boot_cpu_data.x86 == 6 &&
            boot_cpu_data.x86_model == 1 &&
            boot_cpu_data.x86_mask < 8) {
-               printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n");
+               pr_info("Pentium Pro with Errata#50 detected. Taking evasive action.\n");
                return 1;
        }
        return 0;
@@ -225,7 +238,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
 
                set_cpu_bug(c, X86_BUG_F00F);
                if (!f00f_workaround_enabled) {
-                       printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
+                       pr_notice("Intel Pentium with F0 0F bug - workaround enabled.\n");
                        f00f_workaround_enabled = 1;
                }
        }
@@ -244,7 +257,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c)
         * Forcefully enable PAE if kernel parameter "forcepae" is present.
         */
        if (forcepae) {
-               printk(KERN_WARNING "PAE forced!\n");
+               pr_warn("PAE forced!\n");
                set_cpu_cap(c, X86_FEATURE_PAE);
                add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE);
        }
index 0b6c52388cf484f809a7f328f475424dd262417c..de6626c18e427b771ea902451ae77ab52e233915 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/sysfs.h>
 #include <linux/pci.h>
 
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <asm/amd_nb.h>
 #include <asm/smp.h>
 
@@ -444,7 +444,7 @@ static ssize_t store_cache_disable(struct cacheinfo *this_leaf,
        err = amd_set_l3_disable_slot(nb, cpu, slot, val);
        if (err) {
                if (err == -EEXIST)
-                       pr_warning("L3 slot %d in use/index already disabled!\n",
+                       pr_warn("L3 slot %d in use/index already disabled!\n",
                                   slot);
                return err;
        }
diff --git a/arch/x86/kernel/cpu/intel_pt.h b/arch/x86/kernel/cpu/intel_pt.h
deleted file mode 100644 (file)
index 336878a..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Intel(R) Processor Trace PMU driver for perf
- * Copyright (c) 2013-2014, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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.
- *
- * Intel PT is specified in the Intel Architecture Instruction Set Extensions
- * Programming Reference:
- * http://software.intel.com/en-us/intel-isa-extensions
- */
-
-#ifndef __INTEL_PT_H__
-#define __INTEL_PT_H__
-
-/*
- * Single-entry ToPA: when this close to region boundary, switch
- * buffers to avoid losing data.
- */
-#define TOPA_PMI_MARGIN 512
-
-#define TOPA_SHIFT 12
-
-static inline unsigned int sizes(unsigned int tsz)
-{
-       return 1 << (tsz + TOPA_SHIFT);
-};
-
-struct topa_entry {
-       u64     end     : 1;
-       u64     rsvd0   : 1;
-       u64     intr    : 1;
-       u64     rsvd1   : 1;
-       u64     stop    : 1;
-       u64     rsvd2   : 1;
-       u64     size    : 4;
-       u64     rsvd3   : 2;
-       u64     base    : 36;
-       u64     rsvd4   : 16;
-};
-
-#define PT_CPUID_LEAVES                2
-#define PT_CPUID_REGS_NUM      4 /* number of regsters (eax, ebx, ecx, edx) */
-
-enum pt_capabilities {
-       PT_CAP_max_subleaf = 0,
-       PT_CAP_cr3_filtering,
-       PT_CAP_psb_cyc,
-       PT_CAP_mtc,
-       PT_CAP_topa_output,
-       PT_CAP_topa_multiple_entries,
-       PT_CAP_single_range_output,
-       PT_CAP_payloads_lip,
-       PT_CAP_mtc_periods,
-       PT_CAP_cycle_thresholds,
-       PT_CAP_psb_periods,
-};
-
-struct pt_pmu {
-       struct pmu              pmu;
-       u32                     caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
-};
-
-/**
- * struct pt_buffer - buffer configuration; one buffer per task_struct or
- *             cpu, depending on perf event configuration
- * @cpu:       cpu for per-cpu allocation
- * @tables:    list of ToPA tables in this buffer
- * @first:     shorthand for first topa table
- * @last:      shorthand for last topa table
- * @cur:       current topa table
- * @nr_pages:  buffer size in pages
- * @cur_idx:   current output region's index within @cur table
- * @output_off:        offset within the current output region
- * @data_size: running total of the amount of data in this buffer
- * @lost:      if data was lost/truncated
- * @head:      logical write offset inside the buffer
- * @snapshot:  if this is for a snapshot/overwrite counter
- * @stop_pos:  STOP topa entry in the buffer
- * @intr_pos:  INT topa entry in the buffer
- * @data_pages:        array of pages from perf
- * @topa_index:        table of topa entries indexed by page offset
- */
-struct pt_buffer {
-       int                     cpu;
-       struct list_head        tables;
-       struct topa             *first, *last, *cur;
-       unsigned int            cur_idx;
-       size_t                  output_off;
-       unsigned long           nr_pages;
-       local_t                 data_size;
-       local_t                 lost;
-       local64_t               head;
-       bool                    snapshot;
-       unsigned long           stop_pos, intr_pos;
-       void                    **data_pages;
-       struct topa_entry       *topa_index[0];
-};
-
-/**
- * struct pt - per-cpu pt context
- * @handle:    perf output handle
- * @handle_nmi:        do handle PT PMI on this cpu, there's an active event
- */
-struct pt {
-       struct perf_output_handle handle;
-       int                     handle_nmi;
-};
-
-#endif /* __INTEL_PT_H__ */
index afa9f0d487ea07b79936fcd5b62040540102fad3..fbb5e90557a5257bbde11179cdeb415e60485019 100644 (file)
@@ -1,5 +1,5 @@
 #include <asm/cpu_device_id.h>
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 4cfba4371a71f28c4615610475e3eec9e8d9790c..517619ea6498b41839f87f28bce4a76b1e43c7ab 100644 (file)
@@ -115,7 +115,7 @@ static int raise_local(void)
        int cpu = m->extcpu;
 
        if (m->inject_flags & MCJ_EXCEPTION) {
-               printk(KERN_INFO "Triggering MCE exception on CPU %d\n", cpu);
+               pr_info("Triggering MCE exception on CPU %d\n", cpu);
                switch (context) {
                case MCJ_CTX_IRQ:
                        /*
@@ -128,15 +128,15 @@ static int raise_local(void)
                        raise_exception(m, NULL);
                        break;
                default:
-                       printk(KERN_INFO "Invalid MCE context\n");
+                       pr_info("Invalid MCE context\n");
                        ret = -EINVAL;
                }
-               printk(KERN_INFO "MCE exception done on CPU %d\n", cpu);
+               pr_info("MCE exception done on CPU %d\n", cpu);
        } else if (m->status) {
-               printk(KERN_INFO "Starting machine check poll CPU %d\n", cpu);
+               pr_info("Starting machine check poll CPU %d\n", cpu);
                raise_poll(m);
                mce_notify_irq();
-               printk(KERN_INFO "Machine check poll done on CPU %d\n", cpu);
+               pr_info("Machine check poll done on CPU %d\n", cpu);
        } else
                m->finished = 0;
 
@@ -183,8 +183,7 @@ static void raise_mce(struct mce *m)
                start = jiffies;
                while (!cpumask_empty(mce_inject_cpumask)) {
                        if (!time_before(jiffies, start + 2*HZ)) {
-                               printk(KERN_ERR
-                               "Timeout waiting for mce inject %lx\n",
+                               pr_err("Timeout waiting for mce inject %lx\n",
                                        *cpumask_bits(mce_inject_cpumask));
                                break;
                        }
@@ -241,7 +240,7 @@ static int inject_init(void)
 {
        if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
                return -ENOMEM;
-       printk(KERN_INFO "Machine check injector initialized\n");
+       pr_info("Machine check injector initialized\n");
        register_mce_write_callback(mce_write);
        register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
                                "mce_notify");
index 9c682c222071db1960ba848c24c76567306d0542..5119766d988925a4c8eb9df23a3ff7b1b626d174 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/debugfs.h>
 #include <asm/mce.h>
+#include <asm/uaccess.h>
 
 #include "mce-internal.h"
 
@@ -29,7 +30,7 @@
  * panic situations)
  */
 
-enum context { IN_KERNEL = 1, IN_USER = 2 };
+enum context { IN_KERNEL = 1, IN_USER = 2, IN_KERNEL_RECOV = 3 };
 enum ser { SER_REQUIRED = 1, NO_SER = 2 };
 enum exception { EXCP_CONTEXT = 1, NO_EXCP = 2 };
 
@@ -48,6 +49,7 @@ static struct severity {
 #define MCESEV(s, m, c...) { .sev = MCE_ ## s ## _SEVERITY, .msg = m, ## c }
 #define  KERNEL                .context = IN_KERNEL
 #define  USER          .context = IN_USER
+#define  KERNEL_RECOV  .context = IN_KERNEL_RECOV
 #define  SER           .ser = SER_REQUIRED
 #define  NOSER         .ser = NO_SER
 #define  EXCP          .excp = EXCP_CONTEXT
@@ -86,6 +88,10 @@ static struct severity {
                PANIC, "In kernel and no restart IP",
                EXCP, KERNEL, MCGMASK(MCG_STATUS_RIPV, 0)
                ),
+       MCESEV(
+               PANIC, "In kernel and no restart IP",
+               EXCP, KERNEL_RECOV, MCGMASK(MCG_STATUS_RIPV, 0)
+               ),
        MCESEV(
                DEFERRED, "Deferred error",
                NOSER, MASK(MCI_STATUS_UC|MCI_STATUS_DEFERRED|MCI_STATUS_POISON, MCI_STATUS_DEFERRED)
@@ -122,6 +128,11 @@ static struct severity {
                SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR, MCI_UC_SAR|MCI_ADDR),
                MCGMASK(MCG_STATUS_RIPV|MCG_STATUS_EIPV, MCG_STATUS_RIPV)
                ),
+       MCESEV(
+               AR, "Action required: data load in error recoverable area of kernel",
+               SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA),
+               KERNEL_RECOV
+               ),
        MCESEV(
                AR, "Action required: data load error in a user process",
                SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA),
@@ -170,6 +181,9 @@ static struct severity {
                )       /* always matches. keep at end */
 };
 
+#define mc_recoverable(mcg) (((mcg) & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) == \
+                               (MCG_STATUS_RIPV|MCG_STATUS_EIPV))
+
 /*
  * If mcgstatus indicated that ip/cs on the stack were
  * no good, then "m->cs" will be zero and we will have
@@ -183,7 +197,11 @@ static struct severity {
  */
 static int error_context(struct mce *m)
 {
-       return ((m->cs & 3) == 3) ? IN_USER : IN_KERNEL;
+       if ((m->cs & 3) == 3)
+               return IN_USER;
+       if (mc_recoverable(m->mcgstatus) && ex_has_fault_handler(m->ip))
+               return IN_KERNEL_RECOV;
+       return IN_KERNEL;
 }
 
 /*
index a006f4cd792b10d54a92eff4a3b9c6860aa5382e..f0c921b03e4245e1f7a4b16687c0d9e7600b4256 100644 (file)
@@ -961,6 +961,20 @@ static void mce_clear_state(unsigned long *toclear)
        }
 }
 
+static int do_memory_failure(struct mce *m)
+{
+       int flags = MF_ACTION_REQUIRED;
+       int ret;
+
+       pr_err("Uncorrected hardware memory error in user-access at %llx", m->addr);
+       if (!(m->mcgstatus & MCG_STATUS_RIPV))
+               flags |= MF_MUST_KILL;
+       ret = memory_failure(m->addr >> PAGE_SHIFT, MCE_VECTOR, flags);
+       if (ret)
+               pr_err("Memory error not recovered");
+       return ret;
+}
+
 /*
  * The actual machine check handler. This only handles real
  * exceptions when something got corrupted coming in through int 18.
@@ -998,8 +1012,6 @@ void do_machine_check(struct pt_regs *regs, long error_code)
        DECLARE_BITMAP(toclear, MAX_NR_BANKS);
        DECLARE_BITMAP(valid_banks, MAX_NR_BANKS);
        char *msg = "Unknown";
-       u64 recover_paddr = ~0ull;
-       int flags = MF_ACTION_REQUIRED;
        int lmce = 0;
 
        /* If this CPU is offline, just bail out. */
@@ -1136,22 +1148,13 @@ void do_machine_check(struct pt_regs *regs, long error_code)
        }
 
        /*
-        * At insane "tolerant" levels we take no action. Otherwise
-        * we only die if we have no other choice. For less serious
-        * issues we try to recover, or limit damage to the current
-        * process.
+        * If tolerant is at an insane level we drop requests to kill
+        * processes and continue even when there is no way out.
         */
-       if (cfg->tolerant < 3) {
-               if (no_way_out)
-                       mce_panic("Fatal machine check on current CPU", &m, msg);
-               if (worst == MCE_AR_SEVERITY) {
-                       recover_paddr = m.addr;
-                       if (!(m.mcgstatus & MCG_STATUS_RIPV))
-                               flags |= MF_MUST_KILL;
-               } else if (kill_it) {
-                       force_sig(SIGBUS, current);
-               }
-       }
+       if (cfg->tolerant == 3)
+               kill_it = 0;
+       else if (no_way_out)
+               mce_panic("Fatal machine check on current CPU", &m, msg);
 
        if (worst > 0)
                mce_report_event(regs);
@@ -1159,25 +1162,24 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 out:
        sync_core();
 
-       if (recover_paddr == ~0ull)
-               goto done;
+       if (worst != MCE_AR_SEVERITY && !kill_it)
+               goto out_ist;
 
-       pr_err("Uncorrected hardware memory error in user-access at %llx",
-                recover_paddr);
-       /*
-        * We must call memory_failure() here even if the current process is
-        * doomed. We still need to mark the page as poisoned and alert any
-        * other users of the page.
-        */
-       ist_begin_non_atomic(regs);
-       local_irq_enable();
-       if (memory_failure(recover_paddr >> PAGE_SHIFT, MCE_VECTOR, flags) < 0) {
-               pr_err("Memory error not recovered");
-               force_sig(SIGBUS, current);
+       /* Fault was in user mode and we need to take some action */
+       if ((m.cs & 3) == 3) {
+               ist_begin_non_atomic(regs);
+               local_irq_enable();
+
+               if (kill_it || do_memory_failure(&m))
+                       force_sig(SIGBUS, current);
+               local_irq_disable();
+               ist_end_non_atomic();
+       } else {
+               if (!fixup_exception(regs, X86_TRAP_MC))
+                       mce_panic("Failed kernel mode recovery", &m, NULL);
        }
-       local_irq_disable();
-       ist_end_non_atomic();
-done:
+
+out_ist:
        ist_exit(regs);
 }
 EXPORT_SYMBOL_GPL(do_machine_check);
@@ -1576,6 +1578,17 @@ static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 
                if (c->x86 == 6 && c->x86_model == 45)
                        quirk_no_way_out = quirk_sandybridge_ifu;
+               /*
+                * MCG_CAP.MCG_SER_P is necessary but not sufficient to know
+                * whether this processor will actually generate recoverable
+                * machine checks. Check to see if this is an E7 model Xeon.
+                * We can't do a model number check because E5 and E7 use the
+                * same model number. E5 doesn't support recovery, E7 does.
+                */
+               if (mca_cfg.recovery || (mca_cfg.ser &&
+                       !strncmp(c->x86_model_id,
+                                "Intel(R) Xeon(R) CPU E7-", 24)))
+                       set_cpu_cap(c, X86_FEATURE_MCE_RECOVERY);
        }
        if (cfg->monarch_timeout < 0)
                cfg->monarch_timeout = 0;
@@ -1617,10 +1630,10 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
        case X86_VENDOR_AMD: {
                u32 ebx = cpuid_ebx(0x80000007);
 
-               mce_amd_feature_init(c);
                mce_flags.overflow_recov = !!(ebx & BIT(0));
                mce_flags.succor         = !!(ebx & BIT(1));
                mce_flags.smca           = !!(ebx & BIT(3));
+               mce_amd_feature_init(c);
 
                break;
                }
@@ -2028,6 +2041,8 @@ static int __init mcheck_enable(char *str)
                cfg->bootlog = (str[0] == 'b');
        else if (!strcmp(str, "bios_cmci_threshold"))
                cfg->bios_cmci_threshold = true;
+       else if (!strcmp(str, "recovery"))
+               cfg->recovery = true;
        else if (isdigit(str[0])) {
                if (get_option(&str, &cfg->tolerant) == 2)
                        get_option(&str, &(cfg->monarch_timeout));
index e99b15077e9464b9c9f337873ae58101285e3215..9d656fd436efd6c90ad148a3cfbbd673248000f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  (c) 2005-2015 Advanced Micro Devices, Inc.
+ *  (c) 2005-2016 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
@@ -28,7 +28,7 @@
 #include <asm/msr.h>
 #include <asm/trace/irq_vectors.h>
 
-#define NR_BLOCKS         9
+#define NR_BLOCKS         5
 #define THRESHOLD_MAX     0xFFF
 #define INT_TYPE_APIC     0x00020000
 #define MASK_VALID_HI     0x80000000
 #define DEF_LVT_OFF            0x2
 #define DEF_INT_TYPE_APIC      0x2
 
+/* Scalable MCA: */
+
+/* Threshold LVT offset is at MSR0xC0000410[15:12] */
+#define SMCA_THR_LVT_OFF       0xF000
+
+/*
+ * OS is required to set the MCAX bit to acknowledge that it is now using the
+ * new MSR ranges and new registers under each bank. It also means that the OS
+ * will configure deferred errors in the new MCx_CONFIG register. If the bit is
+ * not set, uncorrectable errors will cause a system panic.
+ */
+#define SMCA_MCAX_EN_OFF       0x1
+
 static const char * const th_names[] = {
        "load_store",
        "insn_fetch",
@@ -58,6 +71,35 @@ static const char * const th_names[] = {
        "execution_unit",
 };
 
+/* Define HWID to IP type mappings for Scalable MCA */
+struct amd_hwid amd_hwids[] = {
+       [SMCA_F17H_CORE]        = { "f17h_core",        0xB0 },
+       [SMCA_DF]               = { "data_fabric",      0x2E },
+       [SMCA_UMC]              = { "umc",              0x96 },
+       [SMCA_PB]               = { "param_block",      0x5 },
+       [SMCA_PSP]              = { "psp",              0xFF },
+       [SMCA_SMU]              = { "smu",              0x1 },
+};
+EXPORT_SYMBOL_GPL(amd_hwids);
+
+const char * const amd_core_mcablock_names[] = {
+       [SMCA_LS]               = "load_store",
+       [SMCA_IF]               = "insn_fetch",
+       [SMCA_L2_CACHE]         = "l2_cache",
+       [SMCA_DE]               = "decode_unit",
+       [RES]                   = "",
+       [SMCA_EX]               = "execution_unit",
+       [SMCA_FP]               = "floating_point",
+       [SMCA_L3_CACHE]         = "l3_cache",
+};
+EXPORT_SYMBOL_GPL(amd_core_mcablock_names);
+
+const char * const amd_df_mcablock_names[] = {
+       [SMCA_CS]               = "coherent_slave",
+       [SMCA_PIE]              = "pie",
+};
+EXPORT_SYMBOL_GPL(amd_df_mcablock_names);
+
 static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks);
 static DEFINE_PER_CPU(unsigned char, bank_map);        /* see which banks are on */
 
@@ -84,6 +126,13 @@ struct thresh_restart {
 
 static inline bool is_shared_bank(int bank)
 {
+       /*
+        * Scalable MCA provides for only one core to have access to the MSRs of
+        * a shared bank.
+        */
+       if (mce_flags.smca)
+               return false;
+
        /* Bank 4 is for northbridge reporting and is thus shared */
        return (bank == 4);
 }
@@ -135,6 +184,14 @@ static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
        }
 
        if (apic != msr) {
+               /*
+                * On SMCA CPUs, LVT offset is programmed at a different MSR, and
+                * the BIOS provides the value. The original field where LVT offset
+                * was set is reserved. Return early here:
+                */
+               if (mce_flags.smca)
+                       return 0;
+
                pr_err(FW_BUG "cpu %d, invalid threshold interrupt offset %d "
                       "for bank %d, block %d (MSR%08X=0x%x%08x)\n",
                       b->cpu, apic, b->bank, b->block, b->address, hi, lo);
@@ -144,10 +201,7 @@ static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
        return 1;
 };
 
-/*
- * Called via smp_call_function_single(), must be called with correct
- * cpu affinity.
- */
+/* Reprogram MCx_MISC MSR behind this threshold bank. */
 static void threshold_restart_bank(void *_tr)
 {
        struct thresh_restart *tr = _tr;
@@ -247,27 +301,116 @@ static void deferred_error_interrupt_enable(struct cpuinfo_x86 *c)
        wrmsr(MSR_CU_DEF_ERR, low, high);
 }
 
+static u32 get_block_address(u32 current_addr, u32 low, u32 high,
+                            unsigned int bank, unsigned int block)
+{
+       u32 addr = 0, offset = 0;
+
+       if (mce_flags.smca) {
+               if (!block) {
+                       addr = MSR_AMD64_SMCA_MCx_MISC(bank);
+               } else {
+                       /*
+                        * For SMCA enabled processors, BLKPTR field of the
+                        * first MISC register (MCx_MISC0) indicates presence of
+                        * additional MISC register set (MISC1-4).
+                        */
+                       u32 low, high;
+
+                       if (rdmsr_safe(MSR_AMD64_SMCA_MCx_CONFIG(bank), &low, &high))
+                               return addr;
+
+                       if (!(low & MCI_CONFIG_MCAX))
+                               return addr;
+
+                       if (!rdmsr_safe(MSR_AMD64_SMCA_MCx_MISC(bank), &low, &high) &&
+                           (low & MASK_BLKPTR_LO))
+                               addr = MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
+               }
+               return addr;
+       }
+
+       /* Fall back to method we used for older processors: */
+       switch (block) {
+       case 0:
+               addr = MSR_IA32_MCx_MISC(bank);
+               break;
+       case 1:
+               offset = ((low & MASK_BLKPTR_LO) >> 21);
+               if (offset)
+                       addr = MCG_XBLK_ADDR + offset;
+               break;
+       default:
+               addr = ++current_addr;
+       }
+       return addr;
+}
+
+static int
+prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
+                       int offset, u32 misc_high)
+{
+       unsigned int cpu = smp_processor_id();
+       struct threshold_block b;
+       int new;
+
+       if (!block)
+               per_cpu(bank_map, cpu) |= (1 << bank);
+
+       memset(&b, 0, sizeof(b));
+       b.cpu                   = cpu;
+       b.bank                  = bank;
+       b.block                 = block;
+       b.address               = addr;
+       b.interrupt_capable     = lvt_interrupt_supported(bank, misc_high);
+
+       if (!b.interrupt_capable)
+               goto done;
+
+       b.interrupt_enable = 1;
+
+       if (mce_flags.smca) {
+               u32 smca_low, smca_high;
+               u32 smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
+
+               if (!rdmsr_safe(smca_addr, &smca_low, &smca_high)) {
+                       smca_high |= SMCA_MCAX_EN_OFF;
+                       wrmsr(smca_addr, smca_low, smca_high);
+               }
+
+               /* Gather LVT offset for thresholding: */
+               if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high))
+                       goto out;
+
+               new = (smca_low & SMCA_THR_LVT_OFF) >> 12;
+       } else {
+               new = (misc_high & MASK_LVTOFF_HI) >> 20;
+       }
+
+       offset = setup_APIC_mce_threshold(offset, new);
+
+       if ((offset == new) && (mce_threshold_vector != amd_threshold_interrupt))
+               mce_threshold_vector = amd_threshold_interrupt;
+
+done:
+       mce_threshold_block_init(&b, offset);
+
+out:
+       return offset;
+}
+
 /* cpu init entry point, called from mce.c with preempt off */
 void mce_amd_feature_init(struct cpuinfo_x86 *c)
 {
-       struct threshold_block b;
-       unsigned int cpu = smp_processor_id();
        u32 low = 0, high = 0, address = 0;
        unsigned int bank, block;
-       int offset = -1, new;
+       int offset = -1;
 
        for (bank = 0; bank < mca_cfg.banks; ++bank) {
                for (block = 0; block < NR_BLOCKS; ++block) {
-                       if (block == 0)
-                               address = MSR_IA32_MCx_MISC(bank);
-                       else if (block == 1) {
-                               address = (low & MASK_BLKPTR_LO) >> 21;
-                               if (!address)
-                                       break;
-
-                               address += MCG_XBLK_ADDR;
-                       } else
-                               ++address;
+                       address = get_block_address(address, low, high, bank, block);
+                       if (!address)
+                               break;
 
                        if (rdmsr_safe(address, &low, &high))
                                break;
@@ -279,29 +422,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
                             (high & MASK_LOCKED_HI))
                                continue;
 
-                       if (!block)
-                               per_cpu(bank_map, cpu) |= (1 << bank);
-
-                       memset(&b, 0, sizeof(b));
-                       b.cpu                   = cpu;
-                       b.bank                  = bank;
-                       b.block                 = block;
-                       b.address               = address;
-                       b.interrupt_capable     = lvt_interrupt_supported(bank, high);
-
-                       if (!b.interrupt_capable)
-                               goto init;
-
-                       b.interrupt_enable = 1;
-                       new     = (high & MASK_LVTOFF_HI) >> 20;
-                       offset  = setup_APIC_mce_threshold(offset, new);
-
-                       if ((offset == new) &&
-                           (mce_threshold_vector != amd_threshold_interrupt))
-                               mce_threshold_vector = amd_threshold_interrupt;
-
-init:
-                       mce_threshold_block_init(&b, offset);
+                       offset = prepare_threshold_block(bank, block, address, offset, high);
                }
        }
 
@@ -394,16 +515,9 @@ static void amd_threshold_interrupt(void)
                if (!(per_cpu(bank_map, cpu) & (1 << bank)))
                        continue;
                for (block = 0; block < NR_BLOCKS; ++block) {
-                       if (block == 0) {
-                               address = MSR_IA32_MCx_MISC(bank);
-                       } else if (block == 1) {
-                               address = (low & MASK_BLKPTR_LO) >> 21;
-                               if (!address)
-                                       break;
-                               address += MCG_XBLK_ADDR;
-                       } else {
-                               ++address;
-                       }
+                       address = get_block_address(address, low, high, bank, block);
+                       if (!address)
+                               break;
 
                        if (rdmsr_safe(address, &low, &high))
                                break;
@@ -623,16 +737,11 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
        if (err)
                goto out_free;
 recurse:
-       if (!block) {
-               address = (low & MASK_BLKPTR_LO) >> 21;
-               if (!address)
-                       return 0;
-               address += MCG_XBLK_ADDR;
-       } else {
-               ++address;
-       }
+       address = get_block_address(address, low, high, bank, ++block);
+       if (!address)
+               return 0;
 
-       err = allocate_threshold_blocks(cpu, bank, ++block, address);
+       err = allocate_threshold_blocks(cpu, bank, block, address);
        if (err)
                goto out_free;
 
index 12402e10aeffda428821dd6dcb88597203e48054..2a0717bf803372d3968dca9d2b2e6c81740d946d 100644 (file)
@@ -26,14 +26,12 @@ static void pentium_machine_check(struct pt_regs *regs, long error_code)
        rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi);
        rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi);
 
-       printk(KERN_EMERG
-               "CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n",
-               smp_processor_id(), loaddr, lotype);
+       pr_emerg("CPU#%d: Machine Check Exception:  0x%8X (type 0x%8X).\n",
+                smp_processor_id(), loaddr, lotype);
 
        if (lotype & (1<<5)) {
-               printk(KERN_EMERG
-                       "CPU#%d: Possible thermal failure (CPU on fire ?).\n",
-                       smp_processor_id());
+               pr_emerg("CPU#%d: Possible thermal failure (CPU on fire ?).\n",
+                        smp_processor_id());
        }
 
        add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
@@ -61,12 +59,10 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
        /* Read registers before enabling: */
        rdmsr(MSR_IA32_P5_MC_ADDR, l, h);
        rdmsr(MSR_IA32_P5_MC_TYPE, l, h);
-       printk(KERN_INFO
-              "Intel old style machine check architecture supported.\n");
+       pr_info("Intel old style machine check architecture supported.\n");
 
        /* Enable MCE: */
        cr4_set_bits(X86_CR4_MCE);
-       printk(KERN_INFO
-              "Intel old style machine check reporting enabled on CPU#%d.\n",
-              smp_processor_id());
+       pr_info("Intel old style machine check reporting enabled on CPU#%d.\n",
+               smp_processor_id());
 }
index 2c5aaf8c2e2f3dcc94d348dfe91da6d7d5000ae9..0b445c2ff735d44fedc469fd8ce0c1b8b1f1633b 100644 (file)
@@ -190,7 +190,7 @@ static int therm_throt_process(bool new_event, int event, int level)
        /* if we just entered the thermal event */
        if (new_event) {
                if (event == THERMAL_THROTTLING_EVENT)
-                       printk(KERN_CRIT "CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n",
+                       pr_crit("CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n",
                                this_cpu,
                                level == CORE_LEVEL ? "Core" : "Package",
                                state->count);
@@ -198,8 +198,7 @@ static int therm_throt_process(bool new_event, int event, int level)
        }
        if (old_event) {
                if (event == THERMAL_THROTTLING_EVENT)
-                       printk(KERN_INFO "CPU%d: %s temperature/speed normal\n",
-                               this_cpu,
+                       pr_info("CPU%d: %s temperature/speed normal\n", this_cpu,
                                level == CORE_LEVEL ? "Core" : "Package");
                return 1;
        }
@@ -417,8 +416,8 @@ static void intel_thermal_interrupt(void)
 
 static void unexpected_thermal_interrupt(void)
 {
-       printk(KERN_ERR "CPU%d: Unexpected LVT thermal interrupt!\n",
-                       smp_processor_id());
+       pr_err("CPU%d: Unexpected LVT thermal interrupt!\n",
+               smp_processor_id());
 }
 
 static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt;
@@ -499,7 +498,7 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
 
        if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
                if (system_state == SYSTEM_BOOTING)
-                       printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n", cpu);
+                       pr_debug("CPU%d: Thermal monitoring handled by SMI\n", cpu);
                return;
        }
 
@@ -557,8 +556,8 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
        l = apic_read(APIC_LVTTHMR);
        apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
 
-       printk_once(KERN_INFO "CPU0: Thermal monitoring enabled (%s)\n",
-                      tm2 ? "TM2" : "TM1");
+       pr_info_once("CPU0: Thermal monitoring enabled (%s)\n",
+                     tm2 ? "TM2" : "TM1");
 
        /* enable thermal throttle processing */
        atomic_set(&therm_throt_en, 1);
index 7245980186eea047e643af5010e1509bfc991632..fcf9ae9384f4cb4693d67cc8ee6433562dfc9f34 100644 (file)
@@ -12,8 +12,8 @@
 
 static void default_threshold_interrupt(void)
 {
-       printk(KERN_ERR "Unexpected threshold interrupt at vector %x\n",
-                        THRESHOLD_APIC_VECTOR);
+       pr_err("Unexpected threshold interrupt at vector %x\n",
+               THRESHOLD_APIC_VECTOR);
 }
 
 void (*mce_threshold_vector)(void) = default_threshold_interrupt;
index 01dd8702880b7f2db9fcdc3874ba8809c2ce9b80..c6a722e1d011458fa30ec5ad3ad4e78c58d2fa82 100644 (file)
@@ -17,7 +17,7 @@ static void winchip_machine_check(struct pt_regs *regs, long error_code)
 {
        ist_enter(regs);
 
-       printk(KERN_EMERG "CPU0: Machine Check Exception.\n");
+       pr_emerg("CPU0: Machine Check Exception.\n");
        add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE);
 
        ist_exit(regs);
@@ -39,6 +39,5 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c)
 
        cr4_set_bits(X86_CR4_MCE);
 
-       printk(KERN_INFO
-              "Winchip machine check reporting enabled on CPU#0.\n");
+       pr_info("Winchip machine check reporting enabled on CPU#0.\n");
 }
index 2233f8a766156891a52b9a7658f04efeaf4f86c8..8581963894c791e718f67fe37b9b1b4cee3391d6 100644 (file)
@@ -431,10 +431,6 @@ int __init save_microcode_in_initrd_amd(void)
        else
                container = cont_va;
 
-       if (ucode_new_rev)
-               pr_info("microcode: updated early to new patch_level=0x%08x\n",
-                       ucode_new_rev);
-
        eax   = cpuid_eax(0x00000001);
        eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
 
@@ -469,8 +465,7 @@ void reload_ucode_amd(void)
        if (mc && rev < mc->hdr.patch_id) {
                if (!__apply_microcode_amd(mc)) {
                        ucode_new_rev = mc->hdr.patch_id;
-                       pr_info("microcode: reload patch_level=0x%08x\n",
-                               ucode_new_rev);
+                       pr_info("reload patch_level=0x%08x\n", ucode_new_rev);
                }
        }
 }
@@ -793,15 +788,13 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
                return -EINVAL;
        }
 
-       patch->data = kzalloc(patch_size, GFP_KERNEL);
+       patch->data = kmemdup(fw + SECTION_HDR_SIZE, patch_size, GFP_KERNEL);
        if (!patch->data) {
                pr_err("Patch data allocation failure.\n");
                kfree(patch);
                return -EINVAL;
        }
 
-       /* All looks ok, copy patch... */
-       memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size);
        INIT_LIST_HEAD(&patch->plist);
        patch->patch_id  = mc_hdr->patch_id;
        patch->equiv_cpu = proc_id;
@@ -953,10 +946,14 @@ struct microcode_ops * __init init_amd_microcode(void)
        struct cpuinfo_x86 *c = &boot_cpu_data;
 
        if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
-               pr_warning("AMD CPU family 0x%x not supported\n", c->x86);
+               pr_warn("AMD CPU family 0x%x not supported\n", c->x86);
                return NULL;
        }
 
+       if (ucode_new_rev)
+               pr_info_once("microcode updated early to new patch_level=0x%08x\n",
+                            ucode_new_rev);
+
        return &microcode_amd_ops;
 }
 
index faec7120c508584c9f038445c0dae593cfb5faae..ac360bfbbdb6d98af9ffbee6fb6a751d936a5da1 100644 (file)
 #define MICROCODE_VERSION      "2.01"
 
 static struct microcode_ops    *microcode_ops;
-
 static bool dis_ucode_ldr;
 
-static int __init disable_loader(char *str)
-{
-       dis_ucode_ldr = true;
-       return 1;
-}
-__setup("dis_ucode_ldr", disable_loader);
-
 /*
  * Synchronization.
  *
@@ -81,15 +73,16 @@ struct cpu_info_ctx {
 
 static bool __init check_loader_disabled_bsp(void)
 {
+       static const char *__dis_opt_str = "dis_ucode_ldr";
+
 #ifdef CONFIG_X86_32
        const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
-       const char *opt     = "dis_ucode_ldr";
-       const char *option  = (const char *)__pa_nodebug(opt);
+       const char *option  = (const char *)__pa_nodebug(__dis_opt_str);
        bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);
 
 #else /* CONFIG_X86_64 */
        const char *cmdline = boot_command_line;
-       const char *option  = "dis_ucode_ldr";
+       const char *option  = __dis_opt_str;
        bool *res = &dis_ucode_ldr;
 #endif
 
@@ -479,7 +472,7 @@ static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
        enum ucode_state ustate;
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
-       if (uci && uci->valid)
+       if (uci->valid)
                return UCODE_OK;
 
        if (collect_cpu_info(cpu))
@@ -630,7 +623,7 @@ int __init microcode_init(void)
        struct cpuinfo_x86 *c = &boot_cpu_data;
        int error;
 
-       if (paravirt_enabled() || dis_ucode_ldr)
+       if (dis_ucode_ldr)
                return -EINVAL;
 
        if (c->x86_vendor == X86_VENDOR_INTEL)
index ee81c544ee0daa8f6d8f35569463ba3b9f444f06..cbb3cf09b0652a7556649237598c9f74e53744c7 100644 (file)
 #include <asm/setup.h>
 #include <asm/msr.h>
 
-static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT];
+/*
+ * Temporary microcode blobs pointers storage. We note here the pointers to
+ * microcode blobs we've got from whatever storage (detached initrd, builtin).
+ * Later on, we put those into final storage mc_saved_data.mc_saved.
+ */
+static unsigned long mc_tmp_ptrs[MAX_UCODE_COUNT];
+
 static struct mc_saved_data {
-       unsigned int mc_saved_count;
+       unsigned int num_saved;
        struct microcode_intel **mc_saved;
 } mc_saved_data;
 
@@ -78,53 +84,50 @@ load_microcode_early(struct microcode_intel **saved,
 }
 
 static inline void
-copy_initrd_ptrs(struct microcode_intel **mc_saved, unsigned long *initrd,
-                 unsigned long off, int num_saved)
+copy_ptrs(struct microcode_intel **mc_saved, unsigned long *mc_ptrs,
+         unsigned long off, int num_saved)
 {
        int i;
 
        for (i = 0; i < num_saved; i++)
-               mc_saved[i] = (struct microcode_intel *)(initrd[i] + off);
+               mc_saved[i] = (struct microcode_intel *)(mc_ptrs[i] + off);
 }
 
 #ifdef CONFIG_X86_32
 static void
-microcode_phys(struct microcode_intel **mc_saved_tmp,
-              struct mc_saved_data *mc_saved_data)
+microcode_phys(struct microcode_intel **mc_saved_tmp, struct mc_saved_data *mcs)
 {
        int i;
        struct microcode_intel ***mc_saved;
 
-       mc_saved = (struct microcode_intel ***)
-                  __pa_nodebug(&mc_saved_data->mc_saved);
-       for (i = 0; i < mc_saved_data->mc_saved_count; i++) {
+       mc_saved = (struct microcode_intel ***)__pa_nodebug(&mcs->mc_saved);
+
+       for (i = 0; i < mcs->num_saved; i++) {
                struct microcode_intel *p;
 
-               p = *(struct microcode_intel **)
-                       __pa_nodebug(mc_saved_data->mc_saved + i);
+               p = *(struct microcode_intel **)__pa_nodebug(mcs->mc_saved + i);
                mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p);
        }
 }
 #endif
 
 static enum ucode_state
-load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
-              unsigned long initrd_start, struct ucode_cpu_info *uci)
+load_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
+              unsigned long offset, struct ucode_cpu_info *uci)
 {
        struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
-       unsigned int count = mc_saved_data->mc_saved_count;
+       unsigned int count = mcs->num_saved;
 
-       if (!mc_saved_data->mc_saved) {
-               copy_initrd_ptrs(mc_saved_tmp, initrd, initrd_start, count);
+       if (!mcs->mc_saved) {
+               copy_ptrs(mc_saved_tmp, mc_ptrs, offset, count);
 
                return load_microcode_early(mc_saved_tmp, count, uci);
        } else {
 #ifdef CONFIG_X86_32
-               microcode_phys(mc_saved_tmp, mc_saved_data);
+               microcode_phys(mc_saved_tmp, mcs);
                return load_microcode_early(mc_saved_tmp, count, uci);
 #else
-               return load_microcode_early(mc_saved_data->mc_saved,
-                                                   count, uci);
+               return load_microcode_early(mcs->mc_saved, count, uci);
 #endif
        }
 }
@@ -175,25 +178,25 @@ matching_model_microcode(struct microcode_header_intel *mc_header,
 }
 
 static int
-save_microcode(struct mc_saved_data *mc_saved_data,
+save_microcode(struct mc_saved_data *mcs,
               struct microcode_intel **mc_saved_src,
-              unsigned int mc_saved_count)
+              unsigned int num_saved)
 {
        int i, j;
        struct microcode_intel **saved_ptr;
        int ret;
 
-       if (!mc_saved_count)
+       if (!num_saved)
                return -EINVAL;
 
        /*
         * Copy new microcode data.
         */
-       saved_ptr = kcalloc(mc_saved_count, sizeof(struct microcode_intel *), GFP_KERNEL);
+       saved_ptr = kcalloc(num_saved, sizeof(struct microcode_intel *), GFP_KERNEL);
        if (!saved_ptr)
                return -ENOMEM;
 
-       for (i = 0; i < mc_saved_count; i++) {
+       for (i = 0; i < num_saved; i++) {
                struct microcode_header_intel *mc_hdr;
                struct microcode_intel *mc;
                unsigned long size;
@@ -207,20 +210,18 @@ save_microcode(struct mc_saved_data *mc_saved_data,
                mc_hdr = &mc->hdr;
                size   = get_totalsize(mc_hdr);
 
-               saved_ptr[i] = kmalloc(size, GFP_KERNEL);
+               saved_ptr[i] = kmemdup(mc, size, GFP_KERNEL);
                if (!saved_ptr[i]) {
                        ret = -ENOMEM;
                        goto err;
                }
-
-               memcpy(saved_ptr[i], mc, size);
        }
 
        /*
         * Point to newly saved microcode.
         */
-       mc_saved_data->mc_saved = saved_ptr;
-       mc_saved_data->mc_saved_count = mc_saved_count;
+       mcs->mc_saved  = saved_ptr;
+       mcs->num_saved = num_saved;
 
        return 0;
 
@@ -284,22 +285,20 @@ static unsigned int _save_mc(struct microcode_intel **mc_saved,
  * BSP can stay in the platform.
  */
 static enum ucode_state __init
-get_matching_model_microcode(int cpu, unsigned long start,
-                            void *data, size_t size,
-                            struct mc_saved_data *mc_saved_data,
-                            unsigned long *mc_saved_in_initrd,
+get_matching_model_microcode(unsigned long start, void *data, size_t size,
+                            struct mc_saved_data *mcs, unsigned long *mc_ptrs,
                             struct ucode_cpu_info *uci)
 {
-       u8 *ucode_ptr = data;
-       unsigned int leftover = size;
+       struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
+       struct microcode_header_intel *mc_header;
+       unsigned int num_saved = mcs->num_saved;
        enum ucode_state state = UCODE_OK;
+       unsigned int leftover = size;
+       u8 *ucode_ptr = data;
        unsigned int mc_size;
-       struct microcode_header_intel *mc_header;
-       struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
-       unsigned int mc_saved_count = mc_saved_data->mc_saved_count;
        int i;
 
-       while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) {
+       while (leftover && num_saved < ARRAY_SIZE(mc_saved_tmp)) {
 
                if (leftover < sizeof(mc_header))
                        break;
@@ -318,32 +317,31 @@ get_matching_model_microcode(int cpu, unsigned long start,
                 * the platform, we need to find and save microcode patches
                 * with the same family and model as the BSP.
                 */
-               if (matching_model_microcode(mc_header, uci->cpu_sig.sig) !=
-                        UCODE_OK) {
+               if (matching_model_microcode(mc_header, uci->cpu_sig.sig) != UCODE_OK) {
                        ucode_ptr += mc_size;
                        continue;
                }
 
-               mc_saved_count = _save_mc(mc_saved_tmp, ucode_ptr, mc_saved_count);
+               num_saved = _save_mc(mc_saved_tmp, ucode_ptr, num_saved);
 
                ucode_ptr += mc_size;
        }
 
        if (leftover) {
                state = UCODE_ERROR;
-               goto out;
+               return state;
        }
 
-       if (mc_saved_count == 0) {
+       if (!num_saved) {
                state = UCODE_NFOUND;
-               goto out;
+               return state;
        }
 
-       for (i = 0; i < mc_saved_count; i++)
-               mc_saved_in_initrd[i] = (unsigned long)mc_saved_tmp[i] - start;
+       for (i = 0; i < num_saved; i++)
+               mc_ptrs[i] = (unsigned long)mc_saved_tmp[i] - start;
+
+       mcs->num_saved = num_saved;
 
-       mc_saved_data->mc_saved_count = mc_saved_count;
-out:
        return state;
 }
 
@@ -373,7 +371,7 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
                native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
                csig.pf = 1 << ((val[1] >> 18) & 7);
        }
-       native_wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+       native_wrmsrl(MSR_IA32_UCODE_REV, 0);
 
        /* As documented in the SDM: Do a CPUID 1 here */
        sync_core();
@@ -396,11 +394,11 @@ static void show_saved_mc(void)
        unsigned int sig, pf, rev, total_size, data_size, date;
        struct ucode_cpu_info uci;
 
-       if (mc_saved_data.mc_saved_count == 0) {
+       if (!mc_saved_data.num_saved) {
                pr_debug("no microcode data saved.\n");
                return;
        }
-       pr_debug("Total microcode saved: %d\n", mc_saved_data.mc_saved_count);
+       pr_debug("Total microcode saved: %d\n", mc_saved_data.num_saved);
 
        collect_cpu_info_early(&uci);
 
@@ -409,7 +407,7 @@ static void show_saved_mc(void)
        rev = uci.cpu_sig.rev;
        pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev);
 
-       for (i = 0; i < mc_saved_data.mc_saved_count; i++) {
+       for (i = 0; i < mc_saved_data.num_saved; i++) {
                struct microcode_header_intel *mc_saved_header;
                struct extended_sigtable *ext_header;
                int ext_sigcount;
@@ -465,7 +463,7 @@ int save_mc_for_early(u8 *mc)
 {
        struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
        unsigned int mc_saved_count_init;
-       unsigned int mc_saved_count;
+       unsigned int num_saved;
        struct microcode_intel **mc_saved;
        int ret = 0;
        int i;
@@ -476,23 +474,23 @@ int save_mc_for_early(u8 *mc)
         */
        mutex_lock(&x86_cpu_microcode_mutex);
 
-       mc_saved_count_init = mc_saved_data.mc_saved_count;
-       mc_saved_count = mc_saved_data.mc_saved_count;
+       mc_saved_count_init = mc_saved_data.num_saved;
+       num_saved = mc_saved_data.num_saved;
        mc_saved = mc_saved_data.mc_saved;
 
-       if (mc_saved && mc_saved_count)
+       if (mc_saved && num_saved)
                memcpy(mc_saved_tmp, mc_saved,
-                      mc_saved_count * sizeof(struct microcode_intel *));
+                      num_saved * sizeof(struct microcode_intel *));
        /*
         * Save the microcode patch mc in mc_save_tmp structure if it's a newer
         * version.
         */
-       mc_saved_count = _save_mc(mc_saved_tmp, mc, mc_saved_count);
+       num_saved = _save_mc(mc_saved_tmp, mc, num_saved);
 
        /*
         * Save the mc_save_tmp in global mc_saved_data.
         */
-       ret = save_microcode(&mc_saved_data, mc_saved_tmp, mc_saved_count);
+       ret = save_microcode(&mc_saved_data, mc_saved_tmp, num_saved);
        if (ret) {
                pr_err("Cannot save microcode patch.\n");
                goto out;
@@ -536,7 +534,7 @@ static bool __init load_builtin_intel_microcode(struct cpio_data *cp)
 
 static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin";
 static __init enum ucode_state
-scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
+scan_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
               unsigned long start, unsigned long size,
               struct ucode_cpu_info *uci)
 {
@@ -551,14 +549,18 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
        cd.data = NULL;
        cd.size = 0;
 
-       cd = find_cpio_data(p, (void *)start, size, &offset);
-       if (!cd.data) {
+       /* try built-in microcode if no initrd */
+       if (!size) {
                if (!load_builtin_intel_microcode(&cd))
                        return UCODE_ERROR;
+       } else {
+               cd = find_cpio_data(p, (void *)start, size, &offset);
+               if (!cd.data)
+                       return UCODE_ERROR;
        }
 
-       return get_matching_model_microcode(0, start, cd.data, cd.size,
-                                           mc_saved_data, initrd, uci);
+       return get_matching_model_microcode(start, cd.data, cd.size,
+                                           mcs, mc_ptrs, uci);
 }
 
 /*
@@ -567,14 +569,11 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
 static void
 print_ucode_info(struct ucode_cpu_info *uci, unsigned int date)
 {
-       int cpu = smp_processor_id();
-
-       pr_info("CPU%d microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n",
-               cpu,
-               uci->cpu_sig.rev,
-               date & 0xffff,
-               date >> 24,
-               (date >> 16) & 0xff);
+       pr_info_once("microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n",
+                    uci->cpu_sig.rev,
+                    date & 0xffff,
+                    date >> 24,
+                    (date >> 16) & 0xff);
 }
 
 #ifdef CONFIG_X86_32
@@ -603,19 +602,19 @@ void show_ucode_info_early(void)
  */
 static void print_ucode(struct ucode_cpu_info *uci)
 {
-       struct microcode_intel *mc_intel;
+       struct microcode_intel *mc;
        int *delay_ucode_info_p;
        int *current_mc_date_p;
 
-       mc_intel = uci->mc;
-       if (mc_intel == NULL)
+       mc = uci->mc;
+       if (!mc)
                return;
 
        delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info);
        current_mc_date_p = (int *)__pa_nodebug(&current_mc_date);
 
        *delay_ucode_info_p = 1;
-       *current_mc_date_p = mc_intel->hdr.date;
+       *current_mc_date_p = mc->hdr.date;
 }
 #else
 
@@ -630,37 +629,35 @@ static inline void flush_tlb_early(void)
 
 static inline void print_ucode(struct ucode_cpu_info *uci)
 {
-       struct microcode_intel *mc_intel;
+       struct microcode_intel *mc;
 
-       mc_intel = uci->mc;
-       if (mc_intel == NULL)
+       mc = uci->mc;
+       if (!mc)
                return;
 
-       print_ucode_info(uci, mc_intel->hdr.date);
+       print_ucode_info(uci, mc->hdr.date);
 }
 #endif
 
 static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
 {
-       struct microcode_intel *mc_intel;
+       struct microcode_intel *mc;
        unsigned int val[2];
 
-       mc_intel = uci->mc;
-       if (mc_intel == NULL)
+       mc = uci->mc;
+       if (!mc)
                return 0;
 
        /* write microcode via MSR 0x79 */
-       native_wrmsr(MSR_IA32_UCODE_WRITE,
-             (unsigned long) mc_intel->bits,
-             (unsigned long) mc_intel->bits >> 16 >> 16);
-       native_wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+       native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
+       native_wrmsrl(MSR_IA32_UCODE_REV, 0);
 
        /* As documented in the SDM: Do a CPUID 1 here */
        sync_core();
 
        /* get the current revision from MSR 0x8B */
        native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-       if (val[1] != mc_intel->hdr.rev)
+       if (val[1] != mc->hdr.rev)
                return -1;
 
 #ifdef CONFIG_X86_64
@@ -672,25 +669,26 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
        if (early)
                print_ucode(uci);
        else
-               print_ucode_info(uci, mc_intel->hdr.date);
+               print_ucode_info(uci, mc->hdr.date);
 
        return 0;
 }
 
 /*
  * This function converts microcode patch offsets previously stored in
- * mc_saved_in_initrd to pointers and stores the pointers in mc_saved_data.
+ * mc_tmp_ptrs to pointers and stores the pointers in mc_saved_data.
  */
 int __init save_microcode_in_initrd_intel(void)
 {
-       unsigned int count = mc_saved_data.mc_saved_count;
+       unsigned int count = mc_saved_data.num_saved;
        struct microcode_intel *mc_saved[MAX_UCODE_COUNT];
        int ret = 0;
 
-       if (count == 0)
+       if (!count)
                return ret;
 
-       copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count);
+       copy_ptrs(mc_saved, mc_tmp_ptrs, get_initrd_start(), count);
+
        ret = save_microcode(&mc_saved_data, mc_saved, count);
        if (ret)
                pr_err("Cannot save microcode patches from initrd.\n");
@@ -701,8 +699,7 @@ int __init save_microcode_in_initrd_intel(void)
 }
 
 static void __init
-_load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data,
-                     unsigned long *initrd,
+_load_ucode_intel_bsp(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
                      unsigned long start, unsigned long size)
 {
        struct ucode_cpu_info uci;
@@ -710,11 +707,11 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data,
 
        collect_cpu_info_early(&uci);
 
-       ret = scan_microcode(mc_saved_data, initrd, start, size, &uci);
+       ret = scan_microcode(mcs, mc_ptrs, start, size, &uci);
        if (ret != UCODE_OK)
                return;
 
-       ret = load_microcode(mc_saved_data, initrd, start, &uci);
+       ret = load_microcode(mcs, mc_ptrs, start, &uci);
        if (ret != UCODE_OK)
                return;
 
@@ -728,53 +725,49 @@ void __init load_ucode_intel_bsp(void)
        struct boot_params *p;
 
        p       = (struct boot_params *)__pa_nodebug(&boot_params);
-       start   = p->hdr.ramdisk_image;
        size    = p->hdr.ramdisk_size;
 
-       _load_ucode_intel_bsp(
-                       (struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
-                       (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
-                       start, size);
+       /*
+        * Set start only if we have an initrd image. We cannot use initrd_start
+        * because it is not set that early yet.
+        */
+       start   = (size ? p->hdr.ramdisk_image : 0);
+
+       _load_ucode_intel_bsp((struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
+                             (unsigned long *)__pa_nodebug(&mc_tmp_ptrs),
+                             start, size);
 #else
-       start   = boot_params.hdr.ramdisk_image + PAGE_OFFSET;
        size    = boot_params.hdr.ramdisk_size;
+       start   = (size ? boot_params.hdr.ramdisk_image + PAGE_OFFSET : 0);
 
-       _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size);
+       _load_ucode_intel_bsp(&mc_saved_data, mc_tmp_ptrs, start, size);
 #endif
 }
 
 void load_ucode_intel_ap(void)
 {
-       struct mc_saved_data *mc_saved_data_p;
+       unsigned long *mcs_tmp_p;
+       struct mc_saved_data *mcs_p;
        struct ucode_cpu_info uci;
-       unsigned long *mc_saved_in_initrd_p;
-       unsigned long initrd_start_addr;
        enum ucode_state ret;
 #ifdef CONFIG_X86_32
-       unsigned long *initrd_start_p;
 
-       mc_saved_in_initrd_p =
-               (unsigned long *)__pa_nodebug(mc_saved_in_initrd);
-       mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
-       initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
-       initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p);
+       mcs_tmp_p = (unsigned long *)__pa_nodebug(mc_tmp_ptrs);
+       mcs_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
 #else
-       mc_saved_data_p = &mc_saved_data;
-       mc_saved_in_initrd_p = mc_saved_in_initrd;
-       initrd_start_addr = initrd_start;
+       mcs_tmp_p = mc_tmp_ptrs;
+       mcs_p = &mc_saved_data;
 #endif
 
        /*
         * If there is no valid ucode previously saved in memory, no need to
         * update ucode on this AP.
         */
-       if (mc_saved_data_p->mc_saved_count == 0)
+       if (!mcs_p->num_saved)
                return;
 
        collect_cpu_info_early(&uci);
-       ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
-                            initrd_start_addr, &uci);
-
+       ret = load_microcode(mcs_p, mcs_tmp_p, get_initrd_start_addr(), &uci);
        if (ret != UCODE_OK)
                return;
 
@@ -786,13 +779,13 @@ void reload_ucode_intel(void)
        struct ucode_cpu_info uci;
        enum ucode_state ret;
 
-       if (!mc_saved_data.mc_saved_count)
+       if (!mc_saved_data.num_saved)
                return;
 
        collect_cpu_info_early(&uci);
 
        ret = load_microcode_early(mc_saved_data.mc_saved,
-                                  mc_saved_data.mc_saved_count, &uci);
+                                  mc_saved_data.num_saved, &uci);
        if (ret != UCODE_OK)
                return;
 
@@ -825,7 +818,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
  * return 0 - no update found
  * return 1 - found update
  */
-static int get_matching_mc(struct microcode_intel *mc_intel, int cpu)
+static int get_matching_mc(struct microcode_intel *mc, int cpu)
 {
        struct cpu_signature cpu_sig;
        unsigned int csig, cpf, crev;
@@ -836,39 +829,36 @@ static int get_matching_mc(struct microcode_intel *mc_intel, int cpu)
        cpf = cpu_sig.pf;
        crev = cpu_sig.rev;
 
-       return has_newer_microcode(mc_intel, csig, cpf, crev);
+       return has_newer_microcode(mc, csig, cpf, crev);
 }
 
 static int apply_microcode_intel(int cpu)
 {
-       struct microcode_intel *mc_intel;
+       struct microcode_intel *mc;
        struct ucode_cpu_info *uci;
+       struct cpuinfo_x86 *c;
        unsigned int val[2];
-       int cpu_num = raw_smp_processor_id();
-       struct cpuinfo_x86 *c = &cpu_data(cpu_num);
-
-       uci = ucode_cpu_info + cpu;
-       mc_intel = uci->mc;
 
        /* We should bind the task to the CPU */
-       BUG_ON(cpu_num != cpu);
+       if (WARN_ON(raw_smp_processor_id() != cpu))
+               return -1;
 
-       if (mc_intel == NULL)
+       uci = ucode_cpu_info + cpu;
+       mc = uci->mc;
+       if (!mc)
                return 0;
 
        /*
         * Microcode on this CPU could be updated earlier. Only apply the
-        * microcode patch in mc_intel when it is newer than the one on this
+        * microcode patch in mc when it is newer than the one on this
         * CPU.
         */
-       if (get_matching_mc(mc_intel, cpu) == 0)
+       if (!get_matching_mc(mc, cpu))
                return 0;
 
        /* write microcode via MSR 0x79 */
-       wrmsr(MSR_IA32_UCODE_WRITE,
-             (unsigned long) mc_intel->bits,
-             (unsigned long) mc_intel->bits >> 16 >> 16);
-       wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+       wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
+       wrmsrl(MSR_IA32_UCODE_REV, 0);
 
        /* As documented in the SDM: Do a CPUID 1 here */
        sync_core();
@@ -876,16 +866,19 @@ static int apply_microcode_intel(int cpu)
        /* get the current revision from MSR 0x8B */
        rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 
-       if (val[1] != mc_intel->hdr.rev) {
+       if (val[1] != mc->hdr.rev) {
                pr_err("CPU%d update to revision 0x%x failed\n",
-                      cpu_num, mc_intel->hdr.rev);
+                      cpu, mc->hdr.rev);
                return -1;
        }
+
        pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n",
-               cpu_num, val[1],
-               mc_intel->hdr.date & 0xffff,
-               mc_intel->hdr.date >> 24,
-               (mc_intel->hdr.date >> 16) & 0xff);
+               cpu, val[1],
+               mc->hdr.date & 0xffff,
+               mc->hdr.date >> 24,
+               (mc->hdr.date >> 16) & 0xff);
+
+       c = &cpu_data(cpu);
 
        uci->cpu_sig.rev = val[1];
        c->microcode = val[1];
index b96896bcbdaf1ac88d4dcfa2a7ce3a98d291ccad..2ce1a7dc45b730cde0097e77353b9c426f3782b8 100644 (file)
@@ -49,7 +49,7 @@ int microcode_sanity_check(void *mc, int print_err)
        unsigned long total_size, data_size, ext_table_size;
        struct microcode_header_intel *mc_header = mc;
        struct extended_sigtable *ext_header = NULL;
-       int sum, orig_sum, ext_sigcount = 0, i;
+       u32 sum, orig_sum, ext_sigcount = 0, i;
        struct extended_signature *ext_sig;
 
        total_size = get_totalsize(mc_header);
@@ -57,69 +57,85 @@ int microcode_sanity_check(void *mc, int print_err)
 
        if (data_size + MC_HEADER_SIZE > total_size) {
                if (print_err)
-                       pr_err("error! Bad data size in microcode data file\n");
+                       pr_err("Error: bad microcode data file size.\n");
                return -EINVAL;
        }
 
        if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
                if (print_err)
-                       pr_err("error! Unknown microcode update format\n");
+                       pr_err("Error: invalid/unknown microcode update format.\n");
                return -EINVAL;
        }
+
        ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
        if (ext_table_size) {
+               u32 ext_table_sum = 0;
+               u32 *ext_tablep;
+
                if ((ext_table_size < EXT_HEADER_SIZE)
                 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
                        if (print_err)
-                               pr_err("error! Small exttable size in microcode data file\n");
+                               pr_err("Error: truncated extended signature table.\n");
                        return -EINVAL;
                }
+
                ext_header = mc + MC_HEADER_SIZE + data_size;
                if (ext_table_size != exttable_size(ext_header)) {
                        if (print_err)
-                               pr_err("error! Bad exttable size in microcode data file\n");
+                               pr_err("Error: extended signature table size mismatch.\n");
                        return -EFAULT;
                }
+
                ext_sigcount = ext_header->count;
-       }
 
-       /* check extended table checksum */
-       if (ext_table_size) {
-               int ext_table_sum = 0;
-               int *ext_tablep = (int *)ext_header;
+               /*
+                * Check extended table checksum: the sum of all dwords that
+                * comprise a valid table must be 0.
+                */
+               ext_tablep = (u32 *)ext_header;
 
-               i = ext_table_size / DWSIZE;
+               i = ext_table_size / sizeof(u32);
                while (i--)
                        ext_table_sum += ext_tablep[i];
+
                if (ext_table_sum) {
                        if (print_err)
-                               pr_warn("aborting, bad extended signature table checksum\n");
+                               pr_warn("Bad extended signature table checksum, aborting.\n");
                        return -EINVAL;
                }
        }
 
-       /* calculate the checksum */
+       /*
+        * Calculate the checksum of update data and header. The checksum of
+        * valid update data and header including the extended signature table
+        * must be 0.
+        */
        orig_sum = 0;
-       i = (MC_HEADER_SIZE + data_size) / DWSIZE;
+       i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
        while (i--)
-               orig_sum += ((int *)mc)[i];
+               orig_sum += ((u32 *)mc)[i];
+
        if (orig_sum) {
                if (print_err)
-                       pr_err("aborting, bad checksum\n");
+                       pr_err("Bad microcode data checksum, aborting.\n");
                return -EINVAL;
        }
+
        if (!ext_table_size)
                return 0;
-       /* check extended signature checksum */
+
+       /*
+        * Check extended signature checksum: 0 => valid.
+        */
        for (i = 0; i < ext_sigcount; i++) {
                ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
                          EXT_SIGNATURE_SIZE * i;
-               sum = orig_sum
-                       - (mc_header->sig + mc_header->pf + mc_header->cksum)
-                       + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+
+               sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
+                     (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
                if (sum) {
                        if (print_err)
-                               pr_err("aborting, bad checksum\n");
+                               pr_err("Bad extended signature checksum, aborting.\n");
                        return -EINVAL;
                }
        }
index 3f20710a5b23b7f7456e99bb7f654ce703bb6abf..6988c74409a825313a2711be6914a20369d223e0 100644 (file)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeature.h
+# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeatures.h
 #
 
 IN=$1
@@ -49,8 +49,8 @@ dump_array()
 trap 'rm "$OUT"' EXIT
 
 (
-       echo "#ifndef _ASM_X86_CPUFEATURE_H"
-       echo "#include <asm/cpufeature.h>"
+       echo "#ifndef _ASM_X86_CPUFEATURES_H"
+       echo "#include <asm/cpufeatures.h>"
        echo "#endif"
        echo ""
 
index 20e242ea1bc46b5f5828c7b95071d920853b7609..4e7c6933691cc8de42aa4a82473482127bd0faab 100644 (file)
@@ -161,8 +161,8 @@ static void __init ms_hyperv_init_platform(void)
        ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
        ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
 
-       printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
-              ms_hyperv.features, ms_hyperv.hints);
+       pr_info("HyperV: features 0x%x, hints 0x%x\n",
+               ms_hyperv.features, ms_hyperv.hints);
 
 #ifdef CONFIG_X86_LOCAL_APIC
        if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) {
@@ -174,8 +174,8 @@ static void __init ms_hyperv_init_platform(void)
                rdmsrl(HV_X64_MSR_APIC_FREQUENCY, hv_lapic_frequency);
                hv_lapic_frequency = div_u64(hv_lapic_frequency, HZ);
                lapic_timer_frequency = hv_lapic_frequency;
-               printk(KERN_INFO "HyperV: LAPIC Timer Frequency: %#x\n",
-                               lapic_timer_frequency);
+               pr_info("HyperV: LAPIC Timer Frequency: %#x\n",
+                       lapic_timer_frequency);
        }
 #endif
 
index 316fe3e60a9764e479d4e49d01346c7921763ee8..3d689937fc1b13974a0a8a5edd31ddda0f6401b2 100644 (file)
@@ -103,7 +103,7 @@ centaur_validate_add_page(unsigned long base, unsigned long size, unsigned int t
         */
        if (type != MTRR_TYPE_WRCOMB &&
            (centaur_mcr_type == 0 || type != MTRR_TYPE_UNCACHABLE)) {
-               pr_warning("mtrr: only write-combining%s supported\n",
+               pr_warn("mtrr: only write-combining%s supported\n",
                           centaur_mcr_type ? " and uncacheable are" : " is");
                return -EINVAL;
        }
index 0d98503c2245aab81283526c062f746650b99c32..31e951ce6dff33782c9610c7b43898181d59d637 100644 (file)
@@ -57,9 +57,9 @@ static int __initdata                         nr_range;
 static struct var_mtrr_range_state __initdata  range_state[RANGE_NUM];
 
 static int __initdata debug_print;
-#define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0)
+#define Dprintk(x...) do { if (debug_print) pr_debug(x); } while (0)
 
-#define BIOS_BUG_MSG KERN_WARNING \
+#define BIOS_BUG_MSG \
        "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n"
 
 static int __init
@@ -81,9 +81,9 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range,
                                                base, base + size);
        }
        if (debug_print) {
-               printk(KERN_DEBUG "After WB checking\n");
+               pr_debug("After WB checking\n");
                for (i = 0; i < nr_range; i++)
-                       printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n",
+                       pr_debug("MTRR MAP PFN: %016llx - %016llx\n",
                                 range[i].start, range[i].end);
        }
 
@@ -101,7 +101,7 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range,
                    (mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) &&
                    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
                        /* Var MTRR contains UC entry below 1M? Skip it: */
-                       printk(BIOS_BUG_MSG, i);
+                       pr_warn(BIOS_BUG_MSG, i);
                        if (base + size <= (1<<(20-PAGE_SHIFT)))
                                continue;
                        size -= (1<<(20-PAGE_SHIFT)) - base;
@@ -114,11 +114,11 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range,
                                 extra_remove_base + extra_remove_size);
 
        if  (debug_print) {
-               printk(KERN_DEBUG "After UC checking\n");
+               pr_debug("After UC checking\n");
                for (i = 0; i < RANGE_NUM; i++) {
                        if (!range[i].end)
                                continue;
-                       printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n",
+                       pr_debug("MTRR MAP PFN: %016llx - %016llx\n",
                                 range[i].start, range[i].end);
                }
        }
@@ -126,9 +126,9 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range,
        /* sort the ranges */
        nr_range = clean_sort_range(range, RANGE_NUM);
        if  (debug_print) {
-               printk(KERN_DEBUG "After sorting\n");
+               pr_debug("After sorting\n");
                for (i = 0; i < nr_range; i++)
-                       printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n",
+                       pr_debug("MTRR MAP PFN: %016llx - %016llx\n",
                                 range[i].start, range[i].end);
        }
 
@@ -544,7 +544,7 @@ static void __init print_out_mtrr_range_state(void)
                start_base = to_size_factor(start_base, &start_factor),
                type = range_state[i].type;
 
-               printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n",
+               pr_debug("reg %d, base: %ld%cB, range: %ld%cB, type %s\n",
                        i, start_base, start_factor,
                        size_base, size_factor,
                        (type == MTRR_TYPE_UNCACHABLE) ? "UC" :
@@ -713,7 +713,7 @@ int __init mtrr_cleanup(unsigned address_bits)
                return 0;
 
        /* Print original var MTRRs at first, for debugging: */
-       printk(KERN_DEBUG "original variable MTRRs\n");
+       pr_debug("original variable MTRRs\n");
        print_out_mtrr_range_state();
 
        memset(range, 0, sizeof(range));
@@ -733,7 +733,7 @@ int __init mtrr_cleanup(unsigned address_bits)
                                          x_remove_base, x_remove_size);
 
        range_sums = sum_ranges(range, nr_range);
-       printk(KERN_INFO "total RAM covered: %ldM\n",
+       pr_info("total RAM covered: %ldM\n",
               range_sums >> (20 - PAGE_SHIFT));
 
        if (mtrr_chunk_size && mtrr_gran_size) {
@@ -745,12 +745,11 @@ int __init mtrr_cleanup(unsigned address_bits)
 
                if (!result[i].bad) {
                        set_var_mtrr_all(address_bits);
-                       printk(KERN_DEBUG "New variable MTRRs\n");
+                       pr_debug("New variable MTRRs\n");
                        print_out_mtrr_range_state();
                        return 1;
                }
-               printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, "
-                      "will find optimal one\n");
+               pr_info("invalid mtrr_gran_size or mtrr_chunk_size, will find optimal one\n");
        }
 
        i = 0;
@@ -768,7 +767,7 @@ int __init mtrr_cleanup(unsigned address_bits)
                                      x_remove_base, x_remove_size, i);
                        if (debug_print) {
                                mtrr_print_out_one_result(i);
-                               printk(KERN_INFO "\n");
+                               pr_info("\n");
                        }
 
                        i++;
@@ -779,7 +778,7 @@ int __init mtrr_cleanup(unsigned address_bits)
        index_good = mtrr_search_optimal_index();
 
        if (index_good != -1) {
-               printk(KERN_INFO "Found optimal setting for mtrr clean up\n");
+               pr_info("Found optimal setting for mtrr clean up\n");
                i = index_good;
                mtrr_print_out_one_result(i);
 
@@ -790,7 +789,7 @@ int __init mtrr_cleanup(unsigned address_bits)
                gran_size <<= 10;
                x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size);
                set_var_mtrr_all(address_bits);
-               printk(KERN_DEBUG "New variable MTRRs\n");
+               pr_debug("New variable MTRRs\n");
                print_out_mtrr_range_state();
                return 1;
        } else {
@@ -799,8 +798,8 @@ int __init mtrr_cleanup(unsigned address_bits)
                        mtrr_print_out_one_result(i);
        }
 
-       printk(KERN_INFO "mtrr_cleanup: can not find optimal value\n");
-       printk(KERN_INFO "please specify mtrr_gran_size/mtrr_chunk_size\n");
+       pr_info("mtrr_cleanup: can not find optimal value\n");
+       pr_info("please specify mtrr_gran_size/mtrr_chunk_size\n");
 
        return 0;
 }
@@ -918,7 +917,7 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
 
        /* kvm/qemu doesn't have mtrr set right, don't trim them all: */
        if (!highest_pfn) {
-               printk(KERN_INFO "CPU MTRRs all blank - virtualized system.\n");
+               pr_info("CPU MTRRs all blank - virtualized system.\n");
                return 0;
        }
 
@@ -973,7 +972,8 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn)
                                                         end_pfn);
 
        if (total_trim_size) {
-               pr_warning("WARNING: BIOS bug: CPU MTRRs don't cover all of memory, losing %lluMB of RAM.\n", total_trim_size >> 20);
+               pr_warn("WARNING: BIOS bug: CPU MTRRs don't cover all of memory, losing %lluMB of RAM.\n",
+                       total_trim_size >> 20);
 
                if (!changed_by_mtrr_cleanup)
                        WARN_ON(1);
index c870af1610083ec3dda7cb61b966860c9a224374..fcbcb2f678ca47360d23623887d216165969d6e8 100644 (file)
@@ -55,7 +55,7 @@ static inline void k8_check_syscfg_dram_mod_en(void)
 
        rdmsr(MSR_K8_SYSCFG, lo, hi);
        if (lo & K8_MTRRFIXRANGE_DRAM_MODIFY) {
-               printk(KERN_ERR FW_WARN "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]"
+               pr_err(FW_WARN "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]"
                       " not cleared by BIOS, clearing this bit\n",
                       smp_processor_id());
                lo &= ~K8_MTRRFIXRANGE_DRAM_MODIFY;
@@ -501,14 +501,14 @@ void __init mtrr_state_warn(void)
        if (!mask)
                return;
        if (mask & MTRR_CHANGE_MASK_FIXED)
-               pr_warning("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
+               pr_warn("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
        if (mask & MTRR_CHANGE_MASK_VARIABLE)
-               pr_warning("mtrr: your CPUs had inconsistent variable MTRR settings\n");
+               pr_warn("mtrr: your CPUs had inconsistent variable MTRR settings\n");
        if (mask & MTRR_CHANGE_MASK_DEFTYPE)
-               pr_warning("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
+               pr_warn("mtrr: your CPUs had inconsistent MTRRdefType settings\n");
 
-       printk(KERN_INFO "mtrr: probably your BIOS does not setup all CPUs.\n");
-       printk(KERN_INFO "mtrr: corrected configuration.\n");
+       pr_info("mtrr: probably your BIOS does not setup all CPUs.\n");
+       pr_info("mtrr: corrected configuration.\n");
 }
 
 /*
@@ -519,8 +519,7 @@ void __init mtrr_state_warn(void)
 void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
 {
        if (wrmsr_safe(msr, a, b) < 0) {
-               printk(KERN_ERR
-                       "MTRR: CPU %u: Writing MSR %x to %x:%x failed\n",
+               pr_err("MTRR: CPU %u: Writing MSR %x to %x:%x failed\n",
                        smp_processor_id(), msr, a, b);
        }
 }
@@ -607,7 +606,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
                tmp |= ~((1ULL<<(hi - 1)) - 1);
 
                if (tmp != mask) {
-                       printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n");
+                       pr_warn("mtrr: your BIOS has configured an incorrect mask, fixing it.\n");
                        add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
                        mask = tmp;
                }
@@ -858,13 +857,13 @@ int generic_validate_add_page(unsigned long base, unsigned long size,
            boot_cpu_data.x86_model == 1 &&
            boot_cpu_data.x86_mask <= 7) {
                if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) {
-                       pr_warning("mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
+                       pr_warn("mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
                        return -EINVAL;
                }
                if (!(base + size < 0x70000 || base > 0x7003F) &&
                    (type == MTRR_TYPE_WRCOMB
                     || type == MTRR_TYPE_WRBACK)) {
-                       pr_warning("mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
+                       pr_warn("mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
                        return -EINVAL;
                }
        }
@@ -878,7 +877,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size,
             lbase = lbase >> 1, last = last >> 1)
                ;
        if (lbase != last) {
-               pr_warning("mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n", base, size);
+               pr_warn("mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n", base, size);
                return -EINVAL;
        }
        return 0;
index 5c3d149ee91cb1f6c87ff6ad1853a38adfce82da..10f8d4796240709cea61c0e56522d75eeff8ffdd 100644 (file)
@@ -47,7 +47,7 @@
 #include <linux/smp.h>
 #include <linux/syscore_ops.h>
 
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <asm/e820.h>
 #include <asm/mtrr.h>
 #include <asm/msr.h>
@@ -300,24 +300,24 @@ int mtrr_add_page(unsigned long base, unsigned long size,
                return error;
 
        if (type >= MTRR_NUM_TYPES) {
-               pr_warning("mtrr: type: %u invalid\n", type);
+               pr_warn("mtrr: type: %u invalid\n", type);
                return -EINVAL;
        }
 
        /* If the type is WC, check that this processor supports it */
        if ((type == MTRR_TYPE_WRCOMB) && !have_wrcomb()) {
-               pr_warning("mtrr: your processor doesn't support write-combining\n");
+               pr_warn("mtrr: your processor doesn't support write-combining\n");
                return -ENOSYS;
        }
 
        if (!size) {
-               pr_warning("mtrr: zero sized request\n");
+               pr_warn("mtrr: zero sized request\n");
                return -EINVAL;
        }
 
        if ((base | (base + size - 1)) >>
            (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) {
-               pr_warning("mtrr: base or size exceeds the MTRR width\n");
+               pr_warn("mtrr: base or size exceeds the MTRR width\n");
                return -EINVAL;
        }
 
@@ -348,7 +348,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
                                } else if (types_compatible(type, ltype))
                                        continue;
                        }
-                       pr_warning("mtrr: 0x%lx000,0x%lx000 overlaps existing"
+                       pr_warn("mtrr: 0x%lx000,0x%lx000 overlaps existing"
                                " 0x%lx000,0x%lx000\n", base, size, lbase,
                                lsize);
                        goto out;
@@ -357,7 +357,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
                if (ltype != type) {
                        if (types_compatible(type, ltype))
                                continue;
-                       pr_warning("mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
+                       pr_warn("mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n",
                                base, size, mtrr_attrib_to_str(ltype),
                                mtrr_attrib_to_str(type));
                        goto out;
@@ -395,7 +395,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
 static int mtrr_check(unsigned long base, unsigned long size)
 {
        if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
-               pr_warning("mtrr: size and base must be multiples of 4 kiB\n");
+               pr_warn("mtrr: size and base must be multiples of 4 kiB\n");
                pr_debug("mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
                dump_stack();
                return -1;
@@ -493,16 +493,16 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
                }
        }
        if (reg >= max) {
-               pr_warning("mtrr: register: %d too big\n", reg);
+               pr_warn("mtrr: register: %d too big\n", reg);
                goto out;
        }
        mtrr_if->get(reg, &lbase, &lsize, &ltype);
        if (lsize < 1) {
-               pr_warning("mtrr: MTRR %d not used\n", reg);
+               pr_warn("mtrr: MTRR %d not used\n", reg);
                goto out;
        }
        if (mtrr_usage_table[reg] < 1) {
-               pr_warning("mtrr: reg: %d has count=0\n", reg);
+               pr_warn("mtrr: reg: %d has count=0\n", reg);
                goto out;
        }
        if (--mtrr_usage_table[reg] < 1)
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
deleted file mode 100644 (file)
index 1b443db..0000000
+++ /dev/null
@@ -1,2428 +0,0 @@
-/*
- * Performance events x86 architecture code
- *
- *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
- *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2009 Jaswinder Singh Rajput
- *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
- *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
- *  Copyright (C) 2009 Google, Inc., Stephane Eranian
- *
- *  For licencing details see kernel-base/COPYING
- */
-
-#include <linux/perf_event.h>
-#include <linux/capability.h>
-#include <linux/notifier.h>
-#include <linux/hardirq.h>
-#include <linux/kprobes.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/sched.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/cpu.h>
-#include <linux/bitops.h>
-#include <linux/device.h>
-
-#include <asm/apic.h>
-#include <asm/stacktrace.h>
-#include <asm/nmi.h>
-#include <asm/smp.h>
-#include <asm/alternative.h>
-#include <asm/mmu_context.h>
-#include <asm/tlbflush.h>
-#include <asm/timer.h>
-#include <asm/desc.h>
-#include <asm/ldt.h>
-
-#include "perf_event.h"
-
-struct x86_pmu x86_pmu __read_mostly;
-
-DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
-       .enabled = 1,
-};
-
-struct static_key rdpmc_always_available = STATIC_KEY_INIT_FALSE;
-
-u64 __read_mostly hw_cache_event_ids
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
-u64 __read_mostly hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
-
-/*
- * Propagate event elapsed time into the generic event.
- * Can only be executed on the CPU where the event is active.
- * Returns the delta events processed.
- */
-u64 x86_perf_event_update(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       int shift = 64 - x86_pmu.cntval_bits;
-       u64 prev_raw_count, new_raw_count;
-       int idx = hwc->idx;
-       s64 delta;
-
-       if (idx == INTEL_PMC_IDX_FIXED_BTS)
-               return 0;
-
-       /*
-        * Careful: an NMI might modify the previous event value.
-        *
-        * Our tactic to handle this is to first atomically read and
-        * exchange a new raw count - then add that new-prev delta
-        * count to the generic event atomically:
-        */
-again:
-       prev_raw_count = local64_read(&hwc->prev_count);
-       rdpmcl(hwc->event_base_rdpmc, new_raw_count);
-
-       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-                                       new_raw_count) != prev_raw_count)
-               goto again;
-
-       /*
-        * Now we have the new raw value and have updated the prev
-        * timestamp already. We can now calculate the elapsed delta
-        * (event-)time and add that to the generic event.
-        *
-        * Careful, not all hw sign-extends above the physical width
-        * of the count.
-        */
-       delta = (new_raw_count << shift) - (prev_raw_count << shift);
-       delta >>= shift;
-
-       local64_add(delta, &event->count);
-       local64_sub(delta, &hwc->period_left);
-
-       return new_raw_count;
-}
-
-/*
- * Find and validate any extra registers to set up.
- */
-static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg;
-       struct extra_reg *er;
-
-       reg = &event->hw.extra_reg;
-
-       if (!x86_pmu.extra_regs)
-               return 0;
-
-       for (er = x86_pmu.extra_regs; er->msr; er++) {
-               if (er->event != (config & er->config_mask))
-                       continue;
-               if (event->attr.config1 & ~er->valid_mask)
-                       return -EINVAL;
-               /* Check if the extra msrs can be safely accessed*/
-               if (!er->extra_msr_access)
-                       return -ENXIO;
-
-               reg->idx = er->idx;
-               reg->config = event->attr.config1;
-               reg->reg = er->msr;
-               break;
-       }
-       return 0;
-}
-
-static atomic_t active_events;
-static atomic_t pmc_refcount;
-static DEFINE_MUTEX(pmc_reserve_mutex);
-
-#ifdef CONFIG_X86_LOCAL_APIC
-
-static bool reserve_pmc_hardware(void)
-{
-       int i;
-
-       for (i = 0; i < x86_pmu.num_counters; i++) {
-               if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
-                       goto perfctr_fail;
-       }
-
-       for (i = 0; i < x86_pmu.num_counters; i++) {
-               if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
-                       goto eventsel_fail;
-       }
-
-       return true;
-
-eventsel_fail:
-       for (i--; i >= 0; i--)
-               release_evntsel_nmi(x86_pmu_config_addr(i));
-
-       i = x86_pmu.num_counters;
-
-perfctr_fail:
-       for (i--; i >= 0; i--)
-               release_perfctr_nmi(x86_pmu_event_addr(i));
-
-       return false;
-}
-
-static void release_pmc_hardware(void)
-{
-       int i;
-
-       for (i = 0; i < x86_pmu.num_counters; i++) {
-               release_perfctr_nmi(x86_pmu_event_addr(i));
-               release_evntsel_nmi(x86_pmu_config_addr(i));
-       }
-}
-
-#else
-
-static bool reserve_pmc_hardware(void) { return true; }
-static void release_pmc_hardware(void) {}
-
-#endif
-
-static bool check_hw_exists(void)
-{
-       u64 val, val_fail, val_new= ~0;
-       int i, reg, reg_fail, ret = 0;
-       int bios_fail = 0;
-       int reg_safe = -1;
-
-       /*
-        * Check to see if the BIOS enabled any of the counters, if so
-        * complain and bail.
-        */
-       for (i = 0; i < x86_pmu.num_counters; i++) {
-               reg = x86_pmu_config_addr(i);
-               ret = rdmsrl_safe(reg, &val);
-               if (ret)
-                       goto msr_fail;
-               if (val & ARCH_PERFMON_EVENTSEL_ENABLE) {
-                       bios_fail = 1;
-                       val_fail = val;
-                       reg_fail = reg;
-               } else {
-                       reg_safe = i;
-               }
-       }
-
-       if (x86_pmu.num_counters_fixed) {
-               reg = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
-               ret = rdmsrl_safe(reg, &val);
-               if (ret)
-                       goto msr_fail;
-               for (i = 0; i < x86_pmu.num_counters_fixed; i++) {
-                       if (val & (0x03 << i*4)) {
-                               bios_fail = 1;
-                               val_fail = val;
-                               reg_fail = reg;
-                       }
-               }
-       }
-
-       /*
-        * If all the counters are enabled, the below test will always
-        * fail.  The tools will also become useless in this scenario.
-        * Just fail and disable the hardware counters.
-        */
-
-       if (reg_safe == -1) {
-               reg = reg_safe;
-               goto msr_fail;
-       }
-
-       /*
-        * Read the current value, change it and read it back to see if it
-        * matches, this is needed to detect certain hardware emulators
-        * (qemu/kvm) that don't trap on the MSR access and always return 0s.
-        */
-       reg = x86_pmu_event_addr(reg_safe);
-       if (rdmsrl_safe(reg, &val))
-               goto msr_fail;
-       val ^= 0xffffUL;
-       ret = wrmsrl_safe(reg, val);
-       ret |= rdmsrl_safe(reg, &val_new);
-       if (ret || val != val_new)
-               goto msr_fail;
-
-       /*
-        * We still allow the PMU driver to operate:
-        */
-       if (bios_fail) {
-               printk(KERN_CONT "Broken BIOS detected, complain to your hardware vendor.\n");
-               printk(KERN_ERR FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n", reg_fail, val_fail);
-       }
-
-       return true;
-
-msr_fail:
-       printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n");
-       printk("%sFailed to access perfctr msr (MSR %x is %Lx)\n",
-               boot_cpu_has(X86_FEATURE_HYPERVISOR) ? KERN_INFO : KERN_ERR,
-               reg, val_new);
-
-       return false;
-}
-
-static void hw_perf_event_destroy(struct perf_event *event)
-{
-       x86_release_hardware();
-       atomic_dec(&active_events);
-}
-
-void hw_perf_lbr_event_destroy(struct perf_event *event)
-{
-       hw_perf_event_destroy(event);
-
-       /* undo the lbr/bts event accounting */
-       x86_del_exclusive(x86_lbr_exclusive_lbr);
-}
-
-static inline int x86_pmu_initialized(void)
-{
-       return x86_pmu.handle_irq != NULL;
-}
-
-static inline int
-set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
-{
-       struct perf_event_attr *attr = &event->attr;
-       unsigned int cache_type, cache_op, cache_result;
-       u64 config, val;
-
-       config = attr->config;
-
-       cache_type = (config >>  0) & 0xff;
-       if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
-               return -EINVAL;
-
-       cache_op = (config >>  8) & 0xff;
-       if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
-               return -EINVAL;
-
-       cache_result = (config >> 16) & 0xff;
-       if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
-               return -EINVAL;
-
-       val = hw_cache_event_ids[cache_type][cache_op][cache_result];
-
-       if (val == 0)
-               return -ENOENT;
-
-       if (val == -1)
-               return -EINVAL;
-
-       hwc->config |= val;
-       attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
-       return x86_pmu_extra_regs(val, event);
-}
-
-int x86_reserve_hardware(void)
-{
-       int err = 0;
-
-       if (!atomic_inc_not_zero(&pmc_refcount)) {
-               mutex_lock(&pmc_reserve_mutex);
-               if (atomic_read(&pmc_refcount) == 0) {
-                       if (!reserve_pmc_hardware())
-                               err = -EBUSY;
-                       else
-                               reserve_ds_buffers();
-               }
-               if (!err)
-                       atomic_inc(&pmc_refcount);
-               mutex_unlock(&pmc_reserve_mutex);
-       }
-
-       return err;
-}
-
-void x86_release_hardware(void)
-{
-       if (atomic_dec_and_mutex_lock(&pmc_refcount, &pmc_reserve_mutex)) {
-               release_pmc_hardware();
-               release_ds_buffers();
-               mutex_unlock(&pmc_reserve_mutex);
-       }
-}
-
-/*
- * Check if we can create event of a certain type (that no conflicting events
- * are present).
- */
-int x86_add_exclusive(unsigned int what)
-{
-       int i;
-
-       if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
-               mutex_lock(&pmc_reserve_mutex);
-               for (i = 0; i < ARRAY_SIZE(x86_pmu.lbr_exclusive); i++) {
-                       if (i != what && atomic_read(&x86_pmu.lbr_exclusive[i]))
-                               goto fail_unlock;
-               }
-               atomic_inc(&x86_pmu.lbr_exclusive[what]);
-               mutex_unlock(&pmc_reserve_mutex);
-       }
-
-       atomic_inc(&active_events);
-       return 0;
-
-fail_unlock:
-       mutex_unlock(&pmc_reserve_mutex);
-       return -EBUSY;
-}
-
-void x86_del_exclusive(unsigned int what)
-{
-       atomic_dec(&x86_pmu.lbr_exclusive[what]);
-       atomic_dec(&active_events);
-}
-
-int x86_setup_perfctr(struct perf_event *event)
-{
-       struct perf_event_attr *attr = &event->attr;
-       struct hw_perf_event *hwc = &event->hw;
-       u64 config;
-
-       if (!is_sampling_event(event)) {
-               hwc->sample_period = x86_pmu.max_period;
-               hwc->last_period = hwc->sample_period;
-               local64_set(&hwc->period_left, hwc->sample_period);
-       }
-
-       if (attr->type == PERF_TYPE_RAW)
-               return x86_pmu_extra_regs(event->attr.config, event);
-
-       if (attr->type == PERF_TYPE_HW_CACHE)
-               return set_ext_hw_attr(hwc, event);
-
-       if (attr->config >= x86_pmu.max_events)
-               return -EINVAL;
-
-       /*
-        * The generic map:
-        */
-       config = x86_pmu.event_map(attr->config);
-
-       if (config == 0)
-               return -ENOENT;
-
-       if (config == -1LL)
-               return -EINVAL;
-
-       /*
-        * Branch tracing:
-        */
-       if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
-           !attr->freq && hwc->sample_period == 1) {
-               /* BTS is not supported by this architecture. */
-               if (!x86_pmu.bts_active)
-                       return -EOPNOTSUPP;
-
-               /* BTS is currently only allowed for user-mode. */
-               if (!attr->exclude_kernel)
-                       return -EOPNOTSUPP;
-
-               /* disallow bts if conflicting events are present */
-               if (x86_add_exclusive(x86_lbr_exclusive_lbr))
-                       return -EBUSY;
-
-               event->destroy = hw_perf_lbr_event_destroy;
-       }
-
-       hwc->config |= config;
-
-       return 0;
-}
-
-/*
- * check that branch_sample_type is compatible with
- * settings needed for precise_ip > 1 which implies
- * using the LBR to capture ALL taken branches at the
- * priv levels of the measurement
- */
-static inline int precise_br_compat(struct perf_event *event)
-{
-       u64 m = event->attr.branch_sample_type;
-       u64 b = 0;
-
-       /* must capture all branches */
-       if (!(m & PERF_SAMPLE_BRANCH_ANY))
-               return 0;
-
-       m &= PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_USER;
-
-       if (!event->attr.exclude_user)
-               b |= PERF_SAMPLE_BRANCH_USER;
-
-       if (!event->attr.exclude_kernel)
-               b |= PERF_SAMPLE_BRANCH_KERNEL;
-
-       /*
-        * ignore PERF_SAMPLE_BRANCH_HV, not supported on x86
-        */
-
-       return m == b;
-}
-
-int x86_pmu_hw_config(struct perf_event *event)
-{
-       if (event->attr.precise_ip) {
-               int precise = 0;
-
-               /* Support for constant skid */
-               if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
-                       precise++;
-
-                       /* Support for IP fixup */
-                       if (x86_pmu.lbr_nr || x86_pmu.intel_cap.pebs_format >= 2)
-                               precise++;
-
-                       if (x86_pmu.pebs_prec_dist)
-                               precise++;
-               }
-
-               if (event->attr.precise_ip > precise)
-                       return -EOPNOTSUPP;
-       }
-       /*
-        * check that PEBS LBR correction does not conflict with
-        * whatever the user is asking with attr->branch_sample_type
-        */
-       if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format < 2) {
-               u64 *br_type = &event->attr.branch_sample_type;
-
-               if (has_branch_stack(event)) {
-                       if (!precise_br_compat(event))
-                               return -EOPNOTSUPP;
-
-                       /* branch_sample_type is compatible */
-
-               } else {
-                       /*
-                        * user did not specify  branch_sample_type
-                        *
-                        * For PEBS fixups, we capture all
-                        * the branches at the priv level of the
-                        * event.
-                        */
-                       *br_type = PERF_SAMPLE_BRANCH_ANY;
-
-                       if (!event->attr.exclude_user)
-                               *br_type |= PERF_SAMPLE_BRANCH_USER;
-
-                       if (!event->attr.exclude_kernel)
-                               *br_type |= PERF_SAMPLE_BRANCH_KERNEL;
-               }
-       }
-
-       if (event->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK)
-               event->attach_state |= PERF_ATTACH_TASK_DATA;
-
-       /*
-        * Generate PMC IRQs:
-        * (keep 'enabled' bit clear for now)
-        */
-       event->hw.config = ARCH_PERFMON_EVENTSEL_INT;
-
-       /*
-        * Count user and OS events unless requested not to
-        */
-       if (!event->attr.exclude_user)
-               event->hw.config |= ARCH_PERFMON_EVENTSEL_USR;
-       if (!event->attr.exclude_kernel)
-               event->hw.config |= ARCH_PERFMON_EVENTSEL_OS;
-
-       if (event->attr.type == PERF_TYPE_RAW)
-               event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK;
-
-       if (event->attr.sample_period && x86_pmu.limit_period) {
-               if (x86_pmu.limit_period(event, event->attr.sample_period) >
-                               event->attr.sample_period)
-                       return -EINVAL;
-       }
-
-       return x86_setup_perfctr(event);
-}
-
-/*
- * Setup the hardware configuration for a given attr_type
- */
-static int __x86_pmu_event_init(struct perf_event *event)
-{
-       int err;
-
-       if (!x86_pmu_initialized())
-               return -ENODEV;
-
-       err = x86_reserve_hardware();
-       if (err)
-               return err;
-
-       atomic_inc(&active_events);
-       event->destroy = hw_perf_event_destroy;
-
-       event->hw.idx = -1;
-       event->hw.last_cpu = -1;
-       event->hw.last_tag = ~0ULL;
-
-       /* mark unused */
-       event->hw.extra_reg.idx = EXTRA_REG_NONE;
-       event->hw.branch_reg.idx = EXTRA_REG_NONE;
-
-       return x86_pmu.hw_config(event);
-}
-
-void x86_pmu_disable_all(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       int idx;
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               u64 val;
-
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-               rdmsrl(x86_pmu_config_addr(idx), val);
-               if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
-                       continue;
-               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
-               wrmsrl(x86_pmu_config_addr(idx), val);
-       }
-}
-
-static void x86_pmu_disable(struct pmu *pmu)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       if (!x86_pmu_initialized())
-               return;
-
-       if (!cpuc->enabled)
-               return;
-
-       cpuc->n_added = 0;
-       cpuc->enabled = 0;
-       barrier();
-
-       x86_pmu.disable_all();
-}
-
-void x86_pmu_enable_all(int added)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       int idx;
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
-
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
-               __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
-       }
-}
-
-static struct pmu pmu;
-
-static inline int is_x86_event(struct perf_event *event)
-{
-       return event->pmu == &pmu;
-}
-
-/*
- * Event scheduler state:
- *
- * Assign events iterating over all events and counters, beginning
- * with events with least weights first. Keep the current iterator
- * state in struct sched_state.
- */
-struct sched_state {
-       int     weight;
-       int     event;          /* event index */
-       int     counter;        /* counter index */
-       int     unassigned;     /* number of events to be assigned left */
-       int     nr_gp;          /* number of GP counters used */
-       unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-};
-
-/* Total max is X86_PMC_IDX_MAX, but we are O(n!) limited */
-#define        SCHED_STATES_MAX        2
-
-struct perf_sched {
-       int                     max_weight;
-       int                     max_events;
-       int                     max_gp;
-       int                     saved_states;
-       struct event_constraint **constraints;
-       struct sched_state      state;
-       struct sched_state      saved[SCHED_STATES_MAX];
-};
-
-/*
- * Initialize interator that runs through all events and counters.
- */
-static void perf_sched_init(struct perf_sched *sched, struct event_constraint **constraints,
-                           int num, int wmin, int wmax, int gpmax)
-{
-       int idx;
-
-       memset(sched, 0, sizeof(*sched));
-       sched->max_events       = num;
-       sched->max_weight       = wmax;
-       sched->max_gp           = gpmax;
-       sched->constraints      = constraints;
-
-       for (idx = 0; idx < num; idx++) {
-               if (constraints[idx]->weight == wmin)
-                       break;
-       }
-
-       sched->state.event      = idx;          /* start with min weight */
-       sched->state.weight     = wmin;
-       sched->state.unassigned = num;
-}
-
-static void perf_sched_save_state(struct perf_sched *sched)
-{
-       if (WARN_ON_ONCE(sched->saved_states >= SCHED_STATES_MAX))
-               return;
-
-       sched->saved[sched->saved_states] = sched->state;
-       sched->saved_states++;
-}
-
-static bool perf_sched_restore_state(struct perf_sched *sched)
-{
-       if (!sched->saved_states)
-               return false;
-
-       sched->saved_states--;
-       sched->state = sched->saved[sched->saved_states];
-
-       /* continue with next counter: */
-       clear_bit(sched->state.counter++, sched->state.used);
-
-       return true;
-}
-
-/*
- * Select a counter for the current event to schedule. Return true on
- * success.
- */
-static bool __perf_sched_find_counter(struct perf_sched *sched)
-{
-       struct event_constraint *c;
-       int idx;
-
-       if (!sched->state.unassigned)
-               return false;
-
-       if (sched->state.event >= sched->max_events)
-               return false;
-
-       c = sched->constraints[sched->state.event];
-       /* Prefer fixed purpose counters */
-       if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
-               idx = INTEL_PMC_IDX_FIXED;
-               for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) {
-                       if (!__test_and_set_bit(idx, sched->state.used))
-                               goto done;
-               }
-       }
-
-       /* Grab the first unused counter starting with idx */
-       idx = sched->state.counter;
-       for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
-               if (!__test_and_set_bit(idx, sched->state.used)) {
-                       if (sched->state.nr_gp++ >= sched->max_gp)
-                               return false;
-
-                       goto done;
-               }
-       }
-
-       return false;
-
-done:
-       sched->state.counter = idx;
-
-       if (c->overlap)
-               perf_sched_save_state(sched);
-
-       return true;
-}
-
-static bool perf_sched_find_counter(struct perf_sched *sched)
-{
-       while (!__perf_sched_find_counter(sched)) {
-               if (!perf_sched_restore_state(sched))
-                       return false;
-       }
-
-       return true;
-}
-
-/*
- * Go through all unassigned events and find the next one to schedule.
- * Take events with the least weight first. Return true on success.
- */
-static bool perf_sched_next_event(struct perf_sched *sched)
-{
-       struct event_constraint *c;
-
-       if (!sched->state.unassigned || !--sched->state.unassigned)
-               return false;
-
-       do {
-               /* next event */
-               sched->state.event++;
-               if (sched->state.event >= sched->max_events) {
-                       /* next weight */
-                       sched->state.event = 0;
-                       sched->state.weight++;
-                       if (sched->state.weight > sched->max_weight)
-                               return false;
-               }
-               c = sched->constraints[sched->state.event];
-       } while (c->weight != sched->state.weight);
-
-       sched->state.counter = 0;       /* start with first counter */
-
-       return true;
-}
-
-/*
- * Assign a counter for each event.
- */
-int perf_assign_events(struct event_constraint **constraints, int n,
-                       int wmin, int wmax, int gpmax, int *assign)
-{
-       struct perf_sched sched;
-
-       perf_sched_init(&sched, constraints, n, wmin, wmax, gpmax);
-
-       do {
-               if (!perf_sched_find_counter(&sched))
-                       break;  /* failed */
-               if (assign)
-                       assign[sched.state.event] = sched.state.counter;
-       } while (perf_sched_next_event(&sched));
-
-       return sched.state.unassigned;
-}
-EXPORT_SYMBOL_GPL(perf_assign_events);
-
-int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
-{
-       struct event_constraint *c;
-       unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-       struct perf_event *e;
-       int i, wmin, wmax, unsched = 0;
-       struct hw_perf_event *hwc;
-
-       bitmap_zero(used_mask, X86_PMC_IDX_MAX);
-
-       if (x86_pmu.start_scheduling)
-               x86_pmu.start_scheduling(cpuc);
-
-       for (i = 0, wmin = X86_PMC_IDX_MAX, wmax = 0; i < n; i++) {
-               cpuc->event_constraint[i] = NULL;
-               c = x86_pmu.get_event_constraints(cpuc, i, cpuc->event_list[i]);
-               cpuc->event_constraint[i] = c;
-
-               wmin = min(wmin, c->weight);
-               wmax = max(wmax, c->weight);
-       }
-
-       /*
-        * fastpath, try to reuse previous register
-        */
-       for (i = 0; i < n; i++) {
-               hwc = &cpuc->event_list[i]->hw;
-               c = cpuc->event_constraint[i];
-
-               /* never assigned */
-               if (hwc->idx == -1)
-                       break;
-
-               /* constraint still honored */
-               if (!test_bit(hwc->idx, c->idxmsk))
-                       break;
-
-               /* not already used */
-               if (test_bit(hwc->idx, used_mask))
-                       break;
-
-               __set_bit(hwc->idx, used_mask);
-               if (assign)
-                       assign[i] = hwc->idx;
-       }
-
-       /* slow path */
-       if (i != n) {
-               int gpmax = x86_pmu.num_counters;
-
-               /*
-                * Do not allow scheduling of more than half the available
-                * generic counters.
-                *
-                * This helps avoid counter starvation of sibling thread by
-                * ensuring at most half the counters cannot be in exclusive
-                * mode. There is no designated counters for the limits. Any
-                * N/2 counters can be used. This helps with events with
-                * specific counter constraints.
-                */
-               if (is_ht_workaround_enabled() && !cpuc->is_fake &&
-                   READ_ONCE(cpuc->excl_cntrs->exclusive_present))
-                       gpmax /= 2;
-
-               unsched = perf_assign_events(cpuc->event_constraint, n, wmin,
-                                            wmax, gpmax, assign);
-       }
-
-       /*
-        * In case of success (unsched = 0), mark events as committed,
-        * so we do not put_constraint() in case new events are added
-        * and fail to be scheduled
-        *
-        * We invoke the lower level commit callback to lock the resource
-        *
-        * We do not need to do all of this in case we are called to
-        * validate an event group (assign == NULL)
-        */
-       if (!unsched && assign) {
-               for (i = 0; i < n; i++) {
-                       e = cpuc->event_list[i];
-                       e->hw.flags |= PERF_X86_EVENT_COMMITTED;
-                       if (x86_pmu.commit_scheduling)
-                               x86_pmu.commit_scheduling(cpuc, i, assign[i]);
-               }
-       } else {
-               for (i = 0; i < n; i++) {
-                       e = cpuc->event_list[i];
-                       /*
-                        * do not put_constraint() on comitted events,
-                        * because they are good to go
-                        */
-                       if ((e->hw.flags & PERF_X86_EVENT_COMMITTED))
-                               continue;
-
-                       /*
-                        * release events that failed scheduling
-                        */
-                       if (x86_pmu.put_event_constraints)
-                               x86_pmu.put_event_constraints(cpuc, e);
-               }
-       }
-
-       if (x86_pmu.stop_scheduling)
-               x86_pmu.stop_scheduling(cpuc);
-
-       return unsched ? -EINVAL : 0;
-}
-
-/*
- * dogrp: true if must collect siblings events (group)
- * returns total number of events and error code
- */
-static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, bool dogrp)
-{
-       struct perf_event *event;
-       int n, max_count;
-
-       max_count = x86_pmu.num_counters + x86_pmu.num_counters_fixed;
-
-       /* current number of events already accepted */
-       n = cpuc->n_events;
-
-       if (is_x86_event(leader)) {
-               if (n >= max_count)
-                       return -EINVAL;
-               cpuc->event_list[n] = leader;
-               n++;
-       }
-       if (!dogrp)
-               return n;
-
-       list_for_each_entry(event, &leader->sibling_list, group_entry) {
-               if (!is_x86_event(event) ||
-                   event->state <= PERF_EVENT_STATE_OFF)
-                       continue;
-
-               if (n >= max_count)
-                       return -EINVAL;
-
-               cpuc->event_list[n] = event;
-               n++;
-       }
-       return n;
-}
-
-static inline void x86_assign_hw_event(struct perf_event *event,
-                               struct cpu_hw_events *cpuc, int i)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       hwc->idx = cpuc->assign[i];
-       hwc->last_cpu = smp_processor_id();
-       hwc->last_tag = ++cpuc->tags[i];
-
-       if (hwc->idx == INTEL_PMC_IDX_FIXED_BTS) {
-               hwc->config_base = 0;
-               hwc->event_base = 0;
-       } else if (hwc->idx >= INTEL_PMC_IDX_FIXED) {
-               hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
-               hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - INTEL_PMC_IDX_FIXED);
-               hwc->event_base_rdpmc = (hwc->idx - INTEL_PMC_IDX_FIXED) | 1<<30;
-       } else {
-               hwc->config_base = x86_pmu_config_addr(hwc->idx);
-               hwc->event_base  = x86_pmu_event_addr(hwc->idx);
-               hwc->event_base_rdpmc = x86_pmu_rdpmc_index(hwc->idx);
-       }
-}
-
-static inline int match_prev_assignment(struct hw_perf_event *hwc,
-                                       struct cpu_hw_events *cpuc,
-                                       int i)
-{
-       return hwc->idx == cpuc->assign[i] &&
-               hwc->last_cpu == smp_processor_id() &&
-               hwc->last_tag == cpuc->tags[i];
-}
-
-static void x86_pmu_start(struct perf_event *event, int flags);
-
-static void x86_pmu_enable(struct pmu *pmu)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct perf_event *event;
-       struct hw_perf_event *hwc;
-       int i, added = cpuc->n_added;
-
-       if (!x86_pmu_initialized())
-               return;
-
-       if (cpuc->enabled)
-               return;
-
-       if (cpuc->n_added) {
-               int n_running = cpuc->n_events - cpuc->n_added;
-               /*
-                * apply assignment obtained either from
-                * hw_perf_group_sched_in() or x86_pmu_enable()
-                *
-                * step1: save events moving to new counters
-                */
-               for (i = 0; i < n_running; i++) {
-                       event = cpuc->event_list[i];
-                       hwc = &event->hw;
-
-                       /*
-                        * we can avoid reprogramming counter if:
-                        * - assigned same counter as last time
-                        * - running on same CPU as last time
-                        * - no other event has used the counter since
-                        */
-                       if (hwc->idx == -1 ||
-                           match_prev_assignment(hwc, cpuc, i))
-                               continue;
-
-                       /*
-                        * Ensure we don't accidentally enable a stopped
-                        * counter simply because we rescheduled.
-                        */
-                       if (hwc->state & PERF_HES_STOPPED)
-                               hwc->state |= PERF_HES_ARCH;
-
-                       x86_pmu_stop(event, PERF_EF_UPDATE);
-               }
-
-               /*
-                * step2: reprogram moved events into new counters
-                */
-               for (i = 0; i < cpuc->n_events; i++) {
-                       event = cpuc->event_list[i];
-                       hwc = &event->hw;
-
-                       if (!match_prev_assignment(hwc, cpuc, i))
-                               x86_assign_hw_event(event, cpuc, i);
-                       else if (i < n_running)
-                               continue;
-
-                       if (hwc->state & PERF_HES_ARCH)
-                               continue;
-
-                       x86_pmu_start(event, PERF_EF_RELOAD);
-               }
-               cpuc->n_added = 0;
-               perf_events_lapic_init();
-       }
-
-       cpuc->enabled = 1;
-       barrier();
-
-       x86_pmu.enable_all(added);
-}
-
-static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
-
-/*
- * Set the next IRQ period, based on the hwc->period_left value.
- * To be called with the event disabled in hw:
- */
-int x86_perf_event_set_period(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       s64 left = local64_read(&hwc->period_left);
-       s64 period = hwc->sample_period;
-       int ret = 0, idx = hwc->idx;
-
-       if (idx == INTEL_PMC_IDX_FIXED_BTS)
-               return 0;
-
-       /*
-        * If we are way outside a reasonable range then just skip forward:
-        */
-       if (unlikely(left <= -period)) {
-               left = period;
-               local64_set(&hwc->period_left, left);
-               hwc->last_period = period;
-               ret = 1;
-       }
-
-       if (unlikely(left <= 0)) {
-               left += period;
-               local64_set(&hwc->period_left, left);
-               hwc->last_period = period;
-               ret = 1;
-       }
-       /*
-        * Quirk: certain CPUs dont like it if just 1 hw_event is left:
-        */
-       if (unlikely(left < 2))
-               left = 2;
-
-       if (left > x86_pmu.max_period)
-               left = x86_pmu.max_period;
-
-       if (x86_pmu.limit_period)
-               left = x86_pmu.limit_period(event, left);
-
-       per_cpu(pmc_prev_left[idx], smp_processor_id()) = left;
-
-       if (!(hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) ||
-           local64_read(&hwc->prev_count) != (u64)-left) {
-               /*
-                * The hw event starts counting from this event offset,
-                * mark it to be able to extra future deltas:
-                */
-               local64_set(&hwc->prev_count, (u64)-left);
-
-               wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
-       }
-
-       /*
-        * Due to erratum on certan cpu we need
-        * a second write to be sure the register
-        * is updated properly
-        */
-       if (x86_pmu.perfctr_second_write) {
-               wrmsrl(hwc->event_base,
-                       (u64)(-left) & x86_pmu.cntval_mask);
-       }
-
-       perf_event_update_userpage(event);
-
-       return ret;
-}
-
-void x86_pmu_enable_event(struct perf_event *event)
-{
-       if (__this_cpu_read(cpu_hw_events.enabled))
-               __x86_pmu_enable_event(&event->hw,
-                                      ARCH_PERFMON_EVENTSEL_ENABLE);
-}
-
-/*
- * Add a single event to the PMU.
- *
- * The event is added to the group of enabled events
- * but only if it can be scehduled with existing events.
- */
-static int x86_pmu_add(struct perf_event *event, int flags)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct hw_perf_event *hwc;
-       int assign[X86_PMC_IDX_MAX];
-       int n, n0, ret;
-
-       hwc = &event->hw;
-
-       n0 = cpuc->n_events;
-       ret = n = collect_events(cpuc, event, false);
-       if (ret < 0)
-               goto out;
-
-       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
-       if (!(flags & PERF_EF_START))
-               hwc->state |= PERF_HES_ARCH;
-
-       /*
-        * If group events scheduling transaction was started,
-        * skip the schedulability test here, it will be performed
-        * at commit time (->commit_txn) as a whole.
-        */
-       if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
-               goto done_collect;
-
-       ret = x86_pmu.schedule_events(cpuc, n, assign);
-       if (ret)
-               goto out;
-       /*
-        * copy new assignment, now we know it is possible
-        * will be used by hw_perf_enable()
-        */
-       memcpy(cpuc->assign, assign, n*sizeof(int));
-
-done_collect:
-       /*
-        * Commit the collect_events() state. See x86_pmu_del() and
-        * x86_pmu_*_txn().
-        */
-       cpuc->n_events = n;
-       cpuc->n_added += n - n0;
-       cpuc->n_txn += n - n0;
-
-       ret = 0;
-out:
-       return ret;
-}
-
-static void x86_pmu_start(struct perf_event *event, int flags)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       int idx = event->hw.idx;
-
-       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
-               return;
-
-       if (WARN_ON_ONCE(idx == -1))
-               return;
-
-       if (flags & PERF_EF_RELOAD) {
-               WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
-               x86_perf_event_set_period(event);
-       }
-
-       event->hw.state = 0;
-
-       cpuc->events[idx] = event;
-       __set_bit(idx, cpuc->active_mask);
-       __set_bit(idx, cpuc->running);
-       x86_pmu.enable(event);
-       perf_event_update_userpage(event);
-}
-
-void perf_event_print_debug(void)
-{
-       u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed;
-       u64 pebs, debugctl;
-       struct cpu_hw_events *cpuc;
-       unsigned long flags;
-       int cpu, idx;
-
-       if (!x86_pmu.num_counters)
-               return;
-
-       local_irq_save(flags);
-
-       cpu = smp_processor_id();
-       cpuc = &per_cpu(cpu_hw_events, cpu);
-
-       if (x86_pmu.version >= 2) {
-               rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, ctrl);
-               rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
-               rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow);
-               rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed);
-
-               pr_info("\n");
-               pr_info("CPU#%d: ctrl:       %016llx\n", cpu, ctrl);
-               pr_info("CPU#%d: status:     %016llx\n", cpu, status);
-               pr_info("CPU#%d: overflow:   %016llx\n", cpu, overflow);
-               pr_info("CPU#%d: fixed:      %016llx\n", cpu, fixed);
-               if (x86_pmu.pebs_constraints) {
-                       rdmsrl(MSR_IA32_PEBS_ENABLE, pebs);
-                       pr_info("CPU#%d: pebs:       %016llx\n", cpu, pebs);
-               }
-               if (x86_pmu.lbr_nr) {
-                       rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
-                       pr_info("CPU#%d: debugctl:   %016llx\n", cpu, debugctl);
-               }
-       }
-       pr_info("CPU#%d: active:     %016llx\n", cpu, *(u64 *)cpuc->active_mask);
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               rdmsrl(x86_pmu_config_addr(idx), pmc_ctrl);
-               rdmsrl(x86_pmu_event_addr(idx), pmc_count);
-
-               prev_left = per_cpu(pmc_prev_left[idx], cpu);
-
-               pr_info("CPU#%d:   gen-PMC%d ctrl:  %016llx\n",
-                       cpu, idx, pmc_ctrl);
-               pr_info("CPU#%d:   gen-PMC%d count: %016llx\n",
-                       cpu, idx, pmc_count);
-               pr_info("CPU#%d:   gen-PMC%d left:  %016llx\n",
-                       cpu, idx, prev_left);
-       }
-       for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) {
-               rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count);
-
-               pr_info("CPU#%d: fixed-PMC%d count: %016llx\n",
-                       cpu, idx, pmc_count);
-       }
-       local_irq_restore(flags);
-}
-
-void x86_pmu_stop(struct perf_event *event, int flags)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (__test_and_clear_bit(hwc->idx, cpuc->active_mask)) {
-               x86_pmu.disable(event);
-               cpuc->events[hwc->idx] = NULL;
-               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
-               hwc->state |= PERF_HES_STOPPED;
-       }
-
-       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
-               /*
-                * Drain the remaining delta count out of a event
-                * that we are disabling:
-                */
-               x86_perf_event_update(event);
-               hwc->state |= PERF_HES_UPTODATE;
-       }
-}
-
-static void x86_pmu_del(struct perf_event *event, int flags)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       int i;
-
-       /*
-        * event is descheduled
-        */
-       event->hw.flags &= ~PERF_X86_EVENT_COMMITTED;
-
-       /*
-        * If we're called during a txn, we don't need to do anything.
-        * The events never got scheduled and ->cancel_txn will truncate
-        * the event_list.
-        *
-        * XXX assumes any ->del() called during a TXN will only be on
-        * an event added during that same TXN.
-        */
-       if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
-               return;
-
-       /*
-        * Not a TXN, therefore cleanup properly.
-        */
-       x86_pmu_stop(event, PERF_EF_UPDATE);
-
-       for (i = 0; i < cpuc->n_events; i++) {
-               if (event == cpuc->event_list[i])
-                       break;
-       }
-
-       if (WARN_ON_ONCE(i == cpuc->n_events)) /* called ->del() without ->add() ? */
-               return;
-
-       /* If we have a newly added event; make sure to decrease n_added. */
-       if (i >= cpuc->n_events - cpuc->n_added)
-               --cpuc->n_added;
-
-       if (x86_pmu.put_event_constraints)
-               x86_pmu.put_event_constraints(cpuc, event);
-
-       /* Delete the array entry. */
-       while (++i < cpuc->n_events) {
-               cpuc->event_list[i-1] = cpuc->event_list[i];
-               cpuc->event_constraint[i-1] = cpuc->event_constraint[i];
-       }
-       --cpuc->n_events;
-
-       perf_event_update_userpage(event);
-}
-
-int x86_pmu_handle_irq(struct pt_regs *regs)
-{
-       struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
-       struct perf_event *event;
-       int idx, handled = 0;
-       u64 val;
-
-       cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       /*
-        * Some chipsets need to unmask the LVTPC in a particular spot
-        * inside the nmi handler.  As a result, the unmasking was pushed
-        * into all the nmi handlers.
-        *
-        * This generic handler doesn't seem to have any issues where the
-        * unmasking occurs so it was left at the top.
-        */
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               if (!test_bit(idx, cpuc->active_mask)) {
-                       /*
-                        * Though we deactivated the counter some cpus
-                        * might still deliver spurious interrupts still
-                        * in flight. Catch them:
-                        */
-                       if (__test_and_clear_bit(idx, cpuc->running))
-                               handled++;
-                       continue;
-               }
-
-               event = cpuc->events[idx];
-
-               val = x86_perf_event_update(event);
-               if (val & (1ULL << (x86_pmu.cntval_bits - 1)))
-                       continue;
-
-               /*
-                * event overflow
-                */
-               handled++;
-               perf_sample_data_init(&data, 0, event->hw.last_period);
-
-               if (!x86_perf_event_set_period(event))
-                       continue;
-
-               if (perf_event_overflow(event, &data, regs))
-                       x86_pmu_stop(event, 0);
-       }
-
-       if (handled)
-               inc_irq_stat(apic_perf_irqs);
-
-       return handled;
-}
-
-void perf_events_lapic_init(void)
-{
-       if (!x86_pmu.apic || !x86_pmu_initialized())
-               return;
-
-       /*
-        * Always use NMI for PMU
-        */
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-}
-
-static int
-perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs)
-{
-       u64 start_clock;
-       u64 finish_clock;
-       int ret;
-
-       /*
-        * All PMUs/events that share this PMI handler should make sure to
-        * increment active_events for their events.
-        */
-       if (!atomic_read(&active_events))
-               return NMI_DONE;
-
-       start_clock = sched_clock();
-       ret = x86_pmu.handle_irq(regs);
-       finish_clock = sched_clock();
-
-       perf_sample_event_took(finish_clock - start_clock);
-
-       return ret;
-}
-NOKPROBE_SYMBOL(perf_event_nmi_handler);
-
-struct event_constraint emptyconstraint;
-struct event_constraint unconstrained;
-
-static int
-x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (long)hcpu;
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-       int i, ret = NOTIFY_OK;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_UP_PREPARE:
-               for (i = 0 ; i < X86_PERF_KFREE_MAX; i++)
-                       cpuc->kfree_on_online[i] = NULL;
-               if (x86_pmu.cpu_prepare)
-                       ret = x86_pmu.cpu_prepare(cpu);
-               break;
-
-       case CPU_STARTING:
-               if (x86_pmu.cpu_starting)
-                       x86_pmu.cpu_starting(cpu);
-               break;
-
-       case CPU_ONLINE:
-               for (i = 0 ; i < X86_PERF_KFREE_MAX; i++) {
-                       kfree(cpuc->kfree_on_online[i]);
-                       cpuc->kfree_on_online[i] = NULL;
-               }
-               break;
-
-       case CPU_DYING:
-               if (x86_pmu.cpu_dying)
-                       x86_pmu.cpu_dying(cpu);
-               break;
-
-       case CPU_UP_CANCELED:
-       case CPU_DEAD:
-               if (x86_pmu.cpu_dead)
-                       x86_pmu.cpu_dead(cpu);
-               break;
-
-       default:
-               break;
-       }
-
-       return ret;
-}
-
-static void __init pmu_check_apic(void)
-{
-       if (cpu_has_apic)
-               return;
-
-       x86_pmu.apic = 0;
-       pr_info("no APIC, boot with the \"lapic\" boot parameter to force-enable it.\n");
-       pr_info("no hardware sampling interrupt available.\n");
-
-       /*
-        * If we have a PMU initialized but no APIC
-        * interrupts, we cannot sample hardware
-        * events (user-space has to fall back and
-        * sample via a hrtimer based software event):
-        */
-       pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
-
-}
-
-static struct attribute_group x86_pmu_format_group = {
-       .name = "format",
-       .attrs = NULL,
-};
-
-/*
- * Remove all undefined events (x86_pmu.event_map(id) == 0)
- * out of events_attr attributes.
- */
-static void __init filter_events(struct attribute **attrs)
-{
-       struct device_attribute *d;
-       struct perf_pmu_events_attr *pmu_attr;
-       int offset = 0;
-       int i, j;
-
-       for (i = 0; attrs[i]; i++) {
-               d = (struct device_attribute *)attrs[i];
-               pmu_attr = container_of(d, struct perf_pmu_events_attr, attr);
-               /* str trumps id */
-               if (pmu_attr->event_str)
-                       continue;
-               if (x86_pmu.event_map(i + offset))
-                       continue;
-
-               for (j = i; attrs[j]; j++)
-                       attrs[j] = attrs[j + 1];
-
-               /* Check the shifted attr. */
-               i--;
-
-               /*
-                * event_map() is index based, the attrs array is organized
-                * by increasing event index. If we shift the events, then
-                * we need to compensate for the event_map(), otherwise
-                * we are looking up the wrong event in the map
-                */
-               offset++;
-       }
-}
-
-/* Merge two pointer arrays */
-__init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
-{
-       struct attribute **new;
-       int j, i;
-
-       for (j = 0; a[j]; j++)
-               ;
-       for (i = 0; b[i]; i++)
-               j++;
-       j++;
-
-       new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL);
-       if (!new)
-               return NULL;
-
-       j = 0;
-       for (i = 0; a[i]; i++)
-               new[j++] = a[i];
-       for (i = 0; b[i]; i++)
-               new[j++] = b[i];
-       new[j] = NULL;
-
-       return new;
-}
-
-ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
-                         char *page)
-{
-       struct perf_pmu_events_attr *pmu_attr = \
-               container_of(attr, struct perf_pmu_events_attr, attr);
-       u64 config = x86_pmu.event_map(pmu_attr->id);
-
-       /* string trumps id */
-       if (pmu_attr->event_str)
-               return sprintf(page, "%s", pmu_attr->event_str);
-
-       return x86_pmu.events_sysfs_show(page, config);
-}
-
-EVENT_ATTR(cpu-cycles,                 CPU_CYCLES              );
-EVENT_ATTR(instructions,               INSTRUCTIONS            );
-EVENT_ATTR(cache-references,           CACHE_REFERENCES        );
-EVENT_ATTR(cache-misses,               CACHE_MISSES            );
-EVENT_ATTR(branch-instructions,                BRANCH_INSTRUCTIONS     );
-EVENT_ATTR(branch-misses,              BRANCH_MISSES           );
-EVENT_ATTR(bus-cycles,                 BUS_CYCLES              );
-EVENT_ATTR(stalled-cycles-frontend,    STALLED_CYCLES_FRONTEND );
-EVENT_ATTR(stalled-cycles-backend,     STALLED_CYCLES_BACKEND  );
-EVENT_ATTR(ref-cycles,                 REF_CPU_CYCLES          );
-
-static struct attribute *empty_attrs;
-
-static struct attribute *events_attr[] = {
-       EVENT_PTR(CPU_CYCLES),
-       EVENT_PTR(INSTRUCTIONS),
-       EVENT_PTR(CACHE_REFERENCES),
-       EVENT_PTR(CACHE_MISSES),
-       EVENT_PTR(BRANCH_INSTRUCTIONS),
-       EVENT_PTR(BRANCH_MISSES),
-       EVENT_PTR(BUS_CYCLES),
-       EVENT_PTR(STALLED_CYCLES_FRONTEND),
-       EVENT_PTR(STALLED_CYCLES_BACKEND),
-       EVENT_PTR(REF_CPU_CYCLES),
-       NULL,
-};
-
-static struct attribute_group x86_pmu_events_group = {
-       .name = "events",
-       .attrs = events_attr,
-};
-
-ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
-{
-       u64 umask  = (config & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
-       u64 cmask  = (config & ARCH_PERFMON_EVENTSEL_CMASK) >> 24;
-       bool edge  = (config & ARCH_PERFMON_EVENTSEL_EDGE);
-       bool pc    = (config & ARCH_PERFMON_EVENTSEL_PIN_CONTROL);
-       bool any   = (config & ARCH_PERFMON_EVENTSEL_ANY);
-       bool inv   = (config & ARCH_PERFMON_EVENTSEL_INV);
-       ssize_t ret;
-
-       /*
-       * We have whole page size to spend and just little data
-       * to write, so we can safely use sprintf.
-       */
-       ret = sprintf(page, "event=0x%02llx", event);
-
-       if (umask)
-               ret += sprintf(page + ret, ",umask=0x%02llx", umask);
-
-       if (edge)
-               ret += sprintf(page + ret, ",edge");
-
-       if (pc)
-               ret += sprintf(page + ret, ",pc");
-
-       if (any)
-               ret += sprintf(page + ret, ",any");
-
-       if (inv)
-               ret += sprintf(page + ret, ",inv");
-
-       if (cmask)
-               ret += sprintf(page + ret, ",cmask=0x%02llx", cmask);
-
-       ret += sprintf(page + ret, "\n");
-
-       return ret;
-}
-
-static int __init init_hw_perf_events(void)
-{
-       struct x86_pmu_quirk *quirk;
-       int err;
-
-       pr_info("Performance Events: ");
-
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_INTEL:
-               err = intel_pmu_init();
-               break;
-       case X86_VENDOR_AMD:
-               err = amd_pmu_init();
-               break;
-       default:
-               err = -ENOTSUPP;
-       }
-       if (err != 0) {
-               pr_cont("no PMU driver, software events only.\n");
-               return 0;
-       }
-
-       pmu_check_apic();
-
-       /* sanity check that the hardware exists or is emulated */
-       if (!check_hw_exists())
-               return 0;
-
-       pr_cont("%s PMU driver.\n", x86_pmu.name);
-
-       x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
-
-       for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next)
-               quirk->func();
-
-       if (!x86_pmu.intel_ctrl)
-               x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
-
-       perf_events_lapic_init();
-       register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
-
-       unconstrained = (struct event_constraint)
-               __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
-                                  0, x86_pmu.num_counters, 0, 0);
-
-       x86_pmu_format_group.attrs = x86_pmu.format_attrs;
-
-       if (x86_pmu.event_attrs)
-               x86_pmu_events_group.attrs = x86_pmu.event_attrs;
-
-       if (!x86_pmu.events_sysfs_show)
-               x86_pmu_events_group.attrs = &empty_attrs;
-       else
-               filter_events(x86_pmu_events_group.attrs);
-
-       if (x86_pmu.cpu_events) {
-               struct attribute **tmp;
-
-               tmp = merge_attr(x86_pmu_events_group.attrs, x86_pmu.cpu_events);
-               if (!WARN_ON(!tmp))
-                       x86_pmu_events_group.attrs = tmp;
-       }
-
-       pr_info("... version:                %d\n",     x86_pmu.version);
-       pr_info("... bit width:              %d\n",     x86_pmu.cntval_bits);
-       pr_info("... generic registers:      %d\n",     x86_pmu.num_counters);
-       pr_info("... value mask:             %016Lx\n", x86_pmu.cntval_mask);
-       pr_info("... max period:             %016Lx\n", x86_pmu.max_period);
-       pr_info("... fixed-purpose events:   %d\n",     x86_pmu.num_counters_fixed);
-       pr_info("... event mask:             %016Lx\n", x86_pmu.intel_ctrl);
-
-       perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
-       perf_cpu_notifier(x86_pmu_notifier);
-
-       return 0;
-}
-early_initcall(init_hw_perf_events);
-
-static inline void x86_pmu_read(struct perf_event *event)
-{
-       x86_perf_event_update(event);
-}
-
-/*
- * Start group events scheduling transaction
- * Set the flag to make pmu::enable() not perform the
- * schedulability test, it will be performed at commit time
- *
- * We only support PERF_PMU_TXN_ADD transactions. Save the
- * transaction flags but otherwise ignore non-PERF_PMU_TXN_ADD
- * transactions.
- */
-static void x86_pmu_start_txn(struct pmu *pmu, unsigned int txn_flags)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       WARN_ON_ONCE(cpuc->txn_flags);          /* txn already in flight */
-
-       cpuc->txn_flags = txn_flags;
-       if (txn_flags & ~PERF_PMU_TXN_ADD)
-               return;
-
-       perf_pmu_disable(pmu);
-       __this_cpu_write(cpu_hw_events.n_txn, 0);
-}
-
-/*
- * Stop group events scheduling transaction
- * Clear the flag and pmu::enable() will perform the
- * schedulability test.
- */
-static void x86_pmu_cancel_txn(struct pmu *pmu)
-{
-       unsigned int txn_flags;
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */
-
-       txn_flags = cpuc->txn_flags;
-       cpuc->txn_flags = 0;
-       if (txn_flags & ~PERF_PMU_TXN_ADD)
-               return;
-
-       /*
-        * Truncate collected array by the number of events added in this
-        * transaction. See x86_pmu_add() and x86_pmu_*_txn().
-        */
-       __this_cpu_sub(cpu_hw_events.n_added, __this_cpu_read(cpu_hw_events.n_txn));
-       __this_cpu_sub(cpu_hw_events.n_events, __this_cpu_read(cpu_hw_events.n_txn));
-       perf_pmu_enable(pmu);
-}
-
-/*
- * Commit group events scheduling transaction
- * Perform the group schedulability test as a whole
- * Return 0 if success
- *
- * Does not cancel the transaction on failure; expects the caller to do this.
- */
-static int x86_pmu_commit_txn(struct pmu *pmu)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       int assign[X86_PMC_IDX_MAX];
-       int n, ret;
-
-       WARN_ON_ONCE(!cpuc->txn_flags); /* no txn in flight */
-
-       if (cpuc->txn_flags & ~PERF_PMU_TXN_ADD) {
-               cpuc->txn_flags = 0;
-               return 0;
-       }
-
-       n = cpuc->n_events;
-
-       if (!x86_pmu_initialized())
-               return -EAGAIN;
-
-       ret = x86_pmu.schedule_events(cpuc, n, assign);
-       if (ret)
-               return ret;
-
-       /*
-        * copy new assignment, now we know it is possible
-        * will be used by hw_perf_enable()
-        */
-       memcpy(cpuc->assign, assign, n*sizeof(int));
-
-       cpuc->txn_flags = 0;
-       perf_pmu_enable(pmu);
-       return 0;
-}
-/*
- * a fake_cpuc is used to validate event groups. Due to
- * the extra reg logic, we need to also allocate a fake
- * per_core and per_cpu structure. Otherwise, group events
- * using extra reg may conflict without the kernel being
- * able to catch this when the last event gets added to
- * the group.
- */
-static void free_fake_cpuc(struct cpu_hw_events *cpuc)
-{
-       kfree(cpuc->shared_regs);
-       kfree(cpuc);
-}
-
-static struct cpu_hw_events *allocate_fake_cpuc(void)
-{
-       struct cpu_hw_events *cpuc;
-       int cpu = raw_smp_processor_id();
-
-       cpuc = kzalloc(sizeof(*cpuc), GFP_KERNEL);
-       if (!cpuc)
-               return ERR_PTR(-ENOMEM);
-
-       /* only needed, if we have extra_regs */
-       if (x86_pmu.extra_regs) {
-               cpuc->shared_regs = allocate_shared_regs(cpu);
-               if (!cpuc->shared_regs)
-                       goto error;
-       }
-       cpuc->is_fake = 1;
-       return cpuc;
-error:
-       free_fake_cpuc(cpuc);
-       return ERR_PTR(-ENOMEM);
-}
-
-/*
- * validate that we can schedule this event
- */
-static int validate_event(struct perf_event *event)
-{
-       struct cpu_hw_events *fake_cpuc;
-       struct event_constraint *c;
-       int ret = 0;
-
-       fake_cpuc = allocate_fake_cpuc();
-       if (IS_ERR(fake_cpuc))
-               return PTR_ERR(fake_cpuc);
-
-       c = x86_pmu.get_event_constraints(fake_cpuc, -1, event);
-
-       if (!c || !c->weight)
-               ret = -EINVAL;
-
-       if (x86_pmu.put_event_constraints)
-               x86_pmu.put_event_constraints(fake_cpuc, event);
-
-       free_fake_cpuc(fake_cpuc);
-
-       return ret;
-}
-
-/*
- * validate a single event group
- *
- * validation include:
- *     - check events are compatible which each other
- *     - events do not compete for the same counter
- *     - number of events <= number of counters
- *
- * validation ensures the group can be loaded onto the
- * PMU if it was the only group available.
- */
-static int validate_group(struct perf_event *event)
-{
-       struct perf_event *leader = event->group_leader;
-       struct cpu_hw_events *fake_cpuc;
-       int ret = -EINVAL, n;
-
-       fake_cpuc = allocate_fake_cpuc();
-       if (IS_ERR(fake_cpuc))
-               return PTR_ERR(fake_cpuc);
-       /*
-        * the event is not yet connected with its
-        * siblings therefore we must first collect
-        * existing siblings, then add the new event
-        * before we can simulate the scheduling
-        */
-       n = collect_events(fake_cpuc, leader, true);
-       if (n < 0)
-               goto out;
-
-       fake_cpuc->n_events = n;
-       n = collect_events(fake_cpuc, event, false);
-       if (n < 0)
-               goto out;
-
-       fake_cpuc->n_events = n;
-
-       ret = x86_pmu.schedule_events(fake_cpuc, n, NULL);
-
-out:
-       free_fake_cpuc(fake_cpuc);
-       return ret;
-}
-
-static int x86_pmu_event_init(struct perf_event *event)
-{
-       struct pmu *tmp;
-       int err;
-
-       switch (event->attr.type) {
-       case PERF_TYPE_RAW:
-       case PERF_TYPE_HARDWARE:
-       case PERF_TYPE_HW_CACHE:
-               break;
-
-       default:
-               return -ENOENT;
-       }
-
-       err = __x86_pmu_event_init(event);
-       if (!err) {
-               /*
-                * we temporarily connect event to its pmu
-                * such that validate_group() can classify
-                * it as an x86 event using is_x86_event()
-                */
-               tmp = event->pmu;
-               event->pmu = &pmu;
-
-               if (event->group_leader != event)
-                       err = validate_group(event);
-               else
-                       err = validate_event(event);
-
-               event->pmu = tmp;
-       }
-       if (err) {
-               if (event->destroy)
-                       event->destroy(event);
-       }
-
-       if (ACCESS_ONCE(x86_pmu.attr_rdpmc))
-               event->hw.flags |= PERF_X86_EVENT_RDPMC_ALLOWED;
-
-       return err;
-}
-
-static void refresh_pce(void *ignored)
-{
-       if (current->mm)
-               load_mm_cr4(current->mm);
-}
-
-static void x86_pmu_event_mapped(struct perf_event *event)
-{
-       if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
-               return;
-
-       if (atomic_inc_return(&current->mm->context.perf_rdpmc_allowed) == 1)
-               on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1);
-}
-
-static void x86_pmu_event_unmapped(struct perf_event *event)
-{
-       if (!current->mm)
-               return;
-
-       if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
-               return;
-
-       if (atomic_dec_and_test(&current->mm->context.perf_rdpmc_allowed))
-               on_each_cpu_mask(mm_cpumask(current->mm), refresh_pce, NULL, 1);
-}
-
-static int x86_pmu_event_idx(struct perf_event *event)
-{
-       int idx = event->hw.idx;
-
-       if (!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED))
-               return 0;
-
-       if (x86_pmu.num_counters_fixed && idx >= INTEL_PMC_IDX_FIXED) {
-               idx -= INTEL_PMC_IDX_FIXED;
-               idx |= 1 << 30;
-       }
-
-       return idx + 1;
-}
-
-static ssize_t get_attr_rdpmc(struct device *cdev,
-                             struct device_attribute *attr,
-                             char *buf)
-{
-       return snprintf(buf, 40, "%d\n", x86_pmu.attr_rdpmc);
-}
-
-static ssize_t set_attr_rdpmc(struct device *cdev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       unsigned long val;
-       ssize_t ret;
-
-       ret = kstrtoul(buf, 0, &val);
-       if (ret)
-               return ret;
-
-       if (val > 2)
-               return -EINVAL;
-
-       if (x86_pmu.attr_rdpmc_broken)
-               return -ENOTSUPP;
-
-       if ((val == 2) != (x86_pmu.attr_rdpmc == 2)) {
-               /*
-                * Changing into or out of always available, aka
-                * perf-event-bypassing mode.  This path is extremely slow,
-                * but only root can trigger it, so it's okay.
-                */
-               if (val == 2)
-                       static_key_slow_inc(&rdpmc_always_available);
-               else
-                       static_key_slow_dec(&rdpmc_always_available);
-               on_each_cpu(refresh_pce, NULL, 1);
-       }
-
-       x86_pmu.attr_rdpmc = val;
-
-       return count;
-}
-
-static DEVICE_ATTR(rdpmc, S_IRUSR | S_IWUSR, get_attr_rdpmc, set_attr_rdpmc);
-
-static struct attribute *x86_pmu_attrs[] = {
-       &dev_attr_rdpmc.attr,
-       NULL,
-};
-
-static struct attribute_group x86_pmu_attr_group = {
-       .attrs = x86_pmu_attrs,
-};
-
-static const struct attribute_group *x86_pmu_attr_groups[] = {
-       &x86_pmu_attr_group,
-       &x86_pmu_format_group,
-       &x86_pmu_events_group,
-       NULL,
-};
-
-static void x86_pmu_sched_task(struct perf_event_context *ctx, bool sched_in)
-{
-       if (x86_pmu.sched_task)
-               x86_pmu.sched_task(ctx, sched_in);
-}
-
-void perf_check_microcode(void)
-{
-       if (x86_pmu.check_microcode)
-               x86_pmu.check_microcode();
-}
-EXPORT_SYMBOL_GPL(perf_check_microcode);
-
-static struct pmu pmu = {
-       .pmu_enable             = x86_pmu_enable,
-       .pmu_disable            = x86_pmu_disable,
-
-       .attr_groups            = x86_pmu_attr_groups,
-
-       .event_init             = x86_pmu_event_init,
-
-       .event_mapped           = x86_pmu_event_mapped,
-       .event_unmapped         = x86_pmu_event_unmapped,
-
-       .add                    = x86_pmu_add,
-       .del                    = x86_pmu_del,
-       .start                  = x86_pmu_start,
-       .stop                   = x86_pmu_stop,
-       .read                   = x86_pmu_read,
-
-       .start_txn              = x86_pmu_start_txn,
-       .cancel_txn             = x86_pmu_cancel_txn,
-       .commit_txn             = x86_pmu_commit_txn,
-
-       .event_idx              = x86_pmu_event_idx,
-       .sched_task             = x86_pmu_sched_task,
-       .task_ctx_size          = sizeof(struct x86_perf_task_context),
-};
-
-void arch_perf_update_userpage(struct perf_event *event,
-                              struct perf_event_mmap_page *userpg, u64 now)
-{
-       struct cyc2ns_data *data;
-
-       userpg->cap_user_time = 0;
-       userpg->cap_user_time_zero = 0;
-       userpg->cap_user_rdpmc =
-               !!(event->hw.flags & PERF_X86_EVENT_RDPMC_ALLOWED);
-       userpg->pmc_width = x86_pmu.cntval_bits;
-
-       if (!sched_clock_stable())
-               return;
-
-       data = cyc2ns_read_begin();
-
-       /*
-        * Internal timekeeping for enabled/running/stopped times
-        * is always in the local_clock domain.
-        */
-       userpg->cap_user_time = 1;
-       userpg->time_mult = data->cyc2ns_mul;
-       userpg->time_shift = data->cyc2ns_shift;
-       userpg->time_offset = data->cyc2ns_offset - now;
-
-       /*
-        * cap_user_time_zero doesn't make sense when we're using a different
-        * time base for the records.
-        */
-       if (event->clock == &local_clock) {
-               userpg->cap_user_time_zero = 1;
-               userpg->time_zero = data->cyc2ns_offset;
-       }
-
-       cyc2ns_read_end(data);
-}
-
-/*
- * callchain support
- */
-
-static int backtrace_stack(void *data, char *name)
-{
-       return 0;
-}
-
-static void backtrace_address(void *data, unsigned long addr, int reliable)
-{
-       struct perf_callchain_entry *entry = data;
-
-       perf_callchain_store(entry, addr);
-}
-
-static const struct stacktrace_ops backtrace_ops = {
-       .stack                  = backtrace_stack,
-       .address                = backtrace_address,
-       .walk_stack             = print_context_stack_bp,
-};
-
-void
-perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
-{
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-               /* TODO: We don't support guest os callchain now */
-               return;
-       }
-
-       perf_callchain_store(entry, regs->ip);
-
-       dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry);
-}
-
-static inline int
-valid_user_frame(const void __user *fp, unsigned long size)
-{
-       return (__range_not_ok(fp, size, TASK_SIZE) == 0);
-}
-
-static unsigned long get_segment_base(unsigned int segment)
-{
-       struct desc_struct *desc;
-       int idx = segment >> 3;
-
-       if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
-#ifdef CONFIG_MODIFY_LDT_SYSCALL
-               struct ldt_struct *ldt;
-
-               if (idx > LDT_ENTRIES)
-                       return 0;
-
-               /* IRQs are off, so this synchronizes with smp_store_release */
-               ldt = lockless_dereference(current->active_mm->context.ldt);
-               if (!ldt || idx > ldt->size)
-                       return 0;
-
-               desc = &ldt->entries[idx];
-#else
-               return 0;
-#endif
-       } else {
-               if (idx > GDT_ENTRIES)
-                       return 0;
-
-               desc = raw_cpu_ptr(gdt_page.gdt) + idx;
-       }
-
-       return get_desc_base(desc);
-}
-
-#ifdef CONFIG_IA32_EMULATION
-
-#include <asm/compat.h>
-
-static inline int
-perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
-{
-       /* 32-bit process in 64-bit kernel. */
-       unsigned long ss_base, cs_base;
-       struct stack_frame_ia32 frame;
-       const void __user *fp;
-
-       if (!test_thread_flag(TIF_IA32))
-               return 0;
-
-       cs_base = get_segment_base(regs->cs);
-       ss_base = get_segment_base(regs->ss);
-
-       fp = compat_ptr(ss_base + regs->bp);
-       pagefault_disable();
-       while (entry->nr < PERF_MAX_STACK_DEPTH) {
-               unsigned long bytes;
-               frame.next_frame     = 0;
-               frame.return_address = 0;
-
-               if (!access_ok(VERIFY_READ, fp, 8))
-                       break;
-
-               bytes = __copy_from_user_nmi(&frame.next_frame, fp, 4);
-               if (bytes != 0)
-                       break;
-               bytes = __copy_from_user_nmi(&frame.return_address, fp+4, 4);
-               if (bytes != 0)
-                       break;
-
-               if (!valid_user_frame(fp, sizeof(frame)))
-                       break;
-
-               perf_callchain_store(entry, cs_base + frame.return_address);
-               fp = compat_ptr(ss_base + frame.next_frame);
-       }
-       pagefault_enable();
-       return 1;
-}
-#else
-static inline int
-perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
-{
-    return 0;
-}
-#endif
-
-void
-perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
-{
-       struct stack_frame frame;
-       const void __user *fp;
-
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-               /* TODO: We don't support guest os callchain now */
-               return;
-       }
-
-       /*
-        * We don't know what to do with VM86 stacks.. ignore them for now.
-        */
-       if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM))
-               return;
-
-       fp = (void __user *)regs->bp;
-
-       perf_callchain_store(entry, regs->ip);
-
-       if (!current->mm)
-               return;
-
-       if (perf_callchain_user32(regs, entry))
-               return;
-
-       pagefault_disable();
-       while (entry->nr < PERF_MAX_STACK_DEPTH) {
-               unsigned long bytes;
-               frame.next_frame             = NULL;
-               frame.return_address = 0;
-
-               if (!access_ok(VERIFY_READ, fp, 16))
-                       break;
-
-               bytes = __copy_from_user_nmi(&frame.next_frame, fp, 8);
-               if (bytes != 0)
-                       break;
-               bytes = __copy_from_user_nmi(&frame.return_address, fp+8, 8);
-               if (bytes != 0)
-                       break;
-
-               if (!valid_user_frame(fp, sizeof(frame)))
-                       break;
-
-               perf_callchain_store(entry, frame.return_address);
-               fp = (void __user *)frame.next_frame;
-       }
-       pagefault_enable();
-}
-
-/*
- * Deal with code segment offsets for the various execution modes:
- *
- *   VM86 - the good olde 16 bit days, where the linear address is
- *          20 bits and we use regs->ip + 0x10 * regs->cs.
- *
- *   IA32 - Where we need to look at GDT/LDT segment descriptor tables
- *          to figure out what the 32bit base address is.
- *
- *    X32 - has TIF_X32 set, but is running in x86_64
- *
- * X86_64 - CS,DS,SS,ES are all zero based.
- */
-static unsigned long code_segment_base(struct pt_regs *regs)
-{
-       /*
-        * For IA32 we look at the GDT/LDT segment base to convert the
-        * effective IP to a linear address.
-        */
-
-#ifdef CONFIG_X86_32
-       /*
-        * If we are in VM86 mode, add the segment offset to convert to a
-        * linear address.
-        */
-       if (regs->flags & X86_VM_MASK)
-               return 0x10 * regs->cs;
-
-       if (user_mode(regs) && regs->cs != __USER_CS)
-               return get_segment_base(regs->cs);
-#else
-       if (user_mode(regs) && !user_64bit_mode(regs) &&
-           regs->cs != __USER32_CS)
-               return get_segment_base(regs->cs);
-#endif
-       return 0;
-}
-
-unsigned long perf_instruction_pointer(struct pt_regs *regs)
-{
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
-               return perf_guest_cbs->get_guest_ip();
-
-       return regs->ip + code_segment_base(regs);
-}
-
-unsigned long perf_misc_flags(struct pt_regs *regs)
-{
-       int misc = 0;
-
-       if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-               if (perf_guest_cbs->is_user_mode())
-                       misc |= PERF_RECORD_MISC_GUEST_USER;
-               else
-                       misc |= PERF_RECORD_MISC_GUEST_KERNEL;
-       } else {
-               if (user_mode(regs))
-                       misc |= PERF_RECORD_MISC_USER;
-               else
-                       misc |= PERF_RECORD_MISC_KERNEL;
-       }
-
-       if (regs->flags & PERF_EFLAGS_EXACT)
-               misc |= PERF_RECORD_MISC_EXACT_IP;
-
-       return misc;
-}
-
-void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
-{
-       cap->version            = x86_pmu.version;
-       cap->num_counters_gp    = x86_pmu.num_counters;
-       cap->num_counters_fixed = x86_pmu.num_counters_fixed;
-       cap->bit_width_gp       = x86_pmu.cntval_bits;
-       cap->bit_width_fixed    = x86_pmu.cntval_bits;
-       cap->events_mask        = (unsigned int)x86_pmu.events_maskl;
-       cap->events_mask_len    = x86_pmu.events_mask_len;
-}
-EXPORT_SYMBOL_GPL(perf_get_x86_pmu_capability);
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
deleted file mode 100644 (file)
index 7bb61e3..0000000
+++ /dev/null
@@ -1,955 +0,0 @@
-/*
- * Performance events x86 architecture header
- *
- *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
- *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2009 Jaswinder Singh Rajput
- *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
- *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
- *  Copyright (C) 2009 Google, Inc., Stephane Eranian
- *
- *  For licencing details see kernel-base/COPYING
- */
-
-#include <linux/perf_event.h>
-
-/* To enable MSR tracing please use the generic trace points. */
-
-/*
- *          |   NHM/WSM    |      SNB     |
- * register -------------------------------
- *          |  HT  | no HT |  HT  | no HT |
- *-----------------------------------------
- * offcore  | core | core  | cpu  | core  |
- * lbr_sel  | core | core  | cpu  | core  |
- * ld_lat   | cpu  | core  | cpu  | core  |
- *-----------------------------------------
- *
- * Given that there is a small number of shared regs,
- * we can pre-allocate their slot in the per-cpu
- * per-core reg tables.
- */
-enum extra_reg_type {
-       EXTRA_REG_NONE  = -1,   /* not used */
-
-       EXTRA_REG_RSP_0 = 0,    /* offcore_response_0 */
-       EXTRA_REG_RSP_1 = 1,    /* offcore_response_1 */
-       EXTRA_REG_LBR   = 2,    /* lbr_select */
-       EXTRA_REG_LDLAT = 3,    /* ld_lat_threshold */
-       EXTRA_REG_FE    = 4,    /* fe_* */
-
-       EXTRA_REG_MAX           /* number of entries needed */
-};
-
-struct event_constraint {
-       union {
-               unsigned long   idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-               u64             idxmsk64;
-       };
-       u64     code;
-       u64     cmask;
-       int     weight;
-       int     overlap;
-       int     flags;
-};
-/*
- * struct hw_perf_event.flags flags
- */
-#define PERF_X86_EVENT_PEBS_LDLAT      0x0001 /* ld+ldlat data address sampling */
-#define PERF_X86_EVENT_PEBS_ST         0x0002 /* st data address sampling */
-#define PERF_X86_EVENT_PEBS_ST_HSW     0x0004 /* haswell style datala, store */
-#define PERF_X86_EVENT_COMMITTED       0x0008 /* event passed commit_txn */
-#define PERF_X86_EVENT_PEBS_LD_HSW     0x0010 /* haswell style datala, load */
-#define PERF_X86_EVENT_PEBS_NA_HSW     0x0020 /* haswell style datala, unknown */
-#define PERF_X86_EVENT_EXCL            0x0040 /* HT exclusivity on counter */
-#define PERF_X86_EVENT_DYNAMIC         0x0080 /* dynamic alloc'd constraint */
-#define PERF_X86_EVENT_RDPMC_ALLOWED   0x0100 /* grant rdpmc permission */
-#define PERF_X86_EVENT_EXCL_ACCT       0x0200 /* accounted EXCL event */
-#define PERF_X86_EVENT_AUTO_RELOAD     0x0400 /* use PEBS auto-reload */
-#define PERF_X86_EVENT_FREERUNNING     0x0800 /* use freerunning PEBS */
-
-
-struct amd_nb {
-       int nb_id;  /* NorthBridge id */
-       int refcnt; /* reference count */
-       struct perf_event *owners[X86_PMC_IDX_MAX];
-       struct event_constraint event_constraints[X86_PMC_IDX_MAX];
-};
-
-/* The maximal number of PEBS events: */
-#define MAX_PEBS_EVENTS                8
-
-/*
- * Flags PEBS can handle without an PMI.
- *
- * TID can only be handled by flushing at context switch.
- *
- */
-#define PEBS_FREERUNNING_FLAGS \
-       (PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_ADDR | \
-       PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_STREAM_ID | \
-       PERF_SAMPLE_DATA_SRC | PERF_SAMPLE_IDENTIFIER | \
-       PERF_SAMPLE_TRANSACTION)
-
-/*
- * A debug store configuration.
- *
- * We only support architectures that use 64bit fields.
- */
-struct debug_store {
-       u64     bts_buffer_base;
-       u64     bts_index;
-       u64     bts_absolute_maximum;
-       u64     bts_interrupt_threshold;
-       u64     pebs_buffer_base;
-       u64     pebs_index;
-       u64     pebs_absolute_maximum;
-       u64     pebs_interrupt_threshold;
-       u64     pebs_event_reset[MAX_PEBS_EVENTS];
-};
-
-/*
- * Per register state.
- */
-struct er_account {
-       raw_spinlock_t          lock;   /* per-core: protect structure */
-       u64                 config;     /* extra MSR config */
-       u64                 reg;        /* extra MSR number */
-       atomic_t            ref;        /* reference count */
-};
-
-/*
- * Per core/cpu state
- *
- * Used to coordinate shared registers between HT threads or
- * among events on a single PMU.
- */
-struct intel_shared_regs {
-       struct er_account       regs[EXTRA_REG_MAX];
-       int                     refcnt;         /* per-core: #HT threads */
-       unsigned                core_id;        /* per-core: core id */
-};
-
-enum intel_excl_state_type {
-       INTEL_EXCL_UNUSED    = 0, /* counter is unused */
-       INTEL_EXCL_SHARED    = 1, /* counter can be used by both threads */
-       INTEL_EXCL_EXCLUSIVE = 2, /* counter can be used by one thread only */
-};
-
-struct intel_excl_states {
-       enum intel_excl_state_type state[X86_PMC_IDX_MAX];
-       bool sched_started; /* true if scheduling has started */
-};
-
-struct intel_excl_cntrs {
-       raw_spinlock_t  lock;
-
-       struct intel_excl_states states[2];
-
-       union {
-               u16     has_exclusive[2];
-               u32     exclusive_present;
-       };
-
-       int             refcnt;         /* per-core: #HT threads */
-       unsigned        core_id;        /* per-core: core id */
-};
-
-#define MAX_LBR_ENTRIES                32
-
-enum {
-       X86_PERF_KFREE_SHARED = 0,
-       X86_PERF_KFREE_EXCL   = 1,
-       X86_PERF_KFREE_MAX
-};
-
-struct cpu_hw_events {
-       /*
-        * Generic x86 PMC bits
-        */
-       struct perf_event       *events[X86_PMC_IDX_MAX]; /* in counter order */
-       unsigned long           active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-       unsigned long           running[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-       int                     enabled;
-
-       int                     n_events; /* the # of events in the below arrays */
-       int                     n_added;  /* the # last events in the below arrays;
-                                            they've never been enabled yet */
-       int                     n_txn;    /* the # last events in the below arrays;
-                                            added in the current transaction */
-       int                     assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
-       u64                     tags[X86_PMC_IDX_MAX];
-
-       struct perf_event       *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
-       struct event_constraint *event_constraint[X86_PMC_IDX_MAX];
-
-       int                     n_excl; /* the number of exclusive events */
-
-       unsigned int            txn_flags;
-       int                     is_fake;
-
-       /*
-        * Intel DebugStore bits
-        */
-       struct debug_store      *ds;
-       u64                     pebs_enabled;
-
-       /*
-        * Intel LBR bits
-        */
-       int                             lbr_users;
-       void                            *lbr_context;
-       struct perf_branch_stack        lbr_stack;
-       struct perf_branch_entry        lbr_entries[MAX_LBR_ENTRIES];
-       struct er_account               *lbr_sel;
-       u64                             br_sel;
-
-       /*
-        * Intel host/guest exclude bits
-        */
-       u64                             intel_ctrl_guest_mask;
-       u64                             intel_ctrl_host_mask;
-       struct perf_guest_switch_msr    guest_switch_msrs[X86_PMC_IDX_MAX];
-
-       /*
-        * Intel checkpoint mask
-        */
-       u64                             intel_cp_status;
-
-       /*
-        * manage shared (per-core, per-cpu) registers
-        * used on Intel NHM/WSM/SNB
-        */
-       struct intel_shared_regs        *shared_regs;
-       /*
-        * manage exclusive counter access between hyperthread
-        */
-       struct event_constraint *constraint_list; /* in enable order */
-       struct intel_excl_cntrs         *excl_cntrs;
-       int excl_thread_id; /* 0 or 1 */
-
-       /*
-        * AMD specific bits
-        */
-       struct amd_nb                   *amd_nb;
-       /* Inverted mask of bits to clear in the perf_ctr ctrl registers */
-       u64                             perf_ctr_virt_mask;
-
-       void                            *kfree_on_online[X86_PERF_KFREE_MAX];
-};
-
-#define __EVENT_CONSTRAINT(c, n, m, w, o, f) {\
-       { .idxmsk64 = (n) },            \
-       .code = (c),                    \
-       .cmask = (m),                   \
-       .weight = (w),                  \
-       .overlap = (o),                 \
-       .flags = f,                     \
-}
-
-#define EVENT_CONSTRAINT(c, n, m)      \
-       __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n), 0, 0)
-
-#define INTEL_EXCLEVT_CONSTRAINT(c, n) \
-       __EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT, HWEIGHT(n),\
-                          0, PERF_X86_EVENT_EXCL)
-
-/*
- * The overlap flag marks event constraints with overlapping counter
- * masks. This is the case if the counter mask of such an event is not
- * a subset of any other counter mask of a constraint with an equal or
- * higher weight, e.g.:
- *
- *  c_overlaps = EVENT_CONSTRAINT_OVERLAP(0, 0x09, 0);
- *  c_another1 = EVENT_CONSTRAINT(0, 0x07, 0);
- *  c_another2 = EVENT_CONSTRAINT(0, 0x38, 0);
- *
- * The event scheduler may not select the correct counter in the first
- * cycle because it needs to know which subsequent events will be
- * scheduled. It may fail to schedule the events then. So we set the
- * overlap flag for such constraints to give the scheduler a hint which
- * events to select for counter rescheduling.
- *
- * Care must be taken as the rescheduling algorithm is O(n!) which
- * will increase scheduling cycles for an over-commited system
- * dramatically.  The number of such EVENT_CONSTRAINT_OVERLAP() macros
- * and its counter masks must be kept at a minimum.
- */
-#define EVENT_CONSTRAINT_OVERLAP(c, n, m)      \
-       __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n), 1, 0)
-
-/*
- * Constraint on the Event code.
- */
-#define INTEL_EVENT_CONSTRAINT(c, n)   \
-       EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT)
-
-/*
- * Constraint on the Event code + UMask + fixed-mask
- *
- * filter mask to validate fixed counter events.
- * the following filters disqualify for fixed counters:
- *  - inv
- *  - edge
- *  - cnt-mask
- *  - in_tx
- *  - in_tx_checkpointed
- *  The other filters are supported by fixed counters.
- *  The any-thread option is supported starting with v3.
- */
-#define FIXED_EVENT_FLAGS (X86_RAW_EVENT_MASK|HSW_IN_TX|HSW_IN_TX_CHECKPOINTED)
-#define FIXED_EVENT_CONSTRAINT(c, n)   \
-       EVENT_CONSTRAINT(c, (1ULL << (32+n)), FIXED_EVENT_FLAGS)
-
-/*
- * Constraint on the Event code + UMask
- */
-#define INTEL_UEVENT_CONSTRAINT(c, n)  \
-       EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
-
-/* Constraint on specific umask bit only + event */
-#define INTEL_UBIT_EVENT_CONSTRAINT(c, n)      \
-       EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT|(c))
-
-/* Like UEVENT_CONSTRAINT, but match flags too */
-#define INTEL_FLAGS_UEVENT_CONSTRAINT(c, n)    \
-       EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
-
-#define INTEL_EXCLUEVT_CONSTRAINT(c, n)        \
-       __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \
-                          HWEIGHT(n), 0, PERF_X86_EVENT_EXCL)
-
-#define INTEL_PLD_CONSTRAINT(c, n)     \
-       __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
-                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LDLAT)
-
-#define INTEL_PST_CONSTRAINT(c, n)     \
-       __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST)
-
-/* Event constraint, but match on all event flags too. */
-#define INTEL_FLAGS_EVENT_CONSTRAINT(c, n) \
-       EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
-
-/* Check only flags, but allow all event/umask */
-#define INTEL_ALL_EVENT_CONSTRAINT(code, n)    \
-       EVENT_CONSTRAINT(code, n, X86_ALL_EVENT_FLAGS)
-
-/* Check flags and event code, and set the HSW store flag */
-#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_ST(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
-                         ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
-
-/* Check flags and event code, and set the HSW load flag */
-#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
-                         ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LD_HSW)
-
-#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
-                         ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, \
-                         PERF_X86_EVENT_PEBS_LD_HSW|PERF_X86_EVENT_EXCL)
-
-/* Check flags and event code/umask, and set the HSW store flag */
-#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
-                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
-
-#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
-                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, \
-                         PERF_X86_EVENT_PEBS_ST_HSW|PERF_X86_EVENT_EXCL)
-
-/* Check flags and event code/umask, and set the HSW load flag */
-#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
-                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LD_HSW)
-
-#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
-                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, \
-                         PERF_X86_EVENT_PEBS_LD_HSW|PERF_X86_EVENT_EXCL)
-
-/* Check flags and event code/umask, and set the HSW N/A flag */
-#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(code, n) \
-       __EVENT_CONSTRAINT(code, n,                     \
-                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
-                         HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_NA_HSW)
-
-
-/*
- * We define the end marker as having a weight of -1
- * to enable blacklisting of events using a counter bitmask
- * of zero and thus a weight of zero.
- * The end marker has a weight that cannot possibly be
- * obtained from counting the bits in the bitmask.
- */
-#define EVENT_CONSTRAINT_END { .weight = -1 }
-
-/*
- * Check for end marker with weight == -1
- */
-#define for_each_event_constraint(e, c)        \
-       for ((e) = (c); (e)->weight != -1; (e)++)
-
-/*
- * Extra registers for specific events.
- *
- * Some events need large masks and require external MSRs.
- * Those extra MSRs end up being shared for all events on
- * a PMU and sometimes between PMU of sibling HT threads.
- * In either case, the kernel needs to handle conflicting
- * accesses to those extra, shared, regs. The data structure
- * to manage those registers is stored in cpu_hw_event.
- */
-struct extra_reg {
-       unsigned int            event;
-       unsigned int            msr;
-       u64                     config_mask;
-       u64                     valid_mask;
-       int                     idx;  /* per_xxx->regs[] reg index */
-       bool                    extra_msr_access;
-};
-
-#define EVENT_EXTRA_REG(e, ms, m, vm, i) {     \
-       .event = (e),                   \
-       .msr = (ms),                    \
-       .config_mask = (m),             \
-       .valid_mask = (vm),             \
-       .idx = EXTRA_REG_##i,           \
-       .extra_msr_access = true,       \
-       }
-
-#define INTEL_EVENT_EXTRA_REG(event, msr, vm, idx)     \
-       EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm, idx)
-
-#define INTEL_UEVENT_EXTRA_REG(event, msr, vm, idx) \
-       EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT | \
-                       ARCH_PERFMON_EVENTSEL_UMASK, vm, idx)
-
-#define INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(c) \
-       INTEL_UEVENT_EXTRA_REG(c, \
-                              MSR_PEBS_LD_LAT_THRESHOLD, \
-                              0xffff, \
-                              LDLAT)
-
-#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0, RSP_0)
-
-union perf_capabilities {
-       struct {
-               u64     lbr_format:6;
-               u64     pebs_trap:1;
-               u64     pebs_arch_reg:1;
-               u64     pebs_format:4;
-               u64     smm_freeze:1;
-               /*
-                * PMU supports separate counter range for writing
-                * values > 32bit.
-                */
-               u64     full_width_write:1;
-       };
-       u64     capabilities;
-};
-
-struct x86_pmu_quirk {
-       struct x86_pmu_quirk *next;
-       void (*func)(void);
-};
-
-union x86_pmu_config {
-       struct {
-               u64 event:8,
-                   umask:8,
-                   usr:1,
-                   os:1,
-                   edge:1,
-                   pc:1,
-                   interrupt:1,
-                   __reserved1:1,
-                   en:1,
-                   inv:1,
-                   cmask:8,
-                   event2:4,
-                   __reserved2:4,
-                   go:1,
-                   ho:1;
-       } bits;
-       u64 value;
-};
-
-#define X86_CONFIG(args...) ((union x86_pmu_config){.bits = {args}}).value
-
-enum {
-       x86_lbr_exclusive_lbr,
-       x86_lbr_exclusive_bts,
-       x86_lbr_exclusive_pt,
-       x86_lbr_exclusive_max,
-};
-
-/*
- * struct x86_pmu - generic x86 pmu
- */
-struct x86_pmu {
-       /*
-        * Generic x86 PMC bits
-        */
-       const char      *name;
-       int             version;
-       int             (*handle_irq)(struct pt_regs *);
-       void            (*disable_all)(void);
-       void            (*enable_all)(int added);
-       void            (*enable)(struct perf_event *);
-       void            (*disable)(struct perf_event *);
-       int             (*hw_config)(struct perf_event *event);
-       int             (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
-       unsigned        eventsel;
-       unsigned        perfctr;
-       int             (*addr_offset)(int index, bool eventsel);
-       int             (*rdpmc_index)(int index);
-       u64             (*event_map)(int);
-       int             max_events;
-       int             num_counters;
-       int             num_counters_fixed;
-       int             cntval_bits;
-       u64             cntval_mask;
-       union {
-                       unsigned long events_maskl;
-                       unsigned long events_mask[BITS_TO_LONGS(ARCH_PERFMON_EVENTS_COUNT)];
-       };
-       int             events_mask_len;
-       int             apic;
-       u64             max_period;
-       struct event_constraint *
-                       (*get_event_constraints)(struct cpu_hw_events *cpuc,
-                                                int idx,
-                                                struct perf_event *event);
-
-       void            (*put_event_constraints)(struct cpu_hw_events *cpuc,
-                                                struct perf_event *event);
-
-       void            (*start_scheduling)(struct cpu_hw_events *cpuc);
-
-       void            (*commit_scheduling)(struct cpu_hw_events *cpuc, int idx, int cntr);
-
-       void            (*stop_scheduling)(struct cpu_hw_events *cpuc);
-
-       struct event_constraint *event_constraints;
-       struct x86_pmu_quirk *quirks;
-       int             perfctr_second_write;
-       bool            late_ack;
-       unsigned        (*limit_period)(struct perf_event *event, unsigned l);
-
-       /*
-        * sysfs attrs
-        */
-       int             attr_rdpmc_broken;
-       int             attr_rdpmc;
-       struct attribute **format_attrs;
-       struct attribute **event_attrs;
-
-       ssize_t         (*events_sysfs_show)(char *page, u64 config);
-       struct attribute **cpu_events;
-
-       /*
-        * CPU Hotplug hooks
-        */
-       int             (*cpu_prepare)(int cpu);
-       void            (*cpu_starting)(int cpu);
-       void            (*cpu_dying)(int cpu);
-       void            (*cpu_dead)(int cpu);
-
-       void            (*check_microcode)(void);
-       void            (*sched_task)(struct perf_event_context *ctx,
-                                     bool sched_in);
-
-       /*
-        * Intel Arch Perfmon v2+
-        */
-       u64                     intel_ctrl;
-       union perf_capabilities intel_cap;
-
-       /*
-        * Intel DebugStore bits
-        */
-       unsigned int    bts             :1,
-                       bts_active      :1,
-                       pebs            :1,
-                       pebs_active     :1,
-                       pebs_broken     :1,
-                       pebs_prec_dist  :1;
-       int             pebs_record_size;
-       void            (*drain_pebs)(struct pt_regs *regs);
-       struct event_constraint *pebs_constraints;
-       void            (*pebs_aliases)(struct perf_event *event);
-       int             max_pebs_events;
-       unsigned long   free_running_flags;
-
-       /*
-        * Intel LBR
-        */
-       unsigned long   lbr_tos, lbr_from, lbr_to; /* MSR base regs       */
-       int             lbr_nr;                    /* hardware stack size */
-       u64             lbr_sel_mask;              /* LBR_SELECT valid bits */
-       const int       *lbr_sel_map;              /* lbr_select mappings */
-       bool            lbr_double_abort;          /* duplicated lbr aborts */
-
-       /*
-        * Intel PT/LBR/BTS are exclusive
-        */
-       atomic_t        lbr_exclusive[x86_lbr_exclusive_max];
-
-       /*
-        * Extra registers for events
-        */
-       struct extra_reg *extra_regs;
-       unsigned int flags;
-
-       /*
-        * Intel host/guest support (KVM)
-        */
-       struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
-};
-
-struct x86_perf_task_context {
-       u64 lbr_from[MAX_LBR_ENTRIES];
-       u64 lbr_to[MAX_LBR_ENTRIES];
-       u64 lbr_info[MAX_LBR_ENTRIES];
-       int tos;
-       int lbr_callstack_users;
-       int lbr_stack_state;
-};
-
-#define x86_add_quirk(func_)                                           \
-do {                                                                   \
-       static struct x86_pmu_quirk __quirk __initdata = {              \
-               .func = func_,                                          \
-       };                                                              \
-       __quirk.next = x86_pmu.quirks;                                  \
-       x86_pmu.quirks = &__quirk;                                      \
-} while (0)
-
-/*
- * x86_pmu flags
- */
-#define PMU_FL_NO_HT_SHARING   0x1 /* no hyper-threading resource sharing */
-#define PMU_FL_HAS_RSP_1       0x2 /* has 2 equivalent offcore_rsp regs   */
-#define PMU_FL_EXCL_CNTRS      0x4 /* has exclusive counter requirements  */
-#define PMU_FL_EXCL_ENABLED    0x8 /* exclusive counter active */
-
-#define EVENT_VAR(_id)  event_attr_##_id
-#define EVENT_PTR(_id) &event_attr_##_id.attr.attr
-
-#define EVENT_ATTR(_name, _id)                                         \
-static struct perf_pmu_events_attr EVENT_VAR(_id) = {                  \
-       .attr           = __ATTR(_name, 0444, events_sysfs_show, NULL), \
-       .id             = PERF_COUNT_HW_##_id,                          \
-       .event_str      = NULL,                                         \
-};
-
-#define EVENT_ATTR_STR(_name, v, str)                                  \
-static struct perf_pmu_events_attr event_attr_##v = {                  \
-       .attr           = __ATTR(_name, 0444, events_sysfs_show, NULL), \
-       .id             = 0,                                            \
-       .event_str      = str,                                          \
-};
-
-extern struct x86_pmu x86_pmu __read_mostly;
-
-static inline bool x86_pmu_has_lbr_callstack(void)
-{
-       return  x86_pmu.lbr_sel_map &&
-               x86_pmu.lbr_sel_map[PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT] > 0;
-}
-
-DECLARE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
-
-int x86_perf_event_set_period(struct perf_event *event);
-
-/*
- * Generalized hw caching related hw_event table, filled
- * in on a per model basis. A value of 0 means
- * 'not supported', -1 means 'hw_event makes no sense on
- * this CPU', any other value means the raw hw_event
- * ID.
- */
-
-#define C(x) PERF_COUNT_HW_CACHE_##x
-
-extern u64 __read_mostly hw_cache_event_ids
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
-extern u64 __read_mostly hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX];
-
-u64 x86_perf_event_update(struct perf_event *event);
-
-static inline unsigned int x86_pmu_config_addr(int index)
-{
-       return x86_pmu.eventsel + (x86_pmu.addr_offset ?
-                                  x86_pmu.addr_offset(index, true) : index);
-}
-
-static inline unsigned int x86_pmu_event_addr(int index)
-{
-       return x86_pmu.perfctr + (x86_pmu.addr_offset ?
-                                 x86_pmu.addr_offset(index, false) : index);
-}
-
-static inline int x86_pmu_rdpmc_index(int index)
-{
-       return x86_pmu.rdpmc_index ? x86_pmu.rdpmc_index(index) : index;
-}
-
-int x86_add_exclusive(unsigned int what);
-
-void x86_del_exclusive(unsigned int what);
-
-int x86_reserve_hardware(void);
-
-void x86_release_hardware(void);
-
-void hw_perf_lbr_event_destroy(struct perf_event *event);
-
-int x86_setup_perfctr(struct perf_event *event);
-
-int x86_pmu_hw_config(struct perf_event *event);
-
-void x86_pmu_disable_all(void);
-
-static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
-                                         u64 enable_mask)
-{
-       u64 disable_mask = __this_cpu_read(cpu_hw_events.perf_ctr_virt_mask);
-
-       if (hwc->extra_reg.reg)
-               wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
-       wrmsrl(hwc->config_base, (hwc->config | enable_mask) & ~disable_mask);
-}
-
-void x86_pmu_enable_all(int added);
-
-int perf_assign_events(struct event_constraint **constraints, int n,
-                       int wmin, int wmax, int gpmax, int *assign);
-int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
-
-void x86_pmu_stop(struct perf_event *event, int flags);
-
-static inline void x86_pmu_disable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       wrmsrl(hwc->config_base, hwc->config);
-}
-
-void x86_pmu_enable_event(struct perf_event *event);
-
-int x86_pmu_handle_irq(struct pt_regs *regs);
-
-extern struct event_constraint emptyconstraint;
-
-extern struct event_constraint unconstrained;
-
-static inline bool kernel_ip(unsigned long ip)
-{
-#ifdef CONFIG_X86_32
-       return ip > PAGE_OFFSET;
-#else
-       return (long)ip < 0;
-#endif
-}
-
-/*
- * Not all PMUs provide the right context information to place the reported IP
- * into full context. Specifically segment registers are typically not
- * supplied.
- *
- * Assuming the address is a linear address (it is for IBS), we fake the CS and
- * vm86 mode using the known zero-based code segment and 'fix up' the registers
- * to reflect this.
- *
- * Intel PEBS/LBR appear to typically provide the effective address, nothing
- * much we can do about that but pray and treat it like a linear address.
- */
-static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip)
-{
-       regs->cs = kernel_ip(ip) ? __KERNEL_CS : __USER_CS;
-       if (regs->flags & X86_VM_MASK)
-               regs->flags ^= (PERF_EFLAGS_VM | X86_VM_MASK);
-       regs->ip = ip;
-}
-
-ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event);
-ssize_t intel_event_sysfs_show(char *page, u64 config);
-
-struct attribute **merge_attr(struct attribute **a, struct attribute **b);
-
-#ifdef CONFIG_CPU_SUP_AMD
-
-int amd_pmu_init(void);
-
-#else /* CONFIG_CPU_SUP_AMD */
-
-static inline int amd_pmu_init(void)
-{
-       return 0;
-}
-
-#endif /* CONFIG_CPU_SUP_AMD */
-
-#ifdef CONFIG_CPU_SUP_INTEL
-
-static inline bool intel_pmu_has_bts(struct perf_event *event)
-{
-       if (event->attr.config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
-           !event->attr.freq && event->hw.sample_period == 1)
-               return true;
-
-       return false;
-}
-
-int intel_pmu_save_and_restart(struct perf_event *event);
-
-struct event_constraint *
-x86_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
-                         struct perf_event *event);
-
-struct intel_shared_regs *allocate_shared_regs(int cpu);
-
-int intel_pmu_init(void);
-
-void init_debug_store_on_cpu(int cpu);
-
-void fini_debug_store_on_cpu(int cpu);
-
-void release_ds_buffers(void);
-
-void reserve_ds_buffers(void);
-
-extern struct event_constraint bts_constraint;
-
-void intel_pmu_enable_bts(u64 config);
-
-void intel_pmu_disable_bts(void);
-
-int intel_pmu_drain_bts_buffer(void);
-
-extern struct event_constraint intel_core2_pebs_event_constraints[];
-
-extern struct event_constraint intel_atom_pebs_event_constraints[];
-
-extern struct event_constraint intel_slm_pebs_event_constraints[];
-
-extern struct event_constraint intel_nehalem_pebs_event_constraints[];
-
-extern struct event_constraint intel_westmere_pebs_event_constraints[];
-
-extern struct event_constraint intel_snb_pebs_event_constraints[];
-
-extern struct event_constraint intel_ivb_pebs_event_constraints[];
-
-extern struct event_constraint intel_hsw_pebs_event_constraints[];
-
-extern struct event_constraint intel_skl_pebs_event_constraints[];
-
-struct event_constraint *intel_pebs_constraints(struct perf_event *event);
-
-void intel_pmu_pebs_enable(struct perf_event *event);
-
-void intel_pmu_pebs_disable(struct perf_event *event);
-
-void intel_pmu_pebs_enable_all(void);
-
-void intel_pmu_pebs_disable_all(void);
-
-void intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in);
-
-void intel_ds_init(void);
-
-void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in);
-
-void intel_pmu_lbr_reset(void);
-
-void intel_pmu_lbr_enable(struct perf_event *event);
-
-void intel_pmu_lbr_disable(struct perf_event *event);
-
-void intel_pmu_lbr_enable_all(bool pmi);
-
-void intel_pmu_lbr_disable_all(void);
-
-void intel_pmu_lbr_read(void);
-
-void intel_pmu_lbr_init_core(void);
-
-void intel_pmu_lbr_init_nhm(void);
-
-void intel_pmu_lbr_init_atom(void);
-
-void intel_pmu_lbr_init_snb(void);
-
-void intel_pmu_lbr_init_hsw(void);
-
-void intel_pmu_lbr_init_skl(void);
-
-void intel_pmu_lbr_init_knl(void);
-
-int intel_pmu_setup_lbr_filter(struct perf_event *event);
-
-void intel_pt_interrupt(void);
-
-int intel_bts_interrupt(void);
-
-void intel_bts_enable_local(void);
-
-void intel_bts_disable_local(void);
-
-int p4_pmu_init(void);
-
-int p6_pmu_init(void);
-
-int knc_pmu_init(void);
-
-ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr,
-                         char *page);
-
-static inline int is_ht_workaround_enabled(void)
-{
-       return !!(x86_pmu.flags & PMU_FL_EXCL_ENABLED);
-}
-
-#else /* CONFIG_CPU_SUP_INTEL */
-
-static inline void reserve_ds_buffers(void)
-{
-}
-
-static inline void release_ds_buffers(void)
-{
-}
-
-static inline int intel_pmu_init(void)
-{
-       return 0;
-}
-
-static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
-{
-       return NULL;
-}
-
-static inline int is_ht_workaround_enabled(void)
-{
-       return 0;
-}
-#endif /* CONFIG_CPU_SUP_INTEL */
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
deleted file mode 100644 (file)
index 5861053..0000000
+++ /dev/null
@@ -1,731 +0,0 @@
-#include <linux/perf_event.h>
-#include <linux/export.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <asm/apicdef.h>
-
-#include "perf_event.h"
-
-static __initconst const u64 amd_hw_cache_event_ids
-                               [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) ] = 0x0040, /* Data Cache Accesses        */
-               [ C(RESULT_MISS)   ] = 0x0141, /* Data Cache Misses          */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0267, /* Data Prefetcher :attempts  */
-               [ C(RESULT_MISS)   ] = 0x0167, /* Data Prefetcher :cancelled */
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction cache fetches  */
-               [ C(RESULT_MISS)   ] = 0x0081, /* Instruction cache misses   */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x014B, /* Prefetch Instructions :Load */
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x037D, /* Requests to L2 Cache :IC+DC */
-               [ C(RESULT_MISS)   ] = 0x037E, /* L2 Cache Misses : IC+DC     */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x017F, /* L2 Fill/Writeback           */
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
-               [ C(RESULT_MISS)   ] = 0x0746, /* L1_DTLB_AND_L2_DLTB_MISS.ALL */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0080, /* Instruction fecthes        */
-               [ C(RESULT_MISS)   ] = 0x0385, /* L1_ITLB_AND_L2_ITLB_MISS.ALL */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c2, /* Retired Branch Instr.      */
-               [ C(RESULT_MISS)   ] = 0x00c3, /* Retired Mispredicted BI    */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0xb8e9, /* CPU Request to Memory, l+r */
-               [ C(RESULT_MISS)   ] = 0x98e9, /* CPU Request to Memory, r   */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
-};
-
-/*
- * AMD Performance Monitor K7 and later.
- */
-static const u64 amd_perfmon_event_map[] =
-{
-  [PERF_COUNT_HW_CPU_CYCLES]                   = 0x0076,
-  [PERF_COUNT_HW_INSTRUCTIONS]                 = 0x00c0,
-  [PERF_COUNT_HW_CACHE_REFERENCES]             = 0x0080,
-  [PERF_COUNT_HW_CACHE_MISSES]                 = 0x0081,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]          = 0x00c2,
-  [PERF_COUNT_HW_BRANCH_MISSES]                        = 0x00c3,
-  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]      = 0x00d0, /* "Decoder empty" event */
-  [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]       = 0x00d1, /* "Dispatch stalls" event */
-};
-
-static u64 amd_pmu_event_map(int hw_event)
-{
-       return amd_perfmon_event_map[hw_event];
-}
-
-/*
- * Previously calculated offsets
- */
-static unsigned int event_offsets[X86_PMC_IDX_MAX] __read_mostly;
-static unsigned int count_offsets[X86_PMC_IDX_MAX] __read_mostly;
-
-/*
- * Legacy CPUs:
- *   4 counters starting at 0xc0010000 each offset by 1
- *
- * CPUs with core performance counter extensions:
- *   6 counters starting at 0xc0010200 each offset by 2
- */
-static inline int amd_pmu_addr_offset(int index, bool eventsel)
-{
-       int offset;
-
-       if (!index)
-               return index;
-
-       if (eventsel)
-               offset = event_offsets[index];
-       else
-               offset = count_offsets[index];
-
-       if (offset)
-               return offset;
-
-       if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
-               offset = index;
-       else
-               offset = index << 1;
-
-       if (eventsel)
-               event_offsets[index] = offset;
-       else
-               count_offsets[index] = offset;
-
-       return offset;
-}
-
-static int amd_core_hw_config(struct perf_event *event)
-{
-       if (event->attr.exclude_host && event->attr.exclude_guest)
-               /*
-                * When HO == GO == 1 the hardware treats that as GO == HO == 0
-                * and will count in both modes. We don't want to count in that
-                * case so we emulate no-counting by setting US = OS = 0.
-                */
-               event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR |
-                                     ARCH_PERFMON_EVENTSEL_OS);
-       else if (event->attr.exclude_host)
-               event->hw.config |= AMD64_EVENTSEL_GUESTONLY;
-       else if (event->attr.exclude_guest)
-               event->hw.config |= AMD64_EVENTSEL_HOSTONLY;
-
-       return 0;
-}
-
-/*
- * AMD64 events are detected based on their event codes.
- */
-static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
-{
-       return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
-}
-
-static inline int amd_is_nb_event(struct hw_perf_event *hwc)
-{
-       return (hwc->config & 0xe0) == 0xe0;
-}
-
-static inline int amd_has_nb(struct cpu_hw_events *cpuc)
-{
-       struct amd_nb *nb = cpuc->amd_nb;
-
-       return nb && nb->nb_id != -1;
-}
-
-static int amd_pmu_hw_config(struct perf_event *event)
-{
-       int ret;
-
-       /* pass precise event sampling to ibs: */
-       if (event->attr.precise_ip && get_ibs_caps())
-               return -ENOENT;
-
-       if (has_branch_stack(event))
-               return -EOPNOTSUPP;
-
-       ret = x86_pmu_hw_config(event);
-       if (ret)
-               return ret;
-
-       if (event->attr.type == PERF_TYPE_RAW)
-               event->hw.config |= event->attr.config & AMD64_RAW_EVENT_MASK;
-
-       return amd_core_hw_config(event);
-}
-
-static void __amd_put_nb_event_constraints(struct cpu_hw_events *cpuc,
-                                          struct perf_event *event)
-{
-       struct amd_nb *nb = cpuc->amd_nb;
-       int i;
-
-       /*
-        * need to scan whole list because event may not have
-        * been assigned during scheduling
-        *
-        * no race condition possible because event can only
-        * be removed on one CPU at a time AND PMU is disabled
-        * when we come here
-        */
-       for (i = 0; i < x86_pmu.num_counters; i++) {
-               if (cmpxchg(nb->owners + i, event, NULL) == event)
-                       break;
-       }
-}
-
- /*
-  * AMD64 NorthBridge events need special treatment because
-  * counter access needs to be synchronized across all cores
-  * of a package. Refer to BKDG section 3.12
-  *
-  * NB events are events measuring L3 cache, Hypertransport
-  * traffic. They are identified by an event code >= 0xe00.
-  * They measure events on the NorthBride which is shared
-  * by all cores on a package. NB events are counted on a
-  * shared set of counters. When a NB event is programmed
-  * in a counter, the data actually comes from a shared
-  * counter. Thus, access to those counters needs to be
-  * synchronized.
-  *
-  * We implement the synchronization such that no two cores
-  * can be measuring NB events using the same counters. Thus,
-  * we maintain a per-NB allocation table. The available slot
-  * is propagated using the event_constraint structure.
-  *
-  * We provide only one choice for each NB event based on
-  * the fact that only NB events have restrictions. Consequently,
-  * if a counter is available, there is a guarantee the NB event
-  * will be assigned to it. If no slot is available, an empty
-  * constraint is returned and scheduling will eventually fail
-  * for this event.
-  *
-  * Note that all cores attached the same NB compete for the same
-  * counters to host NB events, this is why we use atomic ops. Some
-  * multi-chip CPUs may have more than one NB.
-  *
-  * Given that resources are allocated (cmpxchg), they must be
-  * eventually freed for others to use. This is accomplished by
-  * calling __amd_put_nb_event_constraints()
-  *
-  * Non NB events are not impacted by this restriction.
-  */
-static struct event_constraint *
-__amd_get_nb_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
-                              struct event_constraint *c)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct amd_nb *nb = cpuc->amd_nb;
-       struct perf_event *old;
-       int idx, new = -1;
-
-       if (!c)
-               c = &unconstrained;
-
-       if (cpuc->is_fake)
-               return c;
-
-       /*
-        * detect if already present, if so reuse
-        *
-        * cannot merge with actual allocation
-        * because of possible holes
-        *
-        * event can already be present yet not assigned (in hwc->idx)
-        * because of successive calls to x86_schedule_events() from
-        * hw_perf_group_sched_in() without hw_perf_enable()
-        */
-       for_each_set_bit(idx, c->idxmsk, x86_pmu.num_counters) {
-               if (new == -1 || hwc->idx == idx)
-                       /* assign free slot, prefer hwc->idx */
-                       old = cmpxchg(nb->owners + idx, NULL, event);
-               else if (nb->owners[idx] == event)
-                       /* event already present */
-                       old = event;
-               else
-                       continue;
-
-               if (old && old != event)
-                       continue;
-
-               /* reassign to this slot */
-               if (new != -1)
-                       cmpxchg(nb->owners + new, event, NULL);
-               new = idx;
-
-               /* already present, reuse */
-               if (old == event)
-                       break;
-       }
-
-       if (new == -1)
-               return &emptyconstraint;
-
-       return &nb->event_constraints[new];
-}
-
-static struct amd_nb *amd_alloc_nb(int cpu)
-{
-       struct amd_nb *nb;
-       int i;
-
-       nb = kzalloc_node(sizeof(struct amd_nb), GFP_KERNEL, cpu_to_node(cpu));
-       if (!nb)
-               return NULL;
-
-       nb->nb_id = -1;
-
-       /*
-        * initialize all possible NB constraints
-        */
-       for (i = 0; i < x86_pmu.num_counters; i++) {
-               __set_bit(i, nb->event_constraints[i].idxmsk);
-               nb->event_constraints[i].weight = 1;
-       }
-       return nb;
-}
-
-static int amd_pmu_cpu_prepare(int cpu)
-{
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-
-       WARN_ON_ONCE(cpuc->amd_nb);
-
-       if (boot_cpu_data.x86_max_cores < 2)
-               return NOTIFY_OK;
-
-       cpuc->amd_nb = amd_alloc_nb(cpu);
-       if (!cpuc->amd_nb)
-               return NOTIFY_BAD;
-
-       return NOTIFY_OK;
-}
-
-static void amd_pmu_cpu_starting(int cpu)
-{
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-       void **onln = &cpuc->kfree_on_online[X86_PERF_KFREE_SHARED];
-       struct amd_nb *nb;
-       int i, nb_id;
-
-       cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY;
-
-       if (boot_cpu_data.x86_max_cores < 2)
-               return;
-
-       nb_id = amd_get_nb_id(cpu);
-       WARN_ON_ONCE(nb_id == BAD_APICID);
-
-       for_each_online_cpu(i) {
-               nb = per_cpu(cpu_hw_events, i).amd_nb;
-               if (WARN_ON_ONCE(!nb))
-                       continue;
-
-               if (nb->nb_id == nb_id) {
-                       *onln = cpuc->amd_nb;
-                       cpuc->amd_nb = nb;
-                       break;
-               }
-       }
-
-       cpuc->amd_nb->nb_id = nb_id;
-       cpuc->amd_nb->refcnt++;
-}
-
-static void amd_pmu_cpu_dead(int cpu)
-{
-       struct cpu_hw_events *cpuhw;
-
-       if (boot_cpu_data.x86_max_cores < 2)
-               return;
-
-       cpuhw = &per_cpu(cpu_hw_events, cpu);
-
-       if (cpuhw->amd_nb) {
-               struct amd_nb *nb = cpuhw->amd_nb;
-
-               if (nb->nb_id == -1 || --nb->refcnt == 0)
-                       kfree(nb);
-
-               cpuhw->amd_nb = NULL;
-       }
-}
-
-static struct event_constraint *
-amd_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
-                         struct perf_event *event)
-{
-       /*
-        * if not NB event or no NB, then no constraints
-        */
-       if (!(amd_has_nb(cpuc) && amd_is_nb_event(&event->hw)))
-               return &unconstrained;
-
-       return __amd_get_nb_event_constraints(cpuc, event, NULL);
-}
-
-static void amd_put_event_constraints(struct cpu_hw_events *cpuc,
-                                     struct perf_event *event)
-{
-       if (amd_has_nb(cpuc) && amd_is_nb_event(&event->hw))
-               __amd_put_nb_event_constraints(cpuc, event);
-}
-
-PMU_FORMAT_ATTR(event, "config:0-7,32-35");
-PMU_FORMAT_ATTR(umask, "config:8-15"   );
-PMU_FORMAT_ATTR(edge,  "config:18"     );
-PMU_FORMAT_ATTR(inv,   "config:23"     );
-PMU_FORMAT_ATTR(cmask, "config:24-31"  );
-
-static struct attribute *amd_format_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_cmask.attr,
-       NULL,
-};
-
-/* AMD Family 15h */
-
-#define AMD_EVENT_TYPE_MASK    0x000000F0ULL
-
-#define AMD_EVENT_FP           0x00000000ULL ... 0x00000010ULL
-#define AMD_EVENT_LS           0x00000020ULL ... 0x00000030ULL
-#define AMD_EVENT_DC           0x00000040ULL ... 0x00000050ULL
-#define AMD_EVENT_CU           0x00000060ULL ... 0x00000070ULL
-#define AMD_EVENT_IC_DE                0x00000080ULL ... 0x00000090ULL
-#define AMD_EVENT_EX_LS                0x000000C0ULL
-#define AMD_EVENT_DE           0x000000D0ULL
-#define AMD_EVENT_NB           0x000000E0ULL ... 0x000000F0ULL
-
-/*
- * AMD family 15h event code/PMC mappings:
- *
- * type = event_code & 0x0F0:
- *
- * 0x000       FP      PERF_CTL[5:3]
- * 0x010       FP      PERF_CTL[5:3]
- * 0x020       LS      PERF_CTL[5:0]
- * 0x030       LS      PERF_CTL[5:0]
- * 0x040       DC      PERF_CTL[5:0]
- * 0x050       DC      PERF_CTL[5:0]
- * 0x060       CU      PERF_CTL[2:0]
- * 0x070       CU      PERF_CTL[2:0]
- * 0x080       IC/DE   PERF_CTL[2:0]
- * 0x090       IC/DE   PERF_CTL[2:0]
- * 0x0A0       ---
- * 0x0B0       ---
- * 0x0C0       EX/LS   PERF_CTL[5:0]
- * 0x0D0       DE      PERF_CTL[2:0]
- * 0x0E0       NB      NB_PERF_CTL[3:0]
- * 0x0F0       NB      NB_PERF_CTL[3:0]
- *
- * Exceptions:
- *
- * 0x000       FP      PERF_CTL[3], PERF_CTL[5:3] (*)
- * 0x003       FP      PERF_CTL[3]
- * 0x004       FP      PERF_CTL[3], PERF_CTL[5:3] (*)
- * 0x00B       FP      PERF_CTL[3]
- * 0x00D       FP      PERF_CTL[3]
- * 0x023       DE      PERF_CTL[2:0]
- * 0x02D       LS      PERF_CTL[3]
- * 0x02E       LS      PERF_CTL[3,0]
- * 0x031       LS      PERF_CTL[2:0] (**)
- * 0x043       CU      PERF_CTL[2:0]
- * 0x045       CU      PERF_CTL[2:0]
- * 0x046       CU      PERF_CTL[2:0]
- * 0x054       CU      PERF_CTL[2:0]
- * 0x055       CU      PERF_CTL[2:0]
- * 0x08F       IC      PERF_CTL[0]
- * 0x187       DE      PERF_CTL[0]
- * 0x188       DE      PERF_CTL[0]
- * 0x0DB       EX      PERF_CTL[5:0]
- * 0x0DC       LS      PERF_CTL[5:0]
- * 0x0DD       LS      PERF_CTL[5:0]
- * 0x0DE       LS      PERF_CTL[5:0]
- * 0x0DF       LS      PERF_CTL[5:0]
- * 0x1C0       EX      PERF_CTL[5:3]
- * 0x1D6       EX      PERF_CTL[5:0]
- * 0x1D8       EX      PERF_CTL[5:0]
- *
- * (*)  depending on the umask all FPU counters may be used
- * (**) only one unitmask enabled at a time
- */
-
-static struct event_constraint amd_f15_PMC0  = EVENT_CONSTRAINT(0, 0x01, 0);
-static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0);
-static struct event_constraint amd_f15_PMC3  = EVENT_CONSTRAINT(0, 0x08, 0);
-static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT_OVERLAP(0, 0x09, 0);
-static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
-static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
-
-static struct event_constraint *
-amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, int idx,
-                              struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       unsigned int event_code = amd_get_event_code(hwc);
-
-       switch (event_code & AMD_EVENT_TYPE_MASK) {
-       case AMD_EVENT_FP:
-               switch (event_code) {
-               case 0x000:
-                       if (!(hwc->config & 0x0000F000ULL))
-                               break;
-                       if (!(hwc->config & 0x00000F00ULL))
-                               break;
-                       return &amd_f15_PMC3;
-               case 0x004:
-                       if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
-                               break;
-                       return &amd_f15_PMC3;
-               case 0x003:
-               case 0x00B:
-               case 0x00D:
-                       return &amd_f15_PMC3;
-               }
-               return &amd_f15_PMC53;
-       case AMD_EVENT_LS:
-       case AMD_EVENT_DC:
-       case AMD_EVENT_EX_LS:
-               switch (event_code) {
-               case 0x023:
-               case 0x043:
-               case 0x045:
-               case 0x046:
-               case 0x054:
-               case 0x055:
-                       return &amd_f15_PMC20;
-               case 0x02D:
-                       return &amd_f15_PMC3;
-               case 0x02E:
-                       return &amd_f15_PMC30;
-               case 0x031:
-                       if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
-                               return &amd_f15_PMC20;
-                       return &emptyconstraint;
-               case 0x1C0:
-                       return &amd_f15_PMC53;
-               default:
-                       return &amd_f15_PMC50;
-               }
-       case AMD_EVENT_CU:
-       case AMD_EVENT_IC_DE:
-       case AMD_EVENT_DE:
-               switch (event_code) {
-               case 0x08F:
-               case 0x187:
-               case 0x188:
-                       return &amd_f15_PMC0;
-               case 0x0DB ... 0x0DF:
-               case 0x1D6:
-               case 0x1D8:
-                       return &amd_f15_PMC50;
-               default:
-                       return &amd_f15_PMC20;
-               }
-       case AMD_EVENT_NB:
-               /* moved to perf_event_amd_uncore.c */
-               return &emptyconstraint;
-       default:
-               return &emptyconstraint;
-       }
-}
-
-static ssize_t amd_event_sysfs_show(char *page, u64 config)
-{
-       u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
-                   (config & AMD64_EVENTSEL_EVENT) >> 24;
-
-       return x86_event_sysfs_show(page, config, event);
-}
-
-static __initconst const struct x86_pmu amd_pmu = {
-       .name                   = "AMD",
-       .handle_irq             = x86_pmu_handle_irq,
-       .disable_all            = x86_pmu_disable_all,
-       .enable_all             = x86_pmu_enable_all,
-       .enable                 = x86_pmu_enable_event,
-       .disable                = x86_pmu_disable_event,
-       .hw_config              = amd_pmu_hw_config,
-       .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_K7_EVNTSEL0,
-       .perfctr                = MSR_K7_PERFCTR0,
-       .addr_offset            = amd_pmu_addr_offset,
-       .event_map              = amd_pmu_event_map,
-       .max_events             = ARRAY_SIZE(amd_perfmon_event_map),
-       .num_counters           = AMD64_NUM_COUNTERS,
-       .cntval_bits            = 48,
-       .cntval_mask            = (1ULL << 48) - 1,
-       .apic                   = 1,
-       /* use highest bit to detect overflow */
-       .max_period             = (1ULL << 47) - 1,
-       .get_event_constraints  = amd_get_event_constraints,
-       .put_event_constraints  = amd_put_event_constraints,
-
-       .format_attrs           = amd_format_attr,
-       .events_sysfs_show      = amd_event_sysfs_show,
-
-       .cpu_prepare            = amd_pmu_cpu_prepare,
-       .cpu_starting           = amd_pmu_cpu_starting,
-       .cpu_dead               = amd_pmu_cpu_dead,
-};
-
-static int __init amd_core_pmu_init(void)
-{
-       if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
-               return 0;
-
-       switch (boot_cpu_data.x86) {
-       case 0x15:
-               pr_cont("Fam15h ");
-               x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
-               break;
-
-       default:
-               pr_err("core perfctr but no constraints; unknown hardware!\n");
-               return -ENODEV;
-       }
-
-       /*
-        * If core performance counter extensions exists, we must use
-        * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
-        * amd_pmu_addr_offset().
-        */
-       x86_pmu.eventsel        = MSR_F15H_PERF_CTL;
-       x86_pmu.perfctr         = MSR_F15H_PERF_CTR;
-       x86_pmu.num_counters    = AMD64_NUM_COUNTERS_CORE;
-
-       pr_cont("core perfctr, ");
-       return 0;
-}
-
-__init int amd_pmu_init(void)
-{
-       int ret;
-
-       /* Performance-monitoring supported from K7 and later: */
-       if (boot_cpu_data.x86 < 6)
-               return -ENODEV;
-
-       x86_pmu = amd_pmu;
-
-       ret = amd_core_pmu_init();
-       if (ret)
-               return ret;
-
-       /* Events are common for all AMDs */
-       memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
-              sizeof(hw_cache_event_ids));
-
-       return 0;
-}
-
-void amd_pmu_enable_virt(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       cpuc->perf_ctr_virt_mask = 0;
-
-       /* Reload all events */
-       x86_pmu_disable_all();
-       x86_pmu_enable_all(0);
-}
-EXPORT_SYMBOL_GPL(amd_pmu_enable_virt);
-
-void amd_pmu_disable_virt(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       /*
-        * We only mask out the Host-only bit so that host-only counting works
-        * when SVM is disabled. If someone sets up a guest-only counter when
-        * SVM is disabled the Guest-only bits still gets set and the counter
-        * will not count anything.
-        */
-       cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY;
-
-       /* Reload all events */
-       x86_pmu_disable_all();
-       x86_pmu_enable_all(0);
-}
-EXPORT_SYMBOL_GPL(amd_pmu_disable_virt);
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
deleted file mode 100644 (file)
index 989d3c2..0000000
+++ /dev/null
@@ -1,959 +0,0 @@
-/*
- * Performance events - AMD IBS
- *
- *  Copyright (C) 2011 Advanced Micro Devices, Inc., Robert Richter
- *
- *  For licencing details see kernel-base/COPYING
- */
-
-#include <linux/perf_event.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ptrace.h>
-#include <linux/syscore_ops.h>
-
-#include <asm/apic.h>
-
-#include "perf_event.h"
-
-static u32 ibs_caps;
-
-#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
-
-#include <linux/kprobes.h>
-#include <linux/hardirq.h>
-
-#include <asm/nmi.h>
-
-#define IBS_FETCH_CONFIG_MASK  (IBS_FETCH_RAND_EN | IBS_FETCH_MAX_CNT)
-#define IBS_OP_CONFIG_MASK     IBS_OP_MAX_CNT
-
-enum ibs_states {
-       IBS_ENABLED     = 0,
-       IBS_STARTED     = 1,
-       IBS_STOPPING    = 2,
-
-       IBS_MAX_STATES,
-};
-
-struct cpu_perf_ibs {
-       struct perf_event       *event;
-       unsigned long           state[BITS_TO_LONGS(IBS_MAX_STATES)];
-};
-
-struct perf_ibs {
-       struct pmu                      pmu;
-       unsigned int                    msr;
-       u64                             config_mask;
-       u64                             cnt_mask;
-       u64                             enable_mask;
-       u64                             valid_mask;
-       u64                             max_period;
-       unsigned long                   offset_mask[1];
-       int                             offset_max;
-       struct cpu_perf_ibs __percpu    *pcpu;
-
-       struct attribute                **format_attrs;
-       struct attribute_group          format_group;
-       const struct attribute_group    *attr_groups[2];
-
-       u64                             (*get_count)(u64 config);
-};
-
-struct perf_ibs_data {
-       u32             size;
-       union {
-               u32     data[0];        /* data buffer starts here */
-               u32     caps;
-       };
-       u64             regs[MSR_AMD64_IBS_REG_COUNT_MAX];
-};
-
-static int
-perf_event_set_period(struct hw_perf_event *hwc, u64 min, u64 max, u64 *hw_period)
-{
-       s64 left = local64_read(&hwc->period_left);
-       s64 period = hwc->sample_period;
-       int overflow = 0;
-
-       /*
-        * If we are way outside a reasonable range then just skip forward:
-        */
-       if (unlikely(left <= -period)) {
-               left = period;
-               local64_set(&hwc->period_left, left);
-               hwc->last_period = period;
-               overflow = 1;
-       }
-
-       if (unlikely(left < (s64)min)) {
-               left += period;
-               local64_set(&hwc->period_left, left);
-               hwc->last_period = period;
-               overflow = 1;
-       }
-
-       /*
-        * If the hw period that triggers the sw overflow is too short
-        * we might hit the irq handler. This biases the results.
-        * Thus we shorten the next-to-last period and set the last
-        * period to the max period.
-        */
-       if (left > max) {
-               left -= max;
-               if (left > max)
-                       left = max;
-               else if (left < min)
-                       left = min;
-       }
-
-       *hw_period = (u64)left;
-
-       return overflow;
-}
-
-static  int
-perf_event_try_update(struct perf_event *event, u64 new_raw_count, int width)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       int shift = 64 - width;
-       u64 prev_raw_count;
-       u64 delta;
-
-       /*
-        * Careful: an NMI might modify the previous event value.
-        *
-        * Our tactic to handle this is to first atomically read and
-        * exchange a new raw count - then add that new-prev delta
-        * count to the generic event atomically:
-        */
-       prev_raw_count = local64_read(&hwc->prev_count);
-       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-                                       new_raw_count) != prev_raw_count)
-               return 0;
-
-       /*
-        * Now we have the new raw value and have updated the prev
-        * timestamp already. We can now calculate the elapsed delta
-        * (event-)time and add that to the generic event.
-        *
-        * Careful, not all hw sign-extends above the physical width
-        * of the count.
-        */
-       delta = (new_raw_count << shift) - (prev_raw_count << shift);
-       delta >>= shift;
-
-       local64_add(delta, &event->count);
-       local64_sub(delta, &hwc->period_left);
-
-       return 1;
-}
-
-static struct perf_ibs perf_ibs_fetch;
-static struct perf_ibs perf_ibs_op;
-
-static struct perf_ibs *get_ibs_pmu(int type)
-{
-       if (perf_ibs_fetch.pmu.type == type)
-               return &perf_ibs_fetch;
-       if (perf_ibs_op.pmu.type == type)
-               return &perf_ibs_op;
-       return NULL;
-}
-
-/*
- * Use IBS for precise event sampling:
- *
- *  perf record -a -e cpu-cycles:p ...    # use ibs op counting cycle count
- *  perf record -a -e r076:p ...          # same as -e cpu-cycles:p
- *  perf record -a -e r0C1:p ...          # use ibs op counting micro-ops
- *
- * IbsOpCntCtl (bit 19) of IBS Execution Control Register (IbsOpCtl,
- * MSRC001_1033) is used to select either cycle or micro-ops counting
- * mode.
- *
- * The rip of IBS samples has skid 0. Thus, IBS supports precise
- * levels 1 and 2 and the PERF_EFLAGS_EXACT is set. In rare cases the
- * rip is invalid when IBS was not able to record the rip correctly.
- * We clear PERF_EFLAGS_EXACT and take the rip from pt_regs then.
- *
- */
-static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
-{
-       switch (event->attr.precise_ip) {
-       case 0:
-               return -ENOENT;
-       case 1:
-       case 2:
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       switch (event->attr.type) {
-       case PERF_TYPE_HARDWARE:
-               switch (event->attr.config) {
-               case PERF_COUNT_HW_CPU_CYCLES:
-                       *config = 0;
-                       return 0;
-               }
-               break;
-       case PERF_TYPE_RAW:
-               switch (event->attr.config) {
-               case 0x0076:
-                       *config = 0;
-                       return 0;
-               case 0x00C1:
-                       *config = IBS_OP_CNT_CTL;
-                       return 0;
-               }
-               break;
-       default:
-               return -ENOENT;
-       }
-
-       return -EOPNOTSUPP;
-}
-
-static const struct perf_event_attr ibs_notsupp = {
-       .exclude_user   = 1,
-       .exclude_kernel = 1,
-       .exclude_hv     = 1,
-       .exclude_idle   = 1,
-       .exclude_host   = 1,
-       .exclude_guest  = 1,
-};
-
-static int perf_ibs_init(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct perf_ibs *perf_ibs;
-       u64 max_cnt, config;
-       int ret;
-
-       perf_ibs = get_ibs_pmu(event->attr.type);
-       if (perf_ibs) {
-               config = event->attr.config;
-       } else {
-               perf_ibs = &perf_ibs_op;
-               ret = perf_ibs_precise_event(event, &config);
-               if (ret)
-                       return ret;
-       }
-
-       if (event->pmu != &perf_ibs->pmu)
-               return -ENOENT;
-
-       if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp))
-               return -EINVAL;
-
-       if (config & ~perf_ibs->config_mask)
-               return -EINVAL;
-
-       if (hwc->sample_period) {
-               if (config & perf_ibs->cnt_mask)
-                       /* raw max_cnt may not be set */
-                       return -EINVAL;
-               if (!event->attr.sample_freq && hwc->sample_period & 0x0f)
-                       /*
-                        * lower 4 bits can not be set in ibs max cnt,
-                        * but allowing it in case we adjust the
-                        * sample period to set a frequency.
-                        */
-                       return -EINVAL;
-               hwc->sample_period &= ~0x0FULL;
-               if (!hwc->sample_period)
-                       hwc->sample_period = 0x10;
-       } else {
-               max_cnt = config & perf_ibs->cnt_mask;
-               config &= ~perf_ibs->cnt_mask;
-               event->attr.sample_period = max_cnt << 4;
-               hwc->sample_period = event->attr.sample_period;
-       }
-
-       if (!hwc->sample_period)
-               return -EINVAL;
-
-       /*
-        * If we modify hwc->sample_period, we also need to update
-        * hwc->last_period and hwc->period_left.
-        */
-       hwc->last_period = hwc->sample_period;
-       local64_set(&hwc->period_left, hwc->sample_period);
-
-       hwc->config_base = perf_ibs->msr;
-       hwc->config = config;
-
-       return 0;
-}
-
-static int perf_ibs_set_period(struct perf_ibs *perf_ibs,
-                              struct hw_perf_event *hwc, u64 *period)
-{
-       int overflow;
-
-       /* ignore lower 4 bits in min count: */
-       overflow = perf_event_set_period(hwc, 1<<4, perf_ibs->max_period, period);
-       local64_set(&hwc->prev_count, 0);
-
-       return overflow;
-}
-
-static u64 get_ibs_fetch_count(u64 config)
-{
-       return (config & IBS_FETCH_CNT) >> 12;
-}
-
-static u64 get_ibs_op_count(u64 config)
-{
-       u64 count = 0;
-
-       if (config & IBS_OP_VAL)
-               count += (config & IBS_OP_MAX_CNT) << 4; /* cnt rolled over */
-
-       if (ibs_caps & IBS_CAPS_RDWROPCNT)
-               count += (config & IBS_OP_CUR_CNT) >> 32;
-
-       return count;
-}
-
-static void
-perf_ibs_event_update(struct perf_ibs *perf_ibs, struct perf_event *event,
-                     u64 *config)
-{
-       u64 count = perf_ibs->get_count(*config);
-
-       /*
-        * Set width to 64 since we do not overflow on max width but
-        * instead on max count. In perf_ibs_set_period() we clear
-        * prev count manually on overflow.
-        */
-       while (!perf_event_try_update(event, count, 64)) {
-               rdmsrl(event->hw.config_base, *config);
-               count = perf_ibs->get_count(*config);
-       }
-}
-
-static inline void perf_ibs_enable_event(struct perf_ibs *perf_ibs,
-                                        struct hw_perf_event *hwc, u64 config)
-{
-       wrmsrl(hwc->config_base, hwc->config | config | perf_ibs->enable_mask);
-}
-
-/*
- * Erratum #420 Instruction-Based Sampling Engine May Generate
- * Interrupt that Cannot Be Cleared:
- *
- * Must clear counter mask first, then clear the enable bit. See
- * Revision Guide for AMD Family 10h Processors, Publication #41322.
- */
-static inline void perf_ibs_disable_event(struct perf_ibs *perf_ibs,
-                                         struct hw_perf_event *hwc, u64 config)
-{
-       config &= ~perf_ibs->cnt_mask;
-       wrmsrl(hwc->config_base, config);
-       config &= ~perf_ibs->enable_mask;
-       wrmsrl(hwc->config_base, config);
-}
-
-/*
- * We cannot restore the ibs pmu state, so we always needs to update
- * the event while stopping it and then reset the state when starting
- * again. Thus, ignoring PERF_EF_RELOAD and PERF_EF_UPDATE flags in
- * perf_ibs_start()/perf_ibs_stop() and instead always do it.
- */
-static void perf_ibs_start(struct perf_event *event, int flags)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
-       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
-       u64 period;
-
-       if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
-               return;
-
-       WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
-       hwc->state = 0;
-
-       perf_ibs_set_period(perf_ibs, hwc, &period);
-       set_bit(IBS_STARTED, pcpu->state);
-       perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
-
-       perf_event_update_userpage(event);
-}
-
-static void perf_ibs_stop(struct perf_event *event, int flags)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
-       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
-       u64 config;
-       int stopping;
-
-       stopping = test_and_clear_bit(IBS_STARTED, pcpu->state);
-
-       if (!stopping && (hwc->state & PERF_HES_UPTODATE))
-               return;
-
-       rdmsrl(hwc->config_base, config);
-
-       if (stopping) {
-               set_bit(IBS_STOPPING, pcpu->state);
-               perf_ibs_disable_event(perf_ibs, hwc, config);
-               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
-               hwc->state |= PERF_HES_STOPPED;
-       }
-
-       if (hwc->state & PERF_HES_UPTODATE)
-               return;
-
-       /*
-        * Clear valid bit to not count rollovers on update, rollovers
-        * are only updated in the irq handler.
-        */
-       config &= ~perf_ibs->valid_mask;
-
-       perf_ibs_event_update(perf_ibs, event, &config);
-       hwc->state |= PERF_HES_UPTODATE;
-}
-
-static int perf_ibs_add(struct perf_event *event, int flags)
-{
-       struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
-       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
-
-       if (test_and_set_bit(IBS_ENABLED, pcpu->state))
-               return -ENOSPC;
-
-       event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
-
-       pcpu->event = event;
-
-       if (flags & PERF_EF_START)
-               perf_ibs_start(event, PERF_EF_RELOAD);
-
-       return 0;
-}
-
-static void perf_ibs_del(struct perf_event *event, int flags)
-{
-       struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
-       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
-
-       if (!test_and_clear_bit(IBS_ENABLED, pcpu->state))
-               return;
-
-       perf_ibs_stop(event, PERF_EF_UPDATE);
-
-       pcpu->event = NULL;
-
-       perf_event_update_userpage(event);
-}
-
-static void perf_ibs_read(struct perf_event *event) { }
-
-PMU_FORMAT_ATTR(rand_en,       "config:57");
-PMU_FORMAT_ATTR(cnt_ctl,       "config:19");
-
-static struct attribute *ibs_fetch_format_attrs[] = {
-       &format_attr_rand_en.attr,
-       NULL,
-};
-
-static struct attribute *ibs_op_format_attrs[] = {
-       NULL,   /* &format_attr_cnt_ctl.attr if IBS_CAPS_OPCNT */
-       NULL,
-};
-
-static struct perf_ibs perf_ibs_fetch = {
-       .pmu = {
-               .task_ctx_nr    = perf_invalid_context,
-
-               .event_init     = perf_ibs_init,
-               .add            = perf_ibs_add,
-               .del            = perf_ibs_del,
-               .start          = perf_ibs_start,
-               .stop           = perf_ibs_stop,
-               .read           = perf_ibs_read,
-       },
-       .msr                    = MSR_AMD64_IBSFETCHCTL,
-       .config_mask            = IBS_FETCH_CONFIG_MASK,
-       .cnt_mask               = IBS_FETCH_MAX_CNT,
-       .enable_mask            = IBS_FETCH_ENABLE,
-       .valid_mask             = IBS_FETCH_VAL,
-       .max_period             = IBS_FETCH_MAX_CNT << 4,
-       .offset_mask            = { MSR_AMD64_IBSFETCH_REG_MASK },
-       .offset_max             = MSR_AMD64_IBSFETCH_REG_COUNT,
-       .format_attrs           = ibs_fetch_format_attrs,
-
-       .get_count              = get_ibs_fetch_count,
-};
-
-static struct perf_ibs perf_ibs_op = {
-       .pmu = {
-               .task_ctx_nr    = perf_invalid_context,
-
-               .event_init     = perf_ibs_init,
-               .add            = perf_ibs_add,
-               .del            = perf_ibs_del,
-               .start          = perf_ibs_start,
-               .stop           = perf_ibs_stop,
-               .read           = perf_ibs_read,
-       },
-       .msr                    = MSR_AMD64_IBSOPCTL,
-       .config_mask            = IBS_OP_CONFIG_MASK,
-       .cnt_mask               = IBS_OP_MAX_CNT,
-       .enable_mask            = IBS_OP_ENABLE,
-       .valid_mask             = IBS_OP_VAL,
-       .max_period             = IBS_OP_MAX_CNT << 4,
-       .offset_mask            = { MSR_AMD64_IBSOP_REG_MASK },
-       .offset_max             = MSR_AMD64_IBSOP_REG_COUNT,
-       .format_attrs           = ibs_op_format_attrs,
-
-       .get_count              = get_ibs_op_count,
-};
-
-static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
-{
-       struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
-       struct perf_event *event = pcpu->event;
-       struct hw_perf_event *hwc = &event->hw;
-       struct perf_sample_data data;
-       struct perf_raw_record raw;
-       struct pt_regs regs;
-       struct perf_ibs_data ibs_data;
-       int offset, size, check_rip, offset_max, throttle = 0;
-       unsigned int msr;
-       u64 *buf, *config, period;
-
-       if (!test_bit(IBS_STARTED, pcpu->state)) {
-               /*
-                * Catch spurious interrupts after stopping IBS: After
-                * disabling IBS there could be still incoming NMIs
-                * with samples that even have the valid bit cleared.
-                * Mark all this NMIs as handled.
-                */
-               return test_and_clear_bit(IBS_STOPPING, pcpu->state) ? 1 : 0;
-       }
-
-       msr = hwc->config_base;
-       buf = ibs_data.regs;
-       rdmsrl(msr, *buf);
-       if (!(*buf++ & perf_ibs->valid_mask))
-               return 0;
-
-       config = &ibs_data.regs[0];
-       perf_ibs_event_update(perf_ibs, event, config);
-       perf_sample_data_init(&data, 0, hwc->last_period);
-       if (!perf_ibs_set_period(perf_ibs, hwc, &period))
-               goto out;       /* no sw counter overflow */
-
-       ibs_data.caps = ibs_caps;
-       size = 1;
-       offset = 1;
-       check_rip = (perf_ibs == &perf_ibs_op && (ibs_caps & IBS_CAPS_RIPINVALIDCHK));
-       if (event->attr.sample_type & PERF_SAMPLE_RAW)
-               offset_max = perf_ibs->offset_max;
-       else if (check_rip)
-               offset_max = 2;
-       else
-               offset_max = 1;
-       do {
-               rdmsrl(msr + offset, *buf++);
-               size++;
-               offset = find_next_bit(perf_ibs->offset_mask,
-                                      perf_ibs->offset_max,
-                                      offset + 1);
-       } while (offset < offset_max);
-       if (event->attr.sample_type & PERF_SAMPLE_RAW) {
-               /*
-                * Read IbsBrTarget and IbsOpData4 separately
-                * depending on their availability.
-                * Can't add to offset_max as they are staggered
-                */
-               if (ibs_caps & IBS_CAPS_BRNTRGT) {
-                       rdmsrl(MSR_AMD64_IBSBRTARGET, *buf++);
-                       size++;
-               }
-               if (ibs_caps & IBS_CAPS_OPDATA4) {
-                       rdmsrl(MSR_AMD64_IBSOPDATA4, *buf++);
-                       size++;
-               }
-       }
-       ibs_data.size = sizeof(u64) * size;
-
-       regs = *iregs;
-       if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) {
-               regs.flags &= ~PERF_EFLAGS_EXACT;
-       } else {
-               set_linear_ip(&regs, ibs_data.regs[1]);
-               regs.flags |= PERF_EFLAGS_EXACT;
-       }
-
-       if (event->attr.sample_type & PERF_SAMPLE_RAW) {
-               raw.size = sizeof(u32) + ibs_data.size;
-               raw.data = ibs_data.data;
-               data.raw = &raw;
-       }
-
-       throttle = perf_event_overflow(event, &data, &regs);
-out:
-       if (throttle)
-               perf_ibs_disable_event(perf_ibs, hwc, *config);
-       else
-               perf_ibs_enable_event(perf_ibs, hwc, period >> 4);
-
-       perf_event_update_userpage(event);
-
-       return 1;
-}
-
-static int
-perf_ibs_nmi_handler(unsigned int cmd, struct pt_regs *regs)
-{
-       int handled = 0;
-
-       handled += perf_ibs_handle_irq(&perf_ibs_fetch, regs);
-       handled += perf_ibs_handle_irq(&perf_ibs_op, regs);
-
-       if (handled)
-               inc_irq_stat(apic_perf_irqs);
-
-       return handled;
-}
-NOKPROBE_SYMBOL(perf_ibs_nmi_handler);
-
-static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name)
-{
-       struct cpu_perf_ibs __percpu *pcpu;
-       int ret;
-
-       pcpu = alloc_percpu(struct cpu_perf_ibs);
-       if (!pcpu)
-               return -ENOMEM;
-
-       perf_ibs->pcpu = pcpu;
-
-       /* register attributes */
-       if (perf_ibs->format_attrs[0]) {
-               memset(&perf_ibs->format_group, 0, sizeof(perf_ibs->format_group));
-               perf_ibs->format_group.name     = "format";
-               perf_ibs->format_group.attrs    = perf_ibs->format_attrs;
-
-               memset(&perf_ibs->attr_groups, 0, sizeof(perf_ibs->attr_groups));
-               perf_ibs->attr_groups[0]        = &perf_ibs->format_group;
-               perf_ibs->pmu.attr_groups       = perf_ibs->attr_groups;
-       }
-
-       ret = perf_pmu_register(&perf_ibs->pmu, name, -1);
-       if (ret) {
-               perf_ibs->pcpu = NULL;
-               free_percpu(pcpu);
-       }
-
-       return ret;
-}
-
-static __init int perf_event_ibs_init(void)
-{
-       struct attribute **attr = ibs_op_format_attrs;
-
-       if (!ibs_caps)
-               return -ENODEV; /* ibs not supported by the cpu */
-
-       perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
-
-       if (ibs_caps & IBS_CAPS_OPCNT) {
-               perf_ibs_op.config_mask |= IBS_OP_CNT_CTL;
-               *attr++ = &format_attr_cnt_ctl.attr;
-       }
-       perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");
-
-       register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs");
-       printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps);
-
-       return 0;
-}
-
-#else /* defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) */
-
-static __init int perf_event_ibs_init(void) { return 0; }
-
-#endif
-
-/* IBS - apic initialization, for perf and oprofile */
-
-static __init u32 __get_ibs_caps(void)
-{
-       u32 caps;
-       unsigned int max_level;
-
-       if (!boot_cpu_has(X86_FEATURE_IBS))
-               return 0;
-
-       /* check IBS cpuid feature flags */
-       max_level = cpuid_eax(0x80000000);
-       if (max_level < IBS_CPUID_FEATURES)
-               return IBS_CAPS_DEFAULT;
-
-       caps = cpuid_eax(IBS_CPUID_FEATURES);
-       if (!(caps & IBS_CAPS_AVAIL))
-               /* cpuid flags not valid */
-               return IBS_CAPS_DEFAULT;
-
-       return caps;
-}
-
-u32 get_ibs_caps(void)
-{
-       return ibs_caps;
-}
-
-EXPORT_SYMBOL(get_ibs_caps);
-
-static inline int get_eilvt(int offset)
-{
-       return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
-}
-
-static inline int put_eilvt(int offset)
-{
-       return !setup_APIC_eilvt(offset, 0, 0, 1);
-}
-
-/*
- * Check and reserve APIC extended interrupt LVT offset for IBS if available.
- */
-static inline int ibs_eilvt_valid(void)
-{
-       int offset;
-       u64 val;
-       int valid = 0;
-
-       preempt_disable();
-
-       rdmsrl(MSR_AMD64_IBSCTL, val);
-       offset = val & IBSCTL_LVT_OFFSET_MASK;
-
-       if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
-               pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
-                      smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
-               goto out;
-       }
-
-       if (!get_eilvt(offset)) {
-               pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
-                      smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
-               goto out;
-       }
-
-       valid = 1;
-out:
-       preempt_enable();
-
-       return valid;
-}
-
-static int setup_ibs_ctl(int ibs_eilvt_off)
-{
-       struct pci_dev *cpu_cfg;
-       int nodes;
-       u32 value = 0;
-
-       nodes = 0;
-       cpu_cfg = NULL;
-       do {
-               cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD,
-                                        PCI_DEVICE_ID_AMD_10H_NB_MISC,
-                                        cpu_cfg);
-               if (!cpu_cfg)
-                       break;
-               ++nodes;
-               pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off
-                                      | IBSCTL_LVT_OFFSET_VALID);
-               pci_read_config_dword(cpu_cfg, IBSCTL, &value);
-               if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) {
-                       pci_dev_put(cpu_cfg);
-                       printk(KERN_DEBUG "Failed to setup IBS LVT offset, "
-                              "IBSCTL = 0x%08x\n", value);
-                       return -EINVAL;
-               }
-       } while (1);
-
-       if (!nodes) {
-               printk(KERN_DEBUG "No CPU node configured for IBS\n");
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-/*
- * This runs only on the current cpu. We try to find an LVT offset and
- * setup the local APIC. For this we must disable preemption. On
- * success we initialize all nodes with this offset. This updates then
- * the offset in the IBS_CTL per-node msr. The per-core APIC setup of
- * the IBS interrupt vector is handled by perf_ibs_cpu_notifier that
- * is using the new offset.
- */
-static void force_ibs_eilvt_setup(void)
-{
-       int offset;
-       int ret;
-
-       preempt_disable();
-       /* find the next free available EILVT entry, skip offset 0 */
-       for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
-               if (get_eilvt(offset))
-                       break;
-       }
-       preempt_enable();
-
-       if (offset == APIC_EILVT_NR_MAX) {
-               printk(KERN_DEBUG "No EILVT entry available\n");
-               return;
-       }
-
-       ret = setup_ibs_ctl(offset);
-       if (ret)
-               goto out;
-
-       if (!ibs_eilvt_valid())
-               goto out;
-
-       pr_info("IBS: LVT offset %d assigned\n", offset);
-
-       return;
-out:
-       preempt_disable();
-       put_eilvt(offset);
-       preempt_enable();
-       return;
-}
-
-static void ibs_eilvt_setup(void)
-{
-       /*
-        * Force LVT offset assignment for family 10h: The offsets are
-        * not assigned by the BIOS for this family, so the OS is
-        * responsible for doing it. If the OS assignment fails, fall
-        * back to BIOS settings and try to setup this.
-        */
-       if (boot_cpu_data.x86 == 0x10)
-               force_ibs_eilvt_setup();
-}
-
-static inline int get_ibs_lvt_offset(void)
-{
-       u64 val;
-
-       rdmsrl(MSR_AMD64_IBSCTL, val);
-       if (!(val & IBSCTL_LVT_OFFSET_VALID))
-               return -EINVAL;
-
-       return val & IBSCTL_LVT_OFFSET_MASK;
-}
-
-static void setup_APIC_ibs(void *dummy)
-{
-       int offset;
-
-       offset = get_ibs_lvt_offset();
-       if (offset < 0)
-               goto failed;
-
-       if (!setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 0))
-               return;
-failed:
-       pr_warn("perf: IBS APIC setup failed on cpu #%d\n",
-               smp_processor_id());
-}
-
-static void clear_APIC_ibs(void *dummy)
-{
-       int offset;
-
-       offset = get_ibs_lvt_offset();
-       if (offset >= 0)
-               setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1);
-}
-
-#ifdef CONFIG_PM
-
-static int perf_ibs_suspend(void)
-{
-       clear_APIC_ibs(NULL);
-       return 0;
-}
-
-static void perf_ibs_resume(void)
-{
-       ibs_eilvt_setup();
-       setup_APIC_ibs(NULL);
-}
-
-static struct syscore_ops perf_ibs_syscore_ops = {
-       .resume         = perf_ibs_resume,
-       .suspend        = perf_ibs_suspend,
-};
-
-static void perf_ibs_pm_init(void)
-{
-       register_syscore_ops(&perf_ibs_syscore_ops);
-}
-
-#else
-
-static inline void perf_ibs_pm_init(void) { }
-
-#endif
-
-static int
-perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
-{
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_STARTING:
-               setup_APIC_ibs(NULL);
-               break;
-       case CPU_DYING:
-               clear_APIC_ibs(NULL);
-               break;
-       default:
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-static __init int amd_ibs_init(void)
-{
-       u32 caps;
-       int ret = -EINVAL;
-
-       caps = __get_ibs_caps();
-       if (!caps)
-               return -ENODEV; /* ibs not supported by the cpu */
-
-       ibs_eilvt_setup();
-
-       if (!ibs_eilvt_valid())
-               goto out;
-
-       perf_ibs_pm_init();
-       cpu_notifier_register_begin();
-       ibs_caps = caps;
-       /* make ibs_caps visible to other cpus: */
-       smp_mb();
-       smp_call_function(setup_APIC_ibs, NULL, 1);
-       __perf_cpu_notifier(perf_ibs_cpu_notifier);
-       cpu_notifier_register_done();
-
-       ret = perf_event_ibs_init();
-out:
-       if (ret)
-               pr_err("Failed to setup IBS, %d\n", ret);
-       return ret;
-}
-
-/* Since we need the pci subsystem to init ibs we can't do this earlier: */
-device_initcall(amd_ibs_init);
diff --git a/arch/x86/kernel/cpu/perf_event_amd_iommu.c b/arch/x86/kernel/cpu/perf_event_amd_iommu.c
deleted file mode 100644 (file)
index 97242a9..0000000
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (C) 2013 Advanced Micro Devices, Inc.
- *
- * Author: Steven Kinney <Steven.Kinney@amd.com>
- * Author: Suravee Suthikulpanit <Suraveee.Suthikulpanit@amd.com>
- *
- * Perf: amd_iommu - AMD IOMMU Performance Counter PMU implementation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/perf_event.h>
-#include <linux/module.h>
-#include <linux/cpumask.h>
-#include <linux/slab.h>
-
-#include "perf_event.h"
-#include "perf_event_amd_iommu.h"
-
-#define COUNTER_SHIFT          16
-
-#define _GET_BANK(ev)       ((u8)(ev->hw.extra_reg.reg >> 8))
-#define _GET_CNTR(ev)       ((u8)(ev->hw.extra_reg.reg))
-
-/* iommu pmu config masks */
-#define _GET_CSOURCE(ev)    ((ev->hw.config & 0xFFULL))
-#define _GET_DEVID(ev)      ((ev->hw.config >> 8)  & 0xFFFFULL)
-#define _GET_PASID(ev)      ((ev->hw.config >> 24) & 0xFFFFULL)
-#define _GET_DOMID(ev)      ((ev->hw.config >> 40) & 0xFFFFULL)
-#define _GET_DEVID_MASK(ev) ((ev->hw.extra_reg.config)  & 0xFFFFULL)
-#define _GET_PASID_MASK(ev) ((ev->hw.extra_reg.config >> 16) & 0xFFFFULL)
-#define _GET_DOMID_MASK(ev) ((ev->hw.extra_reg.config >> 32) & 0xFFFFULL)
-
-static struct perf_amd_iommu __perf_iommu;
-
-struct perf_amd_iommu {
-       struct pmu pmu;
-       u8 max_banks;
-       u8 max_counters;
-       u64 cntr_assign_mask;
-       raw_spinlock_t lock;
-       const struct attribute_group *attr_groups[4];
-};
-
-#define format_group   attr_groups[0]
-#define cpumask_group  attr_groups[1]
-#define events_group   attr_groups[2]
-#define null_group     attr_groups[3]
-
-/*---------------------------------------------
- * sysfs format attributes
- *---------------------------------------------*/
-PMU_FORMAT_ATTR(csource,    "config:0-7");
-PMU_FORMAT_ATTR(devid,      "config:8-23");
-PMU_FORMAT_ATTR(pasid,      "config:24-39");
-PMU_FORMAT_ATTR(domid,      "config:40-55");
-PMU_FORMAT_ATTR(devid_mask, "config1:0-15");
-PMU_FORMAT_ATTR(pasid_mask, "config1:16-31");
-PMU_FORMAT_ATTR(domid_mask, "config1:32-47");
-
-static struct attribute *iommu_format_attrs[] = {
-       &format_attr_csource.attr,
-       &format_attr_devid.attr,
-       &format_attr_pasid.attr,
-       &format_attr_domid.attr,
-       &format_attr_devid_mask.attr,
-       &format_attr_pasid_mask.attr,
-       &format_attr_domid_mask.attr,
-       NULL,
-};
-
-static struct attribute_group amd_iommu_format_group = {
-       .name = "format",
-       .attrs = iommu_format_attrs,
-};
-
-/*---------------------------------------------
- * sysfs events attributes
- *---------------------------------------------*/
-struct amd_iommu_event_desc {
-       struct kobj_attribute attr;
-       const char *event;
-};
-
-static ssize_t _iommu_event_show(struct kobject *kobj,
-                               struct kobj_attribute *attr, char *buf)
-{
-       struct amd_iommu_event_desc *event =
-               container_of(attr, struct amd_iommu_event_desc, attr);
-       return sprintf(buf, "%s\n", event->event);
-}
-
-#define AMD_IOMMU_EVENT_DESC(_name, _event)                    \
-{                                                              \
-       .attr  = __ATTR(_name, 0444, _iommu_event_show, NULL),  \
-       .event = _event,                                        \
-}
-
-static struct amd_iommu_event_desc amd_iommu_v2_event_descs[] = {
-       AMD_IOMMU_EVENT_DESC(mem_pass_untrans,        "csource=0x01"),
-       AMD_IOMMU_EVENT_DESC(mem_pass_pretrans,       "csource=0x02"),
-       AMD_IOMMU_EVENT_DESC(mem_pass_excl,           "csource=0x03"),
-       AMD_IOMMU_EVENT_DESC(mem_target_abort,        "csource=0x04"),
-       AMD_IOMMU_EVENT_DESC(mem_trans_total,         "csource=0x05"),
-       AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pte_hit,   "csource=0x06"),
-       AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pte_mis,   "csource=0x07"),
-       AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pde_hit,   "csource=0x08"),
-       AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pde_mis,   "csource=0x09"),
-       AMD_IOMMU_EVENT_DESC(mem_dte_hit,             "csource=0x0a"),
-       AMD_IOMMU_EVENT_DESC(mem_dte_mis,             "csource=0x0b"),
-       AMD_IOMMU_EVENT_DESC(page_tbl_read_tot,       "csource=0x0c"),
-       AMD_IOMMU_EVENT_DESC(page_tbl_read_nst,       "csource=0x0d"),
-       AMD_IOMMU_EVENT_DESC(page_tbl_read_gst,       "csource=0x0e"),
-       AMD_IOMMU_EVENT_DESC(int_dte_hit,             "csource=0x0f"),
-       AMD_IOMMU_EVENT_DESC(int_dte_mis,             "csource=0x10"),
-       AMD_IOMMU_EVENT_DESC(cmd_processed,           "csource=0x11"),
-       AMD_IOMMU_EVENT_DESC(cmd_processed_inv,       "csource=0x12"),
-       AMD_IOMMU_EVENT_DESC(tlb_inv,                 "csource=0x13"),
-       { /* end: all zeroes */ },
-};
-
-/*---------------------------------------------
- * sysfs cpumask attributes
- *---------------------------------------------*/
-static cpumask_t iommu_cpumask;
-
-static ssize_t _iommu_cpumask_show(struct device *dev,
-                                  struct device_attribute *attr,
-                                  char *buf)
-{
-       return cpumap_print_to_pagebuf(true, buf, &iommu_cpumask);
-}
-static DEVICE_ATTR(cpumask, S_IRUGO, _iommu_cpumask_show, NULL);
-
-static struct attribute *iommu_cpumask_attrs[] = {
-       &dev_attr_cpumask.attr,
-       NULL,
-};
-
-static struct attribute_group amd_iommu_cpumask_group = {
-       .attrs = iommu_cpumask_attrs,
-};
-
-/*---------------------------------------------*/
-
-static int get_next_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu)
-{
-       unsigned long flags;
-       int shift, bank, cntr, retval;
-       int max_banks = perf_iommu->max_banks;
-       int max_cntrs = perf_iommu->max_counters;
-
-       raw_spin_lock_irqsave(&perf_iommu->lock, flags);
-
-       for (bank = 0, shift = 0; bank < max_banks; bank++) {
-               for (cntr = 0; cntr < max_cntrs; cntr++) {
-                       shift = bank + (bank*3) + cntr;
-                       if (perf_iommu->cntr_assign_mask & (1ULL<<shift)) {
-                               continue;
-                       } else {
-                               perf_iommu->cntr_assign_mask |= (1ULL<<shift);
-                               retval = ((u16)((u16)bank<<8) | (u8)(cntr));
-                               goto out;
-                       }
-               }
-       }
-       retval = -ENOSPC;
-out:
-       raw_spin_unlock_irqrestore(&perf_iommu->lock, flags);
-       return retval;
-}
-
-static int clear_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu,
-                                       u8 bank, u8 cntr)
-{
-       unsigned long flags;
-       int max_banks, max_cntrs;
-       int shift = 0;
-
-       max_banks = perf_iommu->max_banks;
-       max_cntrs = perf_iommu->max_counters;
-
-       if ((bank > max_banks) || (cntr > max_cntrs))
-               return -EINVAL;
-
-       shift = bank + cntr + (bank*3);
-
-       raw_spin_lock_irqsave(&perf_iommu->lock, flags);
-       perf_iommu->cntr_assign_mask &= ~(1ULL<<shift);
-       raw_spin_unlock_irqrestore(&perf_iommu->lock, flags);
-
-       return 0;
-}
-
-static int perf_iommu_event_init(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct perf_amd_iommu *perf_iommu;
-       u64 config, config1;
-
-       /* test the event attr type check for PMU enumeration */
-       if (event->attr.type != event->pmu->type)
-               return -ENOENT;
-
-       /*
-        * IOMMU counters are shared across all cores.
-        * Therefore, it does not support per-process mode.
-        * Also, it does not support event sampling mode.
-        */
-       if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
-               return -EINVAL;
-
-       /* IOMMU counters do not have usr/os/guest/host bits */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-           event->attr.exclude_host || event->attr.exclude_guest)
-               return -EINVAL;
-
-       if (event->cpu < 0)
-               return -EINVAL;
-
-       perf_iommu = &__perf_iommu;
-
-       if (event->pmu != &perf_iommu->pmu)
-               return -ENOENT;
-
-       if (perf_iommu) {
-               config = event->attr.config;
-               config1 = event->attr.config1;
-       } else {
-               return -EINVAL;
-       }
-
-       /* integrate with iommu base devid (0000), assume one iommu */
-       perf_iommu->max_banks =
-               amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID);
-       perf_iommu->max_counters =
-               amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID);
-       if ((perf_iommu->max_banks == 0) || (perf_iommu->max_counters == 0))
-               return -EINVAL;
-
-       /* update the hw_perf_event struct with the iommu config data */
-       hwc->config = config;
-       hwc->extra_reg.config = config1;
-
-       return 0;
-}
-
-static void perf_iommu_enable_event(struct perf_event *ev)
-{
-       u8 csource = _GET_CSOURCE(ev);
-       u16 devid = _GET_DEVID(ev);
-       u64 reg = 0ULL;
-
-       reg = csource;
-       amd_iommu_pc_get_set_reg_val(devid,
-                       _GET_BANK(ev), _GET_CNTR(ev) ,
-                        IOMMU_PC_COUNTER_SRC_REG, &reg, true);
-
-       reg = 0ULL | devid | (_GET_DEVID_MASK(ev) << 32);
-       if (reg)
-               reg |= (1UL << 31);
-       amd_iommu_pc_get_set_reg_val(devid,
-                       _GET_BANK(ev), _GET_CNTR(ev) ,
-                        IOMMU_PC_DEVID_MATCH_REG, &reg, true);
-
-       reg = 0ULL | _GET_PASID(ev) | (_GET_PASID_MASK(ev) << 32);
-       if (reg)
-               reg |= (1UL << 31);
-       amd_iommu_pc_get_set_reg_val(devid,
-                       _GET_BANK(ev), _GET_CNTR(ev) ,
-                        IOMMU_PC_PASID_MATCH_REG, &reg, true);
-
-       reg = 0ULL | _GET_DOMID(ev) | (_GET_DOMID_MASK(ev) << 32);
-       if (reg)
-               reg |= (1UL << 31);
-       amd_iommu_pc_get_set_reg_val(devid,
-                       _GET_BANK(ev), _GET_CNTR(ev) ,
-                        IOMMU_PC_DOMID_MATCH_REG, &reg, true);
-}
-
-static void perf_iommu_disable_event(struct perf_event *event)
-{
-       u64 reg = 0ULL;
-
-       amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
-                       _GET_BANK(event), _GET_CNTR(event),
-                       IOMMU_PC_COUNTER_SRC_REG, &reg, true);
-}
-
-static void perf_iommu_start(struct perf_event *event, int flags)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       pr_debug("perf: amd_iommu:perf_iommu_start\n");
-       if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
-               return;
-
-       WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
-       hwc->state = 0;
-
-       if (flags & PERF_EF_RELOAD) {
-               u64 prev_raw_count =  local64_read(&hwc->prev_count);
-               amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
-                               _GET_BANK(event), _GET_CNTR(event),
-                               IOMMU_PC_COUNTER_REG, &prev_raw_count, true);
-       }
-
-       perf_iommu_enable_event(event);
-       perf_event_update_userpage(event);
-
-}
-
-static void perf_iommu_read(struct perf_event *event)
-{
-       u64 count = 0ULL;
-       u64 prev_raw_count = 0ULL;
-       u64 delta = 0ULL;
-       struct hw_perf_event *hwc = &event->hw;
-       pr_debug("perf: amd_iommu:perf_iommu_read\n");
-
-       amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
-                               _GET_BANK(event), _GET_CNTR(event),
-                               IOMMU_PC_COUNTER_REG, &count, false);
-
-       /* IOMMU pc counter register is only 48 bits */
-       count &= 0xFFFFFFFFFFFFULL;
-
-       prev_raw_count =  local64_read(&hwc->prev_count);
-       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-                                       count) != prev_raw_count)
-               return;
-
-       /* Handling 48-bit counter overflowing */
-       delta = (count << COUNTER_SHIFT) - (prev_raw_count << COUNTER_SHIFT);
-       delta >>= COUNTER_SHIFT;
-       local64_add(delta, &event->count);
-
-}
-
-static void perf_iommu_stop(struct perf_event *event, int flags)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 config;
-
-       pr_debug("perf: amd_iommu:perf_iommu_stop\n");
-
-       if (hwc->state & PERF_HES_UPTODATE)
-               return;
-
-       perf_iommu_disable_event(event);
-       WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
-       hwc->state |= PERF_HES_STOPPED;
-
-       if (hwc->state & PERF_HES_UPTODATE)
-               return;
-
-       config = hwc->config;
-       perf_iommu_read(event);
-       hwc->state |= PERF_HES_UPTODATE;
-}
-
-static int perf_iommu_add(struct perf_event *event, int flags)
-{
-       int retval;
-       struct perf_amd_iommu *perf_iommu =
-                       container_of(event->pmu, struct perf_amd_iommu, pmu);
-
-       pr_debug("perf: amd_iommu:perf_iommu_add\n");
-       event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
-
-       /* request an iommu bank/counter */
-       retval = get_next_avail_iommu_bnk_cntr(perf_iommu);
-       if (retval != -ENOSPC)
-               event->hw.extra_reg.reg = (u16)retval;
-       else
-               return retval;
-
-       if (flags & PERF_EF_START)
-               perf_iommu_start(event, PERF_EF_RELOAD);
-
-       return 0;
-}
-
-static void perf_iommu_del(struct perf_event *event, int flags)
-{
-       struct perf_amd_iommu *perf_iommu =
-                       container_of(event->pmu, struct perf_amd_iommu, pmu);
-
-       pr_debug("perf: amd_iommu:perf_iommu_del\n");
-       perf_iommu_stop(event, PERF_EF_UPDATE);
-
-       /* clear the assigned iommu bank/counter */
-       clear_avail_iommu_bnk_cntr(perf_iommu,
-                                    _GET_BANK(event),
-                                    _GET_CNTR(event));
-
-       perf_event_update_userpage(event);
-}
-
-static __init int _init_events_attrs(struct perf_amd_iommu *perf_iommu)
-{
-       struct attribute **attrs;
-       struct attribute_group *attr_group;
-       int i = 0, j;
-
-       while (amd_iommu_v2_event_descs[i].attr.attr.name)
-               i++;
-
-       attr_group = kzalloc(sizeof(struct attribute *)
-               * (i + 1) + sizeof(*attr_group), GFP_KERNEL);
-       if (!attr_group)
-               return -ENOMEM;
-
-       attrs = (struct attribute **)(attr_group + 1);
-       for (j = 0; j < i; j++)
-               attrs[j] = &amd_iommu_v2_event_descs[j].attr.attr;
-
-       attr_group->name = "events";
-       attr_group->attrs = attrs;
-       perf_iommu->events_group = attr_group;
-
-       return 0;
-}
-
-static __init void amd_iommu_pc_exit(void)
-{
-       if (__perf_iommu.events_group != NULL) {
-               kfree(__perf_iommu.events_group);
-               __perf_iommu.events_group = NULL;
-       }
-}
-
-static __init int _init_perf_amd_iommu(
-       struct perf_amd_iommu *perf_iommu, char *name)
-{
-       int ret;
-
-       raw_spin_lock_init(&perf_iommu->lock);
-
-       /* Init format attributes */
-       perf_iommu->format_group = &amd_iommu_format_group;
-
-       /* Init cpumask attributes to only core 0 */
-       cpumask_set_cpu(0, &iommu_cpumask);
-       perf_iommu->cpumask_group = &amd_iommu_cpumask_group;
-
-       /* Init events attributes */
-       if (_init_events_attrs(perf_iommu) != 0)
-               pr_err("perf: amd_iommu: Only support raw events.\n");
-
-       /* Init null attributes */
-       perf_iommu->null_group = NULL;
-       perf_iommu->pmu.attr_groups = perf_iommu->attr_groups;
-
-       ret = perf_pmu_register(&perf_iommu->pmu, name, -1);
-       if (ret) {
-               pr_err("perf: amd_iommu: Failed to initialized.\n");
-               amd_iommu_pc_exit();
-       } else {
-               pr_info("perf: amd_iommu: Detected. (%d banks, %d counters/bank)\n",
-                       amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID),
-                       amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID));
-       }
-
-       return ret;
-}
-
-static struct perf_amd_iommu __perf_iommu = {
-       .pmu = {
-               .event_init     = perf_iommu_event_init,
-               .add            = perf_iommu_add,
-               .del            = perf_iommu_del,
-               .start          = perf_iommu_start,
-               .stop           = perf_iommu_stop,
-               .read           = perf_iommu_read,
-       },
-       .max_banks              = 0x00,
-       .max_counters           = 0x00,
-       .cntr_assign_mask       = 0ULL,
-       .format_group           = NULL,
-       .cpumask_group          = NULL,
-       .events_group           = NULL,
-       .null_group             = NULL,
-};
-
-static __init int amd_iommu_pc_init(void)
-{
-       /* Make sure the IOMMU PC resource is available */
-       if (!amd_iommu_pc_supported())
-               return -ENODEV;
-
-       _init_perf_amd_iommu(&__perf_iommu, "amd_iommu");
-
-       return 0;
-}
-
-device_initcall(amd_iommu_pc_init);
diff --git a/arch/x86/kernel/cpu/perf_event_amd_iommu.h b/arch/x86/kernel/cpu/perf_event_amd_iommu.h
deleted file mode 100644 (file)
index 845d173..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2013 Advanced Micro Devices, Inc.
- *
- * Author: Steven Kinney <Steven.Kinney@amd.com>
- * Author: Suravee Suthikulpanit <Suraveee.Suthikulpanit@amd.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 _PERF_EVENT_AMD_IOMMU_H_
-#define _PERF_EVENT_AMD_IOMMU_H_
-
-/* iommu pc mmio region register indexes */
-#define IOMMU_PC_COUNTER_REG                   0x00
-#define IOMMU_PC_COUNTER_SRC_REG               0x08
-#define IOMMU_PC_PASID_MATCH_REG               0x10
-#define IOMMU_PC_DOMID_MATCH_REG               0x18
-#define IOMMU_PC_DEVID_MATCH_REG               0x20
-#define IOMMU_PC_COUNTER_REPORT_REG            0x28
-
-/* maximun specified bank/counters */
-#define PC_MAX_SPEC_BNKS                       64
-#define PC_MAX_SPEC_CNTRS                      16
-
-/* iommu pc reg masks*/
-#define IOMMU_BASE_DEVID                       0x0000
-
-/* amd_iommu_init.c external support functions */
-extern bool amd_iommu_pc_supported(void);
-
-extern u8 amd_iommu_pc_get_max_banks(u16 devid);
-
-extern u8 amd_iommu_pc_get_max_counters(u16 devid);
-
-extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr,
-                       u8 fxn, u64 *value, bool is_write);
-
-#endif /*_PERF_EVENT_AMD_IOMMU_H_*/
diff --git a/arch/x86/kernel/cpu/perf_event_amd_uncore.c b/arch/x86/kernel/cpu/perf_event_amd_uncore.c
deleted file mode 100644 (file)
index 8836fc9..0000000
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * Copyright (C) 2013 Advanced Micro Devices, Inc.
- *
- * Author: Jacob Shin <jacob.shin@amd.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.
- */
-
-#include <linux/perf_event.h>
-#include <linux/percpu.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/cpu.h>
-#include <linux/cpumask.h>
-
-#include <asm/cpufeature.h>
-#include <asm/perf_event.h>
-#include <asm/msr.h>
-
-#define NUM_COUNTERS_NB                4
-#define NUM_COUNTERS_L2                4
-#define MAX_COUNTERS           NUM_COUNTERS_NB
-
-#define RDPMC_BASE_NB          6
-#define RDPMC_BASE_L2          10
-
-#define COUNTER_SHIFT          16
-
-struct amd_uncore {
-       int id;
-       int refcnt;
-       int cpu;
-       int num_counters;
-       int rdpmc_base;
-       u32 msr_base;
-       cpumask_t *active_mask;
-       struct pmu *pmu;
-       struct perf_event *events[MAX_COUNTERS];
-       struct amd_uncore *free_when_cpu_online;
-};
-
-static struct amd_uncore * __percpu *amd_uncore_nb;
-static struct amd_uncore * __percpu *amd_uncore_l2;
-
-static struct pmu amd_nb_pmu;
-static struct pmu amd_l2_pmu;
-
-static cpumask_t amd_nb_active_mask;
-static cpumask_t amd_l2_active_mask;
-
-static bool is_nb_event(struct perf_event *event)
-{
-       return event->pmu->type == amd_nb_pmu.type;
-}
-
-static bool is_l2_event(struct perf_event *event)
-{
-       return event->pmu->type == amd_l2_pmu.type;
-}
-
-static struct amd_uncore *event_to_amd_uncore(struct perf_event *event)
-{
-       if (is_nb_event(event) && amd_uncore_nb)
-               return *per_cpu_ptr(amd_uncore_nb, event->cpu);
-       else if (is_l2_event(event) && amd_uncore_l2)
-               return *per_cpu_ptr(amd_uncore_l2, event->cpu);
-
-       return NULL;
-}
-
-static void amd_uncore_read(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 prev, new;
-       s64 delta;
-
-       /*
-        * since we do not enable counter overflow interrupts,
-        * we do not have to worry about prev_count changing on us
-        */
-
-       prev = local64_read(&hwc->prev_count);
-       rdpmcl(hwc->event_base_rdpmc, new);
-       local64_set(&hwc->prev_count, new);
-       delta = (new << COUNTER_SHIFT) - (prev << COUNTER_SHIFT);
-       delta >>= COUNTER_SHIFT;
-       local64_add(delta, &event->count);
-}
-
-static void amd_uncore_start(struct perf_event *event, int flags)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (flags & PERF_EF_RELOAD)
-               wrmsrl(hwc->event_base, (u64)local64_read(&hwc->prev_count));
-
-       hwc->state = 0;
-       wrmsrl(hwc->config_base, (hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE));
-       perf_event_update_userpage(event);
-}
-
-static void amd_uncore_stop(struct perf_event *event, int flags)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       wrmsrl(hwc->config_base, hwc->config);
-       hwc->state |= PERF_HES_STOPPED;
-
-       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
-               amd_uncore_read(event);
-               hwc->state |= PERF_HES_UPTODATE;
-       }
-}
-
-static int amd_uncore_add(struct perf_event *event, int flags)
-{
-       int i;
-       struct amd_uncore *uncore = event_to_amd_uncore(event);
-       struct hw_perf_event *hwc = &event->hw;
-
-       /* are we already assigned? */
-       if (hwc->idx != -1 && uncore->events[hwc->idx] == event)
-               goto out;
-
-       for (i = 0; i < uncore->num_counters; i++) {
-               if (uncore->events[i] == event) {
-                       hwc->idx = i;
-                       goto out;
-               }
-       }
-
-       /* if not, take the first available counter */
-       hwc->idx = -1;
-       for (i = 0; i < uncore->num_counters; i++) {
-               if (cmpxchg(&uncore->events[i], NULL, event) == NULL) {
-                       hwc->idx = i;
-                       break;
-               }
-       }
-
-out:
-       if (hwc->idx == -1)
-               return -EBUSY;
-
-       hwc->config_base = uncore->msr_base + (2 * hwc->idx);
-       hwc->event_base = uncore->msr_base + 1 + (2 * hwc->idx);
-       hwc->event_base_rdpmc = uncore->rdpmc_base + hwc->idx;
-       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
-
-       if (flags & PERF_EF_START)
-               amd_uncore_start(event, PERF_EF_RELOAD);
-
-       return 0;
-}
-
-static void amd_uncore_del(struct perf_event *event, int flags)
-{
-       int i;
-       struct amd_uncore *uncore = event_to_amd_uncore(event);
-       struct hw_perf_event *hwc = &event->hw;
-
-       amd_uncore_stop(event, PERF_EF_UPDATE);
-
-       for (i = 0; i < uncore->num_counters; i++) {
-               if (cmpxchg(&uncore->events[i], event, NULL) == event)
-                       break;
-       }
-
-       hwc->idx = -1;
-}
-
-static int amd_uncore_event_init(struct perf_event *event)
-{
-       struct amd_uncore *uncore;
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (event->attr.type != event->pmu->type)
-               return -ENOENT;
-
-       /*
-        * NB and L2 counters (MSRs) are shared across all cores that share the
-        * same NB / L2 cache. Interrupts can be directed to a single target
-        * core, however, event counts generated by processes running on other
-        * cores cannot be masked out. So we do not support sampling and
-        * per-thread events.
-        */
-       if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
-               return -EINVAL;
-
-       /* NB and L2 counters do not have usr/os/guest/host bits */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-           event->attr.exclude_host || event->attr.exclude_guest)
-               return -EINVAL;
-
-       /* and we do not enable counter overflow interrupts */
-       hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB;
-       hwc->idx = -1;
-
-       if (event->cpu < 0)
-               return -EINVAL;
-
-       uncore = event_to_amd_uncore(event);
-       if (!uncore)
-               return -ENODEV;
-
-       /*
-        * since request can come in to any of the shared cores, we will remap
-        * to a single common cpu.
-        */
-       event->cpu = uncore->cpu;
-
-       return 0;
-}
-
-static ssize_t amd_uncore_attr_show_cpumask(struct device *dev,
-                                           struct device_attribute *attr,
-                                           char *buf)
-{
-       cpumask_t *active_mask;
-       struct pmu *pmu = dev_get_drvdata(dev);
-
-       if (pmu->type == amd_nb_pmu.type)
-               active_mask = &amd_nb_active_mask;
-       else if (pmu->type == amd_l2_pmu.type)
-               active_mask = &amd_l2_active_mask;
-       else
-               return 0;
-
-       return cpumap_print_to_pagebuf(true, buf, active_mask);
-}
-static DEVICE_ATTR(cpumask, S_IRUGO, amd_uncore_attr_show_cpumask, NULL);
-
-static struct attribute *amd_uncore_attrs[] = {
-       &dev_attr_cpumask.attr,
-       NULL,
-};
-
-static struct attribute_group amd_uncore_attr_group = {
-       .attrs = amd_uncore_attrs,
-};
-
-PMU_FORMAT_ATTR(event, "config:0-7,32-35");
-PMU_FORMAT_ATTR(umask, "config:8-15");
-
-static struct attribute *amd_uncore_format_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       NULL,
-};
-
-static struct attribute_group amd_uncore_format_group = {
-       .name = "format",
-       .attrs = amd_uncore_format_attr,
-};
-
-static const struct attribute_group *amd_uncore_attr_groups[] = {
-       &amd_uncore_attr_group,
-       &amd_uncore_format_group,
-       NULL,
-};
-
-static struct pmu amd_nb_pmu = {
-       .attr_groups    = amd_uncore_attr_groups,
-       .name           = "amd_nb",
-       .event_init     = amd_uncore_event_init,
-       .add            = amd_uncore_add,
-       .del            = amd_uncore_del,
-       .start          = amd_uncore_start,
-       .stop           = amd_uncore_stop,
-       .read           = amd_uncore_read,
-};
-
-static struct pmu amd_l2_pmu = {
-       .attr_groups    = amd_uncore_attr_groups,
-       .name           = "amd_l2",
-       .event_init     = amd_uncore_event_init,
-       .add            = amd_uncore_add,
-       .del            = amd_uncore_del,
-       .start          = amd_uncore_start,
-       .stop           = amd_uncore_stop,
-       .read           = amd_uncore_read,
-};
-
-static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
-{
-       return kzalloc_node(sizeof(struct amd_uncore), GFP_KERNEL,
-                       cpu_to_node(cpu));
-}
-
-static int amd_uncore_cpu_up_prepare(unsigned int cpu)
-{
-       struct amd_uncore *uncore_nb = NULL, *uncore_l2;
-
-       if (amd_uncore_nb) {
-               uncore_nb = amd_uncore_alloc(cpu);
-               if (!uncore_nb)
-                       goto fail;
-               uncore_nb->cpu = cpu;
-               uncore_nb->num_counters = NUM_COUNTERS_NB;
-               uncore_nb->rdpmc_base = RDPMC_BASE_NB;
-               uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL;
-               uncore_nb->active_mask = &amd_nb_active_mask;
-               uncore_nb->pmu = &amd_nb_pmu;
-               *per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb;
-       }
-
-       if (amd_uncore_l2) {
-               uncore_l2 = amd_uncore_alloc(cpu);
-               if (!uncore_l2)
-                       goto fail;
-               uncore_l2->cpu = cpu;
-               uncore_l2->num_counters = NUM_COUNTERS_L2;
-               uncore_l2->rdpmc_base = RDPMC_BASE_L2;
-               uncore_l2->msr_base = MSR_F16H_L2I_PERF_CTL;
-               uncore_l2->active_mask = &amd_l2_active_mask;
-               uncore_l2->pmu = &amd_l2_pmu;
-               *per_cpu_ptr(amd_uncore_l2, cpu) = uncore_l2;
-       }
-
-       return 0;
-
-fail:
-       if (amd_uncore_nb)
-               *per_cpu_ptr(amd_uncore_nb, cpu) = NULL;
-       kfree(uncore_nb);
-       return -ENOMEM;
-}
-
-static struct amd_uncore *
-amd_uncore_find_online_sibling(struct amd_uncore *this,
-                              struct amd_uncore * __percpu *uncores)
-{
-       unsigned int cpu;
-       struct amd_uncore *that;
-
-       for_each_online_cpu(cpu) {
-               that = *per_cpu_ptr(uncores, cpu);
-
-               if (!that)
-                       continue;
-
-               if (this == that)
-                       continue;
-
-               if (this->id == that->id) {
-                       that->free_when_cpu_online = this;
-                       this = that;
-                       break;
-               }
-       }
-
-       this->refcnt++;
-       return this;
-}
-
-static void amd_uncore_cpu_starting(unsigned int cpu)
-{
-       unsigned int eax, ebx, ecx, edx;
-       struct amd_uncore *uncore;
-
-       if (amd_uncore_nb) {
-               uncore = *per_cpu_ptr(amd_uncore_nb, cpu);
-               cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
-               uncore->id = ecx & 0xff;
-
-               uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_nb);
-               *per_cpu_ptr(amd_uncore_nb, cpu) = uncore;
-       }
-
-       if (amd_uncore_l2) {
-               unsigned int apicid = cpu_data(cpu).apicid;
-               unsigned int nshared;
-
-               uncore = *per_cpu_ptr(amd_uncore_l2, cpu);
-               cpuid_count(0x8000001d, 2, &eax, &ebx, &ecx, &edx);
-               nshared = ((eax >> 14) & 0xfff) + 1;
-               uncore->id = apicid - (apicid % nshared);
-
-               uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_l2);
-               *per_cpu_ptr(amd_uncore_l2, cpu) = uncore;
-       }
-}
-
-static void uncore_online(unsigned int cpu,
-                         struct amd_uncore * __percpu *uncores)
-{
-       struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu);
-
-       kfree(uncore->free_when_cpu_online);
-       uncore->free_when_cpu_online = NULL;
-
-       if (cpu == uncore->cpu)
-               cpumask_set_cpu(cpu, uncore->active_mask);
-}
-
-static void amd_uncore_cpu_online(unsigned int cpu)
-{
-       if (amd_uncore_nb)
-               uncore_online(cpu, amd_uncore_nb);
-
-       if (amd_uncore_l2)
-               uncore_online(cpu, amd_uncore_l2);
-}
-
-static void uncore_down_prepare(unsigned int cpu,
-                               struct amd_uncore * __percpu *uncores)
-{
-       unsigned int i;
-       struct amd_uncore *this = *per_cpu_ptr(uncores, cpu);
-
-       if (this->cpu != cpu)
-               return;
-
-       /* this cpu is going down, migrate to a shared sibling if possible */
-       for_each_online_cpu(i) {
-               struct amd_uncore *that = *per_cpu_ptr(uncores, i);
-
-               if (cpu == i)
-                       continue;
-
-               if (this == that) {
-                       perf_pmu_migrate_context(this->pmu, cpu, i);
-                       cpumask_clear_cpu(cpu, that->active_mask);
-                       cpumask_set_cpu(i, that->active_mask);
-                       that->cpu = i;
-                       break;
-               }
-       }
-}
-
-static void amd_uncore_cpu_down_prepare(unsigned int cpu)
-{
-       if (amd_uncore_nb)
-               uncore_down_prepare(cpu, amd_uncore_nb);
-
-       if (amd_uncore_l2)
-               uncore_down_prepare(cpu, amd_uncore_l2);
-}
-
-static void uncore_dead(unsigned int cpu, struct amd_uncore * __percpu *uncores)
-{
-       struct amd_uncore *uncore = *per_cpu_ptr(uncores, cpu);
-
-       if (cpu == uncore->cpu)
-               cpumask_clear_cpu(cpu, uncore->active_mask);
-
-       if (!--uncore->refcnt)
-               kfree(uncore);
-       *per_cpu_ptr(uncores, cpu) = NULL;
-}
-
-static void amd_uncore_cpu_dead(unsigned int cpu)
-{
-       if (amd_uncore_nb)
-               uncore_dead(cpu, amd_uncore_nb);
-
-       if (amd_uncore_l2)
-               uncore_dead(cpu, amd_uncore_l2);
-}
-
-static int
-amd_uncore_cpu_notifier(struct notifier_block *self, unsigned long action,
-                       void *hcpu)
-{
-       unsigned int cpu = (long)hcpu;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_UP_PREPARE:
-               if (amd_uncore_cpu_up_prepare(cpu))
-                       return notifier_from_errno(-ENOMEM);
-               break;
-
-       case CPU_STARTING:
-               amd_uncore_cpu_starting(cpu);
-               break;
-
-       case CPU_ONLINE:
-               amd_uncore_cpu_online(cpu);
-               break;
-
-       case CPU_DOWN_PREPARE:
-               amd_uncore_cpu_down_prepare(cpu);
-               break;
-
-       case CPU_UP_CANCELED:
-       case CPU_DEAD:
-               amd_uncore_cpu_dead(cpu);
-               break;
-
-       default:
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block amd_uncore_cpu_notifier_block = {
-       .notifier_call  = amd_uncore_cpu_notifier,
-       .priority       = CPU_PRI_PERF + 1,
-};
-
-static void __init init_cpu_already_online(void *dummy)
-{
-       unsigned int cpu = smp_processor_id();
-
-       amd_uncore_cpu_starting(cpu);
-       amd_uncore_cpu_online(cpu);
-}
-
-static void cleanup_cpu_online(void *dummy)
-{
-       unsigned int cpu = smp_processor_id();
-
-       amd_uncore_cpu_dead(cpu);
-}
-
-static int __init amd_uncore_init(void)
-{
-       unsigned int cpu, cpu2;
-       int ret = -ENODEV;
-
-       if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
-               goto fail_nodev;
-
-       if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
-               goto fail_nodev;
-
-       if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) {
-               amd_uncore_nb = alloc_percpu(struct amd_uncore *);
-               if (!amd_uncore_nb) {
-                       ret = -ENOMEM;
-                       goto fail_nb;
-               }
-               ret = perf_pmu_register(&amd_nb_pmu, amd_nb_pmu.name, -1);
-               if (ret)
-                       goto fail_nb;
-
-               printk(KERN_INFO "perf: AMD NB counters detected\n");
-               ret = 0;
-       }
-
-       if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) {
-               amd_uncore_l2 = alloc_percpu(struct amd_uncore *);
-               if (!amd_uncore_l2) {
-                       ret = -ENOMEM;
-                       goto fail_l2;
-               }
-               ret = perf_pmu_register(&amd_l2_pmu, amd_l2_pmu.name, -1);
-               if (ret)
-                       goto fail_l2;
-
-               printk(KERN_INFO "perf: AMD L2I counters detected\n");
-               ret = 0;
-       }
-
-       if (ret)
-               goto fail_nodev;
-
-       cpu_notifier_register_begin();
-
-       /* init cpus already online before registering for hotplug notifier */
-       for_each_online_cpu(cpu) {
-               ret = amd_uncore_cpu_up_prepare(cpu);
-               if (ret)
-                       goto fail_online;
-               smp_call_function_single(cpu, init_cpu_already_online, NULL, 1);
-       }
-
-       __register_cpu_notifier(&amd_uncore_cpu_notifier_block);
-       cpu_notifier_register_done();
-
-       return 0;
-
-
-fail_online:
-       for_each_online_cpu(cpu2) {
-               if (cpu2 == cpu)
-                       break;
-               smp_call_function_single(cpu, cleanup_cpu_online, NULL, 1);
-       }
-       cpu_notifier_register_done();
-
-       /* amd_uncore_nb/l2 should have been freed by cleanup_cpu_online */
-       amd_uncore_nb = amd_uncore_l2 = NULL;
-
-       if (boot_cpu_has(X86_FEATURE_PERFCTR_L2))
-               perf_pmu_unregister(&amd_l2_pmu);
-fail_l2:
-       if (boot_cpu_has(X86_FEATURE_PERFCTR_NB))
-               perf_pmu_unregister(&amd_nb_pmu);
-       if (amd_uncore_l2)
-               free_percpu(amd_uncore_l2);
-fail_nb:
-       if (amd_uncore_nb)
-               free_percpu(amd_uncore_nb);
-
-fail_nodev:
-       return ret;
-}
-device_initcall(amd_uncore_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
deleted file mode 100644 (file)
index fed2ab1..0000000
+++ /dev/null
@@ -1,3773 +0,0 @@
-/*
- * Per core/cpu state
- *
- * Used to coordinate shared registers between HT threads or
- * among events on a single PMU.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/stddef.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/nmi.h>
-
-#include <asm/cpufeature.h>
-#include <asm/hardirq.h>
-#include <asm/apic.h>
-
-#include "perf_event.h"
-
-/*
- * Intel PerfMon, used on Core and later.
- */
-static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
-{
-       [PERF_COUNT_HW_CPU_CYCLES]              = 0x003c,
-       [PERF_COUNT_HW_INSTRUCTIONS]            = 0x00c0,
-       [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x4f2e,
-       [PERF_COUNT_HW_CACHE_MISSES]            = 0x412e,
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0x00c4,
-       [PERF_COUNT_HW_BRANCH_MISSES]           = 0x00c5,
-       [PERF_COUNT_HW_BUS_CYCLES]              = 0x013c,
-       [PERF_COUNT_HW_REF_CPU_CYCLES]          = 0x0300, /* pseudo-encoding */
-};
-
-static struct event_constraint intel_core_event_constraints[] __read_mostly =
-{
-       INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
-       INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
-       INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
-       INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
-       INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
-       INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FP_COMP_INSTR_RET */
-       EVENT_CONSTRAINT_END
-};
-
-static struct event_constraint intel_core2_event_constraints[] __read_mostly =
-{
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-       INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
-       INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
-       INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
-       INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
-       INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
-       INTEL_EVENT_CONSTRAINT(0x18, 0x1), /* IDLE_DURING_DIV */
-       INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
-       INTEL_EVENT_CONSTRAINT(0xa1, 0x1), /* RS_UOPS_DISPATCH_CYCLES */
-       INTEL_EVENT_CONSTRAINT(0xc9, 0x1), /* ITLB_MISS_RETIRED (T30-9) */
-       INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED */
-       EVENT_CONSTRAINT_END
-};
-
-static struct event_constraint intel_nehalem_event_constraints[] __read_mostly =
-{
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-       INTEL_EVENT_CONSTRAINT(0x40, 0x3), /* L1D_CACHE_LD */
-       INTEL_EVENT_CONSTRAINT(0x41, 0x3), /* L1D_CACHE_ST */
-       INTEL_EVENT_CONSTRAINT(0x42, 0x3), /* L1D_CACHE_LOCK */
-       INTEL_EVENT_CONSTRAINT(0x43, 0x3), /* L1D_ALL_REF */
-       INTEL_EVENT_CONSTRAINT(0x48, 0x3), /* L1D_PEND_MISS */
-       INTEL_EVENT_CONSTRAINT(0x4e, 0x3), /* L1D_PREFETCH */
-       INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
-       INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
-       EVENT_CONSTRAINT_END
-};
-
-static struct extra_reg intel_nehalem_extra_regs[] __read_mostly =
-{
-       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
-       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0),
-       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x100b),
-       EVENT_EXTRA_END
-};
-
-static struct event_constraint intel_westmere_event_constraints[] __read_mostly =
-{
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-       INTEL_EVENT_CONSTRAINT(0x51, 0x3), /* L1D */
-       INTEL_EVENT_CONSTRAINT(0x60, 0x1), /* OFFCORE_REQUESTS_OUTSTANDING */
-       INTEL_EVENT_CONSTRAINT(0x63, 0x3), /* CACHE_LOCK_CYCLES */
-       INTEL_EVENT_CONSTRAINT(0xb3, 0x1), /* SNOOPQ_REQUEST_OUTSTANDING */
-       EVENT_CONSTRAINT_END
-};
-
-static struct event_constraint intel_snb_event_constraints[] __read_mostly =
-{
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_DISPATCH */
-       INTEL_UEVENT_CONSTRAINT(0x05a3, 0xf), /* CYCLE_ACTIVITY.STALLS_L2_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x02a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x06a3, 0x4), /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
-       INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
-       INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
-       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_DISPATCH */
-       INTEL_UEVENT_CONSTRAINT(0x02a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
-
-       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
-
-       EVENT_CONSTRAINT_END
-};
-
-static struct event_constraint intel_ivb_event_constraints[] __read_mostly =
-{
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-       INTEL_UEVENT_CONSTRAINT(0x0148, 0x4), /* L1D_PEND_MISS.PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x0279, 0xf), /* IDQ.EMTPY */
-       INTEL_UEVENT_CONSTRAINT(0x019c, 0xf), /* IDQ_UOPS_NOT_DELIVERED.CORE */
-       INTEL_UEVENT_CONSTRAINT(0x02a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_LDM_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */
-       INTEL_UEVENT_CONSTRAINT(0x05a3, 0xf), /* CYCLE_ACTIVITY.STALLS_L2_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x06a3, 0xf), /* CYCLE_ACTIVITY.STALLS_LDM_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x08a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x0ca3, 0x4), /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
-
-       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
-
-       EVENT_CONSTRAINT_END
-};
-
-static struct extra_reg intel_westmere_extra_regs[] __read_mostly =
-{
-       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
-       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0xffff, RSP_0),
-       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0xffff, RSP_1),
-       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x100b),
-       EVENT_EXTRA_END
-};
-
-static struct event_constraint intel_v1_event_constraints[] __read_mostly =
-{
-       EVENT_CONSTRAINT_END
-};
-
-static struct event_constraint intel_gen_event_constraints[] __read_mostly =
-{
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-       EVENT_CONSTRAINT_END
-};
-
-static struct event_constraint intel_slm_event_constraints[] __read_mostly =
-{
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* pseudo CPU_CLK_UNHALTED.REF */
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_skl_event_constraints[] = {
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0),      /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1),      /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2),      /* CPU_CLK_UNHALTED.REF */
-       INTEL_UEVENT_CONSTRAINT(0x1c0, 0x2),    /* INST_RETIRED.PREC_DIST */
-       EVENT_CONSTRAINT_END
-};
-
-static struct extra_reg intel_knl_extra_regs[] __read_mostly = {
-       INTEL_UEVENT_EXTRA_REG(0x01b7,
-                              MSR_OFFCORE_RSP_0, 0x7f9ffbffffull, RSP_0),
-       INTEL_UEVENT_EXTRA_REG(0x02b7,
-                              MSR_OFFCORE_RSP_1, 0x3f9ffbffffull, RSP_1),
-       EVENT_EXTRA_END
-};
-
-static struct extra_reg intel_snb_extra_regs[] __read_mostly = {
-       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
-       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0),
-       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3f807f8fffull, RSP_1),
-       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
-       EVENT_EXTRA_END
-};
-
-static struct extra_reg intel_snbep_extra_regs[] __read_mostly = {
-       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
-       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
-       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
-       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
-       EVENT_EXTRA_END
-};
-
-static struct extra_reg intel_skl_extra_regs[] __read_mostly = {
-       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
-       INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
-       INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
-       /*
-        * Note the low 8 bits eventsel code is not a continuous field, containing
-        * some #GPing bits. These are masked out.
-        */
-       INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff17, FE),
-       EVENT_EXTRA_END
-};
-
-EVENT_ATTR_STR(mem-loads,      mem_ld_nhm,     "event=0x0b,umask=0x10,ldlat=3");
-EVENT_ATTR_STR(mem-loads,      mem_ld_snb,     "event=0xcd,umask=0x1,ldlat=3");
-EVENT_ATTR_STR(mem-stores,     mem_st_snb,     "event=0xcd,umask=0x2");
-
-struct attribute *nhm_events_attrs[] = {
-       EVENT_PTR(mem_ld_nhm),
-       NULL,
-};
-
-struct attribute *snb_events_attrs[] = {
-       EVENT_PTR(mem_ld_snb),
-       EVENT_PTR(mem_st_snb),
-       NULL,
-};
-
-static struct event_constraint intel_hsw_event_constraints[] = {
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-       INTEL_UEVENT_CONSTRAINT(0x148, 0x4),    /* L1D_PEND_MISS.PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
-       INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
-       /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x08a3, 0x4),
-       /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
-       INTEL_UEVENT_CONSTRAINT(0x0ca3, 0x4),
-       /* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */
-       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf),
-
-       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
-
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_bdw_event_constraints[] = {
-       FIXED_EVENT_CONSTRAINT(0x00c0, 0),      /* INST_RETIRED.ANY */
-       FIXED_EVENT_CONSTRAINT(0x003c, 1),      /* CPU_CLK_UNHALTED.CORE */
-       FIXED_EVENT_CONSTRAINT(0x0300, 2),      /* CPU_CLK_UNHALTED.REF */
-       INTEL_UEVENT_CONSTRAINT(0x148, 0x4),    /* L1D_PEND_MISS.PENDING */
-       INTEL_UBIT_EVENT_CONSTRAINT(0x8a3, 0x4),        /* CYCLE_ACTIVITY.CYCLES_L1D_MISS */
-       EVENT_CONSTRAINT_END
-};
-
-static u64 intel_pmu_event_map(int hw_event)
-{
-       return intel_perfmon_event_map[hw_event];
-}
-
-/*
- * Notes on the events:
- * - data reads do not include code reads (comparable to earlier tables)
- * - data counts include speculative execution (except L1 write, dtlb, bpu)
- * - remote node access includes remote memory, remote cache, remote mmio.
- * - prefetches are not included in the counts.
- * - icache miss does not include decoded icache
- */
-
-#define SKL_DEMAND_DATA_RD             BIT_ULL(0)
-#define SKL_DEMAND_RFO                 BIT_ULL(1)
-#define SKL_ANY_RESPONSE               BIT_ULL(16)
-#define SKL_SUPPLIER_NONE              BIT_ULL(17)
-#define SKL_L3_MISS_LOCAL_DRAM         BIT_ULL(26)
-#define SKL_L3_MISS_REMOTE_HOP0_DRAM   BIT_ULL(27)
-#define SKL_L3_MISS_REMOTE_HOP1_DRAM   BIT_ULL(28)
-#define SKL_L3_MISS_REMOTE_HOP2P_DRAM  BIT_ULL(29)
-#define SKL_L3_MISS                    (SKL_L3_MISS_LOCAL_DRAM| \
-                                        SKL_L3_MISS_REMOTE_HOP0_DRAM| \
-                                        SKL_L3_MISS_REMOTE_HOP1_DRAM| \
-                                        SKL_L3_MISS_REMOTE_HOP2P_DRAM)
-#define SKL_SPL_HIT                    BIT_ULL(30)
-#define SKL_SNOOP_NONE                 BIT_ULL(31)
-#define SKL_SNOOP_NOT_NEEDED           BIT_ULL(32)
-#define SKL_SNOOP_MISS                 BIT_ULL(33)
-#define SKL_SNOOP_HIT_NO_FWD           BIT_ULL(34)
-#define SKL_SNOOP_HIT_WITH_FWD         BIT_ULL(35)
-#define SKL_SNOOP_HITM                 BIT_ULL(36)
-#define SKL_SNOOP_NON_DRAM             BIT_ULL(37)
-#define SKL_ANY_SNOOP                  (SKL_SPL_HIT|SKL_SNOOP_NONE| \
-                                        SKL_SNOOP_NOT_NEEDED|SKL_SNOOP_MISS| \
-                                        SKL_SNOOP_HIT_NO_FWD|SKL_SNOOP_HIT_WITH_FWD| \
-                                        SKL_SNOOP_HITM|SKL_SNOOP_NON_DRAM)
-#define SKL_DEMAND_READ                        SKL_DEMAND_DATA_RD
-#define SKL_SNOOP_DRAM                 (SKL_SNOOP_NONE| \
-                                        SKL_SNOOP_NOT_NEEDED|SKL_SNOOP_MISS| \
-                                        SKL_SNOOP_HIT_NO_FWD|SKL_SNOOP_HIT_WITH_FWD| \
-                                        SKL_SNOOP_HITM|SKL_SPL_HIT)
-#define SKL_DEMAND_WRITE               SKL_DEMAND_RFO
-#define SKL_LLC_ACCESS                 SKL_ANY_RESPONSE
-#define SKL_L3_MISS_REMOTE             (SKL_L3_MISS_REMOTE_HOP0_DRAM| \
-                                        SKL_L3_MISS_REMOTE_HOP1_DRAM| \
-                                        SKL_L3_MISS_REMOTE_HOP2P_DRAM)
-
-static __initconst const u64 skl_hw_cache_event_ids
-                               [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) ] = 0x81d0,  /* MEM_INST_RETIRED.ALL_LOADS */
-               [ C(RESULT_MISS)   ] = 0x151,   /* L1D.REPLACEMENT */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_INST_RETIRED.ALL_STORES */
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x283,   /* ICACHE_64B.MISS */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
-               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
-               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_INST_RETIRED.ALL_LOADS */
-               [ C(RESULT_MISS)   ] = 0x608,   /* DTLB_LOAD_MISSES.WALK_COMPLETED */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_INST_RETIRED.ALL_STORES */
-               [ C(RESULT_MISS)   ] = 0x649,   /* DTLB_STORE_MISSES.WALK_COMPLETED */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x2085,  /* ITLB_MISSES.STLB_HIT */
-               [ C(RESULT_MISS)   ] = 0xe85,   /* ITLB_MISSES.WALK_COMPLETED */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0xc4,    /* BR_INST_RETIRED.ALL_BRANCHES */
-               [ C(RESULT_MISS)   ] = 0xc5,    /* BR_MISP_RETIRED.ALL_BRANCHES */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
-               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
-               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
-};
-
-static __initconst const u64 skl_hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
-{
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = SKL_DEMAND_READ|
-                                      SKL_LLC_ACCESS|SKL_ANY_SNOOP,
-               [ C(RESULT_MISS)   ] = SKL_DEMAND_READ|
-                                      SKL_L3_MISS|SKL_ANY_SNOOP|
-                                      SKL_SUPPLIER_NONE,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = SKL_DEMAND_WRITE|
-                                      SKL_LLC_ACCESS|SKL_ANY_SNOOP,
-               [ C(RESULT_MISS)   ] = SKL_DEMAND_WRITE|
-                                      SKL_L3_MISS|SKL_ANY_SNOOP|
-                                      SKL_SUPPLIER_NONE,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = SKL_DEMAND_READ|
-                                      SKL_L3_MISS_LOCAL_DRAM|SKL_SNOOP_DRAM,
-               [ C(RESULT_MISS)   ] = SKL_DEMAND_READ|
-                                      SKL_L3_MISS_REMOTE|SKL_SNOOP_DRAM,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = SKL_DEMAND_WRITE|
-                                      SKL_L3_MISS_LOCAL_DRAM|SKL_SNOOP_DRAM,
-               [ C(RESULT_MISS)   ] = SKL_DEMAND_WRITE|
-                                      SKL_L3_MISS_REMOTE|SKL_SNOOP_DRAM,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
-};
-
-#define SNB_DMND_DATA_RD       (1ULL << 0)
-#define SNB_DMND_RFO           (1ULL << 1)
-#define SNB_DMND_IFETCH                (1ULL << 2)
-#define SNB_DMND_WB            (1ULL << 3)
-#define SNB_PF_DATA_RD         (1ULL << 4)
-#define SNB_PF_RFO             (1ULL << 5)
-#define SNB_PF_IFETCH          (1ULL << 6)
-#define SNB_LLC_DATA_RD                (1ULL << 7)
-#define SNB_LLC_RFO            (1ULL << 8)
-#define SNB_LLC_IFETCH         (1ULL << 9)
-#define SNB_BUS_LOCKS          (1ULL << 10)
-#define SNB_STRM_ST            (1ULL << 11)
-#define SNB_OTHER              (1ULL << 15)
-#define SNB_RESP_ANY           (1ULL << 16)
-#define SNB_NO_SUPP            (1ULL << 17)
-#define SNB_LLC_HITM           (1ULL << 18)
-#define SNB_LLC_HITE           (1ULL << 19)
-#define SNB_LLC_HITS           (1ULL << 20)
-#define SNB_LLC_HITF           (1ULL << 21)
-#define SNB_LOCAL              (1ULL << 22)
-#define SNB_REMOTE             (0xffULL << 23)
-#define SNB_SNP_NONE           (1ULL << 31)
-#define SNB_SNP_NOT_NEEDED     (1ULL << 32)
-#define SNB_SNP_MISS           (1ULL << 33)
-#define SNB_NO_FWD             (1ULL << 34)
-#define SNB_SNP_FWD            (1ULL << 35)
-#define SNB_HITM               (1ULL << 36)
-#define SNB_NON_DRAM           (1ULL << 37)
-
-#define SNB_DMND_READ          (SNB_DMND_DATA_RD|SNB_LLC_DATA_RD)
-#define SNB_DMND_WRITE         (SNB_DMND_RFO|SNB_LLC_RFO)
-#define SNB_DMND_PREFETCH      (SNB_PF_DATA_RD|SNB_PF_RFO)
-
-#define SNB_SNP_ANY            (SNB_SNP_NONE|SNB_SNP_NOT_NEEDED| \
-                                SNB_SNP_MISS|SNB_NO_FWD|SNB_SNP_FWD| \
-                                SNB_HITM)
-
-#define SNB_DRAM_ANY           (SNB_LOCAL|SNB_REMOTE|SNB_SNP_ANY)
-#define SNB_DRAM_REMOTE                (SNB_REMOTE|SNB_SNP_ANY)
-
-#define SNB_L3_ACCESS          SNB_RESP_ANY
-#define SNB_L3_MISS            (SNB_DRAM_ANY|SNB_NON_DRAM)
-
-static __initconst const u64 snb_hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
-{
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = SNB_DMND_READ|SNB_L3_ACCESS,
-               [ C(RESULT_MISS)   ] = SNB_DMND_READ|SNB_L3_MISS,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = SNB_DMND_WRITE|SNB_L3_ACCESS,
-               [ C(RESULT_MISS)   ] = SNB_DMND_WRITE|SNB_L3_MISS,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = SNB_DMND_PREFETCH|SNB_L3_ACCESS,
-               [ C(RESULT_MISS)   ] = SNB_DMND_PREFETCH|SNB_L3_MISS,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = SNB_DMND_READ|SNB_DRAM_ANY,
-               [ C(RESULT_MISS)   ] = SNB_DMND_READ|SNB_DRAM_REMOTE,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = SNB_DMND_WRITE|SNB_DRAM_ANY,
-               [ C(RESULT_MISS)   ] = SNB_DMND_WRITE|SNB_DRAM_REMOTE,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = SNB_DMND_PREFETCH|SNB_DRAM_ANY,
-               [ C(RESULT_MISS)   ] = SNB_DMND_PREFETCH|SNB_DRAM_REMOTE,
-       },
- },
-};
-
-static __initconst const u64 snb_hw_cache_event_ids
-                               [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) ] = 0xf1d0, /* MEM_UOP_RETIRED.LOADS        */
-               [ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPLACEMENT              */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0xf2d0, /* MEM_UOP_RETIRED.STORES       */
-               [ C(RESULT_MISS)   ] = 0x0851, /* L1D.ALL_M_REPLACEMENT        */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x024e, /* HW_PRE_REQ.DL1_MISS          */
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0280, /* ICACHE.MISSES */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_WRITE) ] = {
-               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_PREFETCH) ] = {
-               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x81d0, /* MEM_UOP_RETIRED.ALL_LOADS */
-               [ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.CAUSES_A_WALK */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x82d0, /* MEM_UOP_RETIRED.ALL_STORES */
-               [ C(RESULT_MISS)   ] = 0x0149, /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1085, /* ITLB_MISSES.STLB_HIT         */
-               [ C(RESULT_MISS)   ] = 0x0185, /* ITLB_MISSES.CAUSES_A_WALK    */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
-               [ C(RESULT_MISS)   ] = 0x00c5, /* BR_MISP_RETIRED.ALL_BRANCHES */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
- },
-
-};
-
-/*
- * Notes on the events:
- * - data reads do not include code reads (comparable to earlier tables)
- * - data counts include speculative execution (except L1 write, dtlb, bpu)
- * - remote node access includes remote memory, remote cache, remote mmio.
- * - prefetches are not included in the counts because they are not
- *   reliably counted.
- */
-
-#define HSW_DEMAND_DATA_RD             BIT_ULL(0)
-#define HSW_DEMAND_RFO                 BIT_ULL(1)
-#define HSW_ANY_RESPONSE               BIT_ULL(16)
-#define HSW_SUPPLIER_NONE              BIT_ULL(17)
-#define HSW_L3_MISS_LOCAL_DRAM         BIT_ULL(22)
-#define HSW_L3_MISS_REMOTE_HOP0                BIT_ULL(27)
-#define HSW_L3_MISS_REMOTE_HOP1                BIT_ULL(28)
-#define HSW_L3_MISS_REMOTE_HOP2P       BIT_ULL(29)
-#define HSW_L3_MISS                    (HSW_L3_MISS_LOCAL_DRAM| \
-                                        HSW_L3_MISS_REMOTE_HOP0|HSW_L3_MISS_REMOTE_HOP1| \
-                                        HSW_L3_MISS_REMOTE_HOP2P)
-#define HSW_SNOOP_NONE                 BIT_ULL(31)
-#define HSW_SNOOP_NOT_NEEDED           BIT_ULL(32)
-#define HSW_SNOOP_MISS                 BIT_ULL(33)
-#define HSW_SNOOP_HIT_NO_FWD           BIT_ULL(34)
-#define HSW_SNOOP_HIT_WITH_FWD         BIT_ULL(35)
-#define HSW_SNOOP_HITM                 BIT_ULL(36)
-#define HSW_SNOOP_NON_DRAM             BIT_ULL(37)
-#define HSW_ANY_SNOOP                  (HSW_SNOOP_NONE| \
-                                        HSW_SNOOP_NOT_NEEDED|HSW_SNOOP_MISS| \
-                                        HSW_SNOOP_HIT_NO_FWD|HSW_SNOOP_HIT_WITH_FWD| \
-                                        HSW_SNOOP_HITM|HSW_SNOOP_NON_DRAM)
-#define HSW_SNOOP_DRAM                 (HSW_ANY_SNOOP & ~HSW_SNOOP_NON_DRAM)
-#define HSW_DEMAND_READ                        HSW_DEMAND_DATA_RD
-#define HSW_DEMAND_WRITE               HSW_DEMAND_RFO
-#define HSW_L3_MISS_REMOTE             (HSW_L3_MISS_REMOTE_HOP0|\
-                                        HSW_L3_MISS_REMOTE_HOP1|HSW_L3_MISS_REMOTE_HOP2P)
-#define HSW_LLC_ACCESS                 HSW_ANY_RESPONSE
-
-#define BDW_L3_MISS_LOCAL              BIT(26)
-#define BDW_L3_MISS                    (BDW_L3_MISS_LOCAL| \
-                                        HSW_L3_MISS_REMOTE_HOP0|HSW_L3_MISS_REMOTE_HOP1| \
-                                        HSW_L3_MISS_REMOTE_HOP2P)
-
-
-static __initconst const u64 hsw_hw_cache_event_ids
-                               [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) ] = 0x81d0,  /* MEM_UOPS_RETIRED.ALL_LOADS */
-               [ C(RESULT_MISS)   ] = 0x151,   /* L1D.REPLACEMENT */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_UOPS_RETIRED.ALL_STORES */
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x280,   /* ICACHE.MISSES */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
-               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
-               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x81d0,  /* MEM_UOPS_RETIRED.ALL_LOADS */
-               [ C(RESULT_MISS)   ] = 0x108,   /* DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x82d0,  /* MEM_UOPS_RETIRED.ALL_STORES */
-               [ C(RESULT_MISS)   ] = 0x149,   /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x6085,  /* ITLB_MISSES.STLB_HIT */
-               [ C(RESULT_MISS)   ] = 0x185,   /* ITLB_MISSES.MISS_CAUSES_A_WALK */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0xc4,    /* BR_INST_RETIRED.ALL_BRANCHES */
-               [ C(RESULT_MISS)   ] = 0xc5,    /* BR_MISP_RETIRED.ALL_BRANCHES */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
-               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
-               [ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
-};
-
-static __initconst const u64 hsw_hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
-{
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = HSW_DEMAND_READ|
-                                      HSW_LLC_ACCESS,
-               [ C(RESULT_MISS)   ] = HSW_DEMAND_READ|
-                                      HSW_L3_MISS|HSW_ANY_SNOOP,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = HSW_DEMAND_WRITE|
-                                      HSW_LLC_ACCESS,
-               [ C(RESULT_MISS)   ] = HSW_DEMAND_WRITE|
-                                      HSW_L3_MISS|HSW_ANY_SNOOP,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = HSW_DEMAND_READ|
-                                      HSW_L3_MISS_LOCAL_DRAM|
-                                      HSW_SNOOP_DRAM,
-               [ C(RESULT_MISS)   ] = HSW_DEMAND_READ|
-                                      HSW_L3_MISS_REMOTE|
-                                      HSW_SNOOP_DRAM,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = HSW_DEMAND_WRITE|
-                                      HSW_L3_MISS_LOCAL_DRAM|
-                                      HSW_SNOOP_DRAM,
-               [ C(RESULT_MISS)   ] = HSW_DEMAND_WRITE|
-                                      HSW_L3_MISS_REMOTE|
-                                      HSW_SNOOP_DRAM,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
-};
-
-static __initconst const u64 westmere_hw_cache_event_ids
-                               [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) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
-               [ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPL                     */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
-               [ C(RESULT_MISS)   ] = 0x0251, /* L1D.M_REPL                   */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS        */
-               [ C(RESULT_MISS)   ] = 0x024e, /* L1D_PREFETCH.MISS            */
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                    */
-               [ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                   */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       /*
-        * Use RFO, not WRITEBACK, because a write miss would typically occur
-        * on RFO.
-        */
-       [ C(OP_WRITE) ] = {
-               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_PREFETCH) ] = {
-               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
-               [ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.ANY         */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
-               [ C(RESULT_MISS)   ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS  */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P           */
-               [ C(RESULT_MISS)   ] = 0x0185, /* ITLB_MISSES.ANY              */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
-               [ C(RESULT_MISS)   ] = 0x03e8, /* BPU_CLEARS.ANY               */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
- },
-};
-
-/*
- * Nehalem/Westmere MSR_OFFCORE_RESPONSE bits;
- * See IA32 SDM Vol 3B 30.6.1.3
- */
-
-#define NHM_DMND_DATA_RD       (1 << 0)
-#define NHM_DMND_RFO           (1 << 1)
-#define NHM_DMND_IFETCH                (1 << 2)
-#define NHM_DMND_WB            (1 << 3)
-#define NHM_PF_DATA_RD         (1 << 4)
-#define NHM_PF_DATA_RFO                (1 << 5)
-#define NHM_PF_IFETCH          (1 << 6)
-#define NHM_OFFCORE_OTHER      (1 << 7)
-#define NHM_UNCORE_HIT         (1 << 8)
-#define NHM_OTHER_CORE_HIT_SNP (1 << 9)
-#define NHM_OTHER_CORE_HITM    (1 << 10)
-                               /* reserved */
-#define NHM_REMOTE_CACHE_FWD   (1 << 12)
-#define NHM_REMOTE_DRAM                (1 << 13)
-#define NHM_LOCAL_DRAM         (1 << 14)
-#define NHM_NON_DRAM           (1 << 15)
-
-#define NHM_LOCAL              (NHM_LOCAL_DRAM|NHM_REMOTE_CACHE_FWD)
-#define NHM_REMOTE             (NHM_REMOTE_DRAM)
-
-#define NHM_DMND_READ          (NHM_DMND_DATA_RD)
-#define NHM_DMND_WRITE         (NHM_DMND_RFO|NHM_DMND_WB)
-#define NHM_DMND_PREFETCH      (NHM_PF_DATA_RD|NHM_PF_DATA_RFO)
-
-#define NHM_L3_HIT     (NHM_UNCORE_HIT|NHM_OTHER_CORE_HIT_SNP|NHM_OTHER_CORE_HITM)
-#define NHM_L3_MISS    (NHM_NON_DRAM|NHM_LOCAL_DRAM|NHM_REMOTE_DRAM|NHM_REMOTE_CACHE_FWD)
-#define NHM_L3_ACCESS  (NHM_L3_HIT|NHM_L3_MISS)
-
-static __initconst const u64 nehalem_hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
-{
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_L3_ACCESS,
-               [ C(RESULT_MISS)   ] = NHM_DMND_READ|NHM_L3_MISS,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_L3_ACCESS,
-               [ C(RESULT_MISS)   ] = NHM_DMND_WRITE|NHM_L3_MISS,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_L3_ACCESS,
-               [ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_L3_MISS,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_LOCAL|NHM_REMOTE,
-               [ C(RESULT_MISS)   ] = NHM_DMND_READ|NHM_REMOTE,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_LOCAL|NHM_REMOTE,
-               [ C(RESULT_MISS)   ] = NHM_DMND_WRITE|NHM_REMOTE,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_LOCAL|NHM_REMOTE,
-               [ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_REMOTE,
-       },
- },
-};
-
-static __initconst const u64 nehalem_hw_cache_event_ids
-                               [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) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
-               [ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPL                     */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
-               [ C(RESULT_MISS)   ] = 0x0251, /* L1D.M_REPL                   */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS        */
-               [ C(RESULT_MISS)   ] = 0x024e, /* L1D_PREFETCH.MISS            */
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                    */
-               [ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                   */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       /*
-        * Use RFO, not WRITEBACK, because a write miss would typically occur
-        * on RFO.
-        */
-       [ C(OP_WRITE) ] = {
-               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_PREFETCH) ] = {
-               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI   (alias)  */
-               [ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.ANY         */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI   (alias)  */
-               [ C(RESULT_MISS)   ] = 0x010c, /* MEM_STORE_RETIRED.DTLB_MISS  */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01c0, /* INST_RETIRED.ANY_P           */
-               [ C(RESULT_MISS)   ] = 0x20c8, /* ITLB_MISS_RETIRED            */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
-               [ C(RESULT_MISS)   ] = 0x03e8, /* BPU_CLEARS.ANY               */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
- },
-};
-
-static __initconst const u64 core2_hw_cache_event_ids
-                               [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) ] = 0x0f40, /* L1D_CACHE_LD.MESI          */
-               [ C(RESULT_MISS)   ] = 0x0140, /* L1D_CACHE_LD.I_STATE       */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI          */
-               [ C(RESULT_MISS)   ] = 0x0141, /* L1D_CACHE_ST.I_STATE       */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x104e, /* L1D_PREFETCH.REQUESTS      */
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0080, /* L1I.READS                  */
-               [ C(RESULT_MISS)   ] = 0x0081, /* L1I.MISSES                 */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI                 */
-               [ C(RESULT_MISS)   ] = 0x4129, /* L2_LD.ISTATE               */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI                 */
-               [ C(RESULT_MISS)   ] = 0x412A, /* L2_ST.ISTATE               */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI  (alias) */
-               [ C(RESULT_MISS)   ] = 0x0208, /* DTLB_MISSES.MISS_LD        */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI  (alias) */
-               [ C(RESULT_MISS)   ] = 0x0808, /* DTLB_MISSES.MISS_ST        */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P         */
-               [ C(RESULT_MISS)   ] = 0x1282, /* ITLBMISSES                 */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY        */
-               [ C(RESULT_MISS)   ] = 0x00c5, /* BP_INST_RETIRED.MISPRED    */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
-};
-
-static __initconst const u64 atom_hw_cache_event_ids
-                               [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) ] = 0x2140, /* L1D_CACHE.LD               */
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE.ST               */
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0380, /* L1I.READS                  */
-               [ C(RESULT_MISS)   ] = 0x0280, /* L1I.MISSES                 */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x4f29, /* L2_LD.MESI                 */
-               [ C(RESULT_MISS)   ] = 0x4129, /* L2_LD.ISTATE               */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x4f2A, /* L2_ST.MESI                 */
-               [ C(RESULT_MISS)   ] = 0x412A, /* L2_ST.ISTATE               */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x2140, /* L1D_CACHE_LD.MESI  (alias) */
-               [ C(RESULT_MISS)   ] = 0x0508, /* DTLB_MISSES.MISS_LD        */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x2240, /* L1D_CACHE_ST.MESI  (alias) */
-               [ C(RESULT_MISS)   ] = 0x0608, /* DTLB_MISSES.MISS_ST        */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P         */
-               [ C(RESULT_MISS)   ] = 0x0282, /* ITLB.MISSES                */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY        */
-               [ C(RESULT_MISS)   ] = 0x00c5, /* BP_INST_RETIRED.MISPRED    */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
-};
-
-static struct extra_reg intel_slm_extra_regs[] __read_mostly =
-{
-       /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
-       INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x768005ffffull, RSP_0),
-       INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0x368005ffffull, RSP_1),
-       EVENT_EXTRA_END
-};
-
-#define SLM_DMND_READ          SNB_DMND_DATA_RD
-#define SLM_DMND_WRITE         SNB_DMND_RFO
-#define SLM_DMND_PREFETCH      (SNB_PF_DATA_RD|SNB_PF_RFO)
-
-#define SLM_SNP_ANY            (SNB_SNP_NONE|SNB_SNP_MISS|SNB_NO_FWD|SNB_HITM)
-#define SLM_LLC_ACCESS         SNB_RESP_ANY
-#define SLM_LLC_MISS           (SLM_SNP_ANY|SNB_NON_DRAM)
-
-static __initconst const u64 slm_hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
-{
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = SLM_DMND_READ|SLM_LLC_ACCESS,
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = SLM_DMND_WRITE|SLM_LLC_ACCESS,
-               [ C(RESULT_MISS)   ] = SLM_DMND_WRITE|SLM_LLC_MISS,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = SLM_DMND_PREFETCH|SLM_LLC_ACCESS,
-               [ C(RESULT_MISS)   ] = SLM_DMND_PREFETCH|SLM_LLC_MISS,
-       },
- },
-};
-
-static __initconst const u64 slm_hw_cache_event_ids
-                               [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) ] = 0,
-               [ C(RESULT_MISS)   ] = 0x0104, /* LD_DCU_MISS */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0380, /* ICACHE.ACCESSES */
-               [ C(RESULT_MISS)   ] = 0x0280, /* ICACGE.MISSES */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_WRITE) ] = {
-               /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
-       [ C(OP_PREFETCH) ] = {
-               /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
-               [ C(RESULT_ACCESS) ] = 0x01b7,
-               /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
-               [ C(RESULT_MISS)   ] = 0x01b7,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0x0804, /* LD_DTLB_MISS */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */
-               [ C(RESULT_MISS)   ] = 0x40205, /* PAGE_WALKS.I_SIDE_WALKS */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ANY */
-               [ C(RESULT_MISS)   ] = 0x00c5, /* BP_INST_RETIRED.MISPRED */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
-};
-
-#define KNL_OT_L2_HITE         BIT_ULL(19) /* Other Tile L2 Hit */
-#define KNL_OT_L2_HITF         BIT_ULL(20) /* Other Tile L2 Hit */
-#define KNL_MCDRAM_LOCAL       BIT_ULL(21)
-#define KNL_MCDRAM_FAR         BIT_ULL(22)
-#define KNL_DDR_LOCAL          BIT_ULL(23)
-#define KNL_DDR_FAR            BIT_ULL(24)
-#define KNL_DRAM_ANY           (KNL_MCDRAM_LOCAL | KNL_MCDRAM_FAR | \
-                                   KNL_DDR_LOCAL | KNL_DDR_FAR)
-#define KNL_L2_READ            SLM_DMND_READ
-#define KNL_L2_WRITE           SLM_DMND_WRITE
-#define KNL_L2_PREFETCH                SLM_DMND_PREFETCH
-#define KNL_L2_ACCESS          SLM_LLC_ACCESS
-#define KNL_L2_MISS            (KNL_OT_L2_HITE | KNL_OT_L2_HITF | \
-                                  KNL_DRAM_ANY | SNB_SNP_ANY | \
-                                                 SNB_NON_DRAM)
-
-static __initconst const u64 knl_hw_cache_extra_regs
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
-       [C(LL)] = {
-               [C(OP_READ)] = {
-                       [C(RESULT_ACCESS)] = KNL_L2_READ | KNL_L2_ACCESS,
-                       [C(RESULT_MISS)]   = 0,
-               },
-               [C(OP_WRITE)] = {
-                       [C(RESULT_ACCESS)] = KNL_L2_WRITE | KNL_L2_ACCESS,
-                       [C(RESULT_MISS)]   = KNL_L2_WRITE | KNL_L2_MISS,
-               },
-               [C(OP_PREFETCH)] = {
-                       [C(RESULT_ACCESS)] = KNL_L2_PREFETCH | KNL_L2_ACCESS,
-                       [C(RESULT_MISS)]   = KNL_L2_PREFETCH | KNL_L2_MISS,
-               },
-       },
-};
-
-/*
- * Use from PMIs where the LBRs are already disabled.
- */
-static void __intel_pmu_disable_all(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
-
-       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
-               intel_pmu_disable_bts();
-       else
-               intel_bts_disable_local();
-
-       intel_pmu_pebs_disable_all();
-}
-
-static void intel_pmu_disable_all(void)
-{
-       __intel_pmu_disable_all();
-       intel_pmu_lbr_disable_all();
-}
-
-static void __intel_pmu_enable_all(int added, bool pmi)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       intel_pmu_pebs_enable_all();
-       intel_pmu_lbr_enable_all(pmi);
-       wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL,
-                       x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask);
-
-       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
-               struct perf_event *event =
-                       cpuc->events[INTEL_PMC_IDX_FIXED_BTS];
-
-               if (WARN_ON_ONCE(!event))
-                       return;
-
-               intel_pmu_enable_bts(event->hw.config);
-       } else
-               intel_bts_enable_local();
-}
-
-static void intel_pmu_enable_all(int added)
-{
-       __intel_pmu_enable_all(added, false);
-}
-
-/*
- * Workaround for:
- *   Intel Errata AAK100 (model 26)
- *   Intel Errata AAP53  (model 30)
- *   Intel Errata BD53   (model 44)
- *
- * The official story:
- *   These chips need to be 'reset' when adding counters by programming the
- *   magic three (non-counting) events 0x4300B5, 0x4300D2, and 0x4300B1 either
- *   in sequence on the same PMC or on different PMCs.
- *
- * In practise it appears some of these events do in fact count, and
- * we need to programm all 4 events.
- */
-static void intel_pmu_nhm_workaround(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       static const unsigned long nhm_magic[4] = {
-               0x4300B5,
-               0x4300D2,
-               0x4300B1,
-               0x4300B1
-       };
-       struct perf_event *event;
-       int i;
-
-       /*
-        * The Errata requires below steps:
-        * 1) Clear MSR_IA32_PEBS_ENABLE and MSR_CORE_PERF_GLOBAL_CTRL;
-        * 2) Configure 4 PERFEVTSELx with the magic events and clear
-        *    the corresponding PMCx;
-        * 3) set bit0~bit3 of MSR_CORE_PERF_GLOBAL_CTRL;
-        * 4) Clear MSR_CORE_PERF_GLOBAL_CTRL;
-        * 5) Clear 4 pairs of ERFEVTSELx and PMCx;
-        */
-
-       /*
-        * The real steps we choose are a little different from above.
-        * A) To reduce MSR operations, we don't run step 1) as they
-        *    are already cleared before this function is called;
-        * B) Call x86_perf_event_update to save PMCx before configuring
-        *    PERFEVTSELx with magic number;
-        * C) With step 5), we do clear only when the PERFEVTSELx is
-        *    not used currently.
-        * D) Call x86_perf_event_set_period to restore PMCx;
-        */
-
-       /* We always operate 4 pairs of PERF Counters */
-       for (i = 0; i < 4; i++) {
-               event = cpuc->events[i];
-               if (event)
-                       x86_perf_event_update(event);
-       }
-
-       for (i = 0; i < 4; i++) {
-               wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + i, nhm_magic[i]);
-               wrmsrl(MSR_ARCH_PERFMON_PERFCTR0 + i, 0x0);
-       }
-
-       wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0xf);
-       wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x0);
-
-       for (i = 0; i < 4; i++) {
-               event = cpuc->events[i];
-
-               if (event) {
-                       x86_perf_event_set_period(event);
-                       __x86_pmu_enable_event(&event->hw,
-                                       ARCH_PERFMON_EVENTSEL_ENABLE);
-               } else
-                       wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + i, 0x0);
-       }
-}
-
-static void intel_pmu_nhm_enable_all(int added)
-{
-       if (added)
-               intel_pmu_nhm_workaround();
-       intel_pmu_enable_all(added);
-}
-
-static inline u64 intel_pmu_get_status(void)
-{
-       u64 status;
-
-       rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status);
-
-       return status;
-}
-
-static inline void intel_pmu_ack_status(u64 ack)
-{
-       wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack);
-}
-
-static void intel_pmu_disable_fixed(struct hw_perf_event *hwc)
-{
-       int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
-       u64 ctrl_val, mask;
-
-       mask = 0xfULL << (idx * 4);
-
-       rdmsrl(hwc->config_base, ctrl_val);
-       ctrl_val &= ~mask;
-       wrmsrl(hwc->config_base, ctrl_val);
-}
-
-static inline bool event_is_checkpointed(struct perf_event *event)
-{
-       return (event->hw.config & HSW_IN_TX_CHECKPOINTED) != 0;
-}
-
-static void intel_pmu_disable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       if (unlikely(hwc->idx == INTEL_PMC_IDX_FIXED_BTS)) {
-               intel_pmu_disable_bts();
-               intel_pmu_drain_bts_buffer();
-               return;
-       }
-
-       cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx);
-       cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
-       cpuc->intel_cp_status &= ~(1ull << hwc->idx);
-
-       /*
-        * must disable before any actual event
-        * because any event may be combined with LBR
-        */
-       if (needs_branch_stack(event))
-               intel_pmu_lbr_disable(event);
-
-       if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
-               intel_pmu_disable_fixed(hwc);
-               return;
-       }
-
-       x86_pmu_disable_event(event);
-
-       if (unlikely(event->attr.precise_ip))
-               intel_pmu_pebs_disable(event);
-}
-
-static void intel_pmu_enable_fixed(struct hw_perf_event *hwc)
-{
-       int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
-       u64 ctrl_val, bits, mask;
-
-       /*
-        * Enable IRQ generation (0x8),
-        * and enable ring-3 counting (0x2) and ring-0 counting (0x1)
-        * if requested:
-        */
-       bits = 0x8ULL;
-       if (hwc->config & ARCH_PERFMON_EVENTSEL_USR)
-               bits |= 0x2;
-       if (hwc->config & ARCH_PERFMON_EVENTSEL_OS)
-               bits |= 0x1;
-
-       /*
-        * ANY bit is supported in v3 and up
-        */
-       if (x86_pmu.version > 2 && hwc->config & ARCH_PERFMON_EVENTSEL_ANY)
-               bits |= 0x4;
-
-       bits <<= (idx * 4);
-       mask = 0xfULL << (idx * 4);
-
-       rdmsrl(hwc->config_base, ctrl_val);
-       ctrl_val &= ~mask;
-       ctrl_val |= bits;
-       wrmsrl(hwc->config_base, ctrl_val);
-}
-
-static void intel_pmu_enable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       if (unlikely(hwc->idx == INTEL_PMC_IDX_FIXED_BTS)) {
-               if (!__this_cpu_read(cpu_hw_events.enabled))
-                       return;
-
-               intel_pmu_enable_bts(hwc->config);
-               return;
-       }
-       /*
-        * must enabled before any actual event
-        * because any event may be combined with LBR
-        */
-       if (needs_branch_stack(event))
-               intel_pmu_lbr_enable(event);
-
-       if (event->attr.exclude_host)
-               cpuc->intel_ctrl_guest_mask |= (1ull << hwc->idx);
-       if (event->attr.exclude_guest)
-               cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx);
-
-       if (unlikely(event_is_checkpointed(event)))
-               cpuc->intel_cp_status |= (1ull << hwc->idx);
-
-       if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
-               intel_pmu_enable_fixed(hwc);
-               return;
-       }
-
-       if (unlikely(event->attr.precise_ip))
-               intel_pmu_pebs_enable(event);
-
-       __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
-}
-
-/*
- * Save and restart an expired event. Called by NMI contexts,
- * so it has to be careful about preempting normal event ops:
- */
-int intel_pmu_save_and_restart(struct perf_event *event)
-{
-       x86_perf_event_update(event);
-       /*
-        * For a checkpointed counter always reset back to 0.  This
-        * avoids a situation where the counter overflows, aborts the
-        * transaction and is then set back to shortly before the
-        * overflow, and overflows and aborts again.
-        */
-       if (unlikely(event_is_checkpointed(event))) {
-               /* No race with NMIs because the counter should not be armed */
-               wrmsrl(event->hw.event_base, 0);
-               local64_set(&event->hw.prev_count, 0);
-       }
-       return x86_perf_event_set_period(event);
-}
-
-static void intel_pmu_reset(void)
-{
-       struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
-       unsigned long flags;
-       int idx;
-
-       if (!x86_pmu.num_counters)
-               return;
-
-       local_irq_save(flags);
-
-       pr_info("clearing PMU state on CPU#%d\n", smp_processor_id());
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               wrmsrl_safe(x86_pmu_config_addr(idx), 0ull);
-               wrmsrl_safe(x86_pmu_event_addr(idx),  0ull);
-       }
-       for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++)
-               wrmsrl_safe(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
-
-       if (ds)
-               ds->bts_index = ds->bts_buffer_base;
-
-       /* Ack all overflows and disable fixed counters */
-       if (x86_pmu.version >= 2) {
-               intel_pmu_ack_status(intel_pmu_get_status());
-               wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
-       }
-
-       /* Reset LBRs and LBR freezing */
-       if (x86_pmu.lbr_nr) {
-               update_debugctlmsr(get_debugctlmsr() &
-                       ~(DEBUGCTLMSR_FREEZE_LBRS_ON_PMI|DEBUGCTLMSR_LBR));
-       }
-
-       local_irq_restore(flags);
-}
-
-/*
- * This handler is triggered by the local APIC, so the APIC IRQ handling
- * rules apply:
- */
-static int intel_pmu_handle_irq(struct pt_regs *regs)
-{
-       struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
-       int bit, loops;
-       u64 status;
-       int handled;
-
-       cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       /*
-        * No known reason to not always do late ACK,
-        * but just in case do it opt-in.
-        */
-       if (!x86_pmu.late_ack)
-               apic_write(APIC_LVTPC, APIC_DM_NMI);
-       __intel_pmu_disable_all();
-       handled = intel_pmu_drain_bts_buffer();
-       handled += intel_bts_interrupt();
-       status = intel_pmu_get_status();
-       if (!status)
-               goto done;
-
-       loops = 0;
-again:
-       intel_pmu_lbr_read();
-       intel_pmu_ack_status(status);
-       if (++loops > 100) {
-               static bool warned = false;
-               if (!warned) {
-                       WARN(1, "perfevents: irq loop stuck!\n");
-                       perf_event_print_debug();
-                       warned = true;
-               }
-               intel_pmu_reset();
-               goto done;
-       }
-
-       inc_irq_stat(apic_perf_irqs);
-
-
-       /*
-        * Ignore a range of extra bits in status that do not indicate
-        * overflow by themselves.
-        */
-       status &= ~(GLOBAL_STATUS_COND_CHG |
-                   GLOBAL_STATUS_ASIF |
-                   GLOBAL_STATUS_LBRS_FROZEN);
-       if (!status)
-               goto done;
-
-       /*
-        * PEBS overflow sets bit 62 in the global status register
-        */
-       if (__test_and_clear_bit(62, (unsigned long *)&status)) {
-               handled++;
-               x86_pmu.drain_pebs(regs);
-       }
-
-       /*
-        * Intel PT
-        */
-       if (__test_and_clear_bit(55, (unsigned long *)&status)) {
-               handled++;
-               intel_pt_interrupt();
-       }
-
-       /*
-        * Checkpointed counters can lead to 'spurious' PMIs because the
-        * rollback caused by the PMI will have cleared the overflow status
-        * bit. Therefore always force probe these counters.
-        */
-       status |= cpuc->intel_cp_status;
-
-       for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
-               struct perf_event *event = cpuc->events[bit];
-
-               handled++;
-
-               if (!test_bit(bit, cpuc->active_mask))
-                       continue;
-
-               if (!intel_pmu_save_and_restart(event))
-                       continue;
-
-               perf_sample_data_init(&data, 0, event->hw.last_period);
-
-               if (has_branch_stack(event))
-                       data.br_stack = &cpuc->lbr_stack;
-
-               if (perf_event_overflow(event, &data, regs))
-                       x86_pmu_stop(event, 0);
-       }
-
-       /*
-        * Repeat if there is more work to be done:
-        */
-       status = intel_pmu_get_status();
-       if (status)
-               goto again;
-
-done:
-       __intel_pmu_enable_all(0, true);
-       /*
-        * Only unmask the NMI after the overflow counters
-        * have been reset. This avoids spurious NMIs on
-        * Haswell CPUs.
-        */
-       if (x86_pmu.late_ack)
-               apic_write(APIC_LVTPC, APIC_DM_NMI);
-       return handled;
-}
-
-static struct event_constraint *
-intel_bts_constraints(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       unsigned int hw_event, bts_event;
-
-       if (event->attr.freq)
-               return NULL;
-
-       hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
-       bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
-
-       if (unlikely(hw_event == bts_event && hwc->sample_period == 1))
-               return &bts_constraint;
-
-       return NULL;
-}
-
-static int intel_alt_er(int idx, u64 config)
-{
-       int alt_idx = idx;
-
-       if (!(x86_pmu.flags & PMU_FL_HAS_RSP_1))
-               return idx;
-
-       if (idx == EXTRA_REG_RSP_0)
-               alt_idx = EXTRA_REG_RSP_1;
-
-       if (idx == EXTRA_REG_RSP_1)
-               alt_idx = EXTRA_REG_RSP_0;
-
-       if (config & ~x86_pmu.extra_regs[alt_idx].valid_mask)
-               return idx;
-
-       return alt_idx;
-}
-
-static void intel_fixup_er(struct perf_event *event, int idx)
-{
-       event->hw.extra_reg.idx = idx;
-
-       if (idx == EXTRA_REG_RSP_0) {
-               event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
-               event->hw.config |= x86_pmu.extra_regs[EXTRA_REG_RSP_0].event;
-               event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0;
-       } else if (idx == EXTRA_REG_RSP_1) {
-               event->hw.config &= ~INTEL_ARCH_EVENT_MASK;
-               event->hw.config |= x86_pmu.extra_regs[EXTRA_REG_RSP_1].event;
-               event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1;
-       }
-}
-
-/*
- * manage allocation of shared extra msr for certain events
- *
- * sharing can be:
- * per-cpu: to be shared between the various events on a single PMU
- * per-core: per-cpu + shared by HT threads
- */
-static struct event_constraint *
-__intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc,
-                                  struct perf_event *event,
-                                  struct hw_perf_event_extra *reg)
-{
-       struct event_constraint *c = &emptyconstraint;
-       struct er_account *era;
-       unsigned long flags;
-       int idx = reg->idx;
-
-       /*
-        * reg->alloc can be set due to existing state, so for fake cpuc we
-        * need to ignore this, otherwise we might fail to allocate proper fake
-        * state for this extra reg constraint. Also see the comment below.
-        */
-       if (reg->alloc && !cpuc->is_fake)
-               return NULL; /* call x86_get_event_constraint() */
-
-again:
-       era = &cpuc->shared_regs->regs[idx];
-       /*
-        * we use spin_lock_irqsave() to avoid lockdep issues when
-        * passing a fake cpuc
-        */
-       raw_spin_lock_irqsave(&era->lock, flags);
-
-       if (!atomic_read(&era->ref) || era->config == reg->config) {
-
-               /*
-                * If its a fake cpuc -- as per validate_{group,event}() we
-                * shouldn't touch event state and we can avoid doing so
-                * since both will only call get_event_constraints() once
-                * on each event, this avoids the need for reg->alloc.
-                *
-                * Not doing the ER fixup will only result in era->reg being
-                * wrong, but since we won't actually try and program hardware
-                * this isn't a problem either.
-                */
-               if (!cpuc->is_fake) {
-                       if (idx != reg->idx)
-                               intel_fixup_er(event, idx);
-
-                       /*
-                        * x86_schedule_events() can call get_event_constraints()
-                        * multiple times on events in the case of incremental
-                        * scheduling(). reg->alloc ensures we only do the ER
-                        * allocation once.
-                        */
-                       reg->alloc = 1;
-               }
-
-               /* lock in msr value */
-               era->config = reg->config;
-               era->reg = reg->reg;
-
-               /* one more user */
-               atomic_inc(&era->ref);
-
-               /*
-                * need to call x86_get_event_constraint()
-                * to check if associated event has constraints
-                */
-               c = NULL;
-       } else {
-               idx = intel_alt_er(idx, reg->config);
-               if (idx != reg->idx) {
-                       raw_spin_unlock_irqrestore(&era->lock, flags);
-                       goto again;
-               }
-       }
-       raw_spin_unlock_irqrestore(&era->lock, flags);
-
-       return c;
-}
-
-static void
-__intel_shared_reg_put_constraints(struct cpu_hw_events *cpuc,
-                                  struct hw_perf_event_extra *reg)
-{
-       struct er_account *era;
-
-       /*
-        * Only put constraint if extra reg was actually allocated. Also takes
-        * care of event which do not use an extra shared reg.
-        *
-        * Also, if this is a fake cpuc we shouldn't touch any event state
-        * (reg->alloc) and we don't care about leaving inconsistent cpuc state
-        * either since it'll be thrown out.
-        */
-       if (!reg->alloc || cpuc->is_fake)
-               return;
-
-       era = &cpuc->shared_regs->regs[reg->idx];
-
-       /* one fewer user */
-       atomic_dec(&era->ref);
-
-       /* allocate again next time */
-       reg->alloc = 0;
-}
-
-static struct event_constraint *
-intel_shared_regs_constraints(struct cpu_hw_events *cpuc,
-                             struct perf_event *event)
-{
-       struct event_constraint *c = NULL, *d;
-       struct hw_perf_event_extra *xreg, *breg;
-
-       xreg = &event->hw.extra_reg;
-       if (xreg->idx != EXTRA_REG_NONE) {
-               c = __intel_shared_reg_get_constraints(cpuc, event, xreg);
-               if (c == &emptyconstraint)
-                       return c;
-       }
-       breg = &event->hw.branch_reg;
-       if (breg->idx != EXTRA_REG_NONE) {
-               d = __intel_shared_reg_get_constraints(cpuc, event, breg);
-               if (d == &emptyconstraint) {
-                       __intel_shared_reg_put_constraints(cpuc, xreg);
-                       c = d;
-               }
-       }
-       return c;
-}
-
-struct event_constraint *
-x86_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
-                         struct perf_event *event)
-{
-       struct event_constraint *c;
-
-       if (x86_pmu.event_constraints) {
-               for_each_event_constraint(c, x86_pmu.event_constraints) {
-                       if ((event->hw.config & c->cmask) == c->code) {
-                               event->hw.flags |= c->flags;
-                               return c;
-                       }
-               }
-       }
-
-       return &unconstrained;
-}
-
-static struct event_constraint *
-__intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
-                           struct perf_event *event)
-{
-       struct event_constraint *c;
-
-       c = intel_bts_constraints(event);
-       if (c)
-               return c;
-
-       c = intel_shared_regs_constraints(cpuc, event);
-       if (c)
-               return c;
-
-       c = intel_pebs_constraints(event);
-       if (c)
-               return c;
-
-       return x86_get_event_constraints(cpuc, idx, event);
-}
-
-static void
-intel_start_scheduling(struct cpu_hw_events *cpuc)
-{
-       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
-       struct intel_excl_states *xl;
-       int tid = cpuc->excl_thread_id;
-
-       /*
-        * nothing needed if in group validation mode
-        */
-       if (cpuc->is_fake || !is_ht_workaround_enabled())
-               return;
-
-       /*
-        * no exclusion needed
-        */
-       if (WARN_ON_ONCE(!excl_cntrs))
-               return;
-
-       xl = &excl_cntrs->states[tid];
-
-       xl->sched_started = true;
-       /*
-        * lock shared state until we are done scheduling
-        * in stop_event_scheduling()
-        * makes scheduling appear as a transaction
-        */
-       raw_spin_lock(&excl_cntrs->lock);
-}
-
-static void intel_commit_scheduling(struct cpu_hw_events *cpuc, int idx, int cntr)
-{
-       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
-       struct event_constraint *c = cpuc->event_constraint[idx];
-       struct intel_excl_states *xl;
-       int tid = cpuc->excl_thread_id;
-
-       if (cpuc->is_fake || !is_ht_workaround_enabled())
-               return;
-
-       if (WARN_ON_ONCE(!excl_cntrs))
-               return;
-
-       if (!(c->flags & PERF_X86_EVENT_DYNAMIC))
-               return;
-
-       xl = &excl_cntrs->states[tid];
-
-       lockdep_assert_held(&excl_cntrs->lock);
-
-       if (c->flags & PERF_X86_EVENT_EXCL)
-               xl->state[cntr] = INTEL_EXCL_EXCLUSIVE;
-       else
-               xl->state[cntr] = INTEL_EXCL_SHARED;
-}
-
-static void
-intel_stop_scheduling(struct cpu_hw_events *cpuc)
-{
-       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
-       struct intel_excl_states *xl;
-       int tid = cpuc->excl_thread_id;
-
-       /*
-        * nothing needed if in group validation mode
-        */
-       if (cpuc->is_fake || !is_ht_workaround_enabled())
-               return;
-       /*
-        * no exclusion needed
-        */
-       if (WARN_ON_ONCE(!excl_cntrs))
-               return;
-
-       xl = &excl_cntrs->states[tid];
-
-       xl->sched_started = false;
-       /*
-        * release shared state lock (acquired in intel_start_scheduling())
-        */
-       raw_spin_unlock(&excl_cntrs->lock);
-}
-
-static struct event_constraint *
-intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
-                          int idx, struct event_constraint *c)
-{
-       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
-       struct intel_excl_states *xlo;
-       int tid = cpuc->excl_thread_id;
-       int is_excl, i;
-
-       /*
-        * validating a group does not require
-        * enforcing cross-thread  exclusion
-        */
-       if (cpuc->is_fake || !is_ht_workaround_enabled())
-               return c;
-
-       /*
-        * no exclusion needed
-        */
-       if (WARN_ON_ONCE(!excl_cntrs))
-               return c;
-
-       /*
-        * because we modify the constraint, we need
-        * to make a copy. Static constraints come
-        * from static const tables.
-        *
-        * only needed when constraint has not yet
-        * been cloned (marked dynamic)
-        */
-       if (!(c->flags & PERF_X86_EVENT_DYNAMIC)) {
-               struct event_constraint *cx;
-
-               /*
-                * grab pre-allocated constraint entry
-                */
-               cx = &cpuc->constraint_list[idx];
-
-               /*
-                * initialize dynamic constraint
-                * with static constraint
-                */
-               *cx = *c;
-
-               /*
-                * mark constraint as dynamic, so we
-                * can free it later on
-                */
-               cx->flags |= PERF_X86_EVENT_DYNAMIC;
-               c = cx;
-       }
-
-       /*
-        * From here on, the constraint is dynamic.
-        * Either it was just allocated above, or it
-        * was allocated during a earlier invocation
-        * of this function
-        */
-
-       /*
-        * state of sibling HT
-        */
-       xlo = &excl_cntrs->states[tid ^ 1];
-
-       /*
-        * event requires exclusive counter access
-        * across HT threads
-        */
-       is_excl = c->flags & PERF_X86_EVENT_EXCL;
-       if (is_excl && !(event->hw.flags & PERF_X86_EVENT_EXCL_ACCT)) {
-               event->hw.flags |= PERF_X86_EVENT_EXCL_ACCT;
-               if (!cpuc->n_excl++)
-                       WRITE_ONCE(excl_cntrs->has_exclusive[tid], 1);
-       }
-
-       /*
-        * Modify static constraint with current dynamic
-        * state of thread
-        *
-        * EXCLUSIVE: sibling counter measuring exclusive event
-        * SHARED   : sibling counter measuring non-exclusive event
-        * UNUSED   : sibling counter unused
-        */
-       for_each_set_bit(i, c->idxmsk, X86_PMC_IDX_MAX) {
-               /*
-                * exclusive event in sibling counter
-                * our corresponding counter cannot be used
-                * regardless of our event
-                */
-               if (xlo->state[i] == INTEL_EXCL_EXCLUSIVE)
-                       __clear_bit(i, c->idxmsk);
-               /*
-                * if measuring an exclusive event, sibling
-                * measuring non-exclusive, then counter cannot
-                * be used
-                */
-               if (is_excl && xlo->state[i] == INTEL_EXCL_SHARED)
-                       __clear_bit(i, c->idxmsk);
-       }
-
-       /*
-        * recompute actual bit weight for scheduling algorithm
-        */
-       c->weight = hweight64(c->idxmsk64);
-
-       /*
-        * if we return an empty mask, then switch
-        * back to static empty constraint to avoid
-        * the cost of freeing later on
-        */
-       if (c->weight == 0)
-               c = &emptyconstraint;
-
-       return c;
-}
-
-static struct event_constraint *
-intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
-                           struct perf_event *event)
-{
-       struct event_constraint *c1 = NULL;
-       struct event_constraint *c2;
-
-       if (idx >= 0) /* fake does < 0 */
-               c1 = cpuc->event_constraint[idx];
-
-       /*
-        * first time only
-        * - static constraint: no change across incremental scheduling calls
-        * - dynamic constraint: handled by intel_get_excl_constraints()
-        */
-       c2 = __intel_get_event_constraints(cpuc, idx, event);
-       if (c1 && (c1->flags & PERF_X86_EVENT_DYNAMIC)) {
-               bitmap_copy(c1->idxmsk, c2->idxmsk, X86_PMC_IDX_MAX);
-               c1->weight = c2->weight;
-               c2 = c1;
-       }
-
-       if (cpuc->excl_cntrs)
-               return intel_get_excl_constraints(cpuc, event, idx, c2);
-
-       return c2;
-}
-
-static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
-               struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
-       int tid = cpuc->excl_thread_id;
-       struct intel_excl_states *xl;
-
-       /*
-        * nothing needed if in group validation mode
-        */
-       if (cpuc->is_fake)
-               return;
-
-       if (WARN_ON_ONCE(!excl_cntrs))
-               return;
-
-       if (hwc->flags & PERF_X86_EVENT_EXCL_ACCT) {
-               hwc->flags &= ~PERF_X86_EVENT_EXCL_ACCT;
-               if (!--cpuc->n_excl)
-                       WRITE_ONCE(excl_cntrs->has_exclusive[tid], 0);
-       }
-
-       /*
-        * If event was actually assigned, then mark the counter state as
-        * unused now.
-        */
-       if (hwc->idx >= 0) {
-               xl = &excl_cntrs->states[tid];
-
-               /*
-                * put_constraint may be called from x86_schedule_events()
-                * which already has the lock held so here make locking
-                * conditional.
-                */
-               if (!xl->sched_started)
-                       raw_spin_lock(&excl_cntrs->lock);
-
-               xl->state[hwc->idx] = INTEL_EXCL_UNUSED;
-
-               if (!xl->sched_started)
-                       raw_spin_unlock(&excl_cntrs->lock);
-       }
-}
-
-static void
-intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc,
-                                       struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg;
-
-       reg = &event->hw.extra_reg;
-       if (reg->idx != EXTRA_REG_NONE)
-               __intel_shared_reg_put_constraints(cpuc, reg);
-
-       reg = &event->hw.branch_reg;
-       if (reg->idx != EXTRA_REG_NONE)
-               __intel_shared_reg_put_constraints(cpuc, reg);
-}
-
-static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
-                                       struct perf_event *event)
-{
-       intel_put_shared_regs_event_constraints(cpuc, event);
-
-       /*
-        * is PMU has exclusive counter restrictions, then
-        * all events are subject to and must call the
-        * put_excl_constraints() routine
-        */
-       if (cpuc->excl_cntrs)
-               intel_put_excl_constraints(cpuc, event);
-}
-
-static void intel_pebs_aliases_core2(struct perf_event *event)
-{
-       if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
-               /*
-                * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P
-                * (0x003c) so that we can use it with PEBS.
-                *
-                * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't
-                * PEBS capable. However we can use INST_RETIRED.ANY_P
-                * (0x00c0), which is a PEBS capable event, to get the same
-                * count.
-                *
-                * INST_RETIRED.ANY_P counts the number of cycles that retires
-                * CNTMASK instructions. By setting CNTMASK to a value (16)
-                * larger than the maximum number of instructions that can be
-                * retired per cycle (4) and then inverting the condition, we
-                * count all cycles that retire 16 or less instructions, which
-                * is every cycle.
-                *
-                * Thereby we gain a PEBS capable cycle counter.
-                */
-               u64 alt_config = X86_CONFIG(.event=0xc0, .inv=1, .cmask=16);
-
-               alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK);
-               event->hw.config = alt_config;
-       }
-}
-
-static void intel_pebs_aliases_snb(struct perf_event *event)
-{
-       if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
-               /*
-                * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P
-                * (0x003c) so that we can use it with PEBS.
-                *
-                * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't
-                * PEBS capable. However we can use UOPS_RETIRED.ALL
-                * (0x01c2), which is a PEBS capable event, to get the same
-                * count.
-                *
-                * UOPS_RETIRED.ALL counts the number of cycles that retires
-                * CNTMASK micro-ops. By setting CNTMASK to a value (16)
-                * larger than the maximum number of micro-ops that can be
-                * retired per cycle (4) and then inverting the condition, we
-                * count all cycles that retire 16 or less micro-ops, which
-                * is every cycle.
-                *
-                * Thereby we gain a PEBS capable cycle counter.
-                */
-               u64 alt_config = X86_CONFIG(.event=0xc2, .umask=0x01, .inv=1, .cmask=16);
-
-               alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK);
-               event->hw.config = alt_config;
-       }
-}
-
-static void intel_pebs_aliases_precdist(struct perf_event *event)
-{
-       if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) {
-               /*
-                * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P
-                * (0x003c) so that we can use it with PEBS.
-                *
-                * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't
-                * PEBS capable. However we can use INST_RETIRED.PREC_DIST
-                * (0x01c0), which is a PEBS capable event, to get the same
-                * count.
-                *
-                * The PREC_DIST event has special support to minimize sample
-                * shadowing effects. One drawback is that it can be
-                * only programmed on counter 1, but that seems like an
-                * acceptable trade off.
-                */
-               u64 alt_config = X86_CONFIG(.event=0xc0, .umask=0x01, .inv=1, .cmask=16);
-
-               alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK);
-               event->hw.config = alt_config;
-       }
-}
-
-static void intel_pebs_aliases_ivb(struct perf_event *event)
-{
-       if (event->attr.precise_ip < 3)
-               return intel_pebs_aliases_snb(event);
-       return intel_pebs_aliases_precdist(event);
-}
-
-static void intel_pebs_aliases_skl(struct perf_event *event)
-{
-       if (event->attr.precise_ip < 3)
-               return intel_pebs_aliases_core2(event);
-       return intel_pebs_aliases_precdist(event);
-}
-
-static unsigned long intel_pmu_free_running_flags(struct perf_event *event)
-{
-       unsigned long flags = x86_pmu.free_running_flags;
-
-       if (event->attr.use_clockid)
-               flags &= ~PERF_SAMPLE_TIME;
-       return flags;
-}
-
-static int intel_pmu_hw_config(struct perf_event *event)
-{
-       int ret = x86_pmu_hw_config(event);
-
-       if (ret)
-               return ret;
-
-       if (event->attr.precise_ip) {
-               if (!event->attr.freq) {
-                       event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD;
-                       if (!(event->attr.sample_type &
-                             ~intel_pmu_free_running_flags(event)))
-                               event->hw.flags |= PERF_X86_EVENT_FREERUNNING;
-               }
-               if (x86_pmu.pebs_aliases)
-                       x86_pmu.pebs_aliases(event);
-       }
-
-       if (needs_branch_stack(event)) {
-               ret = intel_pmu_setup_lbr_filter(event);
-               if (ret)
-                       return ret;
-
-               /*
-                * BTS is set up earlier in this path, so don't account twice
-                */
-               if (!intel_pmu_has_bts(event)) {
-                       /* disallow lbr if conflicting events are present */
-                       if (x86_add_exclusive(x86_lbr_exclusive_lbr))
-                               return -EBUSY;
-
-                       event->destroy = hw_perf_lbr_event_destroy;
-               }
-       }
-
-       if (event->attr.type != PERF_TYPE_RAW)
-               return 0;
-
-       if (!(event->attr.config & ARCH_PERFMON_EVENTSEL_ANY))
-               return 0;
-
-       if (x86_pmu.version < 3)
-               return -EINVAL;
-
-       if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
-               return -EACCES;
-
-       event->hw.config |= ARCH_PERFMON_EVENTSEL_ANY;
-
-       return 0;
-}
-
-struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
-{
-       if (x86_pmu.guest_get_msrs)
-               return x86_pmu.guest_get_msrs(nr);
-       *nr = 0;
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(perf_guest_get_msrs);
-
-static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
-
-       arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;
-       arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;
-       arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask;
-       /*
-        * If PMU counter has PEBS enabled it is not enough to disable counter
-        * on a guest entry since PEBS memory write can overshoot guest entry
-        * and corrupt guest memory. Disabling PEBS solves the problem.
-        */
-       arr[1].msr = MSR_IA32_PEBS_ENABLE;
-       arr[1].host = cpuc->pebs_enabled;
-       arr[1].guest = 0;
-
-       *nr = 2;
-       return arr;
-}
-
-static struct perf_guest_switch_msr *core_guest_get_msrs(int *nr)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct perf_guest_switch_msr *arr = cpuc->guest_switch_msrs;
-       int idx;
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++)  {
-               struct perf_event *event = cpuc->events[idx];
-
-               arr[idx].msr = x86_pmu_config_addr(idx);
-               arr[idx].host = arr[idx].guest = 0;
-
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-
-               arr[idx].host = arr[idx].guest =
-                       event->hw.config | ARCH_PERFMON_EVENTSEL_ENABLE;
-
-               if (event->attr.exclude_host)
-                       arr[idx].host &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
-               else if (event->attr.exclude_guest)
-                       arr[idx].guest &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
-       }
-
-       *nr = x86_pmu.num_counters;
-       return arr;
-}
-
-static void core_pmu_enable_event(struct perf_event *event)
-{
-       if (!event->attr.exclude_host)
-               x86_pmu_enable_event(event);
-}
-
-static void core_pmu_enable_all(int added)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       int idx;
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
-
-               if (!test_bit(idx, cpuc->active_mask) ||
-                               cpuc->events[idx]->attr.exclude_host)
-                       continue;
-
-               __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
-       }
-}
-
-static int hsw_hw_config(struct perf_event *event)
-{
-       int ret = intel_pmu_hw_config(event);
-
-       if (ret)
-               return ret;
-       if (!boot_cpu_has(X86_FEATURE_RTM) && !boot_cpu_has(X86_FEATURE_HLE))
-               return 0;
-       event->hw.config |= event->attr.config & (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED);
-
-       /*
-        * IN_TX/IN_TX-CP filters are not supported by the Haswell PMU with
-        * PEBS or in ANY thread mode. Since the results are non-sensical forbid
-        * this combination.
-        */
-       if ((event->hw.config & (HSW_IN_TX|HSW_IN_TX_CHECKPOINTED)) &&
-            ((event->hw.config & ARCH_PERFMON_EVENTSEL_ANY) ||
-             event->attr.precise_ip > 0))
-               return -EOPNOTSUPP;
-
-       if (event_is_checkpointed(event)) {
-               /*
-                * Sampling of checkpointed events can cause situations where
-                * the CPU constantly aborts because of a overflow, which is
-                * then checkpointed back and ignored. Forbid checkpointing
-                * for sampling.
-                *
-                * But still allow a long sampling period, so that perf stat
-                * from KVM works.
-                */
-               if (event->attr.sample_period > 0 &&
-                   event->attr.sample_period < 0x7fffffff)
-                       return -EOPNOTSUPP;
-       }
-       return 0;
-}
-
-static struct event_constraint counter2_constraint =
-                       EVENT_CONSTRAINT(0, 0x4, 0);
-
-static struct event_constraint *
-hsw_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
-                         struct perf_event *event)
-{
-       struct event_constraint *c;
-
-       c = intel_get_event_constraints(cpuc, idx, event);
-
-       /* Handle special quirk on in_tx_checkpointed only in counter 2 */
-       if (event->hw.config & HSW_IN_TX_CHECKPOINTED) {
-               if (c->idxmsk64 & (1U << 2))
-                       return &counter2_constraint;
-               return &emptyconstraint;
-       }
-
-       return c;
-}
-
-/*
- * Broadwell:
- *
- * The INST_RETIRED.ALL period always needs to have lowest 6 bits cleared
- * (BDM55) and it must not use a period smaller than 100 (BDM11). We combine
- * the two to enforce a minimum period of 128 (the smallest value that has bits
- * 0-5 cleared and >= 100).
- *
- * Because of how the code in x86_perf_event_set_period() works, the truncation
- * of the lower 6 bits is 'harmless' as we'll occasionally add a longer period
- * to make up for the 'lost' events due to carrying the 'error' in period_left.
- *
- * Therefore the effective (average) period matches the requested period,
- * despite coarser hardware granularity.
- */
-static unsigned bdw_limit_period(struct perf_event *event, unsigned left)
-{
-       if ((event->hw.config & INTEL_ARCH_EVENT_MASK) ==
-                       X86_CONFIG(.event=0xc0, .umask=0x01)) {
-               if (left < 128)
-                       left = 128;
-               left &= ~0x3fu;
-       }
-       return left;
-}
-
-PMU_FORMAT_ATTR(event, "config:0-7"    );
-PMU_FORMAT_ATTR(umask, "config:8-15"   );
-PMU_FORMAT_ATTR(edge,  "config:18"     );
-PMU_FORMAT_ATTR(pc,    "config:19"     );
-PMU_FORMAT_ATTR(any,   "config:21"     ); /* v3 + */
-PMU_FORMAT_ATTR(inv,   "config:23"     );
-PMU_FORMAT_ATTR(cmask, "config:24-31"  );
-PMU_FORMAT_ATTR(in_tx,  "config:32");
-PMU_FORMAT_ATTR(in_tx_cp, "config:33");
-
-static struct attribute *intel_arch_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_pc.attr,
-       &format_attr_inv.attr,
-       &format_attr_cmask.attr,
-       NULL,
-};
-
-ssize_t intel_event_sysfs_show(char *page, u64 config)
-{
-       u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT);
-
-       return x86_event_sysfs_show(page, config, event);
-}
-
-struct intel_shared_regs *allocate_shared_regs(int cpu)
-{
-       struct intel_shared_regs *regs;
-       int i;
-
-       regs = kzalloc_node(sizeof(struct intel_shared_regs),
-                           GFP_KERNEL, cpu_to_node(cpu));
-       if (regs) {
-               /*
-                * initialize the locks to keep lockdep happy
-                */
-               for (i = 0; i < EXTRA_REG_MAX; i++)
-                       raw_spin_lock_init(&regs->regs[i].lock);
-
-               regs->core_id = -1;
-       }
-       return regs;
-}
-
-static struct intel_excl_cntrs *allocate_excl_cntrs(int cpu)
-{
-       struct intel_excl_cntrs *c;
-
-       c = kzalloc_node(sizeof(struct intel_excl_cntrs),
-                        GFP_KERNEL, cpu_to_node(cpu));
-       if (c) {
-               raw_spin_lock_init(&c->lock);
-               c->core_id = -1;
-       }
-       return c;
-}
-
-static int intel_pmu_cpu_prepare(int cpu)
-{
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-
-       if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
-               cpuc->shared_regs = allocate_shared_regs(cpu);
-               if (!cpuc->shared_regs)
-                       goto err;
-       }
-
-       if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
-               size_t sz = X86_PMC_IDX_MAX * sizeof(struct event_constraint);
-
-               cpuc->constraint_list = kzalloc(sz, GFP_KERNEL);
-               if (!cpuc->constraint_list)
-                       goto err_shared_regs;
-
-               cpuc->excl_cntrs = allocate_excl_cntrs(cpu);
-               if (!cpuc->excl_cntrs)
-                       goto err_constraint_list;
-
-               cpuc->excl_thread_id = 0;
-       }
-
-       return NOTIFY_OK;
-
-err_constraint_list:
-       kfree(cpuc->constraint_list);
-       cpuc->constraint_list = NULL;
-
-err_shared_regs:
-       kfree(cpuc->shared_regs);
-       cpuc->shared_regs = NULL;
-
-err:
-       return NOTIFY_BAD;
-}
-
-static void intel_pmu_cpu_starting(int cpu)
-{
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-       int core_id = topology_core_id(cpu);
-       int i;
-
-       init_debug_store_on_cpu(cpu);
-       /*
-        * Deal with CPUs that don't clear their LBRs on power-up.
-        */
-       intel_pmu_lbr_reset();
-
-       cpuc->lbr_sel = NULL;
-
-       if (!cpuc->shared_regs)
-               return;
-
-       if (!(x86_pmu.flags & PMU_FL_NO_HT_SHARING)) {
-               for_each_cpu(i, topology_sibling_cpumask(cpu)) {
-                       struct intel_shared_regs *pc;
-
-                       pc = per_cpu(cpu_hw_events, i).shared_regs;
-                       if (pc && pc->core_id == core_id) {
-                               cpuc->kfree_on_online[0] = cpuc->shared_regs;
-                               cpuc->shared_regs = pc;
-                               break;
-                       }
-               }
-               cpuc->shared_regs->core_id = core_id;
-               cpuc->shared_regs->refcnt++;
-       }
-
-       if (x86_pmu.lbr_sel_map)
-               cpuc->lbr_sel = &cpuc->shared_regs->regs[EXTRA_REG_LBR];
-
-       if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
-               for_each_cpu(i, topology_sibling_cpumask(cpu)) {
-                       struct intel_excl_cntrs *c;
-
-                       c = per_cpu(cpu_hw_events, i).excl_cntrs;
-                       if (c && c->core_id == core_id) {
-                               cpuc->kfree_on_online[1] = cpuc->excl_cntrs;
-                               cpuc->excl_cntrs = c;
-                               cpuc->excl_thread_id = 1;
-                               break;
-                       }
-               }
-               cpuc->excl_cntrs->core_id = core_id;
-               cpuc->excl_cntrs->refcnt++;
-       }
-}
-
-static void free_excl_cntrs(int cpu)
-{
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-       struct intel_excl_cntrs *c;
-
-       c = cpuc->excl_cntrs;
-       if (c) {
-               if (c->core_id == -1 || --c->refcnt == 0)
-                       kfree(c);
-               cpuc->excl_cntrs = NULL;
-               kfree(cpuc->constraint_list);
-               cpuc->constraint_list = NULL;
-       }
-}
-
-static void intel_pmu_cpu_dying(int cpu)
-{
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
-       struct intel_shared_regs *pc;
-
-       pc = cpuc->shared_regs;
-       if (pc) {
-               if (pc->core_id == -1 || --pc->refcnt == 0)
-                       kfree(pc);
-               cpuc->shared_regs = NULL;
-       }
-
-       free_excl_cntrs(cpu);
-
-       fini_debug_store_on_cpu(cpu);
-}
-
-static void intel_pmu_sched_task(struct perf_event_context *ctx,
-                                bool sched_in)
-{
-       if (x86_pmu.pebs_active)
-               intel_pmu_pebs_sched_task(ctx, sched_in);
-       if (x86_pmu.lbr_nr)
-               intel_pmu_lbr_sched_task(ctx, sched_in);
-}
-
-PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
-
-PMU_FORMAT_ATTR(ldlat, "config1:0-15");
-
-PMU_FORMAT_ATTR(frontend, "config1:0-23");
-
-static struct attribute *intel_arch3_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_pc.attr,
-       &format_attr_any.attr,
-       &format_attr_inv.attr,
-       &format_attr_cmask.attr,
-       &format_attr_in_tx.attr,
-       &format_attr_in_tx_cp.attr,
-
-       &format_attr_offcore_rsp.attr, /* XXX do NHM/WSM + SNB breakout */
-       &format_attr_ldlat.attr, /* PEBS load latency */
-       NULL,
-};
-
-static struct attribute *skl_format_attr[] = {
-       &format_attr_frontend.attr,
-       NULL,
-};
-
-static __initconst const struct x86_pmu core_pmu = {
-       .name                   = "core",
-       .handle_irq             = x86_pmu_handle_irq,
-       .disable_all            = x86_pmu_disable_all,
-       .enable_all             = core_pmu_enable_all,
-       .enable                 = core_pmu_enable_event,
-       .disable                = x86_pmu_disable_event,
-       .hw_config              = x86_pmu_hw_config,
-       .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_ARCH_PERFMON_EVENTSEL0,
-       .perfctr                = MSR_ARCH_PERFMON_PERFCTR0,
-       .event_map              = intel_pmu_event_map,
-       .max_events             = ARRAY_SIZE(intel_perfmon_event_map),
-       .apic                   = 1,
-       .free_running_flags     = PEBS_FREERUNNING_FLAGS,
-
-       /*
-        * Intel PMCs cannot be accessed sanely above 32-bit width,
-        * so we install an artificial 1<<31 period regardless of
-        * the generic event period:
-        */
-       .max_period             = (1ULL<<31) - 1,
-       .get_event_constraints  = intel_get_event_constraints,
-       .put_event_constraints  = intel_put_event_constraints,
-       .event_constraints      = intel_core_event_constraints,
-       .guest_get_msrs         = core_guest_get_msrs,
-       .format_attrs           = intel_arch_formats_attr,
-       .events_sysfs_show      = intel_event_sysfs_show,
-
-       /*
-        * Virtual (or funny metal) CPU can define x86_pmu.extra_regs
-        * together with PMU version 1 and thus be using core_pmu with
-        * shared_regs. We need following callbacks here to allocate
-        * it properly.
-        */
-       .cpu_prepare            = intel_pmu_cpu_prepare,
-       .cpu_starting           = intel_pmu_cpu_starting,
-       .cpu_dying              = intel_pmu_cpu_dying,
-};
-
-static __initconst const struct x86_pmu intel_pmu = {
-       .name                   = "Intel",
-       .handle_irq             = intel_pmu_handle_irq,
-       .disable_all            = intel_pmu_disable_all,
-       .enable_all             = intel_pmu_enable_all,
-       .enable                 = intel_pmu_enable_event,
-       .disable                = intel_pmu_disable_event,
-       .hw_config              = intel_pmu_hw_config,
-       .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_ARCH_PERFMON_EVENTSEL0,
-       .perfctr                = MSR_ARCH_PERFMON_PERFCTR0,
-       .event_map              = intel_pmu_event_map,
-       .max_events             = ARRAY_SIZE(intel_perfmon_event_map),
-       .apic                   = 1,
-       .free_running_flags     = PEBS_FREERUNNING_FLAGS,
-       /*
-        * Intel PMCs cannot be accessed sanely above 32 bit width,
-        * so we install an artificial 1<<31 period regardless of
-        * the generic event period:
-        */
-       .max_period             = (1ULL << 31) - 1,
-       .get_event_constraints  = intel_get_event_constraints,
-       .put_event_constraints  = intel_put_event_constraints,
-       .pebs_aliases           = intel_pebs_aliases_core2,
-
-       .format_attrs           = intel_arch3_formats_attr,
-       .events_sysfs_show      = intel_event_sysfs_show,
-
-       .cpu_prepare            = intel_pmu_cpu_prepare,
-       .cpu_starting           = intel_pmu_cpu_starting,
-       .cpu_dying              = intel_pmu_cpu_dying,
-       .guest_get_msrs         = intel_guest_get_msrs,
-       .sched_task             = intel_pmu_sched_task,
-};
-
-static __init void intel_clovertown_quirk(void)
-{
-       /*
-        * PEBS is unreliable due to:
-        *
-        *   AJ67  - PEBS may experience CPL leaks
-        *   AJ68  - PEBS PMI may be delayed by one event
-        *   AJ69  - GLOBAL_STATUS[62] will only be set when DEBUGCTL[12]
-        *   AJ106 - FREEZE_LBRS_ON_PMI doesn't work in combination with PEBS
-        *
-        * AJ67 could be worked around by restricting the OS/USR flags.
-        * AJ69 could be worked around by setting PMU_FREEZE_ON_PMI.
-        *
-        * AJ106 could possibly be worked around by not allowing LBR
-        *       usage from PEBS, including the fixup.
-        * AJ68  could possibly be worked around by always programming
-        *       a pebs_event_reset[0] value and coping with the lost events.
-        *
-        * But taken together it might just make sense to not enable PEBS on
-        * these chips.
-        */
-       pr_warn("PEBS disabled due to CPU errata\n");
-       x86_pmu.pebs = 0;
-       x86_pmu.pebs_constraints = NULL;
-}
-
-static int intel_snb_pebs_broken(int cpu)
-{
-       u32 rev = UINT_MAX; /* default to broken for unknown models */
-
-       switch (cpu_data(cpu).x86_model) {
-       case 42: /* SNB */
-               rev = 0x28;
-               break;
-
-       case 45: /* SNB-EP */
-               switch (cpu_data(cpu).x86_mask) {
-               case 6: rev = 0x618; break;
-               case 7: rev = 0x70c; break;
-               }
-       }
-
-       return (cpu_data(cpu).microcode < rev);
-}
-
-static void intel_snb_check_microcode(void)
-{
-       int pebs_broken = 0;
-       int cpu;
-
-       get_online_cpus();
-       for_each_online_cpu(cpu) {
-               if ((pebs_broken = intel_snb_pebs_broken(cpu)))
-                       break;
-       }
-       put_online_cpus();
-
-       if (pebs_broken == x86_pmu.pebs_broken)
-               return;
-
-       /*
-        * Serialized by the microcode lock..
-        */
-       if (x86_pmu.pebs_broken) {
-               pr_info("PEBS enabled due to microcode update\n");
-               x86_pmu.pebs_broken = 0;
-       } else {
-               pr_info("PEBS disabled due to CPU errata, please upgrade microcode\n");
-               x86_pmu.pebs_broken = 1;
-       }
-}
-
-/*
- * Under certain circumstances, access certain MSR may cause #GP.
- * The function tests if the input MSR can be safely accessed.
- */
-static bool check_msr(unsigned long msr, u64 mask)
-{
-       u64 val_old, val_new, val_tmp;
-
-       /*
-        * Read the current value, change it and read it back to see if it
-        * matches, this is needed to detect certain hardware emulators
-        * (qemu/kvm) that don't trap on the MSR access and always return 0s.
-        */
-       if (rdmsrl_safe(msr, &val_old))
-               return false;
-
-       /*
-        * Only change the bits which can be updated by wrmsrl.
-        */
-       val_tmp = val_old ^ mask;
-       if (wrmsrl_safe(msr, val_tmp) ||
-           rdmsrl_safe(msr, &val_new))
-               return false;
-
-       if (val_new != val_tmp)
-               return false;
-
-       /* Here it's sure that the MSR can be safely accessed.
-        * Restore the old value and return.
-        */
-       wrmsrl(msr, val_old);
-
-       return true;
-}
-
-static __init void intel_sandybridge_quirk(void)
-{
-       x86_pmu.check_microcode = intel_snb_check_microcode;
-       intel_snb_check_microcode();
-}
-
-static const struct { int id; char *name; } intel_arch_events_map[] __initconst = {
-       { PERF_COUNT_HW_CPU_CYCLES, "cpu cycles" },
-       { PERF_COUNT_HW_INSTRUCTIONS, "instructions" },
-       { PERF_COUNT_HW_BUS_CYCLES, "bus cycles" },
-       { PERF_COUNT_HW_CACHE_REFERENCES, "cache references" },
-       { PERF_COUNT_HW_CACHE_MISSES, "cache misses" },
-       { PERF_COUNT_HW_BRANCH_INSTRUCTIONS, "branch instructions" },
-       { PERF_COUNT_HW_BRANCH_MISSES, "branch misses" },
-};
-
-static __init void intel_arch_events_quirk(void)
-{
-       int bit;
-
-       /* disable event that reported as not presend by cpuid */
-       for_each_set_bit(bit, x86_pmu.events_mask, ARRAY_SIZE(intel_arch_events_map)) {
-               intel_perfmon_event_map[intel_arch_events_map[bit].id] = 0;
-               pr_warn("CPUID marked event: \'%s\' unavailable\n",
-                       intel_arch_events_map[bit].name);
-       }
-}
-
-static __init void intel_nehalem_quirk(void)
-{
-       union cpuid10_ebx ebx;
-
-       ebx.full = x86_pmu.events_maskl;
-       if (ebx.split.no_branch_misses_retired) {
-               /*
-                * Erratum AAJ80 detected, we work it around by using
-                * the BR_MISP_EXEC.ANY event. This will over-count
-                * branch-misses, but it's still much better than the
-                * architectural event which is often completely bogus:
-                */
-               intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
-               ebx.split.no_branch_misses_retired = 0;
-               x86_pmu.events_maskl = ebx.full;
-               pr_info("CPU erratum AAJ80 worked around\n");
-       }
-}
-
-/*
- * enable software workaround for errata:
- * SNB: BJ122
- * IVB: BV98
- * HSW: HSD29
- *
- * Only needed when HT is enabled. However detecting
- * if HT is enabled is difficult (model specific). So instead,
- * we enable the workaround in the early boot, and verify if
- * it is needed in a later initcall phase once we have valid
- * topology information to check if HT is actually enabled
- */
-static __init void intel_ht_bug(void)
-{
-       x86_pmu.flags |= PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED;
-
-       x86_pmu.start_scheduling = intel_start_scheduling;
-       x86_pmu.commit_scheduling = intel_commit_scheduling;
-       x86_pmu.stop_scheduling = intel_stop_scheduling;
-}
-
-EVENT_ATTR_STR(mem-loads,      mem_ld_hsw,     "event=0xcd,umask=0x1,ldlat=3");
-EVENT_ATTR_STR(mem-stores,     mem_st_hsw,     "event=0xd0,umask=0x82")
-
-/* Haswell special events */
-EVENT_ATTR_STR(tx-start,       tx_start,       "event=0xc9,umask=0x1");
-EVENT_ATTR_STR(tx-commit,      tx_commit,      "event=0xc9,umask=0x2");
-EVENT_ATTR_STR(tx-abort,       tx_abort,       "event=0xc9,umask=0x4");
-EVENT_ATTR_STR(tx-capacity,    tx_capacity,    "event=0x54,umask=0x2");
-EVENT_ATTR_STR(tx-conflict,    tx_conflict,    "event=0x54,umask=0x1");
-EVENT_ATTR_STR(el-start,       el_start,       "event=0xc8,umask=0x1");
-EVENT_ATTR_STR(el-commit,      el_commit,      "event=0xc8,umask=0x2");
-EVENT_ATTR_STR(el-abort,       el_abort,       "event=0xc8,umask=0x4");
-EVENT_ATTR_STR(el-capacity,    el_capacity,    "event=0x54,umask=0x2");
-EVENT_ATTR_STR(el-conflict,    el_conflict,    "event=0x54,umask=0x1");
-EVENT_ATTR_STR(cycles-t,       cycles_t,       "event=0x3c,in_tx=1");
-EVENT_ATTR_STR(cycles-ct,      cycles_ct,      "event=0x3c,in_tx=1,in_tx_cp=1");
-
-static struct attribute *hsw_events_attrs[] = {
-       EVENT_PTR(tx_start),
-       EVENT_PTR(tx_commit),
-       EVENT_PTR(tx_abort),
-       EVENT_PTR(tx_capacity),
-       EVENT_PTR(tx_conflict),
-       EVENT_PTR(el_start),
-       EVENT_PTR(el_commit),
-       EVENT_PTR(el_abort),
-       EVENT_PTR(el_capacity),
-       EVENT_PTR(el_conflict),
-       EVENT_PTR(cycles_t),
-       EVENT_PTR(cycles_ct),
-       EVENT_PTR(mem_ld_hsw),
-       EVENT_PTR(mem_st_hsw),
-       NULL
-};
-
-__init int intel_pmu_init(void)
-{
-       union cpuid10_edx edx;
-       union cpuid10_eax eax;
-       union cpuid10_ebx ebx;
-       struct event_constraint *c;
-       unsigned int unused;
-       struct extra_reg *er;
-       int version, i;
-
-       if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-               switch (boot_cpu_data.x86) {
-               case 0x6:
-                       return p6_pmu_init();
-               case 0xb:
-                       return knc_pmu_init();
-               case 0xf:
-                       return p4_pmu_init();
-               }
-               return -ENODEV;
-       }
-
-       /*
-        * Check whether the Architectural PerfMon supports
-        * Branch Misses Retired hw_event or not.
-        */
-       cpuid(10, &eax.full, &ebx.full, &unused, &edx.full);
-       if (eax.split.mask_length < ARCH_PERFMON_EVENTS_COUNT)
-               return -ENODEV;
-
-       version = eax.split.version_id;
-       if (version < 2)
-               x86_pmu = core_pmu;
-       else
-               x86_pmu = intel_pmu;
-
-       x86_pmu.version                 = version;
-       x86_pmu.num_counters            = eax.split.num_counters;
-       x86_pmu.cntval_bits             = eax.split.bit_width;
-       x86_pmu.cntval_mask             = (1ULL << eax.split.bit_width) - 1;
-
-       x86_pmu.events_maskl            = ebx.full;
-       x86_pmu.events_mask_len         = eax.split.mask_length;
-
-       x86_pmu.max_pebs_events         = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters);
-
-       /*
-        * Quirk: v2 perfmon does not report fixed-purpose events, so
-        * assume at least 3 events:
-        */
-       if (version > 1)
-               x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3);
-
-       if (boot_cpu_has(X86_FEATURE_PDCM)) {
-               u64 capabilities;
-
-               rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities);
-               x86_pmu.intel_cap.capabilities = capabilities;
-       }
-
-       intel_ds_init();
-
-       x86_add_quirk(intel_arch_events_quirk); /* Install first, so it runs last */
-
-       /*
-        * Install the hw-cache-events table:
-        */
-       switch (boot_cpu_data.x86_model) {
-       case 14: /* 65nm Core "Yonah" */
-               pr_cont("Core events, ");
-               break;
-
-       case 15: /* 65nm Core2 "Merom"          */
-               x86_add_quirk(intel_clovertown_quirk);
-       case 22: /* 65nm Core2 "Merom-L"        */
-       case 23: /* 45nm Core2 "Penryn"         */
-       case 29: /* 45nm Core2 "Dunnington (MP) */
-               memcpy(hw_cache_event_ids, core2_hw_cache_event_ids,
-                      sizeof(hw_cache_event_ids));
-
-               intel_pmu_lbr_init_core();
-
-               x86_pmu.event_constraints = intel_core2_event_constraints;
-               x86_pmu.pebs_constraints = intel_core2_pebs_event_constraints;
-               pr_cont("Core2 events, ");
-               break;
-
-       case 30: /* 45nm Nehalem    */
-       case 26: /* 45nm Nehalem-EP */
-       case 46: /* 45nm Nehalem-EX */
-               memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
-                      sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
-                      sizeof(hw_cache_extra_regs));
-
-               intel_pmu_lbr_init_nhm();
-
-               x86_pmu.event_constraints = intel_nehalem_event_constraints;
-               x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
-               x86_pmu.enable_all = intel_pmu_nhm_enable_all;
-               x86_pmu.extra_regs = intel_nehalem_extra_regs;
-
-               x86_pmu.cpu_events = nhm_events_attrs;
-
-               /* UOPS_ISSUED.STALLED_CYCLES */
-               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
-                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
-               /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
-               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
-                       X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
-
-               x86_add_quirk(intel_nehalem_quirk);
-
-               pr_cont("Nehalem events, ");
-               break;
-
-       case 28: /* 45nm Atom "Pineview"   */
-       case 38: /* 45nm Atom "Lincroft"   */
-       case 39: /* 32nm Atom "Penwell"    */
-       case 53: /* 32nm Atom "Cloverview" */
-       case 54: /* 32nm Atom "Cedarview"  */
-               memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
-                      sizeof(hw_cache_event_ids));
-
-               intel_pmu_lbr_init_atom();
-
-               x86_pmu.event_constraints = intel_gen_event_constraints;
-               x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints;
-               x86_pmu.pebs_aliases = intel_pebs_aliases_core2;
-               pr_cont("Atom events, ");
-               break;
-
-       case 55: /* 22nm Atom "Silvermont"                */
-       case 76: /* 14nm Atom "Airmont"                   */
-       case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
-               memcpy(hw_cache_event_ids, slm_hw_cache_event_ids,
-                       sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
-                      sizeof(hw_cache_extra_regs));
-
-               intel_pmu_lbr_init_atom();
-
-               x86_pmu.event_constraints = intel_slm_event_constraints;
-               x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
-               x86_pmu.extra_regs = intel_slm_extra_regs;
-               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               pr_cont("Silvermont events, ");
-               break;
-
-       case 37: /* 32nm Westmere    */
-       case 44: /* 32nm Westmere-EP */
-       case 47: /* 32nm Westmere-EX */
-               memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
-                      sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
-                      sizeof(hw_cache_extra_regs));
-
-               intel_pmu_lbr_init_nhm();
-
-               x86_pmu.event_constraints = intel_westmere_event_constraints;
-               x86_pmu.enable_all = intel_pmu_nhm_enable_all;
-               x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
-               x86_pmu.extra_regs = intel_westmere_extra_regs;
-               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-
-               x86_pmu.cpu_events = nhm_events_attrs;
-
-               /* UOPS_ISSUED.STALLED_CYCLES */
-               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
-                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
-               /* UOPS_EXECUTED.CORE_ACTIVE_CYCLES,c=1,i=1 */
-               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
-                       X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
-
-               pr_cont("Westmere events, ");
-               break;
-
-       case 42: /* 32nm SandyBridge         */
-       case 45: /* 32nm SandyBridge-E/EN/EP */
-               x86_add_quirk(intel_sandybridge_quirk);
-               x86_add_quirk(intel_ht_bug);
-               memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
-                      sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
-                      sizeof(hw_cache_extra_regs));
-
-               intel_pmu_lbr_init_snb();
-
-               x86_pmu.event_constraints = intel_snb_event_constraints;
-               x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
-               x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
-               if (boot_cpu_data.x86_model == 45)
-                       x86_pmu.extra_regs = intel_snbep_extra_regs;
-               else
-                       x86_pmu.extra_regs = intel_snb_extra_regs;
-
-
-               /* all extra regs are per-cpu when HT is on */
-               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-
-               x86_pmu.cpu_events = snb_events_attrs;
-
-               /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
-               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
-                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
-               /* UOPS_DISPATCHED.THREAD,c=1,i=1 to count stall cycles*/
-               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
-                       X86_CONFIG(.event=0xb1, .umask=0x01, .inv=1, .cmask=1);
-
-               pr_cont("SandyBridge events, ");
-               break;
-
-       case 58: /* 22nm IvyBridge       */
-       case 62: /* 22nm IvyBridge-EP/EX */
-               x86_add_quirk(intel_ht_bug);
-               memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
-                      sizeof(hw_cache_event_ids));
-               /* dTLB-load-misses on IVB is different than SNB */
-               hw_cache_event_ids[C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = 0x8108; /* DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK */
-
-               memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
-                      sizeof(hw_cache_extra_regs));
-
-               intel_pmu_lbr_init_snb();
-
-               x86_pmu.event_constraints = intel_ivb_event_constraints;
-               x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
-               x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
-               x86_pmu.pebs_prec_dist = true;
-               if (boot_cpu_data.x86_model == 62)
-                       x86_pmu.extra_regs = intel_snbep_extra_regs;
-               else
-                       x86_pmu.extra_regs = intel_snb_extra_regs;
-               /* all extra regs are per-cpu when HT is on */
-               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-
-               x86_pmu.cpu_events = snb_events_attrs;
-
-               /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
-               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
-                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
-
-               pr_cont("IvyBridge events, ");
-               break;
-
-
-       case 60: /* 22nm Haswell Core */
-       case 63: /* 22nm Haswell Server */
-       case 69: /* 22nm Haswell ULT */
-       case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
-               x86_add_quirk(intel_ht_bug);
-               x86_pmu.late_ack = true;
-               memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
-
-               intel_pmu_lbr_init_hsw();
-
-               x86_pmu.event_constraints = intel_hsw_event_constraints;
-               x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
-               x86_pmu.extra_regs = intel_snbep_extra_regs;
-               x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
-               x86_pmu.pebs_prec_dist = true;
-               /* all extra regs are per-cpu when HT is on */
-               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-
-               x86_pmu.hw_config = hsw_hw_config;
-               x86_pmu.get_event_constraints = hsw_get_event_constraints;
-               x86_pmu.cpu_events = hsw_events_attrs;
-               x86_pmu.lbr_double_abort = true;
-               pr_cont("Haswell events, ");
-               break;
-
-       case 61: /* 14nm Broadwell Core-M */
-       case 86: /* 14nm Broadwell Xeon D */
-       case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
-       case 79: /* 14nm Broadwell Server */
-               x86_pmu.late_ack = true;
-               memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
-
-               /* L3_MISS_LOCAL_DRAM is BIT(26) in Broadwell */
-               hw_cache_extra_regs[C(LL)][C(OP_READ)][C(RESULT_MISS)] = HSW_DEMAND_READ |
-                                                                        BDW_L3_MISS|HSW_SNOOP_DRAM;
-               hw_cache_extra_regs[C(LL)][C(OP_WRITE)][C(RESULT_MISS)] = HSW_DEMAND_WRITE|BDW_L3_MISS|
-                                                                         HSW_SNOOP_DRAM;
-               hw_cache_extra_regs[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)] = HSW_DEMAND_READ|
-                                                                            BDW_L3_MISS_LOCAL|HSW_SNOOP_DRAM;
-               hw_cache_extra_regs[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = HSW_DEMAND_WRITE|
-                                                                             BDW_L3_MISS_LOCAL|HSW_SNOOP_DRAM;
-
-               intel_pmu_lbr_init_hsw();
-
-               x86_pmu.event_constraints = intel_bdw_event_constraints;
-               x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
-               x86_pmu.extra_regs = intel_snbep_extra_regs;
-               x86_pmu.pebs_aliases = intel_pebs_aliases_ivb;
-               x86_pmu.pebs_prec_dist = true;
-               /* all extra regs are per-cpu when HT is on */
-               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-
-               x86_pmu.hw_config = hsw_hw_config;
-               x86_pmu.get_event_constraints = hsw_get_event_constraints;
-               x86_pmu.cpu_events = hsw_events_attrs;
-               x86_pmu.limit_period = bdw_limit_period;
-               pr_cont("Broadwell events, ");
-               break;
-
-       case 87: /* Knights Landing Xeon Phi */
-               memcpy(hw_cache_event_ids,
-                      slm_hw_cache_event_ids, sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs,
-                      knl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
-               intel_pmu_lbr_init_knl();
-
-               x86_pmu.event_constraints = intel_slm_event_constraints;
-               x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
-               x86_pmu.extra_regs = intel_knl_extra_regs;
-
-               /* all extra regs are per-cpu when HT is on */
-               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-
-               pr_cont("Knights Landing events, ");
-               break;
-
-       case 78: /* 14nm Skylake Mobile */
-       case 94: /* 14nm Skylake Desktop */
-               x86_pmu.late_ack = true;
-               memcpy(hw_cache_event_ids, skl_hw_cache_event_ids, sizeof(hw_cache_event_ids));
-               memcpy(hw_cache_extra_regs, skl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
-               intel_pmu_lbr_init_skl();
-
-               x86_pmu.event_constraints = intel_skl_event_constraints;
-               x86_pmu.pebs_constraints = intel_skl_pebs_event_constraints;
-               x86_pmu.extra_regs = intel_skl_extra_regs;
-               x86_pmu.pebs_aliases = intel_pebs_aliases_skl;
-               x86_pmu.pebs_prec_dist = true;
-               /* all extra regs are per-cpu when HT is on */
-               x86_pmu.flags |= PMU_FL_HAS_RSP_1;
-               x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-
-               x86_pmu.hw_config = hsw_hw_config;
-               x86_pmu.get_event_constraints = hsw_get_event_constraints;
-               x86_pmu.format_attrs = merge_attr(intel_arch3_formats_attr,
-                                                 skl_format_attr);
-               WARN_ON(!x86_pmu.format_attrs);
-               x86_pmu.cpu_events = hsw_events_attrs;
-               pr_cont("Skylake events, ");
-               break;
-
-       default:
-               switch (x86_pmu.version) {
-               case 1:
-                       x86_pmu.event_constraints = intel_v1_event_constraints;
-                       pr_cont("generic architected perfmon v1, ");
-                       break;
-               default:
-                       /*
-                        * default constraints for v2 and up
-                        */
-                       x86_pmu.event_constraints = intel_gen_event_constraints;
-                       pr_cont("generic architected perfmon, ");
-                       break;
-               }
-       }
-
-       if (x86_pmu.num_counters > INTEL_PMC_MAX_GENERIC) {
-               WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
-                    x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
-               x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
-       }
-       x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
-
-       if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
-               WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
-                    x86_pmu.num_counters_fixed, INTEL_PMC_MAX_FIXED);
-               x86_pmu.num_counters_fixed = INTEL_PMC_MAX_FIXED;
-       }
-
-       x86_pmu.intel_ctrl |=
-               ((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
-
-       if (x86_pmu.event_constraints) {
-               /*
-                * event on fixed counter2 (REF_CYCLES) only works on this
-                * counter, so do not extend mask to generic counters
-                */
-               for_each_event_constraint(c, x86_pmu.event_constraints) {
-                       if (c->cmask == FIXED_EVENT_FLAGS
-                           && c->idxmsk64 != INTEL_PMC_MSK_FIXED_REF_CYCLES) {
-                               c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
-                       }
-                       c->idxmsk64 &=
-                               ~(~0UL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed));
-                       c->weight = hweight64(c->idxmsk64);
-               }
-       }
-
-       /*
-        * Access LBR MSR may cause #GP under certain circumstances.
-        * E.g. KVM doesn't support LBR MSR
-        * Check all LBT MSR here.
-        * Disable LBR access if any LBR MSRs can not be accessed.
-        */
-       if (x86_pmu.lbr_nr && !check_msr(x86_pmu.lbr_tos, 0x3UL))
-               x86_pmu.lbr_nr = 0;
-       for (i = 0; i < x86_pmu.lbr_nr; i++) {
-               if (!(check_msr(x86_pmu.lbr_from + i, 0xffffUL) &&
-                     check_msr(x86_pmu.lbr_to + i, 0xffffUL)))
-                       x86_pmu.lbr_nr = 0;
-       }
-
-       /*
-        * Access extra MSR may cause #GP under certain circumstances.
-        * E.g. KVM doesn't support offcore event
-        * Check all extra_regs here.
-        */
-       if (x86_pmu.extra_regs) {
-               for (er = x86_pmu.extra_regs; er->msr; er++) {
-                       er->extra_msr_access = check_msr(er->msr, 0x11UL);
-                       /* Disable LBR select mapping */
-                       if ((er->idx == EXTRA_REG_LBR) && !er->extra_msr_access)
-                               x86_pmu.lbr_sel_map = NULL;
-               }
-       }
-
-       /* Support full width counters using alternative MSR range */
-       if (x86_pmu.intel_cap.full_width_write) {
-               x86_pmu.max_period = x86_pmu.cntval_mask;
-               x86_pmu.perfctr = MSR_IA32_PMC0;
-               pr_cont("full-width counters, ");
-       }
-
-       return 0;
-}
-
-/*
- * HT bug: phase 2 init
- * Called once we have valid topology information to check
- * whether or not HT is enabled
- * If HT is off, then we disable the workaround
- */
-static __init int fixup_ht_bug(void)
-{
-       int cpu = smp_processor_id();
-       int w, c;
-       /*
-        * problem not present on this CPU model, nothing to do
-        */
-       if (!(x86_pmu.flags & PMU_FL_EXCL_ENABLED))
-               return 0;
-
-       w = cpumask_weight(topology_sibling_cpumask(cpu));
-       if (w > 1) {
-               pr_info("PMU erratum BJ122, BV98, HSD29 worked around, HT is on\n");
-               return 0;
-       }
-
-       if (lockup_detector_suspend() != 0) {
-               pr_debug("failed to disable PMU erratum BJ122, BV98, HSD29 workaround\n");
-               return 0;
-       }
-
-       x86_pmu.flags &= ~(PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED);
-
-       x86_pmu.start_scheduling = NULL;
-       x86_pmu.commit_scheduling = NULL;
-       x86_pmu.stop_scheduling = NULL;
-
-       lockup_detector_resume();
-
-       get_online_cpus();
-
-       for_each_online_cpu(c) {
-               free_excl_cntrs(c);
-       }
-
-       put_online_cpus();
-       pr_info("PMU erratum BJ122, BV98, HSD29 workaround disabled, HT off\n");
-       return 0;
-}
-subsys_initcall(fixup_ht_bug)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_bts.c b/arch/x86/kernel/cpu/perf_event_intel_bts.c
deleted file mode 100644 (file)
index 2cad71d..0000000
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * BTS PMU driver for perf
- * Copyright (c) 2013-2014, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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.
- */
-
-#undef DEBUG
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/bitops.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/debugfs.h>
-#include <linux/device.h>
-#include <linux/coredump.h>
-
-#include <asm-generic/sizes.h>
-#include <asm/perf_event.h>
-
-#include "perf_event.h"
-
-struct bts_ctx {
-       struct perf_output_handle       handle;
-       struct debug_store              ds_back;
-       int                             started;
-};
-
-static DEFINE_PER_CPU(struct bts_ctx, bts_ctx);
-
-#define BTS_RECORD_SIZE                24
-#define BTS_SAFETY_MARGIN      4080
-
-struct bts_phys {
-       struct page     *page;
-       unsigned long   size;
-       unsigned long   offset;
-       unsigned long   displacement;
-};
-
-struct bts_buffer {
-       size_t          real_size;      /* multiple of BTS_RECORD_SIZE */
-       unsigned int    nr_pages;
-       unsigned int    nr_bufs;
-       unsigned int    cur_buf;
-       bool            snapshot;
-       local_t         data_size;
-       local_t         lost;
-       local_t         head;
-       unsigned long   end;
-       void            **data_pages;
-       struct bts_phys buf[0];
-};
-
-struct pmu bts_pmu;
-
-static size_t buf_size(struct page *page)
-{
-       return 1 << (PAGE_SHIFT + page_private(page));
-}
-
-static void *
-bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
-{
-       struct bts_buffer *buf;
-       struct page *page;
-       int node = (cpu == -1) ? cpu : cpu_to_node(cpu);
-       unsigned long offset;
-       size_t size = nr_pages << PAGE_SHIFT;
-       int pg, nbuf, pad;
-
-       /* count all the high order buffers */
-       for (pg = 0, nbuf = 0; pg < nr_pages;) {
-               page = virt_to_page(pages[pg]);
-               if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1))
-                       return NULL;
-               pg += 1 << page_private(page);
-               nbuf++;
-       }
-
-       /*
-        * to avoid interrupts in overwrite mode, only allow one physical
-        */
-       if (overwrite && nbuf > 1)
-               return NULL;
-
-       buf = kzalloc_node(offsetof(struct bts_buffer, buf[nbuf]), GFP_KERNEL, node);
-       if (!buf)
-               return NULL;
-
-       buf->nr_pages = nr_pages;
-       buf->nr_bufs = nbuf;
-       buf->snapshot = overwrite;
-       buf->data_pages = pages;
-       buf->real_size = size - size % BTS_RECORD_SIZE;
-
-       for (pg = 0, nbuf = 0, offset = 0, pad = 0; nbuf < buf->nr_bufs; nbuf++) {
-               unsigned int __nr_pages;
-
-               page = virt_to_page(pages[pg]);
-               __nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
-               buf->buf[nbuf].page = page;
-               buf->buf[nbuf].offset = offset;
-               buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
-               buf->buf[nbuf].size = buf_size(page) - buf->buf[nbuf].displacement;
-               pad = buf->buf[nbuf].size % BTS_RECORD_SIZE;
-               buf->buf[nbuf].size -= pad;
-
-               pg += __nr_pages;
-               offset += __nr_pages << PAGE_SHIFT;
-       }
-
-       return buf;
-}
-
-static void bts_buffer_free_aux(void *data)
-{
-       kfree(data);
-}
-
-static unsigned long bts_buffer_offset(struct bts_buffer *buf, unsigned int idx)
-{
-       return buf->buf[idx].offset + buf->buf[idx].displacement;
-}
-
-static void
-bts_config_buffer(struct bts_buffer *buf)
-{
-       int cpu = raw_smp_processor_id();
-       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
-       struct bts_phys *phys = &buf->buf[buf->cur_buf];
-       unsigned long index, thresh = 0, end = phys->size;
-       struct page *page = phys->page;
-
-       index = local_read(&buf->head);
-
-       if (!buf->snapshot) {
-               if (buf->end < phys->offset + buf_size(page))
-                       end = buf->end - phys->offset - phys->displacement;
-
-               index -= phys->offset + phys->displacement;
-
-               if (end - index > BTS_SAFETY_MARGIN)
-                       thresh = end - BTS_SAFETY_MARGIN;
-               else if (end - index > BTS_RECORD_SIZE)
-                       thresh = end - BTS_RECORD_SIZE;
-               else
-                       thresh = end;
-       }
-
-       ds->bts_buffer_base = (u64)(long)page_address(page) + phys->displacement;
-       ds->bts_index = ds->bts_buffer_base + index;
-       ds->bts_absolute_maximum = ds->bts_buffer_base + end;
-       ds->bts_interrupt_threshold = !buf->snapshot
-               ? ds->bts_buffer_base + thresh
-               : ds->bts_absolute_maximum + BTS_RECORD_SIZE;
-}
-
-static void bts_buffer_pad_out(struct bts_phys *phys, unsigned long head)
-{
-       unsigned long index = head - phys->offset;
-
-       memset(page_address(phys->page) + index, 0, phys->size - index);
-}
-
-static bool bts_buffer_is_full(struct bts_buffer *buf, struct bts_ctx *bts)
-{
-       if (buf->snapshot)
-               return false;
-
-       if (local_read(&buf->data_size) >= bts->handle.size ||
-           bts->handle.size - local_read(&buf->data_size) < BTS_RECORD_SIZE)
-               return true;
-
-       return false;
-}
-
-static void bts_update(struct bts_ctx *bts)
-{
-       int cpu = raw_smp_processor_id();
-       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
-       struct bts_buffer *buf = perf_get_aux(&bts->handle);
-       unsigned long index = ds->bts_index - ds->bts_buffer_base, old, head;
-
-       if (!buf)
-               return;
-
-       head = index + bts_buffer_offset(buf, buf->cur_buf);
-       old = local_xchg(&buf->head, head);
-
-       if (!buf->snapshot) {
-               if (old == head)
-                       return;
-
-               if (ds->bts_index >= ds->bts_absolute_maximum)
-                       local_inc(&buf->lost);
-
-               /*
-                * old and head are always in the same physical buffer, so we
-                * can subtract them to get the data size.
-                */
-               local_add(head - old, &buf->data_size);
-       } else {
-               local_set(&buf->data_size, head);
-       }
-}
-
-static void __bts_event_start(struct perf_event *event)
-{
-       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-       struct bts_buffer *buf = perf_get_aux(&bts->handle);
-       u64 config = 0;
-
-       if (!buf || bts_buffer_is_full(buf, bts))
-               return;
-
-       event->hw.itrace_started = 1;
-       event->hw.state = 0;
-
-       if (!buf->snapshot)
-               config |= ARCH_PERFMON_EVENTSEL_INT;
-       if (!event->attr.exclude_kernel)
-               config |= ARCH_PERFMON_EVENTSEL_OS;
-       if (!event->attr.exclude_user)
-               config |= ARCH_PERFMON_EVENTSEL_USR;
-
-       bts_config_buffer(buf);
-
-       /*
-        * local barrier to make sure that ds configuration made it
-        * before we enable BTS
-        */
-       wmb();
-
-       intel_pmu_enable_bts(config);
-}
-
-static void bts_event_start(struct perf_event *event, int flags)
-{
-       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-
-       __bts_event_start(event);
-
-       /* PMI handler: this counter is running and likely generating PMIs */
-       ACCESS_ONCE(bts->started) = 1;
-}
-
-static void __bts_event_stop(struct perf_event *event)
-{
-       /*
-        * No extra synchronization is mandated by the documentation to have
-        * BTS data stores globally visible.
-        */
-       intel_pmu_disable_bts();
-
-       if (event->hw.state & PERF_HES_STOPPED)
-               return;
-
-       ACCESS_ONCE(event->hw.state) |= PERF_HES_STOPPED;
-}
-
-static void bts_event_stop(struct perf_event *event, int flags)
-{
-       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-
-       /* PMI handler: don't restart this counter */
-       ACCESS_ONCE(bts->started) = 0;
-
-       __bts_event_stop(event);
-
-       if (flags & PERF_EF_UPDATE)
-               bts_update(bts);
-}
-
-void intel_bts_enable_local(void)
-{
-       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-
-       if (bts->handle.event && bts->started)
-               __bts_event_start(bts->handle.event);
-}
-
-void intel_bts_disable_local(void)
-{
-       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-
-       if (bts->handle.event)
-               __bts_event_stop(bts->handle.event);
-}
-
-static int
-bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle)
-{
-       unsigned long head, space, next_space, pad, gap, skip, wakeup;
-       unsigned int next_buf;
-       struct bts_phys *phys, *next_phys;
-       int ret;
-
-       if (buf->snapshot)
-               return 0;
-
-       head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
-       if (WARN_ON_ONCE(head != local_read(&buf->head)))
-               return -EINVAL;
-
-       phys = &buf->buf[buf->cur_buf];
-       space = phys->offset + phys->displacement + phys->size - head;
-       pad = space;
-       if (space > handle->size) {
-               space = handle->size;
-               space -= space % BTS_RECORD_SIZE;
-       }
-       if (space <= BTS_SAFETY_MARGIN) {
-               /* See if next phys buffer has more space */
-               next_buf = buf->cur_buf + 1;
-               if (next_buf >= buf->nr_bufs)
-                       next_buf = 0;
-               next_phys = &buf->buf[next_buf];
-               gap = buf_size(phys->page) - phys->displacement - phys->size +
-                     next_phys->displacement;
-               skip = pad + gap;
-               if (handle->size >= skip) {
-                       next_space = next_phys->size;
-                       if (next_space + skip > handle->size) {
-                               next_space = handle->size - skip;
-                               next_space -= next_space % BTS_RECORD_SIZE;
-                       }
-                       if (next_space > space || !space) {
-                               if (pad)
-                                       bts_buffer_pad_out(phys, head);
-                               ret = perf_aux_output_skip(handle, skip);
-                               if (ret)
-                                       return ret;
-                               /* Advance to next phys buffer */
-                               phys = next_phys;
-                               space = next_space;
-                               head = phys->offset + phys->displacement;
-                               /*
-                                * After this, cur_buf and head won't match ds
-                                * anymore, so we must not be racing with
-                                * bts_update().
-                                */
-                               buf->cur_buf = next_buf;
-                               local_set(&buf->head, head);
-                       }
-               }
-       }
-
-       /* Don't go far beyond wakeup watermark */
-       wakeup = BTS_SAFETY_MARGIN + BTS_RECORD_SIZE + handle->wakeup -
-                handle->head;
-       if (space > wakeup) {
-               space = wakeup;
-               space -= space % BTS_RECORD_SIZE;
-       }
-
-       buf->end = head + space;
-
-       /*
-        * If we have no space, the lost notification would have been sent when
-        * we hit absolute_maximum - see bts_update()
-        */
-       if (!space)
-               return -ENOSPC;
-
-       return 0;
-}
-
-int intel_bts_interrupt(void)
-{
-       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-       struct perf_event *event = bts->handle.event;
-       struct bts_buffer *buf;
-       s64 old_head;
-       int err;
-
-       if (!event || !bts->started)
-               return 0;
-
-       buf = perf_get_aux(&bts->handle);
-       /*
-        * Skip snapshot counters: they don't use the interrupt, but
-        * there's no other way of telling, because the pointer will
-        * keep moving
-        */
-       if (!buf || buf->snapshot)
-               return 0;
-
-       old_head = local_read(&buf->head);
-       bts_update(bts);
-
-       /* no new data */
-       if (old_head == local_read(&buf->head))
-               return 0;
-
-       perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
-                           !!local_xchg(&buf->lost, 0));
-
-       buf = perf_aux_output_begin(&bts->handle, event);
-       if (!buf)
-               return 1;
-
-       err = bts_buffer_reset(buf, &bts->handle);
-       if (err)
-               perf_aux_output_end(&bts->handle, 0, false);
-
-       return 1;
-}
-
-static void bts_event_del(struct perf_event *event, int mode)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-       struct bts_buffer *buf = perf_get_aux(&bts->handle);
-
-       bts_event_stop(event, PERF_EF_UPDATE);
-
-       if (buf) {
-               if (buf->snapshot)
-                       bts->handle.head =
-                               local_xchg(&buf->data_size,
-                                          buf->nr_pages << PAGE_SHIFT);
-               perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
-                                   !!local_xchg(&buf->lost, 0));
-       }
-
-       cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
-       cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base;
-       cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum;
-       cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold;
-}
-
-static int bts_event_add(struct perf_event *event, int mode)
-{
-       struct bts_buffer *buf;
-       struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct hw_perf_event *hwc = &event->hw;
-       int ret = -EBUSY;
-
-       event->hw.state = PERF_HES_STOPPED;
-
-       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
-               return -EBUSY;
-
-       if (bts->handle.event)
-               return -EBUSY;
-
-       buf = perf_aux_output_begin(&bts->handle, event);
-       if (!buf)
-               return -EINVAL;
-
-       ret = bts_buffer_reset(buf, &bts->handle);
-       if (ret) {
-               perf_aux_output_end(&bts->handle, 0, false);
-               return ret;
-       }
-
-       bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base;
-       bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
-       bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
-
-       if (mode & PERF_EF_START) {
-               bts_event_start(event, 0);
-               if (hwc->state & PERF_HES_STOPPED) {
-                       bts_event_del(event, 0);
-                       return -EBUSY;
-               }
-       }
-
-       return 0;
-}
-
-static void bts_event_destroy(struct perf_event *event)
-{
-       x86_release_hardware();
-       x86_del_exclusive(x86_lbr_exclusive_bts);
-}
-
-static int bts_event_init(struct perf_event *event)
-{
-       int ret;
-
-       if (event->attr.type != bts_pmu.type)
-               return -ENOENT;
-
-       if (x86_add_exclusive(x86_lbr_exclusive_bts))
-               return -EBUSY;
-
-       /*
-        * BTS leaks kernel addresses even when CPL0 tracing is
-        * disabled, so disallow intel_bts driver for unprivileged
-        * users on paranoid systems since it provides trace data
-        * to the user in a zero-copy fashion.
-        *
-        * Note that the default paranoia setting permits unprivileged
-        * users to profile the kernel.
-        */
-       if (event->attr.exclude_kernel && perf_paranoid_kernel() &&
-           !capable(CAP_SYS_ADMIN))
-               return -EACCES;
-
-       ret = x86_reserve_hardware();
-       if (ret) {
-               x86_del_exclusive(x86_lbr_exclusive_bts);
-               return ret;
-       }
-
-       event->destroy = bts_event_destroy;
-
-       return 0;
-}
-
-static void bts_event_read(struct perf_event *event)
-{
-}
-
-static __init int bts_init(void)
-{
-       if (!boot_cpu_has(X86_FEATURE_DTES64) || !x86_pmu.bts)
-               return -ENODEV;
-
-       bts_pmu.capabilities    = PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_ITRACE;
-       bts_pmu.task_ctx_nr     = perf_sw_context;
-       bts_pmu.event_init      = bts_event_init;
-       bts_pmu.add             = bts_event_add;
-       bts_pmu.del             = bts_event_del;
-       bts_pmu.start           = bts_event_start;
-       bts_pmu.stop            = bts_event_stop;
-       bts_pmu.read            = bts_event_read;
-       bts_pmu.setup_aux       = bts_buffer_setup_aux;
-       bts_pmu.free_aux        = bts_buffer_free_aux;
-
-       return perf_pmu_register(&bts_pmu, "intel_bts", -1);
-}
-arch_initcall(bts_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
deleted file mode 100644 (file)
index a316ca9..0000000
+++ /dev/null
@@ -1,1391 +0,0 @@
-/*
- * Intel Cache Quality-of-Service Monitoring (CQM) support.
- *
- * Based very, very heavily on work by Peter Zijlstra.
- */
-
-#include <linux/perf_event.h>
-#include <linux/slab.h>
-#include <asm/cpu_device_id.h>
-#include "perf_event.h"
-
-#define MSR_IA32_PQR_ASSOC     0x0c8f
-#define MSR_IA32_QM_CTR                0x0c8e
-#define MSR_IA32_QM_EVTSEL     0x0c8d
-
-static u32 cqm_max_rmid = -1;
-static unsigned int cqm_l3_scale; /* supposedly cacheline size */
-
-/**
- * struct intel_pqr_state - State cache for the PQR MSR
- * @rmid:              The cached Resource Monitoring ID
- * @closid:            The cached Class Of Service ID
- * @rmid_usecnt:       The usage counter for rmid
- *
- * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
- * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
- * contains both parts, so we need to cache them.
- *
- * The cache also helps to avoid pointless updates if the value does
- * not change.
- */
-struct intel_pqr_state {
-       u32                     rmid;
-       u32                     closid;
-       int                     rmid_usecnt;
-};
-
-/*
- * The cached intel_pqr_state is strictly per CPU and can never be
- * updated from a remote CPU. Both functions which modify the state
- * (intel_cqm_event_start and intel_cqm_event_stop) are called with
- * interrupts disabled, which is sufficient for the protection.
- */
-static DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
-
-/*
- * Protects cache_cgroups and cqm_rmid_free_lru and cqm_rmid_limbo_lru.
- * Also protects event->hw.cqm_rmid
- *
- * Hold either for stability, both for modification of ->hw.cqm_rmid.
- */
-static DEFINE_MUTEX(cache_mutex);
-static DEFINE_RAW_SPINLOCK(cache_lock);
-
-/*
- * Groups of events that have the same target(s), one RMID per group.
- */
-static LIST_HEAD(cache_groups);
-
-/*
- * Mask of CPUs for reading CQM values. We only need one per-socket.
- */
-static cpumask_t cqm_cpumask;
-
-#define RMID_VAL_ERROR         (1ULL << 63)
-#define RMID_VAL_UNAVAIL       (1ULL << 62)
-
-#define QOS_L3_OCCUP_EVENT_ID  (1 << 0)
-
-#define QOS_EVENT_MASK QOS_L3_OCCUP_EVENT_ID
-
-/*
- * This is central to the rotation algorithm in __intel_cqm_rmid_rotate().
- *
- * This rmid is always free and is guaranteed to have an associated
- * near-zero occupancy value, i.e. no cachelines are tagged with this
- * RMID, once __intel_cqm_rmid_rotate() returns.
- */
-static u32 intel_cqm_rotation_rmid;
-
-#define INVALID_RMID           (-1)
-
-/*
- * Is @rmid valid for programming the hardware?
- *
- * rmid 0 is reserved by the hardware for all non-monitored tasks, which
- * means that we should never come across an rmid with that value.
- * Likewise, an rmid value of -1 is used to indicate "no rmid currently
- * assigned" and is used as part of the rotation code.
- */
-static inline bool __rmid_valid(u32 rmid)
-{
-       if (!rmid || rmid == INVALID_RMID)
-               return false;
-
-       return true;
-}
-
-static u64 __rmid_read(u32 rmid)
-{
-       u64 val;
-
-       /*
-        * Ignore the SDM, this thing is _NOTHING_ like a regular perfcnt,
-        * it just says that to increase confusion.
-        */
-       wrmsr(MSR_IA32_QM_EVTSEL, QOS_L3_OCCUP_EVENT_ID, rmid);
-       rdmsrl(MSR_IA32_QM_CTR, val);
-
-       /*
-        * Aside from the ERROR and UNAVAIL bits, assume this thing returns
-        * the number of cachelines tagged with @rmid.
-        */
-       return val;
-}
-
-enum rmid_recycle_state {
-       RMID_YOUNG = 0,
-       RMID_AVAILABLE,
-       RMID_DIRTY,
-};
-
-struct cqm_rmid_entry {
-       u32 rmid;
-       enum rmid_recycle_state state;
-       struct list_head list;
-       unsigned long queue_time;
-};
-
-/*
- * cqm_rmid_free_lru - A least recently used list of RMIDs.
- *
- * Oldest entry at the head, newest (most recently used) entry at the
- * tail. This list is never traversed, it's only used to keep track of
- * the lru order. That is, we only pick entries of the head or insert
- * them on the tail.
- *
- * All entries on the list are 'free', and their RMIDs are not currently
- * in use. To mark an RMID as in use, remove its entry from the lru
- * list.
- *
- *
- * cqm_rmid_limbo_lru - list of currently unused but (potentially) dirty RMIDs.
- *
- * This list is contains RMIDs that no one is currently using but that
- * may have a non-zero occupancy value associated with them. The
- * rotation worker moves RMIDs from the limbo list to the free list once
- * the occupancy value drops below __intel_cqm_threshold.
- *
- * Both lists are protected by cache_mutex.
- */
-static LIST_HEAD(cqm_rmid_free_lru);
-static LIST_HEAD(cqm_rmid_limbo_lru);
-
-/*
- * We use a simple array of pointers so that we can lookup a struct
- * cqm_rmid_entry in O(1). This alleviates the callers of __get_rmid()
- * and __put_rmid() from having to worry about dealing with struct
- * cqm_rmid_entry - they just deal with rmids, i.e. integers.
- *
- * Once this array is initialized it is read-only. No locks are required
- * to access it.
- *
- * All entries for all RMIDs can be looked up in the this array at all
- * times.
- */
-static struct cqm_rmid_entry **cqm_rmid_ptrs;
-
-static inline struct cqm_rmid_entry *__rmid_entry(u32 rmid)
-{
-       struct cqm_rmid_entry *entry;
-
-       entry = cqm_rmid_ptrs[rmid];
-       WARN_ON(entry->rmid != rmid);
-
-       return entry;
-}
-
-/*
- * Returns < 0 on fail.
- *
- * We expect to be called with cache_mutex held.
- */
-static u32 __get_rmid(void)
-{
-       struct cqm_rmid_entry *entry;
-
-       lockdep_assert_held(&cache_mutex);
-
-       if (list_empty(&cqm_rmid_free_lru))
-               return INVALID_RMID;
-
-       entry = list_first_entry(&cqm_rmid_free_lru, struct cqm_rmid_entry, list);
-       list_del(&entry->list);
-
-       return entry->rmid;
-}
-
-static void __put_rmid(u32 rmid)
-{
-       struct cqm_rmid_entry *entry;
-
-       lockdep_assert_held(&cache_mutex);
-
-       WARN_ON(!__rmid_valid(rmid));
-       entry = __rmid_entry(rmid);
-
-       entry->queue_time = jiffies;
-       entry->state = RMID_YOUNG;
-
-       list_add_tail(&entry->list, &cqm_rmid_limbo_lru);
-}
-
-static int intel_cqm_setup_rmid_cache(void)
-{
-       struct cqm_rmid_entry *entry;
-       unsigned int nr_rmids;
-       int r = 0;
-
-       nr_rmids = cqm_max_rmid + 1;
-       cqm_rmid_ptrs = kmalloc(sizeof(struct cqm_rmid_entry *) *
-                               nr_rmids, GFP_KERNEL);
-       if (!cqm_rmid_ptrs)
-               return -ENOMEM;
-
-       for (; r <= cqm_max_rmid; r++) {
-               struct cqm_rmid_entry *entry;
-
-               entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-               if (!entry)
-                       goto fail;
-
-               INIT_LIST_HEAD(&entry->list);
-               entry->rmid = r;
-               cqm_rmid_ptrs[r] = entry;
-
-               list_add_tail(&entry->list, &cqm_rmid_free_lru);
-       }
-
-       /*
-        * RMID 0 is special and is always allocated. It's used for all
-        * tasks that are not monitored.
-        */
-       entry = __rmid_entry(0);
-       list_del(&entry->list);
-
-       mutex_lock(&cache_mutex);
-       intel_cqm_rotation_rmid = __get_rmid();
-       mutex_unlock(&cache_mutex);
-
-       return 0;
-fail:
-       while (r--)
-               kfree(cqm_rmid_ptrs[r]);
-
-       kfree(cqm_rmid_ptrs);
-       return -ENOMEM;
-}
-
-/*
- * Determine if @a and @b measure the same set of tasks.
- *
- * If @a and @b measure the same set of tasks then we want to share a
- * single RMID.
- */
-static bool __match_event(struct perf_event *a, struct perf_event *b)
-{
-       /* Per-cpu and task events don't mix */
-       if ((a->attach_state & PERF_ATTACH_TASK) !=
-           (b->attach_state & PERF_ATTACH_TASK))
-               return false;
-
-#ifdef CONFIG_CGROUP_PERF
-       if (a->cgrp != b->cgrp)
-               return false;
-#endif
-
-       /* If not task event, we're machine wide */
-       if (!(b->attach_state & PERF_ATTACH_TASK))
-               return true;
-
-       /*
-        * Events that target same task are placed into the same cache group.
-        */
-       if (a->hw.target == b->hw.target)
-               return true;
-
-       /*
-        * Are we an inherited event?
-        */
-       if (b->parent == a)
-               return true;
-
-       return false;
-}
-
-#ifdef CONFIG_CGROUP_PERF
-static inline struct perf_cgroup *event_to_cgroup(struct perf_event *event)
-{
-       if (event->attach_state & PERF_ATTACH_TASK)
-               return perf_cgroup_from_task(event->hw.target, event->ctx);
-
-       return event->cgrp;
-}
-#endif
-
-/*
- * Determine if @a's tasks intersect with @b's tasks
- *
- * There are combinations of events that we explicitly prohibit,
- *
- *                PROHIBITS
- *     system-wide    ->       cgroup and task
- *     cgroup        ->        system-wide
- *                           ->        task in cgroup
- *     task          ->        system-wide
- *                           ->        task in cgroup
- *
- * Call this function before allocating an RMID.
- */
-static bool __conflict_event(struct perf_event *a, struct perf_event *b)
-{
-#ifdef CONFIG_CGROUP_PERF
-       /*
-        * We can have any number of cgroups but only one system-wide
-        * event at a time.
-        */
-       if (a->cgrp && b->cgrp) {
-               struct perf_cgroup *ac = a->cgrp;
-               struct perf_cgroup *bc = b->cgrp;
-
-               /*
-                * This condition should have been caught in
-                * __match_event() and we should be sharing an RMID.
-                */
-               WARN_ON_ONCE(ac == bc);
-
-               if (cgroup_is_descendant(ac->css.cgroup, bc->css.cgroup) ||
-                   cgroup_is_descendant(bc->css.cgroup, ac->css.cgroup))
-                       return true;
-
-               return false;
-       }
-
-       if (a->cgrp || b->cgrp) {
-               struct perf_cgroup *ac, *bc;
-
-               /*
-                * cgroup and system-wide events are mutually exclusive
-                */
-               if ((a->cgrp && !(b->attach_state & PERF_ATTACH_TASK)) ||
-                   (b->cgrp && !(a->attach_state & PERF_ATTACH_TASK)))
-                       return true;
-
-               /*
-                * Ensure neither event is part of the other's cgroup
-                */
-               ac = event_to_cgroup(a);
-               bc = event_to_cgroup(b);
-               if (ac == bc)
-                       return true;
-
-               /*
-                * Must have cgroup and non-intersecting task events.
-                */
-               if (!ac || !bc)
-                       return false;
-
-               /*
-                * We have cgroup and task events, and the task belongs
-                * to a cgroup. Check for for overlap.
-                */
-               if (cgroup_is_descendant(ac->css.cgroup, bc->css.cgroup) ||
-                   cgroup_is_descendant(bc->css.cgroup, ac->css.cgroup))
-                       return true;
-
-               return false;
-       }
-#endif
-       /*
-        * If one of them is not a task, same story as above with cgroups.
-        */
-       if (!(a->attach_state & PERF_ATTACH_TASK) ||
-           !(b->attach_state & PERF_ATTACH_TASK))
-               return true;
-
-       /*
-        * Must be non-overlapping.
-        */
-       return false;
-}
-
-struct rmid_read {
-       u32 rmid;
-       atomic64_t value;
-};
-
-static void __intel_cqm_event_count(void *info);
-
-/*
- * Exchange the RMID of a group of events.
- */
-static u32 intel_cqm_xchg_rmid(struct perf_event *group, u32 rmid)
-{
-       struct perf_event *event;
-       struct list_head *head = &group->hw.cqm_group_entry;
-       u32 old_rmid = group->hw.cqm_rmid;
-
-       lockdep_assert_held(&cache_mutex);
-
-       /*
-        * If our RMID is being deallocated, perform a read now.
-        */
-       if (__rmid_valid(old_rmid) && !__rmid_valid(rmid)) {
-               struct rmid_read rr = {
-                       .value = ATOMIC64_INIT(0),
-                       .rmid = old_rmid,
-               };
-
-               on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count,
-                                &rr, 1);
-               local64_set(&group->count, atomic64_read(&rr.value));
-       }
-
-       raw_spin_lock_irq(&cache_lock);
-
-       group->hw.cqm_rmid = rmid;
-       list_for_each_entry(event, head, hw.cqm_group_entry)
-               event->hw.cqm_rmid = rmid;
-
-       raw_spin_unlock_irq(&cache_lock);
-
-       return old_rmid;
-}
-
-/*
- * If we fail to assign a new RMID for intel_cqm_rotation_rmid because
- * cachelines are still tagged with RMIDs in limbo, we progressively
- * increment the threshold until we find an RMID in limbo with <=
- * __intel_cqm_threshold lines tagged. This is designed to mitigate the
- * problem where cachelines tagged with an RMID are not steadily being
- * evicted.
- *
- * On successful rotations we decrease the threshold back towards zero.
- *
- * __intel_cqm_max_threshold provides an upper bound on the threshold,
- * and is measured in bytes because it's exposed to userland.
- */
-static unsigned int __intel_cqm_threshold;
-static unsigned int __intel_cqm_max_threshold;
-
-/*
- * Test whether an RMID has a zero occupancy value on this cpu.
- */
-static void intel_cqm_stable(void *arg)
-{
-       struct cqm_rmid_entry *entry;
-
-       list_for_each_entry(entry, &cqm_rmid_limbo_lru, list) {
-               if (entry->state != RMID_AVAILABLE)
-                       break;
-
-               if (__rmid_read(entry->rmid) > __intel_cqm_threshold)
-                       entry->state = RMID_DIRTY;
-       }
-}
-
-/*
- * If we have group events waiting for an RMID that don't conflict with
- * events already running, assign @rmid.
- */
-static bool intel_cqm_sched_in_event(u32 rmid)
-{
-       struct perf_event *leader, *event;
-
-       lockdep_assert_held(&cache_mutex);
-
-       leader = list_first_entry(&cache_groups, struct perf_event,
-                                 hw.cqm_groups_entry);
-       event = leader;
-
-       list_for_each_entry_continue(event, &cache_groups,
-                                    hw.cqm_groups_entry) {
-               if (__rmid_valid(event->hw.cqm_rmid))
-                       continue;
-
-               if (__conflict_event(event, leader))
-                       continue;
-
-               intel_cqm_xchg_rmid(event, rmid);
-               return true;
-       }
-
-       return false;
-}
-
-/*
- * Initially use this constant for both the limbo queue time and the
- * rotation timer interval, pmu::hrtimer_interval_ms.
- *
- * They don't need to be the same, but the two are related since if you
- * rotate faster than you recycle RMIDs, you may run out of available
- * RMIDs.
- */
-#define RMID_DEFAULT_QUEUE_TIME 250    /* ms */
-
-static unsigned int __rmid_queue_time_ms = RMID_DEFAULT_QUEUE_TIME;
-
-/*
- * intel_cqm_rmid_stabilize - move RMIDs from limbo to free list
- * @nr_available: number of freeable RMIDs on the limbo list
- *
- * Quiescent state; wait for all 'freed' RMIDs to become unused, i.e. no
- * cachelines are tagged with those RMIDs. After this we can reuse them
- * and know that the current set of active RMIDs is stable.
- *
- * Return %true or %false depending on whether stabilization needs to be
- * reattempted.
- *
- * If we return %true then @nr_available is updated to indicate the
- * number of RMIDs on the limbo list that have been queued for the
- * minimum queue time (RMID_AVAILABLE), but whose data occupancy values
- * are above __intel_cqm_threshold.
- */
-static bool intel_cqm_rmid_stabilize(unsigned int *available)
-{
-       struct cqm_rmid_entry *entry, *tmp;
-
-       lockdep_assert_held(&cache_mutex);
-
-       *available = 0;
-       list_for_each_entry(entry, &cqm_rmid_limbo_lru, list) {
-               unsigned long min_queue_time;
-               unsigned long now = jiffies;
-
-               /*
-                * We hold RMIDs placed into limbo for a minimum queue
-                * time. Before the minimum queue time has elapsed we do
-                * not recycle RMIDs.
-                *
-                * The reasoning is that until a sufficient time has
-                * passed since we stopped using an RMID, any RMID
-                * placed onto the limbo list will likely still have
-                * data tagged in the cache, which means we'll probably
-                * fail to recycle it anyway.
-                *
-                * We can save ourselves an expensive IPI by skipping
-                * any RMIDs that have not been queued for the minimum
-                * time.
-                */
-               min_queue_time = entry->queue_time +
-                       msecs_to_jiffies(__rmid_queue_time_ms);
-
-               if (time_after(min_queue_time, now))
-                       break;
-
-               entry->state = RMID_AVAILABLE;
-               (*available)++;
-       }
-
-       /*
-        * Fast return if none of the RMIDs on the limbo list have been
-        * sitting on the queue for the minimum queue time.
-        */
-       if (!*available)
-               return false;
-
-       /*
-        * Test whether an RMID is free for each package.
-        */
-       on_each_cpu_mask(&cqm_cpumask, intel_cqm_stable, NULL, true);
-
-       list_for_each_entry_safe(entry, tmp, &cqm_rmid_limbo_lru, list) {
-               /*
-                * Exhausted all RMIDs that have waited min queue time.
-                */
-               if (entry->state == RMID_YOUNG)
-                       break;
-
-               if (entry->state == RMID_DIRTY)
-                       continue;
-
-               list_del(&entry->list); /* remove from limbo */
-
-               /*
-                * The rotation RMID gets priority if it's
-                * currently invalid. In which case, skip adding
-                * the RMID to the the free lru.
-                */
-               if (!__rmid_valid(intel_cqm_rotation_rmid)) {
-                       intel_cqm_rotation_rmid = entry->rmid;
-                       continue;
-               }
-
-               /*
-                * If we have groups waiting for RMIDs, hand
-                * them one now provided they don't conflict.
-                */
-               if (intel_cqm_sched_in_event(entry->rmid))
-                       continue;
-
-               /*
-                * Otherwise place it onto the free list.
-                */
-               list_add_tail(&entry->list, &cqm_rmid_free_lru);
-       }
-
-
-       return __rmid_valid(intel_cqm_rotation_rmid);
-}
-
-/*
- * Pick a victim group and move it to the tail of the group list.
- * @next: The first group without an RMID
- */
-static void __intel_cqm_pick_and_rotate(struct perf_event *next)
-{
-       struct perf_event *rotor;
-       u32 rmid;
-
-       lockdep_assert_held(&cache_mutex);
-
-       rotor = list_first_entry(&cache_groups, struct perf_event,
-                                hw.cqm_groups_entry);
-
-       /*
-        * The group at the front of the list should always have a valid
-        * RMID. If it doesn't then no groups have RMIDs assigned and we
-        * don't need to rotate the list.
-        */
-       if (next == rotor)
-               return;
-
-       rmid = intel_cqm_xchg_rmid(rotor, INVALID_RMID);
-       __put_rmid(rmid);
-
-       list_rotate_left(&cache_groups);
-}
-
-/*
- * Deallocate the RMIDs from any events that conflict with @event, and
- * place them on the back of the group list.
- */
-static void intel_cqm_sched_out_conflicting_events(struct perf_event *event)
-{
-       struct perf_event *group, *g;
-       u32 rmid;
-
-       lockdep_assert_held(&cache_mutex);
-
-       list_for_each_entry_safe(group, g, &cache_groups, hw.cqm_groups_entry) {
-               if (group == event)
-                       continue;
-
-               rmid = group->hw.cqm_rmid;
-
-               /*
-                * Skip events that don't have a valid RMID.
-                */
-               if (!__rmid_valid(rmid))
-                       continue;
-
-               /*
-                * No conflict? No problem! Leave the event alone.
-                */
-               if (!__conflict_event(group, event))
-                       continue;
-
-               intel_cqm_xchg_rmid(group, INVALID_RMID);
-               __put_rmid(rmid);
-       }
-}
-
-/*
- * Attempt to rotate the groups and assign new RMIDs.
- *
- * We rotate for two reasons,
- *   1. To handle the scheduling of conflicting events
- *   2. To recycle RMIDs
- *
- * Rotating RMIDs is complicated because the hardware doesn't give us
- * any clues.
- *
- * There's problems with the hardware interface; when you change the
- * task:RMID map cachelines retain their 'old' tags, giving a skewed
- * picture. In order to work around this, we must always keep one free
- * RMID - intel_cqm_rotation_rmid.
- *
- * Rotation works by taking away an RMID from a group (the old RMID),
- * and assigning the free RMID to another group (the new RMID). We must
- * then wait for the old RMID to not be used (no cachelines tagged).
- * This ensure that all cachelines are tagged with 'active' RMIDs. At
- * this point we can start reading values for the new RMID and treat the
- * old RMID as the free RMID for the next rotation.
- *
- * Return %true or %false depending on whether we did any rotating.
- */
-static bool __intel_cqm_rmid_rotate(void)
-{
-       struct perf_event *group, *start = NULL;
-       unsigned int threshold_limit;
-       unsigned int nr_needed = 0;
-       unsigned int nr_available;
-       bool rotated = false;
-
-       mutex_lock(&cache_mutex);
-
-again:
-       /*
-        * Fast path through this function if there are no groups and no
-        * RMIDs that need cleaning.
-        */
-       if (list_empty(&cache_groups) && list_empty(&cqm_rmid_limbo_lru))
-               goto out;
-
-       list_for_each_entry(group, &cache_groups, hw.cqm_groups_entry) {
-               if (!__rmid_valid(group->hw.cqm_rmid)) {
-                       if (!start)
-                               start = group;
-                       nr_needed++;
-               }
-       }
-
-       /*
-        * We have some event groups, but they all have RMIDs assigned
-        * and no RMIDs need cleaning.
-        */
-       if (!nr_needed && list_empty(&cqm_rmid_limbo_lru))
-               goto out;
-
-       if (!nr_needed)
-               goto stabilize;
-
-       /*
-        * We have more event groups without RMIDs than available RMIDs,
-        * or we have event groups that conflict with the ones currently
-        * scheduled.
-        *
-        * We force deallocate the rmid of the group at the head of
-        * cache_groups. The first event group without an RMID then gets
-        * assigned intel_cqm_rotation_rmid. This ensures we always make
-        * forward progress.
-        *
-        * Rotate the cache_groups list so the previous head is now the
-        * tail.
-        */
-       __intel_cqm_pick_and_rotate(start);
-
-       /*
-        * If the rotation is going to succeed, reduce the threshold so
-        * that we don't needlessly reuse dirty RMIDs.
-        */
-       if (__rmid_valid(intel_cqm_rotation_rmid)) {
-               intel_cqm_xchg_rmid(start, intel_cqm_rotation_rmid);
-               intel_cqm_rotation_rmid = __get_rmid();
-
-               intel_cqm_sched_out_conflicting_events(start);
-
-               if (__intel_cqm_threshold)
-                       __intel_cqm_threshold--;
-       }
-
-       rotated = true;
-
-stabilize:
-       /*
-        * We now need to stablize the RMID we freed above (if any) to
-        * ensure that the next time we rotate we have an RMID with zero
-        * occupancy value.
-        *
-        * Alternatively, if we didn't need to perform any rotation,
-        * we'll have a bunch of RMIDs in limbo that need stabilizing.
-        */
-       threshold_limit = __intel_cqm_max_threshold / cqm_l3_scale;
-
-       while (intel_cqm_rmid_stabilize(&nr_available) &&
-              __intel_cqm_threshold < threshold_limit) {
-               unsigned int steal_limit;
-
-               /*
-                * Don't spin if nobody is actively waiting for an RMID,
-                * the rotation worker will be kicked as soon as an
-                * event needs an RMID anyway.
-                */
-               if (!nr_needed)
-                       break;
-
-               /* Allow max 25% of RMIDs to be in limbo. */
-               steal_limit = (cqm_max_rmid + 1) / 4;
-
-               /*
-                * We failed to stabilize any RMIDs so our rotation
-                * logic is now stuck. In order to make forward progress
-                * we have a few options:
-                *
-                *   1. rotate ("steal") another RMID
-                *   2. increase the threshold
-                *   3. do nothing
-                *
-                * We do both of 1. and 2. until we hit the steal limit.
-                *
-                * The steal limit prevents all RMIDs ending up on the
-                * limbo list. This can happen if every RMID has a
-                * non-zero occupancy above threshold_limit, and the
-                * occupancy values aren't dropping fast enough.
-                *
-                * Note that there is prioritisation at work here - we'd
-                * rather increase the number of RMIDs on the limbo list
-                * than increase the threshold, because increasing the
-                * threshold skews the event data (because we reuse
-                * dirty RMIDs) - threshold bumps are a last resort.
-                */
-               if (nr_available < steal_limit)
-                       goto again;
-
-               __intel_cqm_threshold++;
-       }
-
-out:
-       mutex_unlock(&cache_mutex);
-       return rotated;
-}
-
-static void intel_cqm_rmid_rotate(struct work_struct *work);
-
-static DECLARE_DELAYED_WORK(intel_cqm_rmid_work, intel_cqm_rmid_rotate);
-
-static struct pmu intel_cqm_pmu;
-
-static void intel_cqm_rmid_rotate(struct work_struct *work)
-{
-       unsigned long delay;
-
-       __intel_cqm_rmid_rotate();
-
-       delay = msecs_to_jiffies(intel_cqm_pmu.hrtimer_interval_ms);
-       schedule_delayed_work(&intel_cqm_rmid_work, delay);
-}
-
-/*
- * Find a group and setup RMID.
- *
- * If we're part of a group, we use the group's RMID.
- */
-static void intel_cqm_setup_event(struct perf_event *event,
-                                 struct perf_event **group)
-{
-       struct perf_event *iter;
-       bool conflict = false;
-       u32 rmid;
-
-       list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) {
-               rmid = iter->hw.cqm_rmid;
-
-               if (__match_event(iter, event)) {
-                       /* All tasks in a group share an RMID */
-                       event->hw.cqm_rmid = rmid;
-                       *group = iter;
-                       return;
-               }
-
-               /*
-                * We only care about conflicts for events that are
-                * actually scheduled in (and hence have a valid RMID).
-                */
-               if (__conflict_event(iter, event) && __rmid_valid(rmid))
-                       conflict = true;
-       }
-
-       if (conflict)
-               rmid = INVALID_RMID;
-       else
-               rmid = __get_rmid();
-
-       event->hw.cqm_rmid = rmid;
-}
-
-static void intel_cqm_event_read(struct perf_event *event)
-{
-       unsigned long flags;
-       u32 rmid;
-       u64 val;
-
-       /*
-        * Task events are handled by intel_cqm_event_count().
-        */
-       if (event->cpu == -1)
-               return;
-
-       raw_spin_lock_irqsave(&cache_lock, flags);
-       rmid = event->hw.cqm_rmid;
-
-       if (!__rmid_valid(rmid))
-               goto out;
-
-       val = __rmid_read(rmid);
-
-       /*
-        * Ignore this reading on error states and do not update the value.
-        */
-       if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
-               goto out;
-
-       local64_set(&event->count, val);
-out:
-       raw_spin_unlock_irqrestore(&cache_lock, flags);
-}
-
-static void __intel_cqm_event_count(void *info)
-{
-       struct rmid_read *rr = info;
-       u64 val;
-
-       val = __rmid_read(rr->rmid);
-
-       if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL))
-               return;
-
-       atomic64_add(val, &rr->value);
-}
-
-static inline bool cqm_group_leader(struct perf_event *event)
-{
-       return !list_empty(&event->hw.cqm_groups_entry);
-}
-
-static u64 intel_cqm_event_count(struct perf_event *event)
-{
-       unsigned long flags;
-       struct rmid_read rr = {
-               .value = ATOMIC64_INIT(0),
-       };
-
-       /*
-        * We only need to worry about task events. System-wide events
-        * are handled like usual, i.e. entirely with
-        * intel_cqm_event_read().
-        */
-       if (event->cpu != -1)
-               return __perf_event_count(event);
-
-       /*
-        * Only the group leader gets to report values. This stops us
-        * reporting duplicate values to userspace, and gives us a clear
-        * rule for which task gets to report the values.
-        *
-        * Note that it is impossible to attribute these values to
-        * specific packages - we forfeit that ability when we create
-        * task events.
-        */
-       if (!cqm_group_leader(event))
-               return 0;
-
-       /*
-        * Getting up-to-date values requires an SMP IPI which is not
-        * possible if we're being called in interrupt context. Return
-        * the cached values instead.
-        */
-       if (unlikely(in_interrupt()))
-               goto out;
-
-       /*
-        * Notice that we don't perform the reading of an RMID
-        * atomically, because we can't hold a spin lock across the
-        * IPIs.
-        *
-        * Speculatively perform the read, since @event might be
-        * assigned a different (possibly invalid) RMID while we're
-        * busying performing the IPI calls. It's therefore necessary to
-        * check @event's RMID afterwards, and if it has changed,
-        * discard the result of the read.
-        */
-       rr.rmid = ACCESS_ONCE(event->hw.cqm_rmid);
-
-       if (!__rmid_valid(rr.rmid))
-               goto out;
-
-       on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count, &rr, 1);
-
-       raw_spin_lock_irqsave(&cache_lock, flags);
-       if (event->hw.cqm_rmid == rr.rmid)
-               local64_set(&event->count, atomic64_read(&rr.value));
-       raw_spin_unlock_irqrestore(&cache_lock, flags);
-out:
-       return __perf_event_count(event);
-}
-
-static void intel_cqm_event_start(struct perf_event *event, int mode)
-{
-       struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
-       u32 rmid = event->hw.cqm_rmid;
-
-       if (!(event->hw.cqm_state & PERF_HES_STOPPED))
-               return;
-
-       event->hw.cqm_state &= ~PERF_HES_STOPPED;
-
-       if (state->rmid_usecnt++) {
-               if (!WARN_ON_ONCE(state->rmid != rmid))
-                       return;
-       } else {
-               WARN_ON_ONCE(state->rmid);
-       }
-
-       state->rmid = rmid;
-       wrmsr(MSR_IA32_PQR_ASSOC, rmid, state->closid);
-}
-
-static void intel_cqm_event_stop(struct perf_event *event, int mode)
-{
-       struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
-
-       if (event->hw.cqm_state & PERF_HES_STOPPED)
-               return;
-
-       event->hw.cqm_state |= PERF_HES_STOPPED;
-
-       intel_cqm_event_read(event);
-
-       if (!--state->rmid_usecnt) {
-               state->rmid = 0;
-               wrmsr(MSR_IA32_PQR_ASSOC, 0, state->closid);
-       } else {
-               WARN_ON_ONCE(!state->rmid);
-       }
-}
-
-static int intel_cqm_event_add(struct perf_event *event, int mode)
-{
-       unsigned long flags;
-       u32 rmid;
-
-       raw_spin_lock_irqsave(&cache_lock, flags);
-
-       event->hw.cqm_state = PERF_HES_STOPPED;
-       rmid = event->hw.cqm_rmid;
-
-       if (__rmid_valid(rmid) && (mode & PERF_EF_START))
-               intel_cqm_event_start(event, mode);
-
-       raw_spin_unlock_irqrestore(&cache_lock, flags);
-
-       return 0;
-}
-
-static void intel_cqm_event_destroy(struct perf_event *event)
-{
-       struct perf_event *group_other = NULL;
-
-       mutex_lock(&cache_mutex);
-
-       /*
-        * If there's another event in this group...
-        */
-       if (!list_empty(&event->hw.cqm_group_entry)) {
-               group_other = list_first_entry(&event->hw.cqm_group_entry,
-                                              struct perf_event,
-                                              hw.cqm_group_entry);
-               list_del(&event->hw.cqm_group_entry);
-       }
-
-       /*
-        * And we're the group leader..
-        */
-       if (cqm_group_leader(event)) {
-               /*
-                * If there was a group_other, make that leader, otherwise
-                * destroy the group and return the RMID.
-                */
-               if (group_other) {
-                       list_replace(&event->hw.cqm_groups_entry,
-                                    &group_other->hw.cqm_groups_entry);
-               } else {
-                       u32 rmid = event->hw.cqm_rmid;
-
-                       if (__rmid_valid(rmid))
-                               __put_rmid(rmid);
-                       list_del(&event->hw.cqm_groups_entry);
-               }
-       }
-
-       mutex_unlock(&cache_mutex);
-}
-
-static int intel_cqm_event_init(struct perf_event *event)
-{
-       struct perf_event *group = NULL;
-       bool rotate = false;
-
-       if (event->attr.type != intel_cqm_pmu.type)
-               return -ENOENT;
-
-       if (event->attr.config & ~QOS_EVENT_MASK)
-               return -EINVAL;
-
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
-               return -EINVAL;
-
-       INIT_LIST_HEAD(&event->hw.cqm_group_entry);
-       INIT_LIST_HEAD(&event->hw.cqm_groups_entry);
-
-       event->destroy = intel_cqm_event_destroy;
-
-       mutex_lock(&cache_mutex);
-
-       /* Will also set rmid */
-       intel_cqm_setup_event(event, &group);
-
-       if (group) {
-               list_add_tail(&event->hw.cqm_group_entry,
-                             &group->hw.cqm_group_entry);
-       } else {
-               list_add_tail(&event->hw.cqm_groups_entry,
-                             &cache_groups);
-
-               /*
-                * All RMIDs are either in use or have recently been
-                * used. Kick the rotation worker to clean/free some.
-                *
-                * We only do this for the group leader, rather than for
-                * every event in a group to save on needless work.
-                */
-               if (!__rmid_valid(event->hw.cqm_rmid))
-                       rotate = true;
-       }
-
-       mutex_unlock(&cache_mutex);
-
-       if (rotate)
-               schedule_delayed_work(&intel_cqm_rmid_work, 0);
-
-       return 0;
-}
-
-EVENT_ATTR_STR(llc_occupancy, intel_cqm_llc, "event=0x01");
-EVENT_ATTR_STR(llc_occupancy.per-pkg, intel_cqm_llc_pkg, "1");
-EVENT_ATTR_STR(llc_occupancy.unit, intel_cqm_llc_unit, "Bytes");
-EVENT_ATTR_STR(llc_occupancy.scale, intel_cqm_llc_scale, NULL);
-EVENT_ATTR_STR(llc_occupancy.snapshot, intel_cqm_llc_snapshot, "1");
-
-static struct attribute *intel_cqm_events_attr[] = {
-       EVENT_PTR(intel_cqm_llc),
-       EVENT_PTR(intel_cqm_llc_pkg),
-       EVENT_PTR(intel_cqm_llc_unit),
-       EVENT_PTR(intel_cqm_llc_scale),
-       EVENT_PTR(intel_cqm_llc_snapshot),
-       NULL,
-};
-
-static struct attribute_group intel_cqm_events_group = {
-       .name = "events",
-       .attrs = intel_cqm_events_attr,
-};
-
-PMU_FORMAT_ATTR(event, "config:0-7");
-static struct attribute *intel_cqm_formats_attr[] = {
-       &format_attr_event.attr,
-       NULL,
-};
-
-static struct attribute_group intel_cqm_format_group = {
-       .name = "format",
-       .attrs = intel_cqm_formats_attr,
-};
-
-static ssize_t
-max_recycle_threshold_show(struct device *dev, struct device_attribute *attr,
-                          char *page)
-{
-       ssize_t rv;
-
-       mutex_lock(&cache_mutex);
-       rv = snprintf(page, PAGE_SIZE-1, "%u\n", __intel_cqm_max_threshold);
-       mutex_unlock(&cache_mutex);
-
-       return rv;
-}
-
-static ssize_t
-max_recycle_threshold_store(struct device *dev,
-                           struct device_attribute *attr,
-                           const char *buf, size_t count)
-{
-       unsigned int bytes, cachelines;
-       int ret;
-
-       ret = kstrtouint(buf, 0, &bytes);
-       if (ret)
-               return ret;
-
-       mutex_lock(&cache_mutex);
-
-       __intel_cqm_max_threshold = bytes;
-       cachelines = bytes / cqm_l3_scale;
-
-       /*
-        * The new maximum takes effect immediately.
-        */
-       if (__intel_cqm_threshold > cachelines)
-               __intel_cqm_threshold = cachelines;
-
-       mutex_unlock(&cache_mutex);
-
-       return count;
-}
-
-static DEVICE_ATTR_RW(max_recycle_threshold);
-
-static struct attribute *intel_cqm_attrs[] = {
-       &dev_attr_max_recycle_threshold.attr,
-       NULL,
-};
-
-static const struct attribute_group intel_cqm_group = {
-       .attrs = intel_cqm_attrs,
-};
-
-static const struct attribute_group *intel_cqm_attr_groups[] = {
-       &intel_cqm_events_group,
-       &intel_cqm_format_group,
-       &intel_cqm_group,
-       NULL,
-};
-
-static struct pmu intel_cqm_pmu = {
-       .hrtimer_interval_ms = RMID_DEFAULT_QUEUE_TIME,
-       .attr_groups         = intel_cqm_attr_groups,
-       .task_ctx_nr         = perf_sw_context,
-       .event_init          = intel_cqm_event_init,
-       .add                 = intel_cqm_event_add,
-       .del                 = intel_cqm_event_stop,
-       .start               = intel_cqm_event_start,
-       .stop                = intel_cqm_event_stop,
-       .read                = intel_cqm_event_read,
-       .count               = intel_cqm_event_count,
-};
-
-static inline void cqm_pick_event_reader(int cpu)
-{
-       int phys_id = topology_physical_package_id(cpu);
-       int i;
-
-       for_each_cpu(i, &cqm_cpumask) {
-               if (phys_id == topology_physical_package_id(i))
-                       return; /* already got reader for this socket */
-       }
-
-       cpumask_set_cpu(cpu, &cqm_cpumask);
-}
-
-static void intel_cqm_cpu_starting(unsigned int cpu)
-{
-       struct intel_pqr_state *state = &per_cpu(pqr_state, cpu);
-       struct cpuinfo_x86 *c = &cpu_data(cpu);
-
-       state->rmid = 0;
-       state->closid = 0;
-       state->rmid_usecnt = 0;
-
-       WARN_ON(c->x86_cache_max_rmid != cqm_max_rmid);
-       WARN_ON(c->x86_cache_occ_scale != cqm_l3_scale);
-}
-
-static void intel_cqm_cpu_exit(unsigned int cpu)
-{
-       int phys_id = topology_physical_package_id(cpu);
-       int i;
-
-       /*
-        * Is @cpu a designated cqm reader?
-        */
-       if (!cpumask_test_and_clear_cpu(cpu, &cqm_cpumask))
-               return;
-
-       for_each_online_cpu(i) {
-               if (i == cpu)
-                       continue;
-
-               if (phys_id == topology_physical_package_id(i)) {
-                       cpumask_set_cpu(i, &cqm_cpumask);
-                       break;
-               }
-       }
-}
-
-static int intel_cqm_cpu_notifier(struct notifier_block *nb,
-                                 unsigned long action, void *hcpu)
-{
-       unsigned int cpu  = (unsigned long)hcpu;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_DOWN_PREPARE:
-               intel_cqm_cpu_exit(cpu);
-               break;
-       case CPU_STARTING:
-               intel_cqm_cpu_starting(cpu);
-               cqm_pick_event_reader(cpu);
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-static const struct x86_cpu_id intel_cqm_match[] = {
-       { .vendor = X86_VENDOR_INTEL, .feature = X86_FEATURE_CQM_OCCUP_LLC },
-       {}
-};
-
-static int __init intel_cqm_init(void)
-{
-       char *str, scale[20];
-       int i, cpu, ret;
-
-       if (!x86_match_cpu(intel_cqm_match))
-               return -ENODEV;
-
-       cqm_l3_scale = boot_cpu_data.x86_cache_occ_scale;
-
-       /*
-        * It's possible that not all resources support the same number
-        * of RMIDs. Instead of making scheduling much more complicated
-        * (where we have to match a task's RMID to a cpu that supports
-        * that many RMIDs) just find the minimum RMIDs supported across
-        * all cpus.
-        *
-        * Also, check that the scales match on all cpus.
-        */
-       cpu_notifier_register_begin();
-
-       for_each_online_cpu(cpu) {
-               struct cpuinfo_x86 *c = &cpu_data(cpu);
-
-               if (c->x86_cache_max_rmid < cqm_max_rmid)
-                       cqm_max_rmid = c->x86_cache_max_rmid;
-
-               if (c->x86_cache_occ_scale != cqm_l3_scale) {
-                       pr_err("Multiple LLC scale values, disabling\n");
-                       ret = -EINVAL;
-                       goto out;
-               }
-       }
-
-       /*
-        * A reasonable upper limit on the max threshold is the number
-        * of lines tagged per RMID if all RMIDs have the same number of
-        * lines tagged in the LLC.
-        *
-        * For a 35MB LLC and 56 RMIDs, this is ~1.8% of the LLC.
-        */
-       __intel_cqm_max_threshold =
-               boot_cpu_data.x86_cache_size * 1024 / (cqm_max_rmid + 1);
-
-       snprintf(scale, sizeof(scale), "%u", cqm_l3_scale);
-       str = kstrdup(scale, GFP_KERNEL);
-       if (!str) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       event_attr_intel_cqm_llc_scale.event_str = str;
-
-       ret = intel_cqm_setup_rmid_cache();
-       if (ret)
-               goto out;
-
-       for_each_online_cpu(i) {
-               intel_cqm_cpu_starting(i);
-               cqm_pick_event_reader(i);
-       }
-
-       __perf_cpu_notifier(intel_cqm_cpu_notifier);
-
-       ret = perf_pmu_register(&intel_cqm_pmu, "intel_cqm", -1);
-       if (ret)
-               pr_err("Intel CQM perf registration failed: %d\n", ret);
-       else
-               pr_info("Intel CQM monitoring enabled\n");
-
-out:
-       cpu_notifier_register_done();
-
-       return ret;
-}
-device_initcall(intel_cqm_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_cstate.c b/arch/x86/kernel/cpu/perf_event_intel_cstate.c
deleted file mode 100644 (file)
index 75a38b5..0000000
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * perf_event_intel_cstate.c: support cstate residency counters
- *
- * Copyright (C) 2015, Intel Corp.
- * Author: Kan Liang (kan.liang@intel.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- */
-
-/*
- * This file export cstate related free running (read-only) counters
- * for perf. These counters may be use simultaneously by other tools,
- * such as turbostat. However, it still make sense to implement them
- * in perf. Because we can conveniently collect them together with
- * other events, and allow to use them from tools without special MSR
- * access code.
- *
- * The events only support system-wide mode counting. There is no
- * sampling support because it is not supported by the hardware.
- *
- * According to counters' scope and category, two PMUs are registered
- * with the perf_event core subsystem.
- *  - 'cstate_core': The counter is available for each physical core.
- *    The counters include CORE_C*_RESIDENCY.
- *  - 'cstate_pkg': The counter is available for each physical package.
- *    The counters include PKG_C*_RESIDENCY.
- *
- * All of these counters are specified in the Intel® 64 and IA-32
- * Architectures Software Developer.s Manual Vol3b.
- *
- * Model specific counters:
- *     MSR_CORE_C1_RES: CORE C1 Residency Counter
- *                      perf code: 0x00
- *                      Available model: SLM,AMT
- *                      Scope: Core (each processor core has a MSR)
- *     MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
- *                            perf code: 0x01
- *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL
- *                            Scope: Core
- *     MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter
- *                            perf code: 0x02
- *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL
- *                            Scope: Core
- *     MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
- *                            perf code: 0x03
- *                            Available model: SNB,IVB,HSW,BDW,SKL
- *                            Scope: Core
- *     MSR_PKG_C2_RESIDENCY:  Package C2 Residency Counter.
- *                            perf code: 0x00
- *                            Available model: SNB,IVB,HSW,BDW,SKL
- *                            Scope: Package (physical package)
- *     MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
- *                            perf code: 0x01
- *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL
- *                            Scope: Package (physical package)
- *     MSR_PKG_C6_RESIDENCY:  Package C6 Residency Counter.
- *                            perf code: 0x02
- *                            Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,SKL
- *                            Scope: Package (physical package)
- *     MSR_PKG_C7_RESIDENCY:  Package C7 Residency Counter.
- *                            perf code: 0x03
- *                            Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL
- *                            Scope: Package (physical package)
- *     MSR_PKG_C8_RESIDENCY:  Package C8 Residency Counter.
- *                            perf code: 0x04
- *                            Available model: HSW ULT only
- *                            Scope: Package (physical package)
- *     MSR_PKG_C9_RESIDENCY:  Package C9 Residency Counter.
- *                            perf code: 0x05
- *                            Available model: HSW ULT only
- *                            Scope: Package (physical package)
- *     MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
- *                            perf code: 0x06
- *                            Available model: HSW ULT only
- *                            Scope: Package (physical package)
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/perf_event.h>
-#include <asm/cpu_device_id.h>
-#include "perf_event.h"
-
-#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format)                \
-static ssize_t __cstate_##_var##_show(struct kobject *kobj,    \
-                               struct kobj_attribute *attr,    \
-                               char *page)                     \
-{                                                              \
-       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);             \
-       return sprintf(page, _format "\n");                     \
-}                                                              \
-static struct kobj_attribute format_attr_##_var =              \
-       __ATTR(_name, 0444, __cstate_##_var##_show, NULL)
-
-static ssize_t cstate_get_attr_cpumask(struct device *dev,
-                                      struct device_attribute *attr,
-                                      char *buf);
-
-struct perf_cstate_msr {
-       u64     msr;
-       struct  perf_pmu_events_attr *attr;
-       bool    (*test)(int idx);
-};
-
-
-/* cstate_core PMU */
-
-static struct pmu cstate_core_pmu;
-static bool has_cstate_core;
-
-enum perf_cstate_core_id {
-       /*
-        * cstate_core events
-        */
-       PERF_CSTATE_CORE_C1_RES = 0,
-       PERF_CSTATE_CORE_C3_RES,
-       PERF_CSTATE_CORE_C6_RES,
-       PERF_CSTATE_CORE_C7_RES,
-
-       PERF_CSTATE_CORE_EVENT_MAX,
-};
-
-bool test_core(int idx)
-{
-       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-           boot_cpu_data.x86 != 6)
-               return false;
-
-       switch (boot_cpu_data.x86_model) {
-       case 30: /* 45nm Nehalem    */
-       case 26: /* 45nm Nehalem-EP */
-       case 46: /* 45nm Nehalem-EX */
-
-       case 37: /* 32nm Westmere    */
-       case 44: /* 32nm Westmere-EP */
-       case 47: /* 32nm Westmere-EX */
-               if (idx == PERF_CSTATE_CORE_C3_RES ||
-                   idx == PERF_CSTATE_CORE_C6_RES)
-                       return true;
-               break;
-       case 42: /* 32nm SandyBridge         */
-       case 45: /* 32nm SandyBridge-E/EN/EP */
-
-       case 58: /* 22nm IvyBridge       */
-       case 62: /* 22nm IvyBridge-EP/EX */
-
-       case 60: /* 22nm Haswell Core */
-       case 63: /* 22nm Haswell Server */
-       case 69: /* 22nm Haswell ULT */
-       case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
-
-       case 61: /* 14nm Broadwell Core-M */
-       case 86: /* 14nm Broadwell Xeon D */
-       case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
-       case 79: /* 14nm Broadwell Server */
-
-       case 78: /* 14nm Skylake Mobile */
-       case 94: /* 14nm Skylake Desktop */
-               if (idx == PERF_CSTATE_CORE_C3_RES ||
-                   idx == PERF_CSTATE_CORE_C6_RES ||
-                   idx == PERF_CSTATE_CORE_C7_RES)
-                       return true;
-               break;
-       case 55: /* 22nm Atom "Silvermont"                */
-       case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
-       case 76: /* 14nm Atom "Airmont"                   */
-               if (idx == PERF_CSTATE_CORE_C1_RES ||
-                   idx == PERF_CSTATE_CORE_C6_RES)
-                       return true;
-               break;
-       }
-
-       return false;
-}
-
-PMU_EVENT_ATTR_STRING(c1-residency, evattr_cstate_core_c1, "event=0x00");
-PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_core_c3, "event=0x01");
-PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_core_c6, "event=0x02");
-PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_core_c7, "event=0x03");
-
-static struct perf_cstate_msr core_msr[] = {
-       [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES,          &evattr_cstate_core_c1, test_core, },
-       [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY,    &evattr_cstate_core_c3, test_core, },
-       [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY,    &evattr_cstate_core_c6, test_core, },
-       [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY,    &evattr_cstate_core_c7, test_core, },
-};
-
-static struct attribute *core_events_attrs[PERF_CSTATE_CORE_EVENT_MAX + 1] = {
-       NULL,
-};
-
-static struct attribute_group core_events_attr_group = {
-       .name = "events",
-       .attrs = core_events_attrs,
-};
-
-DEFINE_CSTATE_FORMAT_ATTR(core_event, event, "config:0-63");
-static struct attribute *core_format_attrs[] = {
-       &format_attr_core_event.attr,
-       NULL,
-};
-
-static struct attribute_group core_format_attr_group = {
-       .name = "format",
-       .attrs = core_format_attrs,
-};
-
-static cpumask_t cstate_core_cpu_mask;
-static DEVICE_ATTR(cpumask, S_IRUGO, cstate_get_attr_cpumask, NULL);
-
-static struct attribute *cstate_cpumask_attrs[] = {
-       &dev_attr_cpumask.attr,
-       NULL,
-};
-
-static struct attribute_group cpumask_attr_group = {
-       .attrs = cstate_cpumask_attrs,
-};
-
-static const struct attribute_group *core_attr_groups[] = {
-       &core_events_attr_group,
-       &core_format_attr_group,
-       &cpumask_attr_group,
-       NULL,
-};
-
-/* cstate_core PMU end */
-
-
-/* cstate_pkg PMU */
-
-static struct pmu cstate_pkg_pmu;
-static bool has_cstate_pkg;
-
-enum perf_cstate_pkg_id {
-       /*
-        * cstate_pkg events
-        */
-       PERF_CSTATE_PKG_C2_RES = 0,
-       PERF_CSTATE_PKG_C3_RES,
-       PERF_CSTATE_PKG_C6_RES,
-       PERF_CSTATE_PKG_C7_RES,
-       PERF_CSTATE_PKG_C8_RES,
-       PERF_CSTATE_PKG_C9_RES,
-       PERF_CSTATE_PKG_C10_RES,
-
-       PERF_CSTATE_PKG_EVENT_MAX,
-};
-
-bool test_pkg(int idx)
-{
-       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-           boot_cpu_data.x86 != 6)
-               return false;
-
-       switch (boot_cpu_data.x86_model) {
-       case 30: /* 45nm Nehalem    */
-       case 26: /* 45nm Nehalem-EP */
-       case 46: /* 45nm Nehalem-EX */
-
-       case 37: /* 32nm Westmere    */
-       case 44: /* 32nm Westmere-EP */
-       case 47: /* 32nm Westmere-EX */
-               if (idx == PERF_CSTATE_CORE_C3_RES ||
-                   idx == PERF_CSTATE_CORE_C6_RES ||
-                   idx == PERF_CSTATE_CORE_C7_RES)
-                       return true;
-               break;
-       case 42: /* 32nm SandyBridge         */
-       case 45: /* 32nm SandyBridge-E/EN/EP */
-
-       case 58: /* 22nm IvyBridge       */
-       case 62: /* 22nm IvyBridge-EP/EX */
-
-       case 60: /* 22nm Haswell Core */
-       case 63: /* 22nm Haswell Server */
-       case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
-
-       case 61: /* 14nm Broadwell Core-M */
-       case 86: /* 14nm Broadwell Xeon D */
-       case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
-       case 79: /* 14nm Broadwell Server */
-
-       case 78: /* 14nm Skylake Mobile */
-       case 94: /* 14nm Skylake Desktop */
-               if (idx == PERF_CSTATE_PKG_C2_RES ||
-                   idx == PERF_CSTATE_PKG_C3_RES ||
-                   idx == PERF_CSTATE_PKG_C6_RES ||
-                   idx == PERF_CSTATE_PKG_C7_RES)
-                       return true;
-               break;
-       case 55: /* 22nm Atom "Silvermont"                */
-       case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
-       case 76: /* 14nm Atom "Airmont"                   */
-               if (idx == PERF_CSTATE_CORE_C6_RES)
-                       return true;
-               break;
-       case 69: /* 22nm Haswell ULT */
-               if (idx == PERF_CSTATE_PKG_C2_RES ||
-                   idx == PERF_CSTATE_PKG_C3_RES ||
-                   idx == PERF_CSTATE_PKG_C6_RES ||
-                   idx == PERF_CSTATE_PKG_C7_RES ||
-                   idx == PERF_CSTATE_PKG_C8_RES ||
-                   idx == PERF_CSTATE_PKG_C9_RES ||
-                   idx == PERF_CSTATE_PKG_C10_RES)
-                       return true;
-               break;
-       }
-
-       return false;
-}
-
-PMU_EVENT_ATTR_STRING(c2-residency, evattr_cstate_pkg_c2, "event=0x00");
-PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_pkg_c3, "event=0x01");
-PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_pkg_c6, "event=0x02");
-PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_pkg_c7, "event=0x03");
-PMU_EVENT_ATTR_STRING(c8-residency, evattr_cstate_pkg_c8, "event=0x04");
-PMU_EVENT_ATTR_STRING(c9-residency, evattr_cstate_pkg_c9, "event=0x05");
-PMU_EVENT_ATTR_STRING(c10-residency, evattr_cstate_pkg_c10, "event=0x06");
-
-static struct perf_cstate_msr pkg_msr[] = {
-       [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY,      &evattr_cstate_pkg_c2,  test_pkg, },
-       [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY,      &evattr_cstate_pkg_c3,  test_pkg, },
-       [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY,      &evattr_cstate_pkg_c6,  test_pkg, },
-       [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY,      &evattr_cstate_pkg_c7,  test_pkg, },
-       [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY,      &evattr_cstate_pkg_c8,  test_pkg, },
-       [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY,      &evattr_cstate_pkg_c9,  test_pkg, },
-       [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY,    &evattr_cstate_pkg_c10, test_pkg, },
-};
-
-static struct attribute *pkg_events_attrs[PERF_CSTATE_PKG_EVENT_MAX + 1] = {
-       NULL,
-};
-
-static struct attribute_group pkg_events_attr_group = {
-       .name = "events",
-       .attrs = pkg_events_attrs,
-};
-
-DEFINE_CSTATE_FORMAT_ATTR(pkg_event, event, "config:0-63");
-static struct attribute *pkg_format_attrs[] = {
-       &format_attr_pkg_event.attr,
-       NULL,
-};
-static struct attribute_group pkg_format_attr_group = {
-       .name = "format",
-       .attrs = pkg_format_attrs,
-};
-
-static cpumask_t cstate_pkg_cpu_mask;
-
-static const struct attribute_group *pkg_attr_groups[] = {
-       &pkg_events_attr_group,
-       &pkg_format_attr_group,
-       &cpumask_attr_group,
-       NULL,
-};
-
-/* cstate_pkg PMU end*/
-
-static ssize_t cstate_get_attr_cpumask(struct device *dev,
-                                      struct device_attribute *attr,
-                                      char *buf)
-{
-       struct pmu *pmu = dev_get_drvdata(dev);
-
-       if (pmu == &cstate_core_pmu)
-               return cpumap_print_to_pagebuf(true, buf, &cstate_core_cpu_mask);
-       else if (pmu == &cstate_pkg_pmu)
-               return cpumap_print_to_pagebuf(true, buf, &cstate_pkg_cpu_mask);
-       else
-               return 0;
-}
-
-static int cstate_pmu_event_init(struct perf_event *event)
-{
-       u64 cfg = event->attr.config;
-       int ret = 0;
-
-       if (event->attr.type != event->pmu->type)
-               return -ENOENT;
-
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
-               return -EINVAL;
-
-       if (event->pmu == &cstate_core_pmu) {
-               if (cfg >= PERF_CSTATE_CORE_EVENT_MAX)
-                       return -EINVAL;
-               if (!core_msr[cfg].attr)
-                       return -EINVAL;
-               event->hw.event_base = core_msr[cfg].msr;
-       } else if (event->pmu == &cstate_pkg_pmu) {
-               if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)
-                       return -EINVAL;
-               if (!pkg_msr[cfg].attr)
-                       return -EINVAL;
-               event->hw.event_base = pkg_msr[cfg].msr;
-       } else
-               return -ENOENT;
-
-       /* must be done before validate_group */
-       event->hw.config = cfg;
-       event->hw.idx = -1;
-
-       return ret;
-}
-
-static inline u64 cstate_pmu_read_counter(struct perf_event *event)
-{
-       u64 val;
-
-       rdmsrl(event->hw.event_base, val);
-       return val;
-}
-
-static void cstate_pmu_event_update(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 prev_raw_count, new_raw_count;
-
-again:
-       prev_raw_count = local64_read(&hwc->prev_count);
-       new_raw_count = cstate_pmu_read_counter(event);
-
-       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-                           new_raw_count) != prev_raw_count)
-               goto again;
-
-       local64_add(new_raw_count - prev_raw_count, &event->count);
-}
-
-static void cstate_pmu_event_start(struct perf_event *event, int mode)
-{
-       local64_set(&event->hw.prev_count, cstate_pmu_read_counter(event));
-}
-
-static void cstate_pmu_event_stop(struct perf_event *event, int mode)
-{
-       cstate_pmu_event_update(event);
-}
-
-static void cstate_pmu_event_del(struct perf_event *event, int mode)
-{
-       cstate_pmu_event_stop(event, PERF_EF_UPDATE);
-}
-
-static int cstate_pmu_event_add(struct perf_event *event, int mode)
-{
-       if (mode & PERF_EF_START)
-               cstate_pmu_event_start(event, mode);
-
-       return 0;
-}
-
-static void cstate_cpu_exit(int cpu)
-{
-       int i, id, target;
-
-       /* cpu exit for cstate core */
-       if (has_cstate_core) {
-               id = topology_core_id(cpu);
-               target = -1;
-
-               for_each_online_cpu(i) {
-                       if (i == cpu)
-                               continue;
-                       if (id == topology_core_id(i)) {
-                               target = i;
-                               break;
-                       }
-               }
-               if (cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask) && target >= 0)
-                       cpumask_set_cpu(target, &cstate_core_cpu_mask);
-               WARN_ON(cpumask_empty(&cstate_core_cpu_mask));
-               if (target >= 0)
-                       perf_pmu_migrate_context(&cstate_core_pmu, cpu, target);
-       }
-
-       /* cpu exit for cstate pkg */
-       if (has_cstate_pkg) {
-               id = topology_physical_package_id(cpu);
-               target = -1;
-
-               for_each_online_cpu(i) {
-                       if (i == cpu)
-                               continue;
-                       if (id == topology_physical_package_id(i)) {
-                               target = i;
-                               break;
-                       }
-               }
-               if (cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask) && target >= 0)
-                       cpumask_set_cpu(target, &cstate_pkg_cpu_mask);
-               WARN_ON(cpumask_empty(&cstate_pkg_cpu_mask));
-               if (target >= 0)
-                       perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target);
-       }
-}
-
-static void cstate_cpu_init(int cpu)
-{
-       int i, id;
-
-       /* cpu init for cstate core */
-       if (has_cstate_core) {
-               id = topology_core_id(cpu);
-               for_each_cpu(i, &cstate_core_cpu_mask) {
-                       if (id == topology_core_id(i))
-                               break;
-               }
-               if (i >= nr_cpu_ids)
-                       cpumask_set_cpu(cpu, &cstate_core_cpu_mask);
-       }
-
-       /* cpu init for cstate pkg */
-       if (has_cstate_pkg) {
-               id = topology_physical_package_id(cpu);
-               for_each_cpu(i, &cstate_pkg_cpu_mask) {
-                       if (id == topology_physical_package_id(i))
-                               break;
-               }
-               if (i >= nr_cpu_ids)
-                       cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
-       }
-}
-
-static int cstate_cpu_notifier(struct notifier_block *self,
-                                 unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (long)hcpu;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_UP_PREPARE:
-               break;
-       case CPU_STARTING:
-               cstate_cpu_init(cpu);
-               break;
-       case CPU_UP_CANCELED:
-       case CPU_DYING:
-               break;
-       case CPU_ONLINE:
-       case CPU_DEAD:
-               break;
-       case CPU_DOWN_PREPARE:
-               cstate_cpu_exit(cpu);
-               break;
-       default:
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-/*
- * Probe the cstate events and insert the available one into sysfs attrs
- * Return false if there is no available events.
- */
-static bool cstate_probe_msr(struct perf_cstate_msr *msr,
-                            struct attribute   **events_attrs,
-                            int max_event_nr)
-{
-       int i, j = 0;
-       u64 val;
-
-       /* Probe the cstate events. */
-       for (i = 0; i < max_event_nr; i++) {
-               if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
-                       msr[i].attr = NULL;
-       }
-
-       /* List remaining events in the sysfs attrs. */
-       for (i = 0; i < max_event_nr; i++) {
-               if (msr[i].attr)
-                       events_attrs[j++] = &msr[i].attr->attr.attr;
-       }
-       events_attrs[j] = NULL;
-
-       return (j > 0) ? true : false;
-}
-
-static int __init cstate_init(void)
-{
-       /* SLM has different MSR for PKG C6 */
-       switch (boot_cpu_data.x86_model) {
-       case 55:
-       case 76:
-       case 77:
-               pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
-       }
-
-       if (cstate_probe_msr(core_msr, core_events_attrs, PERF_CSTATE_CORE_EVENT_MAX))
-               has_cstate_core = true;
-
-       if (cstate_probe_msr(pkg_msr, pkg_events_attrs, PERF_CSTATE_PKG_EVENT_MAX))
-               has_cstate_pkg = true;
-
-       return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV;
-}
-
-static void __init cstate_cpumask_init(void)
-{
-       int cpu;
-
-       cpu_notifier_register_begin();
-
-       for_each_online_cpu(cpu)
-               cstate_cpu_init(cpu);
-
-       __perf_cpu_notifier(cstate_cpu_notifier);
-
-       cpu_notifier_register_done();
-}
-
-static struct pmu cstate_core_pmu = {
-       .attr_groups    = core_attr_groups,
-       .name           = "cstate_core",
-       .task_ctx_nr    = perf_invalid_context,
-       .event_init     = cstate_pmu_event_init,
-       .add            = cstate_pmu_event_add, /* must have */
-       .del            = cstate_pmu_event_del, /* must have */
-       .start          = cstate_pmu_event_start,
-       .stop           = cstate_pmu_event_stop,
-       .read           = cstate_pmu_event_update,
-       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
-};
-
-static struct pmu cstate_pkg_pmu = {
-       .attr_groups    = pkg_attr_groups,
-       .name           = "cstate_pkg",
-       .task_ctx_nr    = perf_invalid_context,
-       .event_init     = cstate_pmu_event_init,
-       .add            = cstate_pmu_event_add, /* must have */
-       .del            = cstate_pmu_event_del, /* must have */
-       .start          = cstate_pmu_event_start,
-       .stop           = cstate_pmu_event_stop,
-       .read           = cstate_pmu_event_update,
-       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
-};
-
-static void __init cstate_pmus_register(void)
-{
-       int err;
-
-       if (has_cstate_core) {
-               err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1);
-               if (WARN_ON(err))
-                       pr_info("Failed to register PMU %s error %d\n",
-                               cstate_core_pmu.name, err);
-       }
-
-       if (has_cstate_pkg) {
-               err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1);
-               if (WARN_ON(err))
-                       pr_info("Failed to register PMU %s error %d\n",
-                               cstate_pkg_pmu.name, err);
-       }
-}
-
-static int __init cstate_pmu_init(void)
-{
-       int err;
-
-       if (cpu_has_hypervisor)
-               return -ENODEV;
-
-       err = cstate_init();
-       if (err)
-               return err;
-
-       cstate_cpumask_init();
-
-       cstate_pmus_register();
-
-       return 0;
-}
-
-device_initcall(cstate_pmu_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
deleted file mode 100644 (file)
index 10602f0..0000000
+++ /dev/null
@@ -1,1368 +0,0 @@
-#include <linux/bitops.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-
-#include <asm/perf_event.h>
-#include <asm/insn.h>
-
-#include "perf_event.h"
-
-/* The size of a BTS record in bytes: */
-#define BTS_RECORD_SIZE                24
-
-#define BTS_BUFFER_SIZE                (PAGE_SIZE << 4)
-#define PEBS_BUFFER_SIZE       (PAGE_SIZE << 4)
-#define PEBS_FIXUP_SIZE                PAGE_SIZE
-
-/*
- * pebs_record_32 for p4 and core not supported
-
-struct pebs_record_32 {
-       u32 flags, ip;
-       u32 ax, bc, cx, dx;
-       u32 si, di, bp, sp;
-};
-
- */
-
-union intel_x86_pebs_dse {
-       u64 val;
-       struct {
-               unsigned int ld_dse:4;
-               unsigned int ld_stlb_miss:1;
-               unsigned int ld_locked:1;
-               unsigned int ld_reserved:26;
-       };
-       struct {
-               unsigned int st_l1d_hit:1;
-               unsigned int st_reserved1:3;
-               unsigned int st_stlb_miss:1;
-               unsigned int st_locked:1;
-               unsigned int st_reserved2:26;
-       };
-};
-
-
-/*
- * Map PEBS Load Latency Data Source encodings to generic
- * memory data source information
- */
-#define P(a, b) PERF_MEM_S(a, b)
-#define OP_LH (P(OP, LOAD) | P(LVL, HIT))
-#define SNOOP_NONE_MISS (P(SNOOP, NONE) | P(SNOOP, MISS))
-
-static const u64 pebs_data_source[] = {
-       P(OP, LOAD) | P(LVL, MISS) | P(LVL, L3) | P(SNOOP, NA),/* 0x00:ukn L3 */
-       OP_LH | P(LVL, L1)  | P(SNOOP, NONE),   /* 0x01: L1 local */
-       OP_LH | P(LVL, LFB) | P(SNOOP, NONE),   /* 0x02: LFB hit */
-       OP_LH | P(LVL, L2)  | P(SNOOP, NONE),   /* 0x03: L2 hit */
-       OP_LH | P(LVL, L3)  | P(SNOOP, NONE),   /* 0x04: L3 hit */
-       OP_LH | P(LVL, L3)  | P(SNOOP, MISS),   /* 0x05: L3 hit, snoop miss */
-       OP_LH | P(LVL, L3)  | P(SNOOP, HIT),    /* 0x06: L3 hit, snoop hit */
-       OP_LH | P(LVL, L3)  | P(SNOOP, HITM),   /* 0x07: L3 hit, snoop hitm */
-       OP_LH | P(LVL, REM_CCE1) | P(SNOOP, HIT),  /* 0x08: L3 miss snoop hit */
-       OP_LH | P(LVL, REM_CCE1) | P(SNOOP, HITM), /* 0x09: L3 miss snoop hitm*/
-       OP_LH | P(LVL, LOC_RAM)  | P(SNOOP, HIT),  /* 0x0a: L3 miss, shared */
-       OP_LH | P(LVL, REM_RAM1) | P(SNOOP, HIT),  /* 0x0b: L3 miss, shared */
-       OP_LH | P(LVL, LOC_RAM)  | SNOOP_NONE_MISS,/* 0x0c: L3 miss, excl */
-       OP_LH | P(LVL, REM_RAM1) | SNOOP_NONE_MISS,/* 0x0d: L3 miss, excl */
-       OP_LH | P(LVL, IO)  | P(SNOOP, NONE), /* 0x0e: I/O */
-       OP_LH | P(LVL, UNC) | P(SNOOP, NONE), /* 0x0f: uncached */
-};
-
-static u64 precise_store_data(u64 status)
-{
-       union intel_x86_pebs_dse dse;
-       u64 val = P(OP, STORE) | P(SNOOP, NA) | P(LVL, L1) | P(TLB, L2);
-
-       dse.val = status;
-
-       /*
-        * bit 4: TLB access
-        * 1 = stored missed 2nd level TLB
-        *
-        * so it either hit the walker or the OS
-        * otherwise hit 2nd level TLB
-        */
-       if (dse.st_stlb_miss)
-               val |= P(TLB, MISS);
-       else
-               val |= P(TLB, HIT);
-
-       /*
-        * bit 0: hit L1 data cache
-        * if not set, then all we know is that
-        * it missed L1D
-        */
-       if (dse.st_l1d_hit)
-               val |= P(LVL, HIT);
-       else
-               val |= P(LVL, MISS);
-
-       /*
-        * bit 5: Locked prefix
-        */
-       if (dse.st_locked)
-               val |= P(LOCK, LOCKED);
-
-       return val;
-}
-
-static u64 precise_datala_hsw(struct perf_event *event, u64 status)
-{
-       union perf_mem_data_src dse;
-
-       dse.val = PERF_MEM_NA;
-
-       if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW)
-               dse.mem_op = PERF_MEM_OP_STORE;
-       else if (event->hw.flags & PERF_X86_EVENT_PEBS_LD_HSW)
-               dse.mem_op = PERF_MEM_OP_LOAD;
-
-       /*
-        * L1 info only valid for following events:
-        *
-        * MEM_UOPS_RETIRED.STLB_MISS_STORES
-        * MEM_UOPS_RETIRED.LOCK_STORES
-        * MEM_UOPS_RETIRED.SPLIT_STORES
-        * MEM_UOPS_RETIRED.ALL_STORES
-        */
-       if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW) {
-               if (status & 1)
-                       dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT;
-               else
-                       dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_MISS;
-       }
-       return dse.val;
-}
-
-static u64 load_latency_data(u64 status)
-{
-       union intel_x86_pebs_dse dse;
-       u64 val;
-       int model = boot_cpu_data.x86_model;
-       int fam = boot_cpu_data.x86;
-
-       dse.val = status;
-
-       /*
-        * use the mapping table for bit 0-3
-        */
-       val = pebs_data_source[dse.ld_dse];
-
-       /*
-        * Nehalem models do not support TLB, Lock infos
-        */
-       if (fam == 0x6 && (model == 26 || model == 30
-           || model == 31 || model == 46)) {
-               val |= P(TLB, NA) | P(LOCK, NA);
-               return val;
-       }
-       /*
-        * bit 4: TLB access
-        * 0 = did not miss 2nd level TLB
-        * 1 = missed 2nd level TLB
-        */
-       if (dse.ld_stlb_miss)
-               val |= P(TLB, MISS) | P(TLB, L2);
-       else
-               val |= P(TLB, HIT) | P(TLB, L1) | P(TLB, L2);
-
-       /*
-        * bit 5: locked prefix
-        */
-       if (dse.ld_locked)
-               val |= P(LOCK, LOCKED);
-
-       return val;
-}
-
-struct pebs_record_core {
-       u64 flags, ip;
-       u64 ax, bx, cx, dx;
-       u64 si, di, bp, sp;
-       u64 r8,  r9,  r10, r11;
-       u64 r12, r13, r14, r15;
-};
-
-struct pebs_record_nhm {
-       u64 flags, ip;
-       u64 ax, bx, cx, dx;
-       u64 si, di, bp, sp;
-       u64 r8,  r9,  r10, r11;
-       u64 r12, r13, r14, r15;
-       u64 status, dla, dse, lat;
-};
-
-/*
- * Same as pebs_record_nhm, with two additional fields.
- */
-struct pebs_record_hsw {
-       u64 flags, ip;
-       u64 ax, bx, cx, dx;
-       u64 si, di, bp, sp;
-       u64 r8,  r9,  r10, r11;
-       u64 r12, r13, r14, r15;
-       u64 status, dla, dse, lat;
-       u64 real_ip, tsx_tuning;
-};
-
-union hsw_tsx_tuning {
-       struct {
-               u32 cycles_last_block     : 32,
-                   hle_abort             : 1,
-                   rtm_abort             : 1,
-                   instruction_abort     : 1,
-                   non_instruction_abort : 1,
-                   retry                 : 1,
-                   data_conflict         : 1,
-                   capacity_writes       : 1,
-                   capacity_reads        : 1;
-       };
-       u64         value;
-};
-
-#define PEBS_HSW_TSX_FLAGS     0xff00000000ULL
-
-/* Same as HSW, plus TSC */
-
-struct pebs_record_skl {
-       u64 flags, ip;
-       u64 ax, bx, cx, dx;
-       u64 si, di, bp, sp;
-       u64 r8,  r9,  r10, r11;
-       u64 r12, r13, r14, r15;
-       u64 status, dla, dse, lat;
-       u64 real_ip, tsx_tuning;
-       u64 tsc;
-};
-
-void init_debug_store_on_cpu(int cpu)
-{
-       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
-
-       if (!ds)
-               return;
-
-       wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA,
-                    (u32)((u64)(unsigned long)ds),
-                    (u32)((u64)(unsigned long)ds >> 32));
-}
-
-void fini_debug_store_on_cpu(int cpu)
-{
-       if (!per_cpu(cpu_hw_events, cpu).ds)
-               return;
-
-       wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0);
-}
-
-static DEFINE_PER_CPU(void *, insn_buffer);
-
-static int alloc_pebs_buffer(int cpu)
-{
-       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
-       int node = cpu_to_node(cpu);
-       int max;
-       void *buffer, *ibuffer;
-
-       if (!x86_pmu.pebs)
-               return 0;
-
-       buffer = kzalloc_node(PEBS_BUFFER_SIZE, GFP_KERNEL, node);
-       if (unlikely(!buffer))
-               return -ENOMEM;
-
-       /*
-        * HSW+ already provides us the eventing ip; no need to allocate this
-        * buffer then.
-        */
-       if (x86_pmu.intel_cap.pebs_format < 2) {
-               ibuffer = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node);
-               if (!ibuffer) {
-                       kfree(buffer);
-                       return -ENOMEM;
-               }
-               per_cpu(insn_buffer, cpu) = ibuffer;
-       }
-
-       max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size;
-
-       ds->pebs_buffer_base = (u64)(unsigned long)buffer;
-       ds->pebs_index = ds->pebs_buffer_base;
-       ds->pebs_absolute_maximum = ds->pebs_buffer_base +
-               max * x86_pmu.pebs_record_size;
-
-       return 0;
-}
-
-static void release_pebs_buffer(int cpu)
-{
-       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
-
-       if (!ds || !x86_pmu.pebs)
-               return;
-
-       kfree(per_cpu(insn_buffer, cpu));
-       per_cpu(insn_buffer, cpu) = NULL;
-
-       kfree((void *)(unsigned long)ds->pebs_buffer_base);
-       ds->pebs_buffer_base = 0;
-}
-
-static int alloc_bts_buffer(int cpu)
-{
-       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
-       int node = cpu_to_node(cpu);
-       int max, thresh;
-       void *buffer;
-
-       if (!x86_pmu.bts)
-               return 0;
-
-       buffer = kzalloc_node(BTS_BUFFER_SIZE, GFP_KERNEL | __GFP_NOWARN, node);
-       if (unlikely(!buffer)) {
-               WARN_ONCE(1, "%s: BTS buffer allocation failure\n", __func__);
-               return -ENOMEM;
-       }
-
-       max = BTS_BUFFER_SIZE / BTS_RECORD_SIZE;
-       thresh = max / 16;
-
-       ds->bts_buffer_base = (u64)(unsigned long)buffer;
-       ds->bts_index = ds->bts_buffer_base;
-       ds->bts_absolute_maximum = ds->bts_buffer_base +
-               max * BTS_RECORD_SIZE;
-       ds->bts_interrupt_threshold = ds->bts_absolute_maximum -
-               thresh * BTS_RECORD_SIZE;
-
-       return 0;
-}
-
-static void release_bts_buffer(int cpu)
-{
-       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
-
-       if (!ds || !x86_pmu.bts)
-               return;
-
-       kfree((void *)(unsigned long)ds->bts_buffer_base);
-       ds->bts_buffer_base = 0;
-}
-
-static int alloc_ds_buffer(int cpu)
-{
-       int node = cpu_to_node(cpu);
-       struct debug_store *ds;
-
-       ds = kzalloc_node(sizeof(*ds), GFP_KERNEL, node);
-       if (unlikely(!ds))
-               return -ENOMEM;
-
-       per_cpu(cpu_hw_events, cpu).ds = ds;
-
-       return 0;
-}
-
-static void release_ds_buffer(int cpu)
-{
-       struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
-
-       if (!ds)
-               return;
-
-       per_cpu(cpu_hw_events, cpu).ds = NULL;
-       kfree(ds);
-}
-
-void release_ds_buffers(void)
-{
-       int cpu;
-
-       if (!x86_pmu.bts && !x86_pmu.pebs)
-               return;
-
-       get_online_cpus();
-       for_each_online_cpu(cpu)
-               fini_debug_store_on_cpu(cpu);
-
-       for_each_possible_cpu(cpu) {
-               release_pebs_buffer(cpu);
-               release_bts_buffer(cpu);
-               release_ds_buffer(cpu);
-       }
-       put_online_cpus();
-}
-
-void reserve_ds_buffers(void)
-{
-       int bts_err = 0, pebs_err = 0;
-       int cpu;
-
-       x86_pmu.bts_active = 0;
-       x86_pmu.pebs_active = 0;
-
-       if (!x86_pmu.bts && !x86_pmu.pebs)
-               return;
-
-       if (!x86_pmu.bts)
-               bts_err = 1;
-
-       if (!x86_pmu.pebs)
-               pebs_err = 1;
-
-       get_online_cpus();
-
-       for_each_possible_cpu(cpu) {
-               if (alloc_ds_buffer(cpu)) {
-                       bts_err = 1;
-                       pebs_err = 1;
-               }
-
-               if (!bts_err && alloc_bts_buffer(cpu))
-                       bts_err = 1;
-
-               if (!pebs_err && alloc_pebs_buffer(cpu))
-                       pebs_err = 1;
-
-               if (bts_err && pebs_err)
-                       break;
-       }
-
-       if (bts_err) {
-               for_each_possible_cpu(cpu)
-                       release_bts_buffer(cpu);
-       }
-
-       if (pebs_err) {
-               for_each_possible_cpu(cpu)
-                       release_pebs_buffer(cpu);
-       }
-
-       if (bts_err && pebs_err) {
-               for_each_possible_cpu(cpu)
-                       release_ds_buffer(cpu);
-       } else {
-               if (x86_pmu.bts && !bts_err)
-                       x86_pmu.bts_active = 1;
-
-               if (x86_pmu.pebs && !pebs_err)
-                       x86_pmu.pebs_active = 1;
-
-               for_each_online_cpu(cpu)
-                       init_debug_store_on_cpu(cpu);
-       }
-
-       put_online_cpus();
-}
-
-/*
- * BTS
- */
-
-struct event_constraint bts_constraint =
-       EVENT_CONSTRAINT(0, 1ULL << INTEL_PMC_IDX_FIXED_BTS, 0);
-
-void intel_pmu_enable_bts(u64 config)
-{
-       unsigned long debugctlmsr;
-
-       debugctlmsr = get_debugctlmsr();
-
-       debugctlmsr |= DEBUGCTLMSR_TR;
-       debugctlmsr |= DEBUGCTLMSR_BTS;
-       if (config & ARCH_PERFMON_EVENTSEL_INT)
-               debugctlmsr |= DEBUGCTLMSR_BTINT;
-
-       if (!(config & ARCH_PERFMON_EVENTSEL_OS))
-               debugctlmsr |= DEBUGCTLMSR_BTS_OFF_OS;
-
-       if (!(config & ARCH_PERFMON_EVENTSEL_USR))
-               debugctlmsr |= DEBUGCTLMSR_BTS_OFF_USR;
-
-       update_debugctlmsr(debugctlmsr);
-}
-
-void intel_pmu_disable_bts(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       unsigned long debugctlmsr;
-
-       if (!cpuc->ds)
-               return;
-
-       debugctlmsr = get_debugctlmsr();
-
-       debugctlmsr &=
-               ~(DEBUGCTLMSR_TR | DEBUGCTLMSR_BTS | DEBUGCTLMSR_BTINT |
-                 DEBUGCTLMSR_BTS_OFF_OS | DEBUGCTLMSR_BTS_OFF_USR);
-
-       update_debugctlmsr(debugctlmsr);
-}
-
-int intel_pmu_drain_bts_buffer(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct debug_store *ds = cpuc->ds;
-       struct bts_record {
-               u64     from;
-               u64     to;
-               u64     flags;
-       };
-       struct perf_event *event = cpuc->events[INTEL_PMC_IDX_FIXED_BTS];
-       struct bts_record *at, *base, *top;
-       struct perf_output_handle handle;
-       struct perf_event_header header;
-       struct perf_sample_data data;
-       unsigned long skip = 0;
-       struct pt_regs regs;
-
-       if (!event)
-               return 0;
-
-       if (!x86_pmu.bts_active)
-               return 0;
-
-       base = (struct bts_record *)(unsigned long)ds->bts_buffer_base;
-       top  = (struct bts_record *)(unsigned long)ds->bts_index;
-
-       if (top <= base)
-               return 0;
-
-       memset(&regs, 0, sizeof(regs));
-
-       ds->bts_index = ds->bts_buffer_base;
-
-       perf_sample_data_init(&data, 0, event->hw.last_period);
-
-       /*
-        * BTS leaks kernel addresses in branches across the cpl boundary,
-        * such as traps or system calls, so unless the user is asking for
-        * kernel tracing (and right now it's not possible), we'd need to
-        * filter them out. But first we need to count how many of those we
-        * have in the current batch. This is an extra O(n) pass, however,
-        * it's much faster than the other one especially considering that
-        * n <= 2560 (BTS_BUFFER_SIZE / BTS_RECORD_SIZE * 15/16; see the
-        * alloc_bts_buffer()).
-        */
-       for (at = base; at < top; at++) {
-               /*
-                * Note that right now *this* BTS code only works if
-                * attr::exclude_kernel is set, but let's keep this extra
-                * check here in case that changes.
-                */
-               if (event->attr.exclude_kernel &&
-                   (kernel_ip(at->from) || kernel_ip(at->to)))
-                       skip++;
-       }
-
-       /*
-        * Prepare a generic sample, i.e. fill in the invariant fields.
-        * We will overwrite the from and to address before we output
-        * the sample.
-        */
-       perf_prepare_sample(&header, &data, event, &regs);
-
-       if (perf_output_begin(&handle, event, header.size *
-                             (top - base - skip)))
-               return 1;
-
-       for (at = base; at < top; at++) {
-               /* Filter out any records that contain kernel addresses. */
-               if (event->attr.exclude_kernel &&
-                   (kernel_ip(at->from) || kernel_ip(at->to)))
-                       continue;
-
-               data.ip         = at->from;
-               data.addr       = at->to;
-
-               perf_output_sample(&handle, &header, &data, event);
-       }
-
-       perf_output_end(&handle);
-
-       /* There's new data available. */
-       event->hw.interrupts++;
-       event->pending_kill = POLL_IN;
-       return 1;
-}
-
-static inline void intel_pmu_drain_pebs_buffer(void)
-{
-       struct pt_regs regs;
-
-       x86_pmu.drain_pebs(&regs);
-}
-
-void intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in)
-{
-       if (!sched_in)
-               intel_pmu_drain_pebs_buffer();
-}
-
-/*
- * PEBS
- */
-struct event_constraint intel_core2_pebs_event_constraints[] = {
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
-       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01),
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_atom_pebs_event_constraints[] = {
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
-       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01),
-       /* Allow all events as PEBS with no flags */
-       INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_slm_pebs_event_constraints[] = {
-       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x1),
-       /* Allow all events as PEBS with no flags */
-       INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_nehalem_pebs_event_constraints[] = {
-       INTEL_PLD_CONSTRAINT(0x100b, 0xf),      /* MEM_INST_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xf),    /* INST_RETIRED.ANY */
-       INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
-       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f),
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_westmere_pebs_event_constraints[] = {
-       INTEL_PLD_CONSTRAINT(0x100b, 0xf),      /* MEM_INST_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xf),    /* INSTR_RETIRED.* */
-       INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
-       /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f),
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_snb_pebs_event_constraints[] = {
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
-       INTEL_PLD_CONSTRAINT(0x01cd, 0x8),    /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */
-       INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */
-       /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
-        INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */
-        INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
-        INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
-        INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf),    /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
-       /* Allow all events as PEBS with no flags */
-       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_ivb_pebs_event_constraints[] = {
-        INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
-        INTEL_PLD_CONSTRAINT(0x01cd, 0x8),    /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */
-       INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */
-       /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
-       /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
-       INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
-       INTEL_EXCLEVT_CONSTRAINT(0xd3, 0xf),    /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
-       /* Allow all events as PEBS with no flags */
-       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
-        EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_hsw_pebs_event_constraints[] = {
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
-       INTEL_PLD_CONSTRAINT(0x01cd, 0xf),    /* MEM_TRANS_RETIRED.* */
-       /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
-       /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x12d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_STORES */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x42d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_STORES */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XST(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd2, 0xf),    /* MEM_LOAD_UOPS_L3_HIT_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_XLD(0xd3, 0xf),    /* MEM_LOAD_UOPS_L3_MISS_RETIRED.* */
-       /* Allow all events as PEBS with no flags */
-       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint intel_skl_pebs_event_constraints[] = {
-       INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x2),      /* INST_RETIRED.PREC_DIST */
-       /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2),
-       /* INST_RETIRED.TOTAL_CYCLES_PS (inv=1, cmask=16) (cycles:p). */
-       INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f),
-       INTEL_PLD_CONSTRAINT(0x1cd, 0xf),                     /* MEM_TRANS_RETIRED.* */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_INST_RETIRED.LOCK_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x22d0, 0xf), /* MEM_INST_RETIRED.LOCK_STORES */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_INST_RETIRED.SPLIT_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_INST_RETIRED.SPLIT_STORES */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_INST_RETIRED.ALL_LOADS */
-       INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_INST_RETIRED.ALL_STORES */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd1, 0xf),    /* MEM_LOAD_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd2, 0xf),    /* MEM_LOAD_L3_HIT_RETIRED.* */
-       INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd3, 0xf),    /* MEM_LOAD_L3_MISS_RETIRED.* */
-       /* Allow all events as PEBS with no flags */
-       INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
-       EVENT_CONSTRAINT_END
-};
-
-struct event_constraint *intel_pebs_constraints(struct perf_event *event)
-{
-       struct event_constraint *c;
-
-       if (!event->attr.precise_ip)
-               return NULL;
-
-       if (x86_pmu.pebs_constraints) {
-               for_each_event_constraint(c, x86_pmu.pebs_constraints) {
-                       if ((event->hw.config & c->cmask) == c->code) {
-                               event->hw.flags |= c->flags;
-                               return c;
-                       }
-               }
-       }
-
-       return &emptyconstraint;
-}
-
-static inline bool pebs_is_enabled(struct cpu_hw_events *cpuc)
-{
-       return (cpuc->pebs_enabled & ((1ULL << MAX_PEBS_EVENTS) - 1));
-}
-
-void intel_pmu_pebs_enable(struct perf_event *event)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct hw_perf_event *hwc = &event->hw;
-       struct debug_store *ds = cpuc->ds;
-       bool first_pebs;
-       u64 threshold;
-
-       hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
-
-       first_pebs = !pebs_is_enabled(cpuc);
-       cpuc->pebs_enabled |= 1ULL << hwc->idx;
-
-       if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
-               cpuc->pebs_enabled |= 1ULL << (hwc->idx + 32);
-       else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
-               cpuc->pebs_enabled |= 1ULL << 63;
-
-       /*
-        * When the event is constrained enough we can use a larger
-        * threshold and run the event with less frequent PMI.
-        */
-       if (hwc->flags & PERF_X86_EVENT_FREERUNNING) {
-               threshold = ds->pebs_absolute_maximum -
-                       x86_pmu.max_pebs_events * x86_pmu.pebs_record_size;
-
-               if (first_pebs)
-                       perf_sched_cb_inc(event->ctx->pmu);
-       } else {
-               threshold = ds->pebs_buffer_base + x86_pmu.pebs_record_size;
-
-               /*
-                * If not all events can use larger buffer,
-                * roll back to threshold = 1
-                */
-               if (!first_pebs &&
-                   (ds->pebs_interrupt_threshold > threshold))
-                       perf_sched_cb_dec(event->ctx->pmu);
-       }
-
-       /* Use auto-reload if possible to save a MSR write in the PMI */
-       if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) {
-               ds->pebs_event_reset[hwc->idx] =
-                       (u64)(-hwc->sample_period) & x86_pmu.cntval_mask;
-       }
-
-       if (first_pebs || ds->pebs_interrupt_threshold > threshold)
-               ds->pebs_interrupt_threshold = threshold;
-}
-
-void intel_pmu_pebs_disable(struct perf_event *event)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct hw_perf_event *hwc = &event->hw;
-       struct debug_store *ds = cpuc->ds;
-       bool large_pebs = ds->pebs_interrupt_threshold >
-               ds->pebs_buffer_base + x86_pmu.pebs_record_size;
-
-       if (large_pebs)
-               intel_pmu_drain_pebs_buffer();
-
-       cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
-
-       if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
-               cpuc->pebs_enabled &= ~(1ULL << (hwc->idx + 32));
-       else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
-               cpuc->pebs_enabled &= ~(1ULL << 63);
-
-       if (large_pebs && !pebs_is_enabled(cpuc))
-               perf_sched_cb_dec(event->ctx->pmu);
-
-       if (cpuc->enabled)
-               wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
-
-       hwc->config |= ARCH_PERFMON_EVENTSEL_INT;
-}
-
-void intel_pmu_pebs_enable_all(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       if (cpuc->pebs_enabled)
-               wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
-}
-
-void intel_pmu_pebs_disable_all(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       if (cpuc->pebs_enabled)
-               wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
-}
-
-static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       unsigned long from = cpuc->lbr_entries[0].from;
-       unsigned long old_to, to = cpuc->lbr_entries[0].to;
-       unsigned long ip = regs->ip;
-       int is_64bit = 0;
-       void *kaddr;
-       int size;
-
-       /*
-        * We don't need to fixup if the PEBS assist is fault like
-        */
-       if (!x86_pmu.intel_cap.pebs_trap)
-               return 1;
-
-       /*
-        * No LBR entry, no basic block, no rewinding
-        */
-       if (!cpuc->lbr_stack.nr || !from || !to)
-               return 0;
-
-       /*
-        * Basic blocks should never cross user/kernel boundaries
-        */
-       if (kernel_ip(ip) != kernel_ip(to))
-               return 0;
-
-       /*
-        * unsigned math, either ip is before the start (impossible) or
-        * the basic block is larger than 1 page (sanity)
-        */
-       if ((ip - to) > PEBS_FIXUP_SIZE)
-               return 0;
-
-       /*
-        * We sampled a branch insn, rewind using the LBR stack
-        */
-       if (ip == to) {
-               set_linear_ip(regs, from);
-               return 1;
-       }
-
-       size = ip - to;
-       if (!kernel_ip(ip)) {
-               int bytes;
-               u8 *buf = this_cpu_read(insn_buffer);
-
-               /* 'size' must fit our buffer, see above */
-               bytes = copy_from_user_nmi(buf, (void __user *)to, size);
-               if (bytes != 0)
-                       return 0;
-
-               kaddr = buf;
-       } else {
-               kaddr = (void *)to;
-       }
-
-       do {
-               struct insn insn;
-
-               old_to = to;
-
-#ifdef CONFIG_X86_64
-               is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
-#endif
-               insn_init(&insn, kaddr, size, is_64bit);
-               insn_get_length(&insn);
-               /*
-                * Make sure there was not a problem decoding the
-                * instruction and getting the length.  This is
-                * doubly important because we have an infinite
-                * loop if insn.length=0.
-                */
-               if (!insn.length)
-                       break;
-
-               to += insn.length;
-               kaddr += insn.length;
-               size -= insn.length;
-       } while (to < ip);
-
-       if (to == ip) {
-               set_linear_ip(regs, old_to);
-               return 1;
-       }
-
-       /*
-        * Even though we decoded the basic block, the instruction stream
-        * never matched the given IP, either the TO or the IP got corrupted.
-        */
-       return 0;
-}
-
-static inline u64 intel_hsw_weight(struct pebs_record_skl *pebs)
-{
-       if (pebs->tsx_tuning) {
-               union hsw_tsx_tuning tsx = { .value = pebs->tsx_tuning };
-               return tsx.cycles_last_block;
-       }
-       return 0;
-}
-
-static inline u64 intel_hsw_transaction(struct pebs_record_skl *pebs)
-{
-       u64 txn = (pebs->tsx_tuning & PEBS_HSW_TSX_FLAGS) >> 32;
-
-       /* For RTM XABORTs also log the abort code from AX */
-       if ((txn & PERF_TXN_TRANSACTION) && (pebs->ax & 1))
-               txn |= ((pebs->ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT;
-       return txn;
-}
-
-static void setup_pebs_sample_data(struct perf_event *event,
-                                  struct pt_regs *iregs, void *__pebs,
-                                  struct perf_sample_data *data,
-                                  struct pt_regs *regs)
-{
-#define PERF_X86_EVENT_PEBS_HSW_PREC \
-               (PERF_X86_EVENT_PEBS_ST_HSW | \
-                PERF_X86_EVENT_PEBS_LD_HSW | \
-                PERF_X86_EVENT_PEBS_NA_HSW)
-       /*
-        * We cast to the biggest pebs_record but are careful not to
-        * unconditionally access the 'extra' entries.
-        */
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct pebs_record_skl *pebs = __pebs;
-       u64 sample_type;
-       int fll, fst, dsrc;
-       int fl = event->hw.flags;
-
-       if (pebs == NULL)
-               return;
-
-       sample_type = event->attr.sample_type;
-       dsrc = sample_type & PERF_SAMPLE_DATA_SRC;
-
-       fll = fl & PERF_X86_EVENT_PEBS_LDLAT;
-       fst = fl & (PERF_X86_EVENT_PEBS_ST | PERF_X86_EVENT_PEBS_HSW_PREC);
-
-       perf_sample_data_init(data, 0, event->hw.last_period);
-
-       data->period = event->hw.last_period;
-
-       /*
-        * Use latency for weight (only avail with PEBS-LL)
-        */
-       if (fll && (sample_type & PERF_SAMPLE_WEIGHT))
-               data->weight = pebs->lat;
-
-       /*
-        * data.data_src encodes the data source
-        */
-       if (dsrc) {
-               u64 val = PERF_MEM_NA;
-               if (fll)
-                       val = load_latency_data(pebs->dse);
-               else if (fst && (fl & PERF_X86_EVENT_PEBS_HSW_PREC))
-                       val = precise_datala_hsw(event, pebs->dse);
-               else if (fst)
-                       val = precise_store_data(pebs->dse);
-               data->data_src.val = val;
-       }
-
-       /*
-        * We use the interrupt regs as a base because the PEBS record
-        * does not contain a full regs set, specifically it seems to
-        * lack segment descriptors, which get used by things like
-        * user_mode().
-        *
-        * In the simple case fix up only the IP and BP,SP regs, for
-        * PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly.
-        * A possible PERF_SAMPLE_REGS will have to transfer all regs.
-        */
-       *regs = *iregs;
-       regs->flags = pebs->flags;
-       set_linear_ip(regs, pebs->ip);
-       regs->bp = pebs->bp;
-       regs->sp = pebs->sp;
-
-       if (sample_type & PERF_SAMPLE_REGS_INTR) {
-               regs->ax = pebs->ax;
-               regs->bx = pebs->bx;
-               regs->cx = pebs->cx;
-               regs->dx = pebs->dx;
-               regs->si = pebs->si;
-               regs->di = pebs->di;
-               regs->bp = pebs->bp;
-               regs->sp = pebs->sp;
-
-               regs->flags = pebs->flags;
-#ifndef CONFIG_X86_32
-               regs->r8 = pebs->r8;
-               regs->r9 = pebs->r9;
-               regs->r10 = pebs->r10;
-               regs->r11 = pebs->r11;
-               regs->r12 = pebs->r12;
-               regs->r13 = pebs->r13;
-               regs->r14 = pebs->r14;
-               regs->r15 = pebs->r15;
-#endif
-       }
-
-       if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) {
-               regs->ip = pebs->real_ip;
-               regs->flags |= PERF_EFLAGS_EXACT;
-       } else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(regs))
-               regs->flags |= PERF_EFLAGS_EXACT;
-       else
-               regs->flags &= ~PERF_EFLAGS_EXACT;
-
-       if ((sample_type & PERF_SAMPLE_ADDR) &&
-           x86_pmu.intel_cap.pebs_format >= 1)
-               data->addr = pebs->dla;
-
-       if (x86_pmu.intel_cap.pebs_format >= 2) {
-               /* Only set the TSX weight when no memory weight. */
-               if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)
-                       data->weight = intel_hsw_weight(pebs);
-
-               if (sample_type & PERF_SAMPLE_TRANSACTION)
-                       data->txn = intel_hsw_transaction(pebs);
-       }
-
-       /*
-        * v3 supplies an accurate time stamp, so we use that
-        * for the time stamp.
-        *
-        * We can only do this for the default trace clock.
-        */
-       if (x86_pmu.intel_cap.pebs_format >= 3 &&
-               event->attr.use_clockid == 0)
-               data->time = native_sched_clock_from_tsc(pebs->tsc);
-
-       if (has_branch_stack(event))
-               data->br_stack = &cpuc->lbr_stack;
-}
-
-static inline void *
-get_next_pebs_record_by_bit(void *base, void *top, int bit)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       void *at;
-       u64 pebs_status;
-
-       /*
-        * fmt0 does not have a status bitfield (does not use
-        * perf_record_nhm format)
-        */
-       if (x86_pmu.intel_cap.pebs_format < 1)
-               return base;
-
-       if (base == NULL)
-               return NULL;
-
-       for (at = base; at < top; at += x86_pmu.pebs_record_size) {
-               struct pebs_record_nhm *p = at;
-
-               if (test_bit(bit, (unsigned long *)&p->status)) {
-                       /* PEBS v3 has accurate status bits */
-                       if (x86_pmu.intel_cap.pebs_format >= 3)
-                               return at;
-
-                       if (p->status == (1 << bit))
-                               return at;
-
-                       /* clear non-PEBS bit and re-check */
-                       pebs_status = p->status & cpuc->pebs_enabled;
-                       pebs_status &= (1ULL << MAX_PEBS_EVENTS) - 1;
-                       if (pebs_status == (1 << bit))
-                               return at;
-               }
-       }
-       return NULL;
-}
-
-static void __intel_pmu_pebs_event(struct perf_event *event,
-                                  struct pt_regs *iregs,
-                                  void *base, void *top,
-                                  int bit, int count)
-{
-       struct perf_sample_data data;
-       struct pt_regs regs;
-       void *at = get_next_pebs_record_by_bit(base, top, bit);
-
-       if (!intel_pmu_save_and_restart(event) &&
-           !(event->hw.flags & PERF_X86_EVENT_AUTO_RELOAD))
-               return;
-
-       while (count > 1) {
-               setup_pebs_sample_data(event, iregs, at, &data, &regs);
-               perf_event_output(event, &data, &regs);
-               at += x86_pmu.pebs_record_size;
-               at = get_next_pebs_record_by_bit(at, top, bit);
-               count--;
-       }
-
-       setup_pebs_sample_data(event, iregs, at, &data, &regs);
-
-       /*
-        * All but the last records are processed.
-        * The last one is left to be able to call the overflow handler.
-        */
-       if (perf_event_overflow(event, &data, &regs)) {
-               x86_pmu_stop(event, 0);
-               return;
-       }
-
-}
-
-static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct debug_store *ds = cpuc->ds;
-       struct perf_event *event = cpuc->events[0]; /* PMC0 only */
-       struct pebs_record_core *at, *top;
-       int n;
-
-       if (!x86_pmu.pebs_active)
-               return;
-
-       at  = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base;
-       top = (struct pebs_record_core *)(unsigned long)ds->pebs_index;
-
-       /*
-        * Whatever else happens, drain the thing
-        */
-       ds->pebs_index = ds->pebs_buffer_base;
-
-       if (!test_bit(0, cpuc->active_mask))
-               return;
-
-       WARN_ON_ONCE(!event);
-
-       if (!event->attr.precise_ip)
-               return;
-
-       n = top - at;
-       if (n <= 0)
-               return;
-
-       __intel_pmu_pebs_event(event, iregs, at, top, 0, n);
-}
-
-static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct debug_store *ds = cpuc->ds;
-       struct perf_event *event;
-       void *base, *at, *top;
-       short counts[MAX_PEBS_EVENTS] = {};
-       short error[MAX_PEBS_EVENTS] = {};
-       int bit, i;
-
-       if (!x86_pmu.pebs_active)
-               return;
-
-       base = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
-       top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
-
-       ds->pebs_index = ds->pebs_buffer_base;
-
-       if (unlikely(base >= top))
-               return;
-
-       for (at = base; at < top; at += x86_pmu.pebs_record_size) {
-               struct pebs_record_nhm *p = at;
-               u64 pebs_status;
-
-               /* PEBS v3 has accurate status bits */
-               if (x86_pmu.intel_cap.pebs_format >= 3) {
-                       for_each_set_bit(bit, (unsigned long *)&p->status,
-                                        MAX_PEBS_EVENTS)
-                               counts[bit]++;
-
-                       continue;
-               }
-
-               pebs_status = p->status & cpuc->pebs_enabled;
-               pebs_status &= (1ULL << x86_pmu.max_pebs_events) - 1;
-
-               /*
-                * On some CPUs the PEBS status can be zero when PEBS is
-                * racing with clearing of GLOBAL_STATUS.
-                *
-                * Normally we would drop that record, but in the
-                * case when there is only a single active PEBS event
-                * we can assume it's for that event.
-                */
-               if (!pebs_status && cpuc->pebs_enabled &&
-                       !(cpuc->pebs_enabled & (cpuc->pebs_enabled-1)))
-                       pebs_status = cpuc->pebs_enabled;
-
-               bit = find_first_bit((unsigned long *)&pebs_status,
-                                       x86_pmu.max_pebs_events);
-               if (bit >= x86_pmu.max_pebs_events)
-                       continue;
-
-               /*
-                * The PEBS hardware does not deal well with the situation
-                * when events happen near to each other and multiple bits
-                * are set. But it should happen rarely.
-                *
-                * If these events include one PEBS and multiple non-PEBS
-                * events, it doesn't impact PEBS record. The record will
-                * be handled normally. (slow path)
-                *
-                * If these events include two or more PEBS events, the
-                * records for the events can be collapsed into a single
-                * one, and it's not possible to reconstruct all events
-                * that caused the PEBS record. It's called collision.
-                * If collision happened, the record will be dropped.
-                */
-               if (p->status != (1ULL << bit)) {
-                       for_each_set_bit(i, (unsigned long *)&pebs_status,
-                                        x86_pmu.max_pebs_events)
-                               error[i]++;
-                       continue;
-               }
-
-               counts[bit]++;
-       }
-
-       for (bit = 0; bit < x86_pmu.max_pebs_events; bit++) {
-               if ((counts[bit] == 0) && (error[bit] == 0))
-                       continue;
-
-               event = cpuc->events[bit];
-               WARN_ON_ONCE(!event);
-               WARN_ON_ONCE(!event->attr.precise_ip);
-
-               /* log dropped samples number */
-               if (error[bit])
-                       perf_log_lost_samples(event, error[bit]);
-
-               if (counts[bit]) {
-                       __intel_pmu_pebs_event(event, iregs, base,
-                                              top, bit, counts[bit]);
-               }
-       }
-}
-
-/*
- * BTS, PEBS probe and setup
- */
-
-void __init intel_ds_init(void)
-{
-       /*
-        * No support for 32bit formats
-        */
-       if (!boot_cpu_has(X86_FEATURE_DTES64))
-               return;
-
-       x86_pmu.bts  = boot_cpu_has(X86_FEATURE_BTS);
-       x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS);
-       if (x86_pmu.pebs) {
-               char pebs_type = x86_pmu.intel_cap.pebs_trap ?  '+' : '-';
-               int format = x86_pmu.intel_cap.pebs_format;
-
-               switch (format) {
-               case 0:
-                       printk(KERN_CONT "PEBS fmt0%c, ", pebs_type);
-                       x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
-                       x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
-                       break;
-
-               case 1:
-                       printk(KERN_CONT "PEBS fmt1%c, ", pebs_type);
-                       x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm);
-                       x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
-                       break;
-
-               case 2:
-                       pr_cont("PEBS fmt2%c, ", pebs_type);
-                       x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw);
-                       x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
-                       break;
-
-               case 3:
-                       pr_cont("PEBS fmt3%c, ", pebs_type);
-                       x86_pmu.pebs_record_size =
-                                               sizeof(struct pebs_record_skl);
-                       x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
-                       x86_pmu.free_running_flags |= PERF_SAMPLE_TIME;
-                       break;
-
-               default:
-                       printk(KERN_CONT "no PEBS fmt%d%c, ", format, pebs_type);
-                       x86_pmu.pebs = 0;
-               }
-       }
-}
-
-void perf_restore_debug_store(void)
-{
-       struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
-
-       if (!x86_pmu.bts && !x86_pmu.pebs)
-               return;
-
-       wrmsrl(MSR_IA32_DS_AREA, (unsigned long)ds);
-}
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
deleted file mode 100644 (file)
index 653f88d..0000000
+++ /dev/null
@@ -1,1062 +0,0 @@
-#include <linux/perf_event.h>
-#include <linux/types.h>
-
-#include <asm/perf_event.h>
-#include <asm/msr.h>
-#include <asm/insn.h>
-
-#include "perf_event.h"
-
-enum {
-       LBR_FORMAT_32           = 0x00,
-       LBR_FORMAT_LIP          = 0x01,
-       LBR_FORMAT_EIP          = 0x02,
-       LBR_FORMAT_EIP_FLAGS    = 0x03,
-       LBR_FORMAT_EIP_FLAGS2   = 0x04,
-       LBR_FORMAT_INFO         = 0x05,
-       LBR_FORMAT_MAX_KNOWN    = LBR_FORMAT_INFO,
-};
-
-static enum {
-       LBR_EIP_FLAGS           = 1,
-       LBR_TSX                 = 2,
-} lbr_desc[LBR_FORMAT_MAX_KNOWN + 1] = {
-       [LBR_FORMAT_EIP_FLAGS]  = LBR_EIP_FLAGS,
-       [LBR_FORMAT_EIP_FLAGS2] = LBR_EIP_FLAGS | LBR_TSX,
-};
-
-/*
- * Intel LBR_SELECT bits
- * Intel Vol3a, April 2011, Section 16.7 Table 16-10
- *
- * Hardware branch filter (not available on all CPUs)
- */
-#define LBR_KERNEL_BIT         0 /* do not capture at ring0 */
-#define LBR_USER_BIT           1 /* do not capture at ring > 0 */
-#define LBR_JCC_BIT            2 /* do not capture conditional branches */
-#define LBR_REL_CALL_BIT       3 /* do not capture relative calls */
-#define LBR_IND_CALL_BIT       4 /* do not capture indirect calls */
-#define LBR_RETURN_BIT         5 /* do not capture near returns */
-#define LBR_IND_JMP_BIT                6 /* do not capture indirect jumps */
-#define LBR_REL_JMP_BIT                7 /* do not capture relative jumps */
-#define LBR_FAR_BIT            8 /* do not capture far branches */
-#define LBR_CALL_STACK_BIT     9 /* enable call stack */
-
-/*
- * Following bit only exists in Linux; we mask it out before writing it to
- * the actual MSR. But it helps the constraint perf code to understand
- * that this is a separate configuration.
- */
-#define LBR_NO_INFO_BIT               63 /* don't read LBR_INFO. */
-
-#define LBR_KERNEL     (1 << LBR_KERNEL_BIT)
-#define LBR_USER       (1 << LBR_USER_BIT)
-#define LBR_JCC                (1 << LBR_JCC_BIT)
-#define LBR_REL_CALL   (1 << LBR_REL_CALL_BIT)
-#define LBR_IND_CALL   (1 << LBR_IND_CALL_BIT)
-#define LBR_RETURN     (1 << LBR_RETURN_BIT)
-#define LBR_REL_JMP    (1 << LBR_REL_JMP_BIT)
-#define LBR_IND_JMP    (1 << LBR_IND_JMP_BIT)
-#define LBR_FAR                (1 << LBR_FAR_BIT)
-#define LBR_CALL_STACK (1 << LBR_CALL_STACK_BIT)
-#define LBR_NO_INFO    (1ULL << LBR_NO_INFO_BIT)
-
-#define LBR_PLM (LBR_KERNEL | LBR_USER)
-
-#define LBR_SEL_MASK   0x1ff   /* valid bits in LBR_SELECT */
-#define LBR_NOT_SUPP   -1      /* LBR filter not supported */
-#define LBR_IGN                0       /* ignored */
-
-#define LBR_ANY                 \
-       (LBR_JCC        |\
-        LBR_REL_CALL   |\
-        LBR_IND_CALL   |\
-        LBR_RETURN     |\
-        LBR_REL_JMP    |\
-        LBR_IND_JMP    |\
-        LBR_FAR)
-
-#define LBR_FROM_FLAG_MISPRED  (1ULL << 63)
-#define LBR_FROM_FLAG_IN_TX    (1ULL << 62)
-#define LBR_FROM_FLAG_ABORT    (1ULL << 61)
-
-/*
- * x86control flow change classification
- * x86control flow changes include branches, interrupts, traps, faults
- */
-enum {
-       X86_BR_NONE             = 0,      /* unknown */
-
-       X86_BR_USER             = 1 << 0, /* branch target is user */
-       X86_BR_KERNEL           = 1 << 1, /* branch target is kernel */
-
-       X86_BR_CALL             = 1 << 2, /* call */
-       X86_BR_RET              = 1 << 3, /* return */
-       X86_BR_SYSCALL          = 1 << 4, /* syscall */
-       X86_BR_SYSRET           = 1 << 5, /* syscall return */
-       X86_BR_INT              = 1 << 6, /* sw interrupt */
-       X86_BR_IRET             = 1 << 7, /* return from interrupt */
-       X86_BR_JCC              = 1 << 8, /* conditional */
-       X86_BR_JMP              = 1 << 9, /* jump */
-       X86_BR_IRQ              = 1 << 10,/* hw interrupt or trap or fault */
-       X86_BR_IND_CALL         = 1 << 11,/* indirect calls */
-       X86_BR_ABORT            = 1 << 12,/* transaction abort */
-       X86_BR_IN_TX            = 1 << 13,/* in transaction */
-       X86_BR_NO_TX            = 1 << 14,/* not in transaction */
-       X86_BR_ZERO_CALL        = 1 << 15,/* zero length call */
-       X86_BR_CALL_STACK       = 1 << 16,/* call stack */
-       X86_BR_IND_JMP          = 1 << 17,/* indirect jump */
-};
-
-#define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL)
-#define X86_BR_ANYTX (X86_BR_NO_TX | X86_BR_IN_TX)
-
-#define X86_BR_ANY       \
-       (X86_BR_CALL    |\
-        X86_BR_RET     |\
-        X86_BR_SYSCALL |\
-        X86_BR_SYSRET  |\
-        X86_BR_INT     |\
-        X86_BR_IRET    |\
-        X86_BR_JCC     |\
-        X86_BR_JMP      |\
-        X86_BR_IRQ      |\
-        X86_BR_ABORT    |\
-        X86_BR_IND_CALL |\
-        X86_BR_IND_JMP  |\
-        X86_BR_ZERO_CALL)
-
-#define X86_BR_ALL (X86_BR_PLM | X86_BR_ANY)
-
-#define X86_BR_ANY_CALL                 \
-       (X86_BR_CALL            |\
-        X86_BR_IND_CALL        |\
-        X86_BR_ZERO_CALL       |\
-        X86_BR_SYSCALL         |\
-        X86_BR_IRQ             |\
-        X86_BR_INT)
-
-static void intel_pmu_lbr_filter(struct cpu_hw_events *cpuc);
-
-/*
- * We only support LBR implementations that have FREEZE_LBRS_ON_PMI
- * otherwise it becomes near impossible to get a reliable stack.
- */
-
-static void __intel_pmu_lbr_enable(bool pmi)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       u64 debugctl, lbr_select = 0, orig_debugctl;
-
-       /*
-        * No need to unfreeze manually, as v4 can do that as part
-        * of the GLOBAL_STATUS ack.
-        */
-       if (pmi && x86_pmu.version >= 4)
-               return;
-
-       /*
-        * No need to reprogram LBR_SELECT in a PMI, as it
-        * did not change.
-        */
-       if (cpuc->lbr_sel)
-               lbr_select = cpuc->lbr_sel->config & x86_pmu.lbr_sel_mask;
-       if (!pmi && cpuc->lbr_sel)
-               wrmsrl(MSR_LBR_SELECT, lbr_select);
-
-       rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
-       orig_debugctl = debugctl;
-       debugctl |= DEBUGCTLMSR_LBR;
-       /*
-        * LBR callstack does not work well with FREEZE_LBRS_ON_PMI.
-        * If FREEZE_LBRS_ON_PMI is set, PMI near call/return instructions
-        * may cause superfluous increase/decrease of LBR_TOS.
-        */
-       if (!(lbr_select & LBR_CALL_STACK))
-               debugctl |= DEBUGCTLMSR_FREEZE_LBRS_ON_PMI;
-       if (orig_debugctl != debugctl)
-               wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
-}
-
-static void __intel_pmu_lbr_disable(void)
-{
-       u64 debugctl;
-
-       rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
-       debugctl &= ~(DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI);
-       wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
-}
-
-static void intel_pmu_lbr_reset_32(void)
-{
-       int i;
-
-       for (i = 0; i < x86_pmu.lbr_nr; i++)
-               wrmsrl(x86_pmu.lbr_from + i, 0);
-}
-
-static void intel_pmu_lbr_reset_64(void)
-{
-       int i;
-
-       for (i = 0; i < x86_pmu.lbr_nr; i++) {
-               wrmsrl(x86_pmu.lbr_from + i, 0);
-               wrmsrl(x86_pmu.lbr_to   + i, 0);
-               if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
-                       wrmsrl(MSR_LBR_INFO_0 + i, 0);
-       }
-}
-
-void intel_pmu_lbr_reset(void)
-{
-       if (!x86_pmu.lbr_nr)
-               return;
-
-       if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
-               intel_pmu_lbr_reset_32();
-       else
-               intel_pmu_lbr_reset_64();
-}
-
-/*
- * TOS = most recently recorded branch
- */
-static inline u64 intel_pmu_lbr_tos(void)
-{
-       u64 tos;
-
-       rdmsrl(x86_pmu.lbr_tos, tos);
-       return tos;
-}
-
-enum {
-       LBR_NONE,
-       LBR_VALID,
-};
-
-static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
-{
-       int i;
-       unsigned lbr_idx, mask;
-       u64 tos;
-
-       if (task_ctx->lbr_callstack_users == 0 ||
-           task_ctx->lbr_stack_state == LBR_NONE) {
-               intel_pmu_lbr_reset();
-               return;
-       }
-
-       mask = x86_pmu.lbr_nr - 1;
-       tos = task_ctx->tos;
-       for (i = 0; i < tos; i++) {
-               lbr_idx = (tos - i) & mask;
-               wrmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
-               wrmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
-               if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
-                       wrmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
-       }
-       wrmsrl(x86_pmu.lbr_tos, tos);
-       task_ctx->lbr_stack_state = LBR_NONE;
-}
-
-static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
-{
-       int i;
-       unsigned lbr_idx, mask;
-       u64 tos;
-
-       if (task_ctx->lbr_callstack_users == 0) {
-               task_ctx->lbr_stack_state = LBR_NONE;
-               return;
-       }
-
-       mask = x86_pmu.lbr_nr - 1;
-       tos = intel_pmu_lbr_tos();
-       for (i = 0; i < tos; i++) {
-               lbr_idx = (tos - i) & mask;
-               rdmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
-               rdmsrl(x86_pmu.lbr_to + lbr_idx, task_ctx->lbr_to[i]);
-               if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
-                       rdmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
-       }
-       task_ctx->tos = tos;
-       task_ctx->lbr_stack_state = LBR_VALID;
-}
-
-void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct x86_perf_task_context *task_ctx;
-
-       /*
-        * If LBR callstack feature is enabled and the stack was saved when
-        * the task was scheduled out, restore the stack. Otherwise flush
-        * the LBR stack.
-        */
-       task_ctx = ctx ? ctx->task_ctx_data : NULL;
-       if (task_ctx) {
-               if (sched_in) {
-                       __intel_pmu_lbr_restore(task_ctx);
-                       cpuc->lbr_context = ctx;
-               } else {
-                       __intel_pmu_lbr_save(task_ctx);
-               }
-               return;
-       }
-
-       /*
-        * When sampling the branck stack in system-wide, it may be
-        * necessary to flush the stack on context switch. This happens
-        * when the branch stack does not tag its entries with the pid
-        * of the current task. Otherwise it becomes impossible to
-        * associate a branch entry with a task. This ambiguity is more
-        * likely to appear when the branch stack supports priv level
-        * filtering and the user sets it to monitor only at the user
-        * level (which could be a useful measurement in system-wide
-        * mode). In that case, the risk is high of having a branch
-        * stack with branch from multiple tasks.
-        */
-       if (sched_in) {
-               intel_pmu_lbr_reset();
-               cpuc->lbr_context = ctx;
-       }
-}
-
-static inline bool branch_user_callstack(unsigned br_sel)
-{
-       return (br_sel & X86_BR_USER) && (br_sel & X86_BR_CALL_STACK);
-}
-
-void intel_pmu_lbr_enable(struct perf_event *event)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct x86_perf_task_context *task_ctx;
-
-       if (!x86_pmu.lbr_nr)
-               return;
-
-       /*
-        * Reset the LBR stack if we changed task context to
-        * avoid data leaks.
-        */
-       if (event->ctx->task && cpuc->lbr_context != event->ctx) {
-               intel_pmu_lbr_reset();
-               cpuc->lbr_context = event->ctx;
-       }
-       cpuc->br_sel = event->hw.branch_reg.reg;
-
-       if (branch_user_callstack(cpuc->br_sel) && event->ctx &&
-                                       event->ctx->task_ctx_data) {
-               task_ctx = event->ctx->task_ctx_data;
-               task_ctx->lbr_callstack_users++;
-       }
-
-       cpuc->lbr_users++;
-       perf_sched_cb_inc(event->ctx->pmu);
-}
-
-void intel_pmu_lbr_disable(struct perf_event *event)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       struct x86_perf_task_context *task_ctx;
-
-       if (!x86_pmu.lbr_nr)
-               return;
-
-       if (branch_user_callstack(cpuc->br_sel) && event->ctx &&
-                                       event->ctx->task_ctx_data) {
-               task_ctx = event->ctx->task_ctx_data;
-               task_ctx->lbr_callstack_users--;
-       }
-
-       cpuc->lbr_users--;
-       WARN_ON_ONCE(cpuc->lbr_users < 0);
-       perf_sched_cb_dec(event->ctx->pmu);
-
-       if (cpuc->enabled && !cpuc->lbr_users) {
-               __intel_pmu_lbr_disable();
-               /* avoid stale pointer */
-               cpuc->lbr_context = NULL;
-       }
-}
-
-void intel_pmu_lbr_enable_all(bool pmi)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       if (cpuc->lbr_users)
-               __intel_pmu_lbr_enable(pmi);
-}
-
-void intel_pmu_lbr_disable_all(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       if (cpuc->lbr_users)
-               __intel_pmu_lbr_disable();
-}
-
-static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
-{
-       unsigned long mask = x86_pmu.lbr_nr - 1;
-       u64 tos = intel_pmu_lbr_tos();
-       int i;
-
-       for (i = 0; i < x86_pmu.lbr_nr; i++) {
-               unsigned long lbr_idx = (tos - i) & mask;
-               union {
-                       struct {
-                               u32 from;
-                               u32 to;
-                       };
-                       u64     lbr;
-               } msr_lastbranch;
-
-               rdmsrl(x86_pmu.lbr_from + lbr_idx, msr_lastbranch.lbr);
-
-               cpuc->lbr_entries[i].from       = msr_lastbranch.from;
-               cpuc->lbr_entries[i].to         = msr_lastbranch.to;
-               cpuc->lbr_entries[i].mispred    = 0;
-               cpuc->lbr_entries[i].predicted  = 0;
-               cpuc->lbr_entries[i].reserved   = 0;
-       }
-       cpuc->lbr_stack.nr = i;
-}
-
-/*
- * Due to lack of segmentation in Linux the effective address (offset)
- * is the same as the linear address, allowing us to merge the LIP and EIP
- * LBR formats.
- */
-static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
-{
-       bool need_info = false;
-       unsigned long mask = x86_pmu.lbr_nr - 1;
-       int lbr_format = x86_pmu.intel_cap.lbr_format;
-       u64 tos = intel_pmu_lbr_tos();
-       int i;
-       int out = 0;
-       int num = x86_pmu.lbr_nr;
-
-       if (cpuc->lbr_sel) {
-               need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO);
-               if (cpuc->lbr_sel->config & LBR_CALL_STACK)
-                       num = tos;
-       }
-
-       for (i = 0; i < num; i++) {
-               unsigned long lbr_idx = (tos - i) & mask;
-               u64 from, to, mis = 0, pred = 0, in_tx = 0, abort = 0;
-               int skip = 0;
-               u16 cycles = 0;
-               int lbr_flags = lbr_desc[lbr_format];
-
-               rdmsrl(x86_pmu.lbr_from + lbr_idx, from);
-               rdmsrl(x86_pmu.lbr_to   + lbr_idx, to);
-
-               if (lbr_format == LBR_FORMAT_INFO && need_info) {
-                       u64 info;
-
-                       rdmsrl(MSR_LBR_INFO_0 + lbr_idx, info);
-                       mis = !!(info & LBR_INFO_MISPRED);
-                       pred = !mis;
-                       in_tx = !!(info & LBR_INFO_IN_TX);
-                       abort = !!(info & LBR_INFO_ABORT);
-                       cycles = (info & LBR_INFO_CYCLES);
-               }
-               if (lbr_flags & LBR_EIP_FLAGS) {
-                       mis = !!(from & LBR_FROM_FLAG_MISPRED);
-                       pred = !mis;
-                       skip = 1;
-               }
-               if (lbr_flags & LBR_TSX) {
-                       in_tx = !!(from & LBR_FROM_FLAG_IN_TX);
-                       abort = !!(from & LBR_FROM_FLAG_ABORT);
-                       skip = 3;
-               }
-               from = (u64)((((s64)from) << skip) >> skip);
-
-               /*
-                * Some CPUs report duplicated abort records,
-                * with the second entry not having an abort bit set.
-                * Skip them here. This loop runs backwards,
-                * so we need to undo the previous record.
-                * If the abort just happened outside the window
-                * the extra entry cannot be removed.
-                */
-               if (abort && x86_pmu.lbr_double_abort && out > 0)
-                       out--;
-
-               cpuc->lbr_entries[out].from      = from;
-               cpuc->lbr_entries[out].to        = to;
-               cpuc->lbr_entries[out].mispred   = mis;
-               cpuc->lbr_entries[out].predicted = pred;
-               cpuc->lbr_entries[out].in_tx     = in_tx;
-               cpuc->lbr_entries[out].abort     = abort;
-               cpuc->lbr_entries[out].cycles    = cycles;
-               cpuc->lbr_entries[out].reserved  = 0;
-               out++;
-       }
-       cpuc->lbr_stack.nr = out;
-}
-
-void intel_pmu_lbr_read(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       if (!cpuc->lbr_users)
-               return;
-
-       if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32)
-               intel_pmu_lbr_read_32(cpuc);
-       else
-               intel_pmu_lbr_read_64(cpuc);
-
-       intel_pmu_lbr_filter(cpuc);
-}
-
-/*
- * SW filter is used:
- * - in case there is no HW filter
- * - in case the HW filter has errata or limitations
- */
-static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
-{
-       u64 br_type = event->attr.branch_sample_type;
-       int mask = 0;
-
-       if (br_type & PERF_SAMPLE_BRANCH_USER)
-               mask |= X86_BR_USER;
-
-       if (br_type & PERF_SAMPLE_BRANCH_KERNEL)
-               mask |= X86_BR_KERNEL;
-
-       /* we ignore BRANCH_HV here */
-
-       if (br_type & PERF_SAMPLE_BRANCH_ANY)
-               mask |= X86_BR_ANY;
-
-       if (br_type & PERF_SAMPLE_BRANCH_ANY_CALL)
-               mask |= X86_BR_ANY_CALL;
-
-       if (br_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
-               mask |= X86_BR_RET | X86_BR_IRET | X86_BR_SYSRET;
-
-       if (br_type & PERF_SAMPLE_BRANCH_IND_CALL)
-               mask |= X86_BR_IND_CALL;
-
-       if (br_type & PERF_SAMPLE_BRANCH_ABORT_TX)
-               mask |= X86_BR_ABORT;
-
-       if (br_type & PERF_SAMPLE_BRANCH_IN_TX)
-               mask |= X86_BR_IN_TX;
-
-       if (br_type & PERF_SAMPLE_BRANCH_NO_TX)
-               mask |= X86_BR_NO_TX;
-
-       if (br_type & PERF_SAMPLE_BRANCH_COND)
-               mask |= X86_BR_JCC;
-
-       if (br_type & PERF_SAMPLE_BRANCH_CALL_STACK) {
-               if (!x86_pmu_has_lbr_callstack())
-                       return -EOPNOTSUPP;
-               if (mask & ~(X86_BR_USER | X86_BR_KERNEL))
-                       return -EINVAL;
-               mask |= X86_BR_CALL | X86_BR_IND_CALL | X86_BR_RET |
-                       X86_BR_CALL_STACK;
-       }
-
-       if (br_type & PERF_SAMPLE_BRANCH_IND_JUMP)
-               mask |= X86_BR_IND_JMP;
-
-       if (br_type & PERF_SAMPLE_BRANCH_CALL)
-               mask |= X86_BR_CALL | X86_BR_ZERO_CALL;
-       /*
-        * stash actual user request into reg, it may
-        * be used by fixup code for some CPU
-        */
-       event->hw.branch_reg.reg = mask;
-       return 0;
-}
-
-/*
- * setup the HW LBR filter
- * Used only when available, may not be enough to disambiguate
- * all branches, may need the help of the SW filter
- */
-static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg;
-       u64 br_type = event->attr.branch_sample_type;
-       u64 mask = 0, v;
-       int i;
-
-       for (i = 0; i < PERF_SAMPLE_BRANCH_MAX_SHIFT; i++) {
-               if (!(br_type & (1ULL << i)))
-                       continue;
-
-               v = x86_pmu.lbr_sel_map[i];
-               if (v == LBR_NOT_SUPP)
-                       return -EOPNOTSUPP;
-
-               if (v != LBR_IGN)
-                       mask |= v;
-       }
-
-       reg = &event->hw.branch_reg;
-       reg->idx = EXTRA_REG_LBR;
-
-       /*
-        * The first 9 bits (LBR_SEL_MASK) in LBR_SELECT operate
-        * in suppress mode. So LBR_SELECT should be set to
-        * (~mask & LBR_SEL_MASK) | (mask & ~LBR_SEL_MASK)
-        */
-       reg->config = mask ^ x86_pmu.lbr_sel_mask;
-
-       if ((br_type & PERF_SAMPLE_BRANCH_NO_CYCLES) &&
-           (br_type & PERF_SAMPLE_BRANCH_NO_FLAGS) &&
-           (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO))
-               reg->config |= LBR_NO_INFO;
-
-       return 0;
-}
-
-int intel_pmu_setup_lbr_filter(struct perf_event *event)
-{
-       int ret = 0;
-
-       /*
-        * no LBR on this PMU
-        */
-       if (!x86_pmu.lbr_nr)
-               return -EOPNOTSUPP;
-
-       /*
-        * setup SW LBR filter
-        */
-       ret = intel_pmu_setup_sw_lbr_filter(event);
-       if (ret)
-               return ret;
-
-       /*
-        * setup HW LBR filter, if any
-        */
-       if (x86_pmu.lbr_sel_map)
-               ret = intel_pmu_setup_hw_lbr_filter(event);
-
-       return ret;
-}
-
-/*
- * return the type of control flow change at address "from"
- * intruction is not necessarily a branch (in case of interrupt).
- *
- * The branch type returned also includes the priv level of the
- * target of the control flow change (X86_BR_USER, X86_BR_KERNEL).
- *
- * If a branch type is unknown OR the instruction cannot be
- * decoded (e.g., text page not present), then X86_BR_NONE is
- * returned.
- */
-static int branch_type(unsigned long from, unsigned long to, int abort)
-{
-       struct insn insn;
-       void *addr;
-       int bytes_read, bytes_left;
-       int ret = X86_BR_NONE;
-       int ext, to_plm, from_plm;
-       u8 buf[MAX_INSN_SIZE];
-       int is64 = 0;
-
-       to_plm = kernel_ip(to) ? X86_BR_KERNEL : X86_BR_USER;
-       from_plm = kernel_ip(from) ? X86_BR_KERNEL : X86_BR_USER;
-
-       /*
-        * maybe zero if lbr did not fill up after a reset by the time
-        * we get a PMU interrupt
-        */
-       if (from == 0 || to == 0)
-               return X86_BR_NONE;
-
-       if (abort)
-               return X86_BR_ABORT | to_plm;
-
-       if (from_plm == X86_BR_USER) {
-               /*
-                * can happen if measuring at the user level only
-                * and we interrupt in a kernel thread, e.g., idle.
-                */
-               if (!current->mm)
-                       return X86_BR_NONE;
-
-               /* may fail if text not present */
-               bytes_left = copy_from_user_nmi(buf, (void __user *)from,
-                                               MAX_INSN_SIZE);
-               bytes_read = MAX_INSN_SIZE - bytes_left;
-               if (!bytes_read)
-                       return X86_BR_NONE;
-
-               addr = buf;
-       } else {
-               /*
-                * The LBR logs any address in the IP, even if the IP just
-                * faulted. This means userspace can control the from address.
-                * Ensure we don't blindy read any address by validating it is
-                * a known text address.
-                */
-               if (kernel_text_address(from)) {
-                       addr = (void *)from;
-                       /*
-                        * Assume we can get the maximum possible size
-                        * when grabbing kernel data.  This is not
-                        * _strictly_ true since we could possibly be
-                        * executing up next to a memory hole, but
-                        * it is very unlikely to be a problem.
-                        */
-                       bytes_read = MAX_INSN_SIZE;
-               } else {
-                       return X86_BR_NONE;
-               }
-       }
-
-       /*
-        * decoder needs to know the ABI especially
-        * on 64-bit systems running 32-bit apps
-        */
-#ifdef CONFIG_X86_64
-       is64 = kernel_ip((unsigned long)addr) || !test_thread_flag(TIF_IA32);
-#endif
-       insn_init(&insn, addr, bytes_read, is64);
-       insn_get_opcode(&insn);
-       if (!insn.opcode.got)
-               return X86_BR_ABORT;
-
-       switch (insn.opcode.bytes[0]) {
-       case 0xf:
-               switch (insn.opcode.bytes[1]) {
-               case 0x05: /* syscall */
-               case 0x34: /* sysenter */
-                       ret = X86_BR_SYSCALL;
-                       break;
-               case 0x07: /* sysret */
-               case 0x35: /* sysexit */
-                       ret = X86_BR_SYSRET;
-                       break;
-               case 0x80 ... 0x8f: /* conditional */
-                       ret = X86_BR_JCC;
-                       break;
-               default:
-                       ret = X86_BR_NONE;
-               }
-               break;
-       case 0x70 ... 0x7f: /* conditional */
-               ret = X86_BR_JCC;
-               break;
-       case 0xc2: /* near ret */
-       case 0xc3: /* near ret */
-       case 0xca: /* far ret */
-       case 0xcb: /* far ret */
-               ret = X86_BR_RET;
-               break;
-       case 0xcf: /* iret */
-               ret = X86_BR_IRET;
-               break;
-       case 0xcc ... 0xce: /* int */
-               ret = X86_BR_INT;
-               break;
-       case 0xe8: /* call near rel */
-               insn_get_immediate(&insn);
-               if (insn.immediate1.value == 0) {
-                       /* zero length call */
-                       ret = X86_BR_ZERO_CALL;
-                       break;
-               }
-       case 0x9a: /* call far absolute */
-               ret = X86_BR_CALL;
-               break;
-       case 0xe0 ... 0xe3: /* loop jmp */
-               ret = X86_BR_JCC;
-               break;
-       case 0xe9 ... 0xeb: /* jmp */
-               ret = X86_BR_JMP;
-               break;
-       case 0xff: /* call near absolute, call far absolute ind */
-               insn_get_modrm(&insn);
-               ext = (insn.modrm.bytes[0] >> 3) & 0x7;
-               switch (ext) {
-               case 2: /* near ind call */
-               case 3: /* far ind call */
-                       ret = X86_BR_IND_CALL;
-                       break;
-               case 4:
-               case 5:
-                       ret = X86_BR_IND_JMP;
-                       break;
-               }
-               break;
-       default:
-               ret = X86_BR_NONE;
-       }
-       /*
-        * interrupts, traps, faults (and thus ring transition) may
-        * occur on any instructions. Thus, to classify them correctly,
-        * we need to first look at the from and to priv levels. If they
-        * are different and to is in the kernel, then it indicates
-        * a ring transition. If the from instruction is not a ring
-        * transition instr (syscall, systenter, int), then it means
-        * it was a irq, trap or fault.
-        *
-        * we have no way of detecting kernel to kernel faults.
-        */
-       if (from_plm == X86_BR_USER && to_plm == X86_BR_KERNEL
-           && ret != X86_BR_SYSCALL && ret != X86_BR_INT)
-               ret = X86_BR_IRQ;
-
-       /*
-        * branch priv level determined by target as
-        * is done by HW when LBR_SELECT is implemented
-        */
-       if (ret != X86_BR_NONE)
-               ret |= to_plm;
-
-       return ret;
-}
-
-/*
- * implement actual branch filter based on user demand.
- * Hardware may not exactly satisfy that request, thus
- * we need to inspect opcodes. Mismatched branches are
- * discarded. Therefore, the number of branches returned
- * in PERF_SAMPLE_BRANCH_STACK sample may vary.
- */
-static void
-intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
-{
-       u64 from, to;
-       int br_sel = cpuc->br_sel;
-       int i, j, type;
-       bool compress = false;
-
-       /* if sampling all branches, then nothing to filter */
-       if ((br_sel & X86_BR_ALL) == X86_BR_ALL)
-               return;
-
-       for (i = 0; i < cpuc->lbr_stack.nr; i++) {
-
-               from = cpuc->lbr_entries[i].from;
-               to = cpuc->lbr_entries[i].to;
-
-               type = branch_type(from, to, cpuc->lbr_entries[i].abort);
-               if (type != X86_BR_NONE && (br_sel & X86_BR_ANYTX)) {
-                       if (cpuc->lbr_entries[i].in_tx)
-                               type |= X86_BR_IN_TX;
-                       else
-                               type |= X86_BR_NO_TX;
-               }
-
-               /* if type does not correspond, then discard */
-               if (type == X86_BR_NONE || (br_sel & type) != type) {
-                       cpuc->lbr_entries[i].from = 0;
-                       compress = true;
-               }
-       }
-
-       if (!compress)
-               return;
-
-       /* remove all entries with from=0 */
-       for (i = 0; i < cpuc->lbr_stack.nr; ) {
-               if (!cpuc->lbr_entries[i].from) {
-                       j = i;
-                       while (++j < cpuc->lbr_stack.nr)
-                               cpuc->lbr_entries[j-1] = cpuc->lbr_entries[j];
-                       cpuc->lbr_stack.nr--;
-                       if (!cpuc->lbr_entries[i].from)
-                               continue;
-               }
-               i++;
-       }
-}
-
-/*
- * Map interface branch filters onto LBR filters
- */
-static const int nhm_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
-       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
-       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
-       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
-       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
-       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_REL_JMP
-                                               | LBR_IND_JMP | LBR_FAR,
-       /*
-        * NHM/WSM erratum: must include REL_JMP+IND_JMP to get CALL branches
-        */
-       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT] =
-        LBR_REL_CALL | LBR_IND_CALL | LBR_REL_JMP | LBR_IND_JMP | LBR_FAR,
-       /*
-        * NHM/WSM erratum: must include IND_JMP to capture IND_CALL
-        */
-       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT] = LBR_IND_CALL | LBR_IND_JMP,
-       [PERF_SAMPLE_BRANCH_COND_SHIFT]     = LBR_JCC,
-       [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT] = LBR_IND_JMP,
-};
-
-static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
-       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
-       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
-       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
-       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
-       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_FAR,
-       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]     = LBR_REL_CALL | LBR_IND_CALL
-                                               | LBR_FAR,
-       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]     = LBR_IND_CALL,
-       [PERF_SAMPLE_BRANCH_COND_SHIFT]         = LBR_JCC,
-       [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT]     = LBR_IND_JMP,
-       [PERF_SAMPLE_BRANCH_CALL_SHIFT]         = LBR_REL_CALL,
-};
-
-static const int hsw_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX_SHIFT] = {
-       [PERF_SAMPLE_BRANCH_ANY_SHIFT]          = LBR_ANY,
-       [PERF_SAMPLE_BRANCH_USER_SHIFT]         = LBR_USER,
-       [PERF_SAMPLE_BRANCH_KERNEL_SHIFT]       = LBR_KERNEL,
-       [PERF_SAMPLE_BRANCH_HV_SHIFT]           = LBR_IGN,
-       [PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT]   = LBR_RETURN | LBR_FAR,
-       [PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT]     = LBR_REL_CALL | LBR_IND_CALL
-                                               | LBR_FAR,
-       [PERF_SAMPLE_BRANCH_IND_CALL_SHIFT]     = LBR_IND_CALL,
-       [PERF_SAMPLE_BRANCH_COND_SHIFT]         = LBR_JCC,
-       [PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT]   = LBR_REL_CALL | LBR_IND_CALL
-                                               | LBR_RETURN | LBR_CALL_STACK,
-       [PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT]     = LBR_IND_JMP,
-       [PERF_SAMPLE_BRANCH_CALL_SHIFT]         = LBR_REL_CALL,
-};
-
-/* core */
-void __init intel_pmu_lbr_init_core(void)
-{
-       x86_pmu.lbr_nr     = 4;
-       x86_pmu.lbr_tos    = MSR_LBR_TOS;
-       x86_pmu.lbr_from   = MSR_LBR_CORE_FROM;
-       x86_pmu.lbr_to     = MSR_LBR_CORE_TO;
-
-       /*
-        * SW branch filter usage:
-        * - compensate for lack of HW filter
-        */
-       pr_cont("4-deep LBR, ");
-}
-
-/* nehalem/westmere */
-void __init intel_pmu_lbr_init_nhm(void)
-{
-       x86_pmu.lbr_nr     = 16;
-       x86_pmu.lbr_tos    = MSR_LBR_TOS;
-       x86_pmu.lbr_from   = MSR_LBR_NHM_FROM;
-       x86_pmu.lbr_to     = MSR_LBR_NHM_TO;
-
-       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
-       x86_pmu.lbr_sel_map  = nhm_lbr_sel_map;
-
-       /*
-        * SW branch filter usage:
-        * - workaround LBR_SEL errata (see above)
-        * - support syscall, sysret capture.
-        *   That requires LBR_FAR but that means far
-        *   jmp need to be filtered out
-        */
-       pr_cont("16-deep LBR, ");
-}
-
-/* sandy bridge */
-void __init intel_pmu_lbr_init_snb(void)
-{
-       x86_pmu.lbr_nr   = 16;
-       x86_pmu.lbr_tos  = MSR_LBR_TOS;
-       x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
-       x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
-
-       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
-       x86_pmu.lbr_sel_map  = snb_lbr_sel_map;
-
-       /*
-        * SW branch filter usage:
-        * - support syscall, sysret capture.
-        *   That requires LBR_FAR but that means far
-        *   jmp need to be filtered out
-        */
-       pr_cont("16-deep LBR, ");
-}
-
-/* haswell */
-void intel_pmu_lbr_init_hsw(void)
-{
-       x86_pmu.lbr_nr   = 16;
-       x86_pmu.lbr_tos  = MSR_LBR_TOS;
-       x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
-       x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
-
-       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
-       x86_pmu.lbr_sel_map  = hsw_lbr_sel_map;
-
-       pr_cont("16-deep LBR, ");
-}
-
-/* skylake */
-__init void intel_pmu_lbr_init_skl(void)
-{
-       x86_pmu.lbr_nr   = 32;
-       x86_pmu.lbr_tos  = MSR_LBR_TOS;
-       x86_pmu.lbr_from = MSR_LBR_NHM_FROM;
-       x86_pmu.lbr_to   = MSR_LBR_NHM_TO;
-
-       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
-       x86_pmu.lbr_sel_map  = hsw_lbr_sel_map;
-
-       /*
-        * SW branch filter usage:
-        * - support syscall, sysret capture.
-        *   That requires LBR_FAR but that means far
-        *   jmp need to be filtered out
-        */
-       pr_cont("32-deep LBR, ");
-}
-
-/* atom */
-void __init intel_pmu_lbr_init_atom(void)
-{
-       /*
-        * only models starting at stepping 10 seems
-        * to have an operational LBR which can freeze
-        * on PMU interrupt
-        */
-       if (boot_cpu_data.x86_model == 28
-           && boot_cpu_data.x86_mask < 10) {
-               pr_cont("LBR disabled due to erratum");
-               return;
-       }
-
-       x86_pmu.lbr_nr     = 8;
-       x86_pmu.lbr_tos    = MSR_LBR_TOS;
-       x86_pmu.lbr_from   = MSR_LBR_CORE_FROM;
-       x86_pmu.lbr_to     = MSR_LBR_CORE_TO;
-
-       /*
-        * SW branch filter usage:
-        * - compensate for lack of HW filter
-        */
-       pr_cont("8-deep LBR, ");
-}
-
-/* Knights Landing */
-void intel_pmu_lbr_init_knl(void)
-{
-       x86_pmu.lbr_nr     = 8;
-       x86_pmu.lbr_tos    = MSR_LBR_TOS;
-       x86_pmu.lbr_from   = MSR_LBR_NHM_FROM;
-       x86_pmu.lbr_to     = MSR_LBR_NHM_TO;
-
-       x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
-       x86_pmu.lbr_sel_map  = snb_lbr_sel_map;
-
-       pr_cont("8-deep LBR, ");
-}
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
deleted file mode 100644 (file)
index c0bbd10..0000000
+++ /dev/null
@@ -1,1188 +0,0 @@
-/*
- * Intel(R) Processor Trace PMU driver for perf
- * Copyright (c) 2013-2014, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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.
- *
- * Intel PT is specified in the Intel Architecture Instruction Set Extensions
- * Programming Reference:
- * http://software.intel.com/en-us/intel-isa-extensions
- */
-
-#undef DEBUG
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-
-#include <asm/perf_event.h>
-#include <asm/insn.h>
-#include <asm/io.h>
-#include <asm/intel_pt.h>
-
-#include "perf_event.h"
-#include "intel_pt.h"
-
-static DEFINE_PER_CPU(struct pt, pt_ctx);
-
-static struct pt_pmu pt_pmu;
-
-enum cpuid_regs {
-       CR_EAX = 0,
-       CR_ECX,
-       CR_EDX,
-       CR_EBX
-};
-
-/*
- * Capabilities of Intel PT hardware, such as number of address bits or
- * supported output schemes, are cached and exported to userspace as "caps"
- * attribute group of pt pmu device
- * (/sys/bus/event_source/devices/intel_pt/caps/) so that userspace can store
- * relevant bits together with intel_pt traces.
- *
- * These are necessary for both trace decoding (payloads_lip, contains address
- * width encoded in IP-related packets), and event configuration (bitmasks with
- * permitted values for certain bit fields).
- */
-#define PT_CAP(_n, _l, _r, _m)                                         \
-       [PT_CAP_ ## _n] = { .name = __stringify(_n), .leaf = _l,        \
-                           .reg = _r, .mask = _m }
-
-static struct pt_cap_desc {
-       const char      *name;
-       u32             leaf;
-       u8              reg;
-       u32             mask;
-} pt_caps[] = {
-       PT_CAP(max_subleaf,             0, CR_EAX, 0xffffffff),
-       PT_CAP(cr3_filtering,           0, CR_EBX, BIT(0)),
-       PT_CAP(psb_cyc,                 0, CR_EBX, BIT(1)),
-       PT_CAP(mtc,                     0, CR_EBX, BIT(3)),
-       PT_CAP(topa_output,             0, CR_ECX, BIT(0)),
-       PT_CAP(topa_multiple_entries,   0, CR_ECX, BIT(1)),
-       PT_CAP(single_range_output,     0, CR_ECX, BIT(2)),
-       PT_CAP(payloads_lip,            0, CR_ECX, BIT(31)),
-       PT_CAP(mtc_periods,             1, CR_EAX, 0xffff0000),
-       PT_CAP(cycle_thresholds,        1, CR_EBX, 0xffff),
-       PT_CAP(psb_periods,             1, CR_EBX, 0xffff0000),
-};
-
-static u32 pt_cap_get(enum pt_capabilities cap)
-{
-       struct pt_cap_desc *cd = &pt_caps[cap];
-       u32 c = pt_pmu.caps[cd->leaf * PT_CPUID_REGS_NUM + cd->reg];
-       unsigned int shift = __ffs(cd->mask);
-
-       return (c & cd->mask) >> shift;
-}
-
-static ssize_t pt_cap_show(struct device *cdev,
-                          struct device_attribute *attr,
-                          char *buf)
-{
-       struct dev_ext_attribute *ea =
-               container_of(attr, struct dev_ext_attribute, attr);
-       enum pt_capabilities cap = (long)ea->var;
-
-       return snprintf(buf, PAGE_SIZE, "%x\n", pt_cap_get(cap));
-}
-
-static struct attribute_group pt_cap_group = {
-       .name   = "caps",
-};
-
-PMU_FORMAT_ATTR(cyc,           "config:1"      );
-PMU_FORMAT_ATTR(mtc,           "config:9"      );
-PMU_FORMAT_ATTR(tsc,           "config:10"     );
-PMU_FORMAT_ATTR(noretcomp,     "config:11"     );
-PMU_FORMAT_ATTR(mtc_period,    "config:14-17"  );
-PMU_FORMAT_ATTR(cyc_thresh,    "config:19-22"  );
-PMU_FORMAT_ATTR(psb_period,    "config:24-27"  );
-
-static struct attribute *pt_formats_attr[] = {
-       &format_attr_cyc.attr,
-       &format_attr_mtc.attr,
-       &format_attr_tsc.attr,
-       &format_attr_noretcomp.attr,
-       &format_attr_mtc_period.attr,
-       &format_attr_cyc_thresh.attr,
-       &format_attr_psb_period.attr,
-       NULL,
-};
-
-static struct attribute_group pt_format_group = {
-       .name   = "format",
-       .attrs  = pt_formats_attr,
-};
-
-static const struct attribute_group *pt_attr_groups[] = {
-       &pt_cap_group,
-       &pt_format_group,
-       NULL,
-};
-
-static int __init pt_pmu_hw_init(void)
-{
-       struct dev_ext_attribute *de_attrs;
-       struct attribute **attrs;
-       size_t size;
-       int ret;
-       long i;
-
-       attrs = NULL;
-
-       for (i = 0; i < PT_CPUID_LEAVES; i++) {
-               cpuid_count(20, i,
-                           &pt_pmu.caps[CR_EAX + i*PT_CPUID_REGS_NUM],
-                           &pt_pmu.caps[CR_EBX + i*PT_CPUID_REGS_NUM],
-                           &pt_pmu.caps[CR_ECX + i*PT_CPUID_REGS_NUM],
-                           &pt_pmu.caps[CR_EDX + i*PT_CPUID_REGS_NUM]);
-       }
-
-       ret = -ENOMEM;
-       size = sizeof(struct attribute *) * (ARRAY_SIZE(pt_caps)+1);
-       attrs = kzalloc(size, GFP_KERNEL);
-       if (!attrs)
-               goto fail;
-
-       size = sizeof(struct dev_ext_attribute) * (ARRAY_SIZE(pt_caps)+1);
-       de_attrs = kzalloc(size, GFP_KERNEL);
-       if (!de_attrs)
-               goto fail;
-
-       for (i = 0; i < ARRAY_SIZE(pt_caps); i++) {
-               struct dev_ext_attribute *de_attr = de_attrs + i;
-
-               de_attr->attr.attr.name = pt_caps[i].name;
-
-               sysfs_attr_init(&de_attr->attr.attr);
-
-               de_attr->attr.attr.mode         = S_IRUGO;
-               de_attr->attr.show              = pt_cap_show;
-               de_attr->var                    = (void *)i;
-
-               attrs[i] = &de_attr->attr.attr;
-       }
-
-       pt_cap_group.attrs = attrs;
-
-       return 0;
-
-fail:
-       kfree(attrs);
-
-       return ret;
-}
-
-#define RTIT_CTL_CYC_PSB (RTIT_CTL_CYCLEACC    | \
-                         RTIT_CTL_CYC_THRESH   | \
-                         RTIT_CTL_PSB_FREQ)
-
-#define RTIT_CTL_MTC   (RTIT_CTL_MTC_EN        | \
-                        RTIT_CTL_MTC_RANGE)
-
-#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN                | \
-                       RTIT_CTL_DISRETC        | \
-                       RTIT_CTL_CYC_PSB        | \
-                       RTIT_CTL_MTC)
-
-static bool pt_event_valid(struct perf_event *event)
-{
-       u64 config = event->attr.config;
-       u64 allowed, requested;
-
-       if ((config & PT_CONFIG_MASK) != config)
-               return false;
-
-       if (config & RTIT_CTL_CYC_PSB) {
-               if (!pt_cap_get(PT_CAP_psb_cyc))
-                       return false;
-
-               allowed = pt_cap_get(PT_CAP_psb_periods);
-               requested = (config & RTIT_CTL_PSB_FREQ) >>
-                       RTIT_CTL_PSB_FREQ_OFFSET;
-               if (requested && (!(allowed & BIT(requested))))
-                       return false;
-
-               allowed = pt_cap_get(PT_CAP_cycle_thresholds);
-               requested = (config & RTIT_CTL_CYC_THRESH) >>
-                       RTIT_CTL_CYC_THRESH_OFFSET;
-               if (requested && (!(allowed & BIT(requested))))
-                       return false;
-       }
-
-       if (config & RTIT_CTL_MTC) {
-               /*
-                * In the unlikely case that CPUID lists valid mtc periods,
-                * but not the mtc capability, drop out here.
-                *
-                * Spec says that setting mtc period bits while mtc bit in
-                * CPUID is 0 will #GP, so better safe than sorry.
-                */
-               if (!pt_cap_get(PT_CAP_mtc))
-                       return false;
-
-               allowed = pt_cap_get(PT_CAP_mtc_periods);
-               if (!allowed)
-                       return false;
-
-               requested = (config & RTIT_CTL_MTC_RANGE) >>
-                       RTIT_CTL_MTC_RANGE_OFFSET;
-
-               if (!(allowed & BIT(requested)))
-                       return false;
-       }
-
-       return true;
-}
-
-/*
- * PT configuration helpers
- * These all are cpu affine and operate on a local PT
- */
-
-static void pt_config(struct perf_event *event)
-{
-       u64 reg;
-
-       if (!event->hw.itrace_started) {
-               event->hw.itrace_started = 1;
-               wrmsrl(MSR_IA32_RTIT_STATUS, 0);
-       }
-
-       reg = RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN;
-
-       if (!event->attr.exclude_kernel)
-               reg |= RTIT_CTL_OS;
-       if (!event->attr.exclude_user)
-               reg |= RTIT_CTL_USR;
-
-       reg |= (event->attr.config & PT_CONFIG_MASK);
-
-       wrmsrl(MSR_IA32_RTIT_CTL, reg);
-}
-
-static void pt_config_start(bool start)
-{
-       u64 ctl;
-
-       rdmsrl(MSR_IA32_RTIT_CTL, ctl);
-       if (start)
-               ctl |= RTIT_CTL_TRACEEN;
-       else
-               ctl &= ~RTIT_CTL_TRACEEN;
-       wrmsrl(MSR_IA32_RTIT_CTL, ctl);
-
-       /*
-        * A wrmsr that disables trace generation serializes other PT
-        * registers and causes all data packets to be written to memory,
-        * but a fence is required for the data to become globally visible.
-        *
-        * The below WMB, separating data store and aux_head store matches
-        * the consumer's RMB that separates aux_head load and data load.
-        */
-       if (!start)
-               wmb();
-}
-
-static void pt_config_buffer(void *buf, unsigned int topa_idx,
-                            unsigned int output_off)
-{
-       u64 reg;
-
-       wrmsrl(MSR_IA32_RTIT_OUTPUT_BASE, virt_to_phys(buf));
-
-       reg = 0x7f | ((u64)topa_idx << 7) | ((u64)output_off << 32);
-
-       wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, reg);
-}
-
-/*
- * Keep ToPA table-related metadata on the same page as the actual table,
- * taking up a few words from the top
- */
-
-#define TENTS_PER_PAGE (((PAGE_SIZE - 40) / sizeof(struct topa_entry)) - 1)
-
-/**
- * struct topa - page-sized ToPA table with metadata at the top
- * @table:     actual ToPA table entries, as understood by PT hardware
- * @list:      linkage to struct pt_buffer's list of tables
- * @phys:      physical address of this page
- * @offset:    offset of the first entry in this table in the buffer
- * @size:      total size of all entries in this table
- * @last:      index of the last initialized entry in this table
- */
-struct topa {
-       struct topa_entry       table[TENTS_PER_PAGE];
-       struct list_head        list;
-       u64                     phys;
-       u64                     offset;
-       size_t                  size;
-       int                     last;
-};
-
-/* make -1 stand for the last table entry */
-#define TOPA_ENTRY(t, i) ((i) == -1 ? &(t)->table[(t)->last] : &(t)->table[(i)])
-
-/**
- * topa_alloc() - allocate page-sized ToPA table
- * @cpu:       CPU on which to allocate.
- * @gfp:       Allocation flags.
- *
- * Return:     On success, return the pointer to ToPA table page.
- */
-static struct topa *topa_alloc(int cpu, gfp_t gfp)
-{
-       int node = cpu_to_node(cpu);
-       struct topa *topa;
-       struct page *p;
-
-       p = alloc_pages_node(node, gfp | __GFP_ZERO, 0);
-       if (!p)
-               return NULL;
-
-       topa = page_address(p);
-       topa->last = 0;
-       topa->phys = page_to_phys(p);
-
-       /*
-        * In case of singe-entry ToPA, always put the self-referencing END
-        * link as the 2nd entry in the table
-        */
-       if (!pt_cap_get(PT_CAP_topa_multiple_entries)) {
-               TOPA_ENTRY(topa, 1)->base = topa->phys >> TOPA_SHIFT;
-               TOPA_ENTRY(topa, 1)->end = 1;
-       }
-
-       return topa;
-}
-
-/**
- * topa_free() - free a page-sized ToPA table
- * @topa:      Table to deallocate.
- */
-static void topa_free(struct topa *topa)
-{
-       free_page((unsigned long)topa);
-}
-
-/**
- * topa_insert_table() - insert a ToPA table into a buffer
- * @buf:        PT buffer that's being extended.
- * @topa:       New topa table to be inserted.
- *
- * If it's the first table in this buffer, set up buffer's pointers
- * accordingly; otherwise, add a END=1 link entry to @topa to the current
- * "last" table and adjust the last table pointer to @topa.
- */
-static void topa_insert_table(struct pt_buffer *buf, struct topa *topa)
-{
-       struct topa *last = buf->last;
-
-       list_add_tail(&topa->list, &buf->tables);
-
-       if (!buf->first) {
-               buf->first = buf->last = buf->cur = topa;
-               return;
-       }
-
-       topa->offset = last->offset + last->size;
-       buf->last = topa;
-
-       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
-               return;
-
-       BUG_ON(last->last != TENTS_PER_PAGE - 1);
-
-       TOPA_ENTRY(last, -1)->base = topa->phys >> TOPA_SHIFT;
-       TOPA_ENTRY(last, -1)->end = 1;
-}
-
-/**
- * topa_table_full() - check if a ToPA table is filled up
- * @topa:      ToPA table.
- */
-static bool topa_table_full(struct topa *topa)
-{
-       /* single-entry ToPA is a special case */
-       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
-               return !!topa->last;
-
-       return topa->last == TENTS_PER_PAGE - 1;
-}
-
-/**
- * topa_insert_pages() - create a list of ToPA tables
- * @buf:       PT buffer being initialized.
- * @gfp:       Allocation flags.
- *
- * This initializes a list of ToPA tables with entries from
- * the data_pages provided by rb_alloc_aux().
- *
- * Return:     0 on success or error code.
- */
-static int topa_insert_pages(struct pt_buffer *buf, gfp_t gfp)
-{
-       struct topa *topa = buf->last;
-       int order = 0;
-       struct page *p;
-
-       p = virt_to_page(buf->data_pages[buf->nr_pages]);
-       if (PagePrivate(p))
-               order = page_private(p);
-
-       if (topa_table_full(topa)) {
-               topa = topa_alloc(buf->cpu, gfp);
-               if (!topa)
-                       return -ENOMEM;
-
-               topa_insert_table(buf, topa);
-       }
-
-       TOPA_ENTRY(topa, -1)->base = page_to_phys(p) >> TOPA_SHIFT;
-       TOPA_ENTRY(topa, -1)->size = order;
-       if (!buf->snapshot && !pt_cap_get(PT_CAP_topa_multiple_entries)) {
-               TOPA_ENTRY(topa, -1)->intr = 1;
-               TOPA_ENTRY(topa, -1)->stop = 1;
-       }
-
-       topa->last++;
-       topa->size += sizes(order);
-
-       buf->nr_pages += 1ul << order;
-
-       return 0;
-}
-
-/**
- * pt_topa_dump() - print ToPA tables and their entries
- * @buf:       PT buffer.
- */
-static void pt_topa_dump(struct pt_buffer *buf)
-{
-       struct topa *topa;
-
-       list_for_each_entry(topa, &buf->tables, list) {
-               int i;
-
-               pr_debug("# table @%p (%016Lx), off %llx size %zx\n", topa->table,
-                        topa->phys, topa->offset, topa->size);
-               for (i = 0; i < TENTS_PER_PAGE; i++) {
-                       pr_debug("# entry @%p (%lx sz %u %c%c%c) raw=%16llx\n",
-                                &topa->table[i],
-                                (unsigned long)topa->table[i].base << TOPA_SHIFT,
-                                sizes(topa->table[i].size),
-                                topa->table[i].end ?  'E' : ' ',
-                                topa->table[i].intr ? 'I' : ' ',
-                                topa->table[i].stop ? 'S' : ' ',
-                                *(u64 *)&topa->table[i]);
-                       if ((pt_cap_get(PT_CAP_topa_multiple_entries) &&
-                            topa->table[i].stop) ||
-                           topa->table[i].end)
-                               break;
-               }
-       }
-}
-
-/**
- * pt_buffer_advance() - advance to the next output region
- * @buf:       PT buffer.
- *
- * Advance the current pointers in the buffer to the next ToPA entry.
- */
-static void pt_buffer_advance(struct pt_buffer *buf)
-{
-       buf->output_off = 0;
-       buf->cur_idx++;
-
-       if (buf->cur_idx == buf->cur->last) {
-               if (buf->cur == buf->last)
-                       buf->cur = buf->first;
-               else
-                       buf->cur = list_entry(buf->cur->list.next, struct topa,
-                                             list);
-               buf->cur_idx = 0;
-       }
-}
-
-/**
- * pt_update_head() - calculate current offsets and sizes
- * @pt:                Per-cpu pt context.
- *
- * Update buffer's current write pointer position and data size.
- */
-static void pt_update_head(struct pt *pt)
-{
-       struct pt_buffer *buf = perf_get_aux(&pt->handle);
-       u64 topa_idx, base, old;
-
-       /* offset of the first region in this table from the beginning of buf */
-       base = buf->cur->offset + buf->output_off;
-
-       /* offset of the current output region within this table */
-       for (topa_idx = 0; topa_idx < buf->cur_idx; topa_idx++)
-               base += sizes(buf->cur->table[topa_idx].size);
-
-       if (buf->snapshot) {
-               local_set(&buf->data_size, base);
-       } else {
-               old = (local64_xchg(&buf->head, base) &
-                      ((buf->nr_pages << PAGE_SHIFT) - 1));
-               if (base < old)
-                       base += buf->nr_pages << PAGE_SHIFT;
-
-               local_add(base - old, &buf->data_size);
-       }
-}
-
-/**
- * pt_buffer_region() - obtain current output region's address
- * @buf:       PT buffer.
- */
-static void *pt_buffer_region(struct pt_buffer *buf)
-{
-       return phys_to_virt(buf->cur->table[buf->cur_idx].base << TOPA_SHIFT);
-}
-
-/**
- * pt_buffer_region_size() - obtain current output region's size
- * @buf:       PT buffer.
- */
-static size_t pt_buffer_region_size(struct pt_buffer *buf)
-{
-       return sizes(buf->cur->table[buf->cur_idx].size);
-}
-
-/**
- * pt_handle_status() - take care of possible status conditions
- * @pt:                Per-cpu pt context.
- */
-static void pt_handle_status(struct pt *pt)
-{
-       struct pt_buffer *buf = perf_get_aux(&pt->handle);
-       int advance = 0;
-       u64 status;
-
-       rdmsrl(MSR_IA32_RTIT_STATUS, status);
-
-       if (status & RTIT_STATUS_ERROR) {
-               pr_err_ratelimited("ToPA ERROR encountered, trying to recover\n");
-               pt_topa_dump(buf);
-               status &= ~RTIT_STATUS_ERROR;
-       }
-
-       if (status & RTIT_STATUS_STOPPED) {
-               status &= ~RTIT_STATUS_STOPPED;
-
-               /*
-                * On systems that only do single-entry ToPA, hitting STOP
-                * means we are already losing data; need to let the decoder
-                * know.
-                */
-               if (!pt_cap_get(PT_CAP_topa_multiple_entries) ||
-                   buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
-                       local_inc(&buf->lost);
-                       advance++;
-               }
-       }
-
-       /*
-        * Also on single-entry ToPA implementations, interrupt will come
-        * before the output reaches its output region's boundary.
-        */
-       if (!pt_cap_get(PT_CAP_topa_multiple_entries) && !buf->snapshot &&
-           pt_buffer_region_size(buf) - buf->output_off <= TOPA_PMI_MARGIN) {
-               void *head = pt_buffer_region(buf);
-
-               /* everything within this margin needs to be zeroed out */
-               memset(head + buf->output_off, 0,
-                      pt_buffer_region_size(buf) -
-                      buf->output_off);
-               advance++;
-       }
-
-       if (advance)
-               pt_buffer_advance(buf);
-
-       wrmsrl(MSR_IA32_RTIT_STATUS, status);
-}
-
-/**
- * pt_read_offset() - translate registers into buffer pointers
- * @buf:       PT buffer.
- *
- * Set buffer's output pointers from MSR values.
- */
-static void pt_read_offset(struct pt_buffer *buf)
-{
-       u64 offset, base_topa;
-
-       rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, base_topa);
-       buf->cur = phys_to_virt(base_topa);
-
-       rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, offset);
-       /* offset within current output region */
-       buf->output_off = offset >> 32;
-       /* index of current output region within this table */
-       buf->cur_idx = (offset & 0xffffff80) >> 7;
-}
-
-/**
- * pt_topa_next_entry() - obtain index of the first page in the next ToPA entry
- * @buf:       PT buffer.
- * @pg:                Page offset in the buffer.
- *
- * When advancing to the next output region (ToPA entry), given a page offset
- * into the buffer, we need to find the offset of the first page in the next
- * region.
- */
-static unsigned int pt_topa_next_entry(struct pt_buffer *buf, unsigned int pg)
-{
-       struct topa_entry *te = buf->topa_index[pg];
-
-       /* one region */
-       if (buf->first == buf->last && buf->first->last == 1)
-               return pg;
-
-       do {
-               pg++;
-               pg &= buf->nr_pages - 1;
-       } while (buf->topa_index[pg] == te);
-
-       return pg;
-}
-
-/**
- * pt_buffer_reset_markers() - place interrupt and stop bits in the buffer
- * @buf:       PT buffer.
- * @handle:    Current output handle.
- *
- * Place INT and STOP marks to prevent overwriting old data that the consumer
- * hasn't yet collected and waking up the consumer after a certain fraction of
- * the buffer has filled up. Only needed and sensible for non-snapshot counters.
- *
- * This obviously relies on buf::head to figure out buffer markers, so it has
- * to be called after pt_buffer_reset_offsets() and before the hardware tracing
- * is enabled.
- */
-static int pt_buffer_reset_markers(struct pt_buffer *buf,
-                                  struct perf_output_handle *handle)
-
-{
-       unsigned long head = local64_read(&buf->head);
-       unsigned long idx, npages, wakeup;
-
-       /* can't stop in the middle of an output region */
-       if (buf->output_off + handle->size + 1 <
-           sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size))
-               return -EINVAL;
-
-
-       /* single entry ToPA is handled by marking all regions STOP=1 INT=1 */
-       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
-               return 0;
-
-       /* clear STOP and INT from current entry */
-       buf->topa_index[buf->stop_pos]->stop = 0;
-       buf->topa_index[buf->intr_pos]->intr = 0;
-
-       /* how many pages till the STOP marker */
-       npages = handle->size >> PAGE_SHIFT;
-
-       /* if it's on a page boundary, fill up one more page */
-       if (!offset_in_page(head + handle->size + 1))
-               npages++;
-
-       idx = (head >> PAGE_SHIFT) + npages;
-       idx &= buf->nr_pages - 1;
-       buf->stop_pos = idx;
-
-       wakeup = handle->wakeup >> PAGE_SHIFT;
-
-       /* in the worst case, wake up the consumer one page before hard stop */
-       idx = (head >> PAGE_SHIFT) + npages - 1;
-       if (idx > wakeup)
-               idx = wakeup;
-
-       idx &= buf->nr_pages - 1;
-       buf->intr_pos = idx;
-
-       buf->topa_index[buf->stop_pos]->stop = 1;
-       buf->topa_index[buf->intr_pos]->intr = 1;
-
-       return 0;
-}
-
-/**
- * pt_buffer_setup_topa_index() - build topa_index[] table of regions
- * @buf:       PT buffer.
- *
- * topa_index[] references output regions indexed by offset into the
- * buffer for purposes of quick reverse lookup.
- */
-static void pt_buffer_setup_topa_index(struct pt_buffer *buf)
-{
-       struct topa *cur = buf->first, *prev = buf->last;
-       struct topa_entry *te_cur = TOPA_ENTRY(cur, 0),
-               *te_prev = TOPA_ENTRY(prev, prev->last - 1);
-       int pg = 0, idx = 0;
-
-       while (pg < buf->nr_pages) {
-               int tidx;
-
-               /* pages within one topa entry */
-               for (tidx = 0; tidx < 1 << te_cur->size; tidx++, pg++)
-                       buf->topa_index[pg] = te_prev;
-
-               te_prev = te_cur;
-
-               if (idx == cur->last - 1) {
-                       /* advance to next topa table */
-                       idx = 0;
-                       cur = list_entry(cur->list.next, struct topa, list);
-               } else {
-                       idx++;
-               }
-               te_cur = TOPA_ENTRY(cur, idx);
-       }
-
-}
-
-/**
- * pt_buffer_reset_offsets() - adjust buffer's write pointers from aux_head
- * @buf:       PT buffer.
- * @head:      Write pointer (aux_head) from AUX buffer.
- *
- * Find the ToPA table and entry corresponding to given @head and set buffer's
- * "current" pointers accordingly. This is done after we have obtained the
- * current aux_head position from a successful call to perf_aux_output_begin()
- * to make sure the hardware is writing to the right place.
- *
- * This function modifies buf::{cur,cur_idx,output_off} that will be programmed
- * into PT msrs when the tracing is enabled and buf::head and buf::data_size,
- * which are used to determine INT and STOP markers' locations by a subsequent
- * call to pt_buffer_reset_markers().
- */
-static void pt_buffer_reset_offsets(struct pt_buffer *buf, unsigned long head)
-{
-       int pg;
-
-       if (buf->snapshot)
-               head &= (buf->nr_pages << PAGE_SHIFT) - 1;
-
-       pg = (head >> PAGE_SHIFT) & (buf->nr_pages - 1);
-       pg = pt_topa_next_entry(buf, pg);
-
-       buf->cur = (struct topa *)((unsigned long)buf->topa_index[pg] & PAGE_MASK);
-       buf->cur_idx = ((unsigned long)buf->topa_index[pg] -
-                       (unsigned long)buf->cur) / sizeof(struct topa_entry);
-       buf->output_off = head & (sizes(buf->cur->table[buf->cur_idx].size) - 1);
-
-       local64_set(&buf->head, head);
-       local_set(&buf->data_size, 0);
-}
-
-/**
- * pt_buffer_fini_topa() - deallocate ToPA structure of a buffer
- * @buf:       PT buffer.
- */
-static void pt_buffer_fini_topa(struct pt_buffer *buf)
-{
-       struct topa *topa, *iter;
-
-       list_for_each_entry_safe(topa, iter, &buf->tables, list) {
-               /*
-                * right now, this is in free_aux() path only, so
-                * no need to unlink this table from the list
-                */
-               topa_free(topa);
-       }
-}
-
-/**
- * pt_buffer_init_topa() - initialize ToPA table for pt buffer
- * @buf:       PT buffer.
- * @size:      Total size of all regions within this ToPA.
- * @gfp:       Allocation flags.
- */
-static int pt_buffer_init_topa(struct pt_buffer *buf, unsigned long nr_pages,
-                              gfp_t gfp)
-{
-       struct topa *topa;
-       int err;
-
-       topa = topa_alloc(buf->cpu, gfp);
-       if (!topa)
-               return -ENOMEM;
-
-       topa_insert_table(buf, topa);
-
-       while (buf->nr_pages < nr_pages) {
-               err = topa_insert_pages(buf, gfp);
-               if (err) {
-                       pt_buffer_fini_topa(buf);
-                       return -ENOMEM;
-               }
-       }
-
-       pt_buffer_setup_topa_index(buf);
-
-       /* link last table to the first one, unless we're double buffering */
-       if (pt_cap_get(PT_CAP_topa_multiple_entries)) {
-               TOPA_ENTRY(buf->last, -1)->base = buf->first->phys >> TOPA_SHIFT;
-               TOPA_ENTRY(buf->last, -1)->end = 1;
-       }
-
-       pt_topa_dump(buf);
-       return 0;
-}
-
-/**
- * pt_buffer_setup_aux() - set up topa tables for a PT buffer
- * @cpu:       Cpu on which to allocate, -1 means current.
- * @pages:     Array of pointers to buffer pages passed from perf core.
- * @nr_pages:  Number of pages in the buffer.
- * @snapshot:  If this is a snapshot/overwrite counter.
- *
- * This is a pmu::setup_aux callback that sets up ToPA tables and all the
- * bookkeeping for an AUX buffer.
- *
- * Return:     Our private PT buffer structure.
- */
-static void *
-pt_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool snapshot)
-{
-       struct pt_buffer *buf;
-       int node, ret;
-
-       if (!nr_pages)
-               return NULL;
-
-       if (cpu == -1)
-               cpu = raw_smp_processor_id();
-       node = cpu_to_node(cpu);
-
-       buf = kzalloc_node(offsetof(struct pt_buffer, topa_index[nr_pages]),
-                          GFP_KERNEL, node);
-       if (!buf)
-               return NULL;
-
-       buf->cpu = cpu;
-       buf->snapshot = snapshot;
-       buf->data_pages = pages;
-
-       INIT_LIST_HEAD(&buf->tables);
-
-       ret = pt_buffer_init_topa(buf, nr_pages, GFP_KERNEL);
-       if (ret) {
-               kfree(buf);
-               return NULL;
-       }
-
-       return buf;
-}
-
-/**
- * pt_buffer_free_aux() - perf AUX deallocation path callback
- * @data:      PT buffer.
- */
-static void pt_buffer_free_aux(void *data)
-{
-       struct pt_buffer *buf = data;
-
-       pt_buffer_fini_topa(buf);
-       kfree(buf);
-}
-
-/**
- * pt_buffer_is_full() - check if the buffer is full
- * @buf:       PT buffer.
- * @pt:                Per-cpu pt handle.
- *
- * If the user hasn't read data from the output region that aux_head
- * points to, the buffer is considered full: the user needs to read at
- * least this region and update aux_tail to point past it.
- */
-static bool pt_buffer_is_full(struct pt_buffer *buf, struct pt *pt)
-{
-       if (buf->snapshot)
-               return false;
-
-       if (local_read(&buf->data_size) >= pt->handle.size)
-               return true;
-
-       return false;
-}
-
-/**
- * intel_pt_interrupt() - PT PMI handler
- */
-void intel_pt_interrupt(void)
-{
-       struct pt *pt = this_cpu_ptr(&pt_ctx);
-       struct pt_buffer *buf;
-       struct perf_event *event = pt->handle.event;
-
-       /*
-        * There may be a dangling PT bit in the interrupt status register
-        * after PT has been disabled by pt_event_stop(). Make sure we don't
-        * do anything (particularly, re-enable) for this event here.
-        */
-       if (!ACCESS_ONCE(pt->handle_nmi))
-               return;
-
-       pt_config_start(false);
-
-       if (!event)
-               return;
-
-       buf = perf_get_aux(&pt->handle);
-       if (!buf)
-               return;
-
-       pt_read_offset(buf);
-
-       pt_handle_status(pt);
-
-       pt_update_head(pt);
-
-       perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0),
-                           local_xchg(&buf->lost, 0));
-
-       if (!event->hw.state) {
-               int ret;
-
-               buf = perf_aux_output_begin(&pt->handle, event);
-               if (!buf) {
-                       event->hw.state = PERF_HES_STOPPED;
-                       return;
-               }
-
-               pt_buffer_reset_offsets(buf, pt->handle.head);
-               /* snapshot counters don't use PMI, so it's safe */
-               ret = pt_buffer_reset_markers(buf, &pt->handle);
-               if (ret) {
-                       perf_aux_output_end(&pt->handle, 0, true);
-                       return;
-               }
-
-               pt_config_buffer(buf->cur->table, buf->cur_idx,
-                                buf->output_off);
-               pt_config(event);
-       }
-}
-
-/*
- * PMU callbacks
- */
-
-static void pt_event_start(struct perf_event *event, int mode)
-{
-       struct pt *pt = this_cpu_ptr(&pt_ctx);
-       struct pt_buffer *buf = perf_get_aux(&pt->handle);
-
-       if (!buf || pt_buffer_is_full(buf, pt)) {
-               event->hw.state = PERF_HES_STOPPED;
-               return;
-       }
-
-       ACCESS_ONCE(pt->handle_nmi) = 1;
-       event->hw.state = 0;
-
-       pt_config_buffer(buf->cur->table, buf->cur_idx,
-                        buf->output_off);
-       pt_config(event);
-}
-
-static void pt_event_stop(struct perf_event *event, int mode)
-{
-       struct pt *pt = this_cpu_ptr(&pt_ctx);
-
-       /*
-        * Protect against the PMI racing with disabling wrmsr,
-        * see comment in intel_pt_interrupt().
-        */
-       ACCESS_ONCE(pt->handle_nmi) = 0;
-       pt_config_start(false);
-
-       if (event->hw.state == PERF_HES_STOPPED)
-               return;
-
-       event->hw.state = PERF_HES_STOPPED;
-
-       if (mode & PERF_EF_UPDATE) {
-               struct pt_buffer *buf = perf_get_aux(&pt->handle);
-
-               if (!buf)
-                       return;
-
-               if (WARN_ON_ONCE(pt->handle.event != event))
-                       return;
-
-               pt_read_offset(buf);
-
-               pt_handle_status(pt);
-
-               pt_update_head(pt);
-       }
-}
-
-static void pt_event_del(struct perf_event *event, int mode)
-{
-       struct pt *pt = this_cpu_ptr(&pt_ctx);
-       struct pt_buffer *buf;
-
-       pt_event_stop(event, PERF_EF_UPDATE);
-
-       buf = perf_get_aux(&pt->handle);
-
-       if (buf) {
-               if (buf->snapshot)
-                       pt->handle.head =
-                               local_xchg(&buf->data_size,
-                                          buf->nr_pages << PAGE_SHIFT);
-               perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0),
-                                   local_xchg(&buf->lost, 0));
-       }
-}
-
-static int pt_event_add(struct perf_event *event, int mode)
-{
-       struct pt_buffer *buf;
-       struct pt *pt = this_cpu_ptr(&pt_ctx);
-       struct hw_perf_event *hwc = &event->hw;
-       int ret = -EBUSY;
-
-       if (pt->handle.event)
-               goto fail;
-
-       buf = perf_aux_output_begin(&pt->handle, event);
-       ret = -EINVAL;
-       if (!buf)
-               goto fail_stop;
-
-       pt_buffer_reset_offsets(buf, pt->handle.head);
-       if (!buf->snapshot) {
-               ret = pt_buffer_reset_markers(buf, &pt->handle);
-               if (ret)
-                       goto fail_end_stop;
-       }
-
-       if (mode & PERF_EF_START) {
-               pt_event_start(event, 0);
-               ret = -EBUSY;
-               if (hwc->state == PERF_HES_STOPPED)
-                       goto fail_end_stop;
-       } else {
-               hwc->state = PERF_HES_STOPPED;
-       }
-
-       return 0;
-
-fail_end_stop:
-       perf_aux_output_end(&pt->handle, 0, true);
-fail_stop:
-       hwc->state = PERF_HES_STOPPED;
-fail:
-       return ret;
-}
-
-static void pt_event_read(struct perf_event *event)
-{
-}
-
-static void pt_event_destroy(struct perf_event *event)
-{
-       x86_del_exclusive(x86_lbr_exclusive_pt);
-}
-
-static int pt_event_init(struct perf_event *event)
-{
-       if (event->attr.type != pt_pmu.pmu.type)
-               return -ENOENT;
-
-       if (!pt_event_valid(event))
-               return -EINVAL;
-
-       if (x86_add_exclusive(x86_lbr_exclusive_pt))
-               return -EBUSY;
-
-       event->destroy = pt_event_destroy;
-
-       return 0;
-}
-
-void cpu_emergency_stop_pt(void)
-{
-       struct pt *pt = this_cpu_ptr(&pt_ctx);
-
-       if (pt->handle.event)
-               pt_event_stop(pt->handle.event, PERF_EF_UPDATE);
-}
-
-static __init int pt_init(void)
-{
-       int ret, cpu, prior_warn = 0;
-
-       BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE);
-
-       if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_INTEL_PT))
-               return -ENODEV;
-
-       get_online_cpus();
-       for_each_online_cpu(cpu) {
-               u64 ctl;
-
-               ret = rdmsrl_safe_on_cpu(cpu, MSR_IA32_RTIT_CTL, &ctl);
-               if (!ret && (ctl & RTIT_CTL_TRACEEN))
-                       prior_warn++;
-       }
-       put_online_cpus();
-
-       if (prior_warn) {
-               x86_add_exclusive(x86_lbr_exclusive_pt);
-               pr_warn("PT is enabled at boot time, doing nothing\n");
-
-               return -EBUSY;
-       }
-
-       ret = pt_pmu_hw_init();
-       if (ret)
-               return ret;
-
-       if (!pt_cap_get(PT_CAP_topa_output)) {
-               pr_warn("ToPA output is not supported on this CPU\n");
-               return -ENODEV;
-       }
-
-       if (!pt_cap_get(PT_CAP_topa_multiple_entries))
-               pt_pmu.pmu.capabilities =
-                       PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF;
-
-       pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE;
-       pt_pmu.pmu.attr_groups  = pt_attr_groups;
-       pt_pmu.pmu.task_ctx_nr  = perf_sw_context;
-       pt_pmu.pmu.event_init   = pt_event_init;
-       pt_pmu.pmu.add          = pt_event_add;
-       pt_pmu.pmu.del          = pt_event_del;
-       pt_pmu.pmu.start        = pt_event_start;
-       pt_pmu.pmu.stop         = pt_event_stop;
-       pt_pmu.pmu.read         = pt_event_read;
-       pt_pmu.pmu.setup_aux    = pt_buffer_setup_aux;
-       pt_pmu.pmu.free_aux     = pt_buffer_free_aux;
-       ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1);
-
-       return ret;
-}
-arch_initcall(pt_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c
deleted file mode 100644 (file)
index 24a351a..0000000
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * perf_event_intel_rapl.c: support Intel RAPL energy consumption counters
- * Copyright (C) 2013 Google, Inc., Stephane Eranian
- *
- * Intel RAPL interface is specified in the IA-32 Manual Vol3b
- * section 14.7.1 (September 2013)
- *
- * RAPL provides more controls than just reporting energy consumption
- * however here we only expose the 3 energy consumption free running
- * counters (pp0, pkg, dram).
- *
- * Each of those counters increments in a power unit defined by the
- * RAPL_POWER_UNIT MSR. On SandyBridge, this unit is 1/(2^16) Joules
- * but it can vary.
- *
- * Counter to rapl events mappings:
- *
- *  pp0 counter: consumption of all physical cores (power plane 0)
- *       event: rapl_energy_cores
- *    perf code: 0x1
- *
- *  pkg counter: consumption of the whole processor package
- *       event: rapl_energy_pkg
- *    perf code: 0x2
- *
- * dram counter: consumption of the dram domain (servers only)
- *       event: rapl_energy_dram
- *    perf code: 0x3
- *
- * dram counter: consumption of the builtin-gpu domain (client only)
- *       event: rapl_energy_gpu
- *    perf code: 0x4
- *
- * We manage those counters as free running (read-only). They may be
- * use simultaneously by other tools, such as turbostat.
- *
- * The events only support system-wide mode counting. There is no
- * sampling support because it does not make sense and is not
- * supported by the RAPL hardware.
- *
- * Because we want to avoid floating-point operations in the kernel,
- * the events are all reported in fixed point arithmetic (32.32).
- * Tools must adjust the counts to convert them to Watts using
- * the duration of the measurement. Tools may use a function such as
- * ldexp(raw_count, -32);
- */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/perf_event.h>
-#include <asm/cpu_device_id.h>
-#include "perf_event.h"
-
-/*
- * RAPL energy status counters
- */
-#define RAPL_IDX_PP0_NRG_STAT  0       /* all cores */
-#define INTEL_RAPL_PP0         0x1     /* pseudo-encoding */
-#define RAPL_IDX_PKG_NRG_STAT  1       /* entire package */
-#define INTEL_RAPL_PKG         0x2     /* pseudo-encoding */
-#define RAPL_IDX_RAM_NRG_STAT  2       /* DRAM */
-#define INTEL_RAPL_RAM         0x3     /* pseudo-encoding */
-#define RAPL_IDX_PP1_NRG_STAT  3       /* gpu */
-#define INTEL_RAPL_PP1         0x4     /* pseudo-encoding */
-
-#define NR_RAPL_DOMAINS         0x4
-static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = {
-       "pp0-core",
-       "package",
-       "dram",
-       "pp1-gpu",
-};
-
-/* Clients have PP0, PKG */
-#define RAPL_IDX_CLN   (1<<RAPL_IDX_PP0_NRG_STAT|\
-                        1<<RAPL_IDX_PKG_NRG_STAT|\
-                        1<<RAPL_IDX_PP1_NRG_STAT)
-
-/* Servers have PP0, PKG, RAM */
-#define RAPL_IDX_SRV   (1<<RAPL_IDX_PP0_NRG_STAT|\
-                        1<<RAPL_IDX_PKG_NRG_STAT|\
-                        1<<RAPL_IDX_RAM_NRG_STAT)
-
-/* Servers have PP0, PKG, RAM, PP1 */
-#define RAPL_IDX_HSW   (1<<RAPL_IDX_PP0_NRG_STAT|\
-                        1<<RAPL_IDX_PKG_NRG_STAT|\
-                        1<<RAPL_IDX_RAM_NRG_STAT|\
-                        1<<RAPL_IDX_PP1_NRG_STAT)
-
-/* Knights Landing has PKG, RAM */
-#define RAPL_IDX_KNL   (1<<RAPL_IDX_PKG_NRG_STAT|\
-                        1<<RAPL_IDX_RAM_NRG_STAT)
-
-/*
- * event code: LSB 8 bits, passed in attr->config
- * any other bit is reserved
- */
-#define RAPL_EVENT_MASK        0xFFULL
-
-#define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format)          \
-static ssize_t __rapl_##_var##_show(struct kobject *kobj,      \
-                               struct kobj_attribute *attr,    \
-                               char *page)                     \
-{                                                              \
-       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);             \
-       return sprintf(page, _format "\n");                     \
-}                                                              \
-static struct kobj_attribute format_attr_##_var =              \
-       __ATTR(_name, 0444, __rapl_##_var##_show, NULL)
-
-#define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */
-
-#define RAPL_EVENT_ATTR_STR(_name, v, str)                                     \
-static struct perf_pmu_events_attr event_attr_##v = {                          \
-       .attr           = __ATTR(_name, 0444, perf_event_sysfs_show, NULL),     \
-       .id             = 0,                                                    \
-       .event_str      = str,                                                  \
-};
-
-struct rapl_pmu {
-       spinlock_t       lock;
-       int              n_active; /* number of active events */
-       struct list_head active_list;
-       struct pmu       *pmu; /* pointer to rapl_pmu_class */
-       ktime_t          timer_interval; /* in ktime_t unit */
-       struct hrtimer   hrtimer;
-};
-
-static int rapl_hw_unit[NR_RAPL_DOMAINS] __read_mostly;  /* 1/2^hw_unit Joule */
-static struct pmu rapl_pmu_class;
-static cpumask_t rapl_cpu_mask;
-static int rapl_cntr_mask;
-
-static DEFINE_PER_CPU(struct rapl_pmu *, rapl_pmu);
-static DEFINE_PER_CPU(struct rapl_pmu *, rapl_pmu_to_free);
-
-static struct x86_pmu_quirk *rapl_quirks;
-static inline u64 rapl_read_counter(struct perf_event *event)
-{
-       u64 raw;
-       rdmsrl(event->hw.event_base, raw);
-       return raw;
-}
-
-#define rapl_add_quirk(func_)                                          \
-do {                                                                   \
-       static struct x86_pmu_quirk __quirk __initdata = {              \
-               .func = func_,                                          \
-       };                                                              \
-       __quirk.next = rapl_quirks;                                     \
-       rapl_quirks = &__quirk;                                         \
-} while (0)
-
-static inline u64 rapl_scale(u64 v, int cfg)
-{
-       if (cfg > NR_RAPL_DOMAINS) {
-               pr_warn("invalid domain %d, failed to scale data\n", cfg);
-               return v;
-       }
-       /*
-        * scale delta to smallest unit (1/2^32)
-        * users must then scale back: count * 1/(1e9*2^32) to get Joules
-        * or use ldexp(count, -32).
-        * Watts = Joules/Time delta
-        */
-       return v << (32 - rapl_hw_unit[cfg - 1]);
-}
-
-static u64 rapl_event_update(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 prev_raw_count, new_raw_count;
-       s64 delta, sdelta;
-       int shift = RAPL_CNTR_WIDTH;
-
-again:
-       prev_raw_count = local64_read(&hwc->prev_count);
-       rdmsrl(event->hw.event_base, new_raw_count);
-
-       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-                           new_raw_count) != prev_raw_count) {
-               cpu_relax();
-               goto again;
-       }
-
-       /*
-        * Now we have the new raw value and have updated the prev
-        * timestamp already. We can now calculate the elapsed delta
-        * (event-)time and add that to the generic event.
-        *
-        * Careful, not all hw sign-extends above the physical width
-        * of the count.
-        */
-       delta = (new_raw_count << shift) - (prev_raw_count << shift);
-       delta >>= shift;
-
-       sdelta = rapl_scale(delta, event->hw.config);
-
-       local64_add(sdelta, &event->count);
-
-       return new_raw_count;
-}
-
-static void rapl_start_hrtimer(struct rapl_pmu *pmu)
-{
-       hrtimer_start(&pmu->hrtimer, pmu->timer_interval,
-                    HRTIMER_MODE_REL_PINNED);
-}
-
-static void rapl_stop_hrtimer(struct rapl_pmu *pmu)
-{
-       hrtimer_cancel(&pmu->hrtimer);
-}
-
-static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer)
-{
-       struct rapl_pmu *pmu = __this_cpu_read(rapl_pmu);
-       struct perf_event *event;
-       unsigned long flags;
-
-       if (!pmu->n_active)
-               return HRTIMER_NORESTART;
-
-       spin_lock_irqsave(&pmu->lock, flags);
-
-       list_for_each_entry(event, &pmu->active_list, active_entry) {
-               rapl_event_update(event);
-       }
-
-       spin_unlock_irqrestore(&pmu->lock, flags);
-
-       hrtimer_forward_now(hrtimer, pmu->timer_interval);
-
-       return HRTIMER_RESTART;
-}
-
-static void rapl_hrtimer_init(struct rapl_pmu *pmu)
-{
-       struct hrtimer *hr = &pmu->hrtimer;
-
-       hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       hr->function = rapl_hrtimer_handle;
-}
-
-static void __rapl_pmu_event_start(struct rapl_pmu *pmu,
-                                  struct perf_event *event)
-{
-       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
-               return;
-
-       event->hw.state = 0;
-
-       list_add_tail(&event->active_entry, &pmu->active_list);
-
-       local64_set(&event->hw.prev_count, rapl_read_counter(event));
-
-       pmu->n_active++;
-       if (pmu->n_active == 1)
-               rapl_start_hrtimer(pmu);
-}
-
-static void rapl_pmu_event_start(struct perf_event *event, int mode)
-{
-       struct rapl_pmu *pmu = __this_cpu_read(rapl_pmu);
-       unsigned long flags;
-
-       spin_lock_irqsave(&pmu->lock, flags);
-       __rapl_pmu_event_start(pmu, event);
-       spin_unlock_irqrestore(&pmu->lock, flags);
-}
-
-static void rapl_pmu_event_stop(struct perf_event *event, int mode)
-{
-       struct rapl_pmu *pmu = __this_cpu_read(rapl_pmu);
-       struct hw_perf_event *hwc = &event->hw;
-       unsigned long flags;
-
-       spin_lock_irqsave(&pmu->lock, flags);
-
-       /* mark event as deactivated and stopped */
-       if (!(hwc->state & PERF_HES_STOPPED)) {
-               WARN_ON_ONCE(pmu->n_active <= 0);
-               pmu->n_active--;
-               if (pmu->n_active == 0)
-                       rapl_stop_hrtimer(pmu);
-
-               list_del(&event->active_entry);
-
-               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
-               hwc->state |= PERF_HES_STOPPED;
-       }
-
-       /* check if update of sw counter is necessary */
-       if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
-               /*
-                * Drain the remaining delta count out of a event
-                * that we are disabling:
-                */
-               rapl_event_update(event);
-               hwc->state |= PERF_HES_UPTODATE;
-       }
-
-       spin_unlock_irqrestore(&pmu->lock, flags);
-}
-
-static int rapl_pmu_event_add(struct perf_event *event, int mode)
-{
-       struct rapl_pmu *pmu = __this_cpu_read(rapl_pmu);
-       struct hw_perf_event *hwc = &event->hw;
-       unsigned long flags;
-
-       spin_lock_irqsave(&pmu->lock, flags);
-
-       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
-
-       if (mode & PERF_EF_START)
-               __rapl_pmu_event_start(pmu, event);
-
-       spin_unlock_irqrestore(&pmu->lock, flags);
-
-       return 0;
-}
-
-static void rapl_pmu_event_del(struct perf_event *event, int flags)
-{
-       rapl_pmu_event_stop(event, PERF_EF_UPDATE);
-}
-
-static int rapl_pmu_event_init(struct perf_event *event)
-{
-       u64 cfg = event->attr.config & RAPL_EVENT_MASK;
-       int bit, msr, ret = 0;
-
-       /* only look at RAPL events */
-       if (event->attr.type != rapl_pmu_class.type)
-               return -ENOENT;
-
-       /* check only supported bits are set */
-       if (event->attr.config & ~RAPL_EVENT_MASK)
-               return -EINVAL;
-
-       /*
-        * check event is known (determines counter)
-        */
-       switch (cfg) {
-       case INTEL_RAPL_PP0:
-               bit = RAPL_IDX_PP0_NRG_STAT;
-               msr = MSR_PP0_ENERGY_STATUS;
-               break;
-       case INTEL_RAPL_PKG:
-               bit = RAPL_IDX_PKG_NRG_STAT;
-               msr = MSR_PKG_ENERGY_STATUS;
-               break;
-       case INTEL_RAPL_RAM:
-               bit = RAPL_IDX_RAM_NRG_STAT;
-               msr = MSR_DRAM_ENERGY_STATUS;
-               break;
-       case INTEL_RAPL_PP1:
-               bit = RAPL_IDX_PP1_NRG_STAT;
-               msr = MSR_PP1_ENERGY_STATUS;
-               break;
-       default:
-               return -EINVAL;
-       }
-       /* check event supported */
-       if (!(rapl_cntr_mask & (1 << bit)))
-               return -EINVAL;
-
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
-               return -EINVAL;
-
-       /* must be done before validate_group */
-       event->hw.event_base = msr;
-       event->hw.config = cfg;
-       event->hw.idx = bit;
-
-       return ret;
-}
-
-static void rapl_pmu_event_read(struct perf_event *event)
-{
-       rapl_event_update(event);
-}
-
-static ssize_t rapl_get_attr_cpumask(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       return cpumap_print_to_pagebuf(true, buf, &rapl_cpu_mask);
-}
-
-static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL);
-
-static struct attribute *rapl_pmu_attrs[] = {
-       &dev_attr_cpumask.attr,
-       NULL,
-};
-
-static struct attribute_group rapl_pmu_attr_group = {
-       .attrs = rapl_pmu_attrs,
-};
-
-RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
-RAPL_EVENT_ATTR_STR(energy-pkg  ,   rapl_pkg, "event=0x02");
-RAPL_EVENT_ATTR_STR(energy-ram  ,   rapl_ram, "event=0x03");
-RAPL_EVENT_ATTR_STR(energy-gpu  ,   rapl_gpu, "event=0x04");
-
-RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
-RAPL_EVENT_ATTR_STR(energy-pkg.unit  ,   rapl_pkg_unit, "Joules");
-RAPL_EVENT_ATTR_STR(energy-ram.unit  ,   rapl_ram_unit, "Joules");
-RAPL_EVENT_ATTR_STR(energy-gpu.unit  ,   rapl_gpu_unit, "Joules");
-
-/*
- * we compute in 0.23 nJ increments regardless of MSR
- */
-RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
-RAPL_EVENT_ATTR_STR(energy-pkg.scale,     rapl_pkg_scale, "2.3283064365386962890625e-10");
-RAPL_EVENT_ATTR_STR(energy-ram.scale,     rapl_ram_scale, "2.3283064365386962890625e-10");
-RAPL_EVENT_ATTR_STR(energy-gpu.scale,     rapl_gpu_scale, "2.3283064365386962890625e-10");
-
-static struct attribute *rapl_events_srv_attr[] = {
-       EVENT_PTR(rapl_cores),
-       EVENT_PTR(rapl_pkg),
-       EVENT_PTR(rapl_ram),
-
-       EVENT_PTR(rapl_cores_unit),
-       EVENT_PTR(rapl_pkg_unit),
-       EVENT_PTR(rapl_ram_unit),
-
-       EVENT_PTR(rapl_cores_scale),
-       EVENT_PTR(rapl_pkg_scale),
-       EVENT_PTR(rapl_ram_scale),
-       NULL,
-};
-
-static struct attribute *rapl_events_cln_attr[] = {
-       EVENT_PTR(rapl_cores),
-       EVENT_PTR(rapl_pkg),
-       EVENT_PTR(rapl_gpu),
-
-       EVENT_PTR(rapl_cores_unit),
-       EVENT_PTR(rapl_pkg_unit),
-       EVENT_PTR(rapl_gpu_unit),
-
-       EVENT_PTR(rapl_cores_scale),
-       EVENT_PTR(rapl_pkg_scale),
-       EVENT_PTR(rapl_gpu_scale),
-       NULL,
-};
-
-static struct attribute *rapl_events_hsw_attr[] = {
-       EVENT_PTR(rapl_cores),
-       EVENT_PTR(rapl_pkg),
-       EVENT_PTR(rapl_gpu),
-       EVENT_PTR(rapl_ram),
-
-       EVENT_PTR(rapl_cores_unit),
-       EVENT_PTR(rapl_pkg_unit),
-       EVENT_PTR(rapl_gpu_unit),
-       EVENT_PTR(rapl_ram_unit),
-
-       EVENT_PTR(rapl_cores_scale),
-       EVENT_PTR(rapl_pkg_scale),
-       EVENT_PTR(rapl_gpu_scale),
-       EVENT_PTR(rapl_ram_scale),
-       NULL,
-};
-
-static struct attribute *rapl_events_knl_attr[] = {
-       EVENT_PTR(rapl_pkg),
-       EVENT_PTR(rapl_ram),
-
-       EVENT_PTR(rapl_pkg_unit),
-       EVENT_PTR(rapl_ram_unit),
-
-       EVENT_PTR(rapl_pkg_scale),
-       EVENT_PTR(rapl_ram_scale),
-       NULL,
-};
-
-static struct attribute_group rapl_pmu_events_group = {
-       .name = "events",
-       .attrs = NULL, /* patched at runtime */
-};
-
-DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7");
-static struct attribute *rapl_formats_attr[] = {
-       &format_attr_event.attr,
-       NULL,
-};
-
-static struct attribute_group rapl_pmu_format_group = {
-       .name = "format",
-       .attrs = rapl_formats_attr,
-};
-
-const struct attribute_group *rapl_attr_groups[] = {
-       &rapl_pmu_attr_group,
-       &rapl_pmu_format_group,
-       &rapl_pmu_events_group,
-       NULL,
-};
-
-static struct pmu rapl_pmu_class = {
-       .attr_groups    = rapl_attr_groups,
-       .task_ctx_nr    = perf_invalid_context, /* system-wide only */
-       .event_init     = rapl_pmu_event_init,
-       .add            = rapl_pmu_event_add, /* must have */
-       .del            = rapl_pmu_event_del, /* must have */
-       .start          = rapl_pmu_event_start,
-       .stop           = rapl_pmu_event_stop,
-       .read           = rapl_pmu_event_read,
-};
-
-static void rapl_cpu_exit(int cpu)
-{
-       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
-       int i, phys_id = topology_physical_package_id(cpu);
-       int target = -1;
-
-       /* find a new cpu on same package */
-       for_each_online_cpu(i) {
-               if (i == cpu)
-                       continue;
-               if (phys_id == topology_physical_package_id(i)) {
-                       target = i;
-                       break;
-               }
-       }
-       /*
-        * clear cpu from cpumask
-        * if was set in cpumask and still some cpu on package,
-        * then move to new cpu
-        */
-       if (cpumask_test_and_clear_cpu(cpu, &rapl_cpu_mask) && target >= 0)
-               cpumask_set_cpu(target, &rapl_cpu_mask);
-
-       WARN_ON(cpumask_empty(&rapl_cpu_mask));
-       /*
-        * migrate events and context to new cpu
-        */
-       if (target >= 0)
-               perf_pmu_migrate_context(pmu->pmu, cpu, target);
-
-       /* cancel overflow polling timer for CPU */
-       rapl_stop_hrtimer(pmu);
-}
-
-static void rapl_cpu_init(int cpu)
-{
-       int i, phys_id = topology_physical_package_id(cpu);
-
-       /* check if phys_is is already covered */
-       for_each_cpu(i, &rapl_cpu_mask) {
-               if (phys_id == topology_physical_package_id(i))
-                       return;
-       }
-       /* was not found, so add it */
-       cpumask_set_cpu(cpu, &rapl_cpu_mask);
-}
-
-static __init void rapl_hsw_server_quirk(void)
-{
-       /*
-        * DRAM domain on HSW server has fixed energy unit which can be
-        * different than the unit from power unit MSR.
-        * "Intel Xeon Processor E5-1600 and E5-2600 v3 Product Families, V2
-        * of 2. Datasheet, September 2014, Reference Number: 330784-001 "
-        */
-       rapl_hw_unit[RAPL_IDX_RAM_NRG_STAT] = 16;
-}
-
-static int rapl_cpu_prepare(int cpu)
-{
-       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
-       int phys_id = topology_physical_package_id(cpu);
-       u64 ms;
-
-       if (pmu)
-               return 0;
-
-       if (phys_id < 0)
-               return -1;
-
-       pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
-       if (!pmu)
-               return -1;
-       spin_lock_init(&pmu->lock);
-
-       INIT_LIST_HEAD(&pmu->active_list);
-
-       pmu->pmu = &rapl_pmu_class;
-
-       /*
-        * use reference of 200W for scaling the timeout
-        * to avoid missing counter overflows.
-        * 200W = 200 Joules/sec
-        * divide interval by 2 to avoid lockstep (2 * 100)
-        * if hw unit is 32, then we use 2 ms 1/200/2
-        */
-       if (rapl_hw_unit[0] < 32)
-               ms = (1000 / (2 * 100)) * (1ULL << (32 - rapl_hw_unit[0] - 1));
-       else
-               ms = 2;
-
-       pmu->timer_interval = ms_to_ktime(ms);
-
-       rapl_hrtimer_init(pmu);
-
-       /* set RAPL pmu for this cpu for now */
-       per_cpu(rapl_pmu, cpu) = pmu;
-       per_cpu(rapl_pmu_to_free, cpu) = NULL;
-
-       return 0;
-}
-
-static void rapl_cpu_kfree(int cpu)
-{
-       struct rapl_pmu *pmu = per_cpu(rapl_pmu_to_free, cpu);
-
-       kfree(pmu);
-
-       per_cpu(rapl_pmu_to_free, cpu) = NULL;
-}
-
-static int rapl_cpu_dying(int cpu)
-{
-       struct rapl_pmu *pmu = per_cpu(rapl_pmu, cpu);
-
-       if (!pmu)
-               return 0;
-
-       per_cpu(rapl_pmu, cpu) = NULL;
-
-       per_cpu(rapl_pmu_to_free, cpu) = pmu;
-
-       return 0;
-}
-
-static int rapl_cpu_notifier(struct notifier_block *self,
-                            unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (long)hcpu;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_UP_PREPARE:
-               rapl_cpu_prepare(cpu);
-               break;
-       case CPU_STARTING:
-               rapl_cpu_init(cpu);
-               break;
-       case CPU_UP_CANCELED:
-       case CPU_DYING:
-               rapl_cpu_dying(cpu);
-               break;
-       case CPU_ONLINE:
-       case CPU_DEAD:
-               rapl_cpu_kfree(cpu);
-               break;
-       case CPU_DOWN_PREPARE:
-               rapl_cpu_exit(cpu);
-               break;
-       default:
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-static int rapl_check_hw_unit(void)
-{
-       u64 msr_rapl_power_unit_bits;
-       int i;
-
-       /* protect rdmsrl() to handle virtualization */
-       if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &msr_rapl_power_unit_bits))
-               return -1;
-       for (i = 0; i < NR_RAPL_DOMAINS; i++)
-               rapl_hw_unit[i] = (msr_rapl_power_unit_bits >> 8) & 0x1FULL;
-
-       return 0;
-}
-
-static const struct x86_cpu_id rapl_cpu_match[] = {
-       [0] = { .vendor = X86_VENDOR_INTEL, .family = 6 },
-       [1] = {},
-};
-
-static int __init rapl_pmu_init(void)
-{
-       struct rapl_pmu *pmu;
-       int cpu, ret;
-       struct x86_pmu_quirk *quirk;
-       int i;
-
-       /*
-        * check for Intel processor family 6
-        */
-       if (!x86_match_cpu(rapl_cpu_match))
-               return 0;
-
-       /* check supported CPU */
-       switch (boot_cpu_data.x86_model) {
-       case 42: /* Sandy Bridge */
-       case 58: /* Ivy Bridge */
-               rapl_cntr_mask = RAPL_IDX_CLN;
-               rapl_pmu_events_group.attrs = rapl_events_cln_attr;
-               break;
-       case 63: /* Haswell-Server */
-               rapl_add_quirk(rapl_hsw_server_quirk);
-               rapl_cntr_mask = RAPL_IDX_SRV;
-               rapl_pmu_events_group.attrs = rapl_events_srv_attr;
-               break;
-       case 60: /* Haswell */
-       case 69: /* Haswell-Celeron */
-       case 61: /* Broadwell */
-               rapl_cntr_mask = RAPL_IDX_HSW;
-               rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
-               break;
-       case 45: /* Sandy Bridge-EP */
-       case 62: /* IvyTown */
-               rapl_cntr_mask = RAPL_IDX_SRV;
-               rapl_pmu_events_group.attrs = rapl_events_srv_attr;
-               break;
-       case 87: /* Knights Landing */
-               rapl_add_quirk(rapl_hsw_server_quirk);
-               rapl_cntr_mask = RAPL_IDX_KNL;
-               rapl_pmu_events_group.attrs = rapl_events_knl_attr;
-
-       default:
-               /* unsupported */
-               return 0;
-       }
-       ret = rapl_check_hw_unit();
-       if (ret)
-               return ret;
-
-       /* run cpu model quirks */
-       for (quirk = rapl_quirks; quirk; quirk = quirk->next)
-               quirk->func();
-       cpu_notifier_register_begin();
-
-       for_each_online_cpu(cpu) {
-               ret = rapl_cpu_prepare(cpu);
-               if (ret)
-                       goto out;
-               rapl_cpu_init(cpu);
-       }
-
-       __perf_cpu_notifier(rapl_cpu_notifier);
-
-       ret = perf_pmu_register(&rapl_pmu_class, "power", -1);
-       if (WARN_ON(ret)) {
-               pr_info("RAPL PMU detected, registration failed (%d), RAPL PMU disabled\n", ret);
-               cpu_notifier_register_done();
-               return -1;
-       }
-
-       pmu = __this_cpu_read(rapl_pmu);
-
-       pr_info("RAPL PMU detected,"
-               " API unit is 2^-32 Joules,"
-               " %d fixed counters"
-               " %llu ms ovfl timer\n",
-               hweight32(rapl_cntr_mask),
-               ktime_to_ms(pmu->timer_interval));
-       for (i = 0; i < NR_RAPL_DOMAINS; i++) {
-               if (rapl_cntr_mask & (1 << i)) {
-                       pr_info("hw unit of domain %s 2^-%d Joules\n",
-                               rapl_domain_names[i], rapl_hw_unit[i]);
-               }
-       }
-out:
-       cpu_notifier_register_done();
-
-       return 0;
-}
-device_initcall(rapl_pmu_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
deleted file mode 100644 (file)
index 3bf41d4..0000000
+++ /dev/null
@@ -1,1401 +0,0 @@
-#include "perf_event_intel_uncore.h"
-
-static struct intel_uncore_type *empty_uncore[] = { NULL, };
-struct intel_uncore_type **uncore_msr_uncores = empty_uncore;
-struct intel_uncore_type **uncore_pci_uncores = empty_uncore;
-
-static bool pcidrv_registered;
-struct pci_driver *uncore_pci_driver;
-/* pci bus to socket mapping */
-DEFINE_RAW_SPINLOCK(pci2phy_map_lock);
-struct list_head pci2phy_map_head = LIST_HEAD_INIT(pci2phy_map_head);
-struct pci_dev *uncore_extra_pci_dev[UNCORE_SOCKET_MAX][UNCORE_EXTRA_PCI_DEV_MAX];
-
-static DEFINE_RAW_SPINLOCK(uncore_box_lock);
-/* mask of cpus that collect uncore events */
-static cpumask_t uncore_cpu_mask;
-
-/* constraint for the fixed counter */
-static struct event_constraint uncore_constraint_fixed =
-       EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL);
-struct event_constraint uncore_constraint_empty =
-       EVENT_CONSTRAINT(0, 0, 0);
-
-int uncore_pcibus_to_physid(struct pci_bus *bus)
-{
-       struct pci2phy_map *map;
-       int phys_id = -1;
-
-       raw_spin_lock(&pci2phy_map_lock);
-       list_for_each_entry(map, &pci2phy_map_head, list) {
-               if (map->segment == pci_domain_nr(bus)) {
-                       phys_id = map->pbus_to_physid[bus->number];
-                       break;
-               }
-       }
-       raw_spin_unlock(&pci2phy_map_lock);
-
-       return phys_id;
-}
-
-struct pci2phy_map *__find_pci2phy_map(int segment)
-{
-       struct pci2phy_map *map, *alloc = NULL;
-       int i;
-
-       lockdep_assert_held(&pci2phy_map_lock);
-
-lookup:
-       list_for_each_entry(map, &pci2phy_map_head, list) {
-               if (map->segment == segment)
-                       goto end;
-       }
-
-       if (!alloc) {
-               raw_spin_unlock(&pci2phy_map_lock);
-               alloc = kmalloc(sizeof(struct pci2phy_map), GFP_KERNEL);
-               raw_spin_lock(&pci2phy_map_lock);
-
-               if (!alloc)
-                       return NULL;
-
-               goto lookup;
-       }
-
-       map = alloc;
-       alloc = NULL;
-       map->segment = segment;
-       for (i = 0; i < 256; i++)
-               map->pbus_to_physid[i] = -1;
-       list_add_tail(&map->list, &pci2phy_map_head);
-
-end:
-       kfree(alloc);
-       return map;
-}
-
-ssize_t uncore_event_show(struct kobject *kobj,
-                         struct kobj_attribute *attr, char *buf)
-{
-       struct uncore_event_desc *event =
-               container_of(attr, struct uncore_event_desc, attr);
-       return sprintf(buf, "%s", event->config);
-}
-
-struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
-{
-       return container_of(event->pmu, struct intel_uncore_pmu, pmu);
-}
-
-struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
-{
-       struct intel_uncore_box *box;
-
-       box = *per_cpu_ptr(pmu->box, cpu);
-       if (box)
-               return box;
-
-       raw_spin_lock(&uncore_box_lock);
-       /* Recheck in lock to handle races. */
-       if (*per_cpu_ptr(pmu->box, cpu))
-               goto out;
-       list_for_each_entry(box, &pmu->box_list, list) {
-               if (box->phys_id == topology_physical_package_id(cpu)) {
-                       atomic_inc(&box->refcnt);
-                       *per_cpu_ptr(pmu->box, cpu) = box;
-                       break;
-               }
-       }
-out:
-       raw_spin_unlock(&uncore_box_lock);
-
-       return *per_cpu_ptr(pmu->box, cpu);
-}
-
-struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
-{
-       /*
-        * perf core schedules event on the basis of cpu, uncore events are
-        * collected by one of the cpus inside a physical package.
-        */
-       return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id());
-}
-
-u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
-{
-       u64 count;
-
-       rdmsrl(event->hw.event_base, count);
-
-       return count;
-}
-
-/*
- * generic get constraint function for shared match/mask registers.
- */
-struct event_constraint *
-uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct intel_uncore_extra_reg *er;
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
-       unsigned long flags;
-       bool ok = false;
-
-       /*
-        * reg->alloc can be set due to existing state, so for fake box we
-        * need to ignore this, otherwise we might fail to allocate proper
-        * fake state for this extra reg constraint.
-        */
-       if (reg1->idx == EXTRA_REG_NONE ||
-           (!uncore_box_is_fake(box) && reg1->alloc))
-               return NULL;
-
-       er = &box->shared_regs[reg1->idx];
-       raw_spin_lock_irqsave(&er->lock, flags);
-       if (!atomic_read(&er->ref) ||
-           (er->config1 == reg1->config && er->config2 == reg2->config)) {
-               atomic_inc(&er->ref);
-               er->config1 = reg1->config;
-               er->config2 = reg2->config;
-               ok = true;
-       }
-       raw_spin_unlock_irqrestore(&er->lock, flags);
-
-       if (ok) {
-               if (!uncore_box_is_fake(box))
-                       reg1->alloc = 1;
-               return NULL;
-       }
-
-       return &uncore_constraint_empty;
-}
-
-void uncore_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct intel_uncore_extra_reg *er;
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-
-       /*
-        * Only put constraint if extra reg was actually allocated. Also
-        * takes care of event which do not use an extra shared reg.
-        *
-        * Also, if this is a fake box we shouldn't touch any event state
-        * (reg->alloc) and we don't care about leaving inconsistent box
-        * state either since it will be thrown out.
-        */
-       if (uncore_box_is_fake(box) || !reg1->alloc)
-               return;
-
-       er = &box->shared_regs[reg1->idx];
-       atomic_dec(&er->ref);
-       reg1->alloc = 0;
-}
-
-u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx)
-{
-       struct intel_uncore_extra_reg *er;
-       unsigned long flags;
-       u64 config;
-
-       er = &box->shared_regs[idx];
-
-       raw_spin_lock_irqsave(&er->lock, flags);
-       config = er->config;
-       raw_spin_unlock_irqrestore(&er->lock, flags);
-
-       return config;
-}
-
-static void uncore_assign_hw_event(struct intel_uncore_box *box, struct perf_event *event, int idx)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       hwc->idx = idx;
-       hwc->last_tag = ++box->tags[idx];
-
-       if (hwc->idx == UNCORE_PMC_IDX_FIXED) {
-               hwc->event_base = uncore_fixed_ctr(box);
-               hwc->config_base = uncore_fixed_ctl(box);
-               return;
-       }
-
-       hwc->config_base = uncore_event_ctl(box, hwc->idx);
-       hwc->event_base  = uncore_perf_ctr(box, hwc->idx);
-}
-
-void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event)
-{
-       u64 prev_count, new_count, delta;
-       int shift;
-
-       if (event->hw.idx >= UNCORE_PMC_IDX_FIXED)
-               shift = 64 - uncore_fixed_ctr_bits(box);
-       else
-               shift = 64 - uncore_perf_ctr_bits(box);
-
-       /* the hrtimer might modify the previous event value */
-again:
-       prev_count = local64_read(&event->hw.prev_count);
-       new_count = uncore_read_counter(box, event);
-       if (local64_xchg(&event->hw.prev_count, new_count) != prev_count)
-               goto again;
-
-       delta = (new_count << shift) - (prev_count << shift);
-       delta >>= shift;
-
-       local64_add(delta, &event->count);
-}
-
-/*
- * The overflow interrupt is unavailable for SandyBridge-EP, is broken
- * for SandyBridge. So we use hrtimer to periodically poll the counter
- * to avoid overflow.
- */
-static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
-{
-       struct intel_uncore_box *box;
-       struct perf_event *event;
-       unsigned long flags;
-       int bit;
-
-       box = container_of(hrtimer, struct intel_uncore_box, hrtimer);
-       if (!box->n_active || box->cpu != smp_processor_id())
-               return HRTIMER_NORESTART;
-       /*
-        * disable local interrupt to prevent uncore_pmu_event_start/stop
-        * to interrupt the update process
-        */
-       local_irq_save(flags);
-
-       /*
-        * handle boxes with an active event list as opposed to active
-        * counters
-        */
-       list_for_each_entry(event, &box->active_list, active_entry) {
-               uncore_perf_event_update(box, event);
-       }
-
-       for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX)
-               uncore_perf_event_update(box, box->events[bit]);
-
-       local_irq_restore(flags);
-
-       hrtimer_forward_now(hrtimer, ns_to_ktime(box->hrtimer_duration));
-       return HRTIMER_RESTART;
-}
-
-void uncore_pmu_start_hrtimer(struct intel_uncore_box *box)
-{
-       hrtimer_start(&box->hrtimer, ns_to_ktime(box->hrtimer_duration),
-                     HRTIMER_MODE_REL_PINNED);
-}
-
-void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box)
-{
-       hrtimer_cancel(&box->hrtimer);
-}
-
-static void uncore_pmu_init_hrtimer(struct intel_uncore_box *box)
-{
-       hrtimer_init(&box->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       box->hrtimer.function = uncore_pmu_hrtimer;
-}
-
-static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type, int node)
-{
-       struct intel_uncore_box *box;
-       int i, size;
-
-       size = sizeof(*box) + type->num_shared_regs * sizeof(struct intel_uncore_extra_reg);
-
-       box = kzalloc_node(size, GFP_KERNEL, node);
-       if (!box)
-               return NULL;
-
-       for (i = 0; i < type->num_shared_regs; i++)
-               raw_spin_lock_init(&box->shared_regs[i].lock);
-
-       uncore_pmu_init_hrtimer(box);
-       atomic_set(&box->refcnt, 1);
-       box->cpu = -1;
-       box->phys_id = -1;
-
-       /* set default hrtimer timeout */
-       box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL;
-
-       INIT_LIST_HEAD(&box->active_list);
-
-       return box;
-}
-
-/*
- * Using uncore_pmu_event_init pmu event_init callback
- * as a detection point for uncore events.
- */
-static int uncore_pmu_event_init(struct perf_event *event);
-
-static bool is_uncore_event(struct perf_event *event)
-{
-       return event->pmu->event_init == uncore_pmu_event_init;
-}
-
-static int
-uncore_collect_events(struct intel_uncore_box *box, struct perf_event *leader, bool dogrp)
-{
-       struct perf_event *event;
-       int n, max_count;
-
-       max_count = box->pmu->type->num_counters;
-       if (box->pmu->type->fixed_ctl)
-               max_count++;
-
-       if (box->n_events >= max_count)
-               return -EINVAL;
-
-       n = box->n_events;
-
-       if (is_uncore_event(leader)) {
-               box->event_list[n] = leader;
-               n++;
-       }
-
-       if (!dogrp)
-               return n;
-
-       list_for_each_entry(event, &leader->sibling_list, group_entry) {
-               if (!is_uncore_event(event) ||
-                   event->state <= PERF_EVENT_STATE_OFF)
-                       continue;
-
-               if (n >= max_count)
-                       return -EINVAL;
-
-               box->event_list[n] = event;
-               n++;
-       }
-       return n;
-}
-
-static struct event_constraint *
-uncore_get_event_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct intel_uncore_type *type = box->pmu->type;
-       struct event_constraint *c;
-
-       if (type->ops->get_constraint) {
-               c = type->ops->get_constraint(box, event);
-               if (c)
-                       return c;
-       }
-
-       if (event->attr.config == UNCORE_FIXED_EVENT)
-               return &uncore_constraint_fixed;
-
-       if (type->constraints) {
-               for_each_event_constraint(c, type->constraints) {
-                       if ((event->hw.config & c->cmask) == c->code)
-                               return c;
-               }
-       }
-
-       return &type->unconstrainted;
-}
-
-static void uncore_put_event_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       if (box->pmu->type->ops->put_constraint)
-               box->pmu->type->ops->put_constraint(box, event);
-}
-
-static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int n)
-{
-       unsigned long used_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
-       struct event_constraint *c;
-       int i, wmin, wmax, ret = 0;
-       struct hw_perf_event *hwc;
-
-       bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX);
-
-       for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) {
-               c = uncore_get_event_constraint(box, box->event_list[i]);
-               box->event_constraint[i] = c;
-               wmin = min(wmin, c->weight);
-               wmax = max(wmax, c->weight);
-       }
-
-       /* fastpath, try to reuse previous register */
-       for (i = 0; i < n; i++) {
-               hwc = &box->event_list[i]->hw;
-               c = box->event_constraint[i];
-
-               /* never assigned */
-               if (hwc->idx == -1)
-                       break;
-
-               /* constraint still honored */
-               if (!test_bit(hwc->idx, c->idxmsk))
-                       break;
-
-               /* not already used */
-               if (test_bit(hwc->idx, used_mask))
-                       break;
-
-               __set_bit(hwc->idx, used_mask);
-               if (assign)
-                       assign[i] = hwc->idx;
-       }
-       /* slow path */
-       if (i != n)
-               ret = perf_assign_events(box->event_constraint, n,
-                                        wmin, wmax, n, assign);
-
-       if (!assign || ret) {
-               for (i = 0; i < n; i++)
-                       uncore_put_event_constraint(box, box->event_list[i]);
-       }
-       return ret ? -EINVAL : 0;
-}
-
-static void uncore_pmu_event_start(struct perf_event *event, int flags)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       int idx = event->hw.idx;
-
-       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
-               return;
-
-       if (WARN_ON_ONCE(idx == -1 || idx >= UNCORE_PMC_IDX_MAX))
-               return;
-
-       event->hw.state = 0;
-       box->events[idx] = event;
-       box->n_active++;
-       __set_bit(idx, box->active_mask);
-
-       local64_set(&event->hw.prev_count, uncore_read_counter(box, event));
-       uncore_enable_event(box, event);
-
-       if (box->n_active == 1) {
-               uncore_enable_box(box);
-               uncore_pmu_start_hrtimer(box);
-       }
-}
-
-static void uncore_pmu_event_stop(struct perf_event *event, int flags)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (__test_and_clear_bit(hwc->idx, box->active_mask)) {
-               uncore_disable_event(box, event);
-               box->n_active--;
-               box->events[hwc->idx] = NULL;
-               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
-               hwc->state |= PERF_HES_STOPPED;
-
-               if (box->n_active == 0) {
-                       uncore_disable_box(box);
-                       uncore_pmu_cancel_hrtimer(box);
-               }
-       }
-
-       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
-               /*
-                * Drain the remaining delta count out of a event
-                * that we are disabling:
-                */
-               uncore_perf_event_update(box, event);
-               hwc->state |= PERF_HES_UPTODATE;
-       }
-}
-
-static int uncore_pmu_event_add(struct perf_event *event, int flags)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       struct hw_perf_event *hwc = &event->hw;
-       int assign[UNCORE_PMC_IDX_MAX];
-       int i, n, ret;
-
-       if (!box)
-               return -ENODEV;
-
-       ret = n = uncore_collect_events(box, event, false);
-       if (ret < 0)
-               return ret;
-
-       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
-       if (!(flags & PERF_EF_START))
-               hwc->state |= PERF_HES_ARCH;
-
-       ret = uncore_assign_events(box, assign, n);
-       if (ret)
-               return ret;
-
-       /* save events moving to new counters */
-       for (i = 0; i < box->n_events; i++) {
-               event = box->event_list[i];
-               hwc = &event->hw;
-
-               if (hwc->idx == assign[i] &&
-                       hwc->last_tag == box->tags[assign[i]])
-                       continue;
-               /*
-                * Ensure we don't accidentally enable a stopped
-                * counter simply because we rescheduled.
-                */
-               if (hwc->state & PERF_HES_STOPPED)
-                       hwc->state |= PERF_HES_ARCH;
-
-               uncore_pmu_event_stop(event, PERF_EF_UPDATE);
-       }
-
-       /* reprogram moved events into new counters */
-       for (i = 0; i < n; i++) {
-               event = box->event_list[i];
-               hwc = &event->hw;
-
-               if (hwc->idx != assign[i] ||
-                       hwc->last_tag != box->tags[assign[i]])
-                       uncore_assign_hw_event(box, event, assign[i]);
-               else if (i < box->n_events)
-                       continue;
-
-               if (hwc->state & PERF_HES_ARCH)
-                       continue;
-
-               uncore_pmu_event_start(event, 0);
-       }
-       box->n_events = n;
-
-       return 0;
-}
-
-static void uncore_pmu_event_del(struct perf_event *event, int flags)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       int i;
-
-       uncore_pmu_event_stop(event, PERF_EF_UPDATE);
-
-       for (i = 0; i < box->n_events; i++) {
-               if (event == box->event_list[i]) {
-                       uncore_put_event_constraint(box, event);
-
-                       while (++i < box->n_events)
-                               box->event_list[i - 1] = box->event_list[i];
-
-                       --box->n_events;
-                       break;
-               }
-       }
-
-       event->hw.idx = -1;
-       event->hw.last_tag = ~0ULL;
-}
-
-void uncore_pmu_event_read(struct perf_event *event)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       uncore_perf_event_update(box, event);
-}
-
-/*
- * validation ensures the group can be loaded onto the
- * PMU if it was the only group available.
- */
-static int uncore_validate_group(struct intel_uncore_pmu *pmu,
-                               struct perf_event *event)
-{
-       struct perf_event *leader = event->group_leader;
-       struct intel_uncore_box *fake_box;
-       int ret = -EINVAL, n;
-
-       fake_box = uncore_alloc_box(pmu->type, NUMA_NO_NODE);
-       if (!fake_box)
-               return -ENOMEM;
-
-       fake_box->pmu = pmu;
-       /*
-        * the event is not yet connected with its
-        * siblings therefore we must first collect
-        * existing siblings, then add the new event
-        * before we can simulate the scheduling
-        */
-       n = uncore_collect_events(fake_box, leader, true);
-       if (n < 0)
-               goto out;
-
-       fake_box->n_events = n;
-       n = uncore_collect_events(fake_box, event, false);
-       if (n < 0)
-               goto out;
-
-       fake_box->n_events = n;
-
-       ret = uncore_assign_events(fake_box, NULL, n);
-out:
-       kfree(fake_box);
-       return ret;
-}
-
-static int uncore_pmu_event_init(struct perf_event *event)
-{
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       struct hw_perf_event *hwc = &event->hw;
-       int ret;
-
-       if (event->attr.type != event->pmu->type)
-               return -ENOENT;
-
-       pmu = uncore_event_to_pmu(event);
-       /* no device found for this pmu */
-       if (pmu->func_id < 0)
-               return -ENOENT;
-
-       /*
-        * Uncore PMU does measure at all privilege level all the time.
-        * So it doesn't make sense to specify any exclude bits.
-        */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-                       event->attr.exclude_hv || event->attr.exclude_idle)
-               return -EINVAL;
-
-       /* Sampling not supported yet */
-       if (hwc->sample_period)
-               return -EINVAL;
-
-       /*
-        * Place all uncore events for a particular physical package
-        * onto a single cpu
-        */
-       if (event->cpu < 0)
-               return -EINVAL;
-       box = uncore_pmu_to_box(pmu, event->cpu);
-       if (!box || box->cpu < 0)
-               return -EINVAL;
-       event->cpu = box->cpu;
-
-       event->hw.idx = -1;
-       event->hw.last_tag = ~0ULL;
-       event->hw.extra_reg.idx = EXTRA_REG_NONE;
-       event->hw.branch_reg.idx = EXTRA_REG_NONE;
-
-       if (event->attr.config == UNCORE_FIXED_EVENT) {
-               /* no fixed counter */
-               if (!pmu->type->fixed_ctl)
-                       return -EINVAL;
-               /*
-                * if there is only one fixed counter, only the first pmu
-                * can access the fixed counter
-                */
-               if (pmu->type->single_fixed && pmu->pmu_idx > 0)
-                       return -EINVAL;
-
-               /* fixed counters have event field hardcoded to zero */
-               hwc->config = 0ULL;
-       } else {
-               hwc->config = event->attr.config & pmu->type->event_mask;
-               if (pmu->type->ops->hw_config) {
-                       ret = pmu->type->ops->hw_config(box, event);
-                       if (ret)
-                               return ret;
-               }
-       }
-
-       if (event->group_leader != event)
-               ret = uncore_validate_group(pmu, event);
-       else
-               ret = 0;
-
-       return ret;
-}
-
-static ssize_t uncore_get_attr_cpumask(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       return cpumap_print_to_pagebuf(true, buf, &uncore_cpu_mask);
-}
-
-static DEVICE_ATTR(cpumask, S_IRUGO, uncore_get_attr_cpumask, NULL);
-
-static struct attribute *uncore_pmu_attrs[] = {
-       &dev_attr_cpumask.attr,
-       NULL,
-};
-
-static struct attribute_group uncore_pmu_attr_group = {
-       .attrs = uncore_pmu_attrs,
-};
-
-static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
-{
-       int ret;
-
-       if (!pmu->type->pmu) {
-               pmu->pmu = (struct pmu) {
-                       .attr_groups    = pmu->type->attr_groups,
-                       .task_ctx_nr    = perf_invalid_context,
-                       .event_init     = uncore_pmu_event_init,
-                       .add            = uncore_pmu_event_add,
-                       .del            = uncore_pmu_event_del,
-                       .start          = uncore_pmu_event_start,
-                       .stop           = uncore_pmu_event_stop,
-                       .read           = uncore_pmu_event_read,
-               };
-       } else {
-               pmu->pmu = *pmu->type->pmu;
-               pmu->pmu.attr_groups = pmu->type->attr_groups;
-       }
-
-       if (pmu->type->num_boxes == 1) {
-               if (strlen(pmu->type->name) > 0)
-                       sprintf(pmu->name, "uncore_%s", pmu->type->name);
-               else
-                       sprintf(pmu->name, "uncore");
-       } else {
-               sprintf(pmu->name, "uncore_%s_%d", pmu->type->name,
-                       pmu->pmu_idx);
-       }
-
-       ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
-       return ret;
-}
-
-static void __init uncore_type_exit(struct intel_uncore_type *type)
-{
-       int i;
-
-       for (i = 0; i < type->num_boxes; i++)
-               free_percpu(type->pmus[i].box);
-       kfree(type->pmus);
-       type->pmus = NULL;
-       kfree(type->events_group);
-       type->events_group = NULL;
-}
-
-static void __init uncore_types_exit(struct intel_uncore_type **types)
-{
-       int i;
-       for (i = 0; types[i]; i++)
-               uncore_type_exit(types[i]);
-}
-
-static int __init uncore_type_init(struct intel_uncore_type *type)
-{
-       struct intel_uncore_pmu *pmus;
-       struct attribute_group *attr_group;
-       struct attribute **attrs;
-       int i, j;
-
-       pmus = kzalloc(sizeof(*pmus) * type->num_boxes, GFP_KERNEL);
-       if (!pmus)
-               return -ENOMEM;
-
-       type->pmus = pmus;
-
-       type->unconstrainted = (struct event_constraint)
-               __EVENT_CONSTRAINT(0, (1ULL << type->num_counters) - 1,
-                               0, type->num_counters, 0, 0);
-
-       for (i = 0; i < type->num_boxes; i++) {
-               pmus[i].func_id = -1;
-               pmus[i].pmu_idx = i;
-               pmus[i].type = type;
-               INIT_LIST_HEAD(&pmus[i].box_list);
-               pmus[i].box = alloc_percpu(struct intel_uncore_box *);
-               if (!pmus[i].box)
-                       goto fail;
-       }
-
-       if (type->event_descs) {
-               i = 0;
-               while (type->event_descs[i].attr.attr.name)
-                       i++;
-
-               attr_group = kzalloc(sizeof(struct attribute *) * (i + 1) +
-                                       sizeof(*attr_group), GFP_KERNEL);
-               if (!attr_group)
-                       goto fail;
-
-               attrs = (struct attribute **)(attr_group + 1);
-               attr_group->name = "events";
-               attr_group->attrs = attrs;
-
-               for (j = 0; j < i; j++)
-                       attrs[j] = &type->event_descs[j].attr.attr;
-
-               type->events_group = attr_group;
-       }
-
-       type->pmu_group = &uncore_pmu_attr_group;
-       return 0;
-fail:
-       uncore_type_exit(type);
-       return -ENOMEM;
-}
-
-static int __init uncore_types_init(struct intel_uncore_type **types)
-{
-       int i, ret;
-
-       for (i = 0; types[i]; i++) {
-               ret = uncore_type_init(types[i]);
-               if (ret)
-                       goto fail;
-       }
-       return 0;
-fail:
-       while (--i >= 0)
-               uncore_type_exit(types[i]);
-       return ret;
-}
-
-/*
- * add a pci uncore device
- */
-static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       struct intel_uncore_type *type;
-       int phys_id;
-       bool first_box = false;
-
-       phys_id = uncore_pcibus_to_physid(pdev->bus);
-       if (phys_id < 0)
-               return -ENODEV;
-
-       if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) {
-               int idx = UNCORE_PCI_DEV_IDX(id->driver_data);
-               uncore_extra_pci_dev[phys_id][idx] = pdev;
-               pci_set_drvdata(pdev, NULL);
-               return 0;
-       }
-
-       type = uncore_pci_uncores[UNCORE_PCI_DEV_TYPE(id->driver_data)];
-       box = uncore_alloc_box(type, NUMA_NO_NODE);
-       if (!box)
-               return -ENOMEM;
-
-       /*
-        * for performance monitoring unit with multiple boxes,
-        * each box has a different function id.
-        */
-       pmu = &type->pmus[UNCORE_PCI_DEV_IDX(id->driver_data)];
-       /* Knights Landing uses a common PCI device ID for multiple instances of
-        * an uncore PMU device type. There is only one entry per device type in
-        * the knl_uncore_pci_ids table inspite of multiple devices present for
-        * some device types. Hence PCI device idx would be 0 for all devices.
-        * So increment pmu pointer to point to an unused array element.
-        */
-       if (boot_cpu_data.x86_model == 87)
-               while (pmu->func_id >= 0)
-                       pmu++;
-       if (pmu->func_id < 0)
-               pmu->func_id = pdev->devfn;
-       else
-               WARN_ON_ONCE(pmu->func_id != pdev->devfn);
-
-       box->phys_id = phys_id;
-       box->pci_dev = pdev;
-       box->pmu = pmu;
-       uncore_box_init(box);
-       pci_set_drvdata(pdev, box);
-
-       raw_spin_lock(&uncore_box_lock);
-       if (list_empty(&pmu->box_list))
-               first_box = true;
-       list_add_tail(&box->list, &pmu->box_list);
-       raw_spin_unlock(&uncore_box_lock);
-
-       if (first_box)
-               uncore_pmu_register(pmu);
-       return 0;
-}
-
-static void uncore_pci_remove(struct pci_dev *pdev)
-{
-       struct intel_uncore_box *box = pci_get_drvdata(pdev);
-       struct intel_uncore_pmu *pmu;
-       int i, cpu, phys_id;
-       bool last_box = false;
-
-       phys_id = uncore_pcibus_to_physid(pdev->bus);
-       box = pci_get_drvdata(pdev);
-       if (!box) {
-               for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) {
-                       if (uncore_extra_pci_dev[phys_id][i] == pdev) {
-                               uncore_extra_pci_dev[phys_id][i] = NULL;
-                               break;
-                       }
-               }
-               WARN_ON_ONCE(i >= UNCORE_EXTRA_PCI_DEV_MAX);
-               return;
-       }
-
-       pmu = box->pmu;
-       if (WARN_ON_ONCE(phys_id != box->phys_id))
-               return;
-
-       pci_set_drvdata(pdev, NULL);
-
-       raw_spin_lock(&uncore_box_lock);
-       list_del(&box->list);
-       if (list_empty(&pmu->box_list))
-               last_box = true;
-       raw_spin_unlock(&uncore_box_lock);
-
-       for_each_possible_cpu(cpu) {
-               if (*per_cpu_ptr(pmu->box, cpu) == box) {
-                       *per_cpu_ptr(pmu->box, cpu) = NULL;
-                       atomic_dec(&box->refcnt);
-               }
-       }
-
-       WARN_ON_ONCE(atomic_read(&box->refcnt) != 1);
-       kfree(box);
-
-       if (last_box)
-               perf_pmu_unregister(&pmu->pmu);
-}
-
-static int __init uncore_pci_init(void)
-{
-       int ret;
-
-       switch (boot_cpu_data.x86_model) {
-       case 45: /* Sandy Bridge-EP */
-               ret = snbep_uncore_pci_init();
-               break;
-       case 62: /* Ivy Bridge-EP */
-               ret = ivbep_uncore_pci_init();
-               break;
-       case 63: /* Haswell-EP */
-               ret = hswep_uncore_pci_init();
-               break;
-       case 79: /* BDX-EP */
-       case 86: /* BDX-DE */
-               ret = bdx_uncore_pci_init();
-               break;
-       case 42: /* Sandy Bridge */
-               ret = snb_uncore_pci_init();
-               break;
-       case 58: /* Ivy Bridge */
-               ret = ivb_uncore_pci_init();
-               break;
-       case 60: /* Haswell */
-       case 69: /* Haswell Celeron */
-               ret = hsw_uncore_pci_init();
-               break;
-       case 61: /* Broadwell */
-               ret = bdw_uncore_pci_init();
-               break;
-       case 87: /* Knights Landing */
-               ret = knl_uncore_pci_init();
-               break;
-       case 94: /* SkyLake */
-               ret = skl_uncore_pci_init();
-               break;
-       default:
-               return 0;
-       }
-
-       if (ret)
-               return ret;
-
-       ret = uncore_types_init(uncore_pci_uncores);
-       if (ret)
-               return ret;
-
-       uncore_pci_driver->probe = uncore_pci_probe;
-       uncore_pci_driver->remove = uncore_pci_remove;
-
-       ret = pci_register_driver(uncore_pci_driver);
-       if (ret == 0)
-               pcidrv_registered = true;
-       else
-               uncore_types_exit(uncore_pci_uncores);
-
-       return ret;
-}
-
-static void __init uncore_pci_exit(void)
-{
-       if (pcidrv_registered) {
-               pcidrv_registered = false;
-               pci_unregister_driver(uncore_pci_driver);
-               uncore_types_exit(uncore_pci_uncores);
-       }
-}
-
-/* CPU hot plug/unplug are serialized by cpu_add_remove_lock mutex */
-static LIST_HEAD(boxes_to_free);
-
-static void uncore_kfree_boxes(void)
-{
-       struct intel_uncore_box *box;
-
-       while (!list_empty(&boxes_to_free)) {
-               box = list_entry(boxes_to_free.next,
-                                struct intel_uncore_box, list);
-               list_del(&box->list);
-               kfree(box);
-       }
-}
-
-static void uncore_cpu_dying(int cpu)
-{
-       struct intel_uncore_type *type;
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       int i, j;
-
-       for (i = 0; uncore_msr_uncores[i]; i++) {
-               type = uncore_msr_uncores[i];
-               for (j = 0; j < type->num_boxes; j++) {
-                       pmu = &type->pmus[j];
-                       box = *per_cpu_ptr(pmu->box, cpu);
-                       *per_cpu_ptr(pmu->box, cpu) = NULL;
-                       if (box && atomic_dec_and_test(&box->refcnt))
-                               list_add(&box->list, &boxes_to_free);
-               }
-       }
-}
-
-static int uncore_cpu_starting(int cpu)
-{
-       struct intel_uncore_type *type;
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box, *exist;
-       int i, j, k, phys_id;
-
-       phys_id = topology_physical_package_id(cpu);
-
-       for (i = 0; uncore_msr_uncores[i]; i++) {
-               type = uncore_msr_uncores[i];
-               for (j = 0; j < type->num_boxes; j++) {
-                       pmu = &type->pmus[j];
-                       box = *per_cpu_ptr(pmu->box, cpu);
-                       /* called by uncore_cpu_init? */
-                       if (box && box->phys_id >= 0) {
-                               uncore_box_init(box);
-                               continue;
-                       }
-
-                       for_each_online_cpu(k) {
-                               exist = *per_cpu_ptr(pmu->box, k);
-                               if (exist && exist->phys_id == phys_id) {
-                                       atomic_inc(&exist->refcnt);
-                                       *per_cpu_ptr(pmu->box, cpu) = exist;
-                                       if (box) {
-                                               list_add(&box->list,
-                                                        &boxes_to_free);
-                                               box = NULL;
-                                       }
-                                       break;
-                               }
-                       }
-
-                       if (box) {
-                               box->phys_id = phys_id;
-                               uncore_box_init(box);
-                       }
-               }
-       }
-       return 0;
-}
-
-static int uncore_cpu_prepare(int cpu, int phys_id)
-{
-       struct intel_uncore_type *type;
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       int i, j;
-
-       for (i = 0; uncore_msr_uncores[i]; i++) {
-               type = uncore_msr_uncores[i];
-               for (j = 0; j < type->num_boxes; j++) {
-                       pmu = &type->pmus[j];
-                       if (pmu->func_id < 0)
-                               pmu->func_id = j;
-
-                       box = uncore_alloc_box(type, cpu_to_node(cpu));
-                       if (!box)
-                               return -ENOMEM;
-
-                       box->pmu = pmu;
-                       box->phys_id = phys_id;
-                       *per_cpu_ptr(pmu->box, cpu) = box;
-               }
-       }
-       return 0;
-}
-
-static void
-uncore_change_context(struct intel_uncore_type **uncores, int old_cpu, int new_cpu)
-{
-       struct intel_uncore_type *type;
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       int i, j;
-
-       for (i = 0; uncores[i]; i++) {
-               type = uncores[i];
-               for (j = 0; j < type->num_boxes; j++) {
-                       pmu = &type->pmus[j];
-                       if (old_cpu < 0)
-                               box = uncore_pmu_to_box(pmu, new_cpu);
-                       else
-                               box = uncore_pmu_to_box(pmu, old_cpu);
-                       if (!box)
-                               continue;
-
-                       if (old_cpu < 0) {
-                               WARN_ON_ONCE(box->cpu != -1);
-                               box->cpu = new_cpu;
-                               continue;
-                       }
-
-                       WARN_ON_ONCE(box->cpu != old_cpu);
-                       if (new_cpu >= 0) {
-                               uncore_pmu_cancel_hrtimer(box);
-                               perf_pmu_migrate_context(&pmu->pmu,
-                                               old_cpu, new_cpu);
-                               box->cpu = new_cpu;
-                       } else {
-                               box->cpu = -1;
-                       }
-               }
-       }
-}
-
-static void uncore_event_exit_cpu(int cpu)
-{
-       int i, phys_id, target;
-
-       /* if exiting cpu is used for collecting uncore events */
-       if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
-               return;
-
-       /* find a new cpu to collect uncore events */
-       phys_id = topology_physical_package_id(cpu);
-       target = -1;
-       for_each_online_cpu(i) {
-               if (i == cpu)
-                       continue;
-               if (phys_id == topology_physical_package_id(i)) {
-                       target = i;
-                       break;
-               }
-       }
-
-       /* migrate uncore events to the new cpu */
-       if (target >= 0)
-               cpumask_set_cpu(target, &uncore_cpu_mask);
-
-       uncore_change_context(uncore_msr_uncores, cpu, target);
-       uncore_change_context(uncore_pci_uncores, cpu, target);
-}
-
-static void uncore_event_init_cpu(int cpu)
-{
-       int i, phys_id;
-
-       phys_id = topology_physical_package_id(cpu);
-       for_each_cpu(i, &uncore_cpu_mask) {
-               if (phys_id == topology_physical_package_id(i))
-                       return;
-       }
-
-       cpumask_set_cpu(cpu, &uncore_cpu_mask);
-
-       uncore_change_context(uncore_msr_uncores, -1, cpu);
-       uncore_change_context(uncore_pci_uncores, -1, cpu);
-}
-
-static int uncore_cpu_notifier(struct notifier_block *self,
-                              unsigned long action, void *hcpu)
-{
-       unsigned int cpu = (long)hcpu;
-
-       /* allocate/free data structure for uncore box */
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_UP_PREPARE:
-               uncore_cpu_prepare(cpu, -1);
-               break;
-       case CPU_STARTING:
-               uncore_cpu_starting(cpu);
-               break;
-       case CPU_UP_CANCELED:
-       case CPU_DYING:
-               uncore_cpu_dying(cpu);
-               break;
-       case CPU_ONLINE:
-       case CPU_DEAD:
-               uncore_kfree_boxes();
-               break;
-       default:
-               break;
-       }
-
-       /* select the cpu that collects uncore events */
-       switch (action & ~CPU_TASKS_FROZEN) {
-       case CPU_DOWN_FAILED:
-       case CPU_STARTING:
-               uncore_event_init_cpu(cpu);
-               break;
-       case CPU_DOWN_PREPARE:
-               uncore_event_exit_cpu(cpu);
-               break;
-       default:
-               break;
-       }
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block uncore_cpu_nb = {
-       .notifier_call  = uncore_cpu_notifier,
-       /*
-        * to migrate uncore events, our notifier should be executed
-        * before perf core's notifier.
-        */
-       .priority       = CPU_PRI_PERF + 1,
-};
-
-static void __init uncore_cpu_setup(void *dummy)
-{
-       uncore_cpu_starting(smp_processor_id());
-}
-
-static int __init uncore_cpu_init(void)
-{
-       int ret;
-
-       switch (boot_cpu_data.x86_model) {
-       case 26: /* Nehalem */
-       case 30:
-       case 37: /* Westmere */
-       case 44:
-               nhm_uncore_cpu_init();
-               break;
-       case 42: /* Sandy Bridge */
-       case 58: /* Ivy Bridge */
-       case 60: /* Haswell */
-       case 69: /* Haswell */
-       case 70: /* Haswell */
-       case 61: /* Broadwell */
-       case 71: /* Broadwell */
-               snb_uncore_cpu_init();
-               break;
-       case 45: /* Sandy Bridge-EP */
-               snbep_uncore_cpu_init();
-               break;
-       case 46: /* Nehalem-EX */
-       case 47: /* Westmere-EX aka. Xeon E7 */
-               nhmex_uncore_cpu_init();
-               break;
-       case 62: /* Ivy Bridge-EP */
-               ivbep_uncore_cpu_init();
-               break;
-       case 63: /* Haswell-EP */
-               hswep_uncore_cpu_init();
-               break;
-       case 79: /* BDX-EP */
-       case 86: /* BDX-DE */
-               bdx_uncore_cpu_init();
-               break;
-       case 87: /* Knights Landing */
-               knl_uncore_cpu_init();
-               break;
-       default:
-               return 0;
-       }
-
-       ret = uncore_types_init(uncore_msr_uncores);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
-static int __init uncore_pmus_register(void)
-{
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_type *type;
-       int i, j;
-
-       for (i = 0; uncore_msr_uncores[i]; i++) {
-               type = uncore_msr_uncores[i];
-               for (j = 0; j < type->num_boxes; j++) {
-                       pmu = &type->pmus[j];
-                       uncore_pmu_register(pmu);
-               }
-       }
-
-       return 0;
-}
-
-static void __init uncore_cpumask_init(void)
-{
-       int cpu;
-
-       /*
-        * ony invoke once from msr or pci init code
-        */
-       if (!cpumask_empty(&uncore_cpu_mask))
-               return;
-
-       cpu_notifier_register_begin();
-
-       for_each_online_cpu(cpu) {
-               int i, phys_id = topology_physical_package_id(cpu);
-
-               for_each_cpu(i, &uncore_cpu_mask) {
-                       if (phys_id == topology_physical_package_id(i)) {
-                               phys_id = -1;
-                               break;
-                       }
-               }
-               if (phys_id < 0)
-                       continue;
-
-               uncore_cpu_prepare(cpu, phys_id);
-               uncore_event_init_cpu(cpu);
-       }
-       on_each_cpu(uncore_cpu_setup, NULL, 1);
-
-       __register_cpu_notifier(&uncore_cpu_nb);
-
-       cpu_notifier_register_done();
-}
-
-
-static int __init intel_uncore_init(void)
-{
-       int ret;
-
-       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
-               return -ENODEV;
-
-       if (cpu_has_hypervisor)
-               return -ENODEV;
-
-       ret = uncore_pci_init();
-       if (ret)
-               goto fail;
-       ret = uncore_cpu_init();
-       if (ret) {
-               uncore_pci_exit();
-               goto fail;
-       }
-       uncore_cpumask_init();
-
-       uncore_pmus_register();
-       return 0;
-fail:
-       return ret;
-}
-device_initcall(intel_uncore_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
deleted file mode 100644 (file)
index a7086b8..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/perf_event.h>
-#include "perf_event.h"
-
-#define UNCORE_PMU_NAME_LEN            32
-#define UNCORE_PMU_HRTIMER_INTERVAL    (60LL * NSEC_PER_SEC)
-#define UNCORE_SNB_IMC_HRTIMER_INTERVAL (5ULL * NSEC_PER_SEC)
-
-#define UNCORE_FIXED_EVENT             0xff
-#define UNCORE_PMC_IDX_MAX_GENERIC     8
-#define UNCORE_PMC_IDX_FIXED           UNCORE_PMC_IDX_MAX_GENERIC
-#define UNCORE_PMC_IDX_MAX             (UNCORE_PMC_IDX_FIXED + 1)
-
-#define UNCORE_PCI_DEV_DATA(type, idx) ((type << 8) | idx)
-#define UNCORE_PCI_DEV_TYPE(data)      ((data >> 8) & 0xff)
-#define UNCORE_PCI_DEV_IDX(data)       (data & 0xff)
-#define UNCORE_EXTRA_PCI_DEV           0xff
-#define UNCORE_EXTRA_PCI_DEV_MAX       3
-
-/* support up to 8 sockets */
-#define UNCORE_SOCKET_MAX              8
-
-#define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff)
-
-struct intel_uncore_ops;
-struct intel_uncore_pmu;
-struct intel_uncore_box;
-struct uncore_event_desc;
-
-struct intel_uncore_type {
-       const char *name;
-       int num_counters;
-       int num_boxes;
-       int perf_ctr_bits;
-       int fixed_ctr_bits;
-       unsigned perf_ctr;
-       unsigned event_ctl;
-       unsigned event_mask;
-       unsigned fixed_ctr;
-       unsigned fixed_ctl;
-       unsigned box_ctl;
-       unsigned msr_offset;
-       unsigned num_shared_regs:8;
-       unsigned single_fixed:1;
-       unsigned pair_ctr_ctl:1;
-       unsigned *msr_offsets;
-       struct event_constraint unconstrainted;
-       struct event_constraint *constraints;
-       struct intel_uncore_pmu *pmus;
-       struct intel_uncore_ops *ops;
-       struct uncore_event_desc *event_descs;
-       const struct attribute_group *attr_groups[4];
-       struct pmu *pmu; /* for custom pmu ops */
-};
-
-#define pmu_group attr_groups[0]
-#define format_group attr_groups[1]
-#define events_group attr_groups[2]
-
-struct intel_uncore_ops {
-       void (*init_box)(struct intel_uncore_box *);
-       void (*disable_box)(struct intel_uncore_box *);
-       void (*enable_box)(struct intel_uncore_box *);
-       void (*disable_event)(struct intel_uncore_box *, struct perf_event *);
-       void (*enable_event)(struct intel_uncore_box *, struct perf_event *);
-       u64 (*read_counter)(struct intel_uncore_box *, struct perf_event *);
-       int (*hw_config)(struct intel_uncore_box *, struct perf_event *);
-       struct event_constraint *(*get_constraint)(struct intel_uncore_box *,
-                                                  struct perf_event *);
-       void (*put_constraint)(struct intel_uncore_box *, struct perf_event *);
-};
-
-struct intel_uncore_pmu {
-       struct pmu pmu;
-       char name[UNCORE_PMU_NAME_LEN];
-       int pmu_idx;
-       int func_id;
-       struct intel_uncore_type *type;
-       struct intel_uncore_box ** __percpu box;
-       struct list_head box_list;
-};
-
-struct intel_uncore_extra_reg {
-       raw_spinlock_t lock;
-       u64 config, config1, config2;
-       atomic_t ref;
-};
-
-struct intel_uncore_box {
-       int phys_id;
-       int n_active;   /* number of active events */
-       int n_events;
-       int cpu;        /* cpu to collect events */
-       unsigned long flags;
-       atomic_t refcnt;
-       struct perf_event *events[UNCORE_PMC_IDX_MAX];
-       struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
-       struct event_constraint *event_constraint[UNCORE_PMC_IDX_MAX];
-       unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
-       u64 tags[UNCORE_PMC_IDX_MAX];
-       struct pci_dev *pci_dev;
-       struct intel_uncore_pmu *pmu;
-       u64 hrtimer_duration; /* hrtimer timeout for this box */
-       struct hrtimer hrtimer;
-       struct list_head list;
-       struct list_head active_list;
-       void *io_addr;
-       struct intel_uncore_extra_reg shared_regs[0];
-};
-
-#define UNCORE_BOX_FLAG_INITIATED      0
-
-struct uncore_event_desc {
-       struct kobj_attribute attr;
-       const char *config;
-};
-
-struct pci2phy_map {
-       struct list_head list;
-       int segment;
-       int pbus_to_physid[256];
-};
-
-int uncore_pcibus_to_physid(struct pci_bus *bus);
-struct pci2phy_map *__find_pci2phy_map(int segment);
-
-ssize_t uncore_event_show(struct kobject *kobj,
-                         struct kobj_attribute *attr, char *buf);
-
-#define INTEL_UNCORE_EVENT_DESC(_name, _config)                        \
-{                                                              \
-       .attr   = __ATTR(_name, 0444, uncore_event_show, NULL), \
-       .config = _config,                                      \
-}
-
-#define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format)                        \
-static ssize_t __uncore_##_var##_show(struct kobject *kobj,            \
-                               struct kobj_attribute *attr,            \
-                               char *page)                             \
-{                                                                      \
-       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);                     \
-       return sprintf(page, _format "\n");                             \
-}                                                                      \
-static struct kobj_attribute format_attr_##_var =                      \
-       __ATTR(_name, 0444, __uncore_##_var##_show, NULL)
-
-static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box)
-{
-       return box->pmu->type->box_ctl;
-}
-
-static inline unsigned uncore_pci_fixed_ctl(struct intel_uncore_box *box)
-{
-       return box->pmu->type->fixed_ctl;
-}
-
-static inline unsigned uncore_pci_fixed_ctr(struct intel_uncore_box *box)
-{
-       return box->pmu->type->fixed_ctr;
-}
-
-static inline
-unsigned uncore_pci_event_ctl(struct intel_uncore_box *box, int idx)
-{
-       return idx * 4 + box->pmu->type->event_ctl;
-}
-
-static inline
-unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx)
-{
-       return idx * 8 + box->pmu->type->perf_ctr;
-}
-
-static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box)
-{
-       struct intel_uncore_pmu *pmu = box->pmu;
-       return pmu->type->msr_offsets ?
-               pmu->type->msr_offsets[pmu->pmu_idx] :
-               pmu->type->msr_offset * pmu->pmu_idx;
-}
-
-static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)
-{
-       if (!box->pmu->type->box_ctl)
-               return 0;
-       return box->pmu->type->box_ctl + uncore_msr_box_offset(box);
-}
-
-static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box)
-{
-       if (!box->pmu->type->fixed_ctl)
-               return 0;
-       return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box);
-}
-
-static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box)
-{
-       return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box);
-}
-
-static inline
-unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)
-{
-       return box->pmu->type->event_ctl +
-               (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
-               uncore_msr_box_offset(box);
-}
-
-static inline
-unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
-{
-       return box->pmu->type->perf_ctr +
-               (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
-               uncore_msr_box_offset(box);
-}
-
-static inline
-unsigned uncore_fixed_ctl(struct intel_uncore_box *box)
-{
-       if (box->pci_dev)
-               return uncore_pci_fixed_ctl(box);
-       else
-               return uncore_msr_fixed_ctl(box);
-}
-
-static inline
-unsigned uncore_fixed_ctr(struct intel_uncore_box *box)
-{
-       if (box->pci_dev)
-               return uncore_pci_fixed_ctr(box);
-       else
-               return uncore_msr_fixed_ctr(box);
-}
-
-static inline
-unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx)
-{
-       if (box->pci_dev)
-               return uncore_pci_event_ctl(box, idx);
-       else
-               return uncore_msr_event_ctl(box, idx);
-}
-
-static inline
-unsigned uncore_perf_ctr(struct intel_uncore_box *box, int idx)
-{
-       if (box->pci_dev)
-               return uncore_pci_perf_ctr(box, idx);
-       else
-               return uncore_msr_perf_ctr(box, idx);
-}
-
-static inline int uncore_perf_ctr_bits(struct intel_uncore_box *box)
-{
-       return box->pmu->type->perf_ctr_bits;
-}
-
-static inline int uncore_fixed_ctr_bits(struct intel_uncore_box *box)
-{
-       return box->pmu->type->fixed_ctr_bits;
-}
-
-static inline int uncore_num_counters(struct intel_uncore_box *box)
-{
-       return box->pmu->type->num_counters;
-}
-
-static inline void uncore_disable_box(struct intel_uncore_box *box)
-{
-       if (box->pmu->type->ops->disable_box)
-               box->pmu->type->ops->disable_box(box);
-}
-
-static inline void uncore_enable_box(struct intel_uncore_box *box)
-{
-       if (box->pmu->type->ops->enable_box)
-               box->pmu->type->ops->enable_box(box);
-}
-
-static inline void uncore_disable_event(struct intel_uncore_box *box,
-                               struct perf_event *event)
-{
-       box->pmu->type->ops->disable_event(box, event);
-}
-
-static inline void uncore_enable_event(struct intel_uncore_box *box,
-                               struct perf_event *event)
-{
-       box->pmu->type->ops->enable_event(box, event);
-}
-
-static inline u64 uncore_read_counter(struct intel_uncore_box *box,
-                               struct perf_event *event)
-{
-       return box->pmu->type->ops->read_counter(box, event);
-}
-
-static inline void uncore_box_init(struct intel_uncore_box *box)
-{
-       if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) {
-               if (box->pmu->type->ops->init_box)
-                       box->pmu->type->ops->init_box(box);
-       }
-}
-
-static inline bool uncore_box_is_fake(struct intel_uncore_box *box)
-{
-       return (box->phys_id < 0);
-}
-
-struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event);
-struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu);
-struct intel_uncore_box *uncore_event_to_box(struct perf_event *event);
-u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event);
-void uncore_pmu_start_hrtimer(struct intel_uncore_box *box);
-void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box);
-void uncore_pmu_event_read(struct perf_event *event);
-void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event);
-struct event_constraint *
-uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event);
-void uncore_put_constraint(struct intel_uncore_box *box, struct perf_event *event);
-u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx);
-
-extern struct intel_uncore_type **uncore_msr_uncores;
-extern struct intel_uncore_type **uncore_pci_uncores;
-extern struct pci_driver *uncore_pci_driver;
-extern raw_spinlock_t pci2phy_map_lock;
-extern struct list_head pci2phy_map_head;
-extern struct pci_dev *uncore_extra_pci_dev[UNCORE_SOCKET_MAX][UNCORE_EXTRA_PCI_DEV_MAX];
-extern struct event_constraint uncore_constraint_empty;
-
-/* perf_event_intel_uncore_snb.c */
-int snb_uncore_pci_init(void);
-int ivb_uncore_pci_init(void);
-int hsw_uncore_pci_init(void);
-int bdw_uncore_pci_init(void);
-int skl_uncore_pci_init(void);
-void snb_uncore_cpu_init(void);
-void nhm_uncore_cpu_init(void);
-int snb_pci2phy_map_init(int devid);
-
-/* perf_event_intel_uncore_snbep.c */
-int snbep_uncore_pci_init(void);
-void snbep_uncore_cpu_init(void);
-int ivbep_uncore_pci_init(void);
-void ivbep_uncore_cpu_init(void);
-int hswep_uncore_pci_init(void);
-void hswep_uncore_cpu_init(void);
-int bdx_uncore_pci_init(void);
-void bdx_uncore_cpu_init(void);
-int knl_uncore_pci_init(void);
-void knl_uncore_cpu_init(void);
-
-/* perf_event_intel_uncore_nhmex.c */
-void nhmex_uncore_cpu_init(void);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c
deleted file mode 100644 (file)
index 2749965..0000000
+++ /dev/null
@@ -1,1221 +0,0 @@
-/* Nehalem-EX/Westmere-EX uncore support */
-#include "perf_event_intel_uncore.h"
-
-/* NHM-EX event control */
-#define NHMEX_PMON_CTL_EV_SEL_MASK     0x000000ff
-#define NHMEX_PMON_CTL_UMASK_MASK      0x0000ff00
-#define NHMEX_PMON_CTL_EN_BIT0         (1 << 0)
-#define NHMEX_PMON_CTL_EDGE_DET                (1 << 18)
-#define NHMEX_PMON_CTL_PMI_EN          (1 << 20)
-#define NHMEX_PMON_CTL_EN_BIT22                (1 << 22)
-#define NHMEX_PMON_CTL_INVERT          (1 << 23)
-#define NHMEX_PMON_CTL_TRESH_MASK      0xff000000
-#define NHMEX_PMON_RAW_EVENT_MASK      (NHMEX_PMON_CTL_EV_SEL_MASK | \
-                                        NHMEX_PMON_CTL_UMASK_MASK | \
-                                        NHMEX_PMON_CTL_EDGE_DET | \
-                                        NHMEX_PMON_CTL_INVERT | \
-                                        NHMEX_PMON_CTL_TRESH_MASK)
-
-/* NHM-EX Ubox */
-#define NHMEX_U_MSR_PMON_GLOBAL_CTL            0xc00
-#define NHMEX_U_MSR_PMON_CTR                   0xc11
-#define NHMEX_U_MSR_PMON_EV_SEL                        0xc10
-
-#define NHMEX_U_PMON_GLOBAL_EN                 (1 << 0)
-#define NHMEX_U_PMON_GLOBAL_PMI_CORE_SEL       0x0000001e
-#define NHMEX_U_PMON_GLOBAL_EN_ALL             (1 << 28)
-#define NHMEX_U_PMON_GLOBAL_RST_ALL            (1 << 29)
-#define NHMEX_U_PMON_GLOBAL_FRZ_ALL            (1 << 31)
-
-#define NHMEX_U_PMON_RAW_EVENT_MASK            \
-               (NHMEX_PMON_CTL_EV_SEL_MASK |   \
-                NHMEX_PMON_CTL_EDGE_DET)
-
-/* NHM-EX Cbox */
-#define NHMEX_C0_MSR_PMON_GLOBAL_CTL           0xd00
-#define NHMEX_C0_MSR_PMON_CTR0                 0xd11
-#define NHMEX_C0_MSR_PMON_EV_SEL0              0xd10
-#define NHMEX_C_MSR_OFFSET                     0x20
-
-/* NHM-EX Bbox */
-#define NHMEX_B0_MSR_PMON_GLOBAL_CTL           0xc20
-#define NHMEX_B0_MSR_PMON_CTR0                 0xc31
-#define NHMEX_B0_MSR_PMON_CTL0                 0xc30
-#define NHMEX_B_MSR_OFFSET                     0x40
-#define NHMEX_B0_MSR_MATCH                     0xe45
-#define NHMEX_B0_MSR_MASK                      0xe46
-#define NHMEX_B1_MSR_MATCH                     0xe4d
-#define NHMEX_B1_MSR_MASK                      0xe4e
-
-#define NHMEX_B_PMON_CTL_EN                    (1 << 0)
-#define NHMEX_B_PMON_CTL_EV_SEL_SHIFT          1
-#define NHMEX_B_PMON_CTL_EV_SEL_MASK           \
-               (0x1f << NHMEX_B_PMON_CTL_EV_SEL_SHIFT)
-#define NHMEX_B_PMON_CTR_SHIFT         6
-#define NHMEX_B_PMON_CTR_MASK          \
-               (0x3 << NHMEX_B_PMON_CTR_SHIFT)
-#define NHMEX_B_PMON_RAW_EVENT_MASK            \
-               (NHMEX_B_PMON_CTL_EV_SEL_MASK | \
-                NHMEX_B_PMON_CTR_MASK)
-
-/* NHM-EX Sbox */
-#define NHMEX_S0_MSR_PMON_GLOBAL_CTL           0xc40
-#define NHMEX_S0_MSR_PMON_CTR0                 0xc51
-#define NHMEX_S0_MSR_PMON_CTL0                 0xc50
-#define NHMEX_S_MSR_OFFSET                     0x80
-#define NHMEX_S0_MSR_MM_CFG                    0xe48
-#define NHMEX_S0_MSR_MATCH                     0xe49
-#define NHMEX_S0_MSR_MASK                      0xe4a
-#define NHMEX_S1_MSR_MM_CFG                    0xe58
-#define NHMEX_S1_MSR_MATCH                     0xe59
-#define NHMEX_S1_MSR_MASK                      0xe5a
-
-#define NHMEX_S_PMON_MM_CFG_EN                 (0x1ULL << 63)
-#define NHMEX_S_EVENT_TO_R_PROG_EV             0
-
-/* NHM-EX Mbox */
-#define NHMEX_M0_MSR_GLOBAL_CTL                        0xca0
-#define NHMEX_M0_MSR_PMU_DSP                   0xca5
-#define NHMEX_M0_MSR_PMU_ISS                   0xca6
-#define NHMEX_M0_MSR_PMU_MAP                   0xca7
-#define NHMEX_M0_MSR_PMU_MSC_THR               0xca8
-#define NHMEX_M0_MSR_PMU_PGT                   0xca9
-#define NHMEX_M0_MSR_PMU_PLD                   0xcaa
-#define NHMEX_M0_MSR_PMU_ZDP_CTL_FVC           0xcab
-#define NHMEX_M0_MSR_PMU_CTL0                  0xcb0
-#define NHMEX_M0_MSR_PMU_CNT0                  0xcb1
-#define NHMEX_M_MSR_OFFSET                     0x40
-#define NHMEX_M0_MSR_PMU_MM_CFG                        0xe54
-#define NHMEX_M1_MSR_PMU_MM_CFG                        0xe5c
-
-#define NHMEX_M_PMON_MM_CFG_EN                 (1ULL << 63)
-#define NHMEX_M_PMON_ADDR_MATCH_MASK           0x3ffffffffULL
-#define NHMEX_M_PMON_ADDR_MASK_MASK            0x7ffffffULL
-#define NHMEX_M_PMON_ADDR_MASK_SHIFT           34
-
-#define NHMEX_M_PMON_CTL_EN                    (1 << 0)
-#define NHMEX_M_PMON_CTL_PMI_EN                        (1 << 1)
-#define NHMEX_M_PMON_CTL_COUNT_MODE_SHIFT      2
-#define NHMEX_M_PMON_CTL_COUNT_MODE_MASK       \
-       (0x3 << NHMEX_M_PMON_CTL_COUNT_MODE_SHIFT)
-#define NHMEX_M_PMON_CTL_STORAGE_MODE_SHIFT    4
-#define NHMEX_M_PMON_CTL_STORAGE_MODE_MASK     \
-       (0x3 << NHMEX_M_PMON_CTL_STORAGE_MODE_SHIFT)
-#define NHMEX_M_PMON_CTL_WRAP_MODE             (1 << 6)
-#define NHMEX_M_PMON_CTL_FLAG_MODE             (1 << 7)
-#define NHMEX_M_PMON_CTL_INC_SEL_SHIFT         9
-#define NHMEX_M_PMON_CTL_INC_SEL_MASK          \
-       (0x1f << NHMEX_M_PMON_CTL_INC_SEL_SHIFT)
-#define NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT    19
-#define NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK     \
-       (0x7 << NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT)
-#define NHMEX_M_PMON_RAW_EVENT_MASK                    \
-               (NHMEX_M_PMON_CTL_COUNT_MODE_MASK |     \
-                NHMEX_M_PMON_CTL_STORAGE_MODE_MASK |   \
-                NHMEX_M_PMON_CTL_WRAP_MODE |           \
-                NHMEX_M_PMON_CTL_FLAG_MODE |           \
-                NHMEX_M_PMON_CTL_INC_SEL_MASK |        \
-                NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK)
-
-#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK          (((1 << 11) - 1) | (1 << 23))
-#define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7ULL << (11 + 3 * (n)))
-
-#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK          (((1 << 12) - 1) | (1 << 24))
-#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7ULL << (12 + 3 * (n)))
-
-/*
- * use the 9~13 bits to select event If the 7th bit is not set,
- * otherwise use the 19~21 bits to select event.
- */
-#define MBOX_INC_SEL(x) ((x) << NHMEX_M_PMON_CTL_INC_SEL_SHIFT)
-#define MBOX_SET_FLAG_SEL(x) (((x) << NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT) | \
-                               NHMEX_M_PMON_CTL_FLAG_MODE)
-#define MBOX_INC_SEL_MASK (NHMEX_M_PMON_CTL_INC_SEL_MASK | \
-                          NHMEX_M_PMON_CTL_FLAG_MODE)
-#define MBOX_SET_FLAG_SEL_MASK (NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK | \
-                               NHMEX_M_PMON_CTL_FLAG_MODE)
-#define MBOX_INC_SEL_EXTAR_REG(c, r) \
-               EVENT_EXTRA_REG(MBOX_INC_SEL(c), NHMEX_M0_MSR_PMU_##r, \
-                               MBOX_INC_SEL_MASK, (u64)-1, NHMEX_M_##r)
-#define MBOX_SET_FLAG_SEL_EXTRA_REG(c, r) \
-               EVENT_EXTRA_REG(MBOX_SET_FLAG_SEL(c), NHMEX_M0_MSR_PMU_##r, \
-                               MBOX_SET_FLAG_SEL_MASK, \
-                               (u64)-1, NHMEX_M_##r)
-
-/* NHM-EX Rbox */
-#define NHMEX_R_MSR_GLOBAL_CTL                 0xe00
-#define NHMEX_R_MSR_PMON_CTL0                  0xe10
-#define NHMEX_R_MSR_PMON_CNT0                  0xe11
-#define NHMEX_R_MSR_OFFSET                     0x20
-
-#define NHMEX_R_MSR_PORTN_QLX_CFG(n)           \
-               ((n) < 4 ? (0xe0c + (n)) : (0xe2c + (n) - 4))
-#define NHMEX_R_MSR_PORTN_IPERF_CFG0(n)                (0xe04 + (n))
-#define NHMEX_R_MSR_PORTN_IPERF_CFG1(n)                (0xe24 + (n))
-#define NHMEX_R_MSR_PORTN_XBR_OFFSET(n)                \
-               (((n) < 4 ? 0 : 0x10) + (n) * 4)
-#define NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n)   \
-               (0xe60 + NHMEX_R_MSR_PORTN_XBR_OFFSET(n))
-#define NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(n)    \
-               (NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) + 1)
-#define NHMEX_R_MSR_PORTN_XBR_SET1_MASK(n)     \
-               (NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) + 2)
-#define NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n)   \
-               (0xe70 + NHMEX_R_MSR_PORTN_XBR_OFFSET(n))
-#define NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(n)    \
-               (NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) + 1)
-#define NHMEX_R_MSR_PORTN_XBR_SET2_MASK(n)     \
-               (NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) + 2)
-
-#define NHMEX_R_PMON_CTL_EN                    (1 << 0)
-#define NHMEX_R_PMON_CTL_EV_SEL_SHIFT          1
-#define NHMEX_R_PMON_CTL_EV_SEL_MASK           \
-               (0x1f << NHMEX_R_PMON_CTL_EV_SEL_SHIFT)
-#define NHMEX_R_PMON_CTL_PMI_EN                        (1 << 6)
-#define NHMEX_R_PMON_RAW_EVENT_MASK            NHMEX_R_PMON_CTL_EV_SEL_MASK
-
-/* NHM-EX Wbox */
-#define NHMEX_W_MSR_GLOBAL_CTL                 0xc80
-#define NHMEX_W_MSR_PMON_CNT0                  0xc90
-#define NHMEX_W_MSR_PMON_EVT_SEL0              0xc91
-#define NHMEX_W_MSR_PMON_FIXED_CTR             0x394
-#define NHMEX_W_MSR_PMON_FIXED_CTL             0x395
-
-#define NHMEX_W_PMON_GLOBAL_FIXED_EN           (1ULL << 31)
-
-#define __BITS_VALUE(x, i, n)  ((typeof(x))(((x) >> ((i) * (n))) & \
-                               ((1ULL << (n)) - 1)))
-
-DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
-DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5");
-DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
-DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
-DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
-DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
-DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7");
-DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63");
-DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63");
-
-static void nhmex_uncore_msr_init_box(struct intel_uncore_box *box)
-{
-       wrmsrl(NHMEX_U_MSR_PMON_GLOBAL_CTL, NHMEX_U_PMON_GLOBAL_EN_ALL);
-}
-
-static void nhmex_uncore_msr_disable_box(struct intel_uncore_box *box)
-{
-       unsigned msr = uncore_msr_box_ctl(box);
-       u64 config;
-
-       if (msr) {
-               rdmsrl(msr, config);
-               config &= ~((1ULL << uncore_num_counters(box)) - 1);
-               /* WBox has a fixed counter */
-               if (uncore_msr_fixed_ctl(box))
-                       config &= ~NHMEX_W_PMON_GLOBAL_FIXED_EN;
-               wrmsrl(msr, config);
-       }
-}
-
-static void nhmex_uncore_msr_enable_box(struct intel_uncore_box *box)
-{
-       unsigned msr = uncore_msr_box_ctl(box);
-       u64 config;
-
-       if (msr) {
-               rdmsrl(msr, config);
-               config |= (1ULL << uncore_num_counters(box)) - 1;
-               /* WBox has a fixed counter */
-               if (uncore_msr_fixed_ctl(box))
-                       config |= NHMEX_W_PMON_GLOBAL_FIXED_EN;
-               wrmsrl(msr, config);
-       }
-}
-
-static void nhmex_uncore_msr_disable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       wrmsrl(event->hw.config_base, 0);
-}
-
-static void nhmex_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (hwc->idx >= UNCORE_PMC_IDX_FIXED)
-               wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0);
-       else if (box->pmu->type->event_mask & NHMEX_PMON_CTL_EN_BIT0)
-               wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
-       else
-               wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);
-}
-
-#define NHMEX_UNCORE_OPS_COMMON_INIT()                         \
-       .init_box       = nhmex_uncore_msr_init_box,            \
-       .disable_box    = nhmex_uncore_msr_disable_box,         \
-       .enable_box     = nhmex_uncore_msr_enable_box,          \
-       .disable_event  = nhmex_uncore_msr_disable_event,       \
-       .read_counter   = uncore_msr_read_counter
-
-static struct intel_uncore_ops nhmex_uncore_ops = {
-       NHMEX_UNCORE_OPS_COMMON_INIT(),
-       .enable_event   = nhmex_uncore_msr_enable_event,
-};
-
-static struct attribute *nhmex_uncore_ubox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_edge.attr,
-       NULL,
-};
-
-static struct attribute_group nhmex_uncore_ubox_format_group = {
-       .name           = "format",
-       .attrs          = nhmex_uncore_ubox_formats_attr,
-};
-
-static struct intel_uncore_type nhmex_uncore_ubox = {
-       .name           = "ubox",
-       .num_counters   = 1,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 48,
-       .event_ctl      = NHMEX_U_MSR_PMON_EV_SEL,
-       .perf_ctr       = NHMEX_U_MSR_PMON_CTR,
-       .event_mask     = NHMEX_U_PMON_RAW_EVENT_MASK,
-       .box_ctl        = NHMEX_U_MSR_PMON_GLOBAL_CTL,
-       .ops            = &nhmex_uncore_ops,
-       .format_group   = &nhmex_uncore_ubox_format_group
-};
-
-static struct attribute *nhmex_uncore_cbox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       NULL,
-};
-
-static struct attribute_group nhmex_uncore_cbox_format_group = {
-       .name = "format",
-       .attrs = nhmex_uncore_cbox_formats_attr,
-};
-
-/* msr offset for each instance of cbox */
-static unsigned nhmex_cbox_msr_offsets[] = {
-       0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0,
-};
-
-static struct intel_uncore_type nhmex_uncore_cbox = {
-       .name                   = "cbox",
-       .num_counters           = 6,
-       .num_boxes              = 10,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = NHMEX_C0_MSR_PMON_EV_SEL0,
-       .perf_ctr               = NHMEX_C0_MSR_PMON_CTR0,
-       .event_mask             = NHMEX_PMON_RAW_EVENT_MASK,
-       .box_ctl                = NHMEX_C0_MSR_PMON_GLOBAL_CTL,
-       .msr_offsets            = nhmex_cbox_msr_offsets,
-       .pair_ctr_ctl           = 1,
-       .ops                    = &nhmex_uncore_ops,
-       .format_group           = &nhmex_uncore_cbox_format_group
-};
-
-static struct uncore_event_desc nhmex_uncore_wbox_events[] = {
-       INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0"),
-       { /* end: all zeroes */ },
-};
-
-static struct intel_uncore_type nhmex_uncore_wbox = {
-       .name                   = "wbox",
-       .num_counters           = 4,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = NHMEX_W_MSR_PMON_CNT0,
-       .perf_ctr               = NHMEX_W_MSR_PMON_EVT_SEL0,
-       .fixed_ctr              = NHMEX_W_MSR_PMON_FIXED_CTR,
-       .fixed_ctl              = NHMEX_W_MSR_PMON_FIXED_CTL,
-       .event_mask             = NHMEX_PMON_RAW_EVENT_MASK,
-       .box_ctl                = NHMEX_W_MSR_GLOBAL_CTL,
-       .pair_ctr_ctl           = 1,
-       .event_descs            = nhmex_uncore_wbox_events,
-       .ops                    = &nhmex_uncore_ops,
-       .format_group           = &nhmex_uncore_cbox_format_group
-};
-
-static int nhmex_bbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-       int ctr, ev_sel;
-
-       ctr = (hwc->config & NHMEX_B_PMON_CTR_MASK) >>
-               NHMEX_B_PMON_CTR_SHIFT;
-       ev_sel = (hwc->config & NHMEX_B_PMON_CTL_EV_SEL_MASK) >>
-                 NHMEX_B_PMON_CTL_EV_SEL_SHIFT;
-
-       /* events that do not use the match/mask registers */
-       if ((ctr == 0 && ev_sel > 0x3) || (ctr == 1 && ev_sel > 0x6) ||
-           (ctr == 2 && ev_sel != 0x4) || ctr == 3)
-               return 0;
-
-       if (box->pmu->pmu_idx == 0)
-               reg1->reg = NHMEX_B0_MSR_MATCH;
-       else
-               reg1->reg = NHMEX_B1_MSR_MATCH;
-       reg1->idx = 0;
-       reg1->config = event->attr.config1;
-       reg2->config = event->attr.config2;
-       return 0;
-}
-
-static void nhmex_bbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-
-       if (reg1->idx != EXTRA_REG_NONE) {
-               wrmsrl(reg1->reg, reg1->config);
-               wrmsrl(reg1->reg + 1, reg2->config);
-       }
-       wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0 |
-               (hwc->config & NHMEX_B_PMON_CTL_EV_SEL_MASK));
-}
-
-/*
- * The Bbox has 4 counters, but each counter monitors different events.
- * Use bits 6-7 in the event config to select counter.
- */
-static struct event_constraint nhmex_uncore_bbox_constraints[] = {
-       EVENT_CONSTRAINT(0 , 1, 0xc0),
-       EVENT_CONSTRAINT(0x40, 2, 0xc0),
-       EVENT_CONSTRAINT(0x80, 4, 0xc0),
-       EVENT_CONSTRAINT(0xc0, 8, 0xc0),
-       EVENT_CONSTRAINT_END,
-};
-
-static struct attribute *nhmex_uncore_bbox_formats_attr[] = {
-       &format_attr_event5.attr,
-       &format_attr_counter.attr,
-       &format_attr_match.attr,
-       &format_attr_mask.attr,
-       NULL,
-};
-
-static struct attribute_group nhmex_uncore_bbox_format_group = {
-       .name = "format",
-       .attrs = nhmex_uncore_bbox_formats_attr,
-};
-
-static struct intel_uncore_ops nhmex_uncore_bbox_ops = {
-       NHMEX_UNCORE_OPS_COMMON_INIT(),
-       .enable_event           = nhmex_bbox_msr_enable_event,
-       .hw_config              = nhmex_bbox_hw_config,
-       .get_constraint         = uncore_get_constraint,
-       .put_constraint         = uncore_put_constraint,
-};
-
-static struct intel_uncore_type nhmex_uncore_bbox = {
-       .name                   = "bbox",
-       .num_counters           = 4,
-       .num_boxes              = 2,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = NHMEX_B0_MSR_PMON_CTL0,
-       .perf_ctr               = NHMEX_B0_MSR_PMON_CTR0,
-       .event_mask             = NHMEX_B_PMON_RAW_EVENT_MASK,
-       .box_ctl                = NHMEX_B0_MSR_PMON_GLOBAL_CTL,
-       .msr_offset             = NHMEX_B_MSR_OFFSET,
-       .pair_ctr_ctl           = 1,
-       .num_shared_regs        = 1,
-       .constraints            = nhmex_uncore_bbox_constraints,
-       .ops                    = &nhmex_uncore_bbox_ops,
-       .format_group           = &nhmex_uncore_bbox_format_group
-};
-
-static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-
-       /* only TO_R_PROG_EV event uses the match/mask register */
-       if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) !=
-           NHMEX_S_EVENT_TO_R_PROG_EV)
-               return 0;
-
-       if (box->pmu->pmu_idx == 0)
-               reg1->reg = NHMEX_S0_MSR_MM_CFG;
-       else
-               reg1->reg = NHMEX_S1_MSR_MM_CFG;
-       reg1->idx = 0;
-       reg1->config = event->attr.config1;
-       reg2->config = event->attr.config2;
-       return 0;
-}
-
-static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-
-       if (reg1->idx != EXTRA_REG_NONE) {
-               wrmsrl(reg1->reg, 0);
-               wrmsrl(reg1->reg + 1, reg1->config);
-               wrmsrl(reg1->reg + 2, reg2->config);
-               wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN);
-       }
-       wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
-}
-
-static struct attribute *nhmex_uncore_sbox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       &format_attr_match.attr,
-       &format_attr_mask.attr,
-       NULL,
-};
-
-static struct attribute_group nhmex_uncore_sbox_format_group = {
-       .name                   = "format",
-       .attrs                  = nhmex_uncore_sbox_formats_attr,
-};
-
-static struct intel_uncore_ops nhmex_uncore_sbox_ops = {
-       NHMEX_UNCORE_OPS_COMMON_INIT(),
-       .enable_event           = nhmex_sbox_msr_enable_event,
-       .hw_config              = nhmex_sbox_hw_config,
-       .get_constraint         = uncore_get_constraint,
-       .put_constraint         = uncore_put_constraint,
-};
-
-static struct intel_uncore_type nhmex_uncore_sbox = {
-       .name                   = "sbox",
-       .num_counters           = 4,
-       .num_boxes              = 2,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = NHMEX_S0_MSR_PMON_CTL0,
-       .perf_ctr               = NHMEX_S0_MSR_PMON_CTR0,
-       .event_mask             = NHMEX_PMON_RAW_EVENT_MASK,
-       .box_ctl                = NHMEX_S0_MSR_PMON_GLOBAL_CTL,
-       .msr_offset             = NHMEX_S_MSR_OFFSET,
-       .pair_ctr_ctl           = 1,
-       .num_shared_regs        = 1,
-       .ops                    = &nhmex_uncore_sbox_ops,
-       .format_group           = &nhmex_uncore_sbox_format_group
-};
-
-enum {
-       EXTRA_REG_NHMEX_M_FILTER,
-       EXTRA_REG_NHMEX_M_DSP,
-       EXTRA_REG_NHMEX_M_ISS,
-       EXTRA_REG_NHMEX_M_MAP,
-       EXTRA_REG_NHMEX_M_MSC_THR,
-       EXTRA_REG_NHMEX_M_PGT,
-       EXTRA_REG_NHMEX_M_PLD,
-       EXTRA_REG_NHMEX_M_ZDP_CTL_FVC,
-};
-
-static struct extra_reg nhmex_uncore_mbox_extra_regs[] = {
-       MBOX_INC_SEL_EXTAR_REG(0x0, DSP),
-       MBOX_INC_SEL_EXTAR_REG(0x4, MSC_THR),
-       MBOX_INC_SEL_EXTAR_REG(0x5, MSC_THR),
-       MBOX_INC_SEL_EXTAR_REG(0x9, ISS),
-       /* event 0xa uses two extra registers */
-       MBOX_INC_SEL_EXTAR_REG(0xa, ISS),
-       MBOX_INC_SEL_EXTAR_REG(0xa, PLD),
-       MBOX_INC_SEL_EXTAR_REG(0xb, PLD),
-       /* events 0xd ~ 0x10 use the same extra register */
-       MBOX_INC_SEL_EXTAR_REG(0xd, ZDP_CTL_FVC),
-       MBOX_INC_SEL_EXTAR_REG(0xe, ZDP_CTL_FVC),
-       MBOX_INC_SEL_EXTAR_REG(0xf, ZDP_CTL_FVC),
-       MBOX_INC_SEL_EXTAR_REG(0x10, ZDP_CTL_FVC),
-       MBOX_INC_SEL_EXTAR_REG(0x16, PGT),
-       MBOX_SET_FLAG_SEL_EXTRA_REG(0x0, DSP),
-       MBOX_SET_FLAG_SEL_EXTRA_REG(0x1, ISS),
-       MBOX_SET_FLAG_SEL_EXTRA_REG(0x5, PGT),
-       MBOX_SET_FLAG_SEL_EXTRA_REG(0x6, MAP),
-       EVENT_EXTRA_END
-};
-
-/* Nehalem-EX or Westmere-EX ? */
-static bool uncore_nhmex;
-
-static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config)
-{
-       struct intel_uncore_extra_reg *er;
-       unsigned long flags;
-       bool ret = false;
-       u64 mask;
-
-       if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
-               er = &box->shared_regs[idx];
-               raw_spin_lock_irqsave(&er->lock, flags);
-               if (!atomic_read(&er->ref) || er->config == config) {
-                       atomic_inc(&er->ref);
-                       er->config = config;
-                       ret = true;
-               }
-               raw_spin_unlock_irqrestore(&er->lock, flags);
-
-               return ret;
-       }
-       /*
-        * The ZDP_CTL_FVC MSR has 4 fields which are used to control
-        * events 0xd ~ 0x10. Besides these 4 fields, there are additional
-        * fields which are shared.
-        */
-       idx -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
-       if (WARN_ON_ONCE(idx >= 4))
-               return false;
-
-       /* mask of the shared fields */
-       if (uncore_nhmex)
-               mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK;
-       else
-               mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK;
-       er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
-
-       raw_spin_lock_irqsave(&er->lock, flags);
-       /* add mask of the non-shared field if it's in use */
-       if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) {
-               if (uncore_nhmex)
-                       mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
-               else
-                       mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
-       }
-
-       if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) {
-               atomic_add(1 << (idx * 8), &er->ref);
-               if (uncore_nhmex)
-                       mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK |
-                               NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
-               else
-                       mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK |
-                               WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
-               er->config &= ~mask;
-               er->config |= (config & mask);
-               ret = true;
-       }
-       raw_spin_unlock_irqrestore(&er->lock, flags);
-
-       return ret;
-}
-
-static void nhmex_mbox_put_shared_reg(struct intel_uncore_box *box, int idx)
-{
-       struct intel_uncore_extra_reg *er;
-
-       if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
-               er = &box->shared_regs[idx];
-               atomic_dec(&er->ref);
-               return;
-       }
-
-       idx -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
-       er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
-       atomic_sub(1 << (idx * 8), &er->ref);
-}
-
-static u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       u64 idx, orig_idx = __BITS_VALUE(reg1->idx, 0, 8);
-       u64 config = reg1->config;
-
-       /* get the non-shared control bits and shift them */
-       idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
-       if (uncore_nhmex)
-               config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
-       else
-               config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
-       if (new_idx > orig_idx) {
-               idx = new_idx - orig_idx;
-               config <<= 3 * idx;
-       } else {
-               idx = orig_idx - new_idx;
-               config >>= 3 * idx;
-       }
-
-       /* add the shared control bits back */
-       if (uncore_nhmex)
-               config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
-       else
-               config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
-       config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
-       if (modify) {
-               /* adjust the main event selector */
-               if (new_idx > orig_idx)
-                       hwc->config += idx << NHMEX_M_PMON_CTL_INC_SEL_SHIFT;
-               else
-                       hwc->config -= idx << NHMEX_M_PMON_CTL_INC_SEL_SHIFT;
-               reg1->config = config;
-               reg1->idx = ~0xff | new_idx;
-       }
-       return config;
-}
-
-static struct event_constraint *
-nhmex_mbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
-       int i, idx[2], alloc = 0;
-       u64 config1 = reg1->config;
-
-       idx[0] = __BITS_VALUE(reg1->idx, 0, 8);
-       idx[1] = __BITS_VALUE(reg1->idx, 1, 8);
-again:
-       for (i = 0; i < 2; i++) {
-               if (!uncore_box_is_fake(box) && (reg1->alloc & (0x1 << i)))
-                       idx[i] = 0xff;
-
-               if (idx[i] == 0xff)
-                       continue;
-
-               if (!nhmex_mbox_get_shared_reg(box, idx[i],
-                               __BITS_VALUE(config1, i, 32)))
-                       goto fail;
-               alloc |= (0x1 << i);
-       }
-
-       /* for the match/mask registers */
-       if (reg2->idx != EXTRA_REG_NONE &&
-           (uncore_box_is_fake(box) || !reg2->alloc) &&
-           !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config))
-               goto fail;
-
-       /*
-        * If it's a fake box -- as per validate_{group,event}() we
-        * shouldn't touch event state and we can avoid doing so
-        * since both will only call get_event_constraints() once
-        * on each event, this avoids the need for reg->alloc.
-        */
-       if (!uncore_box_is_fake(box)) {
-               if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8))
-                       nhmex_mbox_alter_er(event, idx[0], true);
-               reg1->alloc |= alloc;
-               if (reg2->idx != EXTRA_REG_NONE)
-                       reg2->alloc = 1;
-       }
-       return NULL;
-fail:
-       if (idx[0] != 0xff && !(alloc & 0x1) &&
-           idx[0] >= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
-               /*
-                * events 0xd ~ 0x10 are functional identical, but are
-                * controlled by different fields in the ZDP_CTL_FVC
-                * register. If we failed to take one field, try the
-                * rest 3 choices.
-                */
-               BUG_ON(__BITS_VALUE(reg1->idx, 1, 8) != 0xff);
-               idx[0] -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
-               idx[0] = (idx[0] + 1) % 4;
-               idx[0] += EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
-               if (idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) {
-                       config1 = nhmex_mbox_alter_er(event, idx[0], false);
-                       goto again;
-               }
-       }
-
-       if (alloc & 0x1)
-               nhmex_mbox_put_shared_reg(box, idx[0]);
-       if (alloc & 0x2)
-               nhmex_mbox_put_shared_reg(box, idx[1]);
-       return &uncore_constraint_empty;
-}
-
-static void nhmex_mbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
-
-       if (uncore_box_is_fake(box))
-               return;
-
-       if (reg1->alloc & 0x1)
-               nhmex_mbox_put_shared_reg(box, __BITS_VALUE(reg1->idx, 0, 8));
-       if (reg1->alloc & 0x2)
-               nhmex_mbox_put_shared_reg(box, __BITS_VALUE(reg1->idx, 1, 8));
-       reg1->alloc = 0;
-
-       if (reg2->alloc) {
-               nhmex_mbox_put_shared_reg(box, reg2->idx);
-               reg2->alloc = 0;
-       }
-}
-
-static int nhmex_mbox_extra_reg_idx(struct extra_reg *er)
-{
-       if (er->idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC)
-               return er->idx;
-       return er->idx + (er->event >> NHMEX_M_PMON_CTL_INC_SEL_SHIFT) - 0xd;
-}
-
-static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct intel_uncore_type *type = box->pmu->type;
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
-       struct extra_reg *er;
-       unsigned msr;
-       int reg_idx = 0;
-       /*
-        * The mbox events may require 2 extra MSRs at the most. But only
-        * the lower 32 bits in these MSRs are significant, so we can use
-        * config1 to pass two MSRs' config.
-        */
-       for (er = nhmex_uncore_mbox_extra_regs; er->msr; er++) {
-               if (er->event != (event->hw.config & er->config_mask))
-                       continue;
-               if (event->attr.config1 & ~er->valid_mask)
-                       return -EINVAL;
-
-               msr = er->msr + type->msr_offset * box->pmu->pmu_idx;
-               if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff))
-                       return -EINVAL;
-
-               /* always use the 32~63 bits to pass the PLD config */
-               if (er->idx == EXTRA_REG_NHMEX_M_PLD)
-                       reg_idx = 1;
-               else if (WARN_ON_ONCE(reg_idx > 0))
-                       return -EINVAL;
-
-               reg1->idx &= ~(0xff << (reg_idx * 8));
-               reg1->reg &= ~(0xffff << (reg_idx * 16));
-               reg1->idx |= nhmex_mbox_extra_reg_idx(er) << (reg_idx * 8);
-               reg1->reg |= msr << (reg_idx * 16);
-               reg1->config = event->attr.config1;
-               reg_idx++;
-       }
-       /*
-        * The mbox only provides ability to perform address matching
-        * for the PLD events.
-        */
-       if (reg_idx == 2) {
-               reg2->idx = EXTRA_REG_NHMEX_M_FILTER;
-               if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN)
-                       reg2->config = event->attr.config2;
-               else
-                       reg2->config = ~0ULL;
-               if (box->pmu->pmu_idx == 0)
-                       reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG;
-               else
-                       reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG;
-       }
-       return 0;
-}
-
-static u64 nhmex_mbox_shared_reg_config(struct intel_uncore_box *box, int idx)
-{
-       struct intel_uncore_extra_reg *er;
-       unsigned long flags;
-       u64 config;
-
-       if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC)
-               return box->shared_regs[idx].config;
-
-       er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
-       raw_spin_lock_irqsave(&er->lock, flags);
-       config = er->config;
-       raw_spin_unlock_irqrestore(&er->lock, flags);
-       return config;
-}
-
-static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-       int idx;
-
-       idx = __BITS_VALUE(reg1->idx, 0, 8);
-       if (idx != 0xff)
-               wrmsrl(__BITS_VALUE(reg1->reg, 0, 16),
-                       nhmex_mbox_shared_reg_config(box, idx));
-       idx = __BITS_VALUE(reg1->idx, 1, 8);
-       if (idx != 0xff)
-               wrmsrl(__BITS_VALUE(reg1->reg, 1, 16),
-                       nhmex_mbox_shared_reg_config(box, idx));
-
-       if (reg2->idx != EXTRA_REG_NONE) {
-               wrmsrl(reg2->reg, 0);
-               if (reg2->config != ~0ULL) {
-                       wrmsrl(reg2->reg + 1,
-                               reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK);
-                       wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK &
-                               (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT));
-                       wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN);
-               }
-       }
-
-       wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);
-}
-
-DEFINE_UNCORE_FORMAT_ATTR(count_mode,          count_mode,     "config:2-3");
-DEFINE_UNCORE_FORMAT_ATTR(storage_mode,                storage_mode,   "config:4-5");
-DEFINE_UNCORE_FORMAT_ATTR(wrap_mode,           wrap_mode,      "config:6");
-DEFINE_UNCORE_FORMAT_ATTR(flag_mode,           flag_mode,      "config:7");
-DEFINE_UNCORE_FORMAT_ATTR(inc_sel,             inc_sel,        "config:9-13");
-DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel,                set_flag_sel,   "config:19-21");
-DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en,       filter_cfg_en,  "config2:63");
-DEFINE_UNCORE_FORMAT_ATTR(filter_match,                filter_match,   "config2:0-33");
-DEFINE_UNCORE_FORMAT_ATTR(filter_mask,         filter_mask,    "config2:34-61");
-DEFINE_UNCORE_FORMAT_ATTR(dsp,                 dsp,            "config1:0-31");
-DEFINE_UNCORE_FORMAT_ATTR(thr,                 thr,            "config1:0-31");
-DEFINE_UNCORE_FORMAT_ATTR(fvc,                 fvc,            "config1:0-31");
-DEFINE_UNCORE_FORMAT_ATTR(pgt,                 pgt,            "config1:0-31");
-DEFINE_UNCORE_FORMAT_ATTR(map,                 map,            "config1:0-31");
-DEFINE_UNCORE_FORMAT_ATTR(iss,                 iss,            "config1:0-31");
-DEFINE_UNCORE_FORMAT_ATTR(pld,                 pld,            "config1:32-63");
-
-static struct attribute *nhmex_uncore_mbox_formats_attr[] = {
-       &format_attr_count_mode.attr,
-       &format_attr_storage_mode.attr,
-       &format_attr_wrap_mode.attr,
-       &format_attr_flag_mode.attr,
-       &format_attr_inc_sel.attr,
-       &format_attr_set_flag_sel.attr,
-       &format_attr_filter_cfg_en.attr,
-       &format_attr_filter_match.attr,
-       &format_attr_filter_mask.attr,
-       &format_attr_dsp.attr,
-       &format_attr_thr.attr,
-       &format_attr_fvc.attr,
-       &format_attr_pgt.attr,
-       &format_attr_map.attr,
-       &format_attr_iss.attr,
-       &format_attr_pld.attr,
-       NULL,
-};
-
-static struct attribute_group nhmex_uncore_mbox_format_group = {
-       .name           = "format",
-       .attrs          = nhmex_uncore_mbox_formats_attr,
-};
-
-static struct uncore_event_desc nhmex_uncore_mbox_events[] = {
-       INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x2800"),
-       INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x2820"),
-       { /* end: all zeroes */ },
-};
-
-static struct uncore_event_desc wsmex_uncore_mbox_events[] = {
-       INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"),
-       INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"),
-       { /* end: all zeroes */ },
-};
-
-static struct intel_uncore_ops nhmex_uncore_mbox_ops = {
-       NHMEX_UNCORE_OPS_COMMON_INIT(),
-       .enable_event   = nhmex_mbox_msr_enable_event,
-       .hw_config      = nhmex_mbox_hw_config,
-       .get_constraint = nhmex_mbox_get_constraint,
-       .put_constraint = nhmex_mbox_put_constraint,
-};
-
-static struct intel_uncore_type nhmex_uncore_mbox = {
-       .name                   = "mbox",
-       .num_counters           = 6,
-       .num_boxes              = 2,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = NHMEX_M0_MSR_PMU_CTL0,
-       .perf_ctr               = NHMEX_M0_MSR_PMU_CNT0,
-       .event_mask             = NHMEX_M_PMON_RAW_EVENT_MASK,
-       .box_ctl                = NHMEX_M0_MSR_GLOBAL_CTL,
-       .msr_offset             = NHMEX_M_MSR_OFFSET,
-       .pair_ctr_ctl           = 1,
-       .num_shared_regs        = 8,
-       .event_descs            = nhmex_uncore_mbox_events,
-       .ops                    = &nhmex_uncore_mbox_ops,
-       .format_group           = &nhmex_uncore_mbox_format_group,
-};
-
-static void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-
-       /* adjust the main event selector and extra register index */
-       if (reg1->idx % 2) {
-               reg1->idx--;
-               hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
-       } else {
-               reg1->idx++;
-               hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
-       }
-
-       /* adjust extra register config */
-       switch (reg1->idx % 6) {
-       case 2:
-               /* shift the 8~15 bits to the 0~7 bits */
-               reg1->config >>= 8;
-               break;
-       case 3:
-               /* shift the 0~7 bits to the 8~15 bits */
-               reg1->config <<= 8;
-               break;
-       }
-}
-
-/*
- * Each rbox has 4 event set which monitor PQI port 0~3 or 4~7.
- * An event set consists of 6 events, the 3rd and 4th events in
- * an event set use the same extra register. So an event set uses
- * 5 extra registers.
- */
-static struct event_constraint *
-nhmex_rbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-       struct intel_uncore_extra_reg *er;
-       unsigned long flags;
-       int idx, er_idx;
-       u64 config1;
-       bool ok = false;
-
-       if (!uncore_box_is_fake(box) && reg1->alloc)
-               return NULL;
-
-       idx = reg1->idx % 6;
-       config1 = reg1->config;
-again:
-       er_idx = idx;
-       /* the 3rd and 4th events use the same extra register */
-       if (er_idx > 2)
-               er_idx--;
-       er_idx += (reg1->idx / 6) * 5;
-
-       er = &box->shared_regs[er_idx];
-       raw_spin_lock_irqsave(&er->lock, flags);
-       if (idx < 2) {
-               if (!atomic_read(&er->ref) || er->config == reg1->config) {
-                       atomic_inc(&er->ref);
-                       er->config = reg1->config;
-                       ok = true;
-               }
-       } else if (idx == 2 || idx == 3) {
-               /*
-                * these two events use different fields in a extra register,
-                * the 0~7 bits and the 8~15 bits respectively.
-                */
-               u64 mask = 0xff << ((idx - 2) * 8);
-               if (!__BITS_VALUE(atomic_read(&er->ref), idx - 2, 8) ||
-                               !((er->config ^ config1) & mask)) {
-                       atomic_add(1 << ((idx - 2) * 8), &er->ref);
-                       er->config &= ~mask;
-                       er->config |= config1 & mask;
-                       ok = true;
-               }
-       } else {
-               if (!atomic_read(&er->ref) ||
-                               (er->config == (hwc->config >> 32) &&
-                                er->config1 == reg1->config &&
-                                er->config2 == reg2->config)) {
-                       atomic_inc(&er->ref);
-                       er->config = (hwc->config >> 32);
-                       er->config1 = reg1->config;
-                       er->config2 = reg2->config;
-                       ok = true;
-               }
-       }
-       raw_spin_unlock_irqrestore(&er->lock, flags);
-
-       if (!ok) {
-               /*
-                * The Rbox events are always in pairs. The paired
-                * events are functional identical, but use different
-                * extra registers. If we failed to take an extra
-                * register, try the alternative.
-                */
-               idx ^= 1;
-               if (idx != reg1->idx % 6) {
-                       if (idx == 2)
-                               config1 >>= 8;
-                       else if (idx == 3)
-                               config1 <<= 8;
-                       goto again;
-               }
-       } else {
-               if (!uncore_box_is_fake(box)) {
-                       if (idx != reg1->idx % 6)
-                               nhmex_rbox_alter_er(box, event);
-                       reg1->alloc = 1;
-               }
-               return NULL;
-       }
-       return &uncore_constraint_empty;
-}
-
-static void nhmex_rbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct intel_uncore_extra_reg *er;
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       int idx, er_idx;
-
-       if (uncore_box_is_fake(box) || !reg1->alloc)
-               return;
-
-       idx = reg1->idx % 6;
-       er_idx = idx;
-       if (er_idx > 2)
-               er_idx--;
-       er_idx += (reg1->idx / 6) * 5;
-
-       er = &box->shared_regs[er_idx];
-       if (idx == 2 || idx == 3)
-               atomic_sub(1 << ((idx - 2) * 8), &er->ref);
-       else
-               atomic_dec(&er->ref);
-
-       reg1->alloc = 0;
-}
-
-static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
-       int idx;
-
-       idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >>
-               NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
-       if (idx >= 0x18)
-               return -EINVAL;
-
-       reg1->idx = idx;
-       reg1->config = event->attr.config1;
-
-       switch (idx % 6) {
-       case 4:
-       case 5:
-               hwc->config |= event->attr.config & (~0ULL << 32);
-               reg2->config = event->attr.config2;
-               break;
-       }
-       return 0;
-}
-
-static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-       int idx, port;
-
-       idx = reg1->idx;
-       port = idx / 6 + box->pmu->pmu_idx * 4;
-
-       switch (idx % 6) {
-       case 0:
-               wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config);
-               break;
-       case 1:
-               wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config);
-               break;
-       case 2:
-       case 3:
-               wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port),
-                       uncore_shared_reg_config(box, 2 + (idx / 6) * 5));
-               break;
-       case 4:
-               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port),
-                       hwc->config >> 32);
-               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config);
-               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config);
-               break;
-       case 5:
-               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port),
-                       hwc->config >> 32);
-               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config);
-               wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config);
-               break;
-       }
-
-       wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0 |
-               (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK));
-}
-
-DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63");
-DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63");
-DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63");
-DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15");
-DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31");
-
-static struct attribute *nhmex_uncore_rbox_formats_attr[] = {
-       &format_attr_event5.attr,
-       &format_attr_xbr_mm_cfg.attr,
-       &format_attr_xbr_match.attr,
-       &format_attr_xbr_mask.attr,
-       &format_attr_qlx_cfg.attr,
-       &format_attr_iperf_cfg.attr,
-       NULL,
-};
-
-static struct attribute_group nhmex_uncore_rbox_format_group = {
-       .name = "format",
-       .attrs = nhmex_uncore_rbox_formats_attr,
-};
-
-static struct uncore_event_desc nhmex_uncore_rbox_events[] = {
-       INTEL_UNCORE_EVENT_DESC(qpi0_flit_send,         "event=0x0,iperf_cfg=0x80000000"),
-       INTEL_UNCORE_EVENT_DESC(qpi1_filt_send,         "event=0x6,iperf_cfg=0x80000000"),
-       INTEL_UNCORE_EVENT_DESC(qpi0_idle_filt,         "event=0x0,iperf_cfg=0x40000000"),
-       INTEL_UNCORE_EVENT_DESC(qpi1_idle_filt,         "event=0x6,iperf_cfg=0x40000000"),
-       INTEL_UNCORE_EVENT_DESC(qpi0_date_response,     "event=0x0,iperf_cfg=0xc4"),
-       INTEL_UNCORE_EVENT_DESC(qpi1_date_response,     "event=0x6,iperf_cfg=0xc4"),
-       { /* end: all zeroes */ },
-};
-
-static struct intel_uncore_ops nhmex_uncore_rbox_ops = {
-       NHMEX_UNCORE_OPS_COMMON_INIT(),
-       .enable_event           = nhmex_rbox_msr_enable_event,
-       .hw_config              = nhmex_rbox_hw_config,
-       .get_constraint         = nhmex_rbox_get_constraint,
-       .put_constraint         = nhmex_rbox_put_constraint,
-};
-
-static struct intel_uncore_type nhmex_uncore_rbox = {
-       .name                   = "rbox",
-       .num_counters           = 8,
-       .num_boxes              = 2,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = NHMEX_R_MSR_PMON_CTL0,
-       .perf_ctr               = NHMEX_R_MSR_PMON_CNT0,
-       .event_mask             = NHMEX_R_PMON_RAW_EVENT_MASK,
-       .box_ctl                = NHMEX_R_MSR_GLOBAL_CTL,
-       .msr_offset             = NHMEX_R_MSR_OFFSET,
-       .pair_ctr_ctl           = 1,
-       .num_shared_regs        = 20,
-       .event_descs            = nhmex_uncore_rbox_events,
-       .ops                    = &nhmex_uncore_rbox_ops,
-       .format_group           = &nhmex_uncore_rbox_format_group
-};
-
-static struct intel_uncore_type *nhmex_msr_uncores[] = {
-       &nhmex_uncore_ubox,
-       &nhmex_uncore_cbox,
-       &nhmex_uncore_bbox,
-       &nhmex_uncore_sbox,
-       &nhmex_uncore_mbox,
-       &nhmex_uncore_rbox,
-       &nhmex_uncore_wbox,
-       NULL,
-};
-
-void nhmex_uncore_cpu_init(void)
-{
-       if (boot_cpu_data.x86_model == 46)
-               uncore_nhmex = true;
-       else
-               nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events;
-       if (nhmex_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
-               nhmex_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
-       uncore_msr_uncores = nhmex_msr_uncores;
-}
-/* end of Nehalem-EX uncore support */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
deleted file mode 100644 (file)
index 2bd030d..0000000
+++ /dev/null
@@ -1,717 +0,0 @@
-/* Nehalem/SandBridge/Haswell uncore support */
-#include "perf_event_intel_uncore.h"
-
-/* Uncore IMC PCI IDs */
-#define PCI_DEVICE_ID_INTEL_SNB_IMC    0x0100
-#define PCI_DEVICE_ID_INTEL_IVB_IMC    0x0154
-#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
-#define PCI_DEVICE_ID_INTEL_HSW_IMC    0x0c00
-#define PCI_DEVICE_ID_INTEL_HSW_U_IMC  0x0a04
-#define PCI_DEVICE_ID_INTEL_BDW_IMC    0x1604
-#define PCI_DEVICE_ID_INTEL_SKL_IMC    0x191f
-
-/* SNB event control */
-#define SNB_UNC_CTL_EV_SEL_MASK                        0x000000ff
-#define SNB_UNC_CTL_UMASK_MASK                 0x0000ff00
-#define SNB_UNC_CTL_EDGE_DET                   (1 << 18)
-#define SNB_UNC_CTL_EN                         (1 << 22)
-#define SNB_UNC_CTL_INVERT                     (1 << 23)
-#define SNB_UNC_CTL_CMASK_MASK                 0x1f000000
-#define NHM_UNC_CTL_CMASK_MASK                 0xff000000
-#define NHM_UNC_FIXED_CTR_CTL_EN               (1 << 0)
-
-#define SNB_UNC_RAW_EVENT_MASK                 (SNB_UNC_CTL_EV_SEL_MASK | \
-                                                SNB_UNC_CTL_UMASK_MASK | \
-                                                SNB_UNC_CTL_EDGE_DET | \
-                                                SNB_UNC_CTL_INVERT | \
-                                                SNB_UNC_CTL_CMASK_MASK)
-
-#define NHM_UNC_RAW_EVENT_MASK                 (SNB_UNC_CTL_EV_SEL_MASK | \
-                                                SNB_UNC_CTL_UMASK_MASK | \
-                                                SNB_UNC_CTL_EDGE_DET | \
-                                                SNB_UNC_CTL_INVERT | \
-                                                NHM_UNC_CTL_CMASK_MASK)
-
-/* SNB global control register */
-#define SNB_UNC_PERF_GLOBAL_CTL                 0x391
-#define SNB_UNC_FIXED_CTR_CTRL                  0x394
-#define SNB_UNC_FIXED_CTR                       0x395
-
-/* SNB uncore global control */
-#define SNB_UNC_GLOBAL_CTL_CORE_ALL             ((1 << 4) - 1)
-#define SNB_UNC_GLOBAL_CTL_EN                   (1 << 29)
-
-/* SNB Cbo register */
-#define SNB_UNC_CBO_0_PERFEVTSEL0               0x700
-#define SNB_UNC_CBO_0_PER_CTR0                  0x706
-#define SNB_UNC_CBO_MSR_OFFSET                  0x10
-
-/* SNB ARB register */
-#define SNB_UNC_ARB_PER_CTR0                   0x3b0
-#define SNB_UNC_ARB_PERFEVTSEL0                        0x3b2
-#define SNB_UNC_ARB_MSR_OFFSET                 0x10
-
-/* NHM global control register */
-#define NHM_UNC_PERF_GLOBAL_CTL                 0x391
-#define NHM_UNC_FIXED_CTR                       0x394
-#define NHM_UNC_FIXED_CTR_CTRL                  0x395
-
-/* NHM uncore global control */
-#define NHM_UNC_GLOBAL_CTL_EN_PC_ALL            ((1ULL << 8) - 1)
-#define NHM_UNC_GLOBAL_CTL_EN_FC                (1ULL << 32)
-
-/* NHM uncore register */
-#define NHM_UNC_PERFEVTSEL0                     0x3c0
-#define NHM_UNC_UNCORE_PMC0                     0x3b0
-
-DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
-DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
-DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
-DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
-DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28");
-DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31");
-
-/* Sandy Bridge uncore support */
-static void snb_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (hwc->idx < UNCORE_PMC_IDX_FIXED)
-               wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
-       else
-               wrmsrl(hwc->config_base, SNB_UNC_CTL_EN);
-}
-
-static void snb_uncore_msr_disable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       wrmsrl(event->hw.config_base, 0);
-}
-
-static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
-{
-       if (box->pmu->pmu_idx == 0) {
-               wrmsrl(SNB_UNC_PERF_GLOBAL_CTL,
-                       SNB_UNC_GLOBAL_CTL_EN | SNB_UNC_GLOBAL_CTL_CORE_ALL);
-       }
-}
-
-static struct uncore_event_desc snb_uncore_events[] = {
-       INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
-       { /* end: all zeroes */ },
-};
-
-static struct attribute *snb_uncore_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_cmask5.attr,
-       NULL,
-};
-
-static struct attribute_group snb_uncore_format_group = {
-       .name           = "format",
-       .attrs          = snb_uncore_formats_attr,
-};
-
-static struct intel_uncore_ops snb_uncore_msr_ops = {
-       .init_box       = snb_uncore_msr_init_box,
-       .disable_event  = snb_uncore_msr_disable_event,
-       .enable_event   = snb_uncore_msr_enable_event,
-       .read_counter   = uncore_msr_read_counter,
-};
-
-static struct event_constraint snb_uncore_arb_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x80, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x83, 0x1),
-       EVENT_CONSTRAINT_END
-};
-
-static struct intel_uncore_type snb_uncore_cbox = {
-       .name           = "cbox",
-       .num_counters   = 2,
-       .num_boxes      = 4,
-       .perf_ctr_bits  = 44,
-       .fixed_ctr_bits = 48,
-       .perf_ctr       = SNB_UNC_CBO_0_PER_CTR0,
-       .event_ctl      = SNB_UNC_CBO_0_PERFEVTSEL0,
-       .fixed_ctr      = SNB_UNC_FIXED_CTR,
-       .fixed_ctl      = SNB_UNC_FIXED_CTR_CTRL,
-       .single_fixed   = 1,
-       .event_mask     = SNB_UNC_RAW_EVENT_MASK,
-       .msr_offset     = SNB_UNC_CBO_MSR_OFFSET,
-       .ops            = &snb_uncore_msr_ops,
-       .format_group   = &snb_uncore_format_group,
-       .event_descs    = snb_uncore_events,
-};
-
-static struct intel_uncore_type snb_uncore_arb = {
-       .name           = "arb",
-       .num_counters   = 2,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 44,
-       .perf_ctr       = SNB_UNC_ARB_PER_CTR0,
-       .event_ctl      = SNB_UNC_ARB_PERFEVTSEL0,
-       .event_mask     = SNB_UNC_RAW_EVENT_MASK,
-       .msr_offset     = SNB_UNC_ARB_MSR_OFFSET,
-       .constraints    = snb_uncore_arb_constraints,
-       .ops            = &snb_uncore_msr_ops,
-       .format_group   = &snb_uncore_format_group,
-};
-
-static struct intel_uncore_type *snb_msr_uncores[] = {
-       &snb_uncore_cbox,
-       &snb_uncore_arb,
-       NULL,
-};
-
-void snb_uncore_cpu_init(void)
-{
-       uncore_msr_uncores = snb_msr_uncores;
-       if (snb_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
-               snb_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
-}
-
-enum {
-       SNB_PCI_UNCORE_IMC,
-};
-
-static struct uncore_event_desc snb_uncore_imc_events[] = {
-       INTEL_UNCORE_EVENT_DESC(data_reads,  "event=0x01"),
-       INTEL_UNCORE_EVENT_DESC(data_reads.scale, "6.103515625e-5"),
-       INTEL_UNCORE_EVENT_DESC(data_reads.unit, "MiB"),
-
-       INTEL_UNCORE_EVENT_DESC(data_writes, "event=0x02"),
-       INTEL_UNCORE_EVENT_DESC(data_writes.scale, "6.103515625e-5"),
-       INTEL_UNCORE_EVENT_DESC(data_writes.unit, "MiB"),
-
-       { /* end: all zeroes */ },
-};
-
-#define SNB_UNCORE_PCI_IMC_EVENT_MASK          0xff
-#define SNB_UNCORE_PCI_IMC_BAR_OFFSET          0x48
-
-/* page size multiple covering all config regs */
-#define SNB_UNCORE_PCI_IMC_MAP_SIZE            0x6000
-
-#define SNB_UNCORE_PCI_IMC_DATA_READS          0x1
-#define SNB_UNCORE_PCI_IMC_DATA_READS_BASE     0x5050
-#define SNB_UNCORE_PCI_IMC_DATA_WRITES         0x2
-#define SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE    0x5054
-#define SNB_UNCORE_PCI_IMC_CTR_BASE            SNB_UNCORE_PCI_IMC_DATA_READS_BASE
-
-static struct attribute *snb_uncore_imc_formats_attr[] = {
-       &format_attr_event.attr,
-       NULL,
-};
-
-static struct attribute_group snb_uncore_imc_format_group = {
-       .name = "format",
-       .attrs = snb_uncore_imc_formats_attr,
-};
-
-static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       int where = SNB_UNCORE_PCI_IMC_BAR_OFFSET;
-       resource_size_t addr;
-       u32 pci_dword;
-
-       pci_read_config_dword(pdev, where, &pci_dword);
-       addr = pci_dword;
-
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
-       pci_read_config_dword(pdev, where + 4, &pci_dword);
-       addr |= ((resource_size_t)pci_dword << 32);
-#endif
-
-       addr &= ~(PAGE_SIZE - 1);
-
-       box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE);
-       box->hrtimer_duration = UNCORE_SNB_IMC_HRTIMER_INTERVAL;
-}
-
-static void snb_uncore_imc_enable_box(struct intel_uncore_box *box)
-{}
-
-static void snb_uncore_imc_disable_box(struct intel_uncore_box *box)
-{}
-
-static void snb_uncore_imc_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{}
-
-static void snb_uncore_imc_disable_event(struct intel_uncore_box *box, struct perf_event *event)
-{}
-
-static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       return (u64)*(unsigned int *)(box->io_addr + hwc->event_base);
-}
-
-/*
- * custom event_init() function because we define our own fixed, free
- * running counters, so we do not want to conflict with generic uncore
- * logic. Also simplifies processing
- */
-static int snb_uncore_imc_event_init(struct perf_event *event)
-{
-       struct intel_uncore_pmu *pmu;
-       struct intel_uncore_box *box;
-       struct hw_perf_event *hwc = &event->hw;
-       u64 cfg = event->attr.config & SNB_UNCORE_PCI_IMC_EVENT_MASK;
-       int idx, base;
-
-       if (event->attr.type != event->pmu->type)
-               return -ENOENT;
-
-       pmu = uncore_event_to_pmu(event);
-       /* no device found for this pmu */
-       if (pmu->func_id < 0)
-               return -ENOENT;
-
-       /* Sampling not supported yet */
-       if (hwc->sample_period)
-               return -EINVAL;
-
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
-               return -EINVAL;
-
-       /*
-        * Place all uncore events for a particular physical package
-        * onto a single cpu
-        */
-       if (event->cpu < 0)
-               return -EINVAL;
-
-       /* check only supported bits are set */
-       if (event->attr.config & ~SNB_UNCORE_PCI_IMC_EVENT_MASK)
-               return -EINVAL;
-
-       box = uncore_pmu_to_box(pmu, event->cpu);
-       if (!box || box->cpu < 0)
-               return -EINVAL;
-
-       event->cpu = box->cpu;
-
-       event->hw.idx = -1;
-       event->hw.last_tag = ~0ULL;
-       event->hw.extra_reg.idx = EXTRA_REG_NONE;
-       event->hw.branch_reg.idx = EXTRA_REG_NONE;
-       /*
-        * check event is known (whitelist, determines counter)
-        */
-       switch (cfg) {
-       case SNB_UNCORE_PCI_IMC_DATA_READS:
-               base = SNB_UNCORE_PCI_IMC_DATA_READS_BASE;
-               idx = UNCORE_PMC_IDX_FIXED;
-               break;
-       case SNB_UNCORE_PCI_IMC_DATA_WRITES:
-               base = SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE;
-               idx = UNCORE_PMC_IDX_FIXED + 1;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* must be done before validate_group */
-       event->hw.event_base = base;
-       event->hw.config = cfg;
-       event->hw.idx = idx;
-
-       /* no group validation needed, we have free running counters */
-
-       return 0;
-}
-
-static int snb_uncore_imc_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       return 0;
-}
-
-static void snb_uncore_imc_event_start(struct perf_event *event, int flags)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       u64 count;
-
-       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
-               return;
-
-       event->hw.state = 0;
-       box->n_active++;
-
-       list_add_tail(&event->active_entry, &box->active_list);
-
-       count = snb_uncore_imc_read_counter(box, event);
-       local64_set(&event->hw.prev_count, count);
-
-       if (box->n_active == 1)
-               uncore_pmu_start_hrtimer(box);
-}
-
-static void snb_uncore_imc_event_stop(struct perf_event *event, int flags)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (!(hwc->state & PERF_HES_STOPPED)) {
-               box->n_active--;
-
-               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
-               hwc->state |= PERF_HES_STOPPED;
-
-               list_del(&event->active_entry);
-
-               if (box->n_active == 0)
-                       uncore_pmu_cancel_hrtimer(box);
-       }
-
-       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
-               /*
-                * Drain the remaining delta count out of a event
-                * that we are disabling:
-                */
-               uncore_perf_event_update(box, event);
-               hwc->state |= PERF_HES_UPTODATE;
-       }
-}
-
-static int snb_uncore_imc_event_add(struct perf_event *event, int flags)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (!box)
-               return -ENODEV;
-
-       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
-       if (!(flags & PERF_EF_START))
-               hwc->state |= PERF_HES_ARCH;
-
-       snb_uncore_imc_event_start(event, 0);
-
-       box->n_events++;
-
-       return 0;
-}
-
-static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
-{
-       struct intel_uncore_box *box = uncore_event_to_box(event);
-       int i;
-
-       snb_uncore_imc_event_stop(event, PERF_EF_UPDATE);
-
-       for (i = 0; i < box->n_events; i++) {
-               if (event == box->event_list[i]) {
-                       --box->n_events;
-                       break;
-               }
-       }
-}
-
-int snb_pci2phy_map_init(int devid)
-{
-       struct pci_dev *dev = NULL;
-       struct pci2phy_map *map;
-       int bus, segment;
-
-       dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, dev);
-       if (!dev)
-               return -ENOTTY;
-
-       bus = dev->bus->number;
-       segment = pci_domain_nr(dev->bus);
-
-       raw_spin_lock(&pci2phy_map_lock);
-       map = __find_pci2phy_map(segment);
-       if (!map) {
-               raw_spin_unlock(&pci2phy_map_lock);
-               pci_dev_put(dev);
-               return -ENOMEM;
-       }
-       map->pbus_to_physid[bus] = 0;
-       raw_spin_unlock(&pci2phy_map_lock);
-
-       pci_dev_put(dev);
-
-       return 0;
-}
-
-static struct pmu snb_uncore_imc_pmu = {
-       .task_ctx_nr    = perf_invalid_context,
-       .event_init     = snb_uncore_imc_event_init,
-       .add            = snb_uncore_imc_event_add,
-       .del            = snb_uncore_imc_event_del,
-       .start          = snb_uncore_imc_event_start,
-       .stop           = snb_uncore_imc_event_stop,
-       .read           = uncore_pmu_event_read,
-};
-
-static struct intel_uncore_ops snb_uncore_imc_ops = {
-       .init_box       = snb_uncore_imc_init_box,
-       .enable_box     = snb_uncore_imc_enable_box,
-       .disable_box    = snb_uncore_imc_disable_box,
-       .disable_event  = snb_uncore_imc_disable_event,
-       .enable_event   = snb_uncore_imc_enable_event,
-       .hw_config      = snb_uncore_imc_hw_config,
-       .read_counter   = snb_uncore_imc_read_counter,
-};
-
-static struct intel_uncore_type snb_uncore_imc = {
-       .name           = "imc",
-       .num_counters   = 2,
-       .num_boxes      = 1,
-       .fixed_ctr_bits = 32,
-       .fixed_ctr      = SNB_UNCORE_PCI_IMC_CTR_BASE,
-       .event_descs    = snb_uncore_imc_events,
-       .format_group   = &snb_uncore_imc_format_group,
-       .perf_ctr       = SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
-       .event_mask     = SNB_UNCORE_PCI_IMC_EVENT_MASK,
-       .ops            = &snb_uncore_imc_ops,
-       .pmu            = &snb_uncore_imc_pmu,
-};
-
-static struct intel_uncore_type *snb_pci_uncores[] = {
-       [SNB_PCI_UNCORE_IMC]    = &snb_uncore_imc,
-       NULL,
-};
-
-static const struct pci_device_id snb_uncore_pci_ids[] = {
-       { /* IMC */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
-       },
-       { /* end: all zeroes */ },
-};
-
-static const struct pci_device_id ivb_uncore_pci_ids[] = {
-       { /* IMC */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
-       },
-       { /* IMC */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_E3_IMC),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
-       },
-       { /* end: all zeroes */ },
-};
-
-static const struct pci_device_id hsw_uncore_pci_ids[] = {
-       { /* IMC */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
-       },
-       { /* IMC */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_U_IMC),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
-       },
-       { /* end: all zeroes */ },
-};
-
-static const struct pci_device_id bdw_uncore_pci_ids[] = {
-       { /* IMC */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BDW_IMC),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
-       },
-       { /* end: all zeroes */ },
-};
-
-static const struct pci_device_id skl_uncore_pci_ids[] = {
-       { /* IMC */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_IMC),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
-       },
-       { /* end: all zeroes */ },
-};
-
-static struct pci_driver snb_uncore_pci_driver = {
-       .name           = "snb_uncore",
-       .id_table       = snb_uncore_pci_ids,
-};
-
-static struct pci_driver ivb_uncore_pci_driver = {
-       .name           = "ivb_uncore",
-       .id_table       = ivb_uncore_pci_ids,
-};
-
-static struct pci_driver hsw_uncore_pci_driver = {
-       .name           = "hsw_uncore",
-       .id_table       = hsw_uncore_pci_ids,
-};
-
-static struct pci_driver bdw_uncore_pci_driver = {
-       .name           = "bdw_uncore",
-       .id_table       = bdw_uncore_pci_ids,
-};
-
-static struct pci_driver skl_uncore_pci_driver = {
-       .name           = "skl_uncore",
-       .id_table       = skl_uncore_pci_ids,
-};
-
-struct imc_uncore_pci_dev {
-       __u32 pci_id;
-       struct pci_driver *driver;
-};
-#define IMC_DEV(a, d) \
-       { .pci_id = PCI_DEVICE_ID_INTEL_##a, .driver = (d) }
-
-static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
-       IMC_DEV(SNB_IMC, &snb_uncore_pci_driver),
-       IMC_DEV(IVB_IMC, &ivb_uncore_pci_driver),    /* 3rd Gen Core processor */
-       IMC_DEV(IVB_E3_IMC, &ivb_uncore_pci_driver), /* Xeon E3-1200 v2/3rd Gen Core processor */
-       IMC_DEV(HSW_IMC, &hsw_uncore_pci_driver),    /* 4th Gen Core Processor */
-       IMC_DEV(HSW_U_IMC, &hsw_uncore_pci_driver),  /* 4th Gen Core ULT Mobile Processor */
-       IMC_DEV(BDW_IMC, &bdw_uncore_pci_driver),    /* 5th Gen Core U */
-       IMC_DEV(SKL_IMC, &skl_uncore_pci_driver),    /* 6th Gen Core */
-       {  /* end marker */ }
-};
-
-
-#define for_each_imc_pci_id(x, t) \
-       for (x = (t); (x)->pci_id; x++)
-
-static struct pci_driver *imc_uncore_find_dev(void)
-{
-       const struct imc_uncore_pci_dev *p;
-       int ret;
-
-       for_each_imc_pci_id(p, desktop_imc_pci_ids) {
-               ret = snb_pci2phy_map_init(p->pci_id);
-               if (ret == 0)
-                       return p->driver;
-       }
-       return NULL;
-}
-
-static int imc_uncore_pci_init(void)
-{
-       struct pci_driver *imc_drv = imc_uncore_find_dev();
-
-       if (!imc_drv)
-               return -ENODEV;
-
-       uncore_pci_uncores = snb_pci_uncores;
-       uncore_pci_driver = imc_drv;
-
-       return 0;
-}
-
-int snb_uncore_pci_init(void)
-{
-       return imc_uncore_pci_init();
-}
-
-int ivb_uncore_pci_init(void)
-{
-       return imc_uncore_pci_init();
-}
-int hsw_uncore_pci_init(void)
-{
-       return imc_uncore_pci_init();
-}
-
-int bdw_uncore_pci_init(void)
-{
-       return imc_uncore_pci_init();
-}
-
-int skl_uncore_pci_init(void)
-{
-       return imc_uncore_pci_init();
-}
-
-/* end of Sandy Bridge uncore support */
-
-/* Nehalem uncore support */
-static void nhm_uncore_msr_disable_box(struct intel_uncore_box *box)
-{
-       wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, 0);
-}
-
-static void nhm_uncore_msr_enable_box(struct intel_uncore_box *box)
-{
-       wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, NHM_UNC_GLOBAL_CTL_EN_PC_ALL | NHM_UNC_GLOBAL_CTL_EN_FC);
-}
-
-static void nhm_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       if (hwc->idx < UNCORE_PMC_IDX_FIXED)
-               wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
-       else
-               wrmsrl(hwc->config_base, NHM_UNC_FIXED_CTR_CTL_EN);
-}
-
-static struct attribute *nhm_uncore_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_cmask8.attr,
-       NULL,
-};
-
-static struct attribute_group nhm_uncore_format_group = {
-       .name = "format",
-       .attrs = nhm_uncore_formats_attr,
-};
-
-static struct uncore_event_desc nhm_uncore_events[] = {
-       INTEL_UNCORE_EVENT_DESC(clockticks,                "event=0xff,umask=0x00"),
-       INTEL_UNCORE_EVENT_DESC(qmc_writes_full_any,       "event=0x2f,umask=0x0f"),
-       INTEL_UNCORE_EVENT_DESC(qmc_normal_reads_any,      "event=0x2c,umask=0x0f"),
-       INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_reads,     "event=0x20,umask=0x01"),
-       INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_writes,    "event=0x20,umask=0x02"),
-       INTEL_UNCORE_EVENT_DESC(qhl_request_remote_reads,  "event=0x20,umask=0x04"),
-       INTEL_UNCORE_EVENT_DESC(qhl_request_remote_writes, "event=0x20,umask=0x08"),
-       INTEL_UNCORE_EVENT_DESC(qhl_request_local_reads,   "event=0x20,umask=0x10"),
-       INTEL_UNCORE_EVENT_DESC(qhl_request_local_writes,  "event=0x20,umask=0x20"),
-       { /* end: all zeroes */ },
-};
-
-static struct intel_uncore_ops nhm_uncore_msr_ops = {
-       .disable_box    = nhm_uncore_msr_disable_box,
-       .enable_box     = nhm_uncore_msr_enable_box,
-       .disable_event  = snb_uncore_msr_disable_event,
-       .enable_event   = nhm_uncore_msr_enable_event,
-       .read_counter   = uncore_msr_read_counter,
-};
-
-static struct intel_uncore_type nhm_uncore = {
-       .name           = "",
-       .num_counters   = 8,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 48,
-       .fixed_ctr_bits = 48,
-       .event_ctl      = NHM_UNC_PERFEVTSEL0,
-       .perf_ctr       = NHM_UNC_UNCORE_PMC0,
-       .fixed_ctr      = NHM_UNC_FIXED_CTR,
-       .fixed_ctl      = NHM_UNC_FIXED_CTR_CTRL,
-       .event_mask     = NHM_UNC_RAW_EVENT_MASK,
-       .event_descs    = nhm_uncore_events,
-       .ops            = &nhm_uncore_msr_ops,
-       .format_group   = &nhm_uncore_format_group,
-};
-
-static struct intel_uncore_type *nhm_msr_uncores[] = {
-       &nhm_uncore,
-       NULL,
-};
-
-void nhm_uncore_cpu_init(void)
-{
-       uncore_msr_uncores = nhm_msr_uncores;
-}
-
-/* end of Nehalem uncore support */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
deleted file mode 100644 (file)
index 33acb88..0000000
+++ /dev/null
@@ -1,3126 +0,0 @@
-/* SandyBridge-EP/IvyTown uncore support */
-#include "perf_event_intel_uncore.h"
-
-
-/* SNB-EP Box level control */
-#define SNBEP_PMON_BOX_CTL_RST_CTRL    (1 << 0)
-#define SNBEP_PMON_BOX_CTL_RST_CTRS    (1 << 1)
-#define SNBEP_PMON_BOX_CTL_FRZ         (1 << 8)
-#define SNBEP_PMON_BOX_CTL_FRZ_EN      (1 << 16)
-#define SNBEP_PMON_BOX_CTL_INT         (SNBEP_PMON_BOX_CTL_RST_CTRL | \
-                                        SNBEP_PMON_BOX_CTL_RST_CTRS | \
-                                        SNBEP_PMON_BOX_CTL_FRZ_EN)
-/* SNB-EP event control */
-#define SNBEP_PMON_CTL_EV_SEL_MASK     0x000000ff
-#define SNBEP_PMON_CTL_UMASK_MASK      0x0000ff00
-#define SNBEP_PMON_CTL_RST             (1 << 17)
-#define SNBEP_PMON_CTL_EDGE_DET                (1 << 18)
-#define SNBEP_PMON_CTL_EV_SEL_EXT      (1 << 21)
-#define SNBEP_PMON_CTL_EN              (1 << 22)
-#define SNBEP_PMON_CTL_INVERT          (1 << 23)
-#define SNBEP_PMON_CTL_TRESH_MASK      0xff000000
-#define SNBEP_PMON_RAW_EVENT_MASK      (SNBEP_PMON_CTL_EV_SEL_MASK | \
-                                        SNBEP_PMON_CTL_UMASK_MASK | \
-                                        SNBEP_PMON_CTL_EDGE_DET | \
-                                        SNBEP_PMON_CTL_INVERT | \
-                                        SNBEP_PMON_CTL_TRESH_MASK)
-
-/* SNB-EP Ubox event control */
-#define SNBEP_U_MSR_PMON_CTL_TRESH_MASK                0x1f000000
-#define SNBEP_U_MSR_PMON_RAW_EVENT_MASK                \
-                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
-                                SNBEP_PMON_CTL_UMASK_MASK | \
-                                SNBEP_PMON_CTL_EDGE_DET | \
-                                SNBEP_PMON_CTL_INVERT | \
-                                SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
-
-#define SNBEP_CBO_PMON_CTL_TID_EN              (1 << 19)
-#define SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK      (SNBEP_PMON_RAW_EVENT_MASK | \
-                                                SNBEP_CBO_PMON_CTL_TID_EN)
-
-/* SNB-EP PCU event control */
-#define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK    0x0000c000
-#define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK      0x1f000000
-#define SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT      (1 << 30)
-#define SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET    (1 << 31)
-#define SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK      \
-                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
-                                SNBEP_PMON_CTL_EDGE_DET | \
-                                SNBEP_PMON_CTL_EV_SEL_EXT | \
-                                SNBEP_PMON_CTL_INVERT | \
-                                SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
-
-#define SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK      \
-                               (SNBEP_PMON_RAW_EVENT_MASK | \
-                                SNBEP_PMON_CTL_EV_SEL_EXT)
-
-/* SNB-EP pci control register */
-#define SNBEP_PCI_PMON_BOX_CTL                 0xf4
-#define SNBEP_PCI_PMON_CTL0                    0xd8
-/* SNB-EP pci counter register */
-#define SNBEP_PCI_PMON_CTR0                    0xa0
-
-/* SNB-EP home agent register */
-#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH0       0x40
-#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH1       0x44
-#define SNBEP_HA_PCI_PMON_BOX_OPCODEMATCH      0x48
-/* SNB-EP memory controller register */
-#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTL                0xf0
-#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTR                0xd0
-/* SNB-EP QPI register */
-#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH0         0x228
-#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH1         0x22c
-#define SNBEP_Q_Py_PCI_PMON_PKT_MASK0          0x238
-#define SNBEP_Q_Py_PCI_PMON_PKT_MASK1          0x23c
-
-/* SNB-EP Ubox register */
-#define SNBEP_U_MSR_PMON_CTR0                  0xc16
-#define SNBEP_U_MSR_PMON_CTL0                  0xc10
-
-#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTL                0xc08
-#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTR                0xc09
-
-/* SNB-EP Cbo register */
-#define SNBEP_C0_MSR_PMON_CTR0                 0xd16
-#define SNBEP_C0_MSR_PMON_CTL0                 0xd10
-#define SNBEP_C0_MSR_PMON_BOX_CTL              0xd04
-#define SNBEP_C0_MSR_PMON_BOX_FILTER           0xd14
-#define SNBEP_CBO_MSR_OFFSET                   0x20
-
-#define SNBEP_CB0_MSR_PMON_BOX_FILTER_TID      0x1f
-#define SNBEP_CB0_MSR_PMON_BOX_FILTER_NID      0x3fc00
-#define SNBEP_CB0_MSR_PMON_BOX_FILTER_STATE    0x7c0000
-#define SNBEP_CB0_MSR_PMON_BOX_FILTER_OPC      0xff800000
-
-#define SNBEP_CBO_EVENT_EXTRA_REG(e, m, i) {   \
-       .event = (e),                           \
-       .msr = SNBEP_C0_MSR_PMON_BOX_FILTER,    \
-       .config_mask = (m),                     \
-       .idx = (i)                              \
-}
-
-/* SNB-EP PCU register */
-#define SNBEP_PCU_MSR_PMON_CTR0                        0xc36
-#define SNBEP_PCU_MSR_PMON_CTL0                        0xc30
-#define SNBEP_PCU_MSR_PMON_BOX_CTL             0xc24
-#define SNBEP_PCU_MSR_PMON_BOX_FILTER          0xc34
-#define SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK     0xffffffff
-#define SNBEP_PCU_MSR_CORE_C3_CTR              0x3fc
-#define SNBEP_PCU_MSR_CORE_C6_CTR              0x3fd
-
-/* IVBEP event control */
-#define IVBEP_PMON_BOX_CTL_INT         (SNBEP_PMON_BOX_CTL_RST_CTRL | \
-                                        SNBEP_PMON_BOX_CTL_RST_CTRS)
-#define IVBEP_PMON_RAW_EVENT_MASK              (SNBEP_PMON_CTL_EV_SEL_MASK | \
-                                        SNBEP_PMON_CTL_UMASK_MASK | \
-                                        SNBEP_PMON_CTL_EDGE_DET | \
-                                        SNBEP_PMON_CTL_TRESH_MASK)
-/* IVBEP Ubox */
-#define IVBEP_U_MSR_PMON_GLOBAL_CTL            0xc00
-#define IVBEP_U_PMON_GLOBAL_FRZ_ALL            (1 << 31)
-#define IVBEP_U_PMON_GLOBAL_UNFRZ_ALL          (1 << 29)
-
-#define IVBEP_U_MSR_PMON_RAW_EVENT_MASK        \
-                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
-                                SNBEP_PMON_CTL_UMASK_MASK | \
-                                SNBEP_PMON_CTL_EDGE_DET | \
-                                SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
-/* IVBEP Cbo */
-#define IVBEP_CBO_MSR_PMON_RAW_EVENT_MASK              (IVBEP_PMON_RAW_EVENT_MASK | \
-                                                SNBEP_CBO_PMON_CTL_TID_EN)
-
-#define IVBEP_CB0_MSR_PMON_BOX_FILTER_TID              (0x1fULL << 0)
-#define IVBEP_CB0_MSR_PMON_BOX_FILTER_LINK     (0xfULL << 5)
-#define IVBEP_CB0_MSR_PMON_BOX_FILTER_STATE    (0x3fULL << 17)
-#define IVBEP_CB0_MSR_PMON_BOX_FILTER_NID              (0xffffULL << 32)
-#define IVBEP_CB0_MSR_PMON_BOX_FILTER_OPC              (0x1ffULL << 52)
-#define IVBEP_CB0_MSR_PMON_BOX_FILTER_C6               (0x1ULL << 61)
-#define IVBEP_CB0_MSR_PMON_BOX_FILTER_NC               (0x1ULL << 62)
-#define IVBEP_CB0_MSR_PMON_BOX_FILTER_ISOC     (0x1ULL << 63)
-
-/* IVBEP home agent */
-#define IVBEP_HA_PCI_PMON_CTL_Q_OCC_RST                (1 << 16)
-#define IVBEP_HA_PCI_PMON_RAW_EVENT_MASK               \
-                               (IVBEP_PMON_RAW_EVENT_MASK | \
-                                IVBEP_HA_PCI_PMON_CTL_Q_OCC_RST)
-/* IVBEP PCU */
-#define IVBEP_PCU_MSR_PMON_RAW_EVENT_MASK      \
-                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
-                                SNBEP_PMON_CTL_EV_SEL_EXT | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
-                                SNBEP_PMON_CTL_EDGE_DET | \
-                                SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
-/* IVBEP QPI */
-#define IVBEP_QPI_PCI_PMON_RAW_EVENT_MASK      \
-                               (IVBEP_PMON_RAW_EVENT_MASK | \
-                                SNBEP_PMON_CTL_EV_SEL_EXT)
-
-#define __BITS_VALUE(x, i, n)  ((typeof(x))(((x) >> ((i) * (n))) & \
-                               ((1ULL << (n)) - 1)))
-
-/* Haswell-EP Ubox */
-#define HSWEP_U_MSR_PMON_CTR0                  0x709
-#define HSWEP_U_MSR_PMON_CTL0                  0x705
-#define HSWEP_U_MSR_PMON_FILTER                        0x707
-
-#define HSWEP_U_MSR_PMON_UCLK_FIXED_CTL                0x703
-#define HSWEP_U_MSR_PMON_UCLK_FIXED_CTR                0x704
-
-#define HSWEP_U_MSR_PMON_BOX_FILTER_TID                (0x1 << 0)
-#define HSWEP_U_MSR_PMON_BOX_FILTER_CID                (0x1fULL << 1)
-#define HSWEP_U_MSR_PMON_BOX_FILTER_MASK \
-                                       (HSWEP_U_MSR_PMON_BOX_FILTER_TID | \
-                                        HSWEP_U_MSR_PMON_BOX_FILTER_CID)
-
-/* Haswell-EP CBo */
-#define HSWEP_C0_MSR_PMON_CTR0                 0xe08
-#define HSWEP_C0_MSR_PMON_CTL0                 0xe01
-#define HSWEP_C0_MSR_PMON_BOX_CTL                      0xe00
-#define HSWEP_C0_MSR_PMON_BOX_FILTER0          0xe05
-#define HSWEP_CBO_MSR_OFFSET                   0x10
-
-
-#define HSWEP_CB0_MSR_PMON_BOX_FILTER_TID              (0x3fULL << 0)
-#define HSWEP_CB0_MSR_PMON_BOX_FILTER_LINK     (0xfULL << 6)
-#define HSWEP_CB0_MSR_PMON_BOX_FILTER_STATE    (0x7fULL << 17)
-#define HSWEP_CB0_MSR_PMON_BOX_FILTER_NID              (0xffffULL << 32)
-#define HSWEP_CB0_MSR_PMON_BOX_FILTER_OPC              (0x1ffULL << 52)
-#define HSWEP_CB0_MSR_PMON_BOX_FILTER_C6               (0x1ULL << 61)
-#define HSWEP_CB0_MSR_PMON_BOX_FILTER_NC               (0x1ULL << 62)
-#define HSWEP_CB0_MSR_PMON_BOX_FILTER_ISOC     (0x1ULL << 63)
-
-
-/* Haswell-EP Sbox */
-#define HSWEP_S0_MSR_PMON_CTR0                 0x726
-#define HSWEP_S0_MSR_PMON_CTL0                 0x721
-#define HSWEP_S0_MSR_PMON_BOX_CTL                      0x720
-#define HSWEP_SBOX_MSR_OFFSET                  0xa
-#define HSWEP_S_MSR_PMON_RAW_EVENT_MASK                (SNBEP_PMON_RAW_EVENT_MASK | \
-                                                SNBEP_CBO_PMON_CTL_TID_EN)
-
-/* Haswell-EP PCU */
-#define HSWEP_PCU_MSR_PMON_CTR0                        0x717
-#define HSWEP_PCU_MSR_PMON_CTL0                        0x711
-#define HSWEP_PCU_MSR_PMON_BOX_CTL             0x710
-#define HSWEP_PCU_MSR_PMON_BOX_FILTER          0x715
-
-/* KNL Ubox */
-#define KNL_U_MSR_PMON_RAW_EVENT_MASK \
-                                       (SNBEP_U_MSR_PMON_RAW_EVENT_MASK | \
-                                               SNBEP_CBO_PMON_CTL_TID_EN)
-/* KNL CHA */
-#define KNL_CHA_MSR_OFFSET                     0xc
-#define KNL_CHA_MSR_PMON_CTL_QOR               (1 << 16)
-#define KNL_CHA_MSR_PMON_RAW_EVENT_MASK \
-                                       (SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK | \
-                                        KNL_CHA_MSR_PMON_CTL_QOR)
-#define KNL_CHA_MSR_PMON_BOX_FILTER_TID                0x1ff
-#define KNL_CHA_MSR_PMON_BOX_FILTER_STATE      (7 << 18)
-#define KNL_CHA_MSR_PMON_BOX_FILTER_OP         (0xfffffe2aULL << 32)
-
-/* KNL EDC/MC UCLK */
-#define KNL_UCLK_MSR_PMON_CTR0_LOW             0x400
-#define KNL_UCLK_MSR_PMON_CTL0                 0x420
-#define KNL_UCLK_MSR_PMON_BOX_CTL              0x430
-#define KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW       0x44c
-#define KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL       0x454
-#define KNL_PMON_FIXED_CTL_EN                  0x1
-
-/* KNL EDC */
-#define KNL_EDC0_ECLK_MSR_PMON_CTR0_LOW                0xa00
-#define KNL_EDC0_ECLK_MSR_PMON_CTL0            0xa20
-#define KNL_EDC0_ECLK_MSR_PMON_BOX_CTL         0xa30
-#define KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_LOW  0xa3c
-#define KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_CTL  0xa44
-
-/* KNL MC */
-#define KNL_MC0_CH0_MSR_PMON_CTR0_LOW          0xb00
-#define KNL_MC0_CH0_MSR_PMON_CTL0              0xb20
-#define KNL_MC0_CH0_MSR_PMON_BOX_CTL           0xb30
-#define KNL_MC0_CH0_MSR_PMON_FIXED_LOW         0xb3c
-#define KNL_MC0_CH0_MSR_PMON_FIXED_CTL         0xb44
-
-/* KNL IRP */
-#define KNL_IRP_PCI_PMON_BOX_CTL               0xf0
-#define KNL_IRP_PCI_PMON_RAW_EVENT_MASK                (SNBEP_PMON_RAW_EVENT_MASK | \
-                                                KNL_CHA_MSR_PMON_CTL_QOR)
-/* KNL PCU */
-#define KNL_PCU_PMON_CTL_EV_SEL_MASK           0x0000007f
-#define KNL_PCU_PMON_CTL_USE_OCC_CTR           (1 << 7)
-#define KNL_PCU_MSR_PMON_CTL_TRESH_MASK                0x3f000000
-#define KNL_PCU_MSR_PMON_RAW_EVENT_MASK        \
-                               (KNL_PCU_PMON_CTL_EV_SEL_MASK | \
-                                KNL_PCU_PMON_CTL_USE_OCC_CTR | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
-                                SNBEP_PMON_CTL_EDGE_DET | \
-                                SNBEP_CBO_PMON_CTL_TID_EN | \
-                                SNBEP_PMON_CTL_EV_SEL_EXT | \
-                                SNBEP_PMON_CTL_INVERT | \
-                                KNL_PCU_MSR_PMON_CTL_TRESH_MASK | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
-                                SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
-
-DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
-DEFINE_UNCORE_FORMAT_ATTR(event2, event, "config:0-6");
-DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21");
-DEFINE_UNCORE_FORMAT_ATTR(use_occ_ctr, use_occ_ctr, "config:7");
-DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
-DEFINE_UNCORE_FORMAT_ATTR(qor, qor, "config:16");
-DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
-DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19");
-DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
-DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
-DEFINE_UNCORE_FORMAT_ATTR(thresh6, thresh, "config:24-29");
-DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28");
-DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15");
-DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30");
-DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51");
-DEFINE_UNCORE_FORMAT_ATTR(occ_edge_det, occ_edge_det, "config:31");
-DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4");
-DEFINE_UNCORE_FORMAT_ATTR(filter_tid2, filter_tid, "config1:0");
-DEFINE_UNCORE_FORMAT_ATTR(filter_tid3, filter_tid, "config1:0-5");
-DEFINE_UNCORE_FORMAT_ATTR(filter_tid4, filter_tid, "config1:0-8");
-DEFINE_UNCORE_FORMAT_ATTR(filter_cid, filter_cid, "config1:5");
-DEFINE_UNCORE_FORMAT_ATTR(filter_link, filter_link, "config1:5-8");
-DEFINE_UNCORE_FORMAT_ATTR(filter_link2, filter_link, "config1:6-8");
-DEFINE_UNCORE_FORMAT_ATTR(filter_link3, filter_link, "config1:12");
-DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17");
-DEFINE_UNCORE_FORMAT_ATTR(filter_nid2, filter_nid, "config1:32-47");
-DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22");
-DEFINE_UNCORE_FORMAT_ATTR(filter_state2, filter_state, "config1:17-22");
-DEFINE_UNCORE_FORMAT_ATTR(filter_state3, filter_state, "config1:17-23");
-DEFINE_UNCORE_FORMAT_ATTR(filter_state4, filter_state, "config1:18-20");
-DEFINE_UNCORE_FORMAT_ATTR(filter_local, filter_local, "config1:33");
-DEFINE_UNCORE_FORMAT_ATTR(filter_all_op, filter_all_op, "config1:35");
-DEFINE_UNCORE_FORMAT_ATTR(filter_nnm, filter_nnm, "config1:37");
-DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31");
-DEFINE_UNCORE_FORMAT_ATTR(filter_opc2, filter_opc, "config1:52-60");
-DEFINE_UNCORE_FORMAT_ATTR(filter_opc3, filter_opc, "config1:41-60");
-DEFINE_UNCORE_FORMAT_ATTR(filter_nc, filter_nc, "config1:62");
-DEFINE_UNCORE_FORMAT_ATTR(filter_c6, filter_c6, "config1:61");
-DEFINE_UNCORE_FORMAT_ATTR(filter_isoc, filter_isoc, "config1:63");
-DEFINE_UNCORE_FORMAT_ATTR(filter_band0, filter_band0, "config1:0-7");
-DEFINE_UNCORE_FORMAT_ATTR(filter_band1, filter_band1, "config1:8-15");
-DEFINE_UNCORE_FORMAT_ATTR(filter_band2, filter_band2, "config1:16-23");
-DEFINE_UNCORE_FORMAT_ATTR(filter_band3, filter_band3, "config1:24-31");
-DEFINE_UNCORE_FORMAT_ATTR(match_rds, match_rds, "config1:48-51");
-DEFINE_UNCORE_FORMAT_ATTR(match_rnid30, match_rnid30, "config1:32-35");
-DEFINE_UNCORE_FORMAT_ATTR(match_rnid4, match_rnid4, "config1:31");
-DEFINE_UNCORE_FORMAT_ATTR(match_dnid, match_dnid, "config1:13-17");
-DEFINE_UNCORE_FORMAT_ATTR(match_mc, match_mc, "config1:9-12");
-DEFINE_UNCORE_FORMAT_ATTR(match_opc, match_opc, "config1:5-8");
-DEFINE_UNCORE_FORMAT_ATTR(match_vnw, match_vnw, "config1:3-4");
-DEFINE_UNCORE_FORMAT_ATTR(match0, match0, "config1:0-31");
-DEFINE_UNCORE_FORMAT_ATTR(match1, match1, "config1:32-63");
-DEFINE_UNCORE_FORMAT_ATTR(mask_rds, mask_rds, "config2:48-51");
-DEFINE_UNCORE_FORMAT_ATTR(mask_rnid30, mask_rnid30, "config2:32-35");
-DEFINE_UNCORE_FORMAT_ATTR(mask_rnid4, mask_rnid4, "config2:31");
-DEFINE_UNCORE_FORMAT_ATTR(mask_dnid, mask_dnid, "config2:13-17");
-DEFINE_UNCORE_FORMAT_ATTR(mask_mc, mask_mc, "config2:9-12");
-DEFINE_UNCORE_FORMAT_ATTR(mask_opc, mask_opc, "config2:5-8");
-DEFINE_UNCORE_FORMAT_ATTR(mask_vnw, mask_vnw, "config2:3-4");
-DEFINE_UNCORE_FORMAT_ATTR(mask0, mask0, "config2:0-31");
-DEFINE_UNCORE_FORMAT_ATTR(mask1, mask1, "config2:32-63");
-
-static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       int box_ctl = uncore_pci_box_ctl(box);
-       u32 config = 0;
-
-       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
-               config |= SNBEP_PMON_BOX_CTL_FRZ;
-               pci_write_config_dword(pdev, box_ctl, config);
-       }
-}
-
-static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       int box_ctl = uncore_pci_box_ctl(box);
-       u32 config = 0;
-
-       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
-               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
-               pci_write_config_dword(pdev, box_ctl, config);
-       }
-}
-
-static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-
-       pci_write_config_dword(pdev, hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
-}
-
-static void snbep_uncore_pci_disable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-
-       pci_write_config_dword(pdev, hwc->config_base, hwc->config);
-}
-
-static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-       u64 count = 0;
-
-       pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
-       pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
-
-       return count;
-}
-
-static void snbep_uncore_pci_init_box(struct intel_uncore_box *box)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       int box_ctl = uncore_pci_box_ctl(box);
-
-       pci_write_config_dword(pdev, box_ctl, SNBEP_PMON_BOX_CTL_INT);
-}
-
-static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box)
-{
-       u64 config;
-       unsigned msr;
-
-       msr = uncore_msr_box_ctl(box);
-       if (msr) {
-               rdmsrl(msr, config);
-               config |= SNBEP_PMON_BOX_CTL_FRZ;
-               wrmsrl(msr, config);
-       }
-}
-
-static void snbep_uncore_msr_enable_box(struct intel_uncore_box *box)
-{
-       u64 config;
-       unsigned msr;
-
-       msr = uncore_msr_box_ctl(box);
-       if (msr) {
-               rdmsrl(msr, config);
-               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
-               wrmsrl(msr, config);
-       }
-}
-
-static void snbep_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-
-       if (reg1->idx != EXTRA_REG_NONE)
-               wrmsrl(reg1->reg, uncore_shared_reg_config(box, 0));
-
-       wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
-}
-
-static void snbep_uncore_msr_disable_event(struct intel_uncore_box *box,
-                                       struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       wrmsrl(hwc->config_base, hwc->config);
-}
-
-static void snbep_uncore_msr_init_box(struct intel_uncore_box *box)
-{
-       unsigned msr = uncore_msr_box_ctl(box);
-
-       if (msr)
-               wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT);
-}
-
-static struct attribute *snbep_uncore_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       NULL,
-};
-
-static struct attribute *snbep_uncore_ubox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh5.attr,
-       NULL,
-};
-
-static struct attribute *snbep_uncore_cbox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_tid_en.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       &format_attr_filter_tid.attr,
-       &format_attr_filter_nid.attr,
-       &format_attr_filter_state.attr,
-       &format_attr_filter_opc.attr,
-       NULL,
-};
-
-static struct attribute *snbep_uncore_pcu_formats_attr[] = {
-       &format_attr_event_ext.attr,
-       &format_attr_occ_sel.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh5.attr,
-       &format_attr_occ_invert.attr,
-       &format_attr_occ_edge.attr,
-       &format_attr_filter_band0.attr,
-       &format_attr_filter_band1.attr,
-       &format_attr_filter_band2.attr,
-       &format_attr_filter_band3.attr,
-       NULL,
-};
-
-static struct attribute *snbep_uncore_qpi_formats_attr[] = {
-       &format_attr_event_ext.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       &format_attr_match_rds.attr,
-       &format_attr_match_rnid30.attr,
-       &format_attr_match_rnid4.attr,
-       &format_attr_match_dnid.attr,
-       &format_attr_match_mc.attr,
-       &format_attr_match_opc.attr,
-       &format_attr_match_vnw.attr,
-       &format_attr_match0.attr,
-       &format_attr_match1.attr,
-       &format_attr_mask_rds.attr,
-       &format_attr_mask_rnid30.attr,
-       &format_attr_mask_rnid4.attr,
-       &format_attr_mask_dnid.attr,
-       &format_attr_mask_mc.attr,
-       &format_attr_mask_opc.attr,
-       &format_attr_mask_vnw.attr,
-       &format_attr_mask0.attr,
-       &format_attr_mask1.attr,
-       NULL,
-};
-
-static struct uncore_event_desc snbep_uncore_imc_events[] = {
-       INTEL_UNCORE_EVENT_DESC(clockticks,      "event=0xff,umask=0x00"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_read,  "event=0x04,umask=0x03"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_read.scale, "6.103515625e-5"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_read.unit, "MiB"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_write.scale, "6.103515625e-5"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_write.unit, "MiB"),
-       { /* end: all zeroes */ },
-};
-
-static struct uncore_event_desc snbep_uncore_qpi_events[] = {
-       INTEL_UNCORE_EVENT_DESC(clockticks,       "event=0x14"),
-       INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
-       INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x102,umask=0x08"),
-       INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x103,umask=0x04"),
-       { /* end: all zeroes */ },
-};
-
-static struct attribute_group snbep_uncore_format_group = {
-       .name = "format",
-       .attrs = snbep_uncore_formats_attr,
-};
-
-static struct attribute_group snbep_uncore_ubox_format_group = {
-       .name = "format",
-       .attrs = snbep_uncore_ubox_formats_attr,
-};
-
-static struct attribute_group snbep_uncore_cbox_format_group = {
-       .name = "format",
-       .attrs = snbep_uncore_cbox_formats_attr,
-};
-
-static struct attribute_group snbep_uncore_pcu_format_group = {
-       .name = "format",
-       .attrs = snbep_uncore_pcu_formats_attr,
-};
-
-static struct attribute_group snbep_uncore_qpi_format_group = {
-       .name = "format",
-       .attrs = snbep_uncore_qpi_formats_attr,
-};
-
-#define __SNBEP_UNCORE_MSR_OPS_COMMON_INIT()                   \
-       .disable_box    = snbep_uncore_msr_disable_box,         \
-       .enable_box     = snbep_uncore_msr_enable_box,          \
-       .disable_event  = snbep_uncore_msr_disable_event,       \
-       .enable_event   = snbep_uncore_msr_enable_event,        \
-       .read_counter   = uncore_msr_read_counter
-
-#define SNBEP_UNCORE_MSR_OPS_COMMON_INIT()                     \
-       __SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),                   \
-       .init_box       = snbep_uncore_msr_init_box             \
-
-static struct intel_uncore_ops snbep_uncore_msr_ops = {
-       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
-};
-
-#define SNBEP_UNCORE_PCI_OPS_COMMON_INIT()                     \
-       .init_box       = snbep_uncore_pci_init_box,            \
-       .disable_box    = snbep_uncore_pci_disable_box,         \
-       .enable_box     = snbep_uncore_pci_enable_box,          \
-       .disable_event  = snbep_uncore_pci_disable_event,       \
-       .read_counter   = snbep_uncore_pci_read_counter
-
-static struct intel_uncore_ops snbep_uncore_pci_ops = {
-       SNBEP_UNCORE_PCI_OPS_COMMON_INIT(),
-       .enable_event   = snbep_uncore_pci_enable_event,        \
-};
-
-static struct event_constraint snbep_uncore_cbox_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x02, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x04, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x05, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x07, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x09, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x13, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x1b, 0xc),
-       UNCORE_EVENT_CONSTRAINT(0x1c, 0xc),
-       UNCORE_EVENT_CONSTRAINT(0x1d, 0xc),
-       UNCORE_EVENT_CONSTRAINT(0x1e, 0xc),
-       EVENT_CONSTRAINT_OVERLAP(0x1f, 0xe, 0xff),
-       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
-       EVENT_CONSTRAINT_END
-};
-
-static struct event_constraint snbep_uncore_r2pcie_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x12, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
-       EVENT_CONSTRAINT_END
-};
-
-static struct event_constraint snbep_uncore_r3qpi_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2a, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2b, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x30, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
-       EVENT_CONSTRAINT_END
-};
-
-static struct intel_uncore_type snbep_uncore_ubox = {
-       .name           = "ubox",
-       .num_counters   = 2,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 44,
-       .fixed_ctr_bits = 48,
-       .perf_ctr       = SNBEP_U_MSR_PMON_CTR0,
-       .event_ctl      = SNBEP_U_MSR_PMON_CTL0,
-       .event_mask     = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
-       .fixed_ctr      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
-       .fixed_ctl      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
-       .ops            = &snbep_uncore_msr_ops,
-       .format_group   = &snbep_uncore_ubox_format_group,
-};
-
-static struct extra_reg snbep_uncore_cbox_extra_regs[] = {
-       SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
-                                 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0xa),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0xa),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0xa),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0xa),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x2),
-       EVENT_EXTRA_END
-};
-
-static void snbep_cbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct intel_uncore_extra_reg *er = &box->shared_regs[0];
-       int i;
-
-       if (uncore_box_is_fake(box))
-               return;
-
-       for (i = 0; i < 5; i++) {
-               if (reg1->alloc & (0x1 << i))
-                       atomic_sub(1 << (i * 6), &er->ref);
-       }
-       reg1->alloc = 0;
-}
-
-static struct event_constraint *
-__snbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event,
-                           u64 (*cbox_filter_mask)(int fields))
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct intel_uncore_extra_reg *er = &box->shared_regs[0];
-       int i, alloc = 0;
-       unsigned long flags;
-       u64 mask;
-
-       if (reg1->idx == EXTRA_REG_NONE)
-               return NULL;
-
-       raw_spin_lock_irqsave(&er->lock, flags);
-       for (i = 0; i < 5; i++) {
-               if (!(reg1->idx & (0x1 << i)))
-                       continue;
-               if (!uncore_box_is_fake(box) && (reg1->alloc & (0x1 << i)))
-                       continue;
-
-               mask = cbox_filter_mask(0x1 << i);
-               if (!__BITS_VALUE(atomic_read(&er->ref), i, 6) ||
-                   !((reg1->config ^ er->config) & mask)) {
-                       atomic_add(1 << (i * 6), &er->ref);
-                       er->config &= ~mask;
-                       er->config |= reg1->config & mask;
-                       alloc |= (0x1 << i);
-               } else {
-                       break;
-               }
-       }
-       raw_spin_unlock_irqrestore(&er->lock, flags);
-       if (i < 5)
-               goto fail;
-
-       if (!uncore_box_is_fake(box))
-               reg1->alloc |= alloc;
-
-       return NULL;
-fail:
-       for (; i >= 0; i--) {
-               if (alloc & (0x1 << i))
-                       atomic_sub(1 << (i * 6), &er->ref);
-       }
-       return &uncore_constraint_empty;
-}
-
-static u64 snbep_cbox_filter_mask(int fields)
-{
-       u64 mask = 0;
-
-       if (fields & 0x1)
-               mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_TID;
-       if (fields & 0x2)
-               mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_NID;
-       if (fields & 0x4)
-               mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_STATE;
-       if (fields & 0x8)
-               mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_OPC;
-
-       return mask;
-}
-
-static struct event_constraint *
-snbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       return __snbep_cbox_get_constraint(box, event, snbep_cbox_filter_mask);
-}
-
-static int snbep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct extra_reg *er;
-       int idx = 0;
-
-       for (er = snbep_uncore_cbox_extra_regs; er->msr; er++) {
-               if (er->event != (event->hw.config & er->config_mask))
-                       continue;
-               idx |= er->idx;
-       }
-
-       if (idx) {
-               reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
-                       SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
-               reg1->config = event->attr.config1 & snbep_cbox_filter_mask(idx);
-               reg1->idx = idx;
-       }
-       return 0;
-}
-
-static struct intel_uncore_ops snbep_uncore_cbox_ops = {
-       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
-       .hw_config              = snbep_cbox_hw_config,
-       .get_constraint         = snbep_cbox_get_constraint,
-       .put_constraint         = snbep_cbox_put_constraint,
-};
-
-static struct intel_uncore_type snbep_uncore_cbox = {
-       .name                   = "cbox",
-       .num_counters           = 4,
-       .num_boxes              = 8,
-       .perf_ctr_bits          = 44,
-       .event_ctl              = SNBEP_C0_MSR_PMON_CTL0,
-       .perf_ctr               = SNBEP_C0_MSR_PMON_CTR0,
-       .event_mask             = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_C0_MSR_PMON_BOX_CTL,
-       .msr_offset             = SNBEP_CBO_MSR_OFFSET,
-       .num_shared_regs        = 1,
-       .constraints            = snbep_uncore_cbox_constraints,
-       .ops                    = &snbep_uncore_cbox_ops,
-       .format_group           = &snbep_uncore_cbox_format_group,
-};
-
-static u64 snbep_pcu_alter_er(struct perf_event *event, int new_idx, bool modify)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       u64 config = reg1->config;
-
-       if (new_idx > reg1->idx)
-               config <<= 8 * (new_idx - reg1->idx);
-       else
-               config >>= 8 * (reg1->idx - new_idx);
-
-       if (modify) {
-               hwc->config += new_idx - reg1->idx;
-               reg1->config = config;
-               reg1->idx = new_idx;
-       }
-       return config;
-}
-
-static struct event_constraint *
-snbep_pcu_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct intel_uncore_extra_reg *er = &box->shared_regs[0];
-       unsigned long flags;
-       int idx = reg1->idx;
-       u64 mask, config1 = reg1->config;
-       bool ok = false;
-
-       if (reg1->idx == EXTRA_REG_NONE ||
-           (!uncore_box_is_fake(box) && reg1->alloc))
-               return NULL;
-again:
-       mask = 0xffULL << (idx * 8);
-       raw_spin_lock_irqsave(&er->lock, flags);
-       if (!__BITS_VALUE(atomic_read(&er->ref), idx, 8) ||
-           !((config1 ^ er->config) & mask)) {
-               atomic_add(1 << (idx * 8), &er->ref);
-               er->config &= ~mask;
-               er->config |= config1 & mask;
-               ok = true;
-       }
-       raw_spin_unlock_irqrestore(&er->lock, flags);
-
-       if (!ok) {
-               idx = (idx + 1) % 4;
-               if (idx != reg1->idx) {
-                       config1 = snbep_pcu_alter_er(event, idx, false);
-                       goto again;
-               }
-               return &uncore_constraint_empty;
-       }
-
-       if (!uncore_box_is_fake(box)) {
-               if (idx != reg1->idx)
-                       snbep_pcu_alter_er(event, idx, true);
-               reg1->alloc = 1;
-       }
-       return NULL;
-}
-
-static void snbep_pcu_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct intel_uncore_extra_reg *er = &box->shared_regs[0];
-
-       if (uncore_box_is_fake(box) || !reg1->alloc)
-               return;
-
-       atomic_sub(1 << (reg1->idx * 8), &er->ref);
-       reg1->alloc = 0;
-}
-
-static int snbep_pcu_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       int ev_sel = hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK;
-
-       if (ev_sel >= 0xb && ev_sel <= 0xe) {
-               reg1->reg = SNBEP_PCU_MSR_PMON_BOX_FILTER;
-               reg1->idx = ev_sel - 0xb;
-               reg1->config = event->attr.config1 & (0xff << (reg1->idx * 8));
-       }
-       return 0;
-}
-
-static struct intel_uncore_ops snbep_uncore_pcu_ops = {
-       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
-       .hw_config              = snbep_pcu_hw_config,
-       .get_constraint         = snbep_pcu_get_constraint,
-       .put_constraint         = snbep_pcu_put_constraint,
-};
-
-static struct intel_uncore_type snbep_uncore_pcu = {
-       .name                   = "pcu",
-       .num_counters           = 4,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = SNBEP_PCU_MSR_PMON_CTR0,
-       .event_ctl              = SNBEP_PCU_MSR_PMON_CTL0,
-       .event_mask             = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCU_MSR_PMON_BOX_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &snbep_uncore_pcu_ops,
-       .format_group           = &snbep_uncore_pcu_format_group,
-};
-
-static struct intel_uncore_type *snbep_msr_uncores[] = {
-       &snbep_uncore_ubox,
-       &snbep_uncore_cbox,
-       &snbep_uncore_pcu,
-       NULL,
-};
-
-void snbep_uncore_cpu_init(void)
-{
-       if (snbep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
-               snbep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
-       uncore_msr_uncores = snbep_msr_uncores;
-}
-
-enum {
-       SNBEP_PCI_QPI_PORT0_FILTER,
-       SNBEP_PCI_QPI_PORT1_FILTER,
-       HSWEP_PCI_PCU_3,
-};
-
-static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-
-       if ((hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK) == 0x38) {
-               reg1->idx = 0;
-               reg1->reg = SNBEP_Q_Py_PCI_PMON_PKT_MATCH0;
-               reg1->config = event->attr.config1;
-               reg2->reg = SNBEP_Q_Py_PCI_PMON_PKT_MASK0;
-               reg2->config = event->attr.config2;
-       }
-       return 0;
-}
-
-static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
-
-       if (reg1->idx != EXTRA_REG_NONE) {
-               int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER;
-               struct pci_dev *filter_pdev = uncore_extra_pci_dev[box->phys_id][idx];
-               if (filter_pdev) {
-                       pci_write_config_dword(filter_pdev, reg1->reg,
-                                               (u32)reg1->config);
-                       pci_write_config_dword(filter_pdev, reg1->reg + 4,
-                                               (u32)(reg1->config >> 32));
-                       pci_write_config_dword(filter_pdev, reg2->reg,
-                                               (u32)reg2->config);
-                       pci_write_config_dword(filter_pdev, reg2->reg + 4,
-                                               (u32)(reg2->config >> 32));
-               }
-       }
-
-       pci_write_config_dword(pdev, hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
-}
-
-static struct intel_uncore_ops snbep_uncore_qpi_ops = {
-       SNBEP_UNCORE_PCI_OPS_COMMON_INIT(),
-       .enable_event           = snbep_qpi_enable_event,
-       .hw_config              = snbep_qpi_hw_config,
-       .get_constraint         = uncore_get_constraint,
-       .put_constraint         = uncore_put_constraint,
-};
-
-#define SNBEP_UNCORE_PCI_COMMON_INIT()                         \
-       .perf_ctr       = SNBEP_PCI_PMON_CTR0,                  \
-       .event_ctl      = SNBEP_PCI_PMON_CTL0,                  \
-       .event_mask     = SNBEP_PMON_RAW_EVENT_MASK,            \
-       .box_ctl        = SNBEP_PCI_PMON_BOX_CTL,               \
-       .ops            = &snbep_uncore_pci_ops,                \
-       .format_group   = &snbep_uncore_format_group
-
-static struct intel_uncore_type snbep_uncore_ha = {
-       .name           = "ha",
-       .num_counters   = 4,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 48,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct intel_uncore_type snbep_uncore_imc = {
-       .name           = "imc",
-       .num_counters   = 4,
-       .num_boxes      = 4,
-       .perf_ctr_bits  = 48,
-       .fixed_ctr_bits = 48,
-       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
-       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
-       .event_descs    = snbep_uncore_imc_events,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct intel_uncore_type snbep_uncore_qpi = {
-       .name                   = "qpi",
-       .num_counters           = 4,
-       .num_boxes              = 2,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
-       .event_ctl              = SNBEP_PCI_PMON_CTL0,
-       .event_mask             = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &snbep_uncore_qpi_ops,
-       .event_descs            = snbep_uncore_qpi_events,
-       .format_group           = &snbep_uncore_qpi_format_group,
-};
-
-
-static struct intel_uncore_type snbep_uncore_r2pcie = {
-       .name           = "r2pcie",
-       .num_counters   = 4,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 44,
-       .constraints    = snbep_uncore_r2pcie_constraints,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct intel_uncore_type snbep_uncore_r3qpi = {
-       .name           = "r3qpi",
-       .num_counters   = 3,
-       .num_boxes      = 2,
-       .perf_ctr_bits  = 44,
-       .constraints    = snbep_uncore_r3qpi_constraints,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-enum {
-       SNBEP_PCI_UNCORE_HA,
-       SNBEP_PCI_UNCORE_IMC,
-       SNBEP_PCI_UNCORE_QPI,
-       SNBEP_PCI_UNCORE_R2PCIE,
-       SNBEP_PCI_UNCORE_R3QPI,
-};
-
-static struct intel_uncore_type *snbep_pci_uncores[] = {
-       [SNBEP_PCI_UNCORE_HA]           = &snbep_uncore_ha,
-       [SNBEP_PCI_UNCORE_IMC]          = &snbep_uncore_imc,
-       [SNBEP_PCI_UNCORE_QPI]          = &snbep_uncore_qpi,
-       [SNBEP_PCI_UNCORE_R2PCIE]       = &snbep_uncore_r2pcie,
-       [SNBEP_PCI_UNCORE_R3QPI]        = &snbep_uncore_r3qpi,
-       NULL,
-};
-
-static const struct pci_device_id snbep_uncore_pci_ids[] = {
-       { /* Home Agent */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_HA, 0),
-       },
-       { /* MC Channel 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC0),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 0),
-       },
-       { /* MC Channel 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC1),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 1),
-       },
-       { /* MC Channel 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC2),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 2),
-       },
-       { /* MC Channel 3 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC3),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 3),
-       },
-       { /* QPI Port 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI0),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_QPI, 0),
-       },
-       { /* QPI Port 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI1),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_QPI, 1),
-       },
-       { /* R2PCIe */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R2PCIE),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R2PCIE, 0),
-       },
-       { /* R3QPI Link 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI0),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R3QPI, 0),
-       },
-       { /* R3QPI Link 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI1),
-               .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R3QPI, 1),
-       },
-       { /* QPI Port 0 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3c86),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-                                                  SNBEP_PCI_QPI_PORT0_FILTER),
-       },
-       { /* QPI Port 0 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3c96),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-                                                  SNBEP_PCI_QPI_PORT1_FILTER),
-       },
-       { /* end: all zeroes */ }
-};
-
-static struct pci_driver snbep_uncore_pci_driver = {
-       .name           = "snbep_uncore",
-       .id_table       = snbep_uncore_pci_ids,
-};
-
-/*
- * build pci bus to socket mapping
- */
-static int snbep_pci2phy_map_init(int devid)
-{
-       struct pci_dev *ubox_dev = NULL;
-       int i, bus, nodeid, segment;
-       struct pci2phy_map *map;
-       int err = 0;
-       u32 config = 0;
-
-       while (1) {
-               /* find the UBOX device */
-               ubox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, ubox_dev);
-               if (!ubox_dev)
-                       break;
-               bus = ubox_dev->bus->number;
-               /* get the Node ID of the local register */
-               err = pci_read_config_dword(ubox_dev, 0x40, &config);
-               if (err)
-                       break;
-               nodeid = config;
-               /* get the Node ID mapping */
-               err = pci_read_config_dword(ubox_dev, 0x54, &config);
-               if (err)
-                       break;
-
-               segment = pci_domain_nr(ubox_dev->bus);
-               raw_spin_lock(&pci2phy_map_lock);
-               map = __find_pci2phy_map(segment);
-               if (!map) {
-                       raw_spin_unlock(&pci2phy_map_lock);
-                       err = -ENOMEM;
-                       break;
-               }
-
-               /*
-                * every three bits in the Node ID mapping register maps
-                * to a particular node.
-                */
-               for (i = 0; i < 8; i++) {
-                       if (nodeid == ((config >> (3 * i)) & 0x7)) {
-                               map->pbus_to_physid[bus] = i;
-                               break;
-                       }
-               }
-               raw_spin_unlock(&pci2phy_map_lock);
-       }
-
-       if (!err) {
-               /*
-                * For PCI bus with no UBOX device, find the next bus
-                * that has UBOX device and use its mapping.
-                */
-               raw_spin_lock(&pci2phy_map_lock);
-               list_for_each_entry(map, &pci2phy_map_head, list) {
-                       i = -1;
-                       for (bus = 255; bus >= 0; bus--) {
-                               if (map->pbus_to_physid[bus] >= 0)
-                                       i = map->pbus_to_physid[bus];
-                               else
-                                       map->pbus_to_physid[bus] = i;
-                       }
-               }
-               raw_spin_unlock(&pci2phy_map_lock);
-       }
-
-       pci_dev_put(ubox_dev);
-
-       return err ? pcibios_err_to_errno(err) : 0;
-}
-
-int snbep_uncore_pci_init(void)
-{
-       int ret = snbep_pci2phy_map_init(0x3ce0);
-       if (ret)
-               return ret;
-       uncore_pci_uncores = snbep_pci_uncores;
-       uncore_pci_driver = &snbep_uncore_pci_driver;
-       return 0;
-}
-/* end of Sandy Bridge-EP uncore support */
-
-/* IvyTown uncore support */
-static void ivbep_uncore_msr_init_box(struct intel_uncore_box *box)
-{
-       unsigned msr = uncore_msr_box_ctl(box);
-       if (msr)
-               wrmsrl(msr, IVBEP_PMON_BOX_CTL_INT);
-}
-
-static void ivbep_uncore_pci_init_box(struct intel_uncore_box *box)
-{
-       struct pci_dev *pdev = box->pci_dev;
-
-       pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL, IVBEP_PMON_BOX_CTL_INT);
-}
-
-#define IVBEP_UNCORE_MSR_OPS_COMMON_INIT()                     \
-       .init_box       = ivbep_uncore_msr_init_box,            \
-       .disable_box    = snbep_uncore_msr_disable_box,         \
-       .enable_box     = snbep_uncore_msr_enable_box,          \
-       .disable_event  = snbep_uncore_msr_disable_event,       \
-       .enable_event   = snbep_uncore_msr_enable_event,        \
-       .read_counter   = uncore_msr_read_counter
-
-static struct intel_uncore_ops ivbep_uncore_msr_ops = {
-       IVBEP_UNCORE_MSR_OPS_COMMON_INIT(),
-};
-
-static struct intel_uncore_ops ivbep_uncore_pci_ops = {
-       .init_box       = ivbep_uncore_pci_init_box,
-       .disable_box    = snbep_uncore_pci_disable_box,
-       .enable_box     = snbep_uncore_pci_enable_box,
-       .disable_event  = snbep_uncore_pci_disable_event,
-       .enable_event   = snbep_uncore_pci_enable_event,
-       .read_counter   = snbep_uncore_pci_read_counter,
-};
-
-#define IVBEP_UNCORE_PCI_COMMON_INIT()                         \
-       .perf_ctr       = SNBEP_PCI_PMON_CTR0,                  \
-       .event_ctl      = SNBEP_PCI_PMON_CTL0,                  \
-       .event_mask     = IVBEP_PMON_RAW_EVENT_MASK,            \
-       .box_ctl        = SNBEP_PCI_PMON_BOX_CTL,               \
-       .ops            = &ivbep_uncore_pci_ops,                        \
-       .format_group   = &ivbep_uncore_format_group
-
-static struct attribute *ivbep_uncore_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       NULL,
-};
-
-static struct attribute *ivbep_uncore_ubox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh5.attr,
-       NULL,
-};
-
-static struct attribute *ivbep_uncore_cbox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_tid_en.attr,
-       &format_attr_thresh8.attr,
-       &format_attr_filter_tid.attr,
-       &format_attr_filter_link.attr,
-       &format_attr_filter_state2.attr,
-       &format_attr_filter_nid2.attr,
-       &format_attr_filter_opc2.attr,
-       &format_attr_filter_nc.attr,
-       &format_attr_filter_c6.attr,
-       &format_attr_filter_isoc.attr,
-       NULL,
-};
-
-static struct attribute *ivbep_uncore_pcu_formats_attr[] = {
-       &format_attr_event_ext.attr,
-       &format_attr_occ_sel.attr,
-       &format_attr_edge.attr,
-       &format_attr_thresh5.attr,
-       &format_attr_occ_invert.attr,
-       &format_attr_occ_edge.attr,
-       &format_attr_filter_band0.attr,
-       &format_attr_filter_band1.attr,
-       &format_attr_filter_band2.attr,
-       &format_attr_filter_band3.attr,
-       NULL,
-};
-
-static struct attribute *ivbep_uncore_qpi_formats_attr[] = {
-       &format_attr_event_ext.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_thresh8.attr,
-       &format_attr_match_rds.attr,
-       &format_attr_match_rnid30.attr,
-       &format_attr_match_rnid4.attr,
-       &format_attr_match_dnid.attr,
-       &format_attr_match_mc.attr,
-       &format_attr_match_opc.attr,
-       &format_attr_match_vnw.attr,
-       &format_attr_match0.attr,
-       &format_attr_match1.attr,
-       &format_attr_mask_rds.attr,
-       &format_attr_mask_rnid30.attr,
-       &format_attr_mask_rnid4.attr,
-       &format_attr_mask_dnid.attr,
-       &format_attr_mask_mc.attr,
-       &format_attr_mask_opc.attr,
-       &format_attr_mask_vnw.attr,
-       &format_attr_mask0.attr,
-       &format_attr_mask1.attr,
-       NULL,
-};
-
-static struct attribute_group ivbep_uncore_format_group = {
-       .name = "format",
-       .attrs = ivbep_uncore_formats_attr,
-};
-
-static struct attribute_group ivbep_uncore_ubox_format_group = {
-       .name = "format",
-       .attrs = ivbep_uncore_ubox_formats_attr,
-};
-
-static struct attribute_group ivbep_uncore_cbox_format_group = {
-       .name = "format",
-       .attrs = ivbep_uncore_cbox_formats_attr,
-};
-
-static struct attribute_group ivbep_uncore_pcu_format_group = {
-       .name = "format",
-       .attrs = ivbep_uncore_pcu_formats_attr,
-};
-
-static struct attribute_group ivbep_uncore_qpi_format_group = {
-       .name = "format",
-       .attrs = ivbep_uncore_qpi_formats_attr,
-};
-
-static struct intel_uncore_type ivbep_uncore_ubox = {
-       .name           = "ubox",
-       .num_counters   = 2,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 44,
-       .fixed_ctr_bits = 48,
-       .perf_ctr       = SNBEP_U_MSR_PMON_CTR0,
-       .event_ctl      = SNBEP_U_MSR_PMON_CTL0,
-       .event_mask     = IVBEP_U_MSR_PMON_RAW_EVENT_MASK,
-       .fixed_ctr      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
-       .fixed_ctl      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
-       .ops            = &ivbep_uncore_msr_ops,
-       .format_group   = &ivbep_uncore_ubox_format_group,
-};
-
-static struct extra_reg ivbep_uncore_cbox_extra_regs[] = {
-       SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
-                                 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2335, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0x18),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0x18),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x8135, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x8335, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2136, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2336, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0x18),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0x18),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x5036, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x8136, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x8336, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x8),
-       EVENT_EXTRA_END
-};
-
-static u64 ivbep_cbox_filter_mask(int fields)
-{
-       u64 mask = 0;
-
-       if (fields & 0x1)
-               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_TID;
-       if (fields & 0x2)
-               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_LINK;
-       if (fields & 0x4)
-               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_STATE;
-       if (fields & 0x8)
-               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_NID;
-       if (fields & 0x10) {
-               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_OPC;
-               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_NC;
-               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_C6;
-               mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_ISOC;
-       }
-
-       return mask;
-}
-
-static struct event_constraint *
-ivbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       return __snbep_cbox_get_constraint(box, event, ivbep_cbox_filter_mask);
-}
-
-static int ivbep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct extra_reg *er;
-       int idx = 0;
-
-       for (er = ivbep_uncore_cbox_extra_regs; er->msr; er++) {
-               if (er->event != (event->hw.config & er->config_mask))
-                       continue;
-               idx |= er->idx;
-       }
-
-       if (idx) {
-               reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
-                       SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
-               reg1->config = event->attr.config1 & ivbep_cbox_filter_mask(idx);
-               reg1->idx = idx;
-       }
-       return 0;
-}
-
-static void ivbep_cbox_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-
-       if (reg1->idx != EXTRA_REG_NONE) {
-               u64 filter = uncore_shared_reg_config(box, 0);
-               wrmsrl(reg1->reg, filter & 0xffffffff);
-               wrmsrl(reg1->reg + 6, filter >> 32);
-       }
-
-       wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
-}
-
-static struct intel_uncore_ops ivbep_uncore_cbox_ops = {
-       .init_box               = ivbep_uncore_msr_init_box,
-       .disable_box            = snbep_uncore_msr_disable_box,
-       .enable_box             = snbep_uncore_msr_enable_box,
-       .disable_event          = snbep_uncore_msr_disable_event,
-       .enable_event           = ivbep_cbox_enable_event,
-       .read_counter           = uncore_msr_read_counter,
-       .hw_config              = ivbep_cbox_hw_config,
-       .get_constraint         = ivbep_cbox_get_constraint,
-       .put_constraint         = snbep_cbox_put_constraint,
-};
-
-static struct intel_uncore_type ivbep_uncore_cbox = {
-       .name                   = "cbox",
-       .num_counters           = 4,
-       .num_boxes              = 15,
-       .perf_ctr_bits          = 44,
-       .event_ctl              = SNBEP_C0_MSR_PMON_CTL0,
-       .perf_ctr               = SNBEP_C0_MSR_PMON_CTR0,
-       .event_mask             = IVBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_C0_MSR_PMON_BOX_CTL,
-       .msr_offset             = SNBEP_CBO_MSR_OFFSET,
-       .num_shared_regs        = 1,
-       .constraints            = snbep_uncore_cbox_constraints,
-       .ops                    = &ivbep_uncore_cbox_ops,
-       .format_group           = &ivbep_uncore_cbox_format_group,
-};
-
-static struct intel_uncore_ops ivbep_uncore_pcu_ops = {
-       IVBEP_UNCORE_MSR_OPS_COMMON_INIT(),
-       .hw_config              = snbep_pcu_hw_config,
-       .get_constraint         = snbep_pcu_get_constraint,
-       .put_constraint         = snbep_pcu_put_constraint,
-};
-
-static struct intel_uncore_type ivbep_uncore_pcu = {
-       .name                   = "pcu",
-       .num_counters           = 4,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = SNBEP_PCU_MSR_PMON_CTR0,
-       .event_ctl              = SNBEP_PCU_MSR_PMON_CTL0,
-       .event_mask             = IVBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCU_MSR_PMON_BOX_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &ivbep_uncore_pcu_ops,
-       .format_group           = &ivbep_uncore_pcu_format_group,
-};
-
-static struct intel_uncore_type *ivbep_msr_uncores[] = {
-       &ivbep_uncore_ubox,
-       &ivbep_uncore_cbox,
-       &ivbep_uncore_pcu,
-       NULL,
-};
-
-void ivbep_uncore_cpu_init(void)
-{
-       if (ivbep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
-               ivbep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
-       uncore_msr_uncores = ivbep_msr_uncores;
-}
-
-static struct intel_uncore_type ivbep_uncore_ha = {
-       .name           = "ha",
-       .num_counters   = 4,
-       .num_boxes      = 2,
-       .perf_ctr_bits  = 48,
-       IVBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct intel_uncore_type ivbep_uncore_imc = {
-       .name           = "imc",
-       .num_counters   = 4,
-       .num_boxes      = 8,
-       .perf_ctr_bits  = 48,
-       .fixed_ctr_bits = 48,
-       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
-       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
-       .event_descs    = snbep_uncore_imc_events,
-       IVBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-/* registers in IRP boxes are not properly aligned */
-static unsigned ivbep_uncore_irp_ctls[] = {0xd8, 0xdc, 0xe0, 0xe4};
-static unsigned ivbep_uncore_irp_ctrs[] = {0xa0, 0xb0, 0xb8, 0xc0};
-
-static void ivbep_uncore_irp_enable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-
-       pci_write_config_dword(pdev, ivbep_uncore_irp_ctls[hwc->idx],
-                              hwc->config | SNBEP_PMON_CTL_EN);
-}
-
-static void ivbep_uncore_irp_disable_event(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-
-       pci_write_config_dword(pdev, ivbep_uncore_irp_ctls[hwc->idx], hwc->config);
-}
-
-static u64 ivbep_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-       u64 count = 0;
-
-       pci_read_config_dword(pdev, ivbep_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
-       pci_read_config_dword(pdev, ivbep_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
-
-       return count;
-}
-
-static struct intel_uncore_ops ivbep_uncore_irp_ops = {
-       .init_box       = ivbep_uncore_pci_init_box,
-       .disable_box    = snbep_uncore_pci_disable_box,
-       .enable_box     = snbep_uncore_pci_enable_box,
-       .disable_event  = ivbep_uncore_irp_disable_event,
-       .enable_event   = ivbep_uncore_irp_enable_event,
-       .read_counter   = ivbep_uncore_irp_read_counter,
-};
-
-static struct intel_uncore_type ivbep_uncore_irp = {
-       .name                   = "irp",
-       .num_counters           = 4,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .event_mask             = IVBEP_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
-       .ops                    = &ivbep_uncore_irp_ops,
-       .format_group           = &ivbep_uncore_format_group,
-};
-
-static struct intel_uncore_ops ivbep_uncore_qpi_ops = {
-       .init_box       = ivbep_uncore_pci_init_box,
-       .disable_box    = snbep_uncore_pci_disable_box,
-       .enable_box     = snbep_uncore_pci_enable_box,
-       .disable_event  = snbep_uncore_pci_disable_event,
-       .enable_event   = snbep_qpi_enable_event,
-       .read_counter   = snbep_uncore_pci_read_counter,
-       .hw_config      = snbep_qpi_hw_config,
-       .get_constraint = uncore_get_constraint,
-       .put_constraint = uncore_put_constraint,
-};
-
-static struct intel_uncore_type ivbep_uncore_qpi = {
-       .name                   = "qpi",
-       .num_counters           = 4,
-       .num_boxes              = 3,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
-       .event_ctl              = SNBEP_PCI_PMON_CTL0,
-       .event_mask             = IVBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &ivbep_uncore_qpi_ops,
-       .format_group           = &ivbep_uncore_qpi_format_group,
-};
-
-static struct intel_uncore_type ivbep_uncore_r2pcie = {
-       .name           = "r2pcie",
-       .num_counters   = 4,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 44,
-       .constraints    = snbep_uncore_r2pcie_constraints,
-       IVBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct intel_uncore_type ivbep_uncore_r3qpi = {
-       .name           = "r3qpi",
-       .num_counters   = 3,
-       .num_boxes      = 2,
-       .perf_ctr_bits  = 44,
-       .constraints    = snbep_uncore_r3qpi_constraints,
-       IVBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-enum {
-       IVBEP_PCI_UNCORE_HA,
-       IVBEP_PCI_UNCORE_IMC,
-       IVBEP_PCI_UNCORE_IRP,
-       IVBEP_PCI_UNCORE_QPI,
-       IVBEP_PCI_UNCORE_R2PCIE,
-       IVBEP_PCI_UNCORE_R3QPI,
-};
-
-static struct intel_uncore_type *ivbep_pci_uncores[] = {
-       [IVBEP_PCI_UNCORE_HA]   = &ivbep_uncore_ha,
-       [IVBEP_PCI_UNCORE_IMC]  = &ivbep_uncore_imc,
-       [IVBEP_PCI_UNCORE_IRP]  = &ivbep_uncore_irp,
-       [IVBEP_PCI_UNCORE_QPI]  = &ivbep_uncore_qpi,
-       [IVBEP_PCI_UNCORE_R2PCIE]       = &ivbep_uncore_r2pcie,
-       [IVBEP_PCI_UNCORE_R3QPI]        = &ivbep_uncore_r3qpi,
-       NULL,
-};
-
-static const struct pci_device_id ivbep_uncore_pci_ids[] = {
-       { /* Home Agent 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe30),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_HA, 0),
-       },
-       { /* Home Agent 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe38),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_HA, 1),
-       },
-       { /* MC0 Channel 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb4),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 0),
-       },
-       { /* MC0 Channel 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb5),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 1),
-       },
-       { /* MC0 Channel 3 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb0),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 2),
-       },
-       { /* MC0 Channel 4 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb1),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 3),
-       },
-       { /* MC1 Channel 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef4),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 4),
-       },
-       { /* MC1 Channel 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef5),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 5),
-       },
-       { /* MC1 Channel 3 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef0),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 6),
-       },
-       { /* MC1 Channel 4 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 7),
-       },
-       { /* IRP */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe39),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IRP, 0),
-       },
-       { /* QPI0 Port 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 0),
-       },
-       { /* QPI0 Port 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe33),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 1),
-       },
-       { /* QPI1 Port 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3a),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 2),
-       },
-       { /* R2PCIe */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe34),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R2PCIE, 0),
-       },
-       { /* R3QPI0 Link 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe36),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 0),
-       },
-       { /* R3QPI0 Link 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe37),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 1),
-       },
-       { /* R3QPI1 Link 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e),
-               .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 2),
-       },
-       { /* QPI Port 0 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe86),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-                                                  SNBEP_PCI_QPI_PORT0_FILTER),
-       },
-       { /* QPI Port 0 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe96),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-                                                  SNBEP_PCI_QPI_PORT1_FILTER),
-       },
-       { /* end: all zeroes */ }
-};
-
-static struct pci_driver ivbep_uncore_pci_driver = {
-       .name           = "ivbep_uncore",
-       .id_table       = ivbep_uncore_pci_ids,
-};
-
-int ivbep_uncore_pci_init(void)
-{
-       int ret = snbep_pci2phy_map_init(0x0e1e);
-       if (ret)
-               return ret;
-       uncore_pci_uncores = ivbep_pci_uncores;
-       uncore_pci_driver = &ivbep_uncore_pci_driver;
-       return 0;
-}
-/* end of IvyTown uncore support */
-
-/* KNL uncore support */
-static struct attribute *knl_uncore_ubox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_tid_en.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh5.attr,
-       NULL,
-};
-
-static struct attribute_group knl_uncore_ubox_format_group = {
-       .name = "format",
-       .attrs = knl_uncore_ubox_formats_attr,
-};
-
-static struct intel_uncore_type knl_uncore_ubox = {
-       .name                   = "ubox",
-       .num_counters           = 2,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .fixed_ctr_bits         = 48,
-       .perf_ctr               = HSWEP_U_MSR_PMON_CTR0,
-       .event_ctl              = HSWEP_U_MSR_PMON_CTL0,
-       .event_mask             = KNL_U_MSR_PMON_RAW_EVENT_MASK,
-       .fixed_ctr              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
-       .fixed_ctl              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
-       .ops                    = &snbep_uncore_msr_ops,
-       .format_group           = &knl_uncore_ubox_format_group,
-};
-
-static struct attribute *knl_uncore_cha_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_qor.attr,
-       &format_attr_edge.attr,
-       &format_attr_tid_en.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       &format_attr_filter_tid4.attr,
-       &format_attr_filter_link3.attr,
-       &format_attr_filter_state4.attr,
-       &format_attr_filter_local.attr,
-       &format_attr_filter_all_op.attr,
-       &format_attr_filter_nnm.attr,
-       &format_attr_filter_opc3.attr,
-       &format_attr_filter_nc.attr,
-       &format_attr_filter_isoc.attr,
-       NULL,
-};
-
-static struct attribute_group knl_uncore_cha_format_group = {
-       .name = "format",
-       .attrs = knl_uncore_cha_formats_attr,
-};
-
-static struct event_constraint knl_uncore_cha_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x1f, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
-       EVENT_CONSTRAINT_END
-};
-
-static struct extra_reg knl_uncore_cha_extra_regs[] = {
-       SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
-                                 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x3d, 0xff, 0x2),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x35, 0xff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x36, 0xff, 0x4),
-       EVENT_EXTRA_END
-};
-
-static u64 knl_cha_filter_mask(int fields)
-{
-       u64 mask = 0;
-
-       if (fields & 0x1)
-               mask |= KNL_CHA_MSR_PMON_BOX_FILTER_TID;
-       if (fields & 0x2)
-               mask |= KNL_CHA_MSR_PMON_BOX_FILTER_STATE;
-       if (fields & 0x4)
-               mask |= KNL_CHA_MSR_PMON_BOX_FILTER_OP;
-       return mask;
-}
-
-static struct event_constraint *
-knl_cha_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       return __snbep_cbox_get_constraint(box, event, knl_cha_filter_mask);
-}
-
-static int knl_cha_hw_config(struct intel_uncore_box *box,
-                            struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct extra_reg *er;
-       int idx = 0;
-
-       for (er = knl_uncore_cha_extra_regs; er->msr; er++) {
-               if (er->event != (event->hw.config & er->config_mask))
-                       continue;
-               idx |= er->idx;
-       }
-
-       if (idx) {
-               reg1->reg = HSWEP_C0_MSR_PMON_BOX_FILTER0 +
-                           KNL_CHA_MSR_OFFSET * box->pmu->pmu_idx;
-               reg1->config = event->attr.config1 & knl_cha_filter_mask(idx);
-               reg1->idx = idx;
-       }
-       return 0;
-}
-
-static void hswep_cbox_enable_event(struct intel_uncore_box *box,
-                                   struct perf_event *event);
-
-static struct intel_uncore_ops knl_uncore_cha_ops = {
-       .init_box               = snbep_uncore_msr_init_box,
-       .disable_box            = snbep_uncore_msr_disable_box,
-       .enable_box             = snbep_uncore_msr_enable_box,
-       .disable_event          = snbep_uncore_msr_disable_event,
-       .enable_event           = hswep_cbox_enable_event,
-       .read_counter           = uncore_msr_read_counter,
-       .hw_config              = knl_cha_hw_config,
-       .get_constraint         = knl_cha_get_constraint,
-       .put_constraint         = snbep_cbox_put_constraint,
-};
-
-static struct intel_uncore_type knl_uncore_cha = {
-       .name                   = "cha",
-       .num_counters           = 4,
-       .num_boxes              = 38,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = HSWEP_C0_MSR_PMON_CTL0,
-       .perf_ctr               = HSWEP_C0_MSR_PMON_CTR0,
-       .event_mask             = KNL_CHA_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = HSWEP_C0_MSR_PMON_BOX_CTL,
-       .msr_offset             = KNL_CHA_MSR_OFFSET,
-       .num_shared_regs        = 1,
-       .constraints            = knl_uncore_cha_constraints,
-       .ops                    = &knl_uncore_cha_ops,
-       .format_group           = &knl_uncore_cha_format_group,
-};
-
-static struct attribute *knl_uncore_pcu_formats_attr[] = {
-       &format_attr_event2.attr,
-       &format_attr_use_occ_ctr.attr,
-       &format_attr_occ_sel.attr,
-       &format_attr_edge.attr,
-       &format_attr_tid_en.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh6.attr,
-       &format_attr_occ_invert.attr,
-       &format_attr_occ_edge_det.attr,
-       NULL,
-};
-
-static struct attribute_group knl_uncore_pcu_format_group = {
-       .name = "format",
-       .attrs = knl_uncore_pcu_formats_attr,
-};
-
-static struct intel_uncore_type knl_uncore_pcu = {
-       .name                   = "pcu",
-       .num_counters           = 4,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = HSWEP_PCU_MSR_PMON_CTR0,
-       .event_ctl              = HSWEP_PCU_MSR_PMON_CTL0,
-       .event_mask             = KNL_PCU_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = HSWEP_PCU_MSR_PMON_BOX_CTL,
-       .ops                    = &snbep_uncore_msr_ops,
-       .format_group           = &knl_uncore_pcu_format_group,
-};
-
-static struct intel_uncore_type *knl_msr_uncores[] = {
-       &knl_uncore_ubox,
-       &knl_uncore_cha,
-       &knl_uncore_pcu,
-       NULL,
-};
-
-void knl_uncore_cpu_init(void)
-{
-       uncore_msr_uncores = knl_msr_uncores;
-}
-
-static void knl_uncore_imc_enable_box(struct intel_uncore_box *box)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       int box_ctl = uncore_pci_box_ctl(box);
-
-       pci_write_config_dword(pdev, box_ctl, 0);
-}
-
-static void knl_uncore_imc_enable_event(struct intel_uncore_box *box,
-                                       struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-
-       if ((event->attr.config & SNBEP_PMON_CTL_EV_SEL_MASK)
-                                                       == UNCORE_FIXED_EVENT)
-               pci_write_config_dword(pdev, hwc->config_base,
-                                      hwc->config | KNL_PMON_FIXED_CTL_EN);
-       else
-               pci_write_config_dword(pdev, hwc->config_base,
-                                      hwc->config | SNBEP_PMON_CTL_EN);
-}
-
-static struct intel_uncore_ops knl_uncore_imc_ops = {
-       .init_box       = snbep_uncore_pci_init_box,
-       .disable_box    = snbep_uncore_pci_disable_box,
-       .enable_box     = knl_uncore_imc_enable_box,
-       .read_counter   = snbep_uncore_pci_read_counter,
-       .enable_event   = knl_uncore_imc_enable_event,
-       .disable_event  = snbep_uncore_pci_disable_event,
-};
-
-static struct intel_uncore_type knl_uncore_imc_uclk = {
-       .name                   = "imc_uclk",
-       .num_counters           = 4,
-       .num_boxes              = 2,
-       .perf_ctr_bits          = 48,
-       .fixed_ctr_bits         = 48,
-       .perf_ctr               = KNL_UCLK_MSR_PMON_CTR0_LOW,
-       .event_ctl              = KNL_UCLK_MSR_PMON_CTL0,
-       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
-       .fixed_ctr              = KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW,
-       .fixed_ctl              = KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL,
-       .box_ctl                = KNL_UCLK_MSR_PMON_BOX_CTL,
-       .ops                    = &knl_uncore_imc_ops,
-       .format_group           = &snbep_uncore_format_group,
-};
-
-static struct intel_uncore_type knl_uncore_imc_dclk = {
-       .name                   = "imc",
-       .num_counters           = 4,
-       .num_boxes              = 6,
-       .perf_ctr_bits          = 48,
-       .fixed_ctr_bits         = 48,
-       .perf_ctr               = KNL_MC0_CH0_MSR_PMON_CTR0_LOW,
-       .event_ctl              = KNL_MC0_CH0_MSR_PMON_CTL0,
-       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
-       .fixed_ctr              = KNL_MC0_CH0_MSR_PMON_FIXED_LOW,
-       .fixed_ctl              = KNL_MC0_CH0_MSR_PMON_FIXED_CTL,
-       .box_ctl                = KNL_MC0_CH0_MSR_PMON_BOX_CTL,
-       .ops                    = &knl_uncore_imc_ops,
-       .format_group           = &snbep_uncore_format_group,
-};
-
-static struct intel_uncore_type knl_uncore_edc_uclk = {
-       .name                   = "edc_uclk",
-       .num_counters           = 4,
-       .num_boxes              = 8,
-       .perf_ctr_bits          = 48,
-       .fixed_ctr_bits         = 48,
-       .perf_ctr               = KNL_UCLK_MSR_PMON_CTR0_LOW,
-       .event_ctl              = KNL_UCLK_MSR_PMON_CTL0,
-       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
-       .fixed_ctr              = KNL_UCLK_MSR_PMON_UCLK_FIXED_LOW,
-       .fixed_ctl              = KNL_UCLK_MSR_PMON_UCLK_FIXED_CTL,
-       .box_ctl                = KNL_UCLK_MSR_PMON_BOX_CTL,
-       .ops                    = &knl_uncore_imc_ops,
-       .format_group           = &snbep_uncore_format_group,
-};
-
-static struct intel_uncore_type knl_uncore_edc_eclk = {
-       .name                   = "edc_eclk",
-       .num_counters           = 4,
-       .num_boxes              = 8,
-       .perf_ctr_bits          = 48,
-       .fixed_ctr_bits         = 48,
-       .perf_ctr               = KNL_EDC0_ECLK_MSR_PMON_CTR0_LOW,
-       .event_ctl              = KNL_EDC0_ECLK_MSR_PMON_CTL0,
-       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
-       .fixed_ctr              = KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_LOW,
-       .fixed_ctl              = KNL_EDC0_ECLK_MSR_PMON_ECLK_FIXED_CTL,
-       .box_ctl                = KNL_EDC0_ECLK_MSR_PMON_BOX_CTL,
-       .ops                    = &knl_uncore_imc_ops,
-       .format_group           = &snbep_uncore_format_group,
-};
-
-static struct event_constraint knl_uncore_m2pcie_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
-       EVENT_CONSTRAINT_END
-};
-
-static struct intel_uncore_type knl_uncore_m2pcie = {
-       .name           = "m2pcie",
-       .num_counters   = 4,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 48,
-       .constraints    = knl_uncore_m2pcie_constraints,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct attribute *knl_uncore_irp_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_qor.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       NULL,
-};
-
-static struct attribute_group knl_uncore_irp_format_group = {
-       .name = "format",
-       .attrs = knl_uncore_irp_formats_attr,
-};
-
-static struct intel_uncore_type knl_uncore_irp = {
-       .name                   = "irp",
-       .num_counters           = 2,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
-       .event_ctl              = SNBEP_PCI_PMON_CTL0,
-       .event_mask             = KNL_IRP_PCI_PMON_RAW_EVENT_MASK,
-       .box_ctl                = KNL_IRP_PCI_PMON_BOX_CTL,
-       .ops                    = &snbep_uncore_pci_ops,
-       .format_group           = &knl_uncore_irp_format_group,
-};
-
-enum {
-       KNL_PCI_UNCORE_MC_UCLK,
-       KNL_PCI_UNCORE_MC_DCLK,
-       KNL_PCI_UNCORE_EDC_UCLK,
-       KNL_PCI_UNCORE_EDC_ECLK,
-       KNL_PCI_UNCORE_M2PCIE,
-       KNL_PCI_UNCORE_IRP,
-};
-
-static struct intel_uncore_type *knl_pci_uncores[] = {
-       [KNL_PCI_UNCORE_MC_UCLK]        = &knl_uncore_imc_uclk,
-       [KNL_PCI_UNCORE_MC_DCLK]        = &knl_uncore_imc_dclk,
-       [KNL_PCI_UNCORE_EDC_UCLK]       = &knl_uncore_edc_uclk,
-       [KNL_PCI_UNCORE_EDC_ECLK]       = &knl_uncore_edc_eclk,
-       [KNL_PCI_UNCORE_M2PCIE]         = &knl_uncore_m2pcie,
-       [KNL_PCI_UNCORE_IRP]            = &knl_uncore_irp,
-       NULL,
-};
-
-/*
- * KNL uses a common PCI device ID for multiple instances of an Uncore PMU
- * device type. prior to KNL, each instance of a PMU device type had a unique
- * device ID.
- *
- *     PCI Device ID   Uncore PMU Devices
- *     ----------------------------------
- *     0x7841          MC0 UClk, MC1 UClk
- *     0x7843          MC0 DClk CH 0, MC0 DClk CH 1, MC0 DClk CH 2,
- *                     MC1 DClk CH 0, MC1 DClk CH 1, MC1 DClk CH 2
- *     0x7833          EDC0 UClk, EDC1 UClk, EDC2 UClk, EDC3 UClk,
- *                     EDC4 UClk, EDC5 UClk, EDC6 UClk, EDC7 UClk
- *     0x7835          EDC0 EClk, EDC1 EClk, EDC2 EClk, EDC3 EClk,
- *                     EDC4 EClk, EDC5 EClk, EDC6 EClk, EDC7 EClk
- *     0x7817          M2PCIe
- *     0x7814          IRP
-*/
-
-static const struct pci_device_id knl_uncore_pci_ids[] = {
-       { /* MC UClk */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7841),
-               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_MC_UCLK, 0),
-       },
-       { /* MC DClk Channel */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7843),
-               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_MC_DCLK, 0),
-       },
-       { /* EDC UClk */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7833),
-               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_EDC_UCLK, 0),
-       },
-       { /* EDC EClk */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7835),
-               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_EDC_ECLK, 0),
-       },
-       { /* M2PCIe */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7817),
-               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_M2PCIE, 0),
-       },
-       { /* IRP */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7814),
-               .driver_data = UNCORE_PCI_DEV_DATA(KNL_PCI_UNCORE_IRP, 0),
-       },
-       { /* end: all zeroes */ }
-};
-
-static struct pci_driver knl_uncore_pci_driver = {
-       .name           = "knl_uncore",
-       .id_table       = knl_uncore_pci_ids,
-};
-
-int knl_uncore_pci_init(void)
-{
-       int ret;
-
-       /* All KNL PCI based PMON units are on the same PCI bus except IRP */
-       ret = snb_pci2phy_map_init(0x7814); /* IRP */
-       if (ret)
-               return ret;
-       ret = snb_pci2phy_map_init(0x7817); /* M2PCIe */
-       if (ret)
-               return ret;
-       uncore_pci_uncores = knl_pci_uncores;
-       uncore_pci_driver = &knl_uncore_pci_driver;
-       return 0;
-}
-
-/* end of KNL uncore support */
-
-/* Haswell-EP uncore support */
-static struct attribute *hswep_uncore_ubox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh5.attr,
-       &format_attr_filter_tid2.attr,
-       &format_attr_filter_cid.attr,
-       NULL,
-};
-
-static struct attribute_group hswep_uncore_ubox_format_group = {
-       .name = "format",
-       .attrs = hswep_uncore_ubox_formats_attr,
-};
-
-static int hswep_ubox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       reg1->reg = HSWEP_U_MSR_PMON_FILTER;
-       reg1->config = event->attr.config1 & HSWEP_U_MSR_PMON_BOX_FILTER_MASK;
-       reg1->idx = 0;
-       return 0;
-}
-
-static struct intel_uncore_ops hswep_uncore_ubox_ops = {
-       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
-       .hw_config              = hswep_ubox_hw_config,
-       .get_constraint         = uncore_get_constraint,
-       .put_constraint         = uncore_put_constraint,
-};
-
-static struct intel_uncore_type hswep_uncore_ubox = {
-       .name                   = "ubox",
-       .num_counters           = 2,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 44,
-       .fixed_ctr_bits         = 48,
-       .perf_ctr               = HSWEP_U_MSR_PMON_CTR0,
-       .event_ctl              = HSWEP_U_MSR_PMON_CTL0,
-       .event_mask             = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
-       .fixed_ctr              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
-       .fixed_ctl              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &hswep_uncore_ubox_ops,
-       .format_group           = &hswep_uncore_ubox_format_group,
-};
-
-static struct attribute *hswep_uncore_cbox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_tid_en.attr,
-       &format_attr_thresh8.attr,
-       &format_attr_filter_tid3.attr,
-       &format_attr_filter_link2.attr,
-       &format_attr_filter_state3.attr,
-       &format_attr_filter_nid2.attr,
-       &format_attr_filter_opc2.attr,
-       &format_attr_filter_nc.attr,
-       &format_attr_filter_c6.attr,
-       &format_attr_filter_isoc.attr,
-       NULL,
-};
-
-static struct attribute_group hswep_uncore_cbox_format_group = {
-       .name = "format",
-       .attrs = hswep_uncore_cbox_formats_attr,
-};
-
-static struct event_constraint hswep_uncore_cbox_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x09, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x3e, 0x1),
-       EVENT_CONSTRAINT_END
-};
-
-static struct extra_reg hswep_uncore_cbox_extra_regs[] = {
-       SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
-                                 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2134, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x4),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4028, 0x40ff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4032, 0x40ff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4029, 0x40ff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4033, 0x40ff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x402A, 0x40ff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x12),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0x18),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0x18),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2335, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x8335, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x8135, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0x18),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0x18),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x8),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2336, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x8336, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x2136, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x8136, 0xffff, 0x10),
-       SNBEP_CBO_EVENT_EXTRA_REG(0x5036, 0xffff, 0x8),
-       EVENT_EXTRA_END
-};
-
-static u64 hswep_cbox_filter_mask(int fields)
-{
-       u64 mask = 0;
-       if (fields & 0x1)
-               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_TID;
-       if (fields & 0x2)
-               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_LINK;
-       if (fields & 0x4)
-               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_STATE;
-       if (fields & 0x8)
-               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_NID;
-       if (fields & 0x10) {
-               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_OPC;
-               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_NC;
-               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_C6;
-               mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_ISOC;
-       }
-       return mask;
-}
-
-static struct event_constraint *
-hswep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
-{
-       return __snbep_cbox_get_constraint(box, event, hswep_cbox_filter_mask);
-}
-
-static int hswep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
-       struct extra_reg *er;
-       int idx = 0;
-
-       for (er = hswep_uncore_cbox_extra_regs; er->msr; er++) {
-               if (er->event != (event->hw.config & er->config_mask))
-                       continue;
-               idx |= er->idx;
-       }
-
-       if (idx) {
-               reg1->reg = HSWEP_C0_MSR_PMON_BOX_FILTER0 +
-                           HSWEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
-               reg1->config = event->attr.config1 & hswep_cbox_filter_mask(idx);
-               reg1->idx = idx;
-       }
-       return 0;
-}
-
-static void hswep_cbox_enable_event(struct intel_uncore_box *box,
-                                 struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-
-       if (reg1->idx != EXTRA_REG_NONE) {
-               u64 filter = uncore_shared_reg_config(box, 0);
-               wrmsrl(reg1->reg, filter & 0xffffffff);
-               wrmsrl(reg1->reg + 1, filter >> 32);
-       }
-
-       wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
-}
-
-static struct intel_uncore_ops hswep_uncore_cbox_ops = {
-       .init_box               = snbep_uncore_msr_init_box,
-       .disable_box            = snbep_uncore_msr_disable_box,
-       .enable_box             = snbep_uncore_msr_enable_box,
-       .disable_event          = snbep_uncore_msr_disable_event,
-       .enable_event           = hswep_cbox_enable_event,
-       .read_counter           = uncore_msr_read_counter,
-       .hw_config              = hswep_cbox_hw_config,
-       .get_constraint         = hswep_cbox_get_constraint,
-       .put_constraint         = snbep_cbox_put_constraint,
-};
-
-static struct intel_uncore_type hswep_uncore_cbox = {
-       .name                   = "cbox",
-       .num_counters           = 4,
-       .num_boxes              = 18,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = HSWEP_C0_MSR_PMON_CTL0,
-       .perf_ctr               = HSWEP_C0_MSR_PMON_CTR0,
-       .event_mask             = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = HSWEP_C0_MSR_PMON_BOX_CTL,
-       .msr_offset             = HSWEP_CBO_MSR_OFFSET,
-       .num_shared_regs        = 1,
-       .constraints            = hswep_uncore_cbox_constraints,
-       .ops                    = &hswep_uncore_cbox_ops,
-       .format_group           = &hswep_uncore_cbox_format_group,
-};
-
-/*
- * Write SBOX Initialization register bit by bit to avoid spurious #GPs
- */
-static void hswep_uncore_sbox_msr_init_box(struct intel_uncore_box *box)
-{
-       unsigned msr = uncore_msr_box_ctl(box);
-
-       if (msr) {
-               u64 init = SNBEP_PMON_BOX_CTL_INT;
-               u64 flags = 0;
-               int i;
-
-               for_each_set_bit(i, (unsigned long *)&init, 64) {
-                       flags |= (1ULL << i);
-                       wrmsrl(msr, flags);
-               }
-       }
-}
-
-static struct intel_uncore_ops hswep_uncore_sbox_msr_ops = {
-       __SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
-       .init_box               = hswep_uncore_sbox_msr_init_box
-};
-
-static struct attribute *hswep_uncore_sbox_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_tid_en.attr,
-       &format_attr_inv.attr,
-       &format_attr_thresh8.attr,
-       NULL,
-};
-
-static struct attribute_group hswep_uncore_sbox_format_group = {
-       .name = "format",
-       .attrs = hswep_uncore_sbox_formats_attr,
-};
-
-static struct intel_uncore_type hswep_uncore_sbox = {
-       .name                   = "sbox",
-       .num_counters           = 4,
-       .num_boxes              = 4,
-       .perf_ctr_bits          = 44,
-       .event_ctl              = HSWEP_S0_MSR_PMON_CTL0,
-       .perf_ctr               = HSWEP_S0_MSR_PMON_CTR0,
-       .event_mask             = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = HSWEP_S0_MSR_PMON_BOX_CTL,
-       .msr_offset             = HSWEP_SBOX_MSR_OFFSET,
-       .ops                    = &hswep_uncore_sbox_msr_ops,
-       .format_group           = &hswep_uncore_sbox_format_group,
-};
-
-static int hswep_pcu_hw_config(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       int ev_sel = hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK;
-
-       if (ev_sel >= 0xb && ev_sel <= 0xe) {
-               reg1->reg = HSWEP_PCU_MSR_PMON_BOX_FILTER;
-               reg1->idx = ev_sel - 0xb;
-               reg1->config = event->attr.config1 & (0xff << reg1->idx);
-       }
-       return 0;
-}
-
-static struct intel_uncore_ops hswep_uncore_pcu_ops = {
-       SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
-       .hw_config              = hswep_pcu_hw_config,
-       .get_constraint         = snbep_pcu_get_constraint,
-       .put_constraint         = snbep_pcu_put_constraint,
-};
-
-static struct intel_uncore_type hswep_uncore_pcu = {
-       .name                   = "pcu",
-       .num_counters           = 4,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = HSWEP_PCU_MSR_PMON_CTR0,
-       .event_ctl              = HSWEP_PCU_MSR_PMON_CTL0,
-       .event_mask             = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = HSWEP_PCU_MSR_PMON_BOX_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &hswep_uncore_pcu_ops,
-       .format_group           = &snbep_uncore_pcu_format_group,
-};
-
-static struct intel_uncore_type *hswep_msr_uncores[] = {
-       &hswep_uncore_ubox,
-       &hswep_uncore_cbox,
-       &hswep_uncore_sbox,
-       &hswep_uncore_pcu,
-       NULL,
-};
-
-void hswep_uncore_cpu_init(void)
-{
-       if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
-               hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
-
-       /* Detect 6-8 core systems with only two SBOXes */
-       if (uncore_extra_pci_dev[0][HSWEP_PCI_PCU_3]) {
-               u32 capid4;
-
-               pci_read_config_dword(uncore_extra_pci_dev[0][HSWEP_PCI_PCU_3],
-                                     0x94, &capid4);
-               if (((capid4 >> 6) & 0x3) == 0)
-                       hswep_uncore_sbox.num_boxes = 2;
-       }
-
-       uncore_msr_uncores = hswep_msr_uncores;
-}
-
-static struct intel_uncore_type hswep_uncore_ha = {
-       .name           = "ha",
-       .num_counters   = 5,
-       .num_boxes      = 2,
-       .perf_ctr_bits  = 48,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct uncore_event_desc hswep_uncore_imc_events[] = {
-       INTEL_UNCORE_EVENT_DESC(clockticks,      "event=0x00,umask=0x00"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_read,  "event=0x04,umask=0x03"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_read.scale, "6.103515625e-5"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_read.unit, "MiB"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_write.scale, "6.103515625e-5"),
-       INTEL_UNCORE_EVENT_DESC(cas_count_write.unit, "MiB"),
-       { /* end: all zeroes */ },
-};
-
-static struct intel_uncore_type hswep_uncore_imc = {
-       .name           = "imc",
-       .num_counters   = 5,
-       .num_boxes      = 8,
-       .perf_ctr_bits  = 48,
-       .fixed_ctr_bits = 48,
-       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
-       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
-       .event_descs    = hswep_uncore_imc_events,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static unsigned hswep_uncore_irp_ctrs[] = {0xa0, 0xa8, 0xb0, 0xb8};
-
-static u64 hswep_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
-{
-       struct pci_dev *pdev = box->pci_dev;
-       struct hw_perf_event *hwc = &event->hw;
-       u64 count = 0;
-
-       pci_read_config_dword(pdev, hswep_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
-       pci_read_config_dword(pdev, hswep_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
-
-       return count;
-}
-
-static struct intel_uncore_ops hswep_uncore_irp_ops = {
-       .init_box       = snbep_uncore_pci_init_box,
-       .disable_box    = snbep_uncore_pci_disable_box,
-       .enable_box     = snbep_uncore_pci_enable_box,
-       .disable_event  = ivbep_uncore_irp_disable_event,
-       .enable_event   = ivbep_uncore_irp_enable_event,
-       .read_counter   = hswep_uncore_irp_read_counter,
-};
-
-static struct intel_uncore_type hswep_uncore_irp = {
-       .name                   = "irp",
-       .num_counters           = 4,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
-       .ops                    = &hswep_uncore_irp_ops,
-       .format_group           = &snbep_uncore_format_group,
-};
-
-static struct intel_uncore_type hswep_uncore_qpi = {
-       .name                   = "qpi",
-       .num_counters           = 5,
-       .num_boxes              = 3,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
-       .event_ctl              = SNBEP_PCI_PMON_CTL0,
-       .event_mask             = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &snbep_uncore_qpi_ops,
-       .format_group           = &snbep_uncore_qpi_format_group,
-};
-
-static struct event_constraint hswep_uncore_r2pcie_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x23, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x24, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x25, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x27, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2a, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x2b, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
-       EVENT_CONSTRAINT_END
-};
-
-static struct intel_uncore_type hswep_uncore_r2pcie = {
-       .name           = "r2pcie",
-       .num_counters   = 4,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 48,
-       .constraints    = hswep_uncore_r2pcie_constraints,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct event_constraint hswep_uncore_r3qpi_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x01, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x07, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x08, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x09, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x0a, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x0e, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x14, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x15, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x1f, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
-       EVENT_CONSTRAINT_END
-};
-
-static struct intel_uncore_type hswep_uncore_r3qpi = {
-       .name           = "r3qpi",
-       .num_counters   = 4,
-       .num_boxes      = 3,
-       .perf_ctr_bits  = 44,
-       .constraints    = hswep_uncore_r3qpi_constraints,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-enum {
-       HSWEP_PCI_UNCORE_HA,
-       HSWEP_PCI_UNCORE_IMC,
-       HSWEP_PCI_UNCORE_IRP,
-       HSWEP_PCI_UNCORE_QPI,
-       HSWEP_PCI_UNCORE_R2PCIE,
-       HSWEP_PCI_UNCORE_R3QPI,
-};
-
-static struct intel_uncore_type *hswep_pci_uncores[] = {
-       [HSWEP_PCI_UNCORE_HA]   = &hswep_uncore_ha,
-       [HSWEP_PCI_UNCORE_IMC]  = &hswep_uncore_imc,
-       [HSWEP_PCI_UNCORE_IRP]  = &hswep_uncore_irp,
-       [HSWEP_PCI_UNCORE_QPI]  = &hswep_uncore_qpi,
-       [HSWEP_PCI_UNCORE_R2PCIE]       = &hswep_uncore_r2pcie,
-       [HSWEP_PCI_UNCORE_R3QPI]        = &hswep_uncore_r3qpi,
-       NULL,
-};
-
-static const struct pci_device_id hswep_uncore_pci_ids[] = {
-       { /* Home Agent 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f30),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_HA, 0),
-       },
-       { /* Home Agent 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f38),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_HA, 1),
-       },
-       { /* MC0 Channel 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb0),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 0),
-       },
-       { /* MC0 Channel 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb1),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 1),
-       },
-       { /* MC0 Channel 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb4),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 2),
-       },
-       { /* MC0 Channel 3 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb5),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 3),
-       },
-       { /* MC1 Channel 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd0),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 4),
-       },
-       { /* MC1 Channel 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd1),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 5),
-       },
-       { /* MC1 Channel 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd4),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 6),
-       },
-       { /* MC1 Channel 3 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd5),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 7),
-       },
-       { /* IRP */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f39),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IRP, 0),
-       },
-       { /* QPI0 Port 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f32),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 0),
-       },
-       { /* QPI0 Port 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f33),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 1),
-       },
-       { /* QPI1 Port 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f3a),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 2),
-       },
-       { /* R2PCIe */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f34),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R2PCIE, 0),
-       },
-       { /* R3QPI0 Link 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f36),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 0),
-       },
-       { /* R3QPI0 Link 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f37),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 1),
-       },
-       { /* R3QPI1 Link 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f3e),
-               .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 2),
-       },
-       { /* QPI Port 0 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f86),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-                                                  SNBEP_PCI_QPI_PORT0_FILTER),
-       },
-       { /* QPI Port 1 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f96),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-                                                  SNBEP_PCI_QPI_PORT1_FILTER),
-       },
-       { /* PCU.3 (for Capability registers) */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fc0),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-                                                  HSWEP_PCI_PCU_3),
-       },
-       { /* end: all zeroes */ }
-};
-
-static struct pci_driver hswep_uncore_pci_driver = {
-       .name           = "hswep_uncore",
-       .id_table       = hswep_uncore_pci_ids,
-};
-
-int hswep_uncore_pci_init(void)
-{
-       int ret = snbep_pci2phy_map_init(0x2f1e);
-       if (ret)
-               return ret;
-       uncore_pci_uncores = hswep_pci_uncores;
-       uncore_pci_driver = &hswep_uncore_pci_driver;
-       return 0;
-}
-/* end of Haswell-EP uncore support */
-
-/* BDX uncore support */
-
-static struct intel_uncore_type bdx_uncore_ubox = {
-       .name                   = "ubox",
-       .num_counters           = 2,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .fixed_ctr_bits         = 48,
-       .perf_ctr               = HSWEP_U_MSR_PMON_CTR0,
-       .event_ctl              = HSWEP_U_MSR_PMON_CTL0,
-       .event_mask             = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
-       .fixed_ctr              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
-       .fixed_ctl              = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &ivbep_uncore_msr_ops,
-       .format_group           = &ivbep_uncore_ubox_format_group,
-};
-
-static struct event_constraint bdx_uncore_cbox_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x09, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x3e, 0x1),
-       EVENT_CONSTRAINT_END
-};
-
-static struct intel_uncore_type bdx_uncore_cbox = {
-       .name                   = "cbox",
-       .num_counters           = 4,
-       .num_boxes              = 24,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = HSWEP_C0_MSR_PMON_CTL0,
-       .perf_ctr               = HSWEP_C0_MSR_PMON_CTR0,
-       .event_mask             = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = HSWEP_C0_MSR_PMON_BOX_CTL,
-       .msr_offset             = HSWEP_CBO_MSR_OFFSET,
-       .num_shared_regs        = 1,
-       .constraints            = bdx_uncore_cbox_constraints,
-       .ops                    = &hswep_uncore_cbox_ops,
-       .format_group           = &hswep_uncore_cbox_format_group,
-};
-
-static struct intel_uncore_type bdx_uncore_sbox = {
-       .name                   = "sbox",
-       .num_counters           = 4,
-       .num_boxes              = 4,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = HSWEP_S0_MSR_PMON_CTL0,
-       .perf_ctr               = HSWEP_S0_MSR_PMON_CTR0,
-       .event_mask             = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = HSWEP_S0_MSR_PMON_BOX_CTL,
-       .msr_offset             = HSWEP_SBOX_MSR_OFFSET,
-       .ops                    = &hswep_uncore_sbox_msr_ops,
-       .format_group           = &hswep_uncore_sbox_format_group,
-};
-
-static struct intel_uncore_type *bdx_msr_uncores[] = {
-       &bdx_uncore_ubox,
-       &bdx_uncore_cbox,
-       &bdx_uncore_sbox,
-       &hswep_uncore_pcu,
-       NULL,
-};
-
-void bdx_uncore_cpu_init(void)
-{
-       if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
-               bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
-       uncore_msr_uncores = bdx_msr_uncores;
-}
-
-static struct intel_uncore_type bdx_uncore_ha = {
-       .name           = "ha",
-       .num_counters   = 4,
-       .num_boxes      = 2,
-       .perf_ctr_bits  = 48,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct intel_uncore_type bdx_uncore_imc = {
-       .name           = "imc",
-       .num_counters   = 5,
-       .num_boxes      = 8,
-       .perf_ctr_bits  = 48,
-       .fixed_ctr_bits = 48,
-       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
-       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
-       .event_descs    = hswep_uncore_imc_events,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct intel_uncore_type bdx_uncore_irp = {
-       .name                   = "irp",
-       .num_counters           = 4,
-       .num_boxes              = 1,
-       .perf_ctr_bits          = 48,
-       .event_mask             = SNBEP_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
-       .ops                    = &hswep_uncore_irp_ops,
-       .format_group           = &snbep_uncore_format_group,
-};
-
-static struct intel_uncore_type bdx_uncore_qpi = {
-       .name                   = "qpi",
-       .num_counters           = 4,
-       .num_boxes              = 3,
-       .perf_ctr_bits          = 48,
-       .perf_ctr               = SNBEP_PCI_PMON_CTR0,
-       .event_ctl              = SNBEP_PCI_PMON_CTL0,
-       .event_mask             = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
-       .box_ctl                = SNBEP_PCI_PMON_BOX_CTL,
-       .num_shared_regs        = 1,
-       .ops                    = &snbep_uncore_qpi_ops,
-       .format_group           = &snbep_uncore_qpi_format_group,
-};
-
-static struct event_constraint bdx_uncore_r2pcie_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x23, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x25, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
-       EVENT_CONSTRAINT_END
-};
-
-static struct intel_uncore_type bdx_uncore_r2pcie = {
-       .name           = "r2pcie",
-       .num_counters   = 4,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 48,
-       .constraints    = bdx_uncore_r2pcie_constraints,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-static struct event_constraint bdx_uncore_r3qpi_constraints[] = {
-       UNCORE_EVENT_CONSTRAINT(0x01, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x07, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x08, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x09, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x0a, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x0e, 0x7),
-       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
-       UNCORE_EVENT_CONSTRAINT(0x14, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x15, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x1f, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
-       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
-       EVENT_CONSTRAINT_END
-};
-
-static struct intel_uncore_type bdx_uncore_r3qpi = {
-       .name           = "r3qpi",
-       .num_counters   = 3,
-       .num_boxes      = 3,
-       .perf_ctr_bits  = 48,
-       .constraints    = bdx_uncore_r3qpi_constraints,
-       SNBEP_UNCORE_PCI_COMMON_INIT(),
-};
-
-enum {
-       BDX_PCI_UNCORE_HA,
-       BDX_PCI_UNCORE_IMC,
-       BDX_PCI_UNCORE_IRP,
-       BDX_PCI_UNCORE_QPI,
-       BDX_PCI_UNCORE_R2PCIE,
-       BDX_PCI_UNCORE_R3QPI,
-};
-
-static struct intel_uncore_type *bdx_pci_uncores[] = {
-       [BDX_PCI_UNCORE_HA]     = &bdx_uncore_ha,
-       [BDX_PCI_UNCORE_IMC]    = &bdx_uncore_imc,
-       [BDX_PCI_UNCORE_IRP]    = &bdx_uncore_irp,
-       [BDX_PCI_UNCORE_QPI]    = &bdx_uncore_qpi,
-       [BDX_PCI_UNCORE_R2PCIE] = &bdx_uncore_r2pcie,
-       [BDX_PCI_UNCORE_R3QPI]  = &bdx_uncore_r3qpi,
-       NULL,
-};
-
-static const struct pci_device_id bdx_uncore_pci_ids[] = {
-       { /* Home Agent 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f30),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_HA, 0),
-       },
-       { /* Home Agent 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f38),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_HA, 1),
-       },
-       { /* MC0 Channel 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb0),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 0),
-       },
-       { /* MC0 Channel 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb1),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 1),
-       },
-       { /* MC0 Channel 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb4),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 2),
-       },
-       { /* MC0 Channel 3 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fb5),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 3),
-       },
-       { /* MC1 Channel 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd0),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 4),
-       },
-       { /* MC1 Channel 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd1),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 5),
-       },
-       { /* MC1 Channel 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd4),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 6),
-       },
-       { /* MC1 Channel 3 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fd5),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IMC, 7),
-       },
-       { /* IRP */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f39),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_IRP, 0),
-       },
-       { /* QPI0 Port 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f32),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 0),
-       },
-       { /* QPI0 Port 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f33),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 1),
-       },
-       { /* QPI1 Port 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f3a),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_QPI, 2),
-       },
-       { /* R2PCIe */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f34),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R2PCIE, 0),
-       },
-       { /* R3QPI0 Link 0 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f36),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 0),
-       },
-       { /* R3QPI0 Link 1 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f37),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 1),
-       },
-       { /* R3QPI1 Link 2 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f3e),
-               .driver_data = UNCORE_PCI_DEV_DATA(BDX_PCI_UNCORE_R3QPI, 2),
-       },
-       { /* QPI Port 0 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f86),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 0),
-       },
-       { /* QPI Port 1 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f96),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 1),
-       },
-       { /* QPI Port 2 filter  */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6f46),
-               .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, 2),
-       },
-       { /* end: all zeroes */ }
-};
-
-static struct pci_driver bdx_uncore_pci_driver = {
-       .name           = "bdx_uncore",
-       .id_table       = bdx_uncore_pci_ids,
-};
-
-int bdx_uncore_pci_init(void)
-{
-       int ret = snbep_pci2phy_map_init(0x6f1e);
-
-       if (ret)
-               return ret;
-       uncore_pci_uncores = bdx_pci_uncores;
-       uncore_pci_driver = &bdx_uncore_pci_driver;
-       return 0;
-}
-
-/* end of BDX uncore support */
diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c
deleted file mode 100644 (file)
index 5b0c232..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/* Driver for Intel Xeon Phi "Knights Corner" PMU */
-
-#include <linux/perf_event.h>
-#include <linux/types.h>
-
-#include <asm/hardirq.h>
-
-#include "perf_event.h"
-
-static const u64 knc_perfmon_event_map[] =
-{
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x002a,
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x0016,
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0028,
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x0029,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x0012,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x002b,
-};
-
-static const u64 __initconst knc_hw_cache_event_ids
-                               [PERF_COUNT_HW_CACHE_MAX]
-                               [PERF_COUNT_HW_CACHE_OP_MAX]
-                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
-{
- [ C(L1D) ] = {
-       [ C(OP_READ) ] = {
-               /* On Xeon Phi event "0" is a valid DATA_READ          */
-               /*   (L1 Data Cache Reads) Instruction.                */
-               /* We code this as ARCH_PERFMON_EVENTSEL_INT as this   */
-               /* bit will always be set in x86_pmu_hw_config().      */
-               [ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
-                                               /* DATA_READ           */
-               [ C(RESULT_MISS)   ] = 0x0003,  /* DATA_READ_MISS      */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0001,  /* DATA_WRITE          */
-               [ C(RESULT_MISS)   ] = 0x0004,  /* DATA_WRITE_MISS     */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0011,  /* L1_DATA_PF1         */
-               [ C(RESULT_MISS)   ] = 0x001c,  /* L1_DATA_PF1_MISS    */
-       },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x000c,  /* CODE_READ          */
-               [ C(RESULT_MISS)   ] = 0x000e,  /* CODE_CACHE_MISS    */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0x10cb,  /* L2_READ_MISS */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x10cc,  /* L2_WRITE_HIT */
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x10fc,  /* L2_DATA_PF2      */
-               [ C(RESULT_MISS)   ] = 0x10fe,  /* L2_DATA_PF2_MISS */
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = ARCH_PERFMON_EVENTSEL_INT,
-                                               /* DATA_READ */
-                                               /* see note on L1 OP_READ */
-               [ C(RESULT_MISS)   ] = 0x0002,  /* DATA_PAGE_WALK */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0001,  /* DATA_WRITE */
-               [ C(RESULT_MISS)   ] = 0x0002,  /* DATA_PAGE_WALK */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = 0x0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x000c,  /* CODE_READ */
-               [ C(RESULT_MISS)   ] = 0x000d,  /* CODE_PAGE_WALK */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0012,  /* BRANCHES */
-               [ C(RESULT_MISS)   ] = 0x002b,  /* BRANCHES_MISPREDICTED */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
-};
-
-
-static u64 knc_pmu_event_map(int hw_event)
-{
-       return knc_perfmon_event_map[hw_event];
-}
-
-static struct event_constraint knc_event_constraints[] =
-{
-       INTEL_EVENT_CONSTRAINT(0xc3, 0x1),      /* HWP_L2HIT */
-       INTEL_EVENT_CONSTRAINT(0xc4, 0x1),      /* HWP_L2MISS */
-       INTEL_EVENT_CONSTRAINT(0xc8, 0x1),      /* L2_READ_HIT_E */
-       INTEL_EVENT_CONSTRAINT(0xc9, 0x1),      /* L2_READ_HIT_M */
-       INTEL_EVENT_CONSTRAINT(0xca, 0x1),      /* L2_READ_HIT_S */
-       INTEL_EVENT_CONSTRAINT(0xcb, 0x1),      /* L2_READ_MISS */
-       INTEL_EVENT_CONSTRAINT(0xcc, 0x1),      /* L2_WRITE_HIT */
-       INTEL_EVENT_CONSTRAINT(0xce, 0x1),      /* L2_STRONGLY_ORDERED_STREAMING_VSTORES_MISS */
-       INTEL_EVENT_CONSTRAINT(0xcf, 0x1),      /* L2_WEAKLY_ORDERED_STREAMING_VSTORE_MISS */
-       INTEL_EVENT_CONSTRAINT(0xd7, 0x1),      /* L2_VICTIM_REQ_WITH_DATA */
-       INTEL_EVENT_CONSTRAINT(0xe3, 0x1),      /* SNP_HITM_BUNIT */
-       INTEL_EVENT_CONSTRAINT(0xe6, 0x1),      /* SNP_HIT_L2 */
-       INTEL_EVENT_CONSTRAINT(0xe7, 0x1),      /* SNP_HITM_L2 */
-       INTEL_EVENT_CONSTRAINT(0xf1, 0x1),      /* L2_DATA_READ_MISS_CACHE_FILL */
-       INTEL_EVENT_CONSTRAINT(0xf2, 0x1),      /* L2_DATA_WRITE_MISS_CACHE_FILL */
-       INTEL_EVENT_CONSTRAINT(0xf6, 0x1),      /* L2_DATA_READ_MISS_MEM_FILL */
-       INTEL_EVENT_CONSTRAINT(0xf7, 0x1),      /* L2_DATA_WRITE_MISS_MEM_FILL */
-       INTEL_EVENT_CONSTRAINT(0xfc, 0x1),      /* L2_DATA_PF2 */
-       INTEL_EVENT_CONSTRAINT(0xfd, 0x1),      /* L2_DATA_PF2_DROP */
-       INTEL_EVENT_CONSTRAINT(0xfe, 0x1),      /* L2_DATA_PF2_MISS */
-       INTEL_EVENT_CONSTRAINT(0xff, 0x1),      /* L2_DATA_HIT_INFLIGHT_PF2 */
-       EVENT_CONSTRAINT_END
-};
-
-#define MSR_KNC_IA32_PERF_GLOBAL_STATUS                0x0000002d
-#define MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL   0x0000002e
-#define MSR_KNC_IA32_PERF_GLOBAL_CTRL          0x0000002f
-
-#define KNC_ENABLE_COUNTER0                    0x00000001
-#define KNC_ENABLE_COUNTER1                    0x00000002
-
-static void knc_pmu_disable_all(void)
-{
-       u64 val;
-
-       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
-       val &= ~(KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
-       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
-}
-
-static void knc_pmu_enable_all(int added)
-{
-       u64 val;
-
-       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
-       val |= (KNC_ENABLE_COUNTER0|KNC_ENABLE_COUNTER1);
-       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_CTRL, val);
-}
-
-static inline void
-knc_pmu_disable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 val;
-
-       val = hwc->config;
-       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
-
-       (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
-}
-
-static void knc_pmu_enable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 val;
-
-       val = hwc->config;
-       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
-
-       (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
-}
-
-static inline u64 knc_pmu_get_status(void)
-{
-       u64 status;
-
-       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
-
-       return status;
-}
-
-static inline void knc_pmu_ack_status(u64 ack)
-{
-       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
-}
-
-static int knc_pmu_handle_irq(struct pt_regs *regs)
-{
-       struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
-       int handled = 0;
-       int bit, loops;
-       u64 status;
-
-       cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       knc_pmu_disable_all();
-
-       status = knc_pmu_get_status();
-       if (!status) {
-               knc_pmu_enable_all(0);
-               return handled;
-       }
-
-       loops = 0;
-again:
-       knc_pmu_ack_status(status);
-       if (++loops > 100) {
-               WARN_ONCE(1, "perf: irq loop stuck!\n");
-               perf_event_print_debug();
-               goto done;
-       }
-
-       inc_irq_stat(apic_perf_irqs);
-
-       for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
-               struct perf_event *event = cpuc->events[bit];
-
-               handled++;
-
-               if (!test_bit(bit, cpuc->active_mask))
-                       continue;
-
-               if (!intel_pmu_save_and_restart(event))
-                       continue;
-
-               perf_sample_data_init(&data, 0, event->hw.last_period);
-
-               if (perf_event_overflow(event, &data, regs))
-                       x86_pmu_stop(event, 0);
-       }
-
-       /*
-        * Repeat if there is more work to be done:
-        */
-       status = knc_pmu_get_status();
-       if (status)
-               goto again;
-
-done:
-       knc_pmu_enable_all(0);
-
-       return handled;
-}
-
-
-PMU_FORMAT_ATTR(event, "config:0-7"    );
-PMU_FORMAT_ATTR(umask, "config:8-15"   );
-PMU_FORMAT_ATTR(edge,  "config:18"     );
-PMU_FORMAT_ATTR(inv,   "config:23"     );
-PMU_FORMAT_ATTR(cmask, "config:24-31"  );
-
-static struct attribute *intel_knc_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_inv.attr,
-       &format_attr_cmask.attr,
-       NULL,
-};
-
-static const struct x86_pmu knc_pmu __initconst = {
-       .name                   = "knc",
-       .handle_irq             = knc_pmu_handle_irq,
-       .disable_all            = knc_pmu_disable_all,
-       .enable_all             = knc_pmu_enable_all,
-       .enable                 = knc_pmu_enable_event,
-       .disable                = knc_pmu_disable_event,
-       .hw_config              = x86_pmu_hw_config,
-       .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_KNC_EVNTSEL0,
-       .perfctr                = MSR_KNC_PERFCTR0,
-       .event_map              = knc_pmu_event_map,
-       .max_events             = ARRAY_SIZE(knc_perfmon_event_map),
-       .apic                   = 1,
-       .max_period             = (1ULL << 39) - 1,
-       .version                = 0,
-       .num_counters           = 2,
-       .cntval_bits            = 40,
-       .cntval_mask            = (1ULL << 40) - 1,
-       .get_event_constraints  = x86_get_event_constraints,
-       .event_constraints      = knc_event_constraints,
-       .format_attrs           = intel_knc_formats_attr,
-};
-
-__init int knc_pmu_init(void)
-{
-       x86_pmu = knc_pmu;
-
-       memcpy(hw_cache_event_ids, knc_hw_cache_event_ids, 
-               sizeof(hw_cache_event_ids));
-
-       return 0;
-}
diff --git a/arch/x86/kernel/cpu/perf_event_msr.c b/arch/x86/kernel/cpu/perf_event_msr.c
deleted file mode 100644 (file)
index ec863b9..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-#include <linux/perf_event.h>
-
-enum perf_msr_id {
-       PERF_MSR_TSC                    = 0,
-       PERF_MSR_APERF                  = 1,
-       PERF_MSR_MPERF                  = 2,
-       PERF_MSR_PPERF                  = 3,
-       PERF_MSR_SMI                    = 4,
-
-       PERF_MSR_EVENT_MAX,
-};
-
-static bool test_aperfmperf(int idx)
-{
-       return boot_cpu_has(X86_FEATURE_APERFMPERF);
-}
-
-static bool test_intel(int idx)
-{
-       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-           boot_cpu_data.x86 != 6)
-               return false;
-
-       switch (boot_cpu_data.x86_model) {
-       case 30: /* 45nm Nehalem    */
-       case 26: /* 45nm Nehalem-EP */
-       case 46: /* 45nm Nehalem-EX */
-
-       case 37: /* 32nm Westmere    */
-       case 44: /* 32nm Westmere-EP */
-       case 47: /* 32nm Westmere-EX */
-
-       case 42: /* 32nm SandyBridge         */
-       case 45: /* 32nm SandyBridge-E/EN/EP */
-
-       case 58: /* 22nm IvyBridge       */
-       case 62: /* 22nm IvyBridge-EP/EX */
-
-       case 60: /* 22nm Haswell Core */
-       case 63: /* 22nm Haswell Server */
-       case 69: /* 22nm Haswell ULT */
-       case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
-
-       case 61: /* 14nm Broadwell Core-M */
-       case 86: /* 14nm Broadwell Xeon D */
-       case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
-       case 79: /* 14nm Broadwell Server */
-
-       case 55: /* 22nm Atom "Silvermont"                */
-       case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
-       case 76: /* 14nm Atom "Airmont"                   */
-               if (idx == PERF_MSR_SMI)
-                       return true;
-               break;
-
-       case 78: /* 14nm Skylake Mobile */
-       case 94: /* 14nm Skylake Desktop */
-               if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
-                       return true;
-               break;
-       }
-
-       return false;
-}
-
-struct perf_msr {
-       u64     msr;
-       struct  perf_pmu_events_attr *attr;
-       bool    (*test)(int idx);
-};
-
-PMU_EVENT_ATTR_STRING(tsc,   evattr_tsc,   "event=0x00");
-PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01");
-PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02");
-PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03");
-PMU_EVENT_ATTR_STRING(smi,   evattr_smi,   "event=0x04");
-
-static struct perf_msr msr[] = {
-       [PERF_MSR_TSC]   = { 0,                 &evattr_tsc,    NULL,            },
-       [PERF_MSR_APERF] = { MSR_IA32_APERF,    &evattr_aperf,  test_aperfmperf, },
-       [PERF_MSR_MPERF] = { MSR_IA32_MPERF,    &evattr_mperf,  test_aperfmperf, },
-       [PERF_MSR_PPERF] = { MSR_PPERF,         &evattr_pperf,  test_intel,      },
-       [PERF_MSR_SMI]   = { MSR_SMI_COUNT,     &evattr_smi,    test_intel,      },
-};
-
-static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
-       NULL,
-};
-
-static struct attribute_group events_attr_group = {
-       .name = "events",
-       .attrs = events_attrs,
-};
-
-PMU_FORMAT_ATTR(event, "config:0-63");
-static struct attribute *format_attrs[] = {
-       &format_attr_event.attr,
-       NULL,
-};
-static struct attribute_group format_attr_group = {
-       .name = "format",
-       .attrs = format_attrs,
-};
-
-static const struct attribute_group *attr_groups[] = {
-       &events_attr_group,
-       &format_attr_group,
-       NULL,
-};
-
-static int msr_event_init(struct perf_event *event)
-{
-       u64 cfg = event->attr.config;
-
-       if (event->attr.type != event->pmu->type)
-               return -ENOENT;
-
-       if (cfg >= PERF_MSR_EVENT_MAX)
-               return -EINVAL;
-
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
-               return -EINVAL;
-
-       if (!msr[cfg].attr)
-               return -EINVAL;
-
-       event->hw.idx = -1;
-       event->hw.event_base = msr[cfg].msr;
-       event->hw.config = cfg;
-
-       return 0;
-}
-
-static inline u64 msr_read_counter(struct perf_event *event)
-{
-       u64 now;
-
-       if (event->hw.event_base)
-               rdmsrl(event->hw.event_base, now);
-       else
-               rdtscll(now);
-
-       return now;
-}
-static void msr_event_update(struct perf_event *event)
-{
-       u64 prev, now;
-       s64 delta;
-
-       /* Careful, an NMI might modify the previous event value. */
-again:
-       prev = local64_read(&event->hw.prev_count);
-       now = msr_read_counter(event);
-
-       if (local64_cmpxchg(&event->hw.prev_count, prev, now) != prev)
-               goto again;
-
-       delta = now - prev;
-       if (unlikely(event->hw.event_base == MSR_SMI_COUNT))
-               delta = sign_extend64(delta, 31);
-
-       local64_add(now - prev, &event->count);
-}
-
-static void msr_event_start(struct perf_event *event, int flags)
-{
-       u64 now;
-
-       now = msr_read_counter(event);
-       local64_set(&event->hw.prev_count, now);
-}
-
-static void msr_event_stop(struct perf_event *event, int flags)
-{
-       msr_event_update(event);
-}
-
-static void msr_event_del(struct perf_event *event, int flags)
-{
-       msr_event_stop(event, PERF_EF_UPDATE);
-}
-
-static int msr_event_add(struct perf_event *event, int flags)
-{
-       if (flags & PERF_EF_START)
-               msr_event_start(event, flags);
-
-       return 0;
-}
-
-static struct pmu pmu_msr = {
-       .task_ctx_nr    = perf_sw_context,
-       .attr_groups    = attr_groups,
-       .event_init     = msr_event_init,
-       .add            = msr_event_add,
-       .del            = msr_event_del,
-       .start          = msr_event_start,
-       .stop           = msr_event_stop,
-       .read           = msr_event_update,
-       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
-};
-
-static int __init msr_init(void)
-{
-       int i, j = 0;
-
-       if (!boot_cpu_has(X86_FEATURE_TSC)) {
-               pr_cont("no MSR PMU driver.\n");
-               return 0;
-       }
-
-       /* Probe the MSRs. */
-       for (i = PERF_MSR_TSC + 1; i < PERF_MSR_EVENT_MAX; i++) {
-               u64 val;
-
-               /*
-                * Virt sucks arse; you cannot tell if a R/O MSR is present :/
-                */
-               if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
-                       msr[i].attr = NULL;
-       }
-
-       /* List remaining MSRs in the sysfs attrs. */
-       for (i = 0; i < PERF_MSR_EVENT_MAX; i++) {
-               if (msr[i].attr)
-                       events_attrs[j++] = &msr[i].attr->attr.attr;
-       }
-       events_attrs[j] = NULL;
-
-       perf_pmu_register(&pmu_msr, "msr", -1);
-
-       return 0;
-}
-device_initcall(msr_init);
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
deleted file mode 100644 (file)
index f2e5678..0000000
+++ /dev/null
@@ -1,1376 +0,0 @@
-/*
- * Netburst Performance Events (P4, old Xeon)
- *
- *  Copyright (C) 2010 Parallels, Inc., Cyrill Gorcunov <gorcunov@openvz.org>
- *  Copyright (C) 2010 Intel Corporation, Lin Ming <ming.m.lin@intel.com>
- *
- *  For licencing details see kernel-base/COPYING
- */
-
-#include <linux/perf_event.h>
-
-#include <asm/perf_event_p4.h>
-#include <asm/hardirq.h>
-#include <asm/apic.h>
-
-#include "perf_event.h"
-
-#define P4_CNTR_LIMIT 3
-/*
- * array indices: 0,1 - HT threads, used with HT enabled cpu
- */
-struct p4_event_bind {
-       unsigned int opcode;                    /* Event code and ESCR selector */
-       unsigned int escr_msr[2];               /* ESCR MSR for this event */
-       unsigned int escr_emask;                /* valid ESCR EventMask bits */
-       unsigned int shared;                    /* event is shared across threads */
-       char cntr[2][P4_CNTR_LIMIT];            /* counter index (offset), -1 on abscence */
-};
-
-struct p4_pebs_bind {
-       unsigned int metric_pebs;
-       unsigned int metric_vert;
-};
-
-/* it sets P4_PEBS_ENABLE_UOP_TAG as well */
-#define P4_GEN_PEBS_BIND(name, pebs, vert)                     \
-       [P4_PEBS_METRIC__##name] = {                            \
-               .metric_pebs = pebs | P4_PEBS_ENABLE_UOP_TAG,   \
-               .metric_vert = vert,                            \
-       }
-
-/*
- * note we have P4_PEBS_ENABLE_UOP_TAG always set here
- *
- * it's needed for mapping P4_PEBS_CONFIG_METRIC_MASK bits of
- * event configuration to find out which values are to be
- * written into MSR_IA32_PEBS_ENABLE and MSR_P4_PEBS_MATRIX_VERT
- * resgisters
- */
-static struct p4_pebs_bind p4_pebs_bind_map[] = {
-       P4_GEN_PEBS_BIND(1stl_cache_load_miss_retired,  0x0000001, 0x0000001),
-       P4_GEN_PEBS_BIND(2ndl_cache_load_miss_retired,  0x0000002, 0x0000001),
-       P4_GEN_PEBS_BIND(dtlb_load_miss_retired,        0x0000004, 0x0000001),
-       P4_GEN_PEBS_BIND(dtlb_store_miss_retired,       0x0000004, 0x0000002),
-       P4_GEN_PEBS_BIND(dtlb_all_miss_retired,         0x0000004, 0x0000003),
-       P4_GEN_PEBS_BIND(tagged_mispred_branch,         0x0018000, 0x0000010),
-       P4_GEN_PEBS_BIND(mob_load_replay_retired,       0x0000200, 0x0000001),
-       P4_GEN_PEBS_BIND(split_load_retired,            0x0000400, 0x0000001),
-       P4_GEN_PEBS_BIND(split_store_retired,           0x0000400, 0x0000002),
-};
-
-/*
- * Note that we don't use CCCR1 here, there is an
- * exception for P4_BSQ_ALLOCATION but we just have
- * no workaround
- *
- * consider this binding as resources which particular
- * event may borrow, it doesn't contain EventMask,
- * Tags and friends -- they are left to a caller
- */
-static struct p4_event_bind p4_event_bind_map[] = {
-       [P4_EVENT_TC_DELIVER_MODE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_TC_DELIVER_MODE),
-               .escr_msr       = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DD)                 |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DB)                 |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, DI)                 |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BD)                 |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BB)                 |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, BI)                 |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_DELIVER_MODE, ID),
-               .shared         = 1,
-               .cntr           = { {4, 5, -1}, {6, 7, -1} },
-       },
-       [P4_EVENT_BPU_FETCH_REQUEST] = {
-               .opcode         = P4_OPCODE(P4_EVENT_BPU_FETCH_REQUEST),
-               .escr_msr       = { MSR_P4_BPU_ESCR0, MSR_P4_BPU_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BPU_FETCH_REQUEST, TCMISS),
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_ITLB_REFERENCE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_ITLB_REFERENCE),
-               .escr_msr       = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT)                 |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, MISS)                |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_ITLB_REFERENCE, HIT_UK),
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_MEMORY_CANCEL] = {
-               .opcode         = P4_OPCODE(P4_EVENT_MEMORY_CANCEL),
-               .escr_msr       = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, ST_RB_FULL)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_CANCEL, 64K_CONF),
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_MEMORY_COMPLETE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_MEMORY_COMPLETE),
-               .escr_msr       = { MSR_P4_SAAT_ESCR0 , MSR_P4_SAAT_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, LSC)                |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MEMORY_COMPLETE, SSC),
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_LOAD_PORT_REPLAY] = {
-               .opcode         = P4_OPCODE(P4_EVENT_LOAD_PORT_REPLAY),
-               .escr_msr       = { MSR_P4_SAAT_ESCR0, MSR_P4_SAAT_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_LOAD_PORT_REPLAY, SPLIT_LD),
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_STORE_PORT_REPLAY] = {
-               .opcode         = P4_OPCODE(P4_EVENT_STORE_PORT_REPLAY),
-               .escr_msr       = { MSR_P4_SAAT_ESCR0 ,  MSR_P4_SAAT_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_STORE_PORT_REPLAY, SPLIT_ST),
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_MOB_LOAD_REPLAY] = {
-               .opcode         = P4_OPCODE(P4_EVENT_MOB_LOAD_REPLAY),
-               .escr_msr       = { MSR_P4_MOB_ESCR0, MSR_P4_MOB_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STA)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, NO_STD)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, PARTIAL_DATA)       |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MOB_LOAD_REPLAY, UNALGN_ADDR),
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_PAGE_WALK_TYPE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_PAGE_WALK_TYPE),
-               .escr_msr       = { MSR_P4_PMH_ESCR0, MSR_P4_PMH_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, DTMISS)              |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_PAGE_WALK_TYPE, ITMISS),
-               .shared         = 1,
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_BSQ_CACHE_REFERENCE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_BSQ_CACHE_REFERENCE),
-               .escr_msr       = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS),
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_IOQ_ALLOCATION] = {
-               .opcode         = P4_OPCODE(P4_EVENT_IOQ_ALLOCATION),
-               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, DEFAULT)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_READ)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, ALL_WRITE)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_UC)              |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WC)              |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WT)              |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WP)              |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, MEM_WB)              |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OWN)                 |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, OTHER)               |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ALLOCATION, PREFETCH),
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_IOQ_ACTIVE_ENTRIES] = {       /* shared ESCR */
-               .opcode         = P4_OPCODE(P4_EVENT_IOQ_ACTIVE_ENTRIES),
-               .escr_msr       = { MSR_P4_FSB_ESCR1,  MSR_P4_FSB_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, DEFAULT)         |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_READ)        |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_WRITE)       |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_UC)          |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WC)          |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WT)          |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WP)          |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WB)          |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OWN)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, OTHER)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_IOQ_ACTIVE_ENTRIES, PREFETCH),
-               .cntr           = { {2, -1, -1}, {3, -1, -1} },
-       },
-       [P4_EVENT_FSB_DATA_ACTIVITY] = {
-               .opcode         = P4_OPCODE(P4_EVENT_FSB_DATA_ACTIVITY),
-               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV)         |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN)         |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OTHER)       |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_DRV)         |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OWN)         |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OTHER),
-               .shared         = 1,
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_BSQ_ALLOCATION] = {           /* shared ESCR, broken CCCR1 */
-               .opcode         = P4_OPCODE(P4_EVENT_BSQ_ALLOCATION),
-               .escr_msr       = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR0 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE0)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE1)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN0)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LEN1)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_IO_TYPE)         |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_LOCK_TYPE)       |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_CACHE_TYPE)      |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_SPLIT_TYPE)      |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_DEM_TYPE)        |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, REQ_ORD_TYPE)        |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE0)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE1)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE2),
-               .cntr           = { {0, -1, -1}, {1, -1, -1} },
-       },
-       [P4_EVENT_BSQ_ACTIVE_ENTRIES] = {       /* shared ESCR */
-               .opcode         = P4_OPCODE(P4_EVENT_BSQ_ACTIVE_ENTRIES),
-               .escr_msr       = { MSR_P4_BSU_ESCR1 , MSR_P4_BSU_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE0)       |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE1)       |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN0)        |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN1)        |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_IO_TYPE)     |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LOCK_TYPE)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_CACHE_TYPE)  |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_SPLIT_TYPE)  |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_DEM_TYPE)    |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_ORD_TYPE)    |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE0)       |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE1)       |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE2),
-               .cntr           = { {2, -1, -1}, {3, -1, -1} },
-       },
-       [P4_EVENT_SSE_INPUT_ASSIST] = {
-               .opcode         = P4_OPCODE(P4_EVENT_SSE_INPUT_ASSIST),
-               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_SSE_INPUT_ASSIST, ALL),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_PACKED_SP_UOP] = {
-               .opcode         = P4_OPCODE(P4_EVENT_PACKED_SP_UOP),
-               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_SP_UOP, ALL),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_PACKED_DP_UOP] = {
-               .opcode         = P4_OPCODE(P4_EVENT_PACKED_DP_UOP),
-               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_PACKED_DP_UOP, ALL),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_SCALAR_SP_UOP] = {
-               .opcode         = P4_OPCODE(P4_EVENT_SCALAR_SP_UOP),
-               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_SP_UOP, ALL),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_SCALAR_DP_UOP] = {
-               .opcode         = P4_OPCODE(P4_EVENT_SCALAR_DP_UOP),
-               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_SCALAR_DP_UOP, ALL),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_64BIT_MMX_UOP] = {
-               .opcode         = P4_OPCODE(P4_EVENT_64BIT_MMX_UOP),
-               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_64BIT_MMX_UOP, ALL),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_128BIT_MMX_UOP] = {
-               .opcode         = P4_OPCODE(P4_EVENT_128BIT_MMX_UOP),
-               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_128BIT_MMX_UOP, ALL),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_X87_FP_UOP] = {
-               .opcode         = P4_OPCODE(P4_EVENT_X87_FP_UOP),
-               .escr_msr       = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_FP_UOP, ALL),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_TC_MISC] = {
-               .opcode         = P4_OPCODE(P4_EVENT_TC_MISC),
-               .escr_msr       = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_MISC, FLUSH),
-               .cntr           = { {4, 5, -1}, {6, 7, -1} },
-       },
-       [P4_EVENT_GLOBAL_POWER_EVENTS] = {
-               .opcode         = P4_OPCODE(P4_EVENT_GLOBAL_POWER_EVENTS),
-               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING),
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_TC_MS_XFER] = {
-               .opcode         = P4_OPCODE(P4_EVENT_TC_MS_XFER),
-               .escr_msr       = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_TC_MS_XFER, CISC),
-               .cntr           = { {4, 5, -1}, {6, 7, -1} },
-       },
-       [P4_EVENT_UOP_QUEUE_WRITES] = {
-               .opcode         = P4_OPCODE(P4_EVENT_UOP_QUEUE_WRITES),
-               .escr_msr       = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_BUILD)     |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_DELIVER)   |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_QUEUE_WRITES, FROM_ROM),
-               .cntr           = { {4, 5, -1}, {6, 7, -1} },
-       },
-       [P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE),
-               .escr_msr       = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR0 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CONDITIONAL)    |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CALL)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, RETURN)         |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, INDIRECT),
-               .cntr           = { {4, 5, -1}, {6, 7, -1} },
-       },
-       [P4_EVENT_RETIRED_BRANCH_TYPE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_RETIRED_BRANCH_TYPE),
-               .escr_msr       = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL)    |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CALL)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN)         |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT),
-               .cntr           = { {4, 5, -1}, {6, 7, -1} },
-       },
-       [P4_EVENT_RESOURCE_STALL] = {
-               .opcode         = P4_OPCODE(P4_EVENT_RESOURCE_STALL),
-               .escr_msr       = { MSR_P4_ALF_ESCR0, MSR_P4_ALF_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_RESOURCE_STALL, SBFULL),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_WC_BUFFER] = {
-               .opcode         = P4_OPCODE(P4_EVENT_WC_BUFFER),
-               .escr_msr       = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_EVICTS)               |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_WC_BUFFER, WCB_FULL_EVICTS),
-               .shared         = 1,
-               .cntr           = { {8, 9, -1}, {10, 11, -1} },
-       },
-       [P4_EVENT_B2B_CYCLES] = {
-               .opcode         = P4_OPCODE(P4_EVENT_B2B_CYCLES),
-               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
-               .escr_emask     = 0,
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_BNR] = {
-               .opcode         = P4_OPCODE(P4_EVENT_BNR),
-               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
-               .escr_emask     = 0,
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_SNOOP] = {
-               .opcode         = P4_OPCODE(P4_EVENT_SNOOP),
-               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
-               .escr_emask     = 0,
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_RESPONSE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_RESPONSE),
-               .escr_msr       = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 },
-               .escr_emask     = 0,
-               .cntr           = { {0, -1, -1}, {2, -1, -1} },
-       },
-       [P4_EVENT_FRONT_END_EVENT] = {
-               .opcode         = P4_OPCODE(P4_EVENT_FRONT_END_EVENT),
-               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, NBOGUS)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_FRONT_END_EVENT, BOGUS),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_EXECUTION_EVENT] = {
-               .opcode         = P4_OPCODE(P4_EVENT_EXECUTION_EVENT),
-               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_REPLAY_EVENT] = {
-               .opcode         = P4_OPCODE(P4_EVENT_REPLAY_EVENT),
-               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, NBOGUS)                |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_REPLAY_EVENT, BOGUS),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_INSTR_RETIRED] = {
-               .opcode         = P4_OPCODE(P4_EVENT_INSTR_RETIRED),
-               .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG)           |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSTAG)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSNTAG)            |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSTAG),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_UOPS_RETIRED] = {
-               .opcode         = P4_OPCODE(P4_EVENT_UOPS_RETIRED),
-               .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, NBOGUS)                |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_UOPS_RETIRED, BOGUS),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_UOP_TYPE] = {
-               .opcode         = P4_OPCODE(P4_EVENT_UOP_TYPE),
-               .escr_msr       = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGLOADS)                  |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_UOP_TYPE, TAGSTORES),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_BRANCH_RETIRED] = {
-               .opcode         = P4_OPCODE(P4_EVENT_BRANCH_RETIRED),
-               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNP)                |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMNM)                |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTP)                |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_BRANCH_RETIRED, MMTM),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_MISPRED_BRANCH_RETIRED] = {
-               .opcode         = P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED),
-               .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_X87_ASSIST] = {
-               .opcode         = P4_OPCODE(P4_EVENT_X87_ASSIST),
-               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSU)                    |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, FPSO)                    |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAO)                    |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, POAU)                    |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_X87_ASSIST, PREA),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_MACHINE_CLEAR] = {
-               .opcode         = P4_OPCODE(P4_EVENT_MACHINE_CLEAR),
-               .escr_msr       = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, CLEAR)                |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, MOCLEAR)              |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_MACHINE_CLEAR, SMCLEAR),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-       [P4_EVENT_INSTR_COMPLETED] = {
-               .opcode         = P4_OPCODE(P4_EVENT_INSTR_COMPLETED),
-               .escr_msr       = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 },
-               .escr_emask     =
-                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, NBOGUS)             |
-                       P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_COMPLETED, BOGUS),
-               .cntr           = { {12, 13, 16}, {14, 15, 17} },
-       },
-};
-
-#define P4_GEN_CACHE_EVENT(event, bit, metric)                           \
-       p4_config_pack_escr(P4_ESCR_EVENT(event)                        | \
-                           P4_ESCR_EMASK_BIT(event, bit))              | \
-       p4_config_pack_cccr(metric                                      | \
-                           P4_CCCR_ESEL(P4_OPCODE_ESEL(P4_OPCODE(event))))
-
-static __initconst const u64 p4_hw_cache_event_ids
-                               [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) ] = 0x0,
-               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS,
-                                               P4_PEBS_METRIC__1stl_cache_load_miss_retired),
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS,
-                                               P4_PEBS_METRIC__2ndl_cache_load_miss_retired),
-       },
-},
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS,
-                                               P4_PEBS_METRIC__dtlb_load_miss_retired),
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0,
-               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS,
-                                               P4_PEBS_METRIC__dtlb_store_miss_retired),
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, HIT,
-                                               P4_PEBS_METRIC__none),
-               [ C(RESULT_MISS)   ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, MISS,
-                                               P4_PEBS_METRIC__none),
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(NODE) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
-};
-
-/*
- * Because of Netburst being quite restricted in how many
- * identical events may run simultaneously, we introduce event aliases,
- * ie the different events which have the same functionality but
- * utilize non-intersected resources (ESCR/CCCR/counter registers).
- *
- * This allow us to relax restrictions a bit and run two or more
- * identical events together.
- *
- * Never set any custom internal bits such as P4_CONFIG_HT,
- * P4_CONFIG_ALIASABLE or bits for P4_PEBS_METRIC, they are
- * either up to date automatically or not applicable at all.
- */
-struct p4_event_alias {
-       u64 original;
-       u64 alternative;
-} p4_event_aliases[] = {
-       {
-               /*
-                * Non-halted cycles can be substituted with non-sleeping cycles (see
-                * Intel SDM Vol3b for details). We need this alias to be able
-                * to run nmi-watchdog and 'perf top' (or any other user space tool
-                * which is interested in running PERF_COUNT_HW_CPU_CYCLES)
-                * simultaneously.
-                */
-       .original       =
-               p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS)         |
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)),
-       .alternative    =
-               p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_EXECUTION_EVENT)             |
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS0)|
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS1)|
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS2)|
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, NBOGUS3)|
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS0) |
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS1) |
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS2) |
-                                   P4_ESCR_EMASK_BIT(P4_EVENT_EXECUTION_EVENT, BOGUS3))|
-               p4_config_pack_cccr(P4_CCCR_THRESHOLD(15) | P4_CCCR_COMPLEMENT          |
-                                   P4_CCCR_COMPARE),
-       },
-};
-
-static u64 p4_get_alias_event(u64 config)
-{
-       u64 config_match;
-       int i;
-
-       /*
-        * Only event with special mark is allowed,
-        * we're to be sure it didn't come as malformed
-        * RAW event.
-        */
-       if (!(config & P4_CONFIG_ALIASABLE))
-               return 0;
-
-       config_match = config & P4_CONFIG_EVENT_ALIAS_MASK;
-
-       for (i = 0; i < ARRAY_SIZE(p4_event_aliases); i++) {
-               if (config_match == p4_event_aliases[i].original) {
-                       config_match = p4_event_aliases[i].alternative;
-                       break;
-               } else if (config_match == p4_event_aliases[i].alternative) {
-                       config_match = p4_event_aliases[i].original;
-                       break;
-               }
-       }
-
-       if (i >= ARRAY_SIZE(p4_event_aliases))
-               return 0;
-
-       return config_match | (config & P4_CONFIG_EVENT_ALIAS_IMMUTABLE_BITS);
-}
-
-static u64 p4_general_events[PERF_COUNT_HW_MAX] = {
-  /* non-halted CPU clocks */
-  [PERF_COUNT_HW_CPU_CYCLES] =
-       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS)         |
-               P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING))       |
-               P4_CONFIG_ALIASABLE,
-
-  /*
-   * retired instructions
-   * in a sake of simplicity we don't use the FSB tagging
-   */
-  [PERF_COUNT_HW_INSTRUCTIONS] =
-       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_INSTR_RETIRED)               |
-               P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG)           |
-               P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSNTAG)),
-
-  /* cache hits */
-  [PERF_COUNT_HW_CACHE_REFERENCES] =
-       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_BSQ_CACHE_REFERENCE)         |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS)   |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE)   |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM)   |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS)   |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE)   |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM)),
-
-  /* cache misses */
-  [PERF_COUNT_HW_CACHE_MISSES] =
-       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_BSQ_CACHE_REFERENCE)         |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS)   |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS)   |
-               P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS)),
-
-  /* branch instructions retired */
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =
-       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_RETIRED_BRANCH_TYPE)         |
-               P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL)    |
-               P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CALL)           |
-               P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN)         |
-               P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT)),
-
-  /* mispredicted branches retired */
-  [PERF_COUNT_HW_BRANCH_MISSES]        =
-       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_MISPRED_BRANCH_RETIRED)      |
-               P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS)),
-
-  /* bus ready clocks (cpu is driving #DRDY_DRV\#DRDY_OWN):  */
-  [PERF_COUNT_HW_BUS_CYCLES] =
-       p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_FSB_DATA_ACTIVITY)           |
-               P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV)         |
-               P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN))        |
-       p4_config_pack_cccr(P4_CCCR_EDGE | P4_CCCR_COMPARE),
-};
-
-static struct p4_event_bind *p4_config_get_bind(u64 config)
-{
-       unsigned int evnt = p4_config_unpack_event(config);
-       struct p4_event_bind *bind = NULL;
-
-       if (evnt < ARRAY_SIZE(p4_event_bind_map))
-               bind = &p4_event_bind_map[evnt];
-
-       return bind;
-}
-
-static u64 p4_pmu_event_map(int hw_event)
-{
-       struct p4_event_bind *bind;
-       unsigned int esel;
-       u64 config;
-
-       config = p4_general_events[hw_event];
-       bind = p4_config_get_bind(config);
-       esel = P4_OPCODE_ESEL(bind->opcode);
-       config |= p4_config_pack_cccr(P4_CCCR_ESEL(esel));
-
-       return config;
-}
-
-/* check cpu model specifics */
-static bool p4_event_match_cpu_model(unsigned int event_idx)
-{
-       /* INSTR_COMPLETED event only exist for model 3, 4, 6 (Prescott) */
-       if (event_idx == P4_EVENT_INSTR_COMPLETED) {
-               if (boot_cpu_data.x86_model != 3 &&
-                       boot_cpu_data.x86_model != 4 &&
-                       boot_cpu_data.x86_model != 6)
-                       return false;
-       }
-
-       /*
-        * For info
-        * - IQ_ESCR0, IQ_ESCR1 only for models 1 and 2
-        */
-
-       return true;
-}
-
-static int p4_validate_raw_event(struct perf_event *event)
-{
-       unsigned int v, emask;
-
-       /* User data may have out-of-bound event index */
-       v = p4_config_unpack_event(event->attr.config);
-       if (v >= ARRAY_SIZE(p4_event_bind_map))
-               return -EINVAL;
-
-       /* It may be unsupported: */
-       if (!p4_event_match_cpu_model(v))
-               return -EINVAL;
-
-       /*
-        * NOTE: P4_CCCR_THREAD_ANY has not the same meaning as
-        * in Architectural Performance Monitoring, it means not
-        * on _which_ logical cpu to count but rather _when_, ie it
-        * depends on logical cpu state -- count event if one cpu active,
-        * none, both or any, so we just allow user to pass any value
-        * desired.
-        *
-        * In turn we always set Tx_OS/Tx_USR bits bound to logical
-        * cpu without their propagation to another cpu
-        */
-
-       /*
-        * if an event is shared across the logical threads
-        * the user needs special permissions to be able to use it
-        */
-       if (p4_ht_active() && p4_event_bind_map[v].shared) {
-               if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN))
-                       return -EACCES;
-       }
-
-       /* ESCR EventMask bits may be invalid */
-       emask = p4_config_unpack_escr(event->attr.config) & P4_ESCR_EVENTMASK_MASK;
-       if (emask & ~p4_event_bind_map[v].escr_emask)
-               return -EINVAL;
-
-       /*
-        * it may have some invalid PEBS bits
-        */
-       if (p4_config_pebs_has(event->attr.config, P4_PEBS_CONFIG_ENABLE))
-               return -EINVAL;
-
-       v = p4_config_unpack_metric(event->attr.config);
-       if (v >= ARRAY_SIZE(p4_pebs_bind_map))
-               return -EINVAL;
-
-       return 0;
-}
-
-static int p4_hw_config(struct perf_event *event)
-{
-       int cpu = get_cpu();
-       int rc = 0;
-       u32 escr, cccr;
-
-       /*
-        * the reason we use cpu that early is that: if we get scheduled
-        * first time on the same cpu -- we will not need swap thread
-        * specific flags in config (and will save some cpu cycles)
-        */
-
-       cccr = p4_default_cccr_conf(cpu);
-       escr = p4_default_escr_conf(cpu, event->attr.exclude_kernel,
-                                        event->attr.exclude_user);
-       event->hw.config = p4_config_pack_escr(escr) |
-                          p4_config_pack_cccr(cccr);
-
-       if (p4_ht_active() && p4_ht_thread(cpu))
-               event->hw.config = p4_set_ht_bit(event->hw.config);
-
-       if (event->attr.type == PERF_TYPE_RAW) {
-               struct p4_event_bind *bind;
-               unsigned int esel;
-               /*
-                * Clear bits we reserve to be managed by kernel itself
-                * and never allowed from a user space
-                */
-                event->attr.config &= P4_CONFIG_MASK;
-
-               rc = p4_validate_raw_event(event);
-               if (rc)
-                       goto out;
-
-               /*
-                * Note that for RAW events we allow user to use P4_CCCR_RESERVED
-                * bits since we keep additional info here (for cache events and etc)
-                */
-               event->hw.config |= event->attr.config;
-               bind = p4_config_get_bind(event->attr.config);
-               if (!bind) {
-                       rc = -EINVAL;
-                       goto out;
-               }
-               esel = P4_OPCODE_ESEL(bind->opcode);
-               event->hw.config |= p4_config_pack_cccr(P4_CCCR_ESEL(esel));
-       }
-
-       rc = x86_setup_perfctr(event);
-out:
-       put_cpu();
-       return rc;
-}
-
-static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
-{
-       u64 v;
-
-       /* an official way for overflow indication */
-       rdmsrl(hwc->config_base, v);
-       if (v & P4_CCCR_OVF) {
-               wrmsrl(hwc->config_base, v & ~P4_CCCR_OVF);
-               return 1;
-       }
-
-       /*
-        * In some circumstances the overflow might issue an NMI but did
-        * not set P4_CCCR_OVF bit. Because a counter holds a negative value
-        * we simply check for high bit being set, if it's cleared it means
-        * the counter has reached zero value and continued counting before
-        * real NMI signal was received:
-        */
-       rdmsrl(hwc->event_base, v);
-       if (!(v & ARCH_P4_UNFLAGGED_BIT))
-               return 1;
-
-       return 0;
-}
-
-static void p4_pmu_disable_pebs(void)
-{
-       /*
-        * FIXME
-        *
-        * It's still allowed that two threads setup same cache
-        * events so we can't simply clear metrics until we knew
-        * no one is depending on us, so we need kind of counter
-        * for "ReplayEvent" users.
-        *
-        * What is more complex -- RAW events, if user (for some
-        * reason) will pass some cache event metric with improper
-        * event opcode -- it's fine from hardware point of view
-        * but completely nonsense from "meaning" of such action.
-        *
-        * So at moment let leave metrics turned on forever -- it's
-        * ok for now but need to be revisited!
-        *
-        * (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, 0);
-        * (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT, 0);
-        */
-}
-
-static inline void p4_pmu_disable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-
-       /*
-        * If event gets disabled while counter is in overflowed
-        * state we need to clear P4_CCCR_OVF, otherwise interrupt get
-        * asserted again and again
-        */
-       (void)wrmsrl_safe(hwc->config_base,
-               p4_config_unpack_cccr(hwc->config) & ~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED);
-}
-
-static void p4_pmu_disable_all(void)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       int idx;
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               struct perf_event *event = cpuc->events[idx];
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-               p4_pmu_disable_event(event);
-       }
-
-       p4_pmu_disable_pebs();
-}
-
-/* configuration must be valid */
-static void p4_pmu_enable_pebs(u64 config)
-{
-       struct p4_pebs_bind *bind;
-       unsigned int idx;
-
-       BUILD_BUG_ON(P4_PEBS_METRIC__max > P4_PEBS_CONFIG_METRIC_MASK);
-
-       idx = p4_config_unpack_metric(config);
-       if (idx == P4_PEBS_METRIC__none)
-               return;
-
-       bind = &p4_pebs_bind_map[idx];
-
-       (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, (u64)bind->metric_pebs);
-       (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT,      (u64)bind->metric_vert);
-}
-
-static void p4_pmu_enable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       int thread = p4_ht_config_thread(hwc->config);
-       u64 escr_conf = p4_config_unpack_escr(p4_clear_ht_bit(hwc->config));
-       unsigned int idx = p4_config_unpack_event(hwc->config);
-       struct p4_event_bind *bind;
-       u64 escr_addr, cccr;
-
-       bind = &p4_event_bind_map[idx];
-       escr_addr = bind->escr_msr[thread];
-
-       /*
-        * - we dont support cascaded counters yet
-        * - and counter 1 is broken (erratum)
-        */
-       WARN_ON_ONCE(p4_is_event_cascaded(hwc->config));
-       WARN_ON_ONCE(hwc->idx == 1);
-
-       /* we need a real Event value */
-       escr_conf &= ~P4_ESCR_EVENT_MASK;
-       escr_conf |= P4_ESCR_EVENT(P4_OPCODE_EVNT(bind->opcode));
-
-       cccr = p4_config_unpack_cccr(hwc->config);
-
-       /*
-        * it could be Cache event so we need to write metrics
-        * into additional MSRs
-        */
-       p4_pmu_enable_pebs(hwc->config);
-
-       (void)wrmsrl_safe(escr_addr, escr_conf);
-       (void)wrmsrl_safe(hwc->config_base,
-                               (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
-}
-
-static void p4_pmu_enable_all(int added)
-{
-       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-       int idx;
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               struct perf_event *event = cpuc->events[idx];
-               if (!test_bit(idx, cpuc->active_mask))
-                       continue;
-               p4_pmu_enable_event(event);
-       }
-}
-
-static int p4_pmu_handle_irq(struct pt_regs *regs)
-{
-       struct perf_sample_data data;
-       struct cpu_hw_events *cpuc;
-       struct perf_event *event;
-       struct hw_perf_event *hwc;
-       int idx, handled = 0;
-       u64 val;
-
-       cpuc = this_cpu_ptr(&cpu_hw_events);
-
-       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               int overflow;
-
-               if (!test_bit(idx, cpuc->active_mask)) {
-                       /* catch in-flight IRQs */
-                       if (__test_and_clear_bit(idx, cpuc->running))
-                               handled++;
-                       continue;
-               }
-
-               event = cpuc->events[idx];
-               hwc = &event->hw;
-
-               WARN_ON_ONCE(hwc->idx != idx);
-
-               /* it might be unflagged overflow */
-               overflow = p4_pmu_clear_cccr_ovf(hwc);
-
-               val = x86_perf_event_update(event);
-               if (!overflow && (val & (1ULL << (x86_pmu.cntval_bits - 1))))
-                       continue;
-
-               handled += overflow;
-
-               /* event overflow for sure */
-               perf_sample_data_init(&data, 0, hwc->last_period);
-
-               if (!x86_perf_event_set_period(event))
-                       continue;
-
-
-               if (perf_event_overflow(event, &data, regs))
-                       x86_pmu_stop(event, 0);
-       }
-
-       if (handled)
-               inc_irq_stat(apic_perf_irqs);
-
-       /*
-        * When dealing with the unmasking of the LVTPC on P4 perf hw, it has
-        * been observed that the OVF bit flag has to be cleared first _before_
-        * the LVTPC can be unmasked.
-        *
-        * The reason is the NMI line will continue to be asserted while the OVF
-        * bit is set.  This causes a second NMI to generate if the LVTPC is
-        * unmasked before the OVF bit is cleared, leading to unknown NMI
-        * messages.
-        */
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-
-       return handled;
-}
-
-/*
- * swap thread specific fields according to a thread
- * we are going to run on
- */
-static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu)
-{
-       u32 escr, cccr;
-
-       /*
-        * we either lucky and continue on same cpu or no HT support
-        */
-       if (!p4_should_swap_ts(hwc->config, cpu))
-               return;
-
-       /*
-        * the event is migrated from an another logical
-        * cpu, so we need to swap thread specific flags
-        */
-
-       escr = p4_config_unpack_escr(hwc->config);
-       cccr = p4_config_unpack_cccr(hwc->config);
-
-       if (p4_ht_thread(cpu)) {
-               cccr &= ~P4_CCCR_OVF_PMI_T0;
-               cccr |= P4_CCCR_OVF_PMI_T1;
-               if (escr & P4_ESCR_T0_OS) {
-                       escr &= ~P4_ESCR_T0_OS;
-                       escr |= P4_ESCR_T1_OS;
-               }
-               if (escr & P4_ESCR_T0_USR) {
-                       escr &= ~P4_ESCR_T0_USR;
-                       escr |= P4_ESCR_T1_USR;
-               }
-               hwc->config  = p4_config_pack_escr(escr);
-               hwc->config |= p4_config_pack_cccr(cccr);
-               hwc->config |= P4_CONFIG_HT;
-       } else {
-               cccr &= ~P4_CCCR_OVF_PMI_T1;
-               cccr |= P4_CCCR_OVF_PMI_T0;
-               if (escr & P4_ESCR_T1_OS) {
-                       escr &= ~P4_ESCR_T1_OS;
-                       escr |= P4_ESCR_T0_OS;
-               }
-               if (escr & P4_ESCR_T1_USR) {
-                       escr &= ~P4_ESCR_T1_USR;
-                       escr |= P4_ESCR_T0_USR;
-               }
-               hwc->config  = p4_config_pack_escr(escr);
-               hwc->config |= p4_config_pack_cccr(cccr);
-               hwc->config &= ~P4_CONFIG_HT;
-       }
-}
-
-/*
- * ESCR address hashing is tricky, ESCRs are not sequential
- * in memory but all starts from MSR_P4_BSU_ESCR0 (0x03a0) and
- * the metric between any ESCRs is laid in range [0xa0,0xe1]
- *
- * so we make ~70% filled hashtable
- */
-
-#define P4_ESCR_MSR_BASE               0x000003a0
-#define P4_ESCR_MSR_MAX                        0x000003e1
-#define P4_ESCR_MSR_TABLE_SIZE         (P4_ESCR_MSR_MAX - P4_ESCR_MSR_BASE + 1)
-#define P4_ESCR_MSR_IDX(msr)           (msr - P4_ESCR_MSR_BASE)
-#define P4_ESCR_MSR_TABLE_ENTRY(msr)   [P4_ESCR_MSR_IDX(msr)] = msr
-
-static const unsigned int p4_escr_table[P4_ESCR_MSR_TABLE_SIZE] = {
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ALF_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ALF_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BPU_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BPU_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BSU_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BSU_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR2),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR3),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR4),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR5),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_DAC_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_DAC_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FIRM_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FIRM_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FLAME_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FLAME_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FSB_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FSB_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IQ_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IQ_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IS_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IS_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ITLB_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ITLB_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IX_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IX_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MOB_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MOB_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MS_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MS_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_PMH_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_PMH_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_RAT_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_RAT_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SAAT_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SAAT_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SSU_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SSU_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TBPU_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TBPU_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TC_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TC_ESCR1),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_U2L_ESCR0),
-       P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_U2L_ESCR1),
-};
-
-static int p4_get_escr_idx(unsigned int addr)
-{
-       unsigned int idx = P4_ESCR_MSR_IDX(addr);
-
-       if (unlikely(idx >= P4_ESCR_MSR_TABLE_SIZE      ||
-                       !p4_escr_table[idx]             ||
-                       p4_escr_table[idx] != addr)) {
-               WARN_ONCE(1, "P4 PMU: Wrong address passed: %x\n", addr);
-               return -1;
-       }
-
-       return idx;
-}
-
-static int p4_next_cntr(int thread, unsigned long *used_mask,
-                       struct p4_event_bind *bind)
-{
-       int i, j;
-
-       for (i = 0; i < P4_CNTR_LIMIT; i++) {
-               j = bind->cntr[thread][i];
-               if (j != -1 && !test_bit(j, used_mask))
-                       return j;
-       }
-
-       return -1;
-}
-
-static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
-{
-       unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
-       unsigned long escr_mask[BITS_TO_LONGS(P4_ESCR_MSR_TABLE_SIZE)];
-       int cpu = smp_processor_id();
-       struct hw_perf_event *hwc;
-       struct p4_event_bind *bind;
-       unsigned int i, thread, num;
-       int cntr_idx, escr_idx;
-       u64 config_alias;
-       int pass;
-
-       bitmap_zero(used_mask, X86_PMC_IDX_MAX);
-       bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE);
-
-       for (i = 0, num = n; i < n; i++, num--) {
-
-               hwc = &cpuc->event_list[i]->hw;
-               thread = p4_ht_thread(cpu);
-               pass = 0;
-
-again:
-               /*
-                * It's possible to hit a circular lock
-                * between original and alternative events
-                * if both are scheduled already.
-                */
-               if (pass > 2)
-                       goto done;
-
-               bind = p4_config_get_bind(hwc->config);
-               escr_idx = p4_get_escr_idx(bind->escr_msr[thread]);
-               if (unlikely(escr_idx == -1))
-                       goto done;
-
-               if (hwc->idx != -1 && !p4_should_swap_ts(hwc->config, cpu)) {
-                       cntr_idx = hwc->idx;
-                       if (assign)
-                               assign[i] = hwc->idx;
-                       goto reserve;
-               }
-
-               cntr_idx = p4_next_cntr(thread, used_mask, bind);
-               if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) {
-                       /*
-                        * Check whether an event alias is still available.
-                        */
-                       config_alias = p4_get_alias_event(hwc->config);
-                       if (!config_alias)
-                               goto done;
-                       hwc->config = config_alias;
-                       pass++;
-                       goto again;
-               }
-               /*
-                * Perf does test runs to see if a whole group can be assigned
-                * together succesfully.  There can be multiple rounds of this.
-                * Unfortunately, p4_pmu_swap_config_ts touches the hwc->config
-                * bits, such that the next round of group assignments will
-                * cause the above p4_should_swap_ts to pass instead of fail.
-                * This leads to counters exclusive to thread0 being used by
-                * thread1.
-                *
-                * Solve this with a cheap hack, reset the idx back to -1 to
-                * force a new lookup (p4_next_cntr) to get the right counter
-                * for the right thread.
-                *
-                * This probably doesn't comply with the general spirit of how
-                * perf wants to work, but P4 is special. :-(
-                */
-               if (p4_should_swap_ts(hwc->config, cpu))
-                       hwc->idx = -1;
-               p4_pmu_swap_config_ts(hwc, cpu);
-               if (assign)
-                       assign[i] = cntr_idx;
-reserve:
-               set_bit(cntr_idx, used_mask);
-               set_bit(escr_idx, escr_mask);
-       }
-
-done:
-       return num ? -EINVAL : 0;
-}
-
-PMU_FORMAT_ATTR(cccr, "config:0-31" );
-PMU_FORMAT_ATTR(escr, "config:32-62");
-PMU_FORMAT_ATTR(ht,   "config:63"   );
-
-static struct attribute *intel_p4_formats_attr[] = {
-       &format_attr_cccr.attr,
-       &format_attr_escr.attr,
-       &format_attr_ht.attr,
-       NULL,
-};
-
-static __initconst const struct x86_pmu p4_pmu = {
-       .name                   = "Netburst P4/Xeon",
-       .handle_irq             = p4_pmu_handle_irq,
-       .disable_all            = p4_pmu_disable_all,
-       .enable_all             = p4_pmu_enable_all,
-       .enable                 = p4_pmu_enable_event,
-       .disable                = p4_pmu_disable_event,
-       .eventsel               = MSR_P4_BPU_CCCR0,
-       .perfctr                = MSR_P4_BPU_PERFCTR0,
-       .event_map              = p4_pmu_event_map,
-       .max_events             = ARRAY_SIZE(p4_general_events),
-       .get_event_constraints  = x86_get_event_constraints,
-       /*
-        * IF HT disabled we may need to use all
-        * ARCH_P4_MAX_CCCR counters simulaneously
-        * though leave it restricted at moment assuming
-        * HT is on
-        */
-       .num_counters           = ARCH_P4_MAX_CCCR,
-       .apic                   = 1,
-       .cntval_bits            = ARCH_P4_CNTRVAL_BITS,
-       .cntval_mask            = ARCH_P4_CNTRVAL_MASK,
-       .max_period             = (1ULL << (ARCH_P4_CNTRVAL_BITS - 1)) - 1,
-       .hw_config              = p4_hw_config,
-       .schedule_events        = p4_pmu_schedule_events,
-       /*
-        * This handles erratum N15 in intel doc 249199-029,
-        * the counter may not be updated correctly on write
-        * so we need a second write operation to do the trick
-        * (the official workaround didn't work)
-        *
-        * the former idea is taken from OProfile code
-        */
-       .perfctr_second_write   = 1,
-
-       .format_attrs           = intel_p4_formats_attr,
-};
-
-__init int p4_pmu_init(void)
-{
-       unsigned int low, high;
-       int i, reg;
-
-       /* If we get stripped -- indexing fails */
-       BUILD_BUG_ON(ARCH_P4_MAX_CCCR > INTEL_PMC_MAX_GENERIC);
-
-       rdmsr(MSR_IA32_MISC_ENABLE, low, high);
-       if (!(low & (1 << 7))) {
-               pr_cont("unsupported Netburst CPU model %d ",
-                       boot_cpu_data.x86_model);
-               return -ENODEV;
-       }
-
-       memcpy(hw_cache_event_ids, p4_hw_cache_event_ids,
-               sizeof(hw_cache_event_ids));
-
-       pr_cont("Netburst events, ");
-
-       x86_pmu = p4_pmu;
-
-       /*
-        * Even though the counters are configured to interrupt a particular
-        * logical processor when an overflow happens, testing has shown that
-        * on kdump kernels (which uses a single cpu), thread1's counter
-        * continues to run and will report an NMI on thread0.  Due to the
-        * overflow bug, this leads to a stream of unknown NMIs.
-        *
-        * Solve this by zero'ing out the registers to mimic a reset.
-        */
-       for (i = 0; i < x86_pmu.num_counters; i++) {
-               reg = x86_pmu_config_addr(i);
-               wrmsrl_safe(reg, 0ULL);
-       }
-
-       return 0;
-}
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
deleted file mode 100644 (file)
index 7c1a0c0..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-#include <linux/perf_event.h>
-#include <linux/types.h>
-
-#include "perf_event.h"
-
-/*
- * Not sure about some of these
- */
-static const u64 p6_perfmon_event_map[] =
-{
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,       /* CPU_CLK_UNHALTED */
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,       /* INST_RETIRED     */
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,       /* L2_RQSTS:M:E:S:I */
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,       /* L2_RQSTS:I       */
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,       /* BR_INST_RETIRED  */
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,       /* BR_MISS_PRED_RETIRED */
-  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,       /* BUS_DRDY_CLOCKS  */
-  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,    /* RESOURCE_STALLS  */
-
-};
-
-static const u64 __initconst p6_hw_cache_event_ids
-                               [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) ] = 0x0043,  /* DATA_MEM_REFS       */
-                [ C(RESULT_MISS)   ] = 0x0045, /* DCU_LINES_IN        */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0x0f29,  /* L2_LD:M:E:S:I       */
-       },
-        [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-        },
- },
- [ C(L1I ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
-               [ C(RESULT_MISS)   ] = 0x0f28,  /* L2_IFETCH:M:E:S:I  */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(LL  ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0x0025,  /* L2_M_LINES_INM     */
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(DTLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS      */
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = 0,
-               [ C(RESULT_MISS)   ] = 0,
-       },
- },
- [ C(ITLB) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
-               [ C(RESULT_MISS)   ] = 0x0085,  /* ITLB_MISS          */
-       },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
- [ C(BPU ) ] = {
-       [ C(OP_READ) ] = {
-               [ C(RESULT_ACCESS) ] = 0x00c4,  /* BR_INST_RETIRED      */
-               [ C(RESULT_MISS)   ] = 0x00c5,  /* BR_MISS_PRED_RETIRED */
-        },
-       [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
-       [ C(OP_PREFETCH) ] = {
-               [ C(RESULT_ACCESS) ] = -1,
-               [ C(RESULT_MISS)   ] = -1,
-       },
- },
-};
-
-static u64 p6_pmu_event_map(int hw_event)
-{
-       return p6_perfmon_event_map[hw_event];
-}
-
-/*
- * Event setting that is specified not to count anything.
- * We use this to effectively disable a counter.
- *
- * L2_RQSTS with 0 MESI unit mask.
- */
-#define P6_NOP_EVENT                   0x0000002EULL
-
-static struct event_constraint p6_event_constraints[] =
-{
-       INTEL_EVENT_CONSTRAINT(0xc1, 0x1),      /* FLOPS */
-       INTEL_EVENT_CONSTRAINT(0x10, 0x1),      /* FP_COMP_OPS_EXE */
-       INTEL_EVENT_CONSTRAINT(0x11, 0x2),      /* FP_ASSIST */
-       INTEL_EVENT_CONSTRAINT(0x12, 0x2),      /* MUL */
-       INTEL_EVENT_CONSTRAINT(0x13, 0x2),      /* DIV */
-       INTEL_EVENT_CONSTRAINT(0x14, 0x1),      /* CYCLES_DIV_BUSY */
-       EVENT_CONSTRAINT_END
-};
-
-static void p6_pmu_disable_all(void)
-{
-       u64 val;
-
-       /* p6 only has one enable register */
-       rdmsrl(MSR_P6_EVNTSEL0, val);
-       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
-       wrmsrl(MSR_P6_EVNTSEL0, val);
-}
-
-static void p6_pmu_enable_all(int added)
-{
-       unsigned long val;
-
-       /* p6 only has one enable register */
-       rdmsrl(MSR_P6_EVNTSEL0, val);
-       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
-       wrmsrl(MSR_P6_EVNTSEL0, val);
-}
-
-static inline void
-p6_pmu_disable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 val = P6_NOP_EVENT;
-
-       (void)wrmsrl_safe(hwc->config_base, val);
-}
-
-static void p6_pmu_enable_event(struct perf_event *event)
-{
-       struct hw_perf_event *hwc = &event->hw;
-       u64 val;
-
-       val = hwc->config;
-
-       /*
-        * p6 only has a global event enable, set on PerfEvtSel0
-        * We "disable" events by programming P6_NOP_EVENT
-        * and we rely on p6_pmu_enable_all() being called
-        * to actually enable the events.
-        */
-
-       (void)wrmsrl_safe(hwc->config_base, val);
-}
-
-PMU_FORMAT_ATTR(event, "config:0-7"    );
-PMU_FORMAT_ATTR(umask, "config:8-15"   );
-PMU_FORMAT_ATTR(edge,  "config:18"     );
-PMU_FORMAT_ATTR(pc,    "config:19"     );
-PMU_FORMAT_ATTR(inv,   "config:23"     );
-PMU_FORMAT_ATTR(cmask, "config:24-31"  );
-
-static struct attribute *intel_p6_formats_attr[] = {
-       &format_attr_event.attr,
-       &format_attr_umask.attr,
-       &format_attr_edge.attr,
-       &format_attr_pc.attr,
-       &format_attr_inv.attr,
-       &format_attr_cmask.attr,
-       NULL,
-};
-
-static __initconst const struct x86_pmu p6_pmu = {
-       .name                   = "p6",
-       .handle_irq             = x86_pmu_handle_irq,
-       .disable_all            = p6_pmu_disable_all,
-       .enable_all             = p6_pmu_enable_all,
-       .enable                 = p6_pmu_enable_event,
-       .disable                = p6_pmu_disable_event,
-       .hw_config              = x86_pmu_hw_config,
-       .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_P6_EVNTSEL0,
-       .perfctr                = MSR_P6_PERFCTR0,
-       .event_map              = p6_pmu_event_map,
-       .max_events             = ARRAY_SIZE(p6_perfmon_event_map),
-       .apic                   = 1,
-       .max_period             = (1ULL << 31) - 1,
-       .version                = 0,
-       .num_counters           = 2,
-       /*
-        * Events have 40 bits implemented. However they are designed such
-        * that bits [32-39] are sign extensions of bit 31. As such the
-        * effective width of a event for P6-like PMU is 32 bits only.
-        *
-        * See IA-32 Intel Architecture Software developer manual Vol 3B
-        */
-       .cntval_bits            = 32,
-       .cntval_mask            = (1ULL << 32) - 1,
-       .get_event_constraints  = x86_get_event_constraints,
-       .event_constraints      = p6_event_constraints,
-
-       .format_attrs           = intel_p6_formats_attr,
-       .events_sysfs_show      = intel_event_sysfs_show,
-
-};
-
-static __init void p6_pmu_rdpmc_quirk(void)
-{
-       if (boot_cpu_data.x86_mask < 9) {
-               /*
-                * PPro erratum 26; fixed in stepping 9 and above.
-                */
-               pr_warn("Userspace RDPMC support disabled due to a CPU erratum\n");
-               x86_pmu.attr_rdpmc_broken = 1;
-               x86_pmu.attr_rdpmc = 0;
-       }
-}
-
-__init int p6_pmu_init(void)
-{
-       x86_pmu = p6_pmu;
-
-       switch (boot_cpu_data.x86_model) {
-       case  1: /* Pentium Pro */
-               x86_add_quirk(p6_pmu_rdpmc_quirk);
-               break;
-
-       case  3: /* Pentium II - Klamath */
-       case  5: /* Pentium II - Deschutes */
-       case  6: /* Pentium II - Mendocino */
-               break;
-
-       case  7: /* Pentium III - Katmai */
-       case  8: /* Pentium III - Coppermine */
-       case 10: /* Pentium III Xeon */
-       case 11: /* Pentium III - Tualatin */
-               break;
-
-       case  9: /* Pentium M - Banias */
-       case 13: /* Pentium M - Dothan */
-               break;
-
-       default:
-               pr_cont("unsupported p6 CPU model %d ", boot_cpu_data.x86_model);
-               return -ENODEV;
-       }
-
-       memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
-               sizeof(hw_cache_event_ids));
-
-       return 0;
-}
index 819d94982e078b8597f084f8409fcd3106361293..f6f50c4ceaeceef16170d14d6d55376823bbd63f 100644 (file)
@@ -51,7 +51,7 @@ void x86_init_rdrand(struct cpuinfo_x86 *c)
        for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
                if (!rdrand_long(&tmp)) {
                        clear_cpu_cap(c, X86_FEATURE_RDRAND);
-                       printk_once(KERN_WARNING "rdrand: disabled\n");
+                       pr_warn_once("rdrand: disabled\n");
                        return;
                }
        }
index 4c60eaf0571c2fb1a6d73258861398fc6bcc963e..cd531355e8386b4177d4dcecaf1031ba8c2086c8 100644 (file)
@@ -87,10 +87,10 @@ void detect_extended_topology(struct cpuinfo_x86 *c)
        c->x86_max_cores = (core_level_siblings / smp_num_siblings);
 
        if (!printed) {
-               printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
+               pr_info("CPU: Physical Processor ID: %d\n",
                       c->phys_proc_id);
                if (c->x86_max_cores > 1)
-                       printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
+                       pr_info("CPU: Processor Core ID: %d\n",
                               c->cpu_core_id);
                printed = 1;
        }
index 252da7aceca67ff580e8189ed267b2ce44d83373..34178564be2a70adbeaf3fd890cac32d97a51635 100644 (file)
@@ -1,6 +1,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <asm/msr.h>
 #include "cpu.h"
 
@@ -33,7 +33,7 @@ static void init_transmeta(struct cpuinfo_x86 *c)
        if (max >= 0x80860001) {
                cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags);
                if (cpu_rev != 0x02000000) {
-                       printk(KERN_INFO "CPU: Processor revision %u.%u.%u.%u, %u MHz\n",
+                       pr_info("CPU: Processor revision %u.%u.%u.%u, %u MHz\n",
                                (cpu_rev >> 24) & 0xff,
                                (cpu_rev >> 16) & 0xff,
                                (cpu_rev >> 8) & 0xff,
@@ -44,10 +44,10 @@ static void init_transmeta(struct cpuinfo_x86 *c)
        if (max >= 0x80860002) {
                cpuid(0x80860002, &new_cpu_rev, &cms_rev1, &cms_rev2, &dummy);
                if (cpu_rev == 0x02000000) {
-                       printk(KERN_INFO "CPU: Processor revision %08X, %u MHz\n",
+                       pr_info("CPU: Processor revision %08X, %u MHz\n",
                                new_cpu_rev, cpu_freq);
                }
-               printk(KERN_INFO "CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n",
+               pr_info("CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n",
                       (cms_rev1 >> 24) & 0xff,
                       (cms_rev1 >> 16) & 0xff,
                       (cms_rev1 >> 8) & 0xff,
@@ -76,7 +76,7 @@ static void init_transmeta(struct cpuinfo_x86 *c)
                      (void *)&cpu_info[56],
                      (void *)&cpu_info[60]);
                cpu_info[64] = '\0';
-               printk(KERN_INFO "CPU: %s\n", cpu_info);
+               pr_info("CPU: %s\n", cpu_info);
        }
 
        /* Unhide possibly hidden capability flags */
index 628a059a9a0663ef7cbdf07e4750c9e1e4f53006..364e5834689753fc7da34c6dc8a34cca22ab92db 100644 (file)
@@ -62,7 +62,7 @@ static unsigned long vmware_get_tsc_khz(void)
        tsc_hz = eax | (((uint64_t)ebx) << 32);
        do_div(tsc_hz, 1000);
        BUG_ON(tsc_hz >> 32);
-       printk(KERN_INFO "TSC freq read from hypervisor : %lu.%03lu MHz\n",
+       pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
                         (unsigned long) tsc_hz / 1000,
                         (unsigned long) tsc_hz % 1000);
 
@@ -84,8 +84,7 @@ static void __init vmware_platform_setup(void)
        if (ebx != UINT_MAX)
                x86_platform.calibrate_tsc = vmware_get_tsc_khz;
        else
-               printk(KERN_WARNING
-                      "Failed to get TSC freq from the hypervisor\n");
+               pr_warn("Failed to get TSC freq from the hypervisor\n");
 }
 
 /*
index 58f34319b29ab64aee4bd21e6ff30367d478c262..9ef978d69c22e00cffdce3592cbe5a495027a058 100644 (file)
@@ -57,10 +57,9 @@ struct crash_elf_data {
        struct kimage *image;
        /*
         * Total number of ram ranges we have after various adjustments for
-        * GART, crash reserved region etc.
+        * crash reserved region, etc.
         */
        unsigned int max_nr_ranges;
-       unsigned long gart_start, gart_end;
 
        /* Pointer to elf header */
        void *ehdr;
@@ -201,17 +200,6 @@ static int get_nr_ram_ranges_callback(u64 start, u64 end, void *arg)
        return 0;
 }
 
-static int get_gart_ranges_callback(u64 start, u64 end, void *arg)
-{
-       struct crash_elf_data *ced = arg;
-
-       ced->gart_start = start;
-       ced->gart_end = end;
-
-       /* Not expecting more than 1 gart aperture */
-       return 1;
-}
-
 
 /* Gather all the required information to prepare elf headers for ram regions */
 static void fill_up_crash_elf_data(struct crash_elf_data *ced,
@@ -226,22 +214,6 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced,
 
        ced->max_nr_ranges = nr_ranges;
 
-       /*
-        * We don't create ELF headers for GART aperture as an attempt
-        * to dump this memory in second kernel leads to hang/crash.
-        * If gart aperture is present, one needs to exclude that region
-        * and that could lead to need of extra phdr.
-        */
-       walk_iomem_res("GART", IORESOURCE_MEM, 0, -1,
-                               ced, get_gart_ranges_callback);
-
-       /*
-        * If we have gart region, excluding that could potentially split
-        * a memory range, resulting in extra header. Account for  that.
-        */
-       if (ced->gart_end)
-               ced->max_nr_ranges++;
-
        /* Exclusion of crash region could split memory ranges */
        ced->max_nr_ranges++;
 
@@ -350,13 +322,6 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced,
                        return ret;
        }
 
-       /* Exclude GART region */
-       if (ced->gart_end) {
-               ret = exclude_mem_range(cmem, ced->gart_start, ced->gart_end);
-               if (ret)
-                       return ret;
-       }
-
        return ret;
 }
 
@@ -599,12 +564,12 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params)
        /* Add ACPI tables */
        cmd.type = E820_ACPI;
        flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-       walk_iomem_res("ACPI Tables", flags, 0, -1, &cmd,
+       walk_iomem_res_desc(IORES_DESC_ACPI_TABLES, flags, 0, -1, &cmd,
                       memmap_entry_callback);
 
        /* Add ACPI Non-volatile Storage */
        cmd.type = E820_NVS;
-       walk_iomem_res("ACPI Non-volatile Storage", flags, 0, -1, &cmd,
+       walk_iomem_res_desc(IORES_DESC_ACPI_NV_STORAGE, flags, 0, -1, &cmd,
                        memmap_entry_callback);
 
        /* Add crashk_low_res region */
index 9c30acfadae24757cca11f00513d089e488da78d..32e5699eadfee52043a3028e2040a00ea2cc3375 100644 (file)
@@ -265,9 +265,8 @@ int __die(const char *str, struct pt_regs *regs, long err)
 #ifdef CONFIG_SMP
        printk("SMP ");
 #endif
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       printk("DEBUG_PAGEALLOC ");
-#endif
+       if (debug_pagealloc_enabled())
+               printk("DEBUG_PAGEALLOC ");
 #ifdef CONFIG_KASAN
        printk("KASAN");
 #endif
index 569c1e4f96feb897956a64e35bd8fccb07dca6c6..621b501f89351146b84b090b7160166bb9d5907e 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/e820.h>
 #include <asm/proto.h>
 #include <asm/setup.h>
+#include <asm/cpufeature.h>
 
 /*
  * The e820 map is the map that gets modified e.g. with command line parameters
@@ -925,6 +926,41 @@ static const char *e820_type_to_string(int e820_type)
        }
 }
 
+static unsigned long e820_type_to_iomem_type(int e820_type)
+{
+       switch (e820_type) {
+       case E820_RESERVED_KERN:
+       case E820_RAM:
+               return IORESOURCE_SYSTEM_RAM;
+       case E820_ACPI:
+       case E820_NVS:
+       case E820_UNUSABLE:
+       case E820_PRAM:
+       case E820_PMEM:
+       default:
+               return IORESOURCE_MEM;
+       }
+}
+
+static unsigned long e820_type_to_iores_desc(int e820_type)
+{
+       switch (e820_type) {
+       case E820_ACPI:
+               return IORES_DESC_ACPI_TABLES;
+       case E820_NVS:
+               return IORES_DESC_ACPI_NV_STORAGE;
+       case E820_PMEM:
+               return IORES_DESC_PERSISTENT_MEMORY;
+       case E820_PRAM:
+               return IORES_DESC_PERSISTENT_MEMORY_LEGACY;
+       case E820_RESERVED_KERN:
+       case E820_RAM:
+       case E820_UNUSABLE:
+       default:
+               return IORES_DESC_NONE;
+       }
+}
+
 static bool do_mark_busy(u32 type, struct resource *res)
 {
        /* this is the legacy bios/dos rom-shadow + mmio region */
@@ -967,7 +1003,8 @@ void __init e820_reserve_resources(void)
                res->start = e820.map[i].addr;
                res->end = end;
 
-               res->flags = IORESOURCE_MEM;
+               res->flags = e820_type_to_iomem_type(e820.map[i].type);
+               res->desc = e820_type_to_iores_desc(e820.map[i].type);
 
                /*
                 * don't register the region that could be conflicted with
index d25097c3fc1d1af8af35c156f05121f9f4d46a94..0b1b9abd4d5fe002c2f31d70736dc3d785027305 100644 (file)
@@ -114,6 +114,10 @@ void __kernel_fpu_begin(void)
        kernel_fpu_disable();
 
        if (fpu->fpregs_active) {
+               /*
+                * Ignore return value -- we don't care if reg state
+                * is clobbered.
+                */
                copy_fpregs_to_fpstate(fpu);
        } else {
                this_cpu_write(fpu_fpregs_owner_ctx, NULL);
@@ -189,8 +193,12 @@ void fpu__save(struct fpu *fpu)
 
        preempt_disable();
        if (fpu->fpregs_active) {
-               if (!copy_fpregs_to_fpstate(fpu))
-                       fpregs_deactivate(fpu);
+               if (!copy_fpregs_to_fpstate(fpu)) {
+                       if (use_eager_fpu())
+                               copy_kernel_to_fpregs(&fpu->state);
+                       else
+                               fpregs_deactivate(fpu);
+               }
        }
        preempt_enable();
 }
@@ -223,14 +231,15 @@ void fpstate_init(union fpregs_state *state)
 }
 EXPORT_SYMBOL_GPL(fpstate_init);
 
-/*
- * Copy the current task's FPU state to a new task's FPU context.
- *
- * In both the 'eager' and the 'lazy' case we save hardware registers
- * directly to the destination buffer.
- */
-static void fpu_copy(struct fpu *dst_fpu, struct fpu *src_fpu)
+int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
 {
+       dst_fpu->counter = 0;
+       dst_fpu->fpregs_active = 0;
+       dst_fpu->last_cpu = -1;
+
+       if (!src_fpu->fpstate_active || !cpu_has_fpu)
+               return 0;
+
        WARN_ON_FPU(src_fpu != &current->thread.fpu);
 
        /*
@@ -243,10 +252,9 @@ static void fpu_copy(struct fpu *dst_fpu, struct fpu *src_fpu)
        /*
         * Save current FPU registers directly into the child
         * FPU context, without any memory-to-memory copying.
-        *
-        * If the FPU context got destroyed in the process (FNSAVE
-        * done on old CPUs) then copy it back into the source
-        * context and mark the current task for lazy restore.
+        * In lazy mode, if the FPU context isn't loaded into
+        * fpregs, CR0.TS will be set and do_device_not_available
+        * will load the FPU context.
         *
         * We have to do all this with preemption disabled,
         * mostly because of the FNSAVE case, because in that
@@ -259,19 +267,13 @@ static void fpu_copy(struct fpu *dst_fpu, struct fpu *src_fpu)
        preempt_disable();
        if (!copy_fpregs_to_fpstate(dst_fpu)) {
                memcpy(&src_fpu->state, &dst_fpu->state, xstate_size);
-               fpregs_deactivate(src_fpu);
+
+               if (use_eager_fpu())
+                       copy_kernel_to_fpregs(&src_fpu->state);
+               else
+                       fpregs_deactivate(src_fpu);
        }
        preempt_enable();
-}
-
-int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
-{
-       dst_fpu->counter = 0;
-       dst_fpu->fpregs_active = 0;
-       dst_fpu->last_cpu = -1;
-
-       if (src_fpu->fpstate_active && cpu_has_fpu)
-               fpu_copy(dst_fpu, src_fpu);
 
        return 0;
 }
@@ -409,8 +411,10 @@ static inline void copy_init_fpstate_to_fpregs(void)
 {
        if (use_xsave())
                copy_kernel_to_xregs(&init_fpstate.xsave, -1);
-       else
+       else if (static_cpu_has(X86_FEATURE_FXSR))
                copy_kernel_to_fxregs(&init_fpstate.fxsave);
+       else
+               copy_kernel_to_fregs(&init_fpstate.fsave);
 }
 
 /*
@@ -423,7 +427,7 @@ void fpu__clear(struct fpu *fpu)
 {
        WARN_ON_FPU(fpu != &current->thread.fpu); /* Almost certainly an anomaly */
 
-       if (!use_eager_fpu()) {
+       if (!use_eager_fpu() || !static_cpu_has(X86_FEATURE_FPU)) {
                /* FPU state will be reallocated lazily at the first use. */
                fpu__drop(fpu);
        } else {
index 6d9f0a7ef4c8e5da3d596444242de7478d7b9356..54c86fffbf9f85281a77977a4aa8dbb67f112464 100644 (file)
@@ -78,13 +78,15 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
        cr0 &= ~(X86_CR0_TS | X86_CR0_EM);
        write_cr0(cr0);
 
-       asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
-                    : "+m" (fsw), "+m" (fcw));
+       if (!test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
+               asm volatile("fninit ; fnstsw %0 ; fnstcw %1"
+                            : "+m" (fsw), "+m" (fcw));
 
-       if (fsw == 0 && (fcw & 0x103f) == 0x003f)
-               set_cpu_cap(c, X86_FEATURE_FPU);
-       else
-               clear_cpu_cap(c, X86_FEATURE_FPU);
+               if (fsw == 0 && (fcw & 0x103f) == 0x003f)
+                       set_cpu_cap(c, X86_FEATURE_FPU);
+               else
+                       clear_cpu_cap(c, X86_FEATURE_FPU);
+       }
 
 #ifndef CONFIG_MATH_EMULATION
        if (!cpu_has_fpu) {
@@ -132,7 +134,7 @@ static void __init fpu__init_system_generic(void)
         * Set up the legacy init FPU context. (xstate init might overwrite this
         * with a more modern format, if the CPU supports it.)
         */
-       fpstate_init_fxstate(&init_fpstate.fxsave);
+       fpstate_init(&init_fpstate);
 
        fpu__init_system_mxcsr();
 }
@@ -260,7 +262,10 @@ static void __init fpu__init_system_xstate_size_legacy(void)
  * not only saved the restores along the way, but we also have the
  * FPU ready to be used for the original task.
  *
- * 'eager' switching is used on modern CPUs, there we switch the FPU
+ * 'lazy' is deprecated because it's almost never a performance win
+ * and it's much more complicated than 'eager'.
+ *
+ * 'eager' switching is by default on all CPUs, there we switch the FPU
  * state during every context switch, regardless of whether the task
  * has used FPU instructions in that time slice or not. This is done
  * because modern FPU context saving instructions are able to optimize
@@ -271,7 +276,7 @@ static void __init fpu__init_system_xstate_size_legacy(void)
  *   to use 'eager' restores, if we detect that a task is using the FPU
  *   frequently. See the fpu->counter logic in fpu/internal.h for that. ]
  */
-static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO;
+static enum { ENABLE, DISABLE } eagerfpu = ENABLE;
 
 /*
  * Find supported xfeatures based on cpu features and command-line input.
@@ -300,12 +305,6 @@ u64 __init fpu__get_supported_xfeatures_mask(void)
 static void __init fpu__clear_eager_fpu_features(void)
 {
        setup_clear_cpu_cap(X86_FEATURE_MPX);
-       setup_clear_cpu_cap(X86_FEATURE_AVX);
-       setup_clear_cpu_cap(X86_FEATURE_AVX2);
-       setup_clear_cpu_cap(X86_FEATURE_AVX512F);
-       setup_clear_cpu_cap(X86_FEATURE_AVX512PF);
-       setup_clear_cpu_cap(X86_FEATURE_AVX512ER);
-       setup_clear_cpu_cap(X86_FEATURE_AVX512CD);
 }
 
 /*
@@ -348,15 +347,9 @@ static void __init fpu__init_system_ctx_switch(void)
  */
 static void __init fpu__init_parse_early_param(void)
 {
-       /*
-        * No need to check "eagerfpu=auto" again, since it is the
-        * initial default.
-        */
        if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) {
                eagerfpu = DISABLE;
                fpu__clear_eager_fpu_features();
-       } else if (cmdline_find_option_bool(boot_command_line, "eagerfpu=on")) {
-               eagerfpu = ENABLE;
        }
 
        if (cmdline_find_option_bool(boot_command_line, "no387"))
index d425cda5ae6d0f1544c5d8decdb14d8682d7f7dd..6e8354f5a59353bd18801860980d779a19c61f74 100644 (file)
@@ -51,6 +51,9 @@ void fpu__xstate_clear_all_cpu_caps(void)
        setup_clear_cpu_cap(X86_FEATURE_AVX512PF);
        setup_clear_cpu_cap(X86_FEATURE_AVX512ER);
        setup_clear_cpu_cap(X86_FEATURE_AVX512CD);
+       setup_clear_cpu_cap(X86_FEATURE_AVX512DQ);
+       setup_clear_cpu_cap(X86_FEATURE_AVX512BW);
+       setup_clear_cpu_cap(X86_FEATURE_AVX512VL);
        setup_clear_cpu_cap(X86_FEATURE_MPX);
        setup_clear_cpu_cap(X86_FEATURE_XGETBV1);
 }
index 29408d6d66267c12ce4eab826e38bac3d8367d17..702547ce33c9c7a33fd321fdb94367af5515dd8b 100644 (file)
@@ -81,9 +81,9 @@ within(unsigned long addr, unsigned long start, unsigned long end)
 static unsigned long text_ip_addr(unsigned long ip)
 {
        /*
-        * On x86_64, kernel text mappings are mapped read-only with
-        * CONFIG_DEBUG_RODATA. So we use the kernel identity mapping instead
-        * of the kernel text mapping to modify the kernel text.
+        * On x86_64, kernel text mappings are mapped read-only, so we use
+        * the kernel identity mapping instead of the kernel text mapping
+        * to modify the kernel text.
         *
         * For 32bit kernels, these mappings are same and we can use
         * kernel identity mapping to modify code.
@@ -697,9 +697,8 @@ static inline void tramp_free(void *tramp) { }
 #endif
 
 /* Defined as markers to the end of the ftrace default trampolines */
-extern void ftrace_caller_end(void);
 extern void ftrace_regs_caller_end(void);
-extern void ftrace_return(void);
+extern void ftrace_epilogue(void);
 extern void ftrace_caller_op_ptr(void);
 extern void ftrace_regs_caller_op_ptr(void);
 
@@ -746,7 +745,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
                op_offset = (unsigned long)ftrace_regs_caller_op_ptr;
        } else {
                start_offset = (unsigned long)ftrace_caller;
-               end_offset = (unsigned long)ftrace_caller_end;
+               end_offset = (unsigned long)ftrace_epilogue;
                op_offset = (unsigned long)ftrace_caller_op_ptr;
        }
 
@@ -754,7 +753,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 
        /*
         * Allocate enough size to store the ftrace_caller code,
-        * the jmp to ftrace_return, as well as the address of
+        * the jmp to ftrace_epilogue, as well as the address of
         * the ftrace_ops this trampoline is used for.
         */
        trampoline = alloc_tramp(size + MCOUNT_INSN_SIZE + sizeof(void *));
@@ -772,8 +771,8 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size)
 
        ip = (unsigned long)trampoline + size;
 
-       /* The trampoline ends with a jmp to ftrace_return */
-       jmp = ftrace_jmp_replace(ip, (unsigned long)ftrace_return);
+       /* The trampoline ends with a jmp to ftrace_epilogue */
+       jmp = ftrace_jmp_replace(ip, (unsigned long)ftrace_epilogue);
        memcpy(trampoline + size, jmp, MCOUNT_INSN_SIZE);
 
        /*
index 2c0f3407bd1f1ae8adcf43cacdb479c91c096669..1f4422d5c8d013992d6b97a6a08734bde5bdb2b1 100644 (file)
@@ -40,13 +40,8 @@ pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
 /* Wipe all early page tables except for the kernel symbol map */
 static void __init reset_early_page_tables(void)
 {
-       unsigned long i;
-
-       for (i = 0; i < PTRS_PER_PGD-1; i++)
-               early_level4_pgt[i].pgd = 0;
-
+       memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1));
        next_early_pgt = 0;
-
        write_cr3(__pa_nodebug(early_level4_pgt));
 }
 
@@ -54,7 +49,6 @@ static void __init reset_early_page_tables(void)
 int __init early_make_pgtable(unsigned long address)
 {
        unsigned long physaddr = address - __PAGE_OFFSET;
-       unsigned long i;
        pgdval_t pgd, *pgd_p;
        pudval_t pud, *pud_p;
        pmdval_t pmd, *pmd_p;
@@ -81,8 +75,7 @@ again:
                }
 
                pud_p = (pudval_t *)early_dynamic_pgts[next_early_pgt++];
-               for (i = 0; i < PTRS_PER_PUD; i++)
-                       pud_p[i] = 0;
+               memset(pud_p, 0, sizeof(*pud_p) * PTRS_PER_PUD);
                *pgd_p = (pgdval_t)pud_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;
        }
        pud_p += pud_index(address);
@@ -97,8 +90,7 @@ again:
                }
 
                pmd_p = (pmdval_t *)early_dynamic_pgts[next_early_pgt++];
-               for (i = 0; i < PTRS_PER_PMD; i++)
-                       pmd_p[i] = 0;
+               memset(pmd_p, 0, sizeof(*pmd_p) * PTRS_PER_PMD);
                *pud_p = (pudval_t)pmd_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE;
        }
        pmd = (physaddr & PMD_MASK) + early_pmd_flags;
index 6bc9ae24b6d2a74930701c0c6ea60fe090a3ebbc..54cdbd2003fe0930ff0a91158f55d00723e2400e 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/setup.h>
 #include <asm/processor-flags.h>
 #include <asm/msr-index.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/percpu.h>
 #include <asm/nops.h>
 #include <asm/bootparam.h>
@@ -389,6 +389,12 @@ default_entry:
        /* Make changes effective */
        wrmsr
 
+       /*
+        * And make sure that all the mappings we set up have NX set from
+        * the beginning.
+        */
+       orl $(1 << (_PAGE_BIT_NX - 32)), pa(__supported_pte_mask + 4)
+
 enable_paging:
 
 /*
index ffdc0e8603902b12b0cd44fd175d806b046ccb4b..22fbf9df61bb4eecbb5ffe530562b56c1def90b8 100644 (file)
@@ -38,7 +38,6 @@
 #define pud_index(x)   (((x) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
 
 L4_PAGE_OFFSET = pgd_index(__PAGE_OFFSET)
-L3_PAGE_OFFSET = pud_index(__PAGE_OFFSET)
 L4_START_KERNEL = pgd_index(__START_KERNEL_map)
 L3_START_KERNEL = pud_index(__START_KERNEL_map)
 
@@ -76,9 +75,7 @@ startup_64:
        subq    $_text - __START_KERNEL_map, %rbp
 
        /* Is the address not 2M aligned? */
-       movq    %rbp, %rax
-       andl    $~PMD_PAGE_MASK, %eax
-       testl   %eax, %eax
+       testl   $~PMD_PAGE_MASK, %ebp
        jnz     bad_address
 
        /*
index b8e6ff5cd5d055892715af36f1e9b72340f7b18c..be0ebbb6d1d144fc86bcab6716871ea8cdaa4744 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/pm.h>
 #include <linux/io.h>
 
+#include <asm/cpufeature.h>
 #include <asm/irqdomain.h>
 #include <asm/fixmap.h>
 #include <asm/hpet.h>
index 44256a62702b2c51077fc0b8b82a904ed122b9f6..ed15cd486d06347626c080a0081e3eed01ac9128 100644 (file)
@@ -750,9 +750,7 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
        int err;
-#ifdef CONFIG_DEBUG_RODATA
        char opc[BREAK_INSTR_SIZE];
-#endif /* CONFIG_DEBUG_RODATA */
 
        bpt->type = BP_BREAKPOINT;
        err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
@@ -761,7 +759,6 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
                return err;
        err = probe_kernel_write((char *)bpt->bpt_addr,
                                 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
-#ifdef CONFIG_DEBUG_RODATA
        if (!err)
                return err;
        /*
@@ -778,13 +775,12 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
        if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE))
                return -EINVAL;
        bpt->type = BP_POKE_BREAKPOINT;
-#endif /* CONFIG_DEBUG_RODATA */
+
        return err;
 }
 
 int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 {
-#ifdef CONFIG_DEBUG_RODATA
        int err;
        char opc[BREAK_INSTR_SIZE];
 
@@ -801,8 +797,8 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
        if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE))
                goto knl_write;
        return err;
+
 knl_write:
-#endif /* CONFIG_DEBUG_RODATA */
        return probe_kernel_write((char *)bpt->bpt_addr,
                                  (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
 }
index 1deffe6cc87367631fe23b4c5d4b6be697ff4b0e..0f05deeff5ce2e2af5aa7fb1f2fe1f59f4ed8348 100644 (file)
@@ -988,7 +988,7 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
                 * In case the user-specified fault handler returned
                 * zero, try to fix up.
                 */
-               if (fixup_exception(regs))
+               if (fixup_exception(regs, trapnr))
                        return 1;
 
                /*
index 87e1762e2bca74a3f22004d09d9069d72b41b62b..ed48a9f465f84685d1ecdfb78075f869001e369b 100644 (file)
@@ -168,12 +168,14 @@ GLOBAL(ftrace_call)
        restore_mcount_regs
 
        /*
-        * The copied trampoline must call ftrace_return as it
+        * The copied trampoline must call ftrace_epilogue as it
         * still may need to call the function graph tracer.
+        *
+        * The code up to this label is copied into trampolines so
+        * think twice before adding any new code or changing the
+        * layout here.
         */
-GLOBAL(ftrace_caller_end)
-
-GLOBAL(ftrace_return)
+GLOBAL(ftrace_epilogue)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 GLOBAL(ftrace_graph_call)
@@ -244,14 +246,14 @@ GLOBAL(ftrace_regs_call)
        popfq
 
        /*
-        * As this jmp to ftrace_return can be a short jump
+        * As this jmp to ftrace_epilogue can be a short jump
         * it must not be copied into the trampoline.
         * The trampoline will add the code to jump
         * to the return.
         */
 GLOBAL(ftrace_regs_caller_end)
 
-       jmp ftrace_return
+       jmp ftrace_epilogue
 
 END(ftrace_regs_caller)
 
index 30ca7607cbbbbcae4793aa5c14d8f73bbd784d71..97340f2c437c64def7a83f75a8f9b0bc6a968451 100644 (file)
@@ -408,7 +408,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
        processor.cpuflag = CPU_ENABLED;
        processor.cpufeature = (boot_cpu_data.x86 << 8) |
            (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
-       processor.featureflag = boot_cpu_data.x86_capability[0];
+       processor.featureflag = boot_cpu_data.x86_capability[CPUID_1_EDX];
        processor.reserved[0] = 0;
        processor.reserved[1] = 0;
        for (i = 0; i < 2; i++) {
index 64f9616f93f1ec39a85494857d2d07728a7ec5d2..7f3550acde1b8ce604f4b5cc8b53c232450c524f 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/uaccess.h>
 #include <linux/gfp.h>
 
-#include <asm/processor.h>
+#include <asm/cpufeature.h>
 #include <asm/msr.h>
 
 static struct class *msr_class;
index 8a2cdd736fa4da82374fa9392e76b5716cc0f89a..04b132a767f116e8ff35efcbbc036e331a145a4b 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/nmi.h>
 #include <asm/x86_init.h>
 #include <asm/reboot.h>
+#include <asm/cache.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/nmi.h>
@@ -69,7 +70,7 @@ struct nmi_stats {
 
 static DEFINE_PER_CPU(struct nmi_stats, nmi_stats);
 
-static int ignore_nmis;
+static int ignore_nmis __read_mostly;
 
 int unknown_nmi_panic;
 /*
index 14415aff18136524cfa3d4c9b07bdde6ee0d6f54..92f70147a9a673e74b3753637adbb08e2a4869fa 100644 (file)
@@ -13,11 +13,11 @@ static int found(u64 start, u64 end, void *data)
 
 static __init int register_e820_pmem(void)
 {
-       char *pmem = "Persistent Memory (legacy)";
        struct platform_device *pdev;
        int rc;
 
-       rc = walk_iomem_res(pmem, IORESOURCE_MEM, 0, -1, NULL, found);
+       rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+                                IORESOURCE_MEM, 0, -1, NULL, found);
        if (rc <= 0)
                return 0;
 
index 9f7c21c22477e59462d72e930d79a4c2a238a051..2915d54e9dd5f730558fba3ed2e7f3c9d4cd5a5b 100644 (file)
@@ -57,6 +57,9 @@ __visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss) = {
          */
        .io_bitmap              = { [0 ... IO_BITMAP_LONGS] = ~0 },
 #endif
+#ifdef CONFIG_X86_32
+       .SYSENTER_stack_canary  = STACK_END_MAGIC,
+#endif
 };
 EXPORT_PER_CPU_SYMBOL(cpu_tss);
 
@@ -418,9 +421,9 @@ static void mwait_idle(void)
        if (!current_set_polling_and_test()) {
                trace_cpu_idle_rcuidle(1, smp_processor_id());
                if (this_cpu_has(X86_BUG_CLFLUSH_MONITOR)) {
-                       smp_mb(); /* quirk */
+                       mb(); /* quirk */
                        clflush((void *)&current_thread_info()->flags);
-                       smp_mb(); /* quirk */
+                       mb(); /* quirk */
                }
 
                __monitor((void *)&current_thread_info()->flags, 0, 0);
index d3d80e6d42a20ea665325b4cf2a5e7be3c43289a..aa52c10094755e2fa9fdd5ac7a39b0c36effac8a 100644 (file)
@@ -152,21 +152,21 @@ static struct resource data_resource = {
        .name   = "Kernel data",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static struct resource code_resource = {
        .name   = "Kernel code",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 static struct resource bss_resource = {
        .name   = "Kernel bss",
        .start  = 0,
        .end    = 0,
-       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags  = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM
 };
 
 
index cb6282c3638ffbd32bcb33663d8cefc17eac8a8e..548ddf7d6fd2085676328ffcde6375ce3e88b477 100644 (file)
        regs->seg = GET_SEG(seg) | 3;                   \
 } while (0)
 
-int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
+#ifdef CONFIG_X86_64
+/*
+ * If regs->ss will cause an IRET fault, change it.  Otherwise leave it
+ * alone.  Using this generally makes no sense unless
+ * user_64bit_mode(regs) would return true.
+ */
+static void force_valid_ss(struct pt_regs *regs)
+{
+       u32 ar;
+       asm volatile ("lar %[old_ss], %[ar]\n\t"
+                     "jz 1f\n\t"               /* If invalid: */
+                     "xorl %[ar], %[ar]\n\t"   /* set ar = 0 */
+                     "1:"
+                     : [ar] "=r" (ar)
+                     : [old_ss] "rm" ((u16)regs->ss));
+
+       /*
+        * For a valid 64-bit user context, we need DPL 3, type
+        * read-write data or read-write exp-down data, and S and P
+        * set.  We can't use VERW because VERW doesn't check the
+        * P bit.
+        */
+       ar &= AR_DPL_MASK | AR_S | AR_P | AR_TYPE_MASK;
+       if (ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA) &&
+           ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA_EXPDOWN))
+               regs->ss = __USER_DS;
+}
+#endif
+
+static int restore_sigcontext(struct pt_regs *regs,
+                             struct sigcontext __user *sc,
+                             unsigned long uc_flags)
 {
        unsigned long buf_val;
        void __user *buf;
@@ -94,15 +125,18 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
                COPY(r15);
 #endif /* CONFIG_X86_64 */
 
-#ifdef CONFIG_X86_32
                COPY_SEG_CPL3(cs);
                COPY_SEG_CPL3(ss);
-#else /* !CONFIG_X86_32 */
-               /* Kernel saves and restores only the CS segment register on signals,
-                * which is the bare minimum needed to allow mixed 32/64-bit code.
-                * App's signal handler can save/restore other segments if needed. */
-               COPY_SEG_CPL3(cs);
-#endif /* CONFIG_X86_32 */
+
+#ifdef CONFIG_X86_64
+               /*
+                * Fix up SS if needed for the benefit of old DOSEMU and
+                * CRIU.
+                */
+               if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) &&
+                            user_64bit_mode(regs)))
+                       force_valid_ss(regs);
+#endif
 
                get_user_ex(tmpflags, &sc->flags);
                regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
@@ -165,6 +199,7 @@ int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
                put_user_ex(regs->cs, &sc->cs);
                put_user_ex(0, &sc->gs);
                put_user_ex(0, &sc->fs);
+               put_user_ex(regs->ss, &sc->ss);
 #endif /* CONFIG_X86_32 */
 
                put_user_ex(fpstate, &sc->fpstate);
@@ -403,6 +438,21 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
        return 0;
 }
 #else /* !CONFIG_X86_32 */
+static unsigned long frame_uc_flags(struct pt_regs *regs)
+{
+       unsigned long flags;
+
+       if (cpu_has_xsave)
+               flags = UC_FP_XSTATE | UC_SIGCONTEXT_SS;
+       else
+               flags = UC_SIGCONTEXT_SS;
+
+       if (likely(user_64bit_mode(regs)))
+               flags |= UC_STRICT_RESTORE_SS;
+
+       return flags;
+}
+
 static int __setup_rt_frame(int sig, struct ksignal *ksig,
                            sigset_t *set, struct pt_regs *regs)
 {
@@ -422,10 +472,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
 
        put_user_try {
                /* Create the ucontext.  */
-               if (cpu_has_xsave)
-                       put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
-               else
-                       put_user_ex(0, &frame->uc.uc_flags);
+               put_user_ex(frame_uc_flags(regs), &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
                save_altstack_ex(&frame->uc.uc_stack, regs->sp);
 
@@ -459,10 +506,28 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
 
        regs->sp = (unsigned long)frame;
 
-       /* Set up the CS register to run signal handlers in 64-bit mode,
-          even if the handler happens to be interrupting 32-bit code. */
+       /*
+        * Set up the CS and SS registers to run signal handlers in
+        * 64-bit mode, even if the handler happens to be interrupting
+        * 32-bit or 16-bit code.
+        *
+        * SS is subtle.  In 64-bit mode, we don't need any particular
+        * SS descriptor, but we do need SS to be valid.  It's possible
+        * that the old SS is entirely bogus -- this can happen if the
+        * signal we're trying to deliver is #GP or #SS caused by a bad
+        * SS value.  We also have a compatbility issue here: DOSEMU
+        * relies on the contents of the SS register indicating the
+        * SS value at the time of the signal, even though that code in
+        * DOSEMU predates sigreturn's ability to restore SS.  (DOSEMU
+        * avoids relying on sigreturn to restore SS; instead it uses
+        * a trampoline.)  So we do our best: if the old SS was valid,
+        * we keep it.  Otherwise we replace it.
+        */
        regs->cs = __USER_CS;
 
+       if (unlikely(regs->ss != __USER_DS))
+               force_valid_ss(regs);
+
        return 0;
 }
 #endif /* CONFIG_X86_32 */
@@ -489,10 +554,7 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
 
        put_user_try {
                /* Create the ucontext.  */
-               if (cpu_has_xsave)
-                       put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
-               else
-                       put_user_ex(0, &frame->uc.uc_flags);
+               put_user_ex(frame_uc_flags(regs), &frame->uc.uc_flags);
                put_user_ex(0, &frame->uc.uc_link);
                compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp);
                put_user_ex(0, &frame->uc.uc__pad0);
@@ -554,7 +616,11 @@ asmlinkage unsigned long sys_sigreturn(void)
 
        set_current_blocked(&set);
 
-       if (restore_sigcontext(regs, &frame->sc))
+       /*
+        * x86_32 has no uc_flags bits relevant to restore_sigcontext.
+        * Save a few cycles by skipping the __get_user.
+        */
+       if (restore_sigcontext(regs, &frame->sc, 0))
                goto badframe;
        return regs->ax;
 
@@ -570,16 +636,19 @@ asmlinkage long sys_rt_sigreturn(void)
        struct pt_regs *regs = current_pt_regs();
        struct rt_sigframe __user *frame;
        sigset_t set;
+       unsigned long uc_flags;
 
        frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
+       if (__get_user(uc_flags, &frame->uc.uc_flags))
+               goto badframe;
 
        set_current_blocked(&set);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
                goto badframe;
 
        if (restore_altstack(&frame->uc.uc_stack))
@@ -692,12 +761,15 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 
 static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
 {
-#if defined(CONFIG_X86_32) || !defined(CONFIG_X86_64)
+#ifdef CONFIG_X86_64
+       if (is_ia32_task())
+               return __NR_ia32_restart_syscall;
+#endif
+#ifdef CONFIG_X86_X32_ABI
+       return __NR_restart_syscall | (regs->orig_ax & __X32_SYSCALL_BIT);
+#else
        return __NR_restart_syscall;
-#else /* !CONFIG_X86_32 && CONFIG_X86_64 */
-       return test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall :
-               __NR_restart_syscall | (regs->orig_ax & __X32_SYSCALL_BIT);
-#endif /* CONFIG_X86_32 || !CONFIG_X86_64 */
+#endif
 }
 
 /*
@@ -763,6 +835,7 @@ asmlinkage long sys32_x32_rt_sigreturn(void)
        struct pt_regs *regs = current_pt_regs();
        struct rt_sigframe_x32 __user *frame;
        sigset_t set;
+       unsigned long uc_flags;
 
        frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
 
@@ -770,10 +843,12 @@ asmlinkage long sys32_x32_rt_sigreturn(void)
                goto badframe;
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
+       if (__get_user(uc_flags, &frame->uc.uc_flags))
+               goto badframe;
 
        set_current_blocked(&set);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
                goto badframe;
 
        if (compat_restore_altstack(&frame->uc.uc_stack))
index 24d57f77b3c19615840ac4f09c8c0fd299864698..643dbdccf4bc9ac41305d79f1da91762574f7b12 100644 (file)
@@ -97,6 +97,14 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
 DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info);
 EXPORT_PER_CPU_SYMBOL(cpu_info);
 
+/* Logical package management. We might want to allocate that dynamically */
+static int *physical_to_logical_pkg __read_mostly;
+static unsigned long *physical_package_map __read_mostly;;
+static unsigned long *logical_package_map  __read_mostly;
+static unsigned int max_physical_pkg_id __read_mostly;
+unsigned int __max_logical_packages __read_mostly;
+EXPORT_SYMBOL(__max_logical_packages);
+
 static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
 {
        unsigned long flags;
@@ -248,7 +256,98 @@ static void notrace start_secondary(void *unused)
        x86_cpuinit.setup_percpu_clockev();
 
        wmb();
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
+}
+
+int topology_update_package_map(unsigned int apicid, unsigned int cpu)
+{
+       unsigned int new, pkg = apicid >> boot_cpu_data.x86_coreid_bits;
+
+       /* Called from early boot ? */
+       if (!physical_package_map)
+               return 0;
+
+       if (pkg >= max_physical_pkg_id)
+               return -EINVAL;
+
+       /* Set the logical package id */
+       if (test_and_set_bit(pkg, physical_package_map))
+               goto found;
+
+       if (pkg < __max_logical_packages) {
+               set_bit(pkg, logical_package_map);
+               physical_to_logical_pkg[pkg] = pkg;
+               goto found;
+       }
+       new = find_first_zero_bit(logical_package_map, __max_logical_packages);
+       if (new >= __max_logical_packages) {
+               physical_to_logical_pkg[pkg] = -1;
+               pr_warn("APIC(%x) Package %u exceeds logical package map\n",
+                       apicid, pkg);
+               return -ENOSPC;
+       }
+       set_bit(new, logical_package_map);
+       pr_info("APIC(%x) Converting physical %u to logical package %u\n",
+               apicid, pkg, new);
+       physical_to_logical_pkg[pkg] = new;
+
+found:
+       cpu_data(cpu).logical_proc_id = physical_to_logical_pkg[pkg];
+       return 0;
+}
+
+/**
+ * topology_phys_to_logical_pkg - Map a physical package id to a logical
+ *
+ * Returns logical package id or -1 if not found
+ */
+int topology_phys_to_logical_pkg(unsigned int phys_pkg)
+{
+       if (phys_pkg >= max_physical_pkg_id)
+               return -1;
+       return physical_to_logical_pkg[phys_pkg];
+}
+EXPORT_SYMBOL(topology_phys_to_logical_pkg);
+
+static void __init smp_init_package_map(void)
+{
+       unsigned int ncpus, cpu;
+       size_t size;
+
+       /*
+        * Today neither Intel nor AMD support heterogenous systems. That
+        * might change in the future....
+        */
+       ncpus = boot_cpu_data.x86_max_cores * smp_num_siblings;
+       __max_logical_packages = DIV_ROUND_UP(nr_cpu_ids, ncpus);
+
+       /*
+        * Possibly larger than what we need as the number of apic ids per
+        * package can be smaller than the actual used apic ids.
+        */
+       max_physical_pkg_id = DIV_ROUND_UP(MAX_LOCAL_APIC, ncpus);
+       size = max_physical_pkg_id * sizeof(unsigned int);
+       physical_to_logical_pkg = kmalloc(size, GFP_KERNEL);
+       memset(physical_to_logical_pkg, 0xff, size);
+       size = BITS_TO_LONGS(max_physical_pkg_id) * sizeof(unsigned long);
+       physical_package_map = kzalloc(size, GFP_KERNEL);
+       size = BITS_TO_LONGS(__max_logical_packages) * sizeof(unsigned long);
+       logical_package_map = kzalloc(size, GFP_KERNEL);
+
+       pr_info("Max logical packages: %u\n", __max_logical_packages);
+
+       for_each_present_cpu(cpu) {
+               unsigned int apicid = apic->cpu_present_to_apicid(cpu);
+
+               if (apicid == BAD_APICID || !apic->apic_id_valid(apicid))
+                       continue;
+               if (!topology_update_package_map(apicid, cpu))
+                       continue;
+               pr_warn("CPU %u APICId %x disabled\n", cpu, apicid);
+               per_cpu(x86_bios_cpu_apicid, cpu) = BAD_APICID;
+               set_cpu_possible(cpu, false);
+               set_cpu_present(cpu, false);
+       }
 }
 
 void __init smp_store_boot_cpu_info(void)
@@ -258,6 +357,7 @@ void __init smp_store_boot_cpu_info(void)
 
        *c = boot_cpu_data;
        c->cpu_index = id;
+       smp_init_package_map();
 }
 
 /*
index 3f92ce07e525fd41167a64f9d7c4df1bfbe673bf..27538f183c3b15d9d59e225f2612b12660ee979b 100644 (file)
@@ -142,7 +142,6 @@ static int test_NX(void)
         * by the error message
         */
 
-#ifdef CONFIG_DEBUG_RODATA
        /* Test 3: Check if the .rodata section is executable */
        if (rodata_test_data != 0xC3) {
                printk(KERN_ERR "test_nx: .rodata marker has invalid value\n");
@@ -151,7 +150,6 @@ static int test_NX(void)
                printk(KERN_ERR "test_nx: .rodata section is executable\n");
                ret = -ENODEV;
        }
-#endif
 
 #if 0
        /* Test 4: Check if the .data section of a module is executable */
index 5ecbfe5099dad68e140b85ffdaefc75818afc6d9..cb4a01b41e277887b6769e4a17d60cb4139f9864 100644 (file)
@@ -76,5 +76,5 @@ int rodata_test(void)
 }
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Testcase for the DEBUG_RODATA infrastructure");
+MODULE_DESCRIPTION("Testcase for marking rodata as read-only");
 MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>");
index ade185a46b1da63cea0be1ce47731e301f9d1d5a..06cbe25861f1591a7829b5d9347e1a753f874456 100644 (file)
@@ -83,30 +83,16 @@ gate_desc idt_table[NR_VECTORS] __page_aligned_bss;
 DECLARE_BITMAP(used_vectors, NR_VECTORS);
 EXPORT_SYMBOL_GPL(used_vectors);
 
-static inline void conditional_sti(struct pt_regs *regs)
+static inline void cond_local_irq_enable(struct pt_regs *regs)
 {
        if (regs->flags & X86_EFLAGS_IF)
                local_irq_enable();
 }
 
-static inline void preempt_conditional_sti(struct pt_regs *regs)
-{
-       preempt_count_inc();
-       if (regs->flags & X86_EFLAGS_IF)
-               local_irq_enable();
-}
-
-static inline void conditional_cli(struct pt_regs *regs)
-{
-       if (regs->flags & X86_EFLAGS_IF)
-               local_irq_disable();
-}
-
-static inline void preempt_conditional_cli(struct pt_regs *regs)
+static inline void cond_local_irq_disable(struct pt_regs *regs)
 {
        if (regs->flags & X86_EFLAGS_IF)
                local_irq_disable();
-       preempt_count_dec();
 }
 
 void ist_enter(struct pt_regs *regs)
@@ -199,7 +185,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
        }
 
        if (!user_mode(regs)) {
-               if (!fixup_exception(regs)) {
+               if (!fixup_exception(regs, trapnr)) {
                        tsk->thread.error_code = error_code;
                        tsk->thread.trap_nr = trapnr;
                        die(str, regs, error_code);
@@ -262,7 +248,6 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
        tsk->thread.error_code = error_code;
        tsk->thread.trap_nr = trapnr;
 
-#ifdef CONFIG_X86_64
        if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
            printk_ratelimit()) {
                pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx",
@@ -271,7 +256,6 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
                print_vma_addr(" in ", regs->ip);
                pr_cont("\n");
        }
-#endif
 
        force_sig_info(signr, info ?: SEND_SIG_PRIV, tsk);
 }
@@ -286,7 +270,7 @@ static void do_error_trap(struct pt_regs *regs, long error_code, char *str,
 
        if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) !=
                        NOTIFY_STOP) {
-               conditional_sti(regs);
+               cond_local_irq_enable(regs);
                do_trap(trapnr, signr, str, regs, error_code,
                        fill_trap_info(regs, signr, trapnr, &info));
        }
@@ -368,7 +352,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
        if (notify_die(DIE_TRAP, "bounds", regs, error_code,
                        X86_TRAP_BR, SIGSEGV) == NOTIFY_STOP)
                return;
-       conditional_sti(regs);
+       cond_local_irq_enable(regs);
 
        if (!user_mode(regs))
                die("bounds", regs, error_code);
@@ -443,7 +427,7 @@ do_general_protection(struct pt_regs *regs, long error_code)
        struct task_struct *tsk;
 
        RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
-       conditional_sti(regs);
+       cond_local_irq_enable(regs);
 
        if (v8086_mode(regs)) {
                local_irq_enable();
@@ -453,7 +437,7 @@ do_general_protection(struct pt_regs *regs, long error_code)
 
        tsk = current;
        if (!user_mode(regs)) {
-               if (fixup_exception(regs))
+               if (fixup_exception(regs, X86_TRAP_GP))
                        return;
 
                tsk->thread.error_code = error_code;
@@ -517,9 +501,11 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)
         * as we may switch to the interrupt stack.
         */
        debug_stack_usage_inc();
-       preempt_conditional_sti(regs);
+       preempt_disable();
+       cond_local_irq_enable(regs);
        do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
-       preempt_conditional_cli(regs);
+       cond_local_irq_disable(regs);
+       preempt_enable_no_resched();
        debug_stack_usage_dec();
 exit:
        ist_exit(regs);
@@ -571,6 +557,29 @@ struct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
 NOKPROBE_SYMBOL(fixup_bad_iret);
 #endif
 
+static bool is_sysenter_singlestep(struct pt_regs *regs)
+{
+       /*
+        * We don't try for precision here.  If we're anywhere in the region of
+        * code that can be single-stepped in the SYSENTER entry path, then
+        * assume that this is a useless single-step trap due to SYSENTER
+        * being invoked with TF set.  (We don't know in advance exactly
+        * which instructions will be hit because BTF could plausibly
+        * be set.)
+        */
+#ifdef CONFIG_X86_32
+       return (regs->ip - (unsigned long)__begin_SYSENTER_singlestep_region) <
+               (unsigned long)__end_SYSENTER_singlestep_region -
+               (unsigned long)__begin_SYSENTER_singlestep_region;
+#elif defined(CONFIG_IA32_EMULATION)
+       return (regs->ip - (unsigned long)entry_SYSENTER_compat) <
+               (unsigned long)__end_entry_SYSENTER_compat -
+               (unsigned long)entry_SYSENTER_compat;
+#else
+       return false;
+#endif
+}
+
 /*
  * Our handling of the processor debug registers is non-trivial.
  * We do not clear them on entry and exit from the kernel. Therefore
@@ -605,10 +614,41 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
        ist_enter(regs);
 
        get_debugreg(dr6, 6);
+       /*
+        * The Intel SDM says:
+        *
+        *   Certain debug exceptions may clear bits 0-3. The remaining
+        *   contents of the DR6 register are never cleared by the
+        *   processor. To avoid confusion in identifying debug
+        *   exceptions, debug handlers should clear the register before
+        *   returning to the interrupted task.
+        *
+        * Keep it simple: clear DR6 immediately.
+        */
+       set_debugreg(0, 6);
 
        /* Filter out all the reserved bits which are preset to 1 */
        dr6 &= ~DR6_RESERVED;
 
+       /*
+        * The SDM says "The processor clears the BTF flag when it
+        * generates a debug exception."  Clear TIF_BLOCKSTEP to keep
+        * TIF_BLOCKSTEP in sync with the hardware BTF flag.
+        */
+       clear_tsk_thread_flag(tsk, TIF_BLOCKSTEP);
+
+       if (unlikely(!user_mode(regs) && (dr6 & DR_STEP) &&
+                    is_sysenter_singlestep(regs))) {
+               dr6 &= ~DR_STEP;
+               if (!dr6)
+                       goto exit;
+               /*
+                * else we might have gotten a single-step trap and hit a
+                * watchpoint at the same time, in which case we should fall
+                * through and handle the watchpoint.
+                */
+       }
+
        /*
         * If dr6 has no reason to give us about the origin of this trap,
         * then it's very likely the result of an icebp/int01 trap.
@@ -617,18 +657,10 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
        if (!dr6 && user_mode(regs))
                user_icebp = 1;
 
-       /* Catch kmemcheck conditions first of all! */
+       /* Catch kmemcheck conditions! */
        if ((dr6 & DR_STEP) && kmemcheck_trap(regs))
                goto exit;
 
-       /* DR6 may or may not be cleared by the CPU */
-       set_debugreg(0, 6);
-
-       /*
-        * The processor cleared BTF, so don't mark that we need it set.
-        */
-       clear_tsk_thread_flag(tsk, TIF_BLOCKSTEP);
-
        /* Store the virtualized DR6 value */
        tsk->thread.debugreg6 = dr6;
 
@@ -648,24 +680,25 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
        debug_stack_usage_inc();
 
        /* It's safe to allow irq's after DR6 has been saved */
-       preempt_conditional_sti(regs);
+       preempt_disable();
+       cond_local_irq_enable(regs);
 
        if (v8086_mode(regs)) {
                handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code,
                                        X86_TRAP_DB);
-               preempt_conditional_cli(regs);
+               cond_local_irq_disable(regs);
+               preempt_enable_no_resched();
                debug_stack_usage_dec();
                goto exit;
        }
 
-       /*
-        * Single-stepping through system calls: ignore any exceptions in
-        * kernel space, but re-enable TF when returning to user mode.
-        *
-        * We already checked v86 mode above, so we can check for kernel mode
-        * by just checking the CPL of CS.
-        */
-       if ((dr6 & DR_STEP) && !user_mode(regs)) {
+       if (WARN_ON_ONCE((dr6 & DR_STEP) && !user_mode(regs))) {
+               /*
+                * Historical junk that used to handle SYSENTER single-stepping.
+                * This should be unreachable now.  If we survive for a while
+                * without anyone hitting this warning, we'll turn this into
+                * an oops.
+                */
                tsk->thread.debugreg6 &= ~DR_STEP;
                set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
                regs->flags &= ~X86_EFLAGS_TF;
@@ -673,10 +706,19 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code)
        si_code = get_si_code(tsk->thread.debugreg6);
        if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
                send_sigtrap(tsk, regs, error_code, si_code);
-       preempt_conditional_cli(regs);
+       cond_local_irq_disable(regs);
+       preempt_enable_no_resched();
        debug_stack_usage_dec();
 
 exit:
+#if defined(CONFIG_X86_32)
+       /*
+        * This is the most likely code path that involves non-trivial use
+        * of the SYSENTER stack.  Check that we haven't overrun it.
+        */
+       WARN(this_cpu_read(cpu_tss.SYSENTER_stack_canary) != STACK_END_MAGIC,
+            "Overran or corrupted SYSENTER stack\n");
+#endif
        ist_exit(regs);
 }
 NOKPROBE_SYMBOL(do_debug);
@@ -696,10 +738,10 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
 
        if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)
                return;
-       conditional_sti(regs);
+       cond_local_irq_enable(regs);
 
        if (!user_mode(regs)) {
-               if (!fixup_exception(regs)) {
+               if (!fixup_exception(regs, trapnr)) {
                        task->thread.error_code = error_code;
                        task->thread.trap_nr = trapnr;
                        die(str, regs, error_code);
@@ -743,20 +785,19 @@ do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
 dotraplinkage void
 do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
 {
-       conditional_sti(regs);
+       cond_local_irq_enable(regs);
 }
 
 dotraplinkage void
 do_device_not_available(struct pt_regs *regs, long error_code)
 {
        RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
-       BUG_ON(use_eager_fpu());
 
 #ifdef CONFIG_MATH_EMULATION
-       if (read_cr0() & X86_CR0_EM) {
+       if (!boot_cpu_has(X86_FEATURE_FPU) && (read_cr0() & X86_CR0_EM)) {
                struct math_emu_info info = { };
 
-               conditional_sti(regs);
+               cond_local_irq_enable(regs);
 
                info.regs = regs;
                math_emulate(&info);
@@ -765,7 +806,7 @@ do_device_not_available(struct pt_regs *regs, long error_code)
 #endif
        fpu__restore(&current->thread.fpu); /* interrupts still off */
 #ifdef CONFIG_X86_32
-       conditional_sti(regs);
+       cond_local_irq_enable(regs);
 #endif
 }
 NOKPROBE_SYMBOL(do_device_not_available);
@@ -868,7 +909,7 @@ void __init trap_init(void)
 #endif
 
 #ifdef CONFIG_X86_32
-       set_system_trap_gate(IA32_SYSCALL_VECTOR, entry_INT80_32);
+       set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_32);
        set_bit(IA32_SYSCALL_VECTOR, used_vectors);
 #endif
 
index 3d743da828d38acff0013600ed582c8b14ef81b3..56380440d86229a41314487792decd6a04190fca 100644 (file)
@@ -43,6 +43,11 @@ static DEFINE_STATIC_KEY_FALSE(__use_tsc);
 
 int tsc_clocksource_reliable;
 
+static u32 art_to_tsc_numerator;
+static u32 art_to_tsc_denominator;
+static u64 art_to_tsc_offset;
+struct clocksource *art_related_clocksource;
+
 /*
  * Use a ring-buffer like data structure, where a writer advances the head by
  * writing a new data entry and a reader advances the tail when it observes a
@@ -964,6 +969,37 @@ core_initcall(cpufreq_tsc);
 
 #endif /* CONFIG_CPU_FREQ */
 
+#define ART_CPUID_LEAF (0x15)
+#define ART_MIN_DENOMINATOR (1)
+
+
+/*
+ * If ART is present detect the numerator:denominator to convert to TSC
+ */
+static void detect_art(void)
+{
+       unsigned int unused[2];
+
+       if (boot_cpu_data.cpuid_level < ART_CPUID_LEAF)
+               return;
+
+       cpuid(ART_CPUID_LEAF, &art_to_tsc_denominator,
+             &art_to_tsc_numerator, unused, unused+1);
+
+       /* Don't enable ART in a VM, non-stop TSC required */
+       if (boot_cpu_has(X86_FEATURE_HYPERVISOR) ||
+           !boot_cpu_has(X86_FEATURE_NONSTOP_TSC) ||
+           art_to_tsc_denominator < ART_MIN_DENOMINATOR)
+               return;
+
+       if (rdmsrl_safe(MSR_IA32_TSC_ADJUST, &art_to_tsc_offset))
+               return;
+
+       /* Make this sticky over multiple CPU init calls */
+       setup_force_cpu_cap(X86_FEATURE_ART);
+}
+
+
 /* clocksource code */
 
 static struct clocksource clocksource_tsc;
@@ -1071,6 +1107,25 @@ int unsynchronized_tsc(void)
        return 0;
 }
 
+/*
+ * Convert ART to TSC given numerator/denominator found in detect_art()
+ */
+struct system_counterval_t convert_art_to_tsc(cycle_t art)
+{
+       u64 tmp, res, rem;
+
+       rem = do_div(art, art_to_tsc_denominator);
+
+       res = art * art_to_tsc_numerator;
+       tmp = rem * art_to_tsc_numerator;
+
+       do_div(tmp, art_to_tsc_denominator);
+       res += tmp + art_to_tsc_offset;
+
+       return (struct system_counterval_t) {.cs = art_related_clocksource,
+                       .cycles = res};
+}
+EXPORT_SYMBOL(convert_art_to_tsc);
 
 static void tsc_refine_calibration_work(struct work_struct *work);
 static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
@@ -1142,6 +1197,8 @@ static void tsc_refine_calibration_work(struct work_struct *work)
                (unsigned long)tsc_khz % 1000);
 
 out:
+       if (boot_cpu_has(X86_FEATURE_ART))
+               art_related_clocksource = &clocksource_tsc;
        clocksource_register_khz(&clocksource_tsc, tsc_khz);
 }
 
@@ -1235,6 +1292,8 @@ void __init tsc_init(void)
                mark_tsc_unstable("TSCs unsynchronized");
 
        check_system_tsc_reliable();
+
+       detect_art();
 }
 
 #ifdef CONFIG_SMP
@@ -1246,14 +1305,14 @@ void __init tsc_init(void)
  */
 unsigned long calibrate_delay_is_known(void)
 {
-       int i, cpu = smp_processor_id();
+       int sibling, cpu = smp_processor_id();
 
        if (!tsc_disabled && !cpu_has(&cpu_data(cpu), X86_FEATURE_CONSTANT_TSC))
                return 0;
 
-       for_each_online_cpu(i)
-               if (cpu_data(i).phys_proc_id == cpu_data(cpu).phys_proc_id)
-                       return cpu_data(i).loops_per_jiffy;
+       sibling = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+       if (sibling < nr_cpu_ids)
+               return cpu_data(sibling).loops_per_jiffy;
        return 0;
 }
 #endif
index 07efb35ee4bc3fd5f4452af68214de79dc936716..014ea59aa153e4f37725dd8771cdb37d88371e34 100644 (file)
@@ -30,7 +30,7 @@
  *     appropriately. Either display a message or halt.
  */
 
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/msr-index.h>
 
 verify_cpu:
index e574b85465185fe273a839093452c26521ac3d1e..3dce1ca0a653091967f7089ce9e89c9d54399408 100644 (file)
@@ -362,7 +362,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)
        /* make room for real-mode segments */
        tsk->thread.sp0 += 16;
 
-       if (static_cpu_has_safe(X86_FEATURE_SEP))
+       if (static_cpu_has(X86_FEATURE_SEP))
                tsk->thread.sysenter_cs = 0;
 
        load_sp0(tss, &tsk->thread);
index 74e4bf11f562e0354c227518421e2375ec16fafa..5af9958cbdb6be4293b62181ffe104f435caf830 100644 (file)
@@ -41,29 +41,28 @@ ENTRY(phys_startup_64)
 jiffies_64 = jiffies;
 #endif
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
+#if defined(CONFIG_X86_64)
 /*
- * On 64-bit, align RODATA to 2MB so that even with CONFIG_DEBUG_RODATA
- * we retain large page mappings for boundaries spanning kernel text, rodata
- * and data sections.
+ * On 64-bit, align RODATA to 2MB so we retain large page mappings for
+ * boundaries spanning kernel text, rodata and data sections.
  *
  * However, kernel identity mappings will have different RWX permissions
  * to the pages mapping to text and to the pages padding (which are freed) the
  * text section. Hence kernel identity mappings will be broken to smaller
  * pages. For 64-bit, kernel text and kernel identity mappings are different,
- * so we can enable protection checks that come with CONFIG_DEBUG_RODATA,
- * as well as retain 2MB large page mappings for kernel text.
+ * so we can enable protection checks as well as retain 2MB large page
+ * mappings for kernel text.
  */
-#define X64_ALIGN_DEBUG_RODATA_BEGIN   . = ALIGN(HPAGE_SIZE);
+#define X64_ALIGN_RODATA_BEGIN . = ALIGN(HPAGE_SIZE);
 
-#define X64_ALIGN_DEBUG_RODATA_END                             \
+#define X64_ALIGN_RODATA_END                                   \
                . = ALIGN(HPAGE_SIZE);                          \
                __end_rodata_hpage_align = .;
 
 #else
 
-#define X64_ALIGN_DEBUG_RODATA_BEGIN
-#define X64_ALIGN_DEBUG_RODATA_END
+#define X64_ALIGN_RODATA_BEGIN
+#define X64_ALIGN_RODATA_END
 
 #endif
 
@@ -112,13 +111,11 @@ SECTIONS
 
        EXCEPTION_TABLE(16) :text = 0x9090
 
-#if defined(CONFIG_DEBUG_RODATA)
        /* .text should occupy whole number of pages */
        . = ALIGN(PAGE_SIZE);
-#endif
-       X64_ALIGN_DEBUG_RODATA_BEGIN
+       X64_ALIGN_RODATA_BEGIN
        RO_DATA(PAGE_SIZE)
-       X64_ALIGN_DEBUG_RODATA_END
+       X64_ALIGN_RODATA_END
 
        /* Data */
        .data : AT(ADDR(.data) - LOAD_OFFSET) {
@@ -195,6 +192,17 @@ SECTIONS
        :init
 #endif
 
+       /*
+        * Section for code used exclusively before alternatives are run. All
+        * references to such code must be patched out by alternatives, normally
+        * by using X86_FEATURE_ALWAYS CPU feature bit.
+        *
+        * See static_cpu_has() for an example.
+        */
+       .altinstr_aux : AT(ADDR(.altinstr_aux) - LOAD_OFFSET) {
+               *(.altinstr_aux)
+       }
+
        INIT_DATA_SECTION(16)
 
        .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
index a0695be19864eda009742b142ba2046e13ad05f9..cd05942bc9189452d8ec7c0cebd96431cf8dd394 100644 (file)
@@ -37,6 +37,8 @@ EXPORT_SYMBOL(__copy_user_nocache);
 EXPORT_SYMBOL(_copy_from_user);
 EXPORT_SYMBOL(_copy_to_user);
 
+EXPORT_SYMBOL_GPL(memcpy_mcsafe);
+
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(clear_page);
 
index a1ff508bb423b946bddc531dc456bd68a54024b0..464fa477afbfb5211199ddfc73c67829b9a8a67c 100644 (file)
@@ -13,9 +13,10 @@ kvm-$(CONFIG_KVM_ASYNC_PF)   += $(KVM)/async_pf.o
 
 kvm-y                  += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
                           i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
-                          hyperv.o
+                          hyperv.o page_track.o
 
 kvm-$(CONFIG_KVM_DEVICE_ASSIGNMENT)    += assigned-dev.o iommu.o
+
 kvm-intel-y            += vmx.o pmu_intel.o
 kvm-amd-y              += svm.o pmu_amd.o
 
index 9dc091acd5fbab0a6da92510447174a6d995e22c..308b8597c6913c0c2010e7119ea1350d1bf46a3c 100644 (file)
@@ -51,11 +51,9 @@ struct kvm_assigned_dev_kernel {
 static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head,
                                                      int assigned_dev_id)
 {
-       struct list_head *ptr;
        struct kvm_assigned_dev_kernel *match;
 
-       list_for_each(ptr, head) {
-               match = list_entry(ptr, struct kvm_assigned_dev_kernel, list);
+       list_for_each_entry(match, head, list) {
                if (match->assigned_dev_id == assigned_dev_id)
                        return match;
        }
@@ -373,14 +371,10 @@ static void kvm_free_assigned_device(struct kvm *kvm,
 
 void kvm_free_all_assigned_devices(struct kvm *kvm)
 {
-       struct list_head *ptr, *ptr2;
-       struct kvm_assigned_dev_kernel *assigned_dev;
-
-       list_for_each_safe(ptr, ptr2, &kvm->arch.assigned_dev_head) {
-               assigned_dev = list_entry(ptr,
-                                         struct kvm_assigned_dev_kernel,
-                                         list);
+       struct kvm_assigned_dev_kernel *assigned_dev, *tmp;
 
+       list_for_each_entry_safe(assigned_dev, tmp,
+                                &kvm->arch.assigned_dev_head, list) {
                kvm_free_assigned_device(kvm, assigned_dev);
        }
 }
index 6525e926f56682549d697bb0253f5da600728710..0029644bf09c39117ef7c1d2cca05561341a24e1 100644 (file)
@@ -46,11 +46,18 @@ static u32 xstate_required_size(u64 xstate_bv, bool compacted)
        return ret;
 }
 
+bool kvm_mpx_supported(void)
+{
+       return ((host_xcr0 & (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR))
+                && kvm_x86_ops->mpx_supported());
+}
+EXPORT_SYMBOL_GPL(kvm_mpx_supported);
+
 u64 kvm_supported_xcr0(void)
 {
        u64 xcr0 = KVM_SUPPORTED_XCR0 & host_xcr0;
 
-       if (!kvm_x86_ops->mpx_supported())
+       if (!kvm_mpx_supported())
                xcr0 &= ~(XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR);
 
        return xcr0;
@@ -97,8 +104,7 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
        if (best && (best->eax & (F(XSAVES) | F(XSAVEC))))
                best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
 
-       vcpu->arch.eager_fpu = use_eager_fpu() || guest_cpuid_has_mpx(vcpu);
-       if (vcpu->arch.eager_fpu)
+       if (use_eager_fpu())
                kvm_x86_ops->fpu_activate(vcpu);
 
        /*
@@ -295,7 +301,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 #endif
        unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
        unsigned f_invpcid = kvm_x86_ops->invpcid_supported() ? F(INVPCID) : 0;
-       unsigned f_mpx = kvm_x86_ops->mpx_supported() ? F(MPX) : 0;
+       unsigned f_mpx = kvm_mpx_supported() ? F(MPX) : 0;
        unsigned f_xsaves = kvm_x86_ops->xsaves_supported() ? F(XSAVES) : 0;
 
        /* cpuid 1.edx */
index c8eda1498121fc6ee82c2facad7464eb712aa75b..66a6581724ad264aa2f7d9e2678efa243a471fbd 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/cpu.h>
 
 int kvm_update_cpuid(struct kvm_vcpu *vcpu);
+bool kvm_mpx_supported(void);
 struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
                                              u32 function, u32 index);
 int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
@@ -135,14 +136,6 @@ static inline bool guest_cpuid_has_rtm(struct kvm_vcpu *vcpu)
        return best && (best->ebx & bit(X86_FEATURE_RTM));
 }
 
-static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu)
-{
-       struct kvm_cpuid_entry2 *best;
-
-       best = kvm_find_cpuid_entry(vcpu, 7, 0);
-       return best && (best->ebx & bit(X86_FEATURE_MPX));
-}
-
 static inline bool guest_cpuid_has_pcommit(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index 1505587d06e97826703b21aba540ea8403bd8f2c..b9b09fec173bf2fedb0b9ee122b3c4668eb6e471 100644 (file)
@@ -650,10 +650,10 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
        u16 sel;
 
        la = seg_base(ctxt, addr.seg) + addr.ea;
-       *linear = la;
        *max_size = 0;
        switch (mode) {
        case X86EMUL_MODE_PROT64:
+               *linear = la;
                if (is_noncanonical_address(la))
                        goto bad;
 
@@ -662,6 +662,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
                        goto bad;
                break;
        default:
+               *linear = la = (u32)la;
                usable = ctxt->ops->get_segment(ctxt, &sel, &desc, NULL,
                                                addr.seg);
                if (!usable)
@@ -689,7 +690,6 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
                        if (size > *max_size)
                                goto bad;
                }
-               la &= (u32)-1;
                break;
        }
        if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))
index c58ba67175acde5b8b3e12dbaf84df46fb44f62c..5ff3485acb60b2ad37a93084cd91a13c888c6fbc 100644 (file)
@@ -1043,6 +1043,27 @@ bool kvm_hv_hypercall_enabled(struct kvm *kvm)
        return kvm->arch.hyperv.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE;
 }
 
+static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result)
+{
+       bool longmode;
+
+       longmode = is_64_bit_mode(vcpu);
+       if (longmode)
+               kvm_register_write(vcpu, VCPU_REGS_RAX, result);
+       else {
+               kvm_register_write(vcpu, VCPU_REGS_RDX, result >> 32);
+               kvm_register_write(vcpu, VCPU_REGS_RAX, result & 0xffffffff);
+       }
+}
+
+static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu)
+{
+       struct kvm_run *run = vcpu->run;
+
+       kvm_hv_hypercall_set_result(vcpu, run->hyperv.u.hcall.result);
+       return 1;
+}
+
 int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
 {
        u64 param, ingpa, outgpa, ret;
@@ -1055,7 +1076,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
         */
        if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) {
                kvm_queue_exception(vcpu, UD_VECTOR);
-               return 0;
+               return 1;
        }
 
        longmode = is_64_bit_mode(vcpu);
@@ -1083,22 +1104,33 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
 
        trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa);
 
+       /* Hypercall continuation is not supported yet */
+       if (rep_cnt || rep_idx) {
+               res = HV_STATUS_INVALID_HYPERCALL_CODE;
+               goto set_result;
+       }
+
        switch (code) {
-       case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT:
+       case HVCALL_NOTIFY_LONG_SPIN_WAIT:
                kvm_vcpu_on_spin(vcpu);
                break;
+       case HVCALL_POST_MESSAGE:
+       case HVCALL_SIGNAL_EVENT:
+               vcpu->run->exit_reason = KVM_EXIT_HYPERV;
+               vcpu->run->hyperv.type = KVM_EXIT_HYPERV_HCALL;
+               vcpu->run->hyperv.u.hcall.input = param;
+               vcpu->run->hyperv.u.hcall.params[0] = ingpa;
+               vcpu->run->hyperv.u.hcall.params[1] = outgpa;
+               vcpu->arch.complete_userspace_io =
+                               kvm_hv_hypercall_complete_userspace;
+               return 0;
        default:
                res = HV_STATUS_INVALID_HYPERCALL_CODE;
                break;
        }
 
+set_result:
        ret = res | (((u64)rep_done & 0xfff) << 32);
-       if (longmode) {
-               kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
-       } else {
-               kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32);
-               kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0xffffffff);
-       }
-
+       kvm_hv_hypercall_set_result(vcpu, ret);
        return 1;
 }
index b0ea42b78ccdb50879a10c440d5e3a7fe194fbe9..a4bf5b45d65a77d55d7c3e672e1bc934faa9f079 100644 (file)
 #define RW_STATE_WORD0 3
 #define RW_STATE_WORD1 4
 
-/* Compute with 96 bit intermediate result: (a*b)/c */
-static u64 muldiv64(u64 a, u32 b, u32 c)
+static void pit_set_gate(struct kvm_pit *pit, int channel, u32 val)
 {
-       union {
-               u64 ll;
-               struct {
-                       u32 low, high;
-               } l;
-       } u, res;
-       u64 rl, rh;
-
-       u.ll = a;
-       rl = (u64)u.l.low * (u64)b;
-       rh = (u64)u.l.high * (u64)b;
-       rh += (rl >> 32);
-       res.l.high = div64_u64(rh, c);
-       res.l.low = div64_u64(((mod_64(rh, c) << 32) + (rl & 0xffffffff)), c);
-       return res.ll;
-}
-
-static void pit_set_gate(struct kvm *kvm, int channel, u32 val)
-{
-       struct kvm_kpit_channel_state *c =
-               &kvm->arch.vpit->pit_state.channels[channel];
-
-       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+       struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel];
 
        switch (c->mode) {
        default:
@@ -97,18 +74,16 @@ static void pit_set_gate(struct kvm *kvm, int channel, u32 val)
        c->gate = val;
 }
 
-static int pit_get_gate(struct kvm *kvm, int channel)
+static int pit_get_gate(struct kvm_pit *pit, int channel)
 {
-       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
-
-       return kvm->arch.vpit->pit_state.channels[channel].gate;
+       return pit->pit_state.channels[channel].gate;
 }
 
-static s64 __kpit_elapsed(struct kvm *kvm)
+static s64 __kpit_elapsed(struct kvm_pit *pit)
 {
        s64 elapsed;
        ktime_t remaining;
-       struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
+       struct kvm_kpit_state *ps = &pit->pit_state;
 
        if (!ps->period)
                return 0;
@@ -128,26 +103,23 @@ static s64 __kpit_elapsed(struct kvm *kvm)
        return elapsed;
 }
 
-static s64 kpit_elapsed(struct kvm *kvm, struct kvm_kpit_channel_state *c,
+static s64 kpit_elapsed(struct kvm_pit *pit, struct kvm_kpit_channel_state *c,
                        int channel)
 {
        if (channel == 0)
-               return __kpit_elapsed(kvm);
+               return __kpit_elapsed(pit);
 
        return ktime_to_ns(ktime_sub(ktime_get(), c->count_load_time));
 }
 
-static int pit_get_count(struct kvm *kvm, int channel)
+static int pit_get_count(struct kvm_pit *pit, int channel)
 {
-       struct kvm_kpit_channel_state *c =
-               &kvm->arch.vpit->pit_state.channels[channel];
+       struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel];
        s64 d, t;
        int counter;
 
-       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
-
-       t = kpit_elapsed(kvm, c, channel);
-       d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
+       t = kpit_elapsed(pit, c, channel);
+       d = mul_u64_u32_div(t, KVM_PIT_FREQ, NSEC_PER_SEC);
 
        switch (c->mode) {
        case 0:
@@ -167,17 +139,14 @@ static int pit_get_count(struct kvm *kvm, int channel)
        return counter;
 }
 
-static int pit_get_out(struct kvm *kvm, int channel)
+static int pit_get_out(struct kvm_pit *pit, int channel)
 {
-       struct kvm_kpit_channel_state *c =
-               &kvm->arch.vpit->pit_state.channels[channel];
+       struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel];
        s64 d, t;
        int out;
 
-       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
-
-       t = kpit_elapsed(kvm, c, channel);
-       d = muldiv64(t, KVM_PIT_FREQ, NSEC_PER_SEC);
+       t = kpit_elapsed(pit, c, channel);
+       d = mul_u64_u32_div(t, KVM_PIT_FREQ, NSEC_PER_SEC);
 
        switch (c->mode) {
        default:
@@ -202,29 +171,23 @@ static int pit_get_out(struct kvm *kvm, int channel)
        return out;
 }
 
-static void pit_latch_count(struct kvm *kvm, int channel)
+static void pit_latch_count(struct kvm_pit *pit, int channel)
 {
-       struct kvm_kpit_channel_state *c =
-               &kvm->arch.vpit->pit_state.channels[channel];
-
-       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+       struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel];
 
        if (!c->count_latched) {
-               c->latched_count = pit_get_count(kvm, channel);
+               c->latched_count = pit_get_count(pit, channel);
                c->count_latched = c->rw_mode;
        }
 }
 
-static void pit_latch_status(struct kvm *kvm, int channel)
+static void pit_latch_status(struct kvm_pit *pit, int channel)
 {
-       struct kvm_kpit_channel_state *c =
-               &kvm->arch.vpit->pit_state.channels[channel];
-
-       WARN_ON(!mutex_is_locked(&kvm->arch.vpit->pit_state.lock));
+       struct kvm_kpit_channel_state *c = &pit->pit_state.channels[channel];
 
        if (!c->status_latched) {
                /* TODO: Return NULL COUNT (bit 6). */
-               c->status = ((pit_get_out(kvm, channel) << 7) |
+               c->status = ((pit_get_out(pit, channel) << 7) |
                                (c->rw_mode << 4) |
                                (c->mode << 1) |
                                c->bcd);
@@ -232,26 +195,24 @@ static void pit_latch_status(struct kvm *kvm, int channel)
        }
 }
 
+static inline struct kvm_pit *pit_state_to_pit(struct kvm_kpit_state *ps)
+{
+       return container_of(ps, struct kvm_pit, pit_state);
+}
+
 static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
 {
        struct kvm_kpit_state *ps = container_of(kian, struct kvm_kpit_state,
                                                 irq_ack_notifier);
-       int value;
-
-       spin_lock(&ps->inject_lock);
-       value = atomic_dec_return(&ps->pending);
-       if (value < 0)
-               /* spurious acks can be generated if, for example, the
-                * PIC is being reset.  Handle it gracefully here
-                */
-               atomic_inc(&ps->pending);
-       else if (value > 0)
-               /* in this case, we had multiple outstanding pit interrupts
-                * that we needed to inject.  Reinject
-                */
-               queue_kthread_work(&ps->pit->worker, &ps->pit->expired);
-       ps->irq_ack = 1;
-       spin_unlock(&ps->inject_lock);
+       struct kvm_pit *pit = pit_state_to_pit(ps);
+
+       atomic_set(&ps->irq_ack, 1);
+       /* irq_ack should be set before pending is read.  Order accesses with
+        * inc(pending) in pit_timer_fn and xchg(irq_ack, 0) in pit_do_work.
+        */
+       smp_mb();
+       if (atomic_dec_if_positive(&ps->pending) > 0)
+               queue_kthread_work(&pit->worker, &pit->expired);
 }
 
 void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
@@ -282,45 +243,36 @@ static void pit_do_work(struct kthread_work *work)
        struct kvm_vcpu *vcpu;
        int i;
        struct kvm_kpit_state *ps = &pit->pit_state;
-       int inject = 0;
 
-       /* Try to inject pending interrupts when
-        * last one has been acked.
+       if (atomic_read(&ps->reinject) && !atomic_xchg(&ps->irq_ack, 0))
+               return;
+
+       kvm_set_irq(kvm, pit->irq_source_id, 0, 1, false);
+       kvm_set_irq(kvm, pit->irq_source_id, 0, 0, false);
+
+       /*
+        * Provides NMI watchdog support via Virtual Wire mode.
+        * The route is: PIT -> LVT0 in NMI mode.
+        *
+        * Note: Our Virtual Wire implementation does not follow
+        * the MP specification.  We propagate a PIT interrupt to all
+        * VCPUs and only when LVT0 is in NMI mode.  The interrupt can
+        * also be simultaneously delivered through PIC and IOAPIC.
         */
-       spin_lock(&ps->inject_lock);
-       if (ps->irq_ack) {
-               ps->irq_ack = 0;
-               inject = 1;
-       }
-       spin_unlock(&ps->inject_lock);
-       if (inject) {
-               kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 1, false);
-               kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 0, false);
-
-               /*
-                * Provides NMI watchdog support via Virtual Wire mode.
-                * The route is: PIT -> PIC -> LVT0 in NMI mode.
-                *
-                * Note: Our Virtual Wire implementation is simplified, only
-                * propagating PIT interrupts to all VCPUs when they have set
-                * LVT0 to NMI delivery. Other PIC interrupts are just sent to
-                * VCPU0, and only if its LVT0 is in EXTINT mode.
-                */
-               if (atomic_read(&kvm->arch.vapics_in_nmi_mode) > 0)
-                       kvm_for_each_vcpu(i, vcpu, kvm)
-                               kvm_apic_nmi_wd_deliver(vcpu);
-       }
+       if (atomic_read(&kvm->arch.vapics_in_nmi_mode) > 0)
+               kvm_for_each_vcpu(i, vcpu, kvm)
+                       kvm_apic_nmi_wd_deliver(vcpu);
 }
 
 static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
 {
        struct kvm_kpit_state *ps = container_of(data, struct kvm_kpit_state, timer);
-       struct kvm_pit *pt = ps->kvm->arch.vpit;
+       struct kvm_pit *pt = pit_state_to_pit(ps);
 
-       if (ps->reinject || !atomic_read(&ps->pending)) {
+       if (atomic_read(&ps->reinject))
                atomic_inc(&ps->pending);
-               queue_kthread_work(&pt->worker, &pt->expired);
-       }
+
+       queue_kthread_work(&pt->worker, &pt->expired);
 
        if (ps->is_periodic) {
                hrtimer_add_expires_ns(&ps->timer, ps->period);
@@ -329,30 +281,54 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
                return HRTIMER_NORESTART;
 }
 
-static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
+static inline void kvm_pit_reset_reinject(struct kvm_pit *pit)
 {
-       struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
+       atomic_set(&pit->pit_state.pending, 0);
+       atomic_set(&pit->pit_state.irq_ack, 1);
+}
+
+void kvm_pit_set_reinject(struct kvm_pit *pit, bool reinject)
+{
+       struct kvm_kpit_state *ps = &pit->pit_state;
+       struct kvm *kvm = pit->kvm;
+
+       if (atomic_read(&ps->reinject) == reinject)
+               return;
+
+       if (reinject) {
+               /* The initial state is preserved while ps->reinject == 0. */
+               kvm_pit_reset_reinject(pit);
+               kvm_register_irq_ack_notifier(kvm, &ps->irq_ack_notifier);
+               kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
+       } else {
+               kvm_unregister_irq_ack_notifier(kvm, &ps->irq_ack_notifier);
+               kvm_unregister_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
+       }
+
+       atomic_set(&ps->reinject, reinject);
+}
+
+static void create_pit_timer(struct kvm_pit *pit, u32 val, int is_period)
+{
+       struct kvm_kpit_state *ps = &pit->pit_state;
+       struct kvm *kvm = pit->kvm;
        s64 interval;
 
        if (!ioapic_in_kernel(kvm) ||
            ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)
                return;
 
-       interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
+       interval = mul_u64_u32_div(val, NSEC_PER_SEC, KVM_PIT_FREQ);
 
        pr_debug("create pit timer, interval is %llu nsec\n", interval);
 
        /* TODO The new value only affected after the retriggered */
        hrtimer_cancel(&ps->timer);
-       flush_kthread_work(&ps->pit->expired);
+       flush_kthread_work(&pit->expired);
        ps->period = interval;
        ps->is_periodic = is_period;
 
-       ps->timer.function = pit_timer_fn;
-       ps->kvm = ps->pit->kvm;
-
-       atomic_set(&ps->pending, 0);
-       ps->irq_ack = 1;
+       kvm_pit_reset_reinject(pit);
 
        /*
         * Do not allow the guest to program periodic timers with small
@@ -375,11 +351,9 @@ static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
                      HRTIMER_MODE_ABS);
 }
 
-static void pit_load_count(struct kvm *kvm, int channel, u32 val)
+static void pit_load_count(struct kvm_pit *pit, int channel, u32 val)
 {
-       struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
-
-       WARN_ON(!mutex_is_locked(&ps->lock));
+       struct kvm_kpit_state *ps = &pit->pit_state;
 
        pr_debug("load_count val is %d, channel is %d\n", val, channel);
 
@@ -404,29 +378,33 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val)
        case 1:
         /* FIXME: enhance mode 4 precision */
        case 4:
-               create_pit_timer(kvm, val, 0);
+               create_pit_timer(pit, val, 0);
                break;
        case 2:
        case 3:
-               create_pit_timer(kvm, val, 1);
+               create_pit_timer(pit, val, 1);
                break;
        default:
-               destroy_pit_timer(kvm->arch.vpit);
+               destroy_pit_timer(pit);
        }
 }
 
-void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val, int hpet_legacy_start)
+void kvm_pit_load_count(struct kvm_pit *pit, int channel, u32 val,
+               int hpet_legacy_start)
 {
        u8 saved_mode;
+
+       WARN_ON_ONCE(!mutex_is_locked(&pit->pit_state.lock));
+
        if (hpet_legacy_start) {
                /* save existing mode for later reenablement */
                WARN_ON(channel != 0);
-               saved_mode = kvm->arch.vpit->pit_state.channels[0].mode;
-               kvm->arch.vpit->pit_state.channels[0].mode = 0xff; /* disable timer */
-               pit_load_count(kvm, channel, val);
-               kvm->arch.vpit->pit_state.channels[0].mode = saved_mode;
+               saved_mode = pit->pit_state.channels[0].mode;
+               pit->pit_state.channels[0].mode = 0xff; /* disable timer */
+               pit_load_count(pit, channel, val);
+               pit->pit_state.channels[0].mode = saved_mode;
        } else {
-               pit_load_count(kvm, channel, val);
+               pit_load_count(pit, channel, val);
        }
 }
 
@@ -452,7 +430,6 @@ static int pit_ioport_write(struct kvm_vcpu *vcpu,
 {
        struct kvm_pit *pit = dev_to_pit(this);
        struct kvm_kpit_state *pit_state = &pit->pit_state;
-       struct kvm *kvm = pit->kvm;
        int channel, access;
        struct kvm_kpit_channel_state *s;
        u32 val = *(u32 *) data;
@@ -476,9 +453,9 @@ static int pit_ioport_write(struct kvm_vcpu *vcpu,
                                s = &pit_state->channels[channel];
                                if (val & (2 << channel)) {
                                        if (!(val & 0x20))
-                                               pit_latch_count(kvm, channel);
+                                               pit_latch_count(pit, channel);
                                        if (!(val & 0x10))
-                                               pit_latch_status(kvm, channel);
+                                               pit_latch_status(pit, channel);
                                }
                        }
                } else {
@@ -486,7 +463,7 @@ static int pit_ioport_write(struct kvm_vcpu *vcpu,
                        s = &pit_state->channels[channel];
                        access = (val >> 4) & KVM_PIT_CHANNEL_MASK;
                        if (access == 0) {
-                               pit_latch_count(kvm, channel);
+                               pit_latch_count(pit, channel);
                        } else {
                                s->rw_mode = access;
                                s->read_state = access;
@@ -503,17 +480,17 @@ static int pit_ioport_write(struct kvm_vcpu *vcpu,
                switch (s->write_state) {
                default:
                case RW_STATE_LSB:
-                       pit_load_count(kvm, addr, val);
+                       pit_load_count(pit, addr, val);
                        break;
                case RW_STATE_MSB:
-                       pit_load_count(kvm, addr, val << 8);
+                       pit_load_count(pit, addr, val << 8);
                        break;
                case RW_STATE_WORD0:
                        s->write_latch = val;
                        s->write_state = RW_STATE_WORD1;
                        break;
                case RW_STATE_WORD1:
-                       pit_load_count(kvm, addr, s->write_latch | (val << 8));
+                       pit_load_count(pit, addr, s->write_latch | (val << 8));
                        s->write_state = RW_STATE_WORD0;
                        break;
                }
@@ -529,7 +506,6 @@ static int pit_ioport_read(struct kvm_vcpu *vcpu,
 {
        struct kvm_pit *pit = dev_to_pit(this);
        struct kvm_kpit_state *pit_state = &pit->pit_state;
-       struct kvm *kvm = pit->kvm;
        int ret, count;
        struct kvm_kpit_channel_state *s;
        if (!pit_in_range(addr))
@@ -566,20 +542,20 @@ static int pit_ioport_read(struct kvm_vcpu *vcpu,
                switch (s->read_state) {
                default:
                case RW_STATE_LSB:
-                       count = pit_get_count(kvm, addr);
+                       count = pit_get_count(pit, addr);
                        ret = count & 0xff;
                        break;
                case RW_STATE_MSB:
-                       count = pit_get_count(kvm, addr);
+                       count = pit_get_count(pit, addr);
                        ret = (count >> 8) & 0xff;
                        break;
                case RW_STATE_WORD0:
-                       count = pit_get_count(kvm, addr);
+                       count = pit_get_count(pit, addr);
                        ret = count & 0xff;
                        s->read_state = RW_STATE_WORD1;
                        break;
                case RW_STATE_WORD1:
-                       count = pit_get_count(kvm, addr);
+                       count = pit_get_count(pit, addr);
                        ret = (count >> 8) & 0xff;
                        s->read_state = RW_STATE_WORD0;
                        break;
@@ -600,14 +576,13 @@ static int speaker_ioport_write(struct kvm_vcpu *vcpu,
 {
        struct kvm_pit *pit = speaker_to_pit(this);
        struct kvm_kpit_state *pit_state = &pit->pit_state;
-       struct kvm *kvm = pit->kvm;
        u32 val = *(u32 *) data;
        if (addr != KVM_SPEAKER_BASE_ADDRESS)
                return -EOPNOTSUPP;
 
        mutex_lock(&pit_state->lock);
        pit_state->speaker_data_on = (val >> 1) & 1;
-       pit_set_gate(kvm, 2, val & 1);
+       pit_set_gate(pit, 2, val & 1);
        mutex_unlock(&pit_state->lock);
        return 0;
 }
@@ -618,7 +593,6 @@ static int speaker_ioport_read(struct kvm_vcpu *vcpu,
 {
        struct kvm_pit *pit = speaker_to_pit(this);
        struct kvm_kpit_state *pit_state = &pit->pit_state;
-       struct kvm *kvm = pit->kvm;
        unsigned int refresh_clock;
        int ret;
        if (addr != KVM_SPEAKER_BASE_ADDRESS)
@@ -628,8 +602,8 @@ static int speaker_ioport_read(struct kvm_vcpu *vcpu,
        refresh_clock = ((unsigned int)ktime_to_ns(ktime_get()) >> 14) & 1;
 
        mutex_lock(&pit_state->lock);
-       ret = ((pit_state->speaker_data_on << 1) | pit_get_gate(kvm, 2) |
-               (pit_get_out(kvm, 2) << 5) | (refresh_clock << 4));
+       ret = ((pit_state->speaker_data_on << 1) | pit_get_gate(pit, 2) |
+               (pit_get_out(pit, 2) << 5) | (refresh_clock << 4));
        if (len > sizeof(ret))
                len = sizeof(ret);
        memcpy(data, (char *)&ret, len);
@@ -637,33 +611,28 @@ static int speaker_ioport_read(struct kvm_vcpu *vcpu,
        return 0;
 }
 
-void kvm_pit_reset(struct kvm_pit *pit)
+static void kvm_pit_reset(struct kvm_pit *pit)
 {
        int i;
        struct kvm_kpit_channel_state *c;
 
-       mutex_lock(&pit->pit_state.lock);
        pit->pit_state.flags = 0;
        for (i = 0; i < 3; i++) {
                c = &pit->pit_state.channels[i];
                c->mode = 0xff;
                c->gate = (i != 2);
-               pit_load_count(pit->kvm, i, 0);
+               pit_load_count(pit, i, 0);
        }
-       mutex_unlock(&pit->pit_state.lock);
 
-       atomic_set(&pit->pit_state.pending, 0);
-       pit->pit_state.irq_ack = 1;
+       kvm_pit_reset_reinject(pit);
 }
 
 static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask)
 {
        struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier);
 
-       if (!mask) {
-               atomic_set(&pit->pit_state.pending, 0);
-               pit->pit_state.irq_ack = 1;
-       }
+       if (!mask)
+               kvm_pit_reset_reinject(pit);
 }
 
 static const struct kvm_io_device_ops pit_dev_ops = {
@@ -690,14 +659,10 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
                return NULL;
 
        pit->irq_source_id = kvm_request_irq_source_id(kvm);
-       if (pit->irq_source_id < 0) {
-               kfree(pit);
-               return NULL;
-       }
+       if (pit->irq_source_id < 0)
+               goto fail_request;
 
        mutex_init(&pit->pit_state.lock);
-       mutex_lock(&pit->pit_state.lock);
-       spin_lock_init(&pit->pit_state.inject_lock);
 
        pid = get_pid(task_tgid(current));
        pid_nr = pid_vnr(pid);
@@ -706,36 +671,30 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
        init_kthread_worker(&pit->worker);
        pit->worker_task = kthread_run(kthread_worker_fn, &pit->worker,
                                       "kvm-pit/%d", pid_nr);
-       if (IS_ERR(pit->worker_task)) {
-               mutex_unlock(&pit->pit_state.lock);
-               kvm_free_irq_source_id(kvm, pit->irq_source_id);
-               kfree(pit);
-               return NULL;
-       }
+       if (IS_ERR(pit->worker_task))
+               goto fail_kthread;
+
        init_kthread_work(&pit->expired, pit_do_work);
 
-       kvm->arch.vpit = pit;
        pit->kvm = kvm;
 
        pit_state = &pit->pit_state;
-       pit_state->pit = pit;
        hrtimer_init(&pit_state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       pit_state->timer.function = pit_timer_fn;
+
        pit_state->irq_ack_notifier.gsi = 0;
        pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq;
-       kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
-       pit_state->reinject = true;
-       mutex_unlock(&pit->pit_state.lock);
+       pit->mask_notifier.func = pit_mask_notifer;
 
        kvm_pit_reset(pit);
 
-       pit->mask_notifier.func = pit_mask_notifer;
-       kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
+       kvm_pit_set_reinject(pit, true);
 
        kvm_iodevice_init(&pit->dev, &pit_dev_ops);
        ret = kvm_io_bus_register_dev(kvm, KVM_PIO_BUS, KVM_PIT_BASE_ADDRESS,
                                      KVM_PIT_MEM_LENGTH, &pit->dev);
        if (ret < 0)
-               goto fail;
+               goto fail_register_pit;
 
        if (flags & KVM_PIT_SPEAKER_DUMMY) {
                kvm_iodevice_init(&pit->speaker_dev, &speaker_dev_ops);
@@ -743,42 +702,35 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
                                              KVM_SPEAKER_BASE_ADDRESS, 4,
                                              &pit->speaker_dev);
                if (ret < 0)
-                       goto fail_unregister;
+                       goto fail_register_speaker;
        }
 
        return pit;
 
-fail_unregister:
+fail_register_speaker:
        kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->dev);
-
-fail:
-       kvm_unregister_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
-       kvm_unregister_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
-       kvm_free_irq_source_id(kvm, pit->irq_source_id);
+fail_register_pit:
+       kvm_pit_set_reinject(pit, false);
        kthread_stop(pit->worker_task);
+fail_kthread:
+       kvm_free_irq_source_id(kvm, pit->irq_source_id);
+fail_request:
        kfree(pit);
        return NULL;
 }
 
 void kvm_free_pit(struct kvm *kvm)
 {
-       struct hrtimer *timer;
-
-       if (kvm->arch.vpit) {
-               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &kvm->arch.vpit->dev);
-               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
-                                             &kvm->arch.vpit->speaker_dev);
-               kvm_unregister_irq_mask_notifier(kvm, 0,
-                                              &kvm->arch.vpit->mask_notifier);
-               kvm_unregister_irq_ack_notifier(kvm,
-                               &kvm->arch.vpit->pit_state.irq_ack_notifier);
-               mutex_lock(&kvm->arch.vpit->pit_state.lock);
-               timer = &kvm->arch.vpit->pit_state.timer;
-               hrtimer_cancel(timer);
-               flush_kthread_work(&kvm->arch.vpit->expired);
-               kthread_stop(kvm->arch.vpit->worker_task);
-               kvm_free_irq_source_id(kvm, kvm->arch.vpit->irq_source_id);
-               mutex_unlock(&kvm->arch.vpit->pit_state.lock);
-               kfree(kvm->arch.vpit);
+       struct kvm_pit *pit = kvm->arch.vpit;
+
+       if (pit) {
+               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->dev);
+               kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->speaker_dev);
+               kvm_pit_set_reinject(pit, false);
+               hrtimer_cancel(&pit->pit_state.timer);
+               flush_kthread_work(&pit->expired);
+               kthread_stop(pit->worker_task);
+               kvm_free_irq_source_id(kvm, pit->irq_source_id);
+               kfree(pit);
        }
 }
index c84990b42b5b189550eecc904f781c0e3ecadf3d..2f5af079832694e40baba94d41208a85511d04bd 100644 (file)
@@ -22,19 +22,18 @@ struct kvm_kpit_channel_state {
 };
 
 struct kvm_kpit_state {
+       /* All members before "struct mutex lock" are protected by the lock. */
        struct kvm_kpit_channel_state channels[3];
        u32 flags;
        bool is_periodic;
        s64 period;                             /* unit: ns */
        struct hrtimer timer;
-       atomic_t pending;                       /* accumulated triggered timers */
-       bool reinject;
-       struct kvm *kvm;
        u32    speaker_data_on;
+
        struct mutex lock;
-       struct kvm_pit *pit;
-       spinlock_t inject_lock;
-       unsigned long irq_ack;
+       atomic_t reinject;
+       atomic_t pending; /* accumulated triggered timers */
+       atomic_t irq_ack;
        struct kvm_irq_ack_notifier irq_ack_notifier;
 };
 
@@ -57,9 +56,11 @@ struct kvm_pit {
 #define KVM_MAX_PIT_INTR_INTERVAL   HZ / 100
 #define KVM_PIT_CHANNEL_MASK       0x3
 
-void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val, int hpet_legacy_start);
 struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags);
 void kvm_free_pit(struct kvm *kvm);
-void kvm_pit_reset(struct kvm_pit *pit);
+
+void kvm_pit_load_count(struct kvm_pit *pit, int channel, u32 val,
+               int hpet_legacy_start);
+void kvm_pit_set_reinject(struct kvm_pit *pit, bool reinject);
 
 #endif
index 1facfd60b04ac5eed05112b0cc3412396c8aa86d..9db47090ead006040415c423dc18169239068895 100644 (file)
@@ -94,7 +94,7 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
 static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic)
 {
        ioapic->rtc_status.pending_eoi = 0;
-       bitmap_zero(ioapic->rtc_status.dest_map, KVM_MAX_VCPUS);
+       bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPUS);
 }
 
 static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic);
@@ -117,16 +117,16 @@ static void __rtc_irq_eoi_tracking_restore_one(struct kvm_vcpu *vcpu)
                return;
 
        new_val = kvm_apic_pending_eoi(vcpu, e->fields.vector);
-       old_val = test_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map);
+       old_val = test_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map.map);
 
        if (new_val == old_val)
                return;
 
        if (new_val) {
-               __set_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map);
+               __set_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map.map);
                ioapic->rtc_status.pending_eoi++;
        } else {
-               __clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map);
+               __clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map.map);
                ioapic->rtc_status.pending_eoi--;
                rtc_status_pending_eoi_check_valid(ioapic);
        }
@@ -156,7 +156,8 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic)
 
 static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu)
 {
-       if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map)) {
+       if (test_and_clear_bit(vcpu->vcpu_id,
+                              ioapic->rtc_status.dest_map.map)) {
                --ioapic->rtc_status.pending_eoi;
                rtc_status_pending_eoi_check_valid(ioapic);
        }
@@ -236,10 +237,17 @@ static void kvm_ioapic_inject_all(struct kvm_ioapic *ioapic, unsigned long irr)
 void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, ulong *ioapic_handled_vectors)
 {
        struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;
+       struct dest_map *dest_map = &ioapic->rtc_status.dest_map;
        union kvm_ioapic_redirect_entry *e;
        int index;
 
        spin_lock(&ioapic->lock);
+
+       /* Make sure we see any missing RTC EOI */
+       if (test_bit(vcpu->vcpu_id, dest_map->map))
+               __set_bit(dest_map->vectors[vcpu->vcpu_id],
+                         ioapic_handled_vectors);
+
        for (index = 0; index < IOAPIC_NUM_PINS; index++) {
                e = &ioapic->redirtbl[index];
                if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG ||
@@ -346,7 +354,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
                 */
                BUG_ON(ioapic->rtc_status.pending_eoi != 0);
                ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
-                               ioapic->rtc_status.dest_map);
+                                              &ioapic->rtc_status.dest_map);
                ioapic->rtc_status.pending_eoi = (ret < 0 ? 0 : ret);
        } else
                ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, NULL);
@@ -407,8 +415,14 @@ static void kvm_ioapic_eoi_inject_work(struct work_struct *work)
 static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
                        struct kvm_ioapic *ioapic, int vector, int trigger_mode)
 {
-       int i;
+       struct dest_map *dest_map = &ioapic->rtc_status.dest_map;
        struct kvm_lapic *apic = vcpu->arch.apic;
+       int i;
+
+       /* RTC special handling */
+       if (test_bit(vcpu->vcpu_id, dest_map->map) &&
+           vector == dest_map->vectors[vcpu->vcpu_id])
+               rtc_irq_eoi(ioapic, vcpu);
 
        for (i = 0; i < IOAPIC_NUM_PINS; i++) {
                union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[i];
@@ -416,8 +430,6 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
                if (ent->fields.vector != vector)
                        continue;
 
-               if (i == RTC_GSI)
-                       rtc_irq_eoi(ioapic, vcpu);
                /*
                 * We are dropping lock while calling ack notifiers because ack
                 * notifier callbacks for assigned devices call into IOAPIC
index 2d16dc251d81a45cff53ae2a9d629e8ee7ecb732..7d2692a4965756143825d65d37688837d82aaca2 100644 (file)
@@ -40,9 +40,21 @@ struct kvm_vcpu;
 #define RTC_GSI -1U
 #endif
 
+struct dest_map {
+       /* vcpu bitmap where IRQ has been sent */
+       DECLARE_BITMAP(map, KVM_MAX_VCPUS);
+
+       /*
+        * Vector sent to a given vcpu, only valid when
+        * the vcpu's bit in map is set
+        */
+       u8 vectors[KVM_MAX_VCPUS];
+};
+
+
 struct rtc_status {
        int pending_eoi;
-       DECLARE_BITMAP(dest_map, KVM_MAX_VCPUS);
+       struct dest_map dest_map;
 };
 
 union kvm_ioapic_redirect_entry {
@@ -118,7 +130,8 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id,
                       int level, bool line_status);
 void kvm_ioapic_clear_all(struct kvm_ioapic *ioapic, int irq_source_id);
 int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
-               struct kvm_lapic_irq *irq, unsigned long *dest_map);
+                            struct kvm_lapic_irq *irq,
+                            struct dest_map *dest_map);
 int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);
 int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);
 void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu,
index 3982b479bb5fe46ae147b01d0cf91933ea8be455..95fcc7b13866c8af1535edd2b8d66728448dc506 100644 (file)
  */
 int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 {
-       return apic_has_pending_timer(vcpu);
+       if (lapic_in_kernel(vcpu))
+               return apic_has_pending_timer(vcpu);
+
+       return 0;
 }
 EXPORT_SYMBOL(kvm_cpu_has_pending_timer);
 
@@ -137,8 +140,8 @@ EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);
 
 void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
 {
-       kvm_inject_apic_timer_irqs(vcpu);
-       /* TODO: PIT, RTC etc. */
+       if (lapic_in_kernel(vcpu))
+               kvm_inject_apic_timer_irqs(vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
 
index ae5c78f2337d3f1359c99116cf5811ffe190b17a..61ebdc13a29af228a1ff2912c9025a5bbb5694cc 100644 (file)
@@ -109,14 +109,6 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
        return ret;
 }
 
-static inline int lapic_in_kernel(struct kvm_vcpu *vcpu)
-{
-       /* Same as irqchip_in_kernel(vcpu->kvm), but with less
-        * pointer chasing and no unnecessary memory barriers.
-        */
-       return vcpu->arch.apic != NULL;
-}
-
 void kvm_pic_reset(struct kvm_kpic_state *s);
 
 void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
index 8fc89efb5250fda6d8b9baaa6f4d35af1e8844ad..54ead79e444b55e80a28d1dd201f1ee2ddf11a18 100644 (file)
@@ -34,6 +34,7 @@
 #include "lapic.h"
 
 #include "hyperv.h"
+#include "x86.h"
 
 static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
                           struct kvm *kvm, int irq_source_id, int level,
@@ -53,10 +54,12 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
 }
 
 int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
-               struct kvm_lapic_irq *irq, unsigned long *dest_map)
+               struct kvm_lapic_irq *irq, struct dest_map *dest_map)
 {
        int i, r = -1;
        struct kvm_vcpu *vcpu, *lowest = NULL;
+       unsigned long dest_vcpu_bitmap[BITS_TO_LONGS(KVM_MAX_VCPUS)];
+       unsigned int dest_vcpus = 0;
 
        if (irq->dest_mode == 0 && irq->dest_id == 0xff &&
                        kvm_lowest_prio_delivery(irq)) {
@@ -67,6 +70,8 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
        if (kvm_irq_delivery_to_apic_fast(kvm, src, irq, &r, dest_map))
                return r;
 
+       memset(dest_vcpu_bitmap, 0, sizeof(dest_vcpu_bitmap));
+
        kvm_for_each_vcpu(i, vcpu, kvm) {
                if (!kvm_apic_present(vcpu))
                        continue;
@@ -80,13 +85,25 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
                                r = 0;
                        r += kvm_apic_set_irq(vcpu, irq, dest_map);
                } else if (kvm_lapic_enabled(vcpu)) {
-                       if (!lowest)
-                               lowest = vcpu;
-                       else if (kvm_apic_compare_prio(vcpu, lowest) < 0)
-                               lowest = vcpu;
+                       if (!kvm_vector_hashing_enabled()) {
+                               if (!lowest)
+                                       lowest = vcpu;
+                               else if (kvm_apic_compare_prio(vcpu, lowest) < 0)
+                                       lowest = vcpu;
+                       } else {
+                               __set_bit(i, dest_vcpu_bitmap);
+                               dest_vcpus++;
+                       }
                }
        }
 
+       if (dest_vcpus != 0) {
+               int idx = kvm_vector_to_index(irq->vector, dest_vcpus,
+                                       dest_vcpu_bitmap, KVM_MAX_VCPUS);
+
+               lowest = kvm_get_vcpu(kvm, idx);
+       }
+
        if (lowest)
                r = kvm_apic_set_irq(lowest, irq, dest_map);
 
index 36591faed13be04d12c13fa520d46ca9df0dfcf8..443d2a57ad3d9620246097a48ed3cd7de9e02f50 100644 (file)
@@ -281,7 +281,7 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu)
        struct kvm_cpuid_entry2 *feat;
        u32 v = APIC_VERSION;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
+       if (!lapic_in_kernel(vcpu))
                return;
 
        feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0);
@@ -475,26 +475,20 @@ static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
 
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
 {
-       int highest_irr;
-
        /* This may race with setting of irr in __apic_accept_irq() and
         * value returned may be wrong, but kvm_vcpu_kick() in __apic_accept_irq
         * will cause vmexit immediately and the value will be recalculated
         * on the next vmentry.
         */
-       if (!kvm_vcpu_has_lapic(vcpu))
-               return 0;
-       highest_irr = apic_find_highest_irr(vcpu->arch.apic);
-
-       return highest_irr;
+       return apic_find_highest_irr(vcpu->arch.apic);
 }
 
 static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                             int vector, int level, int trig_mode,
-                            unsigned long *dest_map);
+                            struct dest_map *dest_map);
 
 int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
-               unsigned long *dest_map)
+                    struct dest_map *dest_map)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
 
@@ -675,8 +669,33 @@ bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
        }
 }
 
+int kvm_vector_to_index(u32 vector, u32 dest_vcpus,
+                      const unsigned long *bitmap, u32 bitmap_size)
+{
+       u32 mod;
+       int i, idx = -1;
+
+       mod = vector % dest_vcpus;
+
+       for (i = 0; i <= mod; i++) {
+               idx = find_next_bit(bitmap, bitmap_size, idx + 1);
+               BUG_ON(idx == bitmap_size);
+       }
+
+       return idx;
+}
+
+static void kvm_apic_disabled_lapic_found(struct kvm *kvm)
+{
+       if (!kvm->arch.disabled_lapic_found) {
+               kvm->arch.disabled_lapic_found = true;
+               printk(KERN_INFO
+                      "Disabled LAPIC found during irq injection\n");
+       }
+}
+
 bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
-               struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map)
+               struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map)
 {
        struct kvm_apic_map *map;
        unsigned long bitmap = 1;
@@ -727,21 +746,42 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
 
                dst = map->logical_map[cid];
 
-               if (kvm_lowest_prio_delivery(irq)) {
+               if (!kvm_lowest_prio_delivery(irq))
+                       goto set_irq;
+
+               if (!kvm_vector_hashing_enabled()) {
                        int l = -1;
                        for_each_set_bit(i, &bitmap, 16) {
                                if (!dst[i])
                                        continue;
                                if (l < 0)
                                        l = i;
-                               else if (kvm_apic_compare_prio(dst[i]->vcpu, dst[l]->vcpu) < 0)
+                               else if (kvm_apic_compare_prio(dst[i]->vcpu,
+                                                       dst[l]->vcpu) < 0)
                                        l = i;
                        }
-
                        bitmap = (l >= 0) ? 1 << l : 0;
+               } else {
+                       int idx;
+                       unsigned int dest_vcpus;
+
+                       dest_vcpus = hweight16(bitmap);
+                       if (dest_vcpus == 0)
+                               goto out;
+
+                       idx = kvm_vector_to_index(irq->vector,
+                               dest_vcpus, &bitmap, 16);
+
+                       if (!dst[idx]) {
+                               kvm_apic_disabled_lapic_found(kvm);
+                               goto out;
+                       }
+
+                       bitmap = (idx >= 0) ? 1 << idx : 0;
                }
        }
 
+set_irq:
        for_each_set_bit(i, &bitmap, 16) {
                if (!dst[i])
                        continue;
@@ -754,6 +794,20 @@ out:
        return ret;
 }
 
+/*
+ * This routine tries to handler interrupts in posted mode, here is how
+ * it deals with different cases:
+ * - For single-destination interrupts, handle it in posted mode
+ * - Else if vector hashing is enabled and it is a lowest-priority
+ *   interrupt, handle it in posted mode and use the following mechanism
+ *   to find the destinaiton vCPU.
+ *     1. For lowest-priority interrupts, store all the possible
+ *        destination vCPUs in an array.
+ *     2. Use "guest vector % max number of destination vCPUs" to find
+ *        the right destination vCPU in the array for the lowest-priority
+ *        interrupt.
+ * - Otherwise, use remapped mode to inject the interrupt.
+ */
 bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
                        struct kvm_vcpu **dest_vcpu)
 {
@@ -795,16 +849,37 @@ bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
                if (cid >= ARRAY_SIZE(map->logical_map))
                        goto out;
 
-               for_each_set_bit(i, &bitmap, 16) {
-                       dst = map->logical_map[cid][i];
-                       if (++r == 2)
+               if (kvm_vector_hashing_enabled() &&
+                               kvm_lowest_prio_delivery(irq)) {
+                       int idx;
+                       unsigned int dest_vcpus;
+
+                       dest_vcpus = hweight16(bitmap);
+                       if (dest_vcpus == 0)
                                goto out;
-               }
 
-               if (dst && kvm_apic_present(dst->vcpu))
+                       idx = kvm_vector_to_index(irq->vector, dest_vcpus,
+                                                 &bitmap, 16);
+
+                       dst = map->logical_map[cid][idx];
+                       if (!dst) {
+                               kvm_apic_disabled_lapic_found(kvm);
+                               goto out;
+                       }
+
                        *dest_vcpu = dst->vcpu;
-               else
-                       goto out;
+               } else {
+                       for_each_set_bit(i, &bitmap, 16) {
+                               dst = map->logical_map[cid][i];
+                               if (++r == 2)
+                                       goto out;
+                       }
+
+                       if (dst && kvm_apic_present(dst->vcpu))
+                               *dest_vcpu = dst->vcpu;
+                       else
+                               goto out;
+               }
        }
 
        ret = true;
@@ -819,7 +894,7 @@ out:
  */
 static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
                             int vector, int level, int trig_mode,
-                            unsigned long *dest_map)
+                            struct dest_map *dest_map)
 {
        int result = 0;
        struct kvm_vcpu *vcpu = apic->vcpu;
@@ -839,8 +914,10 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 
                result = 1;
 
-               if (dest_map)
-                       __set_bit(vcpu->vcpu_id, dest_map);
+               if (dest_map) {
+                       __set_bit(vcpu->vcpu_id, dest_map->map);
+                       dest_map->vectors[vcpu->vcpu_id] = vector;
+               }
 
                if (apic_test_vector(vector, apic->regs + APIC_TMR) != !!trig_mode) {
                        if (trig_mode)
@@ -1195,7 +1272,7 @@ static void apic_update_lvtt(struct kvm_lapic *apic)
 static void apic_timer_expired(struct kvm_lapic *apic)
 {
        struct kvm_vcpu *vcpu = apic->vcpu;
-       wait_queue_head_t *q = &vcpu->wq;
+       struct swait_queue_head *q = &vcpu->wq;
        struct kvm_timer *ktimer = &apic->lapic_timer;
 
        if (atomic_read(&apic->lapic_timer.pending))
@@ -1204,8 +1281,8 @@ static void apic_timer_expired(struct kvm_lapic *apic)
        atomic_inc(&apic->lapic_timer.pending);
        kvm_set_pending_timer(vcpu);
 
-       if (waitqueue_active(q))
-               wake_up_interruptible(q);
+       if (swait_active(q))
+               swake_up(q);
 
        if (apic_lvtt_tscdeadline(apic))
                ktimer->expired_tscdeadline = ktimer->tscdeadline;
@@ -1239,7 +1316,7 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu)
        struct kvm_lapic *apic = vcpu->arch.apic;
        u64 guest_tsc, tsc_deadline;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
+       if (!lapic_in_kernel(vcpu))
                return;
 
        if (apic->lapic_timer.expired_tscdeadline == 0)
@@ -1515,8 +1592,7 @@ static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
 
 void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu)
 {
-       if (kvm_vcpu_has_lapic(vcpu))
-               apic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
+       apic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
 
@@ -1566,7 +1642,7 @@ u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
 
-       if (!kvm_vcpu_has_lapic(vcpu) || apic_lvtt_oneshot(apic) ||
+       if (!lapic_in_kernel(vcpu) || apic_lvtt_oneshot(apic) ||
                        apic_lvtt_period(apic))
                return 0;
 
@@ -1577,7 +1653,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
 
-       if (!kvm_vcpu_has_lapic(vcpu) || apic_lvtt_oneshot(apic) ||
+       if (!lapic_in_kernel(vcpu) || apic_lvtt_oneshot(apic) ||
                        apic_lvtt_period(apic))
                return;
 
@@ -1590,9 +1666,6 @@ void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
-               return;
-
        apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
                     | (kvm_apic_get_reg(apic, APIC_TASKPRI) & 4));
 }
@@ -1601,9 +1674,6 @@ u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
 {
        u64 tpr;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
-               return 0;
-
        tpr = (u64) kvm_apic_get_reg(vcpu->arch.apic, APIC_TASKPRI);
 
        return (tpr & 0xf0) >> 4;
@@ -1728,8 +1798,7 @@ int apic_has_pending_timer(struct kvm_vcpu *vcpu)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
 
-       if (kvm_vcpu_has_lapic(vcpu) && apic_enabled(apic) &&
-                       apic_lvt_enabled(apic, APIC_LVTT))
+       if (apic_enabled(apic) && apic_lvt_enabled(apic, APIC_LVTT))
                return atomic_read(&apic->lapic_timer.pending);
 
        return 0;
@@ -1826,7 +1895,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
        struct kvm_lapic *apic = vcpu->arch.apic;
        int highest_irr;
 
-       if (!kvm_vcpu_has_lapic(vcpu) || !apic_enabled(apic))
+       if (!apic_enabled(apic))
                return -1;
 
        apic_update_ppr(apic);
@@ -1854,9 +1923,6 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
-               return;
-
        if (atomic_read(&apic->lapic_timer.pending) > 0) {
                kvm_apic_local_deliver(apic, APIC_LVTT);
                if (apic_lvtt_tscdeadline(apic))
@@ -1932,7 +1998,7 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
 {
        struct hrtimer *timer;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
+       if (!lapic_in_kernel(vcpu))
                return;
 
        timer = &vcpu->arch.apic->lapic_timer.timer;
@@ -2105,7 +2171,7 @@ int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
+       if (!lapic_in_kernel(vcpu))
                return 1;
 
        /* if this is ICR write vector before command */
@@ -2119,7 +2185,7 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data)
        struct kvm_lapic *apic = vcpu->arch.apic;
        u32 low, high = 0;
 
-       if (!kvm_vcpu_has_lapic(vcpu))
+       if (!lapic_in_kernel(vcpu))
                return 1;
 
        if (apic_reg_read(apic, reg, 4, &low))
@@ -2151,7 +2217,7 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
        u8 sipi_vector;
        unsigned long pe;
 
-       if (!kvm_vcpu_has_lapic(vcpu) || !apic->pending_events)
+       if (!lapic_in_kernel(vcpu) || !apic->pending_events)
                return;
 
        /*
index 41bdb35b4b67ab10a2ebcd943d2d75d48431ff46..f71183e502ee9ae917b8a8d1d4860a71df02d8f7 100644 (file)
@@ -42,6 +42,9 @@ struct kvm_lapic {
        unsigned long pending_events;
        unsigned int sipi_vector;
 };
+
+struct dest_map;
+
 int kvm_create_lapic(struct kvm_vcpu *vcpu);
 void kvm_free_lapic(struct kvm_vcpu *vcpu);
 
@@ -60,11 +63,11 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu);
 void __kvm_apic_update_irr(u32 *pir, void *regs);
 void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir);
 int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
-               unsigned long *dest_map);
+                    struct dest_map *dest_map);
 int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type);
 
 bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
-               struct kvm_lapic_irq *irq, int *r, unsigned long *dest_map);
+               struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);
 
 u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
 int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
@@ -103,7 +106,7 @@ static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off)
 
 extern struct static_key kvm_no_apic_vcpu;
 
-static inline bool kvm_vcpu_has_lapic(struct kvm_vcpu *vcpu)
+static inline bool lapic_in_kernel(struct kvm_vcpu *vcpu)
 {
        if (static_key_false(&kvm_no_apic_vcpu))
                return vcpu->arch.apic;
@@ -130,7 +133,7 @@ static inline bool kvm_apic_sw_enabled(struct kvm_lapic *apic)
 
 static inline bool kvm_apic_present(struct kvm_vcpu *vcpu)
 {
-       return kvm_vcpu_has_lapic(vcpu) && kvm_apic_hw_enabled(vcpu->arch.apic);
+       return lapic_in_kernel(vcpu) && kvm_apic_hw_enabled(vcpu->arch.apic);
 }
 
 static inline int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
@@ -150,7 +153,7 @@ static inline bool kvm_vcpu_apicv_active(struct kvm_vcpu *vcpu)
 
 static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu)
 {
-       return kvm_vcpu_has_lapic(vcpu) && vcpu->arch.apic->pending_events;
+       return lapic_in_kernel(vcpu) && vcpu->arch.apic->pending_events;
 }
 
 static inline bool kvm_lowest_prio_delivery(struct kvm_lapic_irq *irq)
@@ -161,7 +164,7 @@ static inline bool kvm_lowest_prio_delivery(struct kvm_lapic_irq *irq)
 
 static inline int kvm_lapic_latched_init(struct kvm_vcpu *vcpu)
 {
-       return kvm_vcpu_has_lapic(vcpu) && test_bit(KVM_APIC_INIT, &vcpu->arch.apic->pending_events);
+       return lapic_in_kernel(vcpu) && test_bit(KVM_APIC_INIT, &vcpu->arch.apic->pending_events);
 }
 
 static inline int kvm_apic_id(struct kvm_lapic *apic)
@@ -175,4 +178,6 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu);
 
 bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
                        struct kvm_vcpu **dest_vcpu);
+int kvm_vector_to_index(u32 vector, u32 dest_vcpus,
+                       const unsigned long *bitmap, u32 bitmap_size);
 #endif
index 95a955de5964bcc3f4aa6791a004e29b28504c13..c512f095cdac82b9e2ba258ae052a9a4199dc13c 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/cmpxchg.h>
 #include <asm/io.h>
 #include <asm/vmx.h>
+#include <asm/kvm_page_track.h>
 
 /*
  * When setting this variable to true it enables Two-Dimensional-Paging
@@ -776,62 +777,85 @@ static struct kvm_lpage_info *lpage_info_slot(gfn_t gfn,
        return &slot->arch.lpage_info[level - 2][idx];
 }
 
+static void update_gfn_disallow_lpage_count(struct kvm_memory_slot *slot,
+                                           gfn_t gfn, int count)
+{
+       struct kvm_lpage_info *linfo;
+       int i;
+
+       for (i = PT_DIRECTORY_LEVEL; i <= PT_MAX_HUGEPAGE_LEVEL; ++i) {
+               linfo = lpage_info_slot(gfn, slot, i);
+               linfo->disallow_lpage += count;
+               WARN_ON(linfo->disallow_lpage < 0);
+       }
+}
+
+void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn)
+{
+       update_gfn_disallow_lpage_count(slot, gfn, 1);
+}
+
+void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn)
+{
+       update_gfn_disallow_lpage_count(slot, gfn, -1);
+}
+
 static void account_shadowed(struct kvm *kvm, struct kvm_mmu_page *sp)
 {
        struct kvm_memslots *slots;
        struct kvm_memory_slot *slot;
-       struct kvm_lpage_info *linfo;
        gfn_t gfn;
-       int i;
 
+       kvm->arch.indirect_shadow_pages++;
        gfn = sp->gfn;
        slots = kvm_memslots_for_spte_role(kvm, sp->role);
        slot = __gfn_to_memslot(slots, gfn);
-       for (i = PT_DIRECTORY_LEVEL; i <= PT_MAX_HUGEPAGE_LEVEL; ++i) {
-               linfo = lpage_info_slot(gfn, slot, i);
-               linfo->write_count += 1;
-       }
-       kvm->arch.indirect_shadow_pages++;
+
+       /* the non-leaf shadow pages are keeping readonly. */
+       if (sp->role.level > PT_PAGE_TABLE_LEVEL)
+               return kvm_slot_page_track_add_page(kvm, slot, gfn,
+                                                   KVM_PAGE_TRACK_WRITE);
+
+       kvm_mmu_gfn_disallow_lpage(slot, gfn);
 }
 
 static void unaccount_shadowed(struct kvm *kvm, struct kvm_mmu_page *sp)
 {
        struct kvm_memslots *slots;
        struct kvm_memory_slot *slot;
-       struct kvm_lpage_info *linfo;
        gfn_t gfn;
-       int i;
 
+       kvm->arch.indirect_shadow_pages--;
        gfn = sp->gfn;
        slots = kvm_memslots_for_spte_role(kvm, sp->role);
        slot = __gfn_to_memslot(slots, gfn);
-       for (i = PT_DIRECTORY_LEVEL; i <= PT_MAX_HUGEPAGE_LEVEL; ++i) {
-               linfo = lpage_info_slot(gfn, slot, i);
-               linfo->write_count -= 1;
-               WARN_ON(linfo->write_count < 0);
-       }
-       kvm->arch.indirect_shadow_pages--;
+       if (sp->role.level > PT_PAGE_TABLE_LEVEL)
+               return kvm_slot_page_track_remove_page(kvm, slot, gfn,
+                                                      KVM_PAGE_TRACK_WRITE);
+
+       kvm_mmu_gfn_allow_lpage(slot, gfn);
 }
 
-static int __has_wrprotected_page(gfn_t gfn, int level,
-                                 struct kvm_memory_slot *slot)
+static bool __mmu_gfn_lpage_is_disallowed(gfn_t gfn, int level,
+                                         struct kvm_memory_slot *slot)
 {
        struct kvm_lpage_info *linfo;
 
        if (slot) {
                linfo = lpage_info_slot(gfn, slot, level);
-               return linfo->write_count;
+               return !!linfo->disallow_lpage;
        }
 
-       return 1;
+       return true;
 }
 
-static int has_wrprotected_page(struct kvm_vcpu *vcpu, gfn_t gfn, int level)
+static bool mmu_gfn_lpage_is_disallowed(struct kvm_vcpu *vcpu, gfn_t gfn,
+                                       int level)
 {
        struct kvm_memory_slot *slot;
 
        slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
-       return __has_wrprotected_page(gfn, level, slot);
+       return __mmu_gfn_lpage_is_disallowed(gfn, level, slot);
 }
 
 static int host_mapping_level(struct kvm *kvm, gfn_t gfn)
@@ -897,7 +921,7 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn,
        max_level = min(kvm_x86_ops->get_lpage_level(), host_level);
 
        for (level = PT_DIRECTORY_LEVEL; level <= max_level; ++level)
-               if (__has_wrprotected_page(large_gfn, level, slot))
+               if (__mmu_gfn_lpage_is_disallowed(large_gfn, level, slot))
                        break;
 
        return level - 1;
@@ -1323,23 +1347,29 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
                kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask);
 }
 
-static bool rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
+bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
+                                   struct kvm_memory_slot *slot, u64 gfn)
 {
-       struct kvm_memory_slot *slot;
        struct kvm_rmap_head *rmap_head;
        int i;
        bool write_protected = false;
 
-       slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
-
        for (i = PT_PAGE_TABLE_LEVEL; i <= PT_MAX_HUGEPAGE_LEVEL; ++i) {
                rmap_head = __gfn_to_rmap(gfn, i, slot);
-               write_protected |= __rmap_write_protect(vcpu->kvm, rmap_head, true);
+               write_protected |= __rmap_write_protect(kvm, rmap_head, true);
        }
 
        return write_protected;
 }
 
+static bool rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
+{
+       struct kvm_memory_slot *slot;
+
+       slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
+       return kvm_mmu_slot_gfn_write_protect(vcpu->kvm, slot, gfn);
+}
+
 static bool kvm_zap_rmapp(struct kvm *kvm, struct kvm_rmap_head *rmap_head)
 {
        u64 *sptep;
@@ -1754,7 +1784,7 @@ static void mark_unsync(u64 *spte)
 static int nonpaging_sync_page(struct kvm_vcpu *vcpu,
                               struct kvm_mmu_page *sp)
 {
-       return 1;
+       return 0;
 }
 
 static void nonpaging_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
@@ -1840,13 +1870,16 @@ static int __mmu_unsync_walk(struct kvm_mmu_page *sp,
        return nr_unsync_leaf;
 }
 
+#define INVALID_INDEX (-1)
+
 static int mmu_unsync_walk(struct kvm_mmu_page *sp,
                           struct kvm_mmu_pages *pvec)
 {
+       pvec->nr = 0;
        if (!sp->unsync_children)
                return 0;
 
-       mmu_pages_add(pvec, sp, 0);
+       mmu_pages_add(pvec, sp, INVALID_INDEX);
        return __mmu_unsync_walk(sp, pvec);
 }
 
@@ -1883,37 +1916,35 @@ static void kvm_mmu_commit_zap_page(struct kvm *kvm,
                if ((_sp)->role.direct || (_sp)->role.invalid) {} else
 
 /* @sp->gfn should be write-protected at the call site */
-static int __kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
-                          struct list_head *invalid_list, bool clear_unsync)
+static bool __kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+                           struct list_head *invalid_list)
 {
        if (sp->role.cr4_pae != !!is_pae(vcpu)) {
                kvm_mmu_prepare_zap_page(vcpu->kvm, sp, invalid_list);
-               return 1;
+               return false;
        }
 
-       if (clear_unsync)
-               kvm_unlink_unsync_page(vcpu->kvm, sp);
-
-       if (vcpu->arch.mmu.sync_page(vcpu, sp)) {
+       if (vcpu->arch.mmu.sync_page(vcpu, sp) == 0) {
                kvm_mmu_prepare_zap_page(vcpu->kvm, sp, invalid_list);
-               return 1;
+               return false;
        }
 
-       kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
-       return 0;
+       return true;
 }
 
-static int kvm_sync_page_transient(struct kvm_vcpu *vcpu,
-                                  struct kvm_mmu_page *sp)
+static void kvm_mmu_flush_or_zap(struct kvm_vcpu *vcpu,
+                                struct list_head *invalid_list,
+                                bool remote_flush, bool local_flush)
 {
-       LIST_HEAD(invalid_list);
-       int ret;
-
-       ret = __kvm_sync_page(vcpu, sp, &invalid_list, false);
-       if (ret)
-               kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
+       if (!list_empty(invalid_list)) {
+               kvm_mmu_commit_zap_page(vcpu->kvm, invalid_list);
+               return;
+       }
 
-       return ret;
+       if (remote_flush)
+               kvm_flush_remote_tlbs(vcpu->kvm);
+       else if (local_flush)
+               kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
 }
 
 #ifdef CONFIG_KVM_MMU_AUDIT
@@ -1923,46 +1954,38 @@ static void kvm_mmu_audit(struct kvm_vcpu *vcpu, int point) { }
 static void mmu_audit_disable(void) { }
 #endif
 
-static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+static bool kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
                         struct list_head *invalid_list)
 {
-       return __kvm_sync_page(vcpu, sp, invalid_list, true);
+       kvm_unlink_unsync_page(vcpu->kvm, sp);
+       return __kvm_sync_page(vcpu, sp, invalid_list);
 }
 
 /* @gfn should be write-protected at the call site */
-static void kvm_sync_pages(struct kvm_vcpu *vcpu,  gfn_t gfn)
+static bool kvm_sync_pages(struct kvm_vcpu *vcpu, gfn_t gfn,
+                          struct list_head *invalid_list)
 {
        struct kvm_mmu_page *s;
-       LIST_HEAD(invalid_list);
-       bool flush = false;
+       bool ret = false;
 
        for_each_gfn_indirect_valid_sp(vcpu->kvm, s, gfn) {
                if (!s->unsync)
                        continue;
 
                WARN_ON(s->role.level != PT_PAGE_TABLE_LEVEL);
-               kvm_unlink_unsync_page(vcpu->kvm, s);
-               if ((s->role.cr4_pae != !!is_pae(vcpu)) ||
-                       (vcpu->arch.mmu.sync_page(vcpu, s))) {
-                       kvm_mmu_prepare_zap_page(vcpu->kvm, s, &invalid_list);
-                       continue;
-               }
-               flush = true;
+               ret |= kvm_sync_page(vcpu, s, invalid_list);
        }
 
-       kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
-       if (flush)
-               kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+       return ret;
 }
 
 struct mmu_page_path {
-       struct kvm_mmu_page *parent[PT64_ROOT_LEVEL-1];
-       unsigned int idx[PT64_ROOT_LEVEL-1];
+       struct kvm_mmu_page *parent[PT64_ROOT_LEVEL];
+       unsigned int idx[PT64_ROOT_LEVEL];
 };
 
 #define for_each_sp(pvec, sp, parents, i)                      \
-               for (i = mmu_pages_next(&pvec, &parents, -1),   \
-                       sp = pvec.page[i].sp;                   \
+               for (i = mmu_pages_first(&pvec, &parents);      \
                        i < pvec.nr && ({ sp = pvec.page[i].sp; 1;});   \
                        i = mmu_pages_next(&pvec, &parents, i))
 
@@ -1974,19 +1997,43 @@ static int mmu_pages_next(struct kvm_mmu_pages *pvec,
 
        for (n = i+1; n < pvec->nr; n++) {
                struct kvm_mmu_page *sp = pvec->page[n].sp;
+               unsigned idx = pvec->page[n].idx;
+               int level = sp->role.level;
 
-               if (sp->role.level == PT_PAGE_TABLE_LEVEL) {
-                       parents->idx[0] = pvec->page[n].idx;
-                       return n;
-               }
+               parents->idx[level-1] = idx;
+               if (level == PT_PAGE_TABLE_LEVEL)
+                       break;
 
-               parents->parent[sp->role.level-2] = sp;
-               parents->idx[sp->role.level-1] = pvec->page[n].idx;
+               parents->parent[level-2] = sp;
        }
 
        return n;
 }
 
+static int mmu_pages_first(struct kvm_mmu_pages *pvec,
+                          struct mmu_page_path *parents)
+{
+       struct kvm_mmu_page *sp;
+       int level;
+
+       if (pvec->nr == 0)
+               return 0;
+
+       WARN_ON(pvec->page[0].idx != INVALID_INDEX);
+
+       sp = pvec->page[0].sp;
+       level = sp->role.level;
+       WARN_ON(level == PT_PAGE_TABLE_LEVEL);
+
+       parents->parent[level-2] = sp;
+
+       /* Also set up a sentinel.  Further entries in pvec are all
+        * children of sp, so this element is never overwritten.
+        */
+       parents->parent[level-1] = NULL;
+       return mmu_pages_next(pvec, parents, 0);
+}
+
 static void mmu_pages_clear_parents(struct mmu_page_path *parents)
 {
        struct kvm_mmu_page *sp;
@@ -1994,22 +2041,14 @@ static void mmu_pages_clear_parents(struct mmu_page_path *parents)
 
        do {
                unsigned int idx = parents->idx[level];
-
                sp = parents->parent[level];
                if (!sp)
                        return;
 
+               WARN_ON(idx == INVALID_INDEX);
                clear_unsync_child_bit(sp, idx);
                level++;
-       } while (level < PT64_ROOT_LEVEL-1 && !sp->unsync_children);
-}
-
-static void kvm_mmu_pages_init(struct kvm_mmu_page *parent,
-                              struct mmu_page_path *parents,
-                              struct kvm_mmu_pages *pvec)
-{
-       parents->parent[parent->role.level-1] = NULL;
-       pvec->nr = 0;
+       } while (!sp->unsync_children);
 }
 
 static void mmu_sync_children(struct kvm_vcpu *vcpu,
@@ -2020,30 +2059,36 @@ static void mmu_sync_children(struct kvm_vcpu *vcpu,
        struct mmu_page_path parents;
        struct kvm_mmu_pages pages;
        LIST_HEAD(invalid_list);
+       bool flush = false;
 
-       kvm_mmu_pages_init(parent, &parents, &pages);
        while (mmu_unsync_walk(parent, &pages)) {
                bool protected = false;
 
                for_each_sp(pages, sp, parents, i)
                        protected |= rmap_write_protect(vcpu, sp->gfn);
 
-               if (protected)
+               if (protected) {
                        kvm_flush_remote_tlbs(vcpu->kvm);
+                       flush = false;
+               }
 
                for_each_sp(pages, sp, parents, i) {
-                       kvm_sync_page(vcpu, sp, &invalid_list);
+                       flush |= kvm_sync_page(vcpu, sp, &invalid_list);
                        mmu_pages_clear_parents(&parents);
                }
-               kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
-               cond_resched_lock(&vcpu->kvm->mmu_lock);
-               kvm_mmu_pages_init(parent, &parents, &pages);
+               if (need_resched() || spin_needbreak(&vcpu->kvm->mmu_lock)) {
+                       kvm_mmu_flush_or_zap(vcpu, &invalid_list, false, flush);
+                       cond_resched_lock(&vcpu->kvm->mmu_lock);
+                       flush = false;
+               }
        }
+
+       kvm_mmu_flush_or_zap(vcpu, &invalid_list, false, flush);
 }
 
 static void __clear_sp_write_flooding_count(struct kvm_mmu_page *sp)
 {
-       sp->write_flooding_count = 0;
+       atomic_set(&sp->write_flooding_count,  0);
 }
 
 static void clear_sp_write_flooding_count(u64 *spte)
@@ -2069,6 +2114,8 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
        unsigned quadrant;
        struct kvm_mmu_page *sp;
        bool need_sync = false;
+       bool flush = false;
+       LIST_HEAD(invalid_list);
 
        role = vcpu->arch.mmu.base_role;
        role.level = level;
@@ -2092,8 +2139,16 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
                if (sp->role.word != role.word)
                        continue;
 
-               if (sp->unsync && kvm_sync_page_transient(vcpu, sp))
-                       break;
+               if (sp->unsync) {
+                       /* The page is good, but __kvm_sync_page might still end
+                        * up zapping it.  If so, break in order to rebuild it.
+                        */
+                       if (!__kvm_sync_page(vcpu, sp, &invalid_list))
+                               break;
+
+                       WARN_ON(!list_empty(&invalid_list));
+                       kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+               }
 
                if (sp->unsync_children)
                        kvm_make_request(KVM_REQ_MMU_SYNC, vcpu);
@@ -2112,16 +2167,24 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
        hlist_add_head(&sp->hash_link,
                &vcpu->kvm->arch.mmu_page_hash[kvm_page_table_hashfn(gfn)]);
        if (!direct) {
-               if (rmap_write_protect(vcpu, gfn))
+               /*
+                * we should do write protection before syncing pages
+                * otherwise the content of the synced shadow page may
+                * be inconsistent with guest page table.
+                */
+               account_shadowed(vcpu->kvm, sp);
+               if (level == PT_PAGE_TABLE_LEVEL &&
+                     rmap_write_protect(vcpu, gfn))
                        kvm_flush_remote_tlbs(vcpu->kvm);
-               if (level > PT_PAGE_TABLE_LEVEL && need_sync)
-                       kvm_sync_pages(vcpu, gfn);
 
-               account_shadowed(vcpu->kvm, sp);
+               if (level > PT_PAGE_TABLE_LEVEL && need_sync)
+                       flush |= kvm_sync_pages(vcpu, gfn, &invalid_list);
        }
        sp->mmu_valid_gen = vcpu->kvm->arch.mmu_valid_gen;
        clear_page(sp->spt);
        trace_kvm_mmu_get_page(sp, true);
+
+       kvm_mmu_flush_or_zap(vcpu, &invalid_list, false, flush);
        return sp;
 }
 
@@ -2269,7 +2332,6 @@ static int mmu_zap_unsync_children(struct kvm *kvm,
        if (parent->role.level == PT_PAGE_TABLE_LEVEL)
                return 0;
 
-       kvm_mmu_pages_init(parent, &parents, &pages);
        while (mmu_unsync_walk(parent, &pages)) {
                struct kvm_mmu_page *sp;
 
@@ -2278,7 +2340,6 @@ static int mmu_zap_unsync_children(struct kvm *kvm,
                        mmu_pages_clear_parents(&parents);
                        zapped++;
                }
-               kvm_mmu_pages_init(parent, &parents, &pages);
        }
 
        return zapped;
@@ -2354,8 +2415,8 @@ static bool prepare_zap_oldest_mmu_page(struct kvm *kvm,
        if (list_empty(&kvm->arch.active_mmu_pages))
                return false;
 
-       sp = list_entry(kvm->arch.active_mmu_pages.prev,
-                       struct kvm_mmu_page, link);
+       sp = list_last_entry(&kvm->arch.active_mmu_pages,
+                            struct kvm_mmu_page, link);
        kvm_mmu_prepare_zap_page(kvm, sp, invalid_list);
 
        return true;
@@ -2408,7 +2469,7 @@ int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn)
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_unprotect_page);
 
-static void __kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
+static void kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 {
        trace_kvm_mmu_unsync_page(sp);
        ++vcpu->kvm->stat.mmu_unsync;
@@ -2417,37 +2478,26 @@ static void __kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
        kvm_mmu_mark_parents_unsync(sp);
 }
 
-static void kvm_unsync_pages(struct kvm_vcpu *vcpu,  gfn_t gfn)
+static bool mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn,
+                                  bool can_unsync)
 {
-       struct kvm_mmu_page *s;
-
-       for_each_gfn_indirect_valid_sp(vcpu->kvm, s, gfn) {
-               if (s->unsync)
-                       continue;
-               WARN_ON(s->role.level != PT_PAGE_TABLE_LEVEL);
-               __kvm_unsync_page(vcpu, s);
-       }
-}
+       struct kvm_mmu_page *sp;
 
-static int mmu_need_write_protect(struct kvm_vcpu *vcpu, gfn_t gfn,
-                                 bool can_unsync)
-{
-       struct kvm_mmu_page *s;
-       bool need_unsync = false;
+       if (kvm_page_track_is_active(vcpu, gfn, KVM_PAGE_TRACK_WRITE))
+               return true;
 
-       for_each_gfn_indirect_valid_sp(vcpu->kvm, s, gfn) {
+       for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn) {
                if (!can_unsync)
-                       return 1;
+                       return true;
 
-               if (s->role.level != PT_PAGE_TABLE_LEVEL)
-                       return 1;
+               if (sp->unsync)
+                       continue;
 
-               if (!s->unsync)
-                       need_unsync = true;
+               WARN_ON(sp->role.level != PT_PAGE_TABLE_LEVEL);
+               kvm_unsync_page(vcpu, sp);
        }
-       if (need_unsync)
-               kvm_unsync_pages(vcpu, gfn);
-       return 0;
+
+       return false;
 }
 
 static bool kvm_is_mmio_pfn(kvm_pfn_t pfn)
@@ -2503,7 +2553,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                 * be fixed if guest refault.
                 */
                if (level > PT_PAGE_TABLE_LEVEL &&
-                   has_wrprotected_page(vcpu, gfn, level))
+                   mmu_gfn_lpage_is_disallowed(vcpu, gfn, level))
                        goto done;
 
                spte |= PT_WRITABLE_MASK | SPTE_MMU_WRITEABLE;
@@ -2768,7 +2818,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
        if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
            level == PT_PAGE_TABLE_LEVEL &&
            PageTransCompound(pfn_to_page(pfn)) &&
-           !has_wrprotected_page(vcpu, gfn, PT_DIRECTORY_LEVEL)) {
+           !mmu_gfn_lpage_is_disallowed(vcpu, gfn, PT_DIRECTORY_LEVEL)) {
                unsigned long mask;
                /*
                 * mmu_notifier_retry was successful and we hold the
@@ -2796,20 +2846,16 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
 static bool handle_abnormal_pfn(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
                                kvm_pfn_t pfn, unsigned access, int *ret_val)
 {
-       bool ret = true;
-
        /* The pfn is invalid, report the error! */
        if (unlikely(is_error_pfn(pfn))) {
                *ret_val = kvm_handle_bad_page(vcpu, gfn, pfn);
-               goto exit;
+               return true;
        }
 
        if (unlikely(is_noslot_pfn(pfn)))
                vcpu_cache_mmio_info(vcpu, gva, gfn, access);
 
-       ret = false;
-exit:
-       return ret;
+       return false;
 }
 
 static bool page_fault_can_be_fast(u32 error_code)
@@ -3273,7 +3319,7 @@ static bool is_shadow_zero_bits_set(struct kvm_mmu *mmu, u64 spte, int level)
        return __is_rsvd_bits_set(&mmu->shadow_zero_check, spte, level);
 }
 
-static bool quickly_check_mmio_pf(struct kvm_vcpu *vcpu, u64 addr, bool direct)
+static bool mmio_info_in_cache(struct kvm_vcpu *vcpu, u64 addr, bool direct)
 {
        if (direct)
                return vcpu_match_mmio_gpa(vcpu, addr);
@@ -3332,7 +3378,7 @@ int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct)
        u64 spte;
        bool reserved;
 
-       if (quickly_check_mmio_pf(vcpu, addr, direct))
+       if (mmio_info_in_cache(vcpu, addr, direct))
                return RET_MMIO_PF_EMULATE;
 
        reserved = walk_shadow_page_get_mmio_spte(vcpu, addr, &spte);
@@ -3362,20 +3408,53 @@ int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct)
 }
 EXPORT_SYMBOL_GPL(handle_mmio_page_fault);
 
+static bool page_fault_handle_page_track(struct kvm_vcpu *vcpu,
+                                        u32 error_code, gfn_t gfn)
+{
+       if (unlikely(error_code & PFERR_RSVD_MASK))
+               return false;
+
+       if (!(error_code & PFERR_PRESENT_MASK) ||
+             !(error_code & PFERR_WRITE_MASK))
+               return false;
+
+       /*
+        * guest is writing the page which is write tracked which can
+        * not be fixed by page fault handler.
+        */
+       if (kvm_page_track_is_active(vcpu, gfn, KVM_PAGE_TRACK_WRITE))
+               return true;
+
+       return false;
+}
+
+static void shadow_page_table_clear_flood(struct kvm_vcpu *vcpu, gva_t addr)
+{
+       struct kvm_shadow_walk_iterator iterator;
+       u64 spte;
+
+       if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+               return;
+
+       walk_shadow_page_lockless_begin(vcpu);
+       for_each_shadow_entry_lockless(vcpu, addr, iterator, spte) {
+               clear_sp_write_flooding_count(iterator.sptep);
+               if (!is_shadow_present_pte(spte))
+                       break;
+       }
+       walk_shadow_page_lockless_end(vcpu);
+}
+
 static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
                                u32 error_code, bool prefault)
 {
-       gfn_t gfn;
+       gfn_t gfn = gva >> PAGE_SHIFT;
        int r;
 
        pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code);
 
-       if (unlikely(error_code & PFERR_RSVD_MASK)) {
-               r = handle_mmio_page_fault(vcpu, gva, true);
-
-               if (likely(r != RET_MMIO_PF_INVALID))
-                       return r;
-       }
+       if (page_fault_handle_page_track(vcpu, error_code, gfn))
+               return 1;
 
        r = mmu_topup_memory_caches(vcpu);
        if (r)
@@ -3383,7 +3462,6 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
 
        MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu.root_hpa));
 
-       gfn = gva >> PAGE_SHIFT;
 
        return nonpaging_map(vcpu, gva & PAGE_MASK,
                             error_code, gfn, prefault);
@@ -3460,12 +3538,8 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
 
        MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu.root_hpa));
 
-       if (unlikely(error_code & PFERR_RSVD_MASK)) {
-               r = handle_mmio_page_fault(vcpu, gpa, true);
-
-               if (likely(r != RET_MMIO_PF_INVALID))
-                       return r;
-       }
+       if (page_fault_handle_page_track(vcpu, error_code, gfn))
+               return 1;
 
        r = mmu_topup_memory_caches(vcpu);
        if (r)
@@ -3558,13 +3632,24 @@ static bool sync_mmio_spte(struct kvm_vcpu *vcpu, u64 *sptep, gfn_t gfn,
        return false;
 }
 
-static inline bool is_last_gpte(struct kvm_mmu *mmu, unsigned level, unsigned gpte)
+static inline bool is_last_gpte(struct kvm_mmu *mmu,
+                               unsigned level, unsigned gpte)
 {
-       unsigned index;
+       /*
+        * PT_PAGE_TABLE_LEVEL always terminates.  The RHS has bit 7 set
+        * iff level <= PT_PAGE_TABLE_LEVEL, which for our purpose means
+        * level == PT_PAGE_TABLE_LEVEL; set PT_PAGE_SIZE_MASK in gpte then.
+        */
+       gpte |= level - PT_PAGE_TABLE_LEVEL - 1;
 
-       index = level - 1;
-       index |= (gpte & PT_PAGE_SIZE_MASK) >> (PT_PAGE_SIZE_SHIFT - 2);
-       return mmu->last_pte_bitmap & (1 << index);
+       /*
+        * The RHS has bit 7 set iff level < mmu->last_nonleaf_level.
+        * If it is clear, there are no large pages at this level, so clear
+        * PT_PAGE_SIZE_MASK in gpte if that is the case.
+        */
+       gpte &= level - mmu->last_nonleaf_level;
+
+       return gpte & PT_PAGE_SIZE_MASK;
 }
 
 #define PTTYPE_EPT 18 /* arbitrary */
@@ -3721,13 +3806,15 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
 void
 reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
 {
+       bool uses_nx = context->nx || context->base_role.smep_andnot_wp;
+
        /*
         * Passing "true" to the last argument is okay; it adds a check
         * on bit 8 of the SPTEs which KVM doesn't use anyway.
         */
        __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
                                boot_cpu_data.x86_phys_bits,
-                               context->shadow_root_level, context->nx,
+                               context->shadow_root_level, uses_nx,
                                guest_cpuid_has_gbpages(vcpu), is_pse(vcpu),
                                true);
 }
@@ -3836,22 +3923,13 @@ static void update_permission_bitmask(struct kvm_vcpu *vcpu,
        }
 }
 
-static void update_last_pte_bitmap(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu)
+static void update_last_nonleaf_level(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu)
 {
-       u8 map;
-       unsigned level, root_level = mmu->root_level;
-       const unsigned ps_set_index = 1 << 2;  /* bit 2 of index: ps */
-
-       if (root_level == PT32E_ROOT_LEVEL)
-               --root_level;
-       /* PT_PAGE_TABLE_LEVEL always terminates */
-       map = 1 | (1 << ps_set_index);
-       for (level = PT_DIRECTORY_LEVEL; level <= root_level; ++level) {
-               if (level <= PT_PDPE_LEVEL
-                   && (mmu->root_level >= PT32E_ROOT_LEVEL || is_pse(vcpu)))
-                       map |= 1 << (ps_set_index | (level - 1));
-       }
-       mmu->last_pte_bitmap = map;
+       unsigned root_level = mmu->root_level;
+
+       mmu->last_nonleaf_level = root_level;
+       if (root_level == PT32_ROOT_LEVEL && is_pse(vcpu))
+               mmu->last_nonleaf_level++;
 }
 
 static void paging64_init_context_common(struct kvm_vcpu *vcpu,
@@ -3863,7 +3941,7 @@ static void paging64_init_context_common(struct kvm_vcpu *vcpu,
 
        reset_rsvds_bits_mask(vcpu, context);
        update_permission_bitmask(vcpu, context, false);
-       update_last_pte_bitmap(vcpu, context);
+       update_last_nonleaf_level(vcpu, context);
 
        MMU_WARN_ON(!is_pae(vcpu));
        context->page_fault = paging64_page_fault;
@@ -3890,7 +3968,7 @@ static void paging32_init_context(struct kvm_vcpu *vcpu,
 
        reset_rsvds_bits_mask(vcpu, context);
        update_permission_bitmask(vcpu, context, false);
-       update_last_pte_bitmap(vcpu, context);
+       update_last_nonleaf_level(vcpu, context);
 
        context->page_fault = paging32_page_fault;
        context->gva_to_gpa = paging32_gva_to_gpa;
@@ -3948,7 +4026,7 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
        }
 
        update_permission_bitmask(vcpu, context, false);
-       update_last_pte_bitmap(vcpu, context);
+       update_last_nonleaf_level(vcpu, context);
        reset_tdp_shadow_zero_bits_mask(vcpu, context);
 }
 
@@ -4054,7 +4132,7 @@ static void init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
        }
 
        update_permission_bitmask(vcpu, g_context, false);
-       update_last_pte_bitmap(vcpu, g_context);
+       update_last_nonleaf_level(vcpu, g_context);
 }
 
 static void init_kvm_mmu(struct kvm_vcpu *vcpu)
@@ -4125,18 +4203,6 @@ static bool need_remote_flush(u64 old, u64 new)
        return (old & ~new & PT64_PERM_MASK) != 0;
 }
 
-static void mmu_pte_write_flush_tlb(struct kvm_vcpu *vcpu, bool zap_page,
-                                   bool remote_flush, bool local_flush)
-{
-       if (zap_page)
-               return;
-
-       if (remote_flush)
-               kvm_flush_remote_tlbs(vcpu->kvm);
-       else if (local_flush)
-               kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
-}
-
 static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa,
                                    const u8 *new, int *bytes)
 {
@@ -4186,7 +4252,8 @@ static bool detect_write_flooding(struct kvm_mmu_page *sp)
        if (sp->role.level == PT_PAGE_TABLE_LEVEL)
                return false;
 
-       return ++sp->write_flooding_count >= 3;
+       atomic_inc(&sp->write_flooding_count);
+       return atomic_read(&sp->write_flooding_count) >= 3;
 }
 
 /*
@@ -4248,15 +4315,15 @@ static u64 *get_written_sptes(struct kvm_mmu_page *sp, gpa_t gpa, int *nspte)
        return spte;
 }
 
-void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-                      const u8 *new, int bytes)
+static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+                             const u8 *new, int bytes)
 {
        gfn_t gfn = gpa >> PAGE_SHIFT;
        struct kvm_mmu_page *sp;
        LIST_HEAD(invalid_list);
        u64 entry, gentry, *spte;
        int npte;
-       bool remote_flush, local_flush, zap_page;
+       bool remote_flush, local_flush;
        union kvm_mmu_page_role mask = { };
 
        mask.cr0_wp = 1;
@@ -4273,7 +4340,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
        if (!ACCESS_ONCE(vcpu->kvm->arch.indirect_shadow_pages))
                return;
 
-       zap_page = remote_flush = local_flush = false;
+       remote_flush = local_flush = false;
 
        pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
 
@@ -4293,8 +4360,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
        for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn) {
                if (detect_write_misaligned(sp, gpa, bytes) ||
                      detect_write_flooding(sp)) {
-                       zap_page |= !!kvm_mmu_prepare_zap_page(vcpu->kvm, sp,
-                                                    &invalid_list);
+                       kvm_mmu_prepare_zap_page(vcpu->kvm, sp, &invalid_list);
                        ++vcpu->kvm->stat.mmu_flooded;
                        continue;
                }
@@ -4316,8 +4382,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
                        ++spte;
                }
        }
-       mmu_pte_write_flush_tlb(vcpu, zap_page, remote_flush, local_flush);
-       kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
+       kvm_mmu_flush_or_zap(vcpu, &invalid_list, remote_flush, local_flush);
        kvm_mmu_audit(vcpu, AUDIT_POST_PTE_WRITE);
        spin_unlock(&vcpu->kvm->mmu_lock);
 }
@@ -4354,32 +4419,34 @@ static void make_mmu_pages_available(struct kvm_vcpu *vcpu)
        kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
 }
 
-static bool is_mmio_page_fault(struct kvm_vcpu *vcpu, gva_t addr)
-{
-       if (vcpu->arch.mmu.direct_map || mmu_is_nested(vcpu))
-               return vcpu_match_mmio_gpa(vcpu, addr);
-
-       return vcpu_match_mmio_gva(vcpu, addr);
-}
-
 int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code,
                       void *insn, int insn_len)
 {
        int r, emulation_type = EMULTYPE_RETRY;
        enum emulation_result er;
+       bool direct = vcpu->arch.mmu.direct_map || mmu_is_nested(vcpu);
+
+       if (unlikely(error_code & PFERR_RSVD_MASK)) {
+               r = handle_mmio_page_fault(vcpu, cr2, direct);
+               if (r == RET_MMIO_PF_EMULATE) {
+                       emulation_type = 0;
+                       goto emulate;
+               }
+               if (r == RET_MMIO_PF_RETRY)
+                       return 1;
+               if (r < 0)
+                       return r;
+       }
 
        r = vcpu->arch.mmu.page_fault(vcpu, cr2, error_code, false);
        if (r < 0)
-               goto out;
-
-       if (!r) {
-               r = 1;
-               goto out;
-       }
+               return r;
+       if (!r)
+               return 1;
 
-       if (is_mmio_page_fault(vcpu, cr2))
+       if (mmio_info_in_cache(vcpu, cr2, direct))
                emulation_type = 0;
-
+emulate:
        er = x86_emulate_instruction(vcpu, cr2, emulation_type, insn, insn_len);
 
        switch (er) {
@@ -4393,8 +4460,6 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code,
        default:
                BUG();
        }
-out:
-       return r;
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
 
@@ -4463,6 +4528,21 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu)
        init_kvm_mmu(vcpu);
 }
 
+void kvm_mmu_init_vm(struct kvm *kvm)
+{
+       struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
+
+       node->track_write = kvm_mmu_pte_write;
+       kvm_page_track_register_notifier(kvm, node);
+}
+
+void kvm_mmu_uninit_vm(struct kvm *kvm)
+{
+       struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
+
+       kvm_page_track_unregister_notifier(kvm, node);
+}
+
 /* The return value indicates if tlb flush on all vcpus is needed. */
 typedef bool (*slot_level_handler) (struct kvm *kvm, struct kvm_rmap_head *rmap_head);
 
index 55ffb7b0f95e9f82a97e8fd4ab7caf4f720fc335..58fe98a0a526c00f1126ee3af212428ff5123b06 100644 (file)
@@ -174,4 +174,9 @@ static inline bool permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
 
 void kvm_mmu_invalidate_zap_all_pages(struct kvm *kvm);
 void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end);
+
+void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
+void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
+bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
+                                   struct kvm_memory_slot *slot, u64 gfn);
 #endif
diff --git a/arch/x86/kvm/page_track.c b/arch/x86/kvm/page_track.c
new file mode 100644 (file)
index 0000000..11f7643
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Support KVM gust page tracking
+ *
+ * This feature allows us to track page access in guest. Currently, only
+ * write access is tracked.
+ *
+ * Copyright(C) 2015 Intel Corporation.
+ *
+ * Author:
+ *   Xiao Guangrong <guangrong.xiao@linux.intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <linux/kvm_host.h>
+#include <asm/kvm_host.h>
+#include <asm/kvm_page_track.h>
+
+#include "mmu.h"
+
+void kvm_page_track_free_memslot(struct kvm_memory_slot *free,
+                                struct kvm_memory_slot *dont)
+{
+       int i;
+
+       for (i = 0; i < KVM_PAGE_TRACK_MAX; i++)
+               if (!dont || free->arch.gfn_track[i] !=
+                     dont->arch.gfn_track[i]) {
+                       kvfree(free->arch.gfn_track[i]);
+                       free->arch.gfn_track[i] = NULL;
+               }
+}
+
+int kvm_page_track_create_memslot(struct kvm_memory_slot *slot,
+                                 unsigned long npages)
+{
+       int  i;
+
+       for (i = 0; i < KVM_PAGE_TRACK_MAX; i++) {
+               slot->arch.gfn_track[i] = kvm_kvzalloc(npages *
+                                           sizeof(*slot->arch.gfn_track[i]));
+               if (!slot->arch.gfn_track[i])
+                       goto track_free;
+       }
+
+       return 0;
+
+track_free:
+       kvm_page_track_free_memslot(slot, NULL);
+       return -ENOMEM;
+}
+
+static inline bool page_track_mode_is_valid(enum kvm_page_track_mode mode)
+{
+       if (mode < 0 || mode >= KVM_PAGE_TRACK_MAX)
+               return false;
+
+       return true;
+}
+
+static void update_gfn_track(struct kvm_memory_slot *slot, gfn_t gfn,
+                            enum kvm_page_track_mode mode, short count)
+{
+       int index, val;
+
+       index = gfn_to_index(gfn, slot->base_gfn, PT_PAGE_TABLE_LEVEL);
+
+       val = slot->arch.gfn_track[mode][index];
+
+       if (WARN_ON(val + count < 0 || val + count > USHRT_MAX))
+               return;
+
+       slot->arch.gfn_track[mode][index] += count;
+}
+
+/*
+ * add guest page to the tracking pool so that corresponding access on that
+ * page will be intercepted.
+ *
+ * It should be called under the protection both of mmu-lock and kvm->srcu
+ * or kvm->slots_lock.
+ *
+ * @kvm: the guest instance we are interested in.
+ * @slot: the @gfn belongs to.
+ * @gfn: the guest page.
+ * @mode: tracking mode, currently only write track is supported.
+ */
+void kvm_slot_page_track_add_page(struct kvm *kvm,
+                                 struct kvm_memory_slot *slot, gfn_t gfn,
+                                 enum kvm_page_track_mode mode)
+{
+
+       if (WARN_ON(!page_track_mode_is_valid(mode)))
+               return;
+
+       update_gfn_track(slot, gfn, mode, 1);
+
+       /*
+        * new track stops large page mapping for the
+        * tracked page.
+        */
+       kvm_mmu_gfn_disallow_lpage(slot, gfn);
+
+       if (mode == KVM_PAGE_TRACK_WRITE)
+               if (kvm_mmu_slot_gfn_write_protect(kvm, slot, gfn))
+                       kvm_flush_remote_tlbs(kvm);
+}
+
+/*
+ * remove the guest page from the tracking pool which stops the interception
+ * of corresponding access on that page. It is the opposed operation of
+ * kvm_slot_page_track_add_page().
+ *
+ * It should be called under the protection both of mmu-lock and kvm->srcu
+ * or kvm->slots_lock.
+ *
+ * @kvm: the guest instance we are interested in.
+ * @slot: the @gfn belongs to.
+ * @gfn: the guest page.
+ * @mode: tracking mode, currently only write track is supported.
+ */
+void kvm_slot_page_track_remove_page(struct kvm *kvm,
+                                    struct kvm_memory_slot *slot, gfn_t gfn,
+                                    enum kvm_page_track_mode mode)
+{
+       if (WARN_ON(!page_track_mode_is_valid(mode)))
+               return;
+
+       update_gfn_track(slot, gfn, mode, -1);
+
+       /*
+        * allow large page mapping for the tracked page
+        * after the tracker is gone.
+        */
+       kvm_mmu_gfn_allow_lpage(slot, gfn);
+}
+
+/*
+ * check if the corresponding access on the specified guest page is tracked.
+ */
+bool kvm_page_track_is_active(struct kvm_vcpu *vcpu, gfn_t gfn,
+                             enum kvm_page_track_mode mode)
+{
+       struct kvm_memory_slot *slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
+       int index = gfn_to_index(gfn, slot->base_gfn, PT_PAGE_TABLE_LEVEL);
+
+       if (WARN_ON(!page_track_mode_is_valid(mode)))
+               return false;
+
+       return !!ACCESS_ONCE(slot->arch.gfn_track[mode][index]);
+}
+
+void kvm_page_track_init(struct kvm *kvm)
+{
+       struct kvm_page_track_notifier_head *head;
+
+       head = &kvm->arch.track_notifier_head;
+       init_srcu_struct(&head->track_srcu);
+       INIT_HLIST_HEAD(&head->track_notifier_list);
+}
+
+/*
+ * register the notifier so that event interception for the tracked guest
+ * pages can be received.
+ */
+void
+kvm_page_track_register_notifier(struct kvm *kvm,
+                                struct kvm_page_track_notifier_node *n)
+{
+       struct kvm_page_track_notifier_head *head;
+
+       head = &kvm->arch.track_notifier_head;
+
+       spin_lock(&kvm->mmu_lock);
+       hlist_add_head_rcu(&n->node, &head->track_notifier_list);
+       spin_unlock(&kvm->mmu_lock);
+}
+
+/*
+ * stop receiving the event interception. It is the opposed operation of
+ * kvm_page_track_register_notifier().
+ */
+void
+kvm_page_track_unregister_notifier(struct kvm *kvm,
+                                  struct kvm_page_track_notifier_node *n)
+{
+       struct kvm_page_track_notifier_head *head;
+
+       head = &kvm->arch.track_notifier_head;
+
+       spin_lock(&kvm->mmu_lock);
+       hlist_del_rcu(&n->node);
+       spin_unlock(&kvm->mmu_lock);
+       synchronize_srcu(&head->track_srcu);
+}
+
+/*
+ * Notify the node that write access is intercepted and write emulation is
+ * finished at this time.
+ *
+ * The node should figure out if the written page is the one that node is
+ * interested in by itself.
+ */
+void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
+                         int bytes)
+{
+       struct kvm_page_track_notifier_head *head;
+       struct kvm_page_track_notifier_node *n;
+       int idx;
+
+       head = &vcpu->kvm->arch.track_notifier_head;
+
+       if (hlist_empty(&head->track_notifier_list))
+               return;
+
+       idx = srcu_read_lock(&head->track_srcu);
+       hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
+               if (n->track_write)
+                       n->track_write(vcpu, gpa, new, bytes);
+       srcu_read_unlock(&head->track_srcu, idx);
+}
index 6c9fed957cce1c897f0a490ec74c3f4e4f76d4dc..e159a8185ad9af081de317ff6b686d1ee3eb1d4b 100644 (file)
@@ -189,8 +189,11 @@ static inline unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, u64 gpte)
                ((gpte & VMX_EPT_EXECUTABLE_MASK) ? ACC_EXEC_MASK : 0) |
                ACC_USER_MASK;
 #else
-       access = (gpte & (PT_WRITABLE_MASK | PT_USER_MASK)) | ACC_EXEC_MASK;
-       access &= ~(gpte >> PT64_NX_SHIFT);
+       BUILD_BUG_ON(ACC_EXEC_MASK != PT_PRESENT_MASK);
+       BUILD_BUG_ON(ACC_EXEC_MASK != 1);
+       access = gpte & (PT_WRITABLE_MASK | PT_USER_MASK | PT_PRESENT_MASK);
+       /* Combine NX with P (which is set here) to get ACC_EXEC_MASK.  */
+       access ^= (gpte >> PT64_NX_SHIFT);
 #endif
 
        return access;
@@ -249,7 +252,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
                        return ret;
 
                kvm_vcpu_mark_page_dirty(vcpu, table_gfn);
-               walker->ptes[level] = pte;
+               walker->ptes[level - 1] = pte;
        }
        return 0;
 }
@@ -702,23 +705,16 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
 
        pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
 
-       if (unlikely(error_code & PFERR_RSVD_MASK)) {
-               r = handle_mmio_page_fault(vcpu, addr, mmu_is_nested(vcpu));
-               if (likely(r != RET_MMIO_PF_INVALID))
-                       return r;
-
-               /*
-                * page fault with PFEC.RSVD  = 1 is caused by shadow
-                * page fault, should not be used to walk guest page
-                * table.
-                */
-               error_code &= ~PFERR_RSVD_MASK;
-       };
-
        r = mmu_topup_memory_caches(vcpu);
        if (r)
                return r;
 
+       /*
+        * If PFEC.RSVD is set, this is a shadow page fault.
+        * The bit needs to be cleared before walking guest page tables.
+        */
+       error_code &= ~PFERR_RSVD_MASK;
+
        /*
         * Look up the guest pte for the faulting address.
         */
@@ -735,6 +731,11 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
                return 0;
        }
 
+       if (page_fault_handle_page_track(vcpu, error_code, walker.gfn)) {
+               shadow_page_table_clear_flood(vcpu, addr);
+               return 1;
+       }
+
        vcpu->arch.write_fault_to_shadow_pgtable = false;
 
        is_self_change_mapping = FNAME(is_self_change_mapping)(vcpu,
@@ -945,7 +946,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 
                if (kvm_vcpu_read_guest_atomic(vcpu, pte_gpa, &gpte,
                                               sizeof(pt_element_t)))
-                       return -EINVAL;
+                       return 0;
 
                if (FNAME(prefetch_invalid_gpte)(vcpu, sp, &sp->spt[i], gpte)) {
                        vcpu->kvm->tlbs_dirty++;
@@ -977,7 +978,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
                         host_writable);
        }
 
-       return !nr_present;
+       return nr_present;
 }
 
 #undef pt_element_t
index 31aa2c85dc9761ec104a9b8f36015a120eb41250..06ce377dcbc9ffb40a655a89c9f0a43855f2a732 100644 (file)
@@ -257,7 +257,7 @@ int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned idx, u64 *data)
 
 void kvm_pmu_deliver_pmi(struct kvm_vcpu *vcpu)
 {
-       if (vcpu->arch.apic)
+       if (lapic_in_kernel(vcpu))
                kvm_apic_local_deliver(vcpu->arch.apic, APIC_LVTPC);
 }
 
index c13a64b7d7899a4aab5d7bb72e2b499f40271829..95070386d5991baef11e2934349727af714cfce3 100644 (file)
@@ -1858,8 +1858,7 @@ static int halt_interception(struct vcpu_svm *svm)
 static int vmmcall_interception(struct vcpu_svm *svm)
 {
        svm->next_rip = kvm_rip_read(&svm->vcpu) + 3;
-       kvm_emulate_hypercall(&svm->vcpu);
-       return 1;
+       return kvm_emulate_hypercall(&svm->vcpu);
 }
 
 static unsigned long nested_svm_get_tdp_cr3(struct kvm_vcpu *vcpu)
index ad9f6a23f13961feca86340c9cda300608da8b8e..2f1ea2f61e1fceef4a77b3955c4d3a9c4a936a72 100644 (file)
@@ -996,11 +996,13 @@ TRACE_EVENT(kvm_enter_smm,
  * Tracepoint for VT-d posted-interrupts.
  */
 TRACE_EVENT(kvm_pi_irte_update,
-       TP_PROTO(unsigned int vcpu_id, unsigned int gsi,
-                unsigned int gvec, u64 pi_desc_addr, bool set),
-       TP_ARGS(vcpu_id, gsi, gvec, pi_desc_addr, set),
+       TP_PROTO(unsigned int host_irq, unsigned int vcpu_id,
+                unsigned int gsi, unsigned int gvec,
+                u64 pi_desc_addr, bool set),
+       TP_ARGS(host_irq, vcpu_id, gsi, gvec, pi_desc_addr, set),
 
        TP_STRUCT__entry(
+               __field(        unsigned int,   host_irq        )
                __field(        unsigned int,   vcpu_id         )
                __field(        unsigned int,   gsi             )
                __field(        unsigned int,   gvec            )
@@ -1009,6 +1011,7 @@ TRACE_EVENT(kvm_pi_irte_update,
        ),
 
        TP_fast_assign(
+               __entry->host_irq       = host_irq;
                __entry->vcpu_id        = vcpu_id;
                __entry->gsi            = gsi;
                __entry->gvec           = gvec;
@@ -1016,9 +1019,10 @@ TRACE_EVENT(kvm_pi_irte_update,
                __entry->set            = set;
        ),
 
-       TP_printk("VT-d PI is %s for this irq, vcpu %u, gsi: 0x%x, "
+       TP_printk("VT-d PI is %s for irq %u, vcpu %u, gsi: 0x%x, "
                  "gvec: 0x%x, pi_desc_addr: 0x%llx",
                  __entry->set ? "enabled and being updated" : "disabled",
+                 __entry->host_irq,
                  __entry->vcpu_id,
                  __entry->gsi,
                  __entry->gvec,
index e2951b6edbbce4deb5bad4fb38b8858c8093f8d5..5e45c2731a5d60ba6a9adfc58841ca075cd90834 100644 (file)
@@ -596,6 +596,8 @@ struct vcpu_vmx {
        /* Support for PML */
 #define PML_ENTITY_NUM         512
        struct page *pml_pg;
+
+       u64 current_tsc_ratio;
 };
 
 enum segment_cache_field {
@@ -861,7 +863,6 @@ static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu);
 static u64 construct_eptp(unsigned long root_hpa);
 static void kvm_cpu_vmxon(u64 addr);
 static void kvm_cpu_vmxoff(void);
-static bool vmx_mpx_supported(void);
 static bool vmx_xsaves_supported(void);
 static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr);
 static void vmx_set_segment(struct kvm_vcpu *vcpu,
@@ -961,25 +962,36 @@ static const u32 vmx_msr_index[] = {
        MSR_EFER, MSR_TSC_AUX, MSR_STAR,
 };
 
-static inline bool is_page_fault(u32 intr_info)
+static inline bool is_exception_n(u32 intr_info, u8 vector)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
                             INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_HARD_EXCEPTION | PF_VECTOR | INTR_INFO_VALID_MASK);
+               (INTR_TYPE_HARD_EXCEPTION | vector | INTR_INFO_VALID_MASK);
+}
+
+static inline bool is_debug(u32 intr_info)
+{
+       return is_exception_n(intr_info, DB_VECTOR);
+}
+
+static inline bool is_breakpoint(u32 intr_info)
+{
+       return is_exception_n(intr_info, BP_VECTOR);
+}
+
+static inline bool is_page_fault(u32 intr_info)
+{
+       return is_exception_n(intr_info, PF_VECTOR);
 }
 
 static inline bool is_no_device(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
-                            INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_HARD_EXCEPTION | NM_VECTOR | INTR_INFO_VALID_MASK);
+       return is_exception_n(intr_info, NM_VECTOR);
 }
 
 static inline bool is_invalid_opcode(u32 intr_info)
 {
-       return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK |
-                            INTR_INFO_VALID_MASK)) ==
-               (INTR_TYPE_HARD_EXCEPTION | UD_VECTOR | INTR_INFO_VALID_MASK);
+       return is_exception_n(intr_info, UD_VECTOR);
 }
 
 static inline bool is_external_interrupt(u32 intr_info)
@@ -1811,6 +1823,13 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
                        return;
                }
                break;
+       case MSR_IA32_PEBS_ENABLE:
+               /* PEBS needs a quiescent period after being disabled (to write
+                * a record).  Disabling PEBS through VMX MSR swapping doesn't
+                * provide that period, so a CPU could write host's record into
+                * guest's memory.
+                */
+               wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
        }
 
        for (i = 0; i < m->nr; ++i)
@@ -1848,26 +1867,31 @@ static void reload_tss(void)
 
 static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
 {
-       u64 guest_efer;
-       u64 ignore_bits;
+       u64 guest_efer = vmx->vcpu.arch.efer;
+       u64 ignore_bits = 0;
 
-       guest_efer = vmx->vcpu.arch.efer;
+       if (!enable_ept) {
+               /*
+                * NX is needed to handle CR0.WP=1, CR4.SMEP=1.  Testing
+                * host CPUID is more efficient than testing guest CPUID
+                * or CR4.  Host SMEP is anyway a requirement for guest SMEP.
+                */
+               if (boot_cpu_has(X86_FEATURE_SMEP))
+                       guest_efer |= EFER_NX;
+               else if (!(guest_efer & EFER_NX))
+                       ignore_bits |= EFER_NX;
+       }
 
        /*
-        * NX is emulated; LMA and LME handled by hardware; SCE meaningless
-        * outside long mode
+        * LMA and LME handled by hardware; SCE meaningless outside long mode.
         */
-       ignore_bits = EFER_NX | EFER_SCE;
+       ignore_bits |= EFER_SCE;
 #ifdef CONFIG_X86_64
        ignore_bits |= EFER_LMA | EFER_LME;
        /* SCE is meaningful only in long mode on Intel */
        if (guest_efer & EFER_LMA)
                ignore_bits &= ~(u64)EFER_SCE;
 #endif
-       guest_efer &= ~ignore_bits;
-       guest_efer |= host_efer & ignore_bits;
-       vmx->guest_msrs[efer_offset].data = guest_efer;
-       vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
 
        clear_atomic_switch_msr(vmx, MSR_EFER);
 
@@ -1878,16 +1902,21 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
         */
        if (cpu_has_load_ia32_efer ||
            (enable_ept && ((vmx->vcpu.arch.efer ^ host_efer) & EFER_NX))) {
-               guest_efer = vmx->vcpu.arch.efer;
                if (!(guest_efer & EFER_LMA))
                        guest_efer &= ~EFER_LME;
                if (guest_efer != host_efer)
                        add_atomic_switch_msr(vmx, MSR_EFER,
                                              guest_efer, host_efer);
                return false;
-       }
+       } else {
+               guest_efer &= ~ignore_bits;
+               guest_efer |= host_efer & ignore_bits;
 
-       return true;
+               vmx->guest_msrs[efer_offset].data = guest_efer;
+               vmx->guest_msrs[efer_offset].mask = ~ignore_bits;
+
+               return true;
+       }
 }
 
 static unsigned long segment_base(u16 selector)
@@ -2127,14 +2156,16 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                rdmsrl(MSR_IA32_SYSENTER_ESP, sysenter_esp);
                vmcs_writel(HOST_IA32_SYSENTER_ESP, sysenter_esp); /* 22.2.3 */
 
-               /* Setup TSC multiplier */
-               if (cpu_has_vmx_tsc_scaling())
-                       vmcs_write64(TSC_MULTIPLIER,
-                                    vcpu->arch.tsc_scaling_ratio);
-
                vmx->loaded_vmcs->cpu = cpu;
        }
 
+       /* Setup TSC multiplier */
+       if (kvm_has_tsc_control &&
+           vmx->current_tsc_ratio != vcpu->arch.tsc_scaling_ratio) {
+               vmx->current_tsc_ratio = vcpu->arch.tsc_scaling_ratio;
+               vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio);
+       }
+
        vmx_vcpu_pi_load(vcpu, cpu);
 }
 
@@ -2584,7 +2615,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
                VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER |
                VM_EXIT_SAVE_VMX_PREEMPTION_TIMER | VM_EXIT_ACK_INTR_ON_EXIT;
 
-       if (vmx_mpx_supported())
+       if (kvm_mpx_supported())
                vmx->nested.nested_vmx_exit_ctls_high |= VM_EXIT_CLEAR_BNDCFGS;
 
        /* We support free control of debug control saving. */
@@ -2605,7 +2636,7 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
                VM_ENTRY_LOAD_IA32_PAT;
        vmx->nested.nested_vmx_entry_ctls_high |=
                (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | VM_ENTRY_LOAD_IA32_EFER);
-       if (vmx_mpx_supported())
+       if (kvm_mpx_supported())
                vmx->nested.nested_vmx_entry_ctls_high |= VM_ENTRY_LOAD_BNDCFGS;
 
        /* We support free control of debug control loading. */
@@ -2849,7 +2880,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                msr_info->data = vmcs_readl(GUEST_SYSENTER_ESP);
                break;
        case MSR_IA32_BNDCFGS:
-               if (!vmx_mpx_supported())
+               if (!kvm_mpx_supported())
                        return 1;
                msr_info->data = vmcs_read64(GUEST_BNDCFGS);
                break;
@@ -2926,7 +2957,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                vmcs_writel(GUEST_SYSENTER_ESP, data);
                break;
        case MSR_IA32_BNDCFGS:
-               if (!vmx_mpx_supported())
+               if (!kvm_mpx_supported())
                        return 1;
                vmcs_write64(GUEST_BNDCFGS, data);
                break;
@@ -3399,7 +3430,7 @@ static void init_vmcs_shadow_fields(void)
        for (i = j = 0; i < max_shadow_read_write_fields; i++) {
                switch (shadow_read_write_fields[i]) {
                case GUEST_BNDCFGS:
-                       if (!vmx_mpx_supported())
+                       if (!kvm_mpx_supported())
                                continue;
                        break;
                default:
@@ -5608,11 +5639,8 @@ static int handle_dr(struct kvm_vcpu *vcpu)
        }
 
        if (vcpu->guest_debug == 0) {
-               u32 cpu_based_vm_exec_control;
-
-               cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
-               cpu_based_vm_exec_control &= ~CPU_BASED_MOV_DR_EXITING;
-               vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+               vmcs_clear_bits(CPU_BASED_VM_EXEC_CONTROL,
+                               CPU_BASED_MOV_DR_EXITING);
 
                /*
                 * No more DR vmexits; force a reload of the debug registers
@@ -5649,8 +5677,6 @@ static void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val)
 
 static void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
 {
-       u32 cpu_based_vm_exec_control;
-
        get_debugreg(vcpu->arch.db[0], 0);
        get_debugreg(vcpu->arch.db[1], 1);
        get_debugreg(vcpu->arch.db[2], 2);
@@ -5659,10 +5685,7 @@ static void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
        vcpu->arch.dr7 = vmcs_readl(GUEST_DR7);
 
        vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_WONT_EXIT;
-
-       cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
-       cpu_based_vm_exec_control |= CPU_BASED_MOV_DR_EXITING;
-       vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
+       vmcs_set_bits(CPU_BASED_VM_EXEC_CONTROL, CPU_BASED_MOV_DR_EXITING);
 }
 
 static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val)
@@ -5747,8 +5770,7 @@ static int handle_halt(struct kvm_vcpu *vcpu)
 
 static int handle_vmcall(struct kvm_vcpu *vcpu)
 {
-       kvm_emulate_hypercall(vcpu);
-       return 1;
+       return kvm_emulate_hypercall(vcpu);
 }
 
 static int handle_invd(struct kvm_vcpu *vcpu)
@@ -6435,8 +6457,8 @@ static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)
 
        if (vmx->nested.vmcs02_num >= max(VMCS02_POOL_SIZE, 1)) {
                /* Recycle the least recently used VMCS. */
-               item = list_entry(vmx->nested.vmcs02_pool.prev,
-                       struct vmcs02_list, list);
+               item = list_last_entry(&vmx->nested.vmcs02_pool,
+                                      struct vmcs02_list, list);
                item->vmptr = vmx->nested.current_vmptr;
                list_move(&item->list, &vmx->nested.vmcs02_pool);
                return &item->vmcs02;
@@ -7752,6 +7774,13 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
                else if (is_no_device(intr_info) &&
                         !(vmcs12->guest_cr0 & X86_CR0_TS))
                        return false;
+               else if (is_debug(intr_info) &&
+                        vcpu->guest_debug &
+                        (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
+                       return false;
+               else if (is_breakpoint(intr_info) &&
+                        vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
+                       return false;
                return vmcs12->exception_bitmap &
                                (1u << (intr_info & INTR_INFO_VECTOR_MASK));
        case EXIT_REASON_EXTERNAL_INTERRUPT:
@@ -10256,7 +10285,7 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
        vmcs12->guest_sysenter_cs = vmcs_read32(GUEST_SYSENTER_CS);
        vmcs12->guest_sysenter_esp = vmcs_readl(GUEST_SYSENTER_ESP);
        vmcs12->guest_sysenter_eip = vmcs_readl(GUEST_SYSENTER_EIP);
-       if (vmx_mpx_supported())
+       if (kvm_mpx_supported())
                vmcs12->guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
        if (nested_cpu_has_xsaves(vmcs12))
                vmcs12->xss_exit_bitmap = vmcs_read64(XSS_EXIT_BITMAP);
@@ -10764,13 +10793,26 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
                 */
 
                kvm_set_msi_irq(e, &irq);
-               if (!kvm_intr_is_single_vcpu(kvm, &irq, &vcpu))
+               if (!kvm_intr_is_single_vcpu(kvm, &irq, &vcpu)) {
+                       /*
+                        * Make sure the IRTE is in remapped mode if
+                        * we don't handle it in posted mode.
+                        */
+                       ret = irq_set_vcpu_affinity(host_irq, NULL);
+                       if (ret < 0) {
+                               printk(KERN_INFO
+                                  "failed to back to remapped mode, irq: %u\n",
+                                  host_irq);
+                               goto out;
+                       }
+
                        continue;
+               }
 
                vcpu_info.pi_desc_addr = __pa(vcpu_to_pi_desc(vcpu));
                vcpu_info.vector = irq.vector;
 
-               trace_kvm_pi_irte_update(vcpu->vcpu_id, e->gsi,
+               trace_kvm_pi_irte_update(vcpu->vcpu_id, host_irq, e->gsi,
                                vcpu_info.vector, vcpu_info.pi_desc_addr, set);
 
                if (set)
index 4244c2baf57da55aa5dd266b63781642dcc8af12..7236bd3a4c3d7a0c5a6148decc6fad276eb18bb7 100644 (file)
@@ -123,6 +123,9 @@ module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
 unsigned int __read_mostly lapic_timer_advance_ns = 0;
 module_param(lapic_timer_advance_ns, uint, S_IRUGO | S_IWUSR);
 
+static bool __read_mostly vector_hashing = true;
+module_param(vector_hashing, bool, S_IRUGO);
+
 static bool __read_mostly backwards_tsc_observed = false;
 
 #define KVM_NR_SHARED_MSRS 16
@@ -1196,17 +1199,11 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)
 
 static uint32_t div_frac(uint32_t dividend, uint32_t divisor)
 {
-       uint32_t quotient, remainder;
-
-       /* Don't try to replace with do_div(), this one calculates
-        * "(dividend << 32) / divisor" */
-       __asm__ ( "divl %4"
-                 : "=a" (quotient), "=d" (remainder)
-                 : "0" (0), "1" (dividend), "r" (divisor) );
-       return quotient;
+       do_shl32_div32(dividend, divisor);
+       return dividend;
 }
 
-static void kvm_get_time_scale(uint32_t scaled_khz, uint32_t base_khz,
+static void kvm_get_time_scale(uint64_t scaled_hz, uint64_t base_hz,
                               s8 *pshift, u32 *pmultiplier)
 {
        uint64_t scaled64;
@@ -1214,8 +1211,8 @@ static void kvm_get_time_scale(uint32_t scaled_khz, uint32_t base_khz,
        uint64_t tps64;
        uint32_t tps32;
 
-       tps64 = base_khz * 1000LL;
-       scaled64 = scaled_khz * 1000LL;
+       tps64 = base_hz;
+       scaled64 = scaled_hz;
        while (tps64 > scaled64*2 || tps64 & 0xffffffff00000000ULL) {
                tps64 >>= 1;
                shift--;
@@ -1233,8 +1230,8 @@ static void kvm_get_time_scale(uint32_t scaled_khz, uint32_t base_khz,
        *pshift = shift;
        *pmultiplier = div_frac(scaled64, tps32);
 
-       pr_debug("%s: base_khz %u => %u, shift %d, mul %u\n",
-                __func__, base_khz, scaled_khz, shift, *pmultiplier);
+       pr_debug("%s: base_hz %llu => %llu, shift %d, mul %u\n",
+                __func__, base_hz, scaled_hz, shift, *pmultiplier);
 }
 
 #ifdef CONFIG_X86_64
@@ -1293,23 +1290,23 @@ static int set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
        return 0;
 }
 
-static int kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
+static int kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz)
 {
        u32 thresh_lo, thresh_hi;
        int use_scaling = 0;
 
        /* tsc_khz can be zero if TSC calibration fails */
-       if (this_tsc_khz == 0) {
+       if (user_tsc_khz == 0) {
                /* set tsc_scaling_ratio to a safe value */
                vcpu->arch.tsc_scaling_ratio = kvm_default_tsc_scaling_ratio;
                return -1;
        }
 
        /* Compute a scale to convert nanoseconds in TSC cycles */
-       kvm_get_time_scale(this_tsc_khz, NSEC_PER_SEC / 1000,
+       kvm_get_time_scale(user_tsc_khz * 1000LL, NSEC_PER_SEC,
                           &vcpu->arch.virtual_tsc_shift,
                           &vcpu->arch.virtual_tsc_mult);
-       vcpu->arch.virtual_tsc_khz = this_tsc_khz;
+       vcpu->arch.virtual_tsc_khz = user_tsc_khz;
 
        /*
         * Compute the variation in TSC rate which is acceptable
@@ -1319,11 +1316,11 @@ static int kvm_set_tsc_khz(struct kvm_vcpu *vcpu, u32 this_tsc_khz)
         */
        thresh_lo = adjust_tsc_khz(tsc_khz, -tsc_tolerance_ppm);
        thresh_hi = adjust_tsc_khz(tsc_khz, tsc_tolerance_ppm);
-       if (this_tsc_khz < thresh_lo || this_tsc_khz > thresh_hi) {
-               pr_debug("kvm: requested TSC rate %u falls outside tolerance [%u,%u]\n", this_tsc_khz, thresh_lo, thresh_hi);
+       if (user_tsc_khz < thresh_lo || user_tsc_khz > thresh_hi) {
+               pr_debug("kvm: requested TSC rate %u falls outside tolerance [%u,%u]\n", user_tsc_khz, thresh_lo, thresh_hi);
                use_scaling = 1;
        }
-       return set_tsc_khz(vcpu, this_tsc_khz, use_scaling);
+       return set_tsc_khz(vcpu, user_tsc_khz, use_scaling);
 }
 
 static u64 compute_guest_tsc(struct kvm_vcpu *vcpu, s64 kernel_ns)
@@ -1716,7 +1713,7 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)
 
 static int kvm_guest_time_update(struct kvm_vcpu *v)
 {
-       unsigned long flags, this_tsc_khz, tgt_tsc_khz;
+       unsigned long flags, tgt_tsc_khz;
        struct kvm_vcpu_arch *vcpu = &v->arch;
        struct kvm_arch *ka = &v->kvm->arch;
        s64 kernel_ns;
@@ -1742,8 +1739,8 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 
        /* Keep irq disabled to prevent changes to the clock */
        local_irq_save(flags);
-       this_tsc_khz = __this_cpu_read(cpu_tsc_khz);
-       if (unlikely(this_tsc_khz == 0)) {
+       tgt_tsc_khz = __this_cpu_read(cpu_tsc_khz);
+       if (unlikely(tgt_tsc_khz == 0)) {
                local_irq_restore(flags);
                kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
                return 1;
@@ -1778,13 +1775,14 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
        if (!vcpu->pv_time_enabled)
                return 0;
 
-       if (unlikely(vcpu->hw_tsc_khz != this_tsc_khz)) {
-               tgt_tsc_khz = kvm_has_tsc_control ?
-                       vcpu->virtual_tsc_khz : this_tsc_khz;
-               kvm_get_time_scale(NSEC_PER_SEC / 1000, tgt_tsc_khz,
+       if (kvm_has_tsc_control)
+               tgt_tsc_khz = kvm_scale_tsc(v, tgt_tsc_khz);
+
+       if (unlikely(vcpu->hw_tsc_khz != tgt_tsc_khz)) {
+               kvm_get_time_scale(NSEC_PER_SEC, tgt_tsc_khz * 1000LL,
                                   &vcpu->hv_clock.tsc_shift,
                                   &vcpu->hv_clock.tsc_to_system_mul);
-               vcpu->hw_tsc_khz = this_tsc_khz;
+               vcpu->hw_tsc_khz = tgt_tsc_khz;
        }
 
        /* With all the info we got, fill in the values */
@@ -2987,7 +2985,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
        kvm_x86_ops->set_nmi_mask(vcpu, events->nmi.masked);
 
        if (events->flags & KVM_VCPUEVENT_VALID_SIPI_VECTOR &&
-           kvm_vcpu_has_lapic(vcpu))
+           lapic_in_kernel(vcpu))
                vcpu->arch.apic->sipi_vector = events->sipi_vector;
 
        if (events->flags & KVM_VCPUEVENT_VALID_SMM) {
@@ -3000,7 +2998,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                        vcpu->arch.hflags |= HF_SMM_INSIDE_NMI_MASK;
                else
                        vcpu->arch.hflags &= ~HF_SMM_INSIDE_NMI_MASK;
-               if (kvm_vcpu_has_lapic(vcpu)) {
+               if (lapic_in_kernel(vcpu)) {
                        if (events->smi.latched_init)
                                set_bit(KVM_APIC_INIT, &vcpu->arch.apic->pending_events);
                        else
@@ -3240,7 +3238,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        switch (ioctl) {
        case KVM_GET_LAPIC: {
                r = -EINVAL;
-               if (!vcpu->arch.apic)
+               if (!lapic_in_kernel(vcpu))
                        goto out;
                u.lapic = kzalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
 
@@ -3258,7 +3256,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        }
        case KVM_SET_LAPIC: {
                r = -EINVAL;
-               if (!vcpu->arch.apic)
+               if (!lapic_in_kernel(vcpu))
                        goto out;
                u.lapic = memdup_user(argp, sizeof(*u.lapic));
                if (IS_ERR(u.lapic))
@@ -3605,20 +3603,26 @@ static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
 
 static int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps)
 {
-       mutex_lock(&kvm->arch.vpit->pit_state.lock);
-       memcpy(ps, &kvm->arch.vpit->pit_state, sizeof(struct kvm_pit_state));
-       mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+       struct kvm_kpit_state *kps = &kvm->arch.vpit->pit_state;
+
+       BUILD_BUG_ON(sizeof(*ps) != sizeof(kps->channels));
+
+       mutex_lock(&kps->lock);
+       memcpy(ps, &kps->channels, sizeof(*ps));
+       mutex_unlock(&kps->lock);
        return 0;
 }
 
 static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
 {
        int i;
-       mutex_lock(&kvm->arch.vpit->pit_state.lock);
-       memcpy(&kvm->arch.vpit->pit_state, ps, sizeof(struct kvm_pit_state));
+       struct kvm_pit *pit = kvm->arch.vpit;
+
+       mutex_lock(&pit->pit_state.lock);
+       memcpy(&pit->pit_state.channels, ps, sizeof(*ps));
        for (i = 0; i < 3; i++)
-               kvm_pit_load_count(kvm, i, ps->channels[i].count, 0);
-       mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+               kvm_pit_load_count(pit, i, ps->channels[i].count, 0);
+       mutex_unlock(&pit->pit_state.lock);
        return 0;
 }
 
@@ -3638,29 +3642,39 @@ static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
        int start = 0;
        int i;
        u32 prev_legacy, cur_legacy;
-       mutex_lock(&kvm->arch.vpit->pit_state.lock);
-       prev_legacy = kvm->arch.vpit->pit_state.flags & KVM_PIT_FLAGS_HPET_LEGACY;
+       struct kvm_pit *pit = kvm->arch.vpit;
+
+       mutex_lock(&pit->pit_state.lock);
+       prev_legacy = pit->pit_state.flags & KVM_PIT_FLAGS_HPET_LEGACY;
        cur_legacy = ps->flags & KVM_PIT_FLAGS_HPET_LEGACY;
        if (!prev_legacy && cur_legacy)
                start = 1;
-       memcpy(&kvm->arch.vpit->pit_state.channels, &ps->channels,
-              sizeof(kvm->arch.vpit->pit_state.channels));
-       kvm->arch.vpit->pit_state.flags = ps->flags;
+       memcpy(&pit->pit_state.channels, &ps->channels,
+              sizeof(pit->pit_state.channels));
+       pit->pit_state.flags = ps->flags;
        for (i = 0; i < 3; i++)
-               kvm_pit_load_count(kvm, i, kvm->arch.vpit->pit_state.channels[i].count,
+               kvm_pit_load_count(pit, i, pit->pit_state.channels[i].count,
                                   start && i == 0);
-       mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+       mutex_unlock(&pit->pit_state.lock);
        return 0;
 }
 
 static int kvm_vm_ioctl_reinject(struct kvm *kvm,
                                 struct kvm_reinject_control *control)
 {
-       if (!kvm->arch.vpit)
+       struct kvm_pit *pit = kvm->arch.vpit;
+
+       if (!pit)
                return -ENXIO;
-       mutex_lock(&kvm->arch.vpit->pit_state.lock);
-       kvm->arch.vpit->pit_state.reinject = control->pit_reinject;
-       mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+
+       /* pit->pit_state.lock was overloaded to prevent userspace from getting
+        * an inconsistent state after running multiple KVM_REINJECT_CONTROL
+        * ioctls in parallel.  Use a separate lock if that ioctl isn't rare.
+        */
+       mutex_lock(&pit->pit_state.lock);
+       kvm_pit_set_reinject(pit, control->pit_reinject);
+       mutex_unlock(&pit->pit_state.lock);
+
        return 0;
 }
 
@@ -4093,7 +4107,7 @@ static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
 
        do {
                n = min(len, 8);
-               if (!(vcpu->arch.apic &&
+               if (!(lapic_in_kernel(vcpu) &&
                      !kvm_iodevice_write(vcpu, &vcpu->arch.apic->dev, addr, n, v))
                    && kvm_io_bus_write(vcpu, KVM_MMIO_BUS, addr, n, v))
                        break;
@@ -4113,7 +4127,7 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
 
        do {
                n = min(len, 8);
-               if (!(vcpu->arch.apic &&
+               if (!(lapic_in_kernel(vcpu) &&
                      !kvm_iodevice_read(vcpu, &vcpu->arch.apic->dev,
                                         addr, n, v))
                    && kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, n, v))
@@ -4346,7 +4360,7 @@ int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
        ret = kvm_vcpu_write_guest(vcpu, gpa, val, bytes);
        if (ret < 0)
                return 0;
-       kvm_mmu_pte_write(vcpu, gpa, val, bytes);
+       kvm_page_track_write(vcpu, gpa, val, bytes);
        return 1;
 }
 
@@ -4604,7 +4618,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
                return X86EMUL_CMPXCHG_FAILED;
 
        kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
-       kvm_mmu_pte_write(vcpu, gpa, new, bytes);
+       kvm_page_track_write(vcpu, gpa, new, bytes);
 
        return X86EMUL_CONTINUE;
 
@@ -6010,7 +6024,7 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu)
        if (!kvm_x86_ops->update_cr8_intercept)
                return;
 
-       if (!vcpu->arch.apic)
+       if (!lapic_in_kernel(vcpu))
                return;
 
        if (vcpu->arch.apicv_active)
@@ -6618,12 +6632,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
         * KVM_DEBUGREG_WONT_EXIT again.
         */
        if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) {
-               int i;
-
                WARN_ON(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP);
                kvm_x86_ops->sync_dirty_debug_regs(vcpu);
-               for (i = 0; i < KVM_NR_DB_REGS; i++)
-                       vcpu->arch.eff_db[i] = vcpu->arch.db[i];
+               kvm_update_dr0123(vcpu);
+               kvm_update_dr6(vcpu);
+               kvm_update_dr7(vcpu);
+               vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
        }
 
        /*
@@ -7038,7 +7052,7 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
 int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
                                    struct kvm_mp_state *mp_state)
 {
-       if (!kvm_vcpu_has_lapic(vcpu) &&
+       if (!lapic_in_kernel(vcpu) &&
            mp_state->mp_state != KVM_MP_STATE_RUNNABLE)
                return -EINVAL;
 
@@ -7314,7 +7328,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
         * Every 255 times fpu_counter rolls over to 0; a guest that uses
         * the FPU in bursts will revert to loading it on demand.
         */
-       if (!vcpu->arch.eager_fpu) {
+       if (!use_eager_fpu()) {
                if (++vcpu->fpu_counter < 5)
                        kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
        }
@@ -7593,6 +7607,7 @@ bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
 }
 
 struct static_key kvm_no_apic_vcpu __read_mostly;
+EXPORT_SYMBOL_GPL(kvm_no_apic_vcpu);
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
@@ -7724,6 +7739,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        INIT_DELAYED_WORK(&kvm->arch.kvmclock_update_work, kvmclock_update_fn);
        INIT_DELAYED_WORK(&kvm->arch.kvmclock_sync_work, kvmclock_sync_fn);
 
+       kvm_page_track_init(kvm);
+       kvm_mmu_init_vm(kvm);
+
        return 0;
 }
 
@@ -7850,6 +7868,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
        kfree(kvm->arch.vioapic);
        kvm_free_vcpus(kvm);
        kfree(rcu_dereference_check(kvm->arch.apic_map, 1));
+       kvm_mmu_uninit_vm(kvm);
 }
 
 void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
@@ -7871,6 +7890,8 @@ void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
                        free->arch.lpage_info[i - 1] = NULL;
                }
        }
+
+       kvm_page_track_free_memslot(free, dont);
 }
 
 int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
@@ -7879,6 +7900,7 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
        int i;
 
        for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) {
+               struct kvm_lpage_info *linfo;
                unsigned long ugfn;
                int lpages;
                int level = i + 1;
@@ -7893,15 +7915,16 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
                if (i == 0)
                        continue;
 
-               slot->arch.lpage_info[i - 1] = kvm_kvzalloc(lpages *
-                                       sizeof(*slot->arch.lpage_info[i - 1]));
-               if (!slot->arch.lpage_info[i - 1])
+               linfo = kvm_kvzalloc(lpages * sizeof(*linfo));
+               if (!linfo)
                        goto out_free;
 
+               slot->arch.lpage_info[i - 1] = linfo;
+
                if (slot->base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1))
-                       slot->arch.lpage_info[i - 1][0].write_count = 1;
+                       linfo[0].disallow_lpage = 1;
                if ((slot->base_gfn + npages) & (KVM_PAGES_PER_HPAGE(level) - 1))
-                       slot->arch.lpage_info[i - 1][lpages - 1].write_count = 1;
+                       linfo[lpages - 1].disallow_lpage = 1;
                ugfn = slot->userspace_addr >> PAGE_SHIFT;
                /*
                 * If the gfn and userspace address are not aligned wrt each
@@ -7913,10 +7936,13 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
                        unsigned long j;
 
                        for (j = 0; j < lpages; ++j)
-                               slot->arch.lpage_info[i - 1][j].write_count = 1;
+                               linfo[j].disallow_lpage = 1;
                }
        }
 
+       if (kvm_page_track_create_memslot(slot, npages))
+               goto out_free;
+
        return 0;
 
 out_free:
@@ -8370,6 +8396,12 @@ int kvm_arch_update_irqfd_routing(struct kvm *kvm, unsigned int host_irq,
        return kvm_x86_ops->update_pi_irte(kvm, host_irq, guest_irq, set);
 }
 
+bool kvm_vector_hashing_enabled(void)
+{
+       return vector_hashing;
+}
+EXPORT_SYMBOL_GPL(kvm_vector_hashing_enabled);
+
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit);
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_fast_mmio);
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_inj_virq);
index f2afa5fe48a6dcbd44f5c573cfe9d16f41b8ad16..007940faa5c6357d1c5c1c4bd200b3b8ae195cb0 100644 (file)
@@ -179,6 +179,7 @@ int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data);
 int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
 bool kvm_mtrr_check_gfn_range_consistency(struct kvm_vcpu *vcpu, gfn_t gfn,
                                          int page_num);
+bool kvm_vector_hashing_enabled(void);
 
 #define KVM_SUPPORTED_XCR0     (XFEATURE_MASK_FP | XFEATURE_MASK_SSE \
                                | XFEATURE_MASK_YMM | XFEATURE_MASK_BNDREGS \
@@ -192,4 +193,19 @@ extern unsigned int min_timer_period_us;
 extern unsigned int lapic_timer_advance_ns;
 
 extern struct static_key kvm_no_apic_vcpu;
+
+/* Same "calling convention" as do_div:
+ * - divide (n << 32) by base
+ * - put result in n
+ * - return remainder
+ */
+#define do_shl32_div32(n, base)                                        \
+       ({                                                      \
+           u32 __quot, __rem;                                  \
+           asm("divl %2" : "=a" (__quot), "=d" (__rem)         \
+                       : "rm" (base), "0" (0), "1" ((u32) n)); \
+           n = __quot;                                         \
+           __rem;                                              \
+        })
+
 #endif
index 4ba229ac3f4ff127dddf0c33fb91cc42f2e60b22..fd57d3ae7e16daf24f8cfdb4e708c5e4e9a9f3f9 100644 (file)
@@ -1520,12 +1520,6 @@ __init void lguest_init(void)
         */
        reserve_top_address(lguest_data.reserve_mem);
 
-       /*
-        * If we don't initialize the lock dependency checker now, it crashes
-        * atomic_notifier_chain_register, then paravirt_disable_iospace.
-        */
-       lockdep_init();
-
        /* Hook in our special panic hypercall code. */
        atomic_notifier_chain_register(&panic_notifier_list, &paniced);
 
@@ -1535,7 +1529,7 @@ __init void lguest_init(void)
         */
        cpu_detect(&new_cpu_data);
        /* head.S usually sets up the first capability word, so do it here. */
-       new_cpu_data.x86_capability[0] = cpuid_edx(1);
+       new_cpu_data.x86_capability[CPUID_1_EDX] = cpuid_edx(1);
 
        /* Math is always hard! */
        set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU);
index a2fe51b00ccefc660850e1a6810dd4adee611d2e..65be7cfaf947228d454f2324541e5f5227d85183 100644 (file)
@@ -1,5 +1,5 @@
 #include <linux/linkage.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
 
 /*
index 422db000d72767adf718dc75db682e5df576e877..5cc78bf572325fb1c5b5d6f854bfe878c55dfeb3 100644 (file)
@@ -21,12 +21,16 @@ static inline int myisspace(u8 c)
  * @option: option string to look for
  *
  * Returns the position of that @option (starts counting with 1)
- * or 0 on not found.
+ * or 0 on not found.  @option will only be found if it is found
+ * as an entire word in @cmdline.  For instance, if @option="car"
+ * then a cmdline which contains "cart" will not match.
  */
-int cmdline_find_option_bool(const char *cmdline, const char *option)
+static int
+__cmdline_find_option_bool(const char *cmdline, int max_cmdline_size,
+                          const char *option)
 {
        char c;
-       int len, pos = 0, wstart = 0;
+       int pos = 0, wstart = 0;
        const char *opptr = NULL;
        enum {
                st_wordstart = 0,       /* Start of word/after whitespace */
@@ -37,11 +41,11 @@ int cmdline_find_option_bool(const char *cmdline, const char *option)
        if (!cmdline)
                return -1;      /* No command line */
 
-       len = min_t(int, strlen(cmdline), COMMAND_LINE_SIZE);
-       if (!len)
-               return 0;
-
-       while (len--) {
+       /*
+        * This 'pos' check ensures we do not overrun
+        * a non-NULL-terminated 'cmdline'
+        */
+       while (pos < max_cmdline_size) {
                c = *(char *)cmdline++;
                pos++;
 
@@ -58,18 +62,35 @@ int cmdline_find_option_bool(const char *cmdline, const char *option)
                        /* fall through */
 
                case st_wordcmp:
-                       if (!*opptr)
+                       if (!*opptr) {
+                               /*
+                                * We matched all the way to the end of the
+                                * option we were looking for.  If the
+                                * command-line has a space _or_ ends, then
+                                * we matched!
+                                */
                                if (!c || myisspace(c))
                                        return wstart;
-                               else
-                                       state = st_wordskip;
-                       else if (!c)
+                               /*
+                                * We hit the end of the option, but _not_
+                                * the end of a word on the cmdline.  Not
+                                * a match.
+                                */
+                       } else if (!c) {
+                               /*
+                                * Hit the NULL terminator on the end of
+                                * cmdline.
+                                */
                                return 0;
-                       else if (c != *opptr++)
-                               state = st_wordskip;
-                       else if (!len)          /* last word and is matching */
-                               return wstart;
-                       break;
+                       } else if (c == *opptr++) {
+                               /*
+                                * We are currently matching, so continue
+                                * to the next character on the cmdline.
+                                */
+                               break;
+                       }
+                       state = st_wordskip;
+                       /* fall through */
 
                case st_wordskip:
                        if (!c)
@@ -82,3 +103,8 @@ int cmdline_find_option_bool(const char *cmdline, const char *option)
 
        return 0;       /* Buffer overrun */
 }
+
+int cmdline_find_option_bool(const char *cmdline, const char *option)
+{
+       return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
+}
index 009f98216b7eb316c12847e42f50ac77d4f4b8a3..24ef1c2104d422c35a9ce783934306a0dd9215f1 100644 (file)
@@ -1,7 +1,7 @@
 /* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */
 
 #include <linux/linkage.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
 
 /*
index 27f89c79a44b7da6fc6aef54e3961426e542e7ed..2b0ef26da0bde8eabc38f5b42ef9e4aa02464ad4 100644 (file)
@@ -10,7 +10,7 @@
 #include <asm/current.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
 #include <asm/asm.h>
 #include <asm/smap.h>
index e912b2f6d36e5392b33bf6749f19a53cff6d7a06..2f07c291dcc855af5c483c55133d91a4dff21c92 100644 (file)
@@ -102,7 +102,7 @@ static void delay_mwaitx(unsigned long __loops)
                 * Use cpu_tss as a cacheline-aligned, seldomly
                 * accessed per-cpu variable as the monitor target.
                 */
-               __monitorx(this_cpu_ptr(&cpu_tss), 0, 0);
+               __monitorx(raw_cpu_ptr(&cpu_tss), 0, 0);
 
                /*
                 * AMD, like Intel, supports the EAX hint and EAX=0xf
index 16698bba87deb9ff593d934e8a8fb1447be9b214..cbb8ee5830ff134f131533fd91ea8be35a853dba 100644 (file)
@@ -1,7 +1,7 @@
 /* Copyright 2002 Andi Kleen */
 
 #include <linux/linkage.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
 
 /*
@@ -177,3 +177,120 @@ ENTRY(memcpy_orig)
 .Lend:
        retq
 ENDPROC(memcpy_orig)
+
+#ifndef CONFIG_UML
+/*
+ * memcpy_mcsafe - memory copy with machine check exception handling
+ * Note that we only catch machine checks when reading the source addresses.
+ * Writes to target are posted and don't generate machine checks.
+ */
+ENTRY(memcpy_mcsafe)
+       cmpl $8, %edx
+       /* Less than 8 bytes? Go to byte copy loop */
+       jb .L_no_whole_words
+
+       /* Check for bad alignment of source */
+       testl $7, %esi
+       /* Already aligned */
+       jz .L_8byte_aligned
+
+       /* Copy one byte at a time until source is 8-byte aligned */
+       movl %esi, %ecx
+       andl $7, %ecx
+       subl $8, %ecx
+       negl %ecx
+       subl %ecx, %edx
+.L_copy_leading_bytes:
+       movb (%rsi), %al
+       movb %al, (%rdi)
+       incq %rsi
+       incq %rdi
+       decl %ecx
+       jnz .L_copy_leading_bytes
+
+.L_8byte_aligned:
+       /* Figure out how many whole cache lines (64-bytes) to copy */
+       movl %edx, %ecx
+       andl $63, %edx
+       shrl $6, %ecx
+       jz .L_no_whole_cache_lines
+
+       /* Loop copying whole cache lines */
+.L_cache_w0: movq (%rsi), %r8
+.L_cache_w1: movq 1*8(%rsi), %r9
+.L_cache_w2: movq 2*8(%rsi), %r10
+.L_cache_w3: movq 3*8(%rsi), %r11
+       movq %r8, (%rdi)
+       movq %r9, 1*8(%rdi)
+       movq %r10, 2*8(%rdi)
+       movq %r11, 3*8(%rdi)
+.L_cache_w4: movq 4*8(%rsi), %r8
+.L_cache_w5: movq 5*8(%rsi), %r9
+.L_cache_w6: movq 6*8(%rsi), %r10
+.L_cache_w7: movq 7*8(%rsi), %r11
+       movq %r8, 4*8(%rdi)
+       movq %r9, 5*8(%rdi)
+       movq %r10, 6*8(%rdi)
+       movq %r11, 7*8(%rdi)
+       leaq 64(%rsi), %rsi
+       leaq 64(%rdi), %rdi
+       decl %ecx
+       jnz .L_cache_w0
+
+       /* Are there any trailing 8-byte words? */
+.L_no_whole_cache_lines:
+       movl %edx, %ecx
+       andl $7, %edx
+       shrl $3, %ecx
+       jz .L_no_whole_words
+
+       /* Copy trailing words */
+.L_copy_trailing_words:
+       movq (%rsi), %r8
+       mov %r8, (%rdi)
+       leaq 8(%rsi), %rsi
+       leaq 8(%rdi), %rdi
+       decl %ecx
+       jnz .L_copy_trailing_words
+
+       /* Any trailing bytes? */
+.L_no_whole_words:
+       andl %edx, %edx
+       jz .L_done_memcpy_trap
+
+       /* Copy trailing bytes */
+       movl %edx, %ecx
+.L_copy_trailing_bytes:
+       movb (%rsi), %al
+       movb %al, (%rdi)
+       incq %rsi
+       incq %rdi
+       decl %ecx
+       jnz .L_copy_trailing_bytes
+
+       /* Copy successful. Return true */
+.L_done_memcpy_trap:
+       xorq %rax, %rax
+       ret
+ENDPROC(memcpy_mcsafe)
+
+       .section .fixup, "ax"
+       /* Return false for any failure */
+.L_memcpy_mcsafe_fail:
+       mov     $1, %rax
+       ret
+
+       .previous
+
+       _ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w6, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w7, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_copy_trailing_words, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_copy_trailing_bytes, .L_memcpy_mcsafe_fail)
+#endif
index ca2afdd6d98ed2be90da6f9ea1624beb102f0fc3..90ce01bee00c17f173719652659edb5972ecef07 100644 (file)
@@ -6,7 +6,7 @@
  *     - Copyright 2011 Fenghua Yu <fenghua.yu@intel.com>
  */
 #include <linux/linkage.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
 
 #undef memmove
index 2661fad0582716f780af9904dc5b7c62199a5c58..c9c81227ea37d14968b3acb3ccfa346e73cda5dc 100644 (file)
@@ -1,7 +1,7 @@
 /* Copyright 2002 Andi Kleen, SuSE Labs */
 
 #include <linux/linkage.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/alternative-asm.h>
 
 .weak memset
index 4a6f1d9b51060cc9179598f5916efb69504fa50f..99bfb192803ffcbc22299503a48b6ae84f962f91 100644 (file)
@@ -358,20 +358,19 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
 #define pgd_none(a)  pud_none(__pud(pgd_val(a)))
 #endif
 
-#ifdef CONFIG_X86_64
 static inline bool is_hypervisor_range(int idx)
 {
+#ifdef CONFIG_X86_64
        /*
         * ffff800000000000 - ffff87ffffffffff is reserved for
         * the hypervisor.
         */
-       return paravirt_enabled() &&
-               (idx >= pgd_index(__PAGE_OFFSET) - 16) &&
-               (idx < pgd_index(__PAGE_OFFSET));
-}
+       return  (idx >= pgd_index(__PAGE_OFFSET) - 16) &&
+               (idx <  pgd_index(__PAGE_OFFSET));
 #else
-static inline bool is_hypervisor_range(int idx) { return false; }
+       return false;
 #endif
+}
 
 static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
                                       bool checkwx)
index 903ec1e9c3263f7f7ce6e1f5a59e7a32b224dc85..9dd7e4b7fcdee4a847f98937b9a287b826366a2d 100644 (file)
@@ -3,6 +3,9 @@
 #include <linux/sort.h>
 #include <asm/uaccess.h>
 
+typedef bool (*ex_handler_t)(const struct exception_table_entry *,
+                           struct pt_regs *, int);
+
 static inline unsigned long
 ex_insn_addr(const struct exception_table_entry *x)
 {
@@ -13,11 +16,56 @@ ex_fixup_addr(const struct exception_table_entry *x)
 {
        return (unsigned long)&x->fixup + x->fixup;
 }
+static inline ex_handler_t
+ex_fixup_handler(const struct exception_table_entry *x)
+{
+       return (ex_handler_t)((unsigned long)&x->handler + x->handler);
+}
 
-int fixup_exception(struct pt_regs *regs)
+bool ex_handler_default(const struct exception_table_entry *fixup,
+                      struct pt_regs *regs, int trapnr)
 {
-       const struct exception_table_entry *fixup;
-       unsigned long new_ip;
+       regs->ip = ex_fixup_addr(fixup);
+       return true;
+}
+EXPORT_SYMBOL(ex_handler_default);
+
+bool ex_handler_fault(const struct exception_table_entry *fixup,
+                    struct pt_regs *regs, int trapnr)
+{
+       regs->ip = ex_fixup_addr(fixup);
+       regs->ax = trapnr;
+       return true;
+}
+EXPORT_SYMBOL_GPL(ex_handler_fault);
+
+bool ex_handler_ext(const struct exception_table_entry *fixup,
+                  struct pt_regs *regs, int trapnr)
+{
+       /* Special hack for uaccess_err */
+       current_thread_info()->uaccess_err = 1;
+       regs->ip = ex_fixup_addr(fixup);
+       return true;
+}
+EXPORT_SYMBOL(ex_handler_ext);
+
+bool ex_has_fault_handler(unsigned long ip)
+{
+       const struct exception_table_entry *e;
+       ex_handler_t handler;
+
+       e = search_exception_tables(ip);
+       if (!e)
+               return false;
+       handler = ex_fixup_handler(e);
+
+       return handler == ex_handler_fault;
+}
+
+int fixup_exception(struct pt_regs *regs, int trapnr)
+{
+       const struct exception_table_entry *e;
+       ex_handler_t handler;
 
 #ifdef CONFIG_PNPBIOS
        if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
@@ -33,42 +81,34 @@ int fixup_exception(struct pt_regs *regs)
        }
 #endif
 
-       fixup = search_exception_tables(regs->ip);
-       if (fixup) {
-               new_ip = ex_fixup_addr(fixup);
-
-               if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
-                       /* Special hack for uaccess_err */
-                       current_thread_info()->uaccess_err = 1;
-                       new_ip -= 0x7ffffff0;
-               }
-               regs->ip = new_ip;
-               return 1;
-       }
+       e = search_exception_tables(regs->ip);
+       if (!e)
+               return 0;
 
-       return 0;
+       handler = ex_fixup_handler(e);
+       return handler(e, regs, trapnr);
 }
 
 /* Restricted version used during very early boot */
 int __init early_fixup_exception(unsigned long *ip)
 {
-       const struct exception_table_entry *fixup;
+       const struct exception_table_entry *e;
        unsigned long new_ip;
+       ex_handler_t handler;
 
-       fixup = search_exception_tables(*ip);
-       if (fixup) {
-               new_ip = ex_fixup_addr(fixup);
+       e = search_exception_tables(*ip);
+       if (!e)
+               return 0;
 
-               if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
-                       /* uaccess handling not supported during early boot */
-                       return 0;
-               }
+       new_ip  = ex_fixup_addr(e);
+       handler = ex_fixup_handler(e);
 
-               *ip = new_ip;
-               return 1;
-       }
+       /* special handling not supported during early boot */
+       if (handler != ex_handler_default)
+               return 0;
 
-       return 0;
+       *ip = new_ip;
+       return 1;
 }
 
 /*
@@ -133,6 +173,8 @@ void sort_extable(struct exception_table_entry *start,
                i += 4;
                p->fixup += i;
                i += 4;
+               p->handler += i;
+               i += 4;
        }
 
        sort(start, finish - start, sizeof(struct exception_table_entry),
@@ -145,6 +187,8 @@ void sort_extable(struct exception_table_entry *start,
                i += 4;
                p->fixup -= i;
                i += 4;
+               p->handler -= i;
+               i += 4;
        }
 }
 
index e830c71a13232f4305adf9ef1eb8ce6ffe201d5b..03898aea6e0f2697e2196e9de7f8fe3aeb200ec9 100644 (file)
@@ -663,7 +663,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
        int sig;
 
        /* Are we prepared to handle this kernel fault? */
-       if (fixup_exception(regs)) {
+       if (fixup_exception(regs, X86_TRAP_PF)) {
                /*
                 * Any interrupt that takes a fault gets the fixup. This makes
                 * the below recursive fault logic only apply to a faults from
index 493f54172b4a5c90b1596708f1d5cb2a0f15156c..9d56f271d519592a5fbf316237f73b57b0fc49c4 100644 (file)
@@ -150,13 +150,14 @@ static int page_size_mask;
 
 static void __init probe_page_size_mask(void)
 {
-#if !defined(CONFIG_DEBUG_PAGEALLOC) && !defined(CONFIG_KMEMCHECK)
+#if !defined(CONFIG_KMEMCHECK)
        /*
-        * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
+        * For CONFIG_KMEMCHECK or pagealloc debugging, identity mapping will
+        * use small pages.
         * This will simplify cpa(), which otherwise needs to support splitting
         * large pages into small in interrupt context, etc.
         */
-       if (cpu_has_pse)
+       if (cpu_has_pse && !debug_pagealloc_enabled())
                page_size_mask |= 1 << PG_LEVEL_2M;
 #endif
 
@@ -666,21 +667,22 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
         * mark them not present - any buggy init-section access will
         * create a kernel page fault:
         */
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       printk(KERN_INFO "debug: unmapping init [mem %#010lx-%#010lx]\n",
-               begin, end - 1);
-       set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
-#else
-       /*
-        * We just marked the kernel text read only above, now that
-        * we are going to free part of that, we need to make that
-        * writeable and non-executable first.
-        */
-       set_memory_nx(begin, (end - begin) >> PAGE_SHIFT);
-       set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
+       if (debug_pagealloc_enabled()) {
+               pr_info("debug: unmapping init [mem %#010lx-%#010lx]\n",
+                       begin, end - 1);
+               set_memory_np(begin, (end - begin) >> PAGE_SHIFT);
+       } else {
+               /*
+                * We just marked the kernel text read only above, now that
+                * we are going to free part of that, we need to make that
+                * writeable and non-executable first.
+                */
+               set_memory_nx(begin, (end - begin) >> PAGE_SHIFT);
+               set_memory_rw(begin, (end - begin) >> PAGE_SHIFT);
 
-       free_reserved_area((void *)begin, (void *)end, POISON_FREE_INITMEM, what);
-#endif
+               free_reserved_area((void *)begin, (void *)end,
+                                  POISON_FREE_INITMEM, what);
+       }
 }
 
 void free_initmem(void)
index cb4ef3de61f9ae9c95249876965a71a5d7b58cf8..bd7a9b9e2e14a595adfb1c86bbcfacb787a6579c 100644 (file)
@@ -388,7 +388,6 @@ repeat:
 }
 
 pte_t *kmap_pte;
-pgprot_t kmap_prot;
 
 static inline pte_t *kmap_get_fixmap_pte(unsigned long vaddr)
 {
@@ -405,8 +404,6 @@ static void __init kmap_init(void)
         */
        kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
        kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
-       kmap_prot = PAGE_KERNEL;
 }
 
 #ifdef CONFIG_HIGHMEM
@@ -871,7 +868,6 @@ static noinline int do_test_wp_bit(void)
        return flag;
 }
 
-#ifdef CONFIG_DEBUG_RODATA
 const int rodata_test_data = 0xC3;
 EXPORT_SYMBOL_GPL(rodata_test_data);
 
@@ -960,5 +956,3 @@ void mark_rodata_ro(void)
        if (__supported_pte_mask & _PAGE_NX)
                debug_checkwx();
 }
-#endif
-
index 5488d21123bd2edb3f71ded119495474f3e8b728..214afda979114f3cf1ad7e2d95173e0446a84ed3 100644 (file)
@@ -53,6 +53,7 @@
 #include <asm/numa.h>
 #include <asm/cacheflush.h>
 #include <asm/init.h>
+#include <asm/uv/uv.h>
 #include <asm/setup.h>
 
 #include "mm_internal.h"
@@ -1074,7 +1075,6 @@ void __init mem_init(void)
        mem_init_print_info(NULL);
 }
 
-#ifdef CONFIG_DEBUG_RODATA
 const int rodata_test_data = 0xC3;
 EXPORT_SYMBOL_GPL(rodata_test_data);
 
@@ -1166,8 +1166,6 @@ void mark_rodata_ro(void)
        debug_checkwx();
 }
 
-#endif
-
 int kern_addr_valid(unsigned long addr)
 {
        unsigned long above = ((long)addr) >> __VIRTUAL_MASK_SHIFT;
@@ -1206,26 +1204,13 @@ int kern_addr_valid(unsigned long addr)
 
 static unsigned long probe_memory_block_size(void)
 {
-       /* start from 2g */
-       unsigned long bz = 1UL<<31;
-
-       if (totalram_pages >= (64ULL << (30 - PAGE_SHIFT))) {
-               pr_info("Using 2GB memory block size for large-memory system\n");
-               return 2UL * 1024 * 1024 * 1024;
-       }
-
-       /* less than 64g installed */
-       if ((max_pfn << PAGE_SHIFT) < (16UL << 32))
-               return MIN_MEMORY_BLOCK_SIZE;
+       unsigned long bz = MIN_MEMORY_BLOCK_SIZE;
 
-       /* get the tail size */
-       while (bz > MIN_MEMORY_BLOCK_SIZE) {
-               if (!((max_pfn << PAGE_SHIFT) & (bz - 1)))
-                       break;
-               bz >>= 1;
-       }
+       /* if system is UV or has 64GB of RAM or more, use large blocks */
+       if (is_uv_system() || ((max_pfn << PAGE_SHIFT) >= (64UL << 30)))
+               bz = 2UL << 30; /* 2GB */
 
-       printk(KERN_DEBUG "memory block size : %ldMB\n", bz >> 20);
+       pr_info("x86/mm: Memory block size: %ldMB\n", bz >> 20);
 
        return bz;
 }
index d470cf219a2d8f4608445b47ee8c3307d9929bd8..1b1110fa00570e0d242926ca8f06adc37db518a5 100644 (file)
@@ -120,11 +120,22 @@ void __init kasan_init(void)
        kasan_populate_zero_shadow(kasan_mem_to_shadow((void *)MODULES_END),
                        (void *)KASAN_SHADOW_END);
 
-       memset(kasan_zero_page, 0, PAGE_SIZE);
-
        load_cr3(init_level4_pgt);
        __flush_tlb_all();
-       init_task.kasan_depth = 0;
 
+       /*
+        * kasan_zero_page has been used as early shadow memory, thus it may
+        * contain some garbage. Now we can clear and write protect it, since
+        * after the TLB flush no one should write to it.
+        */
+       memset(kasan_zero_page, 0, PAGE_SIZE);
+       for (i = 0; i < PTRS_PER_PTE; i++) {
+               pte_t pte = __pte(__pa(kasan_zero_page) | __PAGE_KERNEL_RO);
+               set_pte(&kasan_zero_pte[i], pte);
+       }
+       /* Flush TLBs again to be sure that write protection applied. */
+       __flush_tlb_all();
+
+       init_task.kasan_depth = 0;
        pr_info("KernelAddressSanitizer initialized\n");
 }
index 637ab34ed63284d1045f6031104aac7665be6427..ddb2244b06a1d618679d83a9133f72e8d884b3a2 100644 (file)
@@ -33,7 +33,7 @@
 struct kmmio_fault_page {
        struct list_head list;
        struct kmmio_fault_page *release_next;
-       unsigned long page; /* location of the fault page */
+       unsigned long addr; /* the requested address */
        pteval_t old_presence; /* page presence prior to arming */
        bool armed;
 
@@ -70,9 +70,16 @@ unsigned int kmmio_count;
 static struct list_head kmmio_page_table[KMMIO_PAGE_TABLE_SIZE];
 static LIST_HEAD(kmmio_probes);
 
-static struct list_head *kmmio_page_list(unsigned long page)
+static struct list_head *kmmio_page_list(unsigned long addr)
 {
-       return &kmmio_page_table[hash_long(page, KMMIO_PAGE_HASH_BITS)];
+       unsigned int l;
+       pte_t *pte = lookup_address(addr, &l);
+
+       if (!pte)
+               return NULL;
+       addr &= page_level_mask(l);
+
+       return &kmmio_page_table[hash_long(addr, KMMIO_PAGE_HASH_BITS)];
 }
 
 /* Accessed per-cpu */
@@ -98,15 +105,19 @@ static struct kmmio_probe *get_kmmio_probe(unsigned long addr)
 }
 
 /* You must be holding RCU read lock. */
-static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long page)
+static struct kmmio_fault_page *get_kmmio_fault_page(unsigned long addr)
 {
        struct list_head *head;
        struct kmmio_fault_page *f;
+       unsigned int l;
+       pte_t *pte = lookup_address(addr, &l);
 
-       page &= PAGE_MASK;
-       head = kmmio_page_list(page);
+       if (!pte)
+               return NULL;
+       addr &= page_level_mask(l);
+       head = kmmio_page_list(addr);
        list_for_each_entry_rcu(f, head, list) {
-               if (f->page == page)
+               if (f->addr == addr)
                        return f;
        }
        return NULL;
@@ -137,10 +148,10 @@ static void clear_pte_presence(pte_t *pte, bool clear, pteval_t *old)
 static int clear_page_presence(struct kmmio_fault_page *f, bool clear)
 {
        unsigned int level;
-       pte_t *pte = lookup_address(f->page, &level);
+       pte_t *pte = lookup_address(f->addr, &level);
 
        if (!pte) {
-               pr_err("no pte for page 0x%08lx\n", f->page);
+               pr_err("no pte for addr 0x%08lx\n", f->addr);
                return -1;
        }
 
@@ -156,7 +167,7 @@ static int clear_page_presence(struct kmmio_fault_page *f, bool clear)
                return -1;
        }
 
-       __flush_tlb_one(f->page);
+       __flush_tlb_one(f->addr);
        return 0;
 }
 
@@ -176,12 +187,12 @@ static int arm_kmmio_fault_page(struct kmmio_fault_page *f)
        int ret;
        WARN_ONCE(f->armed, KERN_ERR pr_fmt("kmmio page already armed.\n"));
        if (f->armed) {
-               pr_warning("double-arm: page 0x%08lx, ref %d, old %d\n",
-                          f->page, f->count, !!f->old_presence);
+               pr_warning("double-arm: addr 0x%08lx, ref %d, old %d\n",
+                          f->addr, f->count, !!f->old_presence);
        }
        ret = clear_page_presence(f, true);
-       WARN_ONCE(ret < 0, KERN_ERR pr_fmt("arming 0x%08lx failed.\n"),
-                 f->page);
+       WARN_ONCE(ret < 0, KERN_ERR pr_fmt("arming at 0x%08lx failed.\n"),
+                 f->addr);
        f->armed = true;
        return ret;
 }
@@ -191,7 +202,7 @@ static void disarm_kmmio_fault_page(struct kmmio_fault_page *f)
 {
        int ret = clear_page_presence(f, false);
        WARN_ONCE(ret < 0,
-                       KERN_ERR "kmmio disarming 0x%08lx failed.\n", f->page);
+                       KERN_ERR "kmmio disarming at 0x%08lx failed.\n", f->addr);
        f->armed = false;
 }
 
@@ -215,6 +226,12 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr)
        struct kmmio_context *ctx;
        struct kmmio_fault_page *faultpage;
        int ret = 0; /* default to fault not handled */
+       unsigned long page_base = addr;
+       unsigned int l;
+       pte_t *pte = lookup_address(addr, &l);
+       if (!pte)
+               return -EINVAL;
+       page_base &= page_level_mask(l);
 
        /*
         * Preemption is now disabled to prevent process switch during
@@ -227,7 +244,7 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr)
        preempt_disable();
        rcu_read_lock();
 
-       faultpage = get_kmmio_fault_page(addr);
+       faultpage = get_kmmio_fault_page(page_base);
        if (!faultpage) {
                /*
                 * Either this page fault is not caused by kmmio, or
@@ -239,7 +256,7 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr)
 
        ctx = &get_cpu_var(kmmio_ctx);
        if (ctx->active) {
-               if (addr == ctx->addr) {
+               if (page_base == ctx->addr) {
                        /*
                         * A second fault on the same page means some other
                         * condition needs handling by do_page_fault(), the
@@ -267,9 +284,9 @@ int kmmio_handler(struct pt_regs *regs, unsigned long addr)
        ctx->active++;
 
        ctx->fpage = faultpage;
-       ctx->probe = get_kmmio_probe(addr);
+       ctx->probe = get_kmmio_probe(page_base);
        ctx->saved_flags = (regs->flags & (X86_EFLAGS_TF | X86_EFLAGS_IF));
-       ctx->addr = addr;
+       ctx->addr = page_base;
 
        if (ctx->probe && ctx->probe->pre_handler)
                ctx->probe->pre_handler(ctx->probe, regs, addr);
@@ -354,12 +371,11 @@ out:
 }
 
 /* You must be holding kmmio_lock. */
-static int add_kmmio_fault_page(unsigned long page)
+static int add_kmmio_fault_page(unsigned long addr)
 {
        struct kmmio_fault_page *f;
 
-       page &= PAGE_MASK;
-       f = get_kmmio_fault_page(page);
+       f = get_kmmio_fault_page(addr);
        if (f) {
                if (!f->count)
                        arm_kmmio_fault_page(f);
@@ -372,26 +388,25 @@ static int add_kmmio_fault_page(unsigned long page)
                return -1;
 
        f->count = 1;
-       f->page = page;
+       f->addr = addr;
 
        if (arm_kmmio_fault_page(f)) {
                kfree(f);
                return -1;
        }
 
-       list_add_rcu(&f->list, kmmio_page_list(f->page));
+       list_add_rcu(&f->list, kmmio_page_list(f->addr));
 
        return 0;
 }
 
 /* You must be holding kmmio_lock. */
-static void release_kmmio_fault_page(unsigned long page,
+static void release_kmmio_fault_page(unsigned long addr,
                                struct kmmio_fault_page **release_list)
 {
        struct kmmio_fault_page *f;
 
-       page &= PAGE_MASK;
-       f = get_kmmio_fault_page(page);
+       f = get_kmmio_fault_page(addr);
        if (!f)
                return;
 
@@ -420,18 +435,27 @@ int register_kmmio_probe(struct kmmio_probe *p)
        int ret = 0;
        unsigned long size = 0;
        const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK);
+       unsigned int l;
+       pte_t *pte;
 
        spin_lock_irqsave(&kmmio_lock, flags);
        if (get_kmmio_probe(p->addr)) {
                ret = -EEXIST;
                goto out;
        }
+
+       pte = lookup_address(p->addr, &l);
+       if (!pte) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        kmmio_count++;
        list_add_rcu(&p->list, &kmmio_probes);
        while (size < size_lim) {
                if (add_kmmio_fault_page(p->addr + size))
                        pr_err("Unable to set page fault.\n");
-               size += PAGE_SIZE;
+               size += page_level_size(l);
        }
 out:
        spin_unlock_irqrestore(&kmmio_lock, flags);
@@ -506,11 +530,17 @@ void unregister_kmmio_probe(struct kmmio_probe *p)
        const unsigned long size_lim = p->len + (p->addr & ~PAGE_MASK);
        struct kmmio_fault_page *release_list = NULL;
        struct kmmio_delayed_release *drelease;
+       unsigned int l;
+       pte_t *pte;
+
+       pte = lookup_address(p->addr, &l);
+       if (!pte)
+               return;
 
        spin_lock_irqsave(&kmmio_lock, flags);
        while (size < size_lim) {
                release_kmmio_fault_page(p->addr + size, &release_list);
-               size += PAGE_SIZE;
+               size += page_level_size(l);
        }
        list_del_rcu(&p->list);
        kmmio_count--;
index 96bd1e2bffafb3b8ffbc28906a2998ad992d50e8..d2dc0438d654a8bbcfc71583cea8f49f693afcff 100644 (file)
@@ -71,12 +71,12 @@ unsigned long arch_mmap_rnd(void)
 
        if (mmap_is_ia32())
 #ifdef CONFIG_COMPAT
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_compat_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
 #else
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
 #endif
        else
-               rnd = (unsigned long)get_random_int() & ((1 << mmap_rnd_bits) - 1);
+               rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
 
        return rnd << PAGE_SHIFT;
 }
@@ -93,18 +93,6 @@ static unsigned long mmap_base(unsigned long rnd)
        return PAGE_ALIGN(TASK_SIZE - gap - rnd);
 }
 
-/*
- * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
- * does, but not when emulating X86_32
- */
-static unsigned long mmap_legacy_base(unsigned long rnd)
-{
-       if (mmap_is_ia32())
-               return TASK_UNMAPPED_BASE;
-       else
-               return TASK_UNMAPPED_BASE + rnd;
-}
-
 /*
  * This function, called very early during the creation of a new
  * process VM image, sets up which VM layout function to use:
@@ -116,7 +104,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
        if (current->flags & PF_RANDOMIZE)
                random_factor = arch_mmap_rnd();
 
-       mm->mmap_legacy_base = mmap_legacy_base(random_factor);
+       mm->mmap_legacy_base = TASK_UNMAPPED_BASE + random_factor;
 
        if (mmap_is_legacy()) {
                mm->mmap_base = mm->mmap_legacy_base;
index b2fd67da1701433d9168ebf1d0a908330544bd7d..ef05755a190063cdf79210f7ac164aef1a0f4ec5 100644 (file)
@@ -123,7 +123,7 @@ static int get_reg_offset(struct insn *insn, struct pt_regs *regs,
                break;
        }
 
-       if (regno > nr_registers) {
+       if (regno >= nr_registers) {
                WARN_ONCE(1, "decoded an instruction with an invalid register");
                return -EINVAL;
        }
index d04f8094bc2323bbaa76095ab09efa2e8357cc7e..f70c1ff4612515b310ee59fdb843ae15eb2b2a33 100644 (file)
@@ -465,46 +465,67 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
        return true;
 }
 
+/*
+ * Mark all currently memblock-reserved physical memory (which covers the
+ * kernel's own memory ranges) as hot-unswappable.
+ */
 static void __init numa_clear_kernel_node_hotplug(void)
 {
-       int i, nid;
-       nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
-       phys_addr_t start, end;
-       struct memblock_region *r;
+       nodemask_t reserved_nodemask = NODE_MASK_NONE;
+       struct memblock_region *mb_region;
+       int i;
 
        /*
+        * We have to do some preprocessing of memblock regions, to
+        * make them suitable for reservation.
+        *
         * At this time, all memory regions reserved by memblock are
-        * used by the kernel. Set the nid in memblock.reserved will
-        * mark out all the nodes the kernel resides in.
+        * used by the kernel, but those regions are not split up
+        * along node boundaries yet, and don't necessarily have their
+        * node ID set yet either.
+        *
+        * So iterate over all memory known to the x86 architecture,
+        * and use those ranges to set the nid in memblock.reserved.
+        * This will split up the memblock regions along node
+        * boundaries and will set the node IDs as well.
         */
        for (i = 0; i < numa_meminfo.nr_blks; i++) {
-               struct numa_memblk *mb = &numa_meminfo.blk[i];
+               struct numa_memblk *mb = numa_meminfo.blk + i;
+               int ret;
 
-               memblock_set_node(mb->start, mb->end - mb->start,
-                                 &memblock.reserved, mb->nid);
+               ret = memblock_set_node(mb->start, mb->end - mb->start, &memblock.reserved, mb->nid);
+               WARN_ON_ONCE(ret);
        }
 
        /*
-        * Mark all kernel nodes.
+        * Now go over all reserved memblock regions, to construct a
+        * node mask of all kernel reserved memory areas.
         *
-        * When booting with mem=nn[kMG] or in a kdump kernel, numa_meminfo
-        * may not include all the memblock.reserved memory ranges because
-        * trim_snb_memory() reserves specific pages for Sandy Bridge graphics.
+        * [ Note, when booting with mem=nn[kMG] or in a kdump kernel,
+        *   numa_meminfo might not include all memblock.reserved
+        *   memory ranges, because quirks such as trim_snb_memory()
+        *   reserve specific pages for Sandy Bridge graphics. ]
         */
-       for_each_memblock(reserved, r)
-               if (r->nid != MAX_NUMNODES)
-                       node_set(r->nid, numa_kernel_nodes);
+       for_each_memblock(reserved, mb_region) {
+               if (mb_region->nid != MAX_NUMNODES)
+                       node_set(mb_region->nid, reserved_nodemask);
+       }
 
-       /* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
+       /*
+        * Finally, clear the MEMBLOCK_HOTPLUG flag for all memory
+        * belonging to the reserved node mask.
+        *
+        * Note that this will include memory regions that reside
+        * on nodes that contain kernel memory - entire nodes
+        * become hot-unpluggable:
+        */
        for (i = 0; i < numa_meminfo.nr_blks; i++) {
-               nid = numa_meminfo.blk[i].nid;
-               if (!node_isset(nid, numa_kernel_nodes))
-                       continue;
+               struct numa_memblk *mb = numa_meminfo.blk + i;
 
-               start = numa_meminfo.blk[i].start;
-               end = numa_meminfo.blk[i].end;
+               if (!node_isset(mb->nid, reserved_nodemask))
+                       continue;
 
-               memblock_clear_hotplug(start, end - start);
+               memblock_clear_hotplug(mb->start, mb->end - mb->start);
        }
 }
 
index 2440814b00699e33809ce061d6f86a48437f7a10..4d0b26253042d525107106f8e230535c65f25ca8 100644 (file)
@@ -106,12 +106,6 @@ static inline unsigned long highmap_end_pfn(void)
 
 #endif
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
-# define debug_pagealloc 1
-#else
-# define debug_pagealloc 0
-#endif
-
 static inline int
 within(unsigned long addr, unsigned long start, unsigned long end)
 {
@@ -283,7 +277,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
                   __pa_symbol(__end_rodata) >> PAGE_SHIFT))
                pgprot_val(forbidden) |= _PAGE_RW;
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA)
+#if defined(CONFIG_X86_64)
        /*
         * Once the kernel maps the text as RO (kernel_set_to_readonly is set),
         * kernel text mappings for the large page aligned text, rodata sections
@@ -419,24 +413,30 @@ pmd_t *lookup_pmd_address(unsigned long address)
 phys_addr_t slow_virt_to_phys(void *__virt_addr)
 {
        unsigned long virt_addr = (unsigned long)__virt_addr;
-       unsigned long phys_addr, offset;
+       phys_addr_t phys_addr;
+       unsigned long offset;
        enum pg_level level;
        pte_t *pte;
 
        pte = lookup_address(virt_addr, &level);
        BUG_ON(!pte);
 
+       /*
+        * pXX_pfn() returns unsigned long, which must be cast to phys_addr_t
+        * before being left-shifted PAGE_SHIFT bits -- this trick is to
+        * make 32-PAE kernel work correctly.
+        */
        switch (level) {
        case PG_LEVEL_1G:
-               phys_addr = pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
+               phys_addr = (phys_addr_t)pud_pfn(*(pud_t *)pte) << PAGE_SHIFT;
                offset = virt_addr & ~PUD_PAGE_MASK;
                break;
        case PG_LEVEL_2M:
-               phys_addr = pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
+               phys_addr = (phys_addr_t)pmd_pfn(*(pmd_t *)pte) << PAGE_SHIFT;
                offset = virt_addr & ~PMD_PAGE_MASK;
                break;
        default:
-               phys_addr = pte_pfn(*pte) << PAGE_SHIFT;
+               phys_addr = (phys_addr_t)pte_pfn(*pte) << PAGE_SHIFT;
                offset = virt_addr & ~PAGE_MASK;
        }
 
@@ -708,10 +708,10 @@ static int split_large_page(struct cpa_data *cpa, pte_t *kpte,
 {
        struct page *base;
 
-       if (!debug_pagealloc)
+       if (!debug_pagealloc_enabled())
                spin_unlock(&cpa_lock);
        base = alloc_pages(GFP_KERNEL | __GFP_NOTRACK, 0);
-       if (!debug_pagealloc)
+       if (!debug_pagealloc_enabled())
                spin_lock(&cpa_lock);
        if (!base)
                return -ENOMEM;
@@ -1122,8 +1122,10 @@ static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
        /*
         * Ignore all non primary paths.
         */
-       if (!primary)
+       if (!primary) {
+               cpa->numpages = 1;
                return 0;
+       }
 
        /*
         * Ignore the NULL PTE for kernel identity mapping, as it is expected
@@ -1331,10 +1333,10 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
                if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY))
                        cpa->numpages = 1;
 
-               if (!debug_pagealloc)
+               if (!debug_pagealloc_enabled())
                        spin_lock(&cpa_lock);
                ret = __change_page_attr(cpa, checkalias);
-               if (!debug_pagealloc)
+               if (!debug_pagealloc_enabled())
                        spin_unlock(&cpa_lock);
                if (ret)
                        return ret;
index f4ae536b0914db1db521feabe09ae0ab681a4b87..04e2e7144beee51205df17a4e3df024833eac7db 100644 (file)
@@ -943,7 +943,7 @@ int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
                        return -EINVAL;
        }
 
-       *prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
+       *prot = __pgprot((pgprot_val(*prot) & (~_PAGE_CACHE_MASK)) |
                         cachemode2protval(pcm));
 
        return 0;
@@ -959,7 +959,7 @@ int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
 
        /* Set prot based on lookup */
        pcm = lookup_memtype(pfn_t_to_phys(pfn));
-       *prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
+       *prot = __pgprot((pgprot_val(*prot) & (~_PAGE_CACHE_MASK)) |
                         cachemode2protval(pcm));
 
        return 0;
index 92e2eacb33216821e8b18821834c7ce972571f29..8bea84724a7da4bd1c6d3a0509166618c39e5349 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/proto.h>
+#include <asm/cpufeature.h>
 
 static int disable_nx;
 
@@ -31,9 +32,8 @@ early_param("noexec", noexec_setup);
 
 void x86_configure_nx(void)
 {
-       if (boot_cpu_has(X86_FEATURE_NX) && !disable_nx)
-               __supported_pte_mask |= _PAGE_NX;
-       else
+       /* If disable_nx is set, clear NX on all new mappings going forward. */
+       if (disable_nx)
                __supported_pte_mask &= ~_PAGE_NX;
 }
 
index 50d86c0e9ba4973b707de5917cfae78692fd6f68..660a83c8287b61dc52c069832128a83f256258af 100644 (file)
@@ -24,7 +24,6 @@
 #include <asm/nmi.h>
 #include <asm/apic.h>
 #include <asm/processor.h>
-#include <asm/cpufeature.h>
 
 #include "op_x86_model.h"
 #include "op_counter.h"
index 2879efc73a967bca70606547014decd3703c84bf..381a43c40bf7671e9dcbe33e402ef7efb4ff5505 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/dmi.h>
 #include <linux/slab.h>
 
-#include <asm-generic/pci-bridge.h>
 #include <asm/acpi.h>
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -711,28 +710,22 @@ int pcibios_add_device(struct pci_dev *dev)
        return 0;
 }
 
-int pcibios_alloc_irq(struct pci_dev *dev)
+int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-       /*
-        * If the PCI device was already claimed by core code and has
-        * MSI enabled, probing of the pcibios IRQ will overwrite
-        * dev->irq.  So bail out if MSI is already enabled.
-        */
-       if (pci_dev_msi_enabled(dev))
-               return -EBUSY;
+       int err;
 
-       return pcibios_enable_irq(dev);
-}
+       if ((err = pci_enable_resources(dev, mask)) < 0)
+               return err;
 
-void pcibios_free_irq(struct pci_dev *dev)
-{
-       if (pcibios_disable_irq)
-               pcibios_disable_irq(dev);
+       if (!pci_dev_msi_enabled(dev))
+               return pcibios_enable_irq(dev);
+       return 0;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
+void pcibios_disable_device (struct pci_dev *dev)
 {
-       return pci_enable_resources(dev, mask);
+       if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
+               pcibios_disable_irq(dev);
 }
 
 int pci_ext_cfg_avail(void)
index e58565556703bfc781e29f4e387cbd0e2ea1ced8..b7de1929714b7136415a6361cc6c1f3c86058bbd 100644 (file)
@@ -297,14 +297,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,      PCI_DEVICE_ID_INTEL_MCH_PC1,    pcie_r
  *
  * The standard boot ROM sequence for an x86 machine uses the BIOS
  * to select an initial video card for boot display. This boot video
- * card will have it's BIOS copied to C0000 in system RAM.
+ * card will have its BIOS copied to 0xC0000 in system RAM.
  * IORESOURCE_ROM_SHADOW is used to associate the boot video
  * card with this copy. On laptops this copy has to be used since
  * the main ROM may be compressed or combined with another image.
  * See pci_map_rom() for use of this flag. Before marking the device
  * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set
- * by either arch cde or vga-arbitration, if so only apply the fixup to this
- * already determined primary video card.
+ * by either arch code or vga-arbitration; if so only apply the fixup to this
+ * already-determined primary video card.
  */
 
 static void pci_fixup_video(struct pci_dev *pdev)
@@ -312,6 +312,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
        struct pci_dev *bridge;
        struct pci_bus *bus;
        u16 config;
+       struct resource *res;
 
        /* Is VGA routed to us? */
        bus = pdev->bus;
@@ -336,8 +337,18 @@ static void pci_fixup_video(struct pci_dev *pdev)
        if (!vga_default_device() || pdev == vga_default_device()) {
                pci_read_config_word(pdev, PCI_COMMAND, &config);
                if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
-                       pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
-                       dev_printk(KERN_DEBUG, &pdev->dev, "Video device with shadowed ROM\n");
+                       res = &pdev->resource[PCI_ROM_RESOURCE];
+
+                       pci_disable_rom(pdev);
+                       if (res->parent)
+                               release_resource(res);
+
+                       res->start = 0xC0000;
+                       res->end = res->start + 0x20000 - 1;
+                       res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW |
+                                    IORESOURCE_PCI_FIXED;
+                       dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n",
+                                res);
                }
        }
 }
@@ -540,3 +551,10 @@ static void twinhead_reserve_killing_zone(struct pci_dev *dev)
         }
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
+
+static void pci_bdwep_bar(struct pci_dev *dev)
+{
+       dev->non_compliant_bars = 1;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar);
index 0d24e7c101454057f432dd976ea7e3d537e0a38c..8b93e634af84c4698e6f7c6ab718a018e2cdc9db 100644 (file)
@@ -215,7 +215,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
        int polarity;
        int ret;
 
-       if (pci_has_managed_irq(dev))
+       if (dev->irq_managed && dev->irq > 0)
                return 0;
 
        switch (intel_mid_identify_cpu()) {
@@ -256,13 +256,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-       if (pci_has_managed_irq(dev)) {
+       if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
+           dev->irq > 0) {
                mp_unmap_irq(dev->irq);
                dev->irq_managed = 0;
-               /*
-                * Don't reset dev->irq here, otherwise
-                * intel_mid_pci_irq_enable() will fail on next call.
-                */
        }
 }
 
index 32e70343e6fdd0e58ab80644284dd01000dccd82..9bd115484745703791c6515b289938546d2478ab 100644 (file)
@@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        struct pci_dev *temp_dev;
                        int irq;
 
-                       if (pci_has_managed_irq(dev))
+                       if (dev->irq_managed && dev->irq > 0)
                                return 0;
 
                        irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
@@ -1230,7 +1230,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        }
                        dev = temp_dev;
                        if (irq >= 0) {
-                               pci_set_managed_irq(dev, irq);
+                               dev->irq_managed = 1;
+                               dev->irq = irq;
                                dev_info(&dev->dev, "PCI->APIC IRQ transform: "
                                         "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
                                return 0;
@@ -1256,10 +1257,24 @@ static int pirq_enable_irq(struct pci_dev *dev)
        return 0;
 }
 
+bool mp_should_keep_irq(struct device *dev)
+{
+       if (dev->power.is_prepared)
+               return true;
+#ifdef CONFIG_PM
+       if (dev->power.runtime_status == RPM_SUSPENDING)
+               return true;
+#endif
+
+       return false;
+}
+
 static void pirq_disable_irq(struct pci_dev *dev)
 {
-       if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) {
+       if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
+           dev->irq_managed && dev->irq) {
                mp_unmap_irq(dev->irq);
-               pci_reset_managed_irq(dev);
+               dev->irq = 0;
+               dev->irq_managed = 0;
        }
 }
index d57e48016f1578d8e1b04e22d0a30967faaf4e6e..7792aba266df695a6d6aca686c95fbbbc733fa57 100644 (file)
@@ -503,6 +503,18 @@ static struct pci_ops vmd_ops = {
        .write          = vmd_pci_write,
 };
 
+static void vmd_attach_resources(struct vmd_dev *vmd)
+{
+       vmd->dev->resource[VMD_MEMBAR1].child = &vmd->resources[1];
+       vmd->dev->resource[VMD_MEMBAR2].child = &vmd->resources[2];
+}
+
+static void vmd_detach_resources(struct vmd_dev *vmd)
+{
+       vmd->dev->resource[VMD_MEMBAR1].child = NULL;
+       vmd->dev->resource[VMD_MEMBAR2].child = NULL;
+}
+
 /*
  * VMD domains start at 0x1000 to not clash with ACPI _SEG domains.
  */
@@ -527,11 +539,28 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
        res = &vmd->dev->resource[VMD_CFGBAR];
        vmd->resources[0] = (struct resource) {
                .name  = "VMD CFGBAR",
-               .start = res->start,
+               .start = 0,
                .end   = (resource_size(res) >> 20) - 1,
                .flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED,
        };
 
+       /*
+        * If the window is below 4GB, clear IORESOURCE_MEM_64 so we can
+        * put 32-bit resources in the window.
+        *
+        * There's no hardware reason why a 64-bit window *couldn't*
+        * contain a 32-bit resource, but pbus_size_mem() computes the
+        * bridge window size assuming a 64-bit window will contain no
+        * 32-bit resources.  __pci_assign_resource() enforces that
+        * artificial restriction to make sure everything will fit.
+        *
+        * The only way we could use a 64-bit non-prefechable MEMBAR is
+        * if its address is <4GB so that we can convert it to a 32-bit
+        * resource.  To be visible to the host OS, all VMD endpoints must
+        * be initially configured by platform BIOS, which includes setting
+        * up these resources.  We can assume the device is configured
+        * according to the platform needs.
+        */
        res = &vmd->dev->resource[VMD_MEMBAR1];
        upper_bits = upper_32_bits(res->end);
        flags = res->flags & ~IORESOURCE_SIZEALIGN;
@@ -542,6 +571,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
                .start = res->start,
                .end   = res->end,
                .flags = flags,
+               .parent = res,
        };
 
        res = &vmd->dev->resource[VMD_MEMBAR2];
@@ -554,6 +584,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
                .start = res->start + 0x2000,
                .end   = res->end,
                .flags = flags,
+               .parent = res,
        };
 
        sd->domain = vmd_find_free_domain();
@@ -578,6 +609,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
                return -ENODEV;
        }
 
+       vmd_attach_resources(vmd);
        vmd_setup_dma_ops(vmd);
        dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain);
        pci_rescan_bus(vmd->bus);
@@ -674,6 +706,7 @@ static void vmd_remove(struct pci_dev *dev)
 {
        struct vmd_dev *vmd = pci_get_drvdata(dev);
 
+       vmd_detach_resources(vmd);
        pci_set_drvdata(dev, NULL);
        sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
        pci_stop_root_bus(vmd->bus);
index 2d66db8f80f992d3b0609373502031aacf91f161..ed30e79347e86377198009dcafb1c0b26a9865df 100644 (file)
@@ -130,6 +130,27 @@ efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
 }
 EXPORT_SYMBOL_GPL(efi_query_variable_store);
 
+/*
+ * Helper function for efi_reserve_boot_services() to figure out if we
+ * can free regions in efi_free_boot_services().
+ *
+ * Use this function to ensure we do not free regions owned by somebody
+ * else. We must only reserve (and then free) regions:
+ *
+ * - Not within any part of the kernel
+ * - Not the BIOS reserved area (E820_RESERVED, E820_NVS, etc)
+ */
+static bool can_free_region(u64 start, u64 size)
+{
+       if (start + size > __pa_symbol(_text) && start <= __pa_symbol(_end))
+               return false;
+
+       if (!e820_all_mapped(start, start+size, E820_RAM))
+               return false;
+
+       return true;
+}
+
 /*
  * The UEFI specification makes it clear that the operating system is free to do
  * whatever it wants with boot services code after ExitBootServices() has been
@@ -147,26 +168,50 @@ void __init efi_reserve_boot_services(void)
                efi_memory_desc_t *md = p;
                u64 start = md->phys_addr;
                u64 size = md->num_pages << EFI_PAGE_SHIFT;
+               bool already_reserved;
 
                if (md->type != EFI_BOOT_SERVICES_CODE &&
                    md->type != EFI_BOOT_SERVICES_DATA)
                        continue;
-               /* Only reserve where possible:
-                * - Not within any already allocated areas
-                * - Not over any memory area (really needed, if above?)
-                * - Not within any part of the kernel
-                * - Not the bios reserved area
-               */
-               if ((start + size > __pa_symbol(_text)
-                               && start <= __pa_symbol(_end)) ||
-                       !e820_all_mapped(start, start+size, E820_RAM) ||
-                       memblock_is_region_reserved(start, size)) {
-                       /* Could not reserve, skip it */
-                       md->num_pages = 0;
-                       memblock_dbg("Could not reserve boot range [0x%010llx-0x%010llx]\n",
-                                    start, start+size-1);
-               } else
+
+               already_reserved = memblock_is_region_reserved(start, size);
+
+               /*
+                * Because the following memblock_reserve() is paired
+                * with free_bootmem_late() for this region in
+                * efi_free_boot_services(), we must be extremely
+                * careful not to reserve, and subsequently free,
+                * critical regions of memory (like the kernel image) or
+                * those regions that somebody else has already
+                * reserved.
+                *
+                * A good example of a critical region that must not be
+                * freed is page zero (first 4Kb of memory), which may
+                * contain boot services code/data but is marked
+                * E820_RESERVED by trim_bios_range().
+                */
+               if (!already_reserved) {
                        memblock_reserve(start, size);
+
+                       /*
+                        * If we are the first to reserve the region, no
+                        * one else cares about it. We own it and can
+                        * free it later.
+                        */
+                       if (can_free_region(start, size))
+                               continue;
+               }
+
+               /*
+                * We don't own the region. We must not free it.
+                *
+                * Setting this bit for a boot services region really
+                * doesn't make sense as far as the firmware is
+                * concerned, but it does provide us with a way to tag
+                * those regions that must not be paired with
+                * free_bootmem_late().
+                */
+               md->attribute |= EFI_MEMORY_RUNTIME;
        }
 }
 
@@ -183,8 +228,8 @@ void __init efi_free_boot_services(void)
                    md->type != EFI_BOOT_SERVICES_DATA)
                        continue;
 
-               /* Could not reserve boot area */
-               if (!size)
+               /* Do not free, someone else owns it: */
+               if (md->attribute & EFI_MEMORY_RUNTIME)
                        continue;
 
                free_bootmem_late(start, size);
index 76b6632d3143352a8161e64721a1a10af884c0bf..1865c196f13632a317fadcbff4134684c841af5d 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/string.h>
-#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #define BIOS_SIGNATURE_COREBOOT                0x500
 #define BIOS_REGION_SIZE               0x10000
 
+/*
+ * This driver is not modular, but to keep back compatibility
+ * with existing use cases, continuing with module_param is
+ * the easiest way forward.
+ */
 static bool force = 0;
 module_param(force, bool, 0444);
 /* FIXME: Award bios is not automatically detected as Alix platform */
@@ -192,9 +197,4 @@ static int __init alix_init(void)
 
        return 0;
 }
-
-module_init(alix_init);
-
-MODULE_AUTHOR("Ed Wildgoose <kernel@wildgooses.com>");
-MODULE_DESCRIPTION("PCEngines ALIX System Setup");
-MODULE_LICENSE("GPL");
+device_initcall(alix_init);
index aa733fba2471247cd838c86a2ca39de28d997996..4fcdb91318a08d6e5498cd797f9fb84dc325edeb 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/string.h>
-#include <linux/module.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
@@ -120,9 +119,4 @@ static int __init geos_init(void)
 
        return 0;
 }
-
-module_init(geos_init);
-
-MODULE_AUTHOR("Philip Prindeville <philipp@redfish-solutions.com>");
-MODULE_DESCRIPTION("Traverse Technologies Geos System Setup");
-MODULE_LICENSE("GPL");
+device_initcall(geos_init);
index 927e38c0089fac8947de59eab9a0b029d122b696..a2f6b982a7295b634fefdbec303ad37280caeaa6 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/string.h>
-#include <linux/module.h>
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
@@ -146,9 +145,4 @@ static int __init net5501_init(void)
 
        return 0;
 }
-
-module_init(net5501_init);
-
-MODULE_AUTHOR("Philip Prindeville <philipp@redfish-solutions.com>");
-MODULE_DESCRIPTION("Soekris net5501 System Setup");
-MODULE_LICENSE("GPL");
+device_initcall(net5501_init);
index 23381d2174ae1d4d2795ebf9a568ff7e43cf8876..1eb47b6298c20fc20ae6de0c2f9f3762854286cc 100644 (file)
@@ -52,10 +52,7 @@ static unsigned long __init mfld_calibrate_tsc(void)
        /* mark tsc clocksource as reliable */
        set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
 
-       if (fast_calibrate)
-               return fast_calibrate;
-
-       return 0;
+       return fast_calibrate;
 }
 
 static void __init penwell_arch_setup(void)
index aaca91753d3267b94a98af40f7b66f8b5cbbb21c..bd1adc621781117b8044e555509239ee4328247f 100644 (file)
@@ -81,10 +81,7 @@ static unsigned long __init tangier_calibrate_tsc(void)
        /* mark tsc clocksource as reliable */
        set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
 
-       if (fast_calibrate)
-               return fast_calibrate;
-
-       return 0;
+       return fast_calibrate;
 }
 
 static void __init tangier_arch_setup(void)
index c61b6c332e971929fd4d639b9754e8707f513930..17d6d2296e4d8d0b51745b57a10b9256358a7cff 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * imr.c
+ * imr.c -- Intel Isolated Memory Region driver
  *
  * Copyright(c) 2013 Intel Corporation.
  * Copyright(c) 2015 Bryan O'Donoghue <pure.logic@nexus-software.ie>
@@ -31,7 +31,6 @@
 #include <linux/debugfs.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/types.h>
 
 struct imr_device {
@@ -135,11 +134,9 @@ static int imr_read(struct imr_device *idev, u32 imr_id, struct imr_regs *imr)
  * @idev:      pointer to imr_device structure.
  * @imr_id:    IMR entry to write.
  * @imr:       IMR structure representing address and access masks.
- * @lock:      indicates if the IMR lock bit should be applied.
  * @return:    0 on success or error code passed from mbi_iosf on failure.
  */
-static int imr_write(struct imr_device *idev, u32 imr_id,
-                    struct imr_regs *imr, bool lock)
+static int imr_write(struct imr_device *idev, u32 imr_id, struct imr_regs *imr)
 {
        unsigned long flags;
        u32 reg = imr_id * IMR_NUM_REGS + idev->reg_base;
@@ -163,15 +160,6 @@ static int imr_write(struct imr_device *idev, u32 imr_id,
        if (ret)
                goto failed;
 
-       /* Lock bit must be set separately to addr_lo address bits. */
-       if (lock) {
-               imr->addr_lo |= IMR_LOCK;
-               ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE,
-                                    reg - IMR_NUM_REGS, imr->addr_lo);
-               if (ret)
-                       goto failed;
-       }
-
        local_irq_restore(flags);
        return 0;
 failed:
@@ -269,17 +257,6 @@ static int imr_debugfs_register(struct imr_device *idev)
        return PTR_ERR_OR_ZERO(idev->file);
 }
 
-/**
- * imr_debugfs_unregister - unregister debugfs hooks.
- *
- * @idev:      pointer to imr_device structure.
- * @return:
- */
-static void imr_debugfs_unregister(struct imr_device *idev)
-{
-       debugfs_remove(idev->file);
-}
-
 /**
  * imr_check_params - check passed address range IMR alignment and non-zero size
  *
@@ -334,11 +311,10 @@ static inline int imr_address_overlap(phys_addr_t addr, struct imr_regs *imr)
  * @size:      physical size of region in bytes must be aligned to 1KiB.
  * @read_mask: read access mask.
  * @write_mask:        write access mask.
- * @lock:      indicates whether or not to permanently lock this region.
  * @return:    zero on success or negative value indicating error.
  */
 int imr_add_range(phys_addr_t base, size_t size,
-                 unsigned int rmask, unsigned int wmask, bool lock)
+                 unsigned int rmask, unsigned int wmask)
 {
        phys_addr_t end;
        unsigned int i;
@@ -411,7 +387,7 @@ int imr_add_range(phys_addr_t base, size_t size,
        imr.rmask = rmask;
        imr.wmask = wmask;
 
-       ret = imr_write(idev, reg, &imr, lock);
+       ret = imr_write(idev, reg, &imr);
        if (ret < 0) {
                /*
                 * In the highly unlikely event iosf_mbi_write failed
@@ -422,7 +398,7 @@ int imr_add_range(phys_addr_t base, size_t size,
                imr.addr_hi = 0;
                imr.rmask = IMR_READ_ACCESS_ALL;
                imr.wmask = IMR_WRITE_ACCESS_ALL;
-               imr_write(idev, reg, &imr, false);
+               imr_write(idev, reg, &imr);
        }
 failed:
        mutex_unlock(&idev->lock);
@@ -518,7 +494,7 @@ static int __imr_remove_range(int reg, phys_addr_t base, size_t size)
        imr.rmask = IMR_READ_ACCESS_ALL;
        imr.wmask = IMR_WRITE_ACCESS_ALL;
 
-       ret = imr_write(idev, reg, &imr, false);
+       ret = imr_write(idev, reg, &imr);
 
 failed:
        mutex_unlock(&idev->lock);
@@ -592,14 +568,14 @@ static void __init imr_fixup_memmap(struct imr_device *idev)
        end = (unsigned long)__end_rodata - 1;
 
        /*
-        * Setup a locked IMR around the physical extent of the kernel
+        * Setup an unlocked IMR around the physical extent of the kernel
         * from the beginning of the .text secton to the end of the
         * .rodata section as one physically contiguous block.
         *
         * We don't round up @size since it is already PAGE_SIZE aligned.
         * See vmlinux.lds.S for details.
         */
-       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, true);
+       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);
        if (ret < 0) {
                pr_err("unable to setup IMR for kernel: %zu KiB (%lx - %lx)\n",
                        size / 1024, start, end);
@@ -614,7 +590,6 @@ static const struct x86_cpu_id imr_ids[] __initconst = {
        { X86_VENDOR_INTEL, 5, 9 },     /* Intel Quark SoC X1000. */
        {}
 };
-MODULE_DEVICE_TABLE(x86cpu, imr_ids);
 
 /**
  * imr_init - entry point for IMR driver.
@@ -640,22 +615,4 @@ static int __init imr_init(void)
        imr_fixup_memmap(idev);
        return 0;
 }
-
-/**
- * imr_exit - exit point for IMR code.
- *
- * Deregisters debugfs, leave IMR state as-is.
- *
- * return:
- */
-static void __exit imr_exit(void)
-{
-       imr_debugfs_unregister(&imr_dev);
-}
-
-module_init(imr_init);
-module_exit(imr_exit);
-
-MODULE_AUTHOR("Bryan O'Donoghue <pure.logic@nexus-software.ie>");
-MODULE_DESCRIPTION("Intel Isolated Memory Region driver");
-MODULE_LICENSE("Dual BSD/GPL");
+device_initcall(imr_init);
index 278e4da4222f79cf82aa2f8dcbe0e371243fb836..f5bad40936ac5bc7a4b47a868fb07121963fe2be 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * imr_selftest.c
+ * imr_selftest.c -- Intel Isolated Memory Region self-test driver
  *
  * Copyright(c) 2013 Intel Corporation.
  * Copyright(c) 2015 Bryan O'Donoghue <pure.logic@nexus-software.ie>
@@ -15,7 +15,6 @@
 #include <asm/imr.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/module.h>
 #include <linux/types.h>
 
 #define SELFTEST KBUILD_MODNAME ": "
@@ -61,30 +60,30 @@ static void __init imr_self_test(void)
        int ret;
 
        /* Test zero zero. */
-       ret = imr_add_range(0, 0, 0, 0, false);
+       ret = imr_add_range(0, 0, 0, 0);
        imr_self_test_result(ret < 0, "zero sized IMR\n");
 
        /* Test exact overlap. */
-       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false);
+       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);
        imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
 
        /* Test overlap with base inside of existing. */
        base += size - IMR_ALIGN;
-       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false);
+       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);
        imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
 
        /* Test overlap with end inside of existing. */
        base -= size + IMR_ALIGN * 2;
-       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU, false);
+       ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);
        imr_self_test_result(ret < 0, fmt_over, __va(base), __va(base + size));
 
        /* Test that a 1 KiB IMR @ zero with read/write all will bomb out. */
        ret = imr_add_range(0, IMR_ALIGN, IMR_READ_ACCESS_ALL,
-                           IMR_WRITE_ACCESS_ALL, false);
+                           IMR_WRITE_ACCESS_ALL);
        imr_self_test_result(ret < 0, "1KiB IMR @ 0x00000000 - access-all\n");
 
        /* Test that a 1 KiB IMR @ zero with CPU only will work. */
-       ret = imr_add_range(0, IMR_ALIGN, IMR_CPU, IMR_CPU, false);
+       ret = imr_add_range(0, IMR_ALIGN, IMR_CPU, IMR_CPU);
        imr_self_test_result(ret >= 0, "1KiB IMR @ 0x00000000 - cpu-access\n");
        if (ret >= 0) {
                ret = imr_remove_range(0, IMR_ALIGN);
@@ -93,8 +92,7 @@ static void __init imr_self_test(void)
 
        /* Test 2 KiB works. */
        size = IMR_ALIGN * 2;
-       ret = imr_add_range(0, size, IMR_READ_ACCESS_ALL,
-                           IMR_WRITE_ACCESS_ALL, false);
+       ret = imr_add_range(0, size, IMR_READ_ACCESS_ALL, IMR_WRITE_ACCESS_ALL);
        imr_self_test_result(ret >= 0, "2KiB IMR @ 0x00000000\n");
        if (ret >= 0) {
                ret = imr_remove_range(0, size);
@@ -106,7 +104,6 @@ static const struct x86_cpu_id imr_ids[] __initconst = {
        { X86_VENDOR_INTEL, 5, 9 },     /* Intel Quark SoC X1000. */
        {}
 };
-MODULE_DEVICE_TABLE(x86cpu, imr_ids);
 
 /**
  * imr_self_test_init - entry point for IMR driver.
@@ -125,13 +122,4 @@ static int __init imr_self_test_init(void)
  *
  * return:
  */
-static void __exit imr_self_test_exit(void)
-{
-}
-
-module_init(imr_self_test_init);
-module_exit(imr_self_test_exit);
-
-MODULE_AUTHOR("Bryan O'Donoghue <pure.logic@nexus-software.ie>");
-MODULE_DESCRIPTION("Intel Isolated Memory Region self-test driver");
-MODULE_LICENSE("Dual BSD/GPL");
+device_initcall(imr_self_test_init);
index 174781a404ff3cfbeb1f9dccaef820f7aa2e9a51..00c319048d52d78e58755f7da2639aa044e0b885 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <asm/asm.h>
 #include <asm/segment.h>
-#include <asm/cpufeature.h>
+#include <asm/cpufeatures.h>
 #include <asm/cmpxchg.h>
 #include <asm/nops.h>
 
index 8502ad30e61bcfc49a9e28c975d356b4b628a62c..5adb6a2fd117df01c232156e2091bfc3d190eac7 100644 (file)
@@ -109,7 +109,7 @@ unsigned long os_get_top_address(void)
                exit(1);
        }
 
-       printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT);
+       printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT);
        printf("Locating the top of the address space ... ");
        fflush(stdout);
 
@@ -134,7 +134,7 @@ out:
                exit(1);
        }
        top <<= UM_KERN_PAGE_SHIFT;
-       printf("0x%x\n", top);
+       printf("0x%lx\n", top);
 
        return top;
 }
index 439c0994b69689ade4fa49c6a9ead46e25597880..bfce503dffae23bb0b39c621f5d8c2e0d936fec5 100644 (file)
 
 #define old_mmap sys_old_mmap
 
-#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
+#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
 #include <asm/syscalls_32.h>
 
 #undef __SYSCALL_I386
-#define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym,
+#define __SYSCALL_I386(nr, sym, qual) [ nr ] = sym,
 
 extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 
index b74ea6c2c0e7b2fdb43d2f60231edc8c994333c6..f306413d3eb6e332d5ad10db63700101cafd40f0 100644 (file)
 #define stub_execveat sys_execveat
 #define stub_rt_sigreturn sys_rt_sigreturn
 
-#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat)
-#define __SYSCALL_X32(nr, sym, compat) /* Not supported */
-
-#define __SYSCALL_64(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
+#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ;
 #include <asm/syscalls_64.h>
 
 #undef __SYSCALL_64
-#define __SYSCALL_64(nr, sym, compat) [ nr ] = sym,
+#define __SYSCALL_64(nr, sym, qual) [ nr ] = sym,
 
 extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 
index ce7e3607a870feac770b277970b74099c3049208..470564bbd08ea16359e32ab8a275a80f40bcfbda 100644 (file)
@@ -9,14 +9,12 @@
 #include <asm/types.h>
 
 #ifdef __i386__
-#define __SYSCALL_I386(nr, sym, compat) [nr] = 1,
+#define __SYSCALL_I386(nr, sym, qual) [nr] = 1,
 static char syscalls[] = {
 #include <asm/syscalls_32.h>
 };
 #else
-#define __SYSCALL_64(nr, sym, compat) [nr] = 1,
-#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1,
-#define __SYSCALL_X32(nr, sym, compat) /* Not supported */
+#define __SYSCALL_64(nr, sym, qual) [nr] = 1,
 static char syscalls[] = {
 #include <asm/syscalls_64.h>
 };
index d09e4c9d7cc5b4044c4421bde8692aaa6f8b21be..2c261082eadf82f693d062e7f600660fcd56817f 100644 (file)
@@ -1654,7 +1654,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
        cpu_detect(&new_cpu_data);
        set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU);
        new_cpu_data.wp_works_ok = 1;
-       new_cpu_data.x86_capability[0] = cpuid_edx(1);
+       new_cpu_data.x86_capability[CPUID_1_EDX] = cpuid_edx(1);
 #endif
 
        if (xen_start_info->mod_start) {
index 724a08740a04b4a255ca080c103ec3b7381bc4f7..9466354d3e4962f14cdae33b09378a73f9c51a5d 100644 (file)
@@ -11,7 +11,7 @@
 #include "pmu.h"
 
 /* x86_pmu.handle_irq definition */
-#include "../kernel/cpu/perf_event.h"
+#include "../events/perf_event.h"
 
 #define XENPMU_IRQ_PROCESSING    1
 struct xenpmu {
index 3f4ebf0261f28620a96cdd1cd6366c311c6761b5..3c6d17fd423a82006d89c71e7345bb6a566aec09 100644 (file)
@@ -112,7 +112,7 @@ asmlinkage __visible void cpu_bringup_and_idle(int cpu)
                xen_pvh_secondary_vcpu_init(cpu);
 #endif
        cpu_bringup();
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 static void xen_smp_intr_free(unsigned int cpu)
index e9df1567d778e2f87ecdb1a64df1c2dfeb874071..7e9464b0fc00bb3de3267d3e707647f760c852c5 100644 (file)
@@ -413,8 +413,6 @@ config FORCE_MAX_ZONEORDER
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 config PLATFORM_WANT_DEFAULT_MEM
        def_bool n
 
index e438a00fbd6399117b7e525b6874508f9e298ec9..5d6bd932ba4e37eaf1ea19581b3e3a6320ee1099 100644 (file)
@@ -55,9 +55,6 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
 
 #endif /* __KERNEL__ */
 
-/* Implement the pci_ DMA API in terms of the generic device dma_ one */
-#include <asm-generic/pci-dma-compat.h>
-
 /* Generic PCI */
 #include <asm-generic/pci.h>
 
index 4d02e38514f5460cc9c3a65d7b4d390be1c9e3aa..fc4ad21a5ed44f9b170d9587c0934e581f75cd01 100644 (file)
@@ -157,7 +157,7 @@ void secondary_start_kernel(void)
 
        complete(&cpu_running);
 
-       cpu_startup_entry(CPUHP_ONLINE);
+       cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
 static void mx_cpu_start(void *p)
index 161491d0a879ed11ce2276a1923a60bc1d92479e..0363cd731320d8d9d93cdcd8e3fb5351682e6464 100644 (file)
@@ -88,6 +88,19 @@ config BLK_DEV_INTEGRITY
        T10/SCSI Data Integrity Field or the T13/ATA External Path
        Protection.  If in doubt, say N.
 
+config BLK_DEV_DAX
+       bool "Block device DAX support"
+       depends on FS_DAX
+       depends on BROKEN
+       help
+         When DAX support is available (CONFIG_FS_DAX) raw block
+         devices can also support direct userspace access to the
+         storage capacity via MMAP(2) similar to a file on a
+         DAX-enabled filesystem.  However, the DAX I/O-path disables
+         some standard I/O-statistics, and the MMAP(2) path has some
+         operational differences due to bypassing the page
+         cache.  If in doubt, say N.
+
 config BLK_DEV_THROTTLING
        bool "Block layer bio throttling support"
        depends on BLK_CGROUP=y
index f565e11f465aa145120973bce58ef7ecc192f349..a54f0543b956e5ccf5f20206e7983fe66ce2698d 100644 (file)
@@ -57,6 +57,49 @@ static int __blk_rq_unmap_user(struct bio *bio)
        return ret;
 }
 
+static int __blk_rq_map_user_iov(struct request *rq,
+               struct rq_map_data *map_data, struct iov_iter *iter,
+               gfp_t gfp_mask, bool copy)
+{
+       struct request_queue *q = rq->q;
+       struct bio *bio, *orig_bio;
+       int ret;
+
+       if (copy)
+               bio = bio_copy_user_iov(q, map_data, iter, gfp_mask);
+       else
+               bio = bio_map_user_iov(q, iter, gfp_mask);
+
+       if (IS_ERR(bio))
+               return PTR_ERR(bio);
+
+       if (map_data && map_data->null_mapped)
+               bio_set_flag(bio, BIO_NULL_MAPPED);
+
+       iov_iter_advance(iter, bio->bi_iter.bi_size);
+       if (map_data)
+               map_data->offset += bio->bi_iter.bi_size;
+
+       orig_bio = bio;
+       blk_queue_bounce(q, &bio);
+
+       /*
+        * We link the bounce buffer in and could have to traverse it
+        * later so we have to get a ref to prevent it from being freed
+        */
+       bio_get(bio);
+
+       ret = blk_rq_append_bio(q, rq, bio);
+       if (ret) {
+               bio_endio(bio);
+               __blk_rq_unmap_user(orig_bio);
+               bio_put(bio);
+               return ret;
+       }
+
+       return 0;
+}
+
 /**
  * blk_rq_map_user_iov - map user data to a request, for REQ_TYPE_BLOCK_PC usage
  * @q:         request queue where request should be inserted
@@ -82,10 +125,11 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
                        struct rq_map_data *map_data,
                        const struct iov_iter *iter, gfp_t gfp_mask)
 {
-       struct bio *bio;
-       int unaligned = 0;
-       struct iov_iter i;
        struct iovec iov, prv = {.iov_base = NULL, .iov_len = 0};
+       bool copy = (q->dma_pad_mask & iter->count) || map_data;
+       struct bio *bio = NULL;
+       struct iov_iter i;
+       int ret;
 
        if (!iter || !iter->count)
                return -EINVAL;
@@ -101,42 +145,29 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
                 */
                if ((uaddr & queue_dma_alignment(q)) ||
                    iovec_gap_to_prv(q, &prv, &iov))
-                       unaligned = 1;
+                       copy = true;
 
                prv.iov_base = iov.iov_base;
                prv.iov_len = iov.iov_len;
        }
 
-       if (unaligned || (q->dma_pad_mask & iter->count) || map_data)
-               bio = bio_copy_user_iov(q, map_data, iter, gfp_mask);
-       else
-               bio = bio_map_user_iov(q, iter, gfp_mask);
-
-       if (IS_ERR(bio))
-               return PTR_ERR(bio);
-
-       if (map_data && map_data->null_mapped)
-               bio_set_flag(bio, BIO_NULL_MAPPED);
-
-       if (bio->bi_iter.bi_size != iter->count) {
-               /*
-                * Grab an extra reference to this bio, as bio_unmap_user()
-                * expects to be able to drop it twice as it happens on the
-                * normal IO completion path
-                */
-               bio_get(bio);
-               bio_endio(bio);
-               __blk_rq_unmap_user(bio);
-               return -EINVAL;
-       }
+       i = *iter;
+       do {
+               ret =__blk_rq_map_user_iov(rq, map_data, &i, gfp_mask, copy);
+               if (ret)
+                       goto unmap_rq;
+               if (!bio)
+                       bio = rq->bio;
+       } while (iov_iter_count(&i));
 
        if (!bio_flagged(bio, BIO_USER_MAPPED))
                rq->cmd_flags |= REQ_COPY_USER;
-
-       blk_queue_bounce(q, &bio);
-       bio_get(bio);
-       blk_rq_bio_prep(q, rq, bio);
        return 0;
+
+unmap_rq:
+       __blk_rq_unmap_user(bio);
+       rq->bio = NULL;
+       return -EINVAL;
 }
 EXPORT_SYMBOL(blk_rq_map_user_iov);
 
index 888a7fec81f715199c3050576516e55b692f2b9b..261353166dcf33a042ea4466ecae044388dddc98 100644 (file)
@@ -304,7 +304,6 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
                                   struct bio *nxt)
 {
        struct bio_vec end_bv = { NULL }, nxt_bv;
-       struct bvec_iter iter;
 
        if (!blk_queue_cluster(q))
                return 0;
@@ -316,11 +315,8 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
        if (!bio_has_data(bio))
                return 1;
 
-       bio_for_each_segment(end_bv, bio, iter)
-               if (end_bv.bv_len == iter.bi_size)
-                       break;
-
-       nxt_bv = bio_iovec(nxt);
+       bio_get_last_bvec(bio, &end_bv);
+       bio_get_first_bvec(nxt, &nxt_bv);
 
        if (!BIOVEC_PHYS_MERGEABLE(&end_bv, &nxt_bv))
                return 0;
index fefd01b496a0852754d9a586c9b0dd6d940ff746..5d87019410542951c8c94afffe9e4df62fdc8755 100644 (file)
@@ -217,10 +217,21 @@ static void part_release(struct device *dev)
        kfree(p);
 }
 
+static int part_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct hd_struct *part = dev_to_part(dev);
+
+       add_uevent_var(env, "PARTN=%u", part->partno);
+       if (part->info && part->info->volname[0])
+               add_uevent_var(env, "PARTNAME=%s", part->info->volname);
+       return 0;
+}
+
 struct device_type part_type = {
        .name           = "partition",
        .groups         = part_attr_groups,
        .release        = part_release,
+       .uevent         = part_uevent,
 };
 
 static void delete_partition_rcu_cb(struct rcu_head *head)
index cb648a49543a55a091b7ba756c628d7a076ac428..edeb2d1d99bec7b605a1385d1c5e8405da6bef40 100644 (file)
@@ -43,6 +43,7 @@ acpi-y                                += pci_root.o pci_link.o pci_irq.o
 acpi-y                         += acpi_lpss.o acpi_apd.o
 acpi-y                         += acpi_platform.o
 acpi-y                         += acpi_pnp.o
+acpi-$(CONFIG_ARM_AMBA)        += acpi_amba.o
 acpi-y                         += int340x_thermal.o
 acpi-y                         += power.o
 acpi-y                         += event.o
diff --git a/drivers/acpi/acpi_amba.c b/drivers/acpi/acpi_amba.c
new file mode 100644 (file)
index 0000000..2a61b54
--- /dev/null
@@ -0,0 +1,122 @@
+
+/*
+ * ACPI support for platform bus type.
+ *
+ * Copyright (C) 2015, Linaro Ltd
+ * Author: Graeme Gregory <graeme.gregory@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/amba/bus.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "internal.h"
+
+static const struct acpi_device_id amba_id_list[] = {
+       {"ARMH0061", 0}, /* PL061 GPIO Device */
+       {"", 0},
+};
+
+static void amba_register_dummy_clk(void)
+{
+       static struct clk *amba_dummy_clk;
+
+       /* If clock already registered */
+       if (amba_dummy_clk)
+               return;
+
+       amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL,
+                                               CLK_IS_ROOT, 0);
+       clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL);
+}
+
+static int amba_handler_attach(struct acpi_device *adev,
+                               const struct acpi_device_id *id)
+{
+       struct amba_device *dev;
+       struct resource_entry *rentry;
+       struct list_head resource_list;
+       bool address_found = false;
+       int irq_no = 0;
+       int ret;
+
+       /* If the ACPI node already has a physical device attached, skip it. */
+       if (adev->physical_node_count)
+               return 0;
+
+       dev = amba_device_alloc(dev_name(&adev->dev), 0, 0);
+       if (!dev) {
+               dev_err(&adev->dev, "%s(): amba_device_alloc() failed\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       INIT_LIST_HEAD(&resource_list);
+       ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+       if (ret < 0)
+               goto err_free;
+
+       list_for_each_entry(rentry, &resource_list, node) {
+               switch (resource_type(rentry->res)) {
+               case IORESOURCE_MEM:
+                       if (!address_found) {
+                               dev->res = *rentry->res;
+                               address_found = true;
+                       }
+                       break;
+               case IORESOURCE_IRQ:
+                       if (irq_no < AMBA_NR_IRQS)
+                               dev->irq[irq_no++] = rentry->res->start;
+                       break;
+               default:
+                       dev_warn(&adev->dev, "Invalid resource\n");
+                       break;
+               }
+       }
+
+       acpi_dev_free_resource_list(&resource_list);
+
+       /*
+        * If the ACPI node has a parent and that parent has a physical device
+        * attached to it, that physical device should be the parent of
+        * the amba device we are about to create.
+        */
+       if (adev->parent)
+               dev->dev.parent = acpi_get_first_physical_node(adev->parent);
+
+       ACPI_COMPANION_SET(&dev->dev, adev);
+
+       ret = amba_device_add(dev, &iomem_resource);
+       if (ret) {
+               dev_err(&adev->dev, "%s(): amba_device_add() failed (%d)\n",
+                      __func__, ret);
+               goto err_free;
+       }
+
+       return 1;
+
+err_free:
+       amba_device_put(dev);
+       return ret;
+}
+
+static struct acpi_scan_handler amba_handler = {
+       .ids = amba_id_list,
+       .attach = amba_handler_attach,
+};
+
+void __init acpi_amba_init(void)
+{
+       amba_register_dummy_clk();
+       acpi_scan_add_handler(&amba_handler);
+}
index d507cf6deda050fde79d3b6237fdbf410407d5d3..d0aad06b38720555a7da9138d5bc7f307100ca43 100644 (file)
@@ -143,6 +143,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
        /* Generic apd devices */
 #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
        { "AMD0010", APD_ADDR(cz_i2c_desc) },
+       { "AMDI0010", APD_ADDR(cz_i2c_desc) },
        { "AMD0020", APD_ADDR(cz_uart_desc) },
        { "AMD0030", },
 #endif
index 296b7a14893aabba895c578e8671e36b34875a37..159f7f19abceb59816491425daec8df080e482da 100644 (file)
@@ -43,7 +43,6 @@ static const struct acpi_device_id forbidden_id_list[] = {
 struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
 {
        struct platform_device *pdev = NULL;
-       struct acpi_device *acpi_parent;
        struct platform_device_info pdevinfo;
        struct resource_entry *rentry;
        struct list_head resource_list;
@@ -62,7 +61,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
        if (count < 0) {
                return NULL;
        } else if (count > 0) {
-               resources = kmalloc(count * sizeof(struct resource),
+               resources = kzalloc(count * sizeof(struct resource),
                                    GFP_KERNEL);
                if (!resources) {
                        dev_err(&adev->dev, "No memory for resources\n");
@@ -82,22 +81,8 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
         * attached to it, that physical device should be the parent of the
         * platform device we are about to create.
         */
-       pdevinfo.parent = NULL;
-       acpi_parent = adev->parent;
-       if (acpi_parent) {
-               struct acpi_device_physical_node *entry;
-               struct list_head *list;
-
-               mutex_lock(&acpi_parent->physical_node_lock);
-               list = &acpi_parent->physical_node_list;
-               if (!list_empty(list)) {
-                       entry = list_first_entry(list,
-                                       struct acpi_device_physical_node,
-                                       node);
-                       pdevinfo.parent = entry->dev;
-               }
-               mutex_unlock(&acpi_parent->physical_node_lock);
-       }
+       pdevinfo.parent = adev->parent ?
+               acpi_get_first_physical_node(adev->parent) : NULL;
        pdevinfo.name = dev_name(&adev->dev);
        pdevinfo.id = -1;
        pdevinfo.res = resources;
index 6979186dbd4b45bd19b60b51d4fd76c76abd683f..b5e54f2da53de81a9d31448265d3633e47f696b6 100644 (file)
@@ -514,7 +514,24 @@ static struct acpi_scan_handler processor_handler = {
        },
 };
 
+static int acpi_processor_container_attach(struct acpi_device *dev,
+                                          const struct acpi_device_id *id)
+{
+       return 1;
+}
+
+static const struct acpi_device_id processor_container_ids[] = {
+       { ACPI_PROCESSOR_CONTAINER_HID, },
+       { }
+};
+
+static struct acpi_scan_handler processor_container_handler = {
+       .ids = processor_container_ids,
+       .attach = acpi_processor_container_attach,
+};
+
 void __init acpi_processor_init(void)
 {
        acpi_scan_add_handler_with_hotplug(&processor_handler, "processor");
+       acpi_scan_add_handler(&processor_container_handler);
 }
index a76f8be1bfe761f18d223a84e789ea1d85dec7e2..4361bc98ef4c7a1f64272b24f2213b0a28f08f27 100644 (file)
@@ -218,13 +218,6 @@ struct acpi_video_device {
        struct thermal_cooling_device *cooling_dev;
 };
 
-static const char device_decode[][30] = {
-       "motherboard VGA device",
-       "PCI VGA device",
-       "AGP VGA device",
-       "UNKNOWN",
-};
-
 static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data);
 static void acpi_video_device_rebind(struct acpi_video_bus *video);
 static void acpi_video_device_bind(struct acpi_video_bus *video,
index 55c8197036f31634439bb363f7d6125ef44f08a4..51b073b68f161799119af908957b1254d7c68781 100644 (file)
@@ -165,7 +165,7 @@ ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset);
 
 /* Initialization sequencing */
 
-ACPI_INIT_GLOBAL(u8, acpi_gbl_reg_methods_enabled, FALSE);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_namespace_initialized, FALSE);
 
 /* Misc */
 
index e4977fac9c1dba3b87a21124f2efe8b506f898e6..9562a10a1a18855c70fc1436605a3a178961ebf3 100644 (file)
@@ -85,7 +85,7 @@ union acpi_parse_object;
 #define ACPI_MTX_MEMORY                 5      /* Debug memory tracking lists */
 
 #define ACPI_MAX_MUTEX                  5
-#define ACPI_NUM_MUTEX                  ACPI_MAX_MUTEX+1
+#define ACPI_NUM_MUTEX                  (ACPI_MAX_MUTEX+1)
 
 /* Lock structure for reader/writer interfaces */
 
@@ -103,11 +103,11 @@ struct acpi_rw_lock {
 #define ACPI_LOCK_HARDWARE              1
 
 #define ACPI_MAX_LOCK                   1
-#define ACPI_NUM_LOCK                   ACPI_MAX_LOCK+1
+#define ACPI_NUM_LOCK                   (ACPI_MAX_LOCK+1)
 
 /* This Thread ID means that the mutex is not in use (unlocked) */
 
-#define ACPI_MUTEX_NOT_ACQUIRED         (acpi_thread_id) 0
+#define ACPI_MUTEX_NOT_ACQUIRED         ((acpi_thread_id) 0)
 
 /* This Thread ID means an invalid thread ID */
 
index 9684ed61284df5739bcd80215974d5c649f747fd..022d69cb345a07014d73f674e5a55dd189042952 100644 (file)
@@ -88,7 +88,7 @@
  */
 acpi_status acpi_ns_initialize_objects(void);
 
-acpi_status acpi_ns_initialize_devices(void);
+acpi_status acpi_ns_initialize_devices(u32 flags);
 
 /*
  * nsload -  Namespace loading
index 52f6bee52d474da83eb77d834bfa8fc18ee73f35..5faeab41e3028c65d472f3dcd07ba00cf06162c6 100644 (file)
@@ -1125,7 +1125,7 @@ const union acpi_predefined_info acpi_gbl_resource_names[] = {
        PACKAGE_INFO(0, 0, 0, 0, 0, 0)  /* Table terminator */
 };
 
-static const union acpi_predefined_info acpi_gbl_scope_names[] = {
+const union acpi_predefined_info acpi_gbl_scope_names[] = {
        {{"_GPE", 0, 0}},
        {{"_PR_", 0, 0}},
        {{"_SB_", 0, 0}},
index 7ec62c46128013c43104190d868764fb58e83541..772178c96ccf25a90a003135bb0f33ab89bcf104 100644 (file)
@@ -348,7 +348,7 @@ void acpi_db_display_table_info(char *table_arg)
                } else {
                        /* If the pointer is null, the table has been unloaded */
 
-                       ACPI_INFO((AE_INFO, "%4.4s - Table has been unloaded",
+                       ACPI_INFO(("%4.4s - Table has been unloaded",
                                   table_desc->signature.ascii));
                }
        }
index 9fee88f1c6540fa6277e9349f8690d1ca138b7b5..68f4e0f4b095ef0e1f7753d2680a3dc3e1ecf305 100644 (file)
@@ -408,7 +408,7 @@ void acpi_db_dump_pld_buffer(union acpi_object *obj_desc)
 
        new_buffer = acpi_db_encode_pld_buffer(pld_info);
        if (!new_buffer) {
-               return;
+               goto exit;
        }
 
        /* The two bit-packed buffers should match */
@@ -479,6 +479,7 @@ void acpi_db_dump_pld_buffer(union acpi_object *obj_desc)
                               pld_info->horizontal_offset);
        }
 
-       ACPI_FREE(pld_info);
        ACPI_FREE(new_buffer);
+exit:
+       ACPI_FREE(pld_info);
 }
index 6a72047aae1c4c0c1db21db5739172011bf4f217..1982310e6d83a3aa6a6e510e8f72682fb1c05226 100644 (file)
@@ -809,8 +809,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
                if (method_desc->method.
                    info_flags & ACPI_METHOD_SERIALIZED_PENDING) {
                        if (walk_state) {
-                               ACPI_INFO((AE_INFO,
-                                          "Marking method %4.4s as Serialized "
+                               ACPI_INFO(("Marking method %4.4s as Serialized "
                                           "because of AE_ALREADY_EXISTS error",
                                           walk_state->method_node->name.
                                           ascii));
index c303e9d9266f6e5ec4afed89dc825f0c2fac449f..a91de2b4603c78cfe7a627c092e3e37b922bbdd8 100644 (file)
@@ -524,8 +524,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
                        arg = arg->common.next;
                }
 
-               ACPI_INFO((AE_INFO,
-                          "Actual Package length (%u) is larger than "
+               ACPI_INFO(("Actual Package length (%u) is larger than "
                           "NumElements field (%u), truncated",
                           i, element_count));
        } else if (i < element_count) {
index 9275e626ed8d8d04e4c920ff494e35ac3c236e73..447fa1cac64fdb3c3bdde2f3199e0ae326a8d953 100644 (file)
@@ -499,8 +499,7 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
        }
 
        if (gpe_enabled_count) {
-               ACPI_INFO((AE_INFO,
-                          "Enabled %u GPEs in block %02X to %02X",
+               ACPI_INFO(("Enabled %u GPEs in block %02X to %02X",
                           gpe_enabled_count, (u32)gpe_block->block_base_number,
                           (u32)(gpe_block->block_base_number +
                                 (gpe_block->gpe_count - 1))));
index 9fdd8d09141b89e52d059cc6d9bad027fa9fe89d..7dc75474c8979ceb974e50d2eb66898bb87c3293 100644 (file)
@@ -281,7 +281,7 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
        }
 
        if (walk_info.count) {
-               ACPI_INFO((AE_INFO, "Enabled %u new GPEs", walk_info.count));
+               ACPI_INFO(("Enabled %u new GPEs", walk_info.count));
        }
 
        (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
index 47092b4d633cca85f68e16962945bb2fe2164452..63924d1c737a0b303f999fa4de9f08cf5e12a89b 100644 (file)
@@ -600,7 +600,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
 
        if (region_obj2->extra.method_REG == NULL ||
            region_obj->region.handler == NULL ||
-           !acpi_gbl_reg_methods_enabled) {
+           !acpi_gbl_namespace_initialized) {
                return_ACPI_STATUS(AE_OK);
        }
 
index 011df210b7b2339323866f71737680b7e1ed8ead..f7416130103798549e0b95f0f80069e381c30195 100644 (file)
@@ -252,7 +252,7 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
 
        status = acpi_get_table_by_index(table_index, &table);
        if (ACPI_SUCCESS(status)) {
-               ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
+               ACPI_INFO(("Dynamic OEM Table Load:"));
                acpi_tb_print_table_header(0, table);
        }
 
@@ -472,7 +472,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
 
        /* Install the new table into the local data structures */
 
-       ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:"));
+       ACPI_INFO(("Dynamic OEM Table Load:"));
        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
        status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
index 28eb861c44ebeaab2715ee19cae7c9e202daea00..5aa21c4eda1d5b4a8f1101d00c51a50b95353060 100644 (file)
@@ -123,8 +123,10 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
                 * op is intended for use by disassemblers in order to properly
                 * disassemble control method invocations. The opcode or group of
                 * opcodes should be surrounded by an "if (0)" clause to ensure that
-                * AML interpreters never see the opcode.
+                * AML interpreters never see the opcode. Thus, something is
+                * wrong if an external opcode ever gets here.
                 */
+               ACPI_ERROR((AE_INFO, "Executed External Op"));
                status = AE_OK;
                goto cleanup;
 
index 65d58bea43207a80b61805bb51cd9bb1744c5bfd..5d59cfcef6f4eb8a5e8fa0a1b1fdaee40fff1dba 100644 (file)
@@ -378,8 +378,7 @@ void acpi_ns_exec_module_code_list(void)
                acpi_ut_remove_reference(prev);
        }
 
-       ACPI_INFO((AE_INFO,
-                  "Executed %u blocks of module-level executable AML code",
+       ACPI_INFO(("Executed %u blocks of module-level executable AML code",
                   method_count));
 
        ACPI_FREE(info);
index bd75d46234a4209c62bab768edcf3566fc7ed011..d4aa8b696ee9d8e970c904e62ef95907841f1b4c 100644 (file)
@@ -46,6 +46,7 @@
 #include "acnamesp.h"
 #include "acdispat.h"
 #include "acinterp.h"
+#include "acevents.h"
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsinit")
@@ -83,6 +84,8 @@ acpi_status acpi_ns_initialize_objects(void)
 
        ACPI_FUNCTION_TRACE(ns_initialize_objects);
 
+       ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                         "[Init] Completing Initialization of ACPI Objects\n"));
        ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                          "**** Starting initialization of namespace objects ****\n"));
        ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
@@ -133,82 +136,108 @@ acpi_status acpi_ns_initialize_objects(void)
  *
  ******************************************************************************/
 
-acpi_status acpi_ns_initialize_devices(void)
+acpi_status acpi_ns_initialize_devices(u32 flags)
 {
-       acpi_status status;
+       acpi_status status = AE_OK;
        struct acpi_device_walk_info info;
 
        ACPI_FUNCTION_TRACE(ns_initialize_devices);
 
-       /* Init counters */
+       if (!(flags & ACPI_NO_DEVICE_INIT)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                                 "[Init] Initializing ACPI Devices\n"));
 
-       info.device_count = 0;
-       info.num_STA = 0;
-       info.num_INI = 0;
+               /* Init counters */
 
-       ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
-                             "Initializing Device/Processor/Thermal objects "
-                             "and executing _INI/_STA methods:\n"));
+               info.device_count = 0;
+               info.num_STA = 0;
+               info.num_INI = 0;
 
-       /* Tree analysis: find all subtrees that contain _INI methods */
+               ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+                                     "Initializing Device/Processor/Thermal objects "
+                                     "and executing _INI/_STA methods:\n"));
 
-       status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
-                                       ACPI_UINT32_MAX, FALSE,
-                                       acpi_ns_find_ini_methods, NULL, &info,
-                                       NULL);
-       if (ACPI_FAILURE(status)) {
-               goto error_exit;
-       }
+               /* Tree analysis: find all subtrees that contain _INI methods */
+
+               status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+                                               ACPI_UINT32_MAX, FALSE,
+                                               acpi_ns_find_ini_methods, NULL,
+                                               &info, NULL);
+               if (ACPI_FAILURE(status)) {
+                       goto error_exit;
+               }
+
+               /* Allocate the evaluation information block */
 
-       /* Allocate the evaluation information block */
+               info.evaluate_info =
+                   ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+               if (!info.evaluate_info) {
+                       status = AE_NO_MEMORY;
+                       goto error_exit;
+               }
 
-       info.evaluate_info =
-           ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
-       if (!info.evaluate_info) {
-               status = AE_NO_MEMORY;
-               goto error_exit;
+               /*
+                * Execute the "global" _INI method that may appear at the root.
+                * This support is provided for Windows compatibility (Vista+) and
+                * is not part of the ACPI specification.
+                */
+               info.evaluate_info->prefix_node = acpi_gbl_root_node;
+               info.evaluate_info->relative_pathname = METHOD_NAME__INI;
+               info.evaluate_info->parameters = NULL;
+               info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
+
+               status = acpi_ns_evaluate(info.evaluate_info);
+               if (ACPI_SUCCESS(status)) {
+                       info.num_INI++;
+               }
        }
 
        /*
-        * Execute the "global" _INI method that may appear at the root. This
-        * support is provided for Windows compatibility (Vista+) and is not
-        * part of the ACPI specification.
+        * Run all _REG methods
+        *
+        * Note: Any objects accessed by the _REG methods will be automatically
+        * initialized, even if they contain executable AML (see the call to
+        * acpi_ns_initialize_objects below).
         */
-       info.evaluate_info->prefix_node = acpi_gbl_root_node;
-       info.evaluate_info->relative_pathname = METHOD_NAME__INI;
-       info.evaluate_info->parameters = NULL;
-       info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
+       if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                                 "[Init] Executing _REG OpRegion methods\n"));
 
-       status = acpi_ns_evaluate(info.evaluate_info);
-       if (ACPI_SUCCESS(status)) {
-               info.num_INI++;
+               status = acpi_ev_initialize_op_regions();
+               if (ACPI_FAILURE(status)) {
+                       goto error_exit;
+               }
        }
 
-       /* Walk namespace to execute all _INIs on present devices */
+       if (!(flags & ACPI_NO_DEVICE_INIT)) {
 
-       status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
-                                       ACPI_UINT32_MAX, FALSE,
-                                       acpi_ns_init_one_device, NULL, &info,
-                                       NULL);
+               /* Walk namespace to execute all _INIs on present devices */
 
-       /*
-        * Any _OSI requests should be completed by now. If the BIOS has
-        * requested any Windows OSI strings, we will always truncate
-        * I/O addresses to 16 bits -- for Windows compatibility.
-        */
-       if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
-               acpi_gbl_truncate_io_addresses = TRUE;
-       }
+               status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+                                               ACPI_UINT32_MAX, FALSE,
+                                               acpi_ns_init_one_device, NULL,
+                                               &info, NULL);
 
-       ACPI_FREE(info.evaluate_info);
-       if (ACPI_FAILURE(status)) {
-               goto error_exit;
-       }
+               /*
+                * Any _OSI requests should be completed by now. If the BIOS has
+                * requested any Windows OSI strings, we will always truncate
+                * I/O addresses to 16 bits -- for Windows compatibility.
+                */
+               if (acpi_gbl_osi_data >= ACPI_OSI_WIN_2000) {
+                       acpi_gbl_truncate_io_addresses = TRUE;
+               }
 
-       ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
-                             "    Executed %u _INI methods requiring %u _STA executions "
-                             "(examined %u objects)\n",
-                             info.num_INI, info.num_STA, info.device_count));
+               ACPI_FREE(info.evaluate_info);
+               if (ACPI_FAILURE(status)) {
+                       goto error_exit;
+               }
+
+               ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
+                                     "    Executed %u _INI methods requiring %u _STA executions "
+                                     "(examined %u objects)\n",
+                                     info.num_INI, info.num_STA,
+                                     info.device_count));
+       }
 
        return_ACPI_STATUS(status);
 
index 305218539df28cda17b97992ff44a0dbaeb613de..d48cbed342c1dda500d5020c746a9caf1c72ad09 100644 (file)
@@ -269,8 +269,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
         */
        if (ACPI_SUCCESS(status) &&
            possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
-               if (GET_CURRENT_ARG_TYPE(walk_state->arg_types) ==
-                   ARGP_SUPERNAME) {
+               if (walk_state->opcode == AML_UNLOAD_OP) {
                        /*
                         * acpi_ps_get_next_namestring has increased the AML pointer,
                         * so we need to restore the saved AML pointer for method call.
@@ -697,7 +696,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
  *
  * PARAMETERS:  walk_state          - Current state
  *              parser_state        - Current parser state object
- *              arg_type            - The parser argument type (ARGP_*)
+ *              arg_type            - The argument type (AML_*_ARG)
  *              return_arg          - Where the next arg is returned
  *
  * RETURN:      Status, and an op object containing the next argument.
@@ -817,9 +816,9 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
                                return_ACPI_STATUS(AE_NO_MEMORY);
                        }
 
-                       /* super_name allows argument to be a method call */
+                       /* To support super_name arg of Unload */
 
-                       if (arg_type == ARGP_SUPERNAME) {
+                       if (walk_state->opcode == AML_UNLOAD_OP) {
                                status =
                                    acpi_ps_get_next_namepath(walk_state,
                                                              parser_state, arg,
index b661a1e013fbed639da4aab35002670c5fdc2f4e..4dc6108de4ffbf83a37ea714e0342cfcd8847d6c 100644 (file)
@@ -267,8 +267,7 @@ acpi_tb_install_standard_table(acpi_physical_address address,
        if (!reload &&
            acpi_gbl_disable_ssdt_table_install &&
            ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) {
-               ACPI_INFO((AE_INFO,
-                          "Ignoring installation of %4.4s at %8.8X%8.8X",
+               ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X",
                           new_table_desc.signature.ascii,
                           ACPI_FORMAT_UINT64(address)));
                goto release_and_exit;
@@ -432,7 +431,7 @@ finish_override:
                return;
        }
 
-       ACPI_INFO((AE_INFO, "%4.4s 0x%8.8X%8.8X"
+       ACPI_INFO(("%4.4s 0x%8.8X%8.8X"
                   " %s table override, new table: 0x%8.8X%8.8X",
                   old_table_desc->signature.ascii,
                   ACPI_FORMAT_UINT64(old_table_desc->address),
index fd4146d4ff4902660996add0e78ca9582d07e5b3..26d61dbace0a1fa67b8706cc1ee0d124ac3d7e01 100644 (file)
@@ -132,7 +132,7 @@ acpi_tb_print_table_header(acpi_physical_address address,
 
                /* FACS only has signature and length fields */
 
-               ACPI_INFO((AE_INFO, "%-4.4s 0x%8.8X%8.8X %06X",
+               ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X",
                           header->signature, ACPI_FORMAT_UINT64(address),
                           header->length));
        } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
@@ -144,7 +144,7 @@ acpi_tb_print_table_header(acpi_physical_address address,
                       ACPI_OEM_ID_SIZE);
                acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
 
-               ACPI_INFO((AE_INFO, "RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)",
+               ACPI_INFO(("RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)",
                           ACPI_FORMAT_UINT64(address),
                           (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
                            revision >
@@ -158,8 +158,7 @@ acpi_tb_print_table_header(acpi_physical_address address,
 
                acpi_tb_cleanup_table_header(&local_header, header);
 
-               ACPI_INFO((AE_INFO,
-                          "%-4.4s 0x%8.8X%8.8X"
+               ACPI_INFO(("%-4.4s 0x%8.8X%8.8X"
                           " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)",
                           local_header.signature, ACPI_FORMAT_UINT64(address),
                           local_header.length, local_header.revision,
index 3269bef371d7ddd21a32ac18f58d404cefdeb44b..9240c76d2823e333d2b30ca2d24ad32bfae3c5cf 100644 (file)
@@ -174,9 +174,7 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
                                      ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
                                      new_table);
 
-       ACPI_INFO((AE_INFO,
-                  "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
-                  new_table->length));
+       ACPI_INFO(("Forced DSDT copy: length 0x%05X copied locally, original unmapped", new_table->length));
 
        return (new_table);
 }
index 278666e39563e7fc3cacdc4ae6e36a5a7bdc3c93..3151968c10d1a0aef3c2a1610307568b8e171d4a 100644 (file)
@@ -47,6 +47,7 @@
 #include "accommon.h"
 #include "acnamesp.h"
 #include "actables.h"
+#include "acevents.h"
 
 #define _COMPONENT          ACPI_TABLES
 ACPI_MODULE_NAME("tbxfload")
@@ -68,6 +69,25 @@ acpi_status __init acpi_load_tables(void)
 
        ACPI_FUNCTION_TRACE(acpi_load_tables);
 
+       /*
+        * Install the default operation region handlers. These are the
+        * handlers that are defined by the ACPI specification to be
+        * "always accessible" -- namely, system_memory, system_IO, and
+        * PCI_Config. This also means that no _REG methods need to be
+        * run for these address spaces. We need to have these handlers
+        * installed before any AML code can be executed, especially any
+        * module-level code (11/2015).
+        * Note that we allow OSPMs to install their own region handlers
+        * between acpi_initialize_subsystem() and acpi_load_tables() to use
+        * their customized default region handlers.
+        */
+       status = acpi_ev_install_region_handlers();
+       if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) {
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "During Region initialization"));
+               return_ACPI_STATUS(status);
+       }
+
        /* Load the namespace from the tables */
 
        status = acpi_tb_load_namespace();
@@ -83,6 +103,20 @@ acpi_status __init acpi_load_tables(void)
                                "While loading namespace from ACPI tables"));
        }
 
+       if (!acpi_gbl_group_module_level_code) {
+               /*
+                * Initialize the objects that remain uninitialized. This
+                * runs the executable AML that may be part of the
+                * declaration of these objects:
+                * operation_regions, buffer_fields, Buffers, and Packages.
+                */
+               status = acpi_ns_initialize_objects();
+               if (ACPI_FAILURE(status)) {
+                       return_ACPI_STATUS(status);
+               }
+       }
+
+       acpi_gbl_namespace_initialized = TRUE;
        return_ACPI_STATUS(status);
 }
 
@@ -206,9 +240,7 @@ acpi_status acpi_tb_load_namespace(void)
        }
 
        if (!tables_failed) {
-               ACPI_INFO((AE_INFO,
-                          "%u ACPI AML tables successfully acquired and loaded\n",
-                          tables_loaded));
+               ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded\n", tables_loaded));
        } else {
                ACPI_ERROR((AE_INFO,
                            "%u table load failures, %u successful",
@@ -301,7 +333,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table)
 
        /* Install the table and load it into the namespace */
 
-       ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:"));
+       ACPI_INFO(("Host-directed Dynamic ACPI Table Load:"));
        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
        status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
index c9a720f2274a59053533f9ac143dbd350398d400..f8e9978888e162e7f035a69b339741ca515ef2a3 100644 (file)
@@ -245,7 +245,7 @@ void *acpi_os_acquire_object(struct acpi_memory_list *cache)
        acpi_status status;
        void *object;
 
-       ACPI_FUNCTION_NAME(os_acquire_object);
+       ACPI_FUNCTION_TRACE(os_acquire_object);
 
        if (!cache) {
                return_PTR(NULL);
index c427a5cda465e2722b93c4181791063d17bc952d..d5c3adf19bd0595ea6f1e1ea356d7d081986246f 100644 (file)
@@ -140,6 +140,67 @@ int acpi_ut_stricmp(char *string1, char *string2)
        return (c1 - c2);
 }
 
+#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat
+ *
+ * PARAMETERS:  Adds a "DestSize" parameter to each of the standard string
+ *              functions. This is the size of the Destination buffer.
+ *
+ * RETURN:      TRUE if the operation would overflow the destination buffer.
+ *
+ * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that
+ *              the result of the operation will not overflow the output string
+ *              buffer.
+ *
+ * NOTE:        These functions are typically only helpful for processing
+ *              user input and command lines. For most ACPICA code, the
+ *              required buffer length is precisely calculated before buffer
+ *              allocation, so the use of these functions is unnecessary.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source)
+{
+
+       if (strlen(source) >= dest_size) {
+               return (TRUE);
+       }
+
+       strcpy(dest, source);
+       return (FALSE);
+}
+
+u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source)
+{
+
+       if ((strlen(dest) + strlen(source)) >= dest_size) {
+               return (TRUE);
+       }
+
+       strcat(dest, source);
+       return (FALSE);
+}
+
+u8
+acpi_ut_safe_strncat(char *dest,
+                    acpi_size dest_size,
+                    char *source, acpi_size max_transfer_length)
+{
+       acpi_size actual_transfer_length;
+
+       actual_transfer_length = ACPI_MIN(max_transfer_length, strlen(source));
+
+       if ((strlen(dest) + actual_transfer_length) >= dest_size) {
+               return (TRUE);
+       }
+
+       strncat(dest, source, max_transfer_length);
+       return (FALSE);
+}
+#endif
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_strtoul64
@@ -155,7 +216,15 @@ int acpi_ut_stricmp(char *string1, char *string2)
  *              32-bit or 64-bit conversion, depending on the current mode
  *              of the interpreter.
  *
- * NOTE:        Does not support Octal strings, not needed.
+ * NOTES:       acpi_gbl_integer_byte_width should be set to the proper width.
+ *              For the core ACPICA code, this width depends on the DSDT
+ *              version. For iASL, the default byte width is always 8.
+ *
+ *              Does not support Octal strings, not needed at this time.
+ *
+ *              There is an earlier version of the function after this one,
+ *              below. It is slightly different than this one, and the two
+ *              may eventually may need to be merged. (01/2016).
  *
  ******************************************************************************/
 
@@ -171,7 +240,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
        u8 sign_of0x = 0;
        u8 term = 0;
 
-       ACPI_FUNCTION_TRACE_STR(ut_stroul64, string);
+       ACPI_FUNCTION_TRACE_STR(ut_strtoul64, string);
 
        switch (base) {
        case ACPI_ANY_BASE:
@@ -318,63 +387,162 @@ error_exit:
        }
 }
 
-#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION)
+#ifdef _OBSOLETE_FUNCTIONS
+/* TBD: use version in ACPICA main code base? */
+/* DONE: 01/2016 */
+
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_safe_strcpy, acpi_ut_safe_strcat, acpi_ut_safe_strncat
+ * FUNCTION:    strtoul64
  *
- * PARAMETERS:  Adds a "DestSize" parameter to each of the standard string
- *              functions. This is the size of the Destination buffer.
+ * PARAMETERS:  string              - Null terminated string
+ *              terminater          - Where a pointer to the terminating byte
+ *                                    is returned
+ *              base                - Radix of the string
  *
- * RETURN:      TRUE if the operation would overflow the destination buffer.
+ * RETURN:      Converted value
  *
- * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that
- *              the result of the operation will not overflow the output string
- *              buffer.
- *
- * NOTE:        These functions are typically only helpful for processing
- *              user input and command lines. For most ACPICA code, the
- *              required buffer length is precisely calculated before buffer
- *              allocation, so the use of these functions is unnecessary.
+ * DESCRIPTION: Convert a string into an unsigned value.
  *
  ******************************************************************************/
 
-u8 acpi_ut_safe_strcpy(char *dest, acpi_size dest_size, char *source)
+acpi_status strtoul64(char *string, u32 base, u64 *ret_integer)
 {
+       u32 index;
+       u32 sign;
+       u64 return_value = 0;
+       acpi_status status = AE_OK;
 
-       if (strlen(source) >= dest_size) {
-               return (TRUE);
+       *ret_integer = 0;
+
+       switch (base) {
+       case 0:
+       case 8:
+       case 10:
+       case 16:
+
+               break;
+
+       default:
+               /*
+                * The specified Base parameter is not in the domain of
+                * this function:
+                */
+               return (AE_BAD_PARAMETER);
        }
 
-       strcpy(dest, source);
-       return (FALSE);
-}
+       /* Skip over any white space in the buffer: */
 
-u8 acpi_ut_safe_strcat(char *dest, acpi_size dest_size, char *source)
-{
+       while (isspace((int)*string) || *string == '\t') {
+               ++string;
+       }
 
-       if ((strlen(dest) + strlen(source)) >= dest_size) {
-               return (TRUE);
+       /*
+        * The buffer may contain an optional plus or minus sign.
+        * If it does, then skip over it but remember what is was:
+        */
+       if (*string == '-') {
+               sign = ACPI_SIGN_NEGATIVE;
+               ++string;
+       } else if (*string == '+') {
+               ++string;
+               sign = ACPI_SIGN_POSITIVE;
+       } else {
+               sign = ACPI_SIGN_POSITIVE;
        }
 
-       strcat(dest, source);
-       return (FALSE);
-}
+       /*
+        * If the input parameter Base is zero, then we need to
+        * determine if it is octal, decimal, or hexadecimal:
+        */
+       if (base == 0) {
+               if (*string == '0') {
+                       if (tolower((int)*(++string)) == 'x') {
+                               base = 16;
+                               ++string;
+                       } else {
+                               base = 8;
+                       }
+               } else {
+                       base = 10;
+               }
+       }
 
-u8
-acpi_ut_safe_strncat(char *dest,
-                    acpi_size dest_size,
-                    char *source, acpi_size max_transfer_length)
-{
-       acpi_size actual_transfer_length;
+       /*
+        * For octal and hexadecimal bases, skip over the leading
+        * 0 or 0x, if they are present.
+        */
+       if (base == 8 && *string == '0') {
+               string++;
+       }
 
-       actual_transfer_length = ACPI_MIN(max_transfer_length, strlen(source));
+       if (base == 16 && *string == '0' && tolower((int)*(++string)) == 'x') {
+               string++;
+       }
 
-       if ((strlen(dest) + actual_transfer_length) >= dest_size) {
-               return (TRUE);
+       /* Main loop: convert the string to an unsigned long */
+
+       while (*string) {
+               if (isdigit((int)*string)) {
+                       index = ((u8)*string) - '0';
+               } else {
+                       index = (u8)toupper((int)*string);
+                       if (isupper((int)index)) {
+                               index = index - 'A' + 10;
+                       } else {
+                               goto error_exit;
+                       }
+               }
+
+               if (index >= base) {
+                       goto error_exit;
+               }
+
+               /* Check to see if value is out of range: */
+
+               if (return_value > ((ACPI_UINT64_MAX - (u64)index) / (u64)base)) {
+                       goto error_exit;
+               } else {
+                       return_value *= base;
+                       return_value += index;
+               }
+
+               ++string;
        }
 
-       strncat(dest, source, max_transfer_length);
-       return (FALSE);
+       /* If a minus sign was present, then "the conversion is negated": */
+
+       if (sign == ACPI_SIGN_NEGATIVE) {
+               return_value = (ACPI_UINT32_MAX - return_value) + 1;
+       }
+
+       *ret_integer = return_value;
+       return (status);
+
+error_exit:
+       switch (base) {
+       case 8:
+
+               status = AE_BAD_OCTAL_CONSTANT;
+               break;
+
+       case 10:
+
+               status = AE_BAD_DECIMAL_CONSTANT;
+               break;
+
+       case 16:
+
+               status = AE_BAD_HEX_CONSTANT;
+               break;
+
+       default:
+
+               /* Base validated above */
+
+               break;
+       }
+
+       return (status);
 }
 #endif
index c7c2bb8f3559cc71c07fbb8933b13a53d6874ac2..60c406a8efcb3b533b6d2fd1f1f5c9f75f13831e 100644 (file)
@@ -712,7 +712,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
        /* Print summary */
 
        if (!num_outstanding) {
-               ACPI_INFO((AE_INFO, "No outstanding allocations"));
+               ACPI_INFO(("No outstanding allocations"));
        } else {
                ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations",
                            num_outstanding, num_outstanding));
index 6fe59597b5999dc340cd25590e8c6b00a0cc14b6..d9f15cbcd8a0b9228382042abdd802b4322d11ba 100644 (file)
@@ -175,8 +175,7 @@ ACPI_EXPORT_SYMBOL(acpi_warning)
  * TBD: module_name and line_number args are not needed, should be removed.
  *
  ******************************************************************************/
-void ACPI_INTERNAL_VAR_XFACE
-acpi_info(const char *module_name, u32 line_number, const char *format, ...)
+void ACPI_INTERNAL_VAR_XFACE acpi_info(const char *format, ...)
 {
        va_list arg_list;
 
index 721b87cce90865c8c3d20295b664cf2665de84b6..75b5f27da2674b4e34d84cd65aadf0a42ee76819 100644 (file)
@@ -154,21 +154,6 @@ acpi_status __init acpi_enable_subsystem(u32 flags)
         */
        acpi_gbl_early_initialization = FALSE;
 
-       /*
-        * Install the default operation region handlers. These are the
-        * handlers that are defined by the ACPI specification to be
-        * "always accessible" -- namely, system_memory, system_IO, and
-        * PCI_Config. This also means that no _REG methods need to be
-        * run for these address spaces. We need to have these handlers
-        * installed before any AML code can be executed, especially any
-        * module-level code (11/2015).
-        */
-       status = acpi_ev_install_region_handlers();
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status,
-                               "During Region initialization"));
-               return_ACPI_STATUS(status);
-       }
 #if (!ACPI_REDUCED_HARDWARE)
 
        /* Enable ACPI mode */
@@ -260,23 +245,6 @@ acpi_status __init acpi_initialize_objects(u32 flags)
 
        ACPI_FUNCTION_TRACE(acpi_initialize_objects);
 
-       /*
-        * Run all _REG methods
-        *
-        * Note: Any objects accessed by the _REG methods will be automatically
-        * initialized, even if they contain executable AML (see the call to
-        * acpi_ns_initialize_objects below).
-        */
-       acpi_gbl_reg_methods_enabled = TRUE;
-       if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "[Init] Executing _REG OpRegion methods\n"));
-
-               status = acpi_ev_initialize_op_regions();
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
-               }
-       }
 #ifdef ACPI_EXEC_APP
        /*
         * This call implements the "initialization file" option for acpi_exec.
@@ -299,32 +267,27 @@ acpi_status __init acpi_initialize_objects(u32 flags)
         */
        if (acpi_gbl_group_module_level_code) {
                acpi_ns_exec_module_code_list();
-       }
-
-       /*
-        * Initialize the objects that remain uninitialized. This runs the
-        * executable AML that may be part of the declaration of these objects:
-        * operation_regions, buffer_fields, Buffers, and Packages.
-        */
-       if (!(flags & ACPI_NO_OBJECT_INIT)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "[Init] Completing Initialization of ACPI Objects\n"));
 
-               status = acpi_ns_initialize_objects();
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
+               /*
+                * Initialize the objects that remain uninitialized. This
+                * runs the executable AML that may be part of the
+                * declaration of these objects:
+                * operation_regions, buffer_fields, Buffers, and Packages.
+                */
+               if (!(flags & ACPI_NO_OBJECT_INIT)) {
+                       status = acpi_ns_initialize_objects();
+                       if (ACPI_FAILURE(status)) {
+                               return_ACPI_STATUS(status);
+                       }
                }
        }
 
        /*
-        * Initialize all device objects in the namespace. This runs the device
-        * _STA and _INI methods.
+        * Initialize all device/region objects in the namespace. This runs
+        * the device _STA and _INI methods and region _REG methods.
         */
-       if (!(flags & ACPI_NO_DEVICE_INIT)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-                                 "[Init] Initializing ACPI Devices\n"));
-
-               status = acpi_ns_initialize_devices();
+       if (!(flags & (ACPI_NO_DEVICE_INIT | ACPI_NO_ADDRESS_SPACE_INIT))) {
+               status = acpi_ns_initialize_devices(flags);
                if (ACPI_FAILURE(status)) {
                        return_ACPI_STATUS(status);
                }
index a2c8d7adb6eb5a47554708032d30b4b34bbf2a62..da370e1d31f4fe922510e9ba5adc7504b9e859f9 100644 (file)
@@ -536,7 +536,8 @@ int apei_resources_request(struct apei_resources *resources,
                goto err_unmap_ioport;
        }
 
-       return 0;
+       goto arch_res_fini;
+
 err_unmap_ioport:
        list_for_each_entry(res, &resources->ioport, list) {
                if (res == res_bak)
@@ -551,7 +552,8 @@ err_unmap_iomem:
                release_mem_region(res->start, res->end - res->start);
        }
 arch_res_fini:
-       apei_resources_fini(&arch_res);
+       if (arch_apei_filter_addr)
+               apei_resources_fini(&arch_res);
 nvs_res_fini:
        apei_resources_fini(&nvs_resources);
        return rc;
index 0431883653bed9d3c0394368fe87ced99043f185..559c1173de1c99177ba702c60d27993826510e9c 100644 (file)
@@ -519,7 +519,7 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
                             u64 param3, u64 param4)
 {
        int rc;
-       unsigned long pfn;
+       u64 base_addr, size;
 
        /* If user manually set "flags", make sure it is legal */
        if (flags && (flags &
@@ -545,10 +545,17 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
        /*
         * Disallow crazy address masks that give BIOS leeway to pick
         * injection address almost anywhere. Insist on page or
-        * better granularity and that target address is normal RAM.
+        * better granularity and that target address is normal RAM or
+        * NVDIMM.
         */
-       pfn = PFN_DOWN(param1 & param2);
-       if (!page_is_ram(pfn) || ((param2 & PAGE_MASK) != PAGE_MASK))
+       base_addr = param1 & param2;
+       size = ~param2 + 1;
+
+       if (((param2 & PAGE_MASK) != PAGE_MASK) ||
+           ((region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)
+                               != REGION_INTERSECTS) &&
+            (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY)
+                               != REGION_INTERSECTS)))
                return -EINVAL;
 
 inject:
index 6e6bc1059301745fc1d5fd6ebf943d048082e821..006c3894c6ea1a9b3fd344b28b49a88b851c5fc4 100644 (file)
@@ -1207,6 +1207,9 @@ static int __init erst_init(void)
                "Failed to allocate %lld bytes for persistent store error log.\n",
                erst_erange.size);
 
+       /* Cleanup ERST Resources */
+       apei_resources_fini(&erst_resources);
+
        return 0;
 
 err_release_erange:
index 3dd9c462d22afd650b989399ac9c973afc983257..60746ef904e495e382bfa5efe773e62371d46a6d 100644 (file)
@@ -26,7 +26,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/io.h>
        ((struct acpi_hest_generic_status *)                            \
         ((struct ghes_estatus_node *)(estatus_node) + 1))
 
+/*
+ * This driver isn't really modular, however for the time being,
+ * continuing to use module_param is the easiest way to remain
+ * compatible with existing boot arg use cases.
+ */
 bool ghes_disable;
 module_param_named(disable, ghes_disable, bool, 0);
 
@@ -1148,18 +1153,4 @@ err_ioremap_exit:
 err:
        return rc;
 }
-
-static void __exit ghes_exit(void)
-{
-       platform_driver_unregister(&ghes_platform_driver);
-       ghes_estatus_pool_exit();
-       ghes_ioremap_exit();
-}
-
-module_init(ghes_init);
-module_exit(ghes_exit);
-
-MODULE_AUTHOR("Huang Ying");
-MODULE_DESCRIPTION("APEI Generic Hardware Error Source support");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:GHES");
+device_initcall(ghes_init);
index a83e3c62c5a9d04e57a0fc644598d6e41d42c290..75f128e766a979e38a3a91ca00ec8fbde5b686dc 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * BGRT boot graphic support
+ * Authors: Matthew Garrett, Josh Triplett <josh@joshtriplett.org>
  * Copyright 2012 Red Hat, Inc <mjg@redhat.com>
  * Copyright 2012 Intel Corporation
  *
@@ -8,7 +10,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/sysfs.h>
@@ -103,9 +104,4 @@ out_kobject:
        kobject_put(bgrt_kobj);
        return ret;
 }
-
-module_init(bgrt_init);
-
-MODULE_AUTHOR("Matthew Garrett, Josh Triplett <josh@joshtriplett.org>");
-MODULE_DESCRIPTION("BGRT boot graphic support");
-MODULE_LICENSE("GPL");
+device_initcall(bgrt_init);
index 891c42d1cd652c732f4957fc8bb2c2f20a5fc470..0e8567846f1afbce5185361be758cb743c0b6836 100644 (file)
@@ -479,24 +479,38 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device)
                              Device Matching
    -------------------------------------------------------------------------- */
 
-static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev,
-                                                     const struct device *dev)
+/**
+ * acpi_get_first_physical_node - Get first physical node of an ACPI device
+ * @adev:      ACPI device in question
+ *
+ * Return: First physical node of ACPI device @adev
+ */
+struct device *acpi_get_first_physical_node(struct acpi_device *adev)
 {
        struct mutex *physical_node_lock = &adev->physical_node_lock;
+       struct device *phys_dev;
 
        mutex_lock(physical_node_lock);
        if (list_empty(&adev->physical_node_list)) {
-               adev = NULL;
+               phys_dev = NULL;
        } else {
                const struct acpi_device_physical_node *node;
 
                node = list_first_entry(&adev->physical_node_list,
                                        struct acpi_device_physical_node, node);
-               if (node->dev != dev)
-                       adev = NULL;
+
+               phys_dev = node->dev;
        }
        mutex_unlock(physical_node_lock);
-       return adev;
+       return phys_dev;
+}
+
+static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev,
+                                                     const struct device *dev)
+{
+       const struct device *phys_dev = acpi_get_first_physical_node(adev);
+
+       return phys_dev && phys_dev == dev ? adev : NULL;
 }
 
 /**
index 6730f965b3793f25ba73125a00b18f346decf75f..8adac69dba3da52e5bd4ebb7f0780543fc17c51f 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
+#include <linux/ktime.h>
 
 #include <acpi/cppc_acpi.h>
 /*
@@ -63,58 +64,140 @@ static struct mbox_chan *pcc_channel;
 static void __iomem *pcc_comm_addr;
 static u64 comm_base_addr;
 static int pcc_subspace_idx = -1;
-static u16 pcc_cmd_delay;
 static bool pcc_channel_acquired;
+static ktime_t deadline;
+static unsigned int pcc_mpar, pcc_mrtt;
+
+/* pcc mapped address + header size + offset within PCC subspace */
+#define GET_PCC_VADDR(offs) (pcc_comm_addr + 0x8 + (offs))
 
 /*
  * Arbitrary Retries in case the remote processor is slow to respond
- * to PCC commands.
+ * to PCC commands. Keeping it high enough to cover emulators where
+ * the processors run painfully slow.
  */
 #define NUM_RETRIES 500
 
+static int check_pcc_chan(void)
+{
+       int ret = -EIO;
+       struct acpi_pcct_shared_memory __iomem *generic_comm_base = pcc_comm_addr;
+       ktime_t next_deadline = ktime_add(ktime_get(), deadline);
+
+       /* Retry in case the remote processor was too slow to catch up. */
+       while (!ktime_after(ktime_get(), next_deadline)) {
+               /*
+                * Per spec, prior to boot the PCC space wil be initialized by
+                * platform and should have set the command completion bit when
+                * PCC can be used by OSPM
+                */
+               if (readw_relaxed(&generic_comm_base->status) & PCC_CMD_COMPLETE) {
+                       ret = 0;
+                       break;
+               }
+               /*
+                * Reducing the bus traffic in case this loop takes longer than
+                * a few retries.
+                */
+               udelay(3);
+       }
+
+       return ret;
+}
+
 static int send_pcc_cmd(u16 cmd)
 {
-       int retries, result = -EIO;
-       struct acpi_pcct_hw_reduced *pcct_ss = pcc_channel->con_priv;
+       int ret = -EIO;
        struct acpi_pcct_shared_memory *generic_comm_base =
                (struct acpi_pcct_shared_memory *) pcc_comm_addr;
-       u32 cmd_latency = pcct_ss->latency;
+       static ktime_t last_cmd_cmpl_time, last_mpar_reset;
+       static int mpar_count;
+       unsigned int time_delta;
 
-       /* Min time OS should wait before sending next command. */
-       udelay(pcc_cmd_delay);
+       /*
+        * For CMD_WRITE we know for a fact the caller should have checked
+        * the channel before writing to PCC space
+        */
+       if (cmd == CMD_READ) {
+               ret = check_pcc_chan();
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * Handle the Minimum Request Turnaround Time(MRTT)
+        * "The minimum amount of time that OSPM must wait after the completion
+        * of a command before issuing the next command, in microseconds"
+        */
+       if (pcc_mrtt) {
+               time_delta = ktime_us_delta(ktime_get(), last_cmd_cmpl_time);
+               if (pcc_mrtt > time_delta)
+                       udelay(pcc_mrtt - time_delta);
+       }
+
+       /*
+        * Handle the non-zero Maximum Periodic Access Rate(MPAR)
+        * "The maximum number of periodic requests that the subspace channel can
+        * support, reported in commands per minute. 0 indicates no limitation."
+        *
+        * This parameter should be ideally zero or large enough so that it can
+        * handle maximum number of requests that all the cores in the system can
+        * collectively generate. If it is not, we will follow the spec and just
+        * not send the request to the platform after hitting the MPAR limit in
+        * any 60s window
+        */
+       if (pcc_mpar) {
+               if (mpar_count == 0) {
+                       time_delta = ktime_ms_delta(ktime_get(), last_mpar_reset);
+                       if (time_delta < 60 * MSEC_PER_SEC) {
+                               pr_debug("PCC cmd not sent due to MPAR limit");
+                               return -EIO;
+                       }
+                       last_mpar_reset = ktime_get();
+                       mpar_count = pcc_mpar;
+               }
+               mpar_count--;
+       }
 
        /* Write to the shared comm region. */
-       writew(cmd, &generic_comm_base->command);
+       writew_relaxed(cmd, &generic_comm_base->command);
 
        /* Flip CMD COMPLETE bit */
-       writew(0, &generic_comm_base->status);
+       writew_relaxed(0, &generic_comm_base->status);
 
        /* Ring doorbell */
-       result = mbox_send_message(pcc_channel, &cmd);
-       if (result < 0) {
+       ret = mbox_send_message(pcc_channel, &cmd);
+       if (ret < 0) {
                pr_err("Err sending PCC mbox message. cmd:%d, ret:%d\n",
-                               cmd, result);
-               return result;
+                               cmd, ret);
+               return ret;
        }
 
-       /* Wait for a nominal time to let platform process command. */
-       udelay(cmd_latency);
-
-       /* Retry in case the remote processor was too slow to catch up. */
-       for (retries = NUM_RETRIES; retries > 0; retries--) {
-               if (readw_relaxed(&generic_comm_base->status) & PCC_CMD_COMPLETE) {
-                       result = 0;
-                       break;
-               }
+       /*
+        * For READs we need to ensure the cmd completed to ensure
+        * the ensuing read()s can proceed. For WRITEs we dont care
+        * because the actual write()s are done before coming here
+        * and the next READ or WRITE will check if the channel
+        * is busy/free at the entry of this call.
+        *
+        * If Minimum Request Turnaround Time is non-zero, we need
+        * to record the completion time of both READ and WRITE
+        * command for proper handling of MRTT, so we need to check
+        * for pcc_mrtt in addition to CMD_READ
+        */
+       if (cmd == CMD_READ || pcc_mrtt) {
+               ret = check_pcc_chan();
+               if (pcc_mrtt)
+                       last_cmd_cmpl_time = ktime_get();
        }
 
-       mbox_client_txdone(pcc_channel, result);
-       return result;
+       mbox_client_txdone(pcc_channel, ret);
+       return ret;
 }
 
 static void cppc_chan_tx_done(struct mbox_client *cl, void *msg, int ret)
 {
-       if (ret)
+       if (ret < 0)
                pr_debug("TX did not complete: CMD sent:%x, ret:%d\n",
                                *(u16 *)msg, ret);
        else
@@ -306,6 +389,7 @@ static int register_pcc_channel(int pcc_subspace_idx)
 {
        struct acpi_pcct_hw_reduced *cppc_ss;
        unsigned int len;
+       u64 usecs_lat;
 
        if (pcc_subspace_idx >= 0) {
                pcc_channel = pcc_mbox_request_channel(&cppc_mbox_cl,
@@ -335,7 +419,16 @@ static int register_pcc_channel(int pcc_subspace_idx)
                 */
                comm_base_addr = cppc_ss->base_address;
                len = cppc_ss->length;
-               pcc_cmd_delay = cppc_ss->min_turnaround_time;
+
+               /*
+                * cppc_ss->latency is just a Nominal value. In reality
+                * the remote processor could be much slower to reply.
+                * So add an arbitrary amount of wait on top of Nominal.
+                */
+               usecs_lat = NUM_RETRIES * cppc_ss->latency;
+               deadline = ns_to_ktime(usecs_lat * NSEC_PER_USEC);
+               pcc_mrtt = cppc_ss->min_turnaround_time;
+               pcc_mpar = cppc_ss->max_access_rate;
 
                pcc_comm_addr = acpi_os_ioremap(comm_base_addr, len);
                if (!pcc_comm_addr) {
@@ -546,29 +639,74 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr)
 }
 EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit);
 
-static u64 get_phys_addr(struct cpc_reg *reg)
-{
-       /* PCC communication addr space begins at byte offset 0x8. */
-       if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM)
-               return (u64)comm_base_addr + 0x8 + reg->address;
-       else
-               return reg->address;
-}
+/*
+ * Since cpc_read and cpc_write are called while holding pcc_lock, it should be
+ * as fast as possible. We have already mapped the PCC subspace during init, so
+ * we can directly write to it.
+ */
 
-static void cpc_read(struct cpc_reg *reg, u64 *val)
+static int cpc_read(struct cpc_reg *reg, u64 *val)
 {
-       u64 addr = get_phys_addr(reg);
+       int ret_val = 0;
 
-       acpi_os_read_memory((acpi_physical_address)addr,
-                       val, reg->bit_width);
+       *val = 0;
+       if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+               void __iomem *vaddr = GET_PCC_VADDR(reg->address);
+
+               switch (reg->bit_width) {
+               case 8:
+                       *val = readb_relaxed(vaddr);
+                       break;
+               case 16:
+                       *val = readw_relaxed(vaddr);
+                       break;
+               case 32:
+                       *val = readl_relaxed(vaddr);
+                       break;
+               case 64:
+                       *val = readq_relaxed(vaddr);
+                       break;
+               default:
+                       pr_debug("Error: Cannot read %u bit width from PCC\n",
+                               reg->bit_width);
+                       ret_val = -EFAULT;
+               }
+       } else
+               ret_val = acpi_os_read_memory((acpi_physical_address)reg->address,
+                                       val, reg->bit_width);
+       return ret_val;
 }
 
-static void cpc_write(struct cpc_reg *reg, u64 val)
+static int cpc_write(struct cpc_reg *reg, u64 val)
 {
-       u64 addr = get_phys_addr(reg);
+       int ret_val = 0;
 
-       acpi_os_write_memory((acpi_physical_address)addr,
-                       val, reg->bit_width);
+       if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+               void __iomem *vaddr = GET_PCC_VADDR(reg->address);
+
+               switch (reg->bit_width) {
+               case 8:
+                       writeb_relaxed(val, vaddr);
+                       break;
+               case 16:
+                       writew_relaxed(val, vaddr);
+                       break;
+               case 32:
+                       writel_relaxed(val, vaddr);
+                       break;
+               case 64:
+                       writeq_relaxed(val, vaddr);
+                       break;
+               default:
+                       pr_debug("Error: Cannot write %u bit width to PCC\n",
+                               reg->bit_width);
+                       ret_val = -EFAULT;
+                       break;
+               }
+       } else
+               ret_val = acpi_os_write_memory((acpi_physical_address)reg->address,
+                               val, reg->bit_width);
+       return ret_val;
 }
 
 /**
@@ -604,7 +742,7 @@ int cppc_get_perf_caps(int cpunum, struct cppc_perf_caps *perf_caps)
                        (ref_perf->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) ||
                        (nom_perf->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM)) {
                /* Ring doorbell once to update PCC subspace */
-               if (send_pcc_cmd(CMD_READ)) {
+               if (send_pcc_cmd(CMD_READ) < 0) {
                        ret = -EIO;
                        goto out_err;
                }
@@ -662,7 +800,7 @@ int cppc_get_perf_ctrs(int cpunum, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
        if ((delivered_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) ||
                        (reference_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM)) {
                /* Ring doorbell once to update PCC subspace */
-               if (send_pcc_cmd(CMD_READ)) {
+               if (send_pcc_cmd(CMD_READ) < 0) {
                        ret = -EIO;
                        goto out_err;
                }
@@ -713,6 +851,13 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
 
        spin_lock(&pcc_lock);
 
+       /* If this is PCC reg, check if channel is free before writing */
+       if (desired_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
+               ret = check_pcc_chan();
+               if (ret)
+                       goto busy_channel;
+       }
+
        /*
         * Skip writing MIN/MAX until Linux knows how to come up with
         * useful values.
@@ -722,10 +867,10 @@ int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
        /* Is this a PCC reg ?*/
        if (desired_reg->cpc_entry.reg.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
                /* Ring doorbell so Remote can get our perf request. */
-               if (send_pcc_cmd(CMD_WRITE))
+               if (send_pcc_cmd(CMD_WRITE) < 0)
                        ret = -EIO;
        }
-
+busy_channel:
        spin_unlock(&pcc_lock);
 
        return ret;
index bea8e425a8def6e81e4a7d506b2e38588f7af37b..6c7dd7af789e453ce3d16ae80b849ef38bc4a3c0 100644 (file)
@@ -73,6 +73,9 @@ static ssize_t acpi_ec_write_io(struct file *f, const char __user *buf,
        loff_t init_off = *off;
        int err = 0;
 
+       if (!write_support)
+               return -EINVAL;
+
        if (*off >= EC_SPACE_SIZE)
                return 0;
        if (*off + count >= EC_SPACE_SIZE) {
index 6322db64b4a4b999180e8eb818c5279a0b23ef37..384cfc3083e1d98c544918b49ec517a9399c27a3 100644 (file)
@@ -46,7 +46,7 @@ MODULE_DEVICE_TABLE(acpi, fan_device_ids);
 #ifdef CONFIG_PM_SLEEP
 static int acpi_fan_suspend(struct device *dev);
 static int acpi_fan_resume(struct device *dev);
-static struct dev_pm_ops acpi_fan_pm = {
+static const struct dev_pm_ops acpi_fan_pm = {
        .resume = acpi_fan_resume,
        .freeze = acpi_fan_suspend,
        .thaw = acpi_fan_resume,
index 1e6833a5cd44b6db55b5c9e376eceabfb44b30e0..a37508ef66c1b544dbf2a677c7a4c7608022cd40 100644 (file)
@@ -20,6 +20,7 @@
 
 #define PREFIX "ACPI: "
 
+void acpi_initrd_initialize_tables(void);
 acpi_status acpi_os_initialize1(void);
 void init_acpi_device_notify(void);
 int acpi_scan_init(void);
@@ -29,6 +30,11 @@ void acpi_processor_init(void);
 void acpi_platform_init(void);
 void acpi_pnp_init(void);
 void acpi_int340x_thermal_init(void);
+#ifdef CONFIG_ARM_AMBA
+void acpi_amba_init(void);
+#else
+static inline void acpi_amba_init(void) {}
+#endif
 int acpi_sysfs_init(void);
 void acpi_container_init(void);
 void acpi_memory_hotplug_init(void);
@@ -106,6 +112,7 @@ bool acpi_device_is_present(struct acpi_device *adev);
 bool acpi_device_is_battery(struct acpi_device *adev);
 bool acpi_device_is_first_physical_node(struct acpi_device *adev,
                                        const struct device *dev);
+struct device *acpi_get_first_physical_node(struct acpi_device *adev);
 
 /* --------------------------------------------------------------------------
                      Device Matching and Notification
index ad6d8c6b777e7c83885cc3f854396808153653f3..35947ac8764459ab0cea484d66bb3f7e7589dc82 100644 (file)
@@ -469,37 +469,16 @@ static void nfit_mem_find_spa_bdw(struct acpi_nfit_desc *acpi_desc,
        nfit_mem->bdw = NULL;
 }
 
-static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
+static void nfit_mem_init_bdw(struct acpi_nfit_desc *acpi_desc,
                struct nfit_mem *nfit_mem, struct acpi_nfit_system_address *spa)
 {
        u16 dcr = __to_nfit_memdev(nfit_mem)->region_index;
        struct nfit_memdev *nfit_memdev;
        struct nfit_flush *nfit_flush;
-       struct nfit_dcr *nfit_dcr;
        struct nfit_bdw *nfit_bdw;
        struct nfit_idt *nfit_idt;
        u16 idt_idx, range_index;
 
-       list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
-               if (nfit_dcr->dcr->region_index != dcr)
-                       continue;
-               nfit_mem->dcr = nfit_dcr->dcr;
-               break;
-       }
-
-       if (!nfit_mem->dcr) {
-               dev_dbg(acpi_desc->dev, "SPA %d missing:%s%s\n",
-                               spa->range_index, __to_nfit_memdev(nfit_mem)
-                               ? "" : " MEMDEV", nfit_mem->dcr ? "" : " DCR");
-               return -ENODEV;
-       }
-
-       /*
-        * We've found enough to create an nvdimm, optionally
-        * find an associated BDW
-        */
-       list_add(&nfit_mem->list, &acpi_desc->dimms);
-
        list_for_each_entry(nfit_bdw, &acpi_desc->bdws, list) {
                if (nfit_bdw->bdw->region_index != dcr)
                        continue;
@@ -508,12 +487,12 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
        }
 
        if (!nfit_mem->bdw)
-               return 0;
+               return;
 
        nfit_mem_find_spa_bdw(acpi_desc, nfit_mem);
 
        if (!nfit_mem->spa_bdw)
-               return 0;
+               return;
 
        range_index = nfit_mem->spa_bdw->range_index;
        list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
@@ -538,8 +517,6 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc,
                }
                break;
        }
-
-       return 0;
 }
 
 static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
@@ -548,7 +525,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
        struct nfit_mem *nfit_mem, *found;
        struct nfit_memdev *nfit_memdev;
        int type = nfit_spa_type(spa);
-       u16 dcr;
 
        switch (type) {
        case NFIT_SPA_DCR:
@@ -559,14 +535,18 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
        }
 
        list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
-               int rc;
+               struct nfit_dcr *nfit_dcr;
+               u32 device_handle;
+               u16 dcr;
 
                if (nfit_memdev->memdev->range_index != spa->range_index)
                        continue;
                found = NULL;
                dcr = nfit_memdev->memdev->region_index;
+               device_handle = nfit_memdev->memdev->device_handle;
                list_for_each_entry(nfit_mem, &acpi_desc->dimms, list)
-                       if (__to_nfit_memdev(nfit_mem)->region_index == dcr) {
+                       if (__to_nfit_memdev(nfit_mem)->device_handle
+                                       == device_handle) {
                                found = nfit_mem;
                                break;
                        }
@@ -579,6 +559,31 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
                        if (!nfit_mem)
                                return -ENOMEM;
                        INIT_LIST_HEAD(&nfit_mem->list);
+                       list_add(&nfit_mem->list, &acpi_desc->dimms);
+               }
+
+               list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
+                       if (nfit_dcr->dcr->region_index != dcr)
+                               continue;
+                       /*
+                        * Record the control region for the dimm.  For
+                        * the ACPI 6.1 case, where there are separate
+                        * control regions for the pmem vs blk
+                        * interfaces, be sure to record the extended
+                        * blk details.
+                        */
+                       if (!nfit_mem->dcr)
+                               nfit_mem->dcr = nfit_dcr->dcr;
+                       else if (nfit_mem->dcr->windows == 0
+                                       && nfit_dcr->dcr->windows)
+                               nfit_mem->dcr = nfit_dcr->dcr;
+                       break;
+               }
+
+               if (dcr && !nfit_mem->dcr) {
+                       dev_err(acpi_desc->dev, "SPA %d missing DCR %d\n",
+                                       spa->range_index, dcr);
+                       return -ENODEV;
                }
 
                if (type == NFIT_SPA_DCR) {
@@ -595,6 +600,7 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
                                nfit_mem->idt_dcr = nfit_idt->idt;
                                break;
                        }
+                       nfit_mem_init_bdw(acpi_desc, nfit_mem, spa);
                } else {
                        /*
                         * A single dimm may belong to multiple SPA-PM
@@ -603,13 +609,6 @@ static int nfit_mem_dcr_init(struct acpi_nfit_desc *acpi_desc,
                         */
                        nfit_mem->memdev_pmem = nfit_memdev->memdev;
                }
-
-               if (found)
-                       continue;
-
-               rc = nfit_mem_add(acpi_desc, nfit_mem, spa);
-               if (rc)
-                       return rc;
        }
 
        return 0;
@@ -1504,9 +1503,7 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc,
                case 1:
                        /* ARS unsupported, but we should never get here */
                        return 0;
-               case 2:
-                       return -EINVAL;
-               case 3:
+               case 6:
                        /* ARS is in progress */
                        msleep(1000);
                        break;
@@ -1517,13 +1514,13 @@ static int ars_do_start(struct nvdimm_bus_descriptor *nd_desc,
 }
 
 static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc,
-               struct nd_cmd_ars_status *cmd)
+               struct nd_cmd_ars_status *cmd, u32 size)
 {
        int rc;
 
        while (1) {
                rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, cmd,
-                       sizeof(*cmd));
+                       size);
                if (rc || cmd->status & 0xffff)
                        return -ENXIO;
 
@@ -1538,6 +1535,8 @@ static int ars_get_status(struct nvdimm_bus_descriptor *nd_desc,
                case 2:
                        /* No ARS performed for the current boot */
                        return 0;
+               case 3:
+                       /* TODO: error list overflow support */
                default:
                        return -ENXIO;
                }
@@ -1581,6 +1580,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
        struct nd_cmd_ars_start *ars_start = NULL;
        struct nd_cmd_ars_cap *ars_cap = NULL;
        u64 start, len, cur, remaining;
+       u32 ars_status_size;
        int rc;
 
        ars_cap = kzalloc(sizeof(*ars_cap), GFP_KERNEL);
@@ -1590,14 +1590,21 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
        start = ndr_desc->res->start;
        len = ndr_desc->res->end - ndr_desc->res->start + 1;
 
+       /*
+        * If ARS is unimplemented, unsupported, or if the 'Persistent Memory
+        * Scrub' flag in extended status is not set, skip this but continue
+        * initialization
+        */
        rc = ars_get_cap(nd_desc, ars_cap, start, len);
+       if (rc == -ENOTTY) {
+               dev_dbg(acpi_desc->dev,
+                       "Address Range Scrub is not implemented, won't create an error list\n");
+               rc = 0;
+               goto out;
+       }
        if (rc)
                goto out;
 
-       /*
-        * If ARS is unsupported, or if the 'Persistent Memory Scrub' flag in
-        * extended status is not set, skip this but continue initialization
-        */
        if ((ars_cap->status & 0xffff) ||
                !(ars_cap->status >> 16 & ND_ARS_PERSISTENT)) {
                dev_warn(acpi_desc->dev,
@@ -1610,14 +1617,14 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
         * Check if a full-range ARS has been run. If so, use those results
         * without having to start a new ARS.
         */
-       ars_status = kzalloc(ars_cap->max_ars_out + sizeof(*ars_status),
-                       GFP_KERNEL);
+       ars_status_size = ars_cap->max_ars_out;
+       ars_status = kzalloc(ars_status_size, GFP_KERNEL);
        if (!ars_status) {
                rc = -ENOMEM;
                goto out;
        }
 
-       rc = ars_get_status(nd_desc, ars_status);
+       rc = ars_get_status(nd_desc, ars_status, ars_status_size);
        if (rc)
                goto out;
 
@@ -1647,7 +1654,7 @@ static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
                if (rc)
                        goto out;
 
-               rc = ars_get_status(nd_desc, ars_status);
+               rc = ars_get_status(nd_desc, ars_status, ars_status_size);
                if (rc)
                        goto out;
 
index 67da6fb722740bf9f540c2a7d603460ceb0e2e8f..814d5f83b75e1e73385b59f753c733326957696f 100644 (file)
@@ -602,6 +602,14 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
        return AE_OK;
 }
 
+static void acpi_table_taint(struct acpi_table_header *table)
+{
+       pr_warn(PREFIX
+               "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
+               table->signature, table->oem_table_id);
+       add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
+}
+
 #ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
 #include <linux/earlycpio.h>
 #include <linux/memblock.h>
@@ -636,6 +644,7 @@ static const char * const table_sigs[] = {
 
 #define ACPI_OVERRIDE_TABLES 64
 static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
+static DECLARE_BITMAP(acpi_initrd_installed, ACPI_OVERRIDE_TABLES);
 
 #define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
 
@@ -746,96 +755,125 @@ void __init acpi_initrd_override(void *data, size_t size)
                }
        }
 }
-#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
 
-static void acpi_table_taint(struct acpi_table_header *table)
+acpi_status
+acpi_os_physical_table_override(struct acpi_table_header *existing_table,
+                               acpi_physical_address *address, u32 *length)
 {
-       pr_warn(PREFIX
-               "Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
-               table->signature, table->oem_table_id);
-       add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
-}
+       int table_offset = 0;
+       int table_index = 0;
+       struct acpi_table_header *table;
+       u32 table_length;
 
+       *length = 0;
+       *address = 0;
+       if (!acpi_tables_addr)
+               return AE_OK;
 
-acpi_status
-acpi_os_table_override(struct acpi_table_header * existing_table,
-                      struct acpi_table_header ** new_table)
-{
-       if (!existing_table || !new_table)
-               return AE_BAD_PARAMETER;
+       while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
+               table = acpi_os_map_memory(acpi_tables_addr + table_offset,
+                                          ACPI_HEADER_SIZE);
+               if (table_offset + table->length > all_tables_size) {
+                       acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+                       WARN_ON(1);
+                       return AE_OK;
+               }
 
-       *new_table = NULL;
+               table_length = table->length;
 
-#ifdef CONFIG_ACPI_CUSTOM_DSDT
-       if (strncmp(existing_table->signature, "DSDT", 4) == 0)
-               *new_table = (struct acpi_table_header *)AmlCode;
-#endif
-       if (*new_table != NULL)
+               /* Only override tables matched */
+               if (test_bit(table_index, acpi_initrd_installed) ||
+                   memcmp(existing_table->signature, table->signature, 4) ||
+                   memcmp(table->oem_table_id, existing_table->oem_table_id,
+                          ACPI_OEM_TABLE_ID_SIZE)) {
+                       acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+                       goto next_table;
+               }
+
+               *length = table_length;
+               *address = acpi_tables_addr + table_offset;
                acpi_table_taint(existing_table);
+               acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+               set_bit(table_index, acpi_initrd_installed);
+               break;
+
+next_table:
+               table_offset += table_length;
+               table_index++;
+       }
        return AE_OK;
 }
 
-acpi_status
-acpi_os_physical_table_override(struct acpi_table_header *existing_table,
-                               acpi_physical_address *address,
-                               u32 *table_length)
+void __init acpi_initrd_initialize_tables(void)
 {
-#ifndef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
-       *table_length = 0;
-       *address = 0;
-       return AE_OK;
-#else
        int table_offset = 0;
+       int table_index = 0;
+       u32 table_length;
        struct acpi_table_header *table;
 
-       *table_length = 0;
-       *address = 0;
-
        if (!acpi_tables_addr)
-               return AE_OK;
-
-       do {
-               if (table_offset + ACPI_HEADER_SIZE > all_tables_size) {
-                       WARN_ON(1);
-                       return AE_OK;
-               }
+               return;
 
+       while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
                table = acpi_os_map_memory(acpi_tables_addr + table_offset,
                                           ACPI_HEADER_SIZE);
-
                if (table_offset + table->length > all_tables_size) {
                        acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
                        WARN_ON(1);
-                       return AE_OK;
+                       return;
                }
 
-               table_offset += table->length;
+               table_length = table->length;
 
-               if (memcmp(existing_table->signature, table->signature, 4)) {
-                       acpi_os_unmap_memory(table,
-                                    ACPI_HEADER_SIZE);
-                       continue;
-               }
-
-               /* Only override tables with matching oem id */
-               if (memcmp(table->oem_table_id, existing_table->oem_table_id,
-                          ACPI_OEM_TABLE_ID_SIZE)) {
-                       acpi_os_unmap_memory(table,
-                                    ACPI_HEADER_SIZE);
-                       continue;
+               /* Skip RSDT/XSDT which should only be used for override */
+               if (test_bit(table_index, acpi_initrd_installed) ||
+                   ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) ||
+                   ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) {
+                       acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+                       goto next_table;
                }
 
-               table_offset -= table->length;
-               *table_length = table->length;
+               acpi_table_taint(table);
                acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
-               *address = acpi_tables_addr + table_offset;
-               break;
-       } while (table_offset + ACPI_HEADER_SIZE < all_tables_size);
+               acpi_install_table(acpi_tables_addr + table_offset, TRUE);
+               set_bit(table_index, acpi_initrd_installed);
+next_table:
+               table_offset += table_length;
+               table_index++;
+       }
+}
+#else
+acpi_status
+acpi_os_physical_table_override(struct acpi_table_header *existing_table,
+                               acpi_physical_address *address,
+                               u32 *table_length)
+{
+       *table_length = 0;
+       *address = 0;
+       return AE_OK;
+}
+
+void __init acpi_initrd_initialize_tables(void)
+{
+}
+#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
 
-       if (*address != 0)
+acpi_status
+acpi_os_table_override(struct acpi_table_header *existing_table,
+                      struct acpi_table_header **new_table)
+{
+       if (!existing_table || !new_table)
+               return AE_BAD_PARAMETER;
+
+       *new_table = NULL;
+
+#ifdef CONFIG_ACPI_CUSTOM_DSDT
+       if (strncmp(existing_table->signature, "DSDT", 4) == 0)
+               *new_table = (struct acpi_table_header *)AmlCode;
+#endif
+       if (*new_table != NULL)
                acpi_table_taint(existing_table);
        return AE_OK;
-#endif
 }
 
 static irqreturn_t acpi_irq(int irq, void *dev_id)
index d30184c7f3bcb851c62fe410906160b6e802a631..2c45dd3acc17a4f6d9248e9db7ef4b31e8dbfdb0 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
+#include <linux/interrupt.h>
 
 #define PREFIX "ACPI: "
 
@@ -387,6 +388,23 @@ static inline int acpi_isa_register_gsi(struct pci_dev *dev)
 }
 #endif
 
+static inline bool acpi_pci_irq_valid(struct pci_dev *dev, u8 pin)
+{
+#ifdef CONFIG_X86
+       /*
+        * On x86 irq line 0xff means "unknown" or "no connection"
+        * (PCI 3.0, Section 6.2.4, footnote on page 223).
+        */
+       if (dev->irq == 0xff) {
+               dev->irq = IRQ_NOTCONNECTED;
+               dev_warn(&dev->dev, "PCI INT %c: not connected\n",
+                        pin_name(pin));
+               return false;
+       }
+#endif
+       return true;
+}
+
 int acpi_pci_irq_enable(struct pci_dev *dev)
 {
        struct acpi_prt_entry *entry;
@@ -406,7 +424,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                return 0;
        }
 
-       if (pci_has_managed_irq(dev))
+       if (dev->irq_managed && dev->irq > 0)
                return 0;
 
        entry = acpi_pci_irq_lookup(dev, pin);
@@ -431,11 +449,14 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
        } else
                gsi = -1;
 
-       /*
-        * No IRQ known to the ACPI subsystem - maybe the BIOS / 
-        * driver reported one, then use it. Exit in any case.
-        */
        if (gsi < 0) {
+               /*
+                * No IRQ known to the ACPI subsystem - maybe the BIOS /
+                * driver reported one, then use it. Exit in any case.
+                */
+               if (!acpi_pci_irq_valid(dev, pin))
+                       return 0;
+
                if (acpi_isa_register_gsi(dev))
                        dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
                                 pin_name(pin));
@@ -451,7 +472,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                kfree(entry);
                return rc;
        }
-       pci_set_managed_irq(dev, rc);
+       dev->irq = rc;
+       dev->irq_managed = 1;
 
        if (link)
                snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
@@ -474,9 +496,17 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        u8 pin;
 
        pin = dev->pin;
-       if (!pin || !pci_has_managed_irq(dev))
+       if (!pin || !dev->irq_managed || dev->irq <= 0)
                return;
 
+       /* Keep IOAPIC pin configuration when suspending */
+       if (dev->dev.power.is_prepared)
+               return;
+#ifdef CONFIG_PM
+       if (dev->dev.power.runtime_status == RPM_SUSPENDING)
+               return;
+#endif
+
        entry = acpi_pci_irq_lookup(dev, pin);
        if (!entry)
                return;
@@ -496,6 +526,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
        if (gsi >= 0) {
                acpi_unregister_gsi(gsi);
-               pci_reset_managed_irq(dev);
+               dev->irq_managed = 0;
        }
 }
index fa2863567eed3c944c884245118c0d55d5ec5fdd..ededa909df2fc02eb2b77fb495e43f8e850c5469 100644 (file)
@@ -4,7 +4,6 @@
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  *  Copyright (C) 2002       Dominik Brodowski <devel@brodo.de>
- *  Copyright (c) 2015, The Linux Foundation. All rights reserved.
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -438,6 +437,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
  * enabled system.
  */
 
+#define ACPI_MAX_IRQS          256
 #define ACPI_MAX_ISA_IRQ       16
 
 #define PIRQ_PENALTY_PCI_AVAILABLE     (0)
@@ -447,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
 #define PIRQ_PENALTY_ISA_USED          (16*16*16*16*16)
 #define PIRQ_PENALTY_ISA_ALWAYS                (16*16*16*16*16*16)
 
-static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = {
+static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ0 timer */
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ1 keyboard */
        PIRQ_PENALTY_ISA_ALWAYS,        /* IRQ2 cascade */
@@ -464,68 +464,9 @@ static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = {
        PIRQ_PENALTY_ISA_USED,          /* IRQ13 fpe, sometimes */
        PIRQ_PENALTY_ISA_USED,          /* IRQ14 ide0 */
        PIRQ_PENALTY_ISA_USED,          /* IRQ15 ide1 */
+       /* >IRQ15 */
 };
 
-struct irq_penalty_info {
-       int irq;
-       int penalty;
-       struct list_head node;
-};
-
-static LIST_HEAD(acpi_irq_penalty_list);
-
-static int acpi_irq_get_penalty(int irq)
-{
-       struct irq_penalty_info *irq_info;
-
-       if (irq < ACPI_MAX_ISA_IRQ)
-               return acpi_irq_isa_penalty[irq];
-
-       list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
-               if (irq_info->irq == irq)
-                       return irq_info->penalty;
-       }
-
-       return 0;
-}
-
-static int acpi_irq_set_penalty(int irq, int new_penalty)
-{
-       struct irq_penalty_info *irq_info;
-
-       /* see if this is a ISA IRQ */
-       if (irq < ACPI_MAX_ISA_IRQ) {
-               acpi_irq_isa_penalty[irq] = new_penalty;
-               return 0;
-       }
-
-       /* next, try to locate from the dynamic list */
-       list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
-               if (irq_info->irq == irq) {
-                       irq_info->penalty  = new_penalty;
-                       return 0;
-               }
-       }
-
-       /* nope, let's allocate a slot for this IRQ */
-       irq_info = kzalloc(sizeof(*irq_info), GFP_KERNEL);
-       if (!irq_info)
-               return -ENOMEM;
-
-       irq_info->irq = irq;
-       irq_info->penalty = new_penalty;
-       list_add_tail(&irq_info->node, &acpi_irq_penalty_list);
-
-       return 0;
-}
-
-static void acpi_irq_add_penalty(int irq, int penalty)
-{
-       int curpen = acpi_irq_get_penalty(irq);
-
-       acpi_irq_set_penalty(irq, curpen + penalty);
-}
-
 int __init acpi_irq_penalty_init(void)
 {
        struct acpi_pci_link *link;
@@ -546,16 +487,15 @@ int __init acpi_irq_penalty_init(void)
                            link->irq.possible_count;
 
                        for (i = 0; i < link->irq.possible_count; i++) {
-                               if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) {
-                                       int irqpos = link->irq.possible[i];
-
-                                       acpi_irq_add_penalty(irqpos, penalty);
-                               }
+                               if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
+                                       acpi_irq_penalty[link->irq.
+                                                        possible[i]] +=
+                                           penalty;
                        }
 
                } else if (link->irq.active) {
-                       acpi_irq_add_penalty(link->irq.active,
-                                            PIRQ_PENALTY_PCI_POSSIBLE);
+                       acpi_irq_penalty[link->irq.active] +=
+                           PIRQ_PENALTY_PCI_POSSIBLE;
                }
        }
 
@@ -607,12 +547,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                 * the use of IRQs 9, 10, 11, and >15.
                 */
                for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-                       if (acpi_irq_get_penalty(irq) >
-                           acpi_irq_get_penalty(link->irq.possible[i]))
+                       if (acpi_irq_penalty[irq] >
+                           acpi_irq_penalty[link->irq.possible[i]])
                                irq = link->irq.possible[i];
                }
        }
-       if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
+       if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
                printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
                            "Try pci=noacpi or acpi=off\n",
                            acpi_device_name(link->device),
@@ -628,8 +568,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                            acpi_device_bid(link->device));
                return -ENODEV;
        } else {
-               acpi_irq_add_penalty(link->irq.active, PIRQ_PENALTY_PCI_USING);
-
+               acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
                printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
                       acpi_device_name(link->device),
                       acpi_device_bid(link->device), link->irq.active);
@@ -839,7 +778,7 @@ static void acpi_pci_link_remove(struct acpi_device *device)
 }
 
 /*
- * modify penalty from cmdline
+ * modify acpi_irq_penalty[] from cmdline
  */
 static int __init acpi_irq_penalty_update(char *str, int used)
 {
@@ -857,10 +796,13 @@ static int __init acpi_irq_penalty_update(char *str, int used)
                if (irq < 0)
                        continue;
 
+               if (irq >= ARRAY_SIZE(acpi_irq_penalty))
+                       continue;
+
                if (used)
-                       acpi_irq_add_penalty(irq, PIRQ_PENALTY_ISA_USED);
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
                else
-                       acpi_irq_set_penalty(irq, PIRQ_PENALTY_PCI_AVAILABLE);
+                       acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
 
                if (retval != 2)        /* no next number */
                        break;
@@ -877,15 +819,18 @@ static int __init acpi_irq_penalty_update(char *str, int used)
  */
 void acpi_penalize_isa_irq(int irq, int active)
 {
-       if (irq >= 0)
-               acpi_irq_add_penalty(irq, active ?
-                       PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
+       if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
+               if (active)
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
+               else
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
+       }
 }
 
 bool acpi_isa_irq_available(int irq)
 {
-       return irq >= 0 &&
-               (acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
+       return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
+                           acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
 }
 
 /*
@@ -895,18 +840,13 @@ bool acpi_isa_irq_available(int irq)
  */
 void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
 {
-       int penalty;
-
-       if (irq < 0)
-               return;
-
-       if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
-           polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
-               penalty = PIRQ_PENALTY_ISA_ALWAYS;
-       else
-               penalty = PIRQ_PENALTY_PCI_USING;
-
-       acpi_irq_add_penalty(irq, penalty);
+       if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
+               if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
+                   polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS;
+               else
+                       acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
+       }
 }
 
 /*
index 42df46a86c25ade48ee506e3c1bf1a4182cd1e33..fcd1852dcdee0874e4cefffb14e441921221aab0 100644 (file)
@@ -13,7 +13,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/mfd/intel_soc_pmic.h>
 #include <linux/regmap.h>
@@ -205,7 +205,4 @@ static int __init intel_crc_pmic_opregion_driver_init(void)
 {
        return platform_driver_register(&intel_crc_pmic_opregion_driver);
 }
-module_init(intel_crc_pmic_opregion_driver_init);
-
-MODULE_DESCRIPTION("CrystalCove ACPI operation region driver");
-MODULE_LICENSE("GPL");
+device_initcall(intel_crc_pmic_opregion_driver_init);
index 11154a330f075dc04c0fec99299d6f5000e901be..d2fa8cb82d2bd34aa4cf289cf4888ae65931757d 100644 (file)
@@ -314,7 +314,6 @@ static int __init acpi_processor_driver_init(void)
        if (result < 0)
                return result;
 
-       acpi_processor_syscore_init();
        register_hotcpu_notifier(&acpi_cpu_notifier);
        acpi_thermal_cpufreq_init();
        acpi_processor_ppc_init();
@@ -330,7 +329,6 @@ static void __exit acpi_processor_driver_exit(void)
        acpi_processor_ppc_exit();
        acpi_thermal_cpufreq_exit();
        unregister_hotcpu_notifier(&acpi_cpu_notifier);
-       acpi_processor_syscore_exit();
        driver_unregister(&acpi_processor_driver);
 }
 
index 175c86bee3a95b47934d094a491b842973e2e090..444e3745c8b3baa7acbf445e4a764ba760712e92 100644 (file)
@@ -23,6 +23,7 @@
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
+#define pr_fmt(fmt) "ACPI: " fmt
 
 #include <linux/module.h>
 #include <linux/acpi.h>
@@ -30,7 +31,6 @@
 #include <linux/sched.h>       /* need_resched() */
 #include <linux/tick.h>
 #include <linux/cpuidle.h>
-#include <linux/syscore_ops.h>
 #include <acpi/processor.h>
 
 /*
@@ -43,8 +43,6 @@
 #include <asm/apic.h>
 #endif
 
-#define PREFIX "ACPI: "
-
 #define ACPI_PROCESSOR_CLASS            "processor"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_idle");
@@ -61,8 +59,8 @@ module_param(latency_factor, uint, 0644);
 
 static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
 
-static DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX],
-                                                               acpi_cstate);
+static
+DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate);
 
 static int disabled_by_idle_boot_param(void)
 {
@@ -81,9 +79,9 @@ static int set_max_cstate(const struct dmi_system_id *id)
        if (max_cstate > ACPI_PROCESSOR_MAX_POWER)
                return 0;
 
-       printk(KERN_NOTICE PREFIX "%s detected - limiting to C%ld max_cstate."
-              " Override with \"processor.max_cstate=%d\"\n", id->ident,
-              (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1);
+       pr_notice("%s detected - limiting to C%ld max_cstate."
+                 " Override with \"processor.max_cstate=%d\"\n", id->ident,
+                 (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1);
 
        max_cstate = (long)id->driver_data;
 
@@ -194,42 +192,6 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 
 #endif
 
-#ifdef CONFIG_PM_SLEEP
-static u32 saved_bm_rld;
-
-static int acpi_processor_suspend(void)
-{
-       acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld);
-       return 0;
-}
-
-static void acpi_processor_resume(void)
-{
-       u32 resumed_bm_rld = 0;
-
-       acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld);
-       if (resumed_bm_rld == saved_bm_rld)
-               return;
-
-       acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
-}
-
-static struct syscore_ops acpi_processor_syscore_ops = {
-       .suspend = acpi_processor_suspend,
-       .resume = acpi_processor_resume,
-};
-
-void acpi_processor_syscore_init(void)
-{
-       register_syscore_ops(&acpi_processor_syscore_ops);
-}
-
-void acpi_processor_syscore_exit(void)
-{
-       unregister_syscore_ops(&acpi_processor_syscore_ops);
-}
-#endif /* CONFIG_PM_SLEEP */
-
 #if defined(CONFIG_X86)
 static void tsc_check_state(int state)
 {
@@ -351,7 +313,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
 
        /* There must be at least 2 elements */
        if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) {
-               printk(KERN_ERR PREFIX "not enough elements in _CST\n");
+               pr_err("not enough elements in _CST\n");
                ret = -EFAULT;
                goto end;
        }
@@ -360,7 +322,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
 
        /* Validate number of power states. */
        if (count < 1 || count != cst->package.count - 1) {
-               printk(KERN_ERR PREFIX "count given by _CST is not valid\n");
+               pr_err("count given by _CST is not valid\n");
                ret = -EFAULT;
                goto end;
        }
@@ -469,11 +431,9 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
                 * (From 1 through ACPI_PROCESSOR_MAX_POWER - 1)
                 */
                if (current_count >= (ACPI_PROCESSOR_MAX_POWER - 1)) {
-                       printk(KERN_WARNING
-                              "Limiting number of power states to max (%d)\n",
-                              ACPI_PROCESSOR_MAX_POWER);
-                       printk(KERN_WARNING
-                              "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
+                       pr_warn("Limiting number of power states to max (%d)\n",
+                               ACPI_PROCESSOR_MAX_POWER);
+                       pr_warn("Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n");
                        break;
                }
        }
@@ -1097,8 +1057,8 @@ int acpi_processor_power_init(struct acpi_processor *pr)
                        retval = cpuidle_register_driver(&acpi_idle_driver);
                        if (retval)
                                return retval;
-                       printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
-                                       acpi_idle_driver.name);
+                       pr_debug("%s registered with cpuidle\n",
+                                acpi_idle_driver.name);
                }
 
                dev = kzalloc(sizeof(*dev), GFP_KERNEL);
index 407a3760e8de659863fb4f6cea274a78bf11ff7b..5f28cf7783490e1da56d12378d7c3fba0e52185e 100644 (file)
@@ -1930,6 +1930,7 @@ int __init acpi_scan_init(void)
        acpi_memory_hotplug_init();
        acpi_pnp_init();
        acpi_int340x_thermal_init();
+       acpi_amba_init();
 
        acpi_scan_add_handler(&generic_device_handler);
 
index 9cb975200cacba638ce84b19fbee8d9948459300..fbfcce3b5227e0c4ea90e5838f8762582978ae99 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/reboot.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
+#include <linux/syscore_ops.h>
 #include <asm/io.h>
 #include <trace/events/power.h>
 
@@ -677,6 +678,39 @@ static void acpi_sleep_suspend_setup(void)
 static inline void acpi_sleep_suspend_setup(void) {}
 #endif /* !CONFIG_SUSPEND */
 
+#ifdef CONFIG_PM_SLEEP
+static u32 saved_bm_rld;
+
+static int  acpi_save_bm_rld(void)
+{
+       acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &saved_bm_rld);
+       return 0;
+}
+
+static void  acpi_restore_bm_rld(void)
+{
+       u32 resumed_bm_rld = 0;
+
+       acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_RLD, &resumed_bm_rld);
+       if (resumed_bm_rld == saved_bm_rld)
+               return;
+
+       acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
+}
+
+static struct syscore_ops acpi_sleep_syscore_ops = {
+       .suspend = acpi_save_bm_rld,
+       .resume = acpi_restore_bm_rld,
+};
+
+void acpi_sleep_syscore_init(void)
+{
+       register_syscore_ops(&acpi_sleep_syscore_ops);
+}
+#else
+static inline void acpi_sleep_syscore_init(void) {}
+#endif /* CONFIG_PM_SLEEP */
+
 #ifdef CONFIG_HIBERNATION
 static unsigned long s4_hardware_signature;
 static struct acpi_table_facs *facs;
@@ -839,6 +873,7 @@ int __init acpi_sleep_init(void)
 
        sleep_states[ACPI_STATE_S0] = 1;
 
+       acpi_sleep_syscore_init();
        acpi_sleep_suspend_setup();
        acpi_sleep_hibernate_setup();
 
index 6c0f0794aa82bd007a14effaa21494043e3eb8e1..f49c02442d65c2d2c07fffa97ac79c2df305e917 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/errno.h>
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
+#include "internal.h"
 
 #define ACPI_MAX_TABLES                128
 
@@ -456,6 +457,7 @@ int __init acpi_table_init(void)
        status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
        if (ACPI_FAILURE(status))
                return -EINVAL;
+       acpi_initrd_initialize_tables();
 
        check_multiple_madt();
        return 0;
@@ -484,3 +486,13 @@ static int __init acpi_force_table_verification_setup(char *s)
 }
 
 early_param("acpi_force_table_verification", acpi_force_table_verification_setup);
+
+static int __init acpi_force_32bit_fadt_addr(char *s)
+{
+       pr_info("Forcing 32 Bit FADT addresses\n");
+       acpi_gbl_use32_bit_fadt_addresses = TRUE;
+
+       return 0;
+}
+
+early_param("acpi_force_32bit_fadt_addr", acpi_force_32bit_fadt_addr);
index f2f9873bb5c363699b49459ebc2fcc9a00af0776..f12a72428aacc76eef7a24845fe847ff55919e94 100644 (file)
@@ -201,10 +201,6 @@ acpi_extract_package(union acpi_object *package,
                u8 **pointer = NULL;
                union acpi_object *element = &(package->package.elements[i]);
 
-               if (!element) {
-                       return AE_BAD_DATA;
-               }
-
                switch (element->type) {
 
                case ACPI_TYPE_INTEGER:
index a39e85f9efa98854768f39b01502274401673957..7d00b7a015ead0182feaace6231a8d7fad719b64 100644 (file)
@@ -2074,7 +2074,7 @@ static int binder_thread_write(struct binder_proc *proc,
                        if (get_user(cookie, (binder_uintptr_t __user *)ptr))
                                return -EFAULT;
 
-                       ptr += sizeof(void *);
+                       ptr += sizeof(cookie);
                        list_for_each_entry(w, &proc->delivered_death, entry) {
                                struct binder_ref_death *tmp_death = container_of(w, struct binder_ref_death, work);
 
index 546a3692774f8d3819ef76d9bcc656ef1af1c99d..146dc0b8ec61752c03278cf5121061aaaf4c27ce 100644 (file)
@@ -367,15 +367,21 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
        { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
        { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
        { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
        { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
        { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -1325,6 +1331,44 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 {}
 #endif
 
+#ifdef CONFIG_ARM64
+/*
+ * Due to ERRATA#22536, ThunderX needs to handle HOST_IRQ_STAT differently.
+ * Workaround is to make sure all pending IRQs are served before leaving
+ * handler.
+ */
+static irqreturn_t ahci_thunderx_irq_handler(int irq, void *dev_instance)
+{
+       struct ata_host *host = dev_instance;
+       struct ahci_host_priv *hpriv;
+       unsigned int rc = 0;
+       void __iomem *mmio;
+       u32 irq_stat, irq_masked;
+       unsigned int handled = 1;
+
+       VPRINTK("ENTER\n");
+       hpriv = host->private_data;
+       mmio = hpriv->mmio;
+       irq_stat = readl(mmio + HOST_IRQ_STAT);
+       if (!irq_stat)
+               return IRQ_NONE;
+
+       do {
+               irq_masked = irq_stat & hpriv->port_map;
+               spin_lock(&host->lock);
+               rc = ahci_handle_port_intr(host, irq_masked);
+               if (!rc)
+                       handled = 0;
+               writel(irq_stat, mmio + HOST_IRQ_STAT);
+               irq_stat = readl(mmio + HOST_IRQ_STAT);
+               spin_unlock(&host->lock);
+       } while (irq_stat);
+       VPRINTK("EXIT\n");
+
+       return IRQ_RETVAL(handled);
+}
+#endif
+
 /*
  * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer
  * to single msi.
@@ -1560,6 +1604,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ahci_broken_devslp(pdev))
                hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
 
+#ifdef CONFIG_ARM64
+       if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
+               hpriv->irq_handler = ahci_thunderx_irq_handler;
+#endif
+
        /* save initial config */
        ahci_pci_save_initial_config(pdev, hpriv);
 
index a44c75d4c28452969d4012e973f173fce5db19d9..167ba7e3b92e8fcec115ddcbd1988326e7c67ba5 100644 (file)
@@ -240,8 +240,7 @@ enum {
                                                        error-handling stage) */
        AHCI_HFLAG_NO_DEVSLP            = (1 << 17), /* no device sleep */
        AHCI_HFLAG_NO_FBS               = (1 << 18), /* no FBS */
-       AHCI_HFLAG_EDGE_IRQ             = (1 << 19), /* HOST_IRQ_STAT behaves as
-                                                       Edge Triggered */
+
 #ifdef CONFIG_PCI_MSI
        AHCI_HFLAG_MULTI_MSI            = (1 << 20), /* multiple PCI MSIs */
        AHCI_HFLAG_MULTI_MSIX           = (1 << 21), /* per-port MSI-X */
@@ -361,6 +360,7 @@ struct ahci_host_priv {
         * be overridden anytime before the host is activated.
         */
        void                    (*start_engine)(struct ata_port *ap);
+       irqreturn_t             (*irq_handler)(int irq, void *dev_instance);
 };
 
 #ifdef CONFIG_PCI_MSI
@@ -424,6 +424,7 @@ int ahci_reset_em(struct ata_host *host);
 void ahci_print_info(struct ata_host *host, const char *scc_s);
 int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht);
 void ahci_error_handler(struct ata_port *ap);
+u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked);
 
 static inline void __iomem *__ahci_port_base(struct ata_host *host,
                                             unsigned int port_no)
index e2c6d9e0c5ac5ce5ce389b0ae1b0597ae979ee8b..8e3f7faf00d383f8eea284fe122e90a44ee7ce40 100644 (file)
@@ -548,6 +548,88 @@ softreset_retry:
        return rc;
 }
 
+/**
+ * xgene_ahci_handle_broken_edge_irq - Handle the broken irq.
+ * @ata_host: Host that recieved the irq
+ * @irq_masked: HOST_IRQ_STAT value
+ *
+ * For hardware with broken edge trigger latch
+ * the HOST_IRQ_STAT register misses the edge interrupt
+ * when clearing of HOST_IRQ_STAT register and hardware
+ * reporting the PORT_IRQ_STAT register at the
+ * same clock cycle.
+ * As such, the algorithm below outlines the workaround.
+ *
+ * 1. Read HOST_IRQ_STAT register and save the state.
+ * 2. Clear the HOST_IRQ_STAT register.
+ * 3. Read back the HOST_IRQ_STAT register.
+ * 4. If HOST_IRQ_STAT register equals to zero, then
+ *    traverse the rest of port's PORT_IRQ_STAT register
+ *    to check if an interrupt is triggered at that point else
+ *    go to step 6.
+ * 5. If PORT_IRQ_STAT register of rest ports is not equal to zero
+ *    then update the state of HOST_IRQ_STAT saved in step 1.
+ * 6. Handle port interrupts.
+ * 7. Exit
+ */
+static int xgene_ahci_handle_broken_edge_irq(struct ata_host *host,
+                                            u32 irq_masked)
+{
+       struct ahci_host_priv *hpriv = host->private_data;
+       void __iomem *port_mmio;
+       int i;
+
+       if (!readl(hpriv->mmio + HOST_IRQ_STAT)) {
+               for (i = 0; i < host->n_ports; i++) {
+                       if (irq_masked & (1 << i))
+                               continue;
+
+                       port_mmio = ahci_port_base(host->ports[i]);
+                       if (readl(port_mmio + PORT_IRQ_STAT))
+                               irq_masked |= (1 << i);
+               }
+       }
+
+       return ahci_handle_port_intr(host, irq_masked);
+}
+
+static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance)
+{
+       struct ata_host *host = dev_instance;
+       struct ahci_host_priv *hpriv;
+       unsigned int rc = 0;
+       void __iomem *mmio;
+       u32 irq_stat, irq_masked;
+
+       VPRINTK("ENTER\n");
+
+       hpriv = host->private_data;
+       mmio = hpriv->mmio;
+
+       /* sigh.  0xffffffff is a valid return from h/w */
+       irq_stat = readl(mmio + HOST_IRQ_STAT);
+       if (!irq_stat)
+               return IRQ_NONE;
+
+       irq_masked = irq_stat & hpriv->port_map;
+
+       spin_lock(&host->lock);
+
+       /*
+        * HOST_IRQ_STAT behaves as edge triggered latch meaning that
+        * it should be cleared before all the port events are cleared.
+        */
+       writel(irq_stat, mmio + HOST_IRQ_STAT);
+
+       rc = xgene_ahci_handle_broken_edge_irq(host, irq_masked);
+
+       spin_unlock(&host->lock);
+
+       VPRINTK("EXIT\n");
+
+       return IRQ_RETVAL(rc);
+}
+
 static struct ata_port_operations xgene_ahci_v1_ops = {
        .inherits = &ahci_ops,
        .host_stop = xgene_ahci_host_stop,
@@ -779,7 +861,8 @@ skip_clk_phy:
                hpriv->flags = AHCI_HFLAG_NO_NCQ;
                break;
        case XGENE_AHCI_V2:
-               hpriv->flags |= AHCI_HFLAG_YES_FBS | AHCI_HFLAG_EDGE_IRQ;
+               hpriv->flags |= AHCI_HFLAG_YES_FBS;
+               hpriv->irq_handler = xgene_ahci_irq_intr;
                break;
        default:
                break;
index 402967902cbe341d12e3c0b803bb640f7c1cd48d..85ea5142a09518acc9e5c781fffbbf737f262f31 100644 (file)
@@ -113,6 +113,7 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
                                    const char *buf, size_t size);
 static ssize_t ahci_show_em_supported(struct device *dev,
                                      struct device_attribute *attr, char *buf);
+static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance);
 
 static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
 static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
@@ -512,6 +513,9 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
 
        if (!hpriv->start_engine)
                hpriv->start_engine = ahci_start_engine;
+
+       if (!hpriv->irq_handler)
+               hpriv->irq_handler = ahci_single_level_irq_intr;
 }
 EXPORT_SYMBOL_GPL(ahci_save_initial_config);
 
@@ -1164,8 +1168,7 @@ static void ahci_port_init(struct device *dev, struct ata_port *ap,
 
        /* mark esata ports */
        tmp = readl(port_mmio + PORT_CMD);
-       if ((tmp & PORT_CMD_HPCP) ||
-           ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS)))
+       if ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS))
                ap->pflags |= ATA_PFLAG_EXTERNAL;
 }
 
@@ -1846,7 +1849,7 @@ static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance)
        return IRQ_HANDLED;
 }
 
-static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
+u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
 {
        unsigned int i, handled = 0;
 
@@ -1872,43 +1875,7 @@ static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
 
        return handled;
 }
-
-static irqreturn_t ahci_single_edge_irq_intr(int irq, void *dev_instance)
-{
-       struct ata_host *host = dev_instance;
-       struct ahci_host_priv *hpriv;
-       unsigned int rc = 0;
-       void __iomem *mmio;
-       u32 irq_stat, irq_masked;
-
-       VPRINTK("ENTER\n");
-
-       hpriv = host->private_data;
-       mmio = hpriv->mmio;
-
-       /* sigh.  0xffffffff is a valid return from h/w */
-       irq_stat = readl(mmio + HOST_IRQ_STAT);
-       if (!irq_stat)
-               return IRQ_NONE;
-
-       irq_masked = irq_stat & hpriv->port_map;
-
-       spin_lock(&host->lock);
-
-       /*
-        * HOST_IRQ_STAT behaves as edge triggered latch meaning that
-        * it should be cleared before all the port events are cleared.
-        */
-       writel(irq_stat, mmio + HOST_IRQ_STAT);
-
-       rc = ahci_handle_port_intr(host, irq_masked);
-
-       spin_unlock(&host->lock);
-
-       VPRINTK("EXIT\n");
-
-       return IRQ_RETVAL(rc);
-}
+EXPORT_SYMBOL_GPL(ahci_handle_port_intr);
 
 static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance)
 {
@@ -2535,14 +2502,18 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht)
        int irq = hpriv->irq;
        int rc;
 
-       if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX))
+       if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) {
+               if (hpriv->irq_handler)
+                       dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set \
+                                and custom irq handler implemented\n");
+
                rc = ahci_host_activate_multi_irqs(host, sht);
-       else if (hpriv->flags & AHCI_HFLAG_EDGE_IRQ)
-               rc = ata_host_activate(host, irq, ahci_single_edge_irq_intr,
-                                      IRQF_SHARED, sht);
-       else
-               rc = ata_host_activate(host, irq, ahci_single_level_irq_intr,
+       } else {
+               rc = ata_host_activate(host, irq, hpriv->irq_handler,
                                       IRQF_SHARED, sht);
+       }
+
+
        return rc;
 }
 EXPORT_SYMBOL_GPL(ahci_host_activate);
index 7e959f90c0203f9b94124ab73867e4a72bd11188..e417e1a1d02c568595fa465682ade483a9d0645a 100644 (file)
@@ -675,19 +675,18 @@ static int ata_ioc32(struct ata_port *ap)
 int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
                     int cmd, void __user *arg)
 {
-       int val = -EINVAL, rc = -EINVAL;
+       unsigned long val;
+       int rc = -EINVAL;
        unsigned long flags;
 
        switch (cmd) {
-       case ATA_IOC_GET_IO32:
+       case HDIO_GET_32BIT:
                spin_lock_irqsave(ap->lock, flags);
                val = ata_ioc32(ap);
                spin_unlock_irqrestore(ap->lock, flags);
-               if (copy_to_user(arg, &val, 1))
-                       return -EFAULT;
-               return 0;
+               return put_user(val, (unsigned long __user *)arg);
 
-       case ATA_IOC_SET_IO32:
+       case HDIO_SET_32BIT:
                val = (unsigned long) arg;
                rc = 0;
                spin_lock_irqsave(ap->lock, flags);
index e3d4b059fcd14bcb8f4a9e21809c5cb7d30ededa..e347e7acd8edb440d284d6309187bbb80cd90cd2 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/scatterlist.h>
 #include <linux/of.h>
 #include <linux/gfp.h>
+#include <linux/pci.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -30,7 +31,6 @@
 #include <asm/macio.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
-#include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/mediabay.h>
index 12fe0f3bb7e9b0bf8120af19badf4ddf72903565..c8b6a780a29050775f66ec60bc89773d71677683 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/libata.h>
 #include <scsi/scsi_host.h>
 
+#include <asm/mach-rc32434/rb.h>
+
 #define DRV_NAME       "pata-rb532-cf"
 #define DRV_VERSION    "0.1.0"
 #define DRV_DESC       "PATA driver for RouterBOARD 532 Compact Flash"
@@ -107,6 +109,7 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
        int gpio;
        struct resource *res;
        struct ata_host *ah;
+       struct cf_device *pdata;
        struct rb532_cf_info *info;
        int ret;
 
@@ -122,7 +125,13 @@ static int rb532_pata_driver_probe(struct platform_device *pdev)
                return -ENOENT;
        }
 
-       gpio = irq_to_gpio(irq);
+       pdata = dev_get_platdata(&pdev->dev);
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data specified\n");
+               return -EINVAL;
+       }
+
+       gpio = pdata->gpio_pin;
        if (gpio < 0) {
                dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
                return -ENOENT;
index 213456c2b1236a6eb4949155f087a8d139c5aa4e..f46dba8b7092e305ca6e7b404bbf7a2ef8ce2a12 100644 (file)
@@ -251,7 +251,7 @@ memory_block_action(unsigned long phys_index, unsigned long action, int online_t
        return ret;
 }
 
-static int memory_block_change_state(struct memory_block *mem,
+int memory_block_change_state(struct memory_block *mem,
                unsigned long to_state, unsigned long from_state_req)
 {
        int ret = 0;
@@ -438,6 +438,37 @@ print_block_size(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(block_size_bytes, 0444, print_block_size, NULL);
 
+/*
+ * Memory auto online policy.
+ */
+
+static ssize_t
+show_auto_online_blocks(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       if (memhp_auto_online)
+               return sprintf(buf, "online\n");
+       else
+               return sprintf(buf, "offline\n");
+}
+
+static ssize_t
+store_auto_online_blocks(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       if (sysfs_streq(buf, "online"))
+               memhp_auto_online = true;
+       else if (sysfs_streq(buf, "offline"))
+               memhp_auto_online = false;
+       else
+               return -EINVAL;
+
+       return count;
+}
+
+static DEVICE_ATTR(auto_online_blocks, 0644, show_auto_online_blocks,
+                  store_auto_online_blocks);
+
 /*
  * Some architectures will have custom drivers to do this, and
  * will not need to do it from userspace.  The fake hot-add code
@@ -746,6 +777,7 @@ static struct attribute *memory_root_attrs[] = {
 #endif
 
        &dev_attr_block_size_bytes.attr,
+       &dev_attr_auto_online_blocks.attr,
        NULL
 };
 
index 301b785f9f56f5d00b7f83798b6f7cce53bf0e03..56705b52758efea0fb8a95dab16700b4ecf7930e 100644 (file)
@@ -104,6 +104,7 @@ static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
 
 static int genpd_power_on(struct generic_pm_domain *genpd, bool timed)
 {
+       unsigned int state_idx = genpd->state_idx;
        ktime_t time_start;
        s64 elapsed_ns;
        int ret;
@@ -120,10 +121,10 @@ static int genpd_power_on(struct generic_pm_domain *genpd, bool timed)
                return ret;
 
        elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
-       if (elapsed_ns <= genpd->power_on_latency_ns)
+       if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns)
                return ret;
 
-       genpd->power_on_latency_ns = elapsed_ns;
+       genpd->states[state_idx].power_on_latency_ns = elapsed_ns;
        genpd->max_off_time_changed = true;
        pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
                 genpd->name, "on", elapsed_ns);
@@ -133,6 +134,7 @@ static int genpd_power_on(struct generic_pm_domain *genpd, bool timed)
 
 static int genpd_power_off(struct generic_pm_domain *genpd, bool timed)
 {
+       unsigned int state_idx = genpd->state_idx;
        ktime_t time_start;
        s64 elapsed_ns;
        int ret;
@@ -149,10 +151,10 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool timed)
                return ret;
 
        elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
-       if (elapsed_ns <= genpd->power_off_latency_ns)
+       if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns)
                return ret;
 
-       genpd->power_off_latency_ns = elapsed_ns;
+       genpd->states[state_idx].power_off_latency_ns = elapsed_ns;
        genpd->max_off_time_changed = true;
        pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n",
                 genpd->name, "off", elapsed_ns);
@@ -485,8 +487,13 @@ static int pm_genpd_runtime_resume(struct device *dev)
        if (timed && runtime_pm)
                time_start = ktime_get();
 
-       genpd_start_dev(genpd, dev);
-       genpd_restore_dev(genpd, dev);
+       ret = genpd_start_dev(genpd, dev);
+       if (ret)
+               goto err_poweroff;
+
+       ret = genpd_restore_dev(genpd, dev);
+       if (ret)
+               goto err_stop;
 
        /* Update resume latency value if the measured time exceeds it. */
        if (timed && runtime_pm) {
@@ -501,6 +508,17 @@ static int pm_genpd_runtime_resume(struct device *dev)
        }
 
        return 0;
+
+err_stop:
+       genpd_stop_dev(genpd, dev);
+err_poweroff:
+       if (!dev->power.irq_safe) {
+               mutex_lock(&genpd->lock);
+               genpd_poweroff(genpd, 0);
+               mutex_unlock(&genpd->lock);
+       }
+
+       return ret;
 }
 
 static bool pd_ignore_unused;
@@ -585,6 +603,8 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd,
            || atomic_read(&genpd->sd_count) > 0)
                return;
 
+       /* Choose the deepest state when suspending */
+       genpd->state_idx = genpd->state_count - 1;
        genpd_power_off(genpd, timed);
 
        genpd->status = GPD_STATE_POWER_OFF;
@@ -1378,7 +1398,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
        mutex_lock(&subdomain->lock);
        mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
 
-       if (!list_empty(&subdomain->slave_links) || subdomain->device_count) {
+       if (!list_empty(&subdomain->master_links) || subdomain->device_count) {
                pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
                        subdomain->name);
                ret = -EBUSY;
@@ -1508,6 +1528,20 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
                genpd->dev_ops.start = pm_clk_resume;
        }
 
+       if (genpd->state_idx >= GENPD_MAX_NUM_STATES) {
+               pr_warn("Initial state index out of bounds.\n");
+               genpd->state_idx = GENPD_MAX_NUM_STATES - 1;
+       }
+
+       if (genpd->state_count > GENPD_MAX_NUM_STATES) {
+               pr_warn("Limiting states to  %d\n", GENPD_MAX_NUM_STATES);
+               genpd->state_count = GENPD_MAX_NUM_STATES;
+       }
+
+       /* Use only one "off" state if there were no states declared */
+       if (genpd->state_count == 0)
+               genpd->state_count = 1;
+
        mutex_lock(&gpd_list_lock);
        list_add(&genpd->gpd_list_node, &gpd_list);
        mutex_unlock(&gpd_list_lock);
@@ -1668,6 +1702,9 @@ struct generic_pm_domain *of_genpd_get_from_provider(
        struct generic_pm_domain *genpd = ERR_PTR(-ENOENT);
        struct of_genpd_provider *provider;
 
+       if (!genpdspec)
+               return ERR_PTR(-EINVAL);
+
        mutex_lock(&of_genpd_mutex);
 
        /* Check if we have such a provider in our array */
@@ -1864,6 +1901,7 @@ static int pm_genpd_summary_one(struct seq_file *s,
        struct pm_domain_data *pm_data;
        const char *kobj_path;
        struct gpd_link *link;
+       char state[16];
        int ret;
 
        ret = mutex_lock_interruptible(&genpd->lock);
@@ -1872,7 +1910,13 @@ static int pm_genpd_summary_one(struct seq_file *s,
 
        if (WARN_ON(genpd->status >= ARRAY_SIZE(status_lookup)))
                goto exit;
-       seq_printf(s, "%-30s  %-15s ", genpd->name, status_lookup[genpd->status]);
+       if (genpd->status == GPD_STATE_POWER_OFF)
+               snprintf(state, sizeof(state), "%s-%u",
+                        status_lookup[genpd->status], genpd->state_idx);
+       else
+               snprintf(state, sizeof(state), "%s",
+                        status_lookup[genpd->status]);
+       seq_printf(s, "%-30s  %-15s ", genpd->name, state);
 
        /*
         * Modifications on the list require holding locks on both
index 1e937ac5f45661b6e2af770e1ab9633e91ad7bd6..00a5436dd44b6ca056eab506c5b4f05d17eb5f49 100644 (file)
@@ -98,7 +98,8 @@ static bool default_stop_ok(struct device *dev)
  *
  * This routine must be executed under the PM domain's lock.
  */
-static bool default_power_down_ok(struct dev_pm_domain *pd)
+static bool __default_power_down_ok(struct dev_pm_domain *pd,
+                                    unsigned int state)
 {
        struct generic_pm_domain *genpd = pd_to_genpd(pd);
        struct gpd_link *link;
@@ -106,27 +107,9 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
        s64 min_off_time_ns;
        s64 off_on_time_ns;
 
-       if (genpd->max_off_time_changed) {
-               struct gpd_link *link;
-
-               /*
-                * We have to invalidate the cached results for the masters, so
-                * use the observation that default_power_down_ok() is not
-                * going to be called for any master until this instance
-                * returns.
-                */
-               list_for_each_entry(link, &genpd->slave_links, slave_node)
-                       link->master->max_off_time_changed = true;
-
-               genpd->max_off_time_changed = false;
-               genpd->cached_power_down_ok = false;
-               genpd->max_off_time_ns = -1;
-       } else {
-               return genpd->cached_power_down_ok;
-       }
+       off_on_time_ns = genpd->states[state].power_off_latency_ns +
+               genpd->states[state].power_on_latency_ns;
 
-       off_on_time_ns = genpd->power_off_latency_ns +
-                               genpd->power_on_latency_ns;
 
        min_off_time_ns = -1;
        /*
@@ -186,8 +169,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
                        min_off_time_ns = constraint_ns;
        }
 
-       genpd->cached_power_down_ok = true;
-
        /*
         * If the computed minimum device off time is negative, there are no
         * latency constraints, so the domain can spend arbitrary time in the
@@ -201,10 +182,45 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
         * time and the time needed to turn the domain on is the maximum
         * theoretical time this domain can spend in the "off" state.
         */
-       genpd->max_off_time_ns = min_off_time_ns - genpd->power_on_latency_ns;
+       genpd->max_off_time_ns = min_off_time_ns -
+               genpd->states[state].power_on_latency_ns;
        return true;
 }
 
+static bool default_power_down_ok(struct dev_pm_domain *pd)
+{
+       struct generic_pm_domain *genpd = pd_to_genpd(pd);
+       struct gpd_link *link;
+
+       if (!genpd->max_off_time_changed)
+               return genpd->cached_power_down_ok;
+
+       /*
+        * We have to invalidate the cached results for the masters, so
+        * use the observation that default_power_down_ok() is not
+        * going to be called for any master until this instance
+        * returns.
+        */
+       list_for_each_entry(link, &genpd->slave_links, slave_node)
+               link->master->max_off_time_changed = true;
+
+       genpd->max_off_time_ns = -1;
+       genpd->max_off_time_changed = false;
+       genpd->cached_power_down_ok = true;
+       genpd->state_idx = genpd->state_count - 1;
+
+       /* Find a state to power down to, starting from the deepest. */
+       while (!__default_power_down_ok(pd, genpd->state_idx)) {
+               if (genpd->state_idx == 0) {
+                       genpd->cached_power_down_ok = false;
+                       break;
+               }
+               genpd->state_idx--;
+       }
+
+       return genpd->cached_power_down_ok;
+}
+
 static bool always_on_power_down_ok(struct dev_pm_domain *domain)
 {
        return false;
index cf351d3dab1c3b7a9badf6b468092ca216c47012..433b60092972d56abba55897158d6c22156cf631 100644 (file)
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/of.h>
 #include <linux/export.h>
+#include <linux/regulator/consumer.h>
 
 #include "opp.h"
 
 /*
- * The root of the list of all devices. All device_opp structures branch off
- * from here, with each device_opp containing the list of opp it supports in
+ * The root of the list of all opp-tables. All opp_table structures branch off
+ * from here, with each opp_table containing the list of opps it supports in
  * various states of availability.
  */
-static LIST_HEAD(dev_opp_list);
+static LIST_HEAD(opp_tables);
 /* Lock to allow exclusive modification to the device and opp lists */
-DEFINE_MUTEX(dev_opp_list_lock);
+DEFINE_MUTEX(opp_table_lock);
 
 #define opp_rcu_lockdep_assert()                                       \
 do {                                                                   \
        RCU_LOCKDEP_WARN(!rcu_read_lock_held() &&                       \
-                               !lockdep_is_held(&dev_opp_list_lock),   \
-                          "Missing rcu_read_lock() or "                \
-                          "dev_opp_list_lock protection");             \
+                        !lockdep_is_held(&opp_table_lock),             \
+                        "Missing rcu_read_lock() or "                  \
+                        "opp_table_lock protection");                  \
 } while (0)
 
-static struct device_list_opp *_find_list_dev(const struct device *dev,
-                                             struct device_opp *dev_opp)
+static struct opp_device *_find_opp_dev(const struct device *dev,
+                                       struct opp_table *opp_table)
 {
-       struct device_list_opp *list_dev;
+       struct opp_device *opp_dev;
 
-       list_for_each_entry(list_dev, &dev_opp->dev_list, node)
-               if (list_dev->dev == dev)
-                       return list_dev;
+       list_for_each_entry(opp_dev, &opp_table->dev_list, node)
+               if (opp_dev->dev == dev)
+                       return opp_dev;
 
        return NULL;
 }
 
-static struct device_opp *_managed_opp(const struct device_node *np)
+static struct opp_table *_managed_opp(const struct device_node *np)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
 
-       list_for_each_entry_rcu(dev_opp, &dev_opp_list, node) {
-               if (dev_opp->np == np) {
+       list_for_each_entry_rcu(opp_table, &opp_tables, node) {
+               if (opp_table->np == np) {
                        /*
                         * Multiple devices can point to the same OPP table and
                         * so will have same node-pointer, np.
@@ -64,7 +66,7 @@ static struct device_opp *_managed_opp(const struct device_node *np)
                         * But the OPPs will be considered as shared only if the
                         * OPP table contains a "opp-shared" property.
                         */
-                       return dev_opp->shared_opp ? dev_opp : NULL;
+                       return opp_table->shared_opp ? opp_table : NULL;
                }
        }
 
@@ -72,24 +74,24 @@ static struct device_opp *_managed_opp(const struct device_node *np)
 }
 
 /**
- * _find_device_opp() - find device_opp struct using device pointer
- * @dev:       device pointer used to lookup device OPPs
+ * _find_opp_table() - find opp_table struct using device pointer
+ * @dev:       device pointer used to lookup OPP table
  *
- * Search list of device OPPs for one containing matching device. Does a RCU
- * reader operation to grab the pointer needed.
+ * Search OPP table for one containing matching device. Does a RCU reader
+ * operation to grab the pointer needed.
  *
- * Return: pointer to 'struct device_opp' if found, otherwise -ENODEV or
+ * Return: pointer to 'struct opp_table' if found, otherwise -ENODEV or
  * -EINVAL based on type of error.
  *
  * Locking: For readers, this function must be called under rcu_read_lock().
- * device_opp is a RCU protected pointer, which means that device_opp is valid
+ * opp_table is a RCU protected pointer, which means that opp_table is valid
  * as long as we are under RCU lock.
  *
- * For Writers, this function must be called with dev_opp_list_lock held.
+ * For Writers, this function must be called with opp_table_lock held.
  */
-struct device_opp *_find_device_opp(struct device *dev)
+struct opp_table *_find_opp_table(struct device *dev)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
 
        opp_rcu_lockdep_assert();
 
@@ -98,9 +100,9 @@ struct device_opp *_find_device_opp(struct device *dev)
                return ERR_PTR(-EINVAL);
        }
 
-       list_for_each_entry_rcu(dev_opp, &dev_opp_list, node)
-               if (_find_list_dev(dev, dev_opp))
-                       return dev_opp;
+       list_for_each_entry_rcu(opp_table, &opp_tables, node)
+               if (_find_opp_dev(dev, opp_table))
+                       return opp_table;
 
        return ERR_PTR(-ENODEV);
 }
@@ -213,22 +215,98 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_is_turbo);
  */
 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        unsigned long clock_latency_ns;
 
        rcu_read_lock();
 
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp))
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table))
                clock_latency_ns = 0;
        else
-               clock_latency_ns = dev_opp->clock_latency_ns_max;
+               clock_latency_ns = opp_table->clock_latency_ns_max;
 
        rcu_read_unlock();
        return clock_latency_ns;
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
 
+/**
+ * dev_pm_opp_get_max_volt_latency() - Get max voltage latency in nanoseconds
+ * @dev: device for which we do this operation
+ *
+ * Return: This function returns the max voltage latency in nanoseconds.
+ *
+ * Locking: This function takes rcu_read_lock().
+ */
+unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
+{
+       struct opp_table *opp_table;
+       struct dev_pm_opp *opp;
+       struct regulator *reg;
+       unsigned long latency_ns = 0;
+       unsigned long min_uV = ~0, max_uV = 0;
+       int ret;
+
+       rcu_read_lock();
+
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               rcu_read_unlock();
+               return 0;
+       }
+
+       reg = opp_table->regulator;
+       if (IS_ERR(reg)) {
+               /* Regulator may not be required for device */
+               if (reg)
+                       dev_err(dev, "%s: Invalid regulator (%ld)\n", __func__,
+                               PTR_ERR(reg));
+               rcu_read_unlock();
+               return 0;
+       }
+
+       list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
+               if (!opp->available)
+                       continue;
+
+               if (opp->u_volt_min < min_uV)
+                       min_uV = opp->u_volt_min;
+               if (opp->u_volt_max > max_uV)
+                       max_uV = opp->u_volt_max;
+       }
+
+       rcu_read_unlock();
+
+       /*
+        * The caller needs to ensure that opp_table (and hence the regulator)
+        * isn't freed, while we are executing this routine.
+        */
+       ret = regulator_set_voltage_time(reg, min_uV, max_uV);
+       if (ret > 0)
+               latency_ns = ret * 1000;
+
+       return latency_ns;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_volt_latency);
+
+/**
+ * dev_pm_opp_get_max_transition_latency() - Get max transition latency in
+ *                                          nanoseconds
+ * @dev: device for which we do this operation
+ *
+ * Return: This function returns the max transition latency, in nanoseconds, to
+ * switch from one OPP to other.
+ *
+ * Locking: This function takes rcu_read_lock().
+ */
+unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev)
+{
+       return dev_pm_opp_get_max_volt_latency(dev) +
+               dev_pm_opp_get_max_clock_latency(dev);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_transition_latency);
+
 /**
  * dev_pm_opp_get_suspend_opp() - Get suspend opp
  * @dev:       device for which we do this operation
@@ -244,21 +322,21 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
  */
 struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
 
        opp_rcu_lockdep_assert();
 
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp) || !dev_opp->suspend_opp ||
-           !dev_opp->suspend_opp->available)
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table) || !opp_table->suspend_opp ||
+           !opp_table->suspend_opp->available)
                return NULL;
 
-       return dev_opp->suspend_opp;
+       return opp_table->suspend_opp;
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp);
 
 /**
- * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
+ * dev_pm_opp_get_opp_count() - Get number of opps available in the opp table
  * @dev:       device for which we do this operation
  *
  * Return: This function returns the number of available opps if there are any,
@@ -268,21 +346,21 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_suspend_opp);
  */
 int dev_pm_opp_get_opp_count(struct device *dev)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct dev_pm_opp *temp_opp;
        int count = 0;
 
        rcu_read_lock();
 
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp)) {
-               count = PTR_ERR(dev_opp);
-               dev_err(dev, "%s: device OPP not found (%d)\n",
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               count = PTR_ERR(opp_table);
+               dev_err(dev, "%s: OPP table not found (%d)\n",
                        __func__, count);
                goto out_unlock;
        }
 
-       list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+       list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
                if (temp_opp->available)
                        count++;
        }
@@ -299,7 +377,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count);
  * @freq:              frequency to search for
  * @available:         true/false - match for available opp
  *
- * Return: Searches for exact match in the opp list and returns pointer to the
+ * Return: Searches for exact match in the opp table and returns pointer to the
  * matching opp if found, else returns ERR_PTR in case of error and should
  * be handled using IS_ERR. Error return values can be:
  * EINVAL:     for bad pointer
@@ -323,19 +401,20 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
                                              unsigned long freq,
                                              bool available)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        opp_rcu_lockdep_assert();
 
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp)) {
-               int r = PTR_ERR(dev_opp);
-               dev_err(dev, "%s: device OPP not found (%d)\n", __func__, r);
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               int r = PTR_ERR(opp_table);
+
+               dev_err(dev, "%s: OPP table not found (%d)\n", __func__, r);
                return ERR_PTR(r);
        }
 
-       list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+       list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
                if (temp_opp->available == available &&
                                temp_opp->rate == freq) {
                        opp = temp_opp;
@@ -371,7 +450,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact);
 struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
                                             unsigned long *freq)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        opp_rcu_lockdep_assert();
@@ -381,11 +460,11 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp))
-               return ERR_CAST(dev_opp);
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table))
+               return ERR_CAST(opp_table);
 
-       list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+       list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
                if (temp_opp->available && temp_opp->rate >= *freq) {
                        opp = temp_opp;
                        *freq = opp->rate;
@@ -421,7 +500,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil);
 struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
                                              unsigned long *freq)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        opp_rcu_lockdep_assert();
@@ -431,11 +510,11 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
                return ERR_PTR(-EINVAL);
        }
 
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp))
-               return ERR_CAST(dev_opp);
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table))
+               return ERR_CAST(opp_table);
 
-       list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
+       list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
                if (temp_opp->available) {
                        /* go to the next node, before choosing prev */
                        if (temp_opp->rate > *freq)
@@ -451,130 +530,343 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
-/* List-dev Helpers */
-static void _kfree_list_dev_rcu(struct rcu_head *head)
+/*
+ * The caller needs to ensure that opp_table (and hence the clk) isn't freed,
+ * while clk returned here is used.
+ */
+static struct clk *_get_opp_clk(struct device *dev)
+{
+       struct opp_table *opp_table;
+       struct clk *clk;
+
+       rcu_read_lock();
+
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               dev_err(dev, "%s: device opp doesn't exist\n", __func__);
+               clk = ERR_CAST(opp_table);
+               goto unlock;
+       }
+
+       clk = opp_table->clk;
+       if (IS_ERR(clk))
+               dev_err(dev, "%s: No clock available for the device\n",
+                       __func__);
+
+unlock:
+       rcu_read_unlock();
+       return clk;
+}
+
+static int _set_opp_voltage(struct device *dev, struct regulator *reg,
+                           unsigned long u_volt, unsigned long u_volt_min,
+                           unsigned long u_volt_max)
+{
+       int ret;
+
+       /* Regulator not available for device */
+       if (IS_ERR(reg)) {
+               dev_dbg(dev, "%s: regulator not available: %ld\n", __func__,
+                       PTR_ERR(reg));
+               return 0;
+       }
+
+       dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__, u_volt_min,
+               u_volt, u_volt_max);
+
+       ret = regulator_set_voltage_triplet(reg, u_volt_min, u_volt,
+                                           u_volt_max);
+       if (ret)
+               dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n",
+                       __func__, u_volt_min, u_volt, u_volt_max, ret);
+
+       return ret;
+}
+
+/**
+ * dev_pm_opp_set_rate() - Configure new OPP based on frequency
+ * @dev:        device for which we do this operation
+ * @target_freq: frequency to achieve
+ *
+ * This configures the power-supplies and clock source to the levels specified
+ * by the OPP corresponding to the target_freq.
+ *
+ * Locking: This function takes rcu_read_lock().
+ */
+int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
+{
+       struct opp_table *opp_table;
+       struct dev_pm_opp *old_opp, *opp;
+       struct regulator *reg;
+       struct clk *clk;
+       unsigned long freq, old_freq;
+       unsigned long u_volt, u_volt_min, u_volt_max;
+       unsigned long ou_volt, ou_volt_min, ou_volt_max;
+       int ret;
+
+       if (unlikely(!target_freq)) {
+               dev_err(dev, "%s: Invalid target frequency %lu\n", __func__,
+                       target_freq);
+               return -EINVAL;
+       }
+
+       clk = _get_opp_clk(dev);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       freq = clk_round_rate(clk, target_freq);
+       if ((long)freq <= 0)
+               freq = target_freq;
+
+       old_freq = clk_get_rate(clk);
+
+       /* Return early if nothing to do */
+       if (old_freq == freq) {
+               dev_dbg(dev, "%s: old/new frequencies (%lu Hz) are same, nothing to do\n",
+                       __func__, freq);
+               return 0;
+       }
+
+       rcu_read_lock();
+
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               dev_err(dev, "%s: device opp doesn't exist\n", __func__);
+               rcu_read_unlock();
+               return PTR_ERR(opp_table);
+       }
+
+       old_opp = dev_pm_opp_find_freq_ceil(dev, &old_freq);
+       if (!IS_ERR(old_opp)) {
+               ou_volt = old_opp->u_volt;
+               ou_volt_min = old_opp->u_volt_min;
+               ou_volt_max = old_opp->u_volt_max;
+       } else {
+               dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n",
+                       __func__, old_freq, PTR_ERR(old_opp));
+       }
+
+       opp = dev_pm_opp_find_freq_ceil(dev, &freq);
+       if (IS_ERR(opp)) {
+               ret = PTR_ERR(opp);
+               dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n",
+                       __func__, freq, ret);
+               rcu_read_unlock();
+               return ret;
+       }
+
+       u_volt = opp->u_volt;
+       u_volt_min = opp->u_volt_min;
+       u_volt_max = opp->u_volt_max;
+
+       reg = opp_table->regulator;
+
+       rcu_read_unlock();
+
+       /* Scaling up? Scale voltage before frequency */
+       if (freq > old_freq) {
+               ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min,
+                                      u_volt_max);
+               if (ret)
+                       goto restore_voltage;
+       }
+
+       /* Change frequency */
+
+       dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n",
+               __func__, old_freq, freq);
+
+       ret = clk_set_rate(clk, freq);
+       if (ret) {
+               dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
+                       ret);
+               goto restore_voltage;
+       }
+
+       /* Scaling down? Scale voltage after frequency */
+       if (freq < old_freq) {
+               ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min,
+                                      u_volt_max);
+               if (ret)
+                       goto restore_freq;
+       }
+
+       return 0;
+
+restore_freq:
+       if (clk_set_rate(clk, old_freq))
+               dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
+                       __func__, old_freq);
+restore_voltage:
+       /* This shouldn't harm even if the voltages weren't updated earlier */
+       if (!IS_ERR(old_opp))
+               _set_opp_voltage(dev, reg, ou_volt, ou_volt_min, ou_volt_max);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate);
+
+/* OPP-dev Helpers */
+static void _kfree_opp_dev_rcu(struct rcu_head *head)
 {
-       struct device_list_opp *list_dev;
+       struct opp_device *opp_dev;
 
-       list_dev = container_of(head, struct device_list_opp, rcu_head);
-       kfree_rcu(list_dev, rcu_head);
+       opp_dev = container_of(head, struct opp_device, rcu_head);
+       kfree_rcu(opp_dev, rcu_head);
 }
 
-static void _remove_list_dev(struct device_list_opp *list_dev,
-                            struct device_opp *dev_opp)
+static void _remove_opp_dev(struct opp_device *opp_dev,
+                           struct opp_table *opp_table)
 {
-       opp_debug_unregister(list_dev, dev_opp);
-       list_del(&list_dev->node);
-       call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
-                 _kfree_list_dev_rcu);
+       opp_debug_unregister(opp_dev, opp_table);
+       list_del(&opp_dev->node);
+       call_srcu(&opp_table->srcu_head.srcu, &opp_dev->rcu_head,
+                 _kfree_opp_dev_rcu);
 }
 
-struct device_list_opp *_add_list_dev(const struct device *dev,
-                                     struct device_opp *dev_opp)
+struct opp_device *_add_opp_dev(const struct device *dev,
+                               struct opp_table *opp_table)
 {
-       struct device_list_opp *list_dev;
+       struct opp_device *opp_dev;
        int ret;
 
-       list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
-       if (!list_dev)
+       opp_dev = kzalloc(sizeof(*opp_dev), GFP_KERNEL);
+       if (!opp_dev)
                return NULL;
 
-       /* Initialize list-dev */
-       list_dev->dev = dev;
-       list_add_rcu(&list_dev->node, &dev_opp->dev_list);
+       /* Initialize opp-dev */
+       opp_dev->dev = dev;
+       list_add_rcu(&opp_dev->node, &opp_table->dev_list);
 
-       /* Create debugfs entries for the dev_opp */
-       ret = opp_debug_register(list_dev, dev_opp);
+       /* Create debugfs entries for the opp_table */
+       ret = opp_debug_register(opp_dev, opp_table);
        if (ret)
                dev_err(dev, "%s: Failed to register opp debugfs (%d)\n",
                        __func__, ret);
 
-       return list_dev;
+       return opp_dev;
 }
 
 /**
- * _add_device_opp() - Find device OPP table or allocate a new one
+ * _add_opp_table() - Find OPP table or allocate a new one
  * @dev:       device for which we do this operation
  *
  * It tries to find an existing table first, if it couldn't find one, it
  * allocates a new OPP table and returns that.
  *
- * Return: valid device_opp pointer if success, else NULL.
+ * Return: valid opp_table pointer if success, else NULL.
  */
-static struct device_opp *_add_device_opp(struct device *dev)
+static struct opp_table *_add_opp_table(struct device *dev)
 {
-       struct device_opp *dev_opp;
-       struct device_list_opp *list_dev;
+       struct opp_table *opp_table;
+       struct opp_device *opp_dev;
+       struct device_node *np;
+       int ret;
 
-       /* Check for existing list for 'dev' first */
-       dev_opp = _find_device_opp(dev);
-       if (!IS_ERR(dev_opp))
-               return dev_opp;
+       /* Check for existing table for 'dev' first */
+       opp_table = _find_opp_table(dev);
+       if (!IS_ERR(opp_table))
+               return opp_table;
 
        /*
-        * Allocate a new device OPP table. In the infrequent case where a new
+        * Allocate a new OPP table. In the infrequent case where a new
         * device is needed to be added, we pay this penalty.
         */
-       dev_opp = kzalloc(sizeof(*dev_opp), GFP_KERNEL);
-       if (!dev_opp)
+       opp_table = kzalloc(sizeof(*opp_table), GFP_KERNEL);
+       if (!opp_table)
                return NULL;
 
-       INIT_LIST_HEAD(&dev_opp->dev_list);
+       INIT_LIST_HEAD(&opp_table->dev_list);
 
-       list_dev = _add_list_dev(dev, dev_opp);
-       if (!list_dev) {
-               kfree(dev_opp);
+       opp_dev = _add_opp_dev(dev, opp_table);
+       if (!opp_dev) {
+               kfree(opp_table);
                return NULL;
        }
 
-       srcu_init_notifier_head(&dev_opp->srcu_head);
-       INIT_LIST_HEAD(&dev_opp->opp_list);
+       /*
+        * Only required for backward compatibility with v1 bindings, but isn't
+        * harmful for other cases. And so we do it unconditionally.
+        */
+       np = of_node_get(dev->of_node);
+       if (np) {
+               u32 val;
+
+               if (!of_property_read_u32(np, "clock-latency", &val))
+                       opp_table->clock_latency_ns_max = val;
+               of_property_read_u32(np, "voltage-tolerance",
+                                    &opp_table->voltage_tolerance_v1);
+               of_node_put(np);
+       }
+
+       /* Set regulator to a non-NULL error value */
+       opp_table->regulator = ERR_PTR(-ENXIO);
+
+       /* Find clk for the device */
+       opp_table->clk = clk_get(dev, NULL);
+       if (IS_ERR(opp_table->clk)) {
+               ret = PTR_ERR(opp_table->clk);
+               if (ret != -EPROBE_DEFER)
+                       dev_dbg(dev, "%s: Couldn't find clock: %d\n", __func__,
+                               ret);
+       }
 
-       /* Secure the device list modification */
-       list_add_rcu(&dev_opp->node, &dev_opp_list);
-       return dev_opp;
+       srcu_init_notifier_head(&opp_table->srcu_head);
+       INIT_LIST_HEAD(&opp_table->opp_list);
+
+       /* Secure the device table modification */
+       list_add_rcu(&opp_table->node, &opp_tables);
+       return opp_table;
 }
 
 /**
- * _kfree_device_rcu() - Free device_opp RCU handler
+ * _kfree_device_rcu() - Free opp_table RCU handler
  * @head:      RCU head
  */
 static void _kfree_device_rcu(struct rcu_head *head)
 {
-       struct device_opp *device_opp = container_of(head, struct device_opp, rcu_head);
+       struct opp_table *opp_table = container_of(head, struct opp_table,
+                                                  rcu_head);
 
-       kfree_rcu(device_opp, rcu_head);
+       kfree_rcu(opp_table, rcu_head);
 }
 
 /**
- * _remove_device_opp() - Removes a device OPP table
- * @dev_opp: device OPP table to be removed.
+ * _remove_opp_table() - Removes a OPP table
+ * @opp_table: OPP table to be removed.
  *
- * Removes/frees device OPP table it it doesn't contain any OPPs.
+ * Removes/frees OPP table if it doesn't contain any OPPs.
  */
-static void _remove_device_opp(struct device_opp *dev_opp)
+static void _remove_opp_table(struct opp_table *opp_table)
 {
-       struct device_list_opp *list_dev;
+       struct opp_device *opp_dev;
+
+       if (!list_empty(&opp_table->opp_list))
+               return;
 
-       if (!list_empty(&dev_opp->opp_list))
+       if (opp_table->supported_hw)
                return;
 
-       if (dev_opp->supported_hw)
+       if (opp_table->prop_name)
                return;
 
-       if (dev_opp->prop_name)
+       if (!IS_ERR(opp_table->regulator))
                return;
 
-       list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp,
-                                   node);
+       /* Release clk */
+       if (!IS_ERR(opp_table->clk))
+               clk_put(opp_table->clk);
 
-       _remove_list_dev(list_dev, dev_opp);
+       opp_dev = list_first_entry(&opp_table->dev_list, struct opp_device,
+                                  node);
+
+       _remove_opp_dev(opp_dev, opp_table);
 
        /* dev_list must be empty now */
-       WARN_ON(!list_empty(&dev_opp->dev_list));
+       WARN_ON(!list_empty(&opp_table->dev_list));
 
-       list_del_rcu(&dev_opp->node);
-       call_srcu(&dev_opp->srcu_head.srcu, &dev_opp->rcu_head,
+       list_del_rcu(&opp_table->node);
+       call_srcu(&opp_table->srcu_head.srcu, &opp_table->rcu_head,
                  _kfree_device_rcu);
 }
 
@@ -591,17 +883,17 @@ static void _kfree_opp_rcu(struct rcu_head *head)
 
 /**
  * _opp_remove()  - Remove an OPP from a table definition
- * @dev_opp:   points back to the device_opp struct this opp belongs to
+ * @opp_table: points back to the opp_table struct this opp belongs to
  * @opp:       pointer to the OPP to remove
  * @notify:    OPP_EVENT_REMOVE notification should be sent or not
  *
- * This function removes an opp definition from the opp list.
+ * This function removes an opp definition from the opp table.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * It is assumed that the caller holds required mutex for an RCU updater
  * strategy.
  */
-static void _opp_remove(struct device_opp *dev_opp,
+static void _opp_remove(struct opp_table *opp_table,
                        struct dev_pm_opp *opp, bool notify)
 {
        /*
@@ -609,22 +901,23 @@ static void _opp_remove(struct device_opp *dev_opp,
         * frequency/voltage list.
         */
        if (notify)
-               srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+               srcu_notifier_call_chain(&opp_table->srcu_head,
+                                        OPP_EVENT_REMOVE, opp);
        opp_debug_remove_one(opp);
        list_del_rcu(&opp->node);
-       call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
+       call_srcu(&opp_table->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
-       _remove_device_opp(dev_opp);
+       _remove_opp_table(opp_table);
 }
 
 /**
- * dev_pm_opp_remove()  - Remove an OPP from OPP list
+ * dev_pm_opp_remove()  - Remove an OPP from OPP table
  * @dev:       device for which we do this operation
  * @freq:      OPP to remove with matching 'freq'
  *
- * This function removes an opp from the opp list.
+ * This function removes an opp from the opp table.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -633,17 +926,17 @@ static void _opp_remove(struct device_opp *dev_opp,
 void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 {
        struct dev_pm_opp *opp;
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        bool found = false;
 
-       /* Hold our list modification lock here */
-       mutex_lock(&dev_opp_list_lock);
+       /* Hold our table modification lock here */
+       mutex_lock(&opp_table_lock);
 
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp))
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table))
                goto unlock;
 
-       list_for_each_entry(opp, &dev_opp->opp_list, node) {
+       list_for_each_entry(opp, &opp_table->opp_list, node) {
                if (opp->rate == freq) {
                        found = true;
                        break;
@@ -656,14 +949,14 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
                goto unlock;
        }
 
-       _opp_remove(dev_opp, opp, true);
+       _opp_remove(opp_table, opp, true);
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
 static struct dev_pm_opp *_allocate_opp(struct device *dev,
-                                       struct device_opp **dev_opp)
+                                       struct opp_table **opp_table)
 {
        struct dev_pm_opp *opp;
 
@@ -674,8 +967,8 @@ static struct dev_pm_opp *_allocate_opp(struct device *dev,
 
        INIT_LIST_HEAD(&opp->node);
 
-       *dev_opp = _add_device_opp(dev);
-       if (!*dev_opp) {
+       *opp_table = _add_opp_table(dev);
+       if (!*opp_table) {
                kfree(opp);
                return NULL;
        }
@@ -683,22 +976,38 @@ static struct dev_pm_opp *_allocate_opp(struct device *dev,
        return opp;
 }
 
+static bool _opp_supported_by_regulators(struct dev_pm_opp *opp,
+                                        struct opp_table *opp_table)
+{
+       struct regulator *reg = opp_table->regulator;
+
+       if (!IS_ERR(reg) &&
+           !regulator_is_supported_voltage(reg, opp->u_volt_min,
+                                           opp->u_volt_max)) {
+               pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
+                       __func__, opp->u_volt_min, opp->u_volt_max);
+               return false;
+       }
+
+       return true;
+}
+
 static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
-                   struct device_opp *dev_opp)
+                   struct opp_table *opp_table)
 {
        struct dev_pm_opp *opp;
-       struct list_head *head = &dev_opp->opp_list;
+       struct list_head *head = &opp_table->opp_list;
        int ret;
 
        /*
         * Insert new OPP in order of increasing frequency and discard if
         * already present.
         *
-        * Need to use &dev_opp->opp_list in the condition part of the 'for'
+        * Need to use &opp_table->opp_list in the condition part of the 'for'
         * loop, don't replace it with head otherwise it will become an infinite
         * loop.
         */
-       list_for_each_entry_rcu(opp, &dev_opp->opp_list, node) {
+       list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
                if (new_opp->rate > opp->rate) {
                        head = &opp->node;
                        continue;
@@ -716,14 +1025,20 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
                        0 : -EEXIST;
        }
 
-       new_opp->dev_opp = dev_opp;
+       new_opp->opp_table = opp_table;
        list_add_rcu(&new_opp->node, head);
 
-       ret = opp_debug_create_one(new_opp, dev_opp);
+       ret = opp_debug_create_one(new_opp, opp_table);
        if (ret)
                dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n",
                        __func__, ret);
 
+       if (!_opp_supported_by_regulators(new_opp, opp_table)) {
+               new_opp->available = false;
+               dev_warn(dev, "%s: OPP not supported by regulators (%lu)\n",
+                        __func__, new_opp->rate);
+       }
+
        return 0;
 }
 
@@ -734,14 +1049,14 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
  * @u_volt:    Voltage in uVolts for this OPP
  * @dynamic:   Dynamically added OPPs.
  *
- * This function adds an opp definition to the opp list and returns status.
+ * This function adds an opp definition to the opp table and returns status.
  * The opp is made available by default and it can be controlled using
  * dev_pm_opp_enable/disable functions and may be removed by dev_pm_opp_remove.
  *
  * NOTE: "dynamic" parameter impacts OPPs added by the dev_pm_opp_of_add_table
  * and freed by dev_pm_opp_of_remove_table.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -757,14 +1072,15 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
 static int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
                       bool dynamic)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct dev_pm_opp *new_opp;
+       unsigned long tol;
        int ret;
 
-       /* Hold our list modification lock here */
-       mutex_lock(&dev_opp_list_lock);
+       /* Hold our table modification lock here */
+       mutex_lock(&opp_table_lock);
 
-       new_opp = _allocate_opp(dev, &dev_opp);
+       new_opp = _allocate_opp(dev, &opp_table);
        if (!new_opp) {
                ret = -ENOMEM;
                goto unlock;
@@ -772,33 +1088,36 @@ static int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
 
        /* populate the opp table */
        new_opp->rate = freq;
+       tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
        new_opp->u_volt = u_volt;
+       new_opp->u_volt_min = u_volt - tol;
+       new_opp->u_volt_max = u_volt + tol;
        new_opp->available = true;
        new_opp->dynamic = dynamic;
 
-       ret = _opp_add(dev, new_opp, dev_opp);
+       ret = _opp_add(dev, new_opp, opp_table);
        if (ret)
                goto free_opp;
 
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 
        /*
         * Notify the changes in the availability of the operable
         * frequency/voltage list.
         */
-       srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
+       srcu_notifier_call_chain(&opp_table->srcu_head, OPP_EVENT_ADD, new_opp);
        return 0;
 
 free_opp:
-       _opp_remove(dev_opp, new_opp, false);
+       _opp_remove(opp_table, new_opp, false);
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
        return ret;
 }
 
 /* TODO: Support multiple regulators */
 static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
-                             struct device_opp *dev_opp)
+                             struct opp_table *opp_table)
 {
        u32 microvolt[3] = {0};
        u32 val;
@@ -807,9 +1126,9 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
        char name[NAME_MAX];
 
        /* Search for "opp-microvolt-<name>" */
-       if (dev_opp->prop_name) {
+       if (opp_table->prop_name) {
                snprintf(name, sizeof(name), "opp-microvolt-%s",
-                        dev_opp->prop_name);
+                        opp_table->prop_name);
                prop = of_find_property(opp->np, name, NULL);
        }
 
@@ -844,14 +1163,20 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
        }
 
        opp->u_volt = microvolt[0];
-       opp->u_volt_min = microvolt[1];
-       opp->u_volt_max = microvolt[2];
+
+       if (count == 1) {
+               opp->u_volt_min = opp->u_volt;
+               opp->u_volt_max = opp->u_volt;
+       } else {
+               opp->u_volt_min = microvolt[1];
+               opp->u_volt_max = microvolt[2];
+       }
 
        /* Search for "opp-microamp-<name>" */
        prop = NULL;
-       if (dev_opp->prop_name) {
+       if (opp_table->prop_name) {
                snprintf(name, sizeof(name), "opp-microamp-%s",
-                        dev_opp->prop_name);
+                        opp_table->prop_name);
                prop = of_find_property(opp->np, name, NULL);
        }
 
@@ -878,7 +1203,7 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
  * OPPs, which are available for those versions, based on its 'opp-supported-hw'
  * property.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -887,44 +1212,44 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
 int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
                                unsigned int count)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        int ret = 0;
 
-       /* Hold our list modification lock here */
-       mutex_lock(&dev_opp_list_lock);
+       /* Hold our table modification lock here */
+       mutex_lock(&opp_table_lock);
 
-       dev_opp = _add_device_opp(dev);
-       if (!dev_opp) {
+       opp_table = _add_opp_table(dev);
+       if (!opp_table) {
                ret = -ENOMEM;
                goto unlock;
        }
 
-       /* Make sure there are no concurrent readers while updating dev_opp */
-       WARN_ON(!list_empty(&dev_opp->opp_list));
+       /* Make sure there are no concurrent readers while updating opp_table */
+       WARN_ON(!list_empty(&opp_table->opp_list));
 
-       /* Do we already have a version hierarchy associated with dev_opp? */
-       if (dev_opp->supported_hw) {
+       /* Do we already have a version hierarchy associated with opp_table? */
+       if (opp_table->supported_hw) {
                dev_err(dev, "%s: Already have supported hardware list\n",
                        __func__);
                ret = -EBUSY;
                goto err;
        }
 
-       dev_opp->supported_hw = kmemdup(versions, count * sizeof(*versions),
+       opp_table->supported_hw = kmemdup(versions, count * sizeof(*versions),
                                        GFP_KERNEL);
-       if (!dev_opp->supported_hw) {
+       if (!opp_table->supported_hw) {
                ret = -ENOMEM;
                goto err;
        }
 
-       dev_opp->supported_hw_count = count;
-       mutex_unlock(&dev_opp_list_lock);
+       opp_table->supported_hw_count = count;
+       mutex_unlock(&opp_table_lock);
        return 0;
 
 err:
-       _remove_device_opp(dev_opp);
+       _remove_opp_table(opp_table);
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 
        return ret;
 }
@@ -932,13 +1257,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_supported_hw);
 
 /**
  * dev_pm_opp_put_supported_hw() - Releases resources blocked for supported hw
- * @dev: Device for which supported-hw has to be set.
+ * @dev: Device for which supported-hw has to be put.
  *
  * This is required only for the V2 bindings, and is called for a matching
- * dev_pm_opp_set_supported_hw(). Until this is called, the device_opp structure
+ * dev_pm_opp_set_supported_hw(). Until this is called, the opp_table structure
  * will not be freed.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -946,42 +1271,43 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_supported_hw);
  */
 void dev_pm_opp_put_supported_hw(struct device *dev)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
 
-       /* Hold our list modification lock here */
-       mutex_lock(&dev_opp_list_lock);
+       /* Hold our table modification lock here */
+       mutex_lock(&opp_table_lock);
 
-       /* Check for existing list for 'dev' first */
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp)) {
-               dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp));
+       /* Check for existing table for 'dev' first */
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               dev_err(dev, "Failed to find opp_table: %ld\n",
+                       PTR_ERR(opp_table));
                goto unlock;
        }
 
-       /* Make sure there are no concurrent readers while updating dev_opp */
-       WARN_ON(!list_empty(&dev_opp->opp_list));
+       /* Make sure there are no concurrent readers while updating opp_table */
+       WARN_ON(!list_empty(&opp_table->opp_list));
 
-       if (!dev_opp->supported_hw) {
+       if (!opp_table->supported_hw) {
                dev_err(dev, "%s: Doesn't have supported hardware list\n",
                        __func__);
                goto unlock;
        }
 
-       kfree(dev_opp->supported_hw);
-       dev_opp->supported_hw = NULL;
-       dev_opp->supported_hw_count = 0;
+       kfree(opp_table->supported_hw);
+       opp_table->supported_hw = NULL;
+       opp_table->supported_hw_count = 0;
 
-       /* Try freeing device_opp if this was the last blocking resource */
-       _remove_device_opp(dev_opp);
+       /* Try freeing opp_table if this was the last blocking resource */
+       _remove_opp_table(opp_table);
 
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw);
 
 /**
  * dev_pm_opp_set_prop_name() - Set prop-extn name
- * @dev: Device for which the regulator has to be set.
+ * @dev: Device for which the prop-name has to be set.
  * @name: name to postfix to properties.
  *
  * This is required only for the V2 bindings, and it enables a platform to
@@ -989,7 +1315,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw);
  * which the extension will apply are opp-microvolt and opp-microamp. OPP core
  * should postfix the property name with -<name> while looking for them.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -997,42 +1323,42 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw);
  */
 int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        int ret = 0;
 
-       /* Hold our list modification lock here */
-       mutex_lock(&dev_opp_list_lock);
+       /* Hold our table modification lock here */
+       mutex_lock(&opp_table_lock);
 
-       dev_opp = _add_device_opp(dev);
-       if (!dev_opp) {
+       opp_table = _add_opp_table(dev);
+       if (!opp_table) {
                ret = -ENOMEM;
                goto unlock;
        }
 
-       /* Make sure there are no concurrent readers while updating dev_opp */
-       WARN_ON(!list_empty(&dev_opp->opp_list));
+       /* Make sure there are no concurrent readers while updating opp_table */
+       WARN_ON(!list_empty(&opp_table->opp_list));
 
-       /* Do we already have a prop-name associated with dev_opp? */
-       if (dev_opp->prop_name) {
+       /* Do we already have a prop-name associated with opp_table? */
+       if (opp_table->prop_name) {
                dev_err(dev, "%s: Already have prop-name %s\n", __func__,
-                       dev_opp->prop_name);
+                       opp_table->prop_name);
                ret = -EBUSY;
                goto err;
        }
 
-       dev_opp->prop_name = kstrdup(name, GFP_KERNEL);
-       if (!dev_opp->prop_name) {
+       opp_table->prop_name = kstrdup(name, GFP_KERNEL);
+       if (!opp_table->prop_name) {
                ret = -ENOMEM;
                goto err;
        }
 
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
        return 0;
 
 err:
-       _remove_device_opp(dev_opp);
+       _remove_opp_table(opp_table);
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 
        return ret;
 }
@@ -1040,13 +1366,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_prop_name);
 
 /**
  * dev_pm_opp_put_prop_name() - Releases resources blocked for prop-name
- * @dev: Device for which the regulator has to be set.
+ * @dev: Device for which the prop-name has to be put.
  *
  * This is required only for the V2 bindings, and is called for a matching
- * dev_pm_opp_set_prop_name(). Until this is called, the device_opp structure
+ * dev_pm_opp_set_prop_name(). Until this is called, the opp_table structure
  * will not be freed.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -1054,45 +1380,154 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_prop_name);
  */
 void dev_pm_opp_put_prop_name(struct device *dev)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
 
-       /* Hold our list modification lock here */
-       mutex_lock(&dev_opp_list_lock);
+       /* Hold our table modification lock here */
+       mutex_lock(&opp_table_lock);
 
-       /* Check for existing list for 'dev' first */
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp)) {
-               dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp));
+       /* Check for existing table for 'dev' first */
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               dev_err(dev, "Failed to find opp_table: %ld\n",
+                       PTR_ERR(opp_table));
                goto unlock;
        }
 
-       /* Make sure there are no concurrent readers while updating dev_opp */
-       WARN_ON(!list_empty(&dev_opp->opp_list));
+       /* Make sure there are no concurrent readers while updating opp_table */
+       WARN_ON(!list_empty(&opp_table->opp_list));
 
-       if (!dev_opp->prop_name) {
+       if (!opp_table->prop_name) {
                dev_err(dev, "%s: Doesn't have a prop-name\n", __func__);
                goto unlock;
        }
 
-       kfree(dev_opp->prop_name);
-       dev_opp->prop_name = NULL;
+       kfree(opp_table->prop_name);
+       opp_table->prop_name = NULL;
 
-       /* Try freeing device_opp if this was the last blocking resource */
-       _remove_device_opp(dev_opp);
+       /* Try freeing opp_table if this was the last blocking resource */
+       _remove_opp_table(opp_table);
 
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
 
-static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp,
+/**
+ * dev_pm_opp_set_regulator() - Set regulator name for the device
+ * @dev: Device for which regulator name is being set.
+ * @name: Name of the regulator.
+ *
+ * In order to support OPP switching, OPP layer needs to know the name of the
+ * device's regulator, as the core would be required to switch voltages as well.
+ *
+ * This must be called before any OPPs are initialized for the device.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_set_regulator(struct device *dev, const char *name)
+{
+       struct opp_table *opp_table;
+       struct regulator *reg;
+       int ret;
+
+       mutex_lock(&opp_table_lock);
+
+       opp_table = _add_opp_table(dev);
+       if (!opp_table) {
+               ret = -ENOMEM;
+               goto unlock;
+       }
+
+       /* This should be called before OPPs are initialized */
+       if (WARN_ON(!list_empty(&opp_table->opp_list))) {
+               ret = -EBUSY;
+               goto err;
+       }
+
+       /* Already have a regulator set */
+       if (WARN_ON(!IS_ERR(opp_table->regulator))) {
+               ret = -EBUSY;
+               goto err;
+       }
+       /* Allocate the regulator */
+       reg = regulator_get_optional(dev, name);
+       if (IS_ERR(reg)) {
+               ret = PTR_ERR(reg);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "%s: no regulator (%s) found: %d\n",
+                               __func__, name, ret);
+               goto err;
+       }
+
+       opp_table->regulator = reg;
+
+       mutex_unlock(&opp_table_lock);
+       return 0;
+
+err:
+       _remove_opp_table(opp_table);
+unlock:
+       mutex_unlock(&opp_table_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator);
+
+/**
+ * dev_pm_opp_put_regulator() - Releases resources blocked for regulator
+ * @dev: Device for which regulator was set.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_put_regulator(struct device *dev)
+{
+       struct opp_table *opp_table;
+
+       mutex_lock(&opp_table_lock);
+
+       /* Check for existing table for 'dev' first */
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               dev_err(dev, "Failed to find opp_table: %ld\n",
+                       PTR_ERR(opp_table));
+               goto unlock;
+       }
+
+       if (IS_ERR(opp_table->regulator)) {
+               dev_err(dev, "%s: Doesn't have regulator set\n", __func__);
+               goto unlock;
+       }
+
+       /* Make sure there are no concurrent readers while updating opp_table */
+       WARN_ON(!list_empty(&opp_table->opp_list));
+
+       regulator_put(opp_table->regulator);
+       opp_table->regulator = ERR_PTR(-ENXIO);
+
+       /* Try freeing opp_table if this was the last blocking resource */
+       _remove_opp_table(opp_table);
+
+unlock:
+       mutex_unlock(&opp_table_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulator);
+
+static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
                              struct device_node *np)
 {
-       unsigned int count = dev_opp->supported_hw_count;
+       unsigned int count = opp_table->supported_hw_count;
        u32 version;
        int ret;
 
-       if (!dev_opp->supported_hw)
+       if (!opp_table->supported_hw)
                return true;
 
        while (count--) {
@@ -1105,7 +1540,7 @@ static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp,
                }
 
                /* Both of these are bitwise masks of the versions */
-               if (!(version & dev_opp->supported_hw[count]))
+               if (!(version & opp_table->supported_hw[count]))
                        return false;
        }
 
@@ -1117,11 +1552,11 @@ static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp,
  * @dev:       device for which we do this operation
  * @np:                device node
  *
- * This function adds an opp definition to the opp list and returns status. The
+ * This function adds an opp definition to the opp table and returns status. The
  * opp can be controlled using dev_pm_opp_enable/disable functions and may be
  * removed by dev_pm_opp_remove.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -1137,16 +1572,16 @@ static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp,
  */
 static int _opp_add_static_v2(struct device *dev, struct device_node *np)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct dev_pm_opp *new_opp;
        u64 rate;
        u32 val;
        int ret;
 
-       /* Hold our list modification lock here */
-       mutex_lock(&dev_opp_list_lock);
+       /* Hold our table modification lock here */
+       mutex_lock(&opp_table_lock);
 
-       new_opp = _allocate_opp(dev, &dev_opp);
+       new_opp = _allocate_opp(dev, &opp_table);
        if (!new_opp) {
                ret = -ENOMEM;
                goto unlock;
@@ -1159,7 +1594,7 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
        }
 
        /* Check if the OPP supports hardware's hierarchy of versions or not */
-       if (!_opp_is_supported(dev, dev_opp, np)) {
+       if (!_opp_is_supported(dev, opp_table, np)) {
                dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
                goto free_opp;
        }
@@ -1179,30 +1614,30 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
        if (!of_property_read_u32(np, "clock-latency-ns", &val))
                new_opp->clock_latency_ns = val;
 
-       ret = opp_parse_supplies(new_opp, dev, dev_opp);
+       ret = opp_parse_supplies(new_opp, dev, opp_table);
        if (ret)
                goto free_opp;
 
-       ret = _opp_add(dev, new_opp, dev_opp);
+       ret = _opp_add(dev, new_opp, opp_table);
        if (ret)
                goto free_opp;
 
        /* OPP to select on device suspend */
        if (of_property_read_bool(np, "opp-suspend")) {
-               if (dev_opp->suspend_opp) {
+               if (opp_table->suspend_opp) {
                        dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
-                                __func__, dev_opp->suspend_opp->rate,
+                                __func__, opp_table->suspend_opp->rate,
                                 new_opp->rate);
                } else {
                        new_opp->suspend = true;
-                       dev_opp->suspend_opp = new_opp;
+                       opp_table->suspend_opp = new_opp;
                }
        }
 
-       if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
-               dev_opp->clock_latency_ns_max = new_opp->clock_latency_ns;
+       if (new_opp->clock_latency_ns > opp_table->clock_latency_ns_max)
+               opp_table->clock_latency_ns_max = new_opp->clock_latency_ns;
 
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 
        pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
                 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
@@ -1213,13 +1648,13 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np)
         * Notify the changes in the availability of the operable
         * frequency/voltage list.
         */
-       srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ADD, new_opp);
+       srcu_notifier_call_chain(&opp_table->srcu_head, OPP_EVENT_ADD, new_opp);
        return 0;
 
 free_opp:
-       _opp_remove(dev_opp, new_opp, false);
+       _opp_remove(opp_table, new_opp, false);
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
        return ret;
 }
 
@@ -1229,11 +1664,11 @@ unlock:
  * @freq:      Frequency in Hz for this OPP
  * @u_volt:    Voltage in uVolts for this OPP
  *
- * This function adds an opp definition to the opp list and returns status.
+ * This function adds an opp definition to the opp table and returns status.
  * The opp is made available by default and it can be controlled using
  * dev_pm_opp_enable/disable functions.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -1265,7 +1700,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_add);
  * copy operation, returns 0 if no modification was done OR modification was
  * successful.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks to
  * keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -1274,7 +1709,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_add);
 static int _opp_set_availability(struct device *dev, unsigned long freq,
                                 bool availability_req)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
        int r = 0;
 
@@ -1283,18 +1718,18 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
        if (!new_opp)
                return -ENOMEM;
 
-       mutex_lock(&dev_opp_list_lock);
+       mutex_lock(&opp_table_lock);
 
-       /* Find the device_opp */
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp)) {
-               r = PTR_ERR(dev_opp);
+       /* Find the opp_table */
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               r = PTR_ERR(opp_table);
                dev_warn(dev, "%s: Device OPP not found (%d)\n", __func__, r);
                goto unlock;
        }
 
        /* Do we have the frequency? */
-       list_for_each_entry(tmp_opp, &dev_opp->opp_list, node) {
+       list_for_each_entry(tmp_opp, &opp_table->opp_list, node) {
                if (tmp_opp->rate == freq) {
                        opp = tmp_opp;
                        break;
@@ -1315,21 +1750,21 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
        new_opp->available = availability_req;
 
        list_replace_rcu(&opp->node, &new_opp->node);
-       mutex_unlock(&dev_opp_list_lock);
-       call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
+       mutex_unlock(&opp_table_lock);
+       call_srcu(&opp_table->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
 
        /* Notify the change of the OPP availability */
        if (availability_req)
-               srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_ENABLE,
-                                        new_opp);
+               srcu_notifier_call_chain(&opp_table->srcu_head,
+                                        OPP_EVENT_ENABLE, new_opp);
        else
-               srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_DISABLE,
-                                        new_opp);
+               srcu_notifier_call_chain(&opp_table->srcu_head,
+                                        OPP_EVENT_DISABLE, new_opp);
 
        return 0;
 
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
        kfree(new_opp);
        return r;
 }
@@ -1343,7 +1778,7 @@ unlock:
  * corresponding error value. It is meant to be used for users an OPP available
  * after being temporarily made unavailable with dev_pm_opp_disable.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function indirectly uses RCU and mutex locks to keep the
  * integrity of the internal data structures. Callers should ensure that
  * this function is *NOT* called under RCU protection or in contexts where
@@ -1369,7 +1804,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_enable);
  * control by users to make this OPP not available until the circumstances are
  * right to make it available again (with a call to dev_pm_opp_enable).
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function indirectly uses RCU and mutex locks to keep the
  * integrity of the internal data structures. Callers should ensure that
  * this function is *NOT* called under RCU protection or in contexts where
@@ -1387,26 +1822,26 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_disable);
 
 /**
  * dev_pm_opp_get_notifier() - find notifier_head of the device with opp
- * @dev:       device pointer used to lookup device OPPs.
+ * @dev:       device pointer used to lookup OPP table.
  *
  * Return: pointer to  notifier head if found, otherwise -ENODEV or
  * -EINVAL based on type of error casted as pointer. value must be checked
  *  with IS_ERR to determine valid pointer or error result.
  *
- * Locking: This function must be called under rcu_read_lock(). dev_opp is a RCU
- * protected pointer. The reason for the same is that the opp pointer which is
- * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * Locking: This function must be called under rcu_read_lock(). opp_table is a
+ * RCU protected pointer. The reason for the same is that the opp pointer which
+ * is returned will remain valid for use with opp_get_{voltage, freq} only while
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
 struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev)
 {
-       struct device_opp *dev_opp = _find_device_opp(dev);
+       struct opp_table *opp_table = _find_opp_table(dev);
 
-       if (IS_ERR(dev_opp))
-               return ERR_CAST(dev_opp); /* matching type */
+       if (IS_ERR(opp_table))
+               return ERR_CAST(opp_table); /* matching type */
 
-       return &dev_opp->srcu_head;
+       return &opp_table->srcu_head;
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
 
@@ -1414,11 +1849,11 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
 /**
  * dev_pm_opp_of_remove_table() - Free OPP table entries created from static DT
  *                               entries
- * @dev:       device pointer used to lookup device OPPs.
+ * @dev:       device pointer used to lookup OPP table.
  *
  * Free OPPs created using static entries present in DT.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function indirectly uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
@@ -1426,38 +1861,38 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
  */
 void dev_pm_opp_of_remove_table(struct device *dev)
 {
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct dev_pm_opp *opp, *tmp;
 
-       /* Hold our list modification lock here */
-       mutex_lock(&dev_opp_list_lock);
+       /* Hold our table modification lock here */
+       mutex_lock(&opp_table_lock);
 
-       /* Check for existing list for 'dev' */
-       dev_opp = _find_device_opp(dev);
-       if (IS_ERR(dev_opp)) {
-               int error = PTR_ERR(dev_opp);
+       /* Check for existing table for 'dev' */
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table)) {
+               int error = PTR_ERR(opp_table);
 
                if (error != -ENODEV)
-                       WARN(1, "%s: dev_opp: %d\n",
+                       WARN(1, "%s: opp_table: %d\n",
                             IS_ERR_OR_NULL(dev) ?
                                        "Invalid device" : dev_name(dev),
                             error);
                goto unlock;
        }
 
-       /* Find if dev_opp manages a single device */
-       if (list_is_singular(&dev_opp->dev_list)) {
+       /* Find if opp_table manages a single device */
+       if (list_is_singular(&opp_table->dev_list)) {
                /* Free static OPPs */
-               list_for_each_entry_safe(opp, tmp, &dev_opp->opp_list, node) {
+               list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) {
                        if (!opp->dynamic)
-                               _opp_remove(dev_opp, opp, true);
+                               _opp_remove(opp_table, opp, true);
                }
        } else {
-               _remove_list_dev(_find_list_dev(dev, dev_opp), dev_opp);
+               _remove_opp_dev(_find_opp_dev(dev, opp_table), opp_table);
        }
 
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
 
@@ -1478,22 +1913,22 @@ struct device_node *_of_get_opp_desc_node(struct device *dev)
 static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
 {
        struct device_node *np;
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        int ret = 0, count = 0;
 
-       mutex_lock(&dev_opp_list_lock);
+       mutex_lock(&opp_table_lock);
 
-       dev_opp = _managed_opp(opp_np);
-       if (dev_opp) {
+       opp_table = _managed_opp(opp_np);
+       if (opp_table) {
                /* OPPs are already managed */
-               if (!_add_list_dev(dev, dev_opp))
+               if (!_add_opp_dev(dev, opp_table))
                        ret = -ENOMEM;
-               mutex_unlock(&dev_opp_list_lock);
+               mutex_unlock(&opp_table_lock);
                return ret;
        }
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 
-       /* We have opp-list node now, iterate over it and add OPPs */
+       /* We have opp-table node now, iterate over it and add OPPs */
        for_each_available_child_of_node(opp_np, np) {
                count++;
 
@@ -1509,19 +1944,19 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
        if (WARN_ON(!count))
                return -ENOENT;
 
-       mutex_lock(&dev_opp_list_lock);
+       mutex_lock(&opp_table_lock);
 
-       dev_opp = _find_device_opp(dev);
-       if (WARN_ON(IS_ERR(dev_opp))) {
-               ret = PTR_ERR(dev_opp);
-               mutex_unlock(&dev_opp_list_lock);
+       opp_table = _find_opp_table(dev);
+       if (WARN_ON(IS_ERR(opp_table))) {
+               ret = PTR_ERR(opp_table);
+               mutex_unlock(&opp_table_lock);
                goto free_table;
        }
 
-       dev_opp->np = opp_np;
-       dev_opp->shared_opp = of_property_read_bool(opp_np, "opp-shared");
+       opp_table->np = opp_np;
+       opp_table->shared_opp = of_property_read_bool(opp_np, "opp-shared");
 
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 
        return 0;
 
@@ -1550,7 +1985,7 @@ static int _of_add_opp_table_v1(struct device *dev)
         */
        nr = prop->length / sizeof(u32);
        if (nr % 2) {
-               dev_err(dev, "%s: Invalid OPP list\n", __func__);
+               dev_err(dev, "%s: Invalid OPP table\n", __func__);
                return -EINVAL;
        }
 
@@ -1570,11 +2005,11 @@ static int _of_add_opp_table_v1(struct device *dev)
 
 /**
  * dev_pm_opp_of_add_table() - Initialize opp table from device tree
- * @dev:       device pointer used to lookup device OPPs.
+ * @dev:       device pointer used to lookup OPP table.
  *
  * Register the initial OPP table with the OPP library for given device.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function indirectly uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
index 9f0c15570f64c4db0447570a6d4f1856f48d6cde..ba2bdbd932ef3c1ebaff47c6203bddb27fe9c03b 100644 (file)
@@ -31,7 +31,7 @@
  * @table:     Cpufreq table returned back to caller
  *
  * Generate a cpufreq table for a provided device- this assumes that the
- * opp list is already initialized and ready for usage.
+ * opp table is already initialized and ready for usage.
  *
  * This function allocates required memory for the cpufreq table. It is
  * expected that the caller does the required maintenance such as freeing
@@ -44,7 +44,7 @@
  * WARNING: It is  important for the callers to ensure refreshing their copy of
  * the table if any of the mentioned functions have been invoked in the interim.
  *
- * Locking: The internal device_opp and opp structures are RCU protected.
+ * Locking: The internal opp_table and opp structures are RCU protected.
  * Since we just use the regular accessor functions to access the internal data
  * structures, we use RCU read lock inside this function. As a result, users of
  * this function DONOT need to use explicit locks for invoking.
@@ -122,15 +122,15 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
 /* Required only for V1 bindings, as v2 can manage it from DT itself */
 int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
 {
-       struct device_list_opp *list_dev;
-       struct device_opp *dev_opp;
+       struct opp_device *opp_dev;
+       struct opp_table *opp_table;
        struct device *dev;
        int cpu, ret = 0;
 
-       mutex_lock(&dev_opp_list_lock);
+       mutex_lock(&opp_table_lock);
 
-       dev_opp = _find_device_opp(cpu_dev);
-       if (IS_ERR(dev_opp)) {
+       opp_table = _find_opp_table(cpu_dev);
+       if (IS_ERR(opp_table)) {
                ret = -EINVAL;
                goto unlock;
        }
@@ -146,15 +146,15 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
                        continue;
                }
 
-               list_dev = _add_list_dev(dev, dev_opp);
-               if (!list_dev) {
-                       dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
+               opp_dev = _add_opp_dev(dev, opp_table);
+               if (!opp_dev) {
+                       dev_err(dev, "%s: failed to add opp-dev for cpu%d device\n",
                                __func__, cpu);
                        continue;
                }
        }
 unlock:
-       mutex_unlock(&dev_opp_list_lock);
+       mutex_unlock(&opp_table_lock);
 
        return ret;
 }
index ddfe4773e922a022ae00769d4e946a3498aab0f9..ef1ae6b5204273c62edba051dfcd9566d067c3be 100644 (file)
@@ -34,9 +34,9 @@ void opp_debug_remove_one(struct dev_pm_opp *opp)
        debugfs_remove_recursive(opp->dentry);
 }
 
-int opp_debug_create_one(struct dev_pm_opp *opp, struct device_opp *dev_opp)
+int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
 {
-       struct dentry *pdentry = dev_opp->dentry;
+       struct dentry *pdentry = opp_table->dentry;
        struct dentry *d;
        char name[25];  /* 20 chars for 64 bit value + 5 (opp:\0) */
 
@@ -83,52 +83,52 @@ int opp_debug_create_one(struct dev_pm_opp *opp, struct device_opp *dev_opp)
        return 0;
 }
 
-static int device_opp_debug_create_dir(struct device_list_opp *list_dev,
-                                      struct device_opp *dev_opp)
+static int opp_list_debug_create_dir(struct opp_device *opp_dev,
+                                    struct opp_table *opp_table)
 {
-       const struct device *dev = list_dev->dev;
+       const struct device *dev = opp_dev->dev;
        struct dentry *d;
 
-       opp_set_dev_name(dev, dev_opp->dentry_name);
+       opp_set_dev_name(dev, opp_table->dentry_name);
 
        /* Create device specific directory */
-       d = debugfs_create_dir(dev_opp->dentry_name, rootdir);
+       d = debugfs_create_dir(opp_table->dentry_name, rootdir);
        if (!d) {
                dev_err(dev, "%s: Failed to create debugfs dir\n", __func__);
                return -ENOMEM;
        }
 
-       list_dev->dentry = d;
-       dev_opp->dentry = d;
+       opp_dev->dentry = d;
+       opp_table->dentry = d;
 
        return 0;
 }
 
-static int device_opp_debug_create_link(struct device_list_opp *list_dev,
-                                       struct device_opp *dev_opp)
+static int opp_list_debug_create_link(struct opp_device *opp_dev,
+                                     struct opp_table *opp_table)
 {
-       const struct device *dev = list_dev->dev;
+       const struct device *dev = opp_dev->dev;
        char name[NAME_MAX];
        struct dentry *d;
 
-       opp_set_dev_name(list_dev->dev, name);
+       opp_set_dev_name(opp_dev->dev, name);
 
        /* Create device specific directory link */
-       d = debugfs_create_symlink(name, rootdir, dev_opp->dentry_name);
+       d = debugfs_create_symlink(name, rootdir, opp_table->dentry_name);
        if (!d) {
                dev_err(dev, "%s: Failed to create link\n", __func__);
                return -ENOMEM;
        }
 
-       list_dev->dentry = d;
+       opp_dev->dentry = d;
 
        return 0;
 }
 
 /**
  * opp_debug_register - add a device opp node to the debugfs 'opp' directory
- * @list_dev: list-dev pointer for device
- * @dev_opp: the device-opp being added
+ * @opp_dev: opp-dev pointer for device
+ * @opp_table: the device-opp being added
  *
  * Dynamically adds device specific directory in debugfs 'opp' directory. If the
  * device-opp is shared with other devices, then links will be created for all
@@ -136,73 +136,72 @@ static int device_opp_debug_create_link(struct device_list_opp *list_dev,
  *
  * Return: 0 on success, otherwise negative error.
  */
-int opp_debug_register(struct device_list_opp *list_dev,
-                      struct device_opp *dev_opp)
+int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table)
 {
        if (!rootdir) {
                pr_debug("%s: Uninitialized rootdir\n", __func__);
                return -EINVAL;
        }
 
-       if (dev_opp->dentry)
-               return device_opp_debug_create_link(list_dev, dev_opp);
+       if (opp_table->dentry)
+               return opp_list_debug_create_link(opp_dev, opp_table);
 
-       return device_opp_debug_create_dir(list_dev, dev_opp);
+       return opp_list_debug_create_dir(opp_dev, opp_table);
 }
 
-static void opp_migrate_dentry(struct device_list_opp *list_dev,
-                              struct device_opp *dev_opp)
+static void opp_migrate_dentry(struct opp_device *opp_dev,
+                              struct opp_table *opp_table)
 {
-       struct device_list_opp *new_dev;
+       struct opp_device *new_dev;
        const struct device *dev;
        struct dentry *dentry;
 
-       /* Look for next list-dev */
-       list_for_each_entry(new_dev, &dev_opp->dev_list, node)
-               if (new_dev != list_dev)
+       /* Look for next opp-dev */
+       list_for_each_entry(new_dev, &opp_table->dev_list, node)
+               if (new_dev != opp_dev)
                        break;
 
        /* new_dev is guaranteed to be valid here */
        dev = new_dev->dev;
        debugfs_remove_recursive(new_dev->dentry);
 
-       opp_set_dev_name(dev, dev_opp->dentry_name);
+       opp_set_dev_name(dev, opp_table->dentry_name);
 
-       dentry = debugfs_rename(rootdir, list_dev->dentry, rootdir,
-                               dev_opp->dentry_name);
+       dentry = debugfs_rename(rootdir, opp_dev->dentry, rootdir,
+                               opp_table->dentry_name);
        if (!dentry) {
                dev_err(dev, "%s: Failed to rename link from: %s to %s\n",
-                       __func__, dev_name(list_dev->dev), dev_name(dev));
+                       __func__, dev_name(opp_dev->dev), dev_name(dev));
                return;
        }
 
        new_dev->dentry = dentry;
-       dev_opp->dentry = dentry;
+       opp_table->dentry = dentry;
 }
 
 /**
  * opp_debug_unregister - remove a device opp node from debugfs opp directory
- * @list_dev: list-dev pointer for device
- * @dev_opp: the device-opp being removed
+ * @opp_dev: opp-dev pointer for device
+ * @opp_table: the device-opp being removed
  *
  * Dynamically removes device specific directory from debugfs 'opp' directory.
  */
-void opp_debug_unregister(struct device_list_opp *list_dev,
-                         struct device_opp *dev_opp)
+void opp_debug_unregister(struct opp_device *opp_dev,
+                         struct opp_table *opp_table)
 {
-       if (list_dev->dentry == dev_opp->dentry) {
+       if (opp_dev->dentry == opp_table->dentry) {
                /* Move the real dentry object under another device */
-               if (!list_is_singular(&dev_opp->dev_list)) {
-                       opp_migrate_dentry(list_dev, dev_opp);
+               if (!list_is_singular(&opp_table->dev_list)) {
+                       opp_migrate_dentry(opp_dev, opp_table);
                        goto out;
                }
-               dev_opp->dentry = NULL;
+               opp_table->dentry = NULL;
        }
 
-       debugfs_remove_recursive(list_dev->dentry);
+       debugfs_remove_recursive(opp_dev->dentry);
 
 out:
-       list_dev->dentry = NULL;
+       opp_dev->dentry = NULL;
 }
 
 static int __init opp_debug_init(void)
index 690638ef36ee534c1ab9a57d8c4c7ee840f78a51..f67f806fcf3ae8f13866336cdc54958bd57f59b9 100644 (file)
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
 
+struct clk;
+struct regulator;
+
 /* Lock to allow exclusive modification to the device and opp lists */
-extern struct mutex dev_opp_list_lock;
+extern struct mutex opp_table_lock;
 
 /*
  * Internal data structure organization with the OPP layer library is as
  * follows:
- * dev_opp_list (root)
+ * opp_tables (root)
  *     |- device 1 (represents voltage domain 1)
  *     |       |- opp 1 (availability, freq, voltage)
  *     |       |- opp 2 ..
@@ -37,18 +40,18 @@ extern struct mutex dev_opp_list_lock;
  *     |- device 2 (represents the next voltage domain)
  *     ...
  *     `- device m (represents mth voltage domain)
- * device 1, 2.. are represented by dev_opp structure while each opp
+ * device 1, 2.. are represented by opp_table structure while each opp
  * is represented by the opp structure.
  */
 
 /**
  * struct dev_pm_opp - Generic OPP description structure
- * @node:      opp list node. The nodes are maintained throughout the lifetime
+ * @node:      opp table node. The nodes are maintained throughout the lifetime
  *             of boot. It is expected only an optimal set of OPPs are
  *             added to the library by the SoC framework.
- *             RCU usage: opp list is traversed with RCU locks. node
+ *             RCU usage: opp table is traversed with RCU locks. node
  *             modification is possible realtime, hence the modifications
- *             are protected by the dev_opp_list_lock for integrity.
+ *             are protected by the opp_table_lock for integrity.
  *             IMPORTANT: the opp nodes should be maintained in increasing
  *             order.
  * @available: true/false - marks if this OPP as available or not
@@ -62,7 +65,7 @@ extern struct mutex dev_opp_list_lock;
  * @u_amp:     Maximum current drawn by the device in microamperes
  * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
  *             frequency from any other OPP's frequency.
- * @dev_opp:   points back to the device_opp struct this opp belongs to
+ * @opp_table: points back to the opp_table struct this opp belongs to
  * @rcu_head:  RCU callback head used for deferred freeing
  * @np:                OPP's device node.
  * @dentry:    debugfs dentry pointer (per opp)
@@ -84,7 +87,7 @@ struct dev_pm_opp {
        unsigned long u_amp;
        unsigned long clock_latency_ns;
 
-       struct device_opp *dev_opp;
+       struct opp_table *opp_table;
        struct rcu_head rcu_head;
 
        struct device_node *np;
@@ -95,16 +98,16 @@ struct dev_pm_opp {
 };
 
 /**
- * struct device_list_opp - devices managed by 'struct device_opp'
+ * struct opp_device - devices managed by 'struct opp_table'
  * @node:      list node
  * @dev:       device to which the struct object belongs
  * @rcu_head:  RCU callback head used for deferred freeing
  * @dentry:    debugfs dentry pointer (per device)
  *
- * This is an internal data structure maintaining the list of devices that are
- * managed by 'struct device_opp'.
+ * This is an internal data structure maintaining the devices that are managed
+ * by 'struct opp_table'.
  */
-struct device_list_opp {
+struct opp_device {
        struct list_head node;
        const struct device *dev;
        struct rcu_head rcu_head;
@@ -115,16 +118,16 @@ struct device_list_opp {
 };
 
 /**
- * struct device_opp - Device opp structure
- * @node:      list node - contains the devices with OPPs that
+ * struct opp_table - Device opp structure
+ * @node:      table node - contains the devices with OPPs that
  *             have been registered. Nodes once added are not modified in this
- *             list.
- *             RCU usage: nodes are not modified in the list of device_opp,
- *             however addition is possible and is secured by dev_opp_list_lock
+ *             table.
+ *             RCU usage: nodes are not modified in the table of opp_table,
+ *             however addition is possible and is secured by opp_table_lock
  * @srcu_head: notifier head to notify the OPP availability changes.
  * @rcu_head:  RCU callback head used for deferred freeing
  * @dev_list:  list of devices that share these OPPs
- * @opp_list:  list of opps
+ * @opp_list:  table of opps
  * @np:                struct device_node pointer for opp's DT node.
  * @clock_latency_ns_max: Max clock latency in nanoseconds.
  * @shared_opp: OPP is shared between multiple devices.
@@ -132,9 +135,13 @@ struct device_list_opp {
  * @supported_hw: Array of version number to support.
  * @supported_hw_count: Number of elements in supported_hw array.
  * @prop_name: A name to postfix to many DT properties, while parsing them.
+ * @clk: Device's clock handle
+ * @regulator: Supply regulator
  * @dentry:    debugfs dentry pointer of the real device directory (not links).
  * @dentry_name: Name of the real dentry.
  *
+ * @voltage_tolerance_v1: In percentage, for v1 bindings only.
+ *
  * This is an internal data structure maintaining the link to opps attached to
  * a device. This structure is not meant to be shared to users as it is
  * meant for book keeping and private to OPP library.
@@ -143,7 +150,7 @@ struct device_list_opp {
  * need to wait for the grace period of both of them before freeing any
  * resources. And so we have used kfree_rcu() from within call_srcu() handlers.
  */
-struct device_opp {
+struct opp_table {
        struct list_head node;
 
        struct srcu_notifier_head srcu_head;
@@ -153,12 +160,18 @@ struct device_opp {
 
        struct device_node *np;
        unsigned long clock_latency_ns_max;
+
+       /* For backward compatibility with v1 bindings */
+       unsigned int voltage_tolerance_v1;
+
        bool shared_opp;
        struct dev_pm_opp *suspend_opp;
 
        unsigned int *supported_hw;
        unsigned int supported_hw_count;
        const char *prop_name;
+       struct clk *clk;
+       struct regulator *regulator;
 
 #ifdef CONFIG_DEBUG_FS
        struct dentry *dentry;
@@ -167,30 +180,27 @@ struct device_opp {
 };
 
 /* Routines internal to opp core */
-struct device_opp *_find_device_opp(struct device *dev);
-struct device_list_opp *_add_list_dev(const struct device *dev,
-                                     struct device_opp *dev_opp);
+struct opp_table *_find_opp_table(struct device *dev);
+struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
 struct device_node *_of_get_opp_desc_node(struct device *dev);
 
 #ifdef CONFIG_DEBUG_FS
 void opp_debug_remove_one(struct dev_pm_opp *opp);
-int opp_debug_create_one(struct dev_pm_opp *opp, struct device_opp *dev_opp);
-int opp_debug_register(struct device_list_opp *list_dev,
-                      struct device_opp *dev_opp);
-void opp_debug_unregister(struct device_list_opp *list_dev,
-                         struct device_opp *dev_opp);
+int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table);
+int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
+void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table);
 #else
 static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {}
 
 static inline int opp_debug_create_one(struct dev_pm_opp *opp,
-                                      struct device_opp *dev_opp)
+                                      struct opp_table *opp_table)
 { return 0; }
-static inline int opp_debug_register(struct device_list_opp *list_dev,
-                                    struct device_opp *dev_opp)
+static inline int opp_debug_register(struct opp_device *opp_dev,
+                                    struct opp_table *opp_table)
 { return 0; }
 
-static inline void opp_debug_unregister(struct device_list_opp *list_dev,
-                                       struct device_opp *dev_opp)
+static inline void opp_debug_unregister(struct opp_device *opp_dev,
+                                       struct opp_table *opp_table)
 { }
 #endif         /* DEBUG_FS */
 
index a311cfa4c5bd7ca45e944293e0dd8c8a30cbf947..a6975795e7f3c7cb9b815a15355ecb466ac3aa65 100644 (file)
@@ -166,14 +166,14 @@ void generate_pm_trace(const void *tracedata, unsigned int user)
 }
 EXPORT_SYMBOL(generate_pm_trace);
 
-extern char __tracedata_start, __tracedata_end;
+extern char __tracedata_start[], __tracedata_end[];
 static int show_file_hash(unsigned int value)
 {
        int match;
        char *tracedata;
 
        match = 0;
-       for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ;
+       for (tracedata = __tracedata_start ; tracedata < __tracedata_end ;
                        tracedata += 2 + sizeof(unsigned long)) {
                unsigned short lineno = *(unsigned short *)tracedata;
                const char *file = *(const char **)(tracedata + 2);
index c359351d50f1c99e9758b74ea84d97e76b402b0f..76628a7b45f1efb81fb43cc9ec63d85885883692 100644 (file)
@@ -218,7 +218,8 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
        bool ret;
 
        ret = __fwnode_property_present(fwnode, propname);
-       if (ret == false && fwnode && fwnode->secondary)
+       if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
+           !IS_ERR_OR_NULL(fwnode->secondary))
                ret = __fwnode_property_present(fwnode->secondary, propname);
        return ret;
 }
@@ -423,7 +424,8 @@ EXPORT_SYMBOL_GPL(device_property_match_string);
        int _ret_;                                                                      \
        _ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_,              \
                                 _val_, _nval_);                                        \
-       if (_ret_ == -EINVAL && _fwnode_ && _fwnode_->secondary)                        \
+       if (_ret_ == -EINVAL && !IS_ERR_OR_NULL(_fwnode_) &&                            \
+           !IS_ERR_OR_NULL(_fwnode_->secondary))                                       \
                _ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_,       \
                                _proptype_, _val_, _nval_);                             \
        _ret_;                                                                          \
@@ -593,7 +595,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
        int ret;
 
        ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
-       if (ret == -EINVAL && fwnode && fwnode->secondary)
+       if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
+           !IS_ERR_OR_NULL(fwnode->secondary))
                ret = __fwnode_property_read_string_array(fwnode->secondary,
                                                          propname, val, nval);
        return ret;
@@ -621,7 +624,8 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode,
        int ret;
 
        ret = __fwnode_property_read_string(fwnode, propname, val);
-       if (ret == -EINVAL && fwnode && fwnode->secondary)
+       if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
+           !IS_ERR_OR_NULL(fwnode->secondary))
                ret = __fwnode_property_read_string(fwnode->secondary,
                                                    propname, val);
        return ret;
@@ -820,11 +824,16 @@ void device_remove_property_set(struct device *dev)
         * the pset. If there is no real firmware node (ACPI/DT) primary
         * will hold the pset.
         */
-       if (!is_pset_node(fwnode))
-               fwnode = fwnode->secondary;
-       if (!IS_ERR(fwnode) && is_pset_node(fwnode))
+       if (is_pset_node(fwnode)) {
+               set_primary_fwnode(dev, NULL);
                pset_free_set(to_pset_node(fwnode));
-       set_secondary_fwnode(dev, NULL);
+       } else {
+               fwnode = fwnode->secondary;
+               if (!IS_ERR(fwnode) && is_pset_node(fwnode)) {
+                       set_secondary_fwnode(dev, NULL);
+                       pset_free_set(to_pset_node(fwnode));
+               }
+       }
 }
 EXPORT_SYMBOL_GPL(device_remove_property_set);
 
index 3df977054781bcf4d836abf128268da70952436c..5c79526245c2e3309a28766b781a9f2bccc850d5 100644 (file)
@@ -110,6 +110,7 @@ struct regmap {
        /* number of bits to (left) shift the reg value when formatting*/
        int reg_shift;
        int reg_stride;
+       int reg_stride_order;
 
        /* regcache specific members */
        const struct regcache_ops *cache_ops;
@@ -263,4 +264,19 @@ static inline const char *regmap_name(const struct regmap *map)
        return map->name;
 }
 
+static inline unsigned int regmap_get_offset(const struct regmap *map,
+                                            unsigned int index)
+{
+       if (map->reg_stride_order >= 0)
+               return index << map->reg_stride_order;
+       else
+               return index * map->reg_stride;
+}
+
+static inline unsigned int regcache_get_index_by_order(const struct regmap *map,
+                                                      unsigned int reg)
+{
+       return reg >> map->reg_stride_order;
+}
+
 #endif
index 686c9e0b930eff7db5fb5ea01d8760cdf4d5901f..3ee72550b1e3b4ddc8cbaae9c89d0f39778da6d3 100644 (file)
 
 #include "internal.h"
 
+static inline unsigned int regcache_flat_get_index(const struct regmap *map,
+                                                  unsigned int reg)
+{
+       return regcache_get_index_by_order(map, reg);
+}
+
 static int regcache_flat_init(struct regmap *map)
 {
        int i;
        unsigned int *cache;
 
-       map->cache = kcalloc(map->max_register + 1, sizeof(unsigned int),
-                            GFP_KERNEL);
+       if (!map || map->reg_stride_order < 0)
+               return -EINVAL;
+
+       map->cache = kcalloc(regcache_flat_get_index(map, map->max_register)
+                            + 1, sizeof(unsigned int), GFP_KERNEL);
        if (!map->cache)
                return -ENOMEM;
 
        cache = map->cache;
 
        for (i = 0; i < map->num_reg_defaults; i++)
-               cache[map->reg_defaults[i].reg] = map->reg_defaults[i].def;
+               cache[regcache_flat_get_index(map, map->reg_defaults[i].reg)] =
+                               map->reg_defaults[i].def;
 
        return 0;
 }
@@ -47,7 +57,7 @@ static int regcache_flat_read(struct regmap *map,
 {
        unsigned int *cache = map->cache;
 
-       *value = cache[reg];
+       *value = cache[regcache_flat_get_index(map, reg)];
 
        return 0;
 }
@@ -57,7 +67,7 @@ static int regcache_flat_write(struct regmap *map, unsigned int reg,
 {
        unsigned int *cache = map->cache;
 
-       cache[reg] = value;
+       cache[regcache_flat_get_index(map, reg)] = value;
 
        return 0;
 }
index 348be3a354108eb2533587dabed9495e9c324b5a..4170b7d952767074140ce26c4c1ac621823607ad 100644 (file)
@@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map)
        int i, j;
        int ret;
        int count;
-       unsigned int val;
+       unsigned int reg, val;
        void *tmp_buf;
 
        if (!map->num_reg_defaults_raw)
@@ -57,7 +57,7 @@ static int regcache_hw_init(struct regmap *map)
                bool cache_bypass = map->cache_bypass;
                dev_warn(map->dev, "No cache defaults, reading back from HW\n");
 
-               /* Bypass the cache access till data read from HW*/
+               /* Bypass the cache access till data read from HW */
                map->cache_bypass = true;
                tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL);
                if (!tmp_buf) {
@@ -65,29 +65,48 @@ static int regcache_hw_init(struct regmap *map)
                        goto err_free;
                }
                ret = regmap_raw_read(map, 0, tmp_buf,
-                                     map->num_reg_defaults_raw);
+                                     map->cache_size_raw);
                map->cache_bypass = cache_bypass;
-               if (ret < 0)
-                       goto err_cache_free;
-
-               map->reg_defaults_raw = tmp_buf;
-               map->cache_free = 1;
+               if (ret == 0) {
+                       map->reg_defaults_raw = tmp_buf;
+                       map->cache_free = 1;
+               } else {
+                       kfree(tmp_buf);
+               }
        }
 
        /* fill the reg_defaults */
        for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) {
-               if (regmap_volatile(map, i * map->reg_stride))
+               reg = i * map->reg_stride;
+
+               if (!regmap_readable(map, reg))
                        continue;
-               val = regcache_get_val(map, map->reg_defaults_raw, i);
-               map->reg_defaults[j].reg = i * map->reg_stride;
+
+               if (regmap_volatile(map, reg))
+                       continue;
+
+               if (map->reg_defaults_raw) {
+                       val = regcache_get_val(map, map->reg_defaults_raw, i);
+               } else {
+                       bool cache_bypass = map->cache_bypass;
+
+                       map->cache_bypass = true;
+                       ret = regmap_read(map, reg, &val);
+                       map->cache_bypass = cache_bypass;
+                       if (ret != 0) {
+                               dev_err(map->dev, "Failed to read %d: %d\n",
+                                       reg, ret);
+                               goto err_free;
+                       }
+               }
+
+               map->reg_defaults[j].reg = reg;
                map->reg_defaults[j].def = val;
                j++;
        }
 
        return 0;
 
-err_cache_free:
-       kfree(tmp_buf);
 err_free:
        kfree(map->reg_defaults);
 
index 9b0d202414d065bf6e03a6f39bb33c9925dee4db..26f799e71c82355e02ef58ff9847cef33545e444 100644 (file)
@@ -379,6 +379,7 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
        irq_set_chip_data(virq, data);
        irq_set_chip(virq, &data->irq_chip);
        irq_set_nested_thread(virq, 1);
+       irq_set_parent(virq, data->irq);
        irq_set_noprobe(virq);
 
        return 0;
@@ -655,13 +656,34 @@ EXPORT_SYMBOL_GPL(regmap_add_irq_chip);
  *
  * @irq: Primary IRQ for the device
  * @d:   regmap_irq_chip_data allocated by regmap_add_irq_chip()
+ *
+ * This function also dispose all mapped irq on chip.
  */
 void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
 {
+       unsigned int virq;
+       int hwirq;
+
        if (!d)
                return;
 
        free_irq(irq, d);
+
+       /* Dispose all virtual irq from irq domain before removing it */
+       for (hwirq = 0; hwirq < d->chip->num_irqs; hwirq++) {
+               /* Ignore hwirq if holes in the IRQ list */
+               if (!d->chip->irqs[hwirq].mask)
+                       continue;
+
+               /*
+                * Find the virtual irq of hwirq on chip and if it is
+                * there then dispose it
+                */
+               virq = irq_find_mapping(d->domain, hwirq);
+               if (virq)
+                       irq_dispose_mapping(virq);
+       }
+
        irq_domain_remove(d->domain);
        kfree(d->type_buf);
        kfree(d->type_buf_def);
@@ -674,6 +696,88 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
 }
 EXPORT_SYMBOL_GPL(regmap_del_irq_chip);
 
+static void devm_regmap_irq_chip_release(struct device *dev, void *res)
+{
+       struct regmap_irq_chip_data *d = *(struct regmap_irq_chip_data **)res;
+
+       regmap_del_irq_chip(d->irq, d);
+}
+
+static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data)
+
+{
+       struct regmap_irq_chip_data **r = res;
+
+       if (!r || !*r) {
+               WARN_ON(!r || !*r);
+               return 0;
+       }
+       return *r == data;
+}
+
+/**
+ * devm_regmap_add_irq_chip(): Resource manager regmap_add_irq_chip()
+ *
+ * @dev:       The device pointer on which irq_chip belongs to.
+ * @map:       The regmap for the device.
+ * @irq:       The IRQ the device uses to signal interrupts
+ * @irq_flags: The IRQF_ flags to use for the primary interrupt.
+ * @chip:      Configuration for the interrupt controller.
+ * @data:      Runtime data structure for the controller, allocated on success
+ *
+ * Returns 0 on success or an errno on failure.
+ *
+ * The regmap_irq_chip data automatically be released when the device is
+ * unbound.
+ */
+int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
+                            int irq_flags, int irq_base,
+                            const struct regmap_irq_chip *chip,
+                            struct regmap_irq_chip_data **data)
+{
+       struct regmap_irq_chip_data **ptr, *d;
+       int ret;
+
+       ptr = devres_alloc(devm_regmap_irq_chip_release, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       ret = regmap_add_irq_chip(map, irq, irq_flags, irq_base,
+                                 chip, &d);
+       if (ret < 0) {
+               devres_free(ptr);
+               return ret;
+       }
+
+       *ptr = d;
+       devres_add(dev, ptr);
+       *data = d;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regmap_add_irq_chip);
+
+/**
+ * devm_regmap_del_irq_chip(): Resource managed regmap_del_irq_chip()
+ *
+ * @dev: Device for which which resource was allocated.
+ * @irq: Primary IRQ for the device
+ * @d:   regmap_irq_chip_data allocated by regmap_add_irq_chip()
+ */
+void devm_regmap_del_irq_chip(struct device *dev, int irq,
+                             struct regmap_irq_chip_data *data)
+{
+       int rc;
+
+       WARN_ON(irq != data->irq);
+       rc = devres_release(dev, devm_regmap_irq_chip_release,
+                           devm_regmap_irq_chip_match, data);
+
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regmap_del_irq_chip);
+
 /**
  * regmap_irq_chip_get_base(): Retrieve interrupt base for a regmap IRQ chip
  *
index eea51569f0eb9c9e36f5a4bca90de61c8f833444..7526906ca080f81dcff1499b7e57c2ff0b79569e 100644 (file)
 
 struct regmap_mmio_context {
        void __iomem *regs;
-       unsigned reg_bytes;
        unsigned val_bytes;
-       unsigned pad_bytes;
        struct clk *clk;
-};
 
-static inline void regmap_mmio_regsize_check(size_t reg_size)
-{
-       switch (reg_size) {
-       case 1:
-       case 2:
-       case 4:
-#ifdef CONFIG_64BIT
-       case 8:
-#endif
-               break;
-       default:
-               BUG();
-       }
-}
+       void (*reg_write)(struct regmap_mmio_context *ctx,
+                         unsigned int reg, unsigned int val);
+       unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
+                                unsigned int reg);
+};
 
 static int regmap_mmio_regbits_check(size_t reg_bits)
 {
@@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits)
        return min_stride;
 }
 
-static inline void regmap_mmio_count_check(size_t count, u32 offset)
+static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
+                               unsigned int reg,
+                               unsigned int val)
+{
+       writeb(val, ctx->regs + reg);
+}
+
+static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
 {
-       BUG_ON(count <= offset);
+       writew(val, ctx->regs + reg);
 }
 
-static inline unsigned int
-regmap_mmio_get_offset(const void *reg, size_t reg_size)
+static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
 {
-       switch (reg_size) {
-       case 1:
-               return *(u8 *)reg;
-       case 2:
-               return *(u16 *)reg;
-       case 4:
-               return *(u32 *)reg;
+       iowrite16be(val, ctx->regs + reg);
+}
+
+static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
+{
+       writel(val, ctx->regs + reg);
+}
+
+static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
+{
+       iowrite32be(val, ctx->regs + reg);
+}
+
 #ifdef CONFIG_64BIT
-       case 8:
-               return *(u64 *)reg;
-#endif
-       default:
-               BUG();
-       }
+static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
+                                 unsigned int reg,
+                                 unsigned int val)
+{
+       writeq(val, ctx->regs + reg);
 }
+#endif
 
-static int regmap_mmio_gather_write(void *context,
-                                   const void *reg, size_t reg_size,
-                                   const void *val, size_t val_size)
+static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
 {
        struct regmap_mmio_context *ctx = context;
-       unsigned int offset;
        int ret;
 
-       regmap_mmio_regsize_check(reg_size);
-
        if (!IS_ERR(ctx->clk)) {
                ret = clk_enable(ctx->clk);
                if (ret < 0)
                        return ret;
        }
 
-       offset = regmap_mmio_get_offset(reg, reg_size);
-
-       while (val_size) {
-               switch (ctx->val_bytes) {
-               case 1:
-                       writeb(*(u8 *)val, ctx->regs + offset);
-                       break;
-               case 2:
-                       writew(*(u16 *)val, ctx->regs + offset);
-                       break;
-               case 4:
-                       writel(*(u32 *)val, ctx->regs + offset);
-                       break;
-#ifdef CONFIG_64BIT
-               case 8:
-                       writeq(*(u64 *)val, ctx->regs + offset);
-                       break;
-#endif
-               default:
-                       /* Should be caught by regmap_mmio_check_config */
-                       BUG();
-               }
-               val_size -= ctx->val_bytes;
-               val += ctx->val_bytes;
-               offset += ctx->val_bytes;
-       }
+       ctx->reg_write(ctx, reg, val);
 
        if (!IS_ERR(ctx->clk))
                clk_disable(ctx->clk);
@@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context,
        return 0;
 }
 
-static int regmap_mmio_write(void *context, const void *data, size_t count)
+static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
+                                     unsigned int reg)
 {
-       struct regmap_mmio_context *ctx = context;
-       unsigned int offset = ctx->reg_bytes + ctx->pad_bytes;
+       return readb(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return readw(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return ioread16be(ctx->regs + reg);
+}
+
+static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return readl(ctx->regs + reg);
+}
 
-       regmap_mmio_count_check(count, offset);
+static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return ioread32be(ctx->regs + reg);
+}
 
-       return regmap_mmio_gather_write(context, data, ctx->reg_bytes,
-                                       data + offset, count - offset);
+#ifdef CONFIG_64BIT
+static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
+                                        unsigned int reg)
+{
+       return readq(ctx->regs + reg);
 }
+#endif
 
-static int regmap_mmio_read(void *context,
-                           const void *reg, size_t reg_size,
-                           void *val, size_t val_size)
+static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
 {
        struct regmap_mmio_context *ctx = context;
-       unsigned int offset;
        int ret;
 
-       regmap_mmio_regsize_check(reg_size);
-
        if (!IS_ERR(ctx->clk)) {
                ret = clk_enable(ctx->clk);
                if (ret < 0)
                        return ret;
        }
 
-       offset = regmap_mmio_get_offset(reg, reg_size);
-
-       while (val_size) {
-               switch (ctx->val_bytes) {
-               case 1:
-                       *(u8 *)val = readb(ctx->regs + offset);
-                       break;
-               case 2:
-                       *(u16 *)val = readw(ctx->regs + offset);
-                       break;
-               case 4:
-                       *(u32 *)val = readl(ctx->regs + offset);
-                       break;
-#ifdef CONFIG_64BIT
-               case 8:
-                       *(u64 *)val = readq(ctx->regs + offset);
-                       break;
-#endif
-               default:
-                       /* Should be caught by regmap_mmio_check_config */
-                       BUG();
-               }
-               val_size -= ctx->val_bytes;
-               val += ctx->val_bytes;
-               offset += ctx->val_bytes;
-       }
+       *val = ctx->reg_read(ctx, reg);
 
        if (!IS_ERR(ctx->clk))
                clk_disable(ctx->clk);
@@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context)
        kfree(context);
 }
 
-static struct regmap_bus regmap_mmio = {
+static const struct regmap_bus regmap_mmio = {
        .fast_io = true,
-       .write = regmap_mmio_write,
-       .gather_write = regmap_mmio_gather_write,
-       .read = regmap_mmio_read,
+       .reg_write = regmap_mmio_write,
+       .reg_read = regmap_mmio_read,
        .free_context = regmap_mmio_free_context,
-       .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
-       .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
 };
 
 static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
@@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
        if (config->reg_stride < min_stride)
                return ERR_PTR(-EINVAL);
 
-       switch (config->reg_format_endian) {
-       case REGMAP_ENDIAN_DEFAULT:
-       case REGMAP_ENDIAN_NATIVE:
-               break;
-       default:
-               return ERR_PTR(-EINVAL);
-       }
-
        ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return ERR_PTR(-ENOMEM);
 
        ctx->regs = regs;
        ctx->val_bytes = config->val_bits / 8;
-       ctx->reg_bytes = config->reg_bits / 8;
-       ctx->pad_bytes = config->pad_bits / 8;
        ctx->clk = ERR_PTR(-ENODEV);
 
+       switch (config->reg_format_endian) {
+       case REGMAP_ENDIAN_DEFAULT:
+       case REGMAP_ENDIAN_LITTLE:
+#ifdef __LITTLE_ENDIAN
+       case REGMAP_ENDIAN_NATIVE:
+#endif
+               switch (config->val_bits) {
+               case 8:
+                       ctx->reg_read = regmap_mmio_read8;
+                       ctx->reg_write = regmap_mmio_write8;
+                       break;
+               case 16:
+                       ctx->reg_read = regmap_mmio_read16le;
+                       ctx->reg_write = regmap_mmio_write16le;
+                       break;
+               case 32:
+                       ctx->reg_read = regmap_mmio_read32le;
+                       ctx->reg_write = regmap_mmio_write32le;
+                       break;
+#ifdef CONFIG_64BIT
+               case 64:
+                       ctx->reg_read = regmap_mmio_read64le;
+                       ctx->reg_write = regmap_mmio_write64le;
+                       break;
+#endif
+               default:
+                       ret = -EINVAL;
+                       goto err_free;
+               }
+               break;
+       case REGMAP_ENDIAN_BIG:
+#ifdef __BIG_ENDIAN
+       case REGMAP_ENDIAN_NATIVE:
+#endif
+               switch (config->val_bits) {
+               case 8:
+                       ctx->reg_read = regmap_mmio_read8;
+                       ctx->reg_write = regmap_mmio_write8;
+                       break;
+               case 16:
+                       ctx->reg_read = regmap_mmio_read16be;
+                       ctx->reg_write = regmap_mmio_write16be;
+                       break;
+               case 32:
+                       ctx->reg_read = regmap_mmio_read32be;
+                       ctx->reg_write = regmap_mmio_write32be;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       goto err_free;
+               }
+               break;
+       default:
+               ret = -EINVAL;
+               goto err_free;
+       }
+
        if (clk_id == NULL)
                return ctx;
 
index ee54e841de4ad69c96ecb7897ddc04e889e8c702..df2d2ef5d6b38bf374ab8ed3158d80e301a92852 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/rbtree.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
+#include <linux/log2.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -557,6 +558,8 @@ enum regmap_endian regmap_get_val_endian(struct device *dev,
                        endian = REGMAP_ENDIAN_BIG;
                else if (of_property_read_bool(np, "little-endian"))
                        endian = REGMAP_ENDIAN_LITTLE;
+               else if (of_property_read_bool(np, "native-endian"))
+                       endian = REGMAP_ENDIAN_NATIVE;
 
                /* If the endianness was specified in DT, use that */
                if (endian != REGMAP_ENDIAN_DEFAULT)
@@ -638,6 +641,10 @@ struct regmap *__regmap_init(struct device *dev,
                map->reg_stride = config->reg_stride;
        else
                map->reg_stride = 1;
+       if (is_power_of_2(map->reg_stride))
+               map->reg_stride_order = ilog2(map->reg_stride);
+       else
+               map->reg_stride_order = -1;
        map->use_single_read = config->use_single_rw || !bus || !bus->read;
        map->use_single_write = config->use_single_rw || !bus || !bus->write;
        map->can_multi_write = config->can_multi_write && bus && bus->write;
@@ -1308,7 +1315,7 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
        if (map->writeable_reg)
                for (i = 0; i < val_len / map->format.val_bytes; i++)
                        if (!map->writeable_reg(map->dev,
-                                               reg + (i * map->reg_stride)))
+                                              reg + regmap_get_offset(map, i)))
                                return -EINVAL;
 
        if (!map->cache_bypass && map->format.parse_val) {
@@ -1316,7 +1323,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
                int val_bytes = map->format.val_bytes;
                for (i = 0; i < val_len / val_bytes; i++) {
                        ival = map->format.parse_val(val + (i * val_bytes));
-                       ret = regcache_write(map, reg + (i * map->reg_stride),
+                       ret = regcache_write(map,
+                                            reg + regmap_get_offset(map, i),
                                             ival);
                        if (ret) {
                                dev_err(map->dev,
@@ -1690,100 +1698,63 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
 EXPORT_SYMBOL_GPL(regmap_raw_write);
 
 /**
- * regmap_field_write(): Write a value to a single register field
- *
- * @field: Register field to write to
- * @val: Value to be written
- *
- * A value of zero will be returned on success, a negative errno will
- * be returned in error cases.
- */
-int regmap_field_write(struct regmap_field *field, unsigned int val)
-{
-       return regmap_update_bits(field->regmap, field->reg,
-                               field->mask, val << field->shift);
-}
-EXPORT_SYMBOL_GPL(regmap_field_write);
-
-/**
- * regmap_field_update_bits(): Perform a read/modify/write cycle
- *                              on the register field
+ * regmap_field_update_bits_base():
+ *     Perform a read/modify/write cycle on the register field
+ *     with change, async, force option
  *
  * @field: Register field to write to
  * @mask: Bitmask to change
  * @val: Value to be written
+ * @change: Boolean indicating if a write was done
+ * @async: Boolean indicating asynchronously
+ * @force: Boolean indicating use force update
  *
  * A value of zero will be returned on success, a negative errno will
  * be returned in error cases.
  */
-int regmap_field_update_bits(struct regmap_field *field, unsigned int mask, unsigned int val)
+int regmap_field_update_bits_base(struct regmap_field *field,
+                                 unsigned int mask, unsigned int val,
+                                 bool *change, bool async, bool force)
 {
        mask = (mask << field->shift) & field->mask;
 
-       return regmap_update_bits(field->regmap, field->reg,
-                                 mask, val << field->shift);
+       return regmap_update_bits_base(field->regmap, field->reg,
+                                      mask, val << field->shift,
+                                      change, async, force);
 }
-EXPORT_SYMBOL_GPL(regmap_field_update_bits);
+EXPORT_SYMBOL_GPL(regmap_field_update_bits_base);
 
 /**
- * regmap_fields_write(): Write a value to a single register field with port ID
- *
- * @field: Register field to write to
- * @id: port ID
- * @val: Value to be written
- *
- * A value of zero will be returned on success, a negative errno will
- * be returned in error cases.
- */
-int regmap_fields_write(struct regmap_field *field, unsigned int id,
-                       unsigned int val)
-{
-       if (id >= field->id_size)
-               return -EINVAL;
-
-       return regmap_update_bits(field->regmap,
-                                 field->reg + (field->id_offset * id),
-                                 field->mask, val << field->shift);
-}
-EXPORT_SYMBOL_GPL(regmap_fields_write);
-
-int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
-                       unsigned int val)
-{
-       if (id >= field->id_size)
-               return -EINVAL;
-
-       return regmap_write_bits(field->regmap,
-                                 field->reg + (field->id_offset * id),
-                                 field->mask, val << field->shift);
-}
-EXPORT_SYMBOL_GPL(regmap_fields_force_write);
-
-/**
- * regmap_fields_update_bits():        Perform a read/modify/write cycle
- *                              on the register field
+ * regmap_fields_update_bits_base():
+ *     Perform a read/modify/write cycle on the register field
+ *     with change, async, force option
  *
  * @field: Register field to write to
  * @id: port ID
  * @mask: Bitmask to change
  * @val: Value to be written
+ * @change: Boolean indicating if a write was done
+ * @async: Boolean indicating asynchronously
+ * @force: Boolean indicating use force update
  *
  * A value of zero will be returned on success, a negative errno will
  * be returned in error cases.
  */
-int regmap_fields_update_bits(struct regmap_field *field,  unsigned int id,
-                             unsigned int mask, unsigned int val)
+int regmap_fields_update_bits_base(struct regmap_field *field,  unsigned int id,
+                                  unsigned int mask, unsigned int val,
+                                  bool *change, bool async, bool force)
 {
        if (id >= field->id_size)
                return -EINVAL;
 
        mask = (mask << field->shift) & field->mask;
 
-       return regmap_update_bits(field->regmap,
-                                 field->reg + (field->id_offset * id),
-                                 mask, val << field->shift);
+       return regmap_update_bits_base(field->regmap,
+                                      field->reg + (field->id_offset * id),
+                                      mask, val << field->shift,
+                                      change, async, force);
 }
-EXPORT_SYMBOL_GPL(regmap_fields_update_bits);
+EXPORT_SYMBOL_GPL(regmap_fields_update_bits_base);
 
 /*
  * regmap_bulk_write(): Write multiple registers to the device
@@ -1846,8 +1817,9 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
                                goto out;
                        }
 
-                       ret = _regmap_write(map, reg + (i * map->reg_stride),
-                                       ival);
+                       ret = _regmap_write(map,
+                                           reg + regmap_get_offset(map, i),
+                                           ival);
                        if (ret != 0)
                                goto out;
                }
@@ -2253,6 +2225,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
 
        WARN_ON(!map->bus);
 
+       if (!map->bus || !map->bus->read)
+               return -EINVAL;
+
        range = _regmap_range_lookup(map, reg);
        if (range) {
                ret = _regmap_select_page(map, &reg, range,
@@ -2416,7 +2391,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
                 * cost as we expect to hit the cache.
                 */
                for (i = 0; i < val_count; i++) {
-                       ret = _regmap_read(map, reg + (i * map->reg_stride),
+                       ret = _regmap_read(map, reg + regmap_get_offset(map, i),
                                           &v);
                        if (ret != 0)
                                goto out;
@@ -2568,7 +2543,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
        } else {
                for (i = 0; i < val_count; i++) {
                        unsigned int ival;
-                       ret = regmap_read(map, reg + (i * map->reg_stride),
+                       ret = regmap_read(map, reg + regmap_get_offset(map, i),
                                          &ival);
                        if (ret != 0)
                                return ret;
@@ -2648,138 +2623,36 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
 }
 
 /**
- * regmap_update_bits: Perform a read/modify/write cycle on the register map
- *
- * @map: Register map to update
- * @reg: Register to update
- * @mask: Bitmask to change
- * @val: New value for bitmask
- *
- * Returns zero for success, a negative number on error.
- */
-int regmap_update_bits(struct regmap *map, unsigned int reg,
-                      unsigned int mask, unsigned int val)
-{
-       int ret;
-
-       map->lock(map->lock_arg);
-       ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
-       map->unlock(map->lock_arg);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(regmap_update_bits);
-
-/**
- * regmap_write_bits: Perform a read/modify/write cycle on the register map
- *
- * @map: Register map to update
- * @reg: Register to update
- * @mask: Bitmask to change
- * @val: New value for bitmask
- *
- * Returns zero for success, a negative number on error.
- */
-int regmap_write_bits(struct regmap *map, unsigned int reg,
-                     unsigned int mask, unsigned int val)
-{
-       int ret;
-
-       map->lock(map->lock_arg);
-       ret = _regmap_update_bits(map, reg, mask, val, NULL, true);
-       map->unlock(map->lock_arg);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(regmap_write_bits);
-
-/**
- * regmap_update_bits_async: Perform a read/modify/write cycle on the register
- *                           map asynchronously
- *
- * @map: Register map to update
- * @reg: Register to update
- * @mask: Bitmask to change
- * @val: New value for bitmask
- *
- * With most buses the read must be done synchronously so this is most
- * useful for devices with a cache which do not need to interact with
- * the hardware to determine the current register value.
- *
- * Returns zero for success, a negative number on error.
- */
-int regmap_update_bits_async(struct regmap *map, unsigned int reg,
-                            unsigned int mask, unsigned int val)
-{
-       int ret;
-
-       map->lock(map->lock_arg);
-
-       map->async = true;
-
-       ret = _regmap_update_bits(map, reg, mask, val, NULL, false);
-
-       map->async = false;
-
-       map->unlock(map->lock_arg);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(regmap_update_bits_async);
-
-/**
- * regmap_update_bits_check: Perform a read/modify/write cycle on the
- *                           register map and report if updated
- *
- * @map: Register map to update
- * @reg: Register to update
- * @mask: Bitmask to change
- * @val: New value for bitmask
- * @change: Boolean indicating if a write was done
- *
- * Returns zero for success, a negative number on error.
- */
-int regmap_update_bits_check(struct regmap *map, unsigned int reg,
-                            unsigned int mask, unsigned int val,
-                            bool *change)
-{
-       int ret;
-
-       map->lock(map->lock_arg);
-       ret = _regmap_update_bits(map, reg, mask, val, change, false);
-       map->unlock(map->lock_arg);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(regmap_update_bits_check);
-
-/**
- * regmap_update_bits_check_async: Perform a read/modify/write cycle on the
- *                                 register map asynchronously and report if
- *                                 updated
+ * regmap_update_bits_base:
+ *     Perform a read/modify/write cycle on the
+ *     register map with change, async, force option
  *
  * @map: Register map to update
  * @reg: Register to update
  * @mask: Bitmask to change
  * @val: New value for bitmask
  * @change: Boolean indicating if a write was done
+ * @async: Boolean indicating asynchronously
+ * @force: Boolean indicating use force update
  *
+ * if async was true,
  * With most buses the read must be done synchronously so this is most
  * useful for devices with a cache which do not need to interact with
  * the hardware to determine the current register value.
  *
  * Returns zero for success, a negative number on error.
  */
-int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
-                                  unsigned int mask, unsigned int val,
-                                  bool *change)
+int regmap_update_bits_base(struct regmap *map, unsigned int reg,
+                           unsigned int mask, unsigned int val,
+                           bool *change, bool async, bool force)
 {
        int ret;
 
        map->lock(map->lock_arg);
 
-       map->async = true;
+       map->async = async;
 
-       ret = _regmap_update_bits(map, reg, mask, val, change, false);
+       ret = _regmap_update_bits(map, reg, mask, val, change, force);
 
        map->async = false;
 
@@ -2787,7 +2660,7 @@ int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(regmap_update_bits_check_async);
+EXPORT_SYMBOL_GPL(regmap_update_bits_base);
 
 void regmap_async_complete_cb(struct regmap_async *async, int ret)
 {
index 562b5a4ca7b712f6b2b4440375904d8be1ac5200..78a39f736c64f7edb6eb5d721e391d9e25f4a113 100644 (file)
 */
 #include <linux/types.h>
 
-static bool verbose = 0;
+static int verbose = 0;
 static int major = PD_MAJOR;
 static char *name = PD_NAME;
 static int cluster = 64;
@@ -161,7 +161,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV};
 static DEFINE_MUTEX(pd_mutex);
 static DEFINE_SPINLOCK(pd_lock);
 
-module_param(verbose, bool, 0);
+module_param(verbose, int, 0);
 module_param(major, int, 0);
 module_param(name, charp, 0);
 module_param(cluster, int, 0);
index 1740d75e8a3239d80ed1580e96fe92028da2f827..216a94fed5b420bd59627643730d3284308367e7 100644 (file)
 
 */
 
-static bool verbose = 0;
+static int verbose = 0;
 static int major = PT_MAJOR;
 static char *name = PT_NAME;
 static int disable = 0;
@@ -152,7 +152,7 @@ static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3};
 
 #include <asm/uaccess.h>
 
-module_param(verbose, bool, 0);
+module_param(verbose, int, 0);
 module_param(major, int, 0);
 module_param(name, charp, 0);
 module_param_array(drive0, int, NULL, 0);
index 05755441250c1de8495725ea80253957b71abd07..fdced547ad5961ff722cfb438c0e33de9f5fabb2 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <asm/uninorth.h>
-#include <asm/pci-bridge.h>
 #include <asm/prom.h>
 #include <asm/pmac_feature.h>
 #include "agp.h"
index d0da5d852d41e5588bb9bd192431a403a9696848..b583e53366306db870a0d61918156f41985f075e 100644 (file)
@@ -1818,6 +1818,28 @@ unsigned int get_random_int(void)
 }
 EXPORT_SYMBOL(get_random_int);
 
+/*
+ * Same as get_random_int(), but returns unsigned long.
+ */
+unsigned long get_random_long(void)
+{
+       __u32 *hash;
+       unsigned long ret;
+
+       if (arch_get_random_long(&ret))
+               return ret;
+
+       hash = get_cpu_var(get_random_int_hash);
+
+       hash[0] += current->pid + jiffies + random_get_entropy();
+       md5_transform(hash, random_int_secret);
+       ret = *(unsigned long *)hash;
+       put_cpu_var(get_random_int_hash);
+
+       return ret;
+}
+EXPORT_SYMBOL(get_random_long);
+
 /*
  * randomize_range() returns a start address such that
  *
index 1c300388782ba19d1377bdbbbf9ab05a8939791d..cc739291a3ce47466e87023c2bdfd56951e7bf2f 100644 (file)
@@ -460,7 +460,8 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
 
        parent = clk_hw_get_parent(hw);
 
-       if (clk_hw_get_rate(hw) == clk_get_rate(dd->clk_bypass)) {
+       if (clk_hw_get_rate(hw) ==
+           clk_hw_get_rate(__clk_get_hw(dd->clk_bypass))) {
                WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
                r = _omap3_noncore_dpll_bypass(clk);
        } else {
index 33db7406c0e274e8c39c7b0d71509a117c324022..c346be650892affaa890ad3a3212c0f62e360fb4 100644 (file)
@@ -160,6 +160,7 @@ config CLKSRC_EFM32
 config CLKSRC_LPC32XX
        bool "Clocksource for LPC32XX" if COMPILE_TEST
        depends on GENERIC_CLOCKEVENTS && HAS_IOMEM
+       depends on ARM
        select CLKSRC_MMIO
        select CLKSRC_OF
        help
index c64d543d64bf69576d9d75ffc54839439c70ea9b..5152b389815500a77a95cffe69a0602379d4f570 100644 (file)
 #define CNTTIDR                0x08
 #define CNTTIDR_VIRT(n)        (BIT(1) << ((n) * 4))
 
+#define CNTACR(n)      (0x40 + ((n) * 4))
+#define CNTACR_RPCT    BIT(0)
+#define CNTACR_RVCT    BIT(1)
+#define CNTACR_RFRQ    BIT(2)
+#define CNTACR_RVOFF   BIT(3)
+#define CNTACR_RWVT    BIT(4)
+#define CNTACR_RWPT    BIT(5)
+
 #define CNTVCT_LO      0x08
 #define CNTVCT_HI      0x0c
 #define CNTFRQ         0x10
@@ -67,7 +75,7 @@ static int arch_timer_ppi[MAX_TIMER_PPI];
 
 static struct clock_event_device __percpu *arch_timer_evt;
 
-static bool arch_timer_use_virtual = true;
+static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI;
 static bool arch_timer_c3stop;
 static bool arch_timer_mem_use_virtual;
 
@@ -263,14 +271,22 @@ static void __arch_timer_setup(unsigned type,
                clk->name = "arch_sys_timer";
                clk->rating = 450;
                clk->cpumask = cpumask_of(smp_processor_id());
-               if (arch_timer_use_virtual) {
-                       clk->irq = arch_timer_ppi[VIRT_PPI];
+               clk->irq = arch_timer_ppi[arch_timer_uses_ppi];
+               switch (arch_timer_uses_ppi) {
+               case VIRT_PPI:
                        clk->set_state_shutdown = arch_timer_shutdown_virt;
+                       clk->set_state_oneshot_stopped = arch_timer_shutdown_virt;
                        clk->set_next_event = arch_timer_set_next_event_virt;
-               } else {
-                       clk->irq = arch_timer_ppi[PHYS_SECURE_PPI];
+                       break;
+               case PHYS_SECURE_PPI:
+               case PHYS_NONSECURE_PPI:
+               case HYP_PPI:
                        clk->set_state_shutdown = arch_timer_shutdown_phys;
+                       clk->set_state_oneshot_stopped = arch_timer_shutdown_phys;
                        clk->set_next_event = arch_timer_set_next_event_phys;
+                       break;
+               default:
+                       BUG();
                }
        } else {
                clk->features |= CLOCK_EVT_FEAT_DYNIRQ;
@@ -279,10 +295,12 @@ static void __arch_timer_setup(unsigned type,
                clk->cpumask = cpu_all_mask;
                if (arch_timer_mem_use_virtual) {
                        clk->set_state_shutdown = arch_timer_shutdown_virt_mem;
+                       clk->set_state_oneshot_stopped = arch_timer_shutdown_virt_mem;
                        clk->set_next_event =
                                arch_timer_set_next_event_virt_mem;
                } else {
                        clk->set_state_shutdown = arch_timer_shutdown_phys_mem;
+                       clk->set_state_oneshot_stopped = arch_timer_shutdown_phys_mem;
                        clk->set_next_event =
                                arch_timer_set_next_event_phys_mem;
                }
@@ -338,17 +356,20 @@ static void arch_counter_set_user_access(void)
        arch_timer_set_cntkctl(cntkctl);
 }
 
+static bool arch_timer_has_nonsecure_ppi(void)
+{
+       return (arch_timer_uses_ppi == PHYS_SECURE_PPI &&
+               arch_timer_ppi[PHYS_NONSECURE_PPI]);
+}
+
 static int arch_timer_setup(struct clock_event_device *clk)
 {
        __arch_timer_setup(ARCH_CP15_TIMER, clk);
 
-       if (arch_timer_use_virtual)
-               enable_percpu_irq(arch_timer_ppi[VIRT_PPI], 0);
-       else {
-               enable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], 0);
-               if (arch_timer_ppi[PHYS_NONSECURE_PPI])
-                       enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
-       }
+       enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0);
+
+       if (arch_timer_has_nonsecure_ppi())
+               enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
 
        arch_counter_set_user_access();
        if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM))
@@ -390,7 +411,7 @@ static void arch_timer_banner(unsigned type)
                     (unsigned long)arch_timer_rate / 1000000,
                     (unsigned long)(arch_timer_rate / 10000) % 100,
                     type & ARCH_CP15_TIMER ?
-                       arch_timer_use_virtual ? "virt" : "phys" :
+                    (arch_timer_uses_ppi == VIRT_PPI) ? "virt" : "phys" :
                        "",
                     type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ?  "/" : "",
                     type & ARCH_MEM_TIMER ?
@@ -460,7 +481,7 @@ static void __init arch_counter_register(unsigned type)
 
        /* Register the CP15 based counter if we have one */
        if (type & ARCH_CP15_TIMER) {
-               if (IS_ENABLED(CONFIG_ARM64) || arch_timer_use_virtual)
+               if (IS_ENABLED(CONFIG_ARM64) || arch_timer_uses_ppi == VIRT_PPI)
                        arch_timer_read_counter = arch_counter_get_cntvct;
                else
                        arch_timer_read_counter = arch_counter_get_cntpct;
@@ -490,13 +511,9 @@ static void arch_timer_stop(struct clock_event_device *clk)
        pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
                 clk->irq, smp_processor_id());
 
-       if (arch_timer_use_virtual)
-               disable_percpu_irq(arch_timer_ppi[VIRT_PPI]);
-       else {
-               disable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI]);
-               if (arch_timer_ppi[PHYS_NONSECURE_PPI])
-                       disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]);
-       }
+       disable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi]);
+       if (arch_timer_has_nonsecure_ppi())
+               disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]);
 
        clk->set_state_shutdown(clk);
 }
@@ -562,12 +579,14 @@ static int __init arch_timer_register(void)
                goto out;
        }
 
-       if (arch_timer_use_virtual) {
-               ppi = arch_timer_ppi[VIRT_PPI];
+       ppi = arch_timer_ppi[arch_timer_uses_ppi];
+       switch (arch_timer_uses_ppi) {
+       case VIRT_PPI:
                err = request_percpu_irq(ppi, arch_timer_handler_virt,
                                         "arch_timer", arch_timer_evt);
-       } else {
-               ppi = arch_timer_ppi[PHYS_SECURE_PPI];
+               break;
+       case PHYS_SECURE_PPI:
+       case PHYS_NONSECURE_PPI:
                err = request_percpu_irq(ppi, arch_timer_handler_phys,
                                         "arch_timer", arch_timer_evt);
                if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) {
@@ -578,6 +597,13 @@ static int __init arch_timer_register(void)
                                free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI],
                                                arch_timer_evt);
                }
+               break;
+       case HYP_PPI:
+               err = request_percpu_irq(ppi, arch_timer_handler_phys,
+                                        "arch_timer", arch_timer_evt);
+               break;
+       default:
+               BUG();
        }
 
        if (err) {
@@ -602,15 +628,10 @@ static int __init arch_timer_register(void)
 out_unreg_notify:
        unregister_cpu_notifier(&arch_timer_cpu_nb);
 out_free_irq:
-       if (arch_timer_use_virtual)
-               free_percpu_irq(arch_timer_ppi[VIRT_PPI], arch_timer_evt);
-       else {
-               free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI],
+       free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt);
+       if (arch_timer_has_nonsecure_ppi())
+               free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI],
                                arch_timer_evt);
-               if (arch_timer_ppi[PHYS_NONSECURE_PPI])
-                       free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI],
-                                       arch_timer_evt);
-       }
 
 out_free:
        free_percpu(arch_timer_evt);
@@ -697,12 +718,25 @@ static void __init arch_timer_init(void)
         *
         * If no interrupt provided for virtual timer, we'll have to
         * stick to the physical timer. It'd better be accessible...
+        *
+        * On ARMv8.1 with VH extensions, the kernel runs in HYP. VHE
+        * accesses to CNTP_*_EL1 registers are silently redirected to
+        * their CNTHP_*_EL2 counterparts, and use a different PPI
+        * number.
         */
        if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) {
-               arch_timer_use_virtual = false;
+               bool has_ppi;
 
-               if (!arch_timer_ppi[PHYS_SECURE_PPI] ||
-                   !arch_timer_ppi[PHYS_NONSECURE_PPI]) {
+               if (is_kernel_in_hyp_mode()) {
+                       arch_timer_uses_ppi = HYP_PPI;
+                       has_ppi = !!arch_timer_ppi[HYP_PPI];
+               } else {
+                       arch_timer_uses_ppi = PHYS_SECURE_PPI;
+                       has_ppi = (!!arch_timer_ppi[PHYS_SECURE_PPI] ||
+                                  !!arch_timer_ppi[PHYS_NONSECURE_PPI]);
+               }
+
+               if (!has_ppi) {
                        pr_warn("arch_timer: No interrupt available, giving up\n");
                        return;
                }
@@ -735,7 +769,7 @@ static void __init arch_timer_of_init(struct device_node *np)
         */
        if (IS_ENABLED(CONFIG_ARM) &&
            of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
-                       arch_timer_use_virtual = false;
+               arch_timer_uses_ppi = PHYS_SECURE_PPI;
 
        arch_timer_init();
 }
@@ -757,7 +791,6 @@ static void __init arch_timer_mem_init(struct device_node *np)
        }
 
        cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
-       iounmap(cntctlbase);
 
        /*
         * Try to find a virtual capable frame. Otherwise fall back to a
@@ -765,20 +798,31 @@ static void __init arch_timer_mem_init(struct device_node *np)
         */
        for_each_available_child_of_node(np, frame) {
                int n;
+               u32 cntacr;
 
                if (of_property_read_u32(frame, "frame-number", &n)) {
                        pr_err("arch_timer: Missing frame-number\n");
-                       of_node_put(best_frame);
                        of_node_put(frame);
-                       return;
+                       goto out;
                }
 
-               if (cnttidr & CNTTIDR_VIRT(n)) {
+               /* Try enabling everything, and see what sticks */
+               cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
+                        CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
+               writel_relaxed(cntacr, cntctlbase + CNTACR(n));
+               cntacr = readl_relaxed(cntctlbase + CNTACR(n));
+
+               if ((cnttidr & CNTTIDR_VIRT(n)) &&
+                   !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT))) {
                        of_node_put(best_frame);
                        best_frame = frame;
                        arch_timer_mem_use_virtual = true;
                        break;
                }
+
+               if (~cntacr & (CNTACR_RWPT | CNTACR_RPCT))
+                       continue;
+
                of_node_put(best_frame);
                best_frame = of_node_get(frame);
        }
@@ -786,24 +830,26 @@ static void __init arch_timer_mem_init(struct device_node *np)
        base = arch_counter_base = of_iomap(best_frame, 0);
        if (!base) {
                pr_err("arch_timer: Can't map frame's registers\n");
-               of_node_put(best_frame);
-               return;
+               goto out;
        }
 
        if (arch_timer_mem_use_virtual)
                irq = irq_of_parse_and_map(best_frame, 1);
        else
                irq = irq_of_parse_and_map(best_frame, 0);
-       of_node_put(best_frame);
+
        if (!irq) {
                pr_err("arch_timer: Frame missing %s irq",
                       arch_timer_mem_use_virtual ? "virt" : "phys");
-               return;
+               goto out;
        }
 
        arch_timer_detect_rate(base, np);
        arch_timer_mem_register(base, irq);
        arch_timer_common_init();
+out:
+       iounmap(cntctlbase);
+       of_node_put(best_frame);
 }
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem",
                       arch_timer_mem_init);
index d189d8cb69f70244cacca5a331b32e5beca4b5f1..9df0d1699d22b9f6bbaa8089ca71bc9c17895de0 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/clockchips.h>
 #include <linux/cpu.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -174,6 +175,7 @@ static int gt_clockevents_init(struct clock_event_device *clk)
        clk->set_state_shutdown = gt_clockevent_shutdown;
        clk->set_state_periodic = gt_clockevent_set_periodic;
        clk->set_state_oneshot = gt_clockevent_shutdown;
+       clk->set_state_oneshot_stopped = gt_clockevent_shutdown;
        clk->set_next_event = gt_clockevent_set_next_event;
        clk->cpumask = cpumask_of(cpu);
        clk->rating = 300;
@@ -221,6 +223,21 @@ static u64 notrace gt_sched_clock_read(void)
 }
 #endif
 
+static unsigned long gt_read_long(void)
+{
+       return readl_relaxed(gt_base + GT_COUNTER0);
+}
+
+static struct delay_timer gt_delay_timer = {
+       .read_current_timer = gt_read_long,
+};
+
+static void __init gt_delay_timer_init(void)
+{
+       gt_delay_timer.freq = gt_clk_rate;
+       register_current_timer_delay(&gt_delay_timer);
+}
+
 static void __init gt_clocksource_init(void)
 {
        writel(0, gt_base + GT_CONTROL);
@@ -317,6 +334,7 @@ static void __init global_timer_of_register(struct device_node *np)
        /* Immediately configure the timer on the boot CPU */
        gt_clocksource_init();
        gt_clockevents_init(this_cpu_ptr(gt_evt));
+       gt_delay_timer_init();
 
        return;
 
index ff44082a0827d60ff14a00e40001d5900adc8e92..be09bc0b5e269cb3748644456bf5bfb86d329379 100644 (file)
@@ -313,6 +313,7 @@ static struct clock_event_device mct_comp_device = {
        .set_state_periodic     = mct_set_state_periodic,
        .set_state_shutdown     = mct_set_state_shutdown,
        .set_state_oneshot      = mct_set_state_shutdown,
+       .set_state_oneshot_stopped = mct_set_state_shutdown,
        .tick_resume            = mct_set_state_shutdown,
 };
 
@@ -452,6 +453,7 @@ static int exynos4_local_timer_setup(struct mct_clock_event_device *mevt)
        evt->set_state_periodic = set_state_periodic;
        evt->set_state_shutdown = set_state_shutdown;
        evt->set_state_oneshot = set_state_shutdown;
+       evt->set_state_oneshot_stopped = set_state_shutdown;
        evt->tick_resume = set_state_shutdown;
        evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
        evt->rating = 450;
index 8c77a529d0d445bb91583f3256e7fdc4a6da6caf..b991b288c8032740f4eb0a0a4a30d056fcbb6694 100644 (file)
@@ -122,23 +122,23 @@ static void __init rk_timer_init(struct device_node *np)
        pclk = of_clk_get_by_name(np, "pclk");
        if (IS_ERR(pclk)) {
                pr_err("Failed to get pclk for '%s'\n", TIMER_NAME);
-               return;
+               goto out_unmap;
        }
 
        if (clk_prepare_enable(pclk)) {
                pr_err("Failed to enable pclk for '%s'\n", TIMER_NAME);
-               return;
+               goto out_unmap;
        }
 
        timer_clk = of_clk_get_by_name(np, "timer");
        if (IS_ERR(timer_clk)) {
                pr_err("Failed to get timer clock for '%s'\n", TIMER_NAME);
-               return;
+               goto out_timer_clk;
        }
 
        if (clk_prepare_enable(timer_clk)) {
                pr_err("Failed to enable timer clock\n");
-               return;
+               goto out_timer_clk;
        }
 
        bc_timer.freq = clk_get_rate(timer_clk);
@@ -146,7 +146,7 @@ static void __init rk_timer_init(struct device_node *np)
        irq = irq_of_parse_and_map(np, 0);
        if (!irq) {
                pr_err("Failed to map interrupts for '%s'\n", TIMER_NAME);
-               return;
+               goto out_irq;
        }
 
        ce->name = TIMER_NAME;
@@ -164,10 +164,19 @@ static void __init rk_timer_init(struct device_node *np)
        ret = request_irq(irq, rk_timer_interrupt, IRQF_TIMER, TIMER_NAME, ce);
        if (ret) {
                pr_err("Failed to initialize '%s': %d\n", TIMER_NAME, ret);
-               return;
+               goto out_irq;
        }
 
        clockevents_config_and_register(ce, bc_timer.freq, 1, UINT_MAX);
+
+       return;
+
+out_irq:
+       clk_disable_unprepare(timer_clk);
+out_timer_clk:
+       clk_disable_unprepare(pclk);
+out_unmap:
+       iounmap(bc_timer.base);
 }
 
 CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
index 1316876b487a715bf12bd03e007c4f178ec9136f..daae61e8c820efd3ca9cef3ef074d2d780e54a8e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/clk.h>
 #include <linux/clockchips.h>
 #include <linux/clocksource.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
@@ -43,6 +44,7 @@
 struct lpc32xx_clock_event_ddata {
        struct clock_event_device evtdev;
        void __iomem *base;
+       u32 ticks_per_jiffy;
 };
 
 /* Needed for the sched clock */
@@ -53,6 +55,15 @@ static u64 notrace lpc32xx_read_sched_clock(void)
        return readl(clocksource_timer_counter);
 }
 
+static unsigned long lpc32xx_delay_timer_read(void)
+{
+       return readl(clocksource_timer_counter);
+}
+
+static struct delay_timer lpc32xx_delay_timer = {
+       .read_current_timer = lpc32xx_delay_timer_read,
+};
+
 static int lpc32xx_clkevt_next_event(unsigned long delta,
                                     struct clock_event_device *evtdev)
 {
@@ -60,14 +71,13 @@ static int lpc32xx_clkevt_next_event(unsigned long delta,
                container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
 
        /*
-        * Place timer in reset and program the delta in the prescale
-        * register (PR). When the prescale counter matches the value
-        * in PR the counter register is incremented and the compare
-        * match will trigger. After setup the timer is released from
-        * reset and enabled.
+        * Place timer in reset and program the delta in the match
+        * channel 0 (MR0). When the timer counter matches the value
+        * in MR0 register the match will trigger an interrupt.
+        * After setup the timer is released from reset and enabled.
         */
        writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR);
-       writel_relaxed(delta, ddata->base + LPC32XX_TIMER_PR);
+       writel_relaxed(delta, ddata->base + LPC32XX_TIMER_MR0);
        writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR);
 
        return 0;
@@ -86,11 +96,39 @@ static int lpc32xx_clkevt_shutdown(struct clock_event_device *evtdev)
 
 static int lpc32xx_clkevt_oneshot(struct clock_event_device *evtdev)
 {
+       struct lpc32xx_clock_event_ddata *ddata =
+               container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
+
        /*
         * When using oneshot, we must also disable the timer
         * to wait for the first call to set_next_event().
         */
-       return lpc32xx_clkevt_shutdown(evtdev);
+       writel_relaxed(0, ddata->base + LPC32XX_TIMER_TCR);
+
+       /* Enable interrupt, reset on match and stop on match (MCR). */
+       writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R |
+                      LPC32XX_TIMER_MCR_MR0S, ddata->base + LPC32XX_TIMER_MCR);
+       return 0;
+}
+
+static int lpc32xx_clkevt_periodic(struct clock_event_device *evtdev)
+{
+       struct lpc32xx_clock_event_ddata *ddata =
+               container_of(evtdev, struct lpc32xx_clock_event_ddata, evtdev);
+
+       /* Enable interrupt and reset on match. */
+       writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R,
+                      ddata->base + LPC32XX_TIMER_MCR);
+
+       /*
+        * Place timer in reset and program the delta in the match
+        * channel 0 (MR0).
+        */
+       writel_relaxed(LPC32XX_TIMER_TCR_CRST, ddata->base + LPC32XX_TIMER_TCR);
+       writel_relaxed(ddata->ticks_per_jiffy, ddata->base + LPC32XX_TIMER_MR0);
+       writel_relaxed(LPC32XX_TIMER_TCR_CEN, ddata->base + LPC32XX_TIMER_TCR);
+
+       return 0;
 }
 
 static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id)
@@ -108,11 +146,13 @@ static irqreturn_t lpc32xx_clock_event_handler(int irq, void *dev_id)
 static struct lpc32xx_clock_event_ddata lpc32xx_clk_event_ddata = {
        .evtdev = {
                .name                   = "lpc3220 clockevent",
-               .features               = CLOCK_EVT_FEAT_ONESHOT,
+               .features               = CLOCK_EVT_FEAT_ONESHOT |
+                                         CLOCK_EVT_FEAT_PERIODIC,
                .rating                 = 300,
                .set_next_event         = lpc32xx_clkevt_next_event,
                .set_state_shutdown     = lpc32xx_clkevt_shutdown,
                .set_state_oneshot      = lpc32xx_clkevt_oneshot,
+               .set_state_periodic     = lpc32xx_clkevt_periodic,
        },
 };
 
@@ -162,6 +202,8 @@ static int __init lpc32xx_clocksource_init(struct device_node *np)
        }
 
        clocksource_timer_counter = base + LPC32XX_TIMER_TC;
+       lpc32xx_delay_timer.freq = rate;
+       register_current_timer_delay(&lpc32xx_delay_timer);
        sched_clock_register(lpc32xx_read_sched_clock, 32, rate);
 
        return 0;
@@ -210,18 +252,16 @@ static int __init lpc32xx_clockevent_init(struct device_node *np)
 
        /*
         * Disable timer and clear any pending interrupt (IR) on match
-        * channel 0 (MR0). Configure a compare match value of 1 on MR0
-        * and enable interrupt, reset on match and stop on match (MCR).
+        * channel 0 (MR0). Clear the prescaler as it's not used.
         */
        writel_relaxed(0, base + LPC32XX_TIMER_TCR);
+       writel_relaxed(0, base + LPC32XX_TIMER_PR);
        writel_relaxed(0, base + LPC32XX_TIMER_CTCR);
        writel_relaxed(LPC32XX_TIMER_IR_MR0INT, base + LPC32XX_TIMER_IR);
-       writel_relaxed(1, base + LPC32XX_TIMER_MR0);
-       writel_relaxed(LPC32XX_TIMER_MCR_MR0I | LPC32XX_TIMER_MCR_MR0R |
-                      LPC32XX_TIMER_MCR_MR0S, base + LPC32XX_TIMER_MCR);
 
        rate = clk_get_rate(clk);
        lpc32xx_clk_event_ddata.base = base;
+       lpc32xx_clk_event_ddata.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ);
        clockevents_config_and_register(&lpc32xx_clk_event_ddata.evtdev,
                                        rate, 1, -1);
 
index 659879a56dbac59c7f18e0d2f51393bf9a3e645f..a7f45853c10337c25a6aea4dca90aa7cca5f99b5 100644 (file)
@@ -19,6 +19,7 @@ config CPU_FREQ
 if CPU_FREQ
 
 config CPU_FREQ_GOV_COMMON
+       select IRQ_WORK
        bool
 
 config CPU_FREQ_BOOST_SW
@@ -296,6 +297,7 @@ endif
 config QORIQ_CPUFREQ
        tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
        depends on OF && COMMON_CLK && (PPC_E500MC || ARM)
+       depends on !CPU_THERMAL || THERMAL
        select CLK_QORIQ
        help
          This adds the CPUFreq driver support for Freescale QorIQ SoCs
index 0031069b64c95aa93f2d1d0696ee8a9c63cc59ef..14b1f9393b057e106d7b068883ce486ea70239ec 100644 (file)
@@ -84,10 +84,10 @@ config ARM_KIRKWOOD_CPUFREQ
          SoCs.
 
 config ARM_MT8173_CPUFREQ
-       bool "Mediatek MT8173 CPUFreq support"
+       tristate "Mediatek MT8173 CPUFreq support"
        depends on ARCH_MEDIATEK && REGULATOR
        depends on ARM64 || (ARM_CPU_TOPOLOGY && COMPILE_TEST)
-       depends on !CPU_THERMAL || THERMAL=y
+       depends on !CPU_THERMAL || THERMAL
        select PM_OPP
        help
          This adds the CPUFreq driver support for Mediatek MT8173 SoC.
index 51eef87bbc374f85826b16b27141f024aefd9bbe..59a7b380fbe28fcc242e3aa641ff1eac1a09ebcb 100644 (file)
@@ -70,6 +70,8 @@ struct acpi_cpufreq_data {
        unsigned int cpu_feature;
        unsigned int acpi_perf_cpu;
        cpumask_var_t freqdomain_cpus;
+       void (*cpu_freq_write)(struct acpi_pct_register *reg, u32 val);
+       u32 (*cpu_freq_read)(struct acpi_pct_register *reg);
 };
 
 /* acpi_perf_data is a pointer to percpu data. */
@@ -243,125 +245,119 @@ static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data)
        }
 }
 
-struct msr_addr {
-       u32 reg;
-};
+u32 cpu_freq_read_intel(struct acpi_pct_register *not_used)
+{
+       u32 val, dummy;
 
-struct io_addr {
-       u16 port;
-       u8 bit_width;
-};
+       rdmsr(MSR_IA32_PERF_CTL, val, dummy);
+       return val;
+}
+
+void cpu_freq_write_intel(struct acpi_pct_register *not_used, u32 val)
+{
+       u32 lo, hi;
+
+       rdmsr(MSR_IA32_PERF_CTL, lo, hi);
+       lo = (lo & ~INTEL_MSR_RANGE) | (val & INTEL_MSR_RANGE);
+       wrmsr(MSR_IA32_PERF_CTL, lo, hi);
+}
+
+u32 cpu_freq_read_amd(struct acpi_pct_register *not_used)
+{
+       u32 val, dummy;
+
+       rdmsr(MSR_AMD_PERF_CTL, val, dummy);
+       return val;
+}
+
+void cpu_freq_write_amd(struct acpi_pct_register *not_used, u32 val)
+{
+       wrmsr(MSR_AMD_PERF_CTL, val, 0);
+}
+
+u32 cpu_freq_read_io(struct acpi_pct_register *reg)
+{
+       u32 val;
+
+       acpi_os_read_port(reg->address, &val, reg->bit_width);
+       return val;
+}
+
+void cpu_freq_write_io(struct acpi_pct_register *reg, u32 val)
+{
+       acpi_os_write_port(reg->address, val, reg->bit_width);
+}
 
 struct drv_cmd {
-       unsigned int type;
-       const struct cpumask *mask;
-       union {
-               struct msr_addr msr;
-               struct io_addr io;
-       } addr;
+       struct acpi_pct_register *reg;
        u32 val;
+       union {
+               void (*write)(struct acpi_pct_register *reg, u32 val);
+               u32 (*read)(struct acpi_pct_register *reg);
+       } func;
 };
 
 /* Called via smp_call_function_single(), on the target CPU */
 static void do_drv_read(void *_cmd)
 {
        struct drv_cmd *cmd = _cmd;
-       u32 h;
 
-       switch (cmd->type) {
-       case SYSTEM_INTEL_MSR_CAPABLE:
-       case SYSTEM_AMD_MSR_CAPABLE:
-               rdmsr(cmd->addr.msr.reg, cmd->val, h);
-               break;
-       case SYSTEM_IO_CAPABLE:
-               acpi_os_read_port((acpi_io_address)cmd->addr.io.port,
-                               &cmd->val,
-                               (u32)cmd->addr.io.bit_width);
-               break;
-       default:
-               break;
-       }
+       cmd->val = cmd->func.read(cmd->reg);
 }
 
-/* Called via smp_call_function_many(), on the target CPUs */
-static void do_drv_write(void *_cmd)
+static u32 drv_read(struct acpi_cpufreq_data *data, const struct cpumask *mask)
 {
-       struct drv_cmd *cmd = _cmd;
-       u32 lo, hi;
+       struct acpi_processor_performance *perf = to_perf_data(data);
+       struct drv_cmd cmd = {
+               .reg = &perf->control_register,
+               .func.read = data->cpu_freq_read,
+       };
+       int err;
 
-       switch (cmd->type) {
-       case SYSTEM_INTEL_MSR_CAPABLE:
-               rdmsr(cmd->addr.msr.reg, lo, hi);
-               lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE);
-               wrmsr(cmd->addr.msr.reg, lo, hi);
-               break;
-       case SYSTEM_AMD_MSR_CAPABLE:
-               wrmsr(cmd->addr.msr.reg, cmd->val, 0);
-               break;
-       case SYSTEM_IO_CAPABLE:
-               acpi_os_write_port((acpi_io_address)cmd->addr.io.port,
-                               cmd->val,
-                               (u32)cmd->addr.io.bit_width);
-               break;
-       default:
-               break;
-       }
+       err = smp_call_function_any(mask, do_drv_read, &cmd, 1);
+       WARN_ON_ONCE(err);      /* smp_call_function_any() was buggy? */
+       return cmd.val;
 }
 
-static void drv_read(struct drv_cmd *cmd)
+/* Called via smp_call_function_many(), on the target CPUs */
+static void do_drv_write(void *_cmd)
 {
-       int err;
-       cmd->val = 0;
+       struct drv_cmd *cmd = _cmd;
 
-       err = smp_call_function_any(cmd->mask, do_drv_read, cmd, 1);
-       WARN_ON_ONCE(err);      /* smp_call_function_any() was buggy? */
+       cmd->func.write(cmd->reg, cmd->val);
 }
 
-static void drv_write(struct drv_cmd *cmd)
+static void drv_write(struct acpi_cpufreq_data *data,
+                     const struct cpumask *mask, u32 val)
 {
+       struct acpi_processor_performance *perf = to_perf_data(data);
+       struct drv_cmd cmd = {
+               .reg = &perf->control_register,
+               .val = val,
+               .func.write = data->cpu_freq_write,
+       };
        int this_cpu;
 
        this_cpu = get_cpu();
-       if (cpumask_test_cpu(this_cpu, cmd->mask))
-               do_drv_write(cmd);
-       smp_call_function_many(cmd->mask, do_drv_write, cmd, 1);
+       if (cpumask_test_cpu(this_cpu, mask))
+               do_drv_write(&cmd);
+
+       smp_call_function_many(mask, do_drv_write, &cmd, 1);
        put_cpu();
 }
 
-static u32
-get_cur_val(const struct cpumask *mask, struct acpi_cpufreq_data *data)
+static u32 get_cur_val(const struct cpumask *mask, struct acpi_cpufreq_data *data)
 {
-       struct acpi_processor_performance *perf;
-       struct drv_cmd cmd;
+       u32 val;
 
        if (unlikely(cpumask_empty(mask)))
                return 0;
 
-       switch (data->cpu_feature) {
-       case SYSTEM_INTEL_MSR_CAPABLE:
-               cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
-               cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
-               break;
-       case SYSTEM_AMD_MSR_CAPABLE:
-               cmd.type = SYSTEM_AMD_MSR_CAPABLE;
-               cmd.addr.msr.reg = MSR_AMD_PERF_CTL;
-               break;
-       case SYSTEM_IO_CAPABLE:
-               cmd.type = SYSTEM_IO_CAPABLE;
-               perf = to_perf_data(data);
-               cmd.addr.io.port = perf->control_register.address;
-               cmd.addr.io.bit_width = perf->control_register.bit_width;
-               break;
-       default:
-               return 0;
-       }
-
-       cmd.mask = mask;
-       drv_read(&cmd);
+       val = drv_read(data, mask);
 
-       pr_debug("get_cur_val = %u\n", cmd.val);
+       pr_debug("get_cur_val = %u\n", val);
 
-       return cmd.val;
+       return val;
 }
 
 static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
@@ -416,7 +412,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
 {
        struct acpi_cpufreq_data *data = policy->driver_data;
        struct acpi_processor_performance *perf;
-       struct drv_cmd cmd;
+       const struct cpumask *mask;
        unsigned int next_perf_state = 0; /* Index into perf table */
        int result = 0;
 
@@ -434,42 +430,21 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
                } else {
                        pr_debug("Already at target state (P%d)\n",
                                next_perf_state);
-                       goto out;
+                       return 0;
                }
        }
 
-       switch (data->cpu_feature) {
-       case SYSTEM_INTEL_MSR_CAPABLE:
-               cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
-               cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
-               cmd.val = (u32) perf->states[next_perf_state].control;
-               break;
-       case SYSTEM_AMD_MSR_CAPABLE:
-               cmd.type = SYSTEM_AMD_MSR_CAPABLE;
-               cmd.addr.msr.reg = MSR_AMD_PERF_CTL;
-               cmd.val = (u32) perf->states[next_perf_state].control;
-               break;
-       case SYSTEM_IO_CAPABLE:
-               cmd.type = SYSTEM_IO_CAPABLE;
-               cmd.addr.io.port = perf->control_register.address;
-               cmd.addr.io.bit_width = perf->control_register.bit_width;
-               cmd.val = (u32) perf->states[next_perf_state].control;
-               break;
-       default:
-               result = -ENODEV;
-               goto out;
-       }
-
-       /* cpufreq holds the hotplug lock, so we are safe from here on */
-       if (policy->shared_type != CPUFREQ_SHARED_TYPE_ANY)
-               cmd.mask = policy->cpus;
-       else
-               cmd.mask = cpumask_of(policy->cpu);
+       /*
+        * The core won't allow CPUs to go away until the governor has been
+        * stopped, so we can rely on the stability of policy->cpus.
+        */
+       mask = policy->shared_type == CPUFREQ_SHARED_TYPE_ANY ?
+               cpumask_of(policy->cpu) : policy->cpus;
 
-       drv_write(&cmd);
+       drv_write(data, mask, perf->states[next_perf_state].control);
 
        if (acpi_pstate_strict) {
-               if (!check_freqs(cmd.mask, data->freq_table[index].frequency,
+               if (!check_freqs(mask, data->freq_table[index].frequency,
                                        data)) {
                        pr_debug("acpi_cpufreq_target failed (%d)\n",
                                policy->cpu);
@@ -480,7 +455,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
        if (!result)
                perf->state = next_perf_state;
 
-out:
        return result;
 }
 
@@ -740,15 +714,21 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
                }
                pr_debug("SYSTEM IO addr space\n");
                data->cpu_feature = SYSTEM_IO_CAPABLE;
+               data->cpu_freq_read = cpu_freq_read_io;
+               data->cpu_freq_write = cpu_freq_write_io;
                break;
        case ACPI_ADR_SPACE_FIXED_HARDWARE:
                pr_debug("HARDWARE addr space\n");
                if (check_est_cpu(cpu)) {
                        data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE;
+                       data->cpu_freq_read = cpu_freq_read_intel;
+                       data->cpu_freq_write = cpu_freq_write_intel;
                        break;
                }
                if (check_amd_hwpstate_cpu(cpu)) {
                        data->cpu_feature = SYSTEM_AMD_MSR_CAPABLE;
+                       data->cpu_freq_read = cpu_freq_read_amd;
+                       data->cpu_freq_write = cpu_freq_write_amd;
                        break;
                }
                result = -ENODEV;
index f6b79ab0070b58e91ac4692498b4ab7cb430cfa0..404360cad25c4cf88df2d2a2eedc492bf0a7e744 100644 (file)
@@ -21,7 +21,7 @@
 #include <asm/msr.h>
 #include <asm/cpufeature.h>
 
-#include "cpufreq_governor.h"
+#include "cpufreq_ondemand.h"
 
 #define MSR_AMD64_FREQ_SENSITIVITY_ACTUAL      0xc0010080
 #define MSR_AMD64_FREQ_SENSITIVITY_REFERENCE   0xc0010081
@@ -45,10 +45,10 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy,
        long d_actual, d_reference;
        struct msr actual, reference;
        struct cpu_data_t *data = &per_cpu(cpu_data, policy->cpu);
-       struct dbs_data *od_data = policy->governor_data;
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct dbs_data *od_data = policy_dbs->dbs_data;
        struct od_dbs_tuners *od_tuners = od_data->tuners;
-       struct od_cpu_dbs_info_s *od_info =
-               od_data->cdata->get_cpu_dbs_info_s(policy->cpu);
+       struct od_policy_dbs_info *od_info = to_dbs_info(policy_dbs);
 
        if (!od_info->freq_table)
                return freq_next;
index 0ca74d07005830cec5abaf92a84c59af17325616..f951f911786e086b2b6dc9d615018eb235347dbe 100644 (file)
@@ -31,9 +31,8 @@
 
 struct private_data {
        struct device *cpu_dev;
-       struct regulator *cpu_reg;
        struct thermal_cooling_device *cdev;
-       unsigned int voltage_tolerance; /* in percentage */
+       const char *reg_name;
 };
 
 static struct freq_attr *cpufreq_dt_attr[] = {
@@ -44,175 +43,128 @@ static struct freq_attr *cpufreq_dt_attr[] = {
 
 static int set_target(struct cpufreq_policy *policy, unsigned int index)
 {
-       struct dev_pm_opp *opp;
-       struct cpufreq_frequency_table *freq_table = policy->freq_table;
-       struct clk *cpu_clk = policy->clk;
        struct private_data *priv = policy->driver_data;
-       struct device *cpu_dev = priv->cpu_dev;
-       struct regulator *cpu_reg = priv->cpu_reg;
-       unsigned long volt = 0, tol = 0;
-       int volt_old = 0;
-       unsigned int old_freq, new_freq;
-       long freq_Hz, freq_exact;
-       int ret;
-
-       freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
-       if (freq_Hz <= 0)
-               freq_Hz = freq_table[index].frequency * 1000;
 
-       freq_exact = freq_Hz;
-       new_freq = freq_Hz / 1000;
-       old_freq = clk_get_rate(cpu_clk) / 1000;
+       return dev_pm_opp_set_rate(priv->cpu_dev,
+                                  policy->freq_table[index].frequency * 1000);
+}
 
-       if (!IS_ERR(cpu_reg)) {
-               unsigned long opp_freq;
+/*
+ * An earlier version of opp-v1 bindings used to name the regulator
+ * "cpu0-supply", we still need to handle that for backwards compatibility.
+ */
+static const char *find_supply_name(struct device *dev)
+{
+       struct device_node *np;
+       struct property *pp;
+       int cpu = dev->id;
+       const char *name = NULL;
 
-               rcu_read_lock();
-               opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
-               if (IS_ERR(opp)) {
-                       rcu_read_unlock();
-                       dev_err(cpu_dev, "failed to find OPP for %ld\n",
-                               freq_Hz);
-                       return PTR_ERR(opp);
-               }
-               volt = dev_pm_opp_get_voltage(opp);
-               opp_freq = dev_pm_opp_get_freq(opp);
-               rcu_read_unlock();
-               tol = volt * priv->voltage_tolerance / 100;
-               volt_old = regulator_get_voltage(cpu_reg);
-               dev_dbg(cpu_dev, "Found OPP: %ld kHz, %ld uV\n",
-                       opp_freq / 1000, volt);
-       }
+       np = of_node_get(dev->of_node);
 
-       dev_dbg(cpu_dev, "%u MHz, %d mV --> %u MHz, %ld mV\n",
-               old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
-               new_freq / 1000, volt ? volt / 1000 : -1);
+       /* This must be valid for sure */
+       if (WARN_ON(!np))
+               return NULL;
 
-       /* scaling up?  scale voltage before frequency */
-       if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
-               ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
-               if (ret) {
-                       dev_err(cpu_dev, "failed to scale voltage up: %d\n",
-                               ret);
-                       return ret;
+       /* Try "cpu0" for older DTs */
+       if (!cpu) {
+               pp = of_find_property(np, "cpu0-supply", NULL);
+               if (pp) {
+                       name = "cpu0";
+                       goto node_put;
                }
        }
 
-       ret = clk_set_rate(cpu_clk, freq_exact);
-       if (ret) {
-               dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
-               if (!IS_ERR(cpu_reg) && volt_old > 0)
-                       regulator_set_voltage_tol(cpu_reg, volt_old, tol);
-               return ret;
+       pp = of_find_property(np, "cpu-supply", NULL);
+       if (pp) {
+               name = "cpu";
+               goto node_put;
        }
 
-       /* scaling down?  scale voltage after frequency */
-       if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
-               ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
-               if (ret) {
-                       dev_err(cpu_dev, "failed to scale voltage down: %d\n",
-                               ret);
-                       clk_set_rate(cpu_clk, old_freq * 1000);
-               }
-       }
-
-       return ret;
+       dev_dbg(dev, "no regulator for cpu%d\n", cpu);
+node_put:
+       of_node_put(np);
+       return name;
 }
 
-static int allocate_resources(int cpu, struct device **cdev,
-                             struct regulator **creg, struct clk **cclk)
+static int resources_available(void)
 {
        struct device *cpu_dev;
        struct regulator *cpu_reg;
        struct clk *cpu_clk;
        int ret = 0;
-       char *reg_cpu0 = "cpu0", *reg_cpu = "cpu", *reg;
+       const char *name;
 
-       cpu_dev = get_cpu_device(cpu);
+       cpu_dev = get_cpu_device(0);
        if (!cpu_dev) {
-               pr_err("failed to get cpu%d device\n", cpu);
+               pr_err("failed to get cpu0 device\n");
                return -ENODEV;
        }
 
-       /* Try "cpu0" for older DTs */
-       if (!cpu)
-               reg = reg_cpu0;
-       else
-               reg = reg_cpu;
-
-try_again:
-       cpu_reg = regulator_get_optional(cpu_dev, reg);
-       ret = PTR_ERR_OR_ZERO(cpu_reg);
+       cpu_clk = clk_get(cpu_dev, NULL);
+       ret = PTR_ERR_OR_ZERO(cpu_clk);
        if (ret) {
                /*
-                * If cpu's regulator supply node is present, but regulator is
-                * not yet registered, we should try defering probe.
+                * If cpu's clk node is present, but clock is not yet
+                * registered, we should try defering probe.
                 */
-               if (ret == -EPROBE_DEFER) {
-                       dev_dbg(cpu_dev, "cpu%d regulator not ready, retry\n",
-                               cpu);
-                       return ret;
-               }
-
-               /* Try with "cpu-supply" */
-               if (reg == reg_cpu0) {
-                       reg = reg_cpu;
-                       goto try_again;
-               }
+               if (ret == -EPROBE_DEFER)
+                       dev_dbg(cpu_dev, "clock not ready, retry\n");
+               else
+                       dev_err(cpu_dev, "failed to get clock: %d\n", ret);
 
-               dev_dbg(cpu_dev, "no regulator for cpu%d: %d\n", cpu, ret);
+               return ret;
        }
 
-       cpu_clk = clk_get(cpu_dev, NULL);
-       ret = PTR_ERR_OR_ZERO(cpu_clk);
-       if (ret) {
-               /* put regulator */
-               if (!IS_ERR(cpu_reg))
-                       regulator_put(cpu_reg);
+       clk_put(cpu_clk);
 
+       name = find_supply_name(cpu_dev);
+       /* Platform doesn't require regulator */
+       if (!name)
+               return 0;
+
+       cpu_reg = regulator_get_optional(cpu_dev, name);
+       ret = PTR_ERR_OR_ZERO(cpu_reg);
+       if (ret) {
                /*
-                * If cpu's clk node is present, but clock is not yet
-                * registered, we should try defering probe.
+                * If cpu's regulator supply node is present, but regulator is
+                * not yet registered, we should try defering probe.
                 */
                if (ret == -EPROBE_DEFER)
-                       dev_dbg(cpu_dev, "cpu%d clock not ready, retry\n", cpu);
+                       dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n");
                else
-                       dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", cpu,
-                               ret);
-       } else {
-               *cdev = cpu_dev;
-               *creg = cpu_reg;
-               *cclk = cpu_clk;
+                       dev_dbg(cpu_dev, "no regulator for cpu0: %d\n", ret);
+
+               return ret;
        }
 
-       return ret;
+       regulator_put(cpu_reg);
+       return 0;
 }
 
 static int cpufreq_init(struct cpufreq_policy *policy)
 {
        struct cpufreq_frequency_table *freq_table;
-       struct device_node *np;
        struct private_data *priv;
        struct device *cpu_dev;
-       struct regulator *cpu_reg;
        struct clk *cpu_clk;
        struct dev_pm_opp *suspend_opp;
-       unsigned long min_uV = ~0, max_uV = 0;
        unsigned int transition_latency;
-       bool need_update = false;
+       bool opp_v1 = false;
+       const char *name;
        int ret;
 
-       ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
-       if (ret) {
-               pr_err("%s: Failed to allocate resources: %d\n", __func__, ret);
-               return ret;
+       cpu_dev = get_cpu_device(policy->cpu);
+       if (!cpu_dev) {
+               pr_err("failed to get cpu%d device\n", policy->cpu);
+               return -ENODEV;
        }
 
-       np = of_node_get(cpu_dev->of_node);
-       if (!np) {
-               dev_err(cpu_dev, "failed to find cpu%d node\n", policy->cpu);
-               ret = -ENOENT;
-               goto out_put_reg_clk;
+       cpu_clk = clk_get(cpu_dev, NULL);
+       if (IS_ERR(cpu_clk)) {
+               ret = PTR_ERR(cpu_clk);
+               dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret);
+               return ret;
        }
 
        /* Get OPP-sharing information from "operating-points-v2" bindings */
@@ -223,9 +175,23 @@ static int cpufreq_init(struct cpufreq_policy *policy)
                 * finding shared-OPPs for backward compatibility.
                 */
                if (ret == -ENOENT)
-                       need_update = true;
+                       opp_v1 = true;
                else
-                       goto out_node_put;
+                       goto out_put_clk;
+       }
+
+       /*
+        * OPP layer will be taking care of regulators now, but it needs to know
+        * the name of the regulator first.
+        */
+       name = find_supply_name(cpu_dev);
+       if (name) {
+               ret = dev_pm_opp_set_regulator(cpu_dev, name);
+               if (ret) {
+                       dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
+                               policy->cpu, ret);
+                       goto out_put_clk;
+               }
        }
 
        /*
@@ -246,12 +212,12 @@ static int cpufreq_init(struct cpufreq_policy *policy)
         */
        ret = dev_pm_opp_get_opp_count(cpu_dev);
        if (ret <= 0) {
-               pr_debug("OPP table is not ready, deferring probe\n");
+               dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
                ret = -EPROBE_DEFER;
                goto out_free_opp;
        }
 
-       if (need_update) {
+       if (opp_v1) {
                struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data();
 
                if (!pd || !pd->independent_clocks)
@@ -265,10 +231,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
                if (ret)
                        dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
                                __func__, ret);
-
-               of_property_read_u32(np, "clock-latency", &transition_latency);
-       } else {
-               transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev);
        }
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -277,62 +239,16 @@ static int cpufreq_init(struct cpufreq_policy *policy)
                goto out_free_opp;
        }
 
-       of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
-
-       if (!transition_latency)
-               transition_latency = CPUFREQ_ETERNAL;
-
-       if (!IS_ERR(cpu_reg)) {
-               unsigned long opp_freq = 0;
-
-               /*
-                * Disable any OPPs where the connected regulator isn't able to
-                * provide the specified voltage and record minimum and maximum
-                * voltage levels.
-                */
-               while (1) {
-                       struct dev_pm_opp *opp;
-                       unsigned long opp_uV, tol_uV;
-
-                       rcu_read_lock();
-                       opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq);
-                       if (IS_ERR(opp)) {
-                               rcu_read_unlock();
-                               break;
-                       }
-                       opp_uV = dev_pm_opp_get_voltage(opp);
-                       rcu_read_unlock();
-
-                       tol_uV = opp_uV * priv->voltage_tolerance / 100;
-                       if (regulator_is_supported_voltage(cpu_reg,
-                                                          opp_uV - tol_uV,
-                                                          opp_uV + tol_uV)) {
-                               if (opp_uV < min_uV)
-                                       min_uV = opp_uV;
-                               if (opp_uV > max_uV)
-                                       max_uV = opp_uV;
-                       } else {
-                               dev_pm_opp_disable(cpu_dev, opp_freq);
-                       }
-
-                       opp_freq++;
-               }
-
-               ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
-               if (ret > 0)
-                       transition_latency += ret * 1000;
-       }
+       priv->reg_name = name;
 
        ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
        if (ret) {
-               pr_err("failed to init cpufreq table: %d\n", ret);
+               dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
                goto out_free_priv;
        }
 
        priv->cpu_dev = cpu_dev;
-       priv->cpu_reg = cpu_reg;
        policy->driver_data = priv;
-
        policy->clk = cpu_clk;
 
        rcu_read_lock();
@@ -357,9 +273,11 @@ static int cpufreq_init(struct cpufreq_policy *policy)
                cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
        }
 
-       policy->cpuinfo.transition_latency = transition_latency;
+       transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
+       if (!transition_latency)
+               transition_latency = CPUFREQ_ETERNAL;
 
-       of_node_put(np);
+       policy->cpuinfo.transition_latency = transition_latency;
 
        return 0;
 
@@ -369,12 +287,10 @@ out_free_priv:
        kfree(priv);
 out_free_opp:
        dev_pm_opp_of_cpumask_remove_table(policy->cpus);
-out_node_put:
-       of_node_put(np);
-out_put_reg_clk:
+       if (name)
+               dev_pm_opp_put_regulator(cpu_dev);
+out_put_clk:
        clk_put(cpu_clk);
-       if (!IS_ERR(cpu_reg))
-               regulator_put(cpu_reg);
 
        return ret;
 }
@@ -386,9 +302,10 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
        cpufreq_cooling_unregister(priv->cdev);
        dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
        dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
+       if (priv->reg_name)
+               dev_pm_opp_put_regulator(priv->cpu_dev);
+
        clk_put(policy->clk);
-       if (!IS_ERR(priv->cpu_reg))
-               regulator_put(priv->cpu_reg);
        kfree(priv);
 
        return 0;
@@ -441,9 +358,6 @@ static struct cpufreq_driver dt_cpufreq_driver = {
 
 static int dt_cpufreq_probe(struct platform_device *pdev)
 {
-       struct device *cpu_dev;
-       struct regulator *cpu_reg;
-       struct clk *cpu_clk;
        int ret;
 
        /*
@@ -453,19 +367,15 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
         *
         * FIXME: Is checking this only for CPU0 sufficient ?
         */
-       ret = allocate_resources(0, &cpu_dev, &cpu_reg, &cpu_clk);
+       ret = resources_available();
        if (ret)
                return ret;
 
-       clk_put(cpu_clk);
-       if (!IS_ERR(cpu_reg))
-               regulator_put(cpu_reg);
-
        dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev);
 
        ret = cpufreq_register_driver(&dt_cpufreq_driver);
        if (ret)
-               dev_err(cpu_dev, "failed register driver: %d\n", ret);
+               dev_err(&pdev->dev, "failed register driver: %d\n", ret);
 
        return ret;
 }
index e979ec78b69522edefb2a49b6497c2bbb83e1e62..4c7825856eabebde799913257e936f12b29ec387 100644 (file)
@@ -38,48 +38,10 @@ static inline bool policy_is_inactive(struct cpufreq_policy *policy)
        return cpumask_empty(policy->cpus);
 }
 
-static bool suitable_policy(struct cpufreq_policy *policy, bool active)
-{
-       return active == !policy_is_inactive(policy);
-}
-
-/* Finds Next Acive/Inactive policy */
-static struct cpufreq_policy *next_policy(struct cpufreq_policy *policy,
-                                         bool active)
-{
-       do {
-               /* No more policies in the list */
-               if (list_is_last(&policy->policy_list, &cpufreq_policy_list))
-                       return NULL;
-
-               policy = list_next_entry(policy, policy_list);
-       } while (!suitable_policy(policy, active));
-
-       return policy;
-}
-
-static struct cpufreq_policy *first_policy(bool active)
-{
-       struct cpufreq_policy *policy;
-
-       /* No policies in the list */
-       if (list_empty(&cpufreq_policy_list))
-               return NULL;
-
-       policy = list_first_entry(&cpufreq_policy_list, typeof(*policy),
-                                 policy_list);
-
-       if (!suitable_policy(policy, active))
-               policy = next_policy(policy, active);
-
-       return policy;
-}
-
 /* Macros to iterate over CPU policies */
-#define for_each_suitable_policy(__policy, __active)   \
-       for (__policy = first_policy(__active);         \
-            __policy;                                  \
-            __policy = next_policy(__policy, __active))
+#define for_each_suitable_policy(__policy, __active)                    \
+       list_for_each_entry(__policy, &cpufreq_policy_list, policy_list) \
+               if ((__active) == !policy_is_inactive(__policy))
 
 #define for_each_active_policy(__policy)               \
        for_each_suitable_policy(__policy, true)
@@ -102,7 +64,6 @@ static LIST_HEAD(cpufreq_governor_list);
 static struct cpufreq_driver *cpufreq_driver;
 static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
 static DEFINE_RWLOCK(cpufreq_driver_lock);
-DEFINE_MUTEX(cpufreq_governor_lock);
 
 /* Flag to suspend/resume CPUFreq governors */
 static bool cpufreq_suspended;
@@ -113,10 +74,8 @@ static inline bool has_target(void)
 }
 
 /* internal prototypes */
-static int __cpufreq_governor(struct cpufreq_policy *policy,
-               unsigned int event);
+static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event);
 static unsigned int __cpufreq_get(struct cpufreq_policy *policy);
-static void handle_update(struct work_struct *work);
 
 /**
  * Two notifier lists: the "policy" list is involved in the
@@ -818,12 +777,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
        ssize_t ret;
 
        down_read(&policy->rwsem);
-
-       if (fattr->show)
-               ret = fattr->show(policy, buf);
-       else
-               ret = -EIO;
-
+       ret = fattr->show(policy, buf);
        up_read(&policy->rwsem);
 
        return ret;
@@ -838,18 +792,12 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
 
        get_online_cpus();
 
-       if (!cpu_online(policy->cpu))
-               goto unlock;
-
-       down_write(&policy->rwsem);
-
-       if (fattr->store)
+       if (cpu_online(policy->cpu)) {
+               down_write(&policy->rwsem);
                ret = fattr->store(policy, buf, count);
-       else
-               ret = -EIO;
+               up_write(&policy->rwsem);
+       }
 
-       up_write(&policy->rwsem);
-unlock:
        put_online_cpus();
 
        return ret;
@@ -959,6 +907,11 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy)
        return cpufreq_add_dev_symlink(policy);
 }
 
+__weak struct cpufreq_governor *cpufreq_default_governor(void)
+{
+       return NULL;
+}
+
 static int cpufreq_init_policy(struct cpufreq_policy *policy)
 {
        struct cpufreq_governor *gov = NULL;
@@ -968,11 +921,14 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy)
 
        /* Update governor of new_policy to the governor used before hotplug */
        gov = find_governor(policy->last_governor);
-       if (gov)
+       if (gov) {
                pr_debug("Restoring governor %s for cpu %d\n",
                                policy->governor->name, policy->cpu);
-       else
-               gov = CPUFREQ_DEFAULT_GOVERNOR;
+       } else {
+               gov = cpufreq_default_governor();
+               if (!gov)
+                       return -ENODATA;
+       }
 
        new_policy.governor = gov;
 
@@ -996,36 +952,45 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp
        if (cpumask_test_cpu(cpu, policy->cpus))
                return 0;
 
+       down_write(&policy->rwsem);
        if (has_target()) {
-               ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+               ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
                if (ret) {
                        pr_err("%s: Failed to stop governor\n", __func__);
-                       return ret;
+                       goto unlock;
                }
        }
 
-       down_write(&policy->rwsem);
        cpumask_set_cpu(cpu, policy->cpus);
-       up_write(&policy->rwsem);
 
        if (has_target()) {
-               ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
+               ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
                if (!ret)
-                       ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+                       ret = cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
 
-               if (ret) {
+               if (ret)
                        pr_err("%s: Failed to start governor\n", __func__);
-                       return ret;
-               }
        }
 
-       return 0;
+unlock:
+       up_write(&policy->rwsem);
+       return ret;
+}
+
+static void handle_update(struct work_struct *work)
+{
+       struct cpufreq_policy *policy =
+               container_of(work, struct cpufreq_policy, update);
+       unsigned int cpu = policy->cpu;
+       pr_debug("handle_update for cpu %u called\n", cpu);
+       cpufreq_update_policy(cpu);
 }
 
 static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
 {
        struct device *dev = get_cpu_device(cpu);
        struct cpufreq_policy *policy;
+       int ret;
 
        if (WARN_ON(!dev))
                return NULL;
@@ -1043,7 +1008,13 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
        if (!zalloc_cpumask_var(&policy->real_cpus, GFP_KERNEL))
                goto err_free_rcpumask;
 
-       kobject_init(&policy->kobj, &ktype_cpufreq);
+       ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
+                                  cpufreq_global_kobject, "policy%u", cpu);
+       if (ret) {
+               pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
+               goto err_free_real_cpus;
+       }
+
        INIT_LIST_HEAD(&policy->policy_list);
        init_rwsem(&policy->rwsem);
        spin_lock_init(&policy->transition_lock);
@@ -1054,6 +1025,8 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
        policy->cpu = cpu;
        return policy;
 
+err_free_real_cpus:
+       free_cpumask_var(policy->real_cpus);
 err_free_rcpumask:
        free_cpumask_var(policy->related_cpus);
 err_free_cpumask:
@@ -1158,16 +1131,6 @@ static int cpufreq_online(unsigned int cpu)
                cpumask_copy(policy->related_cpus, policy->cpus);
                /* Remember CPUs present at the policy creation time. */
                cpumask_and(policy->real_cpus, policy->cpus, cpu_present_mask);
-
-               /* Name and add the kobject */
-               ret = kobject_add(&policy->kobj, cpufreq_global_kobject,
-                                 "policy%u",
-                                 cpumask_first(policy->related_cpus));
-               if (ret) {
-                       pr_err("%s: failed to add policy->kobj: %d\n", __func__,
-                              ret);
-                       goto out_exit_policy;
-               }
        }
 
        /*
@@ -1309,9 +1272,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
        return ret;
 }
 
-static void cpufreq_offline_prepare(unsigned int cpu)
+static void cpufreq_offline(unsigned int cpu)
 {
        struct cpufreq_policy *policy;
+       int ret;
 
        pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
 
@@ -1321,13 +1285,13 @@ static void cpufreq_offline_prepare(unsigned int cpu)
                return;
        }
 
+       down_write(&policy->rwsem);
        if (has_target()) {
-               int ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+               ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
                if (ret)
                        pr_err("%s: Failed to stop governor\n", __func__);
        }
 
-       down_write(&policy->rwsem);
        cpumask_clear_cpu(cpu, policy->cpus);
 
        if (policy_is_inactive(policy)) {
@@ -1340,39 +1304,27 @@ static void cpufreq_offline_prepare(unsigned int cpu)
                /* Nominate new CPU */
                policy->cpu = cpumask_any(policy->cpus);
        }
-       up_write(&policy->rwsem);
 
        /* Start governor again for active policy */
        if (!policy_is_inactive(policy)) {
                if (has_target()) {
-                       int ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
+                       ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
                        if (!ret)
-                               ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+                               ret = cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
 
                        if (ret)
                                pr_err("%s: Failed to start governor\n", __func__);
                }
-       } else if (cpufreq_driver->stop_cpu) {
-               cpufreq_driver->stop_cpu(policy);
-       }
-}
 
-static void cpufreq_offline_finish(unsigned int cpu)
-{
-       struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
-
-       if (!policy) {
-               pr_debug("%s: No cpu_data found\n", __func__);
-               return;
+               goto unlock;
        }
 
-       /* Only proceed for inactive policies */
-       if (!policy_is_inactive(policy))
-               return;
+       if (cpufreq_driver->stop_cpu)
+               cpufreq_driver->stop_cpu(policy);
 
        /* If cpu is last user of policy, free policy */
        if (has_target()) {
-               int ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
+               ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
                if (ret)
                        pr_err("%s: Failed to exit governor\n", __func__);
        }
@@ -1386,6 +1338,9 @@ static void cpufreq_offline_finish(unsigned int cpu)
                cpufreq_driver->exit(policy);
                policy->freq_table = NULL;
        }
+
+unlock:
+       up_write(&policy->rwsem);
 }
 
 /**
@@ -1401,10 +1356,8 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
        if (!policy)
                return;
 
-       if (cpu_online(cpu)) {
-               cpufreq_offline_prepare(cpu);
-               cpufreq_offline_finish(cpu);
-       }
+       if (cpu_online(cpu))
+               cpufreq_offline(cpu);
 
        cpumask_clear_cpu(cpu, policy->real_cpus);
        remove_cpu_dev_symlink(policy, cpu);
@@ -1413,15 +1366,6 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
                cpufreq_policy_free(policy, true);
 }
 
-static void handle_update(struct work_struct *work)
-{
-       struct cpufreq_policy *policy =
-               container_of(work, struct cpufreq_policy, update);
-       unsigned int cpu = policy->cpu;
-       pr_debug("handle_update for cpu %u called\n", cpu);
-       cpufreq_update_policy(cpu);
-}
-
 /**
  *     cpufreq_out_of_sync - If actual and saved CPU frequency differs, we're
  *     in deep trouble.
@@ -1584,6 +1528,7 @@ EXPORT_SYMBOL(cpufreq_generic_suspend);
 void cpufreq_suspend(void)
 {
        struct cpufreq_policy *policy;
+       int ret;
 
        if (!cpufreq_driver)
                return;
@@ -1594,7 +1539,11 @@ void cpufreq_suspend(void)
        pr_debug("%s: Suspending Governors\n", __func__);
 
        for_each_active_policy(policy) {
-               if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP))
+               down_write(&policy->rwsem);
+               ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+               up_write(&policy->rwsem);
+
+               if (ret)
                        pr_err("%s: Failed to stop governor for policy: %p\n",
                                __func__, policy);
                else if (cpufreq_driver->suspend
@@ -1616,6 +1565,7 @@ suspend:
 void cpufreq_resume(void)
 {
        struct cpufreq_policy *policy;
+       int ret;
 
        if (!cpufreq_driver)
                return;
@@ -1628,13 +1578,20 @@ void cpufreq_resume(void)
        pr_debug("%s: Resuming Governors\n", __func__);
 
        for_each_active_policy(policy) {
-               if (cpufreq_driver->resume && cpufreq_driver->resume(policy))
+               if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) {
                        pr_err("%s: Failed to resume driver: %p\n", __func__,
                                policy);
-               else if (__cpufreq_governor(policy, CPUFREQ_GOV_START)
-                   || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))
-                       pr_err("%s: Failed to start governor for policy: %p\n",
-                               __func__, policy);
+               } else {
+                       down_write(&policy->rwsem);
+                       ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
+                       if (!ret)
+                               cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+                       up_write(&policy->rwsem);
+
+                       if (ret)
+                               pr_err("%s: Failed to start governor for policy: %p\n",
+                                      __func__, policy);
+               }
        }
 
        /*
@@ -1846,7 +1803,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
                            unsigned int relation)
 {
        unsigned int old_target_freq = target_freq;
-       int retval = -EINVAL;
+       struct cpufreq_frequency_table *freq_table;
+       int index, retval;
 
        if (cpufreq_disabled())
                return -ENODEV;
@@ -1873,34 +1831,28 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
        policy->restore_freq = policy->cur;
 
        if (cpufreq_driver->target)
-               retval = cpufreq_driver->target(policy, target_freq, relation);
-       else if (cpufreq_driver->target_index) {
-               struct cpufreq_frequency_table *freq_table;
-               int index;
-
-               freq_table = cpufreq_frequency_get_table(policy->cpu);
-               if (unlikely(!freq_table)) {
-                       pr_err("%s: Unable to find freq_table\n", __func__);
-                       goto out;
-               }
+               return cpufreq_driver->target(policy, target_freq, relation);
 
-               retval = cpufreq_frequency_table_target(policy, freq_table,
-                               target_freq, relation, &index);
-               if (unlikely(retval)) {
-                       pr_err("%s: Unable to find matching freq\n", __func__);
-                       goto out;
-               }
+       if (!cpufreq_driver->target_index)
+               return -EINVAL;
 
-               if (freq_table[index].frequency == policy->cur) {
-                       retval = 0;
-                       goto out;
-               }
+       freq_table = cpufreq_frequency_get_table(policy->cpu);
+       if (unlikely(!freq_table)) {
+               pr_err("%s: Unable to find freq_table\n", __func__);
+               return -EINVAL;
+       }
 
-               retval = __target_index(policy, freq_table, index);
+       retval = cpufreq_frequency_table_target(policy, freq_table, target_freq,
+                                               relation, &index);
+       if (unlikely(retval)) {
+               pr_err("%s: Unable to find matching freq\n", __func__);
+               return retval;
        }
 
-out:
-       return retval;
+       if (freq_table[index].frequency == policy->cur)
+               return 0;
+
+       return __target_index(policy, freq_table, index);
 }
 EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
 
@@ -1920,20 +1872,14 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
-static int __cpufreq_governor(struct cpufreq_policy *policy,
-                                       unsigned int event)
+__weak struct cpufreq_governor *cpufreq_fallback_governor(void)
 {
-       int ret;
+       return NULL;
+}
 
-       /* Only must be defined when default governor is known to have latency
-          restrictions, like e.g. conservative or ondemand.
-          That this is the case is already ensured in Kconfig
-       */
-#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE
-       struct cpufreq_governor *gov = &cpufreq_gov_performance;
-#else
-       struct cpufreq_governor *gov = NULL;
-#endif
+static int cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
+{
+       int ret;
 
        /* Don't start any governor operations if we are entering suspend */
        if (cpufreq_suspended)
@@ -1948,12 +1894,14 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
        if (policy->governor->max_transition_latency &&
            policy->cpuinfo.transition_latency >
            policy->governor->max_transition_latency) {
-               if (!gov)
-                       return -EINVAL;
-               else {
+               struct cpufreq_governor *gov = cpufreq_fallback_governor();
+
+               if (gov) {
                        pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n",
                                policy->governor->name, gov->name);
                        policy->governor = gov;
+               } else {
+                       return -EINVAL;
                }
        }
 
@@ -1963,21 +1911,6 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
 
        pr_debug("%s: for CPU %u, event %u\n", __func__, policy->cpu, event);
 
-       mutex_lock(&cpufreq_governor_lock);
-       if ((policy->governor_enabled && event == CPUFREQ_GOV_START)
-           || (!policy->governor_enabled
-           && (event == CPUFREQ_GOV_LIMITS || event == CPUFREQ_GOV_STOP))) {
-               mutex_unlock(&cpufreq_governor_lock);
-               return -EBUSY;
-       }
-
-       if (event == CPUFREQ_GOV_STOP)
-               policy->governor_enabled = false;
-       else if (event == CPUFREQ_GOV_START)
-               policy->governor_enabled = true;
-
-       mutex_unlock(&cpufreq_governor_lock);
-
        ret = policy->governor->governor(policy, event);
 
        if (!ret) {
@@ -1985,14 +1918,6 @@ static int __cpufreq_governor(struct cpufreq_policy *policy,
                        policy->governor->initialized++;
                else if (event == CPUFREQ_GOV_POLICY_EXIT)
                        policy->governor->initialized--;
-       } else {
-               /* Restore original values */
-               mutex_lock(&cpufreq_governor_lock);
-               if (event == CPUFREQ_GOV_STOP)
-                       policy->governor_enabled = true;
-               else if (event == CPUFREQ_GOV_START)
-                       policy->governor_enabled = false;
-               mutex_unlock(&cpufreq_governor_lock);
        }
 
        if (((event == CPUFREQ_GOV_POLICY_INIT) && ret) ||
@@ -2147,7 +2072,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
        old_gov = policy->governor;
        /* end old governor */
        if (old_gov) {
-               ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+               ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
                if (ret) {
                        /* This can happen due to race with other operations */
                        pr_debug("%s: Failed to Stop Governor: %s (%d)\n",
@@ -2155,10 +2080,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
                        return ret;
                }
 
-               up_write(&policy->rwsem);
-               ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
-               down_write(&policy->rwsem);
-
+               ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
                if (ret) {
                        pr_err("%s: Failed to Exit Governor: %s (%d)\n",
                               __func__, old_gov->name, ret);
@@ -2168,32 +2090,30 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
 
        /* start new governor */
        policy->governor = new_policy->governor;
-       ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
+       ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT);
        if (!ret) {
-               ret = __cpufreq_governor(policy, CPUFREQ_GOV_START);
+               ret = cpufreq_governor(policy, CPUFREQ_GOV_START);
                if (!ret)
                        goto out;
 
-               up_write(&policy->rwsem);
-               __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
-               down_write(&policy->rwsem);
+               cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
        }
 
        /* new governor failed, so re-start old one */
        pr_debug("starting governor %s failed\n", policy->governor->name);
        if (old_gov) {
                policy->governor = old_gov;
-               if (__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
+               if (cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT))
                        policy->governor = NULL;
                else
-                       __cpufreq_governor(policy, CPUFREQ_GOV_START);
+                       cpufreq_governor(policy, CPUFREQ_GOV_START);
        }
 
        return ret;
 
  out:
        pr_debug("governor: change or update limits\n");
-       return __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+       return cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
 }
 
 /**
@@ -2260,11 +2180,7 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
                break;
 
        case CPU_DOWN_PREPARE:
-               cpufreq_offline_prepare(cpu);
-               break;
-
-       case CPU_POST_DEAD:
-               cpufreq_offline_finish(cpu);
+               cpufreq_offline(cpu);
                break;
 
        case CPU_DOWN_FAILED:
@@ -2297,8 +2213,11 @@ static int cpufreq_boost_set_sw(int state)
                                       __func__);
                                break;
                        }
+
+                       down_write(&policy->rwsem);
                        policy->user_policy.max = policy->max;
-                       __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+                       cpufreq_governor(policy, CPUFREQ_GOV_LIMITS);
+                       up_write(&policy->rwsem);
                }
        }
 
@@ -2384,7 +2303,7 @@ EXPORT_SYMBOL_GPL(cpufreq_boost_enabled);
  * submitted by the CPU Frequency driver.
  *
  * Registers a CPU Frequency driver to this core code. This code
- * returns zero on success, -EBUSY when another driver got here first
+ * returns zero on success, -EEXIST when another driver got here first
  * (and isn't unregistered in the meantime).
  *
  */
index 606ad74abe6e8b248b15a142c4f3fca7241c64be..bf4913f6453b1b26f0b71485ba59896bd4f62fe0 100644 (file)
 #include <linux/slab.h>
 #include "cpufreq_governor.h"
 
+struct cs_policy_dbs_info {
+       struct policy_dbs_info policy_dbs;
+       unsigned int down_skip;
+       unsigned int requested_freq;
+};
+
+static inline struct cs_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
+{
+       return container_of(policy_dbs, struct cs_policy_dbs_info, policy_dbs);
+}
+
+struct cs_dbs_tuners {
+       unsigned int down_threshold;
+       unsigned int freq_step;
+};
+
 /* Conservative governor macros */
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
 #define DEF_FREQUENCY_DOWN_THRESHOLD           (20)
 #define DEF_SAMPLING_DOWN_FACTOR               (1)
 #define MAX_SAMPLING_DOWN_FACTOR               (10)
 
-static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);
-
-static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
-                                  unsigned int event);
-
-#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
-static
-#endif
-struct cpufreq_governor cpufreq_gov_conservative = {
-       .name                   = "conservative",
-       .governor               = cs_cpufreq_governor_dbs,
-       .max_transition_latency = TRANSITION_LATENCY_LIMIT,
-       .owner                  = THIS_MODULE,
-};
-
 static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
                                           struct cpufreq_policy *policy)
 {
@@ -57,27 +58,28 @@ static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
  * Any frequency increase takes it to the maximum frequency. Frequency reduction
  * happens at minimum steps of 5% (default) of maximum frequency
  */
-static void cs_check_cpu(int cpu, unsigned int load)
+static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
 {
-       struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
-       struct cpufreq_policy *policy = dbs_info->cdbs.shared->policy;
-       struct dbs_data *dbs_data = policy->governor_data;
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
+       struct dbs_data *dbs_data = policy_dbs->dbs_data;
        struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+       unsigned int load = dbs_update(policy);
 
        /*
         * break out if we 'cannot' reduce the speed as the user might
         * want freq_step to be zero
         */
        if (cs_tuners->freq_step == 0)
-               return;
+               goto out;
 
        /* Check for frequency increase */
-       if (load > cs_tuners->up_threshold) {
+       if (load > dbs_data->up_threshold) {
                dbs_info->down_skip = 0;
 
                /* if we are already at full speed then break out early */
                if (dbs_info->requested_freq == policy->max)
-                       return;
+                       goto out;
 
                dbs_info->requested_freq += get_freq_target(cs_tuners, policy);
 
@@ -86,12 +88,12 @@ static void cs_check_cpu(int cpu, unsigned int load)
 
                __cpufreq_driver_target(policy, dbs_info->requested_freq,
                        CPUFREQ_RELATION_H);
-               return;
+               goto out;
        }
 
        /* if sampling_down_factor is active break out early */
-       if (++dbs_info->down_skip < cs_tuners->sampling_down_factor)
-               return;
+       if (++dbs_info->down_skip < dbs_data->sampling_down_factor)
+               goto out;
        dbs_info->down_skip = 0;
 
        /* Check for frequency decrease */
@@ -101,7 +103,7 @@ static void cs_check_cpu(int cpu, unsigned int load)
                 * if we cannot reduce the frequency anymore, break out early
                 */
                if (policy->cur == policy->min)
-                       return;
+                       goto out;
 
                freq_target = get_freq_target(cs_tuners, policy);
                if (dbs_info->requested_freq > freq_target)
@@ -111,58 +113,25 @@ static void cs_check_cpu(int cpu, unsigned int load)
 
                __cpufreq_driver_target(policy, dbs_info->requested_freq,
                                CPUFREQ_RELATION_L);
-               return;
        }
-}
-
-static unsigned int cs_dbs_timer(struct cpufreq_policy *policy, bool modify_all)
-{
-       struct dbs_data *dbs_data = policy->governor_data;
-       struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
-
-       if (modify_all)
-               dbs_check_cpu(dbs_data, policy->cpu);
 
-       return delay_for_sampling_rate(cs_tuners->sampling_rate);
+ out:
+       return dbs_data->sampling_rate;
 }
 
 static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-               void *data)
-{
-       struct cpufreq_freqs *freq = data;
-       struct cs_cpu_dbs_info_s *dbs_info =
-                                       &per_cpu(cs_cpu_dbs_info, freq->cpu);
-       struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);
-
-       if (!policy)
-               return 0;
-
-       /* policy isn't governed by conservative governor */
-       if (policy->governor != &cpufreq_gov_conservative)
-               return 0;
-
-       /*
-        * we only care if our internally tracked freq moves outside the 'valid'
-        * ranges of frequency available to us otherwise we do not change it
-       */
-       if (dbs_info->requested_freq > policy->max
-                       || dbs_info->requested_freq < policy->min)
-               dbs_info->requested_freq = freq->new;
-
-       return 0;
-}
+                               void *data);
 
 static struct notifier_block cs_cpufreq_notifier_block = {
        .notifier_call = dbs_cpufreq_notifier,
 };
 
 /************************** sysfs interface ************************/
-static struct common_dbs_data cs_dbs_cdata;
+static struct dbs_governor cs_dbs_gov;
 
 static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
                const char *buf, size_t count)
 {
-       struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
        unsigned int input;
        int ret;
        ret = sscanf(buf, "%u", &input);
@@ -170,22 +139,7 @@ static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
        if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
                return -EINVAL;
 
-       cs_tuners->sampling_down_factor = input;
-       return count;
-}
-
-static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
-               size_t count)
-{
-       struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
-       unsigned int input;
-       int ret;
-       ret = sscanf(buf, "%u", &input);
-
-       if (ret != 1)
-               return -EINVAL;
-
-       cs_tuners->sampling_rate = max(input, dbs_data->min_sampling_rate);
+       dbs_data->sampling_down_factor = input;
        return count;
 }
 
@@ -200,7 +154,7 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
        if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold)
                return -EINVAL;
 
-       cs_tuners->up_threshold = input;
+       dbs_data->up_threshold = input;
        return count;
 }
 
@@ -214,7 +168,7 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
 
        /* cannot be lower than 11 otherwise freq will not fall */
        if (ret != 1 || input < 11 || input > 100 ||
-                       input >= cs_tuners->up_threshold)
+                       input >= dbs_data->up_threshold)
                return -EINVAL;
 
        cs_tuners->down_threshold = input;
@@ -224,8 +178,7 @@ static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
 static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
                const char *buf, size_t count)
 {
-       struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
-       unsigned int input, j;
+       unsigned int input;
        int ret;
 
        ret = sscanf(buf, "%u", &input);
@@ -235,21 +188,14 @@ static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
        if (input > 1)
                input = 1;
 
-       if (input == cs_tuners->ignore_nice_load) /* nothing to do */
+       if (input == dbs_data->ignore_nice_load) /* nothing to do */
                return count;
 
-       cs_tuners->ignore_nice_load = input;
+       dbs_data->ignore_nice_load = input;
 
        /* we need to re-evaluate prev_cpu_idle */
-       for_each_online_cpu(j) {
-               struct cs_cpu_dbs_info_s *dbs_info;
-               dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-               dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
-                                       &dbs_info->cdbs.prev_cpu_wall, 0);
-               if (cs_tuners->ignore_nice_load)
-                       dbs_info->cdbs.prev_cpu_nice =
-                               kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-       }
+       gov_update_cpu_data(dbs_data);
+
        return count;
 }
 
@@ -275,55 +221,47 @@ static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf,
        return count;
 }
 
-show_store_one(cs, sampling_rate);
-show_store_one(cs, sampling_down_factor);
-show_store_one(cs, up_threshold);
-show_store_one(cs, down_threshold);
-show_store_one(cs, ignore_nice_load);
-show_store_one(cs, freq_step);
-declare_show_sampling_rate_min(cs);
-
-gov_sys_pol_attr_rw(sampling_rate);
-gov_sys_pol_attr_rw(sampling_down_factor);
-gov_sys_pol_attr_rw(up_threshold);
-gov_sys_pol_attr_rw(down_threshold);
-gov_sys_pol_attr_rw(ignore_nice_load);
-gov_sys_pol_attr_rw(freq_step);
-gov_sys_pol_attr_ro(sampling_rate_min);
-
-static struct attribute *dbs_attributes_gov_sys[] = {
-       &sampling_rate_min_gov_sys.attr,
-       &sampling_rate_gov_sys.attr,
-       &sampling_down_factor_gov_sys.attr,
-       &up_threshold_gov_sys.attr,
-       &down_threshold_gov_sys.attr,
-       &ignore_nice_load_gov_sys.attr,
-       &freq_step_gov_sys.attr,
+gov_show_one_common(sampling_rate);
+gov_show_one_common(sampling_down_factor);
+gov_show_one_common(up_threshold);
+gov_show_one_common(ignore_nice_load);
+gov_show_one_common(min_sampling_rate);
+gov_show_one(cs, down_threshold);
+gov_show_one(cs, freq_step);
+
+gov_attr_rw(sampling_rate);
+gov_attr_rw(sampling_down_factor);
+gov_attr_rw(up_threshold);
+gov_attr_rw(ignore_nice_load);
+gov_attr_ro(min_sampling_rate);
+gov_attr_rw(down_threshold);
+gov_attr_rw(freq_step);
+
+static struct attribute *cs_attributes[] = {
+       &min_sampling_rate.attr,
+       &sampling_rate.attr,
+       &sampling_down_factor.attr,
+       &up_threshold.attr,
+       &down_threshold.attr,
+       &ignore_nice_load.attr,
+       &freq_step.attr,
        NULL
 };
 
-static struct attribute_group cs_attr_group_gov_sys = {
-       .attrs = dbs_attributes_gov_sys,
-       .name = "conservative",
-};
+/************************** sysfs end ************************/
 
-static struct attribute *dbs_attributes_gov_pol[] = {
-       &sampling_rate_min_gov_pol.attr,
-       &sampling_rate_gov_pol.attr,
-       &sampling_down_factor_gov_pol.attr,
-       &up_threshold_gov_pol.attr,
-       &down_threshold_gov_pol.attr,
-       &ignore_nice_load_gov_pol.attr,
-       &freq_step_gov_pol.attr,
-       NULL
-};
+static struct policy_dbs_info *cs_alloc(void)
+{
+       struct cs_policy_dbs_info *dbs_info;
 
-static struct attribute_group cs_attr_group_gov_pol = {
-       .attrs = dbs_attributes_gov_pol,
-       .name = "conservative",
-};
+       dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL);
+       return dbs_info ? &dbs_info->policy_dbs : NULL;
+}
 
-/************************** sysfs end ************************/
+static void cs_free(struct policy_dbs_info *policy_dbs)
+{
+       kfree(to_dbs_info(policy_dbs));
+}
 
 static int cs_init(struct dbs_data *dbs_data, bool notify)
 {
@@ -335,11 +273,11 @@ static int cs_init(struct dbs_data *dbs_data, bool notify)
                return -ENOMEM;
        }
 
-       tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
        tuners->down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD;
-       tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
-       tuners->ignore_nice_load = 0;
        tuners->freq_step = DEF_FREQUENCY_STEP;
+       dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
+       dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
+       dbs_data->ignore_nice_load = 0;
 
        dbs_data->tuners = tuners;
        dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
@@ -361,35 +299,66 @@ static void cs_exit(struct dbs_data *dbs_data, bool notify)
        kfree(dbs_data->tuners);
 }
 
-define_get_cpu_dbs_routines(cs_cpu_dbs_info);
+static void cs_start(struct cpufreq_policy *policy)
+{
+       struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
+
+       dbs_info->down_skip = 0;
+       dbs_info->requested_freq = policy->cur;
+}
 
-static struct common_dbs_data cs_dbs_cdata = {
-       .governor = GOV_CONSERVATIVE,
-       .attr_group_gov_sys = &cs_attr_group_gov_sys,
-       .attr_group_gov_pol = &cs_attr_group_gov_pol,
-       .get_cpu_cdbs = get_cpu_cdbs,
-       .get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+static struct dbs_governor cs_dbs_gov = {
+       .gov = {
+               .name = "conservative",
+               .governor = cpufreq_governor_dbs,
+               .max_transition_latency = TRANSITION_LATENCY_LIMIT,
+               .owner = THIS_MODULE,
+       },
+       .kobj_type = { .default_attrs = cs_attributes },
        .gov_dbs_timer = cs_dbs_timer,
-       .gov_check_cpu = cs_check_cpu,
+       .alloc = cs_alloc,
+       .free = cs_free,
        .init = cs_init,
        .exit = cs_exit,
-       .mutex = __MUTEX_INITIALIZER(cs_dbs_cdata.mutex),
+       .start = cs_start,
 };
 
-static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
-                                  unsigned int event)
+#define CPU_FREQ_GOV_CONSERVATIVE      (&cs_dbs_gov.gov)
+
+static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+                               void *data)
 {
-       return cpufreq_governor_dbs(policy, &cs_dbs_cdata, event);
+       struct cpufreq_freqs *freq = data;
+       struct cpufreq_policy *policy = cpufreq_cpu_get_raw(freq->cpu);
+       struct cs_policy_dbs_info *dbs_info;
+
+       if (!policy)
+               return 0;
+
+       /* policy isn't governed by conservative governor */
+       if (policy->governor != CPU_FREQ_GOV_CONSERVATIVE)
+               return 0;
+
+       dbs_info = to_dbs_info(policy->governor_data);
+       /*
+        * we only care if our internally tracked freq moves outside the 'valid'
+        * ranges of frequency available to us otherwise we do not change it
+       */
+       if (dbs_info->requested_freq > policy->max
+                       || dbs_info->requested_freq < policy->min)
+               dbs_info->requested_freq = freq->new;
+
+       return 0;
 }
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-       return cpufreq_register_governor(&cpufreq_gov_conservative);
+       return cpufreq_register_governor(CPU_FREQ_GOV_CONSERVATIVE);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
-       cpufreq_unregister_governor(&cpufreq_gov_conservative);
+       cpufreq_unregister_governor(CPU_FREQ_GOV_CONSERVATIVE);
 }
 
 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
@@ -399,6 +368,11 @@ MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
+struct cpufreq_governor *cpufreq_default_governor(void)
+{
+       return CPU_FREQ_GOV_CONSERVATIVE;
+}
+
 fs_initcall(cpufreq_gov_dbs_init);
 #else
 module_init(cpufreq_gov_dbs_init);
index e0d111024d4840e8078fc0553c9ef7dabed71447..1c25ef4056164b2cb7ddc587441637a1973612c1 100644 (file)
 
 #include <linux/export.h>
 #include <linux/kernel_stat.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 
 #include "cpufreq_governor.h"
 
-static struct attribute_group *get_sysfs_attr(struct dbs_data *dbs_data)
-{
-       if (have_governor_per_policy())
-               return dbs_data->cdata->attr_group_gov_pol;
-       else
-               return dbs_data->cdata->attr_group_gov_sys;
-}
+static DEFINE_PER_CPU(struct cpu_dbs_info, cpu_dbs);
+
+static DEFINE_MUTEX(gov_dbs_data_mutex);
 
-void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
+/* Common sysfs tunables */
+/**
+ * store_sampling_rate - update sampling rate effective immediately if needed.
+ *
+ * If new rate is smaller than the old, simply updating
+ * dbs.sampling_rate might not be appropriate. For example, if the
+ * original sampling_rate was 1 second and the requested new sampling rate is 10
+ * ms because the user needs immediate reaction from ondemand governor, but not
+ * sure if higher frequency will be required or not, then, the governor may
+ * change the sampling rate too late; up to 1 second later. Thus, if we are
+ * reducing the sampling rate, we need to make the new value effective
+ * immediately.
+ *
+ * This must be called with dbs_data->mutex held, otherwise traversing
+ * policy_dbs_list isn't safe.
+ */
+ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
+                           size_t count)
 {
-       struct cpu_dbs_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
-       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
-       struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
-       struct cpufreq_policy *policy = cdbs->shared->policy;
-       unsigned int sampling_rate;
-       unsigned int max_load = 0;
-       unsigned int ignore_nice;
-       unsigned int j;
+       struct policy_dbs_info *policy_dbs;
+       unsigned int rate;
+       int ret;
+       ret = sscanf(buf, "%u", &rate);
+       if (ret != 1)
+               return -EINVAL;
 
-       if (dbs_data->cdata->governor == GOV_ONDEMAND) {
-               struct od_cpu_dbs_info_s *od_dbs_info =
-                               dbs_data->cdata->get_cpu_dbs_info_s(cpu);
+       dbs_data->sampling_rate = max(rate, dbs_data->min_sampling_rate);
 
+       /*
+        * We are operating under dbs_data->mutex and so the list and its
+        * entries can't be freed concurrently.
+        */
+       list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
+               mutex_lock(&policy_dbs->timer_mutex);
                /*
-                * Sometimes, the ondemand governor uses an additional
-                * multiplier to give long delays. So apply this multiplier to
-                * the 'sampling_rate', so as to keep the wake-up-from-idle
-                * detection logic a bit conservative.
+                * On 32-bit architectures this may race with the
+                * sample_delay_ns read in dbs_update_util_handler(), but that
+                * really doesn't matter.  If the read returns a value that's
+                * too big, the sample will be skipped, but the next invocation
+                * of dbs_update_util_handler() (when the update has been
+                * completed) will take a sample.
+                *
+                * If this runs in parallel with dbs_work_handler(), we may end
+                * up overwriting the sample_delay_ns value that it has just
+                * written, but it will be corrected next time a sample is
+                * taken, so it shouldn't be significant.
                 */
-               sampling_rate = od_tuners->sampling_rate;
-               sampling_rate *= od_dbs_info->rate_mult;
+               gov_update_sample_delay(policy_dbs, 0);
+               mutex_unlock(&policy_dbs->timer_mutex);
+       }
 
-               ignore_nice = od_tuners->ignore_nice_load;
-       } else {
-               sampling_rate = cs_tuners->sampling_rate;
-               ignore_nice = cs_tuners->ignore_nice_load;
+       return count;
+}
+EXPORT_SYMBOL_GPL(store_sampling_rate);
+
+/**
+ * gov_update_cpu_data - Update CPU load data.
+ * @dbs_data: Top-level governor data pointer.
+ *
+ * Update CPU load data for all CPUs in the domain governed by @dbs_data
+ * (that may be a single policy or a bunch of them if governor tunables are
+ * system-wide).
+ *
+ * Call under the @dbs_data mutex.
+ */
+void gov_update_cpu_data(struct dbs_data *dbs_data)
+{
+       struct policy_dbs_info *policy_dbs;
+
+       list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
+               unsigned int j;
+
+               for_each_cpu(j, policy_dbs->policy->cpus) {
+                       struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
+
+                       j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_cpu_wall,
+                                                                 dbs_data->io_is_busy);
+                       if (dbs_data->ignore_nice_load)
+                               j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+               }
        }
+}
+EXPORT_SYMBOL_GPL(gov_update_cpu_data);
+
+static inline struct dbs_data *to_dbs_data(struct kobject *kobj)
+{
+       return container_of(kobj, struct dbs_data, kobj);
+}
+
+static inline struct governor_attr *to_gov_attr(struct attribute *attr)
+{
+       return container_of(attr, struct governor_attr, attr);
+}
+
+static ssize_t governor_show(struct kobject *kobj, struct attribute *attr,
+                            char *buf)
+{
+       struct dbs_data *dbs_data = to_dbs_data(kobj);
+       struct governor_attr *gattr = to_gov_attr(attr);
+
+       return gattr->show(dbs_data, buf);
+}
+
+static ssize_t governor_store(struct kobject *kobj, struct attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct dbs_data *dbs_data = to_dbs_data(kobj);
+       struct governor_attr *gattr = to_gov_attr(attr);
+       int ret = -EBUSY;
+
+       mutex_lock(&dbs_data->mutex);
+
+       if (dbs_data->usage_count)
+               ret = gattr->store(dbs_data, buf, count);
+
+       mutex_unlock(&dbs_data->mutex);
+
+       return ret;
+}
+
+/*
+ * Sysfs Ops for accessing governor attributes.
+ *
+ * All show/store invocations for governor specific sysfs attributes, will first
+ * call the below show/store callbacks and the attribute specific callback will
+ * be called from within it.
+ */
+static const struct sysfs_ops governor_sysfs_ops = {
+       .show   = governor_show,
+       .store  = governor_store,
+};
+
+unsigned int dbs_update(struct cpufreq_policy *policy)
+{
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct dbs_data *dbs_data = policy_dbs->dbs_data;
+       unsigned int ignore_nice = dbs_data->ignore_nice_load;
+       unsigned int max_load = 0;
+       unsigned int sampling_rate, io_busy, j;
+
+       /*
+        * Sometimes governors may use an additional multiplier to increase
+        * sample delays temporarily.  Apply that multiplier to sampling_rate
+        * so as to keep the wake-up-from-idle detection logic a bit
+        * conservative.
+        */
+       sampling_rate = dbs_data->sampling_rate * policy_dbs->rate_mult;
+       /*
+        * For the purpose of ondemand, waiting for disk IO is an indication
+        * that you're performance critical, and not that the system is actually
+        * idle, so do not add the iowait time to the CPU idle time then.
+        */
+       io_busy = dbs_data->io_is_busy;
 
        /* Get Absolute Load */
        for_each_cpu(j, policy->cpus) {
-               struct cpu_dbs_info *j_cdbs;
+               struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
                u64 cur_wall_time, cur_idle_time;
                unsigned int idle_time, wall_time;
                unsigned int load;
-               int io_busy = 0;
-
-               j_cdbs = dbs_data->cdata->get_cpu_cdbs(j);
 
-               /*
-                * For the purpose of ondemand, waiting for disk IO is
-                * an indication that you're performance critical, and
-                * not that the system is actually idle. So do not add
-                * the iowait time to the cpu idle time.
-                */
-               if (dbs_data->cdata->governor == GOV_ONDEMAND)
-                       io_busy = od_tuners->io_is_busy;
                cur_idle_time = get_cpu_idle_time(j, &cur_wall_time, io_busy);
 
-               wall_time = (unsigned int)
-                       (cur_wall_time - j_cdbs->prev_cpu_wall);
+               wall_time = cur_wall_time - j_cdbs->prev_cpu_wall;
                j_cdbs->prev_cpu_wall = cur_wall_time;
 
-               if (cur_idle_time < j_cdbs->prev_cpu_idle)
-                       cur_idle_time = j_cdbs->prev_cpu_idle;
-
-               idle_time = (unsigned int)
-                       (cur_idle_time - j_cdbs->prev_cpu_idle);
-               j_cdbs->prev_cpu_idle = cur_idle_time;
+               if (cur_idle_time <= j_cdbs->prev_cpu_idle) {
+                       idle_time = 0;
+               } else {
+                       idle_time = cur_idle_time - j_cdbs->prev_cpu_idle;
+                       j_cdbs->prev_cpu_idle = cur_idle_time;
+               }
 
                if (ignore_nice) {
-                       u64 cur_nice;
-                       unsigned long cur_nice_jiffies;
-
-                       cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
-                                        cdbs->prev_cpu_nice;
-                       /*
-                        * Assumption: nice time between sampling periods will
-                        * be less than 2^32 jiffies for 32 bit sys
-                        */
-                       cur_nice_jiffies = (unsigned long)
-                                       cputime64_to_jiffies64(cur_nice);
+                       u64 cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
-                       cdbs->prev_cpu_nice =
-                               kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-                       idle_time += jiffies_to_usecs(cur_nice_jiffies);
+                       idle_time += cputime_to_usecs(cur_nice - j_cdbs->prev_cpu_nice);
+                       j_cdbs->prev_cpu_nice = cur_nice;
                }
 
                if (unlikely(!wall_time || wall_time < idle_time))
@@ -128,10 +226,10 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
                 * dropped down. So we perform the copy only once, upon the
                 * first wake-up from idle.)
                 *
-                * Detecting this situation is easy: the governor's deferrable
-                * timer would not have fired during CPU-idle periods. Hence
-                * an unusually large 'wall_time' (as compared to the sampling
-                * rate) indicates this scenario.
+                * Detecting this situation is easy: the governor's utilization
+                * update handler would not have run during CPU-idle periods.
+                * Hence, an unusually large 'wall_time' (as compared to the
+                * sampling rate) indicates this scenario.
                 *
                 * prev_load can be zero in two cases and we must recalculate it
                 * for both cases:
@@ -156,222 +254,224 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
                if (load > max_load)
                        max_load = load;
        }
-
-       dbs_data->cdata->gov_check_cpu(cpu, max_load);
+       return max_load;
 }
-EXPORT_SYMBOL_GPL(dbs_check_cpu);
+EXPORT_SYMBOL_GPL(dbs_update);
 
-void gov_add_timers(struct cpufreq_policy *policy, unsigned int delay)
+static void gov_set_update_util(struct policy_dbs_info *policy_dbs,
+                               unsigned int delay_us)
 {
-       struct dbs_data *dbs_data = policy->governor_data;
-       struct cpu_dbs_info *cdbs;
+       struct cpufreq_policy *policy = policy_dbs->policy;
        int cpu;
 
+       gov_update_sample_delay(policy_dbs, delay_us);
+       policy_dbs->last_sample_time = 0;
+
        for_each_cpu(cpu, policy->cpus) {
-               cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
-               cdbs->timer.expires = jiffies + delay;
-               add_timer_on(&cdbs->timer, cpu);
+               struct cpu_dbs_info *cdbs = &per_cpu(cpu_dbs, cpu);
+
+               cpufreq_set_update_util_data(cpu, &cdbs->update_util);
        }
 }
-EXPORT_SYMBOL_GPL(gov_add_timers);
 
-static inline void gov_cancel_timers(struct cpufreq_policy *policy)
+static inline void gov_clear_update_util(struct cpufreq_policy *policy)
 {
-       struct dbs_data *dbs_data = policy->governor_data;
-       struct cpu_dbs_info *cdbs;
        int i;
 
-       for_each_cpu(i, policy->cpus) {
-               cdbs = dbs_data->cdata->get_cpu_cdbs(i);
-               del_timer_sync(&cdbs->timer);
-       }
-}
+       for_each_cpu(i, policy->cpus)
+               cpufreq_set_update_util_data(i, NULL);
 
-void gov_cancel_work(struct cpu_common_dbs_info *shared)
-{
-       /* Tell dbs_timer_handler() to skip queuing up work items. */
-       atomic_inc(&shared->skip_work);
-       /*
-        * If dbs_timer_handler() is already running, it may not notice the
-        * incremented skip_work, so wait for it to complete to prevent its work
-        * item from being queued up after the cancel_work_sync() below.
-        */
-       gov_cancel_timers(shared->policy);
-       /*
-        * In case dbs_timer_handler() managed to run and spawn a work item
-        * before the timers have been canceled, wait for that work item to
-        * complete and then cancel all of the timers set up by it.  If
-        * dbs_timer_handler() runs again at that point, it will see the
-        * positive value of skip_work and won't spawn any more work items.
-        */
-       cancel_work_sync(&shared->work);
-       gov_cancel_timers(shared->policy);
-       atomic_set(&shared->skip_work, 0);
+       synchronize_sched();
 }
-EXPORT_SYMBOL_GPL(gov_cancel_work);
 
-/* Will return if we need to evaluate cpu load again or not */
-static bool need_load_eval(struct cpu_common_dbs_info *shared,
-                          unsigned int sampling_rate)
+static void gov_cancel_work(struct cpufreq_policy *policy)
 {
-       if (policy_is_shared(shared->policy)) {
-               ktime_t time_now = ktime_get();
-               s64 delta_us = ktime_us_delta(time_now, shared->time_stamp);
-
-               /* Do nothing if we recently have sampled */
-               if (delta_us < (s64)(sampling_rate / 2))
-                       return false;
-               else
-                       shared->time_stamp = time_now;
-       }
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
 
-       return true;
+       gov_clear_update_util(policy_dbs->policy);
+       irq_work_sync(&policy_dbs->irq_work);
+       cancel_work_sync(&policy_dbs->work);
+       atomic_set(&policy_dbs->work_count, 0);
+       policy_dbs->work_in_progress = false;
 }
 
 static void dbs_work_handler(struct work_struct *work)
 {
-       struct cpu_common_dbs_info *shared = container_of(work, struct
-                                       cpu_common_dbs_info, work);
+       struct policy_dbs_info *policy_dbs;
        struct cpufreq_policy *policy;
-       struct dbs_data *dbs_data;
-       unsigned int sampling_rate, delay;
-       bool eval_load;
-
-       policy = shared->policy;
-       dbs_data = policy->governor_data;
+       struct dbs_governor *gov;
 
-       /* Kill all timers */
-       gov_cancel_timers(policy);
+       policy_dbs = container_of(work, struct policy_dbs_info, work);
+       policy = policy_dbs->policy;
+       gov = dbs_governor_of(policy);
 
-       if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
-               struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
-
-               sampling_rate = cs_tuners->sampling_rate;
-       } else {
-               struct od_dbs_tuners *od_tuners = dbs_data->tuners;
-
-               sampling_rate = od_tuners->sampling_rate;
-       }
-
-       eval_load = need_load_eval(shared, sampling_rate);
+       /*
+        * Make sure cpufreq_governor_limits() isn't evaluating load or the
+        * ondemand governor isn't updating the sampling rate in parallel.
+        */
+       mutex_lock(&policy_dbs->timer_mutex);
+       gov_update_sample_delay(policy_dbs, gov->gov_dbs_timer(policy));
+       mutex_unlock(&policy_dbs->timer_mutex);
 
+       /* Allow the utilization update handler to queue up more work. */
+       atomic_set(&policy_dbs->work_count, 0);
        /*
-        * Make sure cpufreq_governor_limits() isn't evaluating load in
-        * parallel.
+        * If the update below is reordered with respect to the sample delay
+        * modification, the utilization update handler may end up using a stale
+        * sample delay value.
         */
-       mutex_lock(&shared->timer_mutex);
-       delay = dbs_data->cdata->gov_dbs_timer(policy, eval_load);
-       mutex_unlock(&shared->timer_mutex);
+       smp_wmb();
+       policy_dbs->work_in_progress = false;
+}
 
-       atomic_dec(&shared->skip_work);
+static void dbs_irq_work(struct irq_work *irq_work)
+{
+       struct policy_dbs_info *policy_dbs;
 
-       gov_add_timers(policy, delay);
+       policy_dbs = container_of(irq_work, struct policy_dbs_info, irq_work);
+       schedule_work(&policy_dbs->work);
 }
 
-static void dbs_timer_handler(unsigned long data)
+static void dbs_update_util_handler(struct update_util_data *data, u64 time,
+                                   unsigned long util, unsigned long max)
 {
-       struct cpu_dbs_info *cdbs = (struct cpu_dbs_info *)data;
-       struct cpu_common_dbs_info *shared = cdbs->shared;
+       struct cpu_dbs_info *cdbs = container_of(data, struct cpu_dbs_info, update_util);
+       struct policy_dbs_info *policy_dbs = cdbs->policy_dbs;
+       u64 delta_ns, lst;
 
        /*
-        * Timer handler may not be allowed to queue the work at the moment,
-        * because:
-        * - Another timer handler has done that
-        * - We are stopping the governor
-        * - Or we are updating the sampling rate of the ondemand governor
+        * The work may not be allowed to be queued up right now.
+        * Possible reasons:
+        * - Work has already been queued up or is in progress.
+        * - It is too early (too little time from the previous sample).
         */
-       if (atomic_inc_return(&shared->skip_work) > 1)
-               atomic_dec(&shared->skip_work);
-       else
-               queue_work(system_wq, &shared->work);
-}
+       if (policy_dbs->work_in_progress)
+               return;
 
-static void set_sampling_rate(struct dbs_data *dbs_data,
-               unsigned int sampling_rate)
-{
-       if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
-               struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
-               cs_tuners->sampling_rate = sampling_rate;
-       } else {
-               struct od_dbs_tuners *od_tuners = dbs_data->tuners;
-               od_tuners->sampling_rate = sampling_rate;
+       /*
+        * If the reads below are reordered before the check above, the value
+        * of sample_delay_ns used in the computation may be stale.
+        */
+       smp_rmb();
+       lst = READ_ONCE(policy_dbs->last_sample_time);
+       delta_ns = time - lst;
+       if ((s64)delta_ns < policy_dbs->sample_delay_ns)
+               return;
+
+       /*
+        * If the policy is not shared, the irq_work may be queued up right away
+        * at this point.  Otherwise, we need to ensure that only one of the
+        * CPUs sharing the policy will do that.
+        */
+       if (policy_dbs->is_shared) {
+               if (!atomic_add_unless(&policy_dbs->work_count, 1, 1))
+                       return;
+
+               /*
+                * If another CPU updated last_sample_time in the meantime, we
+                * shouldn't be here, so clear the work counter and bail out.
+                */
+               if (unlikely(lst != READ_ONCE(policy_dbs->last_sample_time))) {
+                       atomic_set(&policy_dbs->work_count, 0);
+                       return;
+               }
        }
+
+       policy_dbs->last_sample_time = time;
+       policy_dbs->work_in_progress = true;
+       irq_work_queue(&policy_dbs->irq_work);
 }
 
-static int alloc_common_dbs_info(struct cpufreq_policy *policy,
-                                struct common_dbs_data *cdata)
+static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy,
+                                                    struct dbs_governor *gov)
 {
-       struct cpu_common_dbs_info *shared;
+       struct policy_dbs_info *policy_dbs;
        int j;
 
-       /* Allocate memory for the common information for policy->cpus */
-       shared = kzalloc(sizeof(*shared), GFP_KERNEL);
-       if (!shared)
-               return -ENOMEM;
+       /* Allocate memory for per-policy governor data. */
+       policy_dbs = gov->alloc();
+       if (!policy_dbs)
+               return NULL;
 
-       /* Set shared for all CPUs, online+offline */
-       for_each_cpu(j, policy->related_cpus)
-               cdata->get_cpu_cdbs(j)->shared = shared;
+       policy_dbs->policy = policy;
+       mutex_init(&policy_dbs->timer_mutex);
+       atomic_set(&policy_dbs->work_count, 0);
+       init_irq_work(&policy_dbs->irq_work, dbs_irq_work);
+       INIT_WORK(&policy_dbs->work, dbs_work_handler);
 
-       mutex_init(&shared->timer_mutex);
-       atomic_set(&shared->skip_work, 0);
-       INIT_WORK(&shared->work, dbs_work_handler);
-       return 0;
+       /* Set policy_dbs for all CPUs, online+offline */
+       for_each_cpu(j, policy->related_cpus) {
+               struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
+
+               j_cdbs->policy_dbs = policy_dbs;
+               j_cdbs->update_util.func = dbs_update_util_handler;
+       }
+       return policy_dbs;
 }
 
-static void free_common_dbs_info(struct cpufreq_policy *policy,
-                                struct common_dbs_data *cdata)
+static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
+                                struct dbs_governor *gov)
 {
-       struct cpu_dbs_info *cdbs = cdata->get_cpu_cdbs(policy->cpu);
-       struct cpu_common_dbs_info *shared = cdbs->shared;
        int j;
 
-       mutex_destroy(&shared->timer_mutex);
+       mutex_destroy(&policy_dbs->timer_mutex);
 
-       for_each_cpu(j, policy->cpus)
-               cdata->get_cpu_cdbs(j)->shared = NULL;
+       for_each_cpu(j, policy_dbs->policy->related_cpus) {
+               struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
 
-       kfree(shared);
+               j_cdbs->policy_dbs = NULL;
+               j_cdbs->update_util.func = NULL;
+       }
+       gov->free(policy_dbs);
 }
 
-static int cpufreq_governor_init(struct cpufreq_policy *policy,
-                                struct dbs_data *dbs_data,
-                                struct common_dbs_data *cdata)
+static int cpufreq_governor_init(struct cpufreq_policy *policy)
 {
+       struct dbs_governor *gov = dbs_governor_of(policy);
+       struct dbs_data *dbs_data;
+       struct policy_dbs_info *policy_dbs;
        unsigned int latency;
-       int ret;
+       int ret = 0;
 
        /* State should be equivalent to EXIT */
        if (policy->governor_data)
                return -EBUSY;
 
-       if (dbs_data) {
-               if (WARN_ON(have_governor_per_policy()))
-                       return -EINVAL;
+       policy_dbs = alloc_policy_dbs_info(policy, gov);
+       if (!policy_dbs)
+               return -ENOMEM;
 
-               ret = alloc_common_dbs_info(policy, cdata);
-               if (ret)
-                       return ret;
+       /* Protect gov->gdbs_data against concurrent updates. */
+       mutex_lock(&gov_dbs_data_mutex);
 
+       dbs_data = gov->gdbs_data;
+       if (dbs_data) {
+               if (WARN_ON(have_governor_per_policy())) {
+                       ret = -EINVAL;
+                       goto free_policy_dbs_info;
+               }
+               policy_dbs->dbs_data = dbs_data;
+               policy->governor_data = policy_dbs;
+
+               mutex_lock(&dbs_data->mutex);
                dbs_data->usage_count++;
-               policy->governor_data = dbs_data;
-               return 0;
+               list_add(&policy_dbs->list, &dbs_data->policy_dbs_list);
+               mutex_unlock(&dbs_data->mutex);
+               goto out;
        }
 
        dbs_data = kzalloc(sizeof(*dbs_data), GFP_KERNEL);
-       if (!dbs_data)
-               return -ENOMEM;
-
-       ret = alloc_common_dbs_info(policy, cdata);
-       if (ret)
-               goto free_dbs_data;
+       if (!dbs_data) {
+               ret = -ENOMEM;
+               goto free_policy_dbs_info;
+       }
 
-       dbs_data->cdata = cdata;
-       dbs_data->usage_count = 1;
+       INIT_LIST_HEAD(&dbs_data->policy_dbs_list);
+       mutex_init(&dbs_data->mutex);
 
-       ret = cdata->init(dbs_data, !policy->governor->initialized);
+       ret = gov->init(dbs_data, !policy->governor->initialized);
        if (ret)
-               goto free_common_dbs_info;
+               goto free_policy_dbs_info;
 
        /* policy latency is in ns. Convert it to us first */
        latency = policy->cpuinfo.transition_latency / 1000;
@@ -381,216 +481,156 @@ static int cpufreq_governor_init(struct cpufreq_policy *policy,
        /* Bring kernel and HW constraints together */
        dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
                                          MIN_LATENCY_MULTIPLIER * latency);
-       set_sampling_rate(dbs_data, max(dbs_data->min_sampling_rate,
-                                       latency * LATENCY_MULTIPLIER));
+       dbs_data->sampling_rate = max(dbs_data->min_sampling_rate,
+                                     LATENCY_MULTIPLIER * latency);
 
        if (!have_governor_per_policy())
-               cdata->gdbs_data = dbs_data;
+               gov->gdbs_data = dbs_data;
 
-       policy->governor_data = dbs_data;
+       policy->governor_data = policy_dbs;
 
-       ret = sysfs_create_group(get_governor_parent_kobj(policy),
-                                get_sysfs_attr(dbs_data));
-       if (ret)
-               goto reset_gdbs_data;
+       policy_dbs->dbs_data = dbs_data;
+       dbs_data->usage_count = 1;
+       list_add(&policy_dbs->list, &dbs_data->policy_dbs_list);
 
-       return 0;
+       gov->kobj_type.sysfs_ops = &governor_sysfs_ops;
+       ret = kobject_init_and_add(&dbs_data->kobj, &gov->kobj_type,
+                                  get_governor_parent_kobj(policy),
+                                  "%s", gov->gov.name);
+       if (!ret)
+               goto out;
+
+       /* Failure, so roll back. */
+       pr_err("cpufreq: Governor initialization failed (dbs_data kobject init error %d)\n", ret);
 
-reset_gdbs_data:
        policy->governor_data = NULL;
 
        if (!have_governor_per_policy())
-               cdata->gdbs_data = NULL;
-       cdata->exit(dbs_data, !policy->governor->initialized);
-free_common_dbs_info:
-       free_common_dbs_info(policy, cdata);
-free_dbs_data:
+               gov->gdbs_data = NULL;
+       gov->exit(dbs_data, !policy->governor->initialized);
        kfree(dbs_data);
+
+free_policy_dbs_info:
+       free_policy_dbs_info(policy_dbs, gov);
+
+out:
+       mutex_unlock(&gov_dbs_data_mutex);
        return ret;
 }
 
-static int cpufreq_governor_exit(struct cpufreq_policy *policy,
-                                struct dbs_data *dbs_data)
+static int cpufreq_governor_exit(struct cpufreq_policy *policy)
 {
-       struct common_dbs_data *cdata = dbs_data->cdata;
-       struct cpu_dbs_info *cdbs = cdata->get_cpu_cdbs(policy->cpu);
+       struct dbs_governor *gov = dbs_governor_of(policy);
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct dbs_data *dbs_data = policy_dbs->dbs_data;
+       int count;
 
-       /* State should be equivalent to INIT */
-       if (!cdbs->shared || cdbs->shared->policy)
-               return -EBUSY;
+       /* Protect gov->gdbs_data against concurrent updates. */
+       mutex_lock(&gov_dbs_data_mutex);
+
+       mutex_lock(&dbs_data->mutex);
+       list_del(&policy_dbs->list);
+       count = --dbs_data->usage_count;
+       mutex_unlock(&dbs_data->mutex);
 
-       if (!--dbs_data->usage_count) {
-               sysfs_remove_group(get_governor_parent_kobj(policy),
-                                  get_sysfs_attr(dbs_data));
+       if (!count) {
+               kobject_put(&dbs_data->kobj);
 
                policy->governor_data = NULL;
 
                if (!have_governor_per_policy())
-                       cdata->gdbs_data = NULL;
+                       gov->gdbs_data = NULL;
 
-               cdata->exit(dbs_data, policy->governor->initialized == 1);
+               gov->exit(dbs_data, policy->governor->initialized == 1);
+               mutex_destroy(&dbs_data->mutex);
                kfree(dbs_data);
        } else {
                policy->governor_data = NULL;
        }
 
-       free_common_dbs_info(policy, cdata);
+       free_policy_dbs_info(policy_dbs, gov);
+
+       mutex_unlock(&gov_dbs_data_mutex);
        return 0;
 }
 
-static int cpufreq_governor_start(struct cpufreq_policy *policy,
-                                 struct dbs_data *dbs_data)
+static int cpufreq_governor_start(struct cpufreq_policy *policy)
 {
-       struct common_dbs_data *cdata = dbs_data->cdata;
-       unsigned int sampling_rate, ignore_nice, j, cpu = policy->cpu;
-       struct cpu_dbs_info *cdbs = cdata->get_cpu_cdbs(cpu);
-       struct cpu_common_dbs_info *shared = cdbs->shared;
-       int io_busy = 0;
+       struct dbs_governor *gov = dbs_governor_of(policy);
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct dbs_data *dbs_data = policy_dbs->dbs_data;
+       unsigned int sampling_rate, ignore_nice, j;
+       unsigned int io_busy;
 
        if (!policy->cur)
                return -EINVAL;
 
-       /* State should be equivalent to INIT */
-       if (!shared || shared->policy)
-               return -EBUSY;
+       policy_dbs->is_shared = policy_is_shared(policy);
+       policy_dbs->rate_mult = 1;
 
-       if (cdata->governor == GOV_CONSERVATIVE) {
-               struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
-
-               sampling_rate = cs_tuners->sampling_rate;
-               ignore_nice = cs_tuners->ignore_nice_load;
-       } else {
-               struct od_dbs_tuners *od_tuners = dbs_data->tuners;
-
-               sampling_rate = od_tuners->sampling_rate;
-               ignore_nice = od_tuners->ignore_nice_load;
-               io_busy = od_tuners->io_is_busy;
-       }
-
-       shared->policy = policy;
-       shared->time_stamp = ktime_get();
+       sampling_rate = dbs_data->sampling_rate;
+       ignore_nice = dbs_data->ignore_nice_load;
+       io_busy = dbs_data->io_is_busy;
 
        for_each_cpu(j, policy->cpus) {
-               struct cpu_dbs_info *j_cdbs = cdata->get_cpu_cdbs(j);
+               struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
                unsigned int prev_load;
 
-               j_cdbs->prev_cpu_idle =
-                       get_cpu_idle_time(j, &j_cdbs->prev_cpu_wall, io_busy);
+               j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_cpu_wall, io_busy);
 
-               prev_load = (unsigned int)(j_cdbs->prev_cpu_wall -
-                                           j_cdbs->prev_cpu_idle);
-               j_cdbs->prev_load = 100 * prev_load /
-                                   (unsigned int)j_cdbs->prev_cpu_wall;
+               prev_load = j_cdbs->prev_cpu_wall - j_cdbs->prev_cpu_idle;
+               j_cdbs->prev_load = 100 * prev_load / (unsigned int)j_cdbs->prev_cpu_wall;
 
                if (ignore_nice)
                        j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-
-               __setup_timer(&j_cdbs->timer, dbs_timer_handler,
-                             (unsigned long)j_cdbs,
-                             TIMER_DEFERRABLE | TIMER_IRQSAFE);
        }
 
-       if (cdata->governor == GOV_CONSERVATIVE) {
-               struct cs_cpu_dbs_info_s *cs_dbs_info =
-                       cdata->get_cpu_dbs_info_s(cpu);
-
-               cs_dbs_info->down_skip = 0;
-               cs_dbs_info->requested_freq = policy->cur;
-       } else {
-               struct od_ops *od_ops = cdata->gov_ops;
-               struct od_cpu_dbs_info_s *od_dbs_info = cdata->get_cpu_dbs_info_s(cpu);
-
-               od_dbs_info->rate_mult = 1;
-               od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
-               od_ops->powersave_bias_init_cpu(cpu);
-       }
+       gov->start(policy);
 
-       gov_add_timers(policy, delay_for_sampling_rate(sampling_rate));
+       gov_set_update_util(policy_dbs, sampling_rate);
        return 0;
 }
 
-static int cpufreq_governor_stop(struct cpufreq_policy *policy,
-                                struct dbs_data *dbs_data)
+static int cpufreq_governor_stop(struct cpufreq_policy *policy)
 {
-       struct cpu_dbs_info *cdbs = dbs_data->cdata->get_cpu_cdbs(policy->cpu);
-       struct cpu_common_dbs_info *shared = cdbs->shared;
-
-       /* State should be equivalent to START */
-       if (!shared || !shared->policy)
-               return -EBUSY;
-
-       gov_cancel_work(shared);
-       shared->policy = NULL;
-
+       gov_cancel_work(policy);
        return 0;
 }
 
-static int cpufreq_governor_limits(struct cpufreq_policy *policy,
-                                  struct dbs_data *dbs_data)
+static int cpufreq_governor_limits(struct cpufreq_policy *policy)
 {
-       struct common_dbs_data *cdata = dbs_data->cdata;
-       unsigned int cpu = policy->cpu;
-       struct cpu_dbs_info *cdbs = cdata->get_cpu_cdbs(cpu);
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
 
-       /* State should be equivalent to START */
-       if (!cdbs->shared || !cdbs->shared->policy)
-               return -EBUSY;
+       mutex_lock(&policy_dbs->timer_mutex);
+
+       if (policy->max < policy->cur)
+               __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
+       else if (policy->min > policy->cur)
+               __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
+
+       gov_update_sample_delay(policy_dbs, 0);
 
-       mutex_lock(&cdbs->shared->timer_mutex);
-       if (policy->max < cdbs->shared->policy->cur)
-               __cpufreq_driver_target(cdbs->shared->policy, policy->max,
-                                       CPUFREQ_RELATION_H);
-       else if (policy->min > cdbs->shared->policy->cur)
-               __cpufreq_driver_target(cdbs->shared->policy, policy->min,
-                                       CPUFREQ_RELATION_L);
-       dbs_check_cpu(dbs_data, cpu);
-       mutex_unlock(&cdbs->shared->timer_mutex);
+       mutex_unlock(&policy_dbs->timer_mutex);
 
        return 0;
 }
 
-int cpufreq_governor_dbs(struct cpufreq_policy *policy,
-                        struct common_dbs_data *cdata, unsigned int event)
+int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
 {
-       struct dbs_data *dbs_data;
-       int ret;
-
-       /* Lock governor to block concurrent initialization of governor */
-       mutex_lock(&cdata->mutex);
-
-       if (have_governor_per_policy())
-               dbs_data = policy->governor_data;
-       else
-               dbs_data = cdata->gdbs_data;
-
-       if (!dbs_data && (event != CPUFREQ_GOV_POLICY_INIT)) {
-               ret = -EINVAL;
-               goto unlock;
-       }
-
-       switch (event) {
-       case CPUFREQ_GOV_POLICY_INIT:
-               ret = cpufreq_governor_init(policy, dbs_data, cdata);
-               break;
-       case CPUFREQ_GOV_POLICY_EXIT:
-               ret = cpufreq_governor_exit(policy, dbs_data);
-               break;
-       case CPUFREQ_GOV_START:
-               ret = cpufreq_governor_start(policy, dbs_data);
-               break;
-       case CPUFREQ_GOV_STOP:
-               ret = cpufreq_governor_stop(policy, dbs_data);
-               break;
-       case CPUFREQ_GOV_LIMITS:
-               ret = cpufreq_governor_limits(policy, dbs_data);
-               break;
-       default:
-               ret = -EINVAL;
+       if (event == CPUFREQ_GOV_POLICY_INIT) {
+               return cpufreq_governor_init(policy);
+       } else if (policy->governor_data) {
+               switch (event) {
+               case CPUFREQ_GOV_POLICY_EXIT:
+                       return cpufreq_governor_exit(policy);
+               case CPUFREQ_GOV_START:
+                       return cpufreq_governor_start(policy);
+               case CPUFREQ_GOV_STOP:
+                       return cpufreq_governor_stop(policy);
+               case CPUFREQ_GOV_LIMITS:
+                       return cpufreq_governor_limits(policy);
+               }
        }
-
-unlock:
-       mutex_unlock(&cdata->mutex);
-
-       return ret;
+       return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(cpufreq_governor_dbs);
index 91e767a058a763995971b6e98f8c1336a78df471..61ff82fe0613296678532621847e5cd42361ad33 100644 (file)
@@ -18,6 +18,7 @@
 #define _CPUFREQ_GOVERNOR_H
 
 #include <linux/atomic.h>
+#include <linux/irq_work.h>
 #include <linux/cpufreq.h>
 #include <linux/kernel_stat.h>
 #include <linux/module.h>
 enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};
 
 /*
- * Macro for creating governors sysfs routines
- *
- * - gov_sys: One governor instance per whole system
- * - gov_pol: One governor instance per policy
+ * Abbreviations:
+ * dbs: used as a shortform for demand based switching It helps to keep variable
+ *     names smaller, simpler
+ * cdbs: common dbs
+ * od_*: On-demand governor
+ * cs_*: Conservative governor
  */
 
-/* Create attributes */
-#define gov_sys_attr_ro(_name)                                         \
-static struct global_attr _name##_gov_sys =                            \
-__ATTR(_name, 0444, show_##_name##_gov_sys, NULL)
-
-#define gov_sys_attr_rw(_name)                                         \
-static struct global_attr _name##_gov_sys =                            \
-__ATTR(_name, 0644, show_##_name##_gov_sys, store_##_name##_gov_sys)
-
-#define gov_pol_attr_ro(_name)                                         \
-static struct freq_attr _name##_gov_pol =                              \
-__ATTR(_name, 0444, show_##_name##_gov_pol, NULL)
-
-#define gov_pol_attr_rw(_name)                                         \
-static struct freq_attr _name##_gov_pol =                              \
-__ATTR(_name, 0644, show_##_name##_gov_pol, store_##_name##_gov_pol)
+/* Governor demand based switching data (per-policy or global). */
+struct dbs_data {
+       int usage_count;
+       void *tuners;
+       unsigned int min_sampling_rate;
+       unsigned int ignore_nice_load;
+       unsigned int sampling_rate;
+       unsigned int sampling_down_factor;
+       unsigned int up_threshold;
+       unsigned int io_is_busy;
 
-#define gov_sys_pol_attr_rw(_name)                                     \
-       gov_sys_attr_rw(_name);                                         \
-       gov_pol_attr_rw(_name)
+       struct kobject kobj;
+       struct list_head policy_dbs_list;
+       /*
+        * Protect concurrent updates to governor tunables from sysfs,
+        * policy_dbs_list and usage_count.
+        */
+       struct mutex mutex;
+};
 
-#define gov_sys_pol_attr_ro(_name)                                     \
-       gov_sys_attr_ro(_name);                                         \
-       gov_pol_attr_ro(_name)
+/* Governor's specific attributes */
+struct dbs_data;
+struct governor_attr {
+       struct attribute attr;
+       ssize_t (*show)(struct dbs_data *dbs_data, char *buf);
+       ssize_t (*store)(struct dbs_data *dbs_data, const char *buf,
+                        size_t count);
+};
 
-/* Create show/store routines */
-#define show_one(_gov, file_name)                                      \
-static ssize_t show_##file_name##_gov_sys                              \
-(struct kobject *kobj, struct attribute *attr, char *buf)              \
+#define gov_show_one(_gov, file_name)                                  \
+static ssize_t show_##file_name                                                \
+(struct dbs_data *dbs_data, char *buf)                                 \
 {                                                                      \
-       struct _gov##_dbs_tuners *tuners = _gov##_dbs_cdata.gdbs_data->tuners; \
-       return sprintf(buf, "%u\n", tuners->file_name);                 \
-}                                                                      \
-                                                                       \
-static ssize_t show_##file_name##_gov_pol                              \
-(struct cpufreq_policy *policy, char *buf)                             \
-{                                                                      \
-       struct dbs_data *dbs_data = policy->governor_data;              \
        struct _gov##_dbs_tuners *tuners = dbs_data->tuners;            \
        return sprintf(buf, "%u\n", tuners->file_name);                 \
 }
 
-#define store_one(_gov, file_name)                                     \
-static ssize_t store_##file_name##_gov_sys                             \
-(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) \
-{                                                                      \
-       struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data;         \
-       return store_##file_name(dbs_data, buf, count);                 \
-}                                                                      \
-                                                                       \
-static ssize_t store_##file_name##_gov_pol                             \
-(struct cpufreq_policy *policy, const char *buf, size_t count)         \
+#define gov_show_one_common(file_name)                                 \
+static ssize_t show_##file_name                                                \
+(struct dbs_data *dbs_data, char *buf)                                 \
 {                                                                      \
-       struct dbs_data *dbs_data = policy->governor_data;              \
-       return store_##file_name(dbs_data, buf, count);                 \
+       return sprintf(buf, "%u\n", dbs_data->file_name);               \
 }
 
-#define show_store_one(_gov, file_name)                                        \
-show_one(_gov, file_name);                                             \
-store_one(_gov, file_name)
+#define gov_attr_ro(_name)                                             \
+static struct governor_attr _name =                                    \
+__ATTR(_name, 0444, show_##_name, NULL)
 
-/* create helper routines */
-#define define_get_cpu_dbs_routines(_dbs_info)                         \
-static struct cpu_dbs_info *get_cpu_cdbs(int cpu)                      \
-{                                                                      \
-       return &per_cpu(_dbs_info, cpu).cdbs;                           \
-}                                                                      \
-                                                                       \
-static void *get_cpu_dbs_info_s(int cpu)                               \
-{                                                                      \
-       return &per_cpu(_dbs_info, cpu);                                \
-}
-
-/*
- * Abbreviations:
- * dbs: used as a shortform for demand based switching It helps to keep variable
- *     names smaller, simpler
- * cdbs: common dbs
- * od_*: On-demand governor
- * cs_*: Conservative governor
- */
+#define gov_attr_rw(_name)                                             \
+static struct governor_attr _name =                                    \
+__ATTR(_name, 0644, show_##_name, store_##_name)
 
 /* Common to all CPUs of a policy */
-struct cpu_common_dbs_info {
+struct policy_dbs_info {
        struct cpufreq_policy *policy;
        /*
         * Per policy mutex that serializes load evaluation from limit-change
@@ -138,11 +111,27 @@ struct cpu_common_dbs_info {
         */
        struct mutex timer_mutex;
 
-       ktime_t time_stamp;
-       atomic_t skip_work;
+       u64 last_sample_time;
+       s64 sample_delay_ns;
+       atomic_t work_count;
+       struct irq_work irq_work;
        struct work_struct work;
+       /* dbs_data may be shared between multiple policy objects */
+       struct dbs_data *dbs_data;
+       struct list_head list;
+       /* Multiplier for increasing sample delay temporarily. */
+       unsigned int rate_mult;
+       /* Status indicators */
+       bool is_shared;         /* This object is used by multiple CPUs */
+       bool work_in_progress;  /* Work is being queued up or in progress */
 };
 
+static inline void gov_update_sample_delay(struct policy_dbs_info *policy_dbs,
+                                          unsigned int delay_us)
+{
+       policy_dbs->sample_delay_ns = delay_us * NSEC_PER_USEC;
+}
+
 /* Per cpu structures */
 struct cpu_dbs_info {
        u64 prev_cpu_idle;
@@ -155,54 +144,14 @@ struct cpu_dbs_info {
         * wake-up from idle.
         */
        unsigned int prev_load;
-       struct timer_list timer;
-       struct cpu_common_dbs_info *shared;
-};
-
-struct od_cpu_dbs_info_s {
-       struct cpu_dbs_info cdbs;
-       struct cpufreq_frequency_table *freq_table;
-       unsigned int freq_lo;
-       unsigned int freq_lo_jiffies;
-       unsigned int freq_hi_jiffies;
-       unsigned int rate_mult;
-       unsigned int sample_type:1;
-};
-
-struct cs_cpu_dbs_info_s {
-       struct cpu_dbs_info cdbs;
-       unsigned int down_skip;
-       unsigned int requested_freq;
-};
-
-/* Per policy Governors sysfs tunables */
-struct od_dbs_tuners {
-       unsigned int ignore_nice_load;
-       unsigned int sampling_rate;
-       unsigned int sampling_down_factor;
-       unsigned int up_threshold;
-       unsigned int powersave_bias;
-       unsigned int io_is_busy;
-};
-
-struct cs_dbs_tuners {
-       unsigned int ignore_nice_load;
-       unsigned int sampling_rate;
-       unsigned int sampling_down_factor;
-       unsigned int up_threshold;
-       unsigned int down_threshold;
-       unsigned int freq_step;
+       struct update_util_data update_util;
+       struct policy_dbs_info *policy_dbs;
 };
 
 /* Common Governor data across policies */
-struct dbs_data;
-struct common_dbs_data {
-       /* Common across governors */
-       #define GOV_ONDEMAND            0
-       #define GOV_CONSERVATIVE        1
-       int governor;
-       struct attribute_group *attr_group_gov_sys; /* one governor - system */
-       struct attribute_group *attr_group_gov_pol; /* one governor - policy */
+struct dbs_governor {
+       struct cpufreq_governor gov;
+       struct kobj_type kobj_type;
 
        /*
         * Common data for platforms that don't set
@@ -210,74 +159,32 @@ struct common_dbs_data {
         */
        struct dbs_data *gdbs_data;
 
-       struct cpu_dbs_info *(*get_cpu_cdbs)(int cpu);
-       void *(*get_cpu_dbs_info_s)(int cpu);
-       unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy,
-                                     bool modify_all);
-       void (*gov_check_cpu)(int cpu, unsigned int load);
+       unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy);
+       struct policy_dbs_info *(*alloc)(void);
+       void (*free)(struct policy_dbs_info *policy_dbs);
        int (*init)(struct dbs_data *dbs_data, bool notify);
        void (*exit)(struct dbs_data *dbs_data, bool notify);
-
-       /* Governor specific ops, see below */
-       void *gov_ops;
-
-       /*
-        * Protects governor's data (struct dbs_data and struct common_dbs_data)
-        */
-       struct mutex mutex;
+       void (*start)(struct cpufreq_policy *policy);
 };
 
-/* Governor Per policy data */
-struct dbs_data {
-       struct common_dbs_data *cdata;
-       unsigned int min_sampling_rate;
-       int usage_count;
-       void *tuners;
-};
+static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy)
+{
+       return container_of(policy->governor, struct dbs_governor, gov);
+}
 
-/* Governor specific ops, will be passed to dbs_data->gov_ops */
+/* Governor specific operations */
 struct od_ops {
-       void (*powersave_bias_init_cpu)(int cpu);
        unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
                        unsigned int freq_next, unsigned int relation);
-       void (*freq_increase)(struct cpufreq_policy *policy, unsigned int freq);
 };
 
-static inline int delay_for_sampling_rate(unsigned int sampling_rate)
-{
-       int delay = usecs_to_jiffies(sampling_rate);
-
-       /* We want all CPUs to do sampling nearly on same jiffy */
-       if (num_online_cpus() > 1)
-               delay -= jiffies % delay;
-
-       return delay;
-}
-
-#define declare_show_sampling_rate_min(_gov)                           \
-static ssize_t show_sampling_rate_min_gov_sys                          \
-(struct kobject *kobj, struct attribute *attr, char *buf)              \
-{                                                                      \
-       struct dbs_data *dbs_data = _gov##_dbs_cdata.gdbs_data;         \
-       return sprintf(buf, "%u\n", dbs_data->min_sampling_rate);       \
-}                                                                      \
-                                                                       \
-static ssize_t show_sampling_rate_min_gov_pol                          \
-(struct cpufreq_policy *policy, char *buf)                             \
-{                                                                      \
-       struct dbs_data *dbs_data = policy->governor_data;              \
-       return sprintf(buf, "%u\n", dbs_data->min_sampling_rate);       \
-}
-
-extern struct mutex cpufreq_governor_lock;
-
-void gov_add_timers(struct cpufreq_policy *policy, unsigned int delay);
-void gov_cancel_work(struct cpu_common_dbs_info *shared);
-void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
-int cpufreq_governor_dbs(struct cpufreq_policy *policy,
-               struct common_dbs_data *cdata, unsigned int event);
+unsigned int dbs_update(struct cpufreq_policy *policy);
+int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event);
 void od_register_powersave_bias_handler(unsigned int (*f)
                (struct cpufreq_policy *, unsigned int, unsigned int),
                unsigned int powersave_bias);
 void od_unregister_powersave_bias_handler(void);
+ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
+                           size_t count);
+void gov_update_cpu_data(struct dbs_data *dbs_data);
 #endif /* _CPUFREQ_GOVERNOR_H */
index eae51070c03427573708fe2bd67a081ccc2ffe82..acd80272ded67b46ad651cb0eceb92bdf71e26d7 100644 (file)
@@ -16,7 +16,8 @@
 #include <linux/percpu-defs.h>
 #include <linux/slab.h>
 #include <linux/tick.h>
-#include "cpufreq_governor.h"
+
+#include "cpufreq_ondemand.h"
 
 /* On-demand governor macros */
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
 #define MIN_FREQUENCY_UP_THRESHOLD             (11)
 #define MAX_FREQUENCY_UP_THRESHOLD             (100)
 
-static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info);
-
 static struct od_ops od_ops;
 
-#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
-static struct cpufreq_governor cpufreq_gov_ondemand;
-#endif
-
 static unsigned int default_powersave_bias;
 
-static void ondemand_powersave_bias_init_cpu(int cpu)
-{
-       struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-
-       dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
-       dbs_info->freq_lo = 0;
-}
-
 /*
  * Not all CPUs want IO time to be accounted as busy; this depends on how
  * efficient idling at a higher frequency/voltage is.
@@ -70,8 +57,8 @@ static int should_io_be_busy(void)
 
 /*
  * Find right freq to be set now with powersave_bias on.
- * Returns the freq_hi to be used right now and will set freq_hi_jiffies,
- * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs.
+ * Returns the freq_hi to be used right now and will set freq_hi_delay_us,
+ * freq_lo, and freq_lo_delay_us in percpu area for averaging freqs.
  */
 static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy,
                unsigned int freq_next, unsigned int relation)
@@ -79,15 +66,15 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy,
        unsigned int freq_req, freq_reduc, freq_avg;
        unsigned int freq_hi, freq_lo;
        unsigned int index = 0;
-       unsigned int jiffies_total, jiffies_hi, jiffies_lo;
-       struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
-                                                  policy->cpu);
-       struct dbs_data *dbs_data = policy->governor_data;
+       unsigned int delay_hi_us;
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
+       struct dbs_data *dbs_data = policy_dbs->dbs_data;
        struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 
        if (!dbs_info->freq_table) {
                dbs_info->freq_lo = 0;
-               dbs_info->freq_lo_jiffies = 0;
+               dbs_info->freq_lo_delay_us = 0;
                return freq_next;
        }
 
@@ -110,31 +97,30 @@ static unsigned int generic_powersave_bias_target(struct cpufreq_policy *policy,
        /* Find out how long we have to be in hi and lo freqs */
        if (freq_hi == freq_lo) {
                dbs_info->freq_lo = 0;
-               dbs_info->freq_lo_jiffies = 0;
+               dbs_info->freq_lo_delay_us = 0;
                return freq_lo;
        }
-       jiffies_total = usecs_to_jiffies(od_tuners->sampling_rate);
-       jiffies_hi = (freq_avg - freq_lo) * jiffies_total;
-       jiffies_hi += ((freq_hi - freq_lo) / 2);
-       jiffies_hi /= (freq_hi - freq_lo);
-       jiffies_lo = jiffies_total - jiffies_hi;
+       delay_hi_us = (freq_avg - freq_lo) * dbs_data->sampling_rate;
+       delay_hi_us += (freq_hi - freq_lo) / 2;
+       delay_hi_us /= freq_hi - freq_lo;
+       dbs_info->freq_hi_delay_us = delay_hi_us;
        dbs_info->freq_lo = freq_lo;
-       dbs_info->freq_lo_jiffies = jiffies_lo;
-       dbs_info->freq_hi_jiffies = jiffies_hi;
+       dbs_info->freq_lo_delay_us = dbs_data->sampling_rate - delay_hi_us;
        return freq_hi;
 }
 
-static void ondemand_powersave_bias_init(void)
+static void ondemand_powersave_bias_init(struct cpufreq_policy *policy)
 {
-       int i;
-       for_each_online_cpu(i) {
-               ondemand_powersave_bias_init_cpu(i);
-       }
+       struct od_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
+
+       dbs_info->freq_table = cpufreq_frequency_get_table(policy->cpu);
+       dbs_info->freq_lo = 0;
 }
 
 static void dbs_freq_increase(struct cpufreq_policy *policy, unsigned int freq)
 {
-       struct dbs_data *dbs_data = policy->governor_data;
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct dbs_data *dbs_data = policy_dbs->dbs_data;
        struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 
        if (od_tuners->powersave_bias)
@@ -152,21 +138,21 @@ static void dbs_freq_increase(struct cpufreq_policy *policy, unsigned int freq)
  * (default), then we try to increase frequency. Else, we adjust the frequency
  * proportional to load.
  */
-static void od_check_cpu(int cpu, unsigned int load)
+static void od_update(struct cpufreq_policy *policy)
 {
-       struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-       struct cpufreq_policy *policy = dbs_info->cdbs.shared->policy;
-       struct dbs_data *dbs_data = policy->governor_data;
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
+       struct dbs_data *dbs_data = policy_dbs->dbs_data;
        struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+       unsigned int load = dbs_update(policy);
 
        dbs_info->freq_lo = 0;
 
        /* Check for frequency increase */
-       if (load > od_tuners->up_threshold) {
+       if (load > dbs_data->up_threshold) {
                /* If switching to max speed, apply sampling_down_factor */
                if (policy->cur < policy->max)
-                       dbs_info->rate_mult =
-                               od_tuners->sampling_down_factor;
+                       policy_dbs->rate_mult = dbs_data->sampling_down_factor;
                dbs_freq_increase(policy, policy->max);
        } else {
                /* Calculate the next frequency proportional to load */
@@ -177,177 +163,70 @@ static void od_check_cpu(int cpu, unsigned int load)
                freq_next = min_f + load * (max_f - min_f) / 100;
 
                /* No longer fully busy, reset rate_mult */
-               dbs_info->rate_mult = 1;
+               policy_dbs->rate_mult = 1;
 
-               if (!od_tuners->powersave_bias) {
-                       __cpufreq_driver_target(policy, freq_next,
-                                       CPUFREQ_RELATION_C);
-                       return;
-               }
+               if (od_tuners->powersave_bias)
+                       freq_next = od_ops.powersave_bias_target(policy,
+                                                                freq_next,
+                                                                CPUFREQ_RELATION_L);
 
-               freq_next = od_ops.powersave_bias_target(policy, freq_next,
-                                       CPUFREQ_RELATION_L);
                __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_C);
        }
 }
 
-static unsigned int od_dbs_timer(struct cpufreq_policy *policy, bool modify_all)
+static unsigned int od_dbs_timer(struct cpufreq_policy *policy)
 {
-       struct dbs_data *dbs_data = policy->governor_data;
-       unsigned int cpu = policy->cpu;
-       struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
-                       cpu);
-       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
-       int delay = 0, sample_type = dbs_info->sample_type;
-
-       if (!modify_all)
-               goto max_delay;
+       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct dbs_data *dbs_data = policy_dbs->dbs_data;
+       struct od_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
+       int sample_type = dbs_info->sample_type;
 
        /* Common NORMAL_SAMPLE setup */
        dbs_info->sample_type = OD_NORMAL_SAMPLE;
-       if (sample_type == OD_SUB_SAMPLE) {
-               delay = dbs_info->freq_lo_jiffies;
+       /*
+        * OD_SUB_SAMPLE doesn't make sense if sample_delay_ns is 0, so ignore
+        * it then.
+        */
+       if (sample_type == OD_SUB_SAMPLE && policy_dbs->sample_delay_ns > 0) {
                __cpufreq_driver_target(policy, dbs_info->freq_lo,
                                        CPUFREQ_RELATION_H);
-       } else {
-               dbs_check_cpu(dbs_data, cpu);
-               if (dbs_info->freq_lo) {
-                       /* Setup timer for SUB_SAMPLE */
-                       dbs_info->sample_type = OD_SUB_SAMPLE;
-                       delay = dbs_info->freq_hi_jiffies;
-               }
+               return dbs_info->freq_lo_delay_us;
        }
 
-max_delay:
-       if (!delay)
-               delay = delay_for_sampling_rate(od_tuners->sampling_rate
-                               * dbs_info->rate_mult);
-
-       return delay;
-}
-
-/************************** sysfs interface ************************/
-static struct common_dbs_data od_dbs_cdata;
-
-/**
- * update_sampling_rate - update sampling rate effective immediately if needed.
- * @new_rate: new sampling rate
- *
- * If new rate is smaller than the old, simply updating
- * dbs_tuners_int.sampling_rate might not be appropriate. For example, if the
- * original sampling_rate was 1 second and the requested new sampling rate is 10
- * ms because the user needs immediate reaction from ondemand governor, but not
- * sure if higher frequency will be required or not, then, the governor may
- * change the sampling rate too late; up to 1 second later. Thus, if we are
- * reducing the sampling rate, we need to make the new value effective
- * immediately.
- */
-static void update_sampling_rate(struct dbs_data *dbs_data,
-               unsigned int new_rate)
-{
-       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
-       struct cpumask cpumask;
-       int cpu;
-
-       od_tuners->sampling_rate = new_rate = max(new_rate,
-                       dbs_data->min_sampling_rate);
-
-       /*
-        * Lock governor so that governor start/stop can't execute in parallel.
-        */
-       mutex_lock(&od_dbs_cdata.mutex);
-
-       cpumask_copy(&cpumask, cpu_online_mask);
-
-       for_each_cpu(cpu, &cpumask) {
-               struct cpufreq_policy *policy;
-               struct od_cpu_dbs_info_s *dbs_info;
-               struct cpu_dbs_info *cdbs;
-               struct cpu_common_dbs_info *shared;
-               unsigned long next_sampling, appointed_at;
-
-               dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-               cdbs = &dbs_info->cdbs;
-               shared = cdbs->shared;
-
-               /*
-                * A valid shared and shared->policy means governor hasn't
-                * stopped or exited yet.
-                */
-               if (!shared || !shared->policy)
-                       continue;
-
-               policy = shared->policy;
-
-               /* clear all CPUs of this policy */
-               cpumask_andnot(&cpumask, &cpumask, policy->cpus);
+       od_update(policy);
 
-               /*
-                * Update sampling rate for CPUs whose policy is governed by
-                * dbs_data. In case of governor_per_policy, only a single
-                * policy will be governed by dbs_data, otherwise there can be
-                * multiple policies that are governed by the same dbs_data.
-                */
-               if (dbs_data != policy->governor_data)
-                       continue;
-
-               /*
-                * Checking this for any CPU should be fine, timers for all of
-                * them are scheduled together.
-                */
-               next_sampling = jiffies + usecs_to_jiffies(new_rate);
-               appointed_at = dbs_info->cdbs.timer.expires;
-
-               if (time_before(next_sampling, appointed_at)) {
-                       gov_cancel_work(shared);
-                       gov_add_timers(policy, usecs_to_jiffies(new_rate));
-
-               }
+       if (dbs_info->freq_lo) {
+               /* Setup timer for SUB_SAMPLE */
+               dbs_info->sample_type = OD_SUB_SAMPLE;
+               return dbs_info->freq_hi_delay_us;
        }
 
-       mutex_unlock(&od_dbs_cdata.mutex);
+       return dbs_data->sampling_rate * policy_dbs->rate_mult;
 }
 
-static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
-               size_t count)
-{
-       unsigned int input;
-       int ret;
-       ret = sscanf(buf, "%u", &input);
-       if (ret != 1)
-               return -EINVAL;
-
-       update_sampling_rate(dbs_data, input);
-       return count;
-}
+/************************** sysfs interface ************************/
+static struct dbs_governor od_dbs_gov;
 
 static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf,
                size_t count)
 {
-       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
        unsigned int input;
        int ret;
-       unsigned int j;
 
        ret = sscanf(buf, "%u", &input);
        if (ret != 1)
                return -EINVAL;
-       od_tuners->io_is_busy = !!input;
+       dbs_data->io_is_busy = !!input;
 
        /* we need to re-evaluate prev_cpu_idle */
-       for_each_online_cpu(j) {
-               struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
-                                                                       j);
-               dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
-                       &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy);
-       }
+       gov_update_cpu_data(dbs_data);
+
        return count;
 }
 
 static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
                size_t count)
 {
-       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
        unsigned int input;
        int ret;
        ret = sscanf(buf, "%u", &input);
@@ -357,40 +236,43 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
                return -EINVAL;
        }
 
-       od_tuners->up_threshold = input;
+       dbs_data->up_threshold = input;
        return count;
 }
 
 static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
                const char *buf, size_t count)
 {
-       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
-       unsigned int input, j;
+       struct policy_dbs_info *policy_dbs;
+       unsigned int input;
        int ret;
        ret = sscanf(buf, "%u", &input);
 
        if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
                return -EINVAL;
-       od_tuners->sampling_down_factor = input;
+
+       dbs_data->sampling_down_factor = input;
 
        /* Reset down sampling multiplier in case it was active */
-       for_each_online_cpu(j) {
-               struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
-                               j);
-               dbs_info->rate_mult = 1;
+       list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
+               /*
+                * Doing this without locking might lead to using different
+                * rate_mult values in od_update() and od_dbs_timer().
+                */
+               mutex_lock(&policy_dbs->timer_mutex);
+               policy_dbs->rate_mult = 1;
+               mutex_unlock(&policy_dbs->timer_mutex);
        }
+
        return count;
 }
 
 static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
                const char *buf, size_t count)
 {
-       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
        unsigned int input;
        int ret;
 
-       unsigned int j;
-
        ret = sscanf(buf, "%u", &input);
        if (ret != 1)
                return -EINVAL;
@@ -398,22 +280,14 @@ static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
        if (input > 1)
                input = 1;
 
-       if (input == od_tuners->ignore_nice_load) { /* nothing to do */
+       if (input == dbs_data->ignore_nice_load) { /* nothing to do */
                return count;
        }
-       od_tuners->ignore_nice_load = input;
+       dbs_data->ignore_nice_load = input;
 
        /* we need to re-evaluate prev_cpu_idle */
-       for_each_online_cpu(j) {
-               struct od_cpu_dbs_info_s *dbs_info;
-               dbs_info = &per_cpu(od_cpu_dbs_info, j);
-               dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
-                       &dbs_info->cdbs.prev_cpu_wall, od_tuners->io_is_busy);
-               if (od_tuners->ignore_nice_load)
-                       dbs_info->cdbs.prev_cpu_nice =
-                               kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+       gov_update_cpu_data(dbs_data);
 
-       }
        return count;
 }
 
@@ -421,6 +295,7 @@ static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf,
                size_t count)
 {
        struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+       struct policy_dbs_info *policy_dbs;
        unsigned int input;
        int ret;
        ret = sscanf(buf, "%u", &input);
@@ -432,59 +307,54 @@ static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf,
                input = 1000;
 
        od_tuners->powersave_bias = input;
-       ondemand_powersave_bias_init();
+
+       list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list)
+               ondemand_powersave_bias_init(policy_dbs->policy);
+
        return count;
 }
 
-show_store_one(od, sampling_rate);
-show_store_one(od, io_is_busy);
-show_store_one(od, up_threshold);
-show_store_one(od, sampling_down_factor);
-show_store_one(od, ignore_nice_load);
-show_store_one(od, powersave_bias);
-declare_show_sampling_rate_min(od);
-
-gov_sys_pol_attr_rw(sampling_rate);
-gov_sys_pol_attr_rw(io_is_busy);
-gov_sys_pol_attr_rw(up_threshold);
-gov_sys_pol_attr_rw(sampling_down_factor);
-gov_sys_pol_attr_rw(ignore_nice_load);
-gov_sys_pol_attr_rw(powersave_bias);
-gov_sys_pol_attr_ro(sampling_rate_min);
-
-static struct attribute *dbs_attributes_gov_sys[] = {
-       &sampling_rate_min_gov_sys.attr,
-       &sampling_rate_gov_sys.attr,
-       &up_threshold_gov_sys.attr,
-       &sampling_down_factor_gov_sys.attr,
-       &ignore_nice_load_gov_sys.attr,
-       &powersave_bias_gov_sys.attr,
-       &io_is_busy_gov_sys.attr,
+gov_show_one_common(sampling_rate);
+gov_show_one_common(up_threshold);
+gov_show_one_common(sampling_down_factor);
+gov_show_one_common(ignore_nice_load);
+gov_show_one_common(min_sampling_rate);
+gov_show_one_common(io_is_busy);
+gov_show_one(od, powersave_bias);
+
+gov_attr_rw(sampling_rate);
+gov_attr_rw(io_is_busy);
+gov_attr_rw(up_threshold);
+gov_attr_rw(sampling_down_factor);
+gov_attr_rw(ignore_nice_load);
+gov_attr_rw(powersave_bias);
+gov_attr_ro(min_sampling_rate);
+
+static struct attribute *od_attributes[] = {
+       &min_sampling_rate.attr,
+       &sampling_rate.attr,
+       &up_threshold.attr,
+       &sampling_down_factor.attr,
+       &ignore_nice_load.attr,
+       &powersave_bias.attr,
+       &io_is_busy.attr,
        NULL
 };
 
-static struct attribute_group od_attr_group_gov_sys = {
-       .attrs = dbs_attributes_gov_sys,
-       .name = "ondemand",
-};
+/************************** sysfs end ************************/
 
-static struct attribute *dbs_attributes_gov_pol[] = {
-       &sampling_rate_min_gov_pol.attr,
-       &sampling_rate_gov_pol.attr,
-       &up_threshold_gov_pol.attr,
-       &sampling_down_factor_gov_pol.attr,
-       &ignore_nice_load_gov_pol.attr,
-       &powersave_bias_gov_pol.attr,
-       &io_is_busy_gov_pol.attr,
-       NULL
-};
+static struct policy_dbs_info *od_alloc(void)
+{
+       struct od_policy_dbs_info *dbs_info;
 
-static struct attribute_group od_attr_group_gov_pol = {
-       .attrs = dbs_attributes_gov_pol,
-       .name = "ondemand",
-};
+       dbs_info = kzalloc(sizeof(*dbs_info), GFP_KERNEL);
+       return dbs_info ? &dbs_info->policy_dbs : NULL;
+}
 
-/************************** sysfs end ************************/
+static void od_free(struct policy_dbs_info *policy_dbs)
+{
+       kfree(to_dbs_info(policy_dbs));
+}
 
 static int od_init(struct dbs_data *dbs_data, bool notify)
 {
@@ -503,7 +373,7 @@ static int od_init(struct dbs_data *dbs_data, bool notify)
        put_cpu();
        if (idle_time != -1ULL) {
                /* Idle micro accounting is supported. Use finer thresholds */
-               tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
+               dbs_data->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
                /*
                 * In nohz/micro accounting case we set the minimum frequency
                 * not depending on HZ, but fixed (very low). The deferred
@@ -511,17 +381,17 @@ static int od_init(struct dbs_data *dbs_data, bool notify)
                */
                dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
        } else {
-               tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
+               dbs_data->up_threshold = DEF_FREQUENCY_UP_THRESHOLD;
 
                /* For correct statistics, we need 10 ticks for each measure */
                dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
                        jiffies_to_usecs(10);
        }
 
-       tuners->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
-       tuners->ignore_nice_load = 0;
+       dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR;
+       dbs_data->ignore_nice_load = 0;
        tuners->powersave_bias = default_powersave_bias;
-       tuners->io_is_busy = should_io_be_busy();
+       dbs_data->io_is_busy = should_io_be_busy();
 
        dbs_data->tuners = tuners;
        return 0;
@@ -532,33 +402,38 @@ static void od_exit(struct dbs_data *dbs_data, bool notify)
        kfree(dbs_data->tuners);
 }
 
-define_get_cpu_dbs_routines(od_cpu_dbs_info);
+static void od_start(struct cpufreq_policy *policy)
+{
+       struct od_policy_dbs_info *dbs_info = to_dbs_info(policy->governor_data);
+
+       dbs_info->sample_type = OD_NORMAL_SAMPLE;
+       ondemand_powersave_bias_init(policy);
+}
 
 static struct od_ops od_ops = {
-       .powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu,
        .powersave_bias_target = generic_powersave_bias_target,
-       .freq_increase = dbs_freq_increase,
 };
 
-static struct common_dbs_data od_dbs_cdata = {
-       .governor = GOV_ONDEMAND,
-       .attr_group_gov_sys = &od_attr_group_gov_sys,
-       .attr_group_gov_pol = &od_attr_group_gov_pol,
-       .get_cpu_cdbs = get_cpu_cdbs,
-       .get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+static struct dbs_governor od_dbs_gov = {
+       .gov = {
+               .name = "ondemand",
+               .governor = cpufreq_governor_dbs,
+               .max_transition_latency = TRANSITION_LATENCY_LIMIT,
+               .owner = THIS_MODULE,
+       },
+       .kobj_type = { .default_attrs = od_attributes },
        .gov_dbs_timer = od_dbs_timer,
-       .gov_check_cpu = od_check_cpu,
-       .gov_ops = &od_ops,
+       .alloc = od_alloc,
+       .free = od_free,
        .init = od_init,
        .exit = od_exit,
-       .mutex = __MUTEX_INITIALIZER(od_dbs_cdata.mutex),
+       .start = od_start,
 };
 
+#define CPU_FREQ_GOV_ONDEMAND  (&od_dbs_gov.gov)
+
 static void od_set_powersave_bias(unsigned int powersave_bias)
 {
-       struct cpufreq_policy *policy;
-       struct dbs_data *dbs_data;
-       struct od_dbs_tuners *od_tuners;
        unsigned int cpu;
        cpumask_t done;
 
@@ -567,22 +442,25 @@ static void od_set_powersave_bias(unsigned int powersave_bias)
 
        get_online_cpus();
        for_each_online_cpu(cpu) {
-               struct cpu_common_dbs_info *shared;
+               struct cpufreq_policy *policy;
+               struct policy_dbs_info *policy_dbs;
+               struct dbs_data *dbs_data;
+               struct od_dbs_tuners *od_tuners;
 
                if (cpumask_test_cpu(cpu, &done))
                        continue;
 
-               shared = per_cpu(od_cpu_dbs_info, cpu).cdbs.shared;
-               if (!shared)
+               policy = cpufreq_cpu_get_raw(cpu);
+               if (!policy || policy->governor != CPU_FREQ_GOV_ONDEMAND)
                        continue;
 
-               policy = shared->policy;
-               cpumask_or(&done, &done, policy->cpus);
-
-               if (policy->governor != &cpufreq_gov_ondemand)
+               policy_dbs = policy->governor_data;
+               if (!policy_dbs)
                        continue;
 
-               dbs_data = policy->governor_data;
+               cpumask_or(&done, &done, policy->cpus);
+
+               dbs_data = policy_dbs->dbs_data;
                od_tuners = dbs_data->tuners;
                od_tuners->powersave_bias = default_powersave_bias;
        }
@@ -605,30 +483,14 @@ void od_unregister_powersave_bias_handler(void)
 }
 EXPORT_SYMBOL_GPL(od_unregister_powersave_bias_handler);
 
-static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy,
-               unsigned int event)
-{
-       return cpufreq_governor_dbs(policy, &od_dbs_cdata, event);
-}
-
-#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
-static
-#endif
-struct cpufreq_governor cpufreq_gov_ondemand = {
-       .name                   = "ondemand",
-       .governor               = od_cpufreq_governor_dbs,
-       .max_transition_latency = TRANSITION_LATENCY_LIMIT,
-       .owner                  = THIS_MODULE,
-};
-
 static int __init cpufreq_gov_dbs_init(void)
 {
-       return cpufreq_register_governor(&cpufreq_gov_ondemand);
+       return cpufreq_register_governor(CPU_FREQ_GOV_ONDEMAND);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
-       cpufreq_unregister_governor(&cpufreq_gov_ondemand);
+       cpufreq_unregister_governor(CPU_FREQ_GOV_ONDEMAND);
 }
 
 MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
@@ -638,6 +500,11 @@ MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for "
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
+struct cpufreq_governor *cpufreq_default_governor(void)
+{
+       return CPU_FREQ_GOV_ONDEMAND;
+}
+
 fs_initcall(cpufreq_gov_dbs_init);
 #else
 module_init(cpufreq_gov_dbs_init);
diff --git a/drivers/cpufreq/cpufreq_ondemand.h b/drivers/cpufreq/cpufreq_ondemand.h
new file mode 100644 (file)
index 0000000..f0121db
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Header file for CPUFreq ondemand governor and related code.
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.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.
+ */
+
+#include "cpufreq_governor.h"
+
+struct od_policy_dbs_info {
+       struct policy_dbs_info policy_dbs;
+       struct cpufreq_frequency_table *freq_table;
+       unsigned int freq_lo;
+       unsigned int freq_lo_delay_us;
+       unsigned int freq_hi_delay_us;
+       unsigned int sample_type:1;
+};
+
+static inline struct od_policy_dbs_info *to_dbs_info(struct policy_dbs_info *policy_dbs)
+{
+       return container_of(policy_dbs, struct od_policy_dbs_info, policy_dbs);
+}
+
+struct od_dbs_tuners {
+       unsigned int powersave_bias;
+};
index cf117deb39b1f45c53ade61086236eb888d24a71..af9f4b96f5a8e1ae1fd622ce05f9b198b86ed599 100644 (file)
@@ -33,10 +33,7 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy,
        return 0;
 }
 
-#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE
-static
-#endif
-struct cpufreq_governor cpufreq_gov_performance = {
+static struct cpufreq_governor cpufreq_gov_performance = {
        .name           = "performance",
        .governor       = cpufreq_governor_performance,
        .owner          = THIS_MODULE,
@@ -52,6 +49,19 @@ static void __exit cpufreq_gov_performance_exit(void)
        cpufreq_unregister_governor(&cpufreq_gov_performance);
 }
 
+#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
+struct cpufreq_governor *cpufreq_default_governor(void)
+{
+       return &cpufreq_gov_performance;
+}
+#endif
+#ifndef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE
+struct cpufreq_governor *cpufreq_fallback_governor(void)
+{
+       return &cpufreq_gov_performance;
+}
+#endif
+
 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION("CPUfreq policy governor 'performance'");
 MODULE_LICENSE("GPL");
index e3b874c235eada5d353f4b02831140c6a244af68..b8b400232a7451fe392f767ed7aaecf6600c680d 100644 (file)
@@ -33,10 +33,7 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
        return 0;
 }
 
-#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE
-static
-#endif
-struct cpufreq_governor cpufreq_gov_powersave = {
+static struct cpufreq_governor cpufreq_gov_powersave = {
        .name           = "powersave",
        .governor       = cpufreq_governor_powersave,
        .owner          = THIS_MODULE,
@@ -57,6 +54,11 @@ MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'");
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE
+struct cpufreq_governor *cpufreq_default_governor(void)
+{
+       return &cpufreq_gov_powersave;
+}
+
 fs_initcall(cpufreq_gov_powersave_init);
 #else
 module_init(cpufreq_gov_powersave_init);
index 4dbf1db16aca0e5d29d44b002a6d4ad0cae6d139..4d16f45ee1daf3e64e23c97a9cec8b7a4ea0fc0f 100644 (file)
@@ -89,10 +89,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
        return rc;
 }
 
-#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
-static
-#endif
-struct cpufreq_governor cpufreq_gov_userspace = {
+static struct cpufreq_governor cpufreq_gov_userspace = {
        .name           = "userspace",
        .governor       = cpufreq_governor_userspace,
        .store_setspeed = cpufreq_set,
@@ -116,6 +113,11 @@ MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'");
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
+struct cpufreq_governor *cpufreq_default_governor(void)
+{
+       return &cpufreq_gov_userspace;
+}
+
 fs_initcall(cpufreq_gov_userspace_init);
 #else
 module_init(cpufreq_gov_userspace_init);
index cd83d477e32d412394da574e8e02adb6dd7be832..cb5607495816d73bfa33e3579962aa5a68ff3af4 100644 (file)
@@ -71,7 +71,7 @@ struct sample {
        u64 mperf;
        u64 tsc;
        int freq;
-       ktime_t time;
+       u64 time;
 };
 
 struct pstate_data {
@@ -103,13 +103,13 @@ struct _pid {
 struct cpudata {
        int cpu;
 
-       struct timer_list timer;
+       struct update_util_data update_util;
 
        struct pstate_data pstate;
        struct vid_data vid;
        struct _pid pid;
 
-       ktime_t last_sample_time;
+       u64     last_sample_time;
        u64     prev_aperf;
        u64     prev_mperf;
        u64     prev_tsc;
@@ -120,6 +120,7 @@ struct cpudata {
 static struct cpudata **all_cpu_data;
 struct pstate_adjust_policy {
        int sample_rate_ms;
+       s64 sample_rate_ns;
        int deadband;
        int setpoint;
        int p_gain_pct;
@@ -197,8 +198,8 @@ static struct perf_limits *limits = &powersave_limits;
 
 static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
                             int deadband, int integral) {
-       pid->setpoint = setpoint;
-       pid->deadband  = deadband;
+       pid->setpoint = int_tofp(setpoint);
+       pid->deadband  = int_tofp(deadband);
        pid->integral  = int_tofp(integral);
        pid->last_err  = int_tofp(setpoint) - int_tofp(busy);
 }
@@ -224,9 +225,9 @@ static signed int pid_calc(struct _pid *pid, int32_t busy)
        int32_t pterm, dterm, fp_error;
        int32_t integral_limit;
 
-       fp_error = int_tofp(pid->setpoint) - busy;
+       fp_error = pid->setpoint - busy;
 
-       if (abs(fp_error) <= int_tofp(pid->deadband))
+       if (abs(fp_error) <= pid->deadband)
                return 0;
 
        pterm = mul_fp(pid->p_gain, fp_error);
@@ -286,7 +287,7 @@ static inline void update_turbo_state(void)
                 cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
 }
 
-static void intel_pstate_hwp_set(void)
+static void intel_pstate_hwp_set(const struct cpumask *cpumask)
 {
        int min, hw_min, max, hw_max, cpu, range, adj_range;
        u64 value, cap;
@@ -296,9 +297,7 @@ static void intel_pstate_hwp_set(void)
        hw_max = HWP_HIGHEST_PERF(cap);
        range = hw_max - hw_min;
 
-       get_online_cpus();
-
-       for_each_online_cpu(cpu) {
+       for_each_cpu(cpu, cpumask) {
                rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
                adj_range = limits->min_perf_pct * range / 100;
                min = hw_min + adj_range;
@@ -317,7 +316,12 @@ static void intel_pstate_hwp_set(void)
                value |= HWP_MAX_PERF(max);
                wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value);
        }
+}
 
+static void intel_pstate_hwp_set_online_cpus(void)
+{
+       get_online_cpus();
+       intel_pstate_hwp_set(cpu_online_mask);
        put_online_cpus();
 }
 
@@ -439,7 +443,7 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b,
        limits->no_turbo = clamp_t(int, input, 0, 1);
 
        if (hwp_active)
-               intel_pstate_hwp_set();
+               intel_pstate_hwp_set_online_cpus();
 
        return count;
 }
@@ -465,7 +469,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b,
                                  int_tofp(100));
 
        if (hwp_active)
-               intel_pstate_hwp_set();
+               intel_pstate_hwp_set_online_cpus();
        return count;
 }
 
@@ -490,7 +494,7 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
                                  int_tofp(100));
 
        if (hwp_active)
-               intel_pstate_hwp_set();
+               intel_pstate_hwp_set_online_cpus();
        return count;
 }
 
@@ -531,6 +535,9 @@ static void __init intel_pstate_sysfs_expose_params(void)
 
 static void intel_pstate_hwp_enable(struct cpudata *cpudata)
 {
+       /* First disable HWP notification interrupt as we don't process them */
+       wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
+
        wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
 }
 
@@ -712,7 +719,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate)
        if (limits->no_turbo && !limits->turbo_disabled)
                val |= (u64)1 << 32;
 
-       wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val);
+       wrmsrl(MSR_IA32_PERF_CTL, val);
 }
 
 static int knl_get_turbo_pstate(void)
@@ -824,11 +831,11 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
         * policy, or by cpu specific default values determined through
         * experimentation.
         */
-       max_perf_adj = fp_toint(mul_fp(int_tofp(max_perf), limits->max_perf));
+       max_perf_adj = fp_toint(max_perf * limits->max_perf);
        *max = clamp_t(int, max_perf_adj,
                        cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
 
-       min_perf = fp_toint(mul_fp(int_tofp(max_perf), limits->min_perf));
+       min_perf = fp_toint(max_perf * limits->min_perf);
        *min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
 }
 
@@ -874,16 +881,10 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu)
        core_pct = int_tofp(sample->aperf) * int_tofp(100);
        core_pct = div64_u64(core_pct, int_tofp(sample->mperf));
 
-       sample->freq = fp_toint(
-               mul_fp(int_tofp(
-                       cpu->pstate.max_pstate_physical *
-                       cpu->pstate.scaling / 100),
-                       core_pct));
-
        sample->core_pct_busy = (int32_t)core_pct;
 }
 
-static inline void intel_pstate_sample(struct cpudata *cpu)
+static inline bool intel_pstate_sample(struct cpudata *cpu, u64 time)
 {
        u64 aperf, mperf;
        unsigned long flags;
@@ -893,14 +894,14 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
        rdmsrl(MSR_IA32_APERF, aperf);
        rdmsrl(MSR_IA32_MPERF, mperf);
        tsc = rdtsc();
-       if ((cpu->prev_mperf == mperf) || (cpu->prev_tsc == tsc)) {
+       if (cpu->prev_mperf == mperf || cpu->prev_tsc == tsc) {
                local_irq_restore(flags);
-               return;
+               return false;
        }
        local_irq_restore(flags);
 
        cpu->last_sample_time = cpu->sample.time;
-       cpu->sample.time = ktime_get();
+       cpu->sample.time = time;
        cpu->sample.aperf = aperf;
        cpu->sample.mperf = mperf;
        cpu->sample.tsc =  tsc;
@@ -908,27 +909,16 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
        cpu->sample.mperf -= cpu->prev_mperf;
        cpu->sample.tsc -= cpu->prev_tsc;
 
-       intel_pstate_calc_busy(cpu);
-
        cpu->prev_aperf = aperf;
        cpu->prev_mperf = mperf;
        cpu->prev_tsc = tsc;
+       return true;
 }
 
-static inline void intel_hwp_set_sample_time(struct cpudata *cpu)
-{
-       int delay;
-
-       delay = msecs_to_jiffies(50);
-       mod_timer_pinned(&cpu->timer, jiffies + delay);
-}
-
-static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
+static inline int32_t get_avg_frequency(struct cpudata *cpu)
 {
-       int delay;
-
-       delay = msecs_to_jiffies(pid_params.sample_rate_ms);
-       mod_timer_pinned(&cpu->timer, jiffies + delay);
+       return div64_u64(cpu->pstate.max_pstate_physical * cpu->sample.aperf *
+               cpu->pstate.scaling, cpu->sample.mperf);
 }
 
 static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
@@ -954,7 +944,6 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
        mperf = cpu->sample.mperf + delta_iowait_mperf;
        cpu->prev_cummulative_iowait = cummulative_iowait;
 
-
        /*
         * The load can be estimated as the ratio of the mperf counter
         * running at a constant frequency during active periods
@@ -970,8 +959,9 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
 static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
 {
        int32_t core_busy, max_pstate, current_pstate, sample_ratio;
-       s64 duration_us;
-       u32 sample_time;
+       u64 duration_ns;
+
+       intel_pstate_calc_busy(cpu);
 
        /*
         * core_busy is the ratio of actual performance to max
@@ -990,18 +980,16 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
        core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
 
        /*
-        * Since we have a deferred timer, it will not fire unless
-        * we are in C0.  So, determine if the actual elapsed time
-        * is significantly greater (3x) than our sample interval.  If it
-        * is, then we were idle for a long enough period of time
-        * to adjust our busyness.
+        * Since our utilization update callback will not run unless we are
+        * in C0, check if the actual elapsed time is significantly greater (3x)
+        * than our sample interval.  If it is, then we were idle for a long
+        * enough period of time to adjust our busyness.
         */
-       sample_time = pid_params.sample_rate_ms  * USEC_PER_MSEC;
-       duration_us = ktime_us_delta(cpu->sample.time,
-                                    cpu->last_sample_time);
-       if (duration_us > sample_time * 3) {
-               sample_ratio = div_fp(int_tofp(sample_time),
-                                     int_tofp(duration_us));
+       duration_ns = cpu->sample.time - cpu->last_sample_time;
+       if ((s64)duration_ns > pid_params.sample_rate_ns * 3
+           && cpu->last_sample_time > 0) {
+               sample_ratio = div_fp(int_tofp(pid_params.sample_rate_ns),
+                                     int_tofp(duration_ns));
                core_busy = mul_fp(core_busy, sample_ratio);
        }
 
@@ -1028,26 +1016,21 @@ static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
                sample->mperf,
                sample->aperf,
                sample->tsc,
-               sample->freq);
+               get_avg_frequency(cpu));
 }
 
-static void intel_hwp_timer_func(unsigned long __data)
+static void intel_pstate_update_util(struct update_util_data *data, u64 time,
+                                    unsigned long util, unsigned long max)
 {
-       struct cpudata *cpu = (struct cpudata *) __data;
+       struct cpudata *cpu = container_of(data, struct cpudata, update_util);
+       u64 delta_ns = time - cpu->sample.time;
 
-       intel_pstate_sample(cpu);
-       intel_hwp_set_sample_time(cpu);
-}
+       if ((s64)delta_ns >= pid_params.sample_rate_ns) {
+               bool sample_taken = intel_pstate_sample(cpu, time);
 
-static void intel_pstate_timer_func(unsigned long __data)
-{
-       struct cpudata *cpu = (struct cpudata *) __data;
-
-       intel_pstate_sample(cpu);
-
-       intel_pstate_adjust_busy_pstate(cpu);
-
-       intel_pstate_set_sample_time(cpu);
+               if (sample_taken && !hwp_active)
+                       intel_pstate_adjust_busy_pstate(cpu);
+       }
 }
 
 #define ICPU(model, policy) \
@@ -1095,24 +1078,19 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
 
        cpu->cpu = cpunum;
 
-       if (hwp_active)
+       if (hwp_active) {
                intel_pstate_hwp_enable(cpu);
+               pid_params.sample_rate_ms = 50;
+               pid_params.sample_rate_ns = 50 * NSEC_PER_MSEC;
+       }
 
        intel_pstate_get_cpu_pstates(cpu);
 
-       init_timer_deferrable(&cpu->timer);
-       cpu->timer.data = (unsigned long)cpu;
-       cpu->timer.expires = jiffies + HZ/100;
-
-       if (!hwp_active)
-               cpu->timer.function = intel_pstate_timer_func;
-       else
-               cpu->timer.function = intel_hwp_timer_func;
-
        intel_pstate_busy_pid_reset(cpu);
-       intel_pstate_sample(cpu);
+       intel_pstate_sample(cpu, 0);
 
-       add_timer_on(&cpu->timer, cpunum);
+       cpu->update_util.func = intel_pstate_update_util;
+       cpufreq_set_update_util_data(cpunum, &cpu->update_util);
 
        pr_debug("intel_pstate: controlling: cpu %d\n", cpunum);
 
@@ -1128,7 +1106,7 @@ static unsigned int intel_pstate_get(unsigned int cpu_num)
        if (!cpu)
                return 0;
        sample = &cpu->sample;
-       return sample->freq;
+       return get_avg_frequency(cpu);
 }
 
 static int intel_pstate_set_policy(struct cpufreq_policy *policy)
@@ -1141,7 +1119,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
                pr_debug("intel_pstate: set performance\n");
                limits = &performance_limits;
                if (hwp_active)
-                       intel_pstate_hwp_set();
+                       intel_pstate_hwp_set(policy->cpus);
                return 0;
        }
 
@@ -1173,7 +1151,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
                                  int_tofp(100));
 
        if (hwp_active)
-               intel_pstate_hwp_set();
+               intel_pstate_hwp_set(policy->cpus);
 
        return 0;
 }
@@ -1196,7 +1174,9 @@ static void intel_pstate_stop_cpu(struct cpufreq_policy *policy)
 
        pr_debug("intel_pstate: CPU %d exiting\n", cpu_num);
 
-       del_timer_sync(&all_cpu_data[cpu_num]->timer);
+       cpufreq_set_update_util_data(cpu_num, NULL);
+       synchronize_sched();
+
        if (hwp_active)
                return;
 
@@ -1260,6 +1240,7 @@ static int intel_pstate_msrs_not_valid(void)
 static void copy_pid_params(struct pstate_adjust_policy *policy)
 {
        pid_params.sample_rate_ms = policy->sample_rate_ms;
+       pid_params.sample_rate_ns = pid_params.sample_rate_ms * NSEC_PER_MSEC;
        pid_params.p_gain_pct = policy->p_gain_pct;
        pid_params.i_gain_pct = policy->i_gain_pct;
        pid_params.d_gain_pct = policy->d_gain_pct;
@@ -1397,6 +1378,11 @@ static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; }
 static inline bool intel_pstate_has_acpi_ppc(void) { return false; }
 #endif /* CONFIG_ACPI */
 
+static const struct x86_cpu_id hwp_support_ids[] __initconst = {
+       { X86_VENDOR_INTEL, 6, X86_MODEL_ANY, X86_FEATURE_HWP },
+       {}
+};
+
 static int __init intel_pstate_init(void)
 {
        int cpu, rc = 0;
@@ -1406,17 +1392,16 @@ static int __init intel_pstate_init(void)
        if (no_load)
                return -ENODEV;
 
+       if (x86_match_cpu(hwp_support_ids) && !no_hwp) {
+               copy_cpu_funcs(&core_params.funcs);
+               hwp_active++;
+               goto hwp_cpu_matched;
+       }
+
        id = x86_match_cpu(intel_pstate_cpu_ids);
        if (!id)
                return -ENODEV;
 
-       /*
-        * The Intel pstate driver will be ignored if the platform
-        * firmware has its own power management modes.
-        */
-       if (intel_pstate_platform_pwr_mgmt_exists())
-               return -ENODEV;
-
        cpu_def = (struct cpu_defaults *)id->driver_data;
 
        copy_pid_params(&cpu_def->pid_policy);
@@ -1425,17 +1410,20 @@ static int __init intel_pstate_init(void)
        if (intel_pstate_msrs_not_valid())
                return -ENODEV;
 
+hwp_cpu_matched:
+       /*
+        * The Intel pstate driver will be ignored if the platform
+        * firmware has its own power management modes.
+        */
+       if (intel_pstate_platform_pwr_mgmt_exists())
+               return -ENODEV;
+
        pr_info("Intel P-state driver initializing.\n");
 
        all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus());
        if (!all_cpu_data)
                return -ENOMEM;
 
-       if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp) {
-               pr_info("intel_pstate: HWP enabled\n");
-               hwp_active++;
-       }
-
        if (!hwp_active && hwp_only)
                goto out;
 
@@ -1446,12 +1434,16 @@ static int __init intel_pstate_init(void)
        intel_pstate_debug_expose_params();
        intel_pstate_sysfs_expose_params();
 
+       if (hwp_active)
+               pr_info("intel_pstate: HWP enabled\n");
+
        return rc;
 out:
        get_online_cpus();
        for_each_online_cpu(cpu) {
                if (all_cpu_data[cpu]) {
-                       del_timer_sync(&all_cpu_data[cpu]->timer);
+                       cpufreq_set_update_util_data(cpu, NULL);
+                       synchronize_sched();
                        kfree(all_cpu_data[cpu]);
                }
        }
index 1efba340456dfc5df4b2005517fe0c1b048e198a..2058e6d292ce95fbcd6fb3099b08adf36f857cd1 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/cpu_cooling.h>
 #include <linux/cpufreq.h>
 #include <linux/cpumask.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_opp.h>
index 547890fd9572179eba4c6ce81caf5bbc8b06b947..50bf12033bbc080c70b5de72de3f89c2dc8bd3a6 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/of.h>
 #include <linux/reboot.h>
 #include <linux/slab.h>
+#include <linux/cpu.h>
+#include <trace/events/power.h>
 
 #include <asm/cputhreads.h>
 #include <asm/firmware.h>
 
 static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
 static bool rebooting, throttled, occ_reset;
+static unsigned int *core_to_chip_map;
+
+static const char * const throttle_reason[] = {
+       "No throttling",
+       "Power Cap",
+       "Processor Over Temperature",
+       "Power Supply Failure",
+       "Over Current",
+       "OCC Reset"
+};
 
 static struct chip {
        unsigned int id;
        bool throttled;
+       bool restore;
+       u8 throttle_reason;
        cpumask_t mask;
        struct work_struct throttle;
-       bool restore;
 } *chips;
 
 static int nr_chips;
@@ -312,13 +325,14 @@ static inline unsigned int get_nominal_index(void)
 static void powernv_cpufreq_throttle_check(void *data)
 {
        unsigned int cpu = smp_processor_id();
+       unsigned int chip_id = core_to_chip_map[cpu_core_index_of_thread(cpu)];
        unsigned long pmsr;
        int pmsr_pmax, i;
 
        pmsr = get_pmspr(SPRN_PMSR);
 
        for (i = 0; i < nr_chips; i++)
-               if (chips[i].id == cpu_to_chip_id(cpu))
+               if (chips[i].id == chip_id)
                        break;
 
        /* Check for Pmax Capping */
@@ -328,17 +342,17 @@ static void powernv_cpufreq_throttle_check(void *data)
                        goto next;
                chips[i].throttled = true;
                if (pmsr_pmax < powernv_pstate_info.nominal)
-                       pr_crit("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n",
-                               cpu, chips[i].id, pmsr_pmax,
-                               powernv_pstate_info.nominal);
-               else
-                       pr_info("CPU %d on Chip %u has Pmax reduced below turbo frequency (%d < %d)\n",
-                               cpu, chips[i].id, pmsr_pmax,
-                               powernv_pstate_info.max);
+                       pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n",
+                                    cpu, chips[i].id, pmsr_pmax,
+                                    powernv_pstate_info.nominal);
+               trace_powernv_throttle(chips[i].id,
+                                     throttle_reason[chips[i].throttle_reason],
+                                     pmsr_pmax);
        } else if (chips[i].throttled) {
                chips[i].throttled = false;
-               pr_info("CPU %d on Chip %u has Pmax restored to %d\n", cpu,
-                       chips[i].id, pmsr_pmax);
+               trace_powernv_throttle(chips[i].id,
+                                     throttle_reason[chips[i].throttle_reason],
+                                     pmsr_pmax);
        }
 
        /* Check if Psafe_mode_active is set in PMSR. */
@@ -356,7 +370,7 @@ next:
 
        if (throttled) {
                pr_info("PMSR = %16lx\n", pmsr);
-               pr_crit("CPU Frequency could be throttled\n");
+               pr_warn("CPU Frequency could be throttled\n");
        }
 }
 
@@ -423,18 +437,19 @@ void powernv_cpufreq_work_fn(struct work_struct *work)
 {
        struct chip *chip = container_of(work, struct chip, throttle);
        unsigned int cpu;
-       cpumask_var_t mask;
+       cpumask_t mask;
 
-       smp_call_function_any(&chip->mask,
+       get_online_cpus();
+       cpumask_and(&mask, &chip->mask, cpu_online_mask);
+       smp_call_function_any(&mask,
                              powernv_cpufreq_throttle_check, NULL, 0);
 
        if (!chip->restore)
-               return;
+               goto out;
 
        chip->restore = false;
-       cpumask_copy(mask, &chip->mask);
-       for_each_cpu_and(cpu, mask, cpu_online_mask) {
-               int index, tcpu;
+       for_each_cpu(cpu, &mask) {
+               int index;
                struct cpufreq_policy policy;
 
                cpufreq_get_policy(&policy, cpu);
@@ -442,20 +457,12 @@ void powernv_cpufreq_work_fn(struct work_struct *work)
                                               policy.cur,
                                               CPUFREQ_RELATION_C, &index);
                powernv_cpufreq_target_index(&policy, index);
-               for_each_cpu(tcpu, policy.cpus)
-                       cpumask_clear_cpu(tcpu, mask);
+               cpumask_andnot(&mask, &mask, policy.cpus);
        }
+out:
+       put_online_cpus();
 }
 
-static char throttle_reason[][30] = {
-                                       "No throttling",
-                                       "Power Cap",
-                                       "Processor Over Temperature",
-                                       "Power Supply Failure",
-                                       "Over Current",
-                                       "OCC Reset"
-                                    };
-
 static int powernv_cpufreq_occ_msg(struct notifier_block *nb,
                                   unsigned long msg_type, void *_msg)
 {
@@ -481,7 +488,7 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb,
                 */
                if (!throttled) {
                        throttled = true;
-                       pr_crit("CPU frequency is throttled for duration\n");
+                       pr_warn("CPU frequency is throttled for duration\n");
                }
 
                break;
@@ -505,23 +512,18 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb,
                        return 0;
                }
 
-               if (omsg.throttle_status &&
+               for (i = 0; i < nr_chips; i++)
+                       if (chips[i].id == omsg.chip)
+                               break;
+
+               if (omsg.throttle_status >= 0 &&
                    omsg.throttle_status <= OCC_MAX_THROTTLE_STATUS)
-                       pr_info("OCC: Chip %u Pmax reduced due to %s\n",
-                               (unsigned int)omsg.chip,
-                               throttle_reason[omsg.throttle_status]);
-               else if (!omsg.throttle_status)
-                       pr_info("OCC: Chip %u %s\n", (unsigned int)omsg.chip,
-                               throttle_reason[omsg.throttle_status]);
-               else
-                       return 0;
+                       chips[i].throttle_reason = omsg.throttle_status;
 
-               for (i = 0; i < nr_chips; i++)
-                       if (chips[i].id == omsg.chip) {
-                               if (!omsg.throttle_status)
-                                       chips[i].restore = true;
-                               schedule_work(&chips[i].throttle);
-                       }
+               if (!omsg.throttle_status)
+                       chips[i].restore = true;
+
+               schedule_work(&chips[i].throttle);
        }
        return 0;
 }
@@ -556,29 +558,54 @@ static int init_chip_info(void)
        unsigned int chip[256];
        unsigned int cpu, i;
        unsigned int prev_chip_id = UINT_MAX;
+       cpumask_t cpu_mask;
+       int ret = -ENOMEM;
+
+       core_to_chip_map = kcalloc(cpu_nr_cores(), sizeof(unsigned int),
+                                  GFP_KERNEL);
+       if (!core_to_chip_map)
+               goto out;
 
-       for_each_possible_cpu(cpu) {
+       cpumask_copy(&cpu_mask, cpu_possible_mask);
+       for_each_cpu(cpu, &cpu_mask) {
                unsigned int id = cpu_to_chip_id(cpu);
 
                if (prev_chip_id != id) {
                        prev_chip_id = id;
                        chip[nr_chips++] = id;
                }
+               core_to_chip_map[cpu_core_index_of_thread(cpu)] = id;
+               cpumask_andnot(&cpu_mask, &cpu_mask, cpu_sibling_mask(cpu));
        }
 
-       chips = kmalloc_array(nr_chips, sizeof(struct chip), GFP_KERNEL);
+       chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL);
        if (!chips)
-               return -ENOMEM;
+               goto free_chip_map;
 
        for (i = 0; i < nr_chips; i++) {
                chips[i].id = chip[i];
-               chips[i].throttled = false;
                cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i]));
                INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn);
-               chips[i].restore = false;
        }
 
        return 0;
+free_chip_map:
+       kfree(core_to_chip_map);
+out:
+       return ret;
+}
+
+static inline void clean_chip_info(void)
+{
+       kfree(chips);
+       kfree(core_to_chip_map);
+}
+
+static inline void unregister_all_notifiers(void)
+{
+       opal_message_notifier_unregister(OPAL_MSG_OCC,
+                                        &powernv_cpufreq_opal_nb);
+       unregister_reboot_notifier(&powernv_cpufreq_reboot_nb);
 }
 
 static int __init powernv_cpufreq_init(void)
@@ -591,28 +618,35 @@ static int __init powernv_cpufreq_init(void)
 
        /* Discover pstates from device tree and init */
        rc = init_powernv_pstates();
-       if (rc) {
-               pr_info("powernv-cpufreq disabled. System does not support PState control\n");
-               return rc;
-       }
+       if (rc)
+               goto out;
 
        /* Populate chip info */
        rc = init_chip_info();
        if (rc)
-               return rc;
+               goto out;
 
        register_reboot_notifier(&powernv_cpufreq_reboot_nb);
        opal_message_notifier_register(OPAL_MSG_OCC, &powernv_cpufreq_opal_nb);
-       return cpufreq_register_driver(&powernv_cpufreq_driver);
+
+       rc = cpufreq_register_driver(&powernv_cpufreq_driver);
+       if (!rc)
+               return 0;
+
+       pr_info("Failed to register the cpufreq driver (%d)\n", rc);
+       unregister_all_notifiers();
+       clean_chip_info();
+out:
+       pr_info("Platform driver disabled. System does not support PState control\n");
+       return rc;
 }
 module_init(powernv_cpufreq_init);
 
 static void __exit powernv_cpufreq_exit(void)
 {
-       unregister_reboot_notifier(&powernv_cpufreq_reboot_nb);
-       opal_message_notifier_unregister(OPAL_MSG_OCC,
-                                        &powernv_cpufreq_opal_nb);
        cpufreq_unregister_driver(&powernv_cpufreq_driver);
+       unregister_all_notifiers();
+       clean_chip_info();
 }
 module_exit(powernv_cpufreq_exit);
 
index 0742b32966739cc3a125acd6f28c7e067dc9cb7b..27fc733cb5b97382b458744432e9c9c348170e84 100644 (file)
@@ -199,8 +199,8 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev);
 static void get_typical_interval(struct menu_device *data)
 {
        int i, divisor;
-       unsigned int max, thresh;
-       uint64_t avg, stddev;
+       unsigned int max, thresh, avg;
+       uint64_t sum, variance;
 
        thresh = UINT_MAX; /* Discard outliers above this value */
 
@@ -208,52 +208,51 @@ again:
 
        /* First calculate the average of past intervals */
        max = 0;
-       avg = 0;
+       sum = 0;
        divisor = 0;
        for (i = 0; i < INTERVALS; i++) {
                unsigned int value = data->intervals[i];
                if (value <= thresh) {
-                       avg += value;
+                       sum += value;
                        divisor++;
                        if (value > max)
                                max = value;
                }
        }
        if (divisor == INTERVALS)
-               avg >>= INTERVAL_SHIFT;
+               avg = sum >> INTERVAL_SHIFT;
        else
-               do_div(avg, divisor);
+               avg = div_u64(sum, divisor);
 
-       /* Then try to determine standard deviation */
-       stddev = 0;
+       /* Then try to determine variance */
+       variance = 0;
        for (i = 0; i < INTERVALS; i++) {
                unsigned int value = data->intervals[i];
                if (value <= thresh) {
-                       int64_t diff = value - avg;
-                       stddev += diff * diff;
+                       int64_t diff = (int64_t)value - avg;
+                       variance += diff * diff;
                }
        }
        if (divisor == INTERVALS)
-               stddev >>= INTERVAL_SHIFT;
+               variance >>= INTERVAL_SHIFT;
        else
-               do_div(stddev, divisor);
+               do_div(variance, divisor);
 
        /*
-        * The typical interval is obtained when standard deviation is small
-        * or standard deviation is small compared to the average interval.
-        *
-        * int_sqrt() formal parameter type is unsigned long. When the
-        * greatest difference to an outlier exceeds ~65 ms * sqrt(divisor)
-        * the resulting squared standard deviation exceeds the input domain
-        * of int_sqrt on platforms where unsigned long is 32 bits in size.
-        * In such case reject the candidate average.
+        * The typical interval is obtained when standard deviation is
+        * small (stddev <= 20 us, variance <= 400 us^2) or standard
+        * deviation is small compared to the average interval (avg >
+        * 6*stddev, avg^2 > 36*variance). The average is smaller than
+        * UINT_MAX aka U32_MAX, so computing its square does not
+        * overflow a u64. We simply reject this candidate average if
+        * the standard deviation is greater than 715 s (which is
+        * rather unlikely).
         *
         * Use this result only if there is no timer to wake us up sooner.
         */
-       if (likely(stddev <= ULONG_MAX)) {
-               stddev = int_sqrt(stddev);
-               if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3))
-                                                       || stddev <= 20) {
+       if (likely(variance <= U64_MAX/36)) {
+               if ((((u64)avg*avg > variance*36) && (divisor * 4 >= INTERVALS * 3))
+                                                       || variance <= 400) {
                        if (data->next_timer_us > avg)
                                data->predicted_us = avg;
                        return;
index 848b93ee930fd8ec204a332755c57b18457bfede..fe9dce0245bf0c7d32b2c8eb3590e7f73651ae6d 100644 (file)
@@ -500,6 +500,8 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
        clk_set_min_rate(tegra->emc_clock, rate);
        clk_set_rate(tegra->emc_clock, 0);
 
+       *freq = rate;
+
        return 0;
 }
 
index 64f5d1bdbb48defdddc4c7ed7ee0c5b988b92e1b..8e304b1befc56385b8fc34d7697a529289d8ae3b 100644 (file)
 #define AT_XDMAC_MAX_CHAN      0x20
 #define AT_XDMAC_MAX_CSIZE     16      /* 16 data */
 #define AT_XDMAC_MAX_DWIDTH    8       /* 64 bits */
+#define AT_XDMAC_RESIDUE_MAX_RETRIES   5
 
 #define AT_XDMAC_DMA_BUSWIDTHS\
        (BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) |\
@@ -1395,8 +1396,8 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
        struct at_xdmac_desc    *desc, *_desc;
        struct list_head        *descs_list;
        enum dma_status         ret;
-       int                     residue;
-       u32                     cur_nda, mask, value;
+       int                     residue, retry;
+       u32                     cur_nda, check_nda, cur_ubc, mask, value;
        u8                      dwidth = 0;
        unsigned long           flags;
 
@@ -1433,7 +1434,42 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                        cpu_relax();
        }
 
+       /*
+        * When processing the residue, we need to read two registers but we
+        * can't do it in an atomic way. AT_XDMAC_CNDA is used to find where
+        * we stand in the descriptor list and AT_XDMAC_CUBC is used
+        * to know how many data are remaining for the current descriptor.
+        * Since the dma channel is not paused to not loose data, between the
+        * AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of
+        * descriptor.
+        * For that reason, after reading AT_XDMAC_CUBC, we check if we are
+        * still using the same descriptor by reading a second time
+        * AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to
+        * read again AT_XDMAC_CUBC.
+        * Memory barriers are used to ensure the read order of the registers.
+        * A max number of retries is set because unlikely it can never ends if
+        * we are transferring a lot of data with small buffers.
+        */
        cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
+       rmb();
+       cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
+       for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
+               rmb();
+               check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
+
+               if (likely(cur_nda == check_nda))
+                       break;
+
+               cur_nda = check_nda;
+               rmb();
+               cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
+       }
+
+       if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) {
+               ret = DMA_ERROR;
+               goto spin_unlock;
+       }
+
        /*
         * Remove size of all microblocks already transferred and the current
         * one. Then add the remaining size to transfer of the current
@@ -1446,7 +1482,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda)
                        break;
        }
-       residue += at_xdmac_chan_read(atchan, AT_XDMAC_CUBC) << dwidth;
+       residue += cur_ubc << dwidth;
 
        dma_set_residue(txstate, residue);
 
index 2209f75fdf05bf29114f0fb3ffedff89f55b43f3..aac85c30c2cf6fc64669841c5b6abb5317df1b94 100644 (file)
@@ -522,6 +522,8 @@ static dma_cookie_t fsldma_run_tx_complete_actions(struct fsldma_chan *chan,
                        chan_dbg(chan, "LD %p callback\n", desc);
                        txd->callback(txd->callback_param);
                }
+
+               dma_descriptor_unmap(txd);
        }
 
        /* Run any dependencies */
index e4f43125e0fbbf5017cd848478eeb01550a87508..f039cfadf17b307c32bd88ef0e4a4a5ac749b590 100644 (file)
@@ -1300,10 +1300,10 @@ static int iop_adma_probe(struct platform_device *pdev)
         * note: writecombine gives slightly better performance, but
         * requires that we explicitly flush the writes
         */
-       adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
-                                                         plat_data->pool_size,
-                                                         &adev->dma_desc_pool,
-                                                         GFP_KERNEL);
+       adev->dma_desc_pool_virt = dma_alloc_wc(&pdev->dev,
+                                               plat_data->pool_size,
+                                               &adev->dma_desc_pool,
+                                               GFP_KERNEL);
        if (!adev->dma_desc_pool_virt) {
                ret = -ENOMEM;
                goto err_free_adev;
index 14091f878f80a5ca7cd0843e70284d890ad49f0c..3922a5d5680604f831308dc02a50b93685a089ce 100644 (file)
@@ -964,8 +964,8 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
         * requires that we explicitly flush the writes
         */
        mv_chan->dma_desc_pool_virt =
-         dma_alloc_writecombine(&pdev->dev, MV_XOR_POOL_SIZE,
-                                &mv_chan->dma_desc_pool, GFP_KERNEL);
+         dma_alloc_wc(&pdev->dev, MV_XOR_POOL_SIZE, &mv_chan->dma_desc_pool,
+                      GFP_KERNEL);
        if (!mv_chan->dma_desc_pool_virt)
                return ERR_PTR(-ENOMEM);
 
index f2a0310ae7718c3c49a6ef5a516a50851e1b0359..debca824bed676f0ecacc9e71476ecc33a477298 100644 (file)
@@ -583,6 +583,8 @@ static void set_updater_desc(struct pxad_desc_sw *sw_desc,
                (PXA_DCMD_LENGTH & sizeof(u32));
        if (flags & DMA_PREP_INTERRUPT)
                updater->dcmd |= PXA_DCMD_ENDIRQEN;
+       if (sw_desc->cyclic)
+               sw_desc->hw_desc[sw_desc->nb_desc - 2]->ddadr = sw_desc->first;
 }
 
 static bool is_desc_completed(struct virt_dma_desc *vd)
@@ -673,6 +675,10 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id)
                dev_dbg(&chan->vc.chan.dev->device,
                        "%s(): checking txd %p[%x]: completed=%d\n",
                        __func__, vd, vd->tx.cookie, is_desc_completed(vd));
+               if (to_pxad_sw_desc(vd)->cyclic) {
+                       vchan_cyclic_callback(vd);
+                       break;
+               }
                if (is_desc_completed(vd)) {
                        list_del(&vd->node);
                        vchan_cookie_complete(vd);
@@ -1080,7 +1086,7 @@ pxad_prep_dma_cyclic(struct dma_chan *dchan,
                return NULL;
 
        pxad_get_config(chan, dir, &dcmd, &dsadr, &dtadr);
-       dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH | period_len);
+       dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH & period_len);
        dev_dbg(&chan->vc.chan.dev->device,
                "%s(): buf_addr=0x%lx len=%zu period=%zu dir=%d flags=%lx\n",
                __func__, (unsigned long)buf_addr, len, period_len, dir, flags);
index 5a250cdc83769f0d4aaff65530c76b705a474e25..d34aef7a101b669994e2a92b88e448437f0bb6f8 100644 (file)
@@ -502,8 +502,8 @@ static int bam_alloc_chan(struct dma_chan *chan)
                return 0;
 
        /* allocate FIFO descriptor space, but only if necessary */
-       bchan->fifo_virt = dma_alloc_writecombine(bdev->dev, BAM_DESC_FIFO_SIZE,
-                               &bchan->fifo_phys, GFP_KERNEL);
+       bchan->fifo_virt = dma_alloc_wc(bdev->dev, BAM_DESC_FIFO_SIZE,
+                                       &bchan->fifo_phys, GFP_KERNEL);
 
        if (!bchan->fifo_virt) {
                dev_err(bdev->dev, "Failed to allocate desc fifo\n");
@@ -538,8 +538,8 @@ static void bam_free_chan(struct dma_chan *chan)
        bam_reset_channel(bchan);
        spin_unlock_irqrestore(&bchan->vc.lock, flags);
 
-       dma_free_writecombine(bdev->dev, BAM_DESC_FIFO_SIZE, bchan->fifo_virt,
-                               bchan->fifo_phys);
+       dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE, bchan->fifo_virt,
+                   bchan->fifo_phys);
        bchan->fifo_virt = NULL;
 
        /* mask irq for pipe/channel */
@@ -1231,9 +1231,9 @@ static int bam_dma_remove(struct platform_device *pdev)
                bam_dma_terminate_all(&bdev->channels[i].vc.chan);
                tasklet_kill(&bdev->channels[i].vc.task);
 
-               dma_free_writecombine(bdev->dev, BAM_DESC_FIFO_SIZE,
-                       bdev->channels[i].fifo_virt,
-                       bdev->channels[i].fifo_phys);
+               dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE,
+                           bdev->channels[i].fifo_virt,
+                           bdev->channels[i].fifo_phys);
        }
 
        tasklet_kill(&bdev->task);
index ef25000a5bc69845aa5234a451f80d27f259eb01..37755e63cc289fccc2746ec127193baa854f2dc0 100644 (file)
@@ -367,14 +367,30 @@ config EDAC_OCTEON_PCI
          Support for error detection and correction on the
          Cavium Octeon family of SOCs.
 
-config EDAC_ALTERA_MC
-       bool "Altera SDRAM Memory Controller EDAC"
+config EDAC_ALTERA
+       bool "Altera SOCFPGA ECC"
        depends on EDAC_MM_EDAC=y && ARCH_SOCFPGA
        help
          Support for error detection and correction on the
-         Altera SDRAM memory controller. Note that the
-         preloader must initialize the SDRAM before loading
-         the kernel.
+         Altera SOCs. This must be selected for SDRAM ECC.
+         Note that the preloader must initialize the SDRAM
+         before loading the kernel.
+
+config EDAC_ALTERA_L2C
+       bool "Altera L2 Cache ECC"
+       depends on EDAC_ALTERA=y
+       select CACHE_L2X0
+       help
+         Support for error detection and correction on the
+         Altera L2 cache Memory for Altera SoCs. This option
+         requires L2 cache so it will force that selection.
+
+config EDAC_ALTERA_OCRAM
+       bool "Altera On-Chip RAM ECC"
+       depends on EDAC_ALTERA=y && SRAM && GENERIC_ALLOCATOR
+       help
+         Support for error detection and correction on the
+         Altera On-Chip RAM Memory for Altera SoCs.
 
 config EDAC_SYNOPSYS
        tristate "Synopsys DDR Memory Controller"
index be163e20fe56870c1bddad7a85c53035423ad4f2..f9e4a3e0e6e915d1b5b6217e76e4f7f52323656c 100644 (file)
@@ -67,6 +67,6 @@ obj-$(CONFIG_EDAC_OCTEON_L2C)         += octeon_edac-l2c.o
 obj-$(CONFIG_EDAC_OCTEON_LMC)          += octeon_edac-lmc.o
 obj-$(CONFIG_EDAC_OCTEON_PCI)          += octeon_edac-pci.o
 
-obj-$(CONFIG_EDAC_ALTERA_MC)           += altera_edac.o
+obj-$(CONFIG_EDAC_ALTERA)              += altera_edac.o
 obj-$(CONFIG_EDAC_SYNOPSYS)            += synopsys_edac.o
 obj-$(CONFIG_EDAC_XGENE)               += xgene_edac.o
index 929640981d8a845793ed4c005da23a7a26c0c32b..63e42098726d5616d7941cbf4c4ab5d9247edf52 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright Altera Corporation (C) 2014-2015. All rights reserved.
+ *  Copyright Altera Corporation (C) 2014-2016. All rights reserved.
  *  Copyright 2011-2012 Calxeda, Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * Adapted from the highbank_mc_edac driver.
  */
 
+#include <asm/cacheflush.h>
 #include <linux/ctype.h>
 #include <linux/edac.h>
+#include <linux/genalloc.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mfd/syscon.h>
@@ -34,6 +36,7 @@
 
 #define EDAC_MOD_STR           "altera_edac"
 #define EDAC_VERSION           "1"
+#define EDAC_DEVICE            "Altera"
 
 static const struct altr_sdram_prv_data c5_data = {
        .ecc_ctrl_offset    = CV_CTLCFG_OFST,
@@ -75,6 +78,31 @@ static const struct altr_sdram_prv_data a10_data = {
        .ue_set_mask        = A10_DIAGINT_TDERRA_MASK,
 };
 
+/************************** EDAC Device Defines **************************/
+
+/* OCRAM ECC Management Group Defines */
+#define ALTR_MAN_GRP_OCRAM_ECC_OFFSET   0x04
+#define ALTR_OCR_ECC_EN                 BIT(0)
+#define ALTR_OCR_ECC_INJS               BIT(1)
+#define ALTR_OCR_ECC_INJD               BIT(2)
+#define ALTR_OCR_ECC_SERR               BIT(3)
+#define ALTR_OCR_ECC_DERR               BIT(4)
+
+/* L2 ECC Management Group Defines */
+#define ALTR_MAN_GRP_L2_ECC_OFFSET      0x00
+#define ALTR_L2_ECC_EN                  BIT(0)
+#define ALTR_L2_ECC_INJS                BIT(1)
+#define ALTR_L2_ECC_INJD                BIT(2)
+
+#define ALTR_UE_TRIGGER_CHAR            'U'   /* Trigger for UE */
+#define ALTR_TRIGGER_READ_WRD_CNT       32    /* Line size x 4 */
+#define ALTR_TRIG_OCRAM_BYTE_SIZE       128   /* Line size x 4 */
+#define ALTR_TRIG_L2C_BYTE_SIZE         4096  /* Full Page */
+
+/*********************** EDAC Memory Controller Functions ****************/
+
+/* The SDRAM controller uses the EDAC Memory Controller framework.       */
+
 static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id)
 {
        struct mem_ctl_info *mci = dev_id;
@@ -504,6 +532,466 @@ static struct platform_driver altr_sdram_edac_driver = {
 
 module_platform_driver(altr_sdram_edac_driver);
 
+/************************* EDAC Parent Probe *************************/
+
+static const struct of_device_id altr_edac_device_of_match[];
+
+static const struct of_device_id altr_edac_of_match[] = {
+       { .compatible = "altr,socfpga-ecc-manager" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, altr_edac_of_match);
+
+static int altr_edac_probe(struct platform_device *pdev)
+{
+       of_platform_populate(pdev->dev.of_node, altr_edac_device_of_match,
+                            NULL, &pdev->dev);
+       return 0;
+}
+
+static struct platform_driver altr_edac_driver = {
+       .probe =  altr_edac_probe,
+       .driver = {
+               .name = "socfpga_ecc_manager",
+               .of_match_table = altr_edac_of_match,
+       },
+};
+module_platform_driver(altr_edac_driver);
+
+/************************* EDAC Device Functions *************************/
+
+/*
+ * EDAC Device Functions (shared between various IPs).
+ * The discrete memories use the EDAC Device framework. The probe
+ * and error handling functions are very similar between memories
+ * so they are shared. The memory allocation and freeing for EDAC
+ * trigger testing are different for each memory.
+ */
+
+const struct edac_device_prv_data ocramecc_data;
+const struct edac_device_prv_data l2ecc_data;
+
+struct edac_device_prv_data {
+       int (*setup)(struct platform_device *pdev, void __iomem *base);
+       int ce_clear_mask;
+       int ue_clear_mask;
+       char dbgfs_name[20];
+       void * (*alloc_mem)(size_t size, void **other);
+       void (*free_mem)(void *p, size_t size, void *other);
+       int ecc_enable_mask;
+       int ce_set_mask;
+       int ue_set_mask;
+       int trig_alloc_sz;
+};
+
+struct altr_edac_device_dev {
+       void __iomem *base;
+       int sb_irq;
+       int db_irq;
+       const struct edac_device_prv_data *data;
+       struct dentry *debugfs_dir;
+       char *edac_dev_name;
+};
+
+static irqreturn_t altr_edac_device_handler(int irq, void *dev_id)
+{
+       irqreturn_t ret_value = IRQ_NONE;
+       struct edac_device_ctl_info *dci = dev_id;
+       struct altr_edac_device_dev *drvdata = dci->pvt_info;
+       const struct edac_device_prv_data *priv = drvdata->data;
+
+       if (irq == drvdata->sb_irq) {
+               if (priv->ce_clear_mask)
+                       writel(priv->ce_clear_mask, drvdata->base);
+               edac_device_handle_ce(dci, 0, 0, drvdata->edac_dev_name);
+               ret_value = IRQ_HANDLED;
+       } else if (irq == drvdata->db_irq) {
+               if (priv->ue_clear_mask)
+                       writel(priv->ue_clear_mask, drvdata->base);
+               edac_device_handle_ue(dci, 0, 0, drvdata->edac_dev_name);
+               panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n");
+               ret_value = IRQ_HANDLED;
+       } else {
+               WARN_ON(1);
+       }
+
+       return ret_value;
+}
+
+static ssize_t altr_edac_device_trig(struct file *file,
+                                    const char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+
+{
+       u32 *ptemp, i, error_mask;
+       int result = 0;
+       u8 trig_type;
+       unsigned long flags;
+       struct edac_device_ctl_info *edac_dci = file->private_data;
+       struct altr_edac_device_dev *drvdata = edac_dci->pvt_info;
+       const struct edac_device_prv_data *priv = drvdata->data;
+       void *generic_ptr = edac_dci->dev;
+
+       if (!user_buf || get_user(trig_type, user_buf))
+               return -EFAULT;
+
+       if (!priv->alloc_mem)
+               return -ENOMEM;
+
+       /*
+        * Note that generic_ptr is initialized to the device * but in
+        * some alloc_functions, this is overridden and returns data.
+        */
+       ptemp = priv->alloc_mem(priv->trig_alloc_sz, &generic_ptr);
+       if (!ptemp) {
+               edac_printk(KERN_ERR, EDAC_DEVICE,
+                           "Inject: Buffer Allocation error\n");
+               return -ENOMEM;
+       }
+
+       if (trig_type == ALTR_UE_TRIGGER_CHAR)
+               error_mask = priv->ue_set_mask;
+       else
+               error_mask = priv->ce_set_mask;
+
+       edac_printk(KERN_ALERT, EDAC_DEVICE,
+                   "Trigger Error Mask (0x%X)\n", error_mask);
+
+       local_irq_save(flags);
+       /* write ECC corrupted data out. */
+       for (i = 0; i < (priv->trig_alloc_sz / sizeof(*ptemp)); i++) {
+               /* Read data so we're in the correct state */
+               rmb();
+               if (ACCESS_ONCE(ptemp[i]))
+                       result = -1;
+               /* Toggle Error bit (it is latched), leave ECC enabled */
+               writel(error_mask, drvdata->base);
+               writel(priv->ecc_enable_mask, drvdata->base);
+               ptemp[i] = i;
+       }
+       /* Ensure it has been written out */
+       wmb();
+       local_irq_restore(flags);
+
+       if (result)
+               edac_printk(KERN_ERR, EDAC_DEVICE, "Mem Not Cleared\n");
+
+       /* Read out written data. ECC error caused here */
+       for (i = 0; i < ALTR_TRIGGER_READ_WRD_CNT; i++)
+               if (ACCESS_ONCE(ptemp[i]) != i)
+                       edac_printk(KERN_ERR, EDAC_DEVICE,
+                                   "Read doesn't match written data\n");
+
+       if (priv->free_mem)
+               priv->free_mem(ptemp, priv->trig_alloc_sz, generic_ptr);
+
+       return count;
+}
+
+static const struct file_operations altr_edac_device_inject_fops = {
+       .open = simple_open,
+       .write = altr_edac_device_trig,
+       .llseek = generic_file_llseek,
+};
+
+static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci,
+                                     const struct edac_device_prv_data *priv)
+{
+       struct altr_edac_device_dev *drvdata = edac_dci->pvt_info;
+
+       if (!IS_ENABLED(CONFIG_EDAC_DEBUG))
+               return;
+
+       drvdata->debugfs_dir = edac_debugfs_create_dir(drvdata->edac_dev_name);
+       if (!drvdata->debugfs_dir)
+               return;
+
+       if (!edac_debugfs_create_file(priv->dbgfs_name, S_IWUSR,
+                                     drvdata->debugfs_dir, edac_dci,
+                                     &altr_edac_device_inject_fops))
+               debugfs_remove_recursive(drvdata->debugfs_dir);
+}
+
+static const struct of_device_id altr_edac_device_of_match[] = {
+#ifdef CONFIG_EDAC_ALTERA_L2C
+       { .compatible = "altr,socfpga-l2-ecc", .data = (void *)&l2ecc_data },
+#endif
+#ifdef CONFIG_EDAC_ALTERA_OCRAM
+       { .compatible = "altr,socfpga-ocram-ecc",
+         .data = (void *)&ocramecc_data },
+#endif
+       {},
+};
+MODULE_DEVICE_TABLE(of, altr_edac_device_of_match);
+
+/*
+ * altr_edac_device_probe()
+ *     This is a generic EDAC device driver that will support
+ *     various Altera memory devices such as the L2 cache ECC and
+ *     OCRAM ECC as well as the memories for other peripherals.
+ *     Module specific initialization is done by passing the
+ *     function index in the device tree.
+ */
+static int altr_edac_device_probe(struct platform_device *pdev)
+{
+       struct edac_device_ctl_info *dci;
+       struct altr_edac_device_dev *drvdata;
+       struct resource *r;
+       int res = 0;
+       struct device_node *np = pdev->dev.of_node;
+       char *ecc_name = (char *)np->name;
+       static int dev_instance;
+
+       if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
+               edac_printk(KERN_ERR, EDAC_DEVICE,
+                           "Unable to open devm\n");
+               return -ENOMEM;
+       }
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!r) {
+               edac_printk(KERN_ERR, EDAC_DEVICE,
+                           "Unable to get mem resource\n");
+               res = -ENODEV;
+               goto fail;
+       }
+
+       if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r),
+                                    dev_name(&pdev->dev))) {
+               edac_printk(KERN_ERR, EDAC_DEVICE,
+                           "%s:Error requesting mem region\n", ecc_name);
+               res = -EBUSY;
+               goto fail;
+       }
+
+       dci = edac_device_alloc_ctl_info(sizeof(*drvdata), ecc_name,
+                                        1, ecc_name, 1, 0, NULL, 0,
+                                        dev_instance++);
+
+       if (!dci) {
+               edac_printk(KERN_ERR, EDAC_DEVICE,
+                           "%s: Unable to allocate EDAC device\n", ecc_name);
+               res = -ENOMEM;
+               goto fail;
+       }
+
+       drvdata = dci->pvt_info;
+       dci->dev = &pdev->dev;
+       platform_set_drvdata(pdev, dci);
+       drvdata->edac_dev_name = ecc_name;
+
+       drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+       if (!drvdata->base)
+               goto fail1;
+
+       /* Get driver specific data for this EDAC device */
+       drvdata->data = of_match_node(altr_edac_device_of_match, np)->data;
+
+       /* Check specific dependencies for the module */
+       if (drvdata->data->setup) {
+               res = drvdata->data->setup(pdev, drvdata->base);
+               if (res)
+                       goto fail1;
+       }
+
+       drvdata->sb_irq = platform_get_irq(pdev, 0);
+       res = devm_request_irq(&pdev->dev, drvdata->sb_irq,
+                              altr_edac_device_handler,
+                              0, dev_name(&pdev->dev), dci);
+       if (res)
+               goto fail1;
+
+       drvdata->db_irq = platform_get_irq(pdev, 1);
+       res = devm_request_irq(&pdev->dev, drvdata->db_irq,
+                              altr_edac_device_handler,
+                              0, dev_name(&pdev->dev), dci);
+       if (res)
+               goto fail1;
+
+       dci->mod_name = "Altera ECC Manager";
+       dci->dev_name = drvdata->edac_dev_name;
+
+       res = edac_device_add_device(dci);
+       if (res)
+               goto fail1;
+
+       altr_create_edacdev_dbgfs(dci, drvdata->data);
+
+       devres_close_group(&pdev->dev, NULL);
+
+       return 0;
+
+fail1:
+       edac_device_free_ctl_info(dci);
+fail:
+       devres_release_group(&pdev->dev, NULL);
+       edac_printk(KERN_ERR, EDAC_DEVICE,
+                   "%s:Error setting up EDAC device: %d\n", ecc_name, res);
+
+       return res;
+}
+
+static int altr_edac_device_remove(struct platform_device *pdev)
+{
+       struct edac_device_ctl_info *dci = platform_get_drvdata(pdev);
+       struct altr_edac_device_dev *drvdata = dci->pvt_info;
+
+       debugfs_remove_recursive(drvdata->debugfs_dir);
+       edac_device_del_device(&pdev->dev);
+       edac_device_free_ctl_info(dci);
+
+       return 0;
+}
+
+static struct platform_driver altr_edac_device_driver = {
+       .probe =  altr_edac_device_probe,
+       .remove = altr_edac_device_remove,
+       .driver = {
+               .name = "altr_edac_device",
+               .of_match_table = altr_edac_device_of_match,
+       },
+};
+module_platform_driver(altr_edac_device_driver);
+
+/*********************** OCRAM EDAC Device Functions *********************/
+
+#ifdef CONFIG_EDAC_ALTERA_OCRAM
+
+static void *ocram_alloc_mem(size_t size, void **other)
+{
+       struct device_node *np;
+       struct gen_pool *gp;
+       void *sram_addr;
+
+       np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc");
+       if (!np)
+               return NULL;
+
+       gp = of_gen_pool_get(np, "iram", 0);
+       of_node_put(np);
+       if (!gp)
+               return NULL;
+
+       sram_addr = (void *)gen_pool_alloc(gp, size);
+       if (!sram_addr)
+               return NULL;
+
+       memset(sram_addr, 0, size);
+       /* Ensure data is written out */
+       wmb();
+
+       /* Remember this handle for freeing  later */
+       *other = gp;
+
+       return sram_addr;
+}
+
+static void ocram_free_mem(void *p, size_t size, void *other)
+{
+       gen_pool_free((struct gen_pool *)other, (u32)p, size);
+}
+
+/*
+ * altr_ocram_check_deps()
+ *     Test for OCRAM cache ECC dependencies upon entry because
+ *     platform specific startup should have initialized the
+ *     On-Chip RAM memory and enabled the ECC.
+ *     Can't turn on ECC here because accessing un-initialized
+ *     memory will cause CE/UE errors possibly causing an ABORT.
+ */
+static int altr_ocram_check_deps(struct platform_device *pdev,
+                                void __iomem *base)
+{
+       if (readl(base) & ALTR_OCR_ECC_EN)
+               return 0;
+
+       edac_printk(KERN_ERR, EDAC_DEVICE,
+                   "OCRAM: No ECC present or ECC disabled.\n");
+       return -ENODEV;
+}
+
+const struct edac_device_prv_data ocramecc_data = {
+       .setup = altr_ocram_check_deps,
+       .ce_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_SERR),
+       .ue_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_DERR),
+       .dbgfs_name = "altr_ocram_trigger",
+       .alloc_mem = ocram_alloc_mem,
+       .free_mem = ocram_free_mem,
+       .ecc_enable_mask = ALTR_OCR_ECC_EN,
+       .ce_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJS),
+       .ue_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJD),
+       .trig_alloc_sz = ALTR_TRIG_OCRAM_BYTE_SIZE,
+};
+
+#endif /* CONFIG_EDAC_ALTERA_OCRAM */
+
+/********************* L2 Cache EDAC Device Functions ********************/
+
+#ifdef CONFIG_EDAC_ALTERA_L2C
+
+static void *l2_alloc_mem(size_t size, void **other)
+{
+       struct device *dev = *other;
+       void *ptemp = devm_kzalloc(dev, size, GFP_KERNEL);
+
+       if (!ptemp)
+               return NULL;
+
+       /* Make sure everything is written out */
+       wmb();
+
+       /*
+        * Clean all cache levels up to LoC (includes L2)
+        * This ensures the corrupted data is written into
+        * L2 cache for readback test (which causes ECC error).
+        */
+       flush_cache_all();
+
+       return ptemp;
+}
+
+static void l2_free_mem(void *p, size_t size, void *other)
+{
+       struct device *dev = other;
+
+       if (dev && p)
+               devm_kfree(dev, p);
+}
+
+/*
+ * altr_l2_check_deps()
+ *     Test for L2 cache ECC dependencies upon entry because
+ *     platform specific startup should have initialized the L2
+ *     memory and enabled the ECC.
+ *     Bail if ECC is not enabled.
+ *     Note that L2 Cache Enable is forced at build time.
+ */
+static int altr_l2_check_deps(struct platform_device *pdev,
+                             void __iomem *base)
+{
+       if (readl(base) & ALTR_L2_ECC_EN)
+               return 0;
+
+       edac_printk(KERN_ERR, EDAC_DEVICE,
+                   "L2: No ECC present, or ECC disabled\n");
+       return -ENODEV;
+}
+
+const struct edac_device_prv_data l2ecc_data = {
+       .setup = altr_l2_check_deps,
+       .ce_clear_mask = 0,
+       .ue_clear_mask = 0,
+       .dbgfs_name = "altr_l2_trigger",
+       .alloc_mem = l2_alloc_mem,
+       .free_mem = l2_free_mem,
+       .ecc_enable_mask = ALTR_L2_ECC_EN,
+       .ce_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJS),
+       .ue_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJD),
+       .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE,
+};
+
+#endif /* CONFIG_EDAC_ALTERA_L2C */
+
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Thor Thayer");
-MODULE_DESCRIPTION("EDAC Driver for Altera SDRAM Controller");
+MODULE_DESCRIPTION("EDAC Driver for Altera Memories");
index 9eee13ef83a560fd0c54153c61bc01a77cd3eb7f..d87a47547ba59933d719d39cf1fe1460df2eeb55 100644 (file)
@@ -1452,7 +1452,7 @@ static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range,
        u64 chan_off;
        u64 dram_base           = get_dram_base(pvt, range);
        u64 hole_off            = f10_dhar_offset(pvt);
-       u64 dct_sel_base_off    = (pvt->dct_sel_hi & 0xFFFFFC00) << 16;
+       u64 dct_sel_base_off    = (u64)(pvt->dct_sel_hi & 0xFFFFFC00) << 16;
 
        if (hi_rng) {
                /*
index 54d2f668cb0ae09cccaf559fb199e18dda9b95bc..92dbb7e2320c78fe8cfc69fa80078de5b7b7f682 100644 (file)
@@ -53,7 +53,7 @@ int __init edac_debugfs_init(void)
 
 void edac_debugfs_exit(void)
 {
-       debugfs_remove(edac_debugfs);
+       debugfs_remove_recursive(edac_debugfs);
 }
 
 int edac_create_debugfs_nodes(struct mem_ctl_info *mci)
index 8adfc167c2e38e7de64c0a08224a803ad737ae7a..1472f48c8ac6109677f28da6d1067c11e3e16fa4 100644 (file)
@@ -535,59 +535,20 @@ static void edac_mc_workq_function(struct work_struct *work_req)
 
        mutex_lock(&mem_ctls_mutex);
 
-       /* if this control struct has movd to offline state, we are done */
-       if (mci->op_state == OP_OFFLINE) {
+       if (mci->op_state != OP_RUNNING_POLL) {
                mutex_unlock(&mem_ctls_mutex);
                return;
        }
 
-       /* Only poll controllers that are running polled and have a check */
-       if (edac_mc_assert_error_check_and_clear() && (mci->edac_check != NULL))
+       if (edac_mc_assert_error_check_and_clear())
                mci->edac_check(mci);
 
        mutex_unlock(&mem_ctls_mutex);
 
-       /* Reschedule */
+       /* Queue ourselves again. */
        edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
 }
 
-/*
- * edac_mc_workq_setup
- *     initialize a workq item for this mci
- *     passing in the new delay period in msec
- *
- *     locking model:
- *
- *             called with the mem_ctls_mutex held
- */
-static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
-{
-       edac_dbg(0, "\n");
-
-       /* if this instance is not in the POLL state, then simply return */
-       if (mci->op_state != OP_RUNNING_POLL)
-               return;
-
-       INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
-
-       edac_queue_work(&mci->work, msecs_to_jiffies(msec));
-}
-
-/*
- * edac_mc_workq_teardown
- *     stop the workq processing on this mci
- *
- *     locking model:
- *
- *             called WITHOUT lock held
- */
-static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
-{
-       mci->op_state = OP_OFFLINE;
-
-       edac_stop_work(&mci->work);
-}
-
 /*
  * edac_mc_reset_delay_period(unsigned long value)
  *
@@ -771,12 +732,12 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
                goto fail1;
        }
 
-       /* If there IS a check routine, then we are running POLLED */
-       if (mci->edac_check != NULL) {
-               /* This instance is NOW RUNNING */
+       if (mci->edac_check) {
                mci->op_state = OP_RUNNING_POLL;
 
-               edac_mc_workq_setup(mci, edac_mc_get_poll_msec());
+               INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
+               edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
+
        } else {
                mci->op_state = OP_RUNNING_INTERRUPT;
        }
@@ -823,15 +784,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
                return NULL;
        }
 
+       /* mark MCI offline: */
+       mci->op_state = OP_OFFLINE;
+
        if (!del_mc_from_global_list(mci))
                edac_mc_owner = NULL;
-       mutex_unlock(&mem_ctls_mutex);
 
-       /* flush workq processes */
-       edac_mc_workq_teardown(mci);
+       mutex_unlock(&mem_ctls_mutex);
 
-       /* marking MCI offline */
-       mci->op_state = OP_OFFLINE;
+       if (mci->edac_check)
+               edac_stop_work(&mci->work);
 
        /* remove from sysfs */
        edac_remove_sysfs_mci_device(mci);
index 99685388d3fb5a1a8c6f52f5fbb675a61fa4a065..8f2f2899a7a2e06070689a535a1eb54171fd0ef7 100644 (file)
@@ -195,55 +195,24 @@ static void edac_pci_workq_function(struct work_struct *work_req)
 
        mutex_lock(&edac_pci_ctls_mutex);
 
-       if (pci->op_state == OP_RUNNING_POLL) {
-               /* we might be in POLL mode, but there may NOT be a poll func
-                */
-               if ((pci->edac_check != NULL) && edac_pci_get_check_errors())
-                       pci->edac_check(pci);
-
-               /* if we are on a one second period, then use round */
-               msec = edac_pci_get_poll_msec();
-               if (msec == 1000)
-                       delay = round_jiffies_relative(msecs_to_jiffies(msec));
-               else
-                       delay = msecs_to_jiffies(msec);
-
-               /* Reschedule only if we are in POLL mode */
-               edac_queue_work(&pci->work, delay);
+       if (pci->op_state != OP_RUNNING_POLL) {
+               mutex_unlock(&edac_pci_ctls_mutex);
+               return;
        }
 
-       mutex_unlock(&edac_pci_ctls_mutex);
-}
-
-/*
- * edac_pci_workq_setup()
- *     initialize a workq item for this edac_pci instance
- *     passing in the new delay period in msec
- *
- *     locking model:
- *             called when 'edac_pci_ctls_mutex' is locked
- */
-static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
-                                unsigned int msec)
-{
-       edac_dbg(0, "\n");
+       if (edac_pci_get_check_errors())
+               pci->edac_check(pci);
 
-       INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
+       /* if we are on a one second period, then use round */
+       msec = edac_pci_get_poll_msec();
+       if (msec == 1000)
+               delay = round_jiffies_relative(msecs_to_jiffies(msec));
+       else
+               delay = msecs_to_jiffies(msec);
 
-       edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec()));
-}
+       edac_queue_work(&pci->work, delay);
 
-/*
- * edac_pci_workq_teardown()
- *     stop the workq processing on this edac_pci instance
- */
-static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
-{
-       edac_dbg(0, "\n");
-
-       pci->op_state = OP_OFFLINE;
-
-       edac_stop_work(&pci->work);
+       mutex_unlock(&edac_pci_ctls_mutex);
 }
 
 /*
@@ -289,10 +258,12 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
                goto fail1;
        }
 
-       if (pci->edac_check != NULL) {
+       if (pci->edac_check) {
                pci->op_state = OP_RUNNING_POLL;
 
-               edac_pci_workq_setup(pci, 1000);
+               INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
+               edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec()));
+
        } else {
                pci->op_state = OP_RUNNING_INTERRUPT;
        }
@@ -350,8 +321,8 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
 
        mutex_unlock(&edac_pci_ctls_mutex);
 
-       /* stop the workq timer */
-       edac_pci_workq_teardown(pci);
+       if (pci->edac_check)
+               edac_stop_work(&pci->work);
 
        edac_printk(KERN_INFO, EDAC_PCI,
                "Removed device %d for %s %s: DEV %s\n",
index e3a945ce374b8318526102852b28535948284ae7..49768c08ac0734345007a1faaae7eef70cd34f60 100644 (file)
@@ -147,6 +147,135 @@ static const char * const mc6_mce_desc[] = {
        "Status Register File",
 };
 
+/* Scalable MCA error strings */
+static const char * const f17h_ls_mce_desc[] = {
+       "Load queue parity",
+       "Store queue parity",
+       "Miss address buffer payload parity",
+       "L1 TLB parity",
+       "",                                             /* reserved */
+       "DC tag error type 6",
+       "DC tag error type 1",
+       "Internal error type 1",
+       "Internal error type 2",
+       "Sys Read data error thread 0",
+       "Sys read data error thread 1",
+       "DC tag error type 2",
+       "DC data error type 1 (poison comsumption)",
+       "DC data error type 2",
+       "DC data error type 3",
+       "DC tag error type 4",
+       "L2 TLB parity",
+       "PDC parity error",
+       "DC tag error type 3",
+       "DC tag error type 5",
+       "L2 fill data error",
+};
+
+static const char * const f17h_if_mce_desc[] = {
+       "microtag probe port parity error",
+       "IC microtag or full tag multi-hit error",
+       "IC full tag parity",
+       "IC data array parity",
+       "Decoupling queue phys addr parity error",
+       "L0 ITLB parity error",
+       "L1 ITLB parity error",
+       "L2 ITLB parity error",
+       "BPQ snoop parity on Thread 0",
+       "BPQ snoop parity on Thread 1",
+       "L1 BTB multi-match error",
+       "L2 BTB multi-match error",
+};
+
+static const char * const f17h_l2_mce_desc[] = {
+       "L2M tag multi-way-hit error",
+       "L2M tag ECC error",
+       "L2M data ECC error",
+       "HW assert",
+};
+
+static const char * const f17h_de_mce_desc[] = {
+       "uop cache tag parity error",
+       "uop cache data parity error",
+       "Insn buffer parity error",
+       "Insn dispatch queue parity error",
+       "Fetch address FIFO parity",
+       "Patch RAM data parity",
+       "Patch RAM sequencer parity",
+       "uop buffer parity"
+};
+
+static const char * const f17h_ex_mce_desc[] = {
+       "Watchdog timeout error",
+       "Phy register file parity",
+       "Flag register file parity",
+       "Immediate displacement register file parity",
+       "Address generator payload parity",
+       "EX payload parity",
+       "Checkpoint queue parity",
+       "Retire dispatch queue parity",
+};
+
+static const char * const f17h_fp_mce_desc[] = {
+       "Physical register file parity",
+       "Freelist parity error",
+       "Schedule queue parity",
+       "NSQ parity error",
+       "Retire queue parity",
+       "Status register file parity",
+};
+
+static const char * const f17h_l3_mce_desc[] = {
+       "Shadow tag macro ECC error",
+       "Shadow tag macro multi-way-hit error",
+       "L3M tag ECC error",
+       "L3M tag multi-way-hit error",
+       "L3M data ECC error",
+       "XI parity, L3 fill done channel error",
+       "L3 victim queue parity",
+       "L3 HW assert",
+};
+
+static const char * const f17h_cs_mce_desc[] = {
+       "Illegal request from transport layer",
+       "Address violation",
+       "Security violation",
+       "Illegal response from transport layer",
+       "Unexpected response",
+       "Parity error on incoming request or probe response data",
+       "Parity error on incoming read response data",
+       "Atomic request parity",
+       "ECC error on probe filter access",
+};
+
+static const char * const f17h_pie_mce_desc[] = {
+       "HW assert",
+       "Internal PIE register security violation",
+       "Error on GMI link",
+       "Poison data written to internal PIE register",
+};
+
+static const char * const f17h_umc_mce_desc[] = {
+       "DRAM ECC error",
+       "Data poison error on DRAM",
+       "SDP parity error",
+       "Advanced peripheral bus error",
+       "Command/address parity error",
+       "Write data CRC error",
+};
+
+static const char * const f17h_pb_mce_desc[] = {
+       "Parameter Block RAM ECC error",
+};
+
+static const char * const f17h_psp_mce_desc[] = {
+       "PSP RAM ECC or parity error",
+};
+
+static const char * const f17h_smu_mce_desc[] = {
+       "SMU RAM ECC or parity error",
+};
+
 static bool f12h_mc0_mce(u16 ec, u8 xec)
 {
        bool ret = false;
@@ -691,6 +820,177 @@ static void decode_mc6_mce(struct mce *m)
        pr_emerg(HW_ERR "Corrupted MC6 MCE info?\n");
 }
 
+static void decode_f17h_core_errors(const char *ip_name, u8 xec,
+                                  unsigned int mca_type)
+{
+       const char * const *error_desc_array;
+       size_t len;
+
+       pr_emerg(HW_ERR "%s Error: ", ip_name);
+
+       switch (mca_type) {
+       case SMCA_LS:
+               error_desc_array = f17h_ls_mce_desc;
+               len = ARRAY_SIZE(f17h_ls_mce_desc) - 1;
+
+               if (xec == 0x4) {
+                       pr_cont("Unrecognized LS MCA error code.\n");
+                       return;
+               }
+               break;
+
+       case SMCA_IF:
+               error_desc_array = f17h_if_mce_desc;
+               len = ARRAY_SIZE(f17h_if_mce_desc) - 1;
+               break;
+
+       case SMCA_L2_CACHE:
+               error_desc_array = f17h_l2_mce_desc;
+               len = ARRAY_SIZE(f17h_l2_mce_desc) - 1;
+               break;
+
+       case SMCA_DE:
+               error_desc_array = f17h_de_mce_desc;
+               len = ARRAY_SIZE(f17h_de_mce_desc) - 1;
+               break;
+
+       case SMCA_EX:
+               error_desc_array = f17h_ex_mce_desc;
+               len = ARRAY_SIZE(f17h_ex_mce_desc) - 1;
+               break;
+
+       case SMCA_FP:
+               error_desc_array = f17h_fp_mce_desc;
+               len = ARRAY_SIZE(f17h_fp_mce_desc) - 1;
+               break;
+
+       case SMCA_L3_CACHE:
+               error_desc_array = f17h_l3_mce_desc;
+               len = ARRAY_SIZE(f17h_l3_mce_desc) - 1;
+               break;
+
+       default:
+               pr_cont("Corrupted MCA core error info.\n");
+               return;
+       }
+
+       if (xec > len) {
+               pr_cont("Unrecognized %s MCA bank error code.\n",
+                        amd_core_mcablock_names[mca_type]);
+               return;
+       }
+
+       pr_cont("%s.\n", error_desc_array[xec]);
+}
+
+static void decode_df_errors(u8 xec, unsigned int mca_type)
+{
+       const char * const *error_desc_array;
+       size_t len;
+
+       pr_emerg(HW_ERR "Data Fabric Error: ");
+
+       switch (mca_type) {
+       case  SMCA_CS:
+               error_desc_array = f17h_cs_mce_desc;
+               len = ARRAY_SIZE(f17h_cs_mce_desc) - 1;
+               break;
+
+       case SMCA_PIE:
+               error_desc_array = f17h_pie_mce_desc;
+               len = ARRAY_SIZE(f17h_pie_mce_desc) - 1;
+               break;
+
+       default:
+               pr_cont("Corrupted MCA Data Fabric info.\n");
+               return;
+       }
+
+       if (xec > len) {
+               pr_cont("Unrecognized %s MCA bank error code.\n",
+                        amd_df_mcablock_names[mca_type]);
+               return;
+       }
+
+       pr_cont("%s.\n", error_desc_array[xec]);
+}
+
+/* Decode errors according to Scalable MCA specification */
+static void decode_smca_errors(struct mce *m)
+{
+       u32 addr = MSR_AMD64_SMCA_MCx_IPID(m->bank);
+       unsigned int hwid, mca_type, i;
+       u8 xec = XEC(m->status, xec_mask);
+       const char * const *error_desc_array;
+       const char *ip_name;
+       u32 low, high;
+       size_t len;
+
+       if (rdmsr_safe(addr, &low, &high)) {
+               pr_emerg("Invalid IP block specified, error information is unreliable.\n");
+               return;
+       }
+
+       hwid = high & MCI_IPID_HWID;
+       mca_type = (high & MCI_IPID_MCATYPE) >> 16;
+
+       pr_emerg(HW_ERR "MC%d IPID value: 0x%08x%08x\n", m->bank, high, low);
+
+       /*
+        * Based on hwid and mca_type values, decode errors from respective IPs.
+        * Note: mca_type values make sense only in the context of an hwid.
+        */
+       for (i = 0; i < ARRAY_SIZE(amd_hwids); i++)
+               if (amd_hwids[i].hwid == hwid)
+                       break;
+
+       switch (i) {
+       case SMCA_F17H_CORE:
+               ip_name = (mca_type == SMCA_L3_CACHE) ?
+                         "L3 Cache" : "F17h Core";
+               return decode_f17h_core_errors(ip_name, xec, mca_type);
+               break;
+
+       case SMCA_DF:
+               return decode_df_errors(xec, mca_type);
+               break;
+
+       case SMCA_UMC:
+               error_desc_array = f17h_umc_mce_desc;
+               len = ARRAY_SIZE(f17h_umc_mce_desc) - 1;
+               break;
+
+       case SMCA_PB:
+               error_desc_array = f17h_pb_mce_desc;
+               len = ARRAY_SIZE(f17h_pb_mce_desc) - 1;
+               break;
+
+       case SMCA_PSP:
+               error_desc_array = f17h_psp_mce_desc;
+               len = ARRAY_SIZE(f17h_psp_mce_desc) - 1;
+               break;
+
+       case SMCA_SMU:
+               error_desc_array = f17h_smu_mce_desc;
+               len = ARRAY_SIZE(f17h_smu_mce_desc) - 1;
+               break;
+
+       default:
+               pr_emerg(HW_ERR "HWID:%d does not match any existing IPs.\n", hwid);
+               return;
+       }
+
+       ip_name = amd_hwids[i].name;
+       pr_emerg(HW_ERR "%s Error: ", ip_name);
+
+       if (xec > len) {
+               pr_cont("Unrecognized %s MCA bank error code.\n", ip_name);
+               return;
+       }
+
+       pr_cont("%s.\n", error_desc_array[xec]);
+}
+
 static inline void amd_decode_err_code(u16 ec)
 {
        if (INT_ERROR(ec)) {
@@ -752,6 +1052,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
        struct mce *m = (struct mce *)data;
        struct cpuinfo_x86 *c = &cpu_data(m->extcpu);
        int ecc;
+       u32 ebx = cpuid_ebx(0x80000007);
 
        if (amd_filter_mce(m))
                return NOTIFY_STOP;
@@ -769,11 +1070,20 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
                ((m->status & MCI_STATUS_PCC)   ? "PCC"   : "-"),
                ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-"));
 
-       if (c->x86 == 0x15 || c->x86 == 0x16)
+       if (c->x86 >= 0x15)
                pr_cont("|%s|%s",
                        ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
                        ((m->status & MCI_STATUS_POISON)   ? "Poison"   : "-"));
 
+       if (!!(ebx & BIT(3))) {
+               u32 low, high;
+               u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
+
+               if (!rdmsr_safe(addr, &low, &high) &&
+                   (low & MCI_CONFIG_MCAX))
+                       pr_cont("|%s", ((m->status & MCI_STATUS_TCC) ? "TCC" : "-"));
+       }
+
        /* do the two bits[14:13] together */
        ecc = (m->status >> 45) & 0x3;
        if (ecc)
@@ -784,6 +1094,11 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data)
        if (m->status & MCI_STATUS_ADDRV)
                pr_emerg(HW_ERR "MC%d Error Address: 0x%016llx\n", m->bank, m->addr);
 
+       if (!!(ebx & BIT(3))) {
+               decode_smca_errors(m);
+               goto err_code;
+       }
+
        if (!fam_ops)
                goto err_code;
 
@@ -834,6 +1149,7 @@ static struct notifier_block amd_mce_dec_nb = {
 static int __init mce_amd_init(void)
 {
        struct cpuinfo_x86 *c = &boot_cpu_data;
+       u32 ebx;
 
        if (c->x86_vendor != X86_VENDOR_AMD)
                return -ENODEV;
@@ -888,10 +1204,18 @@ static int __init mce_amd_init(void)
                fam_ops->mc2_mce = f16h_mc2_mce;
                break;
 
+       case 0x17:
+               ebx = cpuid_ebx(0x80000007);
+               xec_mask = 0x3f;
+               if (!(ebx & BIT(3))) {
+                       printk(KERN_WARNING "Decoding supported only on Scalable MCA processors.\n");
+                       goto err_out;
+               }
+               break;
+
        default:
                printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
-               kfree(fam_ops);
-               fam_ops = NULL;
+               goto err_out;
        }
 
        pr_info("MCE: In-kernel MCE decoding enabled.\n");
@@ -899,6 +1223,11 @@ static int __init mce_amd_init(void)
        mce_register_decode_chain(&amd_mce_dec_nb);
 
        return 0;
+
+err_out:
+       kfree(fam_ops);
+       fam_ops = NULL;
+       return -EINVAL;
 }
 early_initcall(mce_amd_init);
 
index b7139c160bafdaf71a4e3a2d45a00b5e67e6cc7f..ca63d0da8889d71db2499b46323783846cf66009 100644 (file)
@@ -1244,7 +1244,7 @@ static struct platform_driver * const drivers[] = {
 static int __init mpc85xx_mc_init(void)
 {
        int res = 0;
-       u32 pvr = 0;
+       u32 __maybe_unused pvr = 0;
 
        printk(KERN_INFO "Freescale(R) MPC85xx EDAC driver, "
               "(C) 2006 Montavista Software\n");
index e438ee5b433f3f498cba20df890730a3fc77220c..93f0d4120289fa92d01a6873fac6d2efd37337e7 100644 (file)
@@ -1574,7 +1574,7 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes)
                                for (cha = 0; cha < KNL_MAX_CHAS; cha++) {
                                        if (knl_get_mc_route(target,
                                                mc_route_reg[cha]) == channel
-                                               && participants[channel]) {
+                                               && !participants[channel]) {
                                                participant_count++;
                                                participants[channel] = 1;
                                                break;
@@ -1839,8 +1839,8 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
                         n_tads, gb, (mb*1000)/1024,
                         ((u64)tmp_mb) << 20L,
-                        (u32)TAD_SOCK(reg),
-                        (u32)TAD_CH(reg),
+                        (u32)(1 << TAD_SOCK(reg)),
+                        (u32)TAD_CH(reg) + 1,
                         (u32)TAD_TGT0(reg),
                         (u32)TAD_TGT1(reg),
                         (u32)TAD_TGT2(reg),
@@ -2118,7 +2118,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        }
 
        ch_way = TAD_CH(reg) + 1;
-       sck_way = TAD_SOCK(reg) + 1;
+       sck_way = 1 << TAD_SOCK(reg);
 
        if (ch_way == 3)
                idx = addr >> 6;
@@ -2175,7 +2175,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
                 n_tads,
                 addr,
                 limit,
-                (u32)TAD_SOCK(reg),
+                sck_way,
                 ch_way,
                 offset,
                 idx,
@@ -2190,18 +2190,12 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
                        offset, addr);
                return -EINVAL;
        }
-       addr -= offset;
-       /* Store the low bits [0:6] of the addr */
-       ch_addr = addr & 0x7f;
-       /* Remove socket wayness and remove 6 bits */
-       addr >>= 6;
-       addr = div_u64(addr, sck_xch);
-#if 0
-       /* Divide by channel way */
-       addr = addr / ch_way;
-#endif
-       /* Recover the last 6 bits */
-       ch_addr |= addr << 6;
+
+       ch_addr = addr - offset;
+       ch_addr >>= (6 + shiftup);
+       ch_addr /= ch_way * sck_way;
+       ch_addr <<= (6 + shiftup);
+       ch_addr |= addr & ((1 << (6 + shiftup)) - 1);
 
        /*
         * Step 3) Decode rank
index 41f876414a18d759ee2d89c33b5a4791ddcd6f43..bf19b6e3bd129929372ba486450b822c098169b4 100644 (file)
@@ -61,6 +61,7 @@ struct xgene_edac {
        struct regmap           *mcba_map;
        struct regmap           *mcbb_map;
        struct regmap           *efuse_map;
+       struct regmap           *rb_map;
        void __iomem            *pcp_csr;
        spinlock_t              lock;
        struct dentry           *dfs;
@@ -1057,7 +1058,7 @@ static bool xgene_edac_l3_promote_to_uc_err(u32 l3cesr, u32 l3celr)
                case 0x041:
                        return true;
                }
-       } else if (L3C_ELR_ERRSYN(l3celr) == 9)
+       } else if (L3C_ELR_ERRWAY(l3celr) == 9)
                return true;
 
        return false;
@@ -1353,6 +1354,17 @@ static int xgene_edac_l3_remove(struct xgene_edac_dev_ctx *l3)
 #define GLBL_MDED_ERRH                 0x0848
 #define GLBL_MDED_ERRHMASK             0x084c
 
+/* IO Bus Registers */
+#define RBCSR                          0x0000
+#define STICKYERR_MASK                 BIT(0)
+#define RBEIR                          0x0008
+#define AGENT_OFFLINE_ERR_MASK         BIT(30)
+#define UNIMPL_RBPAGE_ERR_MASK         BIT(29)
+#define WORD_ALIGNED_ERR_MASK          BIT(28)
+#define PAGE_ACCESS_ERR_MASK           BIT(27)
+#define WRITE_ACCESS_MASK              BIT(26)
+#define RBERRADDR_RD(src)              ((src) & 0x03FFFFFF)
+
 static const char * const soc_mem_err_v1[] = {
        "10GbE0",
        "10GbE1",
@@ -1470,6 +1482,51 @@ static void xgene_edac_rb_report(struct edac_device_ctl_info *edac_dev)
        u32 err_addr_hi;
        u32 reg;
 
+       /* If the register bus resource isn't available, just skip it */
+       if (!ctx->edac->rb_map)
+               goto rb_skip;
+
+       /*
+        * Check RB access errors
+        * 1. Out of range
+        * 2. Un-implemented page
+        * 3. Un-aligned access
+        * 4. Offline slave IP
+        */
+       if (regmap_read(ctx->edac->rb_map, RBCSR, &reg))
+               return;
+       if (reg & STICKYERR_MASK) {
+               bool write;
+               u32 address;
+
+               dev_err(edac_dev->dev, "IOB bus access error(s)\n");
+               if (regmap_read(ctx->edac->rb_map, RBEIR, &reg))
+                       return;
+               write = reg & WRITE_ACCESS_MASK ? 1 : 0;
+               address = RBERRADDR_RD(reg);
+               if (reg & AGENT_OFFLINE_ERR_MASK)
+                       dev_err(edac_dev->dev,
+                               "IOB bus %s access to offline agent error\n",
+                               write ? "write" : "read");
+               if (reg & UNIMPL_RBPAGE_ERR_MASK)
+                       dev_err(edac_dev->dev,
+                               "IOB bus %s access to unimplemented page error\n",
+                               write ? "write" : "read");
+               if (reg & WORD_ALIGNED_ERR_MASK)
+                       dev_err(edac_dev->dev,
+                               "IOB bus %s word aligned access error\n",
+                               write ? "write" : "read");
+               if (reg & PAGE_ACCESS_ERR_MASK)
+                       dev_err(edac_dev->dev,
+                               "IOB bus %s to page out of range access error\n",
+                               write ? "write" : "read");
+               if (regmap_write(ctx->edac->rb_map, RBEIR, 0))
+                       return;
+               if (regmap_write(ctx->edac->rb_map, RBCSR, 0))
+                       return;
+       }
+rb_skip:
+
        /* IOB Bridge agent transaction error interrupt */
        reg = readl(ctx->dev_csr + IOBBATRANSERRINTSTS);
        if (!reg)
@@ -1852,6 +1909,17 @@ static int xgene_edac_probe(struct platform_device *pdev)
                goto out_err;
        }
 
+       /*
+        * NOTE: The register bus resource is optional for compatibility
+        * reason.
+        */
+       edac->rb_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                      "regmap-rb");
+       if (IS_ERR(edac->rb_map)) {
+               dev_warn(edac->dev, "missing syscon regmap rb\n");
+               edac->rb_map = NULL;
+       }
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        edac->pcp_csr = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(edac->pcp_csr)) {
index 72791232e46ba44ff474cf7dadff5ccb433d7348..81037e5fe301ffbc48c1e7cd7ecb5c9bf26b59b5 100644 (file)
@@ -319,6 +319,9 @@ static ssize_t ibft_attr_show_nic(void *data, int type, char *buf)
                val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1));
                str += sprintf(str, "%pI4", &val);
                break;
+       case ISCSI_BOOT_ETH_PREFIX_LEN:
+               str += sprintf(str, "%d\n", nic->subnet_mask_prefix);
+               break;
        case ISCSI_BOOT_ETH_ORIGIN:
                str += sprintf(str, "%d\n", nic->origin);
                break;
@@ -460,6 +463,7 @@ static umode_t ibft_check_nic_for(void *data, int type)
                if (address_not_null(nic->ip_addr))
                        rc = S_IRUGO;
                break;
+       case ISCSI_BOOT_ETH_PREFIX_LEN:
        case ISCSI_BOOT_ETH_SUBNET_MASK:
                if (nic->subnet_mask_prefix)
                        rc = S_IRUGO;
index cf41440aff91971e89090138e7912a3713427623..d9ab0cd1d205963528d7022d66213c26bf8304e5 100644 (file)
@@ -196,6 +196,44 @@ static int gpio_rcar_irq_set_wake(struct irq_data *d, unsigned int on)
        return 0;
 }
 
+static void gpio_rcar_irq_bus_lock(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct gpio_rcar_priv *p = gpiochip_get_data(gc);
+
+       pm_runtime_get_sync(&p->pdev->dev);
+}
+
+static void gpio_rcar_irq_bus_sync_unlock(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct gpio_rcar_priv *p = gpiochip_get_data(gc);
+
+       pm_runtime_put(&p->pdev->dev);
+}
+
+
+static int gpio_rcar_irq_request_resources(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct gpio_rcar_priv *p = gpiochip_get_data(gc);
+       int error;
+
+       error = pm_runtime_get_sync(&p->pdev->dev);
+       if (error < 0)
+               return error;
+
+       return 0;
+}
+
+static void gpio_rcar_irq_release_resources(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct gpio_rcar_priv *p = gpiochip_get_data(gc);
+
+       pm_runtime_put(&p->pdev->dev);
+}
+
 static irqreturn_t gpio_rcar_irq_handler(int irq, void *dev_id)
 {
        struct gpio_rcar_priv *p = dev_id;
@@ -450,6 +488,10 @@ static int gpio_rcar_probe(struct platform_device *pdev)
        irq_chip->irq_unmask = gpio_rcar_irq_enable;
        irq_chip->irq_set_type = gpio_rcar_irq_set_type;
        irq_chip->irq_set_wake = gpio_rcar_irq_set_wake;
+       irq_chip->irq_bus_lock = gpio_rcar_irq_bus_lock;
+       irq_chip->irq_bus_sync_unlock = gpio_rcar_irq_bus_sync_unlock;
+       irq_chip->irq_request_resources = gpio_rcar_irq_request_resources;
+       irq_chip->irq_release_resources = gpio_rcar_irq_release_resources;
        irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
 
        ret = gpiochip_add_data(gpio_chip, p);
index 89c3dd62ba21ecd116b8490ed105573cecd86a82..119cdc2c43e7cef7fadf72736100cfcef1e200cd 100644 (file)
@@ -77,7 +77,7 @@ void amdgpu_connector_hotplug(struct drm_connector *connector)
                        } else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) {
                                /* Don't try to start link training before we
                                 * have the dpcd */
-                               if (!amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
+                               if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector))
                                        return;
 
                                /* set it to OFF so that drm_helper_connector_dpms()
index acd066d0a8051d0ad17f7311d8db1acd37348060..1846d65b72859284b31c536dc2fdc1a29cae0d9e 100644 (file)
@@ -72,8 +72,8 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
 
        struct drm_crtc *crtc = &amdgpuCrtc->base;
        unsigned long flags;
-       unsigned i;
-       int vpos, hpos, stat, min_udelay;
+       unsigned i, repcnt = 4;
+       int vpos, hpos, stat, min_udelay = 0;
        struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
 
        amdgpu_flip_wait_fence(adev, &work->excl);
@@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
         * In practice this won't execute very often unless on very fast
         * machines because the time window for this to happen is very small.
         */
-       for (;;) {
+       while (amdgpuCrtc->enabled && --repcnt) {
                /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
                 * start in hpos, and to the "fudged earlier" vblank start in
                 * vpos.
@@ -112,12 +112,24 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
                        break;
 
                /* Sleep at least until estimated real start of hw vblank */
-               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
+               if (min_udelay > vblank->framedur_ns / 2000) {
+                       /* Don't wait ridiculously long - something is wrong */
+                       repcnt = 0;
+                       break;
+               }
+               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                usleep_range(min_udelay, 2 * min_udelay);
                spin_lock_irqsave(&crtc->dev->event_lock, flags);
        };
 
+       if (!repcnt)
+               DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
+                                "framedur %d, linedur %d, stat %d, vpos %d, "
+                                "hpos %d\n", work->crtc_id, min_udelay,
+                                vblank->framedur_ns / 1000,
+                                vblank->linedur_ns / 1000, stat, vpos, hpos);
+
        /* do the flip (mmio) */
        adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
        /* set the flip status */
index 7380f782cd14a2ba1b3bb182832971368545e404..d20c2a8929cbdaf39164e6c709df67d36b352f35 100644 (file)
@@ -596,7 +596,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
                break;
        }
        ttm_eu_backoff_reservation(&ticket, &list);
-       if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
+       if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
+           !amdgpu_vm_debug)
                amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
 
        drm_gem_object_unreference_unlocked(gobj);
index 7d8d84eaea4a5ab258eb5dac4a383f6aff81850d..95a4a25d8df9e8d37e1ec06d2d566e337353f222 100644 (file)
@@ -113,6 +113,10 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev,
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct amdgpu_device *adev = ddev->dev_private;
 
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return snprintf(buf, PAGE_SIZE, "off\n");
+
        if (adev->pp_enabled) {
                enum amd_dpm_forced_level level;
 
@@ -140,6 +144,11 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
        enum amdgpu_dpm_forced_level level;
        int ret = 0;
 
+       /* Can't force performance level when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
        if (strncmp("low", buf, strlen("low")) == 0) {
                level = AMDGPU_DPM_FORCED_LEVEL_LOW;
        } else if (strncmp("high", buf, strlen("high")) == 0) {
@@ -157,6 +166,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
                mutex_lock(&adev->pm.mutex);
                if (adev->pm.dpm.thermal_active) {
                        count = -EINVAL;
+                       mutex_unlock(&adev->pm.mutex);
                        goto fail;
                }
                ret = amdgpu_dpm_force_performance_level(adev, level);
@@ -167,8 +177,6 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev,
                mutex_unlock(&adev->pm.mutex);
        }
 fail:
-       mutex_unlock(&adev->pm.mutex);
-
        return count;
 }
 
@@ -182,8 +190,14 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
                                      char *buf)
 {
        struct amdgpu_device *adev = dev_get_drvdata(dev);
+       struct drm_device *ddev = adev->ddev;
        int temp;
 
+       /* Can't get temperature when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
        if (!adev->pp_enabled && !adev->pm.funcs->get_temperature)
                temp = 0;
        else
@@ -634,11 +648,6 @@ force:
 
        /* update display watermarks based on new power state */
        amdgpu_display_bandwidth_update(adev);
-       /* update displays */
-       amdgpu_dpm_display_configuration_changed(adev);
-
-       adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
-       adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
 
        /* wait for the rings to drain */
        for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
@@ -655,6 +664,12 @@ force:
 
        amdgpu_dpm_post_set_power_state(adev);
 
+       /* update displays */
+       amdgpu_dpm_display_configuration_changed(adev);
+
+       adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
+       adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
+
        if (adev->pm.funcs->force_performance_level) {
                if (adev->pm.dpm.thermal_active) {
                        enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level;
@@ -847,12 +862,16 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct amdgpu_device *adev = dev->dev_private;
+       struct drm_device *ddev = adev->ddev;
 
        if (!adev->pm.dpm_enabled) {
                seq_printf(m, "dpm not enabled\n");
                return 0;
        }
-       if (adev->pp_enabled) {
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
+               seq_printf(m, "PX asic powered off\n");
+       } else if (adev->pp_enabled) {
                amdgpu_dpm_debugfs_print_current_performance_level(adev, m);
        } else {
                mutex_lock(&adev->pm.mutex);
index b9d0d55f6b47df33ab7ebf7024fe7ca6e821892a..3cb6d6c413c71b0207fe1766d26ca190a083e880 100644 (file)
@@ -143,8 +143,10 @@ static int amdgpu_pp_late_init(void *handle)
                                        adev->powerplay.pp_handle);
 
 #ifdef CONFIG_DRM_AMD_POWERPLAY
-       if (adev->pp_enabled)
+       if (adev->pp_enabled) {
                amdgpu_pm_sysfs_init(adev);
+               amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL);
+       }
 #endif
        return ret;
 }
index 21aacc1f45c1fd7afded7f6088c8a365e9005224..bf731e9f643e9ecddd367034179fae6a40d294ce 100644 (file)
@@ -265,15 +265,27 @@ static int amdgpu_atombios_dp_get_dp_link_config(struct drm_connector *connector
        unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
        unsigned lane_num, i, max_pix_clock;
 
-       for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
-               for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
-                       max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
+       if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+           ENCODER_OBJECT_ID_NUTMEG) {
+               for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+                       max_pix_clock = (lane_num * 270000 * 8) / bpp;
                        if (max_pix_clock >= pix_clock) {
                                *dp_lanes = lane_num;
-                               *dp_rate = link_rates[i];
+                               *dp_rate = 270000;
                                return 0;
                        }
                }
+       } else {
+               for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+                       for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
+                               max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
+                               if (max_pix_clock >= pix_clock) {
+                                       *dp_lanes = lane_num;
+                                       *dp_rate = link_rates[i];
+                                       return 0;
+                               }
+                       }
+               }
        }
 
        return -EINVAL;
index 9056355309d18cbc97beaf015b7e34be6c8b6b8f..e7ef2261ff4a70821a318e0377a33f7383607314 100644 (file)
@@ -2202,8 +2202,7 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
                                                            AMD_PG_STATE_GATE);
 
                                cz_enable_vce_dpm(adev, false);
-                               /* TODO: to figure out why vce can't be poweroff. */
-                               /* cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF); */
+                               cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF);
                                pi->vce_power_gated = true;
                        } else {
                                cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerON);
@@ -2226,10 +2225,8 @@ static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
                }
        } else { /*pi->caps_vce_pg*/
                cz_update_vce_dpm(adev);
-               cz_enable_vce_dpm(adev, true);
+               cz_enable_vce_dpm(adev, !gate);
        }
-
-       return;
 }
 
 const struct amd_ip_funcs cz_dpm_ip_funcs = {
index 7732059ae30f51414ab9173cc1d2fdaa7c07159c..06602df707f86375d8db781db550d6db160e06e0 100644 (file)
@@ -3628,6 +3628,19 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
                                        unsigned vm_id, uint64_t pd_addr)
 {
        int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+       uint32_t seq = ring->fence_drv.sync_seq;
+       uint64_t addr = ring->fence_drv.gpu_addr;
+
+       amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
+       amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
+                                WAIT_REG_MEM_FUNCTION(3) | /* equal */
+                                WAIT_REG_MEM_ENGINE(usepfp)));   /* pfp or me */
+       amdgpu_ring_write(ring, addr & 0xfffffffc);
+       amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
+       amdgpu_ring_write(ring, seq);
+       amdgpu_ring_write(ring, 0xffffffff);
+       amdgpu_ring_write(ring, 4); /* poll interval */
+
        if (usepfp) {
                /* synce CE with ME to prevent CE fetch CEIB before context switch done */
                amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
index 8f8ec37ecd883599b416773a0a6a579da6131515..7086ac17abee11aa68e6a863099c73b273db1717 100644 (file)
@@ -4809,7 +4809,8 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
 
        amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
        amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
-                WAIT_REG_MEM_FUNCTION(3))); /* equal */
+                                WAIT_REG_MEM_FUNCTION(3) | /* equal */
+                                WAIT_REG_MEM_ENGINE(usepfp))); /* pfp or me */
        amdgpu_ring_write(ring, addr & 0xfffffffc);
        amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
        amdgpu_ring_write(ring, seq);
@@ -4995,7 +4996,7 @@ static int gfx_v8_0_set_priv_reg_fault_state(struct amdgpu_device *adev,
        case AMDGPU_IRQ_STATE_ENABLE:
                cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
                cp_int_cntl = REG_SET_FIELD(cp_int_cntl, CP_INT_CNTL_RING0,
-                                           PRIV_REG_INT_ENABLE, 0);
+                                           PRIV_REG_INT_ENABLE, 1);
                WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
                break;
        default:
index aa67244a77ae38cf69761bc964c5f1d4400874c5..589599f66fcce851e9ce5b94b2c5617544165022 100644 (file)
@@ -402,8 +402,11 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input,
 
                data.requested_ui_label = power_state_convert(ps);
                ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
+               break;
        }
-       break;
+       case AMD_PP_EVENT_COMPLETE_INIT:
+               ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
+               break;
        default:
                break;
        }
index 83be3cf210e01439c224e78a5681606472d40bfa..6b52c78cb404870ae019b3cd262f7d9711b590b3 100644 (file)
@@ -165,6 +165,7 @@ const struct action_chain resume_action_chain = {
 };
 
 static const pem_event_action *complete_init_event[] = {
+       unblock_adjust_power_state_tasks,
        adjust_power_state_tasks,
        enable_gfx_clock_gating_tasks,
        enable_gfx_voltage_island_power_gating_tasks,
index 52a3efc97f05651bfb0daeaf475d5a4bfadbd43f..46410e3c73493acce741f955f60790fc9745256e 100644 (file)
@@ -31,7 +31,7 @@
 static int pem_init(struct pp_eventmgr *eventmgr)
 {
        int result = 0;
-       struct pem_event_data event_data;
+       struct pem_event_data event_data = { {0} };
 
        /* Initialize PowerPlay feature info */
        pem_init_feature_info(eventmgr);
@@ -52,7 +52,7 @@ static int pem_init(struct pp_eventmgr *eventmgr)
 
 static void pem_fini(struct pp_eventmgr *eventmgr)
 {
-       struct pem_event_data event_data;
+       struct pem_event_data event_data = { {0} };
 
        pem_uninit_featureInfo(eventmgr);
        pem_unregister_interrupts(eventmgr);
index ad7700822a1cb2ee26235bf6bbba9541480ff88e..ff08ce41bde92f82596894ee178a545916d288df 100644 (file)
@@ -226,7 +226,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
                }
        } else {
                cz_dpm_update_vce_dpm(hwmgr);
-               cz_enable_disable_vce_dpm(hwmgr, true);
+               cz_enable_disable_vce_dpm(hwmgr, !bgate);
                return 0;
        }
 
index 9759009d1da367cd8b3f264671ea7942aa3ab79a..b1480acbb3c3587c720570031eae9c41498d1d93 100644 (file)
@@ -227,7 +227,7 @@ static int ast_get_dram_info(struct drm_device *dev)
        } while (ast_read32(ast, 0x10000) != 0x01);
        data = ast_read32(ast, 0x10004);
 
-       if (data & 0x400)
+       if (data & 0x40)
                ast->dram_bus_width = 16;
        else
                ast->dram_bus_width = 32;
index 7f1a3604b19f60295ded6b684159981c651ca322..b332b4d3b0e284463447519924ecfe08086615ef 100644 (file)
@@ -182,8 +182,8 @@ static const struct pci_device_id bochs_pci_tbl[] = {
        {
                .vendor      = 0x1234,
                .device      = 0x1111,
-               .subvendor   = 0x1af4,
-               .subdevice   = 0x1100,
+               .subvendor   = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
+               .subdevice   = PCI_SUBDEVICE_ID_QEMU,
                .driver_data = BOCHS_QEMU_STDVGA,
        },
        {
index b1619e29a564db97ef626fd2c32bceaa3a18cadc..7bc394ec9fb3af7985ab746eeb3b9f1d020a852e 100644 (file)
@@ -33,8 +33,9 @@ static struct drm_driver driver;
 
 /* only bind to the cirrus chip in qemu */
 static const struct pci_device_id pciidlist[] = {
-       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0,
-         0, 0 },
+       { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446,
+         PCI_SUBVENDOR_ID_REDHAT_QUMRANET, PCI_SUBDEVICE_ID_QEMU,
+         0, 0, 0 },
        { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, PCI_VENDOR_ID_XEN,
          0x0001, 0, 0, 0 },
        {0,}
index e5df53b6e229ff0348541eeaa921acc6cf4700ef..1f500a1b99695a6bb83b3d596b9a2101f6f1f8ef 100644 (file)
@@ -109,8 +109,8 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
        if (IS_ERR(cma_obj))
                return cma_obj;
 
-       cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size,
-                       &cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN);
+       cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr,
+                                     GFP_KERNEL | __GFP_NOWARN);
        if (!cma_obj->vaddr) {
                dev_err(drm->dev, "failed to allocate buffer with size %zu\n",
                        size);
@@ -192,8 +192,8 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
        cma_obj = to_drm_gem_cma_obj(gem_obj);
 
        if (cma_obj->vaddr) {
-               dma_free_writecombine(gem_obj->dev->dev, cma_obj->base.size,
-                                     cma_obj->vaddr, cma_obj->paddr);
+               dma_free_wc(gem_obj->dev->dev, cma_obj->base.size,
+                           cma_obj->vaddr, cma_obj->paddr);
        } else if (gem_obj->import_attach) {
                drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
        }
@@ -324,9 +324,8 @@ static int drm_gem_cma_mmap_obj(struct drm_gem_cma_object *cma_obj,
        vma->vm_flags &= ~VM_PFNMAP;
        vma->vm_pgoff = 0;
 
-       ret = dma_mmap_writecombine(cma_obj->base.dev->dev, vma,
-                                   cma_obj->vaddr, cma_obj->paddr,
-                                   vma->vm_end - vma->vm_start);
+       ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr,
+                         cma_obj->paddr, vma->vm_end - vma->vm_start);
        if (ret)
                drm_gem_vm_close(vma);
 
index a33162cf4f4cc6c4f0aee66433680a15f64cfffc..3c1ce44483d991416fed77f8945dc6686f3a3341 100644 (file)
@@ -1113,8 +1113,8 @@ struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu, u32 size,
        if (!cmdbuf)
                return NULL;
 
-       cmdbuf->vaddr = dma_alloc_writecombine(gpu->dev, size, &cmdbuf->paddr,
-                                              GFP_KERNEL);
+       cmdbuf->vaddr = dma_alloc_wc(gpu->dev, size, &cmdbuf->paddr,
+                                    GFP_KERNEL);
        if (!cmdbuf->vaddr) {
                kfree(cmdbuf);
                return NULL;
@@ -1128,8 +1128,8 @@ struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu, u32 size,
 
 void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
 {
-       dma_free_writecombine(cmdbuf->gpu->dev, cmdbuf->size,
-                             cmdbuf->vaddr, cmdbuf->paddr);
+       dma_free_wc(cmdbuf->gpu->dev, cmdbuf->size, cmdbuf->vaddr,
+                   cmdbuf->paddr);
        kfree(cmdbuf);
 }
 
index 34e38749a8176f87001e54cb4ea8a7cc86fa744e..f8ee740c0e264d488b937503745ac9de06bbc9b1 100644 (file)
@@ -1382,8 +1382,16 @@ static void tda998x_connector_destroy(struct drm_connector *connector)
        drm_connector_cleanup(connector);
 }
 
+static int tda998x_connector_dpms(struct drm_connector *connector, int mode)
+{
+       if (drm_core_check_feature(connector->dev, DRIVER_ATOMIC))
+               return drm_atomic_helper_connector_dpms(connector, mode);
+       else
+               return drm_helper_connector_dpms(connector, mode);
+}
+
 static const struct drm_connector_funcs tda998x_connector_funcs = {
-       .dpms = drm_atomic_helper_connector_dpms,
+       .dpms = tda998x_connector_dpms,
        .reset = drm_atomic_helper_connector_reset,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .detect = tda998x_connector_detect,
index 0fc38bb7276c26920b372ca52c053eba504aa722..cf39ed3133d63aaa434120dc085bd6ea0811b2ee 100644 (file)
@@ -825,8 +825,11 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                }
 
                for_each_pipe(dev_priv, pipe) {
-                       if (!intel_display_power_is_enabled(dev_priv,
-                                               POWER_DOMAIN_PIPE(pipe))) {
+                       enum intel_display_power_domain power_domain;
+
+                       power_domain = POWER_DOMAIN_PIPE(pipe);
+                       if (!intel_display_power_get_if_enabled(dev_priv,
+                                                               power_domain)) {
                                seq_printf(m, "Pipe %c power disabled\n",
                                           pipe_name(pipe));
                                continue;
@@ -840,6 +843,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                        seq_printf(m, "Pipe %c IER:\t%08x\n",
                                   pipe_name(pipe),
                                   I915_READ(GEN8_DE_PIPE_IER(pipe)));
+
+                       intel_display_power_put(dev_priv, power_domain);
                }
 
                seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
@@ -3985,6 +3990,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
        struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
        struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev,
                                                                        pipe));
+       enum intel_display_power_domain power_domain;
        u32 val = 0; /* shut up gcc */
        int ret;
 
@@ -3995,7 +4001,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
        if (pipe_crc->source && source)
                return -EINVAL;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) {
+       power_domain = POWER_DOMAIN_PIPE(pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
                DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
                return -EIO;
        }
@@ -4012,7 +4019,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
                ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val);
 
        if (ret != 0)
-               return ret;
+               goto out;
 
        /* none -> real source transition */
        if (source) {
@@ -4024,8 +4031,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
                entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR,
                                  sizeof(pipe_crc->entries[0]),
                                  GFP_KERNEL);
-               if (!entries)
-                       return -ENOMEM;
+               if (!entries) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
 
                /*
                 * When IPS gets enabled, the pipe CRC changes. Since IPS gets
@@ -4081,7 +4090,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
                hsw_enable_ips(crtc);
        }
 
-       return 0;
+       ret = 0;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 /*
index e7cd311e9fbb250b755857462b4eefff59a22d0a..b0847b9155452366569a4676c9da62bc6c2bc94d 100644 (file)
@@ -751,6 +751,7 @@ struct intel_csr {
        uint32_t mmio_count;
        i915_reg_t mmioaddr[8];
        uint32_t mmiodata[8];
+       uint32_t dc_state;
 };
 
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
index 31f6d212fb1bbbfa1ce64efe8cebde2a5f9f575d..30f921421b0c944217832ba86856a6904f8fef11 100644 (file)
@@ -527,6 +527,8 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
 
        mutex_lock(&dev_priv->av_mutex);
        intel_dig_port->audio_connector = connector;
+       /* referred in audio callbacks */
+       dev_priv->dig_port_map[port] = intel_encoder;
        mutex_unlock(&dev_priv->av_mutex);
 
        if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
@@ -554,6 +556,7 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
 
        mutex_lock(&dev_priv->av_mutex);
        intel_dig_port->audio_connector = NULL;
+       dev_priv->dig_port_map[port] = NULL;
        mutex_unlock(&dev_priv->av_mutex);
 
        if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
index 9c89df1af036de613d71a5e8fccc83050722a088..a7b4a524faddc8a80c6693c89eee98efa3fc4450 100644 (file)
@@ -71,22 +71,29 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
        struct intel_crt *crt = intel_encoder_to_crt(encoder);
        enum intel_display_power_domain power_domain;
        u32 tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(crt->adpa_reg);
 
        if (!(tmp & ADPA_DAC_ENABLE))
-               return false;
+               goto out;
 
        if (HAS_PCH_CPT(dev))
                *pipe = PORT_TO_PIPE_CPT(tmp);
        else
                *pipe = PORT_TO_PIPE(tmp);
 
-       return true;
+       ret = true;
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
index 9bb63a85997a4ffbf31da0e8dbd211786f2e626c..647d85e77c2f4700e84bc275efb711f9b2dc2363 100644 (file)
@@ -240,6 +240,8 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv)
                I915_WRITE(dev_priv->csr.mmioaddr[i],
                           dev_priv->csr.mmiodata[i]);
        }
+
+       dev_priv->csr.dc_state = 0;
 }
 
 static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
index 54a165b9c92dd94a99faa132bdb19f6e6f96daef..084d5586585d012891423067703fde0f9daec0b1 100644 (file)
@@ -1969,13 +1969,16 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
        enum transcoder cpu_transcoder;
        enum intel_display_power_domain power_domain;
        uint32_t tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(intel_encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
-       if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
-               return false;
+       if (!intel_encoder->get_hw_state(intel_encoder, &pipe)) {
+               ret = false;
+               goto out;
+       }
 
        if (port == PORT_A)
                cpu_transcoder = TRANSCODER_EDP;
@@ -1987,23 +1990,33 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
        switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
        case TRANS_DDI_MODE_SELECT_HDMI:
        case TRANS_DDI_MODE_SELECT_DVI:
-               return (type == DRM_MODE_CONNECTOR_HDMIA);
+               ret = type == DRM_MODE_CONNECTOR_HDMIA;
+               break;
 
        case TRANS_DDI_MODE_SELECT_DP_SST:
-               if (type == DRM_MODE_CONNECTOR_eDP)
-                       return true;
-               return (type == DRM_MODE_CONNECTOR_DisplayPort);
+               ret = type == DRM_MODE_CONNECTOR_eDP ||
+                     type == DRM_MODE_CONNECTOR_DisplayPort;
+               break;
+
        case TRANS_DDI_MODE_SELECT_DP_MST:
                /* if the transcoder is in MST state then
                 * connector isn't connected */
-               return false;
+               ret = false;
+               break;
 
        case TRANS_DDI_MODE_SELECT_FDI:
-               return (type == DRM_MODE_CONNECTOR_VGA);
+               ret = type == DRM_MODE_CONNECTOR_VGA;
+               break;
 
        default:
-               return false;
+               ret = false;
+               break;
        }
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
@@ -2015,15 +2028,18 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
        enum intel_display_power_domain power_domain;
        u32 tmp;
        int i;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(DDI_BUF_CTL(port));
 
        if (!(tmp & DDI_BUF_CTL_ENABLE))
-               return false;
+               goto out;
 
        if (port == PORT_A) {
                tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
@@ -2041,25 +2057,32 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
                        break;
                }
 
-               return true;
-       } else {
-               for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) {
-                       tmp = I915_READ(TRANS_DDI_FUNC_CTL(i));
+               ret = true;
 
-                       if ((tmp & TRANS_DDI_PORT_MASK)
-                           == TRANS_DDI_SELECT_PORT(port)) {
-                               if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST)
-                                       return false;
+               goto out;
+       }
 
-                               *pipe = i;
-                               return true;
-                       }
+       for (i = TRANSCODER_A; i <= TRANSCODER_C; i++) {
+               tmp = I915_READ(TRANS_DDI_FUNC_CTL(i));
+
+               if ((tmp & TRANS_DDI_PORT_MASK) == TRANS_DDI_SELECT_PORT(port)) {
+                       if ((tmp & TRANS_DDI_MODE_SELECT_MASK) ==
+                           TRANS_DDI_MODE_SELECT_DP_MST)
+                               goto out;
+
+                       *pipe = i;
+                       ret = true;
+
+                       goto out;
                }
        }
 
        DRM_DEBUG_KMS("No pipe for ddi port %c found\n", port_name(port));
 
-       return false;
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 void intel_ddi_enable_pipe_clock(struct intel_crtc *intel_crtc)
@@ -2508,12 +2531,14 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        uint32_t val;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
        val = I915_READ(WRPLL_CTL(pll->id));
        hw_state->wrpll = val;
 
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
        return val & WRPLL_PLL_ENABLE;
 }
 
@@ -2523,12 +2548,14 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        uint32_t val;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
        val = I915_READ(SPLL_CTL);
        hw_state->spll = val;
 
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
        return val & SPLL_PLL_ENABLE;
 }
 
@@ -2645,16 +2672,19 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
        uint32_t val;
        unsigned int dpll;
        const struct skl_dpll_regs *regs = skl_dpll_regs;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
+       ret = false;
+
        /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
        dpll = pll->id + 1;
 
        val = I915_READ(regs[pll->id].ctl);
        if (!(val & LCPLL_PLL_ENABLE))
-               return false;
+               goto out;
 
        val = I915_READ(DPLL_CTRL1);
        hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f;
@@ -2664,8 +2694,12 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
                hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
                hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
        }
+       ret = true;
 
-       return true;
+out:
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return ret;
 }
 
 static void skl_shared_dplls_init(struct drm_i915_private *dev_priv)
@@ -2932,13 +2966,16 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        enum port port = (enum port)pll->id;    /* 1:1 port->PLL mapping */
        uint32_t val;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
+       ret = false;
+
        val = I915_READ(BXT_PORT_PLL_ENABLE(port));
        if (!(val & PORT_PLL_ENABLE))
-               return false;
+               goto out;
 
        hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
        hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
@@ -2985,7 +3022,12 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
                                 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
        hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+       return ret;
 }
 
 static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv)
@@ -3120,11 +3162,15 @@ bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
 {
        u32 temp;
 
-       if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
+       if (intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_AUDIO)) {
                temp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
+
+               intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
+
                if (temp & AUDIO_OUTPUT_ENABLE(intel_crtc->pipe))
                        return true;
        }
+
        return false;
 }
 
@@ -3312,7 +3358,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
        intel_encoder->get_config = intel_ddi_get_config;
 
        intel_dig_port->port = port;
-       dev_priv->dig_port_map[port] = intel_encoder;
        intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) &
                                          (DDI_BUF_PORT_REVERSAL |
                                           DDI_A_4_LANES);
index 5feb65725c04e350c09d33b8969a53770d3d6049..46947fffd5998074555c95ce8d373343aac20bd6 100644 (file)
@@ -1351,18 +1351,21 @@ void assert_pipe(struct drm_i915_private *dev_priv,
        bool cur_state;
        enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
                                                                      pipe);
+       enum intel_display_power_domain power_domain;
 
        /* if we need the pipe quirk it must be always on */
        if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
            (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
                state = true;
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                               POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
-               cur_state = false;
-       } else {
+       power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+       if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
                u32 val = I915_READ(PIPECONF(cpu_transcoder));
                cur_state = !!(val & PIPECONF_ENABLE);
+
+               intel_display_power_put(dev_priv, power_domain);
+       } else {
+               cur_state = false;
        }
 
        I915_STATE_WARN(cur_state != state,
@@ -8171,18 +8174,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       enum intel_display_power_domain power_domain;
        uint32_t tmp;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                                           POWER_DOMAIN_PIPE(crtc->pipe)))
+       power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
+       ret = false;
+
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
-               return false;
+               goto out;
 
        if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
                switch (tmp & PIPECONF_BPC_MASK) {
@@ -8262,7 +8269,12 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
        pipe_config->base.adjusted_mode.crtc_clock =
                pipe_config->port_clock / pipe_config->pixel_multiplier;
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void ironlake_init_pch_refclk(struct drm_device *dev)
@@ -9366,18 +9378,21 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       enum intel_display_power_domain power_domain;
        uint32_t tmp;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                                           POWER_DOMAIN_PIPE(crtc->pipe)))
+       power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
 
+       ret = false;
        tmp = I915_READ(PIPECONF(crtc->pipe));
        if (!(tmp & PIPECONF_ENABLE))
-               return false;
+               goto out;
 
        switch (tmp & PIPECONF_BPC_MASK) {
        case PIPECONF_6BPC:
@@ -9440,7 +9455,12 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc,
 
        ironlake_get_pfit_config(crtc, pipe_config);
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
@@ -9950,12 +9970,17 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       enum intel_display_power_domain pfit_domain;
+       enum intel_display_power_domain power_domain;
+       unsigned long power_domain_mask;
        uint32_t tmp;
+       bool ret;
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                                        POWER_DOMAIN_PIPE(crtc->pipe)))
+       power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
+       power_domain_mask = BIT(power_domain);
+
+       ret = false;
 
        pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
@@ -9982,13 +10007,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                        pipe_config->cpu_transcoder = TRANSCODER_EDP;
        }
 
-       if (!intel_display_power_is_enabled(dev_priv,
-                       POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
-               return false;
+       power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+               goto out;
+       power_domain_mask |= BIT(power_domain);
 
        tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
        if (!(tmp & PIPECONF_ENABLE))
-               return false;
+               goto out;
 
        haswell_get_ddi_port_state(crtc, pipe_config);
 
@@ -9998,14 +10024,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                skl_init_scalers(dev, crtc, pipe_config);
        }
 
-       pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
-
        if (INTEL_INFO(dev)->gen >= 9) {
                pipe_config->scaler_state.scaler_id = -1;
                pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX);
        }
 
-       if (intel_display_power_is_enabled(dev_priv, pfit_domain)) {
+       power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
+       if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
+               power_domain_mask |= BIT(power_domain);
                if (INTEL_INFO(dev)->gen >= 9)
                        skylake_get_pfit_config(crtc, pipe_config);
                else
@@ -10023,7 +10049,13 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
                pipe_config->pixel_multiplier = 1;
        }
 
-       return true;
+       ret = true;
+
+out:
+       for_each_power_domain(power_domain, power_domain_mask)
+               intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
@@ -13630,7 +13662,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
 {
        uint32_t val;
 
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PLLS))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
                return false;
 
        val = I915_READ(PCH_DPLL(pll->id));
@@ -13638,6 +13670,8 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
        hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
        hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
 
+       intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
        return val & DPLL_VCO_ENABLE;
 }
 
@@ -15568,10 +15602,12 @@ void i915_redisable_vga(struct drm_device *dev)
         * level, just check if the power well is enabled instead of trying to
         * follow the "don't touch the power well if we don't need it" policy
         * the rest of the driver uses. */
-       if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_VGA))
+       if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
                return;
 
        i915_redisable_vga_power_on(dev);
+
+       intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
 }
 
 static bool primary_get_hw_state(struct intel_plane *plane)
index 1bbd67b046daca0abeddf5cbed83b1628b7094ed..cdc2c15873dcc71189ed3263aad55e3c63493ed3 100644 (file)
@@ -2362,15 +2362,18 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum intel_display_power_domain power_domain;
        u32 tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(intel_dp->output_reg);
 
        if (!(tmp & DP_PORT_EN))
-               return false;
+               goto out;
 
        if (IS_GEN7(dev) && port == PORT_A) {
                *pipe = PORT_TO_PIPE_CPT(tmp);
@@ -2381,7 +2384,9 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
                        u32 trans_dp = I915_READ(TRANS_DP_CTL(p));
                        if (TRANS_DP_PIPE_TO_PORT(trans_dp) == port) {
                                *pipe = p;
-                               return true;
+                               ret = true;
+
+                               goto out;
                        }
                }
 
@@ -2393,7 +2398,12 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
                *pipe = PORT_TO_PIPE(tmp);
        }
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void intel_dp_get_config(struct intel_encoder *encoder,
@@ -6035,7 +6045,6 @@ intel_dp_init(struct drm_device *dev,
        }
 
        intel_dig_port->port = port;
-       dev_priv->dig_port_map[port] = intel_encoder;
        intel_dig_port->dp.output_reg = output_reg;
 
        intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
index ea5415851c6e2cc36d4c6790db473fab637fd46d..df7f3cb66056e754c3c8f596583cae343fc2d5a9 100644 (file)
@@ -1428,6 +1428,8 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
                                      enum intel_display_power_domain domain);
 void intel_display_power_get(struct drm_i915_private *dev_priv,
                             enum intel_display_power_domain domain);
+bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+                                       enum intel_display_power_domain domain);
 void intel_display_power_put(struct drm_i915_private *dev_priv,
                             enum intel_display_power_domain domain);
 
@@ -1514,6 +1516,7 @@ enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv)
        enable_rpm_wakeref_asserts(dev_priv)
 
 void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
+bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
 
index 44742fa2f616dd22fc25847b0f4ddb5730e550de..0193c62a53ef34f8e2027fb39e3172d44703bfba 100644 (file)
@@ -664,13 +664,16 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
        struct drm_device *dev = encoder->base.dev;
        enum intel_display_power_domain power_domain;
        enum port port;
+       bool ret;
 
        DRM_DEBUG_KMS("\n");
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        /* XXX: this only works for one DSI output */
        for_each_dsi_port(port, intel_dsi->ports) {
                i915_reg_t ctrl_reg = IS_BROXTON(dev) ?
@@ -691,12 +694,16 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
                if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) {
                        if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) {
                                *pipe = port == PORT_A ? PIPE_A : PIPE_B;
-                               return true;
+                               ret = true;
+
+                               goto out;
                        }
                }
        }
+out:
+       intel_display_power_put(dev_priv, power_domain);
 
-       return false;
+       return ret;
 }
 
 static void intel_dsi_get_config(struct intel_encoder *encoder,
index 4a77639a489dfcd67ff0937e6e3fa4da61fed461..616108c4bc3e5741f59c9a1066aa2df3b63d5fc5 100644 (file)
@@ -880,15 +880,18 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
        enum intel_display_power_domain power_domain;
        u32 tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(intel_hdmi->hdmi_reg);
 
        if (!(tmp & SDVO_ENABLE))
-               return false;
+               goto out;
 
        if (HAS_PCH_CPT(dev))
                *pipe = PORT_TO_PIPE_CPT(tmp);
@@ -897,7 +900,12 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
        else
                *pipe = PORT_TO_PIPE(tmp);
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void intel_hdmi_get_config(struct intel_encoder *encoder,
@@ -2146,7 +2154,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 void intel_hdmi_init(struct drm_device *dev,
                     i915_reg_t hdmi_reg, enum port port)
 {
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_digital_port *intel_dig_port;
        struct intel_encoder *intel_encoder;
        struct intel_connector *intel_connector;
@@ -2215,7 +2222,6 @@ void intel_hdmi_init(struct drm_device *dev,
                intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
 
        intel_dig_port->port = port;
-       dev_priv->dig_port_map[port] = intel_encoder;
        intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
        intel_dig_port->dp.output_reg = INVALID_MMIO_REG;
 
index deb8282c26d83f952473ae145c4fef0b3112b9f1..52fbe530fc9eac207093271a05d44dbf3515e11c 100644 (file)
@@ -664,6 +664,12 @@ int intel_setup_gmbus(struct drm_device *dev)
 
                bus->adapter.algo = &gmbus_algorithm;
 
+               /*
+                * We wish to retry with bit banging
+                * after a timed out GMBUS attempt.
+                */
+               bus->adapter.retries = 1;
+
                /* By default use a conservative clock rate */
                bus->reg0 = pin | GMBUS_RATE_100KHZ;
 
index 0da0240caf815089447d4614b200ac818fd85250..bc04d8d29acb0bcc8112b39741f7614db6615625 100644 (file)
@@ -75,22 +75,30 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
        struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
        enum intel_display_power_domain power_domain;
        u32 tmp;
+       bool ret;
 
        power_domain = intel_display_port_power_domain(encoder);
-       if (!intel_display_power_is_enabled(dev_priv, power_domain))
+       if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                return false;
 
+       ret = false;
+
        tmp = I915_READ(lvds_encoder->reg);
 
        if (!(tmp & LVDS_PORT_EN))
-               return false;
+               goto out;
 
        if (HAS_PCH_CPT(dev))
                *pipe = PORT_TO_PIPE_CPT(tmp);
        else
                *pipe = PORT_TO_PIPE(tmp);
 
-       return true;
+       ret = true;
+
+out:
+       intel_display_power_put(dev_priv, power_domain);
+
+       return ret;
 }
 
 static void intel_lvds_get_config(struct intel_encoder *encoder,
index a234687792f0b3be15b98ad08b84743135eac5ce..b28c29f20e754ec740e5aacd101bbe07867f65a6 100644 (file)
@@ -2829,7 +2829,10 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
        memset(ddb, 0, sizeof(*ddb));
 
        for_each_pipe(dev_priv, pipe) {
-               if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe)))
+               enum intel_display_power_domain power_domain;
+
+               power_domain = POWER_DOMAIN_PIPE(pipe);
+               if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
                        continue;
 
                for_each_plane(dev_priv, pipe, plane) {
@@ -2841,6 +2844,8 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
                val = I915_READ(CUR_BUF_CFG(pipe));
                skl_ddb_entry_init_from_hw(&ddb->plane[pipe][PLANE_CURSOR],
                                           val);
+
+               intel_display_power_put(dev_priv, power_domain);
        }
 }
 
index ddbdbffe829a684eff8c2ef42a3cf29ccbf112d8..4f43d9b32e6639a9f12db67ba0da213ae440f982 100644 (file)
@@ -470,6 +470,43 @@ static void gen9_set_dc_state_debugmask_memory_up(
        }
 }
 
+static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
+                               u32 state)
+{
+       int rewrites = 0;
+       int rereads = 0;
+       u32 v;
+
+       I915_WRITE(DC_STATE_EN, state);
+
+       /* It has been observed that disabling the dc6 state sometimes
+        * doesn't stick and dmc keeps returning old value. Make sure
+        * the write really sticks enough times and also force rewrite until
+        * we are confident that state is exactly what we want.
+        */
+       do  {
+               v = I915_READ(DC_STATE_EN);
+
+               if (v != state) {
+                       I915_WRITE(DC_STATE_EN, state);
+                       rewrites++;
+                       rereads = 0;
+               } else if (rereads++ > 5) {
+                       break;
+               }
+
+       } while (rewrites < 100);
+
+       if (v != state)
+               DRM_ERROR("Writing dc state to 0x%x failed, now 0x%x\n",
+                         state, v);
+
+       /* Most of the times we need one retry, avoid spam */
+       if (rewrites > 1)
+               DRM_DEBUG_KMS("Rewrote dc state to 0x%x %d times\n",
+                             state, rewrites);
+}
+
 static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
 {
        uint32_t val;
@@ -494,10 +531,18 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
        val = I915_READ(DC_STATE_EN);
        DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n",
                      val & mask, state);
+
+       /* Check if DMC is ignoring our DC state requests */
+       if ((val & mask) != dev_priv->csr.dc_state)
+               DRM_ERROR("DC state mismatch (0x%x -> 0x%x)\n",
+                         dev_priv->csr.dc_state, val & mask);
+
        val &= ~mask;
        val |= state;
-       I915_WRITE(DC_STATE_EN, val);
-       POSTING_READ(DC_STATE_EN);
+
+       gen9_write_dc_state(dev_priv, val);
+
+       dev_priv->csr.dc_state = val & mask;
 }
 
 void bxt_enable_dc9(struct drm_i915_private *dev_priv)
@@ -1442,6 +1487,22 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
        chv_set_pipe_power_well(dev_priv, power_well, false);
 }
 
+static void
+__intel_display_power_get_domain(struct drm_i915_private *dev_priv,
+                                enum intel_display_power_domain domain)
+{
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       struct i915_power_well *power_well;
+       int i;
+
+       for_each_power_well(i, power_well, BIT(domain), power_domains) {
+               if (!power_well->count++)
+                       intel_power_well_enable(dev_priv, power_well);
+       }
+
+       power_domains->domain_use_count[domain]++;
+}
+
 /**
  * intel_display_power_get - grab a power domain reference
  * @dev_priv: i915 device instance
@@ -1457,24 +1518,53 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
 void intel_display_power_get(struct drm_i915_private *dev_priv,
                             enum intel_display_power_domain domain)
 {
-       struct i915_power_domains *power_domains;
-       struct i915_power_well *power_well;
-       int i;
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
 
        intel_runtime_pm_get(dev_priv);
 
-       power_domains = &dev_priv->power_domains;
+       mutex_lock(&power_domains->lock);
+
+       __intel_display_power_get_domain(dev_priv, domain);
+
+       mutex_unlock(&power_domains->lock);
+}
+
+/**
+ * intel_display_power_get_if_enabled - grab a reference for an enabled display power domain
+ * @dev_priv: i915 device instance
+ * @domain: power domain to reference
+ *
+ * This function grabs a power domain reference for @domain and ensures that the
+ * power domain and all its parents are powered up. Therefore users should only
+ * grab a reference to the innermost power domain they need.
+ *
+ * Any power domain reference obtained by this function must have a symmetric
+ * call to intel_display_power_put() to release the reference again.
+ */
+bool intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
+                                       enum intel_display_power_domain domain)
+{
+       struct i915_power_domains *power_domains = &dev_priv->power_domains;
+       bool is_enabled;
+
+       if (!intel_runtime_pm_get_if_in_use(dev_priv))
+               return false;
 
        mutex_lock(&power_domains->lock);
 
-       for_each_power_well(i, power_well, BIT(domain), power_domains) {
-               if (!power_well->count++)
-                       intel_power_well_enable(dev_priv, power_well);
+       if (__intel_display_power_is_enabled(dev_priv, domain)) {
+               __intel_display_power_get_domain(dev_priv, domain);
+               is_enabled = true;
+       } else {
+               is_enabled = false;
        }
 
-       power_domains->domain_use_count[domain]++;
-
        mutex_unlock(&power_domains->lock);
+
+       if (!is_enabled)
+               intel_runtime_pm_put(dev_priv);
+
+       return is_enabled;
 }
 
 /**
@@ -2213,15 +2303,15 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
  */
 void intel_power_domains_suspend(struct drm_i915_private *dev_priv)
 {
-       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
-               skl_display_core_uninit(dev_priv);
-
        /*
         * Even if power well support was disabled we still want to disable
         * power wells while we are system suspended.
         */
        if (!i915.disable_power_well)
                intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+
+       if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
+               skl_display_core_uninit(dev_priv);
 }
 
 /**
@@ -2245,6 +2335,41 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
        assert_rpm_wakelock_held(dev_priv);
 }
 
+/**
+ * intel_runtime_pm_get_if_in_use - grab a runtime pm reference if device in use
+ * @dev_priv: i915 device instance
+ *
+ * This function grabs a device-level runtime pm reference if the device is
+ * already in use and ensures that it is powered up.
+ *
+ * Any runtime pm reference obtained by this function must have a symmetric
+ * call to intel_runtime_pm_put() to release the reference again.
+ */
+bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct device *device = &dev->pdev->dev;
+
+       if (IS_ENABLED(CONFIG_PM)) {
+               int ret = pm_runtime_get_if_in_use(device);
+
+               /*
+                * In cases runtime PM is disabled by the RPM core and we get
+                * an -EINVAL return value we are not supposed to call this
+                * function, since the power state is undefined. This applies
+                * atm to the late/early system suspend/resume handlers.
+                */
+               WARN_ON_ONCE(ret < 0);
+               if (ret <= 0)
+                       return false;
+       }
+
+       atomic_inc(&dev_priv->pm.wakeref_count);
+       assert_rpm_wakelock_held(dev_priv);
+
+       return true;
+}
+
 /**
  * intel_runtime_pm_get_noresume - grab a runtime pm reference
  * @dev_priv: i915 device instance
index 30a57185bdb4e41e7ff26a0d4af36577a218b0ea..287226311413c7036cecb02e973e6109d0b26548 100644 (file)
@@ -64,6 +64,7 @@ static void ipu_fb_enable(struct ipu_crtc *ipu_crtc)
        /* Start DC channel and DI after IDMAC */
        ipu_dc_enable_channel(ipu_crtc->dc);
        ipu_di_enable(ipu_crtc->di);
+       drm_crtc_vblank_on(&ipu_crtc->base);
 
        ipu_crtc->enabled = 1;
 }
@@ -80,6 +81,7 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc)
        ipu_di_disable(ipu_crtc->di);
        ipu_plane_disable(ipu_crtc->plane[0]);
        ipu_dc_disable(ipu);
+       drm_crtc_vblank_off(&ipu_crtc->base);
 
        ipu_crtc->enabled = 0;
 }
index 591ba2f1ae03674224b4719660d547ad4e64c0b1..26bb1b626fe3d817812e18e19e0bfb64a4247c3c 100644 (file)
@@ -42,6 +42,7 @@ static const uint32_t ipu_plane_formats[] = {
        DRM_FORMAT_YVYU,
        DRM_FORMAT_YUV420,
        DRM_FORMAT_YVU420,
+       DRM_FORMAT_RGB565,
 };
 
 int ipu_plane_irq(struct ipu_plane *ipu_plane)
index 8a70cec59bcd3f58b43d2d8119afa14c44190bce..2dfe58af12e4ee05103d14946dc4a0d001f7f9c6 100644 (file)
@@ -24,7 +24,7 @@
 static int nouveau_platform_probe(struct platform_device *pdev)
 {
        const struct nvkm_device_tegra_func *func;
-       struct nvkm_device *device;
+       struct nvkm_device *device = NULL;
        struct drm_device *drm;
        int ret;
 
index 7f8a42721eb20ccafe19fcaefe3d972f432a6c7f..e7e581d6a8ff24d256b6526d2b93c41b7a00daa3 100644 (file)
@@ -252,32 +252,40 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
 
        if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL)))
                return -ENOMEM;
-       *pdevice = &tdev->device;
+
        tdev->func = func;
        tdev->pdev = pdev;
        tdev->irq = -1;
 
        tdev->vdd = devm_regulator_get(&pdev->dev, "vdd");
-       if (IS_ERR(tdev->vdd))
-               return PTR_ERR(tdev->vdd);
+       if (IS_ERR(tdev->vdd)) {
+               ret = PTR_ERR(tdev->vdd);
+               goto free;
+       }
 
        tdev->rst = devm_reset_control_get(&pdev->dev, "gpu");
-       if (IS_ERR(tdev->rst))
-               return PTR_ERR(tdev->rst);
+       if (IS_ERR(tdev->rst)) {
+               ret = PTR_ERR(tdev->rst);
+               goto free;
+       }
 
        tdev->clk = devm_clk_get(&pdev->dev, "gpu");
-       if (IS_ERR(tdev->clk))
-               return PTR_ERR(tdev->clk);
+       if (IS_ERR(tdev->clk)) {
+               ret = PTR_ERR(tdev->clk);
+               goto free;
+       }
 
        tdev->clk_pwr = devm_clk_get(&pdev->dev, "pwr");
-       if (IS_ERR(tdev->clk_pwr))
-               return PTR_ERR(tdev->clk_pwr);
+       if (IS_ERR(tdev->clk_pwr)) {
+               ret = PTR_ERR(tdev->clk_pwr);
+               goto free;
+       }
 
        nvkm_device_tegra_probe_iommu(tdev);
 
        ret = nvkm_device_tegra_power_up(tdev);
        if (ret)
-               return ret;
+               goto remove;
 
        tdev->gpu_speedo = tegra_sku_info.gpu_speedo_value;
        ret = nvkm_device_ctor(&nvkm_device_tegra_func, NULL, &pdev->dev,
@@ -285,9 +293,19 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func,
                               cfg, dbg, detect, mmio, subdev_mask,
                               &tdev->device);
        if (ret)
-               return ret;
+               goto powerdown;
+
+       *pdevice = &tdev->device;
 
        return 0;
+
+powerdown:
+       nvkm_device_tegra_power_down(tdev);
+remove:
+       nvkm_device_tegra_remove_iommu(tdev);
+free:
+       kfree(tdev);
+       return ret;
 }
 #else
 int
index 74e2f7c6c07e4a583d9e3f6d62016b92c5694d28..9688970eca47dbe4ccea5b2e700b0cfdb40b02e0 100644 (file)
@@ -328,6 +328,7 @@ nvkm_dp_train(struct work_struct *w)
                .outp = outp,
        }, *dp = &_dp;
        u32 datarate = 0;
+       u8  pwr;
        int ret;
 
        if (!outp->base.info.location && disp->func->sor.magic)
@@ -355,6 +356,15 @@ nvkm_dp_train(struct work_struct *w)
        /* disable link interrupt handling during link training */
        nvkm_notify_put(&outp->irq);
 
+       /* ensure sink is not in a low-power state */
+       if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) {
+               if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
+                       pwr &= ~DPCD_SC00_SET_POWER;
+                       pwr |=  DPCD_SC00_SET_POWER_D0;
+                       nvkm_wraux(outp->aux, DPCD_SC00, &pwr, 1);
+               }
+       }
+
        /* enable down-spreading and execute pre-train script from vbios */
        dp_link_train_init(dp, outp->dpcd[3] & 0x01);
 
index 9596290329c70e0cbe34259fbf5db39e12a9cbcb..6e10c5e0ef1162232253b29a248ad2c15e801f21 100644 (file)
 #define DPCD_LS0C_LANE1_POST_CURSOR2                                       0x0c
 #define DPCD_LS0C_LANE0_POST_CURSOR2                                       0x03
 
+/* DPCD Sink Control */
+#define DPCD_SC00                                                       0x00600
+#define DPCD_SC00_SET_POWER                                                0x03
+#define DPCD_SC00_SET_POWER_D0                                             0x01
+#define DPCD_SC00_SET_POWER_D3                                             0x03
+
 void nvkm_dp_train(struct work_struct *);
 #endif
index dfebdc4aa0f24ac00f47ab3062d1e24e9b455648..85dfe3674b4138ef02e1b3f043699459d9decb25 100644 (file)
@@ -573,10 +573,9 @@ static int omap_dmm_remove(struct platform_device *dev)
 
                kfree(omap_dmm->engines);
                if (omap_dmm->refill_va)
-                       dma_free_writecombine(omap_dmm->dev,
-                               REFILL_BUFFER_SIZE * omap_dmm->num_engines,
-                               omap_dmm->refill_va,
-                               omap_dmm->refill_pa);
+                       dma_free_wc(omap_dmm->dev,
+                                   REFILL_BUFFER_SIZE * omap_dmm->num_engines,
+                                   omap_dmm->refill_va, omap_dmm->refill_pa);
                if (omap_dmm->dummy_page)
                        __free_page(omap_dmm->dummy_page);
 
@@ -701,9 +700,9 @@ static int omap_dmm_probe(struct platform_device *dev)
        omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
 
        /* alloc refill memory */
-       omap_dmm->refill_va = dma_alloc_writecombine(&dev->dev,
-                               REFILL_BUFFER_SIZE * omap_dmm->num_engines,
-                               &omap_dmm->refill_pa, GFP_KERNEL);
+       omap_dmm->refill_va = dma_alloc_wc(&dev->dev,
+                                          REFILL_BUFFER_SIZE * omap_dmm->num_engines,
+                                          &omap_dmm->refill_pa, GFP_KERNEL);
        if (!omap_dmm->refill_va) {
                dev_err(&dev->dev, "could not allocate refill memory\n");
                goto fail;
index 8495a1a4b61745524dd04045616d859b2ac566bb..359b0d7e8ef78faf6cd9d6e044cfb5088f99f0be 100644 (file)
@@ -1330,8 +1330,8 @@ void omap_gem_free_object(struct drm_gem_object *obj)
                        omap_gem_detach_pages(obj);
 
                if (!is_shmem(obj)) {
-                       dma_free_writecombine(dev->dev, obj->size,
-                                       omap_obj->vaddr, omap_obj->paddr);
+                       dma_free_wc(dev->dev, obj->size, omap_obj->vaddr,
+                                   omap_obj->paddr);
                } else if (omap_obj->vaddr) {
                        vunmap(omap_obj->vaddr);
                }
@@ -1395,8 +1395,8 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
                /* attempt to allocate contiguous memory if we don't
                 * have DMM for remappign discontiguous buffers
                 */
-               omap_obj->vaddr =  dma_alloc_writecombine(dev->dev, size,
-                               &omap_obj->paddr, GFP_KERNEL);
+               omap_obj->vaddr =  dma_alloc_wc(dev->dev, size,
+                                               &omap_obj->paddr, GFP_KERNEL);
                if (!omap_obj->vaddr) {
                        kfree(omap_obj);
 
index 44ee72e04df9e953bafe64cdfdadf2f01c1f9bce..6af832545bc5b76b44e836553e72005f01012bbe 100644 (file)
@@ -315,15 +315,27 @@ int radeon_dp_get_dp_link_config(struct drm_connector *connector,
        unsigned max_lane_num = drm_dp_max_lane_count(dpcd);
        unsigned lane_num, i, max_pix_clock;
 
-       for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
-               for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
-                       max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
+       if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+           ENCODER_OBJECT_ID_NUTMEG) {
+               for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+                       max_pix_clock = (lane_num * 270000 * 8) / bpp;
                        if (max_pix_clock >= pix_clock) {
                                *dp_lanes = lane_num;
-                               *dp_rate = link_rates[i];
+                               *dp_rate = 270000;
                                return 0;
                        }
                }
+       } else {
+               for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) {
+                       for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) {
+                               max_pix_clock = (lane_num * link_rates[i] * 8) / bpp;
+                               if (max_pix_clock >= pix_clock) {
+                                       *dp_lanes = lane_num;
+                                       *dp_rate = link_rates[i];
+                                       return 0;
+                               }
+                       }
+               }
        }
 
        return -EINVAL;
index a9b01bcf7d0a2242cf181ef31a77cf9150e6e8f8..432480ff9d228857d57170b3353c143bf0501c3f 100644 (file)
@@ -34,7 +34,6 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #endif /* CONFIG_PPC_PMAC */
 
 /* from radeon_legacy_encoder.c */
index 902b59cebac584b075639a2b7d34f031907cc3d1..4197ca1bb1e4d3f5d1455cc7c282787778660e9c 100644 (file)
@@ -1744,7 +1744,6 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        }
 
        drm_kms_helper_poll_enable(dev);
-       drm_helper_hpd_irq_event(dev);
 
        /* set the power state here in case we are a PX system or headless */
        if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled)
index 298ea1c453c3638fecdf6cef5afce1a48fdefa82..2d9196a447fdc94a49140dcad365b6d3957d43f6 100644 (file)
@@ -403,7 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work)
        struct drm_crtc *crtc = &radeon_crtc->base;
        unsigned long flags;
        int r;
-       int vpos, hpos, stat, min_udelay;
+       int vpos, hpos, stat, min_udelay = 0;
+       unsigned repcnt = 4;
        struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
 
         down_read(&rdev->exclusive_lock);
@@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
         * In practice this won't execute very often unless on very fast
         * machines because the time window for this to happen is very small.
         */
-       for (;;) {
+       while (radeon_crtc->enabled && --repcnt) {
                /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
                 * start in hpos, and to the "fudged earlier" vblank start in
                 * vpos.
@@ -470,12 +471,24 @@ static void radeon_flip_work_func(struct work_struct *__work)
                        break;
 
                /* Sleep at least until estimated real start of hw vblank */
-               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
+               if (min_udelay > vblank->framedur_ns / 2000) {
+                       /* Don't wait ridiculously long - something is wrong */
+                       repcnt = 0;
+                       break;
+               }
+               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                usleep_range(min_udelay, 2 * min_udelay);
                spin_lock_irqsave(&crtc->dev->event_lock, flags);
        };
 
+       if (!repcnt)
+               DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
+                                "framedur %d, linedur %d, stat %d, vpos %d, "
+                                "hpos %d\n", work->crtc_id, min_udelay,
+                                vblank->framedur_ns / 1000,
+                                vblank->linedur_ns / 1000, stat, vpos, hpos);
+
        /* do the flip (mmio) */
        radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
 
index 248c5a9fb0b6faa19467f130428c0c9e7cb3223f..7a98823bacd1cd5da33c9e11dc7f798ae1a866d9 100644 (file)
@@ -1082,10 +1082,6 @@ force:
        /* update displays */
        radeon_dpm_display_configuration_changed(rdev);
 
-       rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
-       rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
-       rdev->pm.dpm.single_display = single_display;
-
        /* wait for the rings to drain */
        for (i = 0; i < RADEON_NUM_RINGS; i++) {
                struct radeon_ring *ring = &rdev->ring[i];
@@ -1101,6 +1097,10 @@ force:
 
        radeon_dpm_post_set_power_state(rdev);
 
+       rdev->pm.dpm.current_active_crtcs = rdev->pm.dpm.new_active_crtcs;
+       rdev->pm.dpm.current_active_crtc_count = rdev->pm.dpm.new_active_crtc_count;
+       rdev->pm.dpm.single_display = single_display;
+
        if (rdev->asic->dpm.force_performance_level) {
                if (rdev->pm.dpm.thermal_active) {
                        enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
index 807863106b8da813949383f291830c60d087d4e0..bd736ace3f8147b25c3362cb2e46aeeef2ef87b8 100644 (file)
@@ -157,17 +157,15 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
                cursor->height = src_h;
 
                if (cursor->pixmap.base)
-                       dma_free_writecombine(cursor->dev,
-                                             cursor->pixmap.size,
-                                             cursor->pixmap.base,
-                                             cursor->pixmap.paddr);
+                       dma_free_wc(cursor->dev, cursor->pixmap.size,
+                                   cursor->pixmap.base, cursor->pixmap.paddr);
 
                cursor->pixmap.size = cursor->width * cursor->height;
 
-               cursor->pixmap.base = dma_alloc_writecombine(cursor->dev,
-                                                       cursor->pixmap.size,
-                                                       &cursor->pixmap.paddr,
-                                                       GFP_KERNEL | GFP_DMA);
+               cursor->pixmap.base = dma_alloc_wc(cursor->dev,
+                                                  cursor->pixmap.size,
+                                                  &cursor->pixmap.paddr,
+                                                  GFP_KERNEL | GFP_DMA);
                if (!cursor->pixmap.base) {
                        DRM_ERROR("Failed to allocate memory for pixmap\n");
                        return;
@@ -252,8 +250,8 @@ struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
 
        /* Allocate clut buffer */
        size = 0x100 * sizeof(unsigned short);
-       cursor->clut = dma_alloc_writecombine(dev, size, &cursor->clut_paddr,
-                                             GFP_KERNEL | GFP_DMA);
+       cursor->clut = dma_alloc_wc(dev, size, &cursor->clut_paddr,
+                                   GFP_KERNEL | GFP_DMA);
 
        if (!cursor->clut) {
                DRM_ERROR("Failed to allocate memory for cursor clut\n");
@@ -286,7 +284,7 @@ struct drm_plane *sti_cursor_create(struct drm_device *drm_dev,
        return &cursor->plane.drm_plane;
 
 err_plane:
-       dma_free_writecombine(dev, size, cursor->clut, cursor->clut_paddr);
+       dma_free_wc(dev, size, cursor->clut, cursor->clut_paddr);
 err_clut:
        devm_kfree(dev, cursor);
        return NULL;
index f9a1d92c9d9519c3ddbeefe33277f26af4f37a32..514551c857bbda87b8fcbbca215bdc17c7bdfe67 100644 (file)
@@ -312,8 +312,7 @@ static void sti_gdp_init(struct sti_gdp *gdp)
        /* Allocate all the nodes within a single memory page */
        size = sizeof(struct sti_gdp_node) *
            GDP_NODE_PER_FIELD * GDP_NODE_NB_BANK;
-       base = dma_alloc_writecombine(gdp->dev,
-                                     size, &dma_addr, GFP_KERNEL | GFP_DMA);
+       base = dma_alloc_wc(gdp->dev, size, &dma_addr, GFP_KERNEL | GFP_DMA);
 
        if (!base) {
                DRM_ERROR("Failed to allocate memory for GDP node\n");
index 43861b52261d7e4fee17839351577e5d4b90080f..1d3c3d029603d030ec02809fd14026d6d5df08da 100644 (file)
@@ -617,9 +617,9 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
 
        /* Allocate memory for the VDP commands */
        size = NB_VDP_CMD * sizeof(struct sti_hqvdp_cmd);
-       hqvdp->hqvdp_cmd = dma_alloc_writecombine(hqvdp->dev, size,
-                                        &hqvdp->hqvdp_cmd_paddr,
-                                        GFP_KERNEL | GFP_DMA);
+       hqvdp->hqvdp_cmd = dma_alloc_wc(hqvdp->dev, size,
+                                       &hqvdp->hqvdp_cmd_paddr,
+                                       GFP_KERNEL | GFP_DMA);
        if (!hqvdp->hqvdp_cmd) {
                DRM_ERROR("Failed to allocate memory for VDP cmd\n");
                return;
index 33add93b4ed96826a3f7da9bfc5d11d0018eff8b..3b0d8c392b707e93e56a0b391345d58d3a5eef4c 100644 (file)
@@ -175,8 +175,7 @@ static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo)
                sg_free_table(bo->sgt);
                kfree(bo->sgt);
        } else if (bo->vaddr) {
-               dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr,
-                                     bo->paddr);
+               dma_free_wc(drm->dev, bo->gem.size, bo->vaddr, bo->paddr);
        }
 }
 
@@ -233,8 +232,8 @@ static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo)
        } else {
                size_t size = bo->gem.size;
 
-               bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr,
-                                                  GFP_KERNEL | __GFP_NOWARN);
+               bo->vaddr = dma_alloc_wc(drm->dev, size, &bo->paddr,
+                                        GFP_KERNEL | __GFP_NOWARN);
                if (!bo->vaddr) {
                        dev_err(drm->dev,
                                "failed to allocate buffer of size %zu\n",
@@ -472,8 +471,8 @@ int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma)
                vma->vm_flags &= ~VM_PFNMAP;
                vma->vm_pgoff = 0;
 
-               ret = dma_mmap_writecombine(gem->dev->dev, vma, bo->vaddr,
-                                           bo->paddr, gem->size);
+               ret = dma_mmap_wc(gem->dev->dev, vma, bo->vaddr, bo->paddr,
+                                 gem->size);
                if (ret) {
                        drm_gem_vm_close(vma);
                        return ret;
index 22278bcfc60eac4ed40fac0e31dda840aa4b703e..034ef2de903769f521c50c6a6936a5099e69578f 100644 (file)
@@ -398,9 +398,8 @@ int vc4_mmap(struct file *filp, struct vm_area_struct *vma)
        vma->vm_flags &= ~VM_PFNMAP;
        vma->vm_pgoff = 0;
 
-       ret = dma_mmap_writecombine(bo->base.base.dev->dev, vma,
-                                   bo->base.vaddr, bo->base.paddr,
-                                   vma->vm_end - vma->vm_start);
+       ret = dma_mmap_wc(bo->base.base.dev->dev, vma, bo->base.vaddr,
+                         bo->base.paddr, vma->vm_end - vma->vm_start);
        if (ret)
                drm_gem_vm_close(vma);
 
index db082bea8dafd023fa6ad19719f7fadf5ebfcad5..c5a1a08b0449004670b79947e68f0ba7fb8afb50 100644 (file)
@@ -563,6 +563,8 @@ static void vmw_sou_connector_destroy(struct drm_connector *connector)
 
 static const struct drm_connector_funcs vmw_sou_connector_funcs = {
        .dpms = vmw_du_connector_dpms,
+       .detect = vmw_du_connector_detect,
+       .fill_modes = vmw_du_connector_fill_modes,
        .set_property = vmw_du_connector_set_property,
        .destroy = vmw_sou_connector_destroy,
 };
index da462afcb225ea6958918b3d8ff52a0ee928cca3..dd2dbb9746cebc337b17733eb41c4cf4536d75c6 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/host1x.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 #include "bus.h"
 #include "dev.h"
@@ -394,6 +395,7 @@ static int host1x_device_add(struct host1x *host1x,
        device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask;
        device->dev.dma_mask = &device->dev.coherent_dma_mask;
        dev_set_name(&device->dev, "%s", driver->driver.name);
+       of_dma_configure(&device->dev, host1x->dev->of_node);
        device->dev.release = host1x_device_release;
        device->dev.bus = &host1x_bus_type;
        device->dev.parent = host1x->dev;
index 5a8c8d55317ab4f622c5754f509d5d3660a3e47c..a18db4d5347cefa99847df944be3a3b364de089a 100644 (file)
@@ -52,8 +52,8 @@ static void host1x_pushbuffer_destroy(struct push_buffer *pb)
        struct host1x *host1x = cdma_to_host1x(cdma);
 
        if (pb->phys != 0)
-               dma_free_writecombine(host1x->dev, pb->size_bytes + 4,
-                                     pb->mapped, pb->phys);
+               dma_free_wc(host1x->dev, pb->size_bytes + 4, pb->mapped,
+                           pb->phys);
 
        pb->mapped = NULL;
        pb->phys = 0;
@@ -76,8 +76,8 @@ static int host1x_pushbuffer_init(struct push_buffer *pb)
        pb->pos = 0;
 
        /* allocate and map pushbuffer memory */
-       pb->mapped = dma_alloc_writecombine(host1x->dev, pb->size_bytes + 4,
-                                           &pb->phys, GFP_KERNEL);
+       pb->mapped = dma_alloc_wc(host1x->dev, pb->size_bytes + 4, &pb->phys,
+                                 GFP_KERNEL);
        if (!pb->mapped)
                goto fail;
 
index 314bf3718cc799b01462dd2cee678dcec604632e..ff348690df94a0eebcddaadedfbf440cb05cac4a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/of_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/host1x.h>
@@ -68,6 +69,7 @@ static const struct host1x_info host1x01_info = {
        .nb_bases       = 8,
        .init           = host1x01_init,
        .sync_offset    = 0x3000,
+       .dma_mask       = DMA_BIT_MASK(32),
 };
 
 static const struct host1x_info host1x02_info = {
@@ -77,6 +79,7 @@ static const struct host1x_info host1x02_info = {
        .nb_bases = 12,
        .init = host1x02_init,
        .sync_offset = 0x3000,
+       .dma_mask = DMA_BIT_MASK(32),
 };
 
 static const struct host1x_info host1x04_info = {
@@ -86,6 +89,7 @@ static const struct host1x_info host1x04_info = {
        .nb_bases = 64,
        .init = host1x04_init,
        .sync_offset = 0x2100,
+       .dma_mask = DMA_BIT_MASK(34),
 };
 
 static const struct host1x_info host1x05_info = {
@@ -95,6 +99,7 @@ static const struct host1x_info host1x05_info = {
        .nb_bases = 64,
        .init = host1x05_init,
        .sync_offset = 0x2100,
+       .dma_mask = DMA_BIT_MASK(34),
 };
 
 static struct of_device_id host1x_of_match[] = {
@@ -148,6 +153,8 @@ static int host1x_probe(struct platform_device *pdev)
        if (IS_ERR(host->regs))
                return PTR_ERR(host->regs);
 
+       dma_set_mask_and_coherent(host->dev, host->info->dma_mask);
+
        if (host->info->init) {
                err = host->info->init(host);
                if (err)
index 0b6e8e9629c5330fbc7fadba1a1ae318ae07da12..dace124994bb2683cc0c66218dcd5cdd15902d2b 100644 (file)
@@ -96,6 +96,7 @@ struct host1x_info {
        int     nb_mlocks;              /* host1x: number of mlocks */
        int     (*init)(struct host1x *); /* initialize per SoC ops */
        int     sync_offset;
+       u64     dma_mask;               /* mask of addressable memory */
 };
 
 struct host1x {
index 63bd63f3c7dfd2da2fd3d9ae58bba1473bceb70b..defa7995f2131a06ddc88e09d13d914f8a244ea1 100644 (file)
@@ -467,9 +467,8 @@ static inline int copy_gathers(struct host1x_job *job, struct device *dev)
                size += g->words * sizeof(u32);
        }
 
-       job->gather_copy_mapped = dma_alloc_writecombine(dev, size,
-                                                        &job->gather_copy,
-                                                        GFP_KERNEL);
+       job->gather_copy_mapped = dma_alloc_wc(dev, size, &job->gather_copy,
+                                              GFP_KERNEL);
        if (!job->gather_copy_mapped) {
                job->gather_copy_mapped = NULL;
                return -ENOMEM;
@@ -578,9 +577,8 @@ void host1x_job_unpin(struct host1x_job *job)
        job->num_unpins = 0;
 
        if (job->gather_copy_size)
-               dma_free_writecombine(job->channel->dev, job->gather_copy_size,
-                                     job->gather_copy_mapped,
-                                     job->gather_copy);
+               dma_free_wc(job->channel->dev, job->gather_copy_size,
+                           job->gather_copy_mapped, job->gather_copy);
 }
 EXPORT_SYMBOL(host1x_job_unpin);
 
index f2e13eb8339ffc1287110e247e0e54e922b7d72a..e00db3f510dd425c62565d913c937c5638a072d5 100644 (file)
@@ -1050,6 +1050,17 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
        for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
                const struct ipu_platform_reg *reg = &client_reg[i];
                struct platform_device *pdev;
+               struct device_node *of_node;
+
+               /* Associate subdevice with the corresponding port node */
+               of_node = of_graph_get_port_by_id(dev->of_node, i);
+               if (!of_node) {
+                       dev_info(dev,
+                                "no port@%d node in %s, not using %s%d\n",
+                                i, dev->of_node->full_name,
+                                (i / 2) ? "DI" : "CSI", i % 2);
+                       continue;
+               }
 
                pdev = platform_device_alloc(reg->name, id++);
                if (!pdev) {
@@ -1057,17 +1068,9 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
                        goto err_register;
                }
 
+               pdev->dev.of_node = of_node;
                pdev->dev.parent = dev;
 
-               /* Associate subdevice with the corresponding port node */
-               pdev->dev.of_node = of_graph_get_port_by_id(dev->of_node, i);
-               if (!pdev->dev.of_node) {
-                       dev_err(dev, "missing port@%d node in %s\n", i,
-                               dev->of_node->full_name);
-                       ret = -ENODEV;
-                       goto err_register;
-               }
-
                ret = platform_device_add_data(pdev, &reg->pdata,
                                               sizeof(reg->pdata));
                if (!ret)
@@ -1289,10 +1292,6 @@ static int ipu_probe(struct platform_device *pdev)
        ipu->irq_sync = irq_sync;
        ipu->irq_err = irq_err;
 
-       ret = ipu_irq_init(ipu);
-       if (ret)
-               goto out_failed_irq;
-
        ret = device_reset(&pdev->dev);
        if (ret) {
                dev_err(&pdev->dev, "failed to reset: %d\n", ret);
@@ -1302,6 +1301,10 @@ static int ipu_probe(struct platform_device *pdev)
        if (ret)
                goto out_failed_reset;
 
+       ret = ipu_irq_init(ipu);
+       if (ret)
+               goto out_failed_irq;
+
        /* Set MCU_T to divide MCU access window into 2 */
        ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
                        IPU_DISP_GEN);
@@ -1324,9 +1327,9 @@ static int ipu_probe(struct platform_device *pdev)
 failed_add_clients:
        ipu_submodules_exit(ipu);
 failed_submodules_init:
-out_failed_reset:
        ipu_irq_exit(ipu);
 out_failed_irq:
+out_failed_reset:
        clk_disable_unprepare(ipu->clk);
        return ret;
 }
index 4ebc796b4f33b83a5e6918c227d8c1bd437ed80e..2f8c0f40930bd09a414ae52e544e4bf2ed5b879a 100644 (file)
@@ -256,12 +256,6 @@ struct hv_monitor_page {
        u8 rsvdz4[1984];
 };
 
-/* Declare the various hypercall operations. */
-enum hv_call_code {
-       HVCALL_POST_MESSAGE     = 0x005c,
-       HVCALL_SIGNAL_EVENT     = 0x005d,
-};
-
 /* Definition of the hv_post_message hypercall input structure. */
 struct hv_input_post_message {
        union hv_connection_id connectionid;
index 60fb80bd353d601563c57710d8e897d0af50bd30..5c2d13a687aab5c1367429c567ac5cf118508c7d 100644 (file)
@@ -685,6 +685,20 @@ config SENSORS_LTC2945
          This driver can also be built as a module. If so, the module will
          be called ltc2945.
 
+config SENSORS_LTC2990
+       tristate "Linear Technology LTC2990 (current monitoring mode only)"
+       depends on I2C
+       help
+         If you say yes here you get support for Linear Technology LTC2990
+         I2C System Monitor. The LTC2990 supports a combination of voltage,
+         current and temperature monitoring, but in addition to the Vcc supply
+         voltage and chip temperature, this driver currently only supports
+         reading two currents by measuring two differential voltages across
+         series resistors.
+
+         This driver can also be built as a module. If so, the module will
+         be called ltc2990.
+
 config SENSORS_LTC4151
        tristate "Linear Technology LTC4151"
        depends on I2C
@@ -1127,7 +1141,7 @@ config SENSORS_NTC_THERMISTOR
 
          Currently, this driver supports
          NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, NCP15WL333,
-         and NCP03WF104 from Murata and B57330V2103 from EPCOS.
+         NCP03WF104 and NCP15XH103 from Murata and B57330V2103 from EPCOS.
 
          This driver can also be built as a module.  If so, the module
          will be called ntc-thermistor.
@@ -1176,6 +1190,21 @@ config SENSORS_NCT7904
          This driver can also be built as a module.  If so, the module
          will be called nct7904.
 
+config SENSORS_NSA320
+       tristate "ZyXEL NSA320 and compatible fan speed and temperature sensors"
+       depends on GPIOLIB && OF
+       depends on MACH_KIRKWOOD || COMPILE_TEST
+       help
+         If you say yes here you get support for hardware monitoring
+         for the ZyXEL NSA320 Media Server and other compatible devices
+         (probably the NSA325 and some NSA310 variants).
+
+         The sensor data is taken from a Holtek HT46R065 microcontroller
+         connected to GPIO lines.
+
+         This driver can also be built as a module. If so, the module
+         will be called nsa320-hwmon.
+
 config SENSORS_PCF8591
        tristate "Philips PCF8591 ADC/DAC"
        depends on I2C
index 30c94df314658fc8f9dcb04c7ae05eb141c979e1..58cc3acba7e7bc1141c8133c08ba0c4b55428cb1 100644 (file)
@@ -100,6 +100,7 @@ obj-$(CONFIG_SENSORS_LM95234)       += lm95234.o
 obj-$(CONFIG_SENSORS_LM95241)  += lm95241.o
 obj-$(CONFIG_SENSORS_LM95245)  += lm95245.o
 obj-$(CONFIG_SENSORS_LTC2945)  += ltc2945.o
+obj-$(CONFIG_SENSORS_LTC2990)  += ltc2990.o
 obj-$(CONFIG_SENSORS_LTC4151)  += ltc4151.o
 obj-$(CONFIG_SENSORS_LTC4215)  += ltc4215.o
 obj-$(CONFIG_SENSORS_LTC4222)  += ltc4222.o
@@ -123,6 +124,7 @@ obj-$(CONFIG_SENSORS_NCT6683)       += nct6683.o
 obj-$(CONFIG_SENSORS_NCT6775)  += nct6775.o
 obj-$(CONFIG_SENSORS_NCT7802)  += nct7802.o
 obj-$(CONFIG_SENSORS_NCT7904)  += nct7904.o
+obj-$(CONFIG_SENSORS_NSA320)   += nsa320-hwmon.o
 obj-$(CONFIG_SENSORS_NTC_THERMISTOR)   += ntc_thermistor.o
 obj-$(CONFIG_SENSORS_PC87360)  += pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)  += pc87427.o
@@ -149,7 +151,7 @@ obj-$(CONFIG_SENSORS_TMP103)        += tmp103.o
 obj-$(CONFIG_SENSORS_TMP401)   += tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)   += tmp421.o
 obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
-obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress.o
+obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress-hwmon.o
 obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
 obj-$(CONFIG_SENSORS_VIA686A)  += via686a.o
 obj-$(CONFIG_SENSORS_VT1211)   += vt1211.o
index 17ae2eb26ce21604edf9a1d9df4e24abe01980d6..b550ba5fa58a9050c178483b47a68c2267e9d8b2 100644 (file)
@@ -67,6 +67,7 @@ static int iio_hwmon_probe(struct platform_device *pdev)
        enum iio_chan_type type;
        struct iio_channel *channels;
        const char *name = "iio_hwmon";
+       char *sname;
 
        if (dev->of_node && dev->of_node->name)
                name = dev->of_node->name;
@@ -144,7 +145,15 @@ static int iio_hwmon_probe(struct platform_device *pdev)
 
        st->attr_group.attrs = st->attrs;
        st->groups[0] = &st->attr_group;
-       st->hwmon_dev = hwmon_device_register_with_groups(dev, name, st,
+
+       sname = devm_kstrdup(dev, name, GFP_KERNEL);
+       if (!sname) {
+               ret = -ENOMEM;
+               goto error_release_channels;
+       }
+
+       strreplace(sname, '-', '_');
+       st->hwmon_dev = hwmon_device_register_with_groups(dev, sname, st,
                                                          st->groups);
        if (IS_ERR(st->hwmon_dev)) {
                ret = PTR_ERR(st->hwmon_dev);
diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c
new file mode 100644 (file)
index 0000000..8f8fe05
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Driver for Linear Technology LTC2990 power monitor
+ *
+ * Copyright (C) 2014 Topic Embedded Products
+ * Author: Mike Looijmans <mike.looijmans@topic.nl>
+ *
+ * License: GPLv2
+ *
+ * This driver assumes the chip is wired as a dual current monitor, and
+ * reports the voltage drop across two series resistors. It also reports
+ * the chip's internal temperature and Vcc power supply voltage.
+ */
+
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#define LTC2990_STATUS 0x00
+#define LTC2990_CONTROL        0x01
+#define LTC2990_TRIGGER        0x02
+#define LTC2990_TINT_MSB       0x04
+#define LTC2990_V1_MSB 0x06
+#define LTC2990_V2_MSB 0x08
+#define LTC2990_V3_MSB 0x0A
+#define LTC2990_V4_MSB 0x0C
+#define LTC2990_VCC_MSB        0x0E
+
+#define LTC2990_CONTROL_KELVIN         BIT(7)
+#define LTC2990_CONTROL_SINGLE         BIT(6)
+#define LTC2990_CONTROL_MEASURE_ALL    (0x3 << 3)
+#define LTC2990_CONTROL_MODE_CURRENT   0x06
+#define LTC2990_CONTROL_MODE_VOLTAGE   0x07
+
+/* convert raw register value to sign-extended integer in 16-bit range */
+static int ltc2990_voltage_to_int(int raw)
+{
+       if (raw & BIT(14))
+               return -(0x4000 - (raw & 0x3FFF)) << 2;
+       else
+               return (raw & 0x3FFF) << 2;
+}
+
+/* Return the converted value from the given register in uV or mC */
+static int ltc2990_get_value(struct i2c_client *i2c, u8 reg, int *result)
+{
+       int val;
+
+       val = i2c_smbus_read_word_swapped(i2c, reg);
+       if (unlikely(val < 0))
+               return val;
+
+       switch (reg) {
+       case LTC2990_TINT_MSB:
+               /* internal temp, 0.0625 degrees/LSB, 13-bit  */
+               val = (val & 0x1FFF) << 3;
+               *result = (val * 1000) >> 7;
+               break;
+       case LTC2990_V1_MSB:
+       case LTC2990_V3_MSB:
+                /* Vx-Vy, 19.42uV/LSB. Depends on mode. */
+               *result = ltc2990_voltage_to_int(val) * 1942 / (4 * 100);
+               break;
+       case LTC2990_VCC_MSB:
+               /* Vcc, 305.18μV/LSB, 2.5V offset */
+               *result = (ltc2990_voltage_to_int(val) * 30518 /
+                          (4 * 100 * 1000)) + 2500;
+               break;
+       default:
+               return -EINVAL; /* won't happen, keep compiler happy */
+       }
+
+       return 0;
+}
+
+static ssize_t ltc2990_show_value(struct device *dev,
+                                 struct device_attribute *da, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       int value;
+       int ret;
+
+       ret = ltc2990_get_value(dev_get_drvdata(dev), attr->index, &value);
+       if (unlikely(ret < 0))
+               return ret;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL,
+                         LTC2990_TINT_MSB);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL,
+                         LTC2990_V1_MSB);
+static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL,
+                         LTC2990_V3_MSB);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL,
+                         LTC2990_VCC_MSB);
+
+static struct attribute *ltc2990_attrs[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_curr1_input.dev_attr.attr,
+       &sensor_dev_attr_curr2_input.dev_attr.attr,
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(ltc2990);
+
+static int ltc2990_i2c_probe(struct i2c_client *i2c,
+                            const struct i2c_device_id *id)
+{
+       int ret;
+       struct device *hwmon_dev;
+
+       if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+                                    I2C_FUNC_SMBUS_WORD_DATA))
+               return -ENODEV;
+
+       /* Setup continuous mode, current monitor */
+       ret = i2c_smbus_write_byte_data(i2c, LTC2990_CONTROL,
+                                       LTC2990_CONTROL_MEASURE_ALL |
+                                       LTC2990_CONTROL_MODE_CURRENT);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Error: Failed to set control mode.\n");
+               return ret;
+       }
+       /* Trigger once to start continuous conversion */
+       ret = i2c_smbus_write_byte_data(i2c, LTC2990_TRIGGER, 1);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Error: Failed to start acquisition.\n");
+               return ret;
+       }
+
+       hwmon_dev = devm_hwmon_device_register_with_groups(&i2c->dev,
+                                                          i2c->name,
+                                                          i2c,
+                                                          ltc2990_groups);
+
+       return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id ltc2990_i2c_id[] = {
+       { "ltc2990", 0 },
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id);
+
+static struct i2c_driver ltc2990_i2c_driver = {
+       .driver = {
+               .name = "ltc2990",
+       },
+       .probe    = ltc2990_i2c_probe,
+       .id_table = ltc2990_i2c_id,
+};
+
+module_i2c_driver(ltc2990_i2c_driver);
+
+MODULE_DESCRIPTION("LTC2990 Sensor Driver");
+MODULE_AUTHOR("Topic Embedded Products");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/nsa320-hwmon.c b/drivers/hwmon/nsa320-hwmon.c
new file mode 100644 (file)
index 0000000..0517a26
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * drivers/hwmon/nsa320-hwmon.c
+ *
+ * ZyXEL NSA320 Media Servers
+ * hardware monitoring
+ *
+ * Copyright (C) 2016 Adam Baker <linux@baker-net.org.uk>
+ * based on a board file driver
+ * Copyright (C) 2012 Peter Schildmann <linux@schildmann.info>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+/* Tests for error return values rely upon this value being < 0x80 */
+#define MAGIC_NUMBER 0x55
+
+/*
+ * The Zyxel hwmon MCU is a Holtek HT46R065 that is factory programmed
+ * to perform temperature and fan speed monitoring. It is read by taking
+ * the active pin low. The 32 bit output word is then clocked onto the
+ * data line. The MSB of the data word is a magic nuber to indicate it
+ * has been read correctly, the next byte is the fan speed (in hundreds
+ * of RPM) and the last two bytes are the temperature (in tenths of a
+ * degree)
+ */
+
+struct nsa320_hwmon {
+       struct mutex            update_lock;    /* lock GPIO operations */
+       unsigned long           last_updated;   /* jiffies */
+       unsigned long           mcu_data;
+       struct gpio_desc        *act;
+       struct gpio_desc        *clk;
+       struct gpio_desc        *data;
+};
+
+enum nsa320_inputs {
+       NSA320_TEMP = 0,
+       NSA320_FAN = 1,
+};
+
+static const char * const nsa320_input_names[] = {
+       [NSA320_TEMP] = "System Temperature",
+       [NSA320_FAN] = "Chassis Fan",
+};
+
+/*
+ * Although this protocol looks similar to SPI the long delay
+ * between the active (aka chip select) signal and the shorter
+ * delay between clock pulses are needed for reliable operation.
+ * The delays provided are taken from the manufacturer kernel,
+ * testing suggest they probably incorporate a reasonable safety
+ * margin. (The single device tested became unreliable if the
+ * delay was reduced to 1/10th of this value.)
+ */
+static s32 nsa320_hwmon_update(struct device *dev)
+{
+       u32 mcu_data;
+       u32 mask;
+       struct nsa320_hwmon *hwmon = dev_get_drvdata(dev);
+
+       mutex_lock(&hwmon->update_lock);
+
+       mcu_data = hwmon->mcu_data;
+
+       if (time_after(jiffies, hwmon->last_updated + HZ) || mcu_data == 0) {
+               gpiod_set_value(hwmon->act, 1);
+               msleep(100);
+
+               mcu_data = 0;
+               for (mask = BIT(31); mask; mask >>= 1) {
+                       gpiod_set_value(hwmon->clk, 0);
+                       usleep_range(100, 200);
+                       gpiod_set_value(hwmon->clk, 1);
+                       usleep_range(100, 200);
+                       if (gpiod_get_value(hwmon->data))
+                               mcu_data |= mask;
+               }
+
+               gpiod_set_value(hwmon->act, 0);
+               dev_dbg(dev, "Read raw MCU data %08x\n", mcu_data);
+
+               if ((mcu_data >> 24) != MAGIC_NUMBER) {
+                       dev_dbg(dev, "Read invalid MCU data %08x\n", mcu_data);
+                       mcu_data = -EIO;
+               } else {
+                       hwmon->mcu_data = mcu_data;
+                       hwmon->last_updated = jiffies;
+               }
+       }
+
+       mutex_unlock(&hwmon->update_lock);
+
+       return mcu_data;
+}
+
+static ssize_t show_label(struct device *dev,
+                         struct device_attribute *attr, char *buf)
+{
+       int channel = to_sensor_dev_attr(attr)->index;
+
+       return sprintf(buf, "%s\n", nsa320_input_names[channel]);
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       s32 mcu_data = nsa320_hwmon_update(dev);
+
+       if (mcu_data < 0)
+               return mcu_data;
+
+       return sprintf(buf, "%d\n", (mcu_data & 0xffff) * 100);
+}
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       s32 mcu_data = nsa320_hwmon_update(dev);
+
+       if (mcu_data < 0)
+               return mcu_data;
+
+       return sprintf(buf, "%d\n", ((mcu_data & 0xff0000) >> 16) * 100);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, NSA320_TEMP);
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, show_label, NULL, NSA320_FAN);
+static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL);
+
+static struct attribute *nsa320_attrs[] = {
+       &sensor_dev_attr_temp1_label.dev_attr.attr,
+       &dev_attr_temp1_input.attr,
+       &sensor_dev_attr_fan1_label.dev_attr.attr,
+       &dev_attr_fan1_input.attr,
+       NULL
+};
+
+ATTRIBUTE_GROUPS(nsa320);
+
+static const struct of_device_id of_nsa320_hwmon_match[] = {
+       { .compatible = "zyxel,nsa320-mcu", },
+       { },
+};
+
+static int nsa320_hwmon_probe(struct platform_device *pdev)
+{
+       struct nsa320_hwmon     *hwmon;
+       struct device           *classdev;
+
+       hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL);
+       if (!hwmon)
+               return -ENOMEM;
+
+       /* Look up the GPIO pins to use */
+       hwmon->act = devm_gpiod_get(&pdev->dev, "act", GPIOD_OUT_LOW);
+       if (IS_ERR(hwmon->act))
+               return PTR_ERR(hwmon->act);
+
+       hwmon->clk = devm_gpiod_get(&pdev->dev, "clk", GPIOD_OUT_HIGH);
+       if (IS_ERR(hwmon->clk))
+               return PTR_ERR(hwmon->clk);
+
+       hwmon->data = devm_gpiod_get(&pdev->dev, "data", GPIOD_IN);
+       if (IS_ERR(hwmon->data))
+               return PTR_ERR(hwmon->data);
+
+       mutex_init(&hwmon->update_lock);
+
+       classdev = devm_hwmon_device_register_with_groups(&pdev->dev,
+                                       "nsa320", hwmon, nsa320_groups);
+
+       return PTR_ERR_OR_ZERO(classdev);
+
+}
+
+/* All allocations use devres so remove() is not needed. */
+
+static struct platform_driver nsa320_hwmon_driver = {
+       .probe = nsa320_hwmon_probe,
+       .driver = {
+               .name = "nsa320-hwmon",
+               .of_match_table = of_match_ptr(of_nsa320_hwmon_match),
+       },
+};
+
+module_platform_driver(nsa320_hwmon_driver);
+
+MODULE_DEVICE_TABLE(of, of_nsa320_hwmon_match);
+MODULE_AUTHOR("Peter Schildmann <linux@schildmann.info>");
+MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>");
+MODULE_DESCRIPTION("NSA320 Hardware Monitoring");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:nsa320-hwmon");
index feed30646d91837a5ea9ddab9e5ccd7e812ace47..faa6e8dfbaaf56a28bcf305b1db3da04aa7f6be3 100644 (file)
@@ -54,6 +54,7 @@ static const struct platform_device_id ntc_thermistor_id[] = {
        { "ncp15wl333", TYPE_NCPXXWL333 },
        { "b57330v2103", TYPE_B57330V2103},
        { "ncp03wf104", TYPE_NCPXXWF104 },
+       { "ncp15xh103", TYPE_NCPXXXH103 },
        { },
 };
 
@@ -173,6 +174,43 @@ static const struct ntc_compensation ncpXXwf104[] = {
        { .temp_c       = 125, .ohm     = 2522 },
 };
 
+static const struct ntc_compensation ncpXXxh103[] = {
+       { .temp_c       = -40, .ohm     = 247565 },
+       { .temp_c       = -35, .ohm     = 181742 },
+       { .temp_c       = -30, .ohm     = 135128 },
+       { .temp_c       = -25, .ohm     = 101678 },
+       { .temp_c       = -20, .ohm     = 77373 },
+       { .temp_c       = -15, .ohm     = 59504 },
+       { .temp_c       = -10, .ohm     = 46222 },
+       { .temp_c       = -5, .ohm      = 36244 },
+       { .temp_c       = 0, .ohm       = 28674 },
+       { .temp_c       = 5, .ohm       = 22878 },
+       { .temp_c       = 10, .ohm      = 18399 },
+       { .temp_c       = 15, .ohm      = 14910 },
+       { .temp_c       = 20, .ohm      = 12169 },
+       { .temp_c       = 25, .ohm      = 10000 },
+       { .temp_c       = 30, .ohm      = 8271 },
+       { .temp_c       = 35, .ohm      = 6883 },
+       { .temp_c       = 40, .ohm      = 5762 },
+       { .temp_c       = 45, .ohm      = 4851 },
+       { .temp_c       = 50, .ohm      = 4105 },
+       { .temp_c       = 55, .ohm      = 3492 },
+       { .temp_c       = 60, .ohm      = 2985 },
+       { .temp_c       = 65, .ohm      = 2563 },
+       { .temp_c       = 70, .ohm      = 2211 },
+       { .temp_c       = 75, .ohm      = 1915 },
+       { .temp_c       = 80, .ohm      = 1666 },
+       { .temp_c       = 85, .ohm      = 1454 },
+       { .temp_c       = 90, .ohm      = 1275 },
+       { .temp_c       = 95, .ohm      = 1121 },
+       { .temp_c       = 100, .ohm     = 990 },
+       { .temp_c       = 105, .ohm     = 876 },
+       { .temp_c       = 110, .ohm     = 779 },
+       { .temp_c       = 115, .ohm     = 694 },
+       { .temp_c       = 120, .ohm     = 620 },
+       { .temp_c       = 125, .ohm     = 556 },
+};
+
 /*
  * The following compensation table is from the specification of EPCOS NTC
  * Thermistors Datasheet
@@ -260,6 +298,8 @@ static const struct of_device_id ntc_match[] = {
                .data = &ntc_thermistor_id[5]},
        { .compatible = "murata,ncp03wf104",
                .data = &ntc_thermistor_id[6] },
+       { .compatible = "murata,ncp15xh103",
+               .data = &ntc_thermistor_id[7] },
 
        /* Usage of vendor name "ntc" is deprecated */
        { .compatible = "ntc,ncp15wb473",
@@ -609,6 +649,10 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
                data->comp = ncpXXwf104;
                data->n_comp = ARRAY_SIZE(ncpXXwf104);
                break;
+       case TYPE_NCPXXXH103:
+               data->comp = ncpXXxh103;
+               data->n_comp = ARRAY_SIZE(ncpXXxh103);
+               break;
        default:
                dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
                                pdev_id->driver_data, pdev_id->name);
index 7e5cc3d025efece94357d369837d4806551e3d83..054d3d863802b558106f43e542b613d159bd2a82 100644 (file)
@@ -31,8 +31,8 @@ config SENSORS_ADM1275
        default n
        help
          If you say yes here you get hardware monitoring support for Analog
-         Devices ADM1075, ADM1275, ADM1276, ADM1293, and ADM1294 Hot-Swap
-         Controller and Digital Power Monitors.
+         Devices ADM1075, ADM1275, ADM1276, ADM1278, ADM1293, and ADM1294
+         Hot-Swap Controller and Digital Power Monitors.
 
          This driver can also be built as a module. If so, the module will
          be called adm1275.
index 188af4c89f40fe1d2dee176e024d73cae0d1d46c..3baa4f4a8c5e8bfd23d2fa79cb132b0f495ca49a 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/bitops.h>
 #include "pmbus.h"
 
-enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 };
+enum chips { adm1075, adm1275, adm1276, adm1278, adm1293, adm1294 };
 
 #define ADM1275_MFR_STATUS_IOUT_WARN2  BIT(0)
 #define ADM1293_MFR_STATUS_VAUX_UV_WARN        BIT(5)
@@ -41,6 +41,10 @@ enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 };
 #define ADM1075_IRANGE_25              BIT(3)
 #define ADM1075_IRANGE_MASK            (BIT(3) | BIT(4))
 
+#define ADM1278_TEMP1_EN               BIT(3)
+#define ADM1278_VIN_EN                 BIT(2)
+#define ADM1278_VOUT_EN                        BIT(1)
+
 #define ADM1293_IRANGE_25              0
 #define ADM1293_IRANGE_50              BIT(6)
 #define ADM1293_IRANGE_100             BIT(7)
@@ -54,6 +58,7 @@ enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 };
 
 #define ADM1293_VAUX_EN                        BIT(1)
 
+#define ADM1278_PEAK_TEMP              0xd7
 #define ADM1275_IOUT_WARN2_LIMIT       0xd7
 #define ADM1275_DEVICE_CONFIG          0xd8
 
@@ -80,6 +85,7 @@ struct adm1275_data {
        bool have_iout_min;
        bool have_pin_min;
        bool have_pin_max;
+       bool have_temp_max;
        struct pmbus_driver_info info;
 };
 
@@ -113,6 +119,13 @@ static const struct coefficients adm1276_coefficients[] = {
        [4] = { 2115, 0, -1 },          /* power, vrange not set */
 };
 
+static const struct coefficients adm1278_coefficients[] = {
+       [0] = { 19599, 0, -2 },         /* voltage */
+       [1] = { 800, 20475, -1 },       /* current */
+       [2] = { 6123, 0, -2 },          /* power */
+       [3] = { 42, 31880, -1 },        /* temperature */
+};
+
 static const struct coefficients adm1293_coefficients[] = {
        [0] = { 3333, -1, 0 },          /* voltage, vrange 1.2V */
        [1] = { 5552, -5, -1 },         /* voltage, vrange 7.4V */
@@ -196,6 +209,11 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
                        return -ENXIO;
                ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN);
                break;
+       case PMBUS_VIRT_READ_TEMP_MAX:
+               if (!data->have_temp_max)
+                       return -ENXIO;
+               ret = pmbus_read_word_data(client, 0, ADM1278_PEAK_TEMP);
+               break;
        case PMBUS_VIRT_RESET_IOUT_HISTORY:
        case PMBUS_VIRT_RESET_VOUT_HISTORY:
        case PMBUS_VIRT_RESET_VIN_HISTORY:
@@ -204,6 +222,10 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
                if (!data->have_pin_max)
                        return -ENXIO;
                break;
+       case PMBUS_VIRT_RESET_TEMP_HISTORY:
+               if (!data->have_temp_max)
+                       return -ENXIO;
+               break;
        default:
                ret = -ENODATA;
                break;
@@ -245,6 +267,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
                        ret = pmbus_write_word_data(client, 0,
                                                    ADM1293_PIN_MIN, 0);
                break;
+       case PMBUS_VIRT_RESET_TEMP_HISTORY:
+               ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0);
+               break;
        default:
                ret = -ENODATA;
                break;
@@ -312,6 +337,7 @@ static const struct i2c_device_id adm1275_id[] = {
        { "adm1075", adm1075 },
        { "adm1275", adm1275 },
        { "adm1276", adm1276 },
+       { "adm1278", adm1278 },
        { "adm1293", adm1293 },
        { "adm1294", adm1294 },
        { }
@@ -329,6 +355,7 @@ static int adm1275_probe(struct i2c_client *client,
        const struct i2c_device_id *mid;
        const struct coefficients *coefficients;
        int vindex = -1, voindex = -1, cindex = -1, pindex = -1;
+       int tindex = -1;
 
        if (!i2c_check_functionality(client->adapter,
                                     I2C_FUNC_SMBUS_READ_BYTE_DATA
@@ -386,6 +413,7 @@ static int adm1275_probe(struct i2c_client *client,
        info->format[PSC_VOLTAGE_OUT] = direct;
        info->format[PSC_CURRENT_OUT] = direct;
        info->format[PSC_POWER] = direct;
+       info->format[PSC_TEMPERATURE] = direct;
        info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT;
 
        info->read_word_data = adm1275_read_word_data;
@@ -460,6 +488,27 @@ static int adm1275_probe(struct i2c_client *client,
                        info->func[0] |=
                          PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
                break;
+       case adm1278:
+               data->have_vout = true;
+               data->have_pin_max = true;
+               data->have_temp_max = true;
+
+               coefficients = adm1278_coefficients;
+               vindex = 0;
+               cindex = 1;
+               pindex = 2;
+               tindex = 3;
+
+               info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT;
+               if (config & ADM1278_TEMP1_EN)
+                       info->func[0] |=
+                               PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+               if (config & ADM1278_VIN_EN)
+                       info->func[0] |= PMBUS_HAVE_VIN;
+               if (config & ADM1278_VOUT_EN)
+                       info->func[0] |=
+                               PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+               break;
        case adm1293:
        case adm1294:
                data->have_iout_min = true;
@@ -537,6 +586,11 @@ static int adm1275_probe(struct i2c_client *client,
                info->b[PSC_POWER] = coefficients[pindex].b;
                info->R[PSC_POWER] = coefficients[pindex].R;
        }
+       if (tindex >= 0) {
+               info->m[PSC_TEMPERATURE] = coefficients[tindex].m;
+               info->b[PSC_TEMPERATURE] = coefficients[tindex].b;
+               info->R[PSC_TEMPERATURE] = coefficients[tindex].R;
+       }
 
        return pmbus_do_probe(client, id, info);
 }
diff --git a/drivers/hwmon/vexpress-hwmon.c b/drivers/hwmon/vexpress-hwmon.c
new file mode 100644 (file)
index 0000000..8ba419d
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-hwmon"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/vexpress.h>
+
+struct vexpress_hwmon_data {
+       struct device *hwmon_dev;
+       struct regmap *reg;
+};
+
+static ssize_t vexpress_hwmon_label_show(struct device *dev,
+               struct device_attribute *dev_attr, char *buffer)
+{
+       const char *label = of_get_property(dev->of_node, "label", NULL);
+
+       return snprintf(buffer, PAGE_SIZE, "%s\n", label);
+}
+
+static ssize_t vexpress_hwmon_u32_show(struct device *dev,
+               struct device_attribute *dev_attr, char *buffer)
+{
+       struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
+       int err;
+       u32 value;
+
+       err = regmap_read(data->reg, 0, &value);
+       if (err)
+               return err;
+
+       return snprintf(buffer, PAGE_SIZE, "%u\n", value /
+                       to_sensor_dev_attr(dev_attr)->index);
+}
+
+static ssize_t vexpress_hwmon_u64_show(struct device *dev,
+               struct device_attribute *dev_attr, char *buffer)
+{
+       struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
+       int err;
+       u32 value_hi, value_lo;
+
+       err = regmap_read(data->reg, 0, &value_lo);
+       if (err)
+               return err;
+
+       err = regmap_read(data->reg, 1, &value_hi);
+       if (err)
+               return err;
+
+       return snprintf(buffer, PAGE_SIZE, "%llu\n",
+                       div_u64(((u64)value_hi << 32) | value_lo,
+                       to_sensor_dev_attr(dev_attr)->index));
+}
+
+static umode_t vexpress_hwmon_attr_is_visible(struct kobject *kobj,
+               struct attribute *attr, int index)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct device_attribute *dev_attr = container_of(attr,
+                               struct device_attribute, attr);
+
+       if (dev_attr->show == vexpress_hwmon_label_show &&
+                       !of_get_property(dev->of_node, "label", NULL))
+               return 0;
+
+       return attr->mode;
+}
+
+struct vexpress_hwmon_type {
+       const char *name;
+       const struct attribute_group **attr_groups;
+};
+
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
+               NULL, 1000);
+static struct attribute *vexpress_hwmon_attrs_volt[] = {
+       &dev_attr_in1_label.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       NULL
+};
+static struct attribute_group vexpress_hwmon_group_volt = {
+       .is_visible = vexpress_hwmon_attr_is_visible,
+       .attrs = vexpress_hwmon_attrs_volt,
+};
+static struct vexpress_hwmon_type vexpress_hwmon_volt = {
+       .name = "vexpress_volt",
+       .attr_groups = (const struct attribute_group *[]) {
+               &vexpress_hwmon_group_volt,
+               NULL,
+       },
+};
+#endif
+
+static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
+               NULL, 1000);
+static struct attribute *vexpress_hwmon_attrs_amp[] = {
+       &dev_attr_curr1_label.attr,
+       &sensor_dev_attr_curr1_input.dev_attr.attr,
+       NULL
+};
+static struct attribute_group vexpress_hwmon_group_amp = {
+       .is_visible = vexpress_hwmon_attr_is_visible,
+       .attrs = vexpress_hwmon_attrs_amp,
+};
+static struct vexpress_hwmon_type vexpress_hwmon_amp = {
+       .name = "vexpress_amp",
+       .attr_groups = (const struct attribute_group *[]) {
+               &vexpress_hwmon_group_amp,
+               NULL
+       },
+};
+
+static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
+               NULL, 1000);
+static struct attribute *vexpress_hwmon_attrs_temp[] = {
+       &dev_attr_temp1_label.attr,
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       NULL
+};
+static struct attribute_group vexpress_hwmon_group_temp = {
+       .is_visible = vexpress_hwmon_attr_is_visible,
+       .attrs = vexpress_hwmon_attrs_temp,
+};
+static struct vexpress_hwmon_type vexpress_hwmon_temp = {
+       .name = "vexpress_temp",
+       .attr_groups = (const struct attribute_group *[]) {
+               &vexpress_hwmon_group_temp,
+               NULL
+       },
+};
+
+static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
+               NULL, 1);
+static struct attribute *vexpress_hwmon_attrs_power[] = {
+       &dev_attr_power1_label.attr,
+       &sensor_dev_attr_power1_input.dev_attr.attr,
+       NULL
+};
+static struct attribute_group vexpress_hwmon_group_power = {
+       .is_visible = vexpress_hwmon_attr_is_visible,
+       .attrs = vexpress_hwmon_attrs_power,
+};
+static struct vexpress_hwmon_type vexpress_hwmon_power = {
+       .name = "vexpress_power",
+       .attr_groups = (const struct attribute_group *[]) {
+               &vexpress_hwmon_group_power,
+               NULL
+       },
+};
+
+static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
+static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
+               NULL, 1);
+static struct attribute *vexpress_hwmon_attrs_energy[] = {
+       &dev_attr_energy1_label.attr,
+       &sensor_dev_attr_energy1_input.dev_attr.attr,
+       NULL
+};
+static struct attribute_group vexpress_hwmon_group_energy = {
+       .is_visible = vexpress_hwmon_attr_is_visible,
+       .attrs = vexpress_hwmon_attrs_energy,
+};
+static struct vexpress_hwmon_type vexpress_hwmon_energy = {
+       .name = "vexpress_energy",
+       .attr_groups = (const struct attribute_group *[]) {
+               &vexpress_hwmon_group_energy,
+               NULL
+       },
+};
+
+static const struct of_device_id vexpress_hwmon_of_match[] = {
+#if !defined(CONFIG_REGULATOR_VEXPRESS)
+       {
+               .compatible = "arm,vexpress-volt",
+               .data = &vexpress_hwmon_volt,
+       },
+#endif
+       {
+               .compatible = "arm,vexpress-amp",
+               .data = &vexpress_hwmon_amp,
+       }, {
+               .compatible = "arm,vexpress-temp",
+               .data = &vexpress_hwmon_temp,
+       }, {
+               .compatible = "arm,vexpress-power",
+               .data = &vexpress_hwmon_power,
+       }, {
+               .compatible = "arm,vexpress-energy",
+               .data = &vexpress_hwmon_energy,
+       },
+       {}
+};
+MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
+
+static int vexpress_hwmon_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       struct vexpress_hwmon_data *data;
+       const struct vexpress_hwmon_type *type;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       platform_set_drvdata(pdev, data);
+
+       match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
+       if (!match)
+               return -ENODEV;
+       type = match->data;
+
+       data->reg = devm_regmap_init_vexpress_config(&pdev->dev);
+       if (IS_ERR(data->reg))
+               return PTR_ERR(data->reg);
+
+       data->hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
+                       type->name, data, type->attr_groups);
+
+       return PTR_ERR_OR_ZERO(data->hwmon_dev);
+}
+
+static struct platform_driver vexpress_hwmon_driver = {
+       .probe = vexpress_hwmon_probe,
+       .driver = {
+               .name = DRVNAME,
+               .of_match_table = vexpress_hwmon_of_match,
+       },
+};
+
+module_platform_driver(vexpress_hwmon_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express hwmon sensors driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-hwmon");
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
deleted file mode 100644 (file)
index 8ba419d..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * Copyright (C) 2012 ARM Limited
- */
-
-#define DRVNAME "vexpress-hwmon"
-#define pr_fmt(fmt) DRVNAME ": " fmt
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/vexpress.h>
-
-struct vexpress_hwmon_data {
-       struct device *hwmon_dev;
-       struct regmap *reg;
-};
-
-static ssize_t vexpress_hwmon_label_show(struct device *dev,
-               struct device_attribute *dev_attr, char *buffer)
-{
-       const char *label = of_get_property(dev->of_node, "label", NULL);
-
-       return snprintf(buffer, PAGE_SIZE, "%s\n", label);
-}
-
-static ssize_t vexpress_hwmon_u32_show(struct device *dev,
-               struct device_attribute *dev_attr, char *buffer)
-{
-       struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
-       int err;
-       u32 value;
-
-       err = regmap_read(data->reg, 0, &value);
-       if (err)
-               return err;
-
-       return snprintf(buffer, PAGE_SIZE, "%u\n", value /
-                       to_sensor_dev_attr(dev_attr)->index);
-}
-
-static ssize_t vexpress_hwmon_u64_show(struct device *dev,
-               struct device_attribute *dev_attr, char *buffer)
-{
-       struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
-       int err;
-       u32 value_hi, value_lo;
-
-       err = regmap_read(data->reg, 0, &value_lo);
-       if (err)
-               return err;
-
-       err = regmap_read(data->reg, 1, &value_hi);
-       if (err)
-               return err;
-
-       return snprintf(buffer, PAGE_SIZE, "%llu\n",
-                       div_u64(((u64)value_hi << 32) | value_lo,
-                       to_sensor_dev_attr(dev_attr)->index));
-}
-
-static umode_t vexpress_hwmon_attr_is_visible(struct kobject *kobj,
-               struct attribute *attr, int index)
-{
-       struct device *dev = kobj_to_dev(kobj);
-       struct device_attribute *dev_attr = container_of(attr,
-                               struct device_attribute, attr);
-
-       if (dev_attr->show == vexpress_hwmon_label_show &&
-                       !of_get_property(dev->of_node, "label", NULL))
-               return 0;
-
-       return attr->mode;
-}
-
-struct vexpress_hwmon_type {
-       const char *name;
-       const struct attribute_group **attr_groups;
-};
-
-#if !defined(CONFIG_REGULATOR_VEXPRESS)
-static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
-               NULL, 1000);
-static struct attribute *vexpress_hwmon_attrs_volt[] = {
-       &dev_attr_in1_label.attr,
-       &sensor_dev_attr_in1_input.dev_attr.attr,
-       NULL
-};
-static struct attribute_group vexpress_hwmon_group_volt = {
-       .is_visible = vexpress_hwmon_attr_is_visible,
-       .attrs = vexpress_hwmon_attrs_volt,
-};
-static struct vexpress_hwmon_type vexpress_hwmon_volt = {
-       .name = "vexpress_volt",
-       .attr_groups = (const struct attribute_group *[]) {
-               &vexpress_hwmon_group_volt,
-               NULL,
-       },
-};
-#endif
-
-static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
-               NULL, 1000);
-static struct attribute *vexpress_hwmon_attrs_amp[] = {
-       &dev_attr_curr1_label.attr,
-       &sensor_dev_attr_curr1_input.dev_attr.attr,
-       NULL
-};
-static struct attribute_group vexpress_hwmon_group_amp = {
-       .is_visible = vexpress_hwmon_attr_is_visible,
-       .attrs = vexpress_hwmon_attrs_amp,
-};
-static struct vexpress_hwmon_type vexpress_hwmon_amp = {
-       .name = "vexpress_amp",
-       .attr_groups = (const struct attribute_group *[]) {
-               &vexpress_hwmon_group_amp,
-               NULL
-       },
-};
-
-static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
-               NULL, 1000);
-static struct attribute *vexpress_hwmon_attrs_temp[] = {
-       &dev_attr_temp1_label.attr,
-       &sensor_dev_attr_temp1_input.dev_attr.attr,
-       NULL
-};
-static struct attribute_group vexpress_hwmon_group_temp = {
-       .is_visible = vexpress_hwmon_attr_is_visible,
-       .attrs = vexpress_hwmon_attrs_temp,
-};
-static struct vexpress_hwmon_type vexpress_hwmon_temp = {
-       .name = "vexpress_temp",
-       .attr_groups = (const struct attribute_group *[]) {
-               &vexpress_hwmon_group_temp,
-               NULL
-       },
-};
-
-static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
-               NULL, 1);
-static struct attribute *vexpress_hwmon_attrs_power[] = {
-       &dev_attr_power1_label.attr,
-       &sensor_dev_attr_power1_input.dev_attr.attr,
-       NULL
-};
-static struct attribute_group vexpress_hwmon_group_power = {
-       .is_visible = vexpress_hwmon_attr_is_visible,
-       .attrs = vexpress_hwmon_attrs_power,
-};
-static struct vexpress_hwmon_type vexpress_hwmon_power = {
-       .name = "vexpress_power",
-       .attr_groups = (const struct attribute_group *[]) {
-               &vexpress_hwmon_group_power,
-               NULL
-       },
-};
-
-static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
-static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
-               NULL, 1);
-static struct attribute *vexpress_hwmon_attrs_energy[] = {
-       &dev_attr_energy1_label.attr,
-       &sensor_dev_attr_energy1_input.dev_attr.attr,
-       NULL
-};
-static struct attribute_group vexpress_hwmon_group_energy = {
-       .is_visible = vexpress_hwmon_attr_is_visible,
-       .attrs = vexpress_hwmon_attrs_energy,
-};
-static struct vexpress_hwmon_type vexpress_hwmon_energy = {
-       .name = "vexpress_energy",
-       .attr_groups = (const struct attribute_group *[]) {
-               &vexpress_hwmon_group_energy,
-               NULL
-       },
-};
-
-static const struct of_device_id vexpress_hwmon_of_match[] = {
-#if !defined(CONFIG_REGULATOR_VEXPRESS)
-       {
-               .compatible = "arm,vexpress-volt",
-               .data = &vexpress_hwmon_volt,
-       },
-#endif
-       {
-               .compatible = "arm,vexpress-amp",
-               .data = &vexpress_hwmon_amp,
-       }, {
-               .compatible = "arm,vexpress-temp",
-               .data = &vexpress_hwmon_temp,
-       }, {
-               .compatible = "arm,vexpress-power",
-               .data = &vexpress_hwmon_power,
-       }, {
-               .compatible = "arm,vexpress-energy",
-               .data = &vexpress_hwmon_energy,
-       },
-       {}
-};
-MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
-
-static int vexpress_hwmon_probe(struct platform_device *pdev)
-{
-       const struct of_device_id *match;
-       struct vexpress_hwmon_data *data;
-       const struct vexpress_hwmon_type *type;
-
-       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       platform_set_drvdata(pdev, data);
-
-       match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
-       if (!match)
-               return -ENODEV;
-       type = match->data;
-
-       data->reg = devm_regmap_init_vexpress_config(&pdev->dev);
-       if (IS_ERR(data->reg))
-               return PTR_ERR(data->reg);
-
-       data->hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
-                       type->name, data, type->attr_groups);
-
-       return PTR_ERR_OR_ZERO(data->hwmon_dev);
-}
-
-static struct platform_driver vexpress_hwmon_driver = {
-       .probe = vexpress_hwmon_probe,
-       .driver = {
-               .name = DRVNAME,
-               .of_match_table = vexpress_hwmon_of_match,
-       },
-};
-
-module_platform_driver(vexpress_hwmon_driver);
-
-MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
-MODULE_DESCRIPTION("Versatile Express hwmon sensors driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:vexpress-hwmon");
index 3711df1d452622edd57fb805f2ffcbbab236d9b4..4a45408dd82060fc56b9e8e10c2e8534e8ebba5d 100644 (file)
@@ -586,8 +586,7 @@ static int brcmstb_i2c_probe(struct platform_device *pdev)
        if (!dev)
                return -ENOMEM;
 
-       dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(struct bsc_regs *),
-                                      GFP_KERNEL);
+       dev->bsc_regmap = devm_kzalloc(&pdev->dev, sizeof(*dev->bsc_regmap), GFP_KERNEL);
        if (!dev->bsc_regmap)
                return -ENOMEM;
 
index 438f1b4964c08024c32e55e831f028f657db0e7d..d656657b805c20dafdfc28925c09179705789eae 100644 (file)
@@ -123,6 +123,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
        { "80860F41", 0 },
        { "808622C1", 0 },
        { "AMD0010", ACCESS_INTR_MASK },
+       { "AMDI0010", ACCESS_INTR_MASK },
        { "AMDI0510", 0 },
        { "APMC0D0F", 0 },
        { }
index 9ad014a7afc797b921d7b687b474cd4faaddfeba..b33646be699cbc090c028730e03ac8ac4b72c4e9 100644 (file)
@@ -28,7 +28,6 @@
 
 #ifdef CONFIG_PPC_PMAC
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #endif
 
 #define DRV_NAME "pdc202xx_new"
index 96a345248224b16fe78a2e71fed1920c8088edaa..7f0434f7e486666be6052e1c11c98c16f8f25174 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/io.h>
 #include <asm/dbdma.h>
 #include <asm/ide.h>
-#include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/sections.h>
index 00da80e02154205c428ca00702f4b7c10fa5a829..94b80a51ab68e7e15c327778122f54351254b9a6 100644 (file)
@@ -358,6 +358,7 @@ int ib_register_device(struct ib_device *device,
        ret = device->query_device(device, &device->attrs, &uhw);
        if (ret) {
                printk(KERN_WARNING "Couldn't query the device attributes\n");
+               ib_cache_cleanup_one(device);
                goto out;
        }
 
index f334090bb6129bf7f3cfe788e5cff7bc762752c3..1e37f3515d98a7fba49a7cbd57975ba2b8492bd5 100644 (file)
@@ -1071,7 +1071,7 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
                }
        }
 
-       if (rec->hop_limit > 1 || use_roce) {
+       if (rec->hop_limit > 0 || use_roce) {
                ah_attr->ah_flags = IB_AH_GRH;
                ah_attr->grh.dgid = rec->dgid;
 
index 6ffc9c4e93afb4efa27fe6f3c17fc3cdf41d8c21..6c6fbff19752ecbcf2d4822965ff6bb09d7ee656 100644 (file)
@@ -1970,7 +1970,8 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
                   resp_size);
        INIT_UDATA(&uhw, buf + sizeof(cmd),
                   (unsigned long)cmd.response + resp_size,
-                  in_len - sizeof(cmd), out_len - resp_size);
+                  in_len - sizeof(cmd) - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - resp_size);
 
        memset(&cmd_ex, 0, sizeof(cmd_ex));
        cmd_ex.user_handle = cmd.user_handle;
@@ -3413,7 +3414,8 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file,
 
        INIT_UDATA(&udata, buf + sizeof cmd,
                   (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+                  in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof resp);
 
        ret = __uverbs_create_xsrq(file, ib_dev, &xcmd, &udata);
        if (ret)
@@ -3439,7 +3441,8 @@ ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
 
        INIT_UDATA(&udata, buf + sizeof cmd,
                   (unsigned long) cmd.response + sizeof resp,
-                  in_len - sizeof cmd, out_len - sizeof resp);
+                  in_len - sizeof cmd - sizeof(struct ib_uverbs_cmd_hdr),
+                  out_len - sizeof resp);
 
        ret = __uverbs_create_xsrq(file, ib_dev, &cmd, &udata);
        if (ret)
index 4659256cd95e698c3a9dad3c69407276e2117f29..3b2ddd64a371689e1533cb08c23007a4d6016b03 100644 (file)
@@ -75,7 +75,8 @@ static void mlx5_ib_srq_event(struct mlx5_core_srq *srq, enum mlx5_event type)
 
 static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
                           struct mlx5_create_srq_mbox_in **in,
-                          struct ib_udata *udata, int buf_size, int *inlen)
+                          struct ib_udata *udata, int buf_size, int *inlen,
+                          int is_xrc)
 {
        struct mlx5_ib_dev *dev = to_mdev(pd->device);
        struct mlx5_ib_create_srq ucmd = {};
@@ -87,13 +88,8 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
        int ncont;
        u32 offset;
        u32 uidx = MLX5_IB_DEFAULT_UIDX;
-       int drv_data = udata->inlen - sizeof(struct ib_uverbs_cmd_hdr);
 
-       if (drv_data < 0)
-               return -EINVAL;
-
-       ucmdlen = (drv_data < sizeof(ucmd)) ?
-                 drv_data : sizeof(ucmd);
+       ucmdlen = min(udata->inlen, sizeof(ucmd));
 
        if (ib_copy_from_udata(&ucmd, udata, ucmdlen)) {
                mlx5_ib_dbg(dev, "failed copy udata\n");
@@ -103,15 +99,17 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
        if (ucmd.reserved0 || ucmd.reserved1)
                return -EINVAL;
 
-       if (drv_data > sizeof(ucmd) &&
+       if (udata->inlen > sizeof(ucmd) &&
            !ib_is_udata_cleared(udata, sizeof(ucmd),
-                                drv_data - sizeof(ucmd)))
+                                udata->inlen - sizeof(ucmd)))
                return -EINVAL;
 
-       err = get_srq_user_index(to_mucontext(pd->uobject->context),
-                                &ucmd, udata->inlen, &uidx);
-       if (err)
-               return err;
+       if (is_xrc) {
+               err = get_srq_user_index(to_mucontext(pd->uobject->context),
+                                        &ucmd, udata->inlen, &uidx);
+               if (err)
+                       return err;
+       }
 
        srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE);
 
@@ -151,7 +149,8 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
        (*in)->ctx.log_pg_sz = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
        (*in)->ctx.pgoff_cqn = cpu_to_be32(offset << 26);
 
-       if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) {
+       if ((MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) &&
+            is_xrc){
                xsrqc = MLX5_ADDR_OF(create_xrc_srq_in, *in,
                                     xrc_srq_context_entry);
                MLX5_SET(xrc_srqc, xsrqc, user_index, uidx);
@@ -170,7 +169,7 @@ err_umem:
 
 static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
                             struct mlx5_create_srq_mbox_in **in, int buf_size,
-                            int *inlen)
+                            int *inlen, int is_xrc)
 {
        int err;
        int i;
@@ -224,7 +223,8 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
 
        (*in)->ctx.log_pg_sz = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
 
-       if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) {
+       if ((MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) &&
+            is_xrc){
                xsrqc = MLX5_ADDR_OF(create_xrc_srq_in, *in,
                                     xrc_srq_context_entry);
                /* 0xffffff means we ask to work with cqe version 0 */
@@ -302,10 +302,14 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
                    desc_size, init_attr->attr.max_wr, srq->msrq.max, srq->msrq.max_gs,
                    srq->msrq.max_avail_gather);
 
+       is_xrc = (init_attr->srq_type == IB_SRQT_XRC);
+
        if (pd->uobject)
-               err = create_srq_user(pd, srq, &in, udata, buf_size, &inlen);
+               err = create_srq_user(pd, srq, &in, udata, buf_size, &inlen,
+                                     is_xrc);
        else
-               err = create_srq_kernel(dev, srq, &in, buf_size, &inlen);
+               err = create_srq_kernel(dev, srq, &in, buf_size, &inlen,
+                                       is_xrc);
 
        if (err) {
                mlx5_ib_warn(dev, "create srq %s failed, err %d\n",
@@ -313,7 +317,6 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
                goto err_srq;
        }
 
-       is_xrc = (init_attr->srq_type == IB_SRQT_XRC);
        in->ctx.state_log_sz = ilog2(srq->msrq.max);
        flgs = ((srq->msrq.wqe_shift - 4) | (is_xrc << 5) | (srq->wq_sig << 7)) << 24;
        xrcdn = 0;
index e5e223938eecc9f013e33977b1de50bbb3cfae3d..374c129219ef0c48c8ff3004662c413d78ad2b4c 100644 (file)
@@ -114,6 +114,7 @@ struct kmem_cache *amd_iommu_irq_cache;
 
 static void update_domain(struct protection_domain *domain);
 static int protection_domain_init(struct protection_domain *domain);
+static void detach_device(struct device *dev);
 
 /*
  * For dynamic growth the aperture size is split into ranges of 128MB of
@@ -384,6 +385,9 @@ static void iommu_uninit_device(struct device *dev)
        if (!dev_data)
                return;
 
+       if (dev_data->domain)
+               detach_device(dev);
+
        iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
                            dev);
 
index 013bdfff2d4d023c30a57baf4c833788bfd7dbee..bf4959f4225bd35c356c49172e0f978e0c81166f 100644 (file)
@@ -228,6 +228,10 @@ static int amd_iommu_enable_interrupts(void);
 static int __init iommu_go_to_state(enum iommu_init_state state);
 static void init_device_table_dma(void);
 
+static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
+                                   u8 bank, u8 cntr, u8 fxn,
+                                   u64 *value, bool is_write);
+
 static inline void update_last_devid(u16 devid)
 {
        if (devid > amd_iommu_last_bdf)
@@ -1015,6 +1019,34 @@ static void amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
        pci_write_config_dword(iommu->dev, 0xf0, 0x90);
 }
 
+/*
+ * Family15h Model 30h-3fh (IOMMU Mishandles ATS Write Permission)
+ * Workaround:
+ *     BIOS should enable ATS write permission check by setting
+ *     L2_DEBUG_3[AtsIgnoreIWDis](D0F2xF4_x47[0]) = 1b
+ */
+static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu)
+{
+       u32 value;
+
+       if ((boot_cpu_data.x86 != 0x15) ||
+           (boot_cpu_data.x86_model < 0x30) ||
+           (boot_cpu_data.x86_model > 0x3f))
+               return;
+
+       /* Test L2_DEBUG_3[AtsIgnoreIWDis] == 1 */
+       value = iommu_read_l2(iommu, 0x47);
+
+       if (value & BIT(0))
+               return;
+
+       /* Set L2_DEBUG_3[AtsIgnoreIWDis] = 1 */
+       iommu_write_l2(iommu, 0x47, value | BIT(0));
+
+       pr_info("AMD-Vi: Applying ATS write check workaround for IOMMU at %s\n",
+               dev_name(&iommu->dev->dev));
+}
+
 /*
  * This function clues the initialization function for one IOMMU
  * together and also allocates the command buffer and programs the
@@ -1142,8 +1174,8 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu)
        amd_iommu_pc_present = true;
 
        /* Check if the performance counters can be written to */
-       if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) ||
-           (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) ||
+       if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) ||
+           (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) ||
            (val != val2)) {
                pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n");
                amd_iommu_pc_present = false;
@@ -1284,6 +1316,7 @@ static int iommu_init_pci(struct amd_iommu *iommu)
        }
 
        amd_iommu_erratum_746_workaround(iommu);
+       amd_iommu_ats_write_check_workaround(iommu);
 
        iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu,
                                               amd_iommu_groups, "ivhd%d",
@@ -2283,22 +2316,15 @@ u8 amd_iommu_pc_get_max_counters(u16 devid)
 }
 EXPORT_SYMBOL(amd_iommu_pc_get_max_counters);
 
-int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
+static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
+                                   u8 bank, u8 cntr, u8 fxn,
                                    u64 *value, bool is_write)
 {
-       struct amd_iommu *iommu;
        u32 offset;
        u32 max_offset_lim;
 
-       /* Make sure the IOMMU PC resource is available */
-       if (!amd_iommu_pc_present)
-               return -ENODEV;
-
-       /* Locate the iommu associated with the device ID */
-       iommu = amd_iommu_rlookup_table[devid];
-
        /* Check for valid iommu and pc register indexing */
-       if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7)))
+       if (WARN_ON((fxn > 0x28) || (fxn & 7)))
                return -ENODEV;
 
        offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn);
@@ -2322,3 +2348,16 @@ int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
        return 0;
 }
 EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val);
+
+int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
+                                   u64 *value, bool is_write)
+{
+       struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+       /* Make sure the IOMMU PC resource is available */
+       if (!amd_iommu_pc_present || iommu == NULL)
+               return -ENODEV;
+
+       return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn,
+                                       value, is_write);
+}
index fb092f3f11cb3e32ec8462925587e9778f862a25..8ffd7568fc919e32b97354b2777db21be263d37f 100644 (file)
@@ -329,7 +329,8 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
        /* Only care about add/remove events for physical functions */
        if (pdev->is_virtfn)
                return NOTIFY_DONE;
-       if (action != BUS_NOTIFY_ADD_DEVICE && action != BUS_NOTIFY_DEL_DEVICE)
+       if (action != BUS_NOTIFY_ADD_DEVICE &&
+           action != BUS_NOTIFY_REMOVED_DEVICE)
                return NOTIFY_DONE;
 
        info = dmar_alloc_pci_notify_info(pdev, action);
@@ -339,7 +340,7 @@ static int dmar_pci_bus_notifier(struct notifier_block *nb,
        down_write(&dmar_global_lock);
        if (action == BUS_NOTIFY_ADD_DEVICE)
                dmar_pci_bus_add_dev(info);
-       else if (action == BUS_NOTIFY_DEL_DEVICE)
+       else if (action == BUS_NOTIFY_REMOVED_DEVICE)
                dmar_pci_bus_del_dev(info);
        up_write(&dmar_global_lock);
 
index 986a53e3eb96b4bb56faedfdb36b4bd658aacb99..a2e1b7f14df29cc78b625ec88455438d0fa1fe07 100644 (file)
@@ -4367,7 +4367,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
                                rmrru->devices_cnt);
                        if(ret < 0)
                                return ret;
-               } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
+               } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
                        dmar_remove_dev_scope(info, rmrr->segment,
                                rmrru->devices, rmrru->devices_cnt);
                }
@@ -4387,7 +4387,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
                                break;
                        else if(ret < 0)
                                return ret;
-               } else if (info->event == BUS_NOTIFY_DEL_DEVICE) {
+               } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
                        if (dmar_remove_dev_scope(info, atsr->segment,
                                        atsru->devices, atsru->devices_cnt))
                                break;
index fb50911b3940c0bd7234a1312e320ccff020f492..7e8c441ff2de3a66207f933e09a88e5c44a7ab07 100644 (file)
@@ -60,6 +60,17 @@ config ARM_VIC_NR
          The maximum number of VICs available in the system, for
          power management.
 
+config ARMADA_370_XP_IRQ
+       bool
+       select GENERIC_IRQ_CHIP
+       select PCI_MSI_IRQ_DOMAIN if PCI_MSI
+
+config ALPINE_MSI
+       bool
+       depends on PCI && PCI_MSI
+       select GENERIC_IRQ_CHIP
+       select PCI_MSI_IRQ_DOMAIN
+
 config ATMEL_AIC_IRQ
        bool
        select GENERIC_IRQ_CHIP
@@ -78,6 +89,11 @@ config I8259
        bool
        select IRQ_DOMAIN
 
+config BCM6345_L1_IRQ
+       bool
+       select GENERIC_IRQ_CHIP
+       select IRQ_DOMAIN
+
 config BCM7038_L1_IRQ
        bool
        select GENERIC_IRQ_CHIP
@@ -151,6 +167,11 @@ config ST_IRQCHIP
        help
          Enables SysCfg Controlled IRQs on STi based platforms.
 
+config TANGO_IRQ
+       bool
+       select IRQ_DOMAIN
+       select GENERIC_IRQ_CHIP
+
 config TB10X_IRQC
        bool
        select IRQ_DOMAIN
@@ -160,6 +181,7 @@ config TS4800_IRQ
        tristate "TS-4800 IRQ controller"
        select IRQ_DOMAIN
        depends on HAS_IOMEM
+       depends on SOC_IMX51 || COMPILE_TEST
        help
          Support for the TS-4800 FPGA IRQ controller
 
@@ -193,6 +215,8 @@ config KEYSTONE_IRQ
 
 config MIPS_GIC
        bool
+       select GENERIC_IRQ_IPI
+       select IRQ_DOMAIN_HIERARCHY
        select MIPS_CM
 
 config INGENIC_IRQ
@@ -218,3 +242,7 @@ config IRQ_MXS
        def_bool y if MACH_ASM9260 || ARCH_MXS
        select IRQ_DOMAIN
        select STMP_DEVICE
+
+config MVEBU_ODMI
+       bool
+       select GENERIC_MSI_IRQ_DOMAIN
index 18caacb60d581e953407ac6cae347c97bf7c4ce7..b03cfcbbac6b949b69c8b2f96ac7d307dd5b54e8 100644 (file)
@@ -1,11 +1,13 @@
 obj-$(CONFIG_IRQCHIP)                  += irqchip.o
 
+obj-$(CONFIG_ALPINE_MSI)               += irq-alpine-msi.o
+obj-$(CONFIG_ATH79)                    += irq-ath79-cpu.o
+obj-$(CONFIG_ATH79)                    += irq-ath79-misc.o
 obj-$(CONFIG_ARCH_BCM2835)             += irq-bcm2835.o
 obj-$(CONFIG_ARCH_BCM2835)             += irq-bcm2836.o
 obj-$(CONFIG_ARCH_EXYNOS)              += exynos-combiner.o
 obj-$(CONFIG_ARCH_HIP04)               += irq-hip04.o
 obj-$(CONFIG_ARCH_MMP)                 += irq-mmp.o
-obj-$(CONFIG_ARCH_MVEBU)               += irq-armada-370-xp.o
 obj-$(CONFIG_IRQ_MXS)                  += irq-mxs.o
 obj-$(CONFIG_ARCH_TEGRA)               += irq-tegra.o
 obj-$(CONFIG_ARCH_S3C24XX)             += irq-s3c24xx.o
@@ -28,6 +30,7 @@ obj-$(CONFIG_ARM_GIC_V3_ITS)          += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-g
 obj-$(CONFIG_HISILICON_IRQ_MBIGEN)     += irq-mbigen.o
 obj-$(CONFIG_ARM_NVIC)                 += irq-nvic.o
 obj-$(CONFIG_ARM_VIC)                  += irq-vic.o
+obj-$(CONFIG_ARMADA_370_XP_IRQ)                += irq-armada-370-xp.o
 obj-$(CONFIG_ATMEL_AIC_IRQ)            += irq-atmel-aic-common.o irq-atmel-aic.o
 obj-$(CONFIG_ATMEL_AIC5_IRQ)   += irq-atmel-aic-common.o irq-atmel-aic5.o
 obj-$(CONFIG_I8259)                    += irq-i8259.o
@@ -40,12 +43,14 @@ obj-$(CONFIG_VERSATILE_FPGA_IRQ)    += irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_NSPIRE)              += irq-zevio.o
 obj-$(CONFIG_ARCH_VT8500)              += irq-vt8500.o
 obj-$(CONFIG_ST_IRQCHIP)               += irq-st.o
+obj-$(CONFIG_TANGO_IRQ)                        += irq-tango.o
 obj-$(CONFIG_TB10X_IRQC)               += irq-tb10x.o
 obj-$(CONFIG_TS4800_IRQ)               += irq-ts4800.o
 obj-$(CONFIG_XTENSA)                   += irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)                        += irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR)             += irq-crossbar.o
 obj-$(CONFIG_SOC_VF610)                        += irq-vf610-mscm-ir.o
+obj-$(CONFIG_BCM6345_L1_IRQ)           += irq-bcm6345-l1.o
 obj-$(CONFIG_BCM7038_L1_IRQ)           += irq-bcm7038-l1.o
 obj-$(CONFIG_BCM7120_L2_IRQ)           += irq-bcm7120-l2.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)           += irq-brcmstb-l2.o
@@ -59,3 +64,4 @@ obj-$(CONFIG_ARCH_SA1100)             += irq-sa11x0.o
 obj-$(CONFIG_INGENIC_IRQ)              += irq-ingenic.o
 obj-$(CONFIG_IMX_GPCV2)                        += irq-imx-gpcv2.o
 obj-$(CONFIG_PIC32_EVIC)               += irq-pic32-evic.o
+obj-$(CONFIG_MVEBU_ODMI)               += irq-mvebu-odmi.o
diff --git a/drivers/irqchip/irq-alpine-msi.c b/drivers/irqchip/irq-alpine-msi.c
new file mode 100644 (file)
index 0000000..2538425
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Annapurna Labs MSIX support services
+ *
+ * Copyright (C) 2016, Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * Antoine Tenart <antoine.tenart@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/msi.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/irq.h>
+#include <asm-generic/msi.h>
+
+/* MSIX message address format: local GIC target */
+#define ALPINE_MSIX_SPI_TARGET_CLUSTER0                BIT(16)
+
+struct alpine_msix_data {
+       spinlock_t msi_map_lock;
+       phys_addr_t addr;
+       u32 spi_first;          /* The SGI number that MSIs start */
+       u32 num_spis;           /* The number of SGIs for MSIs */
+       unsigned long *msi_map;
+};
+
+static void alpine_msix_mask_msi_irq(struct irq_data *d)
+{
+       pci_msi_mask_irq(d);
+       irq_chip_mask_parent(d);
+}
+
+static void alpine_msix_unmask_msi_irq(struct irq_data *d)
+{
+       pci_msi_unmask_irq(d);
+       irq_chip_unmask_parent(d);
+}
+
+static struct irq_chip alpine_msix_irq_chip = {
+       .name                   = "MSIx",
+       .irq_mask               = alpine_msix_mask_msi_irq,
+       .irq_unmask             = alpine_msix_unmask_msi_irq,
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+};
+
+static int alpine_msix_allocate_sgi(struct alpine_msix_data *priv, int num_req)
+{
+       int first;
+
+       spin_lock(&priv->msi_map_lock);
+
+       first = bitmap_find_next_zero_area(priv->msi_map, priv->num_spis, 0,
+                                          num_req, 0);
+       if (first >= priv->num_spis) {
+               spin_unlock(&priv->msi_map_lock);
+               return -ENOSPC;
+       }
+
+       bitmap_set(priv->msi_map, first, num_req);
+
+       spin_unlock(&priv->msi_map_lock);
+
+       return priv->spi_first + first;
+}
+
+static void alpine_msix_free_sgi(struct alpine_msix_data *priv, unsigned sgi,
+                                int num_req)
+{
+       int first = sgi - priv->spi_first;
+
+       spin_lock(&priv->msi_map_lock);
+
+       bitmap_clear(priv->msi_map, first, num_req);
+
+       spin_unlock(&priv->msi_map_lock);
+}
+
+static void alpine_msix_compose_msi_msg(struct irq_data *data,
+                                       struct msi_msg *msg)
+{
+       struct alpine_msix_data *priv = irq_data_get_irq_chip_data(data);
+       phys_addr_t msg_addr = priv->addr;
+
+       msg_addr |= (data->hwirq << 3);
+
+       msg->address_hi = upper_32_bits(msg_addr);
+       msg->address_lo = lower_32_bits(msg_addr);
+       msg->data = 0;
+}
+
+static struct msi_domain_info alpine_msix_domain_info = {
+       .flags  = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+                 MSI_FLAG_PCI_MSIX,
+       .chip   = &alpine_msix_irq_chip,
+};
+
+static struct irq_chip middle_irq_chip = {
+       .name                   = "alpine_msix_middle",
+       .irq_mask               = irq_chip_mask_parent,
+       .irq_unmask             = irq_chip_unmask_parent,
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+       .irq_compose_msi_msg    = alpine_msix_compose_msi_msg,
+};
+
+static int alpine_msix_gic_domain_alloc(struct irq_domain *domain,
+                                       unsigned int virq, int sgi)
+{
+       struct irq_fwspec fwspec;
+       struct irq_data *d;
+       int ret;
+
+       if (!is_of_node(domain->parent->fwnode))
+               return -EINVAL;
+
+       fwspec.fwnode = domain->parent->fwnode;
+       fwspec.param_count = 3;
+       fwspec.param[0] = 0;
+       fwspec.param[1] = sgi;
+       fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+
+       ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
+       if (ret)
+               return ret;
+
+       d = irq_domain_get_irq_data(domain->parent, virq);
+       d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING);
+
+       return 0;
+}
+
+static int alpine_msix_middle_domain_alloc(struct irq_domain *domain,
+                                          unsigned int virq,
+                                          unsigned int nr_irqs, void *args)
+{
+       struct alpine_msix_data *priv = domain->host_data;
+       int sgi, err, i;
+
+       sgi = alpine_msix_allocate_sgi(priv, nr_irqs);
+       if (sgi < 0)
+               return sgi;
+
+       for (i = 0; i < nr_irqs; i++) {
+               err = alpine_msix_gic_domain_alloc(domain, virq + i, sgi + i);
+               if (err)
+                       goto err_sgi;
+
+               irq_domain_set_hwirq_and_chip(domain, virq + i, sgi + i,
+                                             &middle_irq_chip, priv);
+       }
+
+       return 0;
+
+err_sgi:
+       while (--i >= 0)
+               irq_domain_free_irqs_parent(domain, virq, i);
+       alpine_msix_free_sgi(priv, sgi, nr_irqs);
+       return err;
+}
+
+static void alpine_msix_middle_domain_free(struct irq_domain *domain,
+                                          unsigned int virq,
+                                          unsigned int nr_irqs)
+{
+       struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+       struct alpine_msix_data *priv = irq_data_get_irq_chip_data(d);
+
+       irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+       alpine_msix_free_sgi(priv, d->hwirq, nr_irqs);
+}
+
+static const struct irq_domain_ops alpine_msix_middle_domain_ops = {
+       .alloc  = alpine_msix_middle_domain_alloc,
+       .free   = alpine_msix_middle_domain_free,
+};
+
+static int alpine_msix_init_domains(struct alpine_msix_data *priv,
+                                   struct device_node *node)
+{
+       struct irq_domain *middle_domain, *msi_domain, *gic_domain;
+       struct device_node *gic_node;
+
+       gic_node = of_irq_find_parent(node);
+       if (!gic_node) {
+               pr_err("Failed to find the GIC node\n");
+               return -ENODEV;
+       }
+
+       gic_domain = irq_find_host(gic_node);
+       if (!gic_domain) {
+               pr_err("Failed to find the GIC domain\n");
+               return -ENXIO;
+       }
+
+       middle_domain = irq_domain_add_tree(NULL,
+                                           &alpine_msix_middle_domain_ops,
+                                           priv);
+       if (!middle_domain) {
+               pr_err("Failed to create the MSIX middle domain\n");
+               return -ENOMEM;
+       }
+
+       middle_domain->parent = gic_domain;
+
+       msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node),
+                                              &alpine_msix_domain_info,
+                                              middle_domain);
+       if (!msi_domain) {
+               pr_err("Failed to create MSI domain\n");
+               irq_domain_remove(middle_domain);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int alpine_msix_init(struct device_node *node,
+                           struct device_node *parent)
+{
+       struct alpine_msix_data *priv;
+       struct resource res;
+       int ret;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->msi_map_lock);
+
+       ret = of_address_to_resource(node, 0, &res);
+       if (ret) {
+               pr_err("Failed to allocate resource\n");
+               goto err_priv;
+       }
+
+       /*
+        * The 20 least significant bits of addr provide direct information
+        * regarding the interrupt destination.
+        *
+        * To select the primary GIC as the target GIC, bits [18:17] must be set
+        * to 0x0. In this case, bit 16 (SPI_TARGET_CLUSTER0) must be set.
+        */
+       priv->addr = res.start & GENMASK_ULL(63,20);
+       priv->addr |= ALPINE_MSIX_SPI_TARGET_CLUSTER0;
+
+       if (of_property_read_u32(node, "al,msi-base-spi", &priv->spi_first)) {
+               pr_err("Unable to parse MSI base\n");
+               ret = -EINVAL;
+               goto err_priv;
+       }
+
+       if (of_property_read_u32(node, "al,msi-num-spis", &priv->num_spis)) {
+               pr_err("Unable to parse MSI numbers\n");
+               ret = -EINVAL;
+               goto err_priv;
+       }
+
+       priv->msi_map = kzalloc(sizeof(*priv->msi_map) * BITS_TO_LONGS(priv->num_spis),
+                               GFP_KERNEL);
+       if (!priv->msi_map) {
+               ret = -ENOMEM;
+               goto err_priv;
+       }
+
+       pr_debug("Registering %d msixs, starting at %d\n",
+                priv->num_spis, priv->spi_first);
+
+       ret = alpine_msix_init_domains(priv, node);
+       if (ret)
+               goto err_map;
+
+       return 0;
+
+err_map:
+       kfree(priv->msi_map);
+err_priv:
+       kfree(priv);
+       return ret;
+}
+IRQCHIP_DECLARE(alpine_msix, "al,alpine-msix", alpine_msix_init);
index 3f3a8c3d2175ed6a49727bc86d8afde6e7cd9520..e7dc6cbda2a1bb61d5b4817dc14649133f1ab5eb 100644 (file)
@@ -71,6 +71,7 @@ static u32 doorbell_mask_reg;
 static int parent_irq;
 #ifdef CONFIG_PCI_MSI
 static struct irq_domain *armada_370_xp_msi_domain;
+static struct irq_domain *armada_370_xp_msi_inner_domain;
 static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
 static DEFINE_MUTEX(msi_used_lock);
 static phys_addr_t msi_doorbell_addr;
@@ -115,127 +116,102 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
 
 #ifdef CONFIG_PCI_MSI
 
-static int armada_370_xp_alloc_msi(void)
-{
-       int hwirq;
+static struct irq_chip armada_370_xp_msi_irq_chip = {
+       .name = "MPIC MSI",
+       .irq_mask = pci_msi_mask_irq,
+       .irq_unmask = pci_msi_unmask_irq,
+};
 
-       mutex_lock(&msi_used_lock);
-       hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
-       if (hwirq >= PCI_MSI_DOORBELL_NR)
-               hwirq = -ENOSPC;
-       else
-               set_bit(hwirq, msi_used);
-       mutex_unlock(&msi_used_lock);
+static struct msi_domain_info armada_370_xp_msi_domain_info = {
+       .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+                  MSI_FLAG_MULTI_PCI_MSI),
+       .chip   = &armada_370_xp_msi_irq_chip,
+};
 
-       return hwirq;
+static void armada_370_xp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+       msg->address_lo = lower_32_bits(msi_doorbell_addr);
+       msg->address_hi = upper_32_bits(msi_doorbell_addr);
+       msg->data = 0xf00 | (data->hwirq + PCI_MSI_DOORBELL_START);
 }
 
-static void armada_370_xp_free_msi(int hwirq)
+static int armada_370_xp_msi_set_affinity(struct irq_data *irq_data,
+                                         const struct cpumask *mask, bool force)
 {
-       mutex_lock(&msi_used_lock);
-       if (!test_bit(hwirq, msi_used))
-               pr_err("trying to free unused MSI#%d\n", hwirq);
-       else
-               clear_bit(hwirq, msi_used);
-       mutex_unlock(&msi_used_lock);
+        return -EINVAL;
 }
 
-static int armada_370_xp_setup_msi_irq(struct msi_controller *chip,
-                                      struct pci_dev *pdev,
-                                      struct msi_desc *desc)
-{
-       struct msi_msg msg;
-       int virq, hwirq;
+static struct irq_chip armada_370_xp_msi_bottom_irq_chip = {
+       .name                   = "MPIC MSI",
+       .irq_compose_msi_msg    = armada_370_xp_compose_msi_msg,
+       .irq_set_affinity       = armada_370_xp_msi_set_affinity,
+};
 
-       /* We support MSI, but not MSI-X */
-       if (desc->msi_attrib.is_msix)
-               return -EINVAL;
+static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq,
+                                  unsigned int nr_irqs, void *args)
+{
+       int hwirq, i;
 
-       hwirq = armada_370_xp_alloc_msi();
-       if (hwirq < 0)
-               return hwirq;
+       mutex_lock(&msi_used_lock);
 
-       virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
-       if (!virq) {
-               armada_370_xp_free_msi(hwirq);
-               return -EINVAL;
+       hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR,
+                                          0, nr_irqs, 0);
+       if (hwirq >= PCI_MSI_DOORBELL_NR) {
+               mutex_unlock(&msi_used_lock);
+               return -ENOSPC;
        }
 
-       irq_set_msi_desc(virq, desc);
-
-       msg.address_lo = msi_doorbell_addr;
-       msg.address_hi = 0;
-       msg.data = 0xf00 | (hwirq + 16);
-
-       pci_write_msi_msg(virq, &msg);
-       return 0;
-}
+       bitmap_set(msi_used, hwirq, nr_irqs);
+       mutex_unlock(&msi_used_lock);
 
-static void armada_370_xp_teardown_msi_irq(struct msi_controller *chip,
-                                          unsigned int irq)
-{
-       struct irq_data *d = irq_get_irq_data(irq);
-       unsigned long hwirq = d->hwirq;
+       for (i = 0; i < nr_irqs; i++) {
+               irq_domain_set_info(domain, virq + i, hwirq + i,
+                                   &armada_370_xp_msi_bottom_irq_chip,
+                                   domain->host_data, handle_simple_irq,
+                                   NULL, NULL);
+       }
 
-       irq_dispose_mapping(irq);
-       armada_370_xp_free_msi(hwirq);
+       return hwirq;
 }
 
-static struct irq_chip armada_370_xp_msi_irq_chip = {
-       .name = "armada_370_xp_msi_irq",
-       .irq_enable = pci_msi_unmask_irq,
-       .irq_disable = pci_msi_mask_irq,
-       .irq_mask = pci_msi_mask_irq,
-       .irq_unmask = pci_msi_unmask_irq,
-};
-
-static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
-                                irq_hw_number_t hw)
+static void armada_370_xp_msi_free(struct irq_domain *domain,
+                                  unsigned int virq, unsigned int nr_irqs)
 {
-       irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
-                                handle_simple_irq);
+       struct irq_data *d = irq_domain_get_irq_data(domain, virq);
 
-       return 0;
+       mutex_lock(&msi_used_lock);
+       bitmap_clear(msi_used, d->hwirq, nr_irqs);
+       mutex_unlock(&msi_used_lock);
 }
 
-static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
-       .map = armada_370_xp_msi_map,
+static const struct irq_domain_ops armada_370_xp_msi_domain_ops = {
+       .alloc  = armada_370_xp_msi_alloc,
+       .free   = armada_370_xp_msi_free,
 };
 
 static int armada_370_xp_msi_init(struct device_node *node,
                                  phys_addr_t main_int_phys_base)
 {
-       struct msi_controller *msi_chip;
        u32 reg;
-       int ret;
 
        msi_doorbell_addr = main_int_phys_base +
                ARMADA_370_XP_SW_TRIG_INT_OFFS;
 
-       msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
-       if (!msi_chip)
+       armada_370_xp_msi_inner_domain =
+               irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
+                                     &armada_370_xp_msi_domain_ops, NULL);
+       if (!armada_370_xp_msi_inner_domain)
                return -ENOMEM;
 
-       msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
-       msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
-       msi_chip->of_node = node;
-
        armada_370_xp_msi_domain =
-               irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
-                                     &armada_370_xp_msi_irq_ops,
-                                     NULL);
+               pci_msi_create_irq_domain(of_node_to_fwnode(node),
+                                         &armada_370_xp_msi_domain_info,
+                                         armada_370_xp_msi_inner_domain);
        if (!armada_370_xp_msi_domain) {
-               kfree(msi_chip);
+               irq_domain_remove(armada_370_xp_msi_inner_domain);
                return -ENOMEM;
        }
 
-       ret = of_pci_msi_chip_add(msi_chip);
-       if (ret < 0) {
-               irq_domain_remove(armada_370_xp_msi_domain);
-               kfree(msi_chip);
-               return ret;
-       }
-
        reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
                | PCI_MSI_DOORBELL_MASK;
 
@@ -280,7 +256,7 @@ static int armada_xp_set_affinity(struct irq_data *d,
 #endif
 
 static struct irq_chip armada_370_xp_irq_chip = {
-       .name           = "armada_370_xp_irq",
+       .name           = "MPIC",
        .irq_mask       = armada_370_xp_irq_mask,
        .irq_mask_ack   = armada_370_xp_irq_mask,
        .irq_unmask     = armada_370_xp_irq_unmask,
@@ -427,12 +403,12 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
                        continue;
 
                if (is_chained) {
-                       irq = irq_find_mapping(armada_370_xp_msi_domain,
-                                              msinr - 16);
+                       irq = irq_find_mapping(armada_370_xp_msi_inner_domain,
+                                              msinr - PCI_MSI_DOORBELL_START);
                        generic_handle_irq(irq);
                } else {
-                       irq = msinr - 16;
-                       handle_domain_irq(armada_370_xp_msi_domain,
+                       irq = msinr - PCI_MSI_DOORBELL_START;
+                       handle_domain_irq(armada_370_xp_msi_inner_domain,
                                          irq, regs);
                }
        }
@@ -604,8 +580,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
        armada_370_xp_mpic_domain =
                irq_domain_add_linear(node, nr_irqs,
                                &armada_370_xp_mpic_irq_ops, NULL);
-
        BUG_ON(!armada_370_xp_mpic_domain);
+       armada_370_xp_mpic_domain->bus_token = DOMAIN_BUS_WIRED;
 
        /* Setup for the boot CPU */
        armada_xp_mpic_perf_init();
diff --git a/drivers/irqchip/irq-ath79-cpu.c b/drivers/irqchip/irq-ath79-cpu.c
new file mode 100644 (file)
index 0000000..befe93c
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *  Atheros AR71xx/AR724x/AR913x specific interrupt handling
+ *
+ *  Copyright (C) 2015 Alban Bedel <albeu@free.fr>
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irqchip.h>
+#include <linux/of.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mach-ath79/ath79.h>
+
+/*
+ * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for
+ * these devices typically allocate coherent DMA memory, however the
+ * DMA controller may still have some unsynchronized data in the FIFO.
+ * Issue a flush in the handlers to ensure that the driver sees
+ * the update.
+ *
+ * This array map the interrupt lines to the DDR write buffer channels.
+ */
+
+static unsigned irq_wb_chan[8] = {
+       -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+asmlinkage void plat_irq_dispatch(void)
+{
+       unsigned long pending;
+       int irq;
+
+       pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+       if (!pending) {
+               spurious_interrupt();
+               return;
+       }
+
+       pending >>= CAUSEB_IP;
+       while (pending) {
+               irq = fls(pending) - 1;
+               if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1)
+                       ath79_ddr_wb_flush(irq_wb_chan[irq]);
+               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
+               pending &= ~BIT(irq);
+       }
+}
+
+static int __init ar79_cpu_intc_of_init(
+       struct device_node *node, struct device_node *parent)
+{
+       int err, i, count;
+
+       /* Fill the irq_wb_chan table */
+       count = of_count_phandle_with_args(
+               node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells");
+
+       for (i = 0; i < count; i++) {
+               struct of_phandle_args args;
+               u32 irq = i;
+
+               of_property_read_u32_index(
+                       node, "qca,ddr-wb-channel-interrupts", i, &irq);
+               if (irq >= ARRAY_SIZE(irq_wb_chan))
+                       continue;
+
+               err = of_parse_phandle_with_args(
+                       node, "qca,ddr-wb-channels",
+                       "#qca,ddr-wb-channel-cells",
+                       i, &args);
+               if (err)
+                       return err;
+
+               irq_wb_chan[irq] = args.args[0];
+       }
+
+       return mips_cpu_irq_of_init(node, parent);
+}
+IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc",
+               ar79_cpu_intc_of_init);
+
+void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3)
+{
+       irq_wb_chan[2] = irq_wb_chan2;
+       irq_wb_chan[3] = irq_wb_chan3;
+       mips_cpu_irq_init();
+}
diff --git a/drivers/irqchip/irq-ath79-misc.c b/drivers/irqchip/irq-ath79-misc.c
new file mode 100644 (file)
index 0000000..aa72907
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ *  Atheros AR71xx/AR724x/AR913x MISC interrupt controller
+ *
+ *  Copyright (C) 2015 Alban Bedel <albeu@free.fr>
+ *  Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+ *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *  Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define AR71XX_RESET_REG_MISC_INT_STATUS       0
+#define AR71XX_RESET_REG_MISC_INT_ENABLE       4
+
+#define ATH79_MISC_IRQ_COUNT                   32
+
+static void ath79_misc_irq_handler(struct irq_desc *desc)
+{
+       struct irq_domain *domain = irq_desc_get_handler_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       void __iomem *base = domain->host_data;
+       u32 pending;
+
+       chained_irq_enter(chip, desc);
+
+       pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
+                 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+       if (!pending) {
+               spurious_interrupt();
+               chained_irq_exit(chip, desc);
+               return;
+       }
+
+       while (pending) {
+               int bit = __ffs(pending);
+
+               generic_handle_irq(irq_linear_revmap(domain, bit));
+               pending &= ~BIT(bit);
+       }
+
+       chained_irq_exit(chip, desc);
+}
+
+static void ar71xx_misc_irq_unmask(struct irq_data *d)
+{
+       void __iomem *base = irq_data_get_irq_chip_data(d);
+       unsigned int irq = d->hwirq;
+       u32 t;
+
+       t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+       __raw_writel(t | BIT(irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+       /* flush write */
+       __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+}
+
+static void ar71xx_misc_irq_mask(struct irq_data *d)
+{
+       void __iomem *base = irq_data_get_irq_chip_data(d);
+       unsigned int irq = d->hwirq;
+       u32 t;
+
+       t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+       __raw_writel(t & ~BIT(irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+       /* flush write */
+       __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+}
+
+static void ar724x_misc_irq_ack(struct irq_data *d)
+{
+       void __iomem *base = irq_data_get_irq_chip_data(d);
+       unsigned int irq = d->hwirq;
+       u32 t;
+
+       t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
+       __raw_writel(t & ~BIT(irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
+
+       /* flush write */
+       __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
+}
+
+static struct irq_chip ath79_misc_irq_chip = {
+       .name           = "MISC",
+       .irq_unmask     = ar71xx_misc_irq_unmask,
+       .irq_mask       = ar71xx_misc_irq_mask,
+};
+
+static int misc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+       irq_set_chip_and_handler(irq, &ath79_misc_irq_chip, handle_level_irq);
+       irq_set_chip_data(irq, d->host_data);
+       return 0;
+}
+
+static const struct irq_domain_ops misc_irq_domain_ops = {
+       .xlate = irq_domain_xlate_onecell,
+       .map = misc_map,
+};
+
+static void __init ath79_misc_intc_domain_init(
+       struct irq_domain *domain, int irq)
+{
+       void __iomem *base = domain->host_data;
+
+       /* Disable and clear all interrupts */
+       __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
+       __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
+
+       irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
+}
+
+static int __init ath79_misc_intc_of_init(
+       struct device_node *node, struct device_node *parent)
+{
+       struct irq_domain *domain;
+       void __iomem *base;
+       int irq;
+
+       irq = irq_of_parse_and_map(node, 0);
+       if (!irq) {
+               pr_err("Failed to get MISC IRQ\n");
+               return -EINVAL;
+       }
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("Failed to get MISC IRQ registers\n");
+               return -ENOMEM;
+       }
+
+       domain = irq_domain_add_linear(node, ATH79_MISC_IRQ_COUNT,
+                               &misc_irq_domain_ops, base);
+       if (!domain) {
+               pr_err("Failed to add MISC irqdomain\n");
+               return -EINVAL;
+       }
+
+       ath79_misc_intc_domain_init(domain, irq);
+       return 0;
+}
+
+static int __init ar7100_misc_intc_of_init(
+       struct device_node *node, struct device_node *parent)
+{
+       ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
+       return ath79_misc_intc_of_init(node, parent);
+}
+
+IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc",
+               ar7100_misc_intc_of_init);
+
+static int __init ar7240_misc_intc_of_init(
+       struct device_node *node, struct device_node *parent)
+{
+       ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
+       return ath79_misc_intc_of_init(node, parent);
+}
+
+IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc",
+               ar7240_misc_intc_of_init);
+
+void __init ath79_misc_irq_init(void __iomem *regs, int irq,
+                               int irq_base, bool is_ar71xx)
+{
+       struct irq_domain *domain;
+
+       if (is_ar71xx)
+               ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
+       else
+               ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
+
+       domain = irq_domain_add_legacy(NULL, ATH79_MISC_IRQ_COUNT,
+                       irq_base, 0, &misc_irq_domain_ops, regs);
+       if (!domain)
+               panic("Failed to create MISC irqdomain");
+
+       ath79_misc_intc_domain_init(domain, irq);
+}
index 37199b9b2cfa260659a98da3eb1a48053e7bddfb..28b26c80f4cf937b8547328b5d724a69e51b7d05 100644 (file)
@@ -80,16 +80,10 @@ int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val)
        return 0;
 }
 
-int aic_common_set_priority(int priority, unsigned *val)
+void aic_common_set_priority(int priority, unsigned *val)
 {
-       if (priority < AT91_AIC_IRQ_MIN_PRIORITY ||
-           priority > AT91_AIC_IRQ_MAX_PRIORITY)
-               return -EINVAL;
-
        *val &= ~AT91_AIC_PRIOR;
        *val |= priority;
-
-       return 0;
 }
 
 int aic_common_irq_domain_xlate(struct irq_domain *d,
@@ -193,7 +187,7 @@ void __init aic_common_rtt_irq_fixup(struct device_node *root)
        }
 }
 
-void __init aic_common_irq_fixup(const struct of_device_id *matches)
+static void __init aic_common_irq_fixup(const struct of_device_id *matches)
 {
        struct device_node *root = of_find_node_by_path("/");
        const struct of_device_id *match;
@@ -214,7 +208,8 @@ void __init aic_common_irq_fixup(const struct of_device_id *matches)
 
 struct irq_domain *__init aic_common_of_init(struct device_node *node,
                                             const struct irq_domain_ops *ops,
-                                            const char *name, int nirqs)
+                                            const char *name, int nirqs,
+                                            const struct of_device_id *matches)
 {
        struct irq_chip_generic *gc;
        struct irq_domain *domain;
@@ -264,6 +259,7 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node,
        }
 
        aic_common_ext_irq_of_init(domain);
+       aic_common_irq_fixup(matches);
 
        return domain;
 
index 603f0a9d5411afe0f5f50880cea9048f087cc408..af60376d50debe30132acd00c58254c4d1a7ab9a 100644 (file)
@@ -19,7 +19,7 @@
 
 int aic_common_set_type(struct irq_data *d, unsigned type, unsigned *val);
 
-int aic_common_set_priority(int priority, unsigned *val);
+void aic_common_set_priority(int priority, unsigned *val);
 
 int aic_common_irq_domain_xlate(struct irq_domain *d,
                                struct device_node *ctrlr,
@@ -30,12 +30,11 @@ int aic_common_irq_domain_xlate(struct irq_domain *d,
 
 struct irq_domain *__init aic_common_of_init(struct device_node *node,
                                             const struct irq_domain_ops *ops,
-                                            const char *name, int nirqs);
+                                            const char *name, int nirqs,
+                                            const struct of_device_id *matches);
 
 void __init aic_common_rtc_irq_fixup(struct device_node *root);
 
 void __init aic_common_rtt_irq_fixup(struct device_node *root);
 
-void __init aic_common_irq_fixup(const struct of_device_id *matches);
-
 #endif /* __IRQ_ATMEL_AIC_COMMON_H */
index 8a0c7f28819841a83e1afb0e3eccf71d4aa287a7..112e17c2768be06587d340865ade9fe202adc7da 100644 (file)
@@ -196,9 +196,8 @@ static int aic_irq_domain_xlate(struct irq_domain *d,
 
        irq_gc_lock(gc);
        smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq));
-       ret = aic_common_set_priority(intspec[2], &smr);
-       if (!ret)
-               irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq));
+       aic_common_set_priority(intspec[2], &smr);
+       irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq));
        irq_gc_unlock(gc);
 
        return ret;
@@ -248,12 +247,10 @@ static int __init aic_of_init(struct device_node *node,
                return -EEXIST;
 
        domain = aic_common_of_init(node, &aic_irq_ops, "atmel-aic",
-                                   NR_AIC_IRQS);
+                                   NR_AIC_IRQS, aic_irq_fixups);
        if (IS_ERR(domain))
                return PTR_ERR(domain);
 
-       aic_common_irq_fixup(aic_irq_fixups);
-
        aic_domain = domain;
        gc = irq_get_domain_generic_chip(domain, 0);
 
index 62bb840c613f2a660966333f858426af5ab3d93e..4f0d068e1abec2bc068b5a2185bef0fd6df729ff 100644 (file)
@@ -272,9 +272,8 @@ static int aic5_irq_domain_xlate(struct irq_domain *d,
        irq_gc_lock(bgc);
        irq_reg_writel(bgc, *out_hwirq, AT91_AIC5_SSR);
        smr = irq_reg_readl(bgc, AT91_AIC5_SMR);
-       ret = aic_common_set_priority(intspec[2], &smr);
-       if (!ret)
-               irq_reg_writel(bgc, intspec[2] | smr, AT91_AIC5_SMR);
+       aic_common_set_priority(intspec[2], &smr);
+       irq_reg_writel(bgc, smr, AT91_AIC5_SMR);
        irq_gc_unlock(bgc);
 
        return ret;
@@ -312,12 +311,10 @@ static int __init aic5_of_init(struct device_node *node,
                return -EEXIST;
 
        domain = aic_common_of_init(node, &aic5_irq_ops, "atmel-aic5",
-                                   nirqs);
+                                   nirqs, aic5_irq_fixups);
        if (IS_ERR(domain))
                return PTR_ERR(domain);
 
-       aic_common_irq_fixup(aic5_irq_fixups);
-
        aic5_domain = domain;
        nchips = aic5_domain->revmap_size / 32;
        for (i = 0; i < nchips; i++) {
index 963065a0d774149da62a5a1d5cac9152bfa9e696..b6e950d4782a1e020acddb50705efb180fe758b3 100644 (file)
@@ -229,7 +229,6 @@ int __init bcm2836_smp_boot_secondary(unsigned int cpu,
        unsigned long secondary_startup_phys =
                (unsigned long)virt_to_phys((void *)secondary_startup);
 
-       dsb();
        writel(secondary_startup_phys,
               intc.base + LOCAL_MAILBOX3_SET0 + 16 * cpu);
 
diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c
new file mode 100644 (file)
index 0000000..b844c89
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Broadcom BCM6345 style Level 1 interrupt controller driver
+ *
+ * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2015 Simon Arlott
+ *
+ * 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.
+ *
+ * This is based on the BCM7038 (which supports SMP) but with a single
+ * enable register instead of separate mask/set/clear registers.
+ *
+ * The BCM3380 has a similar mask/status register layout, but each pair
+ * of words is at separate locations (and SMP is not supported).
+ *
+ * ENABLE/STATUS words are packed next to each other for each CPU:
+ *
+ * BCM6368:
+ *   0x1000_0020: CPU0_W0_ENABLE
+ *   0x1000_0024: CPU0_W1_ENABLE
+ *   0x1000_0028: CPU0_W0_STATUS               IRQs 31-63
+ *   0x1000_002c: CPU0_W1_STATUS               IRQs 0-31
+ *   0x1000_0030: CPU1_W0_ENABLE
+ *   0x1000_0034: CPU1_W1_ENABLE
+ *   0x1000_0038: CPU1_W0_STATUS               IRQs 31-63
+ *   0x1000_003c: CPU1_W1_STATUS               IRQs 0-31
+ *
+ * BCM63168:
+ *   0x1000_0020: CPU0_W0_ENABLE
+ *   0x1000_0024: CPU0_W1_ENABLE
+ *   0x1000_0028: CPU0_W2_ENABLE
+ *   0x1000_002c: CPU0_W3_ENABLE
+ *   0x1000_0030: CPU0_W0_STATUS       IRQs 96-127
+ *   0x1000_0034: CPU0_W1_STATUS       IRQs 64-95
+ *   0x1000_0038: CPU0_W2_STATUS       IRQs 32-63
+ *   0x1000_003c: CPU0_W3_STATUS       IRQs 0-31
+ *   0x1000_0040: CPU1_W0_ENABLE
+ *   0x1000_0044: CPU1_W1_ENABLE
+ *   0x1000_0048: CPU1_W2_ENABLE
+ *   0x1000_004c: CPU1_W3_ENABLE
+ *   0x1000_0050: CPU1_W0_STATUS       IRQs 96-127
+ *   0x1000_0054: CPU1_W1_STATUS       IRQs 64-95
+ *   0x1000_0058: CPU1_W2_STATUS       IRQs 32-63
+ *   0x1000_005c: CPU1_W3_STATUS       IRQs 0-31
+ *
+ * IRQs are numbered in CPU native endian order
+ * (which is big-endian in these examples)
+ */
+
+#define pr_fmt(fmt)    KBUILD_MODNAME  ": " fmt
+
+#include <linux/bitops.h>
+#include <linux/cpumask.h>
+#include <linux/kconfig.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+
+#define IRQS_PER_WORD          32
+#define REG_BYTES_PER_IRQ_WORD (sizeof(u32) * 2)
+
+struct bcm6345_l1_cpu;
+
+struct bcm6345_l1_chip {
+       raw_spinlock_t          lock;
+       unsigned int            n_words;
+       struct irq_domain       *domain;
+       struct cpumask          cpumask;
+       struct bcm6345_l1_cpu   *cpus[NR_CPUS];
+};
+
+struct bcm6345_l1_cpu {
+       void __iomem            *map_base;
+       unsigned int            parent_irq;
+       u32                     enable_cache[];
+};
+
+static inline unsigned int reg_enable(struct bcm6345_l1_chip *intc,
+                                          unsigned int word)
+{
+#ifdef __BIG_ENDIAN
+       return (1 * intc->n_words - word - 1) * sizeof(u32);
+#else
+       return (0 * intc->n_words + word) * sizeof(u32);
+#endif
+}
+
+static inline unsigned int reg_status(struct bcm6345_l1_chip *intc,
+                                     unsigned int word)
+{
+#ifdef __BIG_ENDIAN
+       return (2 * intc->n_words - word - 1) * sizeof(u32);
+#else
+       return (1 * intc->n_words + word) * sizeof(u32);
+#endif
+}
+
+static inline unsigned int cpu_for_irq(struct bcm6345_l1_chip *intc,
+                                       struct irq_data *d)
+{
+       return cpumask_first_and(&intc->cpumask, irq_data_get_affinity_mask(d));
+}
+
+static void bcm6345_l1_irq_handle(struct irq_desc *desc)
+{
+       struct bcm6345_l1_chip *intc = irq_desc_get_handler_data(desc);
+       struct bcm6345_l1_cpu *cpu;
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned int idx;
+
+#ifdef CONFIG_SMP
+       cpu = intc->cpus[cpu_logical_map(smp_processor_id())];
+#else
+       cpu = intc->cpus[0];
+#endif
+
+       chained_irq_enter(chip, desc);
+
+       for (idx = 0; idx < intc->n_words; idx++) {
+               int base = idx * IRQS_PER_WORD;
+               unsigned long pending;
+               irq_hw_number_t hwirq;
+               unsigned int irq;
+
+               pending = __raw_readl(cpu->map_base + reg_status(intc, idx));
+               pending &= __raw_readl(cpu->map_base + reg_enable(intc, idx));
+
+               for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) {
+                       irq = irq_linear_revmap(intc->domain, base + hwirq);
+                       if (irq)
+                               do_IRQ(irq);
+                       else
+                               spurious_interrupt();
+               }
+       }
+
+       chained_irq_exit(chip, desc);
+}
+
+static inline void __bcm6345_l1_unmask(struct irq_data *d)
+{
+       struct bcm6345_l1_chip *intc = irq_data_get_irq_chip_data(d);
+       u32 word = d->hwirq / IRQS_PER_WORD;
+       u32 mask = BIT(d->hwirq % IRQS_PER_WORD);
+       unsigned int cpu_idx = cpu_for_irq(intc, d);
+
+       intc->cpus[cpu_idx]->enable_cache[word] |= mask;
+       __raw_writel(intc->cpus[cpu_idx]->enable_cache[word],
+               intc->cpus[cpu_idx]->map_base + reg_enable(intc, word));
+}
+
+static inline void __bcm6345_l1_mask(struct irq_data *d)
+{
+       struct bcm6345_l1_chip *intc = irq_data_get_irq_chip_data(d);
+       u32 word = d->hwirq / IRQS_PER_WORD;
+       u32 mask = BIT(d->hwirq % IRQS_PER_WORD);
+       unsigned int cpu_idx = cpu_for_irq(intc, d);
+
+       intc->cpus[cpu_idx]->enable_cache[word] &= ~mask;
+       __raw_writel(intc->cpus[cpu_idx]->enable_cache[word],
+               intc->cpus[cpu_idx]->map_base + reg_enable(intc, word));
+}
+
+static void bcm6345_l1_unmask(struct irq_data *d)
+{
+       struct bcm6345_l1_chip *intc = irq_data_get_irq_chip_data(d);
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&intc->lock, flags);
+       __bcm6345_l1_unmask(d);
+       raw_spin_unlock_irqrestore(&intc->lock, flags);
+}
+
+static void bcm6345_l1_mask(struct irq_data *d)
+{
+       struct bcm6345_l1_chip *intc = irq_data_get_irq_chip_data(d);
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&intc->lock, flags);
+       __bcm6345_l1_mask(d);
+       raw_spin_unlock_irqrestore(&intc->lock, flags);
+}
+
+static int bcm6345_l1_set_affinity(struct irq_data *d,
+                                  const struct cpumask *dest,
+                                  bool force)
+{
+       struct bcm6345_l1_chip *intc = irq_data_get_irq_chip_data(d);
+       u32 word = d->hwirq / IRQS_PER_WORD;
+       u32 mask = BIT(d->hwirq % IRQS_PER_WORD);
+       unsigned int old_cpu = cpu_for_irq(intc, d);
+       unsigned int new_cpu;
+       struct cpumask valid;
+       unsigned long flags;
+       bool enabled;
+
+       if (!cpumask_and(&valid, &intc->cpumask, dest))
+               return -EINVAL;
+
+       new_cpu = cpumask_any_and(&valid, cpu_online_mask);
+       if (new_cpu >= nr_cpu_ids)
+               return -EINVAL;
+
+       dest = cpumask_of(new_cpu);
+
+       raw_spin_lock_irqsave(&intc->lock, flags);
+       if (old_cpu != new_cpu) {
+               enabled = intc->cpus[old_cpu]->enable_cache[word] & mask;
+               if (enabled)
+                       __bcm6345_l1_mask(d);
+               cpumask_copy(irq_data_get_affinity_mask(d), dest);
+               if (enabled)
+                       __bcm6345_l1_unmask(d);
+       } else {
+               cpumask_copy(irq_data_get_affinity_mask(d), dest);
+       }
+       raw_spin_unlock_irqrestore(&intc->lock, flags);
+
+       return IRQ_SET_MASK_OK_NOCOPY;
+}
+
+static int __init bcm6345_l1_init_one(struct device_node *dn,
+                                     unsigned int idx,
+                                     struct bcm6345_l1_chip *intc)
+{
+       struct resource res;
+       resource_size_t sz;
+       struct bcm6345_l1_cpu *cpu;
+       unsigned int i, n_words;
+
+       if (of_address_to_resource(dn, idx, &res))
+               return -EINVAL;
+       sz = resource_size(&res);
+       n_words = sz / REG_BYTES_PER_IRQ_WORD;
+
+       if (!intc->n_words)
+               intc->n_words = n_words;
+       else if (intc->n_words != n_words)
+               return -EINVAL;
+
+       cpu = intc->cpus[idx] = kzalloc(sizeof(*cpu) + n_words * sizeof(u32),
+                                       GFP_KERNEL);
+       if (!cpu)
+               return -ENOMEM;
+
+       cpu->map_base = ioremap(res.start, sz);
+       if (!cpu->map_base)
+               return -ENOMEM;
+
+       for (i = 0; i < n_words; i++) {
+               cpu->enable_cache[i] = 0;
+               __raw_writel(0, cpu->map_base + reg_enable(intc, i));
+       }
+
+       cpu->parent_irq = irq_of_parse_and_map(dn, idx);
+       if (!cpu->parent_irq) {
+               pr_err("failed to map parent interrupt %d\n", cpu->parent_irq);
+               return -EINVAL;
+       }
+       irq_set_chained_handler_and_data(cpu->parent_irq,
+                                               bcm6345_l1_irq_handle, intc);
+
+       return 0;
+}
+
+static struct irq_chip bcm6345_l1_irq_chip = {
+       .name                   = "bcm6345-l1",
+       .irq_mask               = bcm6345_l1_mask,
+       .irq_unmask             = bcm6345_l1_unmask,
+       .irq_set_affinity       = bcm6345_l1_set_affinity,
+};
+
+static int bcm6345_l1_map(struct irq_domain *d, unsigned int virq,
+                         irq_hw_number_t hw_irq)
+{
+       irq_set_chip_and_handler(virq,
+               &bcm6345_l1_irq_chip, handle_percpu_irq);
+       irq_set_chip_data(virq, d->host_data);
+       return 0;
+}
+
+static const struct irq_domain_ops bcm6345_l1_domain_ops = {
+       .xlate                  = irq_domain_xlate_onecell,
+       .map                    = bcm6345_l1_map,
+};
+
+static int __init bcm6345_l1_of_init(struct device_node *dn,
+                             struct device_node *parent)
+{
+       struct bcm6345_l1_chip *intc;
+       unsigned int idx;
+       int ret;
+
+       intc = kzalloc(sizeof(*intc), GFP_KERNEL);
+       if (!intc)
+               return -ENOMEM;
+
+       for_each_possible_cpu(idx) {
+               ret = bcm6345_l1_init_one(dn, idx, intc);
+               if (ret)
+                       pr_err("failed to init intc L1 for cpu %d: %d\n",
+                               idx, ret);
+               else
+                       cpumask_set_cpu(idx, &intc->cpumask);
+       }
+
+       if (!cpumask_weight(&intc->cpumask)) {
+               ret = -ENODEV;
+               goto out_free;
+       }
+
+       raw_spin_lock_init(&intc->lock);
+
+       intc->domain = irq_domain_add_linear(dn, IRQS_PER_WORD * intc->n_words,
+                                            &bcm6345_l1_domain_ops,
+                                            intc);
+       if (!intc->domain) {
+               ret = -ENOMEM;
+               goto out_unmap;
+       }
+
+       pr_info("registered BCM6345 L1 intc (IRQs: %d)\n",
+                       IRQS_PER_WORD * intc->n_words);
+       for_each_cpu(idx, &intc->cpumask) {
+               struct bcm6345_l1_cpu *cpu = intc->cpus[idx];
+
+               pr_info("  CPU%u at MMIO 0x%p (irq = %d)\n", idx,
+                               cpu->map_base, cpu->parent_irq);
+       }
+
+       return 0;
+
+out_unmap:
+       for_each_possible_cpu(idx) {
+               struct bcm6345_l1_cpu *cpu = intc->cpus[idx];
+
+               if (cpu) {
+                       if (cpu->map_base)
+                               iounmap(cpu->map_base);
+                       kfree(cpu);
+               }
+       }
+out_free:
+       kfree(intc);
+       return ret;
+}
+
+IRQCHIP_DECLARE(bcm6345_l1, "brcm,bcm6345-l1-intc", bcm6345_l1_of_init);
index aa46eb280a7f02e06b1279307a55d1c73499b751..54c296401525c1a97df216c2cd045f64c7ce0d60 100644 (file)
@@ -10,7 +10,8 @@
 #include <linux/irqchip/arm-gic.h>
 
 #define REALVIEW_SYS_LOCK_OFFSET       0x20
-#define REALVIEW_PB11MP_SYS_PLD_CTRL1  0x74
+#define REALVIEW_SYS_PLD_CTRL1         0x74
+#define REALVIEW_EB_REVB_SYS_PLD_CTRL1 0xD8
 #define VERSATILE_LOCK_VAL             0xA05F
 #define PLD_INTMODE_MASK               BIT(22)|BIT(23)|BIT(24)
 #define PLD_INTMODE_LEGACY             0x0
 #define PLD_INTMODE_NEW_NO_DCC         BIT(23)
 #define PLD_INTMODE_FIQ_ENABLE         BIT(24)
 
+/* For some reason RealView EB Rev B moved this register */
+static const struct of_device_id syscon_pldset_of_match[] = {
+       {
+               .compatible = "arm,realview-eb11mp-revb-syscon",
+               .data = (void *)REALVIEW_EB_REVB_SYS_PLD_CTRL1,
+       },
+       {
+               .compatible = "arm,realview-eb11mp-revc-syscon",
+               .data = (void *)REALVIEW_SYS_PLD_CTRL1,
+       },
+       {
+               .compatible = "arm,realview-eb-syscon",
+               .data = (void *)REALVIEW_SYS_PLD_CTRL1,
+       },
+       {
+               .compatible = "arm,realview-pb11mp-syscon",
+               .data = (void *)REALVIEW_SYS_PLD_CTRL1,
+       },
+       {},
+};
+
 static int __init
 realview_gic_of_init(struct device_node *node, struct device_node *parent)
 {
        static struct regmap *map;
+       struct device_node *np;
+       const struct of_device_id *gic_id;
+       u32 pld1_ctrl;
+
+       np = of_find_matching_node_and_match(NULL, syscon_pldset_of_match,
+                                            &gic_id);
+       if (!np)
+               return -ENODEV;
+       pld1_ctrl = (u32)gic_id->data;
 
        /* The PB11MPCore GIC needs to be configured in the syscon */
-       map = syscon_regmap_lookup_by_compatible("arm,realview-pb11mp-syscon");
+       map = syscon_node_to_regmap(np);
        if (!IS_ERR(map)) {
                /* new irq mode with no DCC */
                regmap_write(map, REALVIEW_SYS_LOCK_OFFSET,
                             VERSATILE_LOCK_VAL);
-               regmap_update_bits(map, REALVIEW_PB11MP_SYS_PLD_CTRL1,
+               regmap_update_bits(map, pld1_ctrl,
                                   PLD_INTMODE_NEW_NO_DCC,
                                   PLD_INTMODE_MASK);
                regmap_write(map, REALVIEW_SYS_LOCK_OFFSET, 0x0000);
-               pr_info("TC11MP GIC: set up interrupt controller to NEW mode, no DCC\n");
+               pr_info("RealView GIC: set up interrupt controller to NEW mode, no DCC\n");
        } else {
-               pr_err("TC11MP GIC setup: could not find syscon\n");
-               return -ENXIO;
+               pr_err("RealView GIC setup: could not find syscon\n");
+               return -ENODEV;
        }
        return gic_of_init(node, parent);
 }
 IRQCHIP_DECLARE(armtc11mp_gic, "arm,tc11mp-gic", realview_gic_of_init);
+IRQCHIP_DECLARE(armeb11mp_gic, "arm,eb11mp-gic", realview_gic_of_init);
index c779f83e511d4f6c889a88aa38ffa8086228738e..28f047c61baae62ffed6a07c9ef2f55cbd4de05b 100644 (file)
@@ -92,18 +92,6 @@ static struct msi_domain_info gicv2m_msi_domain_info = {
        .chip   = &gicv2m_msi_irq_chip,
 };
 
-static int gicv2m_set_affinity(struct irq_data *irq_data,
-                              const struct cpumask *mask, bool force)
-{
-       int ret;
-
-       ret = irq_chip_set_affinity_parent(irq_data, mask, force);
-       if (ret == IRQ_SET_MASK_OK)
-               ret = IRQ_SET_MASK_OK_DONE;
-
-       return ret;
-}
-
 static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 {
        struct v2m_data *v2m = irq_data_get_irq_chip_data(data);
@@ -122,7 +110,7 @@ static struct irq_chip gicv2m_irq_chip = {
        .irq_mask               = irq_chip_mask_parent,
        .irq_unmask             = irq_chip_unmask_parent,
        .irq_eoi                = irq_chip_eoi_parent,
-       .irq_set_affinity       = gicv2m_set_affinity,
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
        .irq_compose_msi_msg    = gicv2m_compose_msi_msg,
 };
 
index 0a73632b28d573cfa450e4edf75dacfc8683ad86..39261798c59f9d42f5a94d85d5a19d97c8a80d98 100644 (file)
@@ -78,6 +78,9 @@ struct its_node {
 
 #define ITS_ITT_ALIGN          SZ_256
 
+/* Convert page order to size in bytes */
+#define PAGE_ORDER_TO_SIZE(o)  (PAGE_SIZE << (o))
+
 struct event_lpi_map {
        unsigned long           *lpi_map;
        u16                     *col_map;
@@ -100,7 +103,6 @@ struct its_device {
 
 static LIST_HEAD(its_nodes);
 static DEFINE_SPINLOCK(its_lock);
-static struct device_node *gic_root_node;
 static struct rdists *gic_rdists;
 
 #define gic_data_rdist()               (raw_cpu_ptr(gic_rdists->rdist))
@@ -600,11 +602,6 @@ static void its_unmask_irq(struct irq_data *d)
        lpi_set_config(d, true);
 }
 
-static void its_eoi_irq(struct irq_data *d)
-{
-       gic_write_eoir(d->hwirq);
-}
-
 static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
                            bool force)
 {
@@ -641,7 +638,7 @@ static struct irq_chip its_irq_chip = {
        .name                   = "ITS",
        .irq_mask               = its_mask_irq,
        .irq_unmask             = its_unmask_irq,
-       .irq_eoi                = its_eoi_irq,
+       .irq_eoi                = irq_chip_eoi_parent,
        .irq_set_affinity       = its_set_affinity,
        .irq_compose_msi_msg    = its_irq_compose_msi_msg,
 };
@@ -673,7 +670,7 @@ static int its_chunk_to_lpi(int chunk)
        return (chunk << IRQS_PER_CHUNK_SHIFT) + 8192;
 }
 
-static int its_lpi_init(u32 id_bits)
+static int __init its_lpi_init(u32 id_bits)
 {
        lpi_chunks = its_lpi_to_chunk(1UL << id_bits);
 
@@ -846,7 +843,6 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
                u64 type = GITS_BASER_TYPE(val);
                u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
                int order = get_order(psz);
-               int alloc_size;
                int alloc_pages;
                u64 tmp;
                void *base;
@@ -878,9 +874,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
                        }
                }
 
-               alloc_size = (1 << order) * PAGE_SIZE;
 retry_alloc_baser:
-               alloc_pages = (alloc_size / psz);
+               alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
                if (alloc_pages > GITS_BASER_PAGES_MAX) {
                        alloc_pages = GITS_BASER_PAGES_MAX;
                        order = get_order(GITS_BASER_PAGES_MAX * psz);
@@ -933,7 +928,7 @@ retry_baser:
                        shr = tmp & GITS_BASER_SHAREABILITY_MASK;
                        if (!shr) {
                                cache = GITS_BASER_nC;
-                               __flush_dcache_area(base, alloc_size);
+                               __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
                        }
                        goto retry_baser;
                }
@@ -966,7 +961,7 @@ retry_baser:
                }
 
                pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
-                       (int)(alloc_size / entry_size),
+                       (int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
                        its_base_type_string[type],
                        (unsigned long)virt_to_phys(base),
                        psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
@@ -1434,7 +1429,8 @@ static void its_enable_quirks(struct its_node *its)
        gic_enable_quirks(iidr, its_quirks, its);
 }
 
-static int its_probe(struct device_node *node, struct irq_domain *parent)
+static int __init its_probe(struct device_node *node,
+                           struct irq_domain *parent)
 {
        struct resource res;
        struct its_node *its;
@@ -1595,7 +1591,7 @@ static struct of_device_id its_device_id[] = {
        {},
 };
 
-int its_init(struct device_node *node, struct rdists *rdists,
+int __init its_init(struct device_node *node, struct rdists *rdists,
             struct irq_domain *parent_domain)
 {
        struct device_node *np;
@@ -1611,8 +1607,6 @@ int its_init(struct device_node *node, struct rdists *rdists,
        }
 
        gic_rdists = rdists;
-       gic_root_node = node;
-
        its_alloc_lpi_tables();
        its_lpi_init(rdists->id_bits);
 
index d7be6ddc34f685a47dad313274f209b59dff6bf5..5b7d3c2129d8776a3e087b9861f64161142a815a 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -38,6 +40,7 @@
 struct redist_region {
        void __iomem            *redist_base;
        phys_addr_t             phys_base;
+       bool                    single_redist;
 };
 
 struct gic_chip_data {
@@ -434,6 +437,9 @@ static int gic_populate_rdist(void)
                                return 0;
                        }
 
+                       if (gic_data.redist_regions[i].single_redist)
+                               break;
+
                        if (gic_data.redist_stride) {
                                ptr += gic_data.redist_stride;
                        } else {
@@ -634,7 +640,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
        else
                gic_dist_wait_for_rwp();
 
-       return IRQ_SET_MASK_OK;
+       return IRQ_SET_MASK_OK_DONE;
 }
 #else
 #define gic_set_affinity       NULL
@@ -764,6 +770,15 @@ static int gic_irq_domain_translate(struct irq_domain *d,
                return 0;
        }
 
+       if (is_fwnode_irqchip(fwspec->fwnode)) {
+               if(fwspec->param_count != 2)
+                       return -EINVAL;
+
+               *hwirq = fwspec->param[0];
+               *type = fwspec->param[1];
+               return 0;
+       }
+
        return -EINVAL;
 }
 
@@ -811,17 +826,88 @@ static void gicv3_enable_quirks(void)
 #endif
 }
 
+static int __init gic_init_bases(void __iomem *dist_base,
+                                struct redist_region *rdist_regs,
+                                u32 nr_redist_regions,
+                                u64 redist_stride,
+                                struct fwnode_handle *handle)
+{
+       struct device_node *node;
+       u32 typer;
+       int gic_irqs;
+       int err;
+
+       if (!is_hyp_mode_available())
+               static_key_slow_dec(&supports_deactivate);
+
+       if (static_key_true(&supports_deactivate))
+               pr_info("GIC: Using split EOI/Deactivate mode\n");
+
+       gic_data.dist_base = dist_base;
+       gic_data.redist_regions = rdist_regs;
+       gic_data.nr_redist_regions = nr_redist_regions;
+       gic_data.redist_stride = redist_stride;
+
+       gicv3_enable_quirks();
+
+       /*
+        * Find out how many interrupts are supported.
+        * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
+        */
+       typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
+       gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer);
+       gic_irqs = GICD_TYPER_IRQS(typer);
+       if (gic_irqs > 1020)
+               gic_irqs = 1020;
+       gic_data.irq_nr = gic_irqs;
+
+       gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
+                                                &gic_data);
+       gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
+
+       if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
+               err = -ENOMEM;
+               goto out_free;
+       }
+
+       set_handle_irq(gic_handle_irq);
+
+       node = to_of_node(handle);
+       if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis() &&
+           node) /* Temp hack to prevent ITS init for ACPI */
+               its_init(node, &gic_data.rdists, gic_data.domain);
+
+       gic_smp_init();
+       gic_dist_init();
+       gic_cpu_init();
+       gic_cpu_pm_init();
+
+       return 0;
+
+out_free:
+       if (gic_data.domain)
+               irq_domain_remove(gic_data.domain);
+       free_percpu(gic_data.rdists.rdist);
+       return err;
+}
+
+static int __init gic_validate_dist_version(void __iomem *dist_base)
+{
+       u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+
+       if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4)
+               return -ENODEV;
+
+       return 0;
+}
+
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
        void __iomem *dist_base;
        struct redist_region *rdist_regs;
        u64 redist_stride;
        u32 nr_redist_regions;
-       u32 typer;
-       u32 reg;
-       int gic_irqs;
-       int err;
-       int i;
+       int err, i;
 
        dist_base = of_iomap(node, 0);
        if (!dist_base) {
@@ -830,11 +916,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
                return -ENXIO;
        }
 
-       reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
-       if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
+       err = gic_validate_dist_version(dist_base);
+       if (err) {
                pr_err("%s: no distributor detected, giving up\n",
                        node->full_name);
-               err = -ENODEV;
                goto out_unmap_dist;
        }
 
@@ -865,63 +950,229 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
        if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
                redist_stride = 0;
 
-       if (!is_hyp_mode_available())
-               static_key_slow_dec(&supports_deactivate);
+       err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
+                            redist_stride, &node->fwnode);
+       if (!err)
+               return 0;
 
-       if (static_key_true(&supports_deactivate))
-               pr_info("GIC: Using split EOI/Deactivate mode\n");
+out_unmap_rdist:
+       for (i = 0; i < nr_redist_regions; i++)
+               if (rdist_regs[i].redist_base)
+                       iounmap(rdist_regs[i].redist_base);
+       kfree(rdist_regs);
+out_unmap_dist:
+       iounmap(dist_base);
+       return err;
+}
 
-       gic_data.dist_base = dist_base;
-       gic_data.redist_regions = rdist_regs;
-       gic_data.nr_redist_regions = nr_redist_regions;
-       gic_data.redist_stride = redist_stride;
+IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
 
-       gicv3_enable_quirks();
+#ifdef CONFIG_ACPI
+static void __iomem *dist_base;
+static struct redist_region *redist_regs __initdata;
+static u32 nr_redist_regions __initdata;
+static bool single_redist;
+
+static void __init
+gic_acpi_register_redist(phys_addr_t phys_base, void __iomem *redist_base)
+{
+       static int count = 0;
+
+       redist_regs[count].phys_base = phys_base;
+       redist_regs[count].redist_base = redist_base;
+       redist_regs[count].single_redist = single_redist;
+       count++;
+}
+
+static int __init
+gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
+                          const unsigned long end)
+{
+       struct acpi_madt_generic_redistributor *redist =
+                       (struct acpi_madt_generic_redistributor *)header;
+       void __iomem *redist_base;
+
+       redist_base = ioremap(redist->base_address, redist->length);
+       if (!redist_base) {
+               pr_err("Couldn't map GICR region @%llx\n", redist->base_address);
+               return -ENOMEM;
+       }
+
+       gic_acpi_register_redist(redist->base_address, redist_base);
+       return 0;
+}
+
+static int __init
+gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+                        const unsigned long end)
+{
+       struct acpi_madt_generic_interrupt *gicc =
+                               (struct acpi_madt_generic_interrupt *)header;
+       u32 reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
+       u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2;
+       void __iomem *redist_base;
+
+       redist_base = ioremap(gicc->gicr_base_address, size);
+       if (!redist_base)
+               return -ENOMEM;
+
+       gic_acpi_register_redist(gicc->gicr_base_address, redist_base);
+       return 0;
+}
+
+static int __init gic_acpi_collect_gicr_base(void)
+{
+       acpi_tbl_entry_handler redist_parser;
+       enum acpi_madt_type type;
+
+       if (single_redist) {
+               type = ACPI_MADT_TYPE_GENERIC_INTERRUPT;
+               redist_parser = gic_acpi_parse_madt_gicc;
+       } else {
+               type = ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR;
+               redist_parser = gic_acpi_parse_madt_redist;
+       }
+
+       /* Collect redistributor base addresses in GICR entries */
+       if (acpi_table_parse_madt(type, redist_parser, 0) > 0)
+               return 0;
+
+       pr_info("No valid GICR entries exist\n");
+       return -ENODEV;
+}
+
+static int __init gic_acpi_match_gicr(struct acpi_subtable_header *header,
+                                 const unsigned long end)
+{
+       /* Subtable presence means that redist exists, that's it */
+       return 0;
+}
+
+static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
+                                     const unsigned long end)
+{
+       struct acpi_madt_generic_interrupt *gicc =
+                               (struct acpi_madt_generic_interrupt *)header;
 
        /*
-        * Find out how many interrupts are supported.
-        * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
+        * If GICC is enabled and has valid gicr base address, then it means
+        * GICR base is presented via GICC
         */
-       typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
-       gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer);
-       gic_irqs = GICD_TYPER_IRQS(typer);
-       if (gic_irqs > 1020)
-               gic_irqs = 1020;
-       gic_data.irq_nr = gic_irqs;
+       if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
+               return 0;
 
-       gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
-                                             &gic_data);
-       gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
+       return -ENODEV;
+}
 
-       if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
+static int __init gic_acpi_count_gicr_regions(void)
+{
+       int count;
+
+       /*
+        * Count how many redistributor regions we have. It is not allowed
+        * to mix redistributor description, GICR and GICC subtables have to be
+        * mutually exclusive.
+        */
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
+                                     gic_acpi_match_gicr, 0);
+       if (count > 0) {
+               single_redist = false;
+               return count;
+       }
+
+       count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
+                                     gic_acpi_match_gicc, 0);
+       if (count > 0)
+               single_redist = true;
+
+       return count;
+}
+
+static bool __init acpi_validate_gic_table(struct acpi_subtable_header *header,
+                                          struct acpi_probe_entry *ape)
+{
+       struct acpi_madt_generic_distributor *dist;
+       int count;
+
+       dist = (struct acpi_madt_generic_distributor *)header;
+       if (dist->version != ape->driver_data)
+               return false;
+
+       /* We need to do that exercise anyway, the sooner the better */
+       count = gic_acpi_count_gicr_regions();
+       if (count <= 0)
+               return false;
+
+       nr_redist_regions = count;
+       return true;
+}
+
+#define ACPI_GICV3_DIST_MEM_SIZE (SZ_64K)
+
+static int __init
+gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end)
+{
+       struct acpi_madt_generic_distributor *dist;
+       struct fwnode_handle *domain_handle;
+       int i, err;
+
+       /* Get distributor base address */
+       dist = (struct acpi_madt_generic_distributor *)header;
+       dist_base = ioremap(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE);
+       if (!dist_base) {
+               pr_err("Unable to map GICD registers\n");
+               return -ENOMEM;
+       }
+
+       err = gic_validate_dist_version(dist_base);
+       if (err) {
+               pr_err("No distributor detected at @%p, giving up", dist_base);
+               goto out_dist_unmap;
+       }
+
+       redist_regs = kzalloc(sizeof(*redist_regs) * nr_redist_regions,
+                             GFP_KERNEL);
+       if (!redist_regs) {
                err = -ENOMEM;
-               goto out_free;
+               goto out_dist_unmap;
        }
 
-       set_handle_irq(gic_handle_irq);
+       err = gic_acpi_collect_gicr_base();
+       if (err)
+               goto out_redist_unmap;
 
-       if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
-               its_init(node, &gic_data.rdists, gic_data.domain);
+       domain_handle = irq_domain_alloc_fwnode(dist_base);
+       if (!domain_handle) {
+               err = -ENOMEM;
+               goto out_redist_unmap;
+       }
 
-       gic_smp_init();
-       gic_dist_init();
-       gic_cpu_init();
-       gic_cpu_pm_init();
+       err = gic_init_bases(dist_base, redist_regs, nr_redist_regions, 0,
+                            domain_handle);
+       if (err)
+               goto out_fwhandle_free;
 
+       acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
        return 0;
 
-out_free:
-       if (gic_data.domain)
-               irq_domain_remove(gic_data.domain);
-       free_percpu(gic_data.rdists.rdist);
-out_unmap_rdist:
+out_fwhandle_free:
+       irq_domain_free_fwnode(domain_handle);
+out_redist_unmap:
        for (i = 0; i < nr_redist_regions; i++)
-               if (rdist_regs[i].redist_base)
-                       iounmap(rdist_regs[i].redist_base);
-       kfree(rdist_regs);
-out_unmap_dist:
+               if (redist_regs[i].redist_base)
+                       iounmap(redist_regs[i].redist_base);
+       kfree(redist_regs);
+out_dist_unmap:
        iounmap(dist_base);
        return err;
 }
-
-IRQCHIP_DECLARE(gic_v3, "arm,gic-v3", gic_of_init);
+IRQCHIP_ACPI_DECLARE(gic_v3, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+                    acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V3,
+                    gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+                    acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_V4,
+                    gic_acpi_init);
+IRQCHIP_ACPI_DECLARE(gic_v3_or_v4, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
+                    acpi_validate_gic_table, ACPI_MADT_GIC_VERSION_NONE,
+                    gic_acpi_init);
+#endif
index 8f9ebf714e2bbc154d7a045d27920f6c95f7cce6..282344b95ec2b41c5e081c9d73199bb0a66b21d9 100644 (file)
@@ -319,7 +319,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
        writel_relaxed(val | bit, reg);
        raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
 
-       return IRQ_SET_MASK_OK;
+       return IRQ_SET_MASK_OK_DONE;
 }
 #endif
 
index 9e17ef27a183d6f62a6f2860ee416674a314465c..94a30da0cfacac7d48e7e157b7ae7cd803708b50 100644 (file)
@@ -29,16 +29,32 @@ struct gic_pcpu_mask {
        DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
 };
 
+struct gic_irq_spec {
+       enum {
+               GIC_DEVICE,
+               GIC_IPI
+       } type;
+
+       union {
+               struct cpumask *ipimask;
+               unsigned int hwirq;
+       };
+};
+
 static unsigned long __gic_base_addr;
+
 static void __iomem *gic_base;
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
+static struct irq_domain *gic_dev_domain;
+static struct irq_domain *gic_ipi_domain;
 static int gic_shared_intrs;
 static int gic_vpes;
 static unsigned int gic_cpu_pin;
 static unsigned int timer_cpu_pin;
 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
+DECLARE_BITMAP(ipi_resrv, GIC_MAX_INTRS);
 
 static void __gic_irq_dispatch(void);
 
@@ -264,9 +280,11 @@ static void gic_bind_eic_interrupt(int irq, int set)
                  GIC_VPE_EIC_SS(irq), set);
 }
 
-void gic_send_ipi(unsigned int intr)
+static void gic_send_ipi(struct irq_data *d, unsigned int cpu)
 {
-       gic_write(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_SET(intr));
+       irq_hw_number_t hwirq = GIC_HWIRQ_TO_SHARED(irqd_to_hwirq(d));
+
+       gic_write(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_SET(hwirq));
 }
 
 int gic_get_c0_compare_int(void)
@@ -449,7 +467,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
        gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first(&tmp)));
 
        /* Update the pcpu_masks */
-       for (i = 0; i < NR_CPUS; i++)
+       for (i = 0; i < gic_vpes; i++)
                clear_bit(irq, pcpu_masks[i].pcpu_mask);
        set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask);
 
@@ -479,6 +497,7 @@ static struct irq_chip gic_edge_irq_controller = {
 #ifdef CONFIG_SMP
        .irq_set_affinity       =       gic_set_affinity,
 #endif
+       .ipi_send_single        =       gic_send_ipi,
 };
 
 static void gic_handle_local_int(bool chained)
@@ -572,83 +591,6 @@ static void gic_irq_dispatch(struct irq_desc *desc)
        gic_handle_shared_int(true);
 }
 
-#ifdef CONFIG_MIPS_GIC_IPI
-static int gic_resched_int_base;
-static int gic_call_int_base;
-
-unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
-{
-       return gic_resched_int_base + cpu;
-}
-
-unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
-{
-       return gic_call_int_base + cpu;
-}
-
-static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
-{
-       scheduler_ipi();
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
-{
-       generic_smp_call_function_interrupt();
-
-       return IRQ_HANDLED;
-}
-
-static struct irqaction irq_resched = {
-       .handler        = ipi_resched_interrupt,
-       .flags          = IRQF_PERCPU,
-       .name           = "IPI resched"
-};
-
-static struct irqaction irq_call = {
-       .handler        = ipi_call_interrupt,
-       .flags          = IRQF_PERCPU,
-       .name           = "IPI call"
-};
-
-static __init void gic_ipi_init_one(unsigned int intr, int cpu,
-                                   struct irqaction *action)
-{
-       int virq = irq_create_mapping(gic_irq_domain,
-                                     GIC_SHARED_TO_HWIRQ(intr));
-       int i;
-
-       gic_map_to_vpe(intr, mips_cm_vp_id(cpu));
-       for (i = 0; i < NR_CPUS; i++)
-               clear_bit(intr, pcpu_masks[i].pcpu_mask);
-       set_bit(intr, pcpu_masks[cpu].pcpu_mask);
-
-       irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
-
-       irq_set_handler(virq, handle_percpu_irq);
-       setup_irq(virq, action);
-}
-
-static __init void gic_ipi_init(void)
-{
-       int i;
-
-       /* Use last 2 * NR_CPUS interrupts as IPIs */
-       gic_resched_int_base = gic_shared_intrs - nr_cpu_ids;
-       gic_call_int_base = gic_resched_int_base - nr_cpu_ids;
-
-       for (i = 0; i < nr_cpu_ids; i++) {
-               gic_ipi_init_one(gic_call_int_base + i, i, &irq_call);
-               gic_ipi_init_one(gic_resched_int_base + i, i, &irq_resched);
-       }
-}
-#else
-static inline void gic_ipi_init(void)
-{
-}
-#endif
-
 static void __init gic_basic_init(void)
 {
        unsigned int i;
@@ -753,19 +695,21 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 }
 
 static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
-                                    irq_hw_number_t hw)
+                                    irq_hw_number_t hw, unsigned int vpe)
 {
        int intr = GIC_HWIRQ_TO_SHARED(hw);
        unsigned long flags;
+       int i;
 
        irq_set_chip_and_handler(virq, &gic_level_irq_controller,
                                 handle_level_irq);
 
        spin_lock_irqsave(&gic_lock, flags);
        gic_map_to_pin(intr, gic_cpu_pin);
-       /* Map to VPE 0 by default */
-       gic_map_to_vpe(intr, 0);
-       set_bit(intr, pcpu_masks[0].pcpu_mask);
+       gic_map_to_vpe(intr, vpe);
+       for (i = 0; i < gic_vpes; i++)
+               clear_bit(intr, pcpu_masks[i].pcpu_mask);
+       set_bit(intr, pcpu_masks[vpe].pcpu_mask);
        spin_unlock_irqrestore(&gic_lock, flags);
 
        return 0;
@@ -776,10 +720,93 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
 {
        if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS)
                return gic_local_irq_domain_map(d, virq, hw);
-       return gic_shared_irq_domain_map(d, virq, hw);
+       return gic_shared_irq_domain_map(d, virq, hw, 0);
 }
 
-static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq,
+                               unsigned int nr_irqs, void *arg)
+{
+       struct gic_irq_spec *spec = arg;
+       irq_hw_number_t hwirq, base_hwirq;
+       int cpu, ret, i;
+
+       if (spec->type == GIC_DEVICE) {
+               /* verify that it doesn't conflict with an IPI irq */
+               if (test_bit(spec->hwirq, ipi_resrv))
+                       return -EBUSY;
+       } else {
+               base_hwirq = find_first_bit(ipi_resrv, gic_shared_intrs);
+               if (base_hwirq == gic_shared_intrs) {
+                       return -ENOMEM;
+               }
+
+               /* check that we have enough space */
+               for (i = base_hwirq; i < nr_irqs; i++) {
+                       if (!test_bit(i, ipi_resrv))
+                               return -EBUSY;
+               }
+               bitmap_clear(ipi_resrv, base_hwirq, nr_irqs);
+
+               /* map the hwirq for each cpu consecutively */
+               i = 0;
+               for_each_cpu(cpu, spec->ipimask) {
+                       hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i);
+
+                       ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq,
+                                                           &gic_edge_irq_controller,
+                                                           NULL);
+                       if (ret)
+                               goto error;
+
+                       ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu);
+                       if (ret)
+                               goto error;
+
+                       i++;
+               }
+
+               /*
+                * tell the parent about the base hwirq we allocated so it can
+                * set its own domain data
+                */
+               spec->hwirq = base_hwirq;
+       }
+
+       return 0;
+error:
+       bitmap_set(ipi_resrv, base_hwirq, nr_irqs);
+       return ret;
+}
+
+void gic_irq_domain_free(struct irq_domain *d, unsigned int virq,
+                        unsigned int nr_irqs)
+{
+       irq_hw_number_t base_hwirq;
+       struct irq_data *data;
+
+       data = irq_get_irq_data(virq);
+       if (!data)
+               return;
+
+       base_hwirq = GIC_HWIRQ_TO_SHARED(irqd_to_hwirq(data));
+       bitmap_set(ipi_resrv, base_hwirq, nr_irqs);
+}
+
+int gic_irq_domain_match(struct irq_domain *d, struct device_node *node,
+                        enum irq_domain_bus_token bus_token)
+{
+       /* this domain should'nt be accessed directly */
+       return 0;
+}
+
+static const struct irq_domain_ops gic_irq_domain_ops = {
+       .map = gic_irq_domain_map,
+       .alloc = gic_irq_domain_alloc,
+       .free = gic_irq_domain_free,
+       .match = gic_irq_domain_match,
+};
+
+static int gic_dev_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
                                const u32 *intspec, unsigned int intsize,
                                irq_hw_number_t *out_hwirq,
                                unsigned int *out_type)
@@ -798,9 +825,130 @@ static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
        return 0;
 }
 
-static const struct irq_domain_ops gic_irq_domain_ops = {
-       .map = gic_irq_domain_map,
-       .xlate = gic_irq_domain_xlate,
+static int gic_dev_domain_alloc(struct irq_domain *d, unsigned int virq,
+                               unsigned int nr_irqs, void *arg)
+{
+       struct irq_fwspec *fwspec = arg;
+       struct gic_irq_spec spec = {
+               .type = GIC_DEVICE,
+               .hwirq = fwspec->param[1],
+       };
+       int i, ret;
+       bool is_shared = fwspec->param[0] == GIC_SHARED;
+
+       if (is_shared) {
+               ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &spec);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < nr_irqs; i++) {
+               irq_hw_number_t hwirq;
+
+               if (is_shared)
+                       hwirq = GIC_SHARED_TO_HWIRQ(spec.hwirq + i);
+               else
+                       hwirq = GIC_LOCAL_TO_HWIRQ(spec.hwirq + i);
+
+               ret = irq_domain_set_hwirq_and_chip(d, virq + i,
+                                                   hwirq,
+                                                   &gic_level_irq_controller,
+                                                   NULL);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+void gic_dev_domain_free(struct irq_domain *d, unsigned int virq,
+                        unsigned int nr_irqs)
+{
+       /* no real allocation is done for dev irqs, so no need to free anything */
+       return;
+}
+
+static struct irq_domain_ops gic_dev_domain_ops = {
+       .xlate = gic_dev_domain_xlate,
+       .alloc = gic_dev_domain_alloc,
+       .free = gic_dev_domain_free,
+};
+
+static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+                               const u32 *intspec, unsigned int intsize,
+                               irq_hw_number_t *out_hwirq,
+                               unsigned int *out_type)
+{
+       /*
+        * There's nothing to translate here. hwirq is dynamically allocated and
+        * the irq type is always edge triggered.
+        * */
+       *out_hwirq = 0;
+       *out_type = IRQ_TYPE_EDGE_RISING;
+
+       return 0;
+}
+
+static int gic_ipi_domain_alloc(struct irq_domain *d, unsigned int virq,
+                               unsigned int nr_irqs, void *arg)
+{
+       struct cpumask *ipimask = arg;
+       struct gic_irq_spec spec = {
+               .type = GIC_IPI,
+               .ipimask = ipimask
+       };
+       int ret, i;
+
+       ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &spec);
+       if (ret)
+               return ret;
+
+       /* the parent should have set spec.hwirq to the base_hwirq it allocated */
+       for (i = 0; i < nr_irqs; i++) {
+               ret = irq_domain_set_hwirq_and_chip(d, virq + i,
+                                                   GIC_SHARED_TO_HWIRQ(spec.hwirq + i),
+                                                   &gic_edge_irq_controller,
+                                                   NULL);
+               if (ret)
+                       goto error;
+
+               ret = irq_set_irq_type(virq + i, IRQ_TYPE_EDGE_RISING);
+               if (ret)
+                       goto error;
+       }
+
+       return 0;
+error:
+       irq_domain_free_irqs_parent(d, virq, nr_irqs);
+       return ret;
+}
+
+void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq,
+                        unsigned int nr_irqs)
+{
+       irq_domain_free_irqs_parent(d, virq, nr_irqs);
+}
+
+int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node,
+                        enum irq_domain_bus_token bus_token)
+{
+       bool is_ipi;
+
+       switch (bus_token) {
+       case DOMAIN_BUS_IPI:
+               is_ipi = d->bus_token == bus_token;
+               return to_of_node(d->fwnode) == node && is_ipi;
+               break;
+       default:
+               return 0;
+       }
+}
+
+static struct irq_domain_ops gic_ipi_domain_ops = {
+       .xlate = gic_ipi_domain_xlate,
+       .alloc = gic_ipi_domain_alloc,
+       .free = gic_ipi_domain_free,
+       .match = gic_ipi_domain_match,
 };
 
 static void __init __gic_init(unsigned long gic_base_addr,
@@ -809,6 +957,7 @@ static void __init __gic_init(unsigned long gic_base_addr,
                              struct device_node *node)
 {
        unsigned int gicconfig;
+       unsigned int v[2];
 
        __gic_base_addr = gic_base_addr;
 
@@ -864,9 +1013,32 @@ static void __init __gic_init(unsigned long gic_base_addr,
        if (!gic_irq_domain)
                panic("Failed to add GIC IRQ domain");
 
-       gic_basic_init();
+       gic_dev_domain = irq_domain_add_hierarchy(gic_irq_domain, 0,
+                                                 GIC_NUM_LOCAL_INTRS + gic_shared_intrs,
+                                                 node, &gic_dev_domain_ops, NULL);
+       if (!gic_dev_domain)
+               panic("Failed to add GIC DEV domain");
+
+       gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain,
+                                                 IRQ_DOMAIN_FLAG_IPI_PER_CPU,
+                                                 GIC_NUM_LOCAL_INTRS + gic_shared_intrs,
+                                                 node, &gic_ipi_domain_ops, NULL);
+       if (!gic_ipi_domain)
+               panic("Failed to add GIC IPI domain");
 
-       gic_ipi_init();
+       gic_ipi_domain->bus_token = DOMAIN_BUS_IPI;
+
+       if (node &&
+           !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) {
+               bitmap_set(ipi_resrv, v[0], v[1]);
+       } else {
+               /* Make the last 2 * gic_vpes available for IPIs */
+               bitmap_set(ipi_resrv,
+                          gic_shared_intrs - 2 * gic_vpes,
+                          2 * gic_vpes);
+       }
+
+       gic_basic_init();
 }
 
 void __init gic_init(unsigned long gic_base_addr,
diff --git a/drivers/irqchip/irq-mvebu-odmi.c b/drivers/irqchip/irq-mvebu-odmi.c
new file mode 100644 (file)
index 0000000..b4d3678
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2016 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#define pr_fmt(fmt) "GIC-ODMI: " fmt
+
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/msi.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#define GICP_ODMIN_SET                 0x40
+#define   GICP_ODMI_INT_NUM_SHIFT      12
+#define GICP_ODMIN_GM_EP_R0            0x110
+#define GICP_ODMIN_GM_EP_R1            0x114
+#define GICP_ODMIN_GM_EA_R0            0x108
+#define GICP_ODMIN_GM_EA_R1            0x118
+
+/*
+ * We don't support the group events, so we simply have 8 interrupts
+ * per frame.
+ */
+#define NODMIS_SHIFT           3
+#define NODMIS_PER_FRAME       (1 << NODMIS_SHIFT)
+#define NODMIS_MASK            (NODMIS_PER_FRAME - 1)
+
+struct odmi_data {
+       struct resource res;
+       void __iomem *base;
+       unsigned int spi_base;
+};
+
+static struct odmi_data *odmis;
+static unsigned long *odmis_bm;
+static unsigned int odmis_count;
+
+/* Protects odmis_bm */
+static DEFINE_SPINLOCK(odmis_bm_lock);
+
+static void odmi_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
+{
+       struct odmi_data *odmi;
+       phys_addr_t addr;
+       unsigned int odmin;
+
+       if (WARN_ON(d->hwirq >= odmis_count * NODMIS_PER_FRAME))
+               return;
+
+       odmi = &odmis[d->hwirq >> NODMIS_SHIFT];
+       odmin = d->hwirq & NODMIS_MASK;
+
+       addr = odmi->res.start + GICP_ODMIN_SET;
+
+       msg->address_hi = upper_32_bits(addr);
+       msg->address_lo = lower_32_bits(addr);
+       msg->data = odmin << GICP_ODMI_INT_NUM_SHIFT;
+}
+
+static struct irq_chip odmi_irq_chip = {
+       .name                   = "ODMI",
+       .irq_mask               = irq_chip_mask_parent,
+       .irq_unmask             = irq_chip_unmask_parent,
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+       .irq_compose_msi_msg    = odmi_compose_msi_msg,
+};
+
+static int odmi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+                                unsigned int nr_irqs, void *args)
+{
+       struct odmi_data *odmi = NULL;
+       struct irq_fwspec fwspec;
+       struct irq_data *d;
+       unsigned int hwirq, odmin;
+       int ret;
+
+       spin_lock(&odmis_bm_lock);
+       hwirq = find_first_zero_bit(odmis_bm, NODMIS_PER_FRAME * odmis_count);
+       if (hwirq >= NODMIS_PER_FRAME * odmis_count) {
+               spin_unlock(&odmis_bm_lock);
+               return -ENOSPC;
+       }
+
+       __set_bit(hwirq, odmis_bm);
+       spin_unlock(&odmis_bm_lock);
+
+       odmi = &odmis[hwirq >> NODMIS_SHIFT];
+       odmin = hwirq & NODMIS_MASK;
+
+       fwspec.fwnode = domain->parent->fwnode;
+       fwspec.param_count = 3;
+       fwspec.param[0] = GIC_SPI;
+       fwspec.param[1] = odmi->spi_base - 32 + odmin;
+       fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+
+       ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
+       if (ret) {
+               pr_err("Cannot allocate parent IRQ\n");
+               spin_lock(&odmis_bm_lock);
+               __clear_bit(odmin, odmis_bm);
+               spin_unlock(&odmis_bm_lock);
+               return ret;
+       }
+
+       /* Configure the interrupt line to be edge */
+       d = irq_domain_get_irq_data(domain->parent, virq);
+       d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING);
+
+       irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+                                     &odmi_irq_chip, NULL);
+
+       return 0;
+}
+
+static void odmi_irq_domain_free(struct irq_domain *domain,
+                                unsigned int virq, unsigned int nr_irqs)
+{
+       struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+
+       if (d->hwirq >= odmis_count * NODMIS_PER_FRAME) {
+               pr_err("Failed to teardown msi. Invalid hwirq %lu\n", d->hwirq);
+               return;
+       }
+
+       irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+
+       /* Actually free the MSI */
+       spin_lock(&odmis_bm_lock);
+       __clear_bit(d->hwirq, odmis_bm);
+       spin_unlock(&odmis_bm_lock);
+}
+
+static const struct irq_domain_ops odmi_domain_ops = {
+       .alloc  = odmi_irq_domain_alloc,
+       .free   = odmi_irq_domain_free,
+};
+
+static struct irq_chip odmi_msi_irq_chip = {
+       .name   = "ODMI",
+};
+
+static struct msi_domain_ops odmi_msi_ops = {
+};
+
+static struct msi_domain_info odmi_msi_domain_info = {
+       .flags  = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
+       .ops    = &odmi_msi_ops,
+       .chip   = &odmi_msi_irq_chip,
+};
+
+static int __init mvebu_odmi_init(struct device_node *node,
+                                 struct device_node *parent)
+{
+       struct irq_domain *inner_domain, *plat_domain;
+       int ret, i;
+
+       if (of_property_read_u32(node, "marvell,odmi-frames", &odmis_count))
+               return -EINVAL;
+
+       odmis = kcalloc(odmis_count, sizeof(struct odmi_data), GFP_KERNEL);
+       if (!odmis)
+               return -ENOMEM;
+
+       odmis_bm = kcalloc(BITS_TO_LONGS(odmis_count * NODMIS_PER_FRAME),
+                          sizeof(long), GFP_KERNEL);
+       if (!odmis_bm) {
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+
+       for (i = 0; i < odmis_count; i++) {
+               struct odmi_data *odmi = &odmis[i];
+
+               ret = of_address_to_resource(node, i, &odmi->res);
+               if (ret)
+                       goto err_unmap;
+
+               odmi->base = of_io_request_and_map(node, i, "odmi");
+               if (IS_ERR(odmi->base)) {
+                       ret = PTR_ERR(odmi->base);
+                       goto err_unmap;
+               }
+
+               if (of_property_read_u32_index(node, "marvell,spi-base",
+                                              i, &odmi->spi_base)) {
+                       ret = -EINVAL;
+                       goto err_unmap;
+               }
+       }
+
+       inner_domain = irq_domain_create_linear(of_node_to_fwnode(node),
+                                               odmis_count * NODMIS_PER_FRAME,
+                                               &odmi_domain_ops, NULL);
+       if (!inner_domain) {
+               ret = -ENOMEM;
+               goto err_unmap;
+       }
+
+       inner_domain->parent = irq_find_host(parent);
+
+       plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node),
+                                                    &odmi_msi_domain_info,
+                                                    inner_domain);
+       if (!plat_domain) {
+               ret = -ENOMEM;
+               goto err_remove_inner;
+       }
+
+       return 0;
+
+err_remove_inner:
+       irq_domain_remove(inner_domain);
+err_unmap:
+       for (i = 0; i < odmis_count; i++) {
+               struct odmi_data *odmi = &odmis[i];
+
+               if (odmi->base && !IS_ERR(odmi->base))
+                       iounmap(odmis[i].base);
+       }
+       kfree(odmis_bm);
+err_alloc:
+       kfree(odmis);
+       return ret;
+}
+
+IRQCHIP_DECLARE(mvebu_odmi, "marvell,odmi-controller", mvebu_odmi_init);
index efe50845939d91fee149acb085912697031dd9a0..17304705f2cf9443b99690565ece5b537e3e61c4 100644 (file)
@@ -183,7 +183,7 @@ static void __iomem * __init icoll_init_iobase(struct device_node *np)
        void __iomem *icoll_base;
 
        icoll_base = of_io_request_and_map(np, 0, np->name);
-       if (!icoll_base)
+       if (IS_ERR(icoll_base))
                panic("%s: unable to map resource", np->full_name);
        return icoll_base;
 }
index 0820f67cc9a76b42a8891501c9f04c574d6e27e8..668730c5cb66f3bf4b06846ea4daf4b97dd3675d 100644 (file)
@@ -160,9 +160,9 @@ static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
 
        gc = irq_get_domain_generic_chip(domain, 0);
        gc->reg_base = of_io_request_and_map(node, 0, of_node_full_name(node));
-       if (!gc->reg_base) {
+       if (IS_ERR(gc->reg_base)) {
                pr_err("unable to map resource\n");
-               ret = -ENOMEM;
+               ret = PTR_ERR(gc->reg_base);
                goto fail_irqd_remove;
        }
 
diff --git a/drivers/irqchip/irq-tango.c b/drivers/irqchip/irq-tango.c
new file mode 100644 (file)
index 0000000..bdbb5c0
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2014 Mans Rullgard <mans@mansr.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+
+#define IRQ0_CTL_BASE          0x0000
+#define IRQ1_CTL_BASE          0x0100
+#define EDGE_CTL_BASE          0x0200
+#define IRQ2_CTL_BASE          0x0300
+
+#define IRQ_CTL_HI             0x18
+#define EDGE_CTL_HI            0x20
+
+#define IRQ_STATUS             0x00
+#define IRQ_RAWSTAT            0x04
+#define IRQ_EN_SET             0x08
+#define IRQ_EN_CLR             0x0c
+#define IRQ_SOFT_SET           0x10
+#define IRQ_SOFT_CLR           0x14
+
+#define EDGE_STATUS            0x00
+#define EDGE_RAWSTAT           0x04
+#define EDGE_CFG_RISE          0x08
+#define EDGE_CFG_FALL          0x0c
+#define EDGE_CFG_RISE_SET      0x10
+#define EDGE_CFG_RISE_CLR      0x14
+#define EDGE_CFG_FALL_SET      0x18
+#define EDGE_CFG_FALL_CLR      0x1c
+
+struct tangox_irq_chip {
+       void __iomem *base;
+       unsigned long ctl;
+};
+
+static inline u32 intc_readl(struct tangox_irq_chip *chip, int reg)
+{
+       return readl_relaxed(chip->base + reg);
+}
+
+static inline void intc_writel(struct tangox_irq_chip *chip, int reg, u32 val)
+{
+       writel_relaxed(val, chip->base + reg);
+}
+
+static void tangox_dispatch_irqs(struct irq_domain *dom, unsigned int status,
+                                int base)
+{
+       unsigned int hwirq;
+       unsigned int virq;
+
+       while (status) {
+               hwirq = __ffs(status);
+               virq = irq_find_mapping(dom, base + hwirq);
+               if (virq)
+                       generic_handle_irq(virq);
+               status &= ~BIT(hwirq);
+       }
+}
+
+static void tangox_irq_handler(struct irq_desc *desc)
+{
+       struct irq_domain *dom = irq_desc_get_handler_data(desc);
+       struct irq_chip *host_chip = irq_desc_get_chip(desc);
+       struct tangox_irq_chip *chip = dom->host_data;
+       unsigned int status_lo, status_hi;
+
+       chained_irq_enter(host_chip, desc);
+
+       status_lo = intc_readl(chip, chip->ctl + IRQ_STATUS);
+       status_hi = intc_readl(chip, chip->ctl + IRQ_CTL_HI + IRQ_STATUS);
+
+       tangox_dispatch_irqs(dom, status_lo, 0);
+       tangox_dispatch_irqs(dom, status_hi, 32);
+
+       chained_irq_exit(host_chip, desc);
+}
+
+static int tangox_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct tangox_irq_chip *chip = gc->domain->host_data;
+       struct irq_chip_regs *regs = &gc->chip_types[0].regs;
+
+       switch (flow_type & IRQ_TYPE_SENSE_MASK) {
+       case IRQ_TYPE_EDGE_RISING:
+               intc_writel(chip, regs->type + EDGE_CFG_RISE_SET, d->mask);
+               intc_writel(chip, regs->type + EDGE_CFG_FALL_CLR, d->mask);
+               break;
+
+       case IRQ_TYPE_EDGE_FALLING:
+               intc_writel(chip, regs->type + EDGE_CFG_RISE_CLR, d->mask);
+               intc_writel(chip, regs->type + EDGE_CFG_FALL_SET, d->mask);
+               break;
+
+       case IRQ_TYPE_LEVEL_HIGH:
+               intc_writel(chip, regs->type + EDGE_CFG_RISE_CLR, d->mask);
+               intc_writel(chip, regs->type + EDGE_CFG_FALL_CLR, d->mask);
+               break;
+
+       case IRQ_TYPE_LEVEL_LOW:
+               intc_writel(chip, regs->type + EDGE_CFG_RISE_SET, d->mask);
+               intc_writel(chip, regs->type + EDGE_CFG_FALL_SET, d->mask);
+               break;
+
+       default:
+               pr_err("Invalid trigger mode %x for IRQ %d\n",
+                      flow_type, d->irq);
+               return -EINVAL;
+       }
+
+       return irq_setup_alt_chip(d, flow_type);
+}
+
+static void __init tangox_irq_init_chip(struct irq_chip_generic *gc,
+                                       unsigned long ctl_offs,
+                                       unsigned long edge_offs)
+{
+       struct tangox_irq_chip *chip = gc->domain->host_data;
+       struct irq_chip_type *ct = gc->chip_types;
+       unsigned long ctl_base = chip->ctl + ctl_offs;
+       unsigned long edge_base = EDGE_CTL_BASE + edge_offs;
+       int i;
+
+       gc->reg_base = chip->base;
+       gc->unused = 0;
+
+       for (i = 0; i < 2; i++) {
+               ct[i].chip.irq_ack = irq_gc_ack_set_bit;
+               ct[i].chip.irq_mask = irq_gc_mask_disable_reg;
+               ct[i].chip.irq_mask_ack = irq_gc_mask_disable_reg_and_ack;
+               ct[i].chip.irq_unmask = irq_gc_unmask_enable_reg;
+               ct[i].chip.irq_set_type = tangox_irq_set_type;
+               ct[i].chip.name = gc->domain->name;
+
+               ct[i].regs.enable = ctl_base + IRQ_EN_SET;
+               ct[i].regs.disable = ctl_base + IRQ_EN_CLR;
+               ct[i].regs.ack = edge_base + EDGE_RAWSTAT;
+               ct[i].regs.type = edge_base;
+       }
+
+       ct[0].type = IRQ_TYPE_LEVEL_MASK;
+       ct[0].handler = handle_level_irq;
+
+       ct[1].type = IRQ_TYPE_EDGE_BOTH;
+       ct[1].handler = handle_edge_irq;
+
+       intc_writel(chip, ct->regs.disable, 0xffffffff);
+       intc_writel(chip, ct->regs.ack, 0xffffffff);
+}
+
+static void __init tangox_irq_domain_init(struct irq_domain *dom)
+{
+       struct irq_chip_generic *gc;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               gc = irq_get_domain_generic_chip(dom, i * 32);
+               tangox_irq_init_chip(gc, i * IRQ_CTL_HI, i * EDGE_CTL_HI);
+       }
+}
+
+static int __init tangox_irq_init(void __iomem *base, struct resource *baseres,
+                                 struct device_node *node)
+{
+       struct tangox_irq_chip *chip;
+       struct irq_domain *dom;
+       struct resource res;
+       int irq;
+       int err;
+
+       irq = irq_of_parse_and_map(node, 0);
+       if (!irq)
+               panic("%s: failed to get IRQ", node->name);
+
+       err = of_address_to_resource(node, 0, &res);
+       if (err)
+               panic("%s: failed to get address", node->name);
+
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       chip->ctl = res.start - baseres->start;
+       chip->base = base;
+
+       dom = irq_domain_add_linear(node, 64, &irq_generic_chip_ops, chip);
+       if (!dom)
+               panic("%s: failed to create irqdomain", node->name);
+
+       err = irq_alloc_domain_generic_chips(dom, 32, 2, node->name,
+                                            handle_level_irq, 0, 0, 0);
+       if (err)
+               panic("%s: failed to allocate irqchip", node->name);
+
+       tangox_irq_domain_init(dom);
+
+       irq_set_chained_handler(irq, tangox_irq_handler);
+       irq_set_handler_data(irq, dom);
+
+       return 0;
+}
+
+static int __init tangox_of_irq_init(struct device_node *node,
+                                    struct device_node *parent)
+{
+       struct device_node *c;
+       struct resource res;
+       void __iomem *base;
+
+       base = of_iomap(node, 0);
+       if (!base)
+               panic("%s: of_iomap failed", node->name);
+
+       of_address_to_resource(node, 0, &res);
+
+       for_each_child_of_node(node, c)
+               tangox_irq_init(base, &res, c);
+
+       return 0;
+}
+IRQCHIP_DECLARE(tangox_intc, "sigma,smp8642-intc", tangox_of_irq_init);
index 4192bdcd27340face79f0b05da538faca706c539..2325fb3c482b8714d9041eed94ea8c91095f2beb 100644 (file)
@@ -59,7 +59,7 @@ static int ts4800_irqdomain_map(struct irq_domain *d, unsigned int irq,
        return 0;
 }
 
-struct irq_domain_ops ts4800_ic_ops = {
+static const struct irq_domain_ops ts4800_ic_ops = {
        .map = ts4800_irqdomain_map,
        .xlate = irq_domain_xlate_onecell,
 };
index 7f940c24a16b0d00163051acfda665b692733b5d..1f64151689981335edec187c20bb71bbc5f1feb6 100644 (file)
@@ -568,6 +568,14 @@ config LEDS_SEAD3
          This driver can also be built as a module. If so the module
          will be called leds-sead3.
 
+config LEDS_IS31FL32XX
+       tristate "LED support for ISSI IS31FL32XX I2C LED controller family"
+       depends on LEDS_CLASS && I2C && OF
+       help
+         Say Y here to include support for ISSI IS31FL32XX and Si-En SN32xx
+         LED controllers. They are I2C devices with multiple constant-current
+         channels, each with independent 256-level PWM control.
+
 comment "LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)"
 
 config LEDS_BLINKM
index e9d53092765d8ca8ae43e970dc63ec1c23e96b78..cb2013df52d9945cd51601529b013828f7120f1b 100644 (file)
@@ -66,6 +66,7 @@ obj-$(CONFIG_LEDS_MENF21BMC)          += leds-menf21bmc.o
 obj-$(CONFIG_LEDS_KTD2692)             += leds-ktd2692.o
 obj-$(CONFIG_LEDS_POWERNV)             += leds-powernv.o
 obj-$(CONFIG_LEDS_SEAD3)               += leds-sead3.o
+obj-$(CONFIG_LEDS_IS31FL32XX)          += leds-is31fl32xx.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)          += leds-dac124s085.o
index 14139c337312c574c82a98bee4c163834cad6bc5..aa84e5b375931825e71b23f6e2d1eefc7c3bea17 100644 (file)
@@ -245,6 +245,8 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
        up_write(&led_cdev->trigger_lock);
 #endif
 
+       led_cdev->flags |= LED_UNREGISTERING;
+
        /* Stop blinking */
        led_stop_software_blink(led_cdev);
 
index 19e1e60dfaa354585ca01e2ffdc2a47f29c49c3b..3495d5d6547f65a6fe507f063dce397bc424496f 100644 (file)
@@ -25,6 +25,26 @@ EXPORT_SYMBOL_GPL(leds_list_lock);
 LIST_HEAD(leds_list);
 EXPORT_SYMBOL_GPL(leds_list);
 
+static int __led_set_brightness(struct led_classdev *led_cdev,
+                               enum led_brightness value)
+{
+       if (!led_cdev->brightness_set)
+               return -ENOTSUPP;
+
+       led_cdev->brightness_set(led_cdev, value);
+
+       return 0;
+}
+
+static int __led_set_brightness_blocking(struct led_classdev *led_cdev,
+                                        enum led_brightness value)
+{
+       if (!led_cdev->brightness_set_blocking)
+               return -ENOTSUPP;
+
+       return led_cdev->brightness_set_blocking(led_cdev, value);
+}
+
 static void led_timer_function(unsigned long data)
 {
        struct led_classdev *led_cdev = (void *)data;
@@ -91,14 +111,14 @@ static void set_brightness_delayed(struct work_struct *ws)
                led_cdev->flags &= ~LED_BLINK_DISABLE;
        }
 
-       if (led_cdev->brightness_set)
-               led_cdev->brightness_set(led_cdev, led_cdev->delayed_set_value);
-       else if (led_cdev->brightness_set_blocking)
-               ret = led_cdev->brightness_set_blocking(led_cdev,
-                                               led_cdev->delayed_set_value);
-       else
-               ret = -ENOTSUPP;
-       if (ret < 0)
+       ret = __led_set_brightness(led_cdev, led_cdev->delayed_set_value);
+       if (ret == -ENOTSUPP)
+               ret = __led_set_brightness_blocking(led_cdev,
+                                       led_cdev->delayed_set_value);
+       if (ret < 0 &&
+           /* LED HW might have been unplugged, therefore don't warn */
+           !(ret == -ENODEV && (led_cdev->flags & LED_UNREGISTERING) &&
+           (led_cdev->flags & LED_HW_PLUGGABLE)))
                dev_err(led_cdev->dev,
                        "Setting an LED's brightness failed (%d)\n", ret);
 }
@@ -233,10 +253,8 @@ void led_set_brightness_nopm(struct led_classdev *led_cdev,
                              enum led_brightness value)
 {
        /* Use brightness_set op if available, it is guaranteed not to sleep */
-       if (led_cdev->brightness_set) {
-               led_cdev->brightness_set(led_cdev, value);
+       if (!__led_set_brightness(led_cdev, value))
                return;
-       }
 
        /* If brightness setting can sleep, delegate it to a work queue task */
        led_cdev->delayed_set_value = value;
@@ -267,10 +285,7 @@ int led_set_brightness_sync(struct led_classdev *led_cdev,
        if (led_cdev->flags & LED_SUSPENDED)
                return 0;
 
-       if (led_cdev->brightness_set_blocking)
-               return led_cdev->brightness_set_blocking(led_cdev,
-                                                        led_cdev->brightness);
-       return -ENOTSUPP;
+       return __led_set_brightness_blocking(led_cdev, led_cdev->brightness);
 }
 EXPORT_SYMBOL_GPL(led_set_brightness_sync);
 
index e1e933424ac9a4366a223eeb7e8ca13d4d9290e3..2181581795d306c125f0cd0a7a9e14e744d07326 100644 (file)
@@ -34,9 +34,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
 {
        struct led_classdev *led_cdev = dev_get_drvdata(dev);
-       char trigger_name[TRIG_NAME_MAX];
        struct led_trigger *trig;
-       size_t len;
        int ret = count;
 
        mutex_lock(&led_cdev->led_access);
@@ -46,21 +44,14 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
                goto unlock;
        }
 
-       trigger_name[sizeof(trigger_name) - 1] = '\0';
-       strncpy(trigger_name, buf, sizeof(trigger_name) - 1);
-       len = strlen(trigger_name);
-
-       if (len && trigger_name[len - 1] == '\n')
-               trigger_name[len - 1] = '\0';
-
-       if (!strcmp(trigger_name, "none")) {
+       if (sysfs_streq(buf, "none")) {
                led_trigger_remove(led_cdev);
                goto unlock;
        }
 
        down_read(&triggers_list_lock);
        list_for_each_entry(trig, &trigger_list, next_trig) {
-               if (!strcmp(trigger_name, trig->name)) {
+               if (sysfs_streq(buf, trig->name)) {
                        down_write(&led_cdev->trigger_lock);
                        led_trigger_set(led_cdev, trig);
                        up_write(&led_cdev->trigger_lock);
index 1ad4d03a0a3ceca894ae1b1ffdc8212d1558165d..77a104d2b1243a503d8daa0660d73ae19baa819e 100644 (file)
@@ -195,7 +195,6 @@ static int pm860x_led_probe(struct platform_device *pdev)
                sprintf(data->name, "led1-blue");
                break;
        }
-       platform_set_drvdata(pdev, data);
        data->chip = chip;
        data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
        data->port = pdev->id;
@@ -208,7 +207,7 @@ static int pm860x_led_probe(struct platform_device *pdev)
        data->cdev.brightness_set_blocking = pm860x_led_set;
        mutex_init(&data->lock);
 
-       ret = led_classdev_register(chip->dev, &data->cdev);
+       ret = devm_led_classdev_register(chip->dev, &data->cdev);
        if (ret < 0) {
                dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
                return ret;
@@ -217,21 +216,12 @@ static int pm860x_led_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int pm860x_led_remove(struct platform_device *pdev)
-{
-       struct pm860x_led *data = platform_get_drvdata(pdev);
-
-       led_classdev_unregister(&data->cdev);
-
-       return 0;
-}
 
 static struct platform_driver pm860x_led_driver = {
        .driver = {
                .name   = "88pm860x-led",
        },
        .probe  = pm860x_led_probe,
-       .remove = pm860x_led_remove,
 };
 
 module_platform_driver(pm860x_led_driver);
index 4752a2b6ba2bc8d0ea9478b7692664ab2020eafa..5ff7d72f73aa4ac62ceeab074fb26a6f09e69b3f 100644 (file)
@@ -113,21 +113,12 @@ static int da903x_led_probe(struct platform_device *pdev)
        led->flags = pdata->flags;
        led->master = pdev->dev.parent;
 
-       ret = led_classdev_register(led->master, &led->cdev);
+       ret = devm_led_classdev_register(led->master, &led->cdev);
        if (ret) {
                dev_err(&pdev->dev, "failed to register LED %d\n", id);
                return ret;
        }
 
-       platform_set_drvdata(pdev, led);
-       return 0;
-}
-
-static int da903x_led_remove(struct platform_device *pdev)
-{
-       struct da903x_led *led = platform_get_drvdata(pdev);
-
-       led_classdev_unregister(&led->cdev);
        return 0;
 }
 
@@ -136,7 +127,6 @@ static struct platform_driver da903x_led_driver = {
                .name   = "da903x-led",
        },
        .probe          = da903x_led_probe,
-       .remove         = da903x_led_remove,
 };
 
 module_platform_driver(da903x_led_driver);
index 7bc53280dbfdd91d0d2efa51bb63986a6bbf336b..61143f55597e42f9b45fe4efe33a1c51614b22b4 100644 (file)
@@ -86,7 +86,7 @@ static int create_gpio_led(const struct gpio_led *template,
                 * still uses GPIO numbers. Ultimately we would like to get
                 * rid of this block completely.
                 */
-               unsigned long flags = 0;
+               unsigned long flags = GPIOF_OUT_INIT_LOW;
 
                /* skip leds that aren't available */
                if (!gpio_is_valid(template->gpio)) {
@@ -104,8 +104,8 @@ static int create_gpio_led(const struct gpio_led *template,
                        return ret;
 
                led_dat->gpiod = gpio_to_desc(template->gpio);
-               if (IS_ERR(led_dat->gpiod))
-                       return PTR_ERR(led_dat->gpiod);
+               if (!led_dat->gpiod)
+                       return -EINVAL;
        }
 
        led_dat->cdev.name = template->name;
diff --git a/drivers/leds/leds-is31fl32xx.c b/drivers/leds/leds-is31fl32xx.c
new file mode 100644 (file)
index 0000000..c901d13
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * Driver for ISSI IS31FL32xx family of I2C LED controllers
+ *
+ * Copyright 2015 Allworx Corp.
+ *
+ *
+ * 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.
+ *
+ * Datasheets:
+ *   http://www.issi.com/US/product-analog-fxled-driver.shtml
+ *   http://www.si-en.com/product.asp?parentid=890
+ */
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+/* Used to indicate a device has no such register */
+#define IS31FL32XX_REG_NONE 0xFF
+
+/* Software Shutdown bit in Shutdown Register */
+#define IS31FL32XX_SHUTDOWN_SSD_ENABLE  0
+#define IS31FL32XX_SHUTDOWN_SSD_DISABLE BIT(0)
+
+/* IS31FL3216 has a number of unique registers */
+#define IS31FL3216_CONFIG_REG 0x00
+#define IS31FL3216_LIGHTING_EFFECT_REG 0x03
+#define IS31FL3216_CHANNEL_CONFIG_REG 0x04
+
+/* Software Shutdown bit in 3216 Config Register */
+#define IS31FL3216_CONFIG_SSD_ENABLE  BIT(7)
+#define IS31FL3216_CONFIG_SSD_DISABLE 0
+
+struct is31fl32xx_priv;
+struct is31fl32xx_led_data {
+       struct led_classdev cdev;
+       u8 channel; /* 1-based, max priv->cdef->channels */
+       struct is31fl32xx_priv *priv;
+};
+
+struct is31fl32xx_priv {
+       const struct is31fl32xx_chipdef *cdef;
+       struct i2c_client *client;
+       unsigned int num_leds;
+       struct is31fl32xx_led_data leds[0];
+};
+
+/**
+ * struct is31fl32xx_chipdef - chip-specific attributes
+ * @channels            : Number of LED channels
+ * @shutdown_reg        : address of Shutdown register (optional)
+ * @pwm_update_reg      : address of PWM Update register
+ * @global_control_reg  : address of Global Control register (optional)
+ * @reset_reg           : address of Reset register (optional)
+ * @pwm_register_base   : address of first PWM register
+ * @pwm_registers_reversed: : true if PWM registers count down instead of up
+ * @led_control_register_base : address of first LED control register (optional)
+ * @enable_bits_per_led_control_register: number of LEDs enable bits in each
+ * @reset_func:         : pointer to reset function
+ *
+ * For all optional register addresses, the sentinel value %IS31FL32XX_REG_NONE
+ * indicates that this chip has no such register.
+ *
+ * If non-NULL, @reset_func will be called during probing to set all
+ * necessary registers to a known initialization state. This is needed
+ * for chips that do not have a @reset_reg.
+ *
+ * @enable_bits_per_led_control_register must be >=1 if
+ * @led_control_register_base != %IS31FL32XX_REG_NONE.
+ */
+struct is31fl32xx_chipdef {
+       u8      channels;
+       u8      shutdown_reg;
+       u8      pwm_update_reg;
+       u8      global_control_reg;
+       u8      reset_reg;
+       u8      pwm_register_base;
+       bool    pwm_registers_reversed;
+       u8      led_control_register_base;
+       u8      enable_bits_per_led_control_register;
+       int (*reset_func)(struct is31fl32xx_priv *priv);
+       int (*sw_shutdown_func)(struct is31fl32xx_priv *priv, bool enable);
+};
+
+static const struct is31fl32xx_chipdef is31fl3236_cdef = {
+       .channels                               = 36,
+       .shutdown_reg                           = 0x00,
+       .pwm_update_reg                         = 0x25,
+       .global_control_reg                     = 0x4a,
+       .reset_reg                              = 0x4f,
+       .pwm_register_base                      = 0x01,
+       .led_control_register_base              = 0x26,
+       .enable_bits_per_led_control_register   = 1,
+};
+
+static const struct is31fl32xx_chipdef is31fl3235_cdef = {
+       .channels                               = 28,
+       .shutdown_reg                           = 0x00,
+       .pwm_update_reg                         = 0x25,
+       .global_control_reg                     = 0x4a,
+       .reset_reg                              = 0x4f,
+       .pwm_register_base                      = 0x05,
+       .led_control_register_base              = 0x2a,
+       .enable_bits_per_led_control_register   = 1,
+};
+
+static const struct is31fl32xx_chipdef is31fl3218_cdef = {
+       .channels                               = 18,
+       .shutdown_reg                           = 0x00,
+       .pwm_update_reg                         = 0x16,
+       .global_control_reg                     = IS31FL32XX_REG_NONE,
+       .reset_reg                              = 0x17,
+       .pwm_register_base                      = 0x01,
+       .led_control_register_base              = 0x13,
+       .enable_bits_per_led_control_register   = 6,
+};
+
+static int is31fl3216_reset(struct is31fl32xx_priv *priv);
+static int is31fl3216_software_shutdown(struct is31fl32xx_priv *priv,
+                                       bool enable);
+static const struct is31fl32xx_chipdef is31fl3216_cdef = {
+       .channels                               = 16,
+       .shutdown_reg                           = IS31FL32XX_REG_NONE,
+       .pwm_update_reg                         = 0xB0,
+       .global_control_reg                     = IS31FL32XX_REG_NONE,
+       .reset_reg                              = IS31FL32XX_REG_NONE,
+       .pwm_register_base                      = 0x10,
+       .pwm_registers_reversed                 = true,
+       .led_control_register_base              = 0x01,
+       .enable_bits_per_led_control_register   = 8,
+       .reset_func                             = is31fl3216_reset,
+       .sw_shutdown_func                       = is31fl3216_software_shutdown,
+};
+
+static int is31fl32xx_write(struct is31fl32xx_priv *priv, u8 reg, u8 val)
+{
+       int ret;
+
+       dev_dbg(&priv->client->dev, "writing register 0x%02X=0x%02X", reg, val);
+
+       ret =  i2c_smbus_write_byte_data(priv->client, reg, val);
+       if (ret) {
+               dev_err(&priv->client->dev,
+                       "register write to 0x%02X failed (error %d)",
+                       reg, ret);
+       }
+       return ret;
+}
+
+/*
+ * Custom reset function for IS31FL3216 because it does not have a RESET
+ * register the way that the other IS31FL32xx chips do. We don't bother
+ * writing the GPIO and animation registers, because the registers we
+ * do write ensure those will have no effect.
+ */
+static int is31fl3216_reset(struct is31fl32xx_priv *priv)
+{
+       unsigned int i;
+       int ret;
+
+       ret = is31fl32xx_write(priv, IS31FL3216_CONFIG_REG,
+                              IS31FL3216_CONFIG_SSD_ENABLE);
+       if (ret)
+               return ret;
+       for (i = 0; i < priv->cdef->channels; i++) {
+               ret = is31fl32xx_write(priv, priv->cdef->pwm_register_base+i,
+                                      0x00);
+               if (ret)
+                       return ret;
+       }
+       ret = is31fl32xx_write(priv, priv->cdef->pwm_update_reg, 0);
+       if (ret)
+               return ret;
+       ret = is31fl32xx_write(priv, IS31FL3216_LIGHTING_EFFECT_REG, 0x00);
+       if (ret)
+               return ret;
+       ret = is31fl32xx_write(priv, IS31FL3216_CHANNEL_CONFIG_REG, 0x00);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+/*
+ * Custom Software-Shutdown function for IS31FL3216 because it does not have
+ * a SHUTDOWN register the way that the other IS31FL32xx chips do.
+ * We don't bother doing a read/modify/write on the CONFIG register because
+ * we only ever use a value of '0' for the other fields in that register.
+ */
+static int is31fl3216_software_shutdown(struct is31fl32xx_priv *priv,
+                                       bool enable)
+{
+       u8 value = enable ? IS31FL3216_CONFIG_SSD_ENABLE :
+                           IS31FL3216_CONFIG_SSD_DISABLE;
+
+       return is31fl32xx_write(priv, IS31FL3216_CONFIG_REG, value);
+}
+
+/*
+ * NOTE: A mutex is not needed in this function because:
+ * - All referenced data is read-only after probe()
+ * - The I2C core has a mutex on to protect the bus
+ * - There are no read/modify/write operations
+ * - Intervening operations between the write of the PWM register
+ *   and the Update register are harmless.
+ *
+ * Example:
+ *     PWM_REG_1 write 16
+ *     UPDATE_REG write 0
+ *     PWM_REG_2 write 128
+ *     UPDATE_REG write 0
+ *   vs:
+ *     PWM_REG_1 write 16
+ *     PWM_REG_2 write 128
+ *     UPDATE_REG write 0
+ *     UPDATE_REG write 0
+ * are equivalent. Poking the Update register merely applies all PWM
+ * register writes up to that point.
+ */
+static int is31fl32xx_brightness_set(struct led_classdev *led_cdev,
+                                    enum led_brightness brightness)
+{
+       const struct is31fl32xx_led_data *led_data =
+               container_of(led_cdev, struct is31fl32xx_led_data, cdev);
+       const struct is31fl32xx_chipdef *cdef = led_data->priv->cdef;
+       u8 pwm_register_offset;
+       int ret;
+
+       dev_dbg(led_cdev->dev, "%s: %d\n", __func__, brightness);
+
+       /* NOTE: led_data->channel is 1-based */
+       if (cdef->pwm_registers_reversed)
+               pwm_register_offset = cdef->channels - led_data->channel;
+       else
+               pwm_register_offset = led_data->channel - 1;
+
+       ret = is31fl32xx_write(led_data->priv,
+                              cdef->pwm_register_base + pwm_register_offset,
+                              brightness);
+       if (ret)
+               return ret;
+
+       return is31fl32xx_write(led_data->priv, cdef->pwm_update_reg, 0);
+}
+
+static int is31fl32xx_reset_regs(struct is31fl32xx_priv *priv)
+{
+       const struct is31fl32xx_chipdef *cdef = priv->cdef;
+       int ret;
+
+       if (cdef->reset_reg != IS31FL32XX_REG_NONE) {
+               ret = is31fl32xx_write(priv, cdef->reset_reg, 0);
+               if (ret)
+                       return ret;
+       }
+
+       if (cdef->reset_func)
+               return cdef->reset_func(priv);
+
+       return 0;
+}
+
+static int is31fl32xx_software_shutdown(struct is31fl32xx_priv *priv,
+                                       bool enable)
+{
+       const struct is31fl32xx_chipdef *cdef = priv->cdef;
+       int ret;
+
+       if (cdef->shutdown_reg != IS31FL32XX_REG_NONE) {
+               u8 value = enable ? IS31FL32XX_SHUTDOWN_SSD_ENABLE :
+                                   IS31FL32XX_SHUTDOWN_SSD_DISABLE;
+               ret = is31fl32xx_write(priv, cdef->shutdown_reg, value);
+               if (ret)
+                       return ret;
+       }
+
+       if (cdef->sw_shutdown_func)
+               return cdef->sw_shutdown_func(priv, enable);
+
+       return 0;
+}
+
+static int is31fl32xx_init_regs(struct is31fl32xx_priv *priv)
+{
+       const struct is31fl32xx_chipdef *cdef = priv->cdef;
+       int ret;
+
+       ret = is31fl32xx_reset_regs(priv);
+       if (ret)
+               return ret;
+
+       /*
+        * Set enable bit for all channels.
+        * We will control state with PWM registers alone.
+        */
+       if (cdef->led_control_register_base != IS31FL32XX_REG_NONE) {
+               u8 value =
+                   GENMASK(cdef->enable_bits_per_led_control_register-1, 0);
+               u8 num_regs = cdef->channels /
+                               cdef->enable_bits_per_led_control_register;
+               int i;
+
+               for (i = 0; i < num_regs; i++) {
+                       ret = is31fl32xx_write(priv,
+                                              cdef->led_control_register_base+i,
+                                              value);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       ret = is31fl32xx_software_shutdown(priv, false);
+       if (ret)
+               return ret;
+
+       if (cdef->global_control_reg != IS31FL32XX_REG_NONE) {
+               ret = is31fl32xx_write(priv, cdef->global_control_reg, 0x00);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static inline size_t sizeof_is31fl32xx_priv(int num_leds)
+{
+       return sizeof(struct is31fl32xx_priv) +
+                     (sizeof(struct is31fl32xx_led_data) * num_leds);
+}
+
+static int is31fl32xx_parse_child_dt(const struct device *dev,
+                                    const struct device_node *child,
+                                    struct is31fl32xx_led_data *led_data)
+{
+       struct led_classdev *cdev = &led_data->cdev;
+       int ret = 0;
+       u32 reg;
+
+       if (of_property_read_string(child, "label", &cdev->name))
+               cdev->name = child->name;
+
+       ret = of_property_read_u32(child, "reg", &reg);
+       if (ret || reg < 1 || reg > led_data->priv->cdef->channels) {
+               dev_err(dev,
+                       "Child node %s does not have a valid reg property\n",
+                       child->full_name);
+               return -EINVAL;
+       }
+       led_data->channel = reg;
+
+       of_property_read_string(child, "linux,default-trigger",
+                               &cdev->default_trigger);
+
+       cdev->brightness_set_blocking = is31fl32xx_brightness_set;
+
+       return 0;
+}
+
+static struct is31fl32xx_led_data *is31fl32xx_find_led_data(
+                                       struct is31fl32xx_priv *priv,
+                                       u8 channel)
+{
+       size_t i;
+
+       for (i = 0; i < priv->num_leds; i++) {
+               if (priv->leds[i].channel == channel)
+                       return &priv->leds[i];
+       }
+
+       return NULL;
+}
+
+static int is31fl32xx_parse_dt(struct device *dev,
+                              struct is31fl32xx_priv *priv)
+{
+       struct device_node *child;
+       int ret = 0;
+
+       for_each_child_of_node(dev->of_node, child) {
+               struct is31fl32xx_led_data *led_data =
+                       &priv->leds[priv->num_leds];
+               const struct is31fl32xx_led_data *other_led_data;
+
+               led_data->priv = priv;
+
+               ret = is31fl32xx_parse_child_dt(dev, child, led_data);
+               if (ret)
+                       goto err;
+
+               /* Detect if channel is already in use by another child */
+               other_led_data = is31fl32xx_find_led_data(priv,
+                                                         led_data->channel);
+               if (other_led_data) {
+                       dev_err(dev,
+                               "%s and %s both attempting to use channel %d\n",
+                               led_data->cdev.name,
+                               other_led_data->cdev.name,
+                               led_data->channel);
+                       goto err;
+               }
+
+               ret = devm_led_classdev_register(dev, &led_data->cdev);
+               if (ret) {
+                       dev_err(dev, "failed to register PWM led for %s: %d\n",
+                               led_data->cdev.name, ret);
+                       goto err;
+               }
+
+               priv->num_leds++;
+       }
+
+       return 0;
+
+err:
+       of_node_put(child);
+       return ret;
+}
+
+static const struct of_device_id of_is31fl31xx_match[] = {
+       { .compatible = "issi,is31fl3236", .data = &is31fl3236_cdef, },
+       { .compatible = "issi,is31fl3235", .data = &is31fl3235_cdef, },
+       { .compatible = "issi,is31fl3218", .data = &is31fl3218_cdef, },
+       { .compatible = "si-en,sn3218",    .data = &is31fl3218_cdef, },
+       { .compatible = "issi,is31fl3216", .data = &is31fl3216_cdef, },
+       { .compatible = "si-en,sn3216",    .data = &is31fl3216_cdef, },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, of_is31fl31xx_match);
+
+static int is31fl32xx_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
+{
+       const struct is31fl32xx_chipdef *cdef;
+       const struct of_device_id *of_dev_id;
+       struct device *dev = &client->dev;
+       struct is31fl32xx_priv *priv;
+       int count;
+       int ret = 0;
+
+       of_dev_id = of_match_device(of_is31fl31xx_match, dev);
+       if (!of_dev_id)
+               return -EINVAL;
+
+       cdef = of_dev_id->data;
+
+       count = of_get_child_count(dev->of_node);
+       if (!count)
+               return -EINVAL;
+
+       priv = devm_kzalloc(dev, sizeof_is31fl32xx_priv(count),
+                           GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->client = client;
+       priv->cdef = cdef;
+       i2c_set_clientdata(client, priv);
+
+       ret = is31fl32xx_init_regs(priv);
+       if (ret)
+               return ret;
+
+       ret = is31fl32xx_parse_dt(dev, priv);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int is31fl32xx_remove(struct i2c_client *client)
+{
+       struct is31fl32xx_priv *priv = i2c_get_clientdata(client);
+
+       return is31fl32xx_reset_regs(priv);
+}
+
+/*
+ * i2c-core requires that id_table be non-NULL, even though
+ * it is not used for DeviceTree based instantiation.
+ */
+static const struct i2c_device_id is31fl31xx_id[] = {
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, is31fl31xx_id);
+
+static struct i2c_driver is31fl32xx_driver = {
+       .driver = {
+               .name   = "is31fl32xx",
+               .of_match_table = of_is31fl31xx_match,
+       },
+       .probe          = is31fl32xx_probe,
+       .remove         = is31fl32xx_remove,
+       .id_table       = is31fl31xx_id,
+};
+
+module_i2c_driver(is31fl32xx_driver);
+
+MODULE_AUTHOR("David Rivshin <drivshin@allworx.com>");
+MODULE_DESCRIPTION("ISSI IS31FL32xx LED driver");
+MODULE_LICENSE("GPL v2");
index 196dcb5e6004a0a93972685b504ae281ed822d0e..5b529dc013d293115c39641ec666a1fbd2935044 100644 (file)
@@ -698,7 +698,7 @@ static int lm3533_led_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, led);
 
-       ret = led_classdev_register(pdev->dev.parent, &led->cdev);
+       ret = devm_led_classdev_register(pdev->dev.parent, &led->cdev);
        if (ret) {
                dev_err(&pdev->dev, "failed to register LED %d\n", pdev->id);
                return ret;
@@ -708,18 +708,13 @@ static int lm3533_led_probe(struct platform_device *pdev)
 
        ret = lm3533_led_setup(led, pdata);
        if (ret)
-               goto err_unregister;
+               return ret;
 
        ret = lm3533_ctrlbank_enable(&led->cb);
        if (ret)
-               goto err_unregister;
+               return ret;
 
        return 0;
-
-err_unregister:
-       led_classdev_unregister(&led->cdev);
-
-       return ret;
 }
 
 static int lm3533_led_remove(struct platform_device *pdev)
@@ -729,7 +724,6 @@ static int lm3533_led_remove(struct platform_device *pdev)
        dev_dbg(&pdev->dev, "%s\n", __func__);
 
        lm3533_ctrlbank_disable(&led->cb);
-       led_classdev_unregister(&led->cdev);
 
        return 0;
 }
index 6c758aea1bbdaa1fb77edf71e9c611e4e131ee0e..be60c181222a562f564eb839d470e85ae932f9d9 100644 (file)
@@ -199,8 +199,11 @@ static int lp3944_led_set(struct lp3944_led_data *led, u8 status)
        if (status > LP3944_LED_STATUS_DIM1)
                return -EINVAL;
 
-       /* invert only 0 and 1, leave unchanged the other values,
-        * remember we are abusing status to set blink patterns
+       /*
+        * Invert status only when it's < 2 (i.e. 0 or 1) which means it's
+        * controlling the on/off state directly.
+        * When, instead, status is >= 2 don't invert it because it would mean
+        * to mess with the hardware blinking mode.
         */
        if (led->type == LP3944_LED_TYPE_LED_INVERTED && status < 2)
                status = 1 - status;
index 0eee38fc05651294cf63f433d331e74942746441..38c253a43700627deebce9751382c645d8c11848 100644 (file)
@@ -146,15 +146,13 @@ static int lp8788_led_probe(struct platform_device *pdev)
 
        mutex_init(&led->lock);
 
-       platform_set_drvdata(pdev, led);
-
        ret = lp8788_led_init_device(led, led_pdata);
        if (ret) {
                dev_err(dev, "led init device err: %d\n", ret);
                return ret;
        }
 
-       ret = led_classdev_register(dev, &led->led_dev);
+       ret = devm_led_classdev_register(dev, &led->led_dev);
        if (ret) {
                dev_err(dev, "led register err: %d\n", ret);
                return ret;
@@ -163,18 +161,8 @@ static int lp8788_led_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int lp8788_led_remove(struct platform_device *pdev)
-{
-       struct lp8788_led *led = platform_get_drvdata(pdev);
-
-       led_classdev_unregister(&led->led_dev);
-
-       return 0;
-}
-
 static struct platform_driver lp8788_led_driver = {
        .probe = lp8788_led_probe,
-       .remove = lp8788_led_remove,
        .driver = {
                .name = LP8788_DEV_KEYLED,
        },
index 01b4590693582c8a0eeaa34bf955535342017c52..4edf74f1d6d4dee72d6fc56621d0e713c17b2eb8 100644 (file)
@@ -281,30 +281,18 @@ static int max8997_led_probe(struct platform_device *pdev)
 
        mutex_init(&led->mutex);
 
-       platform_set_drvdata(pdev, led);
-
-       ret = led_classdev_register(&pdev->dev, &led->cdev);
+       ret = devm_led_classdev_register(&pdev->dev, &led->cdev);
        if (ret < 0)
                return ret;
 
        return 0;
 }
 
-static int max8997_led_remove(struct platform_device *pdev)
-{
-       struct max8997_led *led = platform_get_drvdata(pdev);
-
-       led_classdev_unregister(&led->cdev);
-
-       return 0;
-}
-
 static struct platform_driver max8997_led_driver = {
        .driver = {
                .name  = "max8997-led",
        },
        .probe  = max8997_led_probe,
-       .remove = max8997_led_remove,
 };
 
 module_platform_driver(max8997_led_driver);
index 83641a7b299afe4714bcca197380566dfd1b0712..404da451cb8873d3843007cae607148e40424bda 100644 (file)
@@ -29,11 +29,6 @@ struct s3c24xx_gpio_led {
        struct s3c24xx_led_platdata     *pdata;
 };
 
-static inline struct s3c24xx_gpio_led *pdev_to_gpio(struct platform_device *dev)
-{
-       return platform_get_drvdata(dev);
-}
-
 static inline struct s3c24xx_gpio_led *to_gpio(struct led_classdev *led_cdev)
 {
        return container_of(led_cdev, struct s3c24xx_gpio_led, cdev);
@@ -59,15 +54,6 @@ static void s3c24xx_led_set(struct led_classdev *led_cdev,
        }
 }
 
-static int s3c24xx_led_remove(struct platform_device *dev)
-{
-       struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
-
-       led_classdev_unregister(&led->cdev);
-
-       return 0;
-}
-
 static int s3c24xx_led_probe(struct platform_device *dev)
 {
        struct s3c24xx_led_platdata *pdata = dev_get_platdata(&dev->dev);
@@ -79,8 +65,6 @@ static int s3c24xx_led_probe(struct platform_device *dev)
        if (!led)
                return -ENOMEM;
 
-       platform_set_drvdata(dev, led);
-
        led->cdev.brightness_set = s3c24xx_led_set;
        led->cdev.default_trigger = pdata->def_trigger;
        led->cdev.name = pdata->name;
@@ -104,7 +88,7 @@ static int s3c24xx_led_probe(struct platform_device *dev)
 
        /* register our new led device */
 
-       ret = led_classdev_register(&dev->dev, &led->cdev);
+       ret = devm_led_classdev_register(&dev->dev, &led->cdev);
        if (ret < 0)
                dev_err(&dev->dev, "led_classdev_register failed\n");
 
@@ -113,7 +97,6 @@ static int s3c24xx_led_probe(struct platform_device *dev)
 
 static struct platform_driver s3c24xx_led_driver = {
        .probe          = s3c24xx_led_probe,
-       .remove         = s3c24xx_led_remove,
        .driver         = {
                .name           = "s3c24xx_led",
        },
index 64a22263e7fc50fd5dca571a7ee2f78804b3e8ee..be93b20e792a7aa36dc81a0cb60de7bb8c66654d 100644 (file)
@@ -239,7 +239,6 @@ static int wm831x_status_probe(struct platform_device *pdev)
                               GFP_KERNEL);
        if (!drvdata)
                return -ENOMEM;
-       platform_set_drvdata(pdev, drvdata);
 
        drvdata->wm831x = wm831x;
        drvdata->reg = res->start;
@@ -284,7 +283,7 @@ static int wm831x_status_probe(struct platform_device *pdev)
        drvdata->cdev.blink_set = wm831x_status_blink_set;
        drvdata->cdev.groups = wm831x_status_groups;
 
-       ret = led_classdev_register(wm831x->dev, &drvdata->cdev);
+       ret = devm_led_classdev_register(wm831x->dev, &drvdata->cdev);
        if (ret < 0) {
                dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
                return ret;
@@ -293,21 +292,11 @@ static int wm831x_status_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int wm831x_status_remove(struct platform_device *pdev)
-{
-       struct wm831x_status *drvdata = platform_get_drvdata(pdev);
-
-       led_classdev_unregister(&drvdata->cdev);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_status_driver = {
        .driver = {
                   .name = "wm831x-status",
                   },
        .probe = wm831x_status_probe,
-       .remove = wm831x_status_remove,
 };
 
 module_platform_driver(wm831x_status_driver);
index 4f12c6f01fe7d384d086321a09d73c1fb8fdd4a3..b6819f0fc6083266afd1d9fbea5c7e42c41b13fc 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/macio.h>
 #include <asm/pmac_feature.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 
 #undef DEBUG
 
index 8f779a1ec99c4b248c9721fceef19b579432539b..0ddf638d60f3645c4a083b37027625dfd850b97f 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/platform_device.h>
 #include <linux/mailbox_controller.h>
 #include <linux/mailbox_client.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
 
 #include "mailbox.h"
 
@@ -70,6 +71,9 @@
 
 static struct mbox_chan *pcc_mbox_channels;
 
+/* Array of cached virtual address for doorbell registers */
+static void __iomem **pcc_doorbell_vaddr;
+
 static struct mbox_controller pcc_mbox_ctrl = {};
 /**
  * get_pcc_channel - Given a PCC subspace idx, get
@@ -160,6 +164,66 @@ void pcc_mbox_free_channel(struct mbox_chan *chan)
 }
 EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
 
+/*
+ * PCC can be used with perf critical drivers such as CPPC
+ * So it makes sense to locally cache the virtual address and
+ * use it to read/write to PCC registers such as doorbell register
+ *
+ * The below read_register and write_registers are used to read and
+ * write from perf critical registers such as PCC doorbell register
+ */
+static int read_register(void __iomem *vaddr, u64 *val, unsigned int bit_width)
+{
+       int ret_val = 0;
+
+       switch (bit_width) {
+       case 8:
+               *val = readb(vaddr);
+               break;
+       case 16:
+               *val = readw(vaddr);
+               break;
+       case 32:
+               *val = readl(vaddr);
+               break;
+       case 64:
+               *val = readq(vaddr);
+               break;
+       default:
+               pr_debug("Error: Cannot read register of %u bit width",
+                       bit_width);
+               ret_val = -EFAULT;
+               break;
+       }
+       return ret_val;
+}
+
+static int write_register(void __iomem *vaddr, u64 val, unsigned int bit_width)
+{
+       int ret_val = 0;
+
+       switch (bit_width) {
+       case 8:
+               writeb(val, vaddr);
+               break;
+       case 16:
+               writew(val, vaddr);
+               break;
+       case 32:
+               writel(val, vaddr);
+               break;
+       case 64:
+               writeq(val, vaddr);
+               break;
+       default:
+               pr_debug("Error: Cannot write register of %u bit width",
+                       bit_width);
+               ret_val = -EFAULT;
+               break;
+       }
+       return ret_val;
+}
+
 /**
  * pcc_send_data - Called from Mailbox Controller code. Used
  *             here only to ring the channel doorbell. The PCC client
@@ -175,21 +239,39 @@ EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
 static int pcc_send_data(struct mbox_chan *chan, void *data)
 {
        struct acpi_pcct_hw_reduced *pcct_ss = chan->con_priv;
-       struct acpi_generic_address doorbell;
+       struct acpi_generic_address *doorbell;
        u64 doorbell_preserve;
        u64 doorbell_val;
        u64 doorbell_write;
+       u32 id = chan - pcc_mbox_channels;
+       int ret = 0;
+
+       if (id >= pcc_mbox_ctrl.num_chans) {
+               pr_debug("pcc_send_data: Invalid mbox_chan passed\n");
+               return -ENOENT;
+       }
 
-       doorbell = pcct_ss->doorbell_register;
+       doorbell = &pcct_ss->doorbell_register;
        doorbell_preserve = pcct_ss->preserve_mask;
        doorbell_write = pcct_ss->write_mask;
 
        /* Sync notification from OS to Platform. */
-       acpi_read(&doorbell_val, &doorbell);
-       acpi_write((doorbell_val & doorbell_preserve) | doorbell_write,
-                       &doorbell);
-
-       return 0;
+       if (pcc_doorbell_vaddr[id]) {
+               ret = read_register(pcc_doorbell_vaddr[id], &doorbell_val,
+                       doorbell->bit_width);
+               if (ret)
+                       return ret;
+               ret = write_register(pcc_doorbell_vaddr[id],
+                       (doorbell_val & doorbell_preserve) | doorbell_write,
+                       doorbell->bit_width);
+       } else {
+               ret = acpi_read(&doorbell_val, doorbell);
+               if (ret)
+                       return ret;
+               ret = acpi_write((doorbell_val & doorbell_preserve) | doorbell_write,
+                       doorbell);
+       }
+       return ret;
 }
 
 static const struct mbox_chan_ops pcc_chan_ops = {
@@ -265,14 +347,29 @@ static int __init acpi_pcc_probe(void)
                return -ENOMEM;
        }
 
+       pcc_doorbell_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
+       if (!pcc_doorbell_vaddr) {
+               kfree(pcc_mbox_channels);
+               return -ENOMEM;
+       }
+
        /* Point to the first PCC subspace entry */
        pcct_entry = (struct acpi_subtable_header *) (
                (unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));
 
        for (i = 0; i < count; i++) {
+               struct acpi_generic_address *db_reg;
+               struct acpi_pcct_hw_reduced *pcct_ss;
                pcc_mbox_channels[i].con_priv = pcct_entry;
                pcct_entry = (struct acpi_subtable_header *)
                        ((unsigned long) pcct_entry + pcct_entry->length);
+
+               /* If doorbell is in system memory cache the virt address */
+               pcct_ss = (struct acpi_pcct_hw_reduced *)pcct_entry;
+               db_reg = &pcct_ss->doorbell_register;
+               if (db_reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+                       pcc_doorbell_vaddr[i] = acpi_os_ioremap(db_reg->address,
+                                                       db_reg->bit_width/8);
        }
 
        pcc_mbox_ctrl.num_chans = count;
index 7e9cbf757e956b817e465249669b148cd9b38cb0..fb7ed730d9322fae3c8887f0db71bf16de50efa0 100644 (file)
@@ -497,7 +497,7 @@ static int adp1653_probe(struct i2c_client *client,
                if (!client->dev.platform_data) {
                        dev_err(&client->dev,
                                "Neither DT not platform data provided\n");
-                       return EINVAL;
+                       return -EINVAL;
                }
                flash->platform_data = client->dev.platform_data;
        }
index f8dd7505b5294ff167352a1d3ce8823605916db7..e1719ffdfb3db12a1dc724b189b2c4544729d785 100644 (file)
@@ -1960,10 +1960,9 @@ static int adv76xx_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
        }
 
        /* tx 5v detect */
-       tx_5v = io_read(sd, 0x70) & info->cable_det_mask;
+       tx_5v = irq_reg_0x70 & info->cable_det_mask;
        if (tx_5v) {
                v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
-               io_write(sd, 0x71, tx_5v);
                adv76xx_s_detect_tx_5v_ctrl(sd);
                if (handled)
                        *handled = true;
index 7dae0ac0f3aec12c5d44875111d3a69818e43c92..e9219f528d7e8ada4876649c28b9d0c54ce68117 100644 (file)
@@ -20,6 +20,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/* We need to access legacy defines from linux/media.h */
+#define __NEED_MEDIA_LEGACY_API
+
 #include <linux/compat.h>
 #include <linux/export.h>
 #include <linux/idr.h>
@@ -115,6 +118,26 @@ static long media_device_enum_entities(struct media_device *mdev,
        u_ent.group_id = 0;             /* Unused */
        u_ent.pads = ent->num_pads;
        u_ent.links = ent->num_links - ent->num_backlinks;
+
+       /*
+        * Workaround for a bug at media-ctl <= v1.10 that makes it to
+        * do the wrong thing if the entity function doesn't belong to
+        * either MEDIA_ENT_F_OLD_BASE or MEDIA_ENT_F_OLD_SUBDEV_BASE
+        * Ranges.
+        *
+        * Non-subdevices are expected to be at the MEDIA_ENT_F_OLD_BASE,
+        * or, otherwise, will be silently ignored by media-ctl when
+        * printing the graphviz diagram. So, map them into the devnode
+        * old range.
+        */
+       if (ent->function < MEDIA_ENT_F_OLD_BASE ||
+           ent->function > MEDIA_ENT_T_DEVNODE_UNKNOWN) {
+               if (is_media_entity_v4l2_subdev(ent))
+                       u_ent.type = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
+               else if (ent->function != MEDIA_ENT_F_IO_V4L)
+                       u_ent.type = MEDIA_ENT_T_DEVNODE_UNKNOWN;
+       }
+
        memcpy(&u_ent.raw, &ent->info, sizeof(ent->info));
        if (copy_to_user(uent, &u_ent, sizeof(u_ent)))
                return -EFAULT;
index 7d28899f89ce16c00cd9f00f424a948fa57e2ae8..38aacc7fc692024b58afd94708218b022bafd318 100644 (file)
@@ -1455,9 +1455,9 @@ static int coda_alloc_bitstream_buffer(struct coda_ctx *ctx,
                return 0;
 
        ctx->bitstream.size = roundup_pow_of_two(q_data->sizeimage * 2);
-       ctx->bitstream.vaddr = dma_alloc_writecombine(
-                       &ctx->dev->plat_dev->dev, ctx->bitstream.size,
-                       &ctx->bitstream.paddr, GFP_KERNEL);
+       ctx->bitstream.vaddr = dma_alloc_wc(&ctx->dev->plat_dev->dev,
+                                           ctx->bitstream.size,
+                                           &ctx->bitstream.paddr, GFP_KERNEL);
        if (!ctx->bitstream.vaddr) {
                v4l2_err(&ctx->dev->v4l2_dev,
                         "failed to allocate bitstream ringbuffer");
@@ -1474,8 +1474,8 @@ static void coda_free_bitstream_buffer(struct coda_ctx *ctx)
        if (ctx->bitstream.vaddr == NULL)
                return;
 
-       dma_free_writecombine(&ctx->dev->plat_dev->dev, ctx->bitstream.size,
-                             ctx->bitstream.vaddr, ctx->bitstream.paddr);
+       dma_free_wc(&ctx->dev->plat_dev->dev, ctx->bitstream.size,
+                   ctx->bitstream.vaddr, ctx->bitstream.paddr);
        ctx->bitstream.vaddr = NULL;
        kfifo_init(&ctx->bitstream_fifo, NULL, 0);
 }
index 8c54fd21022e443ee03e2f1b852208c4a03b938e..a1362572284822e7b39a009ab227137dbd8b8595 100644 (file)
@@ -1843,8 +1843,7 @@ static void au0828_analog_create_entities(struct au0828_dev *dev)
                        ent->function = MEDIA_ENT_F_CONN_RF;
                        break;
                default: /* AU0828_VMUX_DEBUG */
-                       ent->function = MEDIA_ENT_F_CONN_TEST;
-                       break;
+                       continue;
                }
 
                ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]);
index d959ebbb2194aa29147d1201eb5e61b7d734b68c..98ecd136a21b99b347f8f8e6b782cbaeb26b0acd 100644 (file)
@@ -35,8 +35,6 @@
 #include <linux/err.h>
 #include <linux/of.h>
 
-#define I2C_ADDR_RTC   (0x0C >> 1)
-
 static const struct mfd_cell max77686_devs[] = {
        { .name = "max77686-pmic", },
        { .name = "max77686-rtc", },
@@ -116,11 +114,6 @@ static const struct regmap_config max77686_regmap_config = {
        .val_bits = 8,
 };
 
-static const struct regmap_config max77686_rtc_regmap_config = {
-       .reg_bits = 8,
-       .val_bits = 8,
-};
-
 static const struct regmap_config max77802_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
@@ -156,25 +149,6 @@ static const struct regmap_irq_chip max77686_irq_chip = {
        .num_irqs               = ARRAY_SIZE(max77686_irqs),
 };
 
-static const struct regmap_irq max77686_rtc_irqs[] = {
-       /* RTC interrupts */
-       { .reg_offset = 0, .mask = MAX77686_RTCINT_RTC60S_MSK, },
-       { .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA1_MSK, },
-       { .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA2_MSK, },
-       { .reg_offset = 0, .mask = MAX77686_RTCINT_SMPL_MSK, },
-       { .reg_offset = 0, .mask = MAX77686_RTCINT_RTC1S_MSK, },
-       { .reg_offset = 0, .mask = MAX77686_RTCINT_WTSR_MSK, },
-};
-
-static const struct regmap_irq_chip max77686_rtc_irq_chip = {
-       .name                   = "max77686-rtc",
-       .status_base            = MAX77686_RTC_INT,
-       .mask_base              = MAX77686_RTC_INTM,
-       .num_regs               = 1,
-       .irqs                   = max77686_rtc_irqs,
-       .num_irqs               = ARRAY_SIZE(max77686_rtc_irqs),
-};
-
 static const struct regmap_irq_chip max77802_irq_chip = {
        .name                   = "max77802-pmic",
        .status_base            = MAX77802_REG_INT1,
@@ -184,15 +158,6 @@ static const struct regmap_irq_chip max77802_irq_chip = {
        .num_irqs               = ARRAY_SIZE(max77686_irqs),
 };
 
-static const struct regmap_irq_chip max77802_rtc_irq_chip = {
-       .name                   = "max77802-rtc",
-       .status_base            = MAX77802_RTC_INT,
-       .mask_base              = MAX77802_RTC_INTM,
-       .num_regs               = 1,
-       .irqs                   = max77686_rtc_irqs, /* same masks as 77686 */
-       .num_irqs               = ARRAY_SIZE(max77686_rtc_irqs),
-};
-
 static const struct of_device_id max77686_pmic_dt_match[] = {
        {
                .compatible = "maxim,max77686",
@@ -214,8 +179,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
        int ret = 0;
        const struct regmap_config *config;
        const struct regmap_irq_chip *irq_chip;
-       const struct regmap_irq_chip *rtc_irq_chip;
-       struct regmap **rtc_regmap;
        const struct mfd_cell *cells;
        int n_devs;
 
@@ -242,15 +205,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
        if (max77686->type == TYPE_MAX77686) {
                config = &max77686_regmap_config;
                irq_chip = &max77686_irq_chip;
-               rtc_irq_chip = &max77686_rtc_irq_chip;
-               rtc_regmap = &max77686->rtc_regmap;
                cells =  max77686_devs;
                n_devs = ARRAY_SIZE(max77686_devs);
        } else {
                config = &max77802_regmap_config;
                irq_chip = &max77802_irq_chip;
-               rtc_irq_chip = &max77802_rtc_irq_chip;
-               rtc_regmap = &max77686->regmap;
                cells =  max77802_devs;
                n_devs = ARRAY_SIZE(max77802_devs);
        }
@@ -270,60 +229,25 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
                return -ENODEV;
        }
 
-       if (max77686->type == TYPE_MAX77686) {
-               max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
-               if (!max77686->rtc) {
-                       dev_err(max77686->dev,
-                               "Failed to allocate I2C device for RTC\n");
-                       return -ENODEV;
-               }
-               i2c_set_clientdata(max77686->rtc, max77686);
-
-               max77686->rtc_regmap =
-                       devm_regmap_init_i2c(max77686->rtc,
-                                            &max77686_rtc_regmap_config);
-               if (IS_ERR(max77686->rtc_regmap)) {
-                       ret = PTR_ERR(max77686->rtc_regmap);
-                       dev_err(max77686->dev,
-                               "failed to allocate RTC regmap: %d\n",
-                               ret);
-                       goto err_unregister_i2c;
-               }
-       }
-
        ret = regmap_add_irq_chip(max77686->regmap, max77686->irq,
                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
                                  IRQF_SHARED, 0, irq_chip,
                                  &max77686->irq_data);
-       if (ret) {
+       if (ret < 0) {
                dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);
-               goto err_unregister_i2c;
-       }
-
-       ret = regmap_add_irq_chip(*rtc_regmap, max77686->irq,
-                                 IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
-                                 IRQF_SHARED, 0, rtc_irq_chip,
-                                 &max77686->rtc_irq_data);
-       if (ret) {
-               dev_err(&i2c->dev, "failed to add RTC irq chip: %d\n", ret);
-               goto err_del_irqc;
+               return ret;
        }
 
        ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL);
        if (ret < 0) {
                dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
-               goto err_del_rtc_irqc;
+               goto err_del_irqc;
        }
 
        return 0;
 
-err_del_rtc_irqc:
-       regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
 err_del_irqc:
        regmap_del_irq_chip(max77686->irq, max77686->irq_data);
-err_unregister_i2c:
-       if (max77686->type == TYPE_MAX77686)
-               i2c_unregister_device(max77686->rtc);
 
        return ret;
 }
@@ -334,12 +258,8 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
 
        mfd_remove_devices(max77686->dev);
 
-       regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
        regmap_del_irq_chip(max77686->irq, max77686->irq_data);
 
-       if (max77686->type == TYPE_MAX77686)
-               i2c_unregister_device(max77686->rtc);
-
        return 0;
 }
 
index 4c1903f781fc1793bb7ddf7205d138e60ea2133a..a89608334ed508f89e0c5aa4f450b4e6b690358b 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <asm/opal.h>
 #include <asm/msi_bitmap.h>
-#include <asm/pci-bridge.h> /* for struct pci_controller */
 #include <asm/pnv-pci.h>
 #include <asm/io.h>
 
@@ -415,7 +414,7 @@ static int cxl_setup_psl_timebase(struct cxl *adapter, struct pci_dev *dev)
                delta = mftb() - psl_tb;
                if (delta < 0)
                        delta = -delta;
-       } while (cputime_to_usecs(delta) > 16);
+       } while (tb_to_ns(delta) > 16000);
 
        return 0;
 }
index 11fdadc68e53e57722b4d58892fdf2c644beba34..2a6eaf1122b4e9b742eb3777fb4b6b317c07b201 100644 (file)
@@ -103,6 +103,7 @@ enum ctype {
        CT_EXEC_USERSPACE,
        CT_ACCESS_USERSPACE,
        CT_WRITE_RO,
+       CT_WRITE_RO_AFTER_INIT,
        CT_WRITE_KERN,
 };
 
@@ -140,6 +141,7 @@ static char* cp_type[] = {
        "EXEC_USERSPACE",
        "ACCESS_USERSPACE",
        "WRITE_RO",
+       "WRITE_RO_AFTER_INIT",
        "WRITE_KERN",
 };
 
@@ -162,6 +164,7 @@ static DEFINE_SPINLOCK(lock_me_up);
 static u8 data_area[EXEC_SIZE];
 
 static const unsigned long rodata = 0xAA55AA55;
+static unsigned long ro_after_init __ro_after_init = 0x55AA5500;
 
 module_param(recur_count, int, 0644);
 MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test");
@@ -503,11 +506,28 @@ static void lkdtm_do_action(enum ctype which)
                break;
        }
        case CT_WRITE_RO: {
-               unsigned long *ptr;
+               /* Explicitly cast away "const" for the test. */
+               unsigned long *ptr = (unsigned long *)&rodata;
 
-               ptr = (unsigned long *)&rodata;
+               pr_info("attempting bad rodata write at %p\n", ptr);
+               *ptr ^= 0xabcd1234;
 
-               pr_info("attempting bad write at %p\n", ptr);
+               break;
+       }
+       case CT_WRITE_RO_AFTER_INIT: {
+               unsigned long *ptr = &ro_after_init;
+
+               /*
+                * Verify we were written to during init. Since an Oops
+                * is considered a "success", a failure is to just skip the
+                * real test.
+                */
+               if ((*ptr & 0xAA) != 0xAA) {
+                       pr_info("%p was NOT written during init!?\n", ptr);
+                       break;
+               }
+
+               pr_info("attempting bad ro_after_init write at %p\n", ptr);
                *ptr ^= 0xabcd1234;
 
                break;
@@ -817,6 +837,9 @@ static int __init lkdtm_module_init(void)
        int n_debugfs_entries = 1; /* Assume only the direct entry */
        int i;
 
+       /* Make sure we can write to __ro_after_init values during __init */
+       ro_after_init |= 0xAA;
+
        /* Register debugfs interface */
        lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
        if (!lkdtm_debugfs_root) {
index 79316159eec63cbca36aa06d27bfaab561b62dc0..88b6c81cebbe68123da96775b3a42c3f96da4a11 100644 (file)
@@ -187,7 +187,7 @@ static int double_bit_error_detect(void *error_data, void *error_ecc,
        __nand_calculate_ecc(error_data, size, calc_ecc);
        ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size);
 
-       return (ret == -1) ? 0 : -EINVAL;
+       return (ret == -EBADMSG) ? 0 : -EINVAL;
 }
 
 static const struct nand_ecc_test nand_ecc_test[] = {
index 2a1b6e037e1a1ced496ac446ca07d6037ef61d0e..0134ba32a05784b65d1a0e6d470eee7a857df74c 100644 (file)
@@ -193,7 +193,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
        vol->changing_leb = 1;
        vol->ch_lnum = req->lnum;
 
-       vol->upd_buf = vmalloc(req->bytes);
+       vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));
        if (!vol->upd_buf)
                return -ENOMEM;
 
index 575790e8a75af8e6184f5611fe133b1d73825679..74a7dfecee2783ac609b9fefbd32f7817b48c43c 100644 (file)
@@ -843,7 +843,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
                if (clear_intf)
                        mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00);
 
-               if (eflag)
+               if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR))
                        mcp251x_write_bits(spi, EFLG, eflag, 0x00);
 
                /* Update can state */
index 5eee62badf45457798c2fabe5005faa26c6286e2..cbc99d5649afa3877158a0ac37a50b8865a7e8ac 100644 (file)
@@ -826,9 +826,8 @@ static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface
 static void gs_destroy_candev(struct gs_can *dev)
 {
        unregister_candev(dev->netdev);
-       free_candev(dev->netdev);
        usb_kill_anchored_urbs(&dev->tx_submitted);
-       kfree(dev);
+       free_candev(dev->netdev);
 }
 
 static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -913,12 +912,15 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *
        for (i = 0; i < icount; i++) {
                dev->canch[i] = gs_make_candev(i, intf);
                if (IS_ERR_OR_NULL(dev->canch[i])) {
+                       /* save error code to return later */
+                       rc = PTR_ERR(dev->canch[i]);
+
                        /* on failure destroy previously created candevs */
                        icount = i;
-                       for (i = 0; i < icount; i++) {
+                       for (i = 0; i < icount; i++)
                                gs_destroy_candev(dev->canch[i]);
-                               dev->canch[i] = NULL;
-                       }
+
+                       usb_kill_anchored_urbs(&dev->rx_submitted);
                        kfree(dev);
                        return rc;
                }
@@ -939,16 +941,12 @@ static void gs_usb_disconnect(struct usb_interface *intf)
                return;
        }
 
-       for (i = 0; i < GS_MAX_INTF; i++) {
-               struct gs_can *can = dev->canch[i];
-
-               if (!can)
-                       continue;
-
-               gs_destroy_candev(can);
-       }
+       for (i = 0; i < GS_MAX_INTF; i++)
+               if (dev->canch[i])
+                       gs_destroy_candev(dev->canch[i]);
 
        usb_kill_anchored_urbs(&dev->rx_submitted);
+       kfree(dev);
 }
 
 static const struct usb_device_id gs_usb_table[] = {
index 79e1a0282163db200916e0f862fa1560eab2fd03..17b2126075e01afde20ee2de1718dfc7db1e4641 100644 (file)
@@ -2461,7 +2461,7 @@ boomerang_interrupt(int irq, void *dev_id)
                                        int i;
                                        pci_unmap_single(VORTEX_PCI(vp),
                                                        le32_to_cpu(vp->tx_ring[entry].frag[0].addr),
-                                                       le32_to_cpu(vp->tx_ring[entry].frag[0].length),
+                                                       le32_to_cpu(vp->tx_ring[entry].frag[0].length)&0xFFF,
                                                        PCI_DMA_TODEVICE);
 
                                        for (i=1; i<=skb_shinfo(skb)->nr_frags; i++)
index 17472851674f19f949f97e04fccdc5a6fb874a3d..f749e4d389eb163132d5ab51ad7a9821c07577e4 100644 (file)
@@ -193,7 +193,6 @@ static void altera_tse_mdio_destroy(struct net_device *dev)
                            priv->mdio->id);
 
        mdiobus_unregister(priv->mdio);
-       kfree(priv->mdio->irq);
        mdiobus_free(priv->mdio);
        priv->mdio = NULL;
 }
index f71ab2647a3bc1f62f6b7450b34dd325c710549d..08a23e6b60e947894783f2115c2fe16abece84bc 100644 (file)
@@ -1460,7 +1460,19 @@ static int nb8800_probe(struct platform_device *pdev)
                goto err_disable_clk;
        }
 
-       priv->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
+       if (of_phy_is_fixed_link(pdev->dev.of_node)) {
+               ret = of_phy_register_fixed_link(pdev->dev.of_node);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "bad fixed-link spec\n");
+                       goto err_free_bus;
+               }
+               priv->phy_node = of_node_get(pdev->dev.of_node);
+       }
+
+       if (!priv->phy_node)
+               priv->phy_node = of_parse_phandle(pdev->dev.of_node,
+                                                 "phy-handle", 0);
+
        if (!priv->phy_node) {
                dev_err(&pdev->dev, "no PHY specified\n");
                ret = -ENODEV;
index 27aa0802d87d5f46d813184649dd9107fdeb541b..91874d24fd560c2d25afbf7ab7e3251774627a5b 100644 (file)
@@ -4896,9 +4896,9 @@ struct c2s_pri_trans_table_entry {
  * cfc delete event data
  */
 struct cfc_del_event_data {
-       u32 cid;
-       u32 reserved0;
-       u32 reserved1;
+       __le32 cid;
+       __le32 reserved0;
+       __le32 reserved1;
 };
 
 
@@ -5114,15 +5114,9 @@ struct vf_pf_channel_zone_trigger {
  * zone that triggers the in-bound interrupt
  */
 struct trigger_vf_zone {
-#if defined(__BIG_ENDIAN)
-       u16 reserved1;
-       u8 reserved0;
-       struct vf_pf_channel_zone_trigger vf_pf_channel;
-#elif defined(__LITTLE_ENDIAN)
        struct vf_pf_channel_zone_trigger vf_pf_channel;
        u8 reserved0;
        u16 reserved1;
-#endif
        u32 reserved2;
 };
 
@@ -5207,9 +5201,9 @@ struct e2_integ_data {
  * set mac event data
  */
 struct eth_event_data {
-       u32 echo;
-       u32 reserved0;
-       u32 reserved1;
+       __le32 echo;
+       __le32 reserved0;
+       __le32 reserved1;
 };
 
 
@@ -5219,9 +5213,9 @@ struct eth_event_data {
 struct vf_pf_event_data {
        u8 vf_id;
        u8 reserved0;
-       u16 reserved1;
-       u32 msg_addr_lo;
-       u32 msg_addr_hi;
+       __le16 reserved1;
+       __le32 msg_addr_lo;
+       __le32 msg_addr_hi;
 };
 
 /*
@@ -5230,9 +5224,9 @@ struct vf_pf_event_data {
 struct vf_flr_event_data {
        u8 vf_id;
        u8 reserved0;
-       u16 reserved1;
-       u32 reserved2;
-       u32 reserved3;
+       __le16 reserved1;
+       __le32 reserved2;
+       __le32 reserved3;
 };
 
 /*
@@ -5241,9 +5235,9 @@ struct vf_flr_event_data {
 struct malicious_vf_event_data {
        u8 vf_id;
        u8 err_id;
-       u16 reserved1;
-       u32 reserved2;
-       u32 reserved3;
+       __le16 reserved1;
+       __le32 reserved2;
+       __le32 reserved3;
 };
 
 /*
index 6c4e3a69976fcaf4ecc0bafcebbcb2e725a40575..2bf9c871144f714c56a72e4e584aa4db431d218c 100644 (file)
@@ -5280,14 +5280,14 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
 {
        unsigned long ramrod_flags = 0;
        int rc = 0;
-       u32 cid = elem->message.data.eth_event.echo & BNX2X_SWCID_MASK;
+       u32 echo = le32_to_cpu(elem->message.data.eth_event.echo);
+       u32 cid = echo & BNX2X_SWCID_MASK;
        struct bnx2x_vlan_mac_obj *vlan_mac_obj;
 
        /* Always push next commands out, don't wait here */
        __set_bit(RAMROD_CONT, &ramrod_flags);
 
-       switch (le32_to_cpu((__force __le32)elem->message.data.eth_event.echo)
-                           >> BNX2X_SWCID_SHIFT) {
+       switch (echo >> BNX2X_SWCID_SHIFT) {
        case BNX2X_FILTER_MAC_PENDING:
                DP(BNX2X_MSG_SP, "Got SETUP_MAC completions\n");
                if (CNIC_LOADED(bp) && (cid == BNX2X_ISCSI_ETH_CID(bp)))
@@ -5308,8 +5308,7 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
                bnx2x_handle_mcast_eqe(bp);
                return;
        default:
-               BNX2X_ERR("Unsupported classification command: %d\n",
-                         elem->message.data.eth_event.echo);
+               BNX2X_ERR("Unsupported classification command: 0x%x\n", echo);
                return;
        }
 
@@ -5478,9 +5477,6 @@ static void bnx2x_eq_int(struct bnx2x *bp)
                        goto next_spqe;
                }
 
-               /* elem CID originates from FW; actually LE */
-               cid = SW_CID((__force __le32)
-                            elem->message.data.cfc_del_event.cid);
                opcode = elem->message.opcode;
 
                /* handle eq element */
@@ -5503,6 +5499,10 @@ static void bnx2x_eq_int(struct bnx2x *bp)
                         * we may want to verify here that the bp state is
                         * HALTING
                         */
+
+                       /* elem CID originates from FW; actually LE */
+                       cid = SW_CID(elem->message.data.cfc_del_event.cid);
+
                        DP(BNX2X_MSG_SP,
                           "got delete ramrod for MULTI[%d]\n", cid);
 
@@ -5596,10 +5596,8 @@ static void bnx2x_eq_int(struct bnx2x *bp)
                      BNX2X_STATE_OPENING_WAIT4_PORT):
                case (EVENT_RING_OPCODE_RSS_UPDATE_RULES |
                      BNX2X_STATE_CLOSING_WAIT4_HALT):
-                       cid = elem->message.data.eth_event.echo &
-                               BNX2X_SWCID_MASK;
                        DP(BNX2X_MSG_SP, "got RSS_UPDATE ramrod. CID %d\n",
-                          cid);
+                          SW_CID(elem->message.data.eth_event.echo));
                        rss_raw->clear_pending(rss_raw);
                        break;
 
@@ -5684,7 +5682,7 @@ static void bnx2x_sp_task(struct work_struct *work)
                if (status & BNX2X_DEF_SB_IDX) {
                        struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
 
-               if (FCOE_INIT(bp) &&
+                       if (FCOE_INIT(bp) &&
                            (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
                                /* Prevent local bottom-halves from running as
                                 * we are going to change the local NAPI list.
index 9d027348cd09b90fcca14843f13e278d54dd89e6..632daff117d305a822f95cc1bcd84b47437b2334 100644 (file)
@@ -1672,11 +1672,12 @@ void bnx2x_vf_handle_classification_eqe(struct bnx2x *bp,
 {
        unsigned long ramrod_flags = 0;
        int rc = 0;
+       u32 echo = le32_to_cpu(elem->message.data.eth_event.echo);
 
        /* Always push next commands out, don't wait here */
        set_bit(RAMROD_CONT, &ramrod_flags);
 
-       switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
+       switch (echo >> BNX2X_SWCID_SHIFT) {
        case BNX2X_FILTER_MAC_PENDING:
                rc = vfq->mac_obj.complete(bp, &vfq->mac_obj, elem,
                                           &ramrod_flags);
@@ -1686,8 +1687,7 @@ void bnx2x_vf_handle_classification_eqe(struct bnx2x *bp,
                                            &ramrod_flags);
                break;
        default:
-               BNX2X_ERR("Unsupported classification command: %d\n",
-                         elem->message.data.eth_event.echo);
+               BNX2X_ERR("Unsupported classification command: 0x%x\n", echo);
                return;
        }
        if (rc < 0)
@@ -1747,16 +1747,14 @@ int bnx2x_iov_eq_sp_event(struct bnx2x *bp, union event_ring_elem *elem)
 
        switch (opcode) {
        case EVENT_RING_OPCODE_CFC_DEL:
-               cid = SW_CID((__force __le32)
-                            elem->message.data.cfc_del_event.cid);
+               cid = SW_CID(elem->message.data.cfc_del_event.cid);
                DP(BNX2X_MSG_IOV, "checking cfc-del comp cid=%d\n", cid);
                break;
        case EVENT_RING_OPCODE_CLASSIFICATION_RULES:
        case EVENT_RING_OPCODE_MULTICAST_RULES:
        case EVENT_RING_OPCODE_FILTERS_RULES:
        case EVENT_RING_OPCODE_RSS_UPDATE_RULES:
-               cid = (elem->message.data.eth_event.echo &
-                      BNX2X_SWCID_MASK);
+               cid = SW_CID(elem->message.data.eth_event.echo);
                DP(BNX2X_MSG_IOV, "checking filtering comp cid=%d\n", cid);
                break;
        case EVENT_RING_OPCODE_VF_FLR:
index 1374e5394a7970ba20ad54ddfc6271ce09e40744..bfae300cf25ff881292dc36ad56e51e37132cd76 100644 (file)
@@ -2187,8 +2187,10 @@ void bnx2x_vf_mbx_schedule(struct bnx2x *bp,
 
        /* Update VFDB with current message and schedule its handling */
        mutex_lock(&BP_VFDB(bp)->event_mutex);
-       BP_VF_MBX(bp, vf_idx)->vf_addr_hi = vfpf_event->msg_addr_hi;
-       BP_VF_MBX(bp, vf_idx)->vf_addr_lo = vfpf_event->msg_addr_lo;
+       BP_VF_MBX(bp, vf_idx)->vf_addr_hi =
+               le32_to_cpu(vfpf_event->msg_addr_hi);
+       BP_VF_MBX(bp, vf_idx)->vf_addr_lo =
+               le32_to_cpu(vfpf_event->msg_addr_lo);
        BP_VFDB(bp)->event_occur |= (1ULL << vf_idx);
        mutex_unlock(&BP_VFDB(bp)->event_mutex);
 
index 8ab000dd52d958317323c8486fc0538576727803..82f191382989b04877177075ea1906f0e941dfb9 100644 (file)
@@ -248,7 +248,8 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                tx_push1->tx_bd_cfa_meta = cpu_to_le32(vlan_tag_flags);
                tx_push1->tx_bd_cfa_action = cpu_to_le32(cfa_action);
 
-               end = PTR_ALIGN(pdata + length + 1, 8) - 1;
+               end = pdata + length;
+               end = PTR_ALIGN(end, 8) - 1;
                *end = 0;
 
                skb_copy_from_linear_data(skb, pdata, len);
index 04b0d16b210e89dd6eae3aa6704987e8543edeca..95bc470ae441af824f7b6ce29df5ff17842d7fee 100644 (file)
@@ -987,7 +987,7 @@ bna_rxf_ucast_cfg_apply(struct bna_rxf *rxf)
        if (!list_empty(&rxf->ucast_pending_add_q)) {
                mac = list_first_entry(&rxf->ucast_pending_add_q,
                                       struct bna_mac, qe);
-               list_add_tail(&mac->qe, &rxf->ucast_active_q);
+               list_move_tail(&mac->qe, &rxf->ucast_active_q);
                bna_bfi_ucast_req(rxf, mac, BFI_ENET_H2I_MAC_UCAST_ADD_REQ);
                return 1;
        }
index 688828865c48253d5f96e0bd4cab4c315a635e37..34e9acea87479db83b852c4e233c3e26b532a6a1 100644 (file)
 #define NIC_PF_INTR_ID_MBOX0           8
 #define NIC_PF_INTR_ID_MBOX1           9
 
+/* Minimum FIFO level before all packets for the CQ are dropped
+ *
+ * This value ensures that once a packet has been "accepted"
+ * for reception it will not get dropped due to non-availability
+ * of CQ descriptor. An errata in HW mandates this value to be
+ * atleast 0x100.
+ */
+#define NICPF_CQM_MIN_DROP_LEVEL       0x100
+
 /* Global timer for CQ timer thresh interrupts
  * Calculated for SCLK of 700Mhz
  * value written should be a 1/16th of what is expected
index 4dded90076c8783b95c7944131e6b2cd3b828e40..95f17f8cadacc08637c485e555242e78aafb48c5 100644 (file)
@@ -304,6 +304,7 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic)
 static void nic_init_hw(struct nicpf *nic)
 {
        int i;
+       u64 cqm_cfg;
 
        /* Enable NIC HW block */
        nic_reg_write(nic, NIC_PF_CFG, 0x3);
@@ -340,6 +341,11 @@ static void nic_init_hw(struct nicpf *nic)
        /* Enable VLAN ethertype matching and stripping */
        nic_reg_write(nic, NIC_PF_RX_ETYPE_0_7,
                      (2 << 19) | (ETYPE_ALG_VLAN_STRIP << 16) | ETH_P_8021Q);
+
+       /* Check if HW expected value is higher (could be in future chips) */
+       cqm_cfg = nic_reg_read(nic, NIC_PF_CQM_CFG);
+       if (cqm_cfg < NICPF_CQM_MIN_DROP_LEVEL)
+               nic_reg_write(nic, NIC_PF_CQM_CFG, NICPF_CQM_MIN_DROP_LEVEL);
 }
 
 /* Channel parse index configuration */
index dd536be20193119c3465cd772a4bff6d649e3319..afb10e326b4fc46043b4d3f4cddb7d17f1cc341c 100644 (file)
@@ -21,7 +21,7 @@
 #define   NIC_PF_TCP_TIMER                     (0x0060)
 #define   NIC_PF_BP_CFG                                (0x0080)
 #define   NIC_PF_RRM_CFG                       (0x0088)
-#define   NIC_PF_CQM_CF                                (0x00A0)
+#define   NIC_PF_CQM_CFG                       (0x00A0)
 #define   NIC_PF_CNM_CF                                (0x00A8)
 #define   NIC_PF_CNM_STATUS                    (0x00B0)
 #define   NIC_PF_CQ_AVG_CFG                    (0x00C0)
index cf837831304be2f4d7edaebf68880a44f96bd057..f9751294ece79e54eff07e20ad9122f585bda32a 100644 (file)
@@ -531,6 +531,7 @@ struct be_adapter {
 
        struct delayed_work be_err_detection_work;
        u8 err_flags;
+       bool pcicfg_mapped;     /* pcicfg obtained via pci_iomap() */
        u32 flags;
        u32 cmd_privileges;
        /* Ethtool knobs and info */
index 241819b36ca72ac6c133875f88d17f4359c0c5d4..6d9a8d78e8ad8413f075960ee45f0033e222861c 100644 (file)
@@ -622,10 +622,13 @@ enum be_if_flags {
                                         BE_IF_FLAGS_VLAN_PROMISCUOUS |\
                                         BE_IF_FLAGS_MCAST_PROMISCUOUS)
 
-#define BE_IF_EN_FLAGS (BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |\
-                       BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_UNTAGGED)
+#define BE_IF_FILT_FLAGS_BASIC (BE_IF_FLAGS_BROADCAST | \
+                               BE_IF_FLAGS_PASS_L3L4_ERRORS | \
+                               BE_IF_FLAGS_UNTAGGED)
 
-#define BE_IF_ALL_FILT_FLAGS   (BE_IF_EN_FLAGS | BE_IF_FLAGS_ALL_PROMISCUOUS)
+#define BE_IF_ALL_FILT_FLAGS   (BE_IF_FILT_FLAGS_BASIC | \
+                                BE_IF_FLAGS_MULTICAST | \
+                                BE_IF_FLAGS_ALL_PROMISCUOUS)
 
 /* An RX interface is an object with one or more MAC addresses and
  * filtering capabilities. */
index f99de3657ce3b5f58b6f08f1f97f470bb11d7788..d1cf1274fc2f4de4b763e683b182e485e39452e6 100644 (file)
@@ -125,6 +125,11 @@ static const char * const ue_status_hi_desc[] = {
        "Unknown"
 };
 
+#define BE_VF_IF_EN_FLAGS      (BE_IF_FLAGS_UNTAGGED | \
+                                BE_IF_FLAGS_BROADCAST | \
+                                BE_IF_FLAGS_MULTICAST | \
+                                BE_IF_FLAGS_PASS_L3L4_ERRORS)
+
 static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
 {
        struct be_dma_mem *mem = &q->dma_mem;
@@ -3537,7 +3542,7 @@ static int be_enable_if_filters(struct be_adapter *adapter)
 {
        int status;
 
-       status = be_cmd_rx_filter(adapter, BE_IF_EN_FLAGS, ON);
+       status = be_cmd_rx_filter(adapter, BE_IF_FILT_FLAGS_BASIC, ON);
        if (status)
                return status;
 
@@ -3857,8 +3862,7 @@ static int be_vfs_if_create(struct be_adapter *adapter)
        int status;
 
        /* If a FW profile exists, then cap_flags are updated */
-       cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
-                   BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
+       cap_flags = BE_VF_IF_EN_FLAGS;
 
        for_all_vfs(adapter, vf_cfg, vf) {
                if (!BE3_chip(adapter)) {
@@ -3874,10 +3878,8 @@ static int be_vfs_if_create(struct be_adapter *adapter)
                        }
                }
 
-               en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
-                                       BE_IF_FLAGS_BROADCAST |
-                                       BE_IF_FLAGS_MULTICAST |
-                                       BE_IF_FLAGS_PASS_L3L4_ERRORS);
+               /* PF should enable IF flags during proxy if_create call */
+               en_flags = cap_flags & BE_VF_IF_EN_FLAGS;
                status = be_cmd_if_create(adapter, cap_flags, en_flags,
                                          &vf_cfg->if_handle, vf + 1);
                if (status)
@@ -4968,6 +4970,8 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
                pci_iounmap(adapter->pdev, adapter->csr);
        if (adapter->db)
                pci_iounmap(adapter->pdev, adapter->db);
+       if (adapter->pcicfg && adapter->pcicfg_mapped)
+               pci_iounmap(adapter->pdev, adapter->pcicfg);
 }
 
 static int db_bar(struct be_adapter *adapter)
@@ -5019,8 +5023,10 @@ static int be_map_pci_bars(struct be_adapter *adapter)
                        if (!addr)
                                goto pci_map_err;
                        adapter->pcicfg = addr;
+                       adapter->pcicfg_mapped = true;
                } else {
                        adapter->pcicfg = adapter->db + SRIOV_VF_PCICFG_OFFSET;
+                       adapter->pcicfg_mapped = false;
                }
        }
 
index 62fa136554ac29a49074e5f176b3fc9ac8d37042..41b01064510098c00a66d86bb49cf2f3fe02f9c3 100644 (file)
@@ -1265,7 +1265,6 @@ static int ethoc_remove(struct platform_device *pdev)
 
                if (priv->mdio) {
                        mdiobus_unregister(priv->mdio);
-                       kfree(priv->mdio->irq);
                        mdiobus_free(priv->mdio);
                }
                if (priv->clk)
index 623aa1c8ebc6ba3149fc529e04994496b2e7be18..79a210aaf0bbd69d86ce830a45909ae8ede07f83 100644 (file)
@@ -2791,6 +2791,8 @@ static struct fman *read_dts_node(struct platform_device *of_dev)
                goto fman_free;
        }
 
+       fman->dev = &of_dev->dev;
+
        return fman;
 
 fman_node_put:
@@ -2845,8 +2847,6 @@ static int fman_probe(struct platform_device *of_dev)
 
        dev_set_drvdata(dev, fman);
 
-       fman->dev = dev;
-
        dev_dbg(dev, "FMan%d probed\n", fman->dts_params.id);
 
        return 0;
index 2aa7b401cc3be29eb24a8fb6d1065bff6caa6e39..b9ecf197ad117754245a290964d7cd55d9be5d4e 100644 (file)
@@ -1111,8 +1111,10 @@ static void __gfar_detect_errata_85xx(struct gfar_private *priv)
 
        if ((SVR_SOC_VER(svr) == SVR_8548) && (SVR_REV(svr) == 0x20))
                priv->errata |= GFAR_ERRATA_12;
+       /* P2020/P1010 Rev 1; MPC8548 Rev 2 */
        if (((SVR_SOC_VER(svr) == SVR_P2020) && (SVR_REV(svr) < 0x20)) ||
-           ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20)))
+           ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20)) ||
+           ((SVR_SOC_VER(svr) == SVR_8548) && (SVR_REV(svr) < 0x31)))
                priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */
 }
 #endif
index 74beb1867230c9cf62a60a2843825316e6d9cdbc..4ccc032633c4e57576b316cca8f0486a3e8b4a98 100644 (file)
@@ -25,6 +25,7 @@ config HIX5HD2_GMAC
 
 config HIP04_ETH
        tristate "HISILICON P04 Ethernet support"
+       depends on HAS_IOMEM    # For MFD_SYSCON
        select MARVELL_PHY
        select MFD_SYSCON
        select HNS_MDIO
index a0070d0e740dae5b3de8f2b2a92a772854b08321..d4f92ed322d6e5c4ac10a3f8d208d94445760e27 100644 (file)
@@ -675,8 +675,12 @@ static int hns_ae_config_loopback(struct hnae_handle *handle,
 {
        int ret;
        struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
+       struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
 
        switch (loop) {
+       case MAC_INTERNALLOOP_PHY:
+               ret = 0;
+               break;
        case MAC_INTERNALLOOP_SERDES:
                ret = hns_mac_config_sds_loopback(vf_cb->mac_cb, en);
                break;
@@ -686,6 +690,10 @@ static int hns_ae_config_loopback(struct hnae_handle *handle,
        default:
                ret = -EINVAL;
        }
+
+       if (!ret)
+               hns_dsaf_set_inner_lb(mac_cb->dsaf_dev, mac_cb->mac_id, en);
+
        return ret;
 }
 
index 9439f04962e1d96bf480d8aedf6472c912e28813..38fc5be3870cc3258755e79d13ac501ffa0826e4 100644 (file)
@@ -230,6 +230,30 @@ static void hns_dsaf_mix_def_qid_cfg(struct dsaf_device *dsaf_dev)
        }
 }
 
+static void hns_dsaf_inner_qid_cfg(struct dsaf_device *dsaf_dev)
+{
+       u16 max_q_per_vf, max_vfn;
+       u32 q_id, q_num_per_port;
+       u32 mac_id;
+
+       if (AE_IS_VER1(dsaf_dev->dsaf_ver))
+               return;
+
+       hns_rcb_get_queue_mode(dsaf_dev->dsaf_mode,
+                              HNS_DSAF_COMM_SERVICE_NW_IDX,
+                              &max_vfn, &max_q_per_vf);
+       q_num_per_port = max_vfn * max_q_per_vf;
+
+       for (mac_id = 0, q_id = 0; mac_id < DSAF_SERVICE_NW_NUM; mac_id++) {
+               dsaf_set_dev_field(dsaf_dev,
+                                  DSAFV2_SERDES_LBK_0_REG + 4 * mac_id,
+                                  DSAFV2_SERDES_LBK_QID_M,
+                                  DSAFV2_SERDES_LBK_QID_S,
+                                  q_id);
+               q_id += q_num_per_port;
+       }
+}
+
 /**
  * hns_dsaf_sw_port_type_cfg - cfg sw type
  * @dsaf_id: dsa fabric id
@@ -691,6 +715,16 @@ void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en)
        dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, DSAF_CFG_MIX_MODE_S, !!en);
 }
 
+void hns_dsaf_set_inner_lb(struct dsaf_device *dsaf_dev, u32 mac_id, u32 en)
+{
+       if (AE_IS_VER1(dsaf_dev->dsaf_ver) ||
+           dsaf_dev->mac_cb[mac_id].mac_type == HNAE_PORT_DEBUG)
+               return;
+
+       dsaf_set_dev_bit(dsaf_dev, DSAFV2_SERDES_LBK_0_REG + 4 * mac_id,
+                        DSAFV2_SERDES_LBK_EN_B, !!en);
+}
+
 /**
  * hns_dsaf_tbl_stat_en - tbl
  * @dsaf_id: dsa fabric id
@@ -1022,6 +1056,9 @@ static void hns_dsaf_comm_init(struct dsaf_device *dsaf_dev)
        /* set promisc def queue id */
        hns_dsaf_mix_def_qid_cfg(dsaf_dev);
 
+       /* set inner loopback queue id */
+       hns_dsaf_inner_qid_cfg(dsaf_dev);
+
        /* in non switch mode, set all port to access mode */
        hns_dsaf_sw_port_type_cfg(dsaf_dev, DSAF_SW_PORT_TYPE_NON_VLAN);
 
index 40205b910f80e66a439c14b53e7f2c907b0fbeb1..5fea226efaf330f968b2942a55065c7fc5c01112 100644 (file)
@@ -417,5 +417,6 @@ void hns_dsaf_get_strings(int stringset, u8 *data, int port);
 void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data);
 int hns_dsaf_get_regs_count(void);
 void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en);
+void hns_dsaf_set_inner_lb(struct dsaf_device *dsaf_dev, u32 mac_id, u32 en);
 
 #endif /* __HNS_DSAF_MAIN_H__ */
index f0c4f9b09d5b0477365c862816bc8b8d4dd19b88..60d695daa471eb23d5284778300807f8b235e546 100644 (file)
 #define DSAF_XGE_INT_STS_0_REG         0x1C0
 #define DSAF_PPE_INT_STS_0_REG         0x1E0
 #define DSAF_ROCEE_INT_STS_0_REG       0x200
+#define DSAFV2_SERDES_LBK_0_REG         0x220
 #define DSAF_PPE_QID_CFG_0_REG         0x300
 #define DSAF_SW_PORT_TYPE_0_REG                0x320
 #define DSAF_STP_PORT_TYPE_0_REG       0x340
 #define PPEV2_CFG_RSS_TBL_4N3_S        24
 #define PPEV2_CFG_RSS_TBL_4N3_M        (((1UL << 5) - 1) << PPEV2_CFG_RSS_TBL_4N3_S)
 
+#define DSAFV2_SERDES_LBK_EN_B  8
+#define DSAFV2_SERDES_LBK_QID_S 0
+#define DSAFV2_SERDES_LBK_QID_M        (((1UL << 8) - 1) << DSAFV2_SERDES_LBK_QID_S)
+
 #define PPE_CNT_CLR_CE_B       0
 #define PPE_CNT_CLR_SNAP_EN_B  1
 
index 3df22840fcd15370393e7e6a5c331b72dd87f476..3c4a3bc31a89230c2453c115316306739e28c2a3 100644 (file)
@@ -295,8 +295,10 @@ static int __lb_setup(struct net_device *ndev,
 
        switch (loop) {
        case MAC_INTERNALLOOP_PHY:
-               if ((phy_dev) && (!phy_dev->is_c45))
+               if ((phy_dev) && (!phy_dev->is_c45)) {
                        ret = hns_nic_config_phy_loopback(phy_dev, 0x1);
+                       ret |= h->dev->ops->set_loopback(h, loop, 0x1);
+               }
                break;
        case MAC_INTERNALLOOP_MAC:
                if ((h->dev->ops->set_loopback) &&
@@ -376,6 +378,7 @@ static void __lb_other_process(struct hns_nic_ring_data *ring_data,
                               struct sk_buff *skb)
 {
        struct net_device *ndev;
+       struct hns_nic_priv *priv;
        struct hnae_ring *ring;
        struct netdev_queue *dev_queue;
        struct sk_buff *new_skb;
@@ -385,8 +388,17 @@ static void __lb_other_process(struct hns_nic_ring_data *ring_data,
        char buff[33]; /* 32B data and the last character '\0' */
 
        if (!ring_data) { /* Just for doing create frame*/
+               ndev = skb->dev;
+               priv = netdev_priv(ndev);
+
                frame_size = skb->len;
                memset(skb->data, 0xFF, frame_size);
+               if ((!AE_IS_VER1(priv->enet_ver)) &&
+                   (priv->ae_handle->port_type == HNAE_PORT_SERVICE)) {
+                       memcpy(skb->data, ndev->dev_addr, 6);
+                       skb->data[5] += 0x1f;
+               }
+
                frame_size &= ~1ul;
                memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
                memset(&skb->data[frame_size / 2 + 10], 0xBE,
@@ -486,6 +498,7 @@ static int __lb_run_test(struct net_device *ndev,
 
        /* place data into test skb */
        (void)skb_put(skb, size);
+       skb->dev = ndev;
        __lb_other_process(NULL, skb);
        skb->queue_mapping = NIC_LB_TEST_RING_ID;
 
index 335417b4756b73d3d2d9f1558b10b2556443bee7..ebe60719e489cd1fbdc12248ee48eed6d0979fd4 100644 (file)
@@ -1166,7 +1166,10 @@ map_failed:
        if (!firmware_has_feature(FW_FEATURE_CMO))
                netdev_err(netdev, "tx: unable to map xmit buffer\n");
        adapter->tx_map_failed++;
-       skb_linearize(skb);
+       if (skb_linearize(skb)) {
+               netdev->stats.tx_dropped++;
+               goto out;
+       }
        force_bounce = 1;
        goto retry_bounce;
 }
index 7d65708437238b48f5c5cdfcb1d901b202e2d547..6e9e16eee5d0eff7d74a2eff4a8a4bb91368afcd 100644 (file)
@@ -1348,44 +1348,44 @@ static void init_sub_crqs(struct ibmvnic_adapter *adapter, int retry)
        crq.request_capability.cmd = REQUEST_CAPABILITY;
 
        crq.request_capability.capability = cpu_to_be16(REQ_TX_QUEUES);
-       crq.request_capability.number = cpu_to_be32(adapter->req_tx_queues);
+       crq.request_capability.number = cpu_to_be64(adapter->req_tx_queues);
        ibmvnic_send_crq(adapter, &crq);
 
        crq.request_capability.capability = cpu_to_be16(REQ_RX_QUEUES);
-       crq.request_capability.number = cpu_to_be32(adapter->req_rx_queues);
+       crq.request_capability.number = cpu_to_be64(adapter->req_rx_queues);
        ibmvnic_send_crq(adapter, &crq);
 
        crq.request_capability.capability = cpu_to_be16(REQ_RX_ADD_QUEUES);
-       crq.request_capability.number = cpu_to_be32(adapter->req_rx_add_queues);
+       crq.request_capability.number = cpu_to_be64(adapter->req_rx_add_queues);
        ibmvnic_send_crq(adapter, &crq);
 
        crq.request_capability.capability =
            cpu_to_be16(REQ_TX_ENTRIES_PER_SUBCRQ);
        crq.request_capability.number =
-           cpu_to_be32(adapter->req_tx_entries_per_subcrq);
+           cpu_to_be64(adapter->req_tx_entries_per_subcrq);
        ibmvnic_send_crq(adapter, &crq);
 
        crq.request_capability.capability =
            cpu_to_be16(REQ_RX_ADD_ENTRIES_PER_SUBCRQ);
        crq.request_capability.number =
-           cpu_to_be32(adapter->req_rx_add_entries_per_subcrq);
+           cpu_to_be64(adapter->req_rx_add_entries_per_subcrq);
        ibmvnic_send_crq(adapter, &crq);
 
        crq.request_capability.capability = cpu_to_be16(REQ_MTU);
-       crq.request_capability.number = cpu_to_be32(adapter->req_mtu);
+       crq.request_capability.number = cpu_to_be64(adapter->req_mtu);
        ibmvnic_send_crq(adapter, &crq);
 
        if (adapter->netdev->flags & IFF_PROMISC) {
                if (adapter->promisc_supported) {
                        crq.request_capability.capability =
                            cpu_to_be16(PROMISC_REQUESTED);
-                       crq.request_capability.number = cpu_to_be32(1);
+                       crq.request_capability.number = cpu_to_be64(1);
                        ibmvnic_send_crq(adapter, &crq);
                }
        } else {
                crq.request_capability.capability =
                    cpu_to_be16(PROMISC_REQUESTED);
-               crq.request_capability.number = cpu_to_be32(0);
+               crq.request_capability.number = cpu_to_be64(0);
                ibmvnic_send_crq(adapter, &crq);
        }
 
@@ -2312,93 +2312,93 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq,
        switch (be16_to_cpu(crq->query_capability.capability)) {
        case MIN_TX_QUEUES:
                adapter->min_tx_queues =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "min_tx_queues = %lld\n",
                           adapter->min_tx_queues);
                break;
        case MIN_RX_QUEUES:
                adapter->min_rx_queues =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "min_rx_queues = %lld\n",
                           adapter->min_rx_queues);
                break;
        case MIN_RX_ADD_QUEUES:
                adapter->min_rx_add_queues =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "min_rx_add_queues = %lld\n",
                           adapter->min_rx_add_queues);
                break;
        case MAX_TX_QUEUES:
                adapter->max_tx_queues =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "max_tx_queues = %lld\n",
                           adapter->max_tx_queues);
                break;
        case MAX_RX_QUEUES:
                adapter->max_rx_queues =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "max_rx_queues = %lld\n",
                           adapter->max_rx_queues);
                break;
        case MAX_RX_ADD_QUEUES:
                adapter->max_rx_add_queues =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "max_rx_add_queues = %lld\n",
                           adapter->max_rx_add_queues);
                break;
        case MIN_TX_ENTRIES_PER_SUBCRQ:
                adapter->min_tx_entries_per_subcrq =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "min_tx_entries_per_subcrq = %lld\n",
                           adapter->min_tx_entries_per_subcrq);
                break;
        case MIN_RX_ADD_ENTRIES_PER_SUBCRQ:
                adapter->min_rx_add_entries_per_subcrq =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "min_rx_add_entrs_per_subcrq = %lld\n",
                           adapter->min_rx_add_entries_per_subcrq);
                break;
        case MAX_TX_ENTRIES_PER_SUBCRQ:
                adapter->max_tx_entries_per_subcrq =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "max_tx_entries_per_subcrq = %lld\n",
                           adapter->max_tx_entries_per_subcrq);
                break;
        case MAX_RX_ADD_ENTRIES_PER_SUBCRQ:
                adapter->max_rx_add_entries_per_subcrq =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "max_rx_add_entrs_per_subcrq = %lld\n",
                           adapter->max_rx_add_entries_per_subcrq);
                break;
        case TCP_IP_OFFLOAD:
                adapter->tcp_ip_offload =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "tcp_ip_offload = %lld\n",
                           adapter->tcp_ip_offload);
                break;
        case PROMISC_SUPPORTED:
                adapter->promisc_supported =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "promisc_supported = %lld\n",
                           adapter->promisc_supported);
                break;
        case MIN_MTU:
-               adapter->min_mtu = be32_to_cpu(crq->query_capability.number);
+               adapter->min_mtu = be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "min_mtu = %lld\n", adapter->min_mtu);
                break;
        case MAX_MTU:
-               adapter->max_mtu = be32_to_cpu(crq->query_capability.number);
+               adapter->max_mtu = be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "max_mtu = %lld\n", adapter->max_mtu);
                break;
        case MAX_MULTICAST_FILTERS:
                adapter->max_multicast_filters =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "max_multicast_filters = %lld\n",
                           adapter->max_multicast_filters);
                break;
        case VLAN_HEADER_INSERTION:
                adapter->vlan_header_insertion =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                if (adapter->vlan_header_insertion)
                        netdev->features |= NETIF_F_HW_VLAN_STAG_TX;
                netdev_dbg(netdev, "vlan_header_insertion = %lld\n",
@@ -2406,43 +2406,43 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq,
                break;
        case MAX_TX_SG_ENTRIES:
                adapter->max_tx_sg_entries =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "max_tx_sg_entries = %lld\n",
                           adapter->max_tx_sg_entries);
                break;
        case RX_SG_SUPPORTED:
                adapter->rx_sg_supported =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "rx_sg_supported = %lld\n",
                           adapter->rx_sg_supported);
                break;
        case OPT_TX_COMP_SUB_QUEUES:
                adapter->opt_tx_comp_sub_queues =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "opt_tx_comp_sub_queues = %lld\n",
                           adapter->opt_tx_comp_sub_queues);
                break;
        case OPT_RX_COMP_QUEUES:
                adapter->opt_rx_comp_queues =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "opt_rx_comp_queues = %lld\n",
                           adapter->opt_rx_comp_queues);
                break;
        case OPT_RX_BUFADD_Q_PER_RX_COMP_Q:
                adapter->opt_rx_bufadd_q_per_rx_comp_q =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "opt_rx_bufadd_q_per_rx_comp_q = %lld\n",
                           adapter->opt_rx_bufadd_q_per_rx_comp_q);
                break;
        case OPT_TX_ENTRIES_PER_SUBCRQ:
                adapter->opt_tx_entries_per_subcrq =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "opt_tx_entries_per_subcrq = %lld\n",
                           adapter->opt_tx_entries_per_subcrq);
                break;
        case OPT_RXBA_ENTRIES_PER_SUBCRQ:
                adapter->opt_rxba_entries_per_subcrq =
-                   be32_to_cpu(crq->query_capability.number);
+                   be64_to_cpu(crq->query_capability.number);
                netdev_dbg(netdev, "opt_rxba_entries_per_subcrq = %lld\n",
                           adapter->opt_rxba_entries_per_subcrq);
                break;
index 1242925ad34cb6b0336524b1c3c1e569158aee24..1a9993cc79b572f58c172a5f4a071594cf4a93b1 100644 (file)
@@ -319,10 +319,8 @@ struct ibmvnic_capability {
        u8 first;
        u8 cmd;
        __be16 capability; /* one of ibmvnic_capabilities */
+       __be64 number;
        struct ibmvnic_rc rc;
-       __be32 number; /*FIX: should be __be64, but I'm getting the least
-                       * significant word first
-                       */
 } __packed __aligned(8);
 
 struct ibmvnic_login {
index fa593dd3efe122daed9de5801457470931ebe41c..3772f3ac956e9efd4399a810347fc2f08a8fd73c 100644 (file)
@@ -83,6 +83,15 @@ config E1000E
          To compile this driver as a module, choose M here. The module
          will be called e1000e.
 
+config E1000E_HWTS
+       bool "Support HW cross-timestamp on PCH devices"
+       default y
+       depends on E1000E && X86
+       ---help---
+        Say Y to enable hardware supported cross-timestamping on PCH
+        devices. The cross-timestamp is available through the PTP clock
+        driver precise cross-timestamp ioctl (PTP_SYS_OFFSET_PRECISE).
+
 config IGB
        tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
        depends on PCI
index f7c7804d79e57776492fee070601536994bae800..0641c0098738033aafdb7f0641f33557642a7056 100644 (file)
 #define E1000_RXCW_C          0x20000000        /* Receive config */
 #define E1000_RXCW_SYNCH      0x40000000        /* Receive config synch */
 
+/* HH Time Sync */
+#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK  0x0000F000 /* max delay */
+#define E1000_TSYNCTXCTL_SYNC_COMP             0x40000000 /* sync complete */
+#define E1000_TSYNCTXCTL_START_SYNC            0x80000000 /* initiate sync */
+
 #define E1000_TSYNCTXCTL_VALID         0x00000001 /* Tx timestamp valid */
 #define E1000_TSYNCTXCTL_ENABLED       0x00000010 /* enable Tx timestamping */
 
index 25a0ad5102d633de71b11b45bdbc8912c3f133a5..e2ff3ef75d5d66e97d5b67229764f9a5afc2c7ac 100644 (file)
 
 #include "e1000.h"
 
+#ifdef CONFIG_E1000E_HWTS
+#include <linux/clocksource.h>
+#include <linux/ktime.h>
+#include <asm/tsc.h>
+#endif
+
 /**
  * e1000e_phc_adjfreq - adjust the frequency of the hardware clock
  * @ptp: ptp clock structure
@@ -98,6 +104,78 @@ static int e1000e_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
        return 0;
 }
 
+#ifdef CONFIG_E1000E_HWTS
+#define MAX_HW_WAIT_COUNT (3)
+
+/**
+ * e1000e_phc_get_syncdevicetime - Callback given to timekeeping code reads system/device registers
+ * @device: current device time
+ * @system: system counter value read synchronously with device time
+ * @ctx: context provided by timekeeping code
+ *
+ * Read device and system (ART) clock simultaneously and return the corrected
+ * clock values in ns.
+ **/
+static int e1000e_phc_get_syncdevicetime(ktime_t *device,
+                                        struct system_counterval_t *system,
+                                        void *ctx)
+{
+       struct e1000_adapter *adapter = (struct e1000_adapter *)ctx;
+       struct e1000_hw *hw = &adapter->hw;
+       unsigned long flags;
+       int i;
+       u32 tsync_ctrl;
+       cycle_t dev_cycles;
+       cycle_t sys_cycles;
+
+       tsync_ctrl = er32(TSYNCTXCTL);
+       tsync_ctrl |= E1000_TSYNCTXCTL_START_SYNC |
+               E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK;
+       ew32(TSYNCTXCTL, tsync_ctrl);
+       for (i = 0; i < MAX_HW_WAIT_COUNT; ++i) {
+               udelay(1);
+               tsync_ctrl = er32(TSYNCTXCTL);
+               if (tsync_ctrl & E1000_TSYNCTXCTL_SYNC_COMP)
+                       break;
+       }
+
+       if (i == MAX_HW_WAIT_COUNT)
+               return -ETIMEDOUT;
+
+       dev_cycles = er32(SYSSTMPH);
+       dev_cycles <<= 32;
+       dev_cycles |= er32(SYSSTMPL);
+       spin_lock_irqsave(&adapter->systim_lock, flags);
+       *device = ns_to_ktime(timecounter_cyc2time(&adapter->tc, dev_cycles));
+       spin_unlock_irqrestore(&adapter->systim_lock, flags);
+
+       sys_cycles = er32(PLTSTMPH);
+       sys_cycles <<= 32;
+       sys_cycles |= er32(PLTSTMPL);
+       *system = convert_art_to_tsc(sys_cycles);
+
+       return 0;
+}
+
+/**
+ * e1000e_phc_getsynctime - Reads the current system/device cross timestamp
+ * @ptp: ptp clock structure
+ * @cts: structure containing timestamp
+ *
+ * Read device and system (ART) clock simultaneously and return the scaled
+ * clock values in ns.
+ **/
+static int e1000e_phc_getcrosststamp(struct ptp_clock_info *ptp,
+                                    struct system_device_crosststamp *xtstamp)
+{
+       struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter,
+                                                    ptp_clock_info);
+
+       return get_device_system_crosststamp(e1000e_phc_get_syncdevicetime,
+                                               adapter, NULL, xtstamp);
+}
+#endif/*CONFIG_E1000E_HWTS*/
+
 /**
  * e1000e_phc_gettime - Reads the current time from the hardware clock
  * @ptp: ptp clock structure
@@ -236,6 +314,13 @@ void e1000e_ptp_init(struct e1000_adapter *adapter)
                break;
        }
 
+#ifdef CONFIG_E1000E_HWTS
+       /* CPU must have ART and GBe must be from Sunrise Point or greater */
+       if (hw->mac.type >= e1000_pch_spt && boot_cpu_has(X86_FEATURE_ART))
+               adapter->ptp_clock_info.getcrosststamp =
+                       e1000e_phc_getcrosststamp;
+#endif/*CONFIG_E1000E_HWTS*/
+
        INIT_DELAYED_WORK(&adapter->systim_overflow_work,
                          e1000e_systim_overflow_work);
 
index 1d5e0b77062a0ea3341dafcab898bd8163bb105f..0cb4d365e5ad72dd6f2a10bd18d22645de3c8dbf 100644 (file)
 #define E1000_SYSTIML  0x0B600 /* System time register Low - RO */
 #define E1000_SYSTIMH  0x0B604 /* System time register High - RO */
 #define E1000_TIMINCA  0x0B608 /* Increment attributes register - RW */
+#define E1000_SYSSTMPL  0x0B648 /* HH Timesync system stamp low register */
+#define E1000_SYSSTMPH  0x0B64C /* HH Timesync system stamp hi register */
+#define E1000_PLTSTMPL  0x0B640 /* HH Timesync platform stamp low register */
+#define E1000_PLTSTMPH  0x0B644 /* HH Timesync platform stamp hi register */
 #define E1000_RXMTRL   0x0B634 /* Time sync Rx EtherType and Msg Type - RW */
 #define E1000_RXUDP    0x0B638 /* Time Sync Rx UDP Port - RW */
 
index b1de7afd41166cc9ef67ed7e43191aaff897ec4e..3ddf657bc10bcc51d5a217595ba8e98ed909e0cd 100644 (file)
@@ -270,11 +270,17 @@ jme_reset_mac_processor(struct jme_adapter *jme)
 }
 
 static inline void
-jme_clear_pm(struct jme_adapter *jme)
+jme_clear_pm_enable_wol(struct jme_adapter *jme)
 {
        jwrite32(jme, JME_PMCS, PMCS_STMASK | jme->reg_pmcs);
 }
 
+static inline void
+jme_clear_pm_disable_wol(struct jme_adapter *jme)
+{
+       jwrite32(jme, JME_PMCS, PMCS_STMASK);
+}
+
 static int
 jme_reload_eeprom(struct jme_adapter *jme)
 {
@@ -1853,7 +1859,7 @@ jme_open(struct net_device *netdev)
        struct jme_adapter *jme = netdev_priv(netdev);
        int rc;
 
-       jme_clear_pm(jme);
+       jme_clear_pm_disable_wol(jme);
        JME_NAPI_ENABLE(jme);
 
        tasklet_init(&jme->linkch_task, jme_link_change_tasklet,
@@ -1925,11 +1931,11 @@ jme_wait_link(struct jme_adapter *jme)
 static void
 jme_powersave_phy(struct jme_adapter *jme)
 {
-       if (jme->reg_pmcs) {
+       if (jme->reg_pmcs && device_may_wakeup(&jme->pdev->dev)) {
                jme_set_100m_half(jme);
                if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
                        jme_wait_link(jme);
-               jme_clear_pm(jme);
+               jme_clear_pm_enable_wol(jme);
        } else {
                jme_phy_off(jme);
        }
@@ -2646,9 +2652,6 @@ jme_set_wol(struct net_device *netdev,
        if (wol->wolopts & WAKE_MAGIC)
                jme->reg_pmcs |= PMCS_MFEN;
 
-       jwrite32(jme, JME_PMCS, jme->reg_pmcs);
-       device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs));
-
        return 0;
 }
 
@@ -3172,8 +3175,8 @@ jme_init_one(struct pci_dev *pdev,
        jme->mii_if.mdio_read = jme_mdio_read;
        jme->mii_if.mdio_write = jme_mdio_write;
 
-       jme_clear_pm(jme);
-       device_set_wakeup_enable(&pdev->dev, true);
+       jme_clear_pm_disable_wol(jme);
+       device_init_wakeup(&pdev->dev, true);
 
        jme_set_phyfifo_5level(jme);
        jme->pcirev = pdev->revision;
@@ -3304,7 +3307,7 @@ jme_resume(struct device *dev)
        if (!netif_running(netdev))
                return 0;
 
-       jme_clear_pm(jme);
+       jme_clear_pm_disable_wol(jme);
        jme_phy_on(jme);
        if (test_bit(JME_FLAG_SSET, &jme->flags))
                jme_set_settings(netdev, &jme->old_ecmd);
@@ -3312,13 +3315,14 @@ jme_resume(struct device *dev)
                jme_reset_phy_processor(jme);
        jme_phy_calibration(jme);
        jme_phy_setEA(jme);
-       jme_start_irq(jme);
        netif_device_attach(netdev);
 
        atomic_inc(&jme->link_changing);
 
        jme_reset_link(jme);
 
+       jme_start_irq(jme);
+
        return 0;
 }
 
index f191a16125893e5b742c5d99ea7bd814dba433a5..21e2c09602716351a21dc2762f1631a298bf05eb 100644 (file)
@@ -2245,7 +2245,7 @@ static int mlx4_en_set_vf_mac(struct net_device *dev, int queue, u8 *mac)
        struct mlx4_en_dev *mdev = en_priv->mdev;
        u64 mac_u64 = mlx4_mac_to_u64(mac);
 
-       if (!is_valid_ether_addr(mac))
+       if (is_multicast_ether_addr(mac))
                return -EINVAL;
 
        return mlx4_set_vf_mac(mdev->dev, en_priv->port, queue, mac_u64);
index 2cc3c626c3fea732d0862ff5f0ce520d442a6205..f8674ae62752d53bc768c16ac9b2de3053e183eb 100644 (file)
@@ -1256,6 +1256,7 @@ err_set_port:
 static int mlx4_mf_bond(struct mlx4_dev *dev)
 {
        int err = 0;
+       int nvfs;
        struct mlx4_slaves_pport slaves_port1;
        struct mlx4_slaves_pport slaves_port2;
        DECLARE_BITMAP(slaves_port_1_2, MLX4_MFUNC_MAX);
@@ -1272,11 +1273,18 @@ static int mlx4_mf_bond(struct mlx4_dev *dev)
                return -EINVAL;
        }
 
+       /* number of virtual functions is number of total functions minus one
+        * physical function for each port.
+        */
+       nvfs = bitmap_weight(slaves_port1.slaves, dev->persist->num_vfs + 1) +
+               bitmap_weight(slaves_port2.slaves, dev->persist->num_vfs + 1) - 2;
+
        /* limit on maximum allowed VFs */
-       if ((bitmap_weight(slaves_port1.slaves, dev->persist->num_vfs + 1) +
-           bitmap_weight(slaves_port2.slaves, dev->persist->num_vfs + 1)) >
-           MAX_MF_BOND_ALLOWED_SLAVES)
+       if (nvfs > MAX_MF_BOND_ALLOWED_SLAVES) {
+               mlx4_warn(dev, "HA mode is not supported for %d VFs (max %d are allowed)\n",
+                         nvfs, MAX_MF_BOND_ALLOWED_SLAVES);
                return -EINVAL;
+       }
 
        if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
                mlx4_warn(dev, "HA mode unsupported for NON DMFS steering\n");
index 787b7bb54d52acd094570283bf6793f1bfb0dab0..211c65087997dd5a92cc53a13f9fd3869927d09d 100644 (file)
@@ -193,10 +193,10 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
        if (need_mf_bond) {
                if (port == 1) {
                        mutex_lock(&table->mutex);
-                       mutex_lock(&dup_table->mutex);
+                       mutex_lock_nested(&dup_table->mutex, SINGLE_DEPTH_NESTING);
                } else {
                        mutex_lock(&dup_table->mutex);
-                       mutex_lock(&table->mutex);
+                       mutex_lock_nested(&table->mutex, SINGLE_DEPTH_NESTING);
                }
        } else {
                mutex_lock(&table->mutex);
@@ -389,10 +389,10 @@ void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
        if (dup) {
                if (port == 1) {
                        mutex_lock(&table->mutex);
-                       mutex_lock(&dup_table->mutex);
+                       mutex_lock_nested(&dup_table->mutex, SINGLE_DEPTH_NESTING);
                } else {
                        mutex_lock(&dup_table->mutex);
-                       mutex_lock(&table->mutex);
+                       mutex_lock_nested(&table->mutex, SINGLE_DEPTH_NESTING);
                }
        } else {
                mutex_lock(&table->mutex);
@@ -479,10 +479,10 @@ int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac)
        if (dup) {
                if (port == 1) {
                        mutex_lock(&table->mutex);
-                       mutex_lock(&dup_table->mutex);
+                       mutex_lock_nested(&dup_table->mutex, SINGLE_DEPTH_NESTING);
                } else {
                        mutex_lock(&dup_table->mutex);
-                       mutex_lock(&table->mutex);
+                       mutex_lock_nested(&table->mutex, SINGLE_DEPTH_NESTING);
                }
        } else {
                mutex_lock(&table->mutex);
@@ -588,10 +588,10 @@ int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan,
        if (need_mf_bond) {
                if (port == 1) {
                        mutex_lock(&table->mutex);
-                       mutex_lock(&dup_table->mutex);
+                       mutex_lock_nested(&dup_table->mutex, SINGLE_DEPTH_NESTING);
                } else {
                        mutex_lock(&dup_table->mutex);
-                       mutex_lock(&table->mutex);
+                       mutex_lock_nested(&table->mutex, SINGLE_DEPTH_NESTING);
                }
        } else {
                mutex_lock(&table->mutex);
@@ -764,10 +764,10 @@ void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan)
        if (dup) {
                if (port == 1) {
                        mutex_lock(&table->mutex);
-                       mutex_lock(&dup_table->mutex);
+                       mutex_lock_nested(&dup_table->mutex, SINGLE_DEPTH_NESTING);
                } else {
                        mutex_lock(&dup_table->mutex);
-                       mutex_lock(&table->mutex);
+                       mutex_lock_nested(&table->mutex, SINGLE_DEPTH_NESTING);
                }
        } else {
                mutex_lock(&table->mutex);
index aac071a7e830b5fd777da7a5e4d014d802ad70d0..5b1753233c5dd8c30c1dd110a952c6d9c4360e39 100644 (file)
@@ -223,6 +223,7 @@ struct mlx5e_pport_stats {
 
 static const char rq_stats_strings[][ETH_GSTRING_LEN] = {
        "packets",
+       "bytes",
        "csum_none",
        "csum_sw",
        "lro_packets",
@@ -232,16 +233,18 @@ static const char rq_stats_strings[][ETH_GSTRING_LEN] = {
 
 struct mlx5e_rq_stats {
        u64 packets;
+       u64 bytes;
        u64 csum_none;
        u64 csum_sw;
        u64 lro_packets;
        u64 lro_bytes;
        u64 wqe_err;
-#define NUM_RQ_STATS 6
+#define NUM_RQ_STATS 7
 };
 
 static const char sq_stats_strings[][ETH_GSTRING_LEN] = {
        "packets",
+       "bytes",
        "tso_packets",
        "tso_bytes",
        "csum_offload_none",
@@ -253,6 +256,7 @@ static const char sq_stats_strings[][ETH_GSTRING_LEN] = {
 
 struct mlx5e_sq_stats {
        u64 packets;
+       u64 bytes;
        u64 tso_packets;
        u64 tso_bytes;
        u64 csum_offload_none;
@@ -260,7 +264,7 @@ struct mlx5e_sq_stats {
        u64 wake;
        u64 dropped;
        u64 nop;
-#define NUM_SQ_STATS 8
+#define NUM_SQ_STATS 9
 };
 
 struct mlx5e_stats {
@@ -304,14 +308,9 @@ enum {
        MLX5E_RQ_STATE_POST_WQES_ENABLE,
 };
 
-enum cq_flags {
-       MLX5E_CQ_HAS_CQES = 1,
-};
-
 struct mlx5e_cq {
        /* data path - accessed per cqe */
        struct mlx5_cqwq           wq;
-       unsigned long              flags;
 
        /* data path - accessed per napi poll */
        struct napi_struct        *napi;
@@ -452,6 +451,8 @@ enum mlx5e_traffic_types {
        MLX5E_NUM_TT,
 };
 
+#define IS_HASHING_TT(tt) (tt != MLX5E_TT_ANY)
+
 enum mlx5e_rqt_ix {
        MLX5E_INDIRECTION_RQT,
        MLX5E_SINGLE_RQ_RQT,
@@ -618,9 +619,12 @@ void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv);
 void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv);
 
 int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix);
+void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv);
 
 int mlx5e_open_locked(struct net_device *netdev);
 int mlx5e_close_locked(struct net_device *netdev);
+void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
+                                  int num_channels);
 
 static inline void mlx5e_tx_notify_hw(struct mlx5e_sq *sq,
                                      struct mlx5e_tx_wqe *wqe, int bf_sz)
index be6543570b2be18d476773f6b530dfeab6057800..2018eebe1531563e036c41c19372331f8a576b14 100644 (file)
@@ -62,10 +62,11 @@ static void mlx5e_timestamp_overflow(struct work_struct *work)
        struct delayed_work *dwork = to_delayed_work(work);
        struct mlx5e_tstamp *tstamp = container_of(dwork, struct mlx5e_tstamp,
                                                   overflow_work);
+       unsigned long flags;
 
-       write_lock(&tstamp->lock);
+       write_lock_irqsave(&tstamp->lock, flags);
        timecounter_read(&tstamp->clock);
-       write_unlock(&tstamp->lock);
+       write_unlock_irqrestore(&tstamp->lock, flags);
        schedule_delayed_work(&tstamp->overflow_work, tstamp->overflow_period);
 }
 
@@ -136,10 +137,11 @@ static int mlx5e_ptp_settime(struct ptp_clock_info *ptp,
        struct mlx5e_tstamp *tstamp = container_of(ptp, struct mlx5e_tstamp,
                                                   ptp_info);
        u64 ns = timespec64_to_ns(ts);
+       unsigned long flags;
 
-       write_lock(&tstamp->lock);
+       write_lock_irqsave(&tstamp->lock, flags);
        timecounter_init(&tstamp->clock, &tstamp->cycles, ns);
-       write_unlock(&tstamp->lock);
+       write_unlock_irqrestore(&tstamp->lock, flags);
 
        return 0;
 }
@@ -150,10 +152,11 @@ static int mlx5e_ptp_gettime(struct ptp_clock_info *ptp,
        struct mlx5e_tstamp *tstamp = container_of(ptp, struct mlx5e_tstamp,
                                                   ptp_info);
        u64 ns;
+       unsigned long flags;
 
-       write_lock(&tstamp->lock);
+       write_lock_irqsave(&tstamp->lock, flags);
        ns = timecounter_read(&tstamp->clock);
-       write_unlock(&tstamp->lock);
+       write_unlock_irqrestore(&tstamp->lock, flags);
 
        *ts = ns_to_timespec64(ns);
 
@@ -164,10 +167,11 @@ static int mlx5e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
 {
        struct mlx5e_tstamp *tstamp = container_of(ptp, struct mlx5e_tstamp,
                                                   ptp_info);
+       unsigned long flags;
 
-       write_lock(&tstamp->lock);
+       write_lock_irqsave(&tstamp->lock, flags);
        timecounter_adjtime(&tstamp->clock, delta);
-       write_unlock(&tstamp->lock);
+       write_unlock_irqrestore(&tstamp->lock, flags);
 
        return 0;
 }
@@ -176,6 +180,7 @@ static int mlx5e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
 {
        u64 adj;
        u32 diff;
+       unsigned long flags;
        int neg_adj = 0;
        struct mlx5e_tstamp *tstamp = container_of(ptp, struct mlx5e_tstamp,
                                                  ptp_info);
@@ -189,11 +194,11 @@ static int mlx5e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 delta)
        adj *= delta;
        diff = div_u64(adj, 1000000000ULL);
 
-       write_lock(&tstamp->lock);
+       write_lock_irqsave(&tstamp->lock, flags);
        timecounter_read(&tstamp->clock);
        tstamp->cycles.mult = neg_adj ? tstamp->nominal_c_mult - diff :
                                        tstamp->nominal_c_mult + diff;
-       write_unlock(&tstamp->lock);
+       write_unlock_irqrestore(&tstamp->lock, flags);
 
        return 0;
 }
index 65624ac65b4c347ac5dedf55f3b209de799e7e5f..5abeb00fceb8b0876d17f4aab813054d55414cc8 100644 (file)
@@ -385,6 +385,8 @@ static int mlx5e_set_channels(struct net_device *dev,
                mlx5e_close_locked(dev);
 
        priv->params.num_channels = count;
+       mlx5e_build_default_indir_rqt(priv->params.indirection_rqt,
+                                     MLX5E_INDIR_RQT_SIZE, count);
 
        if (was_opened)
                err = mlx5e_open_locked(dev);
@@ -703,18 +705,36 @@ static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
        return 0;
 }
 
+static void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
+{
+       struct mlx5_core_dev *mdev = priv->mdev;
+       void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
+       int i;
+
+       MLX5_SET(modify_tir_in, in, bitmask.hash, 1);
+       mlx5e_build_tir_ctx_hash(tirc, priv);
+
+       for (i = 0; i < MLX5E_NUM_TT; i++)
+               if (IS_HASHING_TT(i))
+                       mlx5_core_modify_tir(mdev, priv->tirn[i], in, inlen);
+}
+
 static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
                          const u8 *key, const u8 hfunc)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
-       bool close_open;
-       int err = 0;
+       int inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
+       void *in;
 
        if ((hfunc != ETH_RSS_HASH_NO_CHANGE) &&
            (hfunc != ETH_RSS_HASH_XOR) &&
            (hfunc != ETH_RSS_HASH_TOP))
                return -EINVAL;
 
+       in = mlx5_vzalloc(inlen);
+       if (!in)
+               return -ENOMEM;
+
        mutex_lock(&priv->state_lock);
 
        if (indir) {
@@ -723,11 +743,6 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
                mlx5e_redirect_rqt(priv, MLX5E_INDIRECTION_RQT);
        }
 
-       close_open = (key || (hfunc != ETH_RSS_HASH_NO_CHANGE)) &&
-                    test_bit(MLX5E_STATE_OPENED, &priv->state);
-       if (close_open)
-               mlx5e_close_locked(dev);
-
        if (key)
                memcpy(priv->params.toeplitz_hash_key, key,
                       sizeof(priv->params.toeplitz_hash_key));
@@ -735,12 +750,13 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
        if (hfunc != ETH_RSS_HASH_NO_CHANGE)
                priv->params.rss_hfunc = hfunc;
 
-       if (close_open)
-               err = mlx5e_open_locked(priv->netdev);
+       mlx5e_modify_tirs_hash(priv, in, inlen);
 
        mutex_unlock(&priv->state_lock);
 
-       return err;
+       kvfree(in);
+
+       return 0;
 }
 
 static int mlx5e_get_rxnfc(struct net_device *netdev,
index d4e1c30452009718d9761a8a4949f5195d7f4c59..402994bf7e167d1ae23a8943789f712f82862f46 100644 (file)
@@ -141,6 +141,10 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
                return;
 
        /* Collect firts the SW counters and then HW for consistency */
+       s->rx_packets           = 0;
+       s->rx_bytes             = 0;
+       s->tx_packets           = 0;
+       s->tx_bytes             = 0;
        s->tso_packets          = 0;
        s->tso_bytes            = 0;
        s->tx_queue_stopped     = 0;
@@ -155,6 +159,8 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
        for (i = 0; i < priv->params.num_channels; i++) {
                rq_stats = &priv->channel[i]->rq.stats;
 
+               s->rx_packets   += rq_stats->packets;
+               s->rx_bytes     += rq_stats->bytes;
                s->lro_packets  += rq_stats->lro_packets;
                s->lro_bytes    += rq_stats->lro_bytes;
                s->rx_csum_none += rq_stats->csum_none;
@@ -164,6 +170,8 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
                for (j = 0; j < priv->params.num_tc; j++) {
                        sq_stats = &priv->channel[i]->sq[j].stats;
 
+                       s->tx_packets           += sq_stats->packets;
+                       s->tx_bytes             += sq_stats->bytes;
                        s->tso_packets          += sq_stats->tso_packets;
                        s->tso_bytes            += sq_stats->tso_bytes;
                        s->tx_queue_stopped     += sq_stats->stopped;
@@ -225,23 +233,6 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
        s->tx_broadcast_bytes   =
                MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
 
-       s->rx_packets =
-               s->rx_unicast_packets +
-               s->rx_multicast_packets +
-               s->rx_broadcast_packets;
-       s->rx_bytes =
-               s->rx_unicast_bytes +
-               s->rx_multicast_bytes +
-               s->rx_broadcast_bytes;
-       s->tx_packets =
-               s->tx_unicast_packets +
-               s->tx_multicast_packets +
-               s->tx_broadcast_packets;
-       s->tx_bytes =
-               s->tx_unicast_bytes +
-               s->tx_multicast_bytes +
-               s->tx_broadcast_bytes;
-
        /* Update calculated offload counters */
        s->tx_csum_offload = s->tx_packets - tx_offload_none;
        s->rx_csum_good    = s->rx_packets - s->rx_csum_none -
@@ -1199,7 +1190,6 @@ static void mlx5e_fill_indir_rqt_rqns(struct mlx5e_priv *priv, void *rqtc)
                        ix = mlx5e_bits_invert(i, MLX5E_LOG_INDIR_RQT_SIZE);
 
                ix = priv->params.indirection_rqt[ix];
-               ix = ix % priv->params.num_channels;
                MLX5_SET(rqtc, rqtc, rq_num[i],
                         test_bit(MLX5E_STATE_OPENED, &priv->state) ?
                         priv->channel[ix]->rq.rqn :
@@ -1317,7 +1307,22 @@ static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
                              lro_timer_supported_periods[2]));
 }
 
-static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
+void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
+{
+       MLX5_SET(tirc, tirc, rx_hash_fn,
+                mlx5e_rx_hash_fn(priv->params.rss_hfunc));
+       if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
+               void *rss_key = MLX5_ADDR_OF(tirc, tirc,
+                                            rx_hash_toeplitz_key);
+               size_t len = MLX5_FLD_SZ_BYTES(tirc,
+                                              rx_hash_toeplitz_key);
+
+               MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
+               memcpy(rss_key, priv->params.toeplitz_hash_key, len);
+       }
+}
+
+static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
 
@@ -1325,6 +1330,7 @@ static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
        void *tirc;
        int inlen;
        int err;
+       int tt;
 
        inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
        in = mlx5_vzalloc(inlen);
@@ -1336,7 +1342,11 @@ static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
 
        mlx5e_build_tir_ctx_lro(tirc, priv);
 
-       err = mlx5_core_modify_tir(mdev, priv->tirn[tt], in, inlen);
+       for (tt = 0; tt < MLX5E_NUM_TT; tt++) {
+               err = mlx5_core_modify_tir(mdev, priv->tirn[tt], in, inlen);
+               if (err)
+                       break;
+       }
 
        kvfree(in);
 
@@ -1672,17 +1682,7 @@ static void mlx5e_build_tir_ctx(struct mlx5e_priv *priv, u32 *tirc, int tt)
        default:
                MLX5_SET(tirc, tirc, indirect_table,
                         priv->rqtn[MLX5E_INDIRECTION_RQT]);
-               MLX5_SET(tirc, tirc, rx_hash_fn,
-                        mlx5e_rx_hash_fn(priv->params.rss_hfunc));
-               if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
-                       void *rss_key = MLX5_ADDR_OF(tirc, tirc,
-                                                    rx_hash_toeplitz_key);
-                       size_t len = MLX5_FLD_SZ_BYTES(tirc,
-                                                      rx_hash_toeplitz_key);
-
-                       MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
-                       memcpy(rss_key, priv->params.toeplitz_hash_key, len);
-               }
+               mlx5e_build_tir_ctx_hash(tirc, priv);
                break;
        }
 
@@ -1885,8 +1885,10 @@ static int mlx5e_set_features(struct net_device *netdev,
                        mlx5e_close_locked(priv->netdev);
 
                priv->params.lro_en = !!(features & NETIF_F_LRO);
-               mlx5e_modify_tir_lro(priv, MLX5E_TT_IPV4_TCP);
-               mlx5e_modify_tir_lro(priv, MLX5E_TT_IPV6_TCP);
+               err = mlx5e_modify_tirs_lro(priv);
+               if (err)
+                       mlx5_core_warn(priv->mdev, "lro modify failed, %d\n",
+                                      err);
 
                if (was_opened)
                        err = mlx5e_open_locked(priv->netdev);
@@ -2089,12 +2091,20 @@ u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev)
               2 /*sizeof(mlx5e_tx_wqe.inline_hdr_start)*/;
 }
 
+void mlx5e_build_default_indir_rqt(u32 *indirection_rqt, int len,
+                                  int num_channels)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               indirection_rqt[i] = i % num_channels;
+}
+
 static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
                                    struct net_device *netdev,
                                    int num_channels)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-       int i;
 
        priv->params.log_sq_size           =
                MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
@@ -2118,8 +2128,8 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
        netdev_rss_key_fill(priv->params.toeplitz_hash_key,
                            sizeof(priv->params.toeplitz_hash_key));
 
-       for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
-               priv->params.indirection_rqt[i] = i % num_channels;
+       mlx5e_build_default_indir_rqt(priv->params.indirection_rqt,
+                                     MLX5E_INDIR_RQT_SIZE, num_channels);
 
        priv->params.lro_wqe_sz            =
                MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
index dd959d929aadd561ab78c252fe2127e1beb24fad..59658b9d05d1fc57c9da02f39f96a245929f42e4 100644 (file)
@@ -230,10 +230,6 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
        struct mlx5e_rq *rq = container_of(cq, struct mlx5e_rq, cq);
        int work_done;
 
-       /* avoid accessing cq (dma coherent memory) if not needed */
-       if (!test_and_clear_bit(MLX5E_CQ_HAS_CQES, &cq->flags))
-               return 0;
-
        for (work_done = 0; work_done < budget; work_done++) {
                struct mlx5e_rx_wqe *wqe;
                struct mlx5_cqe64 *cqe;
@@ -267,6 +263,7 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
 
                mlx5e_build_rx_skb(cqe, rq, skb);
                rq->stats.packets++;
+               rq->stats.bytes += be32_to_cpu(cqe->byte_cnt);
                napi_gro_receive(cq->napi, skb);
 
 wq_ll_pop:
@@ -279,8 +276,5 @@ wq_ll_pop:
        /* ensure cq space is freed before enabling more cqes */
        wmb();
 
-       if (work_done == budget)
-               set_bit(MLX5E_CQ_HAS_CQES, &cq->flags);
-
        return work_done;
 }
index 2c3fba0fff546179f68a53ab23fcdf7620ba188e..bb4eeeb007dec48eb022a6917f69d7fd5e1e5071 100644 (file)
@@ -179,6 +179,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
        unsigned int skb_len = skb->len;
        u8  opcode = MLX5_OPCODE_SEND;
        dma_addr_t dma_addr = 0;
+       unsigned int num_bytes;
        bool bf = false;
        u16 headlen;
        u16 ds_cnt;
@@ -204,8 +205,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
                opcode       = MLX5_OPCODE_LSO;
                ihs          = skb_transport_offset(skb) + tcp_hdrlen(skb);
                payload_len  = skb->len - ihs;
-               wi->num_bytes = skb->len +
-                               (skb_shinfo(skb)->gso_segs - 1) * ihs;
+               num_bytes = skb->len + (skb_shinfo(skb)->gso_segs - 1) * ihs;
                sq->stats.tso_packets++;
                sq->stats.tso_bytes += payload_len;
        } else {
@@ -213,9 +213,11 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
                     !skb->xmit_more &&
                     !skb_shinfo(skb)->nr_frags;
                ihs = mlx5e_get_inline_hdr_size(sq, skb, bf);
-               wi->num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN);
+               num_bytes = max_t(unsigned int, skb->len, ETH_ZLEN);
        }
 
+       wi->num_bytes = num_bytes;
+
        if (skb_vlan_tag_present(skb)) {
                mlx5e_insert_vlan(eseg->inline_hdr_start, skb, ihs, &skb_data,
                                  &skb_len);
@@ -307,6 +309,7 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
        sq->bf_budget = bf ? sq->bf_budget - 1 : 0;
 
        sq->stats.packets++;
+       sq->stats.bytes += num_bytes;
        return NETDEV_TX_OK;
 
 dma_unmap_wqe_err:
@@ -335,10 +338,6 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq)
        u16 sqcc;
        int i;
 
-       /* avoid accessing cq (dma coherent memory) if not needed */
-       if (!test_and_clear_bit(MLX5E_CQ_HAS_CQES, &cq->flags))
-               return false;
-
        sq = container_of(cq, struct mlx5e_sq, cq);
 
        npkts = 0;
@@ -422,10 +421,6 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq)
                                netif_tx_wake_queue(sq->txq);
                                sq->stats.wake++;
        }
-       if (i == MLX5E_TX_CQ_POLL_BUDGET) {
-               set_bit(MLX5E_CQ_HAS_CQES, &cq->flags);
-               return true;
-       }
 
-       return false;
+       return (i == MLX5E_TX_CQ_POLL_BUDGET);
 }
index 4ac8d716dbddfd9650d50c9c2af15efe7089a7d6..66d51a77609e890263cd91277c6b8e7315d660e3 100644 (file)
@@ -88,7 +88,6 @@ void mlx5e_completion_event(struct mlx5_core_cq *mcq)
 {
        struct mlx5e_cq *cq = container_of(mcq, struct mlx5e_cq, mcq);
 
-       set_bit(MLX5E_CQ_HAS_CQES, &cq->flags);
        set_bit(MLX5E_CHANNEL_NAPI_SCHED, &cq->channel->flags);
        barrier();
        napi_schedule(cq->napi);
index c071077aafbdb53ad959538b290b203f2256335e..7992c553c1f5ce2e4de9cec4caa798e0da676531 100644 (file)
@@ -215,7 +215,7 @@ mlxsw_pci_queue_elem_info_producer_get(struct mlxsw_pci_queue *q)
 {
        int index = q->producer_counter & (q->count - 1);
 
-       if ((q->producer_counter - q->consumer_counter) == q->count)
+       if ((u16) (q->producer_counter - q->consumer_counter) == q->count)
                return NULL;
        return mlxsw_pci_queue_elem_info_get(q, index);
 }
index 09ce451c283bb8dfb5dd9c4c69bdeb04c0e796b3..a94daa8c346ca11ca10f6eed09b0c15a28dde2c4 100644 (file)
@@ -2358,9 +2358,7 @@ static int mlxsw_sp_port_lag_leave(struct mlxsw_sp_port *mlxsw_sp_port,
        if (mlxsw_sp_port->bridged) {
                mlxsw_sp_port_active_vlans_del(mlxsw_sp_port);
                mlxsw_sp_port_bridge_leave(mlxsw_sp_port, false);
-
-               if (lag->ref_count == 1)
-                       mlxsw_sp_master_bridge_dec(mlxsw_sp, NULL);
+               mlxsw_sp_master_bridge_dec(mlxsw_sp, NULL);
        }
 
        if (lag->ref_count == 1) {
index 00cfd95ca59d53fe040ef5b002e7d30604d35e96..3e67f451f2ab918c95d7a6c3429d45b359e18978 100644 (file)
@@ -474,9 +474,9 @@ static int moxart_mac_probe(struct platform_device *pdev)
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        ndev->base_addr = res->start;
        priv->base = devm_ioremap_resource(p_dev, res);
-       ret = IS_ERR(priv->base);
-       if (ret) {
+       if (IS_ERR(priv->base)) {
                dev_err(p_dev, "devm_ioremap_resource failed\n");
+               ret = PTR_ERR(priv->base);
                goto init_fail;
        }
 
index 689a4a5c8dcfc30fba2675e17293e98691648dd2..1ef03939d25f478356112fbe376ff79cfd1e8eaa 100644 (file)
@@ -811,7 +811,7 @@ qcaspi_netdev_setup(struct net_device *dev)
        dev->netdev_ops = &qcaspi_netdev_ops;
        qcaspi_set_ethtool_ops(dev);
        dev->watchdog_timeo = QCASPI_TX_TIMEOUT;
-       dev->flags = IFF_MULTICAST;
+       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->tx_queue_len = 100;
 
        qca = netdev_priv(dev);
index 537974cfd427091442acc9098a0a40535bbda431..dd2cf3738b738bdf5b21e73587c5ab9aeecbe3c7 100644 (file)
@@ -4933,8 +4933,6 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
                RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
                break;
        case RTL_GIGA_MAC_VER_40:
-               RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
-               break;
        case RTL_GIGA_MAC_VER_41:
        case RTL_GIGA_MAC_VER_42:
        case RTL_GIGA_MAC_VER_43:
@@ -4943,8 +4941,6 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
        case RTL_GIGA_MAC_VER_46:
        case RTL_GIGA_MAC_VER_47:
        case RTL_GIGA_MAC_VER_48:
-               RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
-               break;
        case RTL_GIGA_MAC_VER_49:
        case RTL_GIGA_MAC_VER_50:
        case RTL_GIGA_MAC_VER_51:
@@ -7730,10 +7726,13 @@ rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
        void __iomem *ioaddr = tp->mmio_addr;
+       struct pci_dev *pdev = tp->pci_dev;
        struct rtl8169_counters *counters = tp->counters;
        unsigned int start;
 
-       if (netif_running(dev))
+       pm_runtime_get_noresume(&pdev->dev);
+
+       if (netif_running(dev) && pm_runtime_active(&pdev->dev))
                rtl8169_rx_missed(dev, ioaddr);
 
        do {
@@ -7761,7 +7760,8 @@ rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
         * Fetch additonal counter values missing in stats collected by driver
         * from tally counters.
         */
-       rtl8169_update_counters(dev);
+       if (pm_runtime_active(&pdev->dev))
+               rtl8169_update_counters(dev);
 
        /*
         * Subtract values fetched during initalization.
@@ -7774,6 +7774,8 @@ rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
        stats->tx_aborted_errors = le16_to_cpu(counters->tx_aborted) -
                le16_to_cpu(tp->tc_offset.tx_aborted);
 
+       pm_runtime_put_noidle(&pdev->dev);
+
        return stats;
 }
 
@@ -7853,6 +7855,10 @@ static int rtl8169_runtime_suspend(struct device *device)
 
        rtl8169_net_suspend(dev);
 
+       /* Update counters before going runtime suspend */
+       rtl8169_rx_missed(dev, tp->mmio_addr);
+       rtl8169_update_counters(dev);
+
        return 0;
 }
 
index 744d7806a9eec63e1c4fb18cc7b57fa96d73fcbc..86449c357168ebb4cd6c6fa25d1503583b8cd82d 100644 (file)
@@ -1722,7 +1722,6 @@ static int ravb_set_gti(struct net_device *ndev)
 static int ravb_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
-       const struct of_device_id *match;
        struct ravb_private *priv;
        enum ravb_chip_id chip_id;
        struct net_device *ndev;
@@ -1754,8 +1753,7 @@ static int ravb_probe(struct platform_device *pdev)
        ndev->base_addr = res->start;
        ndev->dma = -1;
 
-       match = of_match_device(of_match_ptr(ravb_match_table), &pdev->dev);
-       chip_id = (enum ravb_chip_id)match->data;
+       chip_id = (enum ravb_chip_id)of_device_get_match_data(&pdev->dev);
 
        if (chip_id == RCAR_GEN3)
                irq = platform_get_irq_byname(pdev, "ch22");
index dfa9e59c9442884dfe6a52a5c6df0c4c70fa4737..7384499928761612775af0f8b1eaf701fcbb4d18 100644 (file)
@@ -3061,15 +3061,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        mdp->ether_link_active_low = pd->ether_link_active_low;
 
        /* set cpu data */
-       if (id) {
+       if (id)
                mdp->cd = (struct sh_eth_cpu_data *)id->driver_data;
-       } else  {
-               const struct of_device_id *match;
+       else
+               mdp->cd = (struct sh_eth_cpu_data *)of_device_get_match_data(&pdev->dev);
 
-               match = of_match_device(of_match_ptr(sh_eth_match_table),
-                                       &pdev->dev);
-               mdp->cd = (struct sh_eth_cpu_data *)match->data;
-       }
        mdp->reg_offset = sh_eth_get_register_offset(mdp->cd->register_type);
        if (!mdp->reg_offset) {
                dev_err(&pdev->dev, "Unknown register type (%d)\n",
index 0faf1633603531a709358388b116d596d746e3e9..efb54f356a67c03e36856ed0047f5e3d9b2bf0f1 100644 (file)
@@ -199,21 +199,12 @@ int stmmac_mdio_register(struct net_device *ndev)
        struct stmmac_priv *priv = netdev_priv(ndev);
        struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
        int addr, found;
-       struct device_node *mdio_node = NULL;
-       struct device_node *child_node = NULL;
+       struct device_node *mdio_node = priv->plat->mdio_node;
 
        if (!mdio_bus_data)
                return 0;
 
        if (IS_ENABLED(CONFIG_OF)) {
-               for_each_child_of_node(priv->device->of_node, child_node) {
-                       if (of_device_is_compatible(child_node,
-                                                   "snps,dwmac-mdio")) {
-                               mdio_node = child_node;
-                               break;
-                       }
-               }
-
                if (mdio_node) {
                        netdev_dbg(ndev, "FOUND MDIO subnode\n");
                } else {
index 6a52fa18cbf2e94958bdfe44c4db258ababcdd02..4514ba73d96116317ca5ff8b797b037ae7434ffd 100644 (file)
@@ -110,6 +110,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
        struct device_node *np = pdev->dev.of_node;
        struct plat_stmmacenet_data *plat;
        struct stmmac_dma_cfg *dma_cfg;
+       struct device_node *child_node = NULL;
 
        plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
        if (!plat)
@@ -140,13 +141,19 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
                plat->phy_node = of_node_get(np);
        }
 
+       for_each_child_of_node(np, child_node)
+               if (of_device_is_compatible(child_node, "snps,dwmac-mdio")) {
+                       plat->mdio_node = child_node;
+                       break;
+               }
+
        /* "snps,phy-addr" is not a standard property. Mark it as deprecated
         * and warn of its use. Remove this when phy node support is added.
         */
        if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0)
                dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
 
-       if ((plat->phy_node && !of_phy_is_fixed_link(np)) || plat->phy_bus_name)
+       if ((plat->phy_node && !of_phy_is_fixed_link(np)) || !plat->mdio_node)
                plat->mdio_bus_data = NULL;
        else
                plat->mdio_bus_data =
index e23a642357e7c01d7010ae070b47632b3a926ba9..2437227712dcd0ee5fd0404113e35527646a8b76 100644 (file)
@@ -51,7 +51,6 @@
 #endif
 
 #ifdef CONFIG_PPC_PMAC
-#include <asm/pci-bridge.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
index fc8bbff2d7e37ec19d807008c1e9b70040551ea2..af11ed1e0bcc09b4ed4fa5e94df8945fab4d581e 100644 (file)
 #define DWC_MMC_RXOCTETCOUNT_GB          0x0784
 #define DWC_MMC_RXPACKETCOUNT_GB         0x0780
 
-static int debug = 3;
+static int debug = -1;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "DWC_eth_qos debug level (0=none,...,16=all)");
 
@@ -650,6 +650,11 @@ struct net_local {
        u32 mmc_tx_counters_mask;
 
        struct dwceqos_flowcontrol flowcontrol;
+
+       /* Tracks the intermediate state of phy started but hardware
+        * init not finished yet.
+        */
+       bool phy_defer;
 };
 
 static void dwceqos_read_mmc_counters(struct net_local *lp, u32 rx_mask,
@@ -901,6 +906,9 @@ static void dwceqos_adjust_link(struct net_device *ndev)
        struct phy_device *phydev = lp->phy_dev;
        int status_change = 0;
 
+       if (lp->phy_defer)
+               return;
+
        if (phydev->link) {
                if ((lp->speed != phydev->speed) ||
                    (lp->duplex != phydev->duplex)) {
@@ -1113,7 +1121,7 @@ static int dwceqos_descriptor_init(struct net_local *lp)
        /* Allocate DMA descriptors */
        size = DWCEQOS_RX_DCNT * sizeof(struct dwceqos_dma_desc);
        lp->rx_descs = dma_alloc_coherent(lp->ndev->dev.parent, size,
-                       &lp->rx_descs_addr, 0);
+                       &lp->rx_descs_addr, GFP_KERNEL);
        if (!lp->rx_descs)
                goto err_out;
        lp->rx_descs_tail_addr = lp->rx_descs_addr +
@@ -1121,7 +1129,7 @@ static int dwceqos_descriptor_init(struct net_local *lp)
 
        size = DWCEQOS_TX_DCNT * sizeof(struct dwceqos_dma_desc);
        lp->tx_descs = dma_alloc_coherent(lp->ndev->dev.parent, size,
-                       &lp->tx_descs_addr, 0);
+                       &lp->tx_descs_addr, GFP_KERNEL);
        if (!lp->tx_descs)
                goto err_out;
        lp->tx_descs_tail_addr = lp->tx_descs_addr +
@@ -1635,6 +1643,12 @@ static void dwceqos_init_hw(struct net_local *lp)
        regval = dwceqos_read(lp, REG_DWCEQOS_MAC_CFG);
        dwceqos_write(lp, REG_DWCEQOS_MAC_CFG,
                      regval | DWCEQOS_MAC_CFG_TE | DWCEQOS_MAC_CFG_RE);
+
+       lp->phy_defer = false;
+       mutex_lock(&lp->phy_dev->lock);
+       phy_read_status(lp->phy_dev);
+       dwceqos_adjust_link(lp->ndev);
+       mutex_unlock(&lp->phy_dev->lock);
 }
 
 static void dwceqos_tx_reclaim(unsigned long data)
@@ -1880,9 +1894,13 @@ static int dwceqos_open(struct net_device *ndev)
        }
        netdev_reset_queue(ndev);
 
+       /* The dwceqos reset state machine requires all phy clocks to complete,
+        * hence the unusual init order with phy_start first.
+        */
+       lp->phy_defer = true;
+       phy_start(lp->phy_dev);
        dwceqos_init_hw(lp);
        napi_enable(&lp->napi);
-       phy_start(lp->phy_dev);
 
        netif_start_queue(ndev);
        tasklet_enable(&lp->tx_bdreclaim_tasklet);
@@ -1915,18 +1933,19 @@ static int dwceqos_stop(struct net_device *ndev)
 {
        struct net_local *lp = netdev_priv(ndev);
 
-       phy_stop(lp->phy_dev);
-
        tasklet_disable(&lp->tx_bdreclaim_tasklet);
-       netif_stop_queue(ndev);
        napi_disable(&lp->napi);
 
-       dwceqos_drain_dma(lp);
+       /* Stop all tx before we drain the tx dma. */
+       netif_tx_lock_bh(lp->ndev);
+       netif_stop_queue(ndev);
+       netif_tx_unlock_bh(lp->ndev);
 
-       netif_tx_lock(lp->ndev);
+       dwceqos_drain_dma(lp);
        dwceqos_reset_hw(lp);
+       phy_stop(lp->phy_dev);
+
        dwceqos_descriptor_free(lp);
-       netif_tx_unlock(lp->ndev);
 
        return 0;
 }
@@ -2178,12 +2197,10 @@ static int dwceqos_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                ((trans.initial_descriptor + trans.nr_descriptors) %
                 DWCEQOS_TX_DCNT));
 
-       dwceqos_tx_finalize(skb, lp, &trans);
-
-       netdev_sent_queue(ndev, skb->len);
-
        spin_lock_bh(&lp->tx_lock);
        lp->tx_free -= trans.nr_descriptors;
+       dwceqos_tx_finalize(skb, lp, &trans);
+       netdev_sent_queue(ndev, skb->len);
        spin_unlock_bh(&lp->tx_lock);
 
        ndev->trans_start = jiffies;
index 3c54a2cae5dfd09e066205b945ae937a3cfabaee..67610270d171a69d5e1ecf5e0c027fe98d053bba 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
-#include <asm/pci-bridge.h>
 #include <net/checksum.h>
 
 #include "spider_net.h"
index 03833dbfca67d1ab53ca1af42398e7ea9dd04f01..dc85f7095e51038c0ebbb1182ba0d169ec0b2dd7 100644 (file)
@@ -297,6 +297,17 @@ static int kszphy_config_init(struct phy_device *phydev)
        if (priv->led_mode >= 0)
                kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode);
 
+       if (phy_interrupt_is_valid(phydev)) {
+               int ctl = phy_read(phydev, MII_BMCR);
+
+               if (ctl < 0)
+                       return ctl;
+
+               ret = phy_write(phydev, MII_BMCR, ctl & ~BMCR_ANENABLE);
+               if (ret < 0)
+                       return ret;
+       }
+
        return 0;
 }
 
@@ -635,6 +646,21 @@ static void kszphy_get_stats(struct phy_device *phydev,
                data[i] = kszphy_get_stat(phydev, i);
 }
 
+static int kszphy_resume(struct phy_device *phydev)
+{
+       int value;
+
+       mutex_lock(&phydev->lock);
+
+       value = phy_read(phydev, MII_BMCR);
+       phy_write(phydev, MII_BMCR, value & ~BMCR_PDOWN);
+
+       kszphy_config_intr(phydev);
+       mutex_unlock(&phydev->lock);
+
+       return 0;
+}
+
 static int kszphy_probe(struct phy_device *phydev)
 {
        const struct kszphy_type *type = phydev->drv->driver_data;
@@ -844,7 +870,7 @@ static struct phy_driver ksphy_driver[] = {
        .get_strings    = kszphy_get_strings,
        .get_stats      = kszphy_get_stats,
        .suspend        = genphy_suspend,
-       .resume         = genphy_resume,
+       .resume         = kszphy_resume,
 }, {
        .phy_id         = PHY_ID_KSZ8061,
        .name           = "Micrel KSZ8061",
index fc8ad001bc949e894e7659301af65565a5a21046..d61da9ece3ba021a7aa68253efe8dd82198cb575 100644 (file)
@@ -443,9 +443,14 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
                         * network traffic (demand mode).
                         */
                        struct ppp *ppp = PF_TO_PPP(pf);
+
+                       ppp_recv_lock(ppp);
                        if (ppp->n_channels == 0 &&
-                           (ppp->flags & SC_LOOP_TRAFFIC) == 0)
+                           (ppp->flags & SC_LOOP_TRAFFIC) == 0) {
+                               ppp_recv_unlock(ppp);
                                break;
+                       }
+                       ppp_recv_unlock(ppp);
                }
                ret = -EAGAIN;
                if (file->f_flags & O_NONBLOCK)
@@ -532,9 +537,12 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait)
        else if (pf->kind == INTERFACE) {
                /* see comment in ppp_read */
                struct ppp *ppp = PF_TO_PPP(pf);
+
+               ppp_recv_lock(ppp);
                if (ppp->n_channels == 0 &&
                    (ppp->flags & SC_LOOP_TRAFFIC) == 0)
                        mask |= POLLIN | POLLRDNORM;
+               ppp_recv_unlock(ppp);
        }
 
        return mask;
@@ -2808,6 +2816,7 @@ static struct ppp *ppp_create_interface(struct net *net, int unit,
 
 out2:
        mutex_unlock(&pn->all_ppp_mutex);
+       rtnl_unlock();
        free_netdev(dev);
 out1:
        *retp = ret;
index 224e7d82de6d2552121a2af643ea57d927e5b05b..cf77f2dffa698fa8399f5ae7b04162be8a1b34fe 100644 (file)
@@ -134,7 +134,6 @@ static void ax88172a_remove_mdio(struct usbnet *dev)
 
        netdev_info(dev->net, "deregistering mdio bus %s\n", priv->mdio->id);
        mdiobus_unregister(priv->mdio);
-       kfree(priv->mdio->irq);
        mdiobus_free(priv->mdio);
 }
 
index dc0212c3cc28cc36267d62cfebe726f51fe0c910..86ba30ba35e8fcf45f9eba287334da04b54203e2 100644 (file)
@@ -837,7 +837,11 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
 
        iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
 
-       /* reset data interface */
+       /* Reset data interface. Some devices will not reset properly
+        * unless they are configured first.  Toggle the altsetting to
+        * force a reset
+        */
+       usb_set_interface(dev->udev, iface_no, data_altsetting);
        temp = usb_set_interface(dev->udev, iface_no, 0);
        if (temp) {
                dev_dbg(&intf->dev, "set interface failed\n");
@@ -984,8 +988,6 @@ EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting);
 
 static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-       int ret;
-
        /* MBIM backwards compatible function? */
        if (cdc_ncm_select_altsetting(intf) != CDC_NCM_COMM_ALTSETTING_NCM)
                return -ENODEV;
@@ -994,16 +996,7 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
         * Additionally, generic NCM devices are assumed to accept arbitrarily
         * placed NDP.
         */
-       ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM, 0);
-
-       /*
-        * We should get an event when network connection is "connected" or
-        * "disconnected". Set network connection in "disconnected" state
-        * (carrier is OFF) during attach, so the IP network stack does not
-        * start IPv6 negotiation and more.
-        */
-       usbnet_link_change(dev, 0, 0);
-       return ret;
+       return cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM, 0);
 }
 
 static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max)
@@ -1586,7 +1579,8 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
 
 static const struct driver_info cdc_ncm_info = {
        .description = "CDC NCM",
-       .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET,
+       .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
+                       | FLAG_LINK_INTR,
        .bind = cdc_ncm_bind,
        .unbind = cdc_ncm_unbind,
        .manage_power = usbnet_manage_power,
@@ -1599,7 +1593,7 @@ static const struct driver_info cdc_ncm_info = {
 static const struct driver_info wwan_info = {
        .description = "Mobile Broadband Network Device",
        .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
-                       | FLAG_WWAN,
+                       | FLAG_LINK_INTR | FLAG_WWAN,
        .bind = cdc_ncm_bind,
        .unbind = cdc_ncm_unbind,
        .manage_power = usbnet_manage_power,
@@ -1612,7 +1606,7 @@ static const struct driver_info wwan_info = {
 static const struct driver_info wwan_noarp_info = {
        .description = "Mobile Broadband Network Device (NO ARP)",
        .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
-                       | FLAG_WWAN | FLAG_NOARP,
+                       | FLAG_LINK_INTR | FLAG_WWAN | FLAG_NOARP,
        .bind = cdc_ncm_bind,
        .unbind = cdc_ncm_unbind,
        .manage_power = usbnet_manage_power,
index 570deef53f74301896cfbb8e2ca5c622a5b67185..a3a4ccf7cf5272530ac8addf182c479feffd47fc 100644 (file)
@@ -861,8 +861,10 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1199, 0x9056, 8)},    /* Sierra Wireless Modem */
        {QMI_FIXED_INTF(0x1199, 0x9057, 8)},
        {QMI_FIXED_INTF(0x1199, 0x9061, 8)},    /* Sierra Wireless Modem */
-       {QMI_FIXED_INTF(0x1199, 0x9071, 8)},    /* Sierra Wireless MC74xx/EM74xx */
-       {QMI_FIXED_INTF(0x1199, 0x9071, 10)},   /* Sierra Wireless MC74xx/EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9071, 8)},    /* Sierra Wireless MC74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9071, 10)},   /* Sierra Wireless MC74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9079, 8)},    /* Sierra Wireless EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9079, 10)},   /* Sierra Wireless EM74xx */
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
        {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},    /* Alcatel L800MA */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
@@ -885,6 +887,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x413c, 0x81a8, 8)},    /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
        {QMI_FIXED_INTF(0x413c, 0x81a9, 8)},    /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
        {QMI_FIXED_INTF(0x413c, 0x81b1, 8)},    /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
+       {QMI_FIXED_INTF(0x413c, 0x81b3, 8)},    /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
        {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},    /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
        {QMI_FIXED_INTF(0x22de, 0x9061, 3)},    /* WeTelecom WPD-600N */
        {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)},    /* SIMCom 7230E */
index 0b0ba7ef14e4e9054adeb1251c29cddba08c5187..10798128c03fc64881c5a437df3510f016461b7c 100644 (file)
@@ -1769,6 +1769,13 @@ out3:
        if (info->unbind)
                info->unbind (dev, udev);
 out1:
+       /* subdrivers must undo all they did in bind() if they
+        * fail it, but we may fail later and a deferred kevent
+        * may trigger an error resubmitting itself and, worse,
+        * schedule a timer. So we kill it all just in case.
+        */
+       cancel_work_sync(&dev->kevent);
+       del_timer_sync(&dev->delay);
        free_netdev(net);
 out:
        return status;
index 0cbf520cea778fc703c9657ab2d085eee522634b..fc895d0e85d9cafced5d7e9d1166e8bc0de833bd 100644 (file)
@@ -814,7 +814,7 @@ vmxnet3_tq_init_all(struct vmxnet3_adapter *adapter)
 
 
 /*
- *    parse and copy relevant protocol headers:
+ *    parse relevant protocol headers:
  *      For a tso pkt, relevant headers are L2/3/4 including options
  *      For a pkt requesting csum offloading, they are L2/3 and may include L4
  *      if it's a TCP/UDP pkt
@@ -827,15 +827,14 @@ vmxnet3_tq_init_all(struct vmxnet3_adapter *adapter)
  * Other effects:
  *    1. related *ctx fields are updated.
  *    2. ctx->copy_size is # of bytes copied
- *    3. the portion copied is guaranteed to be in the linear part
+ *    3. the portion to be copied is guaranteed to be in the linear part
  *
  */
 static int
-vmxnet3_parse_and_copy_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
-                          struct vmxnet3_tx_ctx *ctx,
-                          struct vmxnet3_adapter *adapter)
+vmxnet3_parse_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
+                 struct vmxnet3_tx_ctx *ctx,
+                 struct vmxnet3_adapter *adapter)
 {
-       struct Vmxnet3_TxDataDesc *tdd;
        u8 protocol = 0;
 
        if (ctx->mss) { /* TSO */
@@ -892,16 +891,34 @@ vmxnet3_parse_and_copy_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
                return 0;
        }
 
+       return 1;
+err:
+       return -1;
+}
+
+/*
+ *    copy relevant protocol headers to the transmit ring:
+ *      For a tso pkt, relevant headers are L2/3/4 including options
+ *      For a pkt requesting csum offloading, they are L2/3 and may include L4
+ *      if it's a TCP/UDP pkt
+ *
+ *
+ *    Note that this requires that vmxnet3_parse_hdr be called first to set the
+ *      appropriate bits in ctx first
+ */
+static void
+vmxnet3_copy_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
+                struct vmxnet3_tx_ctx *ctx,
+                struct vmxnet3_adapter *adapter)
+{
+       struct Vmxnet3_TxDataDesc *tdd;
+
        tdd = tq->data_ring.base + tq->tx_ring.next2fill;
 
        memcpy(tdd->data, skb->data, ctx->copy_size);
        netdev_dbg(adapter->netdev,
                "copy %u bytes to dataRing[%u]\n",
                ctx->copy_size, tq->tx_ring.next2fill);
-       return 1;
-
-err:
-       return -1;
 }
 
 
@@ -998,22 +1015,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
                }
        }
 
-       spin_lock_irqsave(&tq->tx_lock, flags);
-
-       if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) {
-               tq->stats.tx_ring_full++;
-               netdev_dbg(adapter->netdev,
-                       "tx queue stopped on %s, next2comp %u"
-                       " next2fill %u\n", adapter->netdev->name,
-                       tq->tx_ring.next2comp, tq->tx_ring.next2fill);
-
-               vmxnet3_tq_stop(tq, adapter);
-               spin_unlock_irqrestore(&tq->tx_lock, flags);
-               return NETDEV_TX_BUSY;
-       }
-
-
-       ret = vmxnet3_parse_and_copy_hdr(skb, tq, &ctx, adapter);
+       ret = vmxnet3_parse_hdr(skb, tq, &ctx, adapter);
        if (ret >= 0) {
                BUG_ON(ret <= 0 && ctx.copy_size != 0);
                /* hdrs parsed, check against other limits */
@@ -1033,9 +1035,26 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
                }
        } else {
                tq->stats.drop_hdr_inspect_err++;
-               goto unlock_drop_pkt;
+               goto drop_pkt;
        }
 
+       spin_lock_irqsave(&tq->tx_lock, flags);
+
+       if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) {
+               tq->stats.tx_ring_full++;
+               netdev_dbg(adapter->netdev,
+                       "tx queue stopped on %s, next2comp %u"
+                       " next2fill %u\n", adapter->netdev->name,
+                       tq->tx_ring.next2comp, tq->tx_ring.next2fill);
+
+               vmxnet3_tq_stop(tq, adapter);
+               spin_unlock_irqrestore(&tq->tx_lock, flags);
+               return NETDEV_TX_BUSY;
+       }
+
+
+       vmxnet3_copy_hdr(skb, tq, &ctx, adapter);
+
        /* fill tx descs related to addr & len */
        if (vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter))
                goto unlock_drop_pkt;
index 66addb7a7911beb33f17c916caa7bb48ae84507e..bdcf617a9d52b86eb41c13dad6df1c3c42d3d319 100644 (file)
@@ -104,20 +104,23 @@ static struct dst_ops vrf_dst_ops = {
 #if IS_ENABLED(CONFIG_IPV6)
 static bool check_ipv6_frame(const struct sk_buff *skb)
 {
-       const struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->data;
-       size_t hlen = sizeof(*ipv6h);
+       const struct ipv6hdr *ipv6h;
+       struct ipv6hdr _ipv6h;
        bool rc = true;
 
-       if (skb->len < hlen)
+       ipv6h = skb_header_pointer(skb, 0, sizeof(_ipv6h), &_ipv6h);
+       if (!ipv6h)
                goto out;
 
        if (ipv6h->nexthdr == NEXTHDR_ICMP) {
                const struct icmp6hdr *icmph;
+               struct icmp6hdr _icmph;
 
-               if (skb->len < hlen + sizeof(*icmph))
+               icmph = skb_header_pointer(skb, sizeof(_ipv6h),
+                                          sizeof(_icmph), &_icmph);
+               if (!icmph)
                        goto out;
 
-               icmph = (struct icmp6hdr *)(skb->data + sizeof(*ipv6h));
                switch (icmph->icmp6_type) {
                case NDISC_ROUTER_SOLICITATION:
                case NDISC_ROUTER_ADVERTISEMENT:
index e6944b29588e1bd329c5b331988373d5297c0bd6..1c32bd10479730a73f2832fa7f15ef3d845941db 100644 (file)
@@ -931,8 +931,10 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
                                                     cb->nlh->nlmsg_seq,
                                                     RTM_NEWNEIGH,
                                                     NLM_F_MULTI, rd);
-                               if (err < 0)
+                               if (err < 0) {
+                                       cb->args[1] = err;
                                        goto out;
+                               }
 skip:
                                ++idx;
                        }
@@ -1306,8 +1308,10 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                gbp = (struct vxlanhdr_gbp *)vxh;
                md->gbp = ntohs(gbp->policy_id);
 
-               if (tun_dst)
+               if (tun_dst) {
                        tun_dst->u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT;
+                       tun_dst->u.tun_info.options_len = sizeof(*md);
+               }
 
                if (gbp->dont_learn)
                        md->gbp |= VXLAN_GBP_DONT_LEARN;
index 4ed5180c547bb6ce8af288a6653220b5cf2c61b4..0ccc697fef76cf25c94443c4cde9d0fb1185df05 100644 (file)
@@ -107,7 +107,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
                                    sizeof(tx_ant_cmd), &tx_ant_cmd);
 }
 
-static void iwl_free_fw_paging(struct iwl_mvm *mvm)
+void iwl_free_fw_paging(struct iwl_mvm *mvm)
 {
        int i;
 
@@ -127,6 +127,8 @@ static void iwl_free_fw_paging(struct iwl_mvm *mvm)
                             get_order(mvm->fw_paging_db[i].fw_paging_size));
        }
        kfree(mvm->trans->paging_download_buf);
+       mvm->trans->paging_download_buf = NULL;
+
        memset(mvm->fw_paging_db, 0, sizeof(mvm->fw_paging_db));
 }
 
index 5f3ac8cccf49d2c5a07644f894b1ba920dca8bfc..ff7c6df9f9418ebac294709f63c21911459cfac1 100644 (file)
@@ -1225,6 +1225,9 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
 void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
                                              struct iwl_rx_cmd_buffer *rxb);
 
+/* Paging */
+void iwl_free_fw_paging(struct iwl_mvm *mvm);
+
 /* MVM debugfs */
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
index 89ea70deeb84410edd0e3ad07ae77abc08476107..e80be9a595207bcf962551cc2bde42d14b898a03 100644 (file)
@@ -684,6 +684,8 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
        for (i = 0; i < NVM_MAX_NUM_SECTIONS; i++)
                kfree(mvm->nvm_sections[i].data);
 
+       iwl_free_fw_paging(mvm);
+
        iwl_mvm_tof_clean(mvm);
 
        ieee80211_free_hw(mvm->hw);
index 0914ec2fd57467023b0f5336b2e630856c06cf81..a040edc550570a11373ed30b4916b7930c7fa832 100644 (file)
@@ -423,6 +423,15 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
                return -1;
        }
 
+       /*
+        * Increase the pending frames counter, so that later when a reply comes
+        * in and the counter is decreased - we don't start getting negative
+        * values.
+        * Note that we don't need to make sure it isn't agg'd, since we're
+        * TXing non-sta
+        */
+       atomic_inc(&mvm->pending_frames[sta_id]);
+
        return 0;
 }
 
index 7e2c43f701bc451463c5273ed3a5a1e49f6be15f..5d28e9405f32fb96dc79049d5cc4dbca01af14c3 100644 (file)
@@ -382,18 +382,18 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = {
        [ND_CMD_ARS_CAP] = {
                .in_num = 2,
                .in_sizes = { 8, 8, },
-               .out_num = 2,
-               .out_sizes = { 4, 4, },
+               .out_num = 4,
+               .out_sizes = { 4, 4, 4, 4, },
        },
        [ND_CMD_ARS_START] = {
-               .in_num = 4,
-               .in_sizes = { 8, 8, 2, 6, },
-               .out_num = 1,
-               .out_sizes = { 4, },
+               .in_num = 5,
+               .in_sizes = { 8, 8, 2, 1, 5, },
+               .out_num = 2,
+               .out_sizes = { 4, 4, },
        },
        [ND_CMD_ARS_STATUS] = {
-               .out_num = 2,
-               .out_sizes = { 4, UINT_MAX, },
+               .out_num = 3,
+               .out_sizes = { 4, 4, UINT_MAX, },
        },
 };
 
@@ -442,8 +442,8 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
                return in_field[1];
        else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2)
                return out_field[1];
-       else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 1)
-               return ND_CMD_ARS_STATUS_MAX;
+       else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2)
+               return out_field[1] - 8;
 
        return UINT_MAX;
 }
index b0045a505dc88c9ef56dcc1094a198bd011d24a7..95825b38559addb8a0dc5cca22bc305e228e65f6 100644 (file)
@@ -55,7 +55,7 @@ static int e820_pmem_probe(struct platform_device *pdev)
        for (p = iomem_resource.child; p ; p = p->sibling) {
                struct nd_region_desc ndr_desc;
 
-               if (strncmp(p->name, "Persistent Memory (legacy)", 26) != 0)
+               if (p->desc != IORES_DESC_PERSISTENT_MEMORY_LEGACY)
                        continue;
 
                memset(&ndr_desc, 0, sizeof(ndr_desc));
index 7edf31671dabed8f8d193806f54f3d1b30401e7c..8d0b546701848eb2b57d87b7207490133e5c32a9 100644 (file)
@@ -41,7 +41,7 @@ struct pmem_device {
        phys_addr_t             phys_addr;
        /* when non-zero this device is hosting a 'pfn' instance */
        phys_addr_t             data_offset;
-       unsigned long           pfn_flags;
+       u64                     pfn_flags;
        void __pmem             *virt_addr;
        size_t                  size;
        struct badblocks        bb;
index 3cd921e6121ec310f664398ad05b3b3171a38cee..03c46412fff4d602477239d0672cbdeb54c13dfb 100644 (file)
@@ -55,8 +55,9 @@ static void nvme_free_ns(struct kref *kref)
        ns->disk->private_data = NULL;
        spin_unlock(&dev_list_lock);
 
-       nvme_put_ctrl(ns->ctrl);
        put_disk(ns->disk);
+       ida_simple_remove(&ns->ctrl->ns_ida, ns->instance);
+       nvme_put_ctrl(ns->ctrl);
        kfree(ns);
 }
 
@@ -183,7 +184,7 @@ int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd,
                        goto out_unmap;
                }
 
-               if (meta_buffer) {
+               if (meta_buffer && meta_len) {
                        struct bio_integrity_payload *bip;
 
                        meta = kmalloc(meta_len, GFP_KERNEL);
@@ -373,6 +374,8 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
 
        if (copy_from_user(&io, uio, sizeof(io)))
                return -EFAULT;
+       if (io.flags)
+               return -EINVAL;
 
        switch (io.opcode) {
        case nvme_cmd_write:
@@ -424,6 +427,8 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
                return -EACCES;
        if (copy_from_user(&cmd, ucmd, sizeof(cmd)))
                return -EFAULT;
+       if (cmd.flags)
+               return -EINVAL;
 
        memset(&c, 0, sizeof(c));
        c.common.opcode = cmd.opcode;
@@ -556,6 +561,10 @@ static int nvme_revalidate_disk(struct gendisk *disk)
        u16 old_ms;
        unsigned short bs;
 
+       if (test_bit(NVME_NS_DEAD, &ns->flags)) {
+               set_capacity(disk, 0);
+               return -ENODEV;
+       }
        if (nvme_identify_ns(ns->ctrl, ns->ns_id, &id)) {
                dev_warn(ns->ctrl->dev, "%s: Identify failure nvme%dn%d\n",
                                __func__, ns->ctrl->instance, ns->ns_id);
@@ -831,6 +840,23 @@ int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl)
        return ret;
 }
 
+static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,
+               struct request_queue *q)
+{
+       if (ctrl->max_hw_sectors) {
+               u32 max_segments =
+                       (ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1;
+
+               blk_queue_max_hw_sectors(q, ctrl->max_hw_sectors);
+               blk_queue_max_segments(q, min_t(u32, max_segments, USHRT_MAX));
+       }
+       if (ctrl->stripe_size)
+               blk_queue_chunk_sectors(q, ctrl->stripe_size >> 9);
+       if (ctrl->vwc & NVME_CTRL_VWC_PRESENT)
+               blk_queue_flush(q, REQ_FLUSH | REQ_FUA);
+       blk_queue_virt_boundary(q, ctrl->page_size - 1);
+}
+
 /*
  * Initialize the cached copies of the Identify data and various controller
  * register in our nvme_ctrl structure.  This should be called as soon as
@@ -888,6 +914,8 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                }
        }
 
+       nvme_set_queue_limits(ctrl, ctrl->admin_q);
+
        kfree(id);
        return 0;
 }
@@ -1118,9 +1146,13 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        if (!ns)
                return;
 
+       ns->instance = ida_simple_get(&ctrl->ns_ida, 1, 0, GFP_KERNEL);
+       if (ns->instance < 0)
+               goto out_free_ns;
+
        ns->queue = blk_mq_init_queue(ctrl->tagset);
        if (IS_ERR(ns->queue))
-               goto out_free_ns;
+               goto out_release_instance;
        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, ns->queue);
        ns->queue->queuedata = ns;
        ns->ctrl = ctrl;
@@ -1134,17 +1166,9 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        ns->disk = disk;
        ns->lba_shift = 9; /* set to a default value for 512 until disk is validated */
 
+
        blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
-       if (ctrl->max_hw_sectors) {
-               blk_queue_max_hw_sectors(ns->queue, ctrl->max_hw_sectors);
-               blk_queue_max_segments(ns->queue,
-                       (ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1);
-       }
-       if (ctrl->stripe_size)
-               blk_queue_chunk_sectors(ns->queue, ctrl->stripe_size >> 9);
-       if (ctrl->vwc & NVME_CTRL_VWC_PRESENT)
-               blk_queue_flush(ns->queue, REQ_FLUSH | REQ_FUA);
-       blk_queue_virt_boundary(ns->queue, ctrl->page_size - 1);
+       nvme_set_queue_limits(ctrl, ns->queue);
 
        disk->major = nvme_major;
        disk->first_minor = 0;
@@ -1153,7 +1177,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        disk->queue = ns->queue;
        disk->driverfs_dev = ctrl->device;
        disk->flags = GENHD_FL_EXT_DEVT;
-       sprintf(disk->disk_name, "nvme%dn%d", ctrl->instance, nsid);
+       sprintf(disk->disk_name, "nvme%dn%d", ctrl->instance, ns->instance);
 
        if (nvme_revalidate_disk(ns->disk))
                goto out_free_disk;
@@ -1173,40 +1197,29 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
        kfree(disk);
  out_free_queue:
        blk_cleanup_queue(ns->queue);
+ out_release_instance:
+       ida_simple_remove(&ctrl->ns_ida, ns->instance);
  out_free_ns:
        kfree(ns);
 }
 
 static void nvme_ns_remove(struct nvme_ns *ns)
 {
-       bool kill = nvme_io_incapable(ns->ctrl) &&
-                       !blk_queue_dying(ns->queue);
-
-       lockdep_assert_held(&ns->ctrl->namespaces_mutex);
-
-       if (kill) {
-               blk_set_queue_dying(ns->queue);
+       if (test_and_set_bit(NVME_NS_REMOVING, &ns->flags))
+               return;
 
-               /*
-                * The controller was shutdown first if we got here through
-                * device removal. The shutdown may requeue outstanding
-                * requests. These need to be aborted immediately so
-                * del_gendisk doesn't block indefinitely for their completion.
-                */
-               blk_mq_abort_requeue_list(ns->queue);
-       }
        if (ns->disk->flags & GENHD_FL_UP) {
                if (blk_get_integrity(ns->disk))
                        blk_integrity_unregister(ns->disk);
                sysfs_remove_group(&disk_to_dev(ns->disk)->kobj,
                                        &nvme_ns_attr_group);
                del_gendisk(ns->disk);
-       }
-       if (kill || !blk_queue_dying(ns->queue)) {
                blk_mq_abort_requeue_list(ns->queue);
                blk_cleanup_queue(ns->queue);
        }
+       mutex_lock(&ns->ctrl->namespaces_mutex);
        list_del_init(&ns->list);
+       mutex_unlock(&ns->ctrl->namespaces_mutex);
        nvme_put_ns(ns);
 }
 
@@ -1300,10 +1313,8 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
 {
        struct nvme_ns *ns, *next;
 
-       mutex_lock(&ctrl->namespaces_mutex);
        list_for_each_entry_safe(ns, next, &ctrl->namespaces, list)
                nvme_ns_remove(ns);
-       mutex_unlock(&ctrl->namespaces_mutex);
 }
 
 static DEFINE_IDA(nvme_instance_ida);
@@ -1350,6 +1361,7 @@ static void nvme_free_ctrl(struct kref *kref)
 
        put_device(ctrl->device);
        nvme_release_instance(ctrl);
+       ida_destroy(&ctrl->ns_ida);
 
        ctrl->ops->free_ctrl(ctrl);
 }
@@ -1390,6 +1402,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
        }
        get_device(ctrl->device);
        dev_set_drvdata(ctrl->device, ctrl);
+       ida_init(&ctrl->ns_ida);
 
        spin_lock(&dev_list_lock);
        list_add_tail(&ctrl->node, &nvme_ctrl_list);
@@ -1402,6 +1415,38 @@ out:
        return ret;
 }
 
+/**
+ * nvme_kill_queues(): Ends all namespace queues
+ * @ctrl: the dead controller that needs to end
+ *
+ * Call this function when the driver determines it is unable to get the
+ * controller in a state capable of servicing IO.
+ */
+void nvme_kill_queues(struct nvme_ctrl *ctrl)
+{
+       struct nvme_ns *ns;
+
+       mutex_lock(&ctrl->namespaces_mutex);
+       list_for_each_entry(ns, &ctrl->namespaces, list) {
+               if (!kref_get_unless_zero(&ns->kref))
+                       continue;
+
+               /*
+                * Revalidating a dead namespace sets capacity to 0. This will
+                * end buffered writers dirtying pages that can't be synced.
+                */
+               if (!test_and_set_bit(NVME_NS_DEAD, &ns->flags))
+                       revalidate_disk(ns->disk);
+
+               blk_set_queue_dying(ns->queue);
+               blk_mq_abort_requeue_list(ns->queue);
+               blk_mq_start_stopped_hw_queues(ns->queue, true);
+
+               nvme_put_ns(ns);
+       }
+       mutex_unlock(&ctrl->namespaces_mutex);
+}
+
 void nvme_stop_queues(struct nvme_ctrl *ctrl)
 {
        struct nvme_ns *ns;
index 9664d07d807d844b470975bc21708e0022b1a31e..fb15ba5f5d19f5650fd2cb76643b2217b06891b0 100644 (file)
@@ -72,6 +72,7 @@ struct nvme_ctrl {
        struct mutex namespaces_mutex;
        struct device *device;  /* char device */
        struct list_head node;
+       struct ida ns_ida;
 
        char name[12];
        char serial[20];
@@ -102,6 +103,7 @@ struct nvme_ns {
        struct request_queue *queue;
        struct gendisk *disk;
        struct kref kref;
+       int instance;
 
        u8 eui[8];
        u8 uuid[16];
@@ -112,6 +114,11 @@ struct nvme_ns {
        bool ext;
        u8 pi_type;
        int type;
+       unsigned long flags;
+
+#define NVME_NS_REMOVING 0
+#define NVME_NS_DEAD     1
+
        u64 mode_select_num_blocks;
        u32 mode_select_block_len;
 };
@@ -240,6 +247,7 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl);
 
 void nvme_stop_queues(struct nvme_ctrl *ctrl);
 void nvme_start_queues(struct nvme_ctrl *ctrl);
+void nvme_kill_queues(struct nvme_ctrl *ctrl);
 
 struct request *nvme_alloc_request(struct request_queue *q,
                struct nvme_command *cmd, unsigned int flags);
index a128672472ecf22b0abb1eb588bb12e896903a27..680f5780750cffa45efc93101fb60eb744fdd04c 100644 (file)
@@ -86,7 +86,6 @@ struct nvme_queue;
 
 static int nvme_reset(struct nvme_dev *dev);
 static void nvme_process_cq(struct nvme_queue *nvmeq);
-static void nvme_remove_dead_ctrl(struct nvme_dev *dev);
 static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown);
 
 /*
@@ -120,6 +119,7 @@ struct nvme_dev {
        unsigned long flags;
 
 #define NVME_CTRL_RESETTING    0
+#define NVME_CTRL_REMOVING     1
 
        struct nvme_ctrl ctrl;
        struct completion ioq_wait;
@@ -286,6 +286,17 @@ static int nvme_init_request(void *data, struct request *req,
        return 0;
 }
 
+static void nvme_queue_scan(struct nvme_dev *dev)
+{
+       /*
+        * Do not queue new scan work when a controller is reset during
+        * removal.
+        */
+       if (test_bit(NVME_CTRL_REMOVING, &dev->flags))
+               return;
+       queue_work(nvme_workq, &dev->scan_work);
+}
+
 static void nvme_complete_async_event(struct nvme_dev *dev,
                struct nvme_completion *cqe)
 {
@@ -300,7 +311,7 @@ static void nvme_complete_async_event(struct nvme_dev *dev,
        switch (result & 0xff07) {
        case NVME_AER_NOTICE_NS_CHANGED:
                dev_info(dev->dev, "rescanning\n");
-               queue_work(nvme_workq, &dev->scan_work);
+               nvme_queue_scan(dev);
        default:
                dev_warn(dev->dev, "async event result %08x\n", result);
        }
@@ -679,7 +690,10 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
 
        spin_lock_irq(&nvmeq->q_lock);
        if (unlikely(nvmeq->cq_vector < 0)) {
-               ret = BLK_MQ_RQ_QUEUE_BUSY;
+               if (ns && !test_bit(NVME_NS_DEAD, &ns->flags))
+                       ret = BLK_MQ_RQ_QUEUE_BUSY;
+               else
+                       ret = BLK_MQ_RQ_QUEUE_ERROR;
                spin_unlock_irq(&nvmeq->q_lock);
                goto out;
        }
@@ -1250,6 +1264,12 @@ static struct blk_mq_ops nvme_mq_ops = {
 static void nvme_dev_remove_admin(struct nvme_dev *dev)
 {
        if (dev->ctrl.admin_q && !blk_queue_dying(dev->ctrl.admin_q)) {
+               /*
+                * If the controller was reset during removal, it's possible
+                * user requests may be waiting on a stopped queue. Start the
+                * queue to flush these to completion.
+                */
+               blk_mq_start_stopped_hw_queues(dev->ctrl.admin_q, true);
                blk_cleanup_queue(dev->ctrl.admin_q);
                blk_mq_free_tag_set(&dev->admin_tagset);
        }
@@ -1690,14 +1710,14 @@ static int nvme_dev_add(struct nvme_dev *dev)
                        return 0;
                dev->ctrl.tagset = &dev->tagset;
        }
-       queue_work(nvme_workq, &dev->scan_work);
+       nvme_queue_scan(dev);
        return 0;
 }
 
-static int nvme_dev_map(struct nvme_dev *dev)
+static int nvme_pci_enable(struct nvme_dev *dev)
 {
        u64 cap;
-       int bars, result = -ENOMEM;
+       int result = -ENOMEM;
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
        if (pci_enable_device_mem(pdev))
@@ -1705,24 +1725,14 @@ static int nvme_dev_map(struct nvme_dev *dev)
 
        dev->entry[0].vector = pdev->irq;
        pci_set_master(pdev);
-       bars = pci_select_bars(pdev, IORESOURCE_MEM);
-       if (!bars)
-               goto disable_pci;
-
-       if (pci_request_selected_regions(pdev, bars, "nvme"))
-               goto disable_pci;
 
        if (dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)) &&
            dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(32)))
                goto disable;
 
-       dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
-       if (!dev->bar)
-               goto disable;
-
        if (readl(dev->bar + NVME_REG_CSTS) == -1) {
                result = -ENODEV;
-               goto unmap;
+               goto disable;
        }
 
        /*
@@ -1732,7 +1742,7 @@ static int nvme_dev_map(struct nvme_dev *dev)
        if (!pdev->irq) {
                result = pci_enable_msix(pdev, dev->entry, 1);
                if (result < 0)
-                       goto unmap;
+                       goto disable;
        }
 
        cap = lo_hi_readq(dev->bar + NVME_REG_CAP);
@@ -1759,17 +1769,19 @@ static int nvme_dev_map(struct nvme_dev *dev)
        pci_save_state(pdev);
        return 0;
 
- unmap:
-       iounmap(dev->bar);
-       dev->bar = NULL;
  disable:
-       pci_release_regions(pdev);
- disable_pci:
        pci_disable_device(pdev);
        return result;
 }
 
 static void nvme_dev_unmap(struct nvme_dev *dev)
+{
+       if (dev->bar)
+               iounmap(dev->bar);
+       pci_release_regions(to_pci_dev(dev->dev));
+}
+
+static void nvme_pci_disable(struct nvme_dev *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
@@ -1778,12 +1790,6 @@ static void nvme_dev_unmap(struct nvme_dev *dev)
        else if (pdev->msix_enabled)
                pci_disable_msix(pdev);
 
-       if (dev->bar) {
-               iounmap(dev->bar);
-               dev->bar = NULL;
-               pci_release_regions(pdev);
-       }
-
        if (pci_is_enabled(pdev)) {
                pci_disable_pcie_error_reporting(pdev);
                pci_disable_device(pdev);
@@ -1842,7 +1848,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
        nvme_dev_list_remove(dev);
 
        mutex_lock(&dev->shutdown_lock);
-       if (dev->bar) {
+       if (pci_is_enabled(to_pci_dev(dev->dev))) {
                nvme_stop_queues(&dev->ctrl);
                csts = readl(dev->bar + NVME_REG_CSTS);
        }
@@ -1855,7 +1861,7 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
                nvme_disable_io_queues(dev);
                nvme_disable_admin_queue(dev, shutdown);
        }
-       nvme_dev_unmap(dev);
+       nvme_pci_disable(dev);
 
        for (i = dev->queue_count - 1; i >= 0; i--)
                nvme_clear_queue(dev->queues[i]);
@@ -1899,10 +1905,20 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl)
        kfree(dev);
 }
 
+static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status)
+{
+       dev_warn(dev->dev, "Removing after probe failure status: %d\n", status);
+
+       kref_get(&dev->ctrl.kref);
+       nvme_dev_disable(dev, false);
+       if (!schedule_work(&dev->remove_work))
+               nvme_put_ctrl(&dev->ctrl);
+}
+
 static void nvme_reset_work(struct work_struct *work)
 {
        struct nvme_dev *dev = container_of(work, struct nvme_dev, reset_work);
-       int result;
+       int result = -ENODEV;
 
        if (WARN_ON(test_bit(NVME_CTRL_RESETTING, &dev->flags)))
                goto out;
@@ -1911,37 +1927,37 @@ static void nvme_reset_work(struct work_struct *work)
         * If we're called to reset a live controller first shut it down before
         * moving on.
         */
-       if (dev->bar)
+       if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
                nvme_dev_disable(dev, false);
 
        set_bit(NVME_CTRL_RESETTING, &dev->flags);
 
-       result = nvme_dev_map(dev);
+       result = nvme_pci_enable(dev);
        if (result)
                goto out;
 
        result = nvme_configure_admin_queue(dev);
        if (result)
-               goto unmap;
+               goto out;
 
        nvme_init_queue(dev->queues[0], 0);
        result = nvme_alloc_admin_tags(dev);
        if (result)
-               goto disable;
+               goto out;
 
        result = nvme_init_identify(&dev->ctrl);
        if (result)
-               goto free_tags;
+               goto out;
 
        result = nvme_setup_io_queues(dev);
        if (result)
-               goto free_tags;
+               goto out;
 
        dev->ctrl.event_limit = NVME_NR_AEN_COMMANDS;
 
        result = nvme_dev_list_add(dev);
        if (result)
-               goto remove;
+               goto out;
 
        /*
         * Keep the controller around but remove all namespaces if we don't have
@@ -1958,19 +1974,8 @@ static void nvme_reset_work(struct work_struct *work)
        clear_bit(NVME_CTRL_RESETTING, &dev->flags);
        return;
 
- remove:
-       nvme_dev_list_remove(dev);
- free_tags:
-       nvme_dev_remove_admin(dev);
-       blk_put_queue(dev->ctrl.admin_q);
-       dev->ctrl.admin_q = NULL;
-       dev->queues[0]->tags = NULL;
- disable:
-       nvme_disable_admin_queue(dev, false);
- unmap:
-       nvme_dev_unmap(dev);
  out:
-       nvme_remove_dead_ctrl(dev);
+       nvme_remove_dead_ctrl(dev, result);
 }
 
 static void nvme_remove_dead_ctrl_work(struct work_struct *work)
@@ -1978,19 +1983,12 @@ static void nvme_remove_dead_ctrl_work(struct work_struct *work)
        struct nvme_dev *dev = container_of(work, struct nvme_dev, remove_work);
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
+       nvme_kill_queues(&dev->ctrl);
        if (pci_get_drvdata(pdev))
                pci_stop_and_remove_bus_device_locked(pdev);
        nvme_put_ctrl(&dev->ctrl);
 }
 
-static void nvme_remove_dead_ctrl(struct nvme_dev *dev)
-{
-       dev_warn(dev->dev, "Removing after probe failure\n");
-       kref_get(&dev->ctrl.kref);
-       if (!schedule_work(&dev->remove_work))
-               nvme_put_ctrl(&dev->ctrl);
-}
-
 static int nvme_reset(struct nvme_dev *dev)
 {
        if (!dev->ctrl.admin_q || blk_queue_dying(dev->ctrl.admin_q))
@@ -2042,6 +2040,27 @@ static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
        .free_ctrl              = nvme_pci_free_ctrl,
 };
 
+static int nvme_dev_map(struct nvme_dev *dev)
+{
+       int bars;
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+       bars = pci_select_bars(pdev, IORESOURCE_MEM);
+       if (!bars)
+               return -ENODEV;
+       if (pci_request_selected_regions(pdev, bars, "nvme"))
+               return -ENODEV;
+
+       dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
+       if (!dev->bar)
+               goto release;
+
+       return 0;
+  release:
+       pci_release_regions(pdev);
+       return -ENODEV;
+}
+
 static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int node, result = -ENOMEM;
@@ -2066,6 +2085,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        dev->dev = get_device(&pdev->dev);
        pci_set_drvdata(pdev, dev);
 
+       result = nvme_dev_map(dev);
+       if (result)
+               goto free;
+
        INIT_LIST_HEAD(&dev->node);
        INIT_WORK(&dev->scan_work, nvme_dev_scan);
        INIT_WORK(&dev->reset_work, nvme_reset_work);
@@ -2089,6 +2112,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        nvme_release_prp_pools(dev);
  put_pci:
        put_device(dev->dev);
+       nvme_dev_unmap(dev);
  free:
        kfree(dev->queues);
        kfree(dev->entry);
@@ -2112,10 +2136,16 @@ static void nvme_shutdown(struct pci_dev *pdev)
        nvme_dev_disable(dev, true);
 }
 
+/*
+ * The driver's remove may be called on a device in a partially initialized
+ * state. This function must not have any dependencies on the device state in
+ * order to proceed.
+ */
 static void nvme_remove(struct pci_dev *pdev)
 {
        struct nvme_dev *dev = pci_get_drvdata(pdev);
 
+       set_bit(NVME_CTRL_REMOVING, &dev->flags);
        pci_set_drvdata(pdev, NULL);
        flush_work(&dev->scan_work);
        nvme_remove_namespaces(&dev->ctrl);
@@ -2126,6 +2156,7 @@ static void nvme_remove(struct pci_dev *pdev)
        nvme_free_queues(dev, 0);
        nvme_release_cmb(dev);
        nvme_release_prp_pools(dev);
+       nvme_dev_unmap(dev);
        nvme_put_ctrl(&dev->ctrl);
 }
 
index 39c4be41ef83d6cf23302fb9af6270f8857f85de..365dc7e83ab43cd3473d0da57d0ea768784869c8 100644 (file)
@@ -305,6 +305,7 @@ EXPORT_SYMBOL(of_phy_find_device);
  * @dev: pointer to net_device claiming the phy
  * @phy_np: Pointer to device tree node for the PHY
  * @hndlr: Link state callback for the network device
+ * @flags: flags to pass to the PHY
  * @iface: PHY data interface type
  *
  * If successful, returns a pointer to the phy_device with the embedded
index b1449f71601cb257f1057b77c217a943da92cab8..13f4fed3804850804dfa9ad285c403e68729c150 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/of_device.h>
 #include <linux/of_pci.h>
 #include <linux/slab.h>
-#include <asm-generic/pci-bridge.h>
 
 static inline int __of_pci_pci_compare(struct device_node *node,
                                       unsigned int data)
index 592de566e72ff5dbd806d5cd314eead262841822..3a102a84d637e7fecb7c8e81b8cb3c4d64d3cbfe 100644 (file)
@@ -110,8 +110,6 @@ config IOMMU_HELPER
 
 source "drivers/pcmcia/Kconfig"
 
-source "drivers/pci/hotplug/Kconfig"
-
 endmenu
 
 menu "PA-RISC specific drivers"
index a656d9e8334302c2ec4f013ad6c016034ace5f27..21905fef2cbf0d34259e37069e50140a66101441 100644 (file)
@@ -91,7 +91,7 @@ static int configure_memory(const unsigned char *buf,
        for (i=0;i<HPEE_MEMORY_MAX_ENT;i++) {
                c = get_8(buf+len);
                
-               if (NULL != (res = kmalloc(sizeof(struct resource), GFP_KERNEL))) {
+               if (NULL != (res = kzalloc(sizeof(struct resource), GFP_KERNEL))) {
                        int result;
                        
                        res->name = name;
@@ -183,7 +183,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent,
        for (i=0;i<HPEE_PORT_MAX_ENT;i++) {
                c = get_8(buf+len);
                
-               if (NULL != (res = kmalloc(sizeof(struct resource), GFP_KERNEL))) {
+               if (NULL != (res = kzalloc(sizeof(struct resource), GFP_KERNEL))) {
                        res->name = board;
                        res->start = get_16(buf+len+1);
                        res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1;
index 73de4efcbe6edc85c8f3fb54e0c925a7ab30492b..a1f37db745ab7fb2e8568fb8dc95df611d4cafe0 100644 (file)
@@ -1,6 +1,9 @@
 #
 # PCI configuration
 #
+
+source "drivers/pci/pcie/Kconfig"
+
 config PCI_BUS_ADDR_T_64BIT
        def_bool y if (ARCH_DMA_ADDR_T_64BIT || 64BIT)
        depends on PCI
@@ -118,4 +121,11 @@ config PCI_LABEL
        def_bool y if (DMI || ACPI)
        select NLS
 
+config PCI_HYPERV
+        tristate "Hyper-V PCI Frontend"
+        depends on PCI && X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
+        help
+          The PCI device frontend driver allows the kernel to import arbitrary
+          PCI devices from a PCI backend to support PCI driver domains.
+
 source "drivers/pci/host/Kconfig"
index be3f631c3f75067103857635e6126a2b9c600a05..2154092ddee8dd1137905eeabcb82afcdfd8399a 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
 # Some architectures use the generic PCI setup functions
 #
 obj-$(CONFIG_ALPHA) += setup-irq.o
+obj-$(CONFIG_ARC) += setup-irq.o
 obj-$(CONFIG_ARM) += setup-irq.o
 obj-$(CONFIG_ARM64) += setup-irq.o
 obj-$(CONFIG_UNICORE32) += setup-irq.o
index 8c05b5ceeaec2f2bf8db5fcc15c736d6ef93b0e2..01b9d0a00abcb06186bdb80d44c5aa9e5f05838c 100644 (file)
@@ -174,38 +174,6 @@ struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
 }
 EXPORT_SYMBOL(pci_bus_set_ops);
 
-/**
- * pci_read_vpd - Read one entry from Vital Product Data
- * @dev:       pci device struct
- * @pos:       offset in vpd space
- * @count:     number of bytes to read
- * @buf:       pointer to where to store result
- *
- */
-ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf)
-{
-       if (!dev->vpd || !dev->vpd->ops)
-               return -ENODEV;
-       return dev->vpd->ops->read(dev, pos, count, buf);
-}
-EXPORT_SYMBOL(pci_read_vpd);
-
-/**
- * pci_write_vpd - Write entry to Vital Product Data
- * @dev:       pci device struct
- * @pos:       offset in vpd space
- * @count:     number of bytes to write
- * @buf:       buffer containing write data
- *
- */
-ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf)
-{
-       if (!dev->vpd || !dev->vpd->ops)
-               return -ENODEV;
-       return dev->vpd->ops->write(dev, pos, count, buf);
-}
-EXPORT_SYMBOL(pci_write_vpd);
-
 /*
  * The following routines are to prevent the user from accessing PCI config
  * space when it's unsafe to do so.  Some devices require this during BIST and
@@ -277,15 +245,91 @@ PCI_USER_WRITE_CONFIG(dword, u32)
 
 /* VPD access through PCI 2.2+ VPD capability */
 
-#define PCI_VPD_PCI22_SIZE (PCI_VPD_ADDR_MASK + 1)
+/**
+ * pci_read_vpd - Read one entry from Vital Product Data
+ * @dev:       pci device struct
+ * @pos:       offset in vpd space
+ * @count:     number of bytes to read
+ * @buf:       pointer to where to store result
+ */
+ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf)
+{
+       if (!dev->vpd || !dev->vpd->ops)
+               return -ENODEV;
+       return dev->vpd->ops->read(dev, pos, count, buf);
+}
+EXPORT_SYMBOL(pci_read_vpd);
 
-struct pci_vpd_pci22 {
-       struct pci_vpd base;
-       struct mutex lock;
-       u16     flag;
-       bool    busy;
-       u8      cap;
-};
+/**
+ * pci_write_vpd - Write entry to Vital Product Data
+ * @dev:       pci device struct
+ * @pos:       offset in vpd space
+ * @count:     number of bytes to write
+ * @buf:       buffer containing write data
+ */
+ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf)
+{
+       if (!dev->vpd || !dev->vpd->ops)
+               return -ENODEV;
+       return dev->vpd->ops->write(dev, pos, count, buf);
+}
+EXPORT_SYMBOL(pci_write_vpd);
+
+#define PCI_VPD_MAX_SIZE (PCI_VPD_ADDR_MASK + 1)
+
+/**
+ * pci_vpd_size - determine actual size of Vital Product Data
+ * @dev:       pci device struct
+ * @old_size:  current assumed size, also maximum allowed size
+ */
+static size_t pci_vpd_size(struct pci_dev *dev, size_t old_size)
+{
+       size_t off = 0;
+       unsigned char header[1+2];      /* 1 byte tag, 2 bytes length */
+
+       while (off < old_size &&
+              pci_read_vpd(dev, off, 1, header) == 1) {
+               unsigned char tag;
+
+               if (header[0] & PCI_VPD_LRDT) {
+                       /* Large Resource Data Type Tag */
+                       tag = pci_vpd_lrdt_tag(header);
+                       /* Only read length from known tag items */
+                       if ((tag == PCI_VPD_LTIN_ID_STRING) ||
+                           (tag == PCI_VPD_LTIN_RO_DATA) ||
+                           (tag == PCI_VPD_LTIN_RW_DATA)) {
+                               if (pci_read_vpd(dev, off+1, 2,
+                                                &header[1]) != 2) {
+                                       dev_warn(&dev->dev,
+                                                "invalid large VPD tag %02x size at offset %zu",
+                                                tag, off + 1);
+                                       return 0;
+                               }
+                               off += PCI_VPD_LRDT_TAG_SIZE +
+                                       pci_vpd_lrdt_size(header);
+                       }
+               } else {
+                       /* Short Resource Data Type Tag */
+                       off += PCI_VPD_SRDT_TAG_SIZE +
+                               pci_vpd_srdt_size(header);
+                       tag = pci_vpd_srdt_tag(header);
+               }
+
+               if (tag == PCI_VPD_STIN_END)    /* End tag descriptor */
+                       return off;
+
+               if ((tag != PCI_VPD_LTIN_ID_STRING) &&
+                   (tag != PCI_VPD_LTIN_RO_DATA) &&
+                   (tag != PCI_VPD_LTIN_RW_DATA)) {
+                       dev_warn(&dev->dev,
+                                "invalid %s VPD tag %02x at offset %zu",
+                                (header[0] & PCI_VPD_LRDT) ? "large" : "short",
+                                tag, off);
+                       return 0;
+               }
+       }
+       return 0;
+}
 
 /*
  * Wait for last operation to complete.
@@ -295,55 +339,71 @@ struct pci_vpd_pci22 {
  *
  * Returns 0 on success, negative values indicate error.
  */
-static int pci_vpd_pci22_wait(struct pci_dev *dev)
+static int pci_vpd_wait(struct pci_dev *dev)
 {
-       struct pci_vpd_pci22 *vpd =
-               container_of(dev->vpd, struct pci_vpd_pci22, base);
-       unsigned long timeout = jiffies + HZ/20 + 2;
+       struct pci_vpd *vpd = dev->vpd;
+       unsigned long timeout = jiffies + msecs_to_jiffies(50);
+       unsigned long max_sleep = 16;
        u16 status;
        int ret;
 
        if (!vpd->busy)
                return 0;
 
-       for (;;) {
+       while (time_before(jiffies, timeout)) {
                ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR,
                                                &status);
                if (ret < 0)
                        return ret;
 
                if ((status & PCI_VPD_ADDR_F) == vpd->flag) {
-                       vpd->busy = false;
+                       vpd->busy = 0;
                        return 0;
                }
 
-               if (time_after(jiffies, timeout)) {
-                       dev_printk(KERN_DEBUG, &dev->dev, "vpd r/w failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update\n");
-                       return -ETIMEDOUT;
-               }
                if (fatal_signal_pending(current))
                        return -EINTR;
-               if (!cond_resched())
-                       udelay(10);
+
+               usleep_range(10, max_sleep);
+               if (max_sleep < 1024)
+                       max_sleep *= 2;
        }
+
+       dev_warn(&dev->dev, "VPD access failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update\n");
+       return -ETIMEDOUT;
 }
 
-static ssize_t pci_vpd_pci22_read(struct pci_dev *dev, loff_t pos, size_t count,
-                                 void *arg)
+static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
+                           void *arg)
 {
-       struct pci_vpd_pci22 *vpd =
-               container_of(dev->vpd, struct pci_vpd_pci22, base);
+       struct pci_vpd *vpd = dev->vpd;
        int ret;
        loff_t end = pos + count;
        u8 *buf = arg;
 
-       if (pos < 0 || pos > vpd->base.len || end > vpd->base.len)
+       if (pos < 0)
                return -EINVAL;
 
+       if (!vpd->valid) {
+               vpd->valid = 1;
+               vpd->len = pci_vpd_size(dev, vpd->len);
+       }
+
+       if (vpd->len == 0)
+               return -EIO;
+
+       if (pos > vpd->len)
+               return 0;
+
+       if (end > vpd->len) {
+               end = vpd->len;
+               count = end - pos;
+       }
+
        if (mutex_lock_killable(&vpd->lock))
                return -EINTR;
 
-       ret = pci_vpd_pci22_wait(dev);
+       ret = pci_vpd_wait(dev);
        if (ret < 0)
                goto out;
 
@@ -355,9 +415,9 @@ static ssize_t pci_vpd_pci22_read(struct pci_dev *dev, loff_t pos, size_t count,
                                                 pos & ~3);
                if (ret < 0)
                        break;
-               vpd->busy = true;
+               vpd->busy = 1;
                vpd->flag = PCI_VPD_ADDR_F;
-               ret = pci_vpd_pci22_wait(dev);
+               ret = pci_vpd_wait(dev);
                if (ret < 0)
                        break;
 
@@ -380,22 +440,32 @@ out:
        return ret ? ret : count;
 }
 
-static ssize_t pci_vpd_pci22_write(struct pci_dev *dev, loff_t pos, size_t count,
-                                  const void *arg)
+static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
+                            const void *arg)
 {
-       struct pci_vpd_pci22 *vpd =
-               container_of(dev->vpd, struct pci_vpd_pci22, base);
+       struct pci_vpd *vpd = dev->vpd;
        const u8 *buf = arg;
        loff_t end = pos + count;
        int ret = 0;
 
-       if (pos < 0 || (pos & 3) || (count & 3) || end > vpd->base.len)
+       if (pos < 0 || (pos & 3) || (count & 3))
+               return -EINVAL;
+
+       if (!vpd->valid) {
+               vpd->valid = 1;
+               vpd->len = pci_vpd_size(dev, vpd->len);
+       }
+
+       if (vpd->len == 0)
+               return -EIO;
+
+       if (end > vpd->len)
                return -EINVAL;
 
        if (mutex_lock_killable(&vpd->lock))
                return -EINTR;
 
-       ret = pci_vpd_pci22_wait(dev);
+       ret = pci_vpd_wait(dev);
        if (ret < 0)
                goto out;
 
@@ -415,9 +485,9 @@ static ssize_t pci_vpd_pci22_write(struct pci_dev *dev, loff_t pos, size_t count
                if (ret < 0)
                        break;
 
-               vpd->busy = true;
+               vpd->busy = 1;
                vpd->flag = 0;
-               ret = pci_vpd_pci22_wait(dev);
+               ret = pci_vpd_wait(dev);
                if (ret < 0)
                        break;
 
@@ -428,15 +498,9 @@ out:
        return ret ? ret : count;
 }
 
-static void pci_vpd_pci22_release(struct pci_dev *dev)
-{
-       kfree(container_of(dev->vpd, struct pci_vpd_pci22, base));
-}
-
-static const struct pci_vpd_ops pci_vpd_pci22_ops = {
-       .read = pci_vpd_pci22_read,
-       .write = pci_vpd_pci22_write,
-       .release = pci_vpd_pci22_release,
+static const struct pci_vpd_ops pci_vpd_ops = {
+       .read = pci_vpd_read,
+       .write = pci_vpd_write,
 };
 
 static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
@@ -472,12 +536,11 @@ static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
 static const struct pci_vpd_ops pci_vpd_f0_ops = {
        .read = pci_vpd_f0_read,
        .write = pci_vpd_f0_write,
-       .release = pci_vpd_pci22_release,
 };
 
-int pci_vpd_pci22_init(struct pci_dev *dev)
+int pci_vpd_init(struct pci_dev *dev)
 {
-       struct pci_vpd_pci22 *vpd;
+       struct pci_vpd *vpd;
        u8 cap;
 
        cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
@@ -488,18 +551,24 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
        if (!vpd)
                return -ENOMEM;
 
-       vpd->base.len = PCI_VPD_PCI22_SIZE;
+       vpd->len = PCI_VPD_MAX_SIZE;
        if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0)
-               vpd->base.ops = &pci_vpd_f0_ops;
+               vpd->ops = &pci_vpd_f0_ops;
        else
-               vpd->base.ops = &pci_vpd_pci22_ops;
+               vpd->ops = &pci_vpd_ops;
        mutex_init(&vpd->lock);
        vpd->cap = cap;
-       vpd->busy = false;
-       dev->vpd = &vpd->base;
+       vpd->busy = 0;
+       vpd->valid = 0;
+       dev->vpd = vpd;
        return 0;
 }
 
+void pci_vpd_release(struct pci_dev *dev)
+{
+       kfree(dev->vpd);
+}
+
 /**
  * pci_cfg_access_lock - Lock PCI config reads/writes
  * @dev:       pci device struct
index 89b3befc7155325b12f21d4667a675b52423bb6d..f2187d491475a6144cd4b11cff7c9589e1a6c82c 100644 (file)
@@ -291,7 +291,12 @@ void pci_bus_add_device(struct pci_dev *dev)
 
        dev->match_driver = true;
        retval = device_attach(&dev->dev);
-       WARN_ON(retval < 0);
+       if (retval < 0) {
+               dev_warn(&dev->dev, "device attach failed (%d)\n", retval);
+               pci_proc_detach_device(dev);
+               pci_remove_sysfs_dev_files(dev);
+               return;
+       }
 
        dev->is_added = 1;
 }
index 75a6054265384d806623caabcc34d98e29a45f82..c5014bf95a204677650045478264cac86d58c100 100644 (file)
@@ -14,8 +14,31 @@ config PCI_DRA7XX
 config PCI_MVEBU
        bool "Marvell EBU PCIe controller"
        depends on ARCH_MVEBU || ARCH_DOVE
+       depends on ARM
        depends on OF
 
+
+config PCIE_XILINX_NWL
+       bool "NWL PCIe Core"
+       depends on ARCH_ZYNQMP
+       select PCI_MSI_IRQ_DOMAIN if PCI_MSI
+       help
+        Say 'Y' here if you want kernel support for Xilinx
+        NWL PCIe controller. The controller can act as Root Port
+        or End Point. The current option selection will only
+        support root port enabling.
+
+config PCIE_DW_PLAT
+       bool "Platform bus based DesignWare PCIe Controller"
+       select PCIE_DW
+       ---help---
+        This selects the DesignWare PCIe controller support. Select this if
+        you have a PCIe controller on Platform bus.
+
+        If you have a controller with this interface, say Y or M here.
+
+        If unsure, say N.
+
 config PCIE_DW
        bool
 
@@ -41,7 +64,7 @@ config PCI_TEGRA
 config PCI_RCAR_GEN2
        bool "Renesas R-Car Gen2 Internal PCI controller"
        depends on ARM
-       depends on ARCH_SHMOBILE || COMPILE_TEST
+       depends on ARCH_RENESAS || COMPILE_TEST
        help
          Say Y here if you want internal PCI support on R-Car Gen2 SoC.
          There are 3 internal PCI controllers available with a single
@@ -49,13 +72,17 @@ config PCI_RCAR_GEN2
 
 config PCI_RCAR_GEN2_PCIE
        bool "Renesas R-Car PCIe controller"
-       depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST)
+       depends on ARCH_RENESAS || (ARM && COMPILE_TEST)
        help
          Say Y here if you want PCIe controller support on R-Car Gen2 SoCs.
 
+config PCI_HOST_COMMON
+       bool
+
 config PCI_HOST_GENERIC
        bool "Generic PCI host controller"
        depends on (ARM || ARM64) && OF
+       select PCI_HOST_COMMON
        help
          Say Y here if you want to support a simple generic PCI host
          controller, such as the one emulated by kvmtool.
@@ -81,7 +108,7 @@ config PCI_KEYSTONE
 
 config PCIE_XILINX
        bool "Xilinx AXI PCIe host bridge support"
-       depends on ARCH_ZYNQ
+       depends on ARCH_ZYNQ || MICROBLAZE
        help
          Say 'Y' here if you want kernel to support the Xilinx AXI PCIe
          Host Bridge driver.
@@ -191,4 +218,18 @@ config PCIE_QCOM
          PCIe controller uses the Designware core plus Qualcomm-specific
          hardware wrappers.
 
+config PCI_HOST_THUNDER_PEM
+       bool "Cavium Thunder PCIe controller to off-chip devices"
+       depends on OF && ARM64
+       select PCI_HOST_COMMON
+       help
+         Say Y here if you want PCIe support for CN88XX Cavium Thunder SoCs.
+
+config PCI_HOST_THUNDER_ECAM
+       bool "Cavium Thunder ECAM controller to on-chip devices on pass-1.x silicon"
+       depends on OF && ARM64
+       select PCI_HOST_COMMON
+       help
+         Say Y here if you want ECAM support for CN88XX-Pass-1.x Cavium Thunder SoCs.
+
 endmenu
index 7b2f20c6ccc62bca6317d35e85579eba7429f85a..d85b5faf9bbc86089ee91a4bee114a3d7be40baf 100644 (file)
@@ -1,15 +1,19 @@
 obj-$(CONFIG_PCIE_DW) += pcie-designware.o
+obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
 obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
 obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
 obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
+obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
 obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
 obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
 obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o
+obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
 obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
 obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
 obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
 obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
+obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
 obj-$(CONFIG_PCI_XGENE) += pci-xgene.o
 obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
 obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
@@ -22,3 +26,5 @@ obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
 obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
 obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
 obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
+obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o
+obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
index 923607bdabc5c63ef940453f3ffe42180b29b02b..2ca3a1f30ebf2770f1db370955c2c11f33245001 100644 (file)
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -108,7 +107,6 @@ static int dra7xx_pcie_establish_link(struct pcie_port *pp)
 {
        struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
        u32 reg;
-       unsigned int retries;
 
        if (dw_pcie_link_up(pp)) {
                dev_err(pp->dev, "link is already up\n");
@@ -119,14 +117,7 @@ static int dra7xx_pcie_establish_link(struct pcie_port *pp)
        reg |= LTSSM_EN;
        dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
 
-       for (retries = 0; retries < 1000; retries++) {
-               if (dw_pcie_link_up(pp))
-                       return 0;
-               usleep_range(10, 20);
-       }
-
-       dev_err(pp->dev, "link is not up\n");
-       return -EINVAL;
+       return dw_pcie_wait_for_link(pp);
 }
 
 static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp)
index d997d22d4231da6de08cab29dd101d699dbb4fe0..219976103efc5b67e7c31df52c9102f1582a67e1 100644 (file)
@@ -318,7 +318,6 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
 {
        struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
        u32 val;
-       unsigned int retries;
 
        if (dw_pcie_link_up(pp)) {
                dev_err(pp->dev, "Link already up\n");
@@ -357,13 +356,8 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
                          PCIE_APP_LTSSM_ENABLE);
 
        /* check if the link is up or not */
-       for (retries = 0; retries < 10; retries++) {
-               if (dw_pcie_link_up(pp)) {
-                       dev_info(pp->dev, "Link up\n");
-                       return 0;
-               }
-               mdelay(100);
-       }
+       if (!dw_pcie_wait_for_link(pp))
+               return 0;
 
        while (exynos_phy_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED) == 0) {
                val = exynos_blk_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED);
@@ -372,8 +366,7 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)
        /* power off phy */
        exynos_pcie_power_off_phy(pp);
 
-       dev_err(pp->dev, "PCIe Link Fail\n");
-       return -EINVAL;
+       return -ETIMEDOUT;
 }
 
 static void exynos_pcie_clear_irq_pulse(struct pcie_port *pp)
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c
new file mode 100644 (file)
index 0000000..e9f850f
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2014 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pci-host-common.h"
+
+static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
+{
+       pci_free_resource_list(&pci->resources);
+}
+
+static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
+{
+       int err, res_valid = 0;
+       struct device *dev = pci->host.dev.parent;
+       struct device_node *np = dev->of_node;
+       resource_size_t iobase;
+       struct resource_entry *win;
+
+       err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
+                                              &iobase);
+       if (err)
+               return err;
+
+       resource_list_for_each_entry(win, &pci->resources) {
+               struct resource *parent, *res = win->res;
+
+               switch (resource_type(res)) {
+               case IORESOURCE_IO:
+                       parent = &ioport_resource;
+                       err = pci_remap_iospace(res, iobase);
+                       if (err) {
+                               dev_warn(dev, "error %d: failed to map resource %pR\n",
+                                        err, res);
+                               continue;
+                       }
+                       break;
+               case IORESOURCE_MEM:
+                       parent = &iomem_resource;
+                       res_valid |= !(res->flags & IORESOURCE_PREFETCH);
+                       break;
+               case IORESOURCE_BUS:
+                       pci->cfg.bus_range = res;
+               default:
+                       continue;
+               }
+
+               err = devm_request_resource(dev, parent, res);
+               if (err)
+                       goto out_release_res;
+       }
+
+       if (!res_valid) {
+               dev_err(dev, "non-prefetchable memory resource required\n");
+               err = -EINVAL;
+               goto out_release_res;
+       }
+
+       return 0;
+
+out_release_res:
+       gen_pci_release_of_pci_ranges(pci);
+       return err;
+}
+
+static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
+{
+       int err;
+       u8 bus_max;
+       resource_size_t busn;
+       struct resource *bus_range;
+       struct device *dev = pci->host.dev.parent;
+       struct device_node *np = dev->of_node;
+       u32 sz = 1 << pci->cfg.ops->bus_shift;
+
+       err = of_address_to_resource(np, 0, &pci->cfg.res);
+       if (err) {
+               dev_err(dev, "missing \"reg\" property\n");
+               return err;
+       }
+
+       /* Limit the bus-range to fit within reg */
+       bus_max = pci->cfg.bus_range->start +
+                 (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
+       pci->cfg.bus_range->end = min_t(resource_size_t,
+                                       pci->cfg.bus_range->end, bus_max);
+
+       pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
+                                   sizeof(*pci->cfg.win), GFP_KERNEL);
+       if (!pci->cfg.win)
+               return -ENOMEM;
+
+       /* Map our Configuration Space windows */
+       if (!devm_request_mem_region(dev, pci->cfg.res.start,
+                                    resource_size(&pci->cfg.res),
+                                    "Configuration Space"))
+               return -ENOMEM;
+
+       bus_range = pci->cfg.bus_range;
+       for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
+               u32 idx = busn - bus_range->start;
+
+               pci->cfg.win[idx] = devm_ioremap(dev,
+                                                pci->cfg.res.start + idx * sz,
+                                                sz);
+               if (!pci->cfg.win[idx])
+                       return -ENOMEM;
+       }
+
+       return 0;
+}
+
+int pci_host_common_probe(struct platform_device *pdev,
+                         struct gen_pci *pci)
+{
+       int err;
+       const char *type;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct pci_bus *bus, *child;
+
+       type = of_get_property(np, "device_type", NULL);
+       if (!type || strcmp(type, "pci")) {
+               dev_err(dev, "invalid \"device_type\" %s\n", type);
+               return -EINVAL;
+       }
+
+       of_pci_check_probe_only();
+
+       pci->host.dev.parent = dev;
+       INIT_LIST_HEAD(&pci->host.windows);
+       INIT_LIST_HEAD(&pci->resources);
+
+       /* Parse our PCI ranges and request their resources */
+       err = gen_pci_parse_request_of_pci_ranges(pci);
+       if (err)
+               return err;
+
+       /* Parse and map our Configuration Space windows */
+       err = gen_pci_parse_map_cfg_windows(pci);
+       if (err) {
+               gen_pci_release_of_pci_ranges(pci);
+               return err;
+       }
+
+       /* Do not reassign resources if probe only */
+       if (!pci_has_flag(PCI_PROBE_ONLY))
+               pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
+
+
+       bus = pci_scan_root_bus(dev, pci->cfg.bus_range->start,
+                               &pci->cfg.ops->ops, pci, &pci->resources);
+       if (!bus) {
+               dev_err(dev, "Scanning rootbus failed");
+               return -ENODEV;
+       }
+
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+
+       if (!pci_has_flag(PCI_PROBE_ONLY)) {
+               pci_bus_size_bridges(bus);
+               pci_bus_assign_resources(bus);
+
+               list_for_each_entry(child, &bus->children, node)
+                       pcie_bus_configure_settings(child);
+       }
+
+       pci_bus_add_devices(bus);
+       return 0;
+}
+
+MODULE_DESCRIPTION("Generic PCI host driver common code");
+MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pci-host-common.h b/drivers/pci/host/pci-host-common.h
new file mode 100644 (file)
index 0000000..09f3fa0
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2014 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#ifndef _PCI_HOST_COMMON_H
+#define _PCI_HOST_COMMON_H
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+struct gen_pci_cfg_bus_ops {
+       u32 bus_shift;
+       struct pci_ops ops;
+};
+
+struct gen_pci_cfg_windows {
+       struct resource                         res;
+       struct resource                         *bus_range;
+       void __iomem                            **win;
+
+       struct gen_pci_cfg_bus_ops              *ops;
+};
+
+struct gen_pci {
+       struct pci_host_bridge                  host;
+       struct gen_pci_cfg_windows              cfg;
+       struct list_head                        resources;
+};
+
+int pci_host_common_probe(struct platform_device *pdev,
+                         struct gen_pci *pci);
+
+#endif /* _PCI_HOST_COMMON_H */
index 1652bc70b1453663cc4a7614d68a3e7c5ea12524..e8aa78faa16df31becd8f717e0cdcee94c42e391 100644 (file)
 #include <linux/of_pci.h>
 #include <linux/platform_device.h>
 
-struct gen_pci_cfg_bus_ops {
-       u32 bus_shift;
-       struct pci_ops ops;
-};
-
-struct gen_pci_cfg_windows {
-       struct resource                         res;
-       struct resource                         *bus_range;
-       void __iomem                            **win;
-
-       struct gen_pci_cfg_bus_ops              *ops;
-};
-
-struct gen_pci {
-       struct pci_host_bridge                  host;
-       struct gen_pci_cfg_windows              cfg;
-       struct list_head                        resources;
-};
+#include "pci-host-common.h"
 
 static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,
                                             unsigned int devfn,
@@ -93,175 +76,19 @@ static const struct of_device_id gen_pci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, gen_pci_of_match);
 
-static void gen_pci_release_of_pci_ranges(struct gen_pci *pci)
-{
-       pci_free_resource_list(&pci->resources);
-}
-
-static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci)
-{
-       int err, res_valid = 0;
-       struct device *dev = pci->host.dev.parent;
-       struct device_node *np = dev->of_node;
-       resource_size_t iobase;
-       struct resource_entry *win;
-
-       err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources,
-                                              &iobase);
-       if (err)
-               return err;
-
-       resource_list_for_each_entry(win, &pci->resources) {
-               struct resource *parent, *res = win->res;
-
-               switch (resource_type(res)) {
-               case IORESOURCE_IO:
-                       parent = &ioport_resource;
-                       err = pci_remap_iospace(res, iobase);
-                       if (err) {
-                               dev_warn(dev, "error %d: failed to map resource %pR\n",
-                                        err, res);
-                               continue;
-                       }
-                       break;
-               case IORESOURCE_MEM:
-                       parent = &iomem_resource;
-                       res_valid |= !(res->flags & IORESOURCE_PREFETCH);
-                       break;
-               case IORESOURCE_BUS:
-                       pci->cfg.bus_range = res;
-               default:
-                       continue;
-               }
-
-               err = devm_request_resource(dev, parent, res);
-               if (err)
-                       goto out_release_res;
-       }
-
-       if (!res_valid) {
-               dev_err(dev, "non-prefetchable memory resource required\n");
-               err = -EINVAL;
-               goto out_release_res;
-       }
-
-       return 0;
-
-out_release_res:
-       gen_pci_release_of_pci_ranges(pci);
-       return err;
-}
-
-static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)
-{
-       int err;
-       u8 bus_max;
-       resource_size_t busn;
-       struct resource *bus_range;
-       struct device *dev = pci->host.dev.parent;
-       struct device_node *np = dev->of_node;
-       u32 sz = 1 << pci->cfg.ops->bus_shift;
-
-       err = of_address_to_resource(np, 0, &pci->cfg.res);
-       if (err) {
-               dev_err(dev, "missing \"reg\" property\n");
-               return err;
-       }
-
-       /* Limit the bus-range to fit within reg */
-       bus_max = pci->cfg.bus_range->start +
-                 (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1;
-       pci->cfg.bus_range->end = min_t(resource_size_t,
-                                       pci->cfg.bus_range->end, bus_max);
-
-       pci->cfg.win = devm_kcalloc(dev, resource_size(pci->cfg.bus_range),
-                                   sizeof(*pci->cfg.win), GFP_KERNEL);
-       if (!pci->cfg.win)
-               return -ENOMEM;
-
-       /* Map our Configuration Space windows */
-       if (!devm_request_mem_region(dev, pci->cfg.res.start,
-                                    resource_size(&pci->cfg.res),
-                                    "Configuration Space"))
-               return -ENOMEM;
-
-       bus_range = pci->cfg.bus_range;
-       for (busn = bus_range->start; busn <= bus_range->end; ++busn) {
-               u32 idx = busn - bus_range->start;
-
-               pci->cfg.win[idx] = devm_ioremap(dev,
-                                                pci->cfg.res.start + idx * sz,
-                                                sz);
-               if (!pci->cfg.win[idx])
-                       return -ENOMEM;
-       }
-
-       return 0;
-}
-
 static int gen_pci_probe(struct platform_device *pdev)
 {
-       int err;
-       const char *type;
-       const struct of_device_id *of_id;
        struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
+       const struct of_device_id *of_id;
        struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
-       struct pci_bus *bus, *child;
 
        if (!pci)
                return -ENOMEM;
 
-       type = of_get_property(np, "device_type", NULL);
-       if (!type || strcmp(type, "pci")) {
-               dev_err(dev, "invalid \"device_type\" %s\n", type);
-               return -EINVAL;
-       }
-
-       of_pci_check_probe_only();
-
-       of_id = of_match_node(gen_pci_of_match, np);
+       of_id = of_match_node(gen_pci_of_match, dev->of_node);
        pci->cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
-       pci->host.dev.parent = dev;
-       INIT_LIST_HEAD(&pci->host.windows);
-       INIT_LIST_HEAD(&pci->resources);
-
-       /* Parse our PCI ranges and request their resources */
-       err = gen_pci_parse_request_of_pci_ranges(pci);
-       if (err)
-               return err;
-
-       /* Parse and map our Configuration Space windows */
-       err = gen_pci_parse_map_cfg_windows(pci);
-       if (err) {
-               gen_pci_release_of_pci_ranges(pci);
-               return err;
-       }
-
-       /* Do not reassign resources if probe only */
-       if (!pci_has_flag(PCI_PROBE_ONLY))
-               pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
-
-
-       bus = pci_scan_root_bus(dev, pci->cfg.bus_range->start,
-                               &pci->cfg.ops->ops, pci, &pci->resources);
-       if (!bus) {
-               dev_err(dev, "Scanning rootbus failed");
-               return -ENODEV;
-       }
-
-       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
-
-       if (!pci_has_flag(PCI_PROBE_ONLY)) {
-               pci_bus_size_bridges(bus);
-               pci_bus_assign_resources(bus);
-
-               list_for_each_entry(child, &bus->children, node)
-                       pcie_bus_configure_settings(child);
-       }
 
-       pci_bus_add_devices(bus);
-       return 0;
+       return pci_host_common_probe(pdev, pci);
 }
 
 static struct platform_driver gen_pci_driver = {
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
new file mode 100644 (file)
index 0000000..ed651ba
--- /dev/null
@@ -0,0 +1,2346 @@
+/*
+ * Copyright (c) Microsoft Corporation.
+ *
+ * Author:
+ *   Jake Oshins <jakeo@microsoft.com>
+ *
+ * This driver acts as a paravirtual front-end for PCI Express root buses.
+ * When a PCI Express function (either an entire device or an SR-IOV
+ * Virtual Function) is being passed through to the VM, this driver exposes
+ * a new bus to the guest VM.  This is modeled as a root PCI bus because
+ * no bridges are being exposed to the VM.  In fact, with a "Generation 2"
+ * VM within Hyper-V, there may seem to be no PCI bus at all in the VM
+ * until a device as been exposed using this driver.
+ *
+ * Each root PCI bus has its own PCI domain, which is called "Segment" in
+ * the PCI Firmware Specifications.  Thus while each device passed through
+ * to the VM using this front-end will appear at "device 0", the domain will
+ * be unique.  Typically, each bus will have one PCI function on it, though
+ * this driver does support more than one.
+ *
+ * In order to map the interrupts from the device through to the guest VM,
+ * this driver also implements an IRQ Domain, which handles interrupts (either
+ * MSI or MSI-X) associated with the functions on the bus.  As interrupts are
+ * set up, torn down, or reaffined, this driver communicates with the
+ * underlying hypervisor to adjust the mappings in the I/O MMU so that each
+ * interrupt will be delivered to the correct virtual processor at the right
+ * vector.  This driver does not support level-triggered (line-based)
+ * interrupts, and will report that the Interrupt Line register in the
+ * function's configuration space is zero.
+ *
+ * The rest of this driver mostly maps PCI concepts onto underlying Hyper-V
+ * facilities.  For instance, the configuration space of a function exposed
+ * by Hyper-V is mapped into a single page of memory space, and the
+ * read and write handlers for config space must be aware of this mechanism.
+ * Similarly, device setup and teardown involves messages sent to and from
+ * the PCI back-end driver in Hyper-V.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/semaphore.h>
+#include <linux/irqdomain.h>
+#include <asm/irqdomain.h>
+#include <asm/apic.h>
+#include <linux/msi.h>
+#include <linux/hyperv.h>
+#include <asm/mshyperv.h>
+
+/*
+ * Protocol versions. The low word is the minor version, the high word the
+ * major version.
+ */
+
+#define PCI_MAKE_VERSION(major, minor) ((u32)(((major) << 16) | (major)))
+#define PCI_MAJOR_VERSION(version) ((u32)(version) >> 16)
+#define PCI_MINOR_VERSION(version) ((u32)(version) & 0xff)
+
+enum {
+       PCI_PROTOCOL_VERSION_1_1 = PCI_MAKE_VERSION(1, 1),
+       PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1
+};
+
+#define PCI_CONFIG_MMIO_LENGTH 0x2000
+#define CFG_PAGE_OFFSET 0x1000
+#define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET)
+
+#define MAX_SUPPORTED_MSI_MESSAGES 0x400
+
+/*
+ * Message Types
+ */
+
+enum pci_message_type {
+       /*
+        * Version 1.1
+        */
+       PCI_MESSAGE_BASE                = 0x42490000,
+       PCI_BUS_RELATIONS               = PCI_MESSAGE_BASE + 0,
+       PCI_QUERY_BUS_RELATIONS         = PCI_MESSAGE_BASE + 1,
+       PCI_POWER_STATE_CHANGE          = PCI_MESSAGE_BASE + 4,
+       PCI_QUERY_RESOURCE_REQUIREMENTS = PCI_MESSAGE_BASE + 5,
+       PCI_QUERY_RESOURCE_RESOURCES    = PCI_MESSAGE_BASE + 6,
+       PCI_BUS_D0ENTRY                 = PCI_MESSAGE_BASE + 7,
+       PCI_BUS_D0EXIT                  = PCI_MESSAGE_BASE + 8,
+       PCI_READ_BLOCK                  = PCI_MESSAGE_BASE + 9,
+       PCI_WRITE_BLOCK                 = PCI_MESSAGE_BASE + 0xA,
+       PCI_EJECT                       = PCI_MESSAGE_BASE + 0xB,
+       PCI_QUERY_STOP                  = PCI_MESSAGE_BASE + 0xC,
+       PCI_REENABLE                    = PCI_MESSAGE_BASE + 0xD,
+       PCI_QUERY_STOP_FAILED           = PCI_MESSAGE_BASE + 0xE,
+       PCI_EJECTION_COMPLETE           = PCI_MESSAGE_BASE + 0xF,
+       PCI_RESOURCES_ASSIGNED          = PCI_MESSAGE_BASE + 0x10,
+       PCI_RESOURCES_RELEASED          = PCI_MESSAGE_BASE + 0x11,
+       PCI_INVALIDATE_BLOCK            = PCI_MESSAGE_BASE + 0x12,
+       PCI_QUERY_PROTOCOL_VERSION      = PCI_MESSAGE_BASE + 0x13,
+       PCI_CREATE_INTERRUPT_MESSAGE    = PCI_MESSAGE_BASE + 0x14,
+       PCI_DELETE_INTERRUPT_MESSAGE    = PCI_MESSAGE_BASE + 0x15,
+       PCI_MESSAGE_MAXIMUM
+};
+
+/*
+ * Structures defining the virtual PCI Express protocol.
+ */
+
+union pci_version {
+       struct {
+               u16 minor_version;
+               u16 major_version;
+       } parts;
+       u32 version;
+} __packed;
+
+/*
+ * Function numbers are 8-bits wide on Express, as interpreted through ARI,
+ * which is all this driver does.  This representation is the one used in
+ * Windows, which is what is expected when sending this back and forth with
+ * the Hyper-V parent partition.
+ */
+union win_slot_encoding {
+       struct {
+               u32     func:8;
+               u32     reserved:24;
+       } bits;
+       u32 slot;
+} __packed;
+
+/*
+ * Pretty much as defined in the PCI Specifications.
+ */
+struct pci_function_description {
+       u16     v_id;   /* vendor ID */
+       u16     d_id;   /* device ID */
+       u8      rev;
+       u8      prog_intf;
+       u8      subclass;
+       u8      base_class;
+       u32     subsystem_id;
+       union win_slot_encoding win_slot;
+       u32     ser;    /* serial number */
+} __packed;
+
+/**
+ * struct hv_msi_desc
+ * @vector:            IDT entry
+ * @delivery_mode:     As defined in Intel's Programmer's
+ *                     Reference Manual, Volume 3, Chapter 8.
+ * @vector_count:      Number of contiguous entries in the
+ *                     Interrupt Descriptor Table that are
+ *                     occupied by this Message-Signaled
+ *                     Interrupt. For "MSI", as first defined
+ *                     in PCI 2.2, this can be between 1 and
+ *                     32. For "MSI-X," as first defined in PCI
+ *                     3.0, this must be 1, as each MSI-X table
+ *                     entry would have its own descriptor.
+ * @reserved:          Empty space
+ * @cpu_mask:          All the target virtual processors.
+ */
+struct hv_msi_desc {
+       u8      vector;
+       u8      delivery_mode;
+       u16     vector_count;
+       u32     reserved;
+       u64     cpu_mask;
+} __packed;
+
+/**
+ * struct tran_int_desc
+ * @reserved:          unused, padding
+ * @vector_count:      same as in hv_msi_desc
+ * @data:              This is the "data payload" value that is
+ *                     written by the device when it generates
+ *                     a message-signaled interrupt, either MSI
+ *                     or MSI-X.
+ * @address:           This is the address to which the data
+ *                     payload is written on interrupt
+ *                     generation.
+ */
+struct tran_int_desc {
+       u16     reserved;
+       u16     vector_count;
+       u32     data;
+       u64     address;
+} __packed;
+
+/*
+ * A generic message format for virtual PCI.
+ * Specific message formats are defined later in the file.
+ */
+
+struct pci_message {
+       u32 message_type;
+} __packed;
+
+struct pci_child_message {
+       u32 message_type;
+       union win_slot_encoding wslot;
+} __packed;
+
+struct pci_incoming_message {
+       struct vmpacket_descriptor hdr;
+       struct pci_message message_type;
+} __packed;
+
+struct pci_response {
+       struct vmpacket_descriptor hdr;
+       s32 status;                     /* negative values are failures */
+} __packed;
+
+struct pci_packet {
+       void (*completion_func)(void *context, struct pci_response *resp,
+                               int resp_packet_size);
+       void *compl_ctxt;
+       struct pci_message message;
+};
+
+/*
+ * Specific message types supporting the PCI protocol.
+ */
+
+/*
+ * Version negotiation message. Sent from the guest to the host.
+ * The guest is free to try different versions until the host
+ * accepts the version.
+ *
+ * pci_version: The protocol version requested.
+ * is_last_attempt: If TRUE, this is the last version guest will request.
+ * reservedz: Reserved field, set to zero.
+ */
+
+struct pci_version_request {
+       struct pci_message message_type;
+       enum pci_message_type protocol_version;
+} __packed;
+
+/*
+ * Bus D0 Entry.  This is sent from the guest to the host when the virtual
+ * bus (PCI Express port) is ready for action.
+ */
+
+struct pci_bus_d0_entry {
+       struct pci_message message_type;
+       u32 reserved;
+       u64 mmio_base;
+} __packed;
+
+struct pci_bus_relations {
+       struct pci_incoming_message incoming;
+       u32 device_count;
+       struct pci_function_description func[1];
+} __packed;
+
+struct pci_q_res_req_response {
+       struct vmpacket_descriptor hdr;
+       s32 status;                     /* negative values are failures */
+       u32 probed_bar[6];
+} __packed;
+
+struct pci_set_power {
+       struct pci_message message_type;
+       union win_slot_encoding wslot;
+       u32 power_state;                /* In Windows terms */
+       u32 reserved;
+} __packed;
+
+struct pci_set_power_response {
+       struct vmpacket_descriptor hdr;
+       s32 status;                     /* negative values are failures */
+       union win_slot_encoding wslot;
+       u32 resultant_state;            /* In Windows terms */
+       u32 reserved;
+} __packed;
+
+struct pci_resources_assigned {
+       struct pci_message message_type;
+       union win_slot_encoding wslot;
+       u8 memory_range[0x14][6];       /* not used here */
+       u32 msi_descriptors;
+       u32 reserved[4];
+} __packed;
+
+struct pci_create_interrupt {
+       struct pci_message message_type;
+       union win_slot_encoding wslot;
+       struct hv_msi_desc int_desc;
+} __packed;
+
+struct pci_create_int_response {
+       struct pci_response response;
+       u32 reserved;
+       struct tran_int_desc int_desc;
+} __packed;
+
+struct pci_delete_interrupt {
+       struct pci_message message_type;
+       union win_slot_encoding wslot;
+       struct tran_int_desc int_desc;
+} __packed;
+
+struct pci_dev_incoming {
+       struct pci_incoming_message incoming;
+       union win_slot_encoding wslot;
+} __packed;
+
+struct pci_eject_response {
+       u32 message_type;
+       union win_slot_encoding wslot;
+       u32 status;
+} __packed;
+
+static int pci_ring_size = (4 * PAGE_SIZE);
+
+/*
+ * Definitions or interrupt steering hypercall.
+ */
+#define HV_PARTITION_ID_SELF           ((u64)-1)
+#define HVCALL_RETARGET_INTERRUPT      0x7e
+
+struct retarget_msi_interrupt {
+       u64     partition_id;           /* use "self" */
+       u64     device_id;
+       u32     source;                 /* 1 for MSI(-X) */
+       u32     reserved1;
+       u32     address;
+       u32     data;
+       u64     reserved2;
+       u32     vector;
+       u32     flags;
+       u64     vp_mask;
+} __packed;
+
+/*
+ * Driver specific state.
+ */
+
+enum hv_pcibus_state {
+       hv_pcibus_init = 0,
+       hv_pcibus_probed,
+       hv_pcibus_installed,
+       hv_pcibus_maximum
+};
+
+struct hv_pcibus_device {
+       struct pci_sysdata sysdata;
+       enum hv_pcibus_state state;
+       atomic_t remove_lock;
+       struct hv_device *hdev;
+       resource_size_t low_mmio_space;
+       resource_size_t high_mmio_space;
+       struct resource *mem_config;
+       struct resource *low_mmio_res;
+       struct resource *high_mmio_res;
+       struct completion *survey_event;
+       struct completion remove_event;
+       struct pci_bus *pci_bus;
+       spinlock_t config_lock; /* Avoid two threads writing index page */
+       spinlock_t device_list_lock;    /* Protect lists below */
+       void __iomem *cfg_addr;
+
+       struct semaphore enum_sem;
+       struct list_head resources_for_children;
+
+       struct list_head children;
+       struct list_head dr_list;
+       struct work_struct wrk;
+
+       struct msi_domain_info msi_info;
+       struct msi_controller msi_chip;
+       struct irq_domain *irq_domain;
+};
+
+/*
+ * Tracks "Device Relations" messages from the host, which must be both
+ * processed in order and deferred so that they don't run in the context
+ * of the incoming packet callback.
+ */
+struct hv_dr_work {
+       struct work_struct wrk;
+       struct hv_pcibus_device *bus;
+};
+
+struct hv_dr_state {
+       struct list_head list_entry;
+       u32 device_count;
+       struct pci_function_description func[1];
+};
+
+enum hv_pcichild_state {
+       hv_pcichild_init = 0,
+       hv_pcichild_requirements,
+       hv_pcichild_resourced,
+       hv_pcichild_ejecting,
+       hv_pcichild_maximum
+};
+
+enum hv_pcidev_ref_reason {
+       hv_pcidev_ref_invalid = 0,
+       hv_pcidev_ref_initial,
+       hv_pcidev_ref_by_slot,
+       hv_pcidev_ref_packet,
+       hv_pcidev_ref_pnp,
+       hv_pcidev_ref_childlist,
+       hv_pcidev_irqdata,
+       hv_pcidev_ref_max
+};
+
+struct hv_pci_dev {
+       /* List protected by pci_rescan_remove_lock */
+       struct list_head list_entry;
+       atomic_t refs;
+       enum hv_pcichild_state state;
+       struct pci_function_description desc;
+       bool reported_missing;
+       struct hv_pcibus_device *hbus;
+       struct work_struct wrk;
+
+       /*
+        * What would be observed if one wrote 0xFFFFFFFF to a BAR and then
+        * read it back, for each of the BAR offsets within config space.
+        */
+       u32 probed_bar[6];
+};
+
+struct hv_pci_compl {
+       struct completion host_event;
+       s32 completion_status;
+};
+
+/**
+ * hv_pci_generic_compl() - Invoked for a completion packet
+ * @context:           Set up by the sender of the packet.
+ * @resp:              The response packet
+ * @resp_packet_size:  Size in bytes of the packet
+ *
+ * This function is used to trigger an event and report status
+ * for any message for which the completion packet contains a
+ * status and nothing else.
+ */
+static
+void
+hv_pci_generic_compl(void *context, struct pci_response *resp,
+                    int resp_packet_size)
+{
+       struct hv_pci_compl *comp_pkt = context;
+
+       if (resp_packet_size >= offsetofend(struct pci_response, status))
+               comp_pkt->completion_status = resp->status;
+       complete(&comp_pkt->host_event);
+}
+
+static struct hv_pci_dev *get_pcichild_wslot(struct hv_pcibus_device *hbus,
+                                               u32 wslot);
+static void get_pcichild(struct hv_pci_dev *hv_pcidev,
+                        enum hv_pcidev_ref_reason reason);
+static void put_pcichild(struct hv_pci_dev *hv_pcidev,
+                        enum hv_pcidev_ref_reason reason);
+
+static void get_hvpcibus(struct hv_pcibus_device *hv_pcibus);
+static void put_hvpcibus(struct hv_pcibus_device *hv_pcibus);
+
+/**
+ * devfn_to_wslot() - Convert from Linux PCI slot to Windows
+ * @devfn:     The Linux representation of PCI slot
+ *
+ * Windows uses a slightly different representation of PCI slot.
+ *
+ * Return: The Windows representation
+ */
+static u32 devfn_to_wslot(int devfn)
+{
+       union win_slot_encoding wslot;
+
+       wslot.slot = 0;
+       wslot.bits.func = PCI_SLOT(devfn) | (PCI_FUNC(devfn) << 5);
+
+       return wslot.slot;
+}
+
+/**
+ * wslot_to_devfn() - Convert from Windows PCI slot to Linux
+ * @wslot:     The Windows representation of PCI slot
+ *
+ * Windows uses a slightly different representation of PCI slot.
+ *
+ * Return: The Linux representation
+ */
+static int wslot_to_devfn(u32 wslot)
+{
+       union win_slot_encoding slot_no;
+
+       slot_no.slot = wslot;
+       return PCI_DEVFN(0, slot_no.bits.func);
+}
+
+/*
+ * PCI Configuration Space for these root PCI buses is implemented as a pair
+ * of pages in memory-mapped I/O space.  Writing to the first page chooses
+ * the PCI function being written or read.  Once the first page has been
+ * written to, the following page maps in the entire configuration space of
+ * the function.
+ */
+
+/**
+ * _hv_pcifront_read_config() - Internal PCI config read
+ * @hpdev:     The PCI driver's representation of the device
+ * @where:     Offset within config space
+ * @size:      Size of the transfer
+ * @val:       Pointer to the buffer receiving the data
+ */
+static void _hv_pcifront_read_config(struct hv_pci_dev *hpdev, int where,
+                                    int size, u32 *val)
+{
+       unsigned long flags;
+       void __iomem *addr = hpdev->hbus->cfg_addr + CFG_PAGE_OFFSET + where;
+
+       /*
+        * If the attempt is to read the IDs or the ROM BAR, simulate that.
+        */
+       if (where + size <= PCI_COMMAND) {
+               memcpy(val, ((u8 *)&hpdev->desc.v_id) + where, size);
+       } else if (where >= PCI_CLASS_REVISION && where + size <=
+                  PCI_CACHE_LINE_SIZE) {
+               memcpy(val, ((u8 *)&hpdev->desc.rev) + where -
+                      PCI_CLASS_REVISION, size);
+       } else if (where >= PCI_SUBSYSTEM_VENDOR_ID && where + size <=
+                  PCI_ROM_ADDRESS) {
+               memcpy(val, (u8 *)&hpdev->desc.subsystem_id + where -
+                      PCI_SUBSYSTEM_VENDOR_ID, size);
+       } else if (where >= PCI_ROM_ADDRESS && where + size <=
+                  PCI_CAPABILITY_LIST) {
+               /* ROM BARs are unimplemented */
+               *val = 0;
+       } else if (where >= PCI_INTERRUPT_LINE && where + size <=
+                  PCI_INTERRUPT_PIN) {
+               /*
+                * Interrupt Line and Interrupt PIN are hard-wired to zero
+                * because this front-end only supports message-signaled
+                * interrupts.
+                */
+               *val = 0;
+       } else if (where + size <= CFG_PAGE_SIZE) {
+               spin_lock_irqsave(&hpdev->hbus->config_lock, flags);
+               /* Choose the function to be read. (See comment above) */
+               writel(hpdev->desc.win_slot.slot, hpdev->hbus->cfg_addr);
+               /* Read from that function's config space. */
+               switch (size) {
+               case 1:
+                       *val = readb(addr);
+                       break;
+               case 2:
+                       *val = readw(addr);
+                       break;
+               default:
+                       *val = readl(addr);
+                       break;
+               }
+               spin_unlock_irqrestore(&hpdev->hbus->config_lock, flags);
+       } else {
+               dev_err(&hpdev->hbus->hdev->device,
+                       "Attempt to read beyond a function's config space.\n");
+       }
+}
+
+/**
+ * _hv_pcifront_write_config() - Internal PCI config write
+ * @hpdev:     The PCI driver's representation of the device
+ * @where:     Offset within config space
+ * @size:      Size of the transfer
+ * @val:       The data being transferred
+ */
+static void _hv_pcifront_write_config(struct hv_pci_dev *hpdev, int where,
+                                     int size, u32 val)
+{
+       unsigned long flags;
+       void __iomem *addr = hpdev->hbus->cfg_addr + CFG_PAGE_OFFSET + where;
+
+       if (where >= PCI_SUBSYSTEM_VENDOR_ID &&
+           where + size <= PCI_CAPABILITY_LIST) {
+               /* SSIDs and ROM BARs are read-only */
+       } else if (where >= PCI_COMMAND && where + size <= CFG_PAGE_SIZE) {
+               spin_lock_irqsave(&hpdev->hbus->config_lock, flags);
+               /* Choose the function to be written. (See comment above) */
+               writel(hpdev->desc.win_slot.slot, hpdev->hbus->cfg_addr);
+               /* Write to that function's config space. */
+               switch (size) {
+               case 1:
+                       writeb(val, addr);
+                       break;
+               case 2:
+                       writew(val, addr);
+                       break;
+               default:
+                       writel(val, addr);
+                       break;
+               }
+               spin_unlock_irqrestore(&hpdev->hbus->config_lock, flags);
+       } else {
+               dev_err(&hpdev->hbus->hdev->device,
+                       "Attempt to write beyond a function's config space.\n");
+       }
+}
+
+/**
+ * hv_pcifront_read_config() - Read configuration space
+ * @bus: PCI Bus structure
+ * @devfn: Device/function
+ * @where: Offset from base
+ * @size: Byte/word/dword
+ * @val: Value to be read
+ *
+ * Return: PCIBIOS_SUCCESSFUL on success
+ *        PCIBIOS_DEVICE_NOT_FOUND on failure
+ */
+static int hv_pcifront_read_config(struct pci_bus *bus, unsigned int devfn,
+                                  int where, int size, u32 *val)
+{
+       struct hv_pcibus_device *hbus =
+               container_of(bus->sysdata, struct hv_pcibus_device, sysdata);
+       struct hv_pci_dev *hpdev;
+
+       hpdev = get_pcichild_wslot(hbus, devfn_to_wslot(devfn));
+       if (!hpdev)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       _hv_pcifront_read_config(hpdev, where, size, val);
+
+       put_pcichild(hpdev, hv_pcidev_ref_by_slot);
+       return PCIBIOS_SUCCESSFUL;
+}
+
+/**
+ * hv_pcifront_write_config() - Write configuration space
+ * @bus: PCI Bus structure
+ * @devfn: Device/function
+ * @where: Offset from base
+ * @size: Byte/word/dword
+ * @val: Value to be written to device
+ *
+ * Return: PCIBIOS_SUCCESSFUL on success
+ *        PCIBIOS_DEVICE_NOT_FOUND on failure
+ */
+static int hv_pcifront_write_config(struct pci_bus *bus, unsigned int devfn,
+                                   int where, int size, u32 val)
+{
+       struct hv_pcibus_device *hbus =
+           container_of(bus->sysdata, struct hv_pcibus_device, sysdata);
+       struct hv_pci_dev *hpdev;
+
+       hpdev = get_pcichild_wslot(hbus, devfn_to_wslot(devfn));
+       if (!hpdev)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       _hv_pcifront_write_config(hpdev, where, size, val);
+
+       put_pcichild(hpdev, hv_pcidev_ref_by_slot);
+       return PCIBIOS_SUCCESSFUL;
+}
+
+/* PCIe operations */
+static struct pci_ops hv_pcifront_ops = {
+       .read  = hv_pcifront_read_config,
+       .write = hv_pcifront_write_config,
+};
+
+/* Interrupt management hooks */
+static void hv_int_desc_free(struct hv_pci_dev *hpdev,
+                            struct tran_int_desc *int_desc)
+{
+       struct pci_delete_interrupt *int_pkt;
+       struct {
+               struct pci_packet pkt;
+               u8 buffer[sizeof(struct pci_delete_interrupt) -
+                         sizeof(struct pci_message)];
+       } ctxt;
+
+       memset(&ctxt, 0, sizeof(ctxt));
+       int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message;
+       int_pkt->message_type.message_type =
+               PCI_DELETE_INTERRUPT_MESSAGE;
+       int_pkt->wslot.slot = hpdev->desc.win_slot.slot;
+       int_pkt->int_desc = *int_desc;
+       vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt, sizeof(*int_pkt),
+                        (unsigned long)&ctxt.pkt, VM_PKT_DATA_INBAND, 0);
+       kfree(int_desc);
+}
+
+/**
+ * hv_msi_free() - Free the MSI.
+ * @domain:    The interrupt domain pointer
+ * @info:      Extra MSI-related context
+ * @irq:       Identifies the IRQ.
+ *
+ * The Hyper-V parent partition and hypervisor are tracking the
+ * messages that are in use, keeping the interrupt redirection
+ * table up to date.  This callback sends a message that frees
+ * the IRT entry and related tracking nonsense.
+ */
+static void hv_msi_free(struct irq_domain *domain, struct msi_domain_info *info,
+                       unsigned int irq)
+{
+       struct hv_pcibus_device *hbus;
+       struct hv_pci_dev *hpdev;
+       struct pci_dev *pdev;
+       struct tran_int_desc *int_desc;
+       struct irq_data *irq_data = irq_domain_get_irq_data(domain, irq);
+       struct msi_desc *msi = irq_data_get_msi_desc(irq_data);
+
+       pdev = msi_desc_to_pci_dev(msi);
+       hbus = info->data;
+       hpdev = get_pcichild_wslot(hbus, devfn_to_wslot(pdev->devfn));
+       if (!hpdev)
+               return;
+
+       int_desc = irq_data_get_irq_chip_data(irq_data);
+       if (int_desc) {
+               irq_data->chip_data = NULL;
+               hv_int_desc_free(hpdev, int_desc);
+       }
+
+       put_pcichild(hpdev, hv_pcidev_ref_by_slot);
+}
+
+static int hv_set_affinity(struct irq_data *data, const struct cpumask *dest,
+                          bool force)
+{
+       struct irq_data *parent = data->parent_data;
+
+       return parent->chip->irq_set_affinity(parent, dest, force);
+}
+
+void hv_irq_mask(struct irq_data *data)
+{
+       pci_msi_mask_irq(data);
+}
+
+/**
+ * hv_irq_unmask() - "Unmask" the IRQ by setting its current
+ * affinity.
+ * @data:      Describes the IRQ
+ *
+ * Build new a destination for the MSI and make a hypercall to
+ * update the Interrupt Redirection Table. "Device Logical ID"
+ * is built out of this PCI bus's instance GUID and the function
+ * number of the device.
+ */
+void hv_irq_unmask(struct irq_data *data)
+{
+       struct msi_desc *msi_desc = irq_data_get_msi_desc(data);
+       struct irq_cfg *cfg = irqd_cfg(data);
+       struct retarget_msi_interrupt params;
+       struct hv_pcibus_device *hbus;
+       struct cpumask *dest;
+       struct pci_bus *pbus;
+       struct pci_dev *pdev;
+       int cpu;
+
+       dest = irq_data_get_affinity_mask(data);
+       pdev = msi_desc_to_pci_dev(msi_desc);
+       pbus = pdev->bus;
+       hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
+
+       memset(&params, 0, sizeof(params));
+       params.partition_id = HV_PARTITION_ID_SELF;
+       params.source = 1; /* MSI(-X) */
+       params.address = msi_desc->msg.address_lo;
+       params.data = msi_desc->msg.data;
+       params.device_id = (hbus->hdev->dev_instance.b[5] << 24) |
+                          (hbus->hdev->dev_instance.b[4] << 16) |
+                          (hbus->hdev->dev_instance.b[7] << 8) |
+                          (hbus->hdev->dev_instance.b[6] & 0xf8) |
+                          PCI_FUNC(pdev->devfn);
+       params.vector = cfg->vector;
+
+       for_each_cpu_and(cpu, dest, cpu_online_mask)
+               params.vp_mask |= (1ULL << vmbus_cpu_number_to_vp_number(cpu));
+
+       hv_do_hypercall(HVCALL_RETARGET_INTERRUPT, &params, NULL);
+
+       pci_msi_unmask_irq(data);
+}
+
+struct compose_comp_ctxt {
+       struct hv_pci_compl comp_pkt;
+       struct tran_int_desc int_desc;
+};
+
+static void hv_pci_compose_compl(void *context, struct pci_response *resp,
+                                int resp_packet_size)
+{
+       struct compose_comp_ctxt *comp_pkt = context;
+       struct pci_create_int_response *int_resp =
+               (struct pci_create_int_response *)resp;
+
+       comp_pkt->comp_pkt.completion_status = resp->status;
+       comp_pkt->int_desc = int_resp->int_desc;
+       complete(&comp_pkt->comp_pkt.host_event);
+}
+
+/**
+ * hv_compose_msi_msg() - Supplies a valid MSI address/data
+ * @data:      Everything about this MSI
+ * @msg:       Buffer that is filled in by this function
+ *
+ * This function unpacks the IRQ looking for target CPU set, IDT
+ * vector and mode and sends a message to the parent partition
+ * asking for a mapping for that tuple in this partition.  The
+ * response supplies a data value and address to which that data
+ * should be written to trigger that interrupt.
+ */
+static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+       struct irq_cfg *cfg = irqd_cfg(data);
+       struct hv_pcibus_device *hbus;
+       struct hv_pci_dev *hpdev;
+       struct pci_bus *pbus;
+       struct pci_dev *pdev;
+       struct pci_create_interrupt *int_pkt;
+       struct compose_comp_ctxt comp;
+       struct tran_int_desc *int_desc;
+       struct cpumask *affinity;
+       struct {
+               struct pci_packet pkt;
+               u8 buffer[sizeof(struct pci_create_interrupt) -
+                         sizeof(struct pci_message)];
+       } ctxt;
+       int cpu;
+       int ret;
+
+       pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data));
+       pbus = pdev->bus;
+       hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
+       hpdev = get_pcichild_wslot(hbus, devfn_to_wslot(pdev->devfn));
+       if (!hpdev)
+               goto return_null_message;
+
+       /* Free any previous message that might have already been composed. */
+       if (data->chip_data) {
+               int_desc = data->chip_data;
+               data->chip_data = NULL;
+               hv_int_desc_free(hpdev, int_desc);
+       }
+
+       int_desc = kzalloc(sizeof(*int_desc), GFP_KERNEL);
+       if (!int_desc)
+               goto drop_reference;
+
+       memset(&ctxt, 0, sizeof(ctxt));
+       init_completion(&comp.comp_pkt.host_event);
+       ctxt.pkt.completion_func = hv_pci_compose_compl;
+       ctxt.pkt.compl_ctxt = &comp;
+       int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message;
+       int_pkt->message_type.message_type = PCI_CREATE_INTERRUPT_MESSAGE;
+       int_pkt->wslot.slot = hpdev->desc.win_slot.slot;
+       int_pkt->int_desc.vector = cfg->vector;
+       int_pkt->int_desc.vector_count = 1;
+       int_pkt->int_desc.delivery_mode =
+               (apic->irq_delivery_mode == dest_LowestPrio) ? 1 : 0;
+
+       /*
+        * This bit doesn't have to work on machines with more than 64
+        * processors because Hyper-V only supports 64 in a guest.
+        */
+       affinity = irq_data_get_affinity_mask(data);
+       for_each_cpu_and(cpu, affinity, cpu_online_mask) {
+               int_pkt->int_desc.cpu_mask |=
+                       (1ULL << vmbus_cpu_number_to_vp_number(cpu));
+       }
+
+       ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt,
+                              sizeof(*int_pkt), (unsigned long)&ctxt.pkt,
+                              VM_PKT_DATA_INBAND,
+                              VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+       if (!ret)
+               wait_for_completion(&comp.comp_pkt.host_event);
+
+       if (comp.comp_pkt.completion_status < 0) {
+               dev_err(&hbus->hdev->device,
+                       "Request for interrupt failed: 0x%x",
+                       comp.comp_pkt.completion_status);
+               goto free_int_desc;
+       }
+
+       /*
+        * Record the assignment so that this can be unwound later. Using
+        * irq_set_chip_data() here would be appropriate, but the lock it takes
+        * is already held.
+        */
+       *int_desc = comp.int_desc;
+       data->chip_data = int_desc;
+
+       /* Pass up the result. */
+       msg->address_hi = comp.int_desc.address >> 32;
+       msg->address_lo = comp.int_desc.address & 0xffffffff;
+       msg->data = comp.int_desc.data;
+
+       put_pcichild(hpdev, hv_pcidev_ref_by_slot);
+       return;
+
+free_int_desc:
+       kfree(int_desc);
+drop_reference:
+       put_pcichild(hpdev, hv_pcidev_ref_by_slot);
+return_null_message:
+       msg->address_hi = 0;
+       msg->address_lo = 0;
+       msg->data = 0;
+}
+
+/* HW Interrupt Chip Descriptor */
+static struct irq_chip hv_msi_irq_chip = {
+       .name                   = "Hyper-V PCIe MSI",
+       .irq_compose_msi_msg    = hv_compose_msi_msg,
+       .irq_set_affinity       = hv_set_affinity,
+       .irq_ack                = irq_chip_ack_parent,
+       .irq_mask               = hv_irq_mask,
+       .irq_unmask             = hv_irq_unmask,
+};
+
+static irq_hw_number_t hv_msi_domain_ops_get_hwirq(struct msi_domain_info *info,
+                                                  msi_alloc_info_t *arg)
+{
+       return arg->msi_hwirq;
+}
+
+static struct msi_domain_ops hv_msi_ops = {
+       .get_hwirq      = hv_msi_domain_ops_get_hwirq,
+       .msi_prepare    = pci_msi_prepare,
+       .set_desc       = pci_msi_set_desc,
+       .msi_free       = hv_msi_free,
+};
+
+/**
+ * hv_pcie_init_irq_domain() - Initialize IRQ domain
+ * @hbus:      The root PCI bus
+ *
+ * This function creates an IRQ domain which will be used for
+ * interrupts from devices that have been passed through.  These
+ * devices only support MSI and MSI-X, not line-based interrupts
+ * or simulations of line-based interrupts through PCIe's
+ * fabric-layer messages.  Because interrupts are remapped, we
+ * can support multi-message MSI here.
+ *
+ * Return: '0' on success and error value on failure
+ */
+static int hv_pcie_init_irq_domain(struct hv_pcibus_device *hbus)
+{
+       hbus->msi_info.chip = &hv_msi_irq_chip;
+       hbus->msi_info.ops = &hv_msi_ops;
+       hbus->msi_info.flags = (MSI_FLAG_USE_DEF_DOM_OPS |
+               MSI_FLAG_USE_DEF_CHIP_OPS | MSI_FLAG_MULTI_PCI_MSI |
+               MSI_FLAG_PCI_MSIX);
+       hbus->msi_info.handler = handle_edge_irq;
+       hbus->msi_info.handler_name = "edge";
+       hbus->msi_info.data = hbus;
+       hbus->irq_domain = pci_msi_create_irq_domain(hbus->sysdata.fwnode,
+                                                    &hbus->msi_info,
+                                                    x86_vector_domain);
+       if (!hbus->irq_domain) {
+               dev_err(&hbus->hdev->device,
+                       "Failed to build an MSI IRQ domain\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/**
+ * get_bar_size() - Get the address space consumed by a BAR
+ * @bar_val:   Value that a BAR returned after -1 was written
+ *              to it.
+ *
+ * This function returns the size of the BAR, rounded up to 1
+ * page.  It has to be rounded up because the hypervisor's page
+ * table entry that maps the BAR into the VM can't specify an
+ * offset within a page.  The invariant is that the hypervisor
+ * must place any BARs of smaller than page length at the
+ * beginning of a page.
+ *
+ * Return:     Size in bytes of the consumed MMIO space.
+ */
+static u64 get_bar_size(u64 bar_val)
+{
+       return round_up((1 + ~(bar_val & PCI_BASE_ADDRESS_MEM_MASK)),
+                       PAGE_SIZE);
+}
+
+/**
+ * survey_child_resources() - Total all MMIO requirements
+ * @hbus:      Root PCI bus, as understood by this driver
+ */
+static void survey_child_resources(struct hv_pcibus_device *hbus)
+{
+       struct list_head *iter;
+       struct hv_pci_dev *hpdev;
+       resource_size_t bar_size = 0;
+       unsigned long flags;
+       struct completion *event;
+       u64 bar_val;
+       int i;
+
+       /* If nobody is waiting on the answer, don't compute it. */
+       event = xchg(&hbus->survey_event, NULL);
+       if (!event)
+               return;
+
+       /* If the answer has already been computed, go with it. */
+       if (hbus->low_mmio_space || hbus->high_mmio_space) {
+               complete(event);
+               return;
+       }
+
+       spin_lock_irqsave(&hbus->device_list_lock, flags);
+
+       /*
+        * Due to an interesting quirk of the PCI spec, all memory regions
+        * for a child device are a power of 2 in size and aligned in memory,
+        * so it's sufficient to just add them up without tracking alignment.
+        */
+       list_for_each(iter, &hbus->children) {
+               hpdev = container_of(iter, struct hv_pci_dev, list_entry);
+               for (i = 0; i < 6; i++) {
+                       if (hpdev->probed_bar[i] & PCI_BASE_ADDRESS_SPACE_IO)
+                               dev_err(&hbus->hdev->device,
+                                       "There's an I/O BAR in this list!\n");
+
+                       if (hpdev->probed_bar[i] != 0) {
+                               /*
+                                * A probed BAR has all the upper bits set that
+                                * can be changed.
+                                */
+
+                               bar_val = hpdev->probed_bar[i];
+                               if (bar_val & PCI_BASE_ADDRESS_MEM_TYPE_64)
+                                       bar_val |=
+                                       ((u64)hpdev->probed_bar[++i] << 32);
+                               else
+                                       bar_val |= 0xffffffff00000000ULL;
+
+                               bar_size = get_bar_size(bar_val);
+
+                               if (bar_val & PCI_BASE_ADDRESS_MEM_TYPE_64)
+                                       hbus->high_mmio_space += bar_size;
+                               else
+                                       hbus->low_mmio_space += bar_size;
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+       complete(event);
+}
+
+/**
+ * prepopulate_bars() - Fill in BARs with defaults
+ * @hbus:      Root PCI bus, as understood by this driver
+ *
+ * The core PCI driver code seems much, much happier if the BARs
+ * for a device have values upon first scan. So fill them in.
+ * The algorithm below works down from large sizes to small,
+ * attempting to pack the assignments optimally. The assumption,
+ * enforced in other parts of the code, is that the beginning of
+ * the memory-mapped I/O space will be aligned on the largest
+ * BAR size.
+ */
+static void prepopulate_bars(struct hv_pcibus_device *hbus)
+{
+       resource_size_t high_size = 0;
+       resource_size_t low_size = 0;
+       resource_size_t high_base = 0;
+       resource_size_t low_base = 0;
+       resource_size_t bar_size;
+       struct hv_pci_dev *hpdev;
+       struct list_head *iter;
+       unsigned long flags;
+       u64 bar_val;
+       u32 command;
+       bool high;
+       int i;
+
+       if (hbus->low_mmio_space) {
+               low_size = 1ULL << (63 - __builtin_clzll(hbus->low_mmio_space));
+               low_base = hbus->low_mmio_res->start;
+       }
+
+       if (hbus->high_mmio_space) {
+               high_size = 1ULL <<
+                       (63 - __builtin_clzll(hbus->high_mmio_space));
+               high_base = hbus->high_mmio_res->start;
+       }
+
+       spin_lock_irqsave(&hbus->device_list_lock, flags);
+
+       /* Pick addresses for the BARs. */
+       do {
+               list_for_each(iter, &hbus->children) {
+                       hpdev = container_of(iter, struct hv_pci_dev,
+                                            list_entry);
+                       for (i = 0; i < 6; i++) {
+                               bar_val = hpdev->probed_bar[i];
+                               if (bar_val == 0)
+                                       continue;
+                               high = bar_val & PCI_BASE_ADDRESS_MEM_TYPE_64;
+                               if (high) {
+                                       bar_val |=
+                                               ((u64)hpdev->probed_bar[i + 1]
+                                                << 32);
+                               } else {
+                                       bar_val |= 0xffffffffULL << 32;
+                               }
+                               bar_size = get_bar_size(bar_val);
+                               if (high) {
+                                       if (high_size != bar_size) {
+                                               i++;
+                                               continue;
+                                       }
+                                       _hv_pcifront_write_config(hpdev,
+                                               PCI_BASE_ADDRESS_0 + (4 * i),
+                                               4,
+                                               (u32)(high_base & 0xffffff00));
+                                       i++;
+                                       _hv_pcifront_write_config(hpdev,
+                                               PCI_BASE_ADDRESS_0 + (4 * i),
+                                               4, (u32)(high_base >> 32));
+                                       high_base += bar_size;
+                               } else {
+                                       if (low_size != bar_size)
+                                               continue;
+                                       _hv_pcifront_write_config(hpdev,
+                                               PCI_BASE_ADDRESS_0 + (4 * i),
+                                               4,
+                                               (u32)(low_base & 0xffffff00));
+                                       low_base += bar_size;
+                               }
+                       }
+                       if (high_size <= 1 && low_size <= 1) {
+                               /* Set the memory enable bit. */
+                               _hv_pcifront_read_config(hpdev, PCI_COMMAND, 2,
+                                                        &command);
+                               command |= PCI_COMMAND_MEMORY;
+                               _hv_pcifront_write_config(hpdev, PCI_COMMAND, 2,
+                                                         command);
+                               break;
+                       }
+               }
+
+               high_size >>= 1;
+               low_size >>= 1;
+       }  while (high_size || low_size);
+
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+}
+
+/**
+ * create_root_hv_pci_bus() - Expose a new root PCI bus
+ * @hbus:      Root PCI bus, as understood by this driver
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus)
+{
+       /* Register the device */
+       hbus->pci_bus = pci_create_root_bus(&hbus->hdev->device,
+                                           0, /* bus number is always zero */
+                                           &hv_pcifront_ops,
+                                           &hbus->sysdata,
+                                           &hbus->resources_for_children);
+       if (!hbus->pci_bus)
+               return -ENODEV;
+
+       hbus->pci_bus->msi = &hbus->msi_chip;
+       hbus->pci_bus->msi->dev = &hbus->hdev->device;
+
+       pci_scan_child_bus(hbus->pci_bus);
+       pci_bus_assign_resources(hbus->pci_bus);
+       pci_bus_add_devices(hbus->pci_bus);
+       hbus->state = hv_pcibus_installed;
+       return 0;
+}
+
+struct q_res_req_compl {
+       struct completion host_event;
+       struct hv_pci_dev *hpdev;
+};
+
+/**
+ * q_resource_requirements() - Query Resource Requirements
+ * @context:           The completion context.
+ * @resp:              The response that came from the host.
+ * @resp_packet_size:  The size in bytes of resp.
+ *
+ * This function is invoked on completion of a Query Resource
+ * Requirements packet.
+ */
+static void q_resource_requirements(void *context, struct pci_response *resp,
+                                   int resp_packet_size)
+{
+       struct q_res_req_compl *completion = context;
+       struct pci_q_res_req_response *q_res_req =
+               (struct pci_q_res_req_response *)resp;
+       int i;
+
+       if (resp->status < 0) {
+               dev_err(&completion->hpdev->hbus->hdev->device,
+                       "query resource requirements failed: %x\n",
+                       resp->status);
+       } else {
+               for (i = 0; i < 6; i++) {
+                       completion->hpdev->probed_bar[i] =
+                               q_res_req->probed_bar[i];
+               }
+       }
+
+       complete(&completion->host_event);
+}
+
+static void get_pcichild(struct hv_pci_dev *hpdev,
+                           enum hv_pcidev_ref_reason reason)
+{
+       atomic_inc(&hpdev->refs);
+}
+
+static void put_pcichild(struct hv_pci_dev *hpdev,
+                           enum hv_pcidev_ref_reason reason)
+{
+       if (atomic_dec_and_test(&hpdev->refs))
+               kfree(hpdev);
+}
+
+/**
+ * new_pcichild_device() - Create a new child device
+ * @hbus:      The internal struct tracking this root PCI bus.
+ * @desc:      The information supplied so far from the host
+ *              about the device.
+ *
+ * This function creates the tracking structure for a new child
+ * device and kicks off the process of figuring out what it is.
+ *
+ * Return: Pointer to the new tracking struct
+ */
+static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
+               struct pci_function_description *desc)
+{
+       struct hv_pci_dev *hpdev;
+       struct pci_child_message *res_req;
+       struct q_res_req_compl comp_pkt;
+       union {
+       struct pci_packet init_packet;
+               u8 buffer[0x100];
+       } pkt;
+       unsigned long flags;
+       int ret;
+
+       hpdev = kzalloc(sizeof(*hpdev), GFP_ATOMIC);
+       if (!hpdev)
+               return NULL;
+
+       hpdev->hbus = hbus;
+
+       memset(&pkt, 0, sizeof(pkt));
+       init_completion(&comp_pkt.host_event);
+       comp_pkt.hpdev = hpdev;
+       pkt.init_packet.compl_ctxt = &comp_pkt;
+       pkt.init_packet.completion_func = q_resource_requirements;
+       res_req = (struct pci_child_message *)&pkt.init_packet.message;
+       res_req->message_type = PCI_QUERY_RESOURCE_REQUIREMENTS;
+       res_req->wslot.slot = desc->win_slot.slot;
+
+       ret = vmbus_sendpacket(hbus->hdev->channel, res_req,
+                              sizeof(struct pci_child_message),
+                              (unsigned long)&pkt.init_packet,
+                              VM_PKT_DATA_INBAND,
+                              VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+       if (ret)
+               goto error;
+
+       wait_for_completion(&comp_pkt.host_event);
+
+       hpdev->desc = *desc;
+       get_pcichild(hpdev, hv_pcidev_ref_initial);
+       get_pcichild(hpdev, hv_pcidev_ref_childlist);
+       spin_lock_irqsave(&hbus->device_list_lock, flags);
+       list_add_tail(&hpdev->list_entry, &hbus->children);
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+       return hpdev;
+
+error:
+       kfree(hpdev);
+       return NULL;
+}
+
+/**
+ * get_pcichild_wslot() - Find device from slot
+ * @hbus:      Root PCI bus, as understood by this driver
+ * @wslot:     Location on the bus
+ *
+ * This function looks up a PCI device and returns the internal
+ * representation of it.  It acquires a reference on it, so that
+ * the device won't be deleted while somebody is using it.  The
+ * caller is responsible for calling put_pcichild() to release
+ * this reference.
+ *
+ * Return:     Internal representation of a PCI device
+ */
+static struct hv_pci_dev *get_pcichild_wslot(struct hv_pcibus_device *hbus,
+                                            u32 wslot)
+{
+       unsigned long flags;
+       struct hv_pci_dev *iter, *hpdev = NULL;
+
+       spin_lock_irqsave(&hbus->device_list_lock, flags);
+       list_for_each_entry(iter, &hbus->children, list_entry) {
+               if (iter->desc.win_slot.slot == wslot) {
+                       hpdev = iter;
+                       get_pcichild(hpdev, hv_pcidev_ref_by_slot);
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+
+       return hpdev;
+}
+
+/**
+ * pci_devices_present_work() - Handle new list of child devices
+ * @work:      Work struct embedded in struct hv_dr_work
+ *
+ * "Bus Relations" is the Windows term for "children of this
+ * bus."  The terminology is preserved here for people trying to
+ * debug the interaction between Hyper-V and Linux.  This
+ * function is called when the parent partition reports a list
+ * of functions that should be observed under this PCI Express
+ * port (bus).
+ *
+ * This function updates the list, and must tolerate being
+ * called multiple times with the same information.  The typical
+ * number of child devices is one, with very atypical cases
+ * involving three or four, so the algorithms used here can be
+ * simple and inefficient.
+ *
+ * It must also treat the omission of a previously observed device as
+ * notification that the device no longer exists.
+ *
+ * Note that this function is a work item, and it may not be
+ * invoked in the order that it was queued.  Back to back
+ * updates of the list of present devices may involve queuing
+ * multiple work items, and this one may run before ones that
+ * were sent later. As such, this function only does something
+ * if is the last one in the queue.
+ */
+static void pci_devices_present_work(struct work_struct *work)
+{
+       u32 child_no;
+       bool found;
+       struct list_head *iter;
+       struct pci_function_description *new_desc;
+       struct hv_pci_dev *hpdev;
+       struct hv_pcibus_device *hbus;
+       struct list_head removed;
+       struct hv_dr_work *dr_wrk;
+       struct hv_dr_state *dr = NULL;
+       unsigned long flags;
+
+       dr_wrk = container_of(work, struct hv_dr_work, wrk);
+       hbus = dr_wrk->bus;
+       kfree(dr_wrk);
+
+       INIT_LIST_HEAD(&removed);
+
+       if (down_interruptible(&hbus->enum_sem)) {
+               put_hvpcibus(hbus);
+               return;
+       }
+
+       /* Pull this off the queue and process it if it was the last one. */
+       spin_lock_irqsave(&hbus->device_list_lock, flags);
+       while (!list_empty(&hbus->dr_list)) {
+               dr = list_first_entry(&hbus->dr_list, struct hv_dr_state,
+                                     list_entry);
+               list_del(&dr->list_entry);
+
+               /* Throw this away if the list still has stuff in it. */
+               if (!list_empty(&hbus->dr_list)) {
+                       kfree(dr);
+                       continue;
+               }
+       }
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+
+       if (!dr) {
+               up(&hbus->enum_sem);
+               put_hvpcibus(hbus);
+               return;
+       }
+
+       /* First, mark all existing children as reported missing. */
+       spin_lock_irqsave(&hbus->device_list_lock, flags);
+       list_for_each(iter, &hbus->children) {
+                       hpdev = container_of(iter, struct hv_pci_dev,
+                                            list_entry);
+                       hpdev->reported_missing = true;
+       }
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+
+       /* Next, add back any reported devices. */
+       for (child_no = 0; child_no < dr->device_count; child_no++) {
+               found = false;
+               new_desc = &dr->func[child_no];
+
+               spin_lock_irqsave(&hbus->device_list_lock, flags);
+               list_for_each(iter, &hbus->children) {
+                       hpdev = container_of(iter, struct hv_pci_dev,
+                                            list_entry);
+                       if ((hpdev->desc.win_slot.slot ==
+                            new_desc->win_slot.slot) &&
+                           (hpdev->desc.v_id == new_desc->v_id) &&
+                           (hpdev->desc.d_id == new_desc->d_id) &&
+                           (hpdev->desc.ser == new_desc->ser)) {
+                               hpdev->reported_missing = false;
+                               found = true;
+                       }
+               }
+               spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+
+               if (!found) {
+                       hpdev = new_pcichild_device(hbus, new_desc);
+                       if (!hpdev)
+                               dev_err(&hbus->hdev->device,
+                                       "couldn't record a child device.\n");
+               }
+       }
+
+       /* Move missing children to a list on the stack. */
+       spin_lock_irqsave(&hbus->device_list_lock, flags);
+       do {
+               found = false;
+               list_for_each(iter, &hbus->children) {
+                       hpdev = container_of(iter, struct hv_pci_dev,
+                                            list_entry);
+                       if (hpdev->reported_missing) {
+                               found = true;
+                               put_pcichild(hpdev, hv_pcidev_ref_childlist);
+                               list_del(&hpdev->list_entry);
+                               list_add_tail(&hpdev->list_entry, &removed);
+                               break;
+                       }
+               }
+       } while (found);
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+
+       /* Delete everything that should no longer exist. */
+       while (!list_empty(&removed)) {
+               hpdev = list_first_entry(&removed, struct hv_pci_dev,
+                                        list_entry);
+               list_del(&hpdev->list_entry);
+               put_pcichild(hpdev, hv_pcidev_ref_initial);
+       }
+
+       /* Tell the core to rescan bus because there may have been changes. */
+       if (hbus->state == hv_pcibus_installed) {
+               pci_lock_rescan_remove();
+               pci_scan_child_bus(hbus->pci_bus);
+               pci_unlock_rescan_remove();
+       } else {
+               survey_child_resources(hbus);
+       }
+
+       up(&hbus->enum_sem);
+       put_hvpcibus(hbus);
+       kfree(dr);
+}
+
+/**
+ * hv_pci_devices_present() - Handles list of new children
+ * @hbus:      Root PCI bus, as understood by this driver
+ * @relations: Packet from host listing children
+ *
+ * This function is invoked whenever a new list of devices for
+ * this bus appears.
+ */
+static void hv_pci_devices_present(struct hv_pcibus_device *hbus,
+                                  struct pci_bus_relations *relations)
+{
+       struct hv_dr_state *dr;
+       struct hv_dr_work *dr_wrk;
+       unsigned long flags;
+
+       dr_wrk = kzalloc(sizeof(*dr_wrk), GFP_NOWAIT);
+       if (!dr_wrk)
+               return;
+
+       dr = kzalloc(offsetof(struct hv_dr_state, func) +
+                    (sizeof(struct pci_function_description) *
+                     (relations->device_count)), GFP_NOWAIT);
+       if (!dr)  {
+               kfree(dr_wrk);
+               return;
+       }
+
+       INIT_WORK(&dr_wrk->wrk, pci_devices_present_work);
+       dr_wrk->bus = hbus;
+       dr->device_count = relations->device_count;
+       if (dr->device_count != 0) {
+               memcpy(dr->func, relations->func,
+                      sizeof(struct pci_function_description) *
+                      dr->device_count);
+       }
+
+       spin_lock_irqsave(&hbus->device_list_lock, flags);
+       list_add_tail(&dr->list_entry, &hbus->dr_list);
+       spin_unlock_irqrestore(&hbus->device_list_lock, flags);
+
+       get_hvpcibus(hbus);
+       schedule_work(&dr_wrk->wrk);
+}
+
+/**
+ * hv_eject_device_work() - Asynchronously handles ejection
+ * @work:      Work struct embedded in internal device struct
+ *
+ * This function handles ejecting a device.  Windows will
+ * attempt to gracefully eject a device, waiting 60 seconds to
+ * hear back from the guest OS that this completed successfully.
+ * If this timer expires, the device will be forcibly removed.
+ */
+static void hv_eject_device_work(struct work_struct *work)
+{
+       struct pci_eject_response *ejct_pkt;
+       struct hv_pci_dev *hpdev;
+       struct pci_dev *pdev;
+       unsigned long flags;
+       int wslot;
+       struct {
+               struct pci_packet pkt;
+               u8 buffer[sizeof(struct pci_eject_response) -
+                         sizeof(struct pci_message)];
+       } ctxt;
+
+       hpdev = container_of(work, struct hv_pci_dev, wrk);
+
+       if (hpdev->state != hv_pcichild_ejecting) {
+               put_pcichild(hpdev, hv_pcidev_ref_pnp);
+               return;
+       }
+
+       /*
+        * Ejection can come before or after the PCI bus has been set up, so
+        * attempt to find it and tear down the bus state, if it exists.  This
+        * must be done without constructs like pci_domain_nr(hbus->pci_bus)
+        * because hbus->pci_bus may not exist yet.
+        */
+       wslot = wslot_to_devfn(hpdev->desc.win_slot.slot);
+       pdev = pci_get_domain_bus_and_slot(hpdev->hbus->sysdata.domain, 0,
+                                          wslot);
+       if (pdev) {
+               pci_stop_and_remove_bus_device(pdev);
+               pci_dev_put(pdev);
+       }
+
+       memset(&ctxt, 0, sizeof(ctxt));
+       ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message;
+       ejct_pkt->message_type = PCI_EJECTION_COMPLETE;
+       ejct_pkt->wslot.slot = hpdev->desc.win_slot.slot;
+       vmbus_sendpacket(hpdev->hbus->hdev->channel, ejct_pkt,
+                        sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt,
+                        VM_PKT_DATA_INBAND, 0);
+
+       spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags);
+       list_del(&hpdev->list_entry);
+       spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags);
+
+       put_pcichild(hpdev, hv_pcidev_ref_childlist);
+       put_pcichild(hpdev, hv_pcidev_ref_pnp);
+       put_hvpcibus(hpdev->hbus);
+}
+
+/**
+ * hv_pci_eject_device() - Handles device ejection
+ * @hpdev:     Internal device tracking struct
+ *
+ * This function is invoked when an ejection packet arrives.  It
+ * just schedules work so that we don't re-enter the packet
+ * delivery code handling the ejection.
+ */
+static void hv_pci_eject_device(struct hv_pci_dev *hpdev)
+{
+       hpdev->state = hv_pcichild_ejecting;
+       get_pcichild(hpdev, hv_pcidev_ref_pnp);
+       INIT_WORK(&hpdev->wrk, hv_eject_device_work);
+       get_hvpcibus(hpdev->hbus);
+       schedule_work(&hpdev->wrk);
+}
+
+/**
+ * hv_pci_onchannelcallback() - Handles incoming packets
+ * @context:   Internal bus tracking struct
+ *
+ * This function is invoked whenever the host sends a packet to
+ * this channel (which is private to this root PCI bus).
+ */
+static void hv_pci_onchannelcallback(void *context)
+{
+       const int packet_size = 0x100;
+       int ret;
+       struct hv_pcibus_device *hbus = context;
+       u32 bytes_recvd;
+       u64 req_id;
+       struct vmpacket_descriptor *desc;
+       unsigned char *buffer;
+       int bufferlen = packet_size;
+       struct pci_packet *comp_packet;
+       struct pci_response *response;
+       struct pci_incoming_message *new_message;
+       struct pci_bus_relations *bus_rel;
+       struct pci_dev_incoming *dev_message;
+       struct hv_pci_dev *hpdev;
+
+       buffer = kmalloc(bufferlen, GFP_ATOMIC);
+       if (!buffer)
+               return;
+
+       while (1) {
+               ret = vmbus_recvpacket_raw(hbus->hdev->channel, buffer,
+                                          bufferlen, &bytes_recvd, &req_id);
+
+               if (ret == -ENOBUFS) {
+                       kfree(buffer);
+                       /* Handle large packet */
+                       bufferlen = bytes_recvd;
+                       buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
+                       if (!buffer)
+                               return;
+                       continue;
+               }
+
+               /*
+                * All incoming packets must be at least as large as a
+                * response.
+                */
+               if (bytes_recvd <= sizeof(struct pci_response)) {
+                       kfree(buffer);
+                       return;
+               }
+               desc = (struct vmpacket_descriptor *)buffer;
+
+               switch (desc->type) {
+               case VM_PKT_COMP:
+
+                       /*
+                        * The host is trusted, and thus it's safe to interpret
+                        * this transaction ID as a pointer.
+                        */
+                       comp_packet = (struct pci_packet *)req_id;
+                       response = (struct pci_response *)buffer;
+                       comp_packet->completion_func(comp_packet->compl_ctxt,
+                                                    response,
+                                                    bytes_recvd);
+                       kfree(buffer);
+                       return;
+
+               case VM_PKT_DATA_INBAND:
+
+                       new_message = (struct pci_incoming_message *)buffer;
+                       switch (new_message->message_type.message_type) {
+                       case PCI_BUS_RELATIONS:
+
+                               bus_rel = (struct pci_bus_relations *)buffer;
+                               if (bytes_recvd <
+                                   offsetof(struct pci_bus_relations, func) +
+                                   (sizeof(struct pci_function_description) *
+                                    (bus_rel->device_count))) {
+                                       dev_err(&hbus->hdev->device,
+                                               "bus relations too small\n");
+                                       break;
+                               }
+
+                               hv_pci_devices_present(hbus, bus_rel);
+                               break;
+
+                       case PCI_EJECT:
+
+                               dev_message = (struct pci_dev_incoming *)buffer;
+                               hpdev = get_pcichild_wslot(hbus,
+                                                     dev_message->wslot.slot);
+                               if (hpdev) {
+                                       hv_pci_eject_device(hpdev);
+                                       put_pcichild(hpdev,
+                                                       hv_pcidev_ref_by_slot);
+                               }
+                               break;
+
+                       default:
+                               dev_warn(&hbus->hdev->device,
+                                       "Unimplemented protocol message %x\n",
+                                       new_message->message_type.message_type);
+                               break;
+                       }
+                       break;
+
+               default:
+                       dev_err(&hbus->hdev->device,
+                               "unhandled packet type %d, tid %llx len %d\n",
+                               desc->type, req_id, bytes_recvd);
+                       break;
+               }
+               break;
+       }
+}
+
+/**
+ * hv_pci_protocol_negotiation() - Set up protocol
+ * @hdev:      VMBus's tracking struct for this root PCI bus
+ *
+ * This driver is intended to support running on Windows 10
+ * (server) and later versions. It will not run on earlier
+ * versions, as they assume that many of the operations which
+ * Linux needs accomplished with a spinlock held were done via
+ * asynchronous messaging via VMBus.  Windows 10 increases the
+ * surface area of PCI emulation so that these actions can take
+ * place by suspending a virtual processor for their duration.
+ *
+ * This function negotiates the channel protocol version,
+ * failing if the host doesn't support the necessary protocol
+ * level.
+ */
+static int hv_pci_protocol_negotiation(struct hv_device *hdev)
+{
+       struct pci_version_request *version_req;
+       struct hv_pci_compl comp_pkt;
+       struct pci_packet *pkt;
+       int ret;
+
+       /*
+        * Initiate the handshake with the host and negotiate
+        * a version that the host can support. We start with the
+        * highest version number and go down if the host cannot
+        * support it.
+        */
+       pkt = kzalloc(sizeof(*pkt) + sizeof(*version_req), GFP_KERNEL);
+       if (!pkt)
+               return -ENOMEM;
+
+       init_completion(&comp_pkt.host_event);
+       pkt->completion_func = hv_pci_generic_compl;
+       pkt->compl_ctxt = &comp_pkt;
+       version_req = (struct pci_version_request *)&pkt->message;
+       version_req->message_type.message_type = PCI_QUERY_PROTOCOL_VERSION;
+       version_req->protocol_version = PCI_PROTOCOL_VERSION_CURRENT;
+
+       ret = vmbus_sendpacket(hdev->channel, version_req,
+                              sizeof(struct pci_version_request),
+                              (unsigned long)pkt, VM_PKT_DATA_INBAND,
+                              VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+       if (ret)
+               goto exit;
+
+       wait_for_completion(&comp_pkt.host_event);
+
+       if (comp_pkt.completion_status < 0) {
+               dev_err(&hdev->device,
+                       "PCI Pass-through VSP failed version request %x\n",
+                       comp_pkt.completion_status);
+               ret = -EPROTO;
+               goto exit;
+       }
+
+       ret = 0;
+
+exit:
+       kfree(pkt);
+       return ret;
+}
+
+/**
+ * hv_pci_free_bridge_windows() - Release memory regions for the
+ * bus
+ * @hbus:      Root PCI bus, as understood by this driver
+ */
+static void hv_pci_free_bridge_windows(struct hv_pcibus_device *hbus)
+{
+       /*
+        * Set the resources back to the way they looked when they
+        * were allocated by setting IORESOURCE_BUSY again.
+        */
+
+       if (hbus->low_mmio_space && hbus->low_mmio_res) {
+               hbus->low_mmio_res->flags |= IORESOURCE_BUSY;
+               release_mem_region(hbus->low_mmio_res->start,
+                                  resource_size(hbus->low_mmio_res));
+       }
+
+       if (hbus->high_mmio_space && hbus->high_mmio_res) {
+               hbus->high_mmio_res->flags |= IORESOURCE_BUSY;
+               release_mem_region(hbus->high_mmio_res->start,
+                                  resource_size(hbus->high_mmio_res));
+       }
+}
+
+/**
+ * hv_pci_allocate_bridge_windows() - Allocate memory regions
+ * for the bus
+ * @hbus:      Root PCI bus, as understood by this driver
+ *
+ * This function calls vmbus_allocate_mmio(), which is itself a
+ * bit of a compromise.  Ideally, we might change the pnp layer
+ * in the kernel such that it comprehends either PCI devices
+ * which are "grandchildren of ACPI," with some intermediate bus
+ * node (in this case, VMBus) or change it such that it
+ * understands VMBus.  The pnp layer, however, has been declared
+ * deprecated, and not subject to change.
+ *
+ * The workaround, implemented here, is to ask VMBus to allocate
+ * MMIO space for this bus.  VMBus itself knows which ranges are
+ * appropriate by looking at its own ACPI objects.  Then, after
+ * these ranges are claimed, they're modified to look like they
+ * would have looked if the ACPI and pnp code had allocated
+ * bridge windows.  These descriptors have to exist in this form
+ * in order to satisfy the code which will get invoked when the
+ * endpoint PCI function driver calls request_mem_region() or
+ * request_mem_region_exclusive().
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int hv_pci_allocate_bridge_windows(struct hv_pcibus_device *hbus)
+{
+       resource_size_t align;
+       int ret;
+
+       if (hbus->low_mmio_space) {
+               align = 1ULL << (63 - __builtin_clzll(hbus->low_mmio_space));
+               ret = vmbus_allocate_mmio(&hbus->low_mmio_res, hbus->hdev, 0,
+                                         (u64)(u32)0xffffffff,
+                                         hbus->low_mmio_space,
+                                         align, false);
+               if (ret) {
+                       dev_err(&hbus->hdev->device,
+                               "Need %#llx of low MMIO space. Consider reconfiguring the VM.\n",
+                               hbus->low_mmio_space);
+                       return ret;
+               }
+
+               /* Modify this resource to become a bridge window. */
+               hbus->low_mmio_res->flags |= IORESOURCE_WINDOW;
+               hbus->low_mmio_res->flags &= ~IORESOURCE_BUSY;
+               pci_add_resource(&hbus->resources_for_children,
+                                hbus->low_mmio_res);
+       }
+
+       if (hbus->high_mmio_space) {
+               align = 1ULL << (63 - __builtin_clzll(hbus->high_mmio_space));
+               ret = vmbus_allocate_mmio(&hbus->high_mmio_res, hbus->hdev,
+                                         0x100000000, -1,
+                                         hbus->high_mmio_space, align,
+                                         false);
+               if (ret) {
+                       dev_err(&hbus->hdev->device,
+                               "Need %#llx of high MMIO space. Consider reconfiguring the VM.\n",
+                               hbus->high_mmio_space);
+                       goto release_low_mmio;
+               }
+
+               /* Modify this resource to become a bridge window. */
+               hbus->high_mmio_res->flags |= IORESOURCE_WINDOW;
+               hbus->high_mmio_res->flags &= ~IORESOURCE_BUSY;
+               pci_add_resource(&hbus->resources_for_children,
+                                hbus->high_mmio_res);
+       }
+
+       return 0;
+
+release_low_mmio:
+       if (hbus->low_mmio_res) {
+               release_mem_region(hbus->low_mmio_res->start,
+                                  resource_size(hbus->low_mmio_res));
+       }
+
+       return ret;
+}
+
+/**
+ * hv_allocate_config_window() - Find MMIO space for PCI Config
+ * @hbus:      Root PCI bus, as understood by this driver
+ *
+ * This function claims memory-mapped I/O space for accessing
+ * configuration space for the functions on this bus.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int hv_allocate_config_window(struct hv_pcibus_device *hbus)
+{
+       int ret;
+
+       /*
+        * Set up a region of MMIO space to use for accessing configuration
+        * space.
+        */
+       ret = vmbus_allocate_mmio(&hbus->mem_config, hbus->hdev, 0, -1,
+                                 PCI_CONFIG_MMIO_LENGTH, 0x1000, false);
+       if (ret)
+               return ret;
+
+       /*
+        * vmbus_allocate_mmio() gets used for allocating both device endpoint
+        * resource claims (those which cannot be overlapped) and the ranges
+        * which are valid for the children of this bus, which are intended
+        * to be overlapped by those children.  Set the flag on this claim
+        * meaning that this region can't be overlapped.
+        */
+
+       hbus->mem_config->flags |= IORESOURCE_BUSY;
+
+       return 0;
+}
+
+static void hv_free_config_window(struct hv_pcibus_device *hbus)
+{
+       release_mem_region(hbus->mem_config->start, PCI_CONFIG_MMIO_LENGTH);
+}
+
+/**
+ * hv_pci_enter_d0() - Bring the "bus" into the D0 power state
+ * @hdev:      VMBus's tracking struct for this root PCI bus
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int hv_pci_enter_d0(struct hv_device *hdev)
+{
+       struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
+       struct pci_bus_d0_entry *d0_entry;
+       struct hv_pci_compl comp_pkt;
+       struct pci_packet *pkt;
+       int ret;
+
+       /*
+        * Tell the host that the bus is ready to use, and moved into the
+        * powered-on state.  This includes telling the host which region
+        * of memory-mapped I/O space has been chosen for configuration space
+        * access.
+        */
+       pkt = kzalloc(sizeof(*pkt) + sizeof(*d0_entry), GFP_KERNEL);
+       if (!pkt)
+               return -ENOMEM;
+
+       init_completion(&comp_pkt.host_event);
+       pkt->completion_func = hv_pci_generic_compl;
+       pkt->compl_ctxt = &comp_pkt;
+       d0_entry = (struct pci_bus_d0_entry *)&pkt->message;
+       d0_entry->message_type.message_type = PCI_BUS_D0ENTRY;
+       d0_entry->mmio_base = hbus->mem_config->start;
+
+       ret = vmbus_sendpacket(hdev->channel, d0_entry, sizeof(*d0_entry),
+                              (unsigned long)pkt, VM_PKT_DATA_INBAND,
+                              VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+       if (ret)
+               goto exit;
+
+       wait_for_completion(&comp_pkt.host_event);
+
+       if (comp_pkt.completion_status < 0) {
+               dev_err(&hdev->device,
+                       "PCI Pass-through VSP failed D0 Entry with status %x\n",
+                       comp_pkt.completion_status);
+               ret = -EPROTO;
+               goto exit;
+       }
+
+       ret = 0;
+
+exit:
+       kfree(pkt);
+       return ret;
+}
+
+/**
+ * hv_pci_query_relations() - Ask host to send list of child
+ * devices
+ * @hdev:      VMBus's tracking struct for this root PCI bus
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int hv_pci_query_relations(struct hv_device *hdev)
+{
+       struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
+       struct pci_message message;
+       struct completion comp;
+       int ret;
+
+       /* Ask the host to send along the list of child devices */
+       init_completion(&comp);
+       if (cmpxchg(&hbus->survey_event, NULL, &comp))
+               return -ENOTEMPTY;
+
+       memset(&message, 0, sizeof(message));
+       message.message_type = PCI_QUERY_BUS_RELATIONS;
+
+       ret = vmbus_sendpacket(hdev->channel, &message, sizeof(message),
+                              0, VM_PKT_DATA_INBAND, 0);
+       if (ret)
+               return ret;
+
+       wait_for_completion(&comp);
+       return 0;
+}
+
+/**
+ * hv_send_resources_allocated() - Report local resource choices
+ * @hdev:      VMBus's tracking struct for this root PCI bus
+ *
+ * The host OS is expecting to be sent a request as a message
+ * which contains all the resources that the device will use.
+ * The response contains those same resources, "translated"
+ * which is to say, the values which should be used by the
+ * hardware, when it delivers an interrupt.  (MMIO resources are
+ * used in local terms.)  This is nice for Windows, and lines up
+ * with the FDO/PDO split, which doesn't exist in Linux.  Linux
+ * is deeply expecting to scan an emulated PCI configuration
+ * space.  So this message is sent here only to drive the state
+ * machine on the host forward.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int hv_send_resources_allocated(struct hv_device *hdev)
+{
+       struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
+       struct pci_resources_assigned *res_assigned;
+       struct hv_pci_compl comp_pkt;
+       struct hv_pci_dev *hpdev;
+       struct pci_packet *pkt;
+       u32 wslot;
+       int ret;
+
+       pkt = kmalloc(sizeof(*pkt) + sizeof(*res_assigned), GFP_KERNEL);
+       if (!pkt)
+               return -ENOMEM;
+
+       ret = 0;
+
+       for (wslot = 0; wslot < 256; wslot++) {
+               hpdev = get_pcichild_wslot(hbus, wslot);
+               if (!hpdev)
+                       continue;
+
+               memset(pkt, 0, sizeof(*pkt) + sizeof(*res_assigned));
+               init_completion(&comp_pkt.host_event);
+               pkt->completion_func = hv_pci_generic_compl;
+               pkt->compl_ctxt = &comp_pkt;
+               pkt->message.message_type = PCI_RESOURCES_ASSIGNED;
+               res_assigned = (struct pci_resources_assigned *)&pkt->message;
+               res_assigned->wslot.slot = hpdev->desc.win_slot.slot;
+
+               put_pcichild(hpdev, hv_pcidev_ref_by_slot);
+
+               ret = vmbus_sendpacket(
+                       hdev->channel, &pkt->message,
+                       sizeof(*res_assigned),
+                       (unsigned long)pkt,
+                       VM_PKT_DATA_INBAND,
+                       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+               if (ret)
+                       break;
+
+               wait_for_completion(&comp_pkt.host_event);
+
+               if (comp_pkt.completion_status < 0) {
+                       ret = -EPROTO;
+                       dev_err(&hdev->device,
+                               "resource allocated returned 0x%x",
+                               comp_pkt.completion_status);
+                       break;
+               }
+       }
+
+       kfree(pkt);
+       return ret;
+}
+
+/**
+ * hv_send_resources_released() - Report local resources
+ * released
+ * @hdev:      VMBus's tracking struct for this root PCI bus
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int hv_send_resources_released(struct hv_device *hdev)
+{
+       struct hv_pcibus_device *hbus = hv_get_drvdata(hdev);
+       struct pci_child_message pkt;
+       struct hv_pci_dev *hpdev;
+       u32 wslot;
+       int ret;
+
+       for (wslot = 0; wslot < 256; wslot++) {
+               hpdev = get_pcichild_wslot(hbus, wslot);
+               if (!hpdev)
+                       continue;
+
+               memset(&pkt, 0, sizeof(pkt));
+               pkt.message_type = PCI_RESOURCES_RELEASED;
+               pkt.wslot.slot = hpdev->desc.win_slot.slot;
+
+               put_pcichild(hpdev, hv_pcidev_ref_by_slot);
+
+               ret = vmbus_sendpacket(hdev->channel, &pkt, sizeof(pkt), 0,
+                                      VM_PKT_DATA_INBAND, 0);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void get_hvpcibus(struct hv_pcibus_device *hbus)
+{
+       atomic_inc(&hbus->remove_lock);
+}
+
+static void put_hvpcibus(struct hv_pcibus_device *hbus)
+{
+       if (atomic_dec_and_test(&hbus->remove_lock))
+               complete(&hbus->remove_event);
+}
+
+/**
+ * hv_pci_probe() - New VMBus channel probe, for a root PCI bus
+ * @hdev:      VMBus's tracking struct for this root PCI bus
+ * @dev_id:    Identifies the device itself
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int hv_pci_probe(struct hv_device *hdev,
+                       const struct hv_vmbus_device_id *dev_id)
+{
+       struct hv_pcibus_device *hbus;
+       int ret;
+
+       hbus = kzalloc(sizeof(*hbus), GFP_KERNEL);
+       if (!hbus)
+               return -ENOMEM;
+
+       /*
+        * The PCI bus "domain" is what is called "segment" in ACPI and
+        * other specs.  Pull it from the instance ID, to get something
+        * unique.  Bytes 8 and 9 are what is used in Windows guests, so
+        * do the same thing for consistency.  Note that, since this code
+        * only runs in a Hyper-V VM, Hyper-V can (and does) guarantee
+        * that (1) the only domain in use for something that looks like
+        * a physical PCI bus (which is actually emulated by the
+        * hypervisor) is domain 0 and (2) there will be no overlap
+        * between domains derived from these instance IDs in the same
+        * VM.
+        */
+       hbus->sysdata.domain = hdev->dev_instance.b[9] |
+                              hdev->dev_instance.b[8] << 8;
+
+       hbus->hdev = hdev;
+       atomic_inc(&hbus->remove_lock);
+       INIT_LIST_HEAD(&hbus->children);
+       INIT_LIST_HEAD(&hbus->dr_list);
+       INIT_LIST_HEAD(&hbus->resources_for_children);
+       spin_lock_init(&hbus->config_lock);
+       spin_lock_init(&hbus->device_list_lock);
+       sema_init(&hbus->enum_sem, 1);
+       init_completion(&hbus->remove_event);
+
+       ret = vmbus_open(hdev->channel, pci_ring_size, pci_ring_size, NULL, 0,
+                        hv_pci_onchannelcallback, hbus);
+       if (ret)
+               goto free_bus;
+
+       hv_set_drvdata(hdev, hbus);
+
+       ret = hv_pci_protocol_negotiation(hdev);
+       if (ret)
+               goto close;
+
+       ret = hv_allocate_config_window(hbus);
+       if (ret)
+               goto close;
+
+       hbus->cfg_addr = ioremap(hbus->mem_config->start,
+                                PCI_CONFIG_MMIO_LENGTH);
+       if (!hbus->cfg_addr) {
+               dev_err(&hdev->device,
+                       "Unable to map a virtual address for config space\n");
+               ret = -ENOMEM;
+               goto free_config;
+       }
+
+       hbus->sysdata.fwnode = irq_domain_alloc_fwnode(hbus);
+       if (!hbus->sysdata.fwnode) {
+               ret = -ENOMEM;
+               goto unmap;
+       }
+
+       ret = hv_pcie_init_irq_domain(hbus);
+       if (ret)
+               goto free_fwnode;
+
+       ret = hv_pci_query_relations(hdev);
+       if (ret)
+               goto free_irq_domain;
+
+       ret = hv_pci_enter_d0(hdev);
+       if (ret)
+               goto free_irq_domain;
+
+       ret = hv_pci_allocate_bridge_windows(hbus);
+       if (ret)
+               goto free_irq_domain;
+
+       ret = hv_send_resources_allocated(hdev);
+       if (ret)
+               goto free_windows;
+
+       prepopulate_bars(hbus);
+
+       hbus->state = hv_pcibus_probed;
+
+       ret = create_root_hv_pci_bus(hbus);
+       if (ret)
+               goto free_windows;
+
+       return 0;
+
+free_windows:
+       hv_pci_free_bridge_windows(hbus);
+free_irq_domain:
+       irq_domain_remove(hbus->irq_domain);
+free_fwnode:
+       irq_domain_free_fwnode(hbus->sysdata.fwnode);
+unmap:
+       iounmap(hbus->cfg_addr);
+free_config:
+       hv_free_config_window(hbus);
+close:
+       vmbus_close(hdev->channel);
+free_bus:
+       kfree(hbus);
+       return ret;
+}
+
+/**
+ * hv_pci_remove() - Remove routine for this VMBus channel
+ * @hdev:      VMBus's tracking struct for this root PCI bus
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int hv_pci_remove(struct hv_device *hdev)
+{
+       int ret;
+       struct hv_pcibus_device *hbus;
+       union {
+               struct pci_packet teardown_packet;
+               u8 buffer[0x100];
+       } pkt;
+       struct pci_bus_relations relations;
+       struct hv_pci_compl comp_pkt;
+
+       hbus = hv_get_drvdata(hdev);
+
+       ret = hv_send_resources_released(hdev);
+       if (ret)
+               dev_err(&hdev->device,
+                       "Couldn't send resources released packet(s)\n");
+
+       memset(&pkt.teardown_packet, 0, sizeof(pkt.teardown_packet));
+       init_completion(&comp_pkt.host_event);
+       pkt.teardown_packet.completion_func = hv_pci_generic_compl;
+       pkt.teardown_packet.compl_ctxt = &comp_pkt;
+       pkt.teardown_packet.message.message_type = PCI_BUS_D0EXIT;
+
+       ret = vmbus_sendpacket(hdev->channel, &pkt.teardown_packet.message,
+                              sizeof(struct pci_message),
+                              (unsigned long)&pkt.teardown_packet,
+                              VM_PKT_DATA_INBAND,
+                              VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+       if (!ret)
+               wait_for_completion_timeout(&comp_pkt.host_event, 10 * HZ);
+
+       if (hbus->state == hv_pcibus_installed) {
+               /* Remove the bus from PCI's point of view. */
+               pci_lock_rescan_remove();
+               pci_stop_root_bus(hbus->pci_bus);
+               pci_remove_root_bus(hbus->pci_bus);
+               pci_unlock_rescan_remove();
+       }
+
+       vmbus_close(hdev->channel);
+
+       /* Delete any children which might still exist. */
+       memset(&relations, 0, sizeof(relations));
+       hv_pci_devices_present(hbus, &relations);
+
+       iounmap(hbus->cfg_addr);
+       hv_free_config_window(hbus);
+       pci_free_resource_list(&hbus->resources_for_children);
+       hv_pci_free_bridge_windows(hbus);
+       irq_domain_remove(hbus->irq_domain);
+       irq_domain_free_fwnode(hbus->sysdata.fwnode);
+       put_hvpcibus(hbus);
+       wait_for_completion(&hbus->remove_event);
+       kfree(hbus);
+       return 0;
+}
+
+static const struct hv_vmbus_device_id hv_pci_id_table[] = {
+       /* PCI Pass-through Class ID */
+       /* 44C4F61D-4444-4400-9D52-802E27EDE19F */
+       { HV_PCIE_GUID, },
+       { },
+};
+
+MODULE_DEVICE_TABLE(vmbus, hv_pci_id_table);
+
+static struct hv_driver hv_pci_drv = {
+       .name           = "hv_pci",
+       .id_table       = hv_pci_id_table,
+       .probe          = hv_pci_probe,
+       .remove         = hv_pci_remove,
+};
+
+static void __exit exit_hv_pci_drv(void)
+{
+       vmbus_driver_unregister(&hv_pci_drv);
+}
+
+static int __init init_hv_pci_drv(void)
+{
+       return vmbus_driver_register(&hv_pci_drv);
+}
+
+module_init(init_hv_pci_drv);
+module_exit(exit_hv_pci_drv);
+
+MODULE_DESCRIPTION("Hyper-V PCI");
+MODULE_LICENSE("GPL v2");
index fe600964fa50177bc17b28627568268608896010..eb5a2755a1646649a7e1aaea263a1cf118a45af4 100644 (file)
@@ -39,6 +39,11 @@ struct imx6_pcie {
        struct pcie_port        pp;
        struct regmap           *iomuxc_gpr;
        void __iomem            *mem_base;
+       u32                     tx_deemph_gen1;
+       u32                     tx_deemph_gen2_3p5db;
+       u32                     tx_deemph_gen2_6db;
+       u32                     tx_swing_full;
+       u32                     tx_swing_low;
 };
 
 /* PCIe Root Complex registers (memory-mapped) */
@@ -202,6 +207,23 @@ static int pcie_phy_write(void __iomem *dbi_base, int addr, int data)
        return 0;
 }
 
+static void imx6_pcie_reset_phy(struct pcie_port *pp)
+{
+       u32 tmp;
+
+       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
+       tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
+               PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
+
+       usleep_range(2000, 3000);
+
+       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
+       tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
+                 PHY_RX_OVRD_IN_LO_RX_PLL_EN);
+       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
+}
+
 /*  Added for PCI abort handling */
 static int imx6q_pcie_abort_handler(unsigned long addr,
                unsigned int fsr, struct pt_regs *regs)
@@ -317,32 +339,32 @@ static void imx6_pcie_init_phy(struct pcie_port *pp)
                        IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
 
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_DEEMPH_GEN1, 0 << 0);
+                          IMX6Q_GPR8_TX_DEEMPH_GEN1,
+                          imx6_pcie->tx_deemph_gen1 << 0);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6);
+                          IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
+                          imx6_pcie->tx_deemph_gen2_3p5db << 6);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12);
+                          IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
+                          imx6_pcie->tx_deemph_gen2_6db << 12);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_SWING_FULL, 127 << 18);
+                          IMX6Q_GPR8_TX_SWING_FULL,
+                          imx6_pcie->tx_swing_full << 18);
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                       IMX6Q_GPR8_TX_SWING_LOW, 127 << 25);
+                          IMX6Q_GPR8_TX_SWING_LOW,
+                          imx6_pcie->tx_swing_low << 25);
 }
 
 static int imx6_pcie_wait_for_link(struct pcie_port *pp)
 {
-       unsigned int retries;
-
-       for (retries = 0; retries < 200; retries++) {
-               if (dw_pcie_link_up(pp))
-                       return 0;
-               usleep_range(100, 1000);
-       }
+       /* check if the link is up or not */
+       if (!dw_pcie_wait_for_link(pp))
+               return 0;
 
-       dev_err(pp->dev, "phy link never came up\n");
        dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
                readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
                readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
-       return -EINVAL;
+       return -ETIMEDOUT;
 }
 
 static int imx6_pcie_wait_for_speed_change(struct pcie_port *pp)
@@ -390,8 +412,10 @@ static int imx6_pcie_establish_link(struct pcie_port *pp)
                        IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
 
        ret = imx6_pcie_wait_for_link(pp);
-       if (ret)
-               return ret;
+       if (ret) {
+               dev_info(pp->dev, "Link never came up\n");
+               goto err_reset_phy;
+       }
 
        /* Allow Gen2 mode after the link is up. */
        tmp = readl(pp->dbi_base + PCIE_RC_LCR);
@@ -410,19 +434,28 @@ static int imx6_pcie_establish_link(struct pcie_port *pp)
        ret = imx6_pcie_wait_for_speed_change(pp);
        if (ret) {
                dev_err(pp->dev, "Failed to bring link up!\n");
-               return ret;
+               goto err_reset_phy;
        }
 
        /* Make sure link training is finished as well! */
        ret = imx6_pcie_wait_for_link(pp);
        if (ret) {
                dev_err(pp->dev, "Failed to bring link up!\n");
-               return ret;
+               goto err_reset_phy;
        }
 
        tmp = readl(pp->dbi_base + PCIE_RC_LCSR);
        dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
+
        return 0;
+
+err_reset_phy:
+       dev_dbg(pp->dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
+               readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
+               readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
+       imx6_pcie_reset_phy(pp);
+
+       return ret;
 }
 
 static void imx6_pcie_host_init(struct pcie_port *pp)
@@ -441,81 +474,10 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
                dw_pcie_msi_init(pp);
 }
 
-static void imx6_pcie_reset_phy(struct pcie_port *pp)
-{
-       u32 tmp;
-
-       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
-       tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
-               PHY_RX_OVRD_IN_LO_RX_PLL_EN);
-       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
-
-       usleep_range(2000, 3000);
-
-       pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp);
-       tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
-                 PHY_RX_OVRD_IN_LO_RX_PLL_EN);
-       pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp);
-}
-
 static int imx6_pcie_link_up(struct pcie_port *pp)
 {
-       u32 rc, debug_r0, rx_valid;
-       int count = 5;
-
-       /*
-        * Test if the PHY reports that the link is up and also that the LTSSM
-        * training finished. There are three possible states of the link when
-        * this code is called:
-        * 1) The link is DOWN (unlikely)
-        *     The link didn't come up yet for some reason. This usually means
-        *     we have a real problem somewhere. Reset the PHY and exit. This
-        *     state calls for inspection of the DEBUG registers.
-        * 2) The link is UP, but still in LTSSM training
-        *     Wait for the training to finish, which should take a very short
-        *     time. If the training does not finish, we have a problem and we
-        *     need to inspect the DEBUG registers. If the training does finish,
-        *     the link is up and operating correctly.
-        * 3) The link is UP and no longer in LTSSM training
-        *     The link is up and operating correctly.
-        */
-       while (1) {
-               rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
-               if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP))
-                       break;
-               if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
-                       return 1;
-               if (!count--)
-                       break;
-               dev_dbg(pp->dev, "Link is up, but still in training\n");
-               /*
-                * Wait a little bit, then re-check if the link finished
-                * the training.
-                */
-               usleep_range(1000, 2000);
-       }
-       /*
-        * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
-        * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
-        * If (MAC/LTSSM.state == Recovery.RcvrLock)
-        * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition
-        * to gen2 is stuck
-        */
-       pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
-       debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
-
-       if (rx_valid & PCIE_PHY_RX_ASIC_OUT_VALID)
-               return 0;
-
-       if ((debug_r0 & 0x3f) != 0x0d)
-               return 0;
-
-       dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
-       dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc);
-
-       imx6_pcie_reset_phy(pp);
-
-       return 0;
+       return readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) &
+                       PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
 }
 
 static struct pcie_host_ops imx6_pcie_host_ops = {
@@ -562,6 +524,7 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
        struct imx6_pcie *imx6_pcie;
        struct pcie_port *pp;
        struct resource *dbi_base;
+       struct device_node *node = pdev->dev.of_node;
        int ret;
 
        imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL);
@@ -614,6 +577,27 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                return PTR_ERR(imx6_pcie->iomuxc_gpr);
        }
 
+       /* Grab PCIe PHY Tx Settings */
+       if (of_property_read_u32(node, "fsl,tx-deemph-gen1",
+                                &imx6_pcie->tx_deemph_gen1))
+               imx6_pcie->tx_deemph_gen1 = 0;
+
+       if (of_property_read_u32(node, "fsl,tx-deemph-gen2-3p5db",
+                                &imx6_pcie->tx_deemph_gen2_3p5db))
+               imx6_pcie->tx_deemph_gen2_3p5db = 0;
+
+       if (of_property_read_u32(node, "fsl,tx-deemph-gen2-6db",
+                                &imx6_pcie->tx_deemph_gen2_6db))
+               imx6_pcie->tx_deemph_gen2_6db = 20;
+
+       if (of_property_read_u32(node, "fsl,tx-swing-full",
+                                &imx6_pcie->tx_swing_full))
+               imx6_pcie->tx_swing_full = 127;
+
+       if (of_property_read_u32(node, "fsl,tx-swing-low",
+                                &imx6_pcie->tx_swing_low))
+               imx6_pcie->tx_swing_low = 127;
+
        ret = imx6_add_pcie_port(pp, pdev);
        if (ret < 0)
                return ret;
index ed34c9520a02987503b02e2f371ea9e2a6d3a1a4..6153853ca9c31e319f4c6aae6dd92ed05215ba07 100644 (file)
 
 #define to_keystone_pcie(x)    container_of(x, struct keystone_pcie, pp)
 
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-       return sys->private_data;
-}
-
 static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
                                             u32 *bit_pos)
 {
@@ -108,7 +103,7 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
        struct pcie_port *pp;
 
        msi = irq_data_get_msi_desc(d);
-       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
+       pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
        ks_pcie = to_keystone_pcie(pp);
        offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
        update_reg_offset_bit_pos(offset, &reg_offset, &bit_pos);
@@ -146,7 +141,7 @@ static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
        u32 offset;
 
        msi = irq_data_get_msi_desc(d);
-       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
+       pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
        ks_pcie = to_keystone_pcie(pp);
        offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
 
@@ -167,7 +162,7 @@ static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
        u32 offset;
 
        msi = irq_data_get_msi_desc(d);
-       pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
+       pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
        ks_pcie = to_keystone_pcie(pp);
        offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
 
index 0aa81bd3de12d8eca876851e6f019a87f9b88f64..b71f55bb03156479d365892aa343858e1720e960 100644 (file)
@@ -97,17 +97,15 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
                return 0;
        }
 
-       ks_dw_pcie_initiate_link_train(ks_pcie);
        /* check if the link is up or not */
-       for (retries = 0; retries < 200; retries++) {
-               if (dw_pcie_link_up(pp))
-                       return 0;
-               usleep_range(100, 1000);
+       for (retries = 0; retries < 5; retries++) {
                ks_dw_pcie_initiate_link_train(ks_pcie);
+               if (!dw_pcie_wait_for_link(pp))
+                       return 0;
        }
 
        dev_err(pp->dev, "phy link never came up\n");
-       return -EINVAL;
+       return -ETIMEDOUT;
 }
 
 static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
@@ -359,6 +357,9 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
 
        /* initialize SerDes Phy if present */
        phy = devm_phy_get(dev, "pcie-phy");
+       if (PTR_ERR_OR_ZERO(phy) == -EPROBE_DEFER)
+               return PTR_ERR(phy);
+
        if (!IS_ERR_OR_NULL(phy)) {
                ret = phy_init(phy);
                if (ret < 0)
index 3923bed93c7e06fa8327cafef9429c34d1b063cb..a21e229d95e066fa440b94b6eeb0be77b9368877 100644 (file)
@@ -77,6 +77,16 @@ static void ls_pcie_fix_class(struct ls_pcie *pcie)
        iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE);
 }
 
+/* Drop MSG TLP except for Vendor MSG */
+static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
+{
+       u32 val;
+
+       val = ioread32(pcie->dbi + PCIE_STRFMR1);
+       val &= 0xDFFFFFFF;
+       iowrite32(val, pcie->dbi + PCIE_STRFMR1);
+}
+
 static int ls1021_pcie_link_up(struct pcie_port *pp)
 {
        u32 state;
@@ -97,7 +107,7 @@ static int ls1021_pcie_link_up(struct pcie_port *pp)
 static void ls1021_pcie_host_init(struct pcie_port *pp)
 {
        struct ls_pcie *pcie = to_ls_pcie(pp);
-       u32 val, index[2];
+       u32 index[2];
 
        pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node,
                                                     "fsl,pcie-scfg");
@@ -116,13 +126,7 @@ static void ls1021_pcie_host_init(struct pcie_port *pp)
 
        dw_pcie_setup_rc(pp);
 
-       /*
-        * LS1021A Workaround for internal TKT228622
-        * to fix the INTx hang issue
-        */
-       val = ioread32(pcie->dbi + PCIE_STRFMR1);
-       val &= 0xffff;
-       iowrite32(val, pcie->dbi + PCIE_STRFMR1);
+       ls_pcie_drop_msg_tlp(pcie);
 }
 
 static int ls_pcie_link_up(struct pcie_port *pp)
@@ -147,6 +151,7 @@ static void ls_pcie_host_init(struct pcie_port *pp)
        iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN);
        ls_pcie_fix_class(pcie);
        ls_pcie_clear_multifunction(pcie);
+       ls_pcie_drop_msg_tlp(pcie);
        iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN);
 }
 
@@ -203,6 +208,7 @@ static const struct of_device_id ls_pcie_of_match[] = {
        { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
        { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
        { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
+       { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
        { },
 };
 MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
index 30323114c53cca80b0c4f7bee7f361d65565fc26..68d1f41b3cbfb85750cae417739f7ff076ee4202 100644 (file)
@@ -281,6 +281,11 @@ struct tegra_pcie {
        struct resource prefetch;
        struct resource busn;
 
+       struct {
+               resource_size_t mem;
+               resource_size_t io;
+       } offset;
+
        struct clk *pex_clk;
        struct clk *afi_clk;
        struct clk *pll_e;
@@ -295,7 +300,6 @@ struct tegra_pcie {
        struct tegra_msi msi;
 
        struct list_head ports;
-       unsigned int num_ports;
        u32 xbar_config;
 
        struct regulator_bulk_data *supplies;
@@ -426,31 +430,38 @@ free:
        return ERR_PTR(err);
 }
 
-/*
- * Look up a virtual address mapping for the specified bus number. If no such
- * mapping exists, try to create one.
- */
-static void __iomem *tegra_pcie_bus_map(struct tegra_pcie *pcie,
-                                       unsigned int busnr)
+static int tegra_pcie_add_bus(struct pci_bus *bus)
 {
-       struct tegra_pcie_bus *bus;
+       struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata);
+       struct tegra_pcie_bus *b;
 
-       list_for_each_entry(bus, &pcie->buses, list)
-               if (bus->nr == busnr)
-                       return (void __iomem *)bus->area->addr;
+       b = tegra_pcie_bus_alloc(pcie, bus->number);
+       if (IS_ERR(b))
+               return PTR_ERR(b);
 
-       bus = tegra_pcie_bus_alloc(pcie, busnr);
-       if (IS_ERR(bus))
-               return NULL;
+       list_add_tail(&b->list, &pcie->buses);
 
-       list_add_tail(&bus->list, &pcie->buses);
+       return 0;
+}
 
-       return (void __iomem *)bus->area->addr;
+static void tegra_pcie_remove_bus(struct pci_bus *child)
+{
+       struct tegra_pcie *pcie = sys_to_pcie(child->sysdata);
+       struct tegra_pcie_bus *bus, *tmp;
+
+       list_for_each_entry_safe(bus, tmp, &pcie->buses, list) {
+               if (bus->nr == child->number) {
+                       vunmap(bus->area->addr);
+                       list_del(&bus->list);
+                       kfree(bus);
+                       break;
+               }
+       }
 }
 
-static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
-                                            unsigned int devfn,
-                                            int where)
+static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus,
+                                       unsigned int devfn,
+                                       int where)
 {
        struct tegra_pcie *pcie = sys_to_pcie(bus->sysdata);
        void __iomem *addr = NULL;
@@ -466,7 +477,12 @@ static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
                        }
                }
        } else {
-               addr = tegra_pcie_bus_map(pcie, bus->number);
+               struct tegra_pcie_bus *b;
+
+               list_for_each_entry(b, &pcie->buses, list)
+                       if (b->nr == bus->number)
+                               addr = (void __iomem *)b->area->addr;
+
                if (!addr) {
                        dev_err(pcie->dev,
                                "failed to map cfg. space for bus %u\n",
@@ -481,7 +497,9 @@ static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus,
 }
 
 static struct pci_ops tegra_pcie_ops = {
-       .map_bus = tegra_pcie_conf_address,
+       .add_bus = tegra_pcie_add_bus,
+       .remove_bus = tegra_pcie_remove_bus,
+       .map_bus = tegra_pcie_map_bus,
        .read = pci_generic_config_read32,
        .write = pci_generic_config_write32,
 };
@@ -598,6 +616,17 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
        struct tegra_pcie *pcie = sys_to_pcie(sys);
        int err;
 
+       sys->mem_offset = pcie->offset.mem;
+       sys->io_offset = pcie->offset.io;
+
+       err = devm_request_resource(pcie->dev, &pcie->all, &pcie->io);
+       if (err < 0)
+               return err;
+
+       err = devm_request_resource(pcie->dev, &ioport_resource, &pcie->pio);
+       if (err < 0)
+               return err;
+
        err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem);
        if (err < 0)
                return err;
@@ -606,6 +635,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
        if (err)
                return err;
 
+       pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset);
        pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
        pci_add_resource_offset(&sys->resources, &pcie->prefetch,
                                sys->mem_offset);
@@ -741,7 +771,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie)
        afi_writel(pcie, 0, AFI_FPCI_BAR5);
 
        /* map all upstream transactions as uncached */
-       afi_writel(pcie, PHYS_OFFSET, AFI_CACHE_BAR0_ST);
+       afi_writel(pcie, 0, AFI_CACHE_BAR0_ST);
        afi_writel(pcie, 0, AFI_CACHE_BAR0_SZ);
        afi_writel(pcie, 0, AFI_CACHE_BAR1_ST);
        afi_writel(pcie, 0, AFI_CACHE_BAR1_SZ);
@@ -1601,6 +1631,9 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
 
                switch (res.flags & IORESOURCE_TYPE_BITS) {
                case IORESOURCE_IO:
+                       /* Track the bus -> CPU I/O mapping offset. */
+                       pcie->offset.io = res.start - range.pci_addr;
+
                        memcpy(&pcie->pio, &res, sizeof(res));
                        pcie->pio.name = np->full_name;
 
@@ -1621,6 +1654,14 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
                        break;
 
                case IORESOURCE_MEM:
+                       /*
+                        * Track the bus -> CPU memory mapping offset. This
+                        * assumes that the prefetchable and non-prefetchable
+                        * regions will be the last of type IORESOURCE_MEM in
+                        * the ranges property.
+                        * */
+                       pcie->offset.mem = res.start - range.pci_addr;
+
                        if (res.flags & IORESOURCE_PREFETCH) {
                                memcpy(&pcie->prefetch, &res, sizeof(res));
                                pcie->prefetch.name = "prefetchable";
diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/host/pci-thunder-ecam.c
new file mode 100644 (file)
index 0000000..d71935c
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2015, 2016 Cavium, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/of_pci.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pci-host-common.h"
+
+/* Mapping is standard ECAM */
+static void __iomem *thunder_ecam_map_bus(struct pci_bus *bus,
+                                         unsigned int devfn,
+                                         int where)
+{
+       struct gen_pci *pci = bus->sysdata;
+       resource_size_t idx = bus->number - pci->cfg.bus_range->start;
+
+       return pci->cfg.win[idx] + ((devfn << 12) | where);
+}
+
+static void set_val(u32 v, int where, int size, u32 *val)
+{
+       int shift = (where & 3) * 8;
+
+       pr_debug("set_val %04x: %08x\n", (unsigned)(where & ~3), v);
+       v >>= shift;
+       if (size == 1)
+               v &= 0xff;
+       else if (size == 2)
+               v &= 0xffff;
+       *val = v;
+}
+
+static int handle_ea_bar(u32 e0, int bar, struct pci_bus *bus,
+                        unsigned int devfn, int where, int size, u32 *val)
+{
+       void __iomem *addr;
+       u32 v;
+
+       /* Entries are 16-byte aligned; bits[2,3] select word in entry */
+       int where_a = where & 0xc;
+
+       if (where_a == 0) {
+               set_val(e0, where, size, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       if (where_a == 0x4) {
+               addr = bus->ops->map_bus(bus, devfn, bar); /* BAR 0 */
+               if (!addr) {
+                       *val = ~0;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+               v = readl(addr);
+               v &= ~0xf;
+               v |= 2; /* EA entry-1. Base-L */
+               set_val(v, where, size, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       if (where_a == 0x8) {
+               u32 barl_orig;
+               u32 barl_rb;
+
+               addr = bus->ops->map_bus(bus, devfn, bar); /* BAR 0 */
+               if (!addr) {
+                       *val = ~0;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+               barl_orig = readl(addr + 0);
+               writel(0xffffffff, addr + 0);
+               barl_rb = readl(addr + 0);
+               writel(barl_orig, addr + 0);
+               /* zeros in unsettable bits */
+               v = ~barl_rb & ~3;
+               v |= 0xc; /* EA entry-2. Offset-L */
+               set_val(v, where, size, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       if (where_a == 0xc) {
+               addr = bus->ops->map_bus(bus, devfn, bar + 4); /* BAR 1 */
+               if (!addr) {
+                       *val = ~0;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+               v = readl(addr); /* EA entry-3. Base-H */
+               set_val(v, where, size, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int thunder_ecam_p2_config_read(struct pci_bus *bus, unsigned int devfn,
+                                      int where, int size, u32 *val)
+{
+       struct gen_pci *pci = bus->sysdata;
+       int where_a = where & ~3;
+       void __iomem *addr;
+       u32 node_bits;
+       u32 v;
+
+       /* EA Base[63:32] may be missing some bits ... */
+       switch (where_a) {
+       case 0xa8:
+       case 0xbc:
+       case 0xd0:
+       case 0xe4:
+               break;
+       default:
+               return pci_generic_config_read(bus, devfn, where, size, val);
+       }
+
+       addr = bus->ops->map_bus(bus, devfn, where_a);
+       if (!addr) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       v = readl(addr);
+
+       /*
+        * Bit 44 of the 64-bit Base must match the same bit in
+        * the config space access window.  Since we are working with
+        * the high-order 32 bits, shift everything down by 32 bits.
+        */
+       node_bits = (pci->cfg.res.start >> 32) & (1 << 12);
+
+       v |= node_bits;
+       set_val(v, where, size, val);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int thunder_ecam_config_read(struct pci_bus *bus, unsigned int devfn,
+                                   int where, int size, u32 *val)
+{
+       u32 v;
+       u32 vendor_device;
+       u32 class_rev;
+       void __iomem *addr;
+       int cfg_type;
+       int where_a = where & ~3;
+
+       addr = bus->ops->map_bus(bus, devfn, 0xc);
+       if (!addr) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       v = readl(addr);
+
+       /* Check for non type-00 header */
+       cfg_type = (v >> 16) & 0x7f;
+
+       addr = bus->ops->map_bus(bus, devfn, 8);
+       if (!addr) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       class_rev = readl(addr);
+       if (class_rev == 0xffffffff)
+               goto no_emulation;
+
+       if ((class_rev & 0xff) >= 8) {
+               /* Pass-2 handling */
+               if (cfg_type)
+                       goto no_emulation;
+               return thunder_ecam_p2_config_read(bus, devfn, where,
+                                                  size, val);
+       }
+
+       /*
+        * All BARs have fixed addresses specified by the EA
+        * capability; they must return zero on read.
+        */
+       if (cfg_type == 0 &&
+           ((where >= 0x10 && where < 0x2c) ||
+            (where >= 0x1a4 && where < 0x1bc))) {
+               /* BAR or SR-IOV BAR */
+               *val = 0;
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       addr = bus->ops->map_bus(bus, devfn, 0);
+       if (!addr) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       vendor_device = readl(addr);
+       if (vendor_device == 0xffffffff)
+               goto no_emulation;
+
+       pr_debug("%04x:%04x - Fix pass#: %08x, where: %03x, devfn: %03x\n",
+                vendor_device & 0xffff, vendor_device >> 16, class_rev,
+                (unsigned) where, devfn);
+
+       /* Check for non type-00 header */
+       if (cfg_type == 0) {
+               bool has_msix;
+               bool is_nic = (vendor_device == 0xa01e177d);
+               bool is_tns = (vendor_device == 0xa01f177d);
+
+               addr = bus->ops->map_bus(bus, devfn, 0x70);
+               if (!addr) {
+                       *val = ~0;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+               /* E_CAP */
+               v = readl(addr);
+               has_msix = (v & 0xff00) != 0;
+
+               if (!has_msix && where_a == 0x70) {
+                       v |= 0xbc00; /* next capability is EA at 0xbc */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xb0) {
+                       addr = bus->ops->map_bus(bus, devfn, where_a);
+                       if (!addr) {
+                               *val = ~0;
+                               return PCIBIOS_DEVICE_NOT_FOUND;
+                       }
+                       v = readl(addr);
+                       if (v & 0xff00)
+                               pr_err("Bad MSIX cap header: %08x\n", v);
+                       v |= 0xbc00; /* next capability is EA at 0xbc */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xbc) {
+                       if (is_nic)
+                               v = 0x40014; /* EA last in chain, 4 entries */
+                       else if (is_tns)
+                               v = 0x30014; /* EA last in chain, 3 entries */
+                       else if (has_msix)
+                               v = 0x20014; /* EA last in chain, 2 entries */
+                       else
+                               v = 0x10014; /* EA last in chain, 1 entry */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a >= 0xc0 && where_a < 0xd0)
+                       /* EA entry-0. PP=0, BAR0 Size:3 */
+                       return handle_ea_bar(0x80ff0003,
+                                            0x10, bus, devfn, where,
+                                            size, val);
+               if (where_a >= 0xd0 && where_a < 0xe0 && has_msix)
+                        /* EA entry-1. PP=0, BAR4 Size:3 */
+                       return handle_ea_bar(0x80ff0043,
+                                            0x20, bus, devfn, where,
+                                            size, val);
+               if (where_a >= 0xe0 && where_a < 0xf0 && is_tns)
+                       /* EA entry-2. PP=0, BAR2, Size:3 */
+                       return handle_ea_bar(0x80ff0023,
+                                            0x18, bus, devfn, where,
+                                            size, val);
+               if (where_a >= 0xe0 && where_a < 0xf0 && is_nic)
+                       /* EA entry-2. PP=4, VF_BAR0 (9), Size:3 */
+                       return handle_ea_bar(0x80ff0493,
+                                            0x1a4, bus, devfn, where,
+                                            size, val);
+               if (where_a >= 0xf0 && where_a < 0x100 && is_nic)
+                       /* EA entry-3. PP=4, VF_BAR4 (d), Size:3 */
+                       return handle_ea_bar(0x80ff04d3,
+                                            0x1b4, bus, devfn, where,
+                                            size, val);
+       } else if (cfg_type == 1) {
+               bool is_rsl_bridge = devfn == 0x08;
+               bool is_rad_bridge = devfn == 0xa0;
+               bool is_zip_bridge = devfn == 0xa8;
+               bool is_dfa_bridge = devfn == 0xb0;
+               bool is_nic_bridge = devfn == 0x10;
+
+               if (where_a == 0x70) {
+                       addr = bus->ops->map_bus(bus, devfn, where_a);
+                       if (!addr) {
+                               *val = ~0;
+                               return PCIBIOS_DEVICE_NOT_FOUND;
+                       }
+                       v = readl(addr);
+                       if (v & 0xff00)
+                               pr_err("Bad PCIe cap header: %08x\n", v);
+                       v |= 0xbc00; /* next capability is EA at 0xbc */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xbc) {
+                       if (is_nic_bridge)
+                               v = 0x10014; /* EA last in chain, 1 entry */
+                       else
+                               v = 0x00014; /* EA last in chain, no entries */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xc0) {
+                       if (is_rsl_bridge || is_nic_bridge)
+                               v = 0x0101; /* subordinate:secondary = 1:1 */
+                       else if (is_rad_bridge)
+                               v = 0x0202; /* subordinate:secondary = 2:2 */
+                       else if (is_zip_bridge)
+                               v = 0x0303; /* subordinate:secondary = 3:3 */
+                       else if (is_dfa_bridge)
+                               v = 0x0404; /* subordinate:secondary = 4:4 */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xc4 && is_nic_bridge) {
+                       /* Enabled, not-Write, SP=ff, PP=05, BEI=6, ES=4 */
+                       v = 0x80ff0564;
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xc8 && is_nic_bridge) {
+                       v = 0x00000002; /* Base-L 64-bit */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xcc && is_nic_bridge) {
+                       v = 0xfffffffe; /* MaxOffset-L 64-bit */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xd0 && is_nic_bridge) {
+                       v = 0x00008430; /* NIC Base-H */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+               if (where_a == 0xd4 && is_nic_bridge) {
+                       v = 0x0000000f; /* MaxOffset-H */
+                       set_val(v, where, size, val);
+                       return PCIBIOS_SUCCESSFUL;
+               }
+       }
+no_emulation:
+       return pci_generic_config_read(bus, devfn, where, size, val);
+}
+
+static int thunder_ecam_config_write(struct pci_bus *bus, unsigned int devfn,
+                                    int where, int size, u32 val)
+{
+       /*
+        * All BARs have fixed addresses; ignore BAR writes so they
+        * don't get corrupted.
+        */
+       if ((where >= 0x10 && where < 0x2c) ||
+           (where >= 0x1a4 && where < 0x1bc))
+               /* BAR or SR-IOV BAR */
+               return PCIBIOS_SUCCESSFUL;
+
+       return pci_generic_config_write(bus, devfn, where, size, val);
+}
+
+static struct gen_pci_cfg_bus_ops thunder_ecam_bus_ops = {
+       .bus_shift      = 20,
+       .ops            = {
+               .map_bus        = thunder_ecam_map_bus,
+               .read           = thunder_ecam_config_read,
+               .write          = thunder_ecam_config_write,
+       }
+};
+
+static const struct of_device_id thunder_ecam_of_match[] = {
+       { .compatible = "cavium,pci-host-thunder-ecam",
+         .data = &thunder_ecam_bus_ops },
+
+       { },
+};
+MODULE_DEVICE_TABLE(of, thunder_ecam_of_match);
+
+static int thunder_ecam_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id;
+       struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
+
+       if (!pci)
+               return -ENOMEM;
+
+       of_id = of_match_node(thunder_ecam_of_match, dev->of_node);
+       pci->cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
+
+       return pci_host_common_probe(pdev, pci);
+}
+
+static struct platform_driver thunder_ecam_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+               .of_match_table = thunder_ecam_of_match,
+       },
+       .probe = thunder_ecam_probe,
+};
+module_platform_driver(thunder_ecam_driver);
+
+MODULE_DESCRIPTION("Thunder ECAM PCI host driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
new file mode 100644 (file)
index 0000000..cabb92a
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2015 - 2016 Cavium, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pci-host-common.h"
+
+#define PEM_CFG_WR 0x28
+#define PEM_CFG_RD 0x30
+
+struct thunder_pem_pci {
+       struct gen_pci  gen_pci;
+       u32             ea_entry[3];
+       void __iomem    *pem_reg_base;
+};
+
+static void __iomem *thunder_pem_map_bus(struct pci_bus *bus,
+                                        unsigned int devfn, int where)
+{
+       struct gen_pci *pci = bus->sysdata;
+       resource_size_t idx = bus->number - pci->cfg.bus_range->start;
+
+       return pci->cfg.win[idx] + ((devfn << 16) | where);
+}
+
+static int thunder_pem_bridge_read(struct pci_bus *bus, unsigned int devfn,
+                                  int where, int size, u32 *val)
+{
+       u64 read_val;
+       struct thunder_pem_pci *pem_pci;
+       struct gen_pci *pci = bus->sysdata;
+
+       pem_pci = container_of(pci, struct thunder_pem_pci, gen_pci);
+
+       if (devfn != 0 || where >= 2048) {
+               *val = ~0;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       /*
+        * 32-bit accesses only.  Write the address to the low order
+        * bits of PEM_CFG_RD, then trigger the read by reading back.
+        * The config data lands in the upper 32-bits of PEM_CFG_RD.
+        */
+       read_val = where & ~3ull;
+       writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
+       read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
+       read_val >>= 32;
+
+       /*
+        * The config space contains some garbage, fix it up.  Also
+        * synthesize an EA capability for the BAR used by MSI-X.
+        */
+       switch (where & ~3) {
+       case 0x40:
+               read_val &= 0xffff00ff;
+               read_val |= 0x00007000; /* Skip MSI CAP */
+               break;
+       case 0x70: /* Express Cap */
+               /* PME interrupt on vector 2*/
+               read_val |= (2u << 25);
+               break;
+       case 0xb0: /* MSI-X Cap */
+               /* TableSize=4, Next Cap is EA */
+               read_val &= 0xc00000ff;
+               read_val |= 0x0003bc00;
+               break;
+       case 0xb4:
+               /* Table offset=0, BIR=0 */
+               read_val = 0x00000000;
+               break;
+       case 0xb8:
+               /* BPA offset=0xf0000, BIR=0 */
+               read_val = 0x000f0000;
+               break;
+       case 0xbc:
+               /* EA, 1 entry, no next Cap */
+               read_val = 0x00010014;
+               break;
+       case 0xc0:
+               /* DW2 for type-1 */
+               read_val = 0x00000000;
+               break;
+       case 0xc4:
+               /* Entry BEI=0, PP=0x00, SP=0xff, ES=3 */
+               read_val = 0x80ff0003;
+               break;
+       case 0xc8:
+               read_val = pem_pci->ea_entry[0];
+               break;
+       case 0xcc:
+               read_val = pem_pci->ea_entry[1];
+               break;
+       case 0xd0:
+               read_val = pem_pci->ea_entry[2];
+               break;
+       default:
+               break;
+       }
+       read_val >>= (8 * (where & 3));
+       switch (size) {
+       case 1:
+               read_val &= 0xff;
+               break;
+       case 2:
+               read_val &= 0xffff;
+               break;
+       default:
+               break;
+       }
+       *val = read_val;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int thunder_pem_config_read(struct pci_bus *bus, unsigned int devfn,
+                                  int where, int size, u32 *val)
+{
+       struct gen_pci *pci = bus->sysdata;
+
+       if (bus->number < pci->cfg.bus_range->start ||
+           bus->number > pci->cfg.bus_range->end)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * The first device on the bus is the PEM PCIe bridge.
+        * Special case its config access.
+        */
+       if (bus->number == pci->cfg.bus_range->start)
+               return thunder_pem_bridge_read(bus, devfn, where, size, val);
+
+       return pci_generic_config_read(bus, devfn, where, size, val);
+}
+
+/*
+ * Some of the w1c_bits below also include read-only or non-writable
+ * reserved bits, this makes the code simpler and is OK as the bits
+ * are not affected by writing zeros to them.
+ */
+static u32 thunder_pem_bridge_w1c_bits(int where)
+{
+       u32 w1c_bits = 0;
+
+       switch (where & ~3) {
+       case 0x04: /* Command/Status */
+       case 0x1c: /* Base and I/O Limit/Secondary Status */
+               w1c_bits = 0xff000000;
+               break;
+       case 0x44: /* Power Management Control and Status */
+               w1c_bits = 0xfffffe00;
+               break;
+       case 0x78: /* Device Control/Device Status */
+       case 0x80: /* Link Control/Link Status */
+       case 0x88: /* Slot Control/Slot Status */
+       case 0x90: /* Root Status */
+       case 0xa0: /* Link Control 2 Registers/Link Status 2 */
+               w1c_bits = 0xffff0000;
+               break;
+       case 0x104: /* Uncorrectable Error Status */
+       case 0x110: /* Correctable Error Status */
+       case 0x130: /* Error Status */
+       case 0x160: /* Link Control 4 */
+               w1c_bits = 0xffffffff;
+               break;
+       default:
+               break;
+       }
+       return w1c_bits;
+}
+
+static int thunder_pem_bridge_write(struct pci_bus *bus, unsigned int devfn,
+                                   int where, int size, u32 val)
+{
+       struct gen_pci *pci = bus->sysdata;
+       struct thunder_pem_pci *pem_pci;
+       u64 write_val, read_val;
+       u32 mask = 0;
+
+       pem_pci = container_of(pci, struct thunder_pem_pci, gen_pci);
+
+       if (devfn != 0 || where >= 2048)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * 32-bit accesses only.  If the write is for a size smaller
+        * than 32-bits, we must first read the 32-bit value and merge
+        * in the desired bits and then write the whole 32-bits back
+        * out.
+        */
+       switch (size) {
+       case 1:
+               read_val = where & ~3ull;
+               writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
+               read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
+               read_val >>= 32;
+               mask = ~(0xff << (8 * (where & 3)));
+               read_val &= mask;
+               val = (val & 0xff) << (8 * (where & 3));
+               val |= (u32)read_val;
+               break;
+       case 2:
+               read_val = where & ~3ull;
+               writeq(read_val, pem_pci->pem_reg_base + PEM_CFG_RD);
+               read_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
+               read_val >>= 32;
+               mask = ~(0xffff << (8 * (where & 3)));
+               read_val &= mask;
+               val = (val & 0xffff) << (8 * (where & 3));
+               val |= (u32)read_val;
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * By expanding the write width to 32 bits, we may
+        * inadvertently hit some W1C bits that were not intended to
+        * be written.  Calculate the mask that must be applied to the
+        * data to be written to avoid these cases.
+        */
+       if (mask) {
+               u32 w1c_bits = thunder_pem_bridge_w1c_bits(where);
+
+               if (w1c_bits) {
+                       mask &= w1c_bits;
+                       val &= ~mask;
+               }
+       }
+
+       /*
+        * Low order bits are the config address, the high order 32
+        * bits are the data to be written.
+        */
+       write_val = where & ~3ull;
+       write_val |= (((u64)val) << 32);
+       writeq(write_val, pem_pci->pem_reg_base + PEM_CFG_WR);
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int thunder_pem_config_write(struct pci_bus *bus, unsigned int devfn,
+                                   int where, int size, u32 val)
+{
+       struct gen_pci *pci = bus->sysdata;
+
+       if (bus->number < pci->cfg.bus_range->start ||
+           bus->number > pci->cfg.bus_range->end)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       /*
+        * The first device on the bus is the PEM PCIe bridge.
+        * Special case its config access.
+        */
+       if (bus->number == pci->cfg.bus_range->start)
+               return thunder_pem_bridge_write(bus, devfn, where, size, val);
+
+
+       return pci_generic_config_write(bus, devfn, where, size, val);
+}
+
+static struct gen_pci_cfg_bus_ops thunder_pem_bus_ops = {
+       .bus_shift      = 24,
+       .ops            = {
+               .map_bus        = thunder_pem_map_bus,
+               .read           = thunder_pem_config_read,
+               .write          = thunder_pem_config_write,
+       }
+};
+
+static const struct of_device_id thunder_pem_of_match[] = {
+       { .compatible = "cavium,pci-host-thunder-pem",
+         .data = &thunder_pem_bus_ops },
+
+       { },
+};
+MODULE_DEVICE_TABLE(of, thunder_pem_of_match);
+
+static int thunder_pem_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *of_id;
+       resource_size_t bar4_start;
+       struct resource *res_pem;
+       struct thunder_pem_pci *pem_pci;
+
+       pem_pci = devm_kzalloc(dev, sizeof(*pem_pci), GFP_KERNEL);
+       if (!pem_pci)
+               return -ENOMEM;
+
+       of_id = of_match_node(thunder_pem_of_match, dev->of_node);
+       pem_pci->gen_pci.cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data;
+
+       /*
+        * The second register range is the PEM bridge to the PCIe
+        * bus.  It has a different config access method than those
+        * devices behind the bridge.
+        */
+       res_pem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!res_pem) {
+               dev_err(dev, "missing \"reg[1]\"property\n");
+               return -EINVAL;
+       }
+
+       pem_pci->pem_reg_base = devm_ioremap(dev, res_pem->start, 0x10000);
+       if (!pem_pci->pem_reg_base)
+               return -ENOMEM;
+
+       /*
+        * The MSI-X BAR for the PEM and AER interrupts is located at
+        * a fixed offset from the PEM register base.  Generate a
+        * fragment of the synthesized Enhanced Allocation capability
+        * structure here for the BAR.
+        */
+       bar4_start = res_pem->start + 0xf00000;
+       pem_pci->ea_entry[0] = (u32)bar4_start | 2;
+       pem_pci->ea_entry[1] = (u32)(res_pem->end - bar4_start) & ~3u;
+       pem_pci->ea_entry[2] = (u32)(bar4_start >> 32);
+
+       return pci_host_common_probe(pdev, &pem_pci->gen_pci);
+}
+
+static struct platform_driver thunder_pem_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+               .of_match_table = thunder_pem_of_match,
+       },
+       .probe = thunder_pem_probe,
+};
+module_platform_driver(thunder_pem_driver);
+
+MODULE_DESCRIPTION("Thunder PEM PCIe host driver");
+MODULE_LICENSE("GPL v2");
index 99da549d5d06a067b58d3bbe08c39041a9d90605..dbac6fb3f0bdfbccaaceefc0c1467e80ce0345df 100644 (file)
@@ -40,6 +40,7 @@
 #define P2A_INT_ENABLE                 0x3070
 #define P2A_INT_ENA_ALL                        0xf
 #define RP_LTSSM                       0x3c64
+#define RP_LTSSM_MASK                  0x1f
 #define LTSSM_L0                       0xf
 
 /* TLP configuration type 0 and 1 */
@@ -140,7 +141,7 @@ static void tlp_write_tx(struct altera_pcie *pcie,
 
 static bool altera_pcie_link_is_up(struct altera_pcie *pcie)
 {
-       return !!(cra_readl(pcie, RP_LTSSM) & LTSSM_L0);
+       return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0);
 }
 
 static bool altera_pcie_valid_config(struct altera_pcie *pcie,
diff --git a/drivers/pci/host/pcie-designware-plat.c b/drivers/pci/host/pcie-designware-plat.c
new file mode 100644 (file)
index 0000000..b350099
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * PCIe RC driver for Synopsys DesignWare Core
+ *
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * Authors: Joao Pinto <jpinto@synopsys.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.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/signal.h>
+#include <linux/types.h>
+
+#include "pcie-designware.h"
+
+struct dw_plat_pcie {
+       void __iomem            *mem_base;
+       struct pcie_port        pp;
+};
+
+static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
+{
+       struct pcie_port *pp = arg;
+
+       return dw_handle_msi_irq(pp);
+}
+
+static void dw_plat_pcie_host_init(struct pcie_port *pp)
+{
+       dw_pcie_setup_rc(pp);
+       dw_pcie_wait_for_link(pp);
+
+       if (IS_ENABLED(CONFIG_PCI_MSI))
+               dw_pcie_msi_init(pp);
+}
+
+static struct pcie_host_ops dw_plat_pcie_host_ops = {
+       .host_init = dw_plat_pcie_host_init,
+};
+
+static int dw_plat_add_pcie_port(struct pcie_port *pp,
+                                struct platform_device *pdev)
+{
+       int ret;
+
+       pp->irq = platform_get_irq(pdev, 1);
+       if (pp->irq < 0)
+               return pp->irq;
+
+       if (IS_ENABLED(CONFIG_PCI_MSI)) {
+               pp->msi_irq = platform_get_irq(pdev, 0);
+               if (pp->msi_irq < 0)
+                       return pp->msi_irq;
+
+               ret = devm_request_irq(&pdev->dev, pp->msi_irq,
+                                       dw_plat_pcie_msi_irq_handler,
+                                       IRQF_SHARED, "dw-plat-pcie-msi", pp);
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to request MSI IRQ\n");
+                       return ret;
+               }
+       }
+
+       pp->root_bus_nr = -1;
+       pp->ops = &dw_plat_pcie_host_ops;
+
+       ret = dw_pcie_host_init(pp);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to initialize host\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int dw_plat_pcie_probe(struct platform_device *pdev)
+{
+       struct dw_plat_pcie *dw_plat_pcie;
+       struct pcie_port *pp;
+       struct resource *res;  /* Resource from DT */
+       int ret;
+
+       dw_plat_pcie = devm_kzalloc(&pdev->dev, sizeof(*dw_plat_pcie),
+                                       GFP_KERNEL);
+       if (!dw_plat_pcie)
+               return -ENOMEM;
+
+       pp = &dw_plat_pcie->pp;
+       pp->dev = &pdev->dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENODEV;
+
+       dw_plat_pcie->mem_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(dw_plat_pcie->mem_base))
+               return PTR_ERR(dw_plat_pcie->mem_base);
+
+       pp->dbi_base = dw_plat_pcie->mem_base;
+
+       ret = dw_plat_add_pcie_port(pp, pdev);
+       if (ret < 0)
+               return ret;
+
+       platform_set_drvdata(pdev, dw_plat_pcie);
+       return 0;
+}
+
+static const struct of_device_id dw_plat_pcie_of_match[] = {
+       { .compatible = "snps,dw-pcie", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, dw_plat_pcie_of_match);
+
+static struct platform_driver dw_plat_pcie_driver = {
+       .driver = {
+               .name   = "dw-pcie",
+               .of_match_table = dw_plat_pcie_of_match,
+       },
+       .probe = dw_plat_pcie_probe,
+};
+
+module_platform_driver(dw_plat_pcie_driver);
+
+MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
+MODULE_DESCRIPTION("Synopsys PCIe host controller glue platform driver");
+MODULE_LICENSE("GPL v2");
index 21716827847a8ab02f1123a49ffc23141571ebc9..a4cccd356304662fc52c5efef682723960428195 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/pci_regs.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
+#include <linux/delay.h>
 
 #include "pcie-designware.h"
 
 #define PCIE_ATU_FUNC(x)               (((x) & 0x7) << 16)
 #define PCIE_ATU_UPPER_TARGET          0x91C
 
+/* PCIe Port Logic registers */
+#define PLR_OFFSET                     0x700
+#define PCIE_PHY_DEBUG_R1              (PLR_OFFSET + 0x2c)
+#define PCIE_PHY_DEBUG_R1_LINK_UP      0x00000010
+
 static struct pci_ops dw_pcie_ops;
 
 int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val)
@@ -380,12 +386,33 @@ static struct msi_controller dw_pcie_msi_chip = {
        .teardown_irq = dw_msi_teardown_irq,
 };
 
+int dw_pcie_wait_for_link(struct pcie_port *pp)
+{
+       int retries;
+
+       /* check if the link is up or not */
+       for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+               if (dw_pcie_link_up(pp)) {
+                       dev_info(pp->dev, "link up\n");
+                       return 0;
+               }
+               usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+       }
+
+       dev_err(pp->dev, "phy link never came up\n");
+
+       return -ETIMEDOUT;
+}
+
 int dw_pcie_link_up(struct pcie_port *pp)
 {
+       u32 val;
+
        if (pp->ops->link_up)
                return pp->ops->link_up(pp);
 
-       return 0;
+       val = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
+       return val & PCIE_PHY_DEBUG_R1_LINK_UP;
 }
 
 static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
@@ -517,6 +544,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
        if (pp->ops->host_init)
                pp->ops->host_init(pp);
 
+       /*
+        * If the platform provides ->rd_other_conf, it means the platform
+        * uses its own address translation component rather than ATU, so
+        * we should not program the ATU here.
+        */
        if (!pp->ops->rd_other_conf)
                dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
                                          PCIE_ATU_TYPE_MEM, pp->mem_base,
@@ -551,13 +583,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
        pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
 #endif
 
-       if (!pci_has_flag(PCI_PROBE_ONLY)) {
-               pci_bus_size_bridges(bus);
-               pci_bus_assign_resources(bus);
+       pci_bus_size_bridges(bus);
+       pci_bus_assign_resources(bus);
 
-               list_for_each_entry(child, &bus->children, node)
-                       pcie_bus_configure_settings(child);
-       }
+       list_for_each_entry(child, &bus->children, node)
+               pcie_bus_configure_settings(child);
 
        pci_bus_add_devices(bus);
        return 0;
index 2356d29e8527e71062d4fd5addb9f0ac55652b46..f437f9b5be04dd73174aec81afb7d41ff56fac14 100644 (file)
 #define MAX_MSI_IRQS                   32
 #define MAX_MSI_CTRLS                  (MAX_MSI_IRQS / 32)
 
+/* Parameters for the waiting for link up routine */
+#define LINK_WAIT_MAX_RETRIES          10
+#define LINK_WAIT_USLEEP_MIN           90000
+#define LINK_WAIT_USLEEP_MAX           100000
+
 struct pcie_port {
        struct device           *dev;
        u8                      root_bus_nr;
@@ -76,6 +81,7 @@ int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val);
 int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val);
 irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
 void dw_pcie_msi_init(struct pcie_port *pp);
+int dw_pcie_wait_for_link(struct pcie_port *pp);
 int dw_pcie_link_up(struct pcie_port *pp);
 void dw_pcie_setup_rc(struct pcie_port *pp);
 int dw_pcie_host_init(struct pcie_port *pp);
index e845fba19632d8518cb6af9a622f301668f5aa0c..f2f90c50f75d7f496f67e38495727826feed951f 100644 (file)
@@ -116,8 +116,6 @@ static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
 
 static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
 {
-       struct device *dev = pcie->dev;
-       unsigned int retries = 0;
        u32 val;
 
        if (dw_pcie_link_up(&pcie->pp))
@@ -128,15 +126,7 @@ static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
        val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE;
        writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL);
 
-       do {
-               if (dw_pcie_link_up(&pcie->pp))
-                       return 0;
-               usleep_range(250, 1000);
-       } while (retries < 200);
-
-       dev_warn(dev, "phy link never came up\n");
-
-       return -ETIMEDOUT;
+       return dw_pcie_wait_for_link(&pcie->pp);
 }
 
 static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
index 4edb5181f4e2ca64dc24d8c2cc1ebec46b2d7384..35092188039b99264f7911a3fdd91005c043d4d0 100644 (file)
@@ -390,9 +390,7 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie)
 
        rcar_pcie_setup(&res, pcie);
 
-       /* Do not reassign resources if probe only */
-       if (!pci_has_flag(PCI_PROBE_ONLY))
-               pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
+       pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
 
        if (IS_ENABLED(CONFIG_PCI_MSI))
                bus = pci_scan_root_bus_msi(pcie->dev, pcie->root_bus_nr,
@@ -408,13 +406,11 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie)
 
        pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
 
-       if (!pci_has_flag(PCI_PROBE_ONLY)) {
-               pci_bus_size_bridges(bus);
-               pci_bus_assign_resources(bus);
+       pci_bus_size_bridges(bus);
+       pci_bus_assign_resources(bus);
 
-               list_for_each_entry(child, &bus->children, node)
-                       pcie_bus_configure_settings(child);
-       }
+       list_for_each_entry(child, &bus->children, node)
+               pcie_bus_configure_settings(child);
 
        pci_bus_add_devices(bus);
 
index a6cd8233e8c08c8fee6e1df3a1a7d40fdc2250a8..a4060b85ab23b6bcd41222ffc387d1626a3b0185 100644 (file)
@@ -13,7 +13,6 @@
  */
 
 #include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -149,7 +148,6 @@ static int spear13xx_pcie_establish_link(struct pcie_port *pp)
        struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
        struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
        u32 exp_cap_off = EXP_CAP_ID_OFFSET;
-       unsigned int retries;
 
        if (dw_pcie_link_up(pp)) {
                dev_err(pp->dev, "link already up\n");
@@ -200,17 +198,7 @@ static int spear13xx_pcie_establish_link(struct pcie_port *pp)
                        | ((u32)1 << REG_TRANSLATION_ENABLE),
                        &app_reg->app_ctrl_0);
 
-       /* check if the link is up or not */
-       for (retries = 0; retries < 10; retries++) {
-               if (dw_pcie_link_up(pp)) {
-                       dev_info(pp->dev, "link up\n");
-                       return 0;
-               }
-               mdelay(100);
-       }
-
-       dev_err(pp->dev, "link Fail\n");
-       return -EINVAL;
+       return dw_pcie_wait_for_link(pp);
 }
 
 static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c
new file mode 100644 (file)
index 0000000..5139e64
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ * PCIe host controller driver for NWL PCIe Bridge
+ * Based on pcie-xilinx.c, pci-tegra.c
+ *
+ * (C) Copyright 2014 - 2015, Xilinx, 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/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/irqchip/chained_irq.h>
+
+/* Bridge core config registers */
+#define BRCFG_PCIE_RX0                 0x00000000
+#define BRCFG_INTERRUPT                        0x00000010
+#define BRCFG_PCIE_RX_MSG_FILTER       0x00000020
+
+/* Egress - Bridge translation registers */
+#define E_BREG_CAPABILITIES            0x00000200
+#define E_BREG_CONTROL                 0x00000208
+#define E_BREG_BASE_LO                 0x00000210
+#define E_BREG_BASE_HI                 0x00000214
+#define E_ECAM_CAPABILITIES            0x00000220
+#define E_ECAM_CONTROL                 0x00000228
+#define E_ECAM_BASE_LO                 0x00000230
+#define E_ECAM_BASE_HI                 0x00000234
+
+/* Ingress - address translations */
+#define I_MSII_CAPABILITIES            0x00000300
+#define I_MSII_CONTROL                 0x00000308
+#define I_MSII_BASE_LO                 0x00000310
+#define I_MSII_BASE_HI                 0x00000314
+
+#define I_ISUB_CONTROL                 0x000003E8
+#define SET_ISUB_CONTROL               BIT(0)
+/* Rxed msg fifo  - Interrupt status registers */
+#define MSGF_MISC_STATUS               0x00000400
+#define MSGF_MISC_MASK                 0x00000404
+#define MSGF_LEG_STATUS                        0x00000420
+#define MSGF_LEG_MASK                  0x00000424
+#define MSGF_MSI_STATUS_LO             0x00000440
+#define MSGF_MSI_STATUS_HI             0x00000444
+#define MSGF_MSI_MASK_LO               0x00000448
+#define MSGF_MSI_MASK_HI               0x0000044C
+
+/* Msg filter mask bits */
+#define CFG_ENABLE_PM_MSG_FWD          BIT(1)
+#define CFG_ENABLE_INT_MSG_FWD         BIT(2)
+#define CFG_ENABLE_ERR_MSG_FWD         BIT(3)
+#define CFG_ENABLE_SLT_MSG_FWD         BIT(5)
+#define CFG_ENABLE_VEN_MSG_FWD         BIT(7)
+#define CFG_ENABLE_OTH_MSG_FWD         BIT(13)
+#define CFG_ENABLE_VEN_MSG_EN          BIT(14)
+#define CFG_ENABLE_VEN_MSG_VEN_INV     BIT(15)
+#define CFG_ENABLE_VEN_MSG_VEN_ID      GENMASK(31, 16)
+#define CFG_ENABLE_MSG_FILTER_MASK     (CFG_ENABLE_PM_MSG_FWD | \
+                                       CFG_ENABLE_INT_MSG_FWD | \
+                                       CFG_ENABLE_ERR_MSG_FWD | \
+                                       CFG_ENABLE_SLT_MSG_FWD | \
+                                       CFG_ENABLE_VEN_MSG_FWD | \
+                                       CFG_ENABLE_OTH_MSG_FWD | \
+                                       CFG_ENABLE_VEN_MSG_EN | \
+                                       CFG_ENABLE_VEN_MSG_VEN_INV | \
+                                       CFG_ENABLE_VEN_MSG_VEN_ID)
+
+/* Misc interrupt status mask bits */
+#define MSGF_MISC_SR_RXMSG_AVAIL       BIT(0)
+#define MSGF_MISC_SR_RXMSG_OVER                BIT(1)
+#define MSGF_MISC_SR_SLAVE_ERR         BIT(4)
+#define MSGF_MISC_SR_MASTER_ERR                BIT(5)
+#define MSGF_MISC_SR_I_ADDR_ERR                BIT(6)
+#define MSGF_MISC_SR_E_ADDR_ERR                BIT(7)
+#define MSGF_MISC_SR_UR_DETECT          BIT(20)
+
+#define MSGF_MISC_SR_PCIE_CORE         GENMASK(18, 16)
+#define MSGF_MISC_SR_PCIE_CORE_ERR     GENMASK(31, 22)
+
+#define MSGF_MISC_SR_MASKALL           (MSGF_MISC_SR_RXMSG_AVAIL | \
+                                       MSGF_MISC_SR_RXMSG_OVER | \
+                                       MSGF_MISC_SR_SLAVE_ERR | \
+                                       MSGF_MISC_SR_MASTER_ERR | \
+                                       MSGF_MISC_SR_I_ADDR_ERR | \
+                                       MSGF_MISC_SR_E_ADDR_ERR | \
+                                       MSGF_MISC_SR_UR_DETECT | \
+                                       MSGF_MISC_SR_PCIE_CORE | \
+                                       MSGF_MISC_SR_PCIE_CORE_ERR)
+
+/* Legacy interrupt status mask bits */
+#define MSGF_LEG_SR_INTA               BIT(0)
+#define MSGF_LEG_SR_INTB               BIT(1)
+#define MSGF_LEG_SR_INTC               BIT(2)
+#define MSGF_LEG_SR_INTD               BIT(3)
+#define MSGF_LEG_SR_MASKALL            (MSGF_LEG_SR_INTA | MSGF_LEG_SR_INTB | \
+                                       MSGF_LEG_SR_INTC | MSGF_LEG_SR_INTD)
+
+/* MSI interrupt status mask bits */
+#define MSGF_MSI_SR_LO_MASK            BIT(0)
+#define MSGF_MSI_SR_HI_MASK            BIT(0)
+
+#define MSII_PRESENT                   BIT(0)
+#define MSII_ENABLE                    BIT(0)
+#define MSII_STATUS_ENABLE             BIT(15)
+
+/* Bridge config interrupt mask */
+#define BRCFG_INTERRUPT_MASK           BIT(0)
+#define BREG_PRESENT                   BIT(0)
+#define BREG_ENABLE                    BIT(0)
+#define BREG_ENABLE_FORCE              BIT(1)
+
+/* E_ECAM status mask bits */
+#define E_ECAM_PRESENT                 BIT(0)
+#define E_ECAM_CR_ENABLE               BIT(0)
+#define E_ECAM_SIZE_LOC                        GENMASK(20, 16)
+#define E_ECAM_SIZE_SHIFT              16
+#define ECAM_BUS_LOC_SHIFT             20
+#define ECAM_DEV_LOC_SHIFT             12
+#define NWL_ECAM_VALUE_DEFAULT         12
+
+#define CFG_DMA_REG_BAR                        GENMASK(2, 0)
+
+#define INT_PCI_MSI_NR                 (2 * 32)
+#define INTX_NUM                       4
+
+/* Readin the PS_LINKUP */
+#define PS_LINKUP_OFFSET               0x00000238
+#define PCIE_PHY_LINKUP_BIT            BIT(0)
+#define PHY_RDY_LINKUP_BIT             BIT(1)
+
+/* Parameters for the waiting for link up routine */
+#define LINK_WAIT_MAX_RETRIES          10
+#define LINK_WAIT_USLEEP_MIN           90000
+#define LINK_WAIT_USLEEP_MAX           100000
+
+struct nwl_msi {                       /* MSI information */
+       struct irq_domain *msi_domain;
+       unsigned long *bitmap;
+       struct irq_domain *dev_domain;
+       struct mutex lock;              /* protect bitmap variable */
+       int irq_msi0;
+       int irq_msi1;
+};
+
+struct nwl_pcie {
+       struct device *dev;
+       void __iomem *breg_base;
+       void __iomem *pcireg_base;
+       void __iomem *ecam_base;
+       phys_addr_t phys_breg_base;     /* Physical Bridge Register Base */
+       phys_addr_t phys_pcie_reg_base; /* Physical PCIe Controller Base */
+       phys_addr_t phys_ecam_base;     /* Physical Configuration Base */
+       u32 breg_size;
+       u32 pcie_reg_size;
+       u32 ecam_size;
+       int irq_intx;
+       int irq_misc;
+       u32 ecam_value;
+       u8 last_busno;
+       u8 root_busno;
+       struct nwl_msi msi;
+       struct irq_domain *legacy_irq_domain;
+};
+
+static inline u32 nwl_bridge_readl(struct nwl_pcie *pcie, u32 off)
+{
+       return readl(pcie->breg_base + off);
+}
+
+static inline void nwl_bridge_writel(struct nwl_pcie *pcie, u32 val, u32 off)
+{
+       writel(val, pcie->breg_base + off);
+}
+
+static bool nwl_pcie_link_up(struct nwl_pcie *pcie)
+{
+       if (readl(pcie->pcireg_base + PS_LINKUP_OFFSET) & PCIE_PHY_LINKUP_BIT)
+               return true;
+       return false;
+}
+
+static bool nwl_phy_link_up(struct nwl_pcie *pcie)
+{
+       if (readl(pcie->pcireg_base + PS_LINKUP_OFFSET) & PHY_RDY_LINKUP_BIT)
+               return true;
+       return false;
+}
+
+static int nwl_wait_for_link(struct nwl_pcie *pcie)
+{
+       int retries;
+
+       /* check if the link is up or not */
+       for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+               if (nwl_phy_link_up(pcie))
+                       return 0;
+               usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+       }
+
+       dev_err(pcie->dev, "PHY link never came up\n");
+       return -ETIMEDOUT;
+}
+
+static bool nwl_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
+{
+       struct nwl_pcie *pcie = bus->sysdata;
+
+       /* Check link before accessing downstream ports */
+       if (bus->number != pcie->root_busno) {
+               if (!nwl_pcie_link_up(pcie))
+                       return false;
+       }
+
+       /* Only one device down on each root port */
+       if (bus->number == pcie->root_busno && devfn > 0)
+               return false;
+
+       return true;
+}
+
+/**
+ * nwl_pcie_map_bus - Get configuration base
+ *
+ * @bus: Bus structure of current bus
+ * @devfn: Device/function
+ * @where: Offset from base
+ *
+ * Return: Base address of the configuration space needed to be
+ *        accessed.
+ */
+static void __iomem *nwl_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
+                                     int where)
+{
+       struct nwl_pcie *pcie = bus->sysdata;
+       int relbus;
+
+       if (!nwl_pcie_valid_device(bus, devfn))
+               return NULL;
+
+       relbus = (bus->number << ECAM_BUS_LOC_SHIFT) |
+                       (devfn << ECAM_DEV_LOC_SHIFT);
+
+       return pcie->ecam_base + relbus + where;
+}
+
+/* PCIe operations */
+static struct pci_ops nwl_pcie_ops = {
+       .map_bus = nwl_pcie_map_bus,
+       .read  = pci_generic_config_read,
+       .write = pci_generic_config_write,
+};
+
+static irqreturn_t nwl_pcie_misc_handler(int irq, void *data)
+{
+       struct nwl_pcie *pcie = data;
+       u32 misc_stat;
+
+       /* Checking for misc interrupts */
+       misc_stat = nwl_bridge_readl(pcie, MSGF_MISC_STATUS) &
+                                    MSGF_MISC_SR_MASKALL;
+       if (!misc_stat)
+               return IRQ_NONE;
+
+       if (misc_stat & MSGF_MISC_SR_RXMSG_OVER)
+               dev_err(pcie->dev, "Received Message FIFO Overflow\n");
+
+       if (misc_stat & MSGF_MISC_SR_SLAVE_ERR)
+               dev_err(pcie->dev, "Slave error\n");
+
+       if (misc_stat & MSGF_MISC_SR_MASTER_ERR)
+               dev_err(pcie->dev, "Master error\n");
+
+       if (misc_stat & MSGF_MISC_SR_I_ADDR_ERR)
+               dev_err(pcie->dev,
+                       "In Misc Ingress address translation error\n");
+
+       if (misc_stat & MSGF_MISC_SR_E_ADDR_ERR)
+               dev_err(pcie->dev,
+                       "In Misc Egress address translation error\n");
+
+       if (misc_stat & MSGF_MISC_SR_PCIE_CORE_ERR)
+               dev_err(pcie->dev, "PCIe Core error\n");
+
+       /* Clear misc interrupt status */
+       nwl_bridge_writel(pcie, misc_stat, MSGF_MISC_STATUS);
+
+       return IRQ_HANDLED;
+}
+
+static void nwl_pcie_leg_handler(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct nwl_pcie *pcie;
+       unsigned long status;
+       u32 bit;
+       u32 virq;
+
+       chained_irq_enter(chip, desc);
+       pcie = irq_desc_get_handler_data(desc);
+
+       while ((status = nwl_bridge_readl(pcie, MSGF_LEG_STATUS) &
+                               MSGF_LEG_SR_MASKALL) != 0) {
+               for_each_set_bit(bit, &status, INTX_NUM) {
+                       virq = irq_find_mapping(pcie->legacy_irq_domain,
+                                               bit + 1);
+                       if (virq)
+                               generic_handle_irq(virq);
+               }
+       }
+
+       chained_irq_exit(chip, desc);
+}
+
+static void nwl_pcie_handle_msi_irq(struct nwl_pcie *pcie, u32 status_reg)
+{
+       struct nwl_msi *msi;
+       unsigned long status;
+       u32 bit;
+       u32 virq;
+
+       msi = &pcie->msi;
+
+       while ((status = nwl_bridge_readl(pcie, status_reg)) != 0) {
+               for_each_set_bit(bit, &status, 32) {
+                       nwl_bridge_writel(pcie, 1 << bit, status_reg);
+                       virq = irq_find_mapping(msi->dev_domain, bit);
+                       if (virq)
+                               generic_handle_irq(virq);
+               }
+       }
+}
+
+static void nwl_pcie_msi_handler_high(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct nwl_pcie *pcie = irq_desc_get_handler_data(desc);
+
+       chained_irq_enter(chip, desc);
+       nwl_pcie_handle_msi_irq(pcie, MSGF_MSI_STATUS_HI);
+       chained_irq_exit(chip, desc);
+}
+
+static void nwl_pcie_msi_handler_low(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct nwl_pcie *pcie = irq_desc_get_handler_data(desc);
+
+       chained_irq_enter(chip, desc);
+       nwl_pcie_handle_msi_irq(pcie, MSGF_MSI_STATUS_LO);
+       chained_irq_exit(chip, desc);
+}
+
+static int nwl_legacy_map(struct irq_domain *domain, unsigned int irq,
+                         irq_hw_number_t hwirq)
+{
+       irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+       irq_set_chip_data(irq, domain->host_data);
+
+       return 0;
+}
+
+static const struct irq_domain_ops legacy_domain_ops = {
+       .map = nwl_legacy_map,
+};
+
+#ifdef CONFIG_PCI_MSI
+static struct irq_chip nwl_msi_irq_chip = {
+       .name = "nwl_pcie:msi",
+       .irq_enable = unmask_msi_irq,
+       .irq_disable = mask_msi_irq,
+       .irq_mask = mask_msi_irq,
+       .irq_unmask = unmask_msi_irq,
+
+};
+
+static struct msi_domain_info nwl_msi_domain_info = {
+       .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+                 MSI_FLAG_MULTI_PCI_MSI),
+       .chip = &nwl_msi_irq_chip,
+};
+#endif
+
+static void nwl_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+       struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data);
+       phys_addr_t msi_addr = pcie->phys_pcie_reg_base;
+
+       msg->address_lo = lower_32_bits(msi_addr);
+       msg->address_hi = upper_32_bits(msi_addr);
+       msg->data = data->hwirq;
+}
+
+static int nwl_msi_set_affinity(struct irq_data *irq_data,
+                               const struct cpumask *mask, bool force)
+{
+       return -EINVAL;
+}
+
+static struct irq_chip nwl_irq_chip = {
+       .name = "Xilinx MSI",
+       .irq_compose_msi_msg = nwl_compose_msi_msg,
+       .irq_set_affinity = nwl_msi_set_affinity,
+};
+
+static int nwl_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+                               unsigned int nr_irqs, void *args)
+{
+       struct nwl_pcie *pcie = domain->host_data;
+       struct nwl_msi *msi = &pcie->msi;
+       int bit;
+       int i;
+
+       mutex_lock(&msi->lock);
+       bit = bitmap_find_next_zero_area(msi->bitmap, INT_PCI_MSI_NR, 0,
+                                        nr_irqs, 0);
+       if (bit >= INT_PCI_MSI_NR) {
+               mutex_unlock(&msi->lock);
+               return -ENOSPC;
+       }
+
+       bitmap_set(msi->bitmap, bit, nr_irqs);
+
+       for (i = 0; i < nr_irqs; i++) {
+               irq_domain_set_info(domain, virq + i, bit + i, &nwl_irq_chip,
+                               domain->host_data, handle_simple_irq,
+                               NULL, NULL);
+       }
+       mutex_unlock(&msi->lock);
+       return 0;
+}
+
+static void nwl_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+                                       unsigned int nr_irqs)
+{
+       struct irq_data *data = irq_domain_get_irq_data(domain, virq);
+       struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data);
+       struct nwl_msi *msi = &pcie->msi;
+
+       mutex_lock(&msi->lock);
+       bitmap_clear(msi->bitmap, data->hwirq, nr_irqs);
+       mutex_unlock(&msi->lock);
+}
+
+static const struct irq_domain_ops dev_msi_domain_ops = {
+       .alloc  = nwl_irq_domain_alloc,
+       .free   = nwl_irq_domain_free,
+};
+
+static void nwl_msi_free_irq_domain(struct nwl_pcie *pcie)
+{
+       struct nwl_msi *msi = &pcie->msi;
+
+       if (msi->irq_msi0)
+               irq_set_chained_handler_and_data(msi->irq_msi0, NULL, NULL);
+       if (msi->irq_msi1)
+               irq_set_chained_handler_and_data(msi->irq_msi1, NULL, NULL);
+
+       if (msi->msi_domain)
+               irq_domain_remove(msi->msi_domain);
+       if (msi->dev_domain)
+               irq_domain_remove(msi->dev_domain);
+
+       kfree(msi->bitmap);
+       msi->bitmap = NULL;
+}
+
+static void nwl_pcie_free_irq_domain(struct nwl_pcie *pcie)
+{
+       int i;
+       u32 irq;
+
+       for (i = 0; i < INTX_NUM; i++) {
+               irq = irq_find_mapping(pcie->legacy_irq_domain, i + 1);
+               if (irq > 0)
+                       irq_dispose_mapping(irq);
+       }
+       if (pcie->legacy_irq_domain)
+               irq_domain_remove(pcie->legacy_irq_domain);
+
+       nwl_msi_free_irq_domain(pcie);
+}
+
+static int nwl_pcie_init_msi_irq_domain(struct nwl_pcie *pcie)
+{
+#ifdef CONFIG_PCI_MSI
+       struct fwnode_handle *fwnode = of_node_to_fwnode(pcie->dev->of_node);
+       struct nwl_msi *msi = &pcie->msi;
+
+       msi->dev_domain = irq_domain_add_linear(NULL, INT_PCI_MSI_NR,
+                                               &dev_msi_domain_ops, pcie);
+       if (!msi->dev_domain) {
+               dev_err(pcie->dev, "failed to create dev IRQ domain\n");
+               return -ENOMEM;
+       }
+       msi->msi_domain = pci_msi_create_irq_domain(fwnode,
+                                                   &nwl_msi_domain_info,
+                                                   msi->dev_domain);
+       if (!msi->msi_domain) {
+               dev_err(pcie->dev, "failed to create msi IRQ domain\n");
+               irq_domain_remove(msi->dev_domain);
+               return -ENOMEM;
+       }
+#endif
+       return 0;
+}
+
+static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie)
+{
+       struct device_node *node = pcie->dev->of_node;
+       struct device_node *legacy_intc_node;
+
+       legacy_intc_node = of_get_next_child(node, NULL);
+       if (!legacy_intc_node) {
+               dev_err(pcie->dev, "No legacy intc node found\n");
+               return -EINVAL;
+       }
+
+       pcie->legacy_irq_domain = irq_domain_add_linear(legacy_intc_node,
+                                                       INTX_NUM,
+                                                       &legacy_domain_ops,
+                                                       pcie);
+
+       if (!pcie->legacy_irq_domain) {
+               dev_err(pcie->dev, "failed to create IRQ domain\n");
+               return -ENOMEM;
+       }
+
+       nwl_pcie_init_msi_irq_domain(pcie);
+       return 0;
+}
+
+static int nwl_pcie_enable_msi(struct nwl_pcie *pcie, struct pci_bus *bus)
+{
+       struct platform_device *pdev = to_platform_device(pcie->dev);
+       struct nwl_msi *msi = &pcie->msi;
+       unsigned long base;
+       int ret;
+       int size = BITS_TO_LONGS(INT_PCI_MSI_NR) * sizeof(long);
+
+       mutex_init(&msi->lock);
+
+       msi->bitmap = kzalloc(size, GFP_KERNEL);
+       if (!msi->bitmap)
+               return -ENOMEM;
+
+       /* Get msi_1 IRQ number */
+       msi->irq_msi1 = platform_get_irq_byname(pdev, "msi1");
+       if (msi->irq_msi1 < 0) {
+               dev_err(&pdev->dev, "failed to get IRQ#%d\n", msi->irq_msi1);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       irq_set_chained_handler_and_data(msi->irq_msi1,
+                                        nwl_pcie_msi_handler_high, pcie);
+
+       /* Get msi_0 IRQ number */
+       msi->irq_msi0 = platform_get_irq_byname(pdev, "msi0");
+       if (msi->irq_msi0 < 0) {
+               dev_err(&pdev->dev, "failed to get IRQ#%d\n", msi->irq_msi0);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       irq_set_chained_handler_and_data(msi->irq_msi0,
+                                        nwl_pcie_msi_handler_low, pcie);
+
+       /* Check for msii_present bit */
+       ret = nwl_bridge_readl(pcie, I_MSII_CAPABILITIES) & MSII_PRESENT;
+       if (!ret) {
+               dev_err(pcie->dev, "MSI not present\n");
+               ret = -EIO;
+               goto err;
+       }
+
+       /* Enable MSII */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, I_MSII_CONTROL) |
+                         MSII_ENABLE, I_MSII_CONTROL);
+
+       /* Enable MSII status */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, I_MSII_CONTROL) |
+                         MSII_STATUS_ENABLE, I_MSII_CONTROL);
+
+       /* setup AFI/FPCI range */
+       base = pcie->phys_pcie_reg_base;
+       nwl_bridge_writel(pcie, lower_32_bits(base), I_MSII_BASE_LO);
+       nwl_bridge_writel(pcie, upper_32_bits(base), I_MSII_BASE_HI);
+
+       /*
+        * For high range MSI interrupts: disable, clear any pending,
+        * and enable
+        */
+       nwl_bridge_writel(pcie, (u32)~MSGF_MSI_SR_HI_MASK, MSGF_MSI_MASK_HI);
+
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie,  MSGF_MSI_STATUS_HI) &
+                         MSGF_MSI_SR_HI_MASK, MSGF_MSI_STATUS_HI);
+
+       nwl_bridge_writel(pcie, MSGF_MSI_SR_HI_MASK, MSGF_MSI_MASK_HI);
+
+       /*
+        * For low range MSI interrupts: disable, clear any pending,
+        * and enable
+        */
+       nwl_bridge_writel(pcie, (u32)~MSGF_MSI_SR_LO_MASK, MSGF_MSI_MASK_LO);
+
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_MSI_STATUS_LO) &
+                         MSGF_MSI_SR_LO_MASK, MSGF_MSI_STATUS_LO);
+
+       nwl_bridge_writel(pcie, MSGF_MSI_SR_LO_MASK, MSGF_MSI_MASK_LO);
+
+       return 0;
+err:
+       kfree(msi->bitmap);
+       msi->bitmap = NULL;
+       return ret;
+}
+
+static int nwl_pcie_bridge_init(struct nwl_pcie *pcie)
+{
+       struct platform_device *pdev = to_platform_device(pcie->dev);
+       u32 breg_val, ecam_val, first_busno = 0;
+       int err;
+
+       breg_val = nwl_bridge_readl(pcie, E_BREG_CAPABILITIES) & BREG_PRESENT;
+       if (!breg_val) {
+               dev_err(pcie->dev, "BREG is not present\n");
+               return breg_val;
+       }
+
+       /* Write bridge_off to breg base */
+       nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_breg_base),
+                         E_BREG_BASE_LO);
+       nwl_bridge_writel(pcie, upper_32_bits(pcie->phys_breg_base),
+                         E_BREG_BASE_HI);
+
+       /* Enable BREG */
+       nwl_bridge_writel(pcie, ~BREG_ENABLE_FORCE & BREG_ENABLE,
+                         E_BREG_CONTROL);
+
+       /* Disable DMA channel registers */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, BRCFG_PCIE_RX0) |
+                         CFG_DMA_REG_BAR, BRCFG_PCIE_RX0);
+
+       /* Enable Ingress subtractive decode translation */
+       nwl_bridge_writel(pcie, SET_ISUB_CONTROL, I_ISUB_CONTROL);
+
+       /* Enable msg filtering details */
+       nwl_bridge_writel(pcie, CFG_ENABLE_MSG_FILTER_MASK,
+                         BRCFG_PCIE_RX_MSG_FILTER);
+
+       err = nwl_wait_for_link(pcie);
+       if (err)
+               return err;
+
+       ecam_val = nwl_bridge_readl(pcie, E_ECAM_CAPABILITIES) & E_ECAM_PRESENT;
+       if (!ecam_val) {
+               dev_err(pcie->dev, "ECAM is not present\n");
+               return ecam_val;
+       }
+
+       /* Enable ECAM */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) |
+                         E_ECAM_CR_ENABLE, E_ECAM_CONTROL);
+
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, E_ECAM_CONTROL) |
+                         (pcie->ecam_value << E_ECAM_SIZE_SHIFT),
+                         E_ECAM_CONTROL);
+
+       nwl_bridge_writel(pcie, lower_32_bits(pcie->phys_ecam_base),
+                         E_ECAM_BASE_LO);
+       nwl_bridge_writel(pcie, upper_32_bits(pcie->phys_ecam_base),
+                         E_ECAM_BASE_HI);
+
+       /* Get bus range */
+       ecam_val = nwl_bridge_readl(pcie, E_ECAM_CONTROL);
+       pcie->last_busno = (ecam_val & E_ECAM_SIZE_LOC) >> E_ECAM_SIZE_SHIFT;
+       /* Write primary, secondary and subordinate bus numbers */
+       ecam_val = first_busno;
+       ecam_val |= (first_busno + 1) << 8;
+       ecam_val |= (pcie->last_busno << E_ECAM_SIZE_SHIFT);
+       writel(ecam_val, (pcie->ecam_base + PCI_PRIMARY_BUS));
+
+       if (nwl_pcie_link_up(pcie))
+               dev_info(pcie->dev, "Link is UP\n");
+       else
+               dev_info(pcie->dev, "Link is DOWN\n");
+
+       /* Get misc IRQ number */
+       pcie->irq_misc = platform_get_irq_byname(pdev, "misc");
+       if (pcie->irq_misc < 0) {
+               dev_err(&pdev->dev, "failed to get misc IRQ %d\n",
+                       pcie->irq_misc);
+               return -EINVAL;
+       }
+
+       err = devm_request_irq(pcie->dev, pcie->irq_misc,
+                              nwl_pcie_misc_handler, IRQF_SHARED,
+                              "nwl_pcie:misc", pcie);
+       if (err) {
+               dev_err(pcie->dev, "fail to register misc IRQ#%d\n",
+                       pcie->irq_misc);
+               return err;
+       }
+
+       /* Disable all misc interrupts */
+       nwl_bridge_writel(pcie, (u32)~MSGF_MISC_SR_MASKALL, MSGF_MISC_MASK);
+
+       /* Clear pending misc interrupts */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_MISC_STATUS) &
+                         MSGF_MISC_SR_MASKALL, MSGF_MISC_STATUS);
+
+       /* Enable all misc interrupts */
+       nwl_bridge_writel(pcie, MSGF_MISC_SR_MASKALL, MSGF_MISC_MASK);
+
+
+       /* Disable all legacy interrupts */
+       nwl_bridge_writel(pcie, (u32)~MSGF_LEG_SR_MASKALL, MSGF_LEG_MASK);
+
+       /* Clear pending legacy interrupts */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, MSGF_LEG_STATUS) &
+                         MSGF_LEG_SR_MASKALL, MSGF_LEG_STATUS);
+
+       /* Enable all legacy interrupts */
+       nwl_bridge_writel(pcie, MSGF_LEG_SR_MASKALL, MSGF_LEG_MASK);
+
+       /* Enable the bridge config interrupt */
+       nwl_bridge_writel(pcie, nwl_bridge_readl(pcie, BRCFG_INTERRUPT) |
+                         BRCFG_INTERRUPT_MASK, BRCFG_INTERRUPT);
+
+       return 0;
+}
+
+static int nwl_pcie_parse_dt(struct nwl_pcie *pcie,
+                            struct platform_device *pdev)
+{
+       struct device_node *node = pcie->dev->of_node;
+       struct resource *res;
+       const char *type;
+
+       /* Check for device type */
+       type = of_get_property(node, "device_type", NULL);
+       if (!type || strcmp(type, "pci")) {
+               dev_err(pcie->dev, "invalid \"device_type\" %s\n", type);
+               return -EINVAL;
+       }
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "breg");
+       pcie->breg_base = devm_ioremap_resource(pcie->dev, res);
+       if (IS_ERR(pcie->breg_base))
+               return PTR_ERR(pcie->breg_base);
+       pcie->phys_breg_base = res->start;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcireg");
+       pcie->pcireg_base = devm_ioremap_resource(pcie->dev, res);
+       if (IS_ERR(pcie->pcireg_base))
+               return PTR_ERR(pcie->pcireg_base);
+       pcie->phys_pcie_reg_base = res->start;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
+       pcie->ecam_base = devm_ioremap_resource(pcie->dev, res);
+       if (IS_ERR(pcie->ecam_base))
+               return PTR_ERR(pcie->ecam_base);
+       pcie->phys_ecam_base = res->start;
+
+       /* Get intx IRQ number */
+       pcie->irq_intx = platform_get_irq_byname(pdev, "intx");
+       if (pcie->irq_intx < 0) {
+               dev_err(&pdev->dev, "failed to get intx IRQ %d\n",
+                       pcie->irq_intx);
+               return -EINVAL;
+       }
+
+       irq_set_chained_handler_and_data(pcie->irq_intx,
+                                        nwl_pcie_leg_handler, pcie);
+
+       return 0;
+}
+
+static const struct of_device_id nwl_pcie_of_match[] = {
+       { .compatible = "xlnx,nwl-pcie-2.11", },
+       {}
+};
+
+static int nwl_pcie_probe(struct platform_device *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct nwl_pcie *pcie;
+       struct pci_bus *bus;
+       struct pci_bus *child;
+       int err;
+       resource_size_t iobase = 0;
+       LIST_HEAD(res);
+
+       pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
+       if (!pcie)
+               return -ENOMEM;
+
+       pcie->dev = &pdev->dev;
+       pcie->ecam_value = NWL_ECAM_VALUE_DEFAULT;
+
+       err = nwl_pcie_parse_dt(pcie, pdev);
+       if (err) {
+               dev_err(pcie->dev, "Parsing DT failed\n");
+               return err;
+       }
+
+       err = nwl_pcie_bridge_init(pcie);
+       if (err) {
+               dev_err(pcie->dev, "HW Initalization failed\n");
+               return err;
+       }
+
+       err = of_pci_get_host_bridge_resources(node, 0, 0xff, &res, &iobase);
+       if (err) {
+               pr_err("Getting bridge resources failed\n");
+               return err;
+       }
+
+       err = nwl_pcie_init_irq_domain(pcie);
+       if (err) {
+               dev_err(pcie->dev, "Failed creating IRQ Domain\n");
+               return err;
+       }
+
+       bus = pci_create_root_bus(&pdev->dev, pcie->root_busno,
+                                 &nwl_pcie_ops, pcie, &res);
+       if (!bus)
+               return -ENOMEM;
+
+       if (IS_ENABLED(CONFIG_PCI_MSI)) {
+               err = nwl_pcie_enable_msi(pcie, bus);
+               if (err < 0) {
+                       dev_err(&pdev->dev,
+                               "failed to enable MSI support: %d\n", err);
+                       return err;
+               }
+       }
+       pci_scan_child_bus(bus);
+       pci_assign_unassigned_bus_resources(bus);
+       list_for_each_entry(child, &bus->children, node)
+               pcie_bus_configure_settings(child);
+       pci_bus_add_devices(bus);
+       platform_set_drvdata(pdev, pcie);
+       return 0;
+}
+
+static int nwl_pcie_remove(struct platform_device *pdev)
+{
+       struct nwl_pcie *pcie = platform_get_drvdata(pdev);
+
+       nwl_pcie_free_irq_domain(pcie);
+       platform_set_drvdata(pdev, NULL);
+       return 0;
+}
+
+static struct platform_driver nwl_pcie_driver = {
+       .driver = {
+               .name = "nwl-pcie",
+               .of_match_table = nwl_pcie_of_match,
+       },
+       .probe = nwl_pcie_probe,
+       .remove = nwl_pcie_remove,
+};
+module_platform_driver(nwl_pcie_driver);
+
+MODULE_AUTHOR("Xilinx, Inc");
+MODULE_DESCRIPTION("NWL PCIe driver");
+MODULE_LICENSE("GPL");
index 4cfa46360d1229976533f3a0c42152c30a282099..65f0fe0c2eafb67141fd84f84b31285ff038c868 100644 (file)
@@ -94,9 +94,6 @@
 /* Number of MSI IRQs */
 #define XILINX_NUM_MSI_IRQS            128
 
-/* Number of Memory Resources */
-#define XILINX_MAX_NUM_RESOURCES       3
-
 /**
  * struct xilinx_pcie_port - PCIe port information
  * @reg_base: IO Mapped Register Base
  * @root_busno: Root Bus number
  * @dev: Device pointer
  * @irq_domain: IRQ domain pointer
- * @bus_range: Bus range
  * @resources: Bus Resources
  */
 struct xilinx_pcie_port {
@@ -115,17 +111,11 @@ struct xilinx_pcie_port {
        u8 root_busno;
        struct device *dev;
        struct irq_domain *irq_domain;
-       struct resource bus_range;
        struct list_head resources;
 };
 
 static DECLARE_BITMAP(msi_irq_in_use, XILINX_NUM_MSI_IRQS);
 
-static inline struct xilinx_pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
-       return sys->private_data;
-}
-
 static inline u32 pcie_read(struct xilinx_pcie_port *port, u32 reg)
 {
        return readl(port->reg_base + reg);
@@ -167,7 +157,7 @@ static void xilinx_pcie_clear_err_interrupts(struct xilinx_pcie_port *port)
  */
 static bool xilinx_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
 {
-       struct xilinx_pcie_port *port = sys_to_pcie(bus->sysdata);
+       struct xilinx_pcie_port *port = bus->sysdata;
 
        /* Check if link is up when trying to access downstream ports */
        if (bus->number != port->root_busno)
@@ -200,7 +190,7 @@ static bool xilinx_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
 static void __iomem *xilinx_pcie_map_bus(struct pci_bus *bus,
                                         unsigned int devfn, int where)
 {
-       struct xilinx_pcie_port *port = sys_to_pcie(bus->sysdata);
+       struct xilinx_pcie_port *port = bus->sysdata;
        int relbus;
 
        if (!xilinx_pcie_valid_device(bus, devfn))
@@ -232,7 +222,7 @@ static void xilinx_pcie_destroy_msi(unsigned int irq)
 
        if (!test_bit(irq, msi_irq_in_use)) {
                msi = irq_get_msi_desc(irq);
-               port = sys_to_pcie(msi_desc_to_pci_sysdata(msi));
+               port = msi_desc_to_pci_sysdata(msi);
                dev_err(port->dev, "Trying to free unused MSI#%d\n", irq);
        } else {
                clear_bit(irq, msi_irq_in_use);
@@ -281,7 +271,7 @@ static int xilinx_pcie_msi_setup_irq(struct msi_controller *chip,
                                     struct pci_dev *pdev,
                                     struct msi_desc *desc)
 {
-       struct xilinx_pcie_port *port = sys_to_pcie(pdev->bus->sysdata);
+       struct xilinx_pcie_port *port = pdev->bus->sysdata;
        unsigned int irq;
        int hwirq;
        struct msi_msg msg;
@@ -617,138 +607,6 @@ static void xilinx_pcie_init_port(struct xilinx_pcie_port *port)
                   XILINX_PCIE_REG_RPSC);
 }
 
-/**
- * xilinx_pcie_setup - Setup memory resources
- * @nr: Bus number
- * @sys: Per controller structure
- *
- * Return: '1' on success and error value on failure
- */
-static int xilinx_pcie_setup(int nr, struct pci_sys_data *sys)
-{
-       struct xilinx_pcie_port *port = sys_to_pcie(sys);
-
-       list_splice_init(&port->resources, &sys->resources);
-
-       return 1;
-}
-
-/**
- * xilinx_pcie_scan_bus - Scan PCIe bus for devices
- * @nr: Bus number
- * @sys: Per controller structure
- *
- * Return: Valid Bus pointer on success and NULL on failure
- */
-static struct pci_bus *xilinx_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
-       struct xilinx_pcie_port *port = sys_to_pcie(sys);
-       struct pci_bus *bus;
-
-       port->root_busno = sys->busnr;
-
-       if (IS_ENABLED(CONFIG_PCI_MSI))
-               bus = pci_scan_root_bus_msi(port->dev, sys->busnr,
-                                           &xilinx_pcie_ops, sys,
-                                           &sys->resources,
-                                           &xilinx_pcie_msi_chip);
-       else
-               bus = pci_scan_root_bus(port->dev, sys->busnr,
-                                       &xilinx_pcie_ops, sys, &sys->resources);
-       return bus;
-}
-
-/**
- * xilinx_pcie_parse_and_add_res - Add resources by parsing ranges
- * @port: PCIe port information
- *
- * Return: '0' on success and error value on failure
- */
-static int xilinx_pcie_parse_and_add_res(struct xilinx_pcie_port *port)
-{
-       struct device *dev = port->dev;
-       struct device_node *node = dev->of_node;
-       struct resource *mem;
-       resource_size_t offset;
-       struct of_pci_range_parser parser;
-       struct of_pci_range range;
-       struct resource_entry *win;
-       int err = 0, mem_resno = 0;
-
-       /* Get the ranges */
-       if (of_pci_range_parser_init(&parser, node)) {
-               dev_err(dev, "missing \"ranges\" property\n");
-               return -EINVAL;
-       }
-
-       /* Parse the ranges and add the resources found to the list */
-       for_each_of_pci_range(&parser, &range) {
-
-               if (mem_resno >= XILINX_MAX_NUM_RESOURCES) {
-                       dev_err(dev, "Maximum memory resources exceeded\n");
-                       return -EINVAL;
-               }
-
-               mem = devm_kmalloc(dev, sizeof(*mem), GFP_KERNEL);
-               if (!mem) {
-                       err = -ENOMEM;
-                       goto free_resources;
-               }
-
-               of_pci_range_to_resource(&range, node, mem);
-
-               switch (mem->flags & IORESOURCE_TYPE_BITS) {
-               case IORESOURCE_MEM:
-                       offset = range.cpu_addr - range.pci_addr;
-                       mem_resno++;
-                       break;
-               default:
-                       err = -EINVAL;
-                       break;
-               }
-
-               if (err < 0) {
-                       dev_warn(dev, "Invalid resource found %pR\n", mem);
-                       continue;
-               }
-
-               err = request_resource(&iomem_resource, mem);
-               if (err)
-                       goto free_resources;
-
-               pci_add_resource_offset(&port->resources, mem, offset);
-       }
-
-       /* Get the bus range */
-       if (of_pci_parse_bus_range(node, &port->bus_range)) {
-               u32 val = pcie_read(port, XILINX_PCIE_REG_BIR);
-               u8 last;
-
-               last = (val & XILINX_PCIE_BIR_ECAM_SZ_MASK) >>
-                       XILINX_PCIE_BIR_ECAM_SZ_SHIFT;
-
-               port->bus_range = (struct resource) {
-                       .name   = node->name,
-                       .start  = 0,
-                       .end    = last,
-                       .flags  = IORESOURCE_BUS,
-               };
-       }
-
-       /* Register bus resource */
-       pci_add_resource(&port->resources, &port->bus_range);
-
-       return 0;
-
-free_resources:
-       release_child_resources(&iomem_resource);
-       resource_list_for_each_entry(win, &port->resources)
-               devm_kfree(dev, win->res);
-       pci_free_resource_list(&port->resources);
-
-       return err;
-}
-
 /**
  * xilinx_pcie_parse_dt - Parse Device tree
  * @port: PCIe port information
@@ -800,9 +658,12 @@ static int xilinx_pcie_parse_dt(struct xilinx_pcie_port *port)
 static int xilinx_pcie_probe(struct platform_device *pdev)
 {
        struct xilinx_pcie_port *port;
-       struct hw_pci hw;
        struct device *dev = &pdev->dev;
+       struct pci_bus *bus;
+
        int err;
+       resource_size_t iobase = 0;
+       LIST_HEAD(res);
 
        if (!dev->of_node)
                return -ENODEV;
@@ -827,34 +688,28 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
                return err;
        }
 
-       /*
-        * Parse PCI ranges, configuration bus range and
-        * request their resources
-        */
-       INIT_LIST_HEAD(&port->resources);
-       err = xilinx_pcie_parse_and_add_res(port);
+       err = of_pci_get_host_bridge_resources(dev->of_node, 0, 0xff, &res,
+                                              &iobase);
        if (err) {
-               dev_err(dev, "Failed adding resources\n");
+               dev_err(dev, "Getting bridge resources failed\n");
                return err;
        }
-
-       platform_set_drvdata(pdev, port);
-
-       /* Register the device */
-       memset(&hw, 0, sizeof(hw));
-       hw = (struct hw_pci) {
-               .nr_controllers = 1,
-               .private_data   = (void **)&port,
-               .setup          = xilinx_pcie_setup,
-               .map_irq        = of_irq_parse_and_map_pci,
-               .scan           = xilinx_pcie_scan_bus,
-               .ops            = &xilinx_pcie_ops,
-       };
+       bus = pci_create_root_bus(&pdev->dev, 0,
+                                 &xilinx_pcie_ops, port, &res);
+       if (!bus)
+               return -ENOMEM;
 
 #ifdef CONFIG_PCI_MSI
        xilinx_pcie_msi_chip.dev = port->dev;
+       bus->msi = &xilinx_pcie_msi_chip;
 #endif
-       pci_common_init_dev(dev, &hw);
+       pci_scan_child_bus(bus);
+       pci_assign_unassigned_bus_resources(bus);
+#ifndef CONFIG_MICROBLAZE
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+       pci_bus_add_devices(bus);
+       platform_set_drvdata(pdev, port);
 
        return 0;
 }
index eb5efaef06ea5572b339d2aa3cead268e57722cc..50b8b7d54416dfe1fb773103fa52516e9690155b 100644 (file)
@@ -93,13 +93,17 @@ out_deconfigure:
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
+       struct pci_dev *pdev;
        int rc;
 
        if (!zpci_fn_configured(slot->zdev->state))
                return -EIO;
 
-       if (slot->zdev->pdev)
-               pci_stop_and_remove_bus_device_locked(slot->zdev->pdev);
+       pdev = pci_get_slot(slot->zdev->bus, ZPCI_DEVFN);
+       if (pdev) {
+               pci_stop_and_remove_bus_device_locked(pdev);
+               pci_dev_put(pdev);
+       }
 
        rc = zpci_disable_device(slot->zdev);
        if (rc)
index 31f31d460fc9de789d28d72365122224fa3b2551..fe4bd0aa91a622eb5ac185ef664d1ee9db698e41 100644 (file)
@@ -387,10 +387,6 @@ static int sriov_init(struct pci_dev *dev, int pos)
        struct resource *res;
        struct pci_dev *pdev;
 
-       if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END &&
-           pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT)
-               return -ENODEV;
-
        pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl);
        if (ctrl & PCI_SRIOV_CTRL_VFE) {
                pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, 0);
index 0ae74d96ed8577b5980484f0c0c9ecbea1e60c84..51357377efbce65d4ad8454ffd678fc4df8de7a2 100644 (file)
@@ -16,7 +16,7 @@
  * the instance number and string from the type 41 record and exports
  * it to sysfs.
  *
- * Please see http://linux.dell.com/wiki/index.php/Oss/libnetdevname for more
+ * Please see http://linux.dell.com/files/biosdevname/ for more
  * information.
  */
 
index 95d9e7bd933bc880315d3584033c4ea2ca41a3b9..e982010f0ed19e0d0379da4a1c02334a1db9f175 100644 (file)
@@ -769,10 +769,12 @@ static ssize_t read_vpd_attr(struct file *filp, struct kobject *kobj,
 {
        struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
 
-       if (off > bin_attr->size)
-               count = 0;
-       else if (count > bin_attr->size - off)
-               count = bin_attr->size - off;
+       if (bin_attr->size > 0) {
+               if (off > bin_attr->size)
+                       count = 0;
+               else if (count > bin_attr->size - off)
+                       count = bin_attr->size - off;
+       }
 
        return pci_read_vpd(dev, off, count, buf);
 }
@@ -783,10 +785,12 @@ static ssize_t write_vpd_attr(struct file *filp, struct kobject *kobj,
 {
        struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
 
-       if (off > bin_attr->size)
-               count = 0;
-       else if (count > bin_attr->size - off)
-               count = bin_attr->size - off;
+       if (bin_attr->size > 0) {
+               if (off > bin_attr->size)
+                       count = 0;
+               else if (count > bin_attr->size - off)
+                       count = bin_attr->size - off;
+       }
 
        return pci_write_vpd(dev, off, count, buf);
 }
@@ -1134,33 +1138,36 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
        /* allocate attribute structure, piggyback attribute name */
        int name_len = write_combine ? 13 : 10;
        struct bin_attribute *res_attr;
+       char *res_attr_name;
        int retval;
 
        res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC);
-       if (res_attr) {
-               char *res_attr_name = (char *)(res_attr + 1);
-
-               sysfs_bin_attr_init(res_attr);
-               if (write_combine) {
-                       pdev->res_attr_wc[num] = res_attr;
-                       sprintf(res_attr_name, "resource%d_wc", num);
-                       res_attr->mmap = pci_mmap_resource_wc;
-               } else {
-                       pdev->res_attr[num] = res_attr;
-                       sprintf(res_attr_name, "resource%d", num);
-                       res_attr->mmap = pci_mmap_resource_uc;
-               }
-               if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
-                       res_attr->read = pci_read_resource_io;
-                       res_attr->write = pci_write_resource_io;
-               }
-               res_attr->attr.name = res_attr_name;
-               res_attr->attr.mode = S_IRUSR | S_IWUSR;
-               res_attr->size = pci_resource_len(pdev, num);
-               res_attr->private = &pdev->resource[num];
-               retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
-       } else
-               retval = -ENOMEM;
+       if (!res_attr)
+               return -ENOMEM;
+
+       res_attr_name = (char *)(res_attr + 1);
+
+       sysfs_bin_attr_init(res_attr);
+       if (write_combine) {
+               pdev->res_attr_wc[num] = res_attr;
+               sprintf(res_attr_name, "resource%d_wc", num);
+               res_attr->mmap = pci_mmap_resource_wc;
+       } else {
+               pdev->res_attr[num] = res_attr;
+               sprintf(res_attr_name, "resource%d", num);
+               res_attr->mmap = pci_mmap_resource_uc;
+       }
+       if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
+               res_attr->read = pci_read_resource_io;
+               res_attr->write = pci_write_resource_io;
+       }
+       res_attr->attr.name = res_attr_name;
+       res_attr->attr.mode = S_IRUSR | S_IWUSR;
+       res_attr->size = pci_resource_len(pdev, num);
+       res_attr->private = &pdev->resource[num];
+       retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
+       if (retval)
+               kfree(res_attr);
 
        return retval;
 }
@@ -1319,7 +1326,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
                        return -ENOMEM;
 
                sysfs_bin_attr_init(attr);
-               attr->size = dev->vpd->len;
+               attr->size = 0;
                attr->attr.name = "vpd";
                attr->attr.mode = S_IRUSR | S_IWUSR;
                attr->read = read_vpd_attr;
@@ -1356,7 +1363,7 @@ error:
 int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
 {
        int retval;
-       int rom_size = 0;
+       int rom_size;
        struct bin_attribute *attr;
 
        if (!sysfs_initialized)
@@ -1373,12 +1380,8 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
        if (retval)
                goto err_config_file;
 
-       if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
-               rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-       else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
-               rom_size = 0x20000;
-
        /* If the device has a ROM, try to expose it in sysfs. */
+       rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
        if (rom_size) {
                attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
                if (!attr) {
@@ -1409,7 +1412,7 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
        return 0;
 
 err_rom_file:
-       if (rom_size) {
+       if (pdev->rom_attr) {
                sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
                kfree(pdev->rom_attr);
                pdev->rom_attr = NULL;
@@ -1447,8 +1450,6 @@ static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
  */
 void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 {
-       int rom_size = 0;
-
        if (!sysfs_initialized)
                return;
 
@@ -1461,18 +1462,13 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 
        pci_remove_resource_files(pdev);
 
-       if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
-               rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-       else if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
-               rom_size = 0x20000;
-
-       if (rom_size && pdev->rom_attr) {
+       if (pdev->rom_attr) {
                sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
                kfree(pdev->rom_attr);
+               pdev->rom_attr = NULL;
        }
 
        pci_remove_firmware_label_files(pdev);
-
 }
 
 static int __init pci_sysfs_init(void)
index 602eb422351060c611967538359b8409885397a1..25e0327d4429bfc00a694f66f4a28fc7233fb7df 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci_hotplug.h>
-#include <asm-generic/pci-bridge.h>
 #include <asm/setup.h>
 #include <linux/aer.h>
 #include "pci.h"
@@ -3386,18 +3385,6 @@ bool pci_check_and_unmask_intx(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
 
-int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
-{
-       return dma_set_max_seg_size(&dev->dev, size);
-}
-EXPORT_SYMBOL(pci_set_dma_max_seg_size);
-
-int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
-{
-       return dma_set_seg_boundary(&dev->dev, mask);
-}
-EXPORT_SYMBOL(pci_set_dma_seg_boundary);
-
 /**
  * pci_wait_for_pending_transaction - waits for pending transaction
  * @dev: the PCI device to operate on
@@ -3414,6 +3401,29 @@ int pci_wait_for_pending_transaction(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_wait_for_pending_transaction);
 
+/*
+ * We should only need to wait 100ms after FLR, but some devices take longer.
+ * Wait for up to 1000ms for config space to return something other than -1.
+ * Intel IGD requires this when an LCD panel is attached.  We read the 2nd
+ * dword because VFs don't implement the 1st dword.
+ */
+static void pci_flr_wait(struct pci_dev *dev)
+{
+       int i = 0;
+       u32 id;
+
+       do {
+               msleep(100);
+               pci_read_config_dword(dev, PCI_COMMAND, &id);
+       } while (i++ < 10 && id == ~0);
+
+       if (id == ~0)
+               dev_warn(&dev->dev, "Failed to return from FLR\n");
+       else if (i > 1)
+               dev_info(&dev->dev, "Required additional %dms to return from FLR\n",
+                        (i - 1) * 100);
+}
+
 static int pcie_flr(struct pci_dev *dev, int probe)
 {
        u32 cap;
@@ -3429,7 +3439,7 @@ static int pcie_flr(struct pci_dev *dev, int probe)
                dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
 
        pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
-       msleep(100);
+       pci_flr_wait(dev);
        return 0;
 }
 
@@ -3459,7 +3469,7 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
                dev_err(&dev->dev, "timed out waiting for pending transaction; performing AF function level reset anyway\n");
 
        pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR);
-       msleep(100);
+       pci_flr_wait(dev);
        return 0;
 }
 
@@ -4772,8 +4782,10 @@ int pci_get_new_domain_nr(void)
 void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
 {
        static int use_dt_domains = -1;
-       int domain = of_get_pci_domain_nr(parent->of_node);
+       int domain = -1;
 
+       if (parent)
+               domain = of_get_pci_domain_nr(parent->of_node);
        /*
         * Check DT domain and use_dt_domains values.
         *
index 9a1660f592ef75f061d154c68629d9bd795c538a..d0fb93481573ad3282e917e09d4852c723ecbd15 100644 (file)
@@ -97,21 +97,21 @@ static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
 struct pci_vpd_ops {
        ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
        ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
-       void (*release)(struct pci_dev *dev);
 };
 
 struct pci_vpd {
-       unsigned int len;
        const struct pci_vpd_ops *ops;
        struct bin_attribute *attr; /* descriptor for sysfs VPD entry */
+       struct mutex    lock;
+       unsigned int    len;
+       u16             flag;
+       u8              cap;
+       u8              busy:1;
+       u8              valid:1;
 };
 
-int pci_vpd_pci22_init(struct pci_dev *dev);
-static inline void pci_vpd_release(struct pci_dev *dev)
-{
-       if (dev->vpd)
-               dev->vpd->ops->release(dev);
-}
+int pci_vpd_init(struct pci_dev *dev);
+void pci_vpd_release(struct pci_dev *dev);
 
 /* PCI /proc functions */
 #ifdef CONFIG_PROC_FS
index e294713c8143bf4e5513872881e11aae0048bf54..72db7f4209cad52181cc80b38558f4827955a866 100644 (file)
@@ -44,6 +44,7 @@ config PCIEASPM
          /sys/module/pcie_aspm/parameters/policy
 
          When in doubt, say Y.
+
 config PCIEASPM_DEBUG
        bool "Debug PCI Express ASPM"
        depends on PCIEASPM
@@ -58,20 +59,20 @@ choice
        depends on PCIEASPM
 
 config PCIEASPM_DEFAULT
-        bool "BIOS default"
+       bool "BIOS default"
        depends on PCIEASPM
        help
          Use the BIOS defaults for PCI Express ASPM.
 
 config PCIEASPM_POWERSAVE
-        bool "Powersave"
+       bool "Powersave"
        depends on PCIEASPM
        help
          Enable PCI Express ASPM L0s and L1 where possible, even if the
          BIOS did not.
 
 config PCIEASPM_PERFORMANCE
-        bool "Performance"
+       bool "Performance"
        depends on PCIEASPM
        help
          Disable PCI Express ASPM L0s and L1, even if the BIOS enabled them.
index 20db790465dd682efae0ade88d7ac42cfd52b060..db553dc22c8e0fca49ad98ff2f9fd3111e18918a 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 #include <linux/stddef.h>
+#include <linux/device.h>
 #include "aerdrv.h"
 
 /* Override the existing corrected and uncorrected error masks */
@@ -124,16 +125,13 @@ static struct pci_ops *__find_pci_bus_ops(struct pci_bus *bus)
 static struct pci_bus_ops *pci_bus_ops_pop(void)
 {
        unsigned long flags;
-       struct pci_bus_ops *bus_ops = NULL;
+       struct pci_bus_ops *bus_ops;
 
        spin_lock_irqsave(&inject_lock, flags);
-       if (list_empty(&pci_bus_ops_list))
-               bus_ops = NULL;
-       else {
-               struct list_head *lh = pci_bus_ops_list.next;
-               list_del(lh);
-               bus_ops = list_entry(lh, struct pci_bus_ops, list);
-       }
+       bus_ops = list_first_entry_or_null(&pci_bus_ops_list,
+                                          struct pci_bus_ops, list);
+       if (bus_ops)
+               list_del(&bus_ops->list);
        spin_unlock_irqrestore(&inject_lock, flags);
        return bus_ops;
 }
@@ -181,14 +179,16 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where,
        return target;
 }
 
-static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
-                       int size, u32 *val)
+static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn,
+                              int where, int size, u32 *val)
 {
        u32 *sim;
        struct aer_error *err;
        unsigned long flags;
        struct pci_ops *ops;
+       struct pci_ops *my_ops;
        int domain;
+       int rv;
 
        spin_lock_irqsave(&inject_lock, flags);
        if (size != sizeof(u32))
@@ -208,19 +208,32 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
        }
 out:
        ops = __find_pci_bus_ops(bus);
+       /*
+        * pci_lock must already be held, so we can directly
+        * manipulate bus->ops.  Many config access functions,
+        * including pci_generic_config_read() require the original
+        * bus->ops be installed to function, so temporarily put them
+        * back.
+        */
+       my_ops = bus->ops;
+       bus->ops = ops;
+       rv = ops->read(bus, devfn, where, size, val);
+       bus->ops = my_ops;
        spin_unlock_irqrestore(&inject_lock, flags);
-       return ops->read(bus, devfn, where, size, val);
+       return rv;
 }
 
-static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where,
-                        int size, u32 val)
+static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn,
+                               int where, int size, u32 val)
 {
        u32 *sim;
        struct aer_error *err;
        unsigned long flags;
        int rw1cs;
        struct pci_ops *ops;
+       struct pci_ops *my_ops;
        int domain;
+       int rv;
 
        spin_lock_irqsave(&inject_lock, flags);
        if (size != sizeof(u32))
@@ -243,13 +256,24 @@ static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where,
        }
 out:
        ops = __find_pci_bus_ops(bus);
+       /*
+        * pci_lock must already be held, so we can directly
+        * manipulate bus->ops.  Many config access functions,
+        * including pci_generic_config_write() require the original
+        * bus->ops be installed to function, so temporarily put them
+        * back.
+        */
+       my_ops = bus->ops;
+       bus->ops = ops;
+       rv = ops->write(bus, devfn, where, size, val);
+       bus->ops = my_ops;
        spin_unlock_irqrestore(&inject_lock, flags);
-       return ops->write(bus, devfn, where, size, val);
+       return rv;
 }
 
-static struct pci_ops pci_ops_aer = {
-       .read = pci_read_aer,
-       .write = pci_write_aer,
+static struct pci_ops aer_inj_pci_ops = {
+       .read = aer_inj_read_config,
+       .write = aer_inj_write_config,
 };
 
 static void pci_bus_ops_init(struct pci_bus_ops *bus_ops,
@@ -270,9 +294,9 @@ static int pci_bus_set_aer_ops(struct pci_bus *bus)
        bus_ops = kmalloc(sizeof(*bus_ops), GFP_KERNEL);
        if (!bus_ops)
                return -ENOMEM;
-       ops = pci_bus_set_ops(bus, &pci_ops_aer);
+       ops = pci_bus_set_ops(bus, &aer_inj_pci_ops);
        spin_lock_irqsave(&inject_lock, flags);
-       if (ops == &pci_ops_aer)
+       if (ops == &aer_inj_pci_ops)
                goto out;
        pci_bus_ops_init(bus_ops, bus, ops);
        list_add(&bus_ops->list, &pci_bus_ops_list);
@@ -334,13 +358,15 @@ static int aer_inject(struct aer_error_inj *einj)
                return -ENODEV;
        rpdev = pcie_find_root_port(dev);
        if (!rpdev) {
+               dev_err(&dev->dev, "aer_inject: Root port not found\n");
                ret = -ENODEV;
                goto out_put;
        }
 
        pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
        if (!pos_cap_err) {
-               ret = -EPERM;
+               dev_err(&dev->dev, "aer_inject: Device doesn't support AER\n");
+               ret = -EPROTONOSUPPORT;
                goto out_put;
        }
        pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
@@ -350,7 +376,9 @@ static int aer_inject(struct aer_error_inj *einj)
 
        rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
        if (!rp_pos_cap_err) {
-               ret = -EPERM;
+               dev_err(&rpdev->dev,
+                       "aer_inject: Root port doesn't support AER\n");
+               ret = -EPROTONOSUPPORT;
                goto out_put;
        }
 
@@ -397,14 +425,16 @@ static int aer_inject(struct aer_error_inj *einj)
        if (!aer_mask_override && einj->cor_status &&
            !(einj->cor_status & ~cor_mask)) {
                ret = -EINVAL;
-               printk(KERN_WARNING "The correctable error(s) is masked by device\n");
+               dev_warn(&dev->dev,
+                        "aer_inject: The correctable error(s) is masked by device\n");
                spin_unlock_irqrestore(&inject_lock, flags);
                goto out_put;
        }
        if (!aer_mask_override && einj->uncor_status &&
            !(einj->uncor_status & ~uncor_mask)) {
                ret = -EINVAL;
-               printk(KERN_WARNING "The uncorrectable error(s) is masked by device\n");
+               dev_warn(&dev->dev,
+                        "aer_inject: The uncorrectable error(s) is masked by device\n");
                spin_unlock_irqrestore(&inject_lock, flags);
                goto out_put;
        }
@@ -457,13 +487,19 @@ static int aer_inject(struct aer_error_inj *einj)
 
        if (find_aer_device(rpdev, &edev)) {
                if (!get_service_data(edev)) {
-                       printk(KERN_WARNING "AER service is not initialized\n");
-                       ret = -EINVAL;
+                       dev_warn(&edev->device,
+                                "aer_inject: AER service is not initialized\n");
+                       ret = -EPROTONOSUPPORT;
                        goto out_put;
                }
+               dev_info(&edev->device,
+                        "aer_inject: Injecting errors %08x/%08x into device %s\n",
+                        einj->cor_status, einj->uncor_status, pci_name(dev));
                aer_irq(-1, edev);
-       } else
-               ret = -EINVAL;
+       } else {
+               dev_err(&rpdev->dev, "aer_inject: AER device not found\n");
+               ret = -ENODEV;
+       }
 out_put:
        kfree(err_alloc);
        kfree(rperr_alloc);
index 63fc63911295e7c0be875b39436c889c6850234e..1ae4c73e7a3c3037f5430df3159b606f69287c77 100644 (file)
@@ -396,7 +396,7 @@ static int pcie_pme_suspend(struct pcie_device *srv)
 {
        struct pcie_pme_service_data *data = get_service_data(srv);
        struct pci_dev *port = srv->port;
-       bool wakeup;
+       bool wakeup, wake_irq_enabled = false;
        int ret;
 
        if (device_may_wakeup(&port->dev)) {
@@ -409,11 +409,12 @@ static int pcie_pme_suspend(struct pcie_device *srv)
        spin_lock_irq(&data->lock);
        if (wakeup) {
                ret = enable_irq_wake(srv->irq);
-               data->suspend_level = PME_SUSPEND_WAKEUP;
+               if (ret == 0) {
+                       data->suspend_level = PME_SUSPEND_WAKEUP;
+                       wake_irq_enabled = true;
+               }
        }
-       if (!wakeup || ret) {
-               struct pci_dev *port = srv->port;
-
+       if (!wake_irq_enabled) {
                pcie_pme_interrupt_enable(port, false);
                pcie_clear_root_pme_status(port);
                data->suspend_level = PME_SUSPEND_NOIRQ;
index 6d7ab9bb0d5a6f002debd5a3b83e569f78c44c96..8004f67c57ec6ae59157714e507f06429127765e 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/pci-aspm.h>
 #include <linux/aer.h>
 #include <linux/acpi.h>
-#include <asm-generic/pci-bridge.h>
+#include <linux/irqdomain.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER  176     /* secondary latency timer */
@@ -179,6 +179,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
        u16 orig_cmd;
        struct pci_bus_region region, inverted_region;
 
+       if (dev->non_compliant_bars)
+               return 0;
+
        mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
 
        /* No printks while decoding is disabled! */
@@ -675,6 +678,20 @@ static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus)
        if (!d)
                d = pci_host_bridge_acpi_msi_domain(bus);
 
+#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+       /*
+        * If no IRQ domain was found via the OF tree, try looking it up
+        * directly through the fwnode_handle.
+        */
+       if (!d) {
+               struct fwnode_handle *fwnode = pci_root_bus_fwnode(bus);
+
+               if (fwnode)
+                       d = irq_find_matching_fwnode(fwnode,
+                                                    DOMAIN_BUS_PCI_MSI);
+       }
+#endif
+
        return d;
 }
 
@@ -758,6 +775,12 @@ add_dev:
 
        pcibios_add_bus(child);
 
+       if (child->ops->add_bus) {
+               ret = child->ops->add_bus(child);
+               if (WARN_ON(ret < 0))
+                       dev_err(&child->dev, "failed to add bus: %d\n", ret);
+       }
+
        /* Create legacy_io and legacy_mem files for this bus */
        pci_create_legacy_files(child);
 
@@ -1171,6 +1194,7 @@ static void pci_msi_setup_pci_dev(struct pci_dev *dev)
 int pci_setup_device(struct pci_dev *dev)
 {
        u32 class;
+       u16 cmd;
        u8 hdr_type;
        int pos = 0;
        struct pci_bus_region region;
@@ -1214,6 +1238,16 @@ int pci_setup_device(struct pci_dev *dev)
        /* device class may be changed after fixup */
        class = dev->class >> 8;
 
+       if (dev->non_compliant_bars) {
+               pci_read_config_word(dev, PCI_COMMAND, &cmd);
+               if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+                       dev_info(&dev->dev, "device has non-compliant BARs; disabling IO/MEM decoding\n");
+                       cmd &= ~PCI_COMMAND_IO;
+                       cmd &= ~PCI_COMMAND_MEMORY;
+                       pci_write_config_word(dev, PCI_COMMAND, cmd);
+               }
+       }
+
        switch (dev->hdr_type) {                    /* header type */
        case PCI_HEADER_TYPE_NORMAL:                /* standard header */
                if (class == PCI_CLASS_BRIDGE_PCI)
@@ -1608,7 +1642,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
        pci_pm_init(dev);
 
        /* Vital Product Data */
-       pci_vpd_pci22_init(dev);
+       pci_vpd_init(dev);
 
        /* Alternative Routing-ID Forwarding */
        pci_configure_ari(dev);
@@ -1803,6 +1837,13 @@ static int only_one_child(struct pci_bus *bus)
                return 0;
        if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT)
                return 1;
+
+       /*
+        * PCIe downstream ports are bridges that normally lead to only a
+        * device 0, but if PCI_SCAN_ALL_PCIE_DEVS is set, scan all
+        * possible devices, not just device 0.  See PCIe spec r3.0,
+        * sec 7.3.1.
+        */
        if (parent->has_secondary_link &&
            !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
                return 1;
index 0575a1e026b4c4550ee07655910cc64d0e0e9341..8e678027b9008ee15e741967313332db2818c8d8 100644 (file)
@@ -438,7 +438,7 @@ static void quirk_amd_nl_class(struct pci_dev *pdev)
        u32 class = pdev->class;
 
        /* Use "USB Device (not host controller)" class */
-       pdev->class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe;
+       pdev->class = PCI_CLASS_SERIAL_USB_DEVICE;
        dev_info(&pdev->dev, "PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
                 class, pdev->class);
 }
@@ -2134,6 +2134,35 @@ static void quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching);
 
+/*
+ * If a device follows the VPD format spec, the PCI core will not read or
+ * write past the VPD End Tag.  But some vendors do not follow the VPD
+ * format spec, so we can't tell how much data is safe to access.  Devices
+ * may behave unpredictably if we access too much.  Blacklist these devices
+ * so we don't touch VPD at all.
+ */
+static void quirk_blacklist_vpd(struct pci_dev *dev)
+{
+       if (dev->vpd) {
+               dev->vpd->len = 0;
+               dev_warn(&dev->dev, FW_BUG "VPD access disabled\n");
+       }
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0060, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x007c, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0413, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0078, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0079, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0073, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0071, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005b, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x002f, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005d, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005f, quirk_blacklist_vpd);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, PCI_ANY_ID,
+               quirk_blacklist_vpd);
+
 /*
  * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the
  * VPD end tag will hang the device.  This problem was initially
@@ -3832,6 +3861,19 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)
 #endif
 }
 
+static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
+{
+       /*
+        * Cavium devices matching this quirk do not perform peer-to-peer
+        * with other functions, allowing masking out these bits as if they
+        * were unimplemented in the ACS capability.
+        */
+       acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
+                      PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
+
+       return acs_flags ? 0 : 1;
+}
+
 /*
  * Many Intel PCH root ports do provide ACS-like features to disable peer
  * transactions and validate bus numbers in requests, but do not provide an
@@ -3984,6 +4026,8 @@ static const struct pci_dev_acs_enabled {
        { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
        { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */
        { 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */
+       /* Cavium ThunderX */
+       { PCI_VENDOR_ID_CAVIUM, PCI_ANY_ID, pci_quirk_cavium_acs },
        { 0 }
 };
 
index 8a280e9c2ad1e00b1cca15b4592d79c7460e1363..8982026637d5598a27c9a36d3b265c6b74cb4a0d 100644 (file)
@@ -7,7 +7,6 @@ static void pci_free_resources(struct pci_dev *dev)
 {
        int i;
 
-       pci_cleanup_rom(dev);
        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
                struct resource *res = dev->resource + i;
                if (res->parent)
@@ -54,6 +53,10 @@ void pci_remove_bus(struct pci_bus *bus)
        pci_bus_release_busn_res(bus);
        up_write(&pci_bus_sem);
        pci_remove_legacy_files(bus);
+
+       if (bus->ops->remove_bus)
+               bus->ops->remove_bus(bus);
+
        pcibios_remove_bus(bus);
        device_unregister(&bus->dev);
 }
index 9eaca39ef38d1ccca5829b708d23b800d52fae61..06663d391b393782de79260c8ae4addc46983535 100644 (file)
  */
 int pci_enable_rom(struct pci_dev *pdev)
 {
-       struct resource *res = pdev->resource + PCI_ROM_RESOURCE;
+       struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
        struct pci_bus_region region;
        u32 rom_addr;
 
        if (!res->flags)
                return -1;
 
+       /* Nothing to enable if we're using a shadow copy in RAM */
+       if (res->flags & IORESOURCE_ROM_SHADOW)
+               return 0;
+
        pcibios_resource_to_bus(pdev->bus, &region, res);
        pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
        rom_addr &= ~PCI_ROM_ADDRESS_MASK;
@@ -49,7 +53,12 @@ EXPORT_SYMBOL_GPL(pci_enable_rom);
  */
 void pci_disable_rom(struct pci_dev *pdev)
 {
+       struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
        u32 rom_addr;
+
+       if (res->flags & IORESOURCE_ROM_SHADOW)
+               return;
+
        pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
        rom_addr &= ~PCI_ROM_ADDRESS_ENABLE;
        pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
@@ -119,43 +128,23 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
        loff_t start;
        void __iomem *rom;
 
-       /*
-        * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
-        * memory map if the VGA enable bit of the Bridge Control register is
-        * set for embedded VGA.
-        */
-       if (res->flags & IORESOURCE_ROM_SHADOW) {
-               /* primary video rom always starts here */
-               start = (loff_t)0xC0000;
-               *size = 0x20000; /* cover C000:0 through E000:0 */
-       } else {
-               if (res->flags &
-                       (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) {
-                       *size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-                       return (void __iomem *)(unsigned long)
-                               pci_resource_start(pdev, PCI_ROM_RESOURCE);
-               } else {
-                       /* assign the ROM an address if it doesn't have one */
-                       if (res->parent == NULL &&
-                           pci_assign_resource(pdev, PCI_ROM_RESOURCE))
-                               return NULL;
-                       start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
-                       *size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
-                       if (*size == 0)
-                               return NULL;
-
-                       /* Enable ROM space decodes */
-                       if (pci_enable_rom(pdev))
-                               return NULL;
-               }
-       }
+       /* assign the ROM an address if it doesn't have one */
+       if (res->parent == NULL && pci_assign_resource(pdev, PCI_ROM_RESOURCE))
+               return NULL;
+
+       start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
+       *size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
+       if (*size == 0)
+               return NULL;
+
+       /* Enable ROM space decodes */
+       if (pci_enable_rom(pdev))
+               return NULL;
 
        rom = ioremap(start, *size);
        if (!rom) {
                /* restore enable if ioremap fails */
-               if (!(res->flags & (IORESOURCE_ROM_ENABLE |
-                                   IORESOURCE_ROM_SHADOW |
-                                   IORESOURCE_ROM_COPY)))
+               if (!(res->flags & IORESOURCE_ROM_ENABLE))
                        pci_disable_rom(pdev);
                return NULL;
        }
@@ -181,36 +170,14 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
 {
        struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
 
-       if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
-               return;
-
        iounmap(rom);
 
-       /* Disable again before continuing, leave enabled if pci=rom */
-       if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
+       /* Disable again before continuing */
+       if (!(res->flags & IORESOURCE_ROM_ENABLE))
                pci_disable_rom(pdev);
 }
 EXPORT_SYMBOL(pci_unmap_rom);
 
-/**
- * pci_cleanup_rom - free the ROM copy created by pci_map_rom_copy
- * @pdev: pointer to pci device struct
- *
- * Free the copied ROM if we allocated one.
- */
-void pci_cleanup_rom(struct pci_dev *pdev)
-{
-       struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
-
-       if (res->flags & IORESOURCE_ROM_COPY) {
-               kfree((void *)(unsigned long)res->start);
-               res->flags |= IORESOURCE_UNSET;
-               res->flags &= ~IORESOURCE_ROM_COPY;
-               res->start = 0;
-               res->end = 0;
-       }
-}
-
 /**
  * pci_platform_rom - provides a pointer to any ROM image provided by the
  * platform
index 7796d0a5befafb958c8bae6193b4bca56da96203..55641a39a3e94f3eab29a5494d943afc9614d3e6 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/ioport.h>
 #include <linux/cache.h>
 #include <linux/slab.h>
-#include <asm-generic/pci-bridge.h>
 #include "pci.h"
 
 unsigned int pci_flags;
index 604011e047d60b9db26e40e54769aeb7a957f53e..66c4d8f4223377d6bb54849d7794fc8172b1e0a2 100644 (file)
@@ -276,6 +276,9 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        resource_size_t align, size;
        int ret;
 
+       if (res->flags & IORESOURCE_PCI_FIXED)
+               return 0;
+
        res->flags |= IORESOURCE_UNSET;
        align = pci_resource_alignment(dev, res);
        if (!align) {
@@ -321,6 +324,9 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz
        resource_size_t new_size;
        int ret;
 
+       if (res->flags & IORESOURCE_PCI_FIXED)
+               return 0;
+
        flags = res->flags;
        res->flags |= IORESOURCE_UNSET;
        if (!res->parent) {
index 99a4c10ed43f7a964c805f0bf55db367d07f9168..fb8200b8e8ec60911ddad766b740e879202d0b94 100644 (file)
@@ -79,7 +79,7 @@ config PINCTRL_AT91PIO4
          controller available on sama5d2 SoC.
 
 config PINCTRL_AMD
-       bool "AMD GPIO pin control"
+       tristate "AMD GPIO pin control"
        depends on GPIOLIB
        select GPIOLIB_IRQCHIP
        select PINCONF
@@ -168,37 +168,6 @@ config PINCTRL_ST
        select PINCONF
        select GPIOLIB_IRQCHIP
 
-config PINCTRL_TEGRA
-       bool
-       select PINMUX
-       select PINCONF
-
-config PINCTRL_TEGRA20
-       bool
-       select PINCTRL_TEGRA
-
-config PINCTRL_TEGRA30
-       bool
-       select PINCTRL_TEGRA
-
-config PINCTRL_TEGRA114
-       bool
-       select PINCTRL_TEGRA
-
-config PINCTRL_TEGRA124
-       bool
-       select PINCTRL_TEGRA
-
-config PINCTRL_TEGRA210
-       bool
-       select PINCTRL_TEGRA
-
-config PINCTRL_TEGRA_XUSB
-       def_bool y if ARCH_TEGRA
-       select GENERIC_PHY
-       select PINCONF
-       select PINMUX
-
 config PINCTRL_TZ1090
        bool "Toumaz Xenif TZ1090 pin control driver"
        depends on SOC_TZ1090
@@ -238,6 +207,23 @@ config PINCTRL_PALMAS
          open drain configuration for the Palmas series devices like
          TPS65913, TPS80036 etc.
 
+config PINCTRL_PIC32
+       bool "Microchip PIC32 pin controller driver"
+       depends on OF
+       depends on MACH_PIC32
+       select PINMUX
+       select GENERIC_PINCONF
+       select GPIOLIB_IRQCHIP
+       select OF_GPIO
+       help
+         This is the pin controller and gpio driver for Microchip PIC32
+         microcontrollers. This option is selected automatically when specific
+         machine and arch are selected to build.
+
+config PINCTRL_PIC32MZDA
+       def_bool y if PIC32MZDA
+       select PINCTRL_PIC32
+
 config PINCTRL_ZYNQ
        bool "Pinctrl driver for Xilinx Zynq"
        depends on ARCH_ZYNQ
@@ -257,7 +243,9 @@ source "drivers/pinctrl/qcom/Kconfig"
 source "drivers/pinctrl/samsung/Kconfig"
 source "drivers/pinctrl/sh-pfc/Kconfig"
 source "drivers/pinctrl/spear/Kconfig"
+source "drivers/pinctrl/stm32/Kconfig"
 source "drivers/pinctrl/sunxi/Kconfig"
+source "drivers/pinctrl/tegra/Kconfig"
 source "drivers/pinctrl/uniphier/Kconfig"
 source "drivers/pinctrl/vt8500/Kconfig"
 source "drivers/pinctrl/mediatek/Kconfig"
index bf1b5ca5180b5a899263ff43b819a04c2135f1c1..e4bc1151e04f3c2d7ed0eac8b659ae27244432ba 100644 (file)
@@ -18,17 +18,12 @@ obj-$(CONFIG_PINCTRL_DIGICOLOR)     += pinctrl-digicolor.o
 obj-$(CONFIG_PINCTRL_FALCON)   += pinctrl-falcon.o
 obj-$(CONFIG_PINCTRL_MESON)    += meson/
 obj-$(CONFIG_PINCTRL_PALMAS)   += pinctrl-palmas.o
+obj-$(CONFIG_PINCTRL_PIC32)    += pinctrl-pic32.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)        += pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
 obj-$(CONFIG_PINCTRL_SINGLE)   += pinctrl-single.o
 obj-$(CONFIG_PINCTRL_SIRF)     += sirf/
-obj-$(CONFIG_PINCTRL_TEGRA)    += pinctrl-tegra.o
-obj-$(CONFIG_PINCTRL_TEGRA20)  += pinctrl-tegra20.o
-obj-$(CONFIG_PINCTRL_TEGRA30)  += pinctrl-tegra30.o
-obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o
-obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o
-obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o
-obj-$(CONFIG_PINCTRL_TEGRA_XUSB)       += pinctrl-tegra-xusb.o
+obj-$(CONFIG_PINCTRL_TEGRA)    += tegra/
 obj-$(CONFIG_PINCTRL_TZ1090)   += pinctrl-tz1090.o
 obj-$(CONFIG_PINCTRL_TZ1090_PDC)       += pinctrl-tz1090-pdc.o
 obj-$(CONFIG_PINCTRL_U300)     += pinctrl-u300.o
@@ -46,12 +41,13 @@ obj-y                               += freescale/
 obj-$(CONFIG_X86)              += intel/
 obj-$(CONFIG_PINCTRL_MVEBU)    += mvebu/
 obj-y                          += nomadik/
-obj-$(CONFIG_ARCH_PXA)         += pxa/
+obj-$(CONFIG_PINCTRL_PXA)      += pxa/
 obj-$(CONFIG_ARCH_QCOM)                += qcom/
 obj-$(CONFIG_PINCTRL_SAMSUNG)  += samsung/
 obj-$(CONFIG_PINCTRL_SH_PFC)   += sh-pfc/
 obj-$(CONFIG_PINCTRL_SPEAR)    += spear/
-obj-$(CONFIG_ARCH_SUNXI)       += sunxi/
+obj-$(CONFIG_PINCTRL_STM32)    += stm32/
+obj-$(CONFIG_PINCTRL_SUNXI)    += sunxi/
 obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
 obj-$(CONFIG_ARCH_VT8500)      += vt8500/
-obj-$(CONFIG_ARCH_MEDIATEK)    += mediatek/
+obj-$(CONFIG_PINCTRL_MTK)      += mediatek/
index 0f5997ceb49494c6039a8ec525f58f24d8d619cc..08b1d93da9fedb36e1ae6ed3450221271f25998f 100644 (file)
@@ -779,7 +779,7 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
                }
                if (num_pulls) {
                        err = of_property_read_u32_index(np, "brcm,pull",
-                                       (num_funcs > 1) ? i : 0, &pull);
+                                       (num_pulls > 1) ? i : 0, &pull);
                        if (err)
                                goto out;
                        err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin,
index 2686a4450dfc3261029d560d2ce9838191fbf39c..f67a8b7a4e18252338c54c282152b78971d34225 100644 (file)
@@ -481,18 +481,12 @@ int pinctrl_get_group_pins(struct pinctrl_dev *pctldev, const char *pin_group,
 }
 EXPORT_SYMBOL_GPL(pinctrl_get_group_pins);
 
-/**
- * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin
- * @pctldev: the pin controller device to look in
- * @pin: a controller-local number to find the range for
- */
 struct pinctrl_gpio_range *
-pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
-                                unsigned int pin)
+pinctrl_find_gpio_range_from_pin_nolock(struct pinctrl_dev *pctldev,
+                                       unsigned int pin)
 {
        struct pinctrl_gpio_range *range;
 
-       mutex_lock(&pctldev->mutex);
        /* Loop over the ranges */
        list_for_each_entry(range, &pctldev->gpio_ranges, node) {
                /* Check if we're in the valid range */
@@ -500,15 +494,32 @@ pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
                        int a;
                        for (a = 0; a < range->npins; a++) {
                                if (range->pins[a] == pin)
-                                       goto out;
+                                       return range;
                        }
                } else if (pin >= range->pin_base &&
                           pin < range->pin_base + range->npins)
-                       goto out;
+                       return range;
        }
-       range = NULL;
-out:
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin_nolock);
+
+/**
+ * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin
+ * @pctldev: the pin controller device to look in
+ * @pin: a controller-local number to find the range for
+ */
+struct pinctrl_gpio_range *
+pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
+                                unsigned int pin)
+{
+       struct pinctrl_gpio_range *range;
+
+       mutex_lock(&pctldev->mutex);
+       range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin);
        mutex_unlock(&pctldev->mutex);
+
        return range;
 }
 EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin);
index b24ea846c8677ebea49ffd435c04c3de40f226b9..ca08723b9ee1e90fdfc792666cc7491ad5fc492e 100644 (file)
@@ -182,6 +182,10 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
        return radix_tree_lookup(&pctldev->pin_desc_tree, pin);
 }
 
+extern struct pinctrl_gpio_range *
+pinctrl_find_gpio_range_from_pin_nolock(struct pinctrl_dev *pctldev,
+                                       unsigned int pin);
+
 int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
                         bool dup);
 void pinctrl_unregister_map(struct pinctrl_map const *map);
index a5bb939873789710d0b00dfcda9805bd287ce92d..46210512d8ecff75cac22f306928798af8436454 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -24,6 +25,7 @@
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
 
 #include "../core.h"
 #include "pinctrl-imx.h"
@@ -341,6 +343,31 @@ mux_pin:
        return 0;
 }
 
+static void imx_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
+                       struct pinctrl_gpio_range *range, unsigned offset)
+{
+       struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+       const struct imx_pinctrl_soc_info *info = ipctl->info;
+       const struct imx_pin_reg *pin_reg;
+       u32 reg;
+
+       /*
+        * Only Vybrid has the input/output buffer enable flags (IBE/OBE)
+        * They are part of the shared mux/conf register.
+        */
+       if (!(info->flags & SHARE_MUX_CONF_REG))
+               return;
+
+       pin_reg = &info->pin_regs[offset];
+       if (pin_reg->mux_reg == -1)
+               return;
+
+       /* Clear IBE/OBE/PUE to disable the pin (Hi-Z) */
+       reg = readl(ipctl->base + pin_reg->mux_reg);
+       reg &= ~0x7;
+       writel(reg, ipctl->base + pin_reg->mux_reg);
+}
+
 static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
           struct pinctrl_gpio_range *range, unsigned offset, bool input)
 {
@@ -377,6 +404,7 @@ static const struct pinmux_ops imx_pmx_ops = {
        .get_function_groups = imx_pmx_get_groups,
        .set_mux = imx_pmx_set,
        .gpio_request_enable = imx_pmx_gpio_request_enable,
+       .gpio_disable_free = imx_pmx_gpio_disable_free,
        .gpio_set_direction = imx_pmx_gpio_set_direction,
 };
 
@@ -692,10 +720,12 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
 int imx_pinctrl_probe(struct platform_device *pdev,
                      struct imx_pinctrl_soc_info *info)
 {
+       struct regmap_config config = { .name = "gpr" };
        struct device_node *dev_np = pdev->dev.of_node;
        struct device_node *np;
        struct imx_pinctrl *ipctl;
        struct resource *res;
+       struct regmap *gpr;
        int ret, i;
 
        if (!info || !info->pins || !info->npins) {
@@ -704,6 +734,12 @@ int imx_pinctrl_probe(struct platform_device *pdev,
        }
        info->dev = &pdev->dev;
 
+       if (info->gpr_compatible) {
+               gpr = syscon_regmap_lookup_by_compatible(info->gpr_compatible);
+               if (!IS_ERR(gpr))
+                       regmap_attach_dev(&pdev->dev, gpr, &config);
+       }
+
        /* Create state holders etc for this driver */
        ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL);
        if (!ipctl)
index 2a592f657c184918ab1e7fbb6d9a4d862f0a2ab5..3b8bd81a39a4362172956933becd64ccad3f7afd 100644 (file)
@@ -82,6 +82,7 @@ struct imx_pinctrl_soc_info {
        struct imx_pmx_func *functions;
        unsigned int nfunctions;
        unsigned int flags;
+       const char *gpr_compatible;
 };
 
 #define SHARE_MUX_CONF_REG     0x1
index 51b31df96273602f5a7077bf66bc94a91c699957..8acc4d960cfa3f833565a51386d896879bd39132 100644 (file)
@@ -389,6 +389,7 @@ static const struct pinctrl_pin_desc imx50_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx50_pinctrl_info = {
        .pins = imx50_pinctrl_pads,
        .npins = ARRAY_SIZE(imx50_pinctrl_pads),
+       .gpr_compatible = "fsl,imx50-iomuxc-gpr",
 };
 
 static const struct of_device_id imx50_pinctrl_of_match[] = {
index 7344d340013c01d2ff67dae7ecfbda77b31f3a5f..d39dfd6a3a44b68b6b9843d615c571e38b217349 100644 (file)
@@ -452,6 +452,7 @@ static const struct pinctrl_pin_desc imx53_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx53_pinctrl_info = {
        .pins = imx53_pinctrl_pads,
        .npins = ARRAY_SIZE(imx53_pinctrl_pads),
+       .gpr_compatible = "fsl,imx53-iomuxc-gpr",
 };
 
 static const struct of_device_id imx53_pinctrl_of_match[] = {
index 6805c678c3b220d2e0d5622466441b69e2071bf6..5a2cdb0549cefba4baeb79be44f712b7c7d64c75 100644 (file)
@@ -458,6 +458,7 @@ static const struct pinctrl_pin_desc imx6dl_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx6dl_pinctrl_info = {
        .pins = imx6dl_pinctrl_pads,
        .npins = ARRAY_SIZE(imx6dl_pinctrl_pads),
+       .gpr_compatible = "fsl,imx6q-iomuxc-gpr",
 };
 
 static const struct of_device_id imx6dl_pinctrl_of_match[] = {
index 4d1fcb861ac1ae2f252cf303f4ac0bdc41bf1c90..7d50a36b1086919a7ded811a498f4af97850b21b 100644 (file)
@@ -464,6 +464,7 @@ static const struct pinctrl_pin_desc imx6q_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx6q_pinctrl_info = {
        .pins = imx6q_pinctrl_pads,
        .npins = ARRAY_SIZE(imx6q_pinctrl_pads),
+       .gpr_compatible = "fsl,imx6q-iomuxc-gpr",
 };
 
 static const struct of_device_id imx6q_pinctrl_of_match[] = {
index 83fa5f19ae89ffefacb596af83b7127ff40400bd..e27d17fdc69d8f670458602d7590b7df6ae7da63 100644 (file)
@@ -364,6 +364,7 @@ static const struct pinctrl_pin_desc imx6sl_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx6sl_pinctrl_info = {
        .pins = imx6sl_pinctrl_pads,
        .npins = ARRAY_SIZE(imx6sl_pinctrl_pads),
+       .gpr_compatible = "fsl,imx6sl-iomuxc-gpr",
 };
 
 static const struct of_device_id imx6sl_pinctrl_of_match[] = {
index 0d78fe690818d17a5556e4a38e86ab02f24c1427..117180c26c500d139157030735f9fc443950036b 100644 (file)
@@ -368,6 +368,7 @@ static const struct pinctrl_pin_desc imx6sx_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx6sx_pinctrl_info = {
        .pins = imx6sx_pinctrl_pads,
        .npins = ARRAY_SIZE(imx6sx_pinctrl_pads),
+       .gpr_compatible = "fsl,imx6sx-iomuxc-gpr",
 };
 
 static const struct of_device_id imx6sx_pinctrl_of_match[] = {
index 08e75764e7be011931385df1d0ad6b3a1b68c6a7..78627c70c6baa66e89ba98190f2b915a5bc8df22 100644 (file)
@@ -284,6 +284,7 @@ static const struct pinctrl_pin_desc imx6ul_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx6ul_pinctrl_info = {
        .pins = imx6ul_pinctrl_pads,
        .npins = ARRAY_SIZE(imx6ul_pinctrl_pads),
+       .gpr_compatible = "fsl,imx6ul-iomuxc-gpr",
 };
 
 static struct of_device_id imx6ul_pinctrl_of_match[] = {
index 16dc925117de1ad63cb4fd36251eac746e5bc8a2..1c89613eb4b75d6a943318a5ccccae8fe3df5b02 100644 (file)
@@ -359,6 +359,7 @@ static const struct pinctrl_pin_desc imx7d_lpsr_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info imx7d_pinctrl_info = {
        .pins = imx7d_pinctrl_pads,
        .npins = ARRAY_SIZE(imx7d_pinctrl_pads),
+       .gpr_compatible = "fsl,imx7d-iomuxc-gpr",
 };
 
 static struct imx_pinctrl_soc_info imx7d_lpsr_pinctrl_info = {
index c0f5586218c457c23a427387e635e8e3ca9e29d4..85536b467c25b50f43e19171996e009352ccb682 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/acpi.h>
-#include <linux/gpio.h>
 #include <linux/gpio/driver.h>
 #include <linux/platform_device.h>
-#include <linux/pm.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/pinctrl/pinconf.h>
index 02f6f92df86c51086fb910330f1a35858e97df4f..4f0bc8a103f4ae273d34cc6bc05d94656e34a420 100644 (file)
@@ -1,6 +1,6 @@
 if ARCH_MEDIATEK || COMPILE_TEST
 
-config PINCTRL_MTK_COMMON
+config PINCTRL_MTK
        bool
        depends on OF
        select PINMUX
@@ -9,17 +9,29 @@ config PINCTRL_MTK_COMMON
        select OF_GPIO
 
 # For ARMv7 SoCs
+config PINCTRL_MT2701
+       bool "Mediatek MT2701 pin control" if COMPILE_TEST && !MACH_MT2701
+       depends on OF
+       default MACH_MT2701
+       select PINCTRL_MTK
+
+config PINCTRL_MT7623
+       bool "Mediatek MT7623 pin control" if COMPILE_TEST && !MACH_MT7623
+       depends on OF
+       default MACH_MT7623
+       select PINCTRL_MTK_COMMON
+
 config PINCTRL_MT8135
        bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135
        depends on OF
        default MACH_MT8135
-       select PINCTRL_MTK_COMMON
+       select PINCTRL_MTK
 
 config PINCTRL_MT8127
        bool "Mediatek MT8127 pin control" if COMPILE_TEST && !MACH_MT8127
        depends on OF
        default MACH_MT8127
-       select PINCTRL_MTK_COMMON
+       select PINCTRL_MTK
 
 # For ARMv8 SoCs
 config PINCTRL_MT8173
@@ -27,13 +39,13 @@ config PINCTRL_MT8173
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
-       select PINCTRL_MTK_COMMON
+       select PINCTRL_MTK
 
 # For PMIC
 config PINCTRL_MT6397
        bool "Mediatek MT6397 pin control" if COMPILE_TEST && !MFD_MT6397
        depends on OF
        default MFD_MT6397
-       select PINCTRL_MTK_COMMON
+       select PINCTRL_MTK
 
 endif
index eb923d64d387871724dd49323ce8146f0093d339..3e3390a1471636c503d72ef80739929d66e264b9 100644 (file)
@@ -1,8 +1,10 @@
 # Core
-obj-$(CONFIG_PINCTRL_MTK_COMMON)       += pinctrl-mtk-common.o
+obj-y                          += pinctrl-mtk-common.o
 
 # SoC Drivers
-obj-$(CONFIG_PINCTRL_MT8135)           += pinctrl-mt8135.o
-obj-$(CONFIG_PINCTRL_MT8127)           += pinctrl-mt8127.o
-obj-$(CONFIG_PINCTRL_MT8173)           += pinctrl-mt8173.o
-obj-$(CONFIG_PINCTRL_MT6397)           += pinctrl-mt6397.o
+obj-$(CONFIG_PINCTRL_MT2701)   += pinctrl-mt2701.o
+obj-$(CONFIG_PINCTRL_MT7623)   += pinctrl-mt7623.o
+obj-$(CONFIG_PINCTRL_MT8135)   += pinctrl-mt8135.o
+obj-$(CONFIG_PINCTRL_MT8127)   += pinctrl-mt8127.o
+obj-$(CONFIG_PINCTRL_MT8173)   += pinctrl-mt8173.o
+obj-$(CONFIG_PINCTRL_MT6397)   += pinctrl-mt6397.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2701.c b/drivers/pinctrl/mediatek/pinctrl-mt2701.c
new file mode 100644 (file)
index 0000000..8d802fa
--- /dev/null
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Biao Huang <biao.huang@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
+
+#include "pinctrl-mtk-common.h"
+#include "pinctrl-mtk-mt2701.h"
+
+/**
+ * struct mtk_spec_pinmux_set
+ * - For special pins' mode setting
+ * @pin: The pin number.
+ * @offset: The offset of extra setting register.
+ * @bit: The bit of extra setting register.
+ */
+struct mtk_spec_pinmux_set {
+       unsigned short pin;
+       unsigned short offset;
+       unsigned char bit;
+};
+
+#define MTK_PINMUX_SPEC(_pin, _offset, _bit)   \
+       {                                       \
+               .pin = _pin,                    \
+               .offset = _offset,              \
+               .bit = _bit,                    \
+       }
+
+static const struct mtk_drv_group_desc mt2701_drv_grp[] =  {
+       /* 0E4E8SR 4/8/12/16 */
+       MTK_DRV_GRP(4, 16, 1, 2, 4),
+       /* 0E2E4SR  2/4/6/8 */
+       MTK_DRV_GRP(2, 8, 1, 2, 2),
+       /* E8E4E2  2/4/6/8/10/12/14/16 */
+       MTK_DRV_GRP(2, 16, 0, 2, 2)
+};
+
+static const struct mtk_pin_drv_grp mt2701_pin_drv[] = {
+       MTK_PIN_DRV_GRP(0, 0xf50, 0, 1),
+       MTK_PIN_DRV_GRP(1, 0xf50, 0, 1),
+       MTK_PIN_DRV_GRP(2, 0xf50, 0, 1),
+       MTK_PIN_DRV_GRP(3, 0xf50, 0, 1),
+       MTK_PIN_DRV_GRP(4, 0xf50, 0, 1),
+       MTK_PIN_DRV_GRP(5, 0xf50, 0, 1),
+       MTK_PIN_DRV_GRP(6, 0xf50, 0, 1),
+       MTK_PIN_DRV_GRP(7, 0xf50, 4, 1),
+       MTK_PIN_DRV_GRP(8, 0xf50, 4, 1),
+       MTK_PIN_DRV_GRP(9, 0xf50, 4, 1),
+       MTK_PIN_DRV_GRP(10, 0xf50, 8, 1),
+       MTK_PIN_DRV_GRP(11, 0xf50, 8, 1),
+       MTK_PIN_DRV_GRP(12, 0xf50, 8, 1),
+       MTK_PIN_DRV_GRP(13, 0xf50, 8, 1),
+       MTK_PIN_DRV_GRP(14, 0xf50, 12, 0),
+       MTK_PIN_DRV_GRP(15, 0xf50, 12, 0),
+       MTK_PIN_DRV_GRP(16, 0xf60, 0, 0),
+       MTK_PIN_DRV_GRP(17, 0xf60, 0, 0),
+       MTK_PIN_DRV_GRP(18, 0xf60, 4, 0),
+       MTK_PIN_DRV_GRP(19, 0xf60, 4, 0),
+       MTK_PIN_DRV_GRP(20, 0xf60, 4, 0),
+       MTK_PIN_DRV_GRP(21, 0xf60, 4, 0),
+       MTK_PIN_DRV_GRP(22, 0xf60, 8, 0),
+       MTK_PIN_DRV_GRP(23, 0xf60, 8, 0),
+       MTK_PIN_DRV_GRP(24, 0xf60, 8, 0),
+       MTK_PIN_DRV_GRP(25, 0xf60, 8, 0),
+       MTK_PIN_DRV_GRP(26, 0xf60, 8, 0),
+       MTK_PIN_DRV_GRP(27, 0xf60, 12, 0),
+       MTK_PIN_DRV_GRP(28, 0xf60, 12, 0),
+       MTK_PIN_DRV_GRP(29, 0xf60, 12, 0),
+       MTK_PIN_DRV_GRP(30, 0xf60, 0, 0),
+       MTK_PIN_DRV_GRP(31, 0xf60, 0, 0),
+       MTK_PIN_DRV_GRP(32, 0xf60, 0, 0),
+       MTK_PIN_DRV_GRP(33, 0xf70, 0, 0),
+       MTK_PIN_DRV_GRP(34, 0xf70, 0, 0),
+       MTK_PIN_DRV_GRP(35, 0xf70, 0, 0),
+       MTK_PIN_DRV_GRP(36, 0xf70, 0, 0),
+       MTK_PIN_DRV_GRP(37, 0xf70, 0, 0),
+       MTK_PIN_DRV_GRP(38, 0xf70, 4, 0),
+       MTK_PIN_DRV_GRP(39, 0xf70, 8, 1),
+       MTK_PIN_DRV_GRP(40, 0xf70, 8, 1),
+       MTK_PIN_DRV_GRP(41, 0xf70, 8, 1),
+       MTK_PIN_DRV_GRP(42, 0xf70, 8, 1),
+       MTK_PIN_DRV_GRP(43, 0xf70, 12, 0),
+       MTK_PIN_DRV_GRP(44, 0xf70, 12, 0),
+       MTK_PIN_DRV_GRP(45, 0xf70, 12, 0),
+       MTK_PIN_DRV_GRP(47, 0xf80, 0, 0),
+       MTK_PIN_DRV_GRP(48, 0xf80, 0, 0),
+       MTK_PIN_DRV_GRP(49, 0xf80, 4, 0),
+       MTK_PIN_DRV_GRP(50, 0xf70, 4, 0),
+       MTK_PIN_DRV_GRP(51, 0xf70, 4, 0),
+       MTK_PIN_DRV_GRP(52, 0xf70, 4, 0),
+       MTK_PIN_DRV_GRP(53, 0xf80, 12, 0),
+       MTK_PIN_DRV_GRP(54, 0xf80, 12, 0),
+       MTK_PIN_DRV_GRP(55, 0xf80, 12, 0),
+       MTK_PIN_DRV_GRP(56, 0xf80, 12, 0),
+       MTK_PIN_DRV_GRP(60, 0xf90, 8, 1),
+       MTK_PIN_DRV_GRP(61, 0xf90, 8, 1),
+       MTK_PIN_DRV_GRP(62, 0xf90, 8, 1),
+       MTK_PIN_DRV_GRP(63, 0xf90, 12, 1),
+       MTK_PIN_DRV_GRP(64, 0xf90, 12, 1),
+       MTK_PIN_DRV_GRP(65, 0xf90, 12, 1),
+       MTK_PIN_DRV_GRP(66, 0xfa0, 0, 1),
+       MTK_PIN_DRV_GRP(67, 0xfa0, 0, 1),
+       MTK_PIN_DRV_GRP(68, 0xfa0, 0, 1),
+       MTK_PIN_DRV_GRP(69, 0xfa0, 0, 1),
+       MTK_PIN_DRV_GRP(70, 0xfa0, 0, 1),
+       MTK_PIN_DRV_GRP(71, 0xfa0, 0, 1),
+       MTK_PIN_DRV_GRP(72, 0xf80, 4, 0),
+       MTK_PIN_DRV_GRP(73, 0xf80, 4, 0),
+       MTK_PIN_DRV_GRP(74, 0xf80, 4, 0),
+       MTK_PIN_DRV_GRP(85, 0xda0, 0, 2),
+       MTK_PIN_DRV_GRP(86, 0xd90, 0, 2),
+       MTK_PIN_DRV_GRP(87, 0xdb0, 0, 2),
+       MTK_PIN_DRV_GRP(88, 0xdb0, 0, 2),
+       MTK_PIN_DRV_GRP(89, 0xdb0, 0, 2),
+       MTK_PIN_DRV_GRP(90, 0xdb0, 0, 2),
+       MTK_PIN_DRV_GRP(105, 0xd40, 0, 2),
+       MTK_PIN_DRV_GRP(106, 0xd30, 0, 2),
+       MTK_PIN_DRV_GRP(107, 0xd50, 0, 2),
+       MTK_PIN_DRV_GRP(108, 0xd50, 0, 2),
+       MTK_PIN_DRV_GRP(109, 0xd50, 0, 2),
+       MTK_PIN_DRV_GRP(110, 0xd50, 0, 2),
+       MTK_PIN_DRV_GRP(111, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(112, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(113, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(114, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(115, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(116, 0xcd0, 0, 2),
+       MTK_PIN_DRV_GRP(117, 0xcc0, 0, 2),
+       MTK_PIN_DRV_GRP(118, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(119, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(120, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(121, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(126, 0xf80, 4, 0),
+       MTK_PIN_DRV_GRP(188, 0xf70, 4, 0),
+       MTK_PIN_DRV_GRP(189, 0xfe0, 8, 0),
+       MTK_PIN_DRV_GRP(190, 0xfe0, 8, 0),
+       MTK_PIN_DRV_GRP(191, 0xfe0, 8, 0),
+       MTK_PIN_DRV_GRP(192, 0xfe0, 8, 0),
+       MTK_PIN_DRV_GRP(193, 0xfe0, 8, 0),
+       MTK_PIN_DRV_GRP(194, 0xfe0, 12, 0),
+       MTK_PIN_DRV_GRP(195, 0xfe0, 12, 0),
+       MTK_PIN_DRV_GRP(196, 0xfe0, 12, 0),
+       MTK_PIN_DRV_GRP(197, 0xfe0, 12, 0),
+       MTK_PIN_DRV_GRP(198, 0xfe0, 12, 0),
+       MTK_PIN_DRV_GRP(199, 0xf50, 4, 1),
+       MTK_PIN_DRV_GRP(200, 0xfd0, 0, 0),
+       MTK_PIN_DRV_GRP(201, 0xfd0, 0, 0),
+       MTK_PIN_DRV_GRP(202, 0xfd0, 0, 0),
+       MTK_PIN_DRV_GRP(203, 0xfd0, 4, 0),
+       MTK_PIN_DRV_GRP(204, 0xfd0, 4, 0),
+       MTK_PIN_DRV_GRP(205, 0xfd0, 4, 0),
+       MTK_PIN_DRV_GRP(206, 0xfd0, 4, 0),
+       MTK_PIN_DRV_GRP(207, 0xfd0, 4, 0),
+       MTK_PIN_DRV_GRP(208, 0xfd0, 8, 0),
+       MTK_PIN_DRV_GRP(209, 0xfd0, 8, 0),
+       MTK_PIN_DRV_GRP(210, 0xfd0, 12, 1),
+       MTK_PIN_DRV_GRP(211, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(212, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(213, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(214, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(215, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(216, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(217, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(218, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(219, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(220, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(221, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(222, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(223, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(224, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(225, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(226, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(227, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(228, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(229, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(230, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(231, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(232, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(233, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(234, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(235, 0xff0, 0, 1),
+       MTK_PIN_DRV_GRP(236, 0xff0, 4, 0),
+       MTK_PIN_DRV_GRP(237, 0xff0, 4, 0),
+       MTK_PIN_DRV_GRP(238, 0xff0, 4, 0),
+       MTK_PIN_DRV_GRP(239, 0xff0, 4, 0),
+       MTK_PIN_DRV_GRP(240, 0xff0, 4, 0),
+       MTK_PIN_DRV_GRP(241, 0xff0, 4, 0),
+       MTK_PIN_DRV_GRP(242, 0xff0, 8, 0),
+       MTK_PIN_DRV_GRP(243, 0xff0, 8, 0),
+       MTK_PIN_DRV_GRP(248, 0xf00, 0, 0),
+       MTK_PIN_DRV_GRP(249, 0xfc0, 0, 2),
+       MTK_PIN_DRV_GRP(250, 0xfc0, 0, 2),
+       MTK_PIN_DRV_GRP(251, 0xfc0, 0, 2),
+       MTK_PIN_DRV_GRP(252, 0xfc0, 0, 2),
+       MTK_PIN_DRV_GRP(253, 0xfc0, 0, 2),
+       MTK_PIN_DRV_GRP(254, 0xfc0, 0, 2),
+       MTK_PIN_DRV_GRP(255, 0xfc0, 0, 2),
+       MTK_PIN_DRV_GRP(256, 0xfc0, 0, 2),
+       MTK_PIN_DRV_GRP(257, 0xce0, 0, 2),
+       MTK_PIN_DRV_GRP(258, 0xcb0, 0, 2),
+       MTK_PIN_DRV_GRP(259, 0xc90, 0, 2),
+       MTK_PIN_DRV_GRP(260, 0x3a0, 0, 2),
+       MTK_PIN_DRV_GRP(261, 0xd50, 0, 2),
+       MTK_PIN_DRV_GRP(262, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(263, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(264, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(265, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(266, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(267, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(268, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(269, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(270, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(271, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(272, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(273, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(274, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(275, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(276, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(277, 0xf00, 8, 0),
+       MTK_PIN_DRV_GRP(278, 0xf70, 8, 1),
+};
+
+static const struct mtk_pin_spec_pupd_set_samereg mt2701_spec_pupd[] = {
+       MTK_PIN_PUPD_SPEC_SR(111, 0xd00, 12, 13, 14),   /* ms0 data7 */
+       MTK_PIN_PUPD_SPEC_SR(112, 0xd00, 8, 9, 10),     /* ms0 data6 */
+       MTK_PIN_PUPD_SPEC_SR(113, 0xd00, 4, 5, 6),      /* ms0 data5 */
+       MTK_PIN_PUPD_SPEC_SR(114, 0xd00, 0, 1, 2),      /* ms0 data4 */
+       MTK_PIN_PUPD_SPEC_SR(115, 0xd10, 0, 1, 2),      /* ms0 rstb */
+       MTK_PIN_PUPD_SPEC_SR(116, 0xcd0, 8, 9, 10),     /* ms0 cmd */
+       MTK_PIN_PUPD_SPEC_SR(117, 0xcc0, 8, 9, 10),     /* ms0 clk */
+       MTK_PIN_PUPD_SPEC_SR(118, 0xcf0, 12, 13, 14),   /* ms0 data3 */
+       MTK_PIN_PUPD_SPEC_SR(119, 0xcf0, 8, 9, 10),     /* ms0 data2 */
+       MTK_PIN_PUPD_SPEC_SR(120, 0xcf0, 4, 5, 6),      /* ms0 data1 */
+       MTK_PIN_PUPD_SPEC_SR(121, 0xcf0, 0, 1, 2),      /* ms0 data0 */
+
+       MTK_PIN_PUPD_SPEC_SR(105, 0xd40, 8, 9, 10),     /* ms1 cmd */
+       MTK_PIN_PUPD_SPEC_SR(106, 0xd30, 8, 9, 10),     /* ms1 clk */
+       MTK_PIN_PUPD_SPEC_SR(107, 0xd60, 0, 1, 2),      /* ms1 dat0 */
+       MTK_PIN_PUPD_SPEC_SR(108, 0xd60, 10, 9, 8),     /* ms1 dat1 */
+       MTK_PIN_PUPD_SPEC_SR(109, 0xd60, 4, 5, 6),      /* ms1 dat2 */
+       MTK_PIN_PUPD_SPEC_SR(110, 0xc60, 12, 13, 14),   /* ms1 dat3 */
+
+       MTK_PIN_PUPD_SPEC_SR(85, 0xda0, 8, 9, 10),      /* ms2 cmd */
+       MTK_PIN_PUPD_SPEC_SR(86, 0xd90, 8, 9, 10),      /* ms2 clk */
+       MTK_PIN_PUPD_SPEC_SR(87, 0xdc0, 0, 1, 2),       /* ms2 dat0 */
+       MTK_PIN_PUPD_SPEC_SR(88, 0xdc0, 10, 9, 8),      /* ms2 dat1 */
+       MTK_PIN_PUPD_SPEC_SR(89, 0xdc0, 4, 5, 6),       /* ms2 dat2 */
+       MTK_PIN_PUPD_SPEC_SR(90, 0xdc0, 12, 13, 14),    /* ms2 dat3 */
+
+       MTK_PIN_PUPD_SPEC_SR(249, 0x140, 0, 1, 2),      /* ms0e rstb */
+       MTK_PIN_PUPD_SPEC_SR(250, 0x130, 12, 13, 14),   /* ms0e dat7 */
+       MTK_PIN_PUPD_SPEC_SR(251, 0x130, 8, 9, 10),     /* ms0e dat6 */
+       MTK_PIN_PUPD_SPEC_SR(252, 0x130, 4, 5, 6),      /* ms0e dat5 */
+       MTK_PIN_PUPD_SPEC_SR(253, 0x130, 0, 1, 2),      /* ms0e dat4 */
+       MTK_PIN_PUPD_SPEC_SR(254, 0xf40, 12, 13, 14),   /* ms0e dat3 */
+       MTK_PIN_PUPD_SPEC_SR(255, 0xf40, 8, 9, 10),     /* ms0e dat2 */
+       MTK_PIN_PUPD_SPEC_SR(256, 0xf40, 4, 5, 6),      /* ms0e dat1 */
+       MTK_PIN_PUPD_SPEC_SR(257, 0xf40, 0, 1, 2),      /* ms0e dat0 */
+       MTK_PIN_PUPD_SPEC_SR(258, 0xcb0, 8, 9, 10),     /* ms0e cmd */
+       MTK_PIN_PUPD_SPEC_SR(259, 0xc90, 8, 9, 10),     /* ms0e clk */
+       MTK_PIN_PUPD_SPEC_SR(261, 0x140, 8, 9, 10),     /* ms1 ins */
+};
+
+static int mt2701_spec_pull_set(struct regmap *regmap, unsigned int pin,
+               unsigned char align, bool isup, unsigned int r1r0)
+{
+       return mtk_pctrl_spec_pull_set_samereg(regmap, mt2701_spec_pupd,
+               ARRAY_SIZE(mt2701_spec_pupd), pin, align, isup, r1r0);
+}
+
+static const struct mtk_pin_ies_smt_set mt2701_ies_set[] = {
+       MTK_PIN_IES_SMT_SPEC(0, 6, 0xb20, 0),
+       MTK_PIN_IES_SMT_SPEC(7, 9, 0xb20, 1),
+       MTK_PIN_IES_SMT_SPEC(10, 13, 0xb30, 3),
+       MTK_PIN_IES_SMT_SPEC(14, 15, 0xb30, 13),
+       MTK_PIN_IES_SMT_SPEC(16, 17, 0xb40, 7),
+       MTK_PIN_IES_SMT_SPEC(18, 21, 0xb40, 13),
+       MTK_PIN_IES_SMT_SPEC(22, 26, 0xb40, 13),
+       MTK_PIN_IES_SMT_SPEC(27, 29, 0xb40, 13),
+       MTK_PIN_IES_SMT_SPEC(30, 32, 0xb40, 7),
+       MTK_PIN_IES_SMT_SPEC(33, 37, 0xb40, 13),
+       MTK_PIN_IES_SMT_SPEC(38, 38, 0xb20, 13),
+       MTK_PIN_IES_SMT_SPEC(39, 42, 0xb40, 13),
+       MTK_PIN_IES_SMT_SPEC(43, 45, 0xb20, 10),
+       MTK_PIN_IES_SMT_SPEC(47, 48, 0xb20, 11),
+       MTK_PIN_IES_SMT_SPEC(49, 49, 0xb20, 12),
+       MTK_PIN_IES_SMT_SPEC(50, 52, 0xb20, 13),
+       MTK_PIN_IES_SMT_SPEC(53, 56, 0xb20, 14),
+       MTK_PIN_IES_SMT_SPEC(57, 58, 0xb20, 15),
+       MTK_PIN_IES_SMT_SPEC(59, 59, 0xb30, 10),
+       MTK_PIN_IES_SMT_SPEC(60, 62, 0xb30, 0),
+       MTK_PIN_IES_SMT_SPEC(63, 65, 0xb30, 1),
+       MTK_PIN_IES_SMT_SPEC(66, 71, 0xb30, 2),
+       MTK_PIN_IES_SMT_SPEC(72, 74, 0xb20, 12),
+       MTK_PIN_IES_SMT_SPEC(75, 76, 0xb30, 3),
+       MTK_PIN_IES_SMT_SPEC(77, 78, 0xb30, 4),
+       MTK_PIN_IES_SMT_SPEC(79, 82, 0xb30, 5),
+       MTK_PIN_IES_SMT_SPEC(83, 84, 0xb30, 2),
+       MTK_PIN_IES_SMT_SPEC(85, 85, 0xda0, 4),
+       MTK_PIN_IES_SMT_SPEC(86, 86, 0xd90, 4),
+       MTK_PIN_IES_SMT_SPEC(87, 90, 0xdb0, 4),
+       MTK_PIN_IES_SMT_SPEC(101, 104, 0xb30, 6),
+       MTK_PIN_IES_SMT_SPEC(105, 105, 0xd40, 4),
+       MTK_PIN_IES_SMT_SPEC(106, 106, 0xd30, 4),
+       MTK_PIN_IES_SMT_SPEC(107, 110, 0xd50, 4),
+       MTK_PIN_IES_SMT_SPEC(111, 115, 0xce0, 4),
+       MTK_PIN_IES_SMT_SPEC(116, 116, 0xcd0, 4),
+       MTK_PIN_IES_SMT_SPEC(117, 117, 0xcc0, 4),
+       MTK_PIN_IES_SMT_SPEC(118, 121, 0xce0, 4),
+       MTK_PIN_IES_SMT_SPEC(122, 125, 0xb30, 7),
+       MTK_PIN_IES_SMT_SPEC(126, 126, 0xb20, 12),
+       MTK_PIN_IES_SMT_SPEC(127, 142, 0xb30, 9),
+       MTK_PIN_IES_SMT_SPEC(143, 160, 0xb30, 10),
+       MTK_PIN_IES_SMT_SPEC(161, 168, 0xb30, 12),
+       MTK_PIN_IES_SMT_SPEC(169, 183, 0xb30, 10),
+       MTK_PIN_IES_SMT_SPEC(184, 186, 0xb30, 9),
+       MTK_PIN_IES_SMT_SPEC(187, 187, 0xb30, 14),
+       MTK_PIN_IES_SMT_SPEC(188, 188, 0xb20, 13),
+       MTK_PIN_IES_SMT_SPEC(189, 193, 0xb30, 15),
+       MTK_PIN_IES_SMT_SPEC(194, 198, 0xb40, 0),
+       MTK_PIN_IES_SMT_SPEC(199, 199, 0xb20, 1),
+       MTK_PIN_IES_SMT_SPEC(200, 202, 0xb40, 1),
+       MTK_PIN_IES_SMT_SPEC(203, 207, 0xb40, 2),
+       MTK_PIN_IES_SMT_SPEC(208, 209, 0xb40, 3),
+       MTK_PIN_IES_SMT_SPEC(210, 210, 0xb40, 4),
+       MTK_PIN_IES_SMT_SPEC(211, 235, 0xb40, 5),
+       MTK_PIN_IES_SMT_SPEC(236, 241, 0xb40, 6),
+       MTK_PIN_IES_SMT_SPEC(242, 243, 0xb40, 7),
+       MTK_PIN_IES_SMT_SPEC(244, 247, 0xb40, 8),
+       MTK_PIN_IES_SMT_SPEC(248, 248, 0xb40, 9),
+       MTK_PIN_IES_SMT_SPEC(249, 257, 0xfc0, 4),
+       MTK_PIN_IES_SMT_SPEC(258, 258, 0xcb0, 4),
+       MTK_PIN_IES_SMT_SPEC(259, 259, 0xc90, 4),
+       MTK_PIN_IES_SMT_SPEC(260, 260, 0x3a0, 4),
+       MTK_PIN_IES_SMT_SPEC(261, 261, 0xd50, 4),
+       MTK_PIN_IES_SMT_SPEC(262, 277, 0xb40, 12),
+       MTK_PIN_IES_SMT_SPEC(278, 278, 0xb40, 13),
+};
+
+static const struct mtk_pin_ies_smt_set mt2701_smt_set[] = {
+       MTK_PIN_IES_SMT_SPEC(0, 6, 0xb50, 0),
+       MTK_PIN_IES_SMT_SPEC(7, 9, 0xb50, 1),
+       MTK_PIN_IES_SMT_SPEC(10, 13, 0xb60, 3),
+       MTK_PIN_IES_SMT_SPEC(14, 15, 0xb60, 13),
+       MTK_PIN_IES_SMT_SPEC(16, 17, 0xb70, 7),
+       MTK_PIN_IES_SMT_SPEC(18, 21, 0xb70, 13),
+       MTK_PIN_IES_SMT_SPEC(22, 26, 0xb70, 13),
+       MTK_PIN_IES_SMT_SPEC(27, 29, 0xb70, 13),
+       MTK_PIN_IES_SMT_SPEC(30, 32, 0xb70, 7),
+       MTK_PIN_IES_SMT_SPEC(33, 37, 0xb70, 13),
+       MTK_PIN_IES_SMT_SPEC(38, 38, 0xb50, 13),
+       MTK_PIN_IES_SMT_SPEC(39, 42, 0xb70, 13),
+       MTK_PIN_IES_SMT_SPEC(43, 45, 0xb50, 10),
+       MTK_PIN_IES_SMT_SPEC(47, 48, 0xb50, 11),
+       MTK_PIN_IES_SMT_SPEC(49, 49, 0xb50, 12),
+       MTK_PIN_IES_SMT_SPEC(50, 52, 0xb50, 13),
+       MTK_PIN_IES_SMT_SPEC(53, 56, 0xb50, 14),
+       MTK_PIN_IES_SMT_SPEC(57, 58, 0xb50, 15),
+       MTK_PIN_IES_SMT_SPEC(59, 59, 0xb60, 10),
+       MTK_PIN_IES_SMT_SPEC(60, 62, 0xb60, 0),
+       MTK_PIN_IES_SMT_SPEC(63, 65, 0xb60, 1),
+       MTK_PIN_IES_SMT_SPEC(66, 71, 0xb60, 2),
+       MTK_PIN_IES_SMT_SPEC(72, 74, 0xb50, 12),
+       MTK_PIN_IES_SMT_SPEC(75, 76, 0xb60, 3),
+       MTK_PIN_IES_SMT_SPEC(77, 78, 0xb60, 4),
+       MTK_PIN_IES_SMT_SPEC(79, 82, 0xb60, 5),
+       MTK_PIN_IES_SMT_SPEC(83, 84, 0xb60, 2),
+       MTK_PIN_IES_SMT_SPEC(85, 85, 0xda0, 11),
+       MTK_PIN_IES_SMT_SPEC(86, 86, 0xd90, 11),
+       MTK_PIN_IES_SMT_SPEC(87, 87, 0xdc0, 3),
+       MTK_PIN_IES_SMT_SPEC(88, 88, 0xdc0, 7),
+       MTK_PIN_IES_SMT_SPEC(89, 89, 0xdc0, 11),
+       MTK_PIN_IES_SMT_SPEC(90, 90, 0xdc0, 15),
+       MTK_PIN_IES_SMT_SPEC(101, 104, 0xb60, 6),
+       MTK_PIN_IES_SMT_SPEC(105, 105, 0xd40, 11),
+       MTK_PIN_IES_SMT_SPEC(106, 106, 0xd30, 11),
+       MTK_PIN_IES_SMT_SPEC(107, 107, 0xd60, 3),
+       MTK_PIN_IES_SMT_SPEC(108, 108, 0xd60, 7),
+       MTK_PIN_IES_SMT_SPEC(109, 109, 0xd60, 11),
+       MTK_PIN_IES_SMT_SPEC(110, 110, 0xd60, 15),
+       MTK_PIN_IES_SMT_SPEC(111, 111, 0xd00, 15),
+       MTK_PIN_IES_SMT_SPEC(112, 112, 0xd00, 11),
+       MTK_PIN_IES_SMT_SPEC(113, 113, 0xd00, 7),
+       MTK_PIN_IES_SMT_SPEC(114, 114, 0xd00, 3),
+       MTK_PIN_IES_SMT_SPEC(115, 115, 0xd10, 3),
+       MTK_PIN_IES_SMT_SPEC(116, 116, 0xcd0, 11),
+       MTK_PIN_IES_SMT_SPEC(117, 117, 0xcc0, 11),
+       MTK_PIN_IES_SMT_SPEC(118, 118, 0xcf0, 15),
+       MTK_PIN_IES_SMT_SPEC(119, 119, 0xcf0, 11),
+       MTK_PIN_IES_SMT_SPEC(120, 120, 0xcf0, 7),
+       MTK_PIN_IES_SMT_SPEC(121, 121, 0xcf0, 3),
+       MTK_PIN_IES_SMT_SPEC(122, 125, 0xb60, 7),
+       MTK_PIN_IES_SMT_SPEC(126, 126, 0xb50, 12),
+       MTK_PIN_IES_SMT_SPEC(127, 142, 0xb60, 9),
+       MTK_PIN_IES_SMT_SPEC(143, 160, 0xb60, 10),
+       MTK_PIN_IES_SMT_SPEC(161, 168, 0xb60, 12),
+       MTK_PIN_IES_SMT_SPEC(169, 183, 0xb60, 10),
+       MTK_PIN_IES_SMT_SPEC(184, 186, 0xb60, 9),
+       MTK_PIN_IES_SMT_SPEC(187, 187, 0xb60, 14),
+       MTK_PIN_IES_SMT_SPEC(188, 188, 0xb50, 13),
+       MTK_PIN_IES_SMT_SPEC(189, 193, 0xb60, 15),
+       MTK_PIN_IES_SMT_SPEC(194, 198, 0xb70, 0),
+       MTK_PIN_IES_SMT_SPEC(199, 199, 0xb50, 1),
+       MTK_PIN_IES_SMT_SPEC(200, 202, 0xb70, 1),
+       MTK_PIN_IES_SMT_SPEC(203, 207, 0xb70, 2),
+       MTK_PIN_IES_SMT_SPEC(208, 209, 0xb70, 3),
+       MTK_PIN_IES_SMT_SPEC(210, 210, 0xb70, 4),
+       MTK_PIN_IES_SMT_SPEC(211, 235, 0xb70, 5),
+       MTK_PIN_IES_SMT_SPEC(236, 241, 0xb70, 6),
+       MTK_PIN_IES_SMT_SPEC(242, 243, 0xb70, 7),
+       MTK_PIN_IES_SMT_SPEC(244, 247, 0xb70, 8),
+       MTK_PIN_IES_SMT_SPEC(248, 248, 0xb70, 9),
+       MTK_PIN_IES_SMT_SPEC(249, 249, 0x140, 3),
+       MTK_PIN_IES_SMT_SPEC(250, 250, 0x130, 15),
+       MTK_PIN_IES_SMT_SPEC(251, 251, 0x130, 11),
+       MTK_PIN_IES_SMT_SPEC(252, 252, 0x130, 7),
+       MTK_PIN_IES_SMT_SPEC(253, 253, 0x130, 3),
+       MTK_PIN_IES_SMT_SPEC(254, 254, 0xf40, 15),
+       MTK_PIN_IES_SMT_SPEC(255, 255, 0xf40, 11),
+       MTK_PIN_IES_SMT_SPEC(256, 256, 0xf40, 7),
+       MTK_PIN_IES_SMT_SPEC(257, 257, 0xf40, 3),
+       MTK_PIN_IES_SMT_SPEC(258, 258, 0xcb0, 11),
+       MTK_PIN_IES_SMT_SPEC(259, 259, 0xc90, 11),
+       MTK_PIN_IES_SMT_SPEC(260, 260, 0x3a0, 11),
+       MTK_PIN_IES_SMT_SPEC(261, 261, 0x0b0, 3),
+       MTK_PIN_IES_SMT_SPEC(262, 277, 0xb70, 12),
+       MTK_PIN_IES_SMT_SPEC(278, 278, 0xb70, 13),
+};
+
+static int mt2701_ies_smt_set(struct regmap *regmap, unsigned int pin,
+               unsigned char align, int value, enum pin_config_param arg)
+{
+       if (arg == PIN_CONFIG_INPUT_ENABLE)
+               return mtk_pconf_spec_set_ies_smt_range(regmap, mt2701_ies_set,
+                       ARRAY_SIZE(mt2701_ies_set), pin, align, value);
+       else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
+               return mtk_pconf_spec_set_ies_smt_range(regmap, mt2701_smt_set,
+                       ARRAY_SIZE(mt2701_smt_set), pin, align, value);
+       return -EINVAL;
+}
+
+static const struct mtk_spec_pinmux_set mt2701_spec_pinmux[] = {
+       MTK_PINMUX_SPEC(22, 0xb10, 3),
+       MTK_PINMUX_SPEC(23, 0xb10, 4),
+       MTK_PINMUX_SPEC(24, 0xb10, 5),
+       MTK_PINMUX_SPEC(29, 0xb10, 9),
+       MTK_PINMUX_SPEC(208, 0xb10, 7),
+       MTK_PINMUX_SPEC(209, 0xb10, 8),
+       MTK_PINMUX_SPEC(203, 0xf20, 0),
+       MTK_PINMUX_SPEC(204, 0xf20, 1),
+       MTK_PINMUX_SPEC(249, 0xef0, 0),
+       MTK_PINMUX_SPEC(250, 0xef0, 0),
+       MTK_PINMUX_SPEC(251, 0xef0, 0),
+       MTK_PINMUX_SPEC(252, 0xef0, 0),
+       MTK_PINMUX_SPEC(253, 0xef0, 0),
+       MTK_PINMUX_SPEC(254, 0xef0, 0),
+       MTK_PINMUX_SPEC(255, 0xef0, 0),
+       MTK_PINMUX_SPEC(256, 0xef0, 0),
+       MTK_PINMUX_SPEC(257, 0xef0, 0),
+       MTK_PINMUX_SPEC(258, 0xef0, 0),
+       MTK_PINMUX_SPEC(259, 0xef0, 0),
+       MTK_PINMUX_SPEC(260, 0xef0, 0),
+};
+
+static void mt2701_spec_pinmux_set(struct regmap *reg, unsigned int pin,
+                       unsigned int mode)
+{
+       unsigned int i, value, mask;
+       unsigned int info_num = ARRAY_SIZE(mt2701_spec_pinmux);
+       unsigned int spec_flag;
+
+       for (i = 0; i < info_num; i++) {
+               if (pin == mt2701_spec_pinmux[i].pin)
+                       break;
+       }
+
+       if (i == info_num)
+               return;
+
+       spec_flag = (mode >> 3);
+       mask = BIT(mt2701_spec_pinmux[i].bit);
+       if (!spec_flag)
+               value = mask;
+       else
+               value = 0;
+       regmap_update_bits(reg, mt2701_spec_pinmux[i].offset, mask, value);
+}
+
+static void mt2701_spec_dir_set(unsigned int *reg_addr, unsigned int pin)
+{
+       if (pin > 175)
+               *reg_addr += 0x10;
+}
+
+static const struct mtk_pinctrl_devdata mt2701_pinctrl_data = {
+       .pins = mtk_pins_mt2701,
+       .npins = ARRAY_SIZE(mtk_pins_mt2701),
+       .grp_desc = mt2701_drv_grp,
+       .n_grp_cls = ARRAY_SIZE(mt2701_drv_grp),
+       .pin_drv_grp = mt2701_pin_drv,
+       .n_pin_drv_grps = ARRAY_SIZE(mt2701_pin_drv),
+       .spec_pull_set = mt2701_spec_pull_set,
+       .spec_ies_smt_set = mt2701_ies_smt_set,
+       .spec_pinmux_set = mt2701_spec_pinmux_set,
+       .spec_dir_set = mt2701_spec_dir_set,
+       .dir_offset = 0x0000,
+       .pullen_offset = 0x0150,
+       .pullsel_offset = 0x0280,
+       .dout_offset = 0x0500,
+       .din_offset = 0x0630,
+       .pinmux_offset = 0x0760,
+       .type1_start = 280,
+       .type1_end = 280,
+       .port_shf = 4,
+       .port_mask = 0x1f,
+       .port_align = 4,
+       .eint_offsets = {
+               .name = "mt2701_eint",
+               .stat      = 0x000,
+               .ack       = 0x040,
+               .mask      = 0x080,
+               .mask_set  = 0x0c0,
+               .mask_clr  = 0x100,
+               .sens      = 0x140,
+               .sens_set  = 0x180,
+               .sens_clr  = 0x1c0,
+               .soft      = 0x200,
+               .soft_set  = 0x240,
+               .soft_clr  = 0x280,
+               .pol       = 0x300,
+               .pol_set   = 0x340,
+               .pol_clr   = 0x380,
+               .dom_en    = 0x400,
+               .dbnc_ctrl = 0x500,
+               .dbnc_set  = 0x600,
+               .dbnc_clr  = 0x700,
+               .port_mask = 6,
+               .ports     = 6,
+       },
+       .ap_num = 169,
+       .db_cnt = 16,
+};
+
+static int mt2701_pinctrl_probe(struct platform_device *pdev)
+{
+       return mtk_pctrl_init(pdev, &mt2701_pinctrl_data, NULL);
+}
+
+static const struct of_device_id mt2701_pctrl_match[] = {
+       { .compatible = "mediatek,mt2701-pinctrl", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, mt2701_pctrl_match);
+
+static struct platform_driver mtk_pinctrl_driver = {
+       .probe = mt2701_pinctrl_probe,
+       .driver = {
+               .name = "mediatek-mt2701-pinctrl",
+               .of_match_table = mt2701_pctrl_match,
+               .pm = &mtk_eint_pm_ops,
+       },
+};
+
+static int __init mtk_pinctrl_init(void)
+{
+       return platform_driver_register(&mtk_pinctrl_driver);
+}
+arch_initcall(mtk_pinctrl_init);
index f9751ae28e327abbee045646b9f14439b1636288..6eccb85c02cd2f764ba43843649c5e6629426225 100644 (file)
@@ -12,7 +12,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -55,7 +55,6 @@ static const struct of_device_id mt6397_pctrl_match[] = {
        { .compatible = "mediatek,mt6397-pinctrl", },
        { }
 };
-MODULE_DEVICE_TABLE(of, mt6397_pctrl_match);
 
 static struct platform_driver mtk_pinctrl_driver = {
        .probe = mt6397_pinctrl_probe,
@@ -69,9 +68,4 @@ static int __init mtk_pinctrl_init(void)
 {
        return platform_driver_register(&mtk_pinctrl_driver);
 }
-
-module_init(mtk_pinctrl_init);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MediaTek MT6397 Pinctrl Driver");
-MODULE_AUTHOR("Hongzhou Yang <hongzhou.yang@mediatek.com>");
+device_initcall(mtk_pinctrl_init);
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7623.c b/drivers/pinctrl/mediatek/pinctrl-mt7623.c
new file mode 100644 (file)
index 0000000..67895f8
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2016 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/regmap.h>
+
+#include "pinctrl-mtk-common.h"
+#include "pinctrl-mtk-mt7623.h"
+
+static const struct mtk_drv_group_desc mt7623_drv_grp[] =  {
+       /* 0E4E8SR 4/8/12/16 */
+       MTK_DRV_GRP(4, 16, 1, 2, 4),
+       /* 0E2E4SR  2/4/6/8 */
+       MTK_DRV_GRP(2, 8, 1, 2, 2),
+       /* E8E4E2  2/4/6/8/10/12/14/16 */
+       MTK_DRV_GRP(2, 16, 0, 2, 2)
+};
+
+#define DRV_SEL0       0xf50
+#define DRV_SEL1       0xf60
+#define DRV_SEL2       0xf70
+#define DRV_SEL3       0xf80
+#define DRV_SEL4       0xf90
+#define DRV_SEL5       0xfa0
+#define DRV_SEL6       0xfb0
+#define DRV_SEL7       0xfe0
+#define DRV_SEL8       0xfd0
+#define DRV_SEL9       0xff0
+#define DRV_SEL10      0xf00
+
+#define MSDC0_CTRL0    0xcc0
+#define MSDC0_CTRL1    0xcd0
+#define MSDC0_CTRL2    0xce0
+#define MSDC0_CTRL3    0xcf0
+#define MSDC0_CTRL4    0xd00
+#define MSDC0_CTRL5    0xd10
+#define MSDC0_CTRL6    0xd20
+#define MSDC1_CTRL0    0xd30
+#define MSDC1_CTRL1    0xd40
+#define MSDC1_CTRL2    0xd50
+#define MSDC1_CTRL3    0xd60
+#define MSDC1_CTRL4    0xd70
+#define MSDC1_CTRL5    0xd80
+#define MSDC1_CTRL6    0xd90
+
+#define IES_EN0                0xb20
+#define IES_EN1                0xb30
+#define IES_EN2                0xb40
+
+#define SMT_EN0                0xb50
+#define SMT_EN1                0xb60
+#define SMT_EN2                0xb70
+
+static const struct mtk_pin_drv_grp mt7623_pin_drv[] = {
+       MTK_PIN_DRV_GRP(0, DRV_SEL0, 0, 1),
+       MTK_PIN_DRV_GRP(1, DRV_SEL0, 0, 1),
+       MTK_PIN_DRV_GRP(2, DRV_SEL0, 0, 1),
+       MTK_PIN_DRV_GRP(3, DRV_SEL0, 0, 1),
+       MTK_PIN_DRV_GRP(4, DRV_SEL0, 0, 1),
+       MTK_PIN_DRV_GRP(5, DRV_SEL0, 0, 1),
+       MTK_PIN_DRV_GRP(6, DRV_SEL0, 0, 1),
+       MTK_PIN_DRV_GRP(7, DRV_SEL0, 4, 1),
+       MTK_PIN_DRV_GRP(8, DRV_SEL0, 4, 1),
+       MTK_PIN_DRV_GRP(9, DRV_SEL0, 4, 1),
+       MTK_PIN_DRV_GRP(10, DRV_SEL0, 8, 1),
+       MTK_PIN_DRV_GRP(11, DRV_SEL0, 8, 1),
+       MTK_PIN_DRV_GRP(12, DRV_SEL0, 8, 1),
+       MTK_PIN_DRV_GRP(13, DRV_SEL0, 8, 1),
+       MTK_PIN_DRV_GRP(14, DRV_SEL0, 12, 0),
+       MTK_PIN_DRV_GRP(15, DRV_SEL0, 12, 0),
+       MTK_PIN_DRV_GRP(18, DRV_SEL1, 4, 0),
+       MTK_PIN_DRV_GRP(19, DRV_SEL1, 4, 0),
+       MTK_PIN_DRV_GRP(20, DRV_SEL1, 4, 0),
+       MTK_PIN_DRV_GRP(21, DRV_SEL1, 4, 0),
+       MTK_PIN_DRV_GRP(22, DRV_SEL1, 8, 0),
+       MTK_PIN_DRV_GRP(23, DRV_SEL1, 8, 0),
+       MTK_PIN_DRV_GRP(24, DRV_SEL1, 8, 0),
+       MTK_PIN_DRV_GRP(25, DRV_SEL1, 8, 0),
+       MTK_PIN_DRV_GRP(26, DRV_SEL1, 8, 0),
+       MTK_PIN_DRV_GRP(27, DRV_SEL1, 12, 0),
+       MTK_PIN_DRV_GRP(28, DRV_SEL1, 12, 0),
+       MTK_PIN_DRV_GRP(29, DRV_SEL1, 12, 0),
+       MTK_PIN_DRV_GRP(33, DRV_SEL2, 0, 0),
+       MTK_PIN_DRV_GRP(34, DRV_SEL2, 0, 0),
+       MTK_PIN_DRV_GRP(35, DRV_SEL2, 0, 0),
+       MTK_PIN_DRV_GRP(36, DRV_SEL2, 0, 0),
+       MTK_PIN_DRV_GRP(37, DRV_SEL2, 0, 0),
+       MTK_PIN_DRV_GRP(39, DRV_SEL2, 8, 1),
+       MTK_PIN_DRV_GRP(40, DRV_SEL2, 8, 1),
+       MTK_PIN_DRV_GRP(41, DRV_SEL2, 8, 1),
+       MTK_PIN_DRV_GRP(42, DRV_SEL2, 8, 1),
+       MTK_PIN_DRV_GRP(43, DRV_SEL2, 12, 0),
+       MTK_PIN_DRV_GRP(44, DRV_SEL2, 12, 0),
+       MTK_PIN_DRV_GRP(45, DRV_SEL2, 12, 0),
+       MTK_PIN_DRV_GRP(47, DRV_SEL3, 0, 0),
+       MTK_PIN_DRV_GRP(48, DRV_SEL3, 0, 0),
+       MTK_PIN_DRV_GRP(49, DRV_SEL3, 4, 0),
+       MTK_PIN_DRV_GRP(53, DRV_SEL3, 12, 0),
+       MTK_PIN_DRV_GRP(54, DRV_SEL3, 12, 0),
+       MTK_PIN_DRV_GRP(55, DRV_SEL3, 12, 0),
+       MTK_PIN_DRV_GRP(56, DRV_SEL3, 12, 0),
+       MTK_PIN_DRV_GRP(60, DRV_SEL4, 8, 1),
+       MTK_PIN_DRV_GRP(61, DRV_SEL4, 8, 1),
+       MTK_PIN_DRV_GRP(62, DRV_SEL4, 8, 1),
+       MTK_PIN_DRV_GRP(63, DRV_SEL4, 12, 1),
+       MTK_PIN_DRV_GRP(64, DRV_SEL4, 12, 1),
+       MTK_PIN_DRV_GRP(65, DRV_SEL4, 12, 1),
+       MTK_PIN_DRV_GRP(66, DRV_SEL5, 0, 1),
+       MTK_PIN_DRV_GRP(67, DRV_SEL5, 0, 1),
+       MTK_PIN_DRV_GRP(68, DRV_SEL5, 0, 1),
+       MTK_PIN_DRV_GRP(69, DRV_SEL5, 0, 1),
+       MTK_PIN_DRV_GRP(70, DRV_SEL5, 0, 1),
+       MTK_PIN_DRV_GRP(71, DRV_SEL5, 0, 1),
+       MTK_PIN_DRV_GRP(72, DRV_SEL3, 4, 0),
+       MTK_PIN_DRV_GRP(73, DRV_SEL3, 4, 0),
+       MTK_PIN_DRV_GRP(74, DRV_SEL3, 4, 0),
+       MTK_PIN_DRV_GRP(83, DRV_SEL5, 0, 1),
+       MTK_PIN_DRV_GRP(84, DRV_SEL5, 0, 1),
+       MTK_PIN_DRV_GRP(105, MSDC1_CTRL1, 0, 1),
+       MTK_PIN_DRV_GRP(106, MSDC1_CTRL0, 0, 1),
+       MTK_PIN_DRV_GRP(107, MSDC1_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(108, MSDC1_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(109, MSDC1_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(110, MSDC1_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(111, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(112, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(113, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(114, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(115, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(116, MSDC0_CTRL1, 0, 1),
+       MTK_PIN_DRV_GRP(117, MSDC0_CTRL0, 0, 1),
+       MTK_PIN_DRV_GRP(118, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(119, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(120, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(121, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(126, DRV_SEL3, 4, 0),
+       MTK_PIN_DRV_GRP(199, DRV_SEL0, 4, 1),
+       MTK_PIN_DRV_GRP(200, DRV_SEL8, 0, 0),
+       MTK_PIN_DRV_GRP(201, DRV_SEL8, 0, 0),
+       MTK_PIN_DRV_GRP(203, DRV_SEL8, 4, 0),
+       MTK_PIN_DRV_GRP(204, DRV_SEL8, 4, 0),
+       MTK_PIN_DRV_GRP(205, DRV_SEL8, 4, 0),
+       MTK_PIN_DRV_GRP(206, DRV_SEL8, 4, 0),
+       MTK_PIN_DRV_GRP(207, DRV_SEL8, 4, 0),
+       MTK_PIN_DRV_GRP(208, DRV_SEL8, 8, 0),
+       MTK_PIN_DRV_GRP(209, DRV_SEL8, 8, 0),
+       MTK_PIN_DRV_GRP(236, DRV_SEL9, 4, 0),
+       MTK_PIN_DRV_GRP(237, DRV_SEL9, 4, 0),
+       MTK_PIN_DRV_GRP(238, DRV_SEL9, 4, 0),
+       MTK_PIN_DRV_GRP(239, DRV_SEL9, 4, 0),
+       MTK_PIN_DRV_GRP(240, DRV_SEL9, 4, 0),
+       MTK_PIN_DRV_GRP(241, DRV_SEL9, 4, 0),
+       MTK_PIN_DRV_GRP(242, DRV_SEL9, 8, 0),
+       MTK_PIN_DRV_GRP(243, DRV_SEL9, 8, 0),
+       MTK_PIN_DRV_GRP(257, MSDC0_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(261, MSDC1_CTRL2, 0, 1),
+       MTK_PIN_DRV_GRP(262, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(263, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(264, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(265, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(266, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(267, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(268, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(269, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(270, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(271, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(272, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(274, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(275, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(276, DRV_SEL10, 8, 0),
+       MTK_PIN_DRV_GRP(278, DRV_SEL2, 8, 1),
+};
+
+static const struct mtk_pin_spec_pupd_set_samereg mt7623_spec_pupd[] = {
+       MTK_PIN_PUPD_SPEC_SR(105, MSDC1_CTRL1, 8, 9, 10),
+       MTK_PIN_PUPD_SPEC_SR(106, MSDC1_CTRL0, 8, 9, 10),
+       MTK_PIN_PUPD_SPEC_SR(107, MSDC1_CTRL3, 0, 1, 2),
+       MTK_PIN_PUPD_SPEC_SR(108, MSDC1_CTRL3, 4, 5, 6),
+       MTK_PIN_PUPD_SPEC_SR(109, MSDC1_CTRL3, 8, 9, 10),
+       MTK_PIN_PUPD_SPEC_SR(110, MSDC1_CTRL3, 12, 13, 14),
+       MTK_PIN_PUPD_SPEC_SR(111, MSDC0_CTRL4, 12, 13, 14),
+       MTK_PIN_PUPD_SPEC_SR(112, MSDC0_CTRL4, 8, 9, 10),
+       MTK_PIN_PUPD_SPEC_SR(113, MSDC0_CTRL4, 4, 5, 6),
+       MTK_PIN_PUPD_SPEC_SR(114, MSDC0_CTRL4, 0, 1, 2),
+       MTK_PIN_PUPD_SPEC_SR(115, MSDC0_CTRL5, 0, 1, 2),
+       MTK_PIN_PUPD_SPEC_SR(116, MSDC0_CTRL1, 8, 9, 10),
+       MTK_PIN_PUPD_SPEC_SR(117, MSDC0_CTRL0, 8, 9, 10),
+       MTK_PIN_PUPD_SPEC_SR(118, MSDC0_CTRL3, 12, 13, 14),
+       MTK_PIN_PUPD_SPEC_SR(119, MSDC0_CTRL3, 8, 9, 10),
+       MTK_PIN_PUPD_SPEC_SR(120, MSDC0_CTRL3, 4, 5, 6),
+       MTK_PIN_PUPD_SPEC_SR(121, MSDC0_CTRL3, 0, 1, 2),
+};
+
+static int mt7623_spec_pull_set(struct regmap *regmap, unsigned int pin,
+               unsigned char align, bool isup, unsigned int r1r0)
+{
+       return mtk_pctrl_spec_pull_set_samereg(regmap, mt7623_spec_pupd,
+               ARRAY_SIZE(mt7623_spec_pupd), pin, align, isup, r1r0);
+}
+
+static const struct mtk_pin_ies_smt_set mt7623_ies_set[] = {
+       MTK_PIN_IES_SMT_SPEC(0, 6, IES_EN0, 0),
+       MTK_PIN_IES_SMT_SPEC(7, 9, IES_EN0, 1),
+       MTK_PIN_IES_SMT_SPEC(10, 13, IES_EN0, 2),
+       MTK_PIN_IES_SMT_SPEC(14, 15, IES_EN0, 3),
+       MTK_PIN_IES_SMT_SPEC(18, 21, IES_EN0, 5),
+       MTK_PIN_IES_SMT_SPEC(22, 26, IES_EN0, 6),
+       MTK_PIN_IES_SMT_SPEC(27, 29, IES_EN0, 7),
+       MTK_PIN_IES_SMT_SPEC(33, 37, IES_EN0, 8),
+       MTK_PIN_IES_SMT_SPEC(39, 42, IES_EN0, 9),
+       MTK_PIN_IES_SMT_SPEC(43, 45, IES_EN0, 10),
+       MTK_PIN_IES_SMT_SPEC(47, 48, IES_EN0, 11),
+       MTK_PIN_IES_SMT_SPEC(49, 49, IES_EN0, 12),
+       MTK_PIN_IES_SMT_SPEC(53, 56, IES_EN0, 14),
+       MTK_PIN_IES_SMT_SPEC(60, 62, IES_EN1, 0),
+       MTK_PIN_IES_SMT_SPEC(63, 65, IES_EN1, 1),
+       MTK_PIN_IES_SMT_SPEC(66, 71, IES_EN1, 2),
+       MTK_PIN_IES_SMT_SPEC(72, 74, IES_EN0, 12),
+       MTK_PIN_IES_SMT_SPEC(75, 76, IES_EN1, 3),
+       MTK_PIN_IES_SMT_SPEC(83, 84, IES_EN1, 2),
+       MTK_PIN_IES_SMT_SPEC(105, 121, MSDC1_CTRL1, 4),
+       MTK_PIN_IES_SMT_SPEC(122, 125, IES_EN1, 7),
+       MTK_PIN_IES_SMT_SPEC(126, 126, IES_EN0, 12),
+       MTK_PIN_IES_SMT_SPEC(199, 201, IES_EN0, 1),
+       MTK_PIN_IES_SMT_SPEC(203, 207, IES_EN2, 2),
+       MTK_PIN_IES_SMT_SPEC(208, 209, IES_EN2, 3),
+       MTK_PIN_IES_SMT_SPEC(236, 241, IES_EN2, 6),
+       MTK_PIN_IES_SMT_SPEC(242, 243, IES_EN2, 7),
+       MTK_PIN_IES_SMT_SPEC(261, 261, MSDC1_CTRL2, 4),
+       MTK_PIN_IES_SMT_SPEC(262, 272, IES_EN2, 12),
+       MTK_PIN_IES_SMT_SPEC(274, 276, IES_EN2, 12),
+       MTK_PIN_IES_SMT_SPEC(278, 278, IES_EN2, 13),
+};
+
+static const struct mtk_pin_ies_smt_set mt7623_smt_set[] = {
+       MTK_PIN_IES_SMT_SPEC(0, 6, SMT_EN0, 0),
+       MTK_PIN_IES_SMT_SPEC(7, 9, SMT_EN0, 1),
+       MTK_PIN_IES_SMT_SPEC(10, 13, SMT_EN0, 2),
+       MTK_PIN_IES_SMT_SPEC(14, 15, SMT_EN0, 3),
+       MTK_PIN_IES_SMT_SPEC(18, 21, SMT_EN0, 5),
+       MTK_PIN_IES_SMT_SPEC(22, 26, SMT_EN0, 6),
+       MTK_PIN_IES_SMT_SPEC(27, 29, SMT_EN0, 7),
+       MTK_PIN_IES_SMT_SPEC(33, 37, SMT_EN0, 8),
+       MTK_PIN_IES_SMT_SPEC(39, 42, SMT_EN0, 9),
+       MTK_PIN_IES_SMT_SPEC(43, 45, SMT_EN0, 10),
+       MTK_PIN_IES_SMT_SPEC(47, 48, SMT_EN0, 11),
+       MTK_PIN_IES_SMT_SPEC(49, 49, SMT_EN0, 12),
+       MTK_PIN_IES_SMT_SPEC(53, 56, SMT_EN0, 14),
+       MTK_PIN_IES_SMT_SPEC(60, 62, SMT_EN1, 0),
+       MTK_PIN_IES_SMT_SPEC(63, 65, SMT_EN1, 1),
+       MTK_PIN_IES_SMT_SPEC(66, 71, SMT_EN1, 2),
+       MTK_PIN_IES_SMT_SPEC(72, 74, SMT_EN0, 12),
+       MTK_PIN_IES_SMT_SPEC(75, 76, SMT_EN1, 3),
+       MTK_PIN_IES_SMT_SPEC(83, 84, SMT_EN1, 2),
+       MTK_PIN_IES_SMT_SPEC(105, 106, MSDC1_CTRL1, 11),
+       MTK_PIN_IES_SMT_SPEC(107, 107, MSDC1_CTRL3, 3),
+       MTK_PIN_IES_SMT_SPEC(108, 108, MSDC1_CTRL3, 7),
+       MTK_PIN_IES_SMT_SPEC(109, 109, MSDC1_CTRL3, 11),
+       MTK_PIN_IES_SMT_SPEC(110, 111, MSDC1_CTRL3, 15),
+       MTK_PIN_IES_SMT_SPEC(112, 112, MSDC0_CTRL4, 11),
+       MTK_PIN_IES_SMT_SPEC(113, 113, MSDC0_CTRL4, 7),
+       MTK_PIN_IES_SMT_SPEC(114, 115, MSDC0_CTRL4, 3),
+       MTK_PIN_IES_SMT_SPEC(116, 117, MSDC0_CTRL1, 11),
+       MTK_PIN_IES_SMT_SPEC(118, 118, MSDC0_CTRL3, 15),
+       MTK_PIN_IES_SMT_SPEC(119, 119, MSDC0_CTRL3, 11),
+       MTK_PIN_IES_SMT_SPEC(120, 120, MSDC0_CTRL3, 7),
+       MTK_PIN_IES_SMT_SPEC(121, 121, MSDC0_CTRL3, 3),
+       MTK_PIN_IES_SMT_SPEC(122, 125, SMT_EN1, 7),
+       MTK_PIN_IES_SMT_SPEC(126, 126, SMT_EN0, 12),
+       MTK_PIN_IES_SMT_SPEC(199, 201, SMT_EN0, 1),
+       MTK_PIN_IES_SMT_SPEC(203, 207, SMT_EN2, 2),
+       MTK_PIN_IES_SMT_SPEC(208, 209, SMT_EN2, 3),
+       MTK_PIN_IES_SMT_SPEC(236, 241, SMT_EN2, 6),
+       MTK_PIN_IES_SMT_SPEC(242, 243, SMT_EN2, 7),
+       MTK_PIN_IES_SMT_SPEC(261, 261, MSDC1_CTRL6, 3),
+       MTK_PIN_IES_SMT_SPEC(262, 272, SMT_EN2, 12),
+       MTK_PIN_IES_SMT_SPEC(274, 276, SMT_EN2, 12),
+       MTK_PIN_IES_SMT_SPEC(278, 278, SMT_EN2, 13),
+};
+
+static int mt7623_ies_smt_set(struct regmap *regmap, unsigned int pin,
+               unsigned char align, int value, enum pin_config_param arg)
+{
+       if (arg == PIN_CONFIG_INPUT_ENABLE)
+               return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_ies_set,
+                       ARRAY_SIZE(mt7623_ies_set), pin, align, value);
+       else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE)
+               return mtk_pconf_spec_set_ies_smt_range(regmap, mt7623_smt_set,
+                       ARRAY_SIZE(mt7623_smt_set), pin, align, value);
+       return -EINVAL;
+}
+
+static const struct mtk_pinctrl_devdata mt7623_pinctrl_data = {
+       .pins = mtk_pins_mt7623,
+       .npins = ARRAY_SIZE(mtk_pins_mt7623),
+       .grp_desc = mt7623_drv_grp,
+       .n_grp_cls = ARRAY_SIZE(mt7623_drv_grp),
+       .pin_drv_grp = mt7623_pin_drv,
+       .n_pin_drv_grps = ARRAY_SIZE(mt7623_pin_drv),
+       .spec_pull_set = mt7623_spec_pull_set,
+       .spec_ies_smt_set = mt7623_ies_smt_set,
+       .dir_offset = 0x0000,
+       .pullen_offset = 0x0150,
+       .pullsel_offset = 0x0280,
+       .dout_offset = 0x0500,
+       .din_offset = 0x0630,
+       .pinmux_offset = 0x0760,
+       .type1_start = 280,
+       .type1_end = 280,
+       .port_shf = 4,
+       .port_mask = 0x1f,
+       .port_align = 4,
+       .eint_offsets = {
+               .name = "mt7623_eint",
+               .stat      = 0x000,
+               .ack       = 0x040,
+               .mask      = 0x080,
+               .mask_set  = 0x0c0,
+               .mask_clr  = 0x100,
+               .sens      = 0x140,
+               .sens_set  = 0x180,
+               .sens_clr  = 0x1c0,
+               .soft      = 0x200,
+               .soft_set  = 0x240,
+               .soft_clr  = 0x280,
+               .pol       = 0x300,
+               .pol_set   = 0x340,
+               .pol_clr   = 0x380,
+               .dom_en    = 0x400,
+               .dbnc_ctrl = 0x500,
+               .dbnc_set  = 0x600,
+               .dbnc_clr  = 0x700,
+               .port_mask = 6,
+               .ports     = 6,
+       },
+       .ap_num = 169,
+       .db_cnt = 16,
+};
+
+static int mt7623_pinctrl_probe(struct platform_device *pdev)
+{
+       return mtk_pctrl_init(pdev, &mt7623_pinctrl_data, NULL);
+}
+
+static const struct of_device_id mt7623_pctrl_match[] = {
+       { .compatible = "mediatek,mt7623-pinctrl", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, mt7623_pctrl_match);
+
+static struct platform_driver mtk_pinctrl_driver = {
+       .probe = mt7623_pinctrl_probe,
+       .driver = {
+               .name = "mediatek-mt7623-pinctrl",
+               .of_match_table = mt7623_pctrl_match,
+       },
+};
+
+static int __init mtk_pinctrl_init(void)
+{
+       return platform_driver_register(&mtk_pinctrl_driver);
+}
+
+arch_initcall(mtk_pinctrl_init);
index 98e0bebfdf92fcf461dbaa121e60d13d48bd5a8c..d76491574841fc525f548a8b70b3d7f2db39ffb0 100644 (file)
@@ -13,7 +13,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -336,7 +336,6 @@ static const struct of_device_id mt8127_pctrl_match[] = {
        { .compatible = "mediatek,mt8127-pinctrl", },
        { }
 };
-MODULE_DEVICE_TABLE(of, mt8127_pctrl_match);
 
 static struct platform_driver mtk_pinctrl_driver = {
        .probe = mt8127_pinctrl_probe,
@@ -350,9 +349,4 @@ static int __init mtk_pinctrl_init(void)
 {
        return platform_driver_register(&mtk_pinctrl_driver);
 }
-
 arch_initcall(mtk_pinctrl_init);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MediaTek MT8127 Pinctrl Driver");
-MODULE_AUTHOR("Yingjoe Chen <yingjoe.chen@mediatek.com>");
index 1c153b860f36533858194cdb72b5a8fb8a77aef4..d8c645f16f21e6131ca4d6c9478fefffbb4c7264 100644 (file)
@@ -12,7 +12,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -351,7 +351,6 @@ static const struct of_device_id mt8135_pctrl_match[] = {
        },
        { }
 };
-MODULE_DEVICE_TABLE(of, mt8135_pctrl_match);
 
 static struct platform_driver mtk_pinctrl_driver = {
        .probe = mt8135_pinctrl_probe,
@@ -365,9 +364,4 @@ static int __init mtk_pinctrl_init(void)
 {
        return platform_driver_register(&mtk_pinctrl_driver);
 }
-
 arch_initcall(mtk_pinctrl_init);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
-MODULE_AUTHOR("Hongzhou Yang <hongzhou.yang@mediatek.com>");
index a62514eb21290b6edee22aff6b63b19ea1334284..8bfd427b9135bb692659607837deda34a2b63811 100644 (file)
@@ -12,7 +12,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -378,7 +378,6 @@ static const struct of_device_id mt8173_pctrl_match[] = {
        },
        { }
 };
-MODULE_DEVICE_TABLE(of, mt8173_pctrl_match);
 
 static struct platform_driver mtk_pinctrl_driver = {
        .probe = mt8173_pinctrl_probe,
@@ -393,9 +392,4 @@ static int __init mtk_pinctrl_init(void)
 {
        return platform_driver_register(&mtk_pinctrl_driver);
 }
-
 arch_initcall(mtk_pinctrl_init);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
-MODULE_AUTHOR("Hongzhou Yang <hongzhou.yang@mediatek.com>");
index e96e86d2e745e06e691344cca3fd38922450de58..2bbe6f7964a79d9099bd512f2ac430f0b2d96861 100644 (file)
 
 #define MAX_GPIO_MODE_PER_REG 5
 #define GPIO_MODE_BITS        3
+#define GPIO_MODE_PREFIX "GPIO"
 
 static const char * const mtk_gpio_functions[] = {
        "func0", "func1", "func2", "func3",
        "func4", "func5", "func6", "func7",
+       "func8", "func9", "func10", "func11",
+       "func12", "func13", "func14", "func15",
 };
 
 /*
@@ -81,6 +84,9 @@ static int mtk_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
        reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dir_offset;
        bit = BIT(offset & 0xf);
 
+       if (pctl->devdata->spec_dir_set)
+               pctl->devdata->spec_dir_set(&reg_addr, offset);
+
        if (input)
                /* Different SoC has different alignment offset. */
                reg_addr = CLR_ADDR(reg_addr, pctl);
@@ -677,9 +683,14 @@ static int mtk_pmx_set_mode(struct pinctrl_dev *pctldev,
        unsigned int mask = (1L << GPIO_MODE_BITS) - 1;
        struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
 
+       if (pctl->devdata->spec_pinmux_set)
+               pctl->devdata->spec_pinmux_set(mtk_get_regmap(pctl, pin),
+                                       pin, mode);
+
        reg_addr = ((pin / MAX_GPIO_MODE_PER_REG) << pctl->devdata->port_shf)
                        + pctl->devdata->pinmux_offset;
 
+       mode &= mask;
        bit = pin % MAX_GPIO_MODE_PER_REG;
        mask <<= (GPIO_MODE_BITS * bit);
        val = (mode << (GPIO_MODE_BITS * bit));
@@ -725,12 +736,48 @@ static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev,
        return 0;
 }
 
+static int mtk_pmx_find_gpio_mode(struct mtk_pinctrl *pctl,
+                               unsigned offset)
+{
+       const struct mtk_desc_pin *pin = pctl->devdata->pins + offset;
+       const struct mtk_desc_function *func = pin->functions;
+
+       while (func && func->name) {
+               if (!strncmp(func->name, GPIO_MODE_PREFIX,
+                       sizeof(GPIO_MODE_PREFIX)-1))
+                       return func->muxval;
+               func++;
+       }
+       return -EINVAL;
+}
+
+static int mtk_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
+                                   struct pinctrl_gpio_range *range,
+                                   unsigned offset)
+{
+       int muxval;
+       struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       muxval = mtk_pmx_find_gpio_mode(pctl, offset);
+
+       if (muxval < 0) {
+               dev_err(pctl->dev, "invalid gpio pin %d.\n", offset);
+               return -EINVAL;
+       }
+
+       mtk_pmx_set_mode(pctldev, offset, muxval);
+       mtk_pconf_set_ies_smt(pctl, offset, 1, PIN_CONFIG_INPUT_ENABLE);
+
+       return 0;
+}
+
 static const struct pinmux_ops mtk_pmx_ops = {
        .get_functions_count    = mtk_pmx_get_funcs_cnt,
        .get_function_name      = mtk_pmx_get_func_name,
        .get_function_groups    = mtk_pmx_get_func_groups,
        .set_mux                = mtk_pmx_set_mux,
        .gpio_set_direction     = mtk_pmx_gpio_set_direction,
+       .gpio_request_enable    = mtk_pmx_gpio_request_enable,
 };
 
 static int mtk_gpio_direction_input(struct gpio_chip *chip,
@@ -756,6 +803,10 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
 
        reg_addr =  mtk_get_port(pctl, offset) + pctl->devdata->dir_offset;
        bit = BIT(offset & 0xf);
+
+       if (pctl->devdata->spec_dir_set)
+               pctl->devdata->spec_dir_set(&reg_addr, offset);
+
        regmap_read(pctl->regmap1, reg_addr, &read_val);
        return !(read_val & bit);
 }
@@ -814,6 +865,10 @@ static int mtk_pinctrl_irq_request_resources(struct irq_data *d)
 
        /* set mux to INT mode */
        mtk_pmx_set_mode(pctl->pctl_dev, pin->pin.number, pin->eint.eintmux);
+       /* set gpio direction to input */
+       mtk_pmx_gpio_set_direction(pctl->pctl_dev, NULL, pin->pin.number, true);
+       /* set input-enable */
+       mtk_pconf_set_ies_smt(pctl, pin->pin.number, 1, PIN_CONFIG_INPUT_ENABLE);
 
        return 0;
 }
index 55a5343389315e1c4213b18bc9ff2875d40704d4..8543bc478a1ec15f3b82f316b9ccb4a0c561a463 100644 (file)
@@ -209,7 +209,14 @@ struct mtk_eint_offsets {
  * means when user set smt, input enable is set at the same time. So they
  * also need special control. If special control is success, this should
  * return 0, otherwise return non-zero value.
- *
+ * @spec_pinmux_set: In some cases, there are two pinmux functions share
+ * the same value in the same segment of pinmux control register. If user
+ * want to use one of the two functions, they need an extra bit setting to
+ * select the right one.
+ * @spec_dir_set: In very few SoCs, direction control registers are not
+ * arranged continuously, they may be cut to parts. So they need special
+ * dir setting.
+
  * @dir_offset: The direction register offset.
  * @pullen_offset: The pull-up/pull-down enable register offset.
  * @pinmux_offset: The pinmux register offset.
@@ -234,6 +241,9 @@ struct mtk_pinctrl_devdata {
                        unsigned char align, bool isup, unsigned int arg);
        int (*spec_ies_smt_set)(struct regmap *reg, unsigned int pin,
                        unsigned char align, int value, enum pin_config_param arg);
+       void (*spec_pinmux_set)(struct regmap *reg, unsigned int pin,
+                       unsigned int mode);
+       void (*spec_dir_set)(unsigned int *reg_addr, unsigned int pin);
        unsigned int dir_offset;
        unsigned int ies_offset;
        unsigned int smt_offset;
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h
new file mode 100644 (file)
index 0000000..f906420
--- /dev/null
@@ -0,0 +1,2323 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Biao Huang <biao.huang@mediatek.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PINCTRL_MTK_MT2701_H
+#define __PINCTRL_MTK_MT2701_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mtk-common.h"
+
+static const struct mtk_desc_pin mtk_pins_mt2701[] = {
+       MTK_PIN(
+               PINCTRL_PIN(0, "PWRAP_SPI0_MI"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 148),
+               MTK_FUNCTION(0, "GPIO0"),
+               MTK_FUNCTION(1, "PWRAP_SPIDO"),
+               MTK_FUNCTION(2, "PWRAP_SPIDI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(1, "PWRAP_SPI0_MO"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 149),
+               MTK_FUNCTION(0, "GPIO1"),
+               MTK_FUNCTION(1, "PWRAP_SPIDI"),
+               MTK_FUNCTION(2, "PWRAP_SPIDO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(2, "PWRAP_INT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 150),
+               MTK_FUNCTION(0, "GPIO2"),
+               MTK_FUNCTION(1, "PWRAP_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(3, "PWRAP_SPI0_CK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 151),
+               MTK_FUNCTION(0, "GPIO3"),
+               MTK_FUNCTION(1, "PWRAP_SPICK_I")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(4, "PWRAP_SPI0_CSN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 152),
+               MTK_FUNCTION(0, "GPIO4"),
+               MTK_FUNCTION(1, "PWRAP_SPICS_B_I")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(5, "PWRAP_SPI0_CK2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 153),
+               MTK_FUNCTION(0, "GPIO5"),
+               MTK_FUNCTION(1, "PWRAP_SPICK2_I"),
+               MTK_FUNCTION(5, "ANT_SEL1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(6, "PWRAP_SPI0_CSN2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 154),
+               MTK_FUNCTION(0, "GPIO6"),
+               MTK_FUNCTION(1, "PWRAP_SPICS2_B_I"),
+               MTK_FUNCTION(5, "ANT_SEL0"),
+               MTK_FUNCTION(7, "DBG_MON_A[0]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(7, "SPI1_CSN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 155),
+               MTK_FUNCTION(0, "GPIO7"),
+               MTK_FUNCTION(1, "SPI1_CS"),
+               MTK_FUNCTION(4, "KCOL0"),
+               MTK_FUNCTION(7, "DBG_MON_B[12]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(8, "SPI1_MI"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 156),
+               MTK_FUNCTION(0, "GPIO8"),
+               MTK_FUNCTION(1, "SPI1_MI"),
+               MTK_FUNCTION(2, "SPI1_MO"),
+               MTK_FUNCTION(4, "KCOL1"),
+               MTK_FUNCTION(7, "DBG_MON_B[13]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(9, "SPI1_MO"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 157),
+               MTK_FUNCTION(0, "GPIO9"),
+               MTK_FUNCTION(1, "SPI1_MO"),
+               MTK_FUNCTION(2, "SPI1_MI"),
+               MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(4, "KCOL2"),
+               MTK_FUNCTION(7, "DBG_MON_B[14]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(10, "RTC32K_CK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 158),
+               MTK_FUNCTION(0, "GPIO10"),
+               MTK_FUNCTION(1, "RTC32K_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(11, "WATCHDOG"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 159),
+               MTK_FUNCTION(0, "GPIO11"),
+               MTK_FUNCTION(1, "WATCHDOG")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(12, "SRCLKENA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 160),
+               MTK_FUNCTION(0, "GPIO12"),
+               MTK_FUNCTION(1, "SRCLKENA")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(13, "SRCLKENAI"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 161),
+               MTK_FUNCTION(0, "GPIO13"),
+               MTK_FUNCTION(1, "SRCLKENAI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(14, "URXD2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 162),
+               MTK_FUNCTION(0, "GPIO14"),
+               MTK_FUNCTION(1, "URXD2"),
+               MTK_FUNCTION(2, "UTXD2"),
+               MTK_FUNCTION(5, "SRCCLKENAI2"),
+               MTK_FUNCTION(7, "DBG_MON_B[30]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(15, "UTXD2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 163),
+               MTK_FUNCTION(0, "GPIO15"),
+               MTK_FUNCTION(1, "UTXD2"),
+               MTK_FUNCTION(2, "URXD2"),
+               MTK_FUNCTION(7, "DBG_MON_B[31]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(16, "I2S5_DATA_IN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 164),
+               MTK_FUNCTION(0, "GPIO16"),
+               MTK_FUNCTION(1, "I2S5_DATA_IN"),
+               MTK_FUNCTION(3, "PCM_RX"),
+               MTK_FUNCTION(4, "ANT_SEL4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(17, "I2S5_BCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 165),
+               MTK_FUNCTION(0, "GPIO17"),
+               MTK_FUNCTION(1, "I2S5_BCK"),
+               MTK_FUNCTION(3, "PCM_CLK0"),
+               MTK_FUNCTION(4, "ANT_SEL2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(18, "PCM_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 166),
+               MTK_FUNCTION(0, "GPIO18"),
+               MTK_FUNCTION(1, "PCM_CLK0"),
+               MTK_FUNCTION(2, "MRG_CLK"),
+               MTK_FUNCTION(4, "MM_TEST_CK"),
+               MTK_FUNCTION(5, "CONN_DSP_JCK"),
+               MTK_FUNCTION(6, "WCN_PCM_CLKO"),
+               MTK_FUNCTION(7, "DBG_MON_A[3]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(19, "PCM_SYNC"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 167),
+               MTK_FUNCTION(0, "GPIO19"),
+               MTK_FUNCTION(1, "PCM_SYNC"),
+               MTK_FUNCTION(2, "MRG_SYNC"),
+               MTK_FUNCTION(5, "CONN_DSP_JINTP"),
+               MTK_FUNCTION(6, "WCN_PCM_SYNC"),
+               MTK_FUNCTION(7, "DBG_MON_A[5]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(20, "PCM_RX"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO20"),
+               MTK_FUNCTION(1, "PCM_RX"),
+               MTK_FUNCTION(2, "MRG_RX"),
+               MTK_FUNCTION(3, "MRG_TX"),
+               MTK_FUNCTION(4, "PCM_TX"),
+               MTK_FUNCTION(5, "CONN_DSP_JDI"),
+               MTK_FUNCTION(6, "WCN_PCM_RX"),
+               MTK_FUNCTION(7, "DBG_MON_A[4]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(21, "PCM_TX"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO21"),
+               MTK_FUNCTION(1, "PCM_TX"),
+               MTK_FUNCTION(2, "MRG_TX"),
+               MTK_FUNCTION(3, "MRG_RX"),
+               MTK_FUNCTION(4, "PCM_RX"),
+               MTK_FUNCTION(5, "CONN_DSP_JMS"),
+               MTK_FUNCTION(6, "WCN_PCM_TX"),
+               MTK_FUNCTION(7, "DBG_MON_A[2]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(22, "EINT0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 0),
+               MTK_FUNCTION(0, "GPIO22"),
+               MTK_FUNCTION(1, "UCTS0"),
+               MTK_FUNCTION(3, "KCOL3"),
+               MTK_FUNCTION(4, "CONN_DSP_JDO"),
+               MTK_FUNCTION(5, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(7, "DBG_MON_A[30]"),
+               MTK_FUNCTION(10, "PCIE0_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(23, "EINT1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 1),
+               MTK_FUNCTION(0, "GPIO23"),
+               MTK_FUNCTION(1, "URTS0"),
+               MTK_FUNCTION(3, "KCOL2"),
+               MTK_FUNCTION(4, "CONN_MCU_TDO"),
+               MTK_FUNCTION(5, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(7, "DBG_MON_A[29]"),
+               MTK_FUNCTION(10, "PCIE1_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(24, "EINT2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 2),
+               MTK_FUNCTION(0, "GPIO24"),
+               MTK_FUNCTION(1, "UCTS1"),
+               MTK_FUNCTION(3, "KCOL1"),
+               MTK_FUNCTION(4, "CONN_MCU_DBGACK_N"),
+               MTK_FUNCTION(7, "DBG_MON_A[28]"),
+               MTK_FUNCTION(10, "PCIE2_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(25, "EINT3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 3),
+               MTK_FUNCTION(0, "GPIO25"),
+               MTK_FUNCTION(1, "URTS1"),
+               MTK_FUNCTION(3, "KCOL0"),
+               MTK_FUNCTION(4, "CONN_MCU_DBGI_N"),
+               MTK_FUNCTION(7, "DBG_MON_A[27]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(26, "EINT4"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 4),
+               MTK_FUNCTION(0, "GPIO26"),
+               MTK_FUNCTION(1, "UCTS3"),
+               MTK_FUNCTION(2, "DRV_VBUS_P1"),
+               MTK_FUNCTION(3, "KROW3"),
+               MTK_FUNCTION(4, "CONN_MCU_TCK0"),
+               MTK_FUNCTION(5, "CONN_MCU_AICE_JCKC"),
+               MTK_FUNCTION(6, "PCIE2_WAKE_N"),
+               MTK_FUNCTION(7, "DBG_MON_A[26]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(27, "EINT5"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 5),
+               MTK_FUNCTION(0, "GPIO27"),
+               MTK_FUNCTION(1, "URTS3"),
+               MTK_FUNCTION(2, "IDDIG_P1"),
+               MTK_FUNCTION(3, "KROW2"),
+               MTK_FUNCTION(4, "CONN_MCU_TDI"),
+               MTK_FUNCTION(6, "PCIE1_WAKE_N"),
+               MTK_FUNCTION(7, "DBG_MON_A[25]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(28, "EINT6"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 6),
+               MTK_FUNCTION(0, "GPIO28"),
+               MTK_FUNCTION(1, "DRV_VBUS"),
+               MTK_FUNCTION(3, "KROW1"),
+               MTK_FUNCTION(4, "CONN_MCU_TRST_B"),
+               MTK_FUNCTION(6, "PCIE0_WAKE_N"),
+               MTK_FUNCTION(7, "DBG_MON_A[24]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(29, "EINT7"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 7),
+               MTK_FUNCTION(0, "GPIO29"),
+               MTK_FUNCTION(1, "IDDIG"),
+               MTK_FUNCTION(2, "MSDC1_WP"),
+               MTK_FUNCTION(3, "KROW0"),
+               MTK_FUNCTION(4, "CONN_MCU_TMS"),
+               MTK_FUNCTION(5, "CONN_MCU_AICE_JMSC"),
+               MTK_FUNCTION(7, "DBG_MON_A[23]"),
+               MTK_FUNCTION(14, "PCIE2_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(30, "I2S5_LRCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 12),
+               MTK_FUNCTION(0, "GPIO30"),
+               MTK_FUNCTION(1, "I2S5_LRCK"),
+               MTK_FUNCTION(3, "PCM_SYNC"),
+               MTK_FUNCTION(4, "ANT_SEL1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(31, "I2S5_MCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 13),
+               MTK_FUNCTION(0, "GPIO31"),
+               MTK_FUNCTION(1, "I2S5_MCLK"),
+               MTK_FUNCTION(4, "ANT_SEL0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(32, "I2S5_DATA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 14),
+               MTK_FUNCTION(0, "GPIO32"),
+               MTK_FUNCTION(1, "I2S5_DATA"),
+               MTK_FUNCTION(2, "I2S5_DATA_BYPS"),
+               MTK_FUNCTION(3, "PCM_TX"),
+               MTK_FUNCTION(4, "ANT_SEL3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(33, "I2S1_DATA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 15),
+               MTK_FUNCTION(0, "GPIO33"),
+               MTK_FUNCTION(1, "I2S1_DATA"),
+               MTK_FUNCTION(2, "I2S1_DATA_BYPS"),
+               MTK_FUNCTION(3, "PCM_TX"),
+               MTK_FUNCTION(4, "IMG_TEST_CK"),
+               MTK_FUNCTION(5, "G1_RXD0"),
+               MTK_FUNCTION(6, "WCN_PCM_TX"),
+               MTK_FUNCTION(7, "DBG_MON_B[8]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(34, "I2S1_DATA_IN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 16),
+               MTK_FUNCTION(0, "GPIO34"),
+               MTK_FUNCTION(1, "I2S1_DATA_IN"),
+               MTK_FUNCTION(3, "PCM_RX"),
+               MTK_FUNCTION(4, "VDEC_TEST_CK"),
+               MTK_FUNCTION(5, "G1_RXD1"),
+               MTK_FUNCTION(6, "WCN_PCM_RX"),
+               MTK_FUNCTION(7, "DBG_MON_B[7]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(35, "I2S1_BCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 17),
+               MTK_FUNCTION(0, "GPIO35"),
+               MTK_FUNCTION(1, "I2S1_BCK"),
+               MTK_FUNCTION(3, "PCM_CLK0"),
+               MTK_FUNCTION(5, "G1_RXD2"),
+               MTK_FUNCTION(6, "WCN_PCM_CLKO"),
+               MTK_FUNCTION(7, "DBG_MON_B[9]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(36, "I2S1_LRCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 18),
+               MTK_FUNCTION(0, "GPIO36"),
+               MTK_FUNCTION(1, "I2S1_LRCK"),
+               MTK_FUNCTION(3, "PCM_SYNC"),
+               MTK_FUNCTION(5, "G1_RXD3"),
+               MTK_FUNCTION(6, "WCN_PCM_SYNC"),
+               MTK_FUNCTION(7, "DBG_MON_B[10]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(37, "I2S1_MCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 19),
+               MTK_FUNCTION(0, "GPIO37"),
+               MTK_FUNCTION(1, "I2S1_MCLK"),
+               MTK_FUNCTION(5, "G1_RXDV"),
+               MTK_FUNCTION(7, "DBG_MON_B[11]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(38, "I2S2_DATA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 20),
+               MTK_FUNCTION(0, "GPIO38"),
+               MTK_FUNCTION(2, "I2S2_DATA_BYPS"),
+               MTK_FUNCTION(3, "PCM_TX"),
+               MTK_FUNCTION(4, "DMIC_DAT0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(39, "JTMS"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 21),
+               MTK_FUNCTION(0, "GPIO39"),
+               MTK_FUNCTION(1, "JTMS"),
+               MTK_FUNCTION(2, "CONN_MCU_TMS"),
+               MTK_FUNCTION(3, "CONN_MCU_AICE_JMSC"),
+               MTK_FUNCTION(4, "DFD_TMS_XI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(40, "JTCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 22),
+               MTK_FUNCTION(0, "GPIO40"),
+               MTK_FUNCTION(1, "JTCK"),
+               MTK_FUNCTION(2, "CONN_MCU_TCK1"),
+               MTK_FUNCTION(3, "CONN_MCU_AICE_JCKC"),
+               MTK_FUNCTION(4, "DFD_TCK_XI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(41, "JTDI"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 23),
+               MTK_FUNCTION(0, "GPIO41"),
+               MTK_FUNCTION(1, "JTDI"),
+               MTK_FUNCTION(2, "CONN_MCU_TDI"),
+               MTK_FUNCTION(4, "DFD_TDI_XI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(42, "JTDO"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 24),
+               MTK_FUNCTION(0, "GPIO42"),
+               MTK_FUNCTION(1, "JTDO"),
+               MTK_FUNCTION(2, "CONN_MCU_TDO"),
+               MTK_FUNCTION(4, "DFD_TDO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(43, "NCLE"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 25),
+               MTK_FUNCTION(0, "GPIO43"),
+               MTK_FUNCTION(1, "NCLE"),
+               MTK_FUNCTION(2, "EXT_XCS2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(44, "NCEB1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 26),
+               MTK_FUNCTION(0, "GPIO44"),
+               MTK_FUNCTION(1, "NCEB1"),
+               MTK_FUNCTION(2, "IDDIG")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(45, "NCEB0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 27),
+               MTK_FUNCTION(0, "GPIO45"),
+               MTK_FUNCTION(1, "NCEB0"),
+               MTK_FUNCTION(2, "DRV_VBUS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(46, "IR"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 28),
+               MTK_FUNCTION(0, "GPIO46"),
+               MTK_FUNCTION(1, "IR")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(47, "NREB"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 29),
+               MTK_FUNCTION(0, "GPIO47"),
+               MTK_FUNCTION(1, "NREB"),
+               MTK_FUNCTION(2, "IDDIG_P1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(48, "NRNB"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 30),
+               MTK_FUNCTION(0, "GPIO48"),
+               MTK_FUNCTION(1, "NRNB"),
+               MTK_FUNCTION(2, "DRV_VBUS_P1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(49, "I2S0_DATA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 31),
+               MTK_FUNCTION(0, "GPIO49"),
+               MTK_FUNCTION(1, "I2S0_DATA"),
+               MTK_FUNCTION(2, "I2S0_DATA_BYPS"),
+               MTK_FUNCTION(3, "PCM_TX"),
+               MTK_FUNCTION(6, "WCN_I2S_DO"),
+               MTK_FUNCTION(7, "DBG_MON_B[3]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(50, "I2S2_BCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 32),
+               MTK_FUNCTION(0, "GPIO50"),
+               MTK_FUNCTION(1, "I2S2_BCK"),
+               MTK_FUNCTION(3, "PCM_CLK0"),
+               MTK_FUNCTION(4, "DMIC_SCK1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(51, "I2S2_DATA_IN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 33),
+               MTK_FUNCTION(0, "GPIO51"),
+               MTK_FUNCTION(1, "I2S2_DATA_IN"),
+               MTK_FUNCTION(3, "PCM_RX"),
+               MTK_FUNCTION(4, "DMIC_SCK0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(52, "I2S2_LRCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 34),
+               MTK_FUNCTION(0, "GPIO52"),
+               MTK_FUNCTION(1, "I2S2_LRCK"),
+               MTK_FUNCTION(3, "PCM_SYNC"),
+               MTK_FUNCTION(4, "DMIC_DAT1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(53, "SPI0_CSN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 35),
+               MTK_FUNCTION(0, "GPIO53"),
+               MTK_FUNCTION(1, "SPI0_CS"),
+               MTK_FUNCTION(3, "SPDIF"),
+               MTK_FUNCTION(4, "ADC_CK"),
+               MTK_FUNCTION(5, "PWM1"),
+               MTK_FUNCTION(7, "DBG_MON_A[7]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(54, "SPI0_CK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 36),
+               MTK_FUNCTION(0, "GPIO54"),
+               MTK_FUNCTION(1, "SPI0_CK"),
+               MTK_FUNCTION(3, "SPDIF_IN1"),
+               MTK_FUNCTION(4, "ADC_DAT_IN"),
+               MTK_FUNCTION(7, "DBG_MON_A[10]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(55, "SPI0_MI"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 37),
+               MTK_FUNCTION(0, "GPIO55"),
+               MTK_FUNCTION(1, "SPI0_MI"),
+               MTK_FUNCTION(2, "SPI0_MO"),
+               MTK_FUNCTION(3, "MSDC1_WP"),
+               MTK_FUNCTION(4, "ADC_WS"),
+               MTK_FUNCTION(5, "PWM2"),
+               MTK_FUNCTION(7, "DBG_MON_A[8]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(56, "SPI0_MO"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 38),
+               MTK_FUNCTION(0, "GPIO56"),
+               MTK_FUNCTION(1, "SPI0_MO"),
+               MTK_FUNCTION(2, "SPI0_MI"),
+               MTK_FUNCTION(3, "SPDIF_IN0"),
+               MTK_FUNCTION(7, "DBG_MON_A[9]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(57, "SDA1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 39),
+               MTK_FUNCTION(0, "GPIO57"),
+               MTK_FUNCTION(1, "SDA1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(58, "SCL1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 40),
+               MTK_FUNCTION(0, "GPIO58"),
+               MTK_FUNCTION(1, "SCL1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(59, "RAMBUF_I_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO59"),
+               MTK_FUNCTION(1, "RAMBUF_I_CLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(60, "WB_RSTB"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 41),
+               MTK_FUNCTION(0, "GPIO60"),
+               MTK_FUNCTION(1, "WB_RSTB"),
+               MTK_FUNCTION(7, "DBG_MON_A[11]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(61, "F2W_DATA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 42),
+               MTK_FUNCTION(0, "GPIO61"),
+               MTK_FUNCTION(1, "F2W_DATA"),
+               MTK_FUNCTION(7, "DBG_MON_A[16]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(62, "F2W_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 43),
+               MTK_FUNCTION(0, "GPIO62"),
+               MTK_FUNCTION(1, "F2W_CK"),
+               MTK_FUNCTION(7, "DBG_MON_A[15]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(63, "WB_SCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 44),
+               MTK_FUNCTION(0, "GPIO63"),
+               MTK_FUNCTION(1, "WB_SCLK"),
+               MTK_FUNCTION(7, "DBG_MON_A[13]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(64, "WB_SDATA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 45),
+               MTK_FUNCTION(0, "GPIO64"),
+               MTK_FUNCTION(1, "WB_SDATA"),
+               MTK_FUNCTION(7, "DBG_MON_A[12]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(65, "WB_SEN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 46),
+               MTK_FUNCTION(0, "GPIO65"),
+               MTK_FUNCTION(1, "WB_SEN"),
+               MTK_FUNCTION(7, "DBG_MON_A[14]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(66, "WB_CRTL0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 47),
+               MTK_FUNCTION(0, "GPIO66"),
+               MTK_FUNCTION(1, "WB_CRTL0"),
+               MTK_FUNCTION(5, "DFD_NTRST_XI"),
+               MTK_FUNCTION(7, "DBG_MON_A[17]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(67, "WB_CRTL1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 48),
+               MTK_FUNCTION(0, "GPIO67"),
+               MTK_FUNCTION(1, "WB_CRTL1"),
+               MTK_FUNCTION(5, "DFD_TMS_XI"),
+               MTK_FUNCTION(7, "DBG_MON_A[18]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(68, "WB_CRTL2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 49),
+               MTK_FUNCTION(0, "GPIO68"),
+               MTK_FUNCTION(1, "WB_CRTL2"),
+               MTK_FUNCTION(5, "DFD_TCK_XI"),
+               MTK_FUNCTION(7, "DBG_MON_A[19]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(69, "WB_CRTL3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 50),
+               MTK_FUNCTION(0, "GPIO69"),
+               MTK_FUNCTION(1, "WB_CRTL3"),
+               MTK_FUNCTION(5, "DFD_TDI_XI"),
+               MTK_FUNCTION(7, "DBG_MON_A[20]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(70, "WB_CRTL4"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 51),
+               MTK_FUNCTION(0, "GPIO70"),
+               MTK_FUNCTION(1, "WB_CRTL4"),
+               MTK_FUNCTION(5, "DFD_TDO"),
+               MTK_FUNCTION(7, "DBG_MON_A[21]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(71, "WB_CRTL5"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 52),
+               MTK_FUNCTION(0, "GPIO71"),
+               MTK_FUNCTION(1, "WB_CRTL5"),
+               MTK_FUNCTION(7, "DBG_MON_A[22]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(72, "I2S0_DATA_IN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 53),
+               MTK_FUNCTION(0, "GPIO72"),
+               MTK_FUNCTION(1, "I2S0_DATA_IN"),
+               MTK_FUNCTION(3, "PCM_RX"),
+               MTK_FUNCTION(4, "PWM0"),
+               MTK_FUNCTION(5, "DISP_PWM"),
+               MTK_FUNCTION(6, "WCN_I2S_DI"),
+               MTK_FUNCTION(7, "DBG_MON_B[2]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(73, "I2S0_LRCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 54),
+               MTK_FUNCTION(0, "GPIO73"),
+               MTK_FUNCTION(1, "I2S0_LRCK"),
+               MTK_FUNCTION(3, "PCM_SYNC"),
+               MTK_FUNCTION(6, "WCN_I2S_LRCK"),
+               MTK_FUNCTION(7, "DBG_MON_B[5]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(74, "I2S0_BCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 55),
+               MTK_FUNCTION(0, "GPIO74"),
+               MTK_FUNCTION(1, "I2S0_BCK"),
+               MTK_FUNCTION(3, "PCM_CLK0"),
+               MTK_FUNCTION(6, "WCN_I2S_BCK"),
+               MTK_FUNCTION(7, "DBG_MON_B[4]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(75, "SDA0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 56),
+               MTK_FUNCTION(0, "GPIO75"),
+               MTK_FUNCTION(1, "SDA0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(76, "SCL0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 57),
+               MTK_FUNCTION(0, "GPIO76"),
+               MTK_FUNCTION(1, "SCL0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(77, "SDA2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 58),
+               MTK_FUNCTION(0, "GPIO77"),
+               MTK_FUNCTION(1, "SDA2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(78, "SCL2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 59),
+               MTK_FUNCTION(0, "GPIO78"),
+               MTK_FUNCTION(1, "SCL2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(79, "URXD0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 60),
+               MTK_FUNCTION(0, "GPIO79"),
+               MTK_FUNCTION(1, "URXD0"),
+               MTK_FUNCTION(2, "UTXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(80, "UTXD0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 61),
+               MTK_FUNCTION(0, "GPIO80"),
+               MTK_FUNCTION(1, "UTXD0"),
+               MTK_FUNCTION(2, "URXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(81, "URXD1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 62),
+               MTK_FUNCTION(0, "GPIO81"),
+               MTK_FUNCTION(1, "URXD1"),
+               MTK_FUNCTION(2, "UTXD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(82, "UTXD1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 63),
+               MTK_FUNCTION(0, "GPIO82"),
+               MTK_FUNCTION(1, "UTXD1"),
+               MTK_FUNCTION(2, "URXD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(83, "LCM_RST"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 64),
+               MTK_FUNCTION(0, "GPIO83"),
+               MTK_FUNCTION(1, "LCM_RST"),
+               MTK_FUNCTION(2, "VDAC_CK_XI"),
+               MTK_FUNCTION(7, "DBG_MON_B[1]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(84, "DSI_TE"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 65),
+               MTK_FUNCTION(0, "GPIO84"),
+               MTK_FUNCTION(1, "DSI_TE"),
+               MTK_FUNCTION(7, "DBG_MON_B[0]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(85, "MSDC2_CMD"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 66),
+               MTK_FUNCTION(0, "GPIO85"),
+               MTK_FUNCTION(1, "MSDC2_CMD"),
+               MTK_FUNCTION(2, "ANT_SEL0"),
+               MTK_FUNCTION(3, "SDA1"),
+               MTK_FUNCTION(6, "I2SOUT_BCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(86, "MSDC2_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 67),
+               MTK_FUNCTION(0, "GPIO86"),
+               MTK_FUNCTION(1, "MSDC2_CLK"),
+               MTK_FUNCTION(2, "ANT_SEL1"),
+               MTK_FUNCTION(3, "SCL1"),
+               MTK_FUNCTION(6, "I2SOUT_LRCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(87, "MSDC2_DAT0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 68),
+               MTK_FUNCTION(0, "GPIO87"),
+               MTK_FUNCTION(1, "MSDC2_DAT0"),
+               MTK_FUNCTION(2, "ANT_SEL2"),
+               MTK_FUNCTION(5, "UTXD0"),
+               MTK_FUNCTION(6, "I2SOUT_DATA_OUT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(88, "MSDC2_DAT1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 71),
+               MTK_FUNCTION(0, "GPIO88"),
+               MTK_FUNCTION(1, "MSDC2_DAT1"),
+               MTK_FUNCTION(2, "ANT_SEL3"),
+               MTK_FUNCTION(3, "PWM0"),
+               MTK_FUNCTION(5, "URXD0"),
+               MTK_FUNCTION(6, "PWM1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(89, "MSDC2_DAT2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 72),
+               MTK_FUNCTION(0, "GPIO89"),
+               MTK_FUNCTION(1, "MSDC2_DAT2"),
+               MTK_FUNCTION(2, "ANT_SEL4"),
+               MTK_FUNCTION(3, "SDA2"),
+               MTK_FUNCTION(5, "UTXD1"),
+               MTK_FUNCTION(6, "PWM2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(90, "MSDC2_DAT3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 73),
+               MTK_FUNCTION(0, "GPIO90"),
+               MTK_FUNCTION(1, "MSDC2_DAT3"),
+               MTK_FUNCTION(2, "ANT_SEL5"),
+               MTK_FUNCTION(3, "SCL2"),
+               MTK_FUNCTION(4, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(5, "URXD1"),
+               MTK_FUNCTION(6, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(91, "TDN3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI91"),
+               MTK_FUNCTION(1, "TDN3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(92, "TDP3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI92"),
+               MTK_FUNCTION(1, "TDP3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(93, "TDN2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI93"),
+               MTK_FUNCTION(1, "TDN2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(94, "TDP2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI94"),
+               MTK_FUNCTION(1, "TDP2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(95, "TCN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI95"),
+               MTK_FUNCTION(1, "TCN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(96, "TCP"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI96"),
+               MTK_FUNCTION(1, "TCP")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(97, "TDN1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI97"),
+               MTK_FUNCTION(1, "TDN1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(98, "TDP1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI98"),
+               MTK_FUNCTION(1, "TDP1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(99, "TDN0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI99"),
+               MTK_FUNCTION(1, "TDN0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(100, "TDP0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPI100"),
+               MTK_FUNCTION(1, "TDP0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(101, "SPI2_CSN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 74),
+               MTK_FUNCTION(0, "GPIO101"),
+               MTK_FUNCTION(1, "SPI2_CS"),
+               MTK_FUNCTION(3, "SCL3"),
+               MTK_FUNCTION(4, "KROW0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(102, "SPI2_MI"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 75),
+               MTK_FUNCTION(0, "GPIO102"),
+               MTK_FUNCTION(1, "SPI2_MI"),
+               MTK_FUNCTION(2, "SPI2_MO"),
+               MTK_FUNCTION(3, "SDA3"),
+               MTK_FUNCTION(4, "KROW1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(103, "SPI2_MO"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 76),
+               MTK_FUNCTION(0, "GPIO103"),
+               MTK_FUNCTION(1, "SPI2_MO"),
+               MTK_FUNCTION(2, "SPI2_MI"),
+               MTK_FUNCTION(3, "SCL3"),
+               MTK_FUNCTION(4, "KROW2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(104, "SPI2_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 77),
+               MTK_FUNCTION(0, "GPIO104"),
+               MTK_FUNCTION(1, "SPI2_CK"),
+               MTK_FUNCTION(3, "SDA3"),
+               MTK_FUNCTION(4, "KROW3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(105, "MSDC1_CMD"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 78),
+               MTK_FUNCTION(0, "GPIO105"),
+               MTK_FUNCTION(1, "MSDC1_CMD"),
+               MTK_FUNCTION(2, "ANT_SEL0"),
+               MTK_FUNCTION(3, "SDA1"),
+               MTK_FUNCTION(6, "I2SOUT_BCK"),
+               MTK_FUNCTION(7, "DBG_MON_B[27]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(106, "MSDC1_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 79),
+               MTK_FUNCTION(0, "GPIO106"),
+               MTK_FUNCTION(1, "MSDC1_CLK"),
+               MTK_FUNCTION(2, "ANT_SEL1"),
+               MTK_FUNCTION(3, "SCL1"),
+               MTK_FUNCTION(6, "I2SOUT_LRCK"),
+               MTK_FUNCTION(7, "DBG_MON_B[28]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(107, "MSDC1_DAT0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 80),
+               MTK_FUNCTION(0, "GPIO107"),
+               MTK_FUNCTION(1, "MSDC1_DAT0"),
+               MTK_FUNCTION(2, "ANT_SEL2"),
+               MTK_FUNCTION(5, "UTXD0"),
+               MTK_FUNCTION(6, "I2SOUT_DATA_OUT"),
+               MTK_FUNCTION(7, "DBG_MON_B[26]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(108, "MSDC1_DAT1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 81),
+               MTK_FUNCTION(0, "GPIO108"),
+               MTK_FUNCTION(1, "MSDC1_DAT1"),
+               MTK_FUNCTION(2, "ANT_SEL3"),
+               MTK_FUNCTION(3, "PWM0"),
+               MTK_FUNCTION(5, "URXD0"),
+               MTK_FUNCTION(6, "PWM1"),
+               MTK_FUNCTION(7, "DBG_MON_B[25]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(109, "MSDC1_DAT2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 82),
+               MTK_FUNCTION(0, "GPIO109"),
+               MTK_FUNCTION(1, "MSDC1_DAT2"),
+               MTK_FUNCTION(2, "ANT_SEL4"),
+               MTK_FUNCTION(3, "SDA2"),
+               MTK_FUNCTION(5, "UTXD1"),
+               MTK_FUNCTION(6, "PWM2"),
+               MTK_FUNCTION(7, "DBG_MON_B[24]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(110, "MSDC1_DAT3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 83),
+               MTK_FUNCTION(0, "GPIO110"),
+               MTK_FUNCTION(1, "MSDC1_DAT3"),
+               MTK_FUNCTION(2, "ANT_SEL5"),
+               MTK_FUNCTION(3, "SCL2"),
+               MTK_FUNCTION(4, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(5, "URXD1"),
+               MTK_FUNCTION(6, "PWM3"),
+               MTK_FUNCTION(7, "DBG_MON_B[23]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(111, "MSDC0_DAT7"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 84),
+               MTK_FUNCTION(0, "GPIO111"),
+               MTK_FUNCTION(1, "MSDC0_DAT7"),
+               MTK_FUNCTION(4, "NLD7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(112, "MSDC0_DAT6"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 85),
+               MTK_FUNCTION(0, "GPIO112"),
+               MTK_FUNCTION(1, "MSDC0_DAT6"),
+               MTK_FUNCTION(4, "NLD6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(113, "MSDC0_DAT5"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 86),
+               MTK_FUNCTION(0, "GPIO113"),
+               MTK_FUNCTION(1, "MSDC0_DAT5"),
+               MTK_FUNCTION(4, "NLD5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(114, "MSDC0_DAT4"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 87),
+               MTK_FUNCTION(0, "GPIO114"),
+               MTK_FUNCTION(1, "MSDC0_DAT4"),
+               MTK_FUNCTION(4, "NLD4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(115, "MSDC0_RSTB"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 88),
+               MTK_FUNCTION(0, "GPIO115"),
+               MTK_FUNCTION(1, "MSDC0_RSTB"),
+               MTK_FUNCTION(4, "NLD8")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(116, "MSDC0_CMD"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 89),
+               MTK_FUNCTION(0, "GPIO116"),
+               MTK_FUNCTION(1, "MSDC0_CMD"),
+               MTK_FUNCTION(4, "NALE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(117, "MSDC0_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 90),
+               MTK_FUNCTION(0, "GPIO117"),
+               MTK_FUNCTION(1, "MSDC0_CLK"),
+               MTK_FUNCTION(4, "NWEB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(118, "MSDC0_DAT3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 91),
+               MTK_FUNCTION(0, "GPIO118"),
+               MTK_FUNCTION(1, "MSDC0_DAT3"),
+               MTK_FUNCTION(4, "NLD3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(119, "MSDC0_DAT2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 92),
+               MTK_FUNCTION(0, "GPIO119"),
+               MTK_FUNCTION(1, "MSDC0_DAT2"),
+               MTK_FUNCTION(4, "NLD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(120, "MSDC0_DAT1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 93),
+               MTK_FUNCTION(0, "GPIO120"),
+               MTK_FUNCTION(1, "MSDC0_DAT1"),
+               MTK_FUNCTION(4, "NLD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(121, "MSDC0_DAT0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 94),
+               MTK_FUNCTION(0, "GPIO121"),
+               MTK_FUNCTION(1, "MSDC0_DAT0"),
+               MTK_FUNCTION(4, "NLD0"),
+               MTK_FUNCTION(5, "WATCHDOG")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(122, "CEC"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 95),
+               MTK_FUNCTION(0, "GPIO122"),
+               MTK_FUNCTION(1, "CEC"),
+               MTK_FUNCTION(4, "SDA2"),
+               MTK_FUNCTION(5, "URXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(123, "HTPLG"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 96),
+               MTK_FUNCTION(0, "GPIO123"),
+               MTK_FUNCTION(1, "HTPLG"),
+               MTK_FUNCTION(4, "SCL2"),
+               MTK_FUNCTION(5, "UTXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(124, "HDMISCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 97),
+               MTK_FUNCTION(0, "GPIO124"),
+               MTK_FUNCTION(1, "HDMISCK"),
+               MTK_FUNCTION(4, "SDA1"),
+               MTK_FUNCTION(5, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(125, "HDMISD"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 98),
+               MTK_FUNCTION(0, "GPIO125"),
+               MTK_FUNCTION(1, "HDMISD"),
+               MTK_FUNCTION(4, "SCL1"),
+               MTK_FUNCTION(5, "PWM4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(126, "I2S0_MCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 99),
+               MTK_FUNCTION(0, "GPIO126"),
+               MTK_FUNCTION(1, "I2S0_MCLK"),
+               MTK_FUNCTION(6, "WCN_I2S_MCLK"),
+               MTK_FUNCTION(7, "DBG_MON_B[6]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(127, "RAMBUF_IDATA0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO127"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(128, "RAMBUF_IDATA1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO128"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(129, "RAMBUF_IDATA2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO129"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(130, "RAMBUF_IDATA3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO130"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(131, "RAMBUF_IDATA4"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO131"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(132, "RAMBUF_IDATA5"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO132"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(133, "RAMBUF_IDATA6"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO133"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(134, "RAMBUF_IDATA7"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO134"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(135, "RAMBUF_IDATA8"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO135"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA8")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(136, "RAMBUF_IDATA9"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO136"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA9")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(137, "RAMBUF_IDATA10"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO137"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA10")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(138, "RAMBUF_IDATA11"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO138"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA11")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(139, "RAMBUF_IDATA12"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO139"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA12")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(140, "RAMBUF_IDATA13"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO140"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA13")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(141, "RAMBUF_IDATA14"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO141"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA14")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(142, "RAMBUF_IDATA15"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO142"),
+               MTK_FUNCTION(1, "RAMBUF_IDATA15")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(143, "RAMBUF_ODATA0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO143"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(144, "RAMBUF_ODATA1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO144"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(145, "RAMBUF_ODATA2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO145"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(146, "RAMBUF_ODATA3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO146"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(147, "RAMBUF_ODATA4"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO147"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(148, "RAMBUF_ODATA5"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO148"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(149, "RAMBUF_ODATA6"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO149"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(150, "RAMBUF_ODATA7"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO150"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(151, "RAMBUF_ODATA8"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO151"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA8")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(152, "RAMBUF_ODATA9"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO152"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA9")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(153, "RAMBUF_ODATA10"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO153"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA10")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(154, "RAMBUF_ODATA11"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO154"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA11")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(155, "RAMBUF_ODATA12"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO155"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA12")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(156, "RAMBUF_ODATA13"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO156"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA13")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(157, "RAMBUF_ODATA14"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO157"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA14")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(158, "RAMBUF_ODATA15"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO158"),
+               MTK_FUNCTION(1, "RAMBUF_ODATA15")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(159, "RAMBUF_BE0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO159"),
+               MTK_FUNCTION(1, "RAMBUF_BE0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(160, "RAMBUF_BE1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO160"),
+               MTK_FUNCTION(1, "RAMBUF_BE1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(161, "AP2PT_INT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO161"),
+               MTK_FUNCTION(1, "AP2PT_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(162, "AP2PT_INT_CLR"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO162"),
+               MTK_FUNCTION(1, "AP2PT_INT_CLR")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(163, "PT2AP_INT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO163"),
+               MTK_FUNCTION(1, "PT2AP_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(164, "PT2AP_INT_CLR"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO164"),
+               MTK_FUNCTION(1, "PT2AP_INT_CLR")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(165, "AP2UP_INT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO165"),
+               MTK_FUNCTION(1, "AP2UP_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(166, "AP2UP_INT_CLR"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO166"),
+               MTK_FUNCTION(1, "AP2UP_INT_CLR")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(167, "UP2AP_INT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO167"),
+               MTK_FUNCTION(1, "UP2AP_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(168, "UP2AP_INT_CLR"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO168"),
+               MTK_FUNCTION(1, "UP2AP_INT_CLR")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(169, "RAMBUF_ADDR0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO169"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(170, "RAMBUF_ADDR1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO170"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(171, "RAMBUF_ADDR2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO171"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(172, "RAMBUF_ADDR3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO172"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(173, "RAMBUF_ADDR4"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO173"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(174, "RAMBUF_ADDR5"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO174"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(175, "RAMBUF_ADDR6"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO175"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(176, "RAMBUF_ADDR7"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO176"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(177, "RAMBUF_ADDR8"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO177"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR8")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(178, "RAMBUF_ADDR9"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO178"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR9")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(179, "RAMBUF_ADDR10"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO179"),
+               MTK_FUNCTION(1, "RAMBUF_ADDR10")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(180, "RAMBUF_RW"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO180"),
+               MTK_FUNCTION(1, "RAMBUF_RW")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(181, "RAMBUF_LAST"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO181"),
+               MTK_FUNCTION(1, "RAMBUF_LAST")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(182, "RAMBUF_HP"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO182"),
+               MTK_FUNCTION(1, "RAMBUF_HP")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(183, "RAMBUF_REQ"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO183"),
+               MTK_FUNCTION(1, "RAMBUF_REQ")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(184, "RAMBUF_ALE"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO184"),
+               MTK_FUNCTION(1, "RAMBUF_ALE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(185, "RAMBUF_DLE"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO185"),
+               MTK_FUNCTION(1, "RAMBUF_DLE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(186, "RAMBUF_WDLE"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO186"),
+               MTK_FUNCTION(1, "RAMBUF_WDLE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(187, "RAMBUF_O_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO187"),
+               MTK_FUNCTION(1, "RAMBUF_O_CLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(188, "I2S2_MCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 100),
+               MTK_FUNCTION(0, "GPIO188"),
+               MTK_FUNCTION(1, "I2S2_MCLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(189, "I2S3_DATA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 101),
+               MTK_FUNCTION(0, "GPIO189"),
+               MTK_FUNCTION(2, "I2S3_DATA_BYPS"),
+               MTK_FUNCTION(3, "PCM_TX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(190, "I2S3_DATA_IN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 102),
+               MTK_FUNCTION(0, "GPIO190"),
+               MTK_FUNCTION(1, "I2S3_DATA_IN"),
+               MTK_FUNCTION(3, "PCM_RX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(191, "I2S3_BCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 103),
+               MTK_FUNCTION(0, "GPIO191"),
+               MTK_FUNCTION(1, "I2S3_BCK"),
+               MTK_FUNCTION(3, "PCM_CLK0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(192, "I2S3_LRCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 104),
+               MTK_FUNCTION(0, "GPIO192"),
+               MTK_FUNCTION(1, "I2S3_LRCK"),
+               MTK_FUNCTION(3, "PCM_SYNC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(193, "I2S3_MCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 105),
+               MTK_FUNCTION(0, "GPIO193"),
+               MTK_FUNCTION(1, "I2S3_MCLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(194, "I2S4_DATA"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 106),
+               MTK_FUNCTION(0, "GPIO194"),
+               MTK_FUNCTION(1, "I2S4_DATA"),
+               MTK_FUNCTION(2, "I2S4_DATA_BYPS"),
+               MTK_FUNCTION(3, "PCM_TX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(195, "I2S4_DATA_IN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 107),
+               MTK_FUNCTION(0, "GPIO195"),
+               MTK_FUNCTION(1, "I2S4_DATA_IN"),
+               MTK_FUNCTION(3, "PCM_RX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(196, "I2S4_BCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 108),
+               MTK_FUNCTION(0, "GPIO196"),
+               MTK_FUNCTION(1, "I2S4_BCK"),
+               MTK_FUNCTION(3, "PCM_CLK0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(197, "I2S4_LRCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 109),
+               MTK_FUNCTION(0, "GPIO197"),
+               MTK_FUNCTION(1, "I2S4_LRCK"),
+               MTK_FUNCTION(3, "PCM_SYNC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(198, "I2S4_MCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 110),
+               MTK_FUNCTION(0, "GPIO198"),
+               MTK_FUNCTION(1, "I2S4_MCLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(199, "SPI1_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 111),
+               MTK_FUNCTION(0, "GPIO199"),
+               MTK_FUNCTION(1, "SPI1_CK"),
+               MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(4, "KCOL3"),
+               MTK_FUNCTION(7, "DBG_MON_B[15]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(200, "SPDIF_OUT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 112),
+               MTK_FUNCTION(0, "GPIO200"),
+               MTK_FUNCTION(1, "SPDIF_OUT"),
+               MTK_FUNCTION(5, "G1_TXD3"),
+               MTK_FUNCTION(6, "URXD2"),
+               MTK_FUNCTION(7, "DBG_MON_B[16]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(201, "SPDIF_IN0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 113),
+               MTK_FUNCTION(0, "GPIO201"),
+               MTK_FUNCTION(1, "SPDIF_IN0"),
+               MTK_FUNCTION(5, "G1_TXEN"),
+               MTK_FUNCTION(6, "UTXD2"),
+               MTK_FUNCTION(7, "DBG_MON_B[17]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(202, "SPDIF_IN1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 114),
+               MTK_FUNCTION(0, "GPIO202"),
+               MTK_FUNCTION(1, "SPDIF_IN1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(203, "PWM0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 115),
+               MTK_FUNCTION(0, "GPIO203"),
+               MTK_FUNCTION(1, "PWM0"),
+               MTK_FUNCTION(2, "DISP_PWM"),
+               MTK_FUNCTION(5, "G1_TXD2"),
+               MTK_FUNCTION(7, "DBG_MON_B[18]"),
+               MTK_FUNCTION(9, "I2S2_DATA")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(204, "PWM1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 116),
+               MTK_FUNCTION(0, "GPIO204"),
+               MTK_FUNCTION(1, "PWM1"),
+               MTK_FUNCTION(2, "CLKM3"),
+               MTK_FUNCTION(5, "G1_TXD1"),
+               MTK_FUNCTION(7, "DBG_MON_B[19]"),
+               MTK_FUNCTION(9, "I2S3_DATA")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(205, "PWM2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 117),
+               MTK_FUNCTION(0, "GPIO205"),
+               MTK_FUNCTION(1, "PWM2"),
+               MTK_FUNCTION(2, "CLKM2"),
+               MTK_FUNCTION(5, "G1_TXD0"),
+               MTK_FUNCTION(7, "DBG_MON_B[20]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(206, "PWM3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 118),
+               MTK_FUNCTION(0, "GPIO206"),
+               MTK_FUNCTION(1, "PWM3"),
+               MTK_FUNCTION(2, "CLKM1"),
+               MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(5, "G1_TXC"),
+               MTK_FUNCTION(7, "DBG_MON_B[21]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(207, "PWM4"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 119),
+               MTK_FUNCTION(0, "GPIO207"),
+               MTK_FUNCTION(1, "PWM4"),
+               MTK_FUNCTION(2, "CLKM0"),
+               MTK_FUNCTION(3, "EXT_FRAME_SYNC"),
+               MTK_FUNCTION(5, "G1_RXC"),
+               MTK_FUNCTION(7, "DBG_MON_B[22]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(208, "AUD_EXT_CK1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 120),
+               MTK_FUNCTION(0, "GPIO208"),
+               MTK_FUNCTION(1, "AUD_EXT_CK1"),
+               MTK_FUNCTION(2, "PWM0"),
+               MTK_FUNCTION(4, "ANT_SEL5"),
+               MTK_FUNCTION(5, "DISP_PWM"),
+               MTK_FUNCTION(7, "DBG_MON_A[31]"),
+               MTK_FUNCTION(11, "PCIE0_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(209, "AUD_EXT_CK2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 121),
+               MTK_FUNCTION(0, "GPIO209"),
+               MTK_FUNCTION(1, "AUD_EXT_CK2"),
+               MTK_FUNCTION(2, "MSDC1_WP"),
+               MTK_FUNCTION(5, "PWM1"),
+               MTK_FUNCTION(7, "DBG_MON_A[32]"),
+               MTK_FUNCTION(11, "PCIE1_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(210, "AUD_CLOCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO210"),
+               MTK_FUNCTION(1, "AUD_CLOCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(211, "DVP_RESET"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO211"),
+               MTK_FUNCTION(1, "DVP_RESET")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(212, "DVP_CLOCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO212"),
+               MTK_FUNCTION(1, "DVP_CLOCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(213, "DVP_CS"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO213"),
+               MTK_FUNCTION(1, "DVP_CS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(214, "DVP_CK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO214"),
+               MTK_FUNCTION(1, "DVP_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(215, "DVP_DI"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO215"),
+               MTK_FUNCTION(1, "DVP_DI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(216, "DVP_DO"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO216"),
+               MTK_FUNCTION(1, "DVP_DO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(217, "AP_CS"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO217"),
+               MTK_FUNCTION(1, "AP_CS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(218, "AP_CK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO218"),
+               MTK_FUNCTION(1, "AP_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(219, "AP_DI"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO219"),
+               MTK_FUNCTION(1, "AP_DI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(220, "AP_DO"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO220"),
+               MTK_FUNCTION(1, "AP_DO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(221, "DVD_BCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO221"),
+               MTK_FUNCTION(1, "DVD_BCLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(222, "T8032_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO222"),
+               MTK_FUNCTION(1, "T8032_CLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(223, "AP_BCLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO223"),
+               MTK_FUNCTION(1, "AP_BCLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(224, "HOST_CS"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO224"),
+               MTK_FUNCTION(1, "HOST_CS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(225, "HOST_CK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO225"),
+               MTK_FUNCTION(1, "HOST_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(226, "HOST_DO0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO226"),
+               MTK_FUNCTION(1, "HOST_DO0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(227, "HOST_DO1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO227"),
+               MTK_FUNCTION(1, "HOST_DO1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(228, "SLV_CS"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO228"),
+               MTK_FUNCTION(1, "SLV_CS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(229, "SLV_CK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO229"),
+               MTK_FUNCTION(1, "SLV_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(230, "SLV_DI0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO230"),
+               MTK_FUNCTION(1, "SLV_DI0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(231, "SLV_DI1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO231"),
+               MTK_FUNCTION(1, "SLV_DI1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(232, "AP2DSP_INT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO232"),
+               MTK_FUNCTION(1, "AP2DSP_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(233, "AP2DSP_INT_CLR"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO233"),
+               MTK_FUNCTION(1, "AP2DSP_INT_CLR")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(234, "DSP2AP_INT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO234"),
+               MTK_FUNCTION(1, "DSP2AP_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(235, "DSP2AP_INT_CLR"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO235"),
+               MTK_FUNCTION(1, "DSP2AP_INT_CLR")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(236, "EXT_SDIO3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 122),
+               MTK_FUNCTION(0, "GPIO236"),
+               MTK_FUNCTION(1, "EXT_SDIO3"),
+               MTK_FUNCTION(2, "IDDIG"),
+               MTK_FUNCTION(7, "DBG_MON_A[1]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(237, "EXT_SDIO2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 123),
+               MTK_FUNCTION(0, "GPIO237"),
+               MTK_FUNCTION(1, "EXT_SDIO2"),
+               MTK_FUNCTION(2, "DRV_VBUS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(238, "EXT_SDIO1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 124),
+               MTK_FUNCTION(0, "GPIO238"),
+               MTK_FUNCTION(1, "EXT_SDIO1"),
+               MTK_FUNCTION(2, "IDDIG_P1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(239, "EXT_SDIO0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 125),
+               MTK_FUNCTION(0, "GPIO239"),
+               MTK_FUNCTION(1, "EXT_SDIO0"),
+               MTK_FUNCTION(2, "DRV_VBUS_P1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(240, "EXT_XCS"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 126),
+               MTK_FUNCTION(0, "GPIO240"),
+               MTK_FUNCTION(1, "EXT_XCS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(241, "EXT_SCK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 127),
+               MTK_FUNCTION(0, "GPIO241"),
+               MTK_FUNCTION(1, "EXT_SCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(242, "URTS2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 128),
+               MTK_FUNCTION(0, "GPIO242"),
+               MTK_FUNCTION(1, "URTS2"),
+               MTK_FUNCTION(2, "UTXD3"),
+               MTK_FUNCTION(3, "URXD3"),
+               MTK_FUNCTION(4, "SCL1"),
+               MTK_FUNCTION(7, "DBG_MON_B[32]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(243, "UCTS2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 129),
+               MTK_FUNCTION(0, "GPIO243"),
+               MTK_FUNCTION(1, "UCTS2"),
+               MTK_FUNCTION(2, "URXD3"),
+               MTK_FUNCTION(3, "UTXD3"),
+               MTK_FUNCTION(4, "SDA1"),
+               MTK_FUNCTION(7, "DBG_MON_A[6]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(244, "HDMI_SDA_RX"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 130),
+               MTK_FUNCTION(0, "GPIO244"),
+               MTK_FUNCTION(1, "HDMI_SDA_RX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(245, "HDMI_SCL_RX"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 131),
+               MTK_FUNCTION(0, "GPIO245"),
+               MTK_FUNCTION(1, "HDMI_SCL_RX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(246, "MHL_SENCE"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 132),
+               MTK_FUNCTION(0, "GPIO246")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(247, "HDMI_HPD_CBUS_RX"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 69),
+               MTK_FUNCTION(0, "GPIO247"),
+               MTK_FUNCTION(1, "HDMI_HPD_RX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(248, "HDMI_TESTOUTP_RX"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 133),
+               MTK_FUNCTION(0, "GPIO248"),
+               MTK_FUNCTION(1, "HDMI_TESTOUTP_RX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(249, "MSDC0E_RSTB"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 134),
+               MTK_FUNCTION(0, "GPIO249"),
+               MTK_FUNCTION(1, "MSDC0E_RSTB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(250, "MSDC0E_DAT7"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 135),
+               MTK_FUNCTION(0, "GPIO250"),
+               MTK_FUNCTION(1, "MSDC3_DAT7"),
+               MTK_FUNCTION(6, "PCIE0_CLKREQ_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(251, "MSDC0E_DAT6"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 136),
+               MTK_FUNCTION(0, "GPIO251"),
+               MTK_FUNCTION(1, "MSDC3_DAT6"),
+               MTK_FUNCTION(6, "PCIE0_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(252, "MSDC0E_DAT5"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 137),
+               MTK_FUNCTION(0, "GPIO252"),
+               MTK_FUNCTION(1, "MSDC3_DAT5"),
+               MTK_FUNCTION(6, "PCIE1_CLKREQ_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(253, "MSDC0E_DAT4"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 138),
+               MTK_FUNCTION(0, "GPIO253"),
+               MTK_FUNCTION(1, "MSDC3_DAT4"),
+               MTK_FUNCTION(6, "PCIE1_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(254, "MSDC0E_DAT3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 139),
+               MTK_FUNCTION(0, "GPIO254"),
+               MTK_FUNCTION(1, "MSDC3_DAT3"),
+               MTK_FUNCTION(6, "PCIE2_CLKREQ_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(255, "MSDC0E_DAT2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 140),
+               MTK_FUNCTION(0, "GPIO255"),
+               MTK_FUNCTION(1, "MSDC3_DAT2"),
+               MTK_FUNCTION(6, "PCIE2_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(256, "MSDC0E_DAT1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 141),
+               MTK_FUNCTION(0, "GPIO256"),
+               MTK_FUNCTION(1, "MSDC3_DAT1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(257, "MSDC0E_DAT0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 142),
+               MTK_FUNCTION(0, "GPIO257"),
+               MTK_FUNCTION(1, "MSDC3_DAT0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(258, "MSDC0E_CMD"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 143),
+               MTK_FUNCTION(0, "GPIO258"),
+               MTK_FUNCTION(1, "MSDC3_CMD")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(259, "MSDC0E_CLK"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 144),
+               MTK_FUNCTION(0, "GPIO259"),
+               MTK_FUNCTION(1, "MSDC3_CLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(260, "MSDC0E_DSL"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 145),
+               MTK_FUNCTION(0, "GPIO260"),
+               MTK_FUNCTION(1, "MSDC3_DSL")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(261, "MSDC1_INS"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 146),
+               MTK_FUNCTION(0, "GPIO261"),
+               MTK_FUNCTION(1, "MSDC1_INS"),
+               MTK_FUNCTION(7, "DBG_MON_B[29]")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(262, "G2_TXEN"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 8),
+               MTK_FUNCTION(0, "GPIO262"),
+               MTK_FUNCTION(1, "G2_TXEN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(263, "G2_TXD3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 9),
+               MTK_FUNCTION(0, "GPIO263"),
+               MTK_FUNCTION(1, "G2_TXD3"),
+               MTK_FUNCTION(6, "ANT_SEL5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(264, "G2_TXD2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 10),
+               MTK_FUNCTION(0, "GPIO264"),
+               MTK_FUNCTION(1, "G2_TXD2"),
+               MTK_FUNCTION(6, "ANT_SEL4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(265, "G2_TXD1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 11),
+               MTK_FUNCTION(0, "GPIO265"),
+               MTK_FUNCTION(1, "G2_TXD1"),
+               MTK_FUNCTION(6, "ANT_SEL3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(266, "G2_TXD0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO266"),
+               MTK_FUNCTION(1, "G2_TXD0"),
+               MTK_FUNCTION(6, "ANT_SEL2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(267, "G2_TXC"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO267"),
+               MTK_FUNCTION(1, "G2_TXC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(268, "G2_RXC"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO268"),
+               MTK_FUNCTION(1, "G2_RXC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(269, "G2_RXD0"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO269"),
+               MTK_FUNCTION(1, "G2_RXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(270, "G2_RXD1"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO270"),
+               MTK_FUNCTION(1, "G2_RXD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(271, "G2_RXD2"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO271"),
+               MTK_FUNCTION(1, "G2_RXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(272, "G2_RXD3"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO272"),
+               MTK_FUNCTION(1, "G2_RXD3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(273, "ESW_INT"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 168),
+               MTK_FUNCTION(0, "GPIO273"),
+               MTK_FUNCTION(1, "ESW_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(274, "G2_RXDV"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO274"),
+               MTK_FUNCTION(1, "G2_RXDV")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(275, "MDC"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO275"),
+               MTK_FUNCTION(1, "MDC"),
+               MTK_FUNCTION(6, "ANT_SEL0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(276, "MDIO"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO276"),
+               MTK_FUNCTION(1, "MDIO"),
+               MTK_FUNCTION(6, "ANT_SEL1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(277, "ESW_RST"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO277"),
+               MTK_FUNCTION(1, "ESW_RST")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(278, "JTAG_RESET"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(0, 147),
+               MTK_FUNCTION(0, "GPIO278"),
+               MTK_FUNCTION(1, "JTAG_RESET")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(279, "USB3_RES_BOND"),
+               NULL, "mt2701",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO279"),
+               MTK_FUNCTION(1, "USB3_RES_BOND")
+       ),
+};
+
+#endif /* __PINCTRL_MTK_MT2701_H */
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt7623.h
new file mode 100644 (file)
index 0000000..3472a76
--- /dev/null
@@ -0,0 +1,1936 @@
+/*
+ * Copyright (c) 2016 John Crispin <blogic@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PINCTRL_MTK_MT7623_H
+#define __PINCTRL_MTK_MT7623_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-mtk-common.h"
+
+static const struct mtk_desc_pin mtk_pins_mt7623[] = {
+       MTK_PIN(
+               PINCTRL_PIN(0, "PWRAP_SPI0_MI"),
+               "J20", "mt7623",
+               MTK_EINT_FUNCTION(0, 148),
+               MTK_FUNCTION(0, "GPIO0"),
+               MTK_FUNCTION(1, "PWRAP_SPIDO"),
+               MTK_FUNCTION(2, "PWRAP_SPIDI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(1, "PWRAP_SPI0_MO"),
+               "D10", "mt7623",
+               MTK_EINT_FUNCTION(0, 149),
+               MTK_FUNCTION(0, "GPIO1"),
+               MTK_FUNCTION(1, "PWRAP_SPIDI"),
+               MTK_FUNCTION(2, "PWRAP_SPIDO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(2, "PWRAP_INT"),
+               "E11", "mt7623",
+               MTK_EINT_FUNCTION(0, 150),
+               MTK_FUNCTION(0, "GPIO2"),
+               MTK_FUNCTION(1, "PWRAP_INT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(3, "PWRAP_SPI0_CK"),
+               "H12", "mt7623",
+               MTK_EINT_FUNCTION(0, 151),
+               MTK_FUNCTION(0, "GPIO3"),
+               MTK_FUNCTION(1, "PWRAP_SPICK_I")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(4, "PWRAP_SPI0_CSN"),
+               "E12", "mt7623",
+               MTK_EINT_FUNCTION(0, 152),
+               MTK_FUNCTION(0, "GPIO4"),
+               MTK_FUNCTION(1, "PWRAP_SPICS_B_I")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(5, "PWRAP_SPI0_CK2"),
+               "H11", "mt7623",
+               MTK_EINT_FUNCTION(0, 155),
+               MTK_FUNCTION(0, "GPIO5"),
+               MTK_FUNCTION(1, "PWRAP_SPICK2_I")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(6, "PWRAP_SPI0_CSN2"),
+               "G11", "mt7623",
+               MTK_EINT_FUNCTION(0, 156),
+               MTK_FUNCTION(0, "GPIO6"),
+               MTK_FUNCTION(1, "PWRAP_SPICS2_B_I")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(7, "SPI1_CSN"),
+               "G19", "mt7623",
+               MTK_EINT_FUNCTION(0, 153),
+               MTK_FUNCTION(0, "GPIO7"),
+               MTK_FUNCTION(1, "SPI1_CS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(8, "SPI1_MI"),
+               "F19", "mt7623",
+               MTK_EINT_FUNCTION(0, 154),
+               MTK_FUNCTION(0, "GPIO8"),
+               MTK_FUNCTION(1, "SPI1_MI"),
+               MTK_FUNCTION(2, "SPI1_MO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(9, "SPI1_MO"),
+               "G20", "mt7623",
+               MTK_EINT_FUNCTION(0, 157),
+               MTK_FUNCTION(0, "GPIO9"),
+               MTK_FUNCTION(1, "SPI1_MO"),
+               MTK_FUNCTION(2, "SPI1_MI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(10, "RTC32K_CK"),
+               "A13", "mt7623",
+               MTK_EINT_FUNCTION(0, 158),
+               MTK_FUNCTION(0, "GPIO10"),
+               MTK_FUNCTION(1, "RTC32K_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(11, "WATCHDOG"),
+               "D14", "mt7623",
+               MTK_EINT_FUNCTION(0, 159),
+               MTK_FUNCTION(0, "GPIO11"),
+               MTK_FUNCTION(1, "WATCHDOG")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(12, "SRCLKENA"),
+               "C13", "mt7623",
+               MTK_EINT_FUNCTION(0, 169),
+               MTK_FUNCTION(0, "GPIO12"),
+               MTK_FUNCTION(1, "SRCLKENA")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(13, "SRCLKENAI"),
+               "B13", "mt7623",
+               MTK_EINT_FUNCTION(0, 161),
+               MTK_FUNCTION(0, "GPIO13"),
+               MTK_FUNCTION(1, "SRCLKENAI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(14, "GPIO14"),
+               "E18", "mt7623",
+               MTK_EINT_FUNCTION(0, 162),
+               MTK_FUNCTION(0, "GPIO14"),
+               MTK_FUNCTION(1, "URXD2"),
+               MTK_FUNCTION(2, "UTXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(15, "GPIO15"),
+               "E17", "mt7623",
+               MTK_EINT_FUNCTION(0, 163),
+               MTK_FUNCTION(0, "GPIO15"),
+               MTK_FUNCTION(1, "UTXD2"),
+               MTK_FUNCTION(2, "URXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(16, "GPIO16"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO16")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(17, "GPIO17"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO17")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(18, "PCM_CLK"),
+               "C19", "mt7623",
+               MTK_EINT_FUNCTION(0, 166),
+               MTK_FUNCTION(0, "GPIO18"),
+               MTK_FUNCTION(1, "PCM_CLK0"),
+               MTK_FUNCTION(6, "AP_PCM_CLKO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(19, "PCM_SYNC"),
+               "D19", "mt7623",
+               MTK_EINT_FUNCTION(0, 167),
+               MTK_FUNCTION(0, "GPIO19"),
+               MTK_FUNCTION(1, "PCM_SYNC"),
+               MTK_FUNCTION(6, "AP_PCM_SYNC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(20, "PCM_RX"),
+               "D18", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO20"),
+               MTK_FUNCTION(1, "PCM_RX"),
+               MTK_FUNCTION(4, "PCM_TX"),
+               MTK_FUNCTION(6, "AP_PCM_RX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(21, "PCM_TX"),
+               "C18", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO21"),
+               MTK_FUNCTION(1, "PCM_TX"),
+               MTK_FUNCTION(4, "PCM_RX"),
+               MTK_FUNCTION(6, "AP_PCM_TX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(22, "EINT0"),
+               "H15", "mt7623",
+               MTK_EINT_FUNCTION(0, 0),
+               MTK_FUNCTION(0, "GPIO22"),
+               MTK_FUNCTION(1, "UCTS0"),
+               MTK_FUNCTION(2, "PCIE0_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(23, "EINT1"),
+               "J16", "mt7623",
+               MTK_EINT_FUNCTION(0, 1),
+               MTK_FUNCTION(0, "GPIO23"),
+               MTK_FUNCTION(1, "URTS0"),
+               MTK_FUNCTION(2, "PCIE1_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(24, "EINT2"),
+               "H16", "mt7623",
+               MTK_EINT_FUNCTION(0, 2),
+               MTK_FUNCTION(0, "GPIO24"),
+               MTK_FUNCTION(1, "UCTS1"),
+               MTK_FUNCTION(2, "PCIE2_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(25, "EINT3"),
+               "K15", "mt7623",
+               MTK_EINT_FUNCTION(0, 3),
+               MTK_FUNCTION(0, "GPIO25"),
+               MTK_FUNCTION(1, "URTS1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(26, "EINT4"),
+               "G15", "mt7623",
+               MTK_EINT_FUNCTION(0, 4),
+               MTK_FUNCTION(0, "GPIO26"),
+               MTK_FUNCTION(1, "UCTS3"),
+               MTK_FUNCTION(6, "PCIE2_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(27, "EINT5"),
+               "F15", "mt7623",
+               MTK_EINT_FUNCTION(0, 5),
+               MTK_FUNCTION(0, "GPIO27"),
+               MTK_FUNCTION(1, "URTS3"),
+               MTK_FUNCTION(6, "PCIE1_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(28, "EINT6"),
+               "J15", "mt7623",
+               MTK_EINT_FUNCTION(0, 6),
+               MTK_FUNCTION(0, "GPIO28"),
+               MTK_FUNCTION(1, "DRV_VBUS"),
+               MTK_FUNCTION(6, "PCIE0_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(29, "EINT7"),
+               "E15", "mt7623",
+               MTK_EINT_FUNCTION(0, 7),
+               MTK_FUNCTION(0, "GPIO29"),
+               MTK_FUNCTION(1, "IDDIG"),
+               MTK_FUNCTION(2, "MSDC1_WP"),
+               MTK_FUNCTION(6, "PCIE2_PERST_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(30, "GPIO30"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO30")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(31, "GPIO31"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO31")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(32, "GPIO32"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO32")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(33, "I2S1_DATA"),
+               "Y18", "mt7623",
+               MTK_EINT_FUNCTION(0, 15),
+               MTK_FUNCTION(0, "GPIO33"),
+               MTK_FUNCTION(1, "I2S1_DATA"),
+               MTK_FUNCTION(3, "PCM_TX"),
+               MTK_FUNCTION(6, "AP_PCM_TX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(34, "I2S1_DATA_IN"),
+               "Y17", "mt7623",
+               MTK_EINT_FUNCTION(0, 16),
+               MTK_FUNCTION(0, "GPIO34"),
+               MTK_FUNCTION(1, "I2S1_DATA_IN"),
+               MTK_FUNCTION(3, "PCM_RX"),
+               MTK_FUNCTION(6, "AP_PCM_RX")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(35, "I2S1_BCK"),
+               "V17", "mt7623",
+               MTK_EINT_FUNCTION(0, 17),
+               MTK_FUNCTION(0, "GPIO35"),
+               MTK_FUNCTION(1, "I2S1_BCK"),
+               MTK_FUNCTION(3, "PCM_CLK0"),
+               MTK_FUNCTION(6, "AP_PCM_CLKO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(36, "I2S1_LRCK"),
+               "W17", "mt7623",
+               MTK_EINT_FUNCTION(0, 18),
+               MTK_FUNCTION(0, "GPIO36"),
+               MTK_FUNCTION(1, "I2S1_LRCK"),
+               MTK_FUNCTION(3, "PCM_SYNC"),
+               MTK_FUNCTION(6, "AP_PCM_SYNC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(37, "I2S1_MCLK"),
+               "AA18", "mt7623",
+               MTK_EINT_FUNCTION(0, 19),
+               MTK_FUNCTION(0, "GPIO37"),
+               MTK_FUNCTION(1, "I2S1_MCLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(38, "GPIO38"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO38")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(39, "JTMS"),
+               "G21", "mt7623",
+               MTK_EINT_FUNCTION(0, 21),
+               MTK_FUNCTION(0, "GPIO39"),
+               MTK_FUNCTION(1, "JTMS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(40, "GPIO40"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO40")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(41, "JTDI"),
+               "H22", "mt7623",
+               MTK_EINT_FUNCTION(0, 23),
+               MTK_FUNCTION(0, "GPIO41"),
+               MTK_FUNCTION(1, "JTDI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(42, "JTDO"),
+               "H21", "mt7623",
+               MTK_EINT_FUNCTION(0, 24),
+               MTK_FUNCTION(0, "GPIO42"),
+               MTK_FUNCTION(1, "JTDO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(43, "NCLE"),
+               "C7", "mt7623",
+               MTK_EINT_FUNCTION(0, 25),
+               MTK_FUNCTION(0, "GPIO43"),
+               MTK_FUNCTION(1, "NCLE"),
+               MTK_FUNCTION(2, "EXT_XCS2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(44, "NCEB1"),
+               "C6", "mt7623",
+               MTK_EINT_FUNCTION(0, 26),
+               MTK_FUNCTION(0, "GPIO44"),
+               MTK_FUNCTION(1, "NCEB1"),
+               MTK_FUNCTION(2, "IDDIG")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(45, "NCEB0"),
+               "D7", "mt7623",
+               MTK_EINT_FUNCTION(0, 27),
+               MTK_FUNCTION(0, "GPIO45"),
+               MTK_FUNCTION(1, "NCEB0"),
+               MTK_FUNCTION(2, "DRV_VBUS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(46, "IR"),
+               "D15", "mt7623",
+               MTK_EINT_FUNCTION(0, 28),
+               MTK_FUNCTION(0, "GPIO46"),
+               MTK_FUNCTION(1, "IR")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(47, "NREB"),
+               "A6", "mt7623",
+               MTK_EINT_FUNCTION(0, 29),
+               MTK_FUNCTION(0, "GPIO47"),
+               MTK_FUNCTION(1, "NREB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(48, "NRNB"),
+               "B6", "mt7623",
+               MTK_EINT_FUNCTION(0, 30),
+               MTK_FUNCTION(0, "GPIO48"),
+               MTK_FUNCTION(1, "NRNB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(49, "I2S0_DATA"),
+               "AB18", "mt7623",
+               MTK_EINT_FUNCTION(0, 31),
+               MTK_FUNCTION(0, "GPIO49"),
+               MTK_FUNCTION(1, "I2S0_DATA"),
+               MTK_FUNCTION(3, "PCM_TX"),
+               MTK_FUNCTION(6, "AP_I2S_DO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(50, "GPIO50"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO50")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(51, "GPIO51"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO51")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(52, "GPIO52"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO52")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(53, "SPI0_CSN"),
+               "E7", "mt7623",
+               MTK_EINT_FUNCTION(0, 35),
+               MTK_FUNCTION(0, "GPIO53"),
+               MTK_FUNCTION(1, "SPI0_CS"),
+               MTK_FUNCTION(5, "PWM1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(54, "SPI0_CK"),
+               "F7", "mt7623",
+               MTK_EINT_FUNCTION(0, 36),
+               MTK_FUNCTION(0, "GPIO54"),
+               MTK_FUNCTION(1, "SPI0_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(55, "SPI0_MI"),
+               "E6", "mt7623",
+               MTK_EINT_FUNCTION(0, 37),
+               MTK_FUNCTION(0, "GPIO55"),
+               MTK_FUNCTION(1, "SPI0_MI"),
+               MTK_FUNCTION(2, "SPI0_MO"),
+               MTK_FUNCTION(3, "MSDC1_WP"),
+               MTK_FUNCTION(5, "PWM2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(56, "SPI0_MO"),
+               "G7", "mt7623",
+               MTK_EINT_FUNCTION(0, 38),
+               MTK_FUNCTION(0, "GPIO56"),
+               MTK_FUNCTION(1, "SPI0_MO"),
+               MTK_FUNCTION(2, "SPI0_MI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(57, "GPIO57"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO57")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(58, "GPIO58"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO58")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(59, "GPIO59"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO59")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(60, "WB_RSTB"),
+               "Y21", "mt7623",
+               MTK_EINT_FUNCTION(0, 41),
+               MTK_FUNCTION(0, "GPIO60"),
+               MTK_FUNCTION(1, "WB_RSTB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(61, "GPIO61"),
+               "AA21", "mt7623",
+               MTK_EINT_FUNCTION(0, 42),
+               MTK_FUNCTION(0, "GPIO61"),
+               MTK_FUNCTION(1, "TEST_FD")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(62, "GPIO62"),
+               "AB22", "mt7623",
+               MTK_EINT_FUNCTION(0, 43),
+               MTK_FUNCTION(0, "GPIO62"),
+               MTK_FUNCTION(1, "TEST_FC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(63, "WB_SCLK"),
+               "AC23", "mt7623",
+               MTK_EINT_FUNCTION(0, 44),
+               MTK_FUNCTION(0, "GPIO63"),
+               MTK_FUNCTION(1, "WB_SCLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(64, "WB_SDATA"),
+               "AB21", "mt7623",
+               MTK_EINT_FUNCTION(0, 45),
+               MTK_FUNCTION(0, "GPIO64"),
+               MTK_FUNCTION(1, "WB_SDATA")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(65, "WB_SEN"),
+               "AB24", "mt7623",
+               MTK_EINT_FUNCTION(0, 46),
+               MTK_FUNCTION(0, "GPIO65"),
+               MTK_FUNCTION(1, "WB_SEN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(66, "WB_CRTL0"),
+               "AB20", "mt7623",
+               MTK_EINT_FUNCTION(0, 47),
+               MTK_FUNCTION(0, "GPIO66"),
+               MTK_FUNCTION(1, "WB_CRTL0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(67, "WB_CRTL1"),
+               "AC20", "mt7623",
+               MTK_EINT_FUNCTION(0, 48),
+               MTK_FUNCTION(0, "GPIO67"),
+               MTK_FUNCTION(1, "WB_CRTL1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(68, "WB_CRTL2"),
+               "AB19", "mt7623",
+               MTK_EINT_FUNCTION(0, 49),
+               MTK_FUNCTION(0, "GPIO68"),
+               MTK_FUNCTION(1, "WB_CRTL2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(69, "WB_CRTL3"),
+               "AC19", "mt7623",
+               MTK_EINT_FUNCTION(0, 50),
+               MTK_FUNCTION(0, "GPIO69"),
+               MTK_FUNCTION(1, "WB_CRTL3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(70, "WB_CRTL4"),
+               "AD19", "mt7623",
+               MTK_EINT_FUNCTION(0, 51),
+               MTK_FUNCTION(0, "GPIO70"),
+               MTK_FUNCTION(1, "WB_CRTL4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(71, "WB_CRTL5"),
+               "AE19", "mt7623",
+               MTK_EINT_FUNCTION(0, 52),
+               MTK_FUNCTION(0, "GPIO71"),
+               MTK_FUNCTION(1, "WB_CRTL5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(72, "I2S0_DATA_IN"),
+               "AA20", "mt7623",
+               MTK_EINT_FUNCTION(0, 53),
+               MTK_FUNCTION(0, "GPIO72"),
+               MTK_FUNCTION(1, "I2S0_DATA_IN"),
+               MTK_FUNCTION(3, "PCM_RX"),
+               MTK_FUNCTION(4, "PWM0"),
+               MTK_FUNCTION(5, "DISP_PWM"),
+               MTK_FUNCTION(6, "AP_I2S_DI")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(73, "I2S0_LRCK"),
+               "Y20", "mt7623",
+               MTK_EINT_FUNCTION(0, 54),
+               MTK_FUNCTION(0, "GPIO73"),
+               MTK_FUNCTION(1, "I2S0_LRCK"),
+               MTK_FUNCTION(3, "PCM_SYNC"),
+               MTK_FUNCTION(6, "AP_I2S_LRCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(74, "I2S0_BCK"),
+               "Y19", "mt7623",
+               MTK_EINT_FUNCTION(0, 55),
+               MTK_FUNCTION(0, "GPIO74"),
+               MTK_FUNCTION(1, "I2S0_BCK"),
+               MTK_FUNCTION(3, "PCM_CLK0"),
+               MTK_FUNCTION(6, "AP_I2S_BCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(75, "SDA0"),
+               "K19", "mt7623",
+               MTK_EINT_FUNCTION(0, 56),
+               MTK_FUNCTION(0, "GPIO75"),
+               MTK_FUNCTION(1, "SDA0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(76, "SCL0"),
+               "K20", "mt7623",
+               MTK_EINT_FUNCTION(0, 57),
+               MTK_FUNCTION(0, "GPIO76"),
+               MTK_FUNCTION(1, "SCL0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(77, "GPIO77"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO77")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(78, "GPIO78"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO78")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(79, "GPIO79"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO79")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(80, "GPIO80"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO80")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(81, "GPIO81"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO81")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(82, "GPIO82"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO82")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(83, "LCM_RST"),
+               "V16", "mt7623",
+               MTK_EINT_FUNCTION(0, 64),
+               MTK_FUNCTION(0, "GPIO83"),
+               MTK_FUNCTION(1, "LCM_RST")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(84, "DSI_TE"),
+               "V14", "mt7623",
+               MTK_EINT_FUNCTION(0, 65),
+               MTK_FUNCTION(0, "GPIO84"),
+               MTK_FUNCTION(1, "DSI_TE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(85, "GPIO85"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO85")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(86, "GPIO86"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO86")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(87, "GPIO87"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO87")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(88, "GPIO88"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO88")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(89, "GPIO89"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO89")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(90, "GPIO90"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO90")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(91, "GPIO91"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO91")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(92, "GPIO92"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO92")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(93, "GPIO93"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO93")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(94, "GPIO94"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO94")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(95, "MIPI_TCN"),
+               "AB14", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO95"),
+               MTK_FUNCTION(1, "TCN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(96, "MIPI_TCP"),
+               "AC14", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO96"),
+               MTK_FUNCTION(1, "TCP")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(97, "MIPI_TDN1"),
+               "AE15", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO97"),
+               MTK_FUNCTION(1, "TDN1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(98, "MIPI_TDP1"),
+               "AD15", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO98"),
+               MTK_FUNCTION(1, "TDP1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(99, "MIPI_TDN0"),
+               "AB15", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO99"),
+               MTK_FUNCTION(1, "TDN0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(100, "MIPI_TDP0"),
+               "AC15", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO100"),
+               MTK_FUNCTION(1, "TDP0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(101, "GPIO101"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO101")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(102, "GPIO102"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO102")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(103, "GPIO103"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO103")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(104, "GPIO104"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO104")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(105, "MSDC1_CMD"),
+               "AD2", "mt7623",
+               MTK_EINT_FUNCTION(0, 78),
+               MTK_FUNCTION(0, "GPIO105"),
+               MTK_FUNCTION(1, "MSDC1_CMD"),
+               MTK_FUNCTION(3, "SDA1"),
+               MTK_FUNCTION(6, "I2SOUT_BCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(106, "MSDC1_CLK"),
+               "AD3", "mt7623",
+               MTK_EINT_FUNCTION(0, 79),
+               MTK_FUNCTION(0, "GPIO106"),
+               MTK_FUNCTION(1, "MSDC1_CLK"),
+               MTK_FUNCTION(3, "SCL1"),
+               MTK_FUNCTION(6, "I2SOUT_LRCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(107, "MSDC1_DAT0"),
+               "AE2", "mt7623",
+               MTK_EINT_FUNCTION(0, 80),
+               MTK_FUNCTION(0, "GPIO107"),
+               MTK_FUNCTION(1, "MSDC1_DAT0"),
+               MTK_FUNCTION(5, "UTXD0"),
+               MTK_FUNCTION(6, "I2SOUT_DATA_OUT")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(108, "MSDC1_DAT1"),
+               "AC1", "mt7623",
+               MTK_EINT_FUNCTION(0, 81),
+               MTK_FUNCTION(0, "GPIO108"),
+               MTK_FUNCTION(1, "MSDC1_DAT1"),
+               MTK_FUNCTION(3, "PWM0"),
+               MTK_FUNCTION(5, "URXD0"),
+               MTK_FUNCTION(6, "PWM1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(109, "MSDC1_DAT2"),
+               "AC3", "mt7623",
+               MTK_EINT_FUNCTION(0, 82),
+               MTK_FUNCTION(0, "GPIO109"),
+               MTK_FUNCTION(1, "MSDC1_DAT2"),
+               MTK_FUNCTION(3, "SDA2"),
+               MTK_FUNCTION(5, "UTXD1"),
+               MTK_FUNCTION(6, "PWM2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(110, "MSDC1_DAT3"),
+               "AC4", "mt7623",
+               MTK_EINT_FUNCTION(0, 83),
+               MTK_FUNCTION(0, "GPIO110"),
+               MTK_FUNCTION(1, "MSDC1_DAT3"),
+               MTK_FUNCTION(3, "SCL2"),
+               MTK_FUNCTION(5, "URXD1"),
+               MTK_FUNCTION(6, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(111, "MSDC0_DAT7"),
+               "A2", "mt7623",
+               MTK_EINT_FUNCTION(0, 84),
+               MTK_FUNCTION(0, "GPIO111"),
+               MTK_FUNCTION(1, "MSDC0_DAT7"),
+               MTK_FUNCTION(4, "NLD7")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(112, "MSDC0_DAT6"),
+               "B3", "mt7623",
+               MTK_EINT_FUNCTION(0, 85),
+               MTK_FUNCTION(0, "GPIO112"),
+               MTK_FUNCTION(1, "MSDC0_DAT6"),
+               MTK_FUNCTION(4, "NLD6")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(113, "MSDC0_DAT5"),
+               "C4", "mt7623",
+               MTK_EINT_FUNCTION(0, 86),
+               MTK_FUNCTION(0, "GPIO113"),
+               MTK_FUNCTION(1, "MSDC0_DAT5"),
+               MTK_FUNCTION(4, "NLD5")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(114, "MSDC0_DAT4"),
+               "A4", "mt7623",
+               MTK_EINT_FUNCTION(0, 87),
+               MTK_FUNCTION(0, "GPIO114"),
+               MTK_FUNCTION(1, "MSDC0_DAT4"),
+               MTK_FUNCTION(4, "NLD4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(115, "MSDC0_RSTB"),
+               "C5", "mt7623",
+               MTK_EINT_FUNCTION(0, 88),
+               MTK_FUNCTION(0, "GPIO115"),
+               MTK_FUNCTION(1, "MSDC0_RSTB"),
+               MTK_FUNCTION(4, "NLD8")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(116, "MSDC0_CMD"),
+               "D5", "mt7623",
+               MTK_EINT_FUNCTION(0, 89),
+               MTK_FUNCTION(0, "GPIO116"),
+               MTK_FUNCTION(1, "MSDC0_CMD"),
+               MTK_FUNCTION(4, "NALE")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(117, "MSDC0_CLK"),
+               "B1", "mt7623",
+               MTK_EINT_FUNCTION(0, 90),
+               MTK_FUNCTION(0, "GPIO117"),
+               MTK_FUNCTION(1, "MSDC0_CLK"),
+               MTK_FUNCTION(4, "NWEB")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(118, "MSDC0_DAT3"),
+               "D6", "mt7623",
+               MTK_EINT_FUNCTION(0, 91),
+               MTK_FUNCTION(0, "GPIO118"),
+               MTK_FUNCTION(1, "MSDC0_DAT3"),
+               MTK_FUNCTION(4, "NLD3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(119, "MSDC0_DAT2"),
+               "B2", "mt7623",
+               MTK_EINT_FUNCTION(0, 92),
+               MTK_FUNCTION(0, "GPIO119"),
+               MTK_FUNCTION(1, "MSDC0_DAT2"),
+               MTK_FUNCTION(4, "NLD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(120, "MSDC0_DAT1"),
+               "A3", "mt7623",
+               MTK_EINT_FUNCTION(0, 93),
+               MTK_FUNCTION(0, "GPIO120"),
+               MTK_FUNCTION(1, "MSDC0_DAT1"),
+               MTK_FUNCTION(4, "NLD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(121, "MSDC0_DAT0"),
+               "B4", "mt7623",
+               MTK_EINT_FUNCTION(0, 94),
+               MTK_FUNCTION(0, "GPIO121"),
+               MTK_FUNCTION(1, "MSDC0_DAT0"),
+               MTK_FUNCTION(4, "NLD0"),
+               MTK_FUNCTION(5, "WATCHDOG")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(122, "GPIO122"),
+               "H17", "mt7623",
+               MTK_EINT_FUNCTION(0, 95),
+               MTK_FUNCTION(0, "GPIO122"),
+               MTK_FUNCTION(1, "TEST"),
+               MTK_FUNCTION(4, "SDA2"),
+               MTK_FUNCTION(5, "URXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(123, "GPIO123"),
+               "F17", "mt7623",
+               MTK_EINT_FUNCTION(0, 96),
+               MTK_FUNCTION(0, "GPIO123"),
+               MTK_FUNCTION(1, "TEST"),
+               MTK_FUNCTION(4, "SCL2"),
+               MTK_FUNCTION(5, "UTXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(124, "GPIO124"),
+               "H18", "mt7623",
+               MTK_EINT_FUNCTION(0, 97),
+               MTK_FUNCTION(0, "GPIO124"),
+               MTK_FUNCTION(1, "TEST"),
+               MTK_FUNCTION(4, "SDA1"),
+               MTK_FUNCTION(5, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(125, "GPIO125"),
+               "G17", "mt7623",
+               MTK_EINT_FUNCTION(0, 98),
+               MTK_FUNCTION(0, "GPIO125"),
+               MTK_FUNCTION(1, "TEST"),
+               MTK_FUNCTION(4, "SCL1"),
+               MTK_FUNCTION(5, "PWM4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(126, "I2S0_MCLK"),
+               "AA19", "mt7623",
+               MTK_EINT_FUNCTION(0, 99),
+               MTK_FUNCTION(0, "GPIO126"),
+               MTK_FUNCTION(1, "I2S0_MCLK"),
+               MTK_FUNCTION(6, "AP_I2S_MCLK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(127, "GPIO127"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO127")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(128, "GPIO128"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO128")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(129, "GPIO129"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO129")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(130, "GPIO130"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO130")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(131, "GPIO131"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO131")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(132, "GPIO132"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO132")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(133, "GPIO133"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO133")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(134, "GPIO134"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO134")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(135, "GPIO135"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO135")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(136, "GPIO136"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO136")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(137, "GPIO137"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO137")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(138, "GPIO138"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO138")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(139, "GPIO139"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO139")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(140, "GPIO140"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO140")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(141, "GPIO141"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO141")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(142, "GPIO142"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO142")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(143, "GPIO143"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO143")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(144, "GPIO144"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO144")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(145, "GPIO145"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO145")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(146, "GPIO146"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO146")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(147, "GPIO147"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO147")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(148, "GPIO148"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO148")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(149, "GPIO149"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO149")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(150, "GPIO150"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO150")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(151, "GPIO151"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO151")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(152, "GPIO152"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO152")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(153, "GPIO153"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO153")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(154, "GPIO154"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO154")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(155, "GPIO155"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO155")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(156, "GPIO156"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO156")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(157, "GPIO157"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO157")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(158, "GPIO158"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO158")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(159, "GPIO159"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO159")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(160, "GPIO160"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO160")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(161, "GPIO161"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO161")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(162, "GPIO162"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO162")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(163, "GPIO163"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO163")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(164, "GPIO164"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO164")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(165, "GPIO165"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO165")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(166, "GPIO166"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO166")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(167, "GPIO167"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO167")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(168, "GPIO168"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO168")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(169, "GPIO169"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO169")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(170, "GPIO170"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO170")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(171, "GPIO171"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO171")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(172, "GPIO172"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO172")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(173, "GPIO173"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO173")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(174, "GPIO174"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO174")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(175, "GPIO175"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO175")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(176, "GPIO176"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO176")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(177, "GPIO177"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO177")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(178, "GPIO178"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO178")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(179, "GPIO179"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO179")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(180, "GPIO180"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO180")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(181, "GPIO181"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO181")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(182, "GPIO182"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO182")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(183, "GPIO183"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO183")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(184, "GPIO184"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO184")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(185, "GPIO185"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO185")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(186, "GPIO186"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO186")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(187, "GPIO187"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO187")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(188, "GPIO188"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO188")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(189, "GPIO189"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO189")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(190, "GPIO190"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO190")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(191, "GPIO191"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO191")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(192, "GPIO192"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO192")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(193, "GPIO193"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO193")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(194, "GPIO194"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO194")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(195, "GPIO195"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO195")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(196, "GPIO196"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO196")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(197, "GPIO197"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO197")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(198, "GPIO198"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO198")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(199, "SPI1_CK"),
+               "E19", "mt7623",
+               MTK_EINT_FUNCTION(0, 111),
+               MTK_FUNCTION(0, "GPIO199"),
+               MTK_FUNCTION(1, "SPI1_CK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(200, "URXD2"),
+               "K18", "mt7623",
+               MTK_EINT_FUNCTION(0, 112),
+               MTK_FUNCTION(0, "GPIO200"),
+               MTK_FUNCTION(6, "URXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(201, "UTXD2"),
+               "L18", "mt7623",
+               MTK_EINT_FUNCTION(0, 113),
+               MTK_FUNCTION(0, "GPIO201"),
+               MTK_FUNCTION(6, "UTXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(202, "GPIO202"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO202")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(203, "PWM0"),
+               "AA16", "mt7623",
+               MTK_EINT_FUNCTION(0, 115),
+               MTK_FUNCTION(0, "GPIO203"),
+               MTK_FUNCTION(1, "PWM0"),
+               MTK_FUNCTION(2, "DISP_PWM")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(204, "PWM1"),
+               "Y16", "mt7623",
+               MTK_EINT_FUNCTION(0, 116),
+               MTK_FUNCTION(0, "GPIO204"),
+               MTK_FUNCTION(1, "PWM1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(205, "PWM2"),
+               "AA15", "mt7623",
+               MTK_EINT_FUNCTION(0, 117),
+               MTK_FUNCTION(0, "GPIO205"),
+               MTK_FUNCTION(1, "PWM2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(206, "PWM3"),
+               "AA17", "mt7623",
+               MTK_EINT_FUNCTION(0, 118),
+               MTK_FUNCTION(0, "GPIO206"),
+               MTK_FUNCTION(1, "PWM3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(207, "PWM4"),
+               "Y15", "mt7623",
+               MTK_EINT_FUNCTION(0, 119),
+               MTK_FUNCTION(0, "GPIO207"),
+               MTK_FUNCTION(1, "PWM4")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(208, "AUD_EXT_CK1"),
+               "W14", "mt7623",
+               MTK_EINT_FUNCTION(0, 120),
+               MTK_FUNCTION(0, "GPIO208"),
+               MTK_FUNCTION(1, "AUD_EXT_CK1"),
+               MTK_FUNCTION(2, "PWM0"),
+               MTK_FUNCTION(3, "PCIE0_PERST_N"),
+               MTK_FUNCTION(5, "DISP_PWM")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(209, "AUD_EXT_CK2"),
+               "V15", "mt7623",
+               MTK_EINT_FUNCTION(0, 121),
+               MTK_FUNCTION(0, "GPIO209"),
+               MTK_FUNCTION(1, "AUD_EXT_CK2"),
+               MTK_FUNCTION(2, "MSDC1_WP"),
+               MTK_FUNCTION(3, "PCIE1_PERST_N"),
+               MTK_FUNCTION(5, "PWM1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(210, "GPIO210"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO210")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(211, "GPIO211"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO211")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(212, "GPIO212"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO212")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(213, "GPIO213"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO213")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(214, "GPIO214"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO214")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(215, "GPIO215"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO215")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(216, "GPIO216"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO216")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(217, "GPIO217"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO217")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(218, "GPIO218"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO218")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(219, "GPIO219"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO219")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(220, "GPIO220"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO220")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(221, "GPIO221"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO221")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(222, "GPIO222"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO222")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(223, "GPIO223"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO223")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(224, "GPIO224"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO224")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(225, "GPIO225"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO225")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(226, "GPIO226"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO226")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(227, "GPIO227"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO227")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(228, "GPIO228"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO228")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(229, "GPIO229"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO229")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(230, "GPIO230"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO230")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(231, "GPIO231"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO231")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(232, "GPIO232"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO232")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(233, "GPIO233"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO233")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(234, "GPIO234"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO234")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(235, "GPIO235"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO235")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(236, "EXT_SDIO3"),
+               "A8", "mt7623",
+               MTK_EINT_FUNCTION(0, 122),
+               MTK_FUNCTION(0, "GPIO236"),
+               MTK_FUNCTION(1, "EXT_SDIO3"),
+               MTK_FUNCTION(2, "IDDIG")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(237, "EXT_SDIO2"),
+               "D8", "mt7623",
+               MTK_EINT_FUNCTION(0, 123),
+               MTK_FUNCTION(0, "GPIO237"),
+               MTK_FUNCTION(1, "EXT_SDIO2"),
+               MTK_FUNCTION(2, "DRV_VBUS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(238, "EXT_SDIO1"),
+               "D9", "mt7623",
+               MTK_EINT_FUNCTION(0, 124),
+               MTK_FUNCTION(0, "GPIO238"),
+               MTK_FUNCTION(1, "EXT_SDIO1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(239, "EXT_SDIO0"),
+               "B8", "mt7623",
+               MTK_EINT_FUNCTION(0, 125),
+               MTK_FUNCTION(0, "GPIO239"),
+               MTK_FUNCTION(1, "EXT_SDIO0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(240, "EXT_XCS"),
+               "C9", "mt7623",
+               MTK_EINT_FUNCTION(0, 126),
+               MTK_FUNCTION(0, "GPIO240"),
+               MTK_FUNCTION(1, "EXT_XCS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(241, "EXT_SCK"),
+               "C8", "mt7623",
+               MTK_EINT_FUNCTION(0, 127),
+               MTK_FUNCTION(0, "GPIO241"),
+               MTK_FUNCTION(1, "EXT_SCK")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(242, "URTS2"),
+               "G18", "mt7623",
+               MTK_EINT_FUNCTION(0, 128),
+               MTK_FUNCTION(0, "GPIO242"),
+               MTK_FUNCTION(1, "URTS2"),
+               MTK_FUNCTION(2, "UTXD3"),
+               MTK_FUNCTION(3, "URXD3"),
+               MTK_FUNCTION(4, "SCL1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(243, "UCTS2"),
+               "H19", "mt7623",
+               MTK_EINT_FUNCTION(0, 129),
+               MTK_FUNCTION(0, "GPIO243"),
+               MTK_FUNCTION(1, "UCTS2"),
+               MTK_FUNCTION(2, "URXD3"),
+               MTK_FUNCTION(3, "UTXD3"),
+               MTK_FUNCTION(4, "SDA1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(244, "GPIO244"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO244")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(245, "GPIO245"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO245")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(246, "GPIO246"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO246")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(247, "GPIO247"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO247")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(248, "GPIO248"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO248")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(249, "GPIO249"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO249")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(250, "GPIO250"),
+               "A15", "mt7623",
+               MTK_EINT_FUNCTION(0, 135),
+               MTK_FUNCTION(0, "GPIO250"),
+               MTK_FUNCTION(1, "TEST_MD7"),
+               MTK_FUNCTION(6, "PCIE0_CLKREQ_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(251, "GPIO251"),
+               "B15", "mt7623",
+               MTK_EINT_FUNCTION(0, 136),
+               MTK_FUNCTION(0, "GPIO251"),
+               MTK_FUNCTION(1, "TEST_MD6"),
+               MTK_FUNCTION(6, "PCIE0_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(252, "GPIO252"),
+               "C16", "mt7623",
+               MTK_EINT_FUNCTION(0, 137),
+               MTK_FUNCTION(0, "GPIO252"),
+               MTK_FUNCTION(1, "TEST_MD5"),
+               MTK_FUNCTION(6, "PCIE1_CLKREQ_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(253, "GPIO253"),
+               "D17", "mt7623",
+               MTK_EINT_FUNCTION(0, 138),
+               MTK_FUNCTION(0, "GPIO253"),
+               MTK_FUNCTION(1, "TEST_MD4"),
+               MTK_FUNCTION(6, "PCIE1_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(254, "GPIO254"),
+               "D16", "mt7623",
+               MTK_EINT_FUNCTION(0, 139),
+               MTK_FUNCTION(0, "GPIO254"),
+               MTK_FUNCTION(1, "TEST_MD3"),
+               MTK_FUNCTION(6, "PCIE2_CLKREQ_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(255, "GPIO255"),
+               "C17", "mt7623",
+               MTK_EINT_FUNCTION(0, 140),
+               MTK_FUNCTION(0, "GPIO255"),
+               MTK_FUNCTION(1, "TEST_MD2"),
+               MTK_FUNCTION(6, "PCIE2_WAKE_N")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(256, "GPIO256"),
+               "B17", "mt7623",
+               MTK_EINT_FUNCTION(0, 141),
+               MTK_FUNCTION(0, "GPIO256"),
+               MTK_FUNCTION(1, "TEST_MD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(257, "GPIO257"),
+               "C15", "mt7623",
+               MTK_EINT_FUNCTION(0, 142),
+               MTK_FUNCTION(0, "GPIO257"),
+               MTK_FUNCTION(1, "TEST_MD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(258, "GPIO258"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO258")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(259, "GPIO259"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO259")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(260, "GPIO260"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO260")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(261, "MSDC1_INS"),
+               "AD1", "mt7623",
+               MTK_EINT_FUNCTION(0, 146),
+               MTK_FUNCTION(0, "GPIO261"),
+               MTK_FUNCTION(1, "MSDC1_INS")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(262, "G2_TXEN"),
+               "A23", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO262"),
+               MTK_FUNCTION(1, "G2_TXEN")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(263, "G2_TXD3"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO263"),
+               MTK_FUNCTION(1, "G2_TXD3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(264, "G2_TXD2"),
+               "C24", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO264"),
+               MTK_FUNCTION(1, "G2_TXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(265, "G2_TXD1"),
+               "B25", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO265"),
+               MTK_FUNCTION(1, "G2_TXD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(266, "G2_TXD0"),
+               "A24", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO266"),
+               MTK_FUNCTION(1, "G2_TXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(267, "G2_TXCLK"),
+               "C23", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO267"),
+               MTK_FUNCTION(1, "G2_TXC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(268, "G2_RXCLK"),
+               "B23", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO268"),
+               MTK_FUNCTION(1, "G2_RXC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(269, "G2_RXD0"),
+               "D21", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO269"),
+               MTK_FUNCTION(1, "G2_RXD0")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(270, "G2_RXD1"),
+               "B22", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO270"),
+               MTK_FUNCTION(1, "G2_RXD1")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(271, "G2_RXD2"),
+               "A22", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO271"),
+               MTK_FUNCTION(1, "G2_RXD2")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(272, "G2_RXD3"),
+               "C22", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO272"),
+               MTK_FUNCTION(1, "G2_RXD3")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(273, "GPIO273"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO273")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(274, "G2_RXDV"),
+               "C21", "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO274"),
+               MTK_FUNCTION(1, "G2_RXDV")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(275, "G2_MDC"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO275"),
+               MTK_FUNCTION(1, "MDC")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(276, "G2_MDIO"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO276"),
+               MTK_FUNCTION(1, "MDIO")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(277, "GPIO277"),
+               NULL, "mt7623",
+               MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT),
+               MTK_FUNCTION(0, "GPIO277")
+       ),
+       MTK_PIN(
+               PINCTRL_PIN(278, "JTAG_RESET"),
+               "H20", "mt7623",
+               MTK_EINT_FUNCTION(0, 147),
+               MTK_FUNCTION(0, "GPIO278"),
+               MTK_FUNCTION(1, "JTAG_RESET")
+       ),
+};
+
+#endif /* __PINCTRL_MTK_MT7623_H */
index 50cab27c64d4055813b34ab5a35cd669e08bce9e..0bdb8fd3afd18c7bc39934904d0729e29b779add 100644 (file)
@@ -49,7 +49,6 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/pinctrl/pinconf-generic.h>
@@ -104,15 +103,13 @@ static int meson_get_domain_and_bank(struct meson_pinctrl *pc, unsigned int pin,
                                     struct meson_bank **bank)
 {
        struct meson_domain *d;
-       int i;
 
-       for (i = 0; i < pc->data->num_domains; i++) {
-               d = &pc->domains[i];
-               if (pin >= d->data->pin_base &&
-                   pin < d->data->pin_base + d->data->num_pins) {
-                       *domain = d;
-                       return meson_get_bank(d, pin, bank);
-               }
+       d = pc->domain;
+
+       if (pin >= d->data->pin_base &&
+           pin < d->data->pin_base + d->data->num_pins) {
+               *domain = d;
+               return meson_get_bank(d, pin, bank);
        }
 
        return -EINVAL;
@@ -204,7 +201,7 @@ static void meson_pmx_disable_other_groups(struct meson_pinctrl *pc,
                for (j = 0; j < group->num_pins; j++) {
                        if (group->pins[j] == pin) {
                                /* We have found a group using the pin */
-                               domain = &pc->domains[group->domain];
+                               domain = pc->domain;
                                regmap_update_bits(domain->reg_mux,
                                                   group->reg * 4,
                                                   BIT(group->bit), 0);
@@ -219,7 +216,7 @@ static int meson_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_num,
        struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
        struct meson_pmx_func *func = &pc->data->funcs[func_num];
        struct meson_pmx_group *group = &pc->data->groups[group_num];
-       struct meson_domain *domain = &pc->domains[group->domain];
+       struct meson_domain *domain = pc->domain;
        int i, ret = 0;
 
        dev_dbg(pc->dev, "enable function %s, group %s\n", func->name,
@@ -537,76 +534,67 @@ static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio)
 
 static const struct of_device_id meson_pinctrl_dt_match[] = {
        {
-               .compatible = "amlogic,meson8-pinctrl",
-               .data = &meson8_pinctrl_data,
+               .compatible = "amlogic,meson8-cbus-pinctrl",
+               .data = &meson8_cbus_pinctrl_data,
+       },
+       {
+               .compatible = "amlogic,meson8b-cbus-pinctrl",
+               .data = &meson8b_cbus_pinctrl_data,
+       },
+       {
+               .compatible = "amlogic,meson8-aobus-pinctrl",
+               .data = &meson8_aobus_pinctrl_data,
        },
        {
-               .compatible = "amlogic,meson8b-pinctrl",
-               .data = &meson8b_pinctrl_data,
+               .compatible = "amlogic,meson8b-aobus-pinctrl",
+               .data = &meson8b_aobus_pinctrl_data,
        },
        { },
 };
-MODULE_DEVICE_TABLE(of, meson_pinctrl_dt_match);
 
 static int meson_gpiolib_register(struct meson_pinctrl *pc)
 {
        struct meson_domain *domain;
-       int i, ret;
+       int ret;
 
-       for (i = 0; i < pc->data->num_domains; i++) {
-               domain = &pc->domains[i];
-
-               domain->chip.label = domain->data->name;
-               domain->chip.parent = pc->dev;
-               domain->chip.request = meson_gpio_request;
-               domain->chip.free = meson_gpio_free;
-               domain->chip.direction_input = meson_gpio_direction_input;
-               domain->chip.direction_output = meson_gpio_direction_output;
-               domain->chip.get = meson_gpio_get;
-               domain->chip.set = meson_gpio_set;
-               domain->chip.base = domain->data->pin_base;
-               domain->chip.ngpio = domain->data->num_pins;
-               domain->chip.can_sleep = false;
-               domain->chip.of_node = domain->of_node;
-               domain->chip.of_gpio_n_cells = 2;
-
-               ret = gpiochip_add_data(&domain->chip, domain);
-               if (ret) {
-                       dev_err(pc->dev, "can't add gpio chip %s\n",
-                               domain->data->name);
-                       goto fail;
-               }
+       domain = pc->domain;
+
+       domain->chip.label = domain->data->name;
+       domain->chip.parent = pc->dev;
+       domain->chip.request = meson_gpio_request;
+       domain->chip.free = meson_gpio_free;
+       domain->chip.direction_input = meson_gpio_direction_input;
+       domain->chip.direction_output = meson_gpio_direction_output;
+       domain->chip.get = meson_gpio_get;
+       domain->chip.set = meson_gpio_set;
+       domain->chip.base = domain->data->pin_base;
+       domain->chip.ngpio = domain->data->num_pins;
+       domain->chip.can_sleep = false;
+       domain->chip.of_node = domain->of_node;
+       domain->chip.of_gpio_n_cells = 2;
+
+       ret = gpiochip_add_data(&domain->chip, domain);
+       if (ret) {
+               dev_err(pc->dev, "can't add gpio chip %s\n",
+                       domain->data->name);
+               goto fail;
+       }
 
-               ret = gpiochip_add_pin_range(&domain->chip, dev_name(pc->dev),
-                                            0, domain->data->pin_base,
-                                            domain->chip.ngpio);
-               if (ret) {
-                       dev_err(pc->dev, "can't add pin range\n");
-                       goto fail;
-               }
+       ret = gpiochip_add_pin_range(&domain->chip, dev_name(pc->dev),
+                                    0, domain->data->pin_base,
+                                    domain->chip.ngpio);
+       if (ret) {
+               dev_err(pc->dev, "can't add pin range\n");
+               goto fail;
        }
 
        return 0;
 fail:
-       for (i--; i >= 0; i--)
-               gpiochip_remove(&pc->domains[i].chip);
+       gpiochip_remove(&pc->domain->chip);
 
        return ret;
 }
 
-static struct meson_domain_data *meson_get_domain_data(struct meson_pinctrl *pc,
-                                                      struct device_node *np)
-{
-       int i;
-
-       for (i = 0; i < pc->data->num_domains; i++) {
-               if (!strcmp(np->name, pc->data->domain_data[i].name))
-                       return &pc->data->domain_data[i];
-       }
-
-       return NULL;
-}
-
 static struct regmap_config meson_regmap_config = {
        .reg_bits = 32,
        .val_bits = 32,
@@ -643,7 +631,7 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
 {
        struct device_node *np;
        struct meson_domain *domain;
-       int i = 0, num_domains = 0;
+       int num_domains = 0;
 
        for_each_child_of_node(node, np) {
                if (!of_find_property(np, "gpio-controller", NULL))
@@ -651,29 +639,22 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
                num_domains++;
        }
 
-       if (num_domains != pc->data->num_domains) {
+       if (num_domains != 1) {
                dev_err(pc->dev, "wrong number of subnodes\n");
                return -EINVAL;
        }
 
-       pc->domains = devm_kzalloc(pc->dev, num_domains *
-                                  sizeof(struct meson_domain), GFP_KERNEL);
-       if (!pc->domains)
+       pc->domain = devm_kzalloc(pc->dev, sizeof(struct meson_domain), GFP_KERNEL);
+       if (!pc->domain)
                return -ENOMEM;
 
+       domain = pc->domain;
+       domain->data = pc->data->domain_data;
+
        for_each_child_of_node(node, np) {
                if (!of_find_property(np, "gpio-controller", NULL))
                        continue;
 
-               domain = &pc->domains[i];
-
-               domain->data = meson_get_domain_data(pc, np);
-               if (!domain->data) {
-                       dev_err(pc->dev, "domain data not found for node %s\n",
-                               np->name);
-                       return -ENODEV;
-               }
-
                domain->of_node = np;
 
                domain->reg_mux = meson_map_resource(pc, np, "mux");
@@ -699,7 +680,7 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
                        return PTR_ERR(domain->reg_gpio);
                }
 
-               i++;
+               break;
        }
 
        return 0;
@@ -718,7 +699,7 @@ static int meson_pinctrl_probe(struct platform_device *pdev)
 
        pc->dev = dev;
        match = of_match_node(meson_pinctrl_dt_match, pdev->dev.of_node);
-       pc->data = (struct meson_pinctrl_data *)match->data;
+       pc->data = (struct meson_pinctrl_data *) match->data;
 
        ret = meson_pinctrl_parse_dt(pc, pdev->dev.of_node);
        if (ret)
@@ -754,8 +735,4 @@ static struct platform_driver meson_pinctrl_driver = {
                .of_match_table = meson_pinctrl_dt_match,
        },
 };
-module_platform_driver(meson_pinctrl_driver);
-
-MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
-MODULE_DESCRIPTION("Amlogic Meson pinctrl driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(meson_pinctrl_driver);
index 0fe7d53849ce09834b72691f0f0bcf74ecc953b8..9c93e0d494a363179715132634fa01f5c9ff93b2 100644 (file)
@@ -34,7 +34,6 @@ struct meson_pmx_group {
        bool is_gpio;
        unsigned int reg;
        unsigned int bit;
-       unsigned int domain;
 };
 
 /**
@@ -144,7 +143,6 @@ struct meson_pinctrl_data {
        unsigned int num_pins;
        unsigned int num_groups;
        unsigned int num_funcs;
-       unsigned int num_domains;
 };
 
 struct meson_pinctrl {
@@ -152,7 +150,7 @@ struct meson_pinctrl {
        struct pinctrl_dev *pcdev;
        struct pinctrl_desc desc;
        struct meson_pinctrl_data *data;
-       struct meson_domain *domains;
+       struct meson_domain *domain;
 };
 
 #define PIN(x, b)      (b + x)
@@ -164,7 +162,6 @@ struct meson_pinctrl {
                .num_pins = ARRAY_SIZE(grp ## _pins),                   \
                .reg = r,                                               \
                .bit = b,                                               \
-               .domain = 0,                                            \
         }
 
 #define GPIO_GROUP(gpio, b)                                            \
@@ -175,16 +172,6 @@ struct meson_pinctrl {
                .is_gpio = true,                                        \
         }
 
-#define GROUP_AO(grp, r, b)                                            \
-       {                                                               \
-               .name = #grp,                                           \
-               .pins = grp ## _pins,                                   \
-               .num_pins = ARRAY_SIZE(grp ## _pins),                   \
-               .reg = r,                                               \
-               .bit = b,                                               \
-               .domain = 1,                                            \
-        }
-
 #define FUNCTION(fn)                                                   \
        {                                                               \
                .name = #fn,                                            \
@@ -208,5 +195,7 @@ struct meson_pinctrl {
 
 #define MESON_PIN(x, b) PINCTRL_PIN(PIN(x, b), #x)
 
-extern struct meson_pinctrl_data meson8_pinctrl_data;
-extern struct meson_pinctrl_data meson8b_pinctrl_data;
+extern struct meson_pinctrl_data meson8_cbus_pinctrl_data;
+extern struct meson_pinctrl_data meson8_aobus_pinctrl_data;
+extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data;
+extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data;
index 7b1cc91733efaf6a5def1fc951660d7209eebf3a..32de191e0807e199c3a8d342cc5ca8e599276e5b 100644 (file)
@@ -16,7 +16,7 @@
 
 #define AO_OFF 120
 
-static const struct pinctrl_pin_desc meson8_pins[] = {
+static const struct pinctrl_pin_desc meson8_cbus_pins[] = {
        MESON_PIN(GPIOX_0, 0),
        MESON_PIN(GPIOX_1, 0),
        MESON_PIN(GPIOX_2, 0),
@@ -137,6 +137,9 @@ static const struct pinctrl_pin_desc meson8_pins[] = {
        MESON_PIN(BOOT_16, 0),
        MESON_PIN(BOOT_17, 0),
        MESON_PIN(BOOT_18, 0),
+};
+
+static const struct pinctrl_pin_desc meson8_aobus_pins[] = {
        MESON_PIN(GPIOAO_0, AO_OFF),
        MESON_PIN(GPIOAO_1, AO_OFF),
        MESON_PIN(GPIOAO_2, AO_OFF),
@@ -379,7 +382,7 @@ static const unsigned int uart_rx_ao_b1_pins[] = { PIN(GPIOAO_5, AO_OFF) };
 static const unsigned int i2c_mst_sck_ao_pins[] = { PIN(GPIOAO_4, AO_OFF) };
 static const unsigned int i2c_mst_sda_ao_pins[] = { PIN(GPIOAO_5, AO_OFF) };
 
-static struct meson_pmx_group meson8_groups[] = {
+static struct meson_pmx_group meson8_cbus_groups[] = {
        GPIO_GROUP(GPIOX_0, 0),
        GPIO_GROUP(GPIOX_1, 0),
        GPIO_GROUP(GPIOX_2, 0),
@@ -474,22 +477,6 @@ static struct meson_pmx_group meson8_groups[] = {
        GPIO_GROUP(GPIOZ_12, 0),
        GPIO_GROUP(GPIOZ_13, 0),
        GPIO_GROUP(GPIOZ_14, 0),
-       GPIO_GROUP(GPIOAO_0, AO_OFF),
-       GPIO_GROUP(GPIOAO_1, AO_OFF),
-       GPIO_GROUP(GPIOAO_2, AO_OFF),
-       GPIO_GROUP(GPIOAO_3, AO_OFF),
-       GPIO_GROUP(GPIOAO_4, AO_OFF),
-       GPIO_GROUP(GPIOAO_5, AO_OFF),
-       GPIO_GROUP(GPIOAO_6, AO_OFF),
-       GPIO_GROUP(GPIOAO_7, AO_OFF),
-       GPIO_GROUP(GPIOAO_8, AO_OFF),
-       GPIO_GROUP(GPIOAO_9, AO_OFF),
-       GPIO_GROUP(GPIOAO_10, AO_OFF),
-       GPIO_GROUP(GPIOAO_11, AO_OFF),
-       GPIO_GROUP(GPIOAO_12, AO_OFF),
-       GPIO_GROUP(GPIOAO_13, AO_OFF),
-       GPIO_GROUP(GPIO_BSD_EN, AO_OFF),
-       GPIO_GROUP(GPIO_TEST_N, AO_OFF),
 
        /* bank X */
        GROUP(sd_d0_a,          8,      5),
@@ -675,26 +662,45 @@ static struct meson_pmx_group meson8_groups[] = {
        GROUP(sdxc_d0_b,        2,      7),
        GROUP(sdxc_clk_b,       2,      5),
        GROUP(sdxc_cmd_b,       2,      4),
+};
+
+static struct meson_pmx_group meson8_aobus_groups[] = {
+       GPIO_GROUP(GPIOAO_0, AO_OFF),
+       GPIO_GROUP(GPIOAO_1, AO_OFF),
+       GPIO_GROUP(GPIOAO_2, AO_OFF),
+       GPIO_GROUP(GPIOAO_3, AO_OFF),
+       GPIO_GROUP(GPIOAO_4, AO_OFF),
+       GPIO_GROUP(GPIOAO_5, AO_OFF),
+       GPIO_GROUP(GPIOAO_6, AO_OFF),
+       GPIO_GROUP(GPIOAO_7, AO_OFF),
+       GPIO_GROUP(GPIOAO_8, AO_OFF),
+       GPIO_GROUP(GPIOAO_9, AO_OFF),
+       GPIO_GROUP(GPIOAO_10, AO_OFF),
+       GPIO_GROUP(GPIOAO_11, AO_OFF),
+       GPIO_GROUP(GPIOAO_12, AO_OFF),
+       GPIO_GROUP(GPIOAO_13, AO_OFF),
+       GPIO_GROUP(GPIO_BSD_EN, AO_OFF),
+       GPIO_GROUP(GPIO_TEST_N, AO_OFF),
 
        /* bank AO */
-       GROUP_AO(uart_tx_ao_a,          0,      12),
-       GROUP_AO(uart_rx_ao_a,          0,      11),
-       GROUP_AO(uart_cts_ao_a,         0,      10),
-       GROUP_AO(uart_rts_ao_a,         0,      9),
+       GROUP(uart_tx_ao_a,             0,      12),
+       GROUP(uart_rx_ao_a,             0,      11),
+       GROUP(uart_cts_ao_a,            0,      10),
+       GROUP(uart_rts_ao_a,            0,      9),
 
-       GROUP_AO(remote_input,          0,      0),
+       GROUP(remote_input,             0,      0),
 
-       GROUP_AO(i2c_slave_sck_ao,      0,      2),
-       GROUP_AO(i2c_slave_sda_ao,      0,      1),
+       GROUP(i2c_slave_sck_ao,         0,      2),
+       GROUP(i2c_slave_sda_ao,         0,      1),
 
-       GROUP_AO(uart_tx_ao_b0,         0,      26),
-       GROUP_AO(uart_rx_ao_b0,         0,      25),
+       GROUP(uart_tx_ao_b0,            0,      26),
+       GROUP(uart_rx_ao_b0,            0,      25),
 
-       GROUP_AO(uart_tx_ao_b1,         0,      24),
-       GROUP_AO(uart_rx_ao_b1,         0,      23),
+       GROUP(uart_tx_ao_b1,            0,      24),
+       GROUP(uart_rx_ao_b1,            0,      23),
 
-       GROUP_AO(i2c_mst_sck_ao,        0,      6),
-       GROUP_AO(i2c_mst_sda_ao,        0,      5),
+       GROUP(i2c_mst_sck_ao,           0,      6),
+       GROUP(i2c_mst_sda_ao,           0,      5),
 };
 
 static const char * const gpio_groups[] = {
@@ -872,7 +878,7 @@ static const char * const i2c_mst_ao_groups[] = {
        "i2c_mst_sck_ao", "i2c_mst_sda_ao"
 };
 
-static struct meson_pmx_func meson8_functions[] = {
+static struct meson_pmx_func meson8_cbus_functions[] = {
        FUNCTION(gpio),
        FUNCTION(sd_a),
        FUNCTION(sdxc_a),
@@ -899,6 +905,9 @@ static struct meson_pmx_func meson8_functions[] = {
        FUNCTION(nor),
        FUNCTION(sd_b),
        FUNCTION(sdxc_b),
+};
+
+static struct meson_pmx_func meson8_aobus_functions[] = {
        FUNCTION(uart_ao),
        FUNCTION(remote),
        FUNCTION(i2c_slave_ao),
@@ -906,7 +915,7 @@ static struct meson_pmx_func meson8_functions[] = {
        FUNCTION(i2c_mst_ao),
 };
 
-static struct meson_bank meson8_banks[] = {
+static struct meson_bank meson8_cbus_banks[] = {
        /*   name    first             last                 pullen  pull    dir     out     in  */
        BANK("X",    PIN(GPIOX_0, 0),  PIN(GPIOX_21, 0),    4,  0,  4,  0,  0,  0,  1,  0,  2,  0),
        BANK("Y",    PIN(GPIOY_0, 0),  PIN(GPIOY_16, 0),    3,  0,  3,  0,  3,  0,  4,  0,  5,  0),
@@ -917,35 +926,43 @@ static struct meson_bank meson8_banks[] = {
        BANK("BOOT", PIN(BOOT_0, 0),   PIN(BOOT_18, 0),     2,  0,  2,  0,  9,  0, 10,  0, 11,  0),
 };
 
-static struct meson_bank meson8_ao_banks[] = {
+static struct meson_bank meson8_aobus_banks[] = {
        /*   name    first                  last                      pullen  pull    dir     out     in  */
        BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
 };
 
-static struct meson_domain_data meson8_domain_data[] = {
-       {
-               .name           = "banks",
-               .banks          = meson8_banks,
-               .num_banks      = ARRAY_SIZE(meson8_banks),
-               .pin_base       = 0,
-               .num_pins       = 120,
-       },
-       {
-               .name           = "ao-bank",
-               .banks          = meson8_ao_banks,
-               .num_banks      = ARRAY_SIZE(meson8_ao_banks),
-               .pin_base       = 120,
-               .num_pins       = 16,
-       },
-};
-
-struct meson_pinctrl_data meson8_pinctrl_data = {
-       .pins           = meson8_pins,
-       .groups         = meson8_groups,
-       .funcs          = meson8_functions,
-       .domain_data    = meson8_domain_data,
-       .num_pins       = ARRAY_SIZE(meson8_pins),
-       .num_groups     = ARRAY_SIZE(meson8_groups),
-       .num_funcs      = ARRAY_SIZE(meson8_functions),
-       .num_domains    = ARRAY_SIZE(meson8_domain_data),
+static struct meson_domain_data meson8_cbus_domain_data = {
+       .name           = "cbus-banks",
+       .banks          = meson8_cbus_banks,
+       .num_banks      = ARRAY_SIZE(meson8_cbus_banks),
+       .pin_base       = 0,
+       .num_pins       = 120,
+};
+
+static struct meson_domain_data meson8_aobus_domain_data = {
+       .name           = "ao-bank",
+       .banks          = meson8_aobus_banks,
+       .num_banks      = ARRAY_SIZE(meson8_aobus_banks),
+       .pin_base       = 120,
+       .num_pins       = 16,
+};
+
+struct meson_pinctrl_data meson8_cbus_pinctrl_data = {
+       .pins           = meson8_cbus_pins,
+       .groups         = meson8_cbus_groups,
+       .funcs          = meson8_cbus_functions,
+       .domain_data    = &meson8_cbus_domain_data,
+       .num_pins       = ARRAY_SIZE(meson8_cbus_pins),
+       .num_groups     = ARRAY_SIZE(meson8_cbus_groups),
+       .num_funcs      = ARRAY_SIZE(meson8_cbus_functions),
+};
+
+struct meson_pinctrl_data meson8_aobus_pinctrl_data = {
+       .pins           = meson8_aobus_pins,
+       .groups         = meson8_aobus_groups,
+       .funcs          = meson8_aobus_functions,
+       .domain_data    = &meson8_aobus_domain_data,
+       .num_pins       = ARRAY_SIZE(meson8_aobus_pins),
+       .num_groups     = ARRAY_SIZE(meson8_aobus_groups),
+       .num_funcs      = ARRAY_SIZE(meson8_aobus_functions),
 };
index 9677807db364d70ee4512799e26449bccba56a08..a100bcf4b17fd2df70add9802b319a9ede90eb26 100644 (file)
@@ -17,7 +17,7 @@
 
 #define AO_OFF 130
 
-static const struct pinctrl_pin_desc meson8b_pins[] = {
+static const struct pinctrl_pin_desc meson8b_cbus_pins[] = {
        MESON_PIN(GPIOX_0, 0),
        MESON_PIN(GPIOX_1, 0),
        MESON_PIN(GPIOX_2, 0),
@@ -107,7 +107,9 @@ static const struct pinctrl_pin_desc meson8b_pins[] = {
        MESON_PIN(DIF_3_N, 0),
        MESON_PIN(DIF_4_P, 0),
        MESON_PIN(DIF_4_N, 0),
+};
 
+static const struct pinctrl_pin_desc meson8b_aobus_pins[] = {
        MESON_PIN(GPIOAO_0, AO_OFF),
        MESON_PIN(GPIOAO_1, AO_OFF),
        MESON_PIN(GPIOAO_2, AO_OFF),
@@ -346,7 +348,7 @@ static const unsigned int eth_ref_clk_pins[]        = { PIN(DIF_3_N, 0) };
 static const unsigned int eth_mdc_pins[]       = { PIN(DIF_4_P, 0) };
 static const unsigned int eth_mdio_en_pins[]   = { PIN(DIF_4_N, 0) };
 
-static struct meson_pmx_group meson8b_groups[] = {
+static struct meson_pmx_group meson8b_cbus_groups[] = {
        GPIO_GROUP(GPIOX_0, 0),
        GPIO_GROUP(GPIOX_1, 0),
        GPIO_GROUP(GPIOX_2, 0),
@@ -409,23 +411,6 @@ static struct meson_pmx_group meson8b_groups[] = {
        GPIO_GROUP(DIF_4_P, 0),
        GPIO_GROUP(DIF_4_N, 0),
 
-       GPIO_GROUP(GPIOAO_0, AO_OFF),
-       GPIO_GROUP(GPIOAO_1, AO_OFF),
-       GPIO_GROUP(GPIOAO_2, AO_OFF),
-       GPIO_GROUP(GPIOAO_3, AO_OFF),
-       GPIO_GROUP(GPIOAO_4, AO_OFF),
-       GPIO_GROUP(GPIOAO_5, AO_OFF),
-       GPIO_GROUP(GPIOAO_6, AO_OFF),
-       GPIO_GROUP(GPIOAO_7, AO_OFF),
-       GPIO_GROUP(GPIOAO_8, AO_OFF),
-       GPIO_GROUP(GPIOAO_9, AO_OFF),
-       GPIO_GROUP(GPIOAO_10, AO_OFF),
-       GPIO_GROUP(GPIOAO_11, AO_OFF),
-       GPIO_GROUP(GPIOAO_12, AO_OFF),
-       GPIO_GROUP(GPIOAO_13, AO_OFF),
-       GPIO_GROUP(GPIO_BSD_EN, AO_OFF),
-       GPIO_GROUP(GPIO_TEST_N, AO_OFF),
-
        /* bank X */
        GROUP(sd_d0_a,          8,      5),
        GROUP(sd_d1_a,          8,      4),
@@ -572,6 +557,37 @@ static struct meson_pmx_group meson8b_groups[] = {
        GROUP(sdxc_clk_b,       2,      5),
        GROUP(sdxc_cmd_b,       2,      4),
 
+       /* bank DIF */
+       GROUP(eth_rxd1,         6,      0),
+       GROUP(eth_rxd0,         6,      1),
+       GROUP(eth_rx_dv,        6,      2),
+       GROUP(eth_rx_clk,       6,      3),
+       GROUP(eth_txd0_1,       6,      4),
+       GROUP(eth_txd1_1,       6,      5),
+       GROUP(eth_tx_en,        6,      0),
+       GROUP(eth_ref_clk,      6,      8),
+       GROUP(eth_mdc,          6,      9),
+       GROUP(eth_mdio_en,      6,      10),
+};
+
+static struct meson_pmx_group meson8b_aobus_groups[] = {
+       GPIO_GROUP(GPIOAO_0, AO_OFF),
+       GPIO_GROUP(GPIOAO_1, AO_OFF),
+       GPIO_GROUP(GPIOAO_2, AO_OFF),
+       GPIO_GROUP(GPIOAO_3, AO_OFF),
+       GPIO_GROUP(GPIOAO_4, AO_OFF),
+       GPIO_GROUP(GPIOAO_5, AO_OFF),
+       GPIO_GROUP(GPIOAO_6, AO_OFF),
+       GPIO_GROUP(GPIOAO_7, AO_OFF),
+       GPIO_GROUP(GPIOAO_8, AO_OFF),
+       GPIO_GROUP(GPIOAO_9, AO_OFF),
+       GPIO_GROUP(GPIOAO_10, AO_OFF),
+       GPIO_GROUP(GPIOAO_11, AO_OFF),
+       GPIO_GROUP(GPIOAO_12, AO_OFF),
+       GPIO_GROUP(GPIOAO_13, AO_OFF),
+       GPIO_GROUP(GPIO_BSD_EN, AO_OFF),
+       GPIO_GROUP(GPIO_TEST_N, AO_OFF),
+
        /* bank AO */
        GROUP(uart_tx_ao_a,     0,      12),
        GROUP(uart_rx_ao_a,     0,      11),
@@ -601,18 +617,6 @@ static struct meson_pmx_group meson8b_groups[] = {
        GROUP(i2s_in_ch01,      0,      13),
        GROUP(i2s_ao_clk_in,    0,      15),
        GROUP(i2s_lr_clk_in,    0,      14),
-
-       /* bank DIF */
-       GROUP(eth_rxd1,         6,      0),
-       GROUP(eth_rxd0,         6,      1),
-       GROUP(eth_rx_dv,        6,      2),
-       GROUP(eth_rx_clk,       6,      3),
-       GROUP(eth_txd0_1,       6,      4),
-       GROUP(eth_txd1_1,       6,      5),
-       GROUP(eth_tx_en,        6,      0),
-       GROUP(eth_ref_clk,      6,      8),
-       GROUP(eth_mdc,          6,      9),
-       GROUP(eth_mdio_en,      6,      10),
 };
 
 static const char * const gpio_groups[] = {
@@ -694,7 +698,10 @@ static const char * const i2c_c_groups[] = {
 };
 
 static const char * const hdmi_groups[] = {
-       "hdmi_hpd", "hdmi_sda", "hdmi_scl", "hdmi_cec_0",
+       "hdmi_hpd", "hdmi_sda", "hdmi_scl", "hdmi_cec_0"
+};
+
+static const char * const hdmi_cec_groups[] = {
        "hdmi_cec_1"
 };
 
@@ -770,12 +777,20 @@ static const char * const i2c_mst_ao_groups[] = {
        "i2c_mst_sck_ao", "i2c_mst_sda_ao"
 };
 
-static const char * const clk_groups[] = {
-       "clk_24m_out", "clk_32k_in_out"
+static const char * const clk_24m_groups[] = {
+       "clk_24m_out"
 };
 
-static const char * const spdif_groups[] = {
-       "spdif_out_1", "spdif_out_0"
+static const char * const clk_32k_groups[] = {
+       "clk_32k_in_out"
+};
+
+static const char * const spdif_0_groups[] = {
+       "spdif_out_0"
+};
+
+static const char * const spdif_1_groups[] = {
+       "spdif_out_1"
 };
 
 static const char * const i2s_groups[] = {
@@ -789,7 +804,11 @@ static const char * const pwm_b_groups[] = {
 };
 
 static const char * const pwm_c_groups[] = {
-       "pwm_c0", "pwm_c1", "pwm_c2"
+       "pwm_c0", "pwm_c1"
+};
+
+static const char * const pwm_c_ao_groups[] = {
+       "pwm_c2"
 };
 
 static const char * const pwm_d_groups[] = {
@@ -814,7 +833,7 @@ static const char * const tsin_b_groups[] = {
        "tsin_d0_b", "tsin_clk_b", "tsin_sop_b", "tsin_d_valid_b"
 };
 
-static struct meson_pmx_func meson8b_functions[] = {
+static struct meson_pmx_func meson8b_cbus_functions[] = {
        FUNCTION(gpio),
        FUNCTION(sd_a),
        FUNCTION(sdxc_a),
@@ -837,14 +856,7 @@ static struct meson_pmx_func meson8b_functions[] = {
        FUNCTION(nor),
        FUNCTION(sd_b),
        FUNCTION(sdxc_b),
-       FUNCTION(uart_ao),
-       FUNCTION(remote),
-       FUNCTION(i2c_slave_ao),
-       FUNCTION(uart_ao_b),
-       FUNCTION(i2c_mst_ao),
-       FUNCTION(clk),
-       FUNCTION(spdif),
-       FUNCTION(i2s),
+       FUNCTION(spdif_0),
        FUNCTION(pwm_b),
        FUNCTION(pwm_c),
        FUNCTION(pwm_d),
@@ -852,9 +864,23 @@ static struct meson_pmx_func meson8b_functions[] = {
        FUNCTION(pwm_vs),
        FUNCTION(tsin_a),
        FUNCTION(tsin_b),
+       FUNCTION(clk_24m),
+};
+
+static struct meson_pmx_func meson8b_aobus_functions[] = {
+       FUNCTION(uart_ao),
+       FUNCTION(uart_ao_b),
+       FUNCTION(i2c_slave_ao),
+       FUNCTION(i2c_mst_ao),
+       FUNCTION(i2s),
+       FUNCTION(remote),
+       FUNCTION(clk_32k),
+       FUNCTION(pwm_c_ao),
+       FUNCTION(spdif_1),
+       FUNCTION(hdmi_cec),
 };
 
-static struct meson_bank meson8b_banks[] = {
+static struct meson_bank meson8b_cbus_banks[] = {
        /*   name    first                      last                   pullen  pull    dir     out     in  */
        BANK("X",    PIN(GPIOX_0, 0),           PIN(GPIOX_21, 0),      4,  0,  4,  0,  0,  0,  1,  0,  2,  0),
        BANK("Y",    PIN(GPIOY_0, 0),           PIN(GPIOY_14, 0),      3,  0,  3,  0,  3,  0,  4,  0,  5,  0),
@@ -865,35 +891,43 @@ static struct meson_bank meson8b_banks[] = {
        BANK("DIF",  PIN(DIF_0_P, 0),           PIN(DIF_4_N, 0),       5,  8,  5,  8, 12, 12, 13, 12, 14, 12),
 };
 
-static struct meson_bank meson8b_ao_banks[] = {
+static struct meson_bank meson8b_aobus_banks[] = {
        /*   name    first                  last                      pullen  pull    dir     out     in  */
        BANK("AO",   PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
 };
 
-static struct meson_domain_data meson8b_domain_data[] = {
-       {
-               .name           = "banks",
-               .banks          = meson8b_banks,
-               .num_banks      = ARRAY_SIZE(meson8b_banks),
-               .pin_base       = 0,
-               .num_pins       = 130,
-       },
-       {
-               .name           = "ao-bank",
-               .banks          = meson8b_ao_banks,
-               .num_banks      = ARRAY_SIZE(meson8b_ao_banks),
-               .pin_base       = 130,
-               .num_pins       = 16,
-       },
-};
-
-struct meson_pinctrl_data meson8b_pinctrl_data = {
-       .pins           = meson8b_pins,
-       .groups         = meson8b_groups,
-       .funcs          = meson8b_functions,
-       .domain_data    = meson8b_domain_data,
-       .num_pins       = ARRAY_SIZE(meson8b_pins),
-       .num_groups     = ARRAY_SIZE(meson8b_groups),
-       .num_funcs      = ARRAY_SIZE(meson8b_functions),
-       .num_domains    = ARRAY_SIZE(meson8b_domain_data),
+static struct meson_domain_data meson8b_cbus_domain_data = {
+       .name           = "cbus-banks",
+       .banks          = meson8b_cbus_banks,
+       .num_banks      = ARRAY_SIZE(meson8b_cbus_banks),
+       .pin_base       = 0,
+       .num_pins       = 130,
+};
+
+static struct meson_domain_data meson8b_aobus_domain_data = {
+       .name           = "aobus-banks",
+       .banks          = meson8b_aobus_banks,
+       .num_banks      = ARRAY_SIZE(meson8b_aobus_banks),
+       .pin_base       = 130,
+       .num_pins       = 16,
+};
+
+struct meson_pinctrl_data meson8b_cbus_pinctrl_data = {
+       .pins           = meson8b_cbus_pins,
+       .groups         = meson8b_cbus_groups,
+       .funcs          = meson8b_cbus_functions,
+       .domain_data    = &meson8b_cbus_domain_data,
+       .num_pins       = ARRAY_SIZE(meson8b_cbus_pins),
+       .num_groups     = ARRAY_SIZE(meson8b_cbus_groups),
+       .num_funcs      = ARRAY_SIZE(meson8b_cbus_functions),
+};
+
+struct meson_pinctrl_data meson8b_aobus_pinctrl_data = {
+       .pins           = meson8b_aobus_pins,
+       .groups         = meson8b_aobus_groups,
+       .funcs          = meson8b_aobus_functions,
+       .domain_data    = &meson8b_aobus_domain_data,
+       .num_pins       = ARRAY_SIZE(meson8b_aobus_pins),
+       .num_groups     = ARRAY_SIZE(meson8b_aobus_groups),
+       .num_funcs      = ARRAY_SIZE(meson8b_aobus_functions),
 };
index 587b222f12f3cf2239b35d71b83de1a287ef9e27..e852048c4c04117c777f11fd17778f330f573d7d 100644 (file)
@@ -287,6 +287,10 @@ static const unsigned i2c0_a_1_pins[] = { STN8815_PIN_D3, STN8815_PIN_D2 };
 /* Altfunction B */
 static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 };
 static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 };
+static const unsigned clcd_16_23_b_1_pins[] = { STN8815_PIN_AB6,
+       STN8815_PIN_AA6, STN8815_PIN_Y6, STN8815_PIN_Y5, STN8815_PIN_AA5,
+       STN8815_PIN_AB5, STN8815_PIN_AB4, STN8815_PIN_Y4 };
+
 
 #define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,                \
                        .npins = ARRAY_SIZE(a##_pins), .altsetting = b }
@@ -302,6 +306,7 @@ static const struct nmk_pingroup nmk_stn8815_groups[] = {
        STN8815_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
        STN8815_PIN_GROUP(u1_b_1, NMK_GPIO_ALT_B),
        STN8815_PIN_GROUP(i2cusb_b_1, NMK_GPIO_ALT_B),
+       STN8815_PIN_GROUP(clcd_16_23_b_1, NMK_GPIO_ALT_B),
 };
 
 /* We use this macro to define the groups applicable to a function */
@@ -314,6 +319,7 @@ STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1");
 STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1");
 STN8815_FUNC_GROUPS(i2c0, "i2c0_a_1");
 STN8815_FUNC_GROUPS(i2cusb, "i2cusb_b_1");
+STN8815_FUNC_GROUPS(clcd, "clcd_16_23_b_1");
 
 #define FUNCTION(fname)                                        \
        {                                               \
@@ -329,6 +335,7 @@ static const struct nmk_function nmk_stn8815_functions[] = {
        FUNCTION(i2c1),
        FUNCTION(i2c0),
        FUNCTION(i2cusb),
+       FUNCTION(clcd),
 };
 
 static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = {
index 657449431301f120fd0b6f28a063670b42071853..5c025f5b504844cad43aa7759eb4a01b285f1b9f 100644 (file)
@@ -753,8 +753,8 @@ static int amd_gpio_probe(struct platform_device *pdev)
 
        gpio_dev->base = devm_ioremap_nocache(&pdev->dev, res->start,
                                                resource_size(res));
-       if (IS_ERR(gpio_dev->base))
-               return PTR_ERR(gpio_dev->base);
+       if (!gpio_dev->base)
+               return -ENOMEM;
 
        irq_base = platform_get_irq(pdev, 0);
        if (irq_base < 0) {
index ee69db6ae1c7e9f3171ca42b92741a683dd8f7e8..4429312e848dba2af05ddb3d9da6cb3b2b176248 100644 (file)
@@ -824,7 +824,7 @@ static struct pinctrl_desc atmel_pinctrl_desc = {
        .pmxops         = &atmel_pmxops,
 };
 
-static int atmel_pctrl_suspend(struct device *dev)
+static int __maybe_unused atmel_pctrl_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev);
@@ -844,7 +844,7 @@ static int atmel_pctrl_suspend(struct device *dev)
        return 0;
 }
 
-static int atmel_pctrl_resume(struct device *dev)
+static int __maybe_unused atmel_pctrl_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev);
index cf7788df0f954a964362e21f4515a0ac87d70d0c..741b39eaeb8be83e1577d196ee5b2b3f248f0a3d 100644 (file)
@@ -127,7 +127,7 @@ struct u300_gpio_confdata {
 }
 
 /* Initial configuration */
-static const struct __initconst u300_gpio_confdata
+static const struct u300_gpio_confdata __initconst
 bs335_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
        /* Port 0, pins 0-7 */
        {
index f0bebbe0682b9b18b622f47bc7cf5471e503ec92..b1767f7e45d10ed582c174165d75fa80b9606343 100644 (file)
 
 #define LPC18XX_SCU_FUNC_PER_PIN       8
 
+/* LPC18XX SCU pin interrupt select registers */
+#define LPC18XX_SCU_PINTSEL0           0xe00
+#define LPC18XX_SCU_PINTSEL1           0xe04
+#define LPC18XX_SCU_PINTSEL_VAL_MASK   0xff
+#define LPC18XX_SCU_PINTSEL_PORT_SHIFT 5
+#define LPC18XX_SCU_IRQ_PER_PINTSEL    4
+#define LPC18XX_GPIO_PINS_PER_PORT     32
+#define LPC18XX_GPIO_PIN_INT_MAX       8
+
+#define LPC18XX_SCU_PINTSEL_VAL(val, n) \
+       ((val) << (((n) % LPC18XX_SCU_IRQ_PER_PINTSEL) * 8))
+
 /* LPC18xx pin types */
 enum {
        TYPE_ND,        /* Normal-drive */
@@ -618,6 +630,25 @@ static const struct pinctrl_pin_desc lpc18xx_pins[] = {
        LPC18XX_PIN(i2c0_sda, PIN_I2C0_SDA),
 };
 
+/**
+ * enum lpc18xx_pin_config_param - possible pin configuration parameters
+ * @PIN_CONFIG_GPIO_PIN_INT: route gpio to the gpio pin interrupt
+ *     controller.
+ */
+enum lpc18xx_pin_config_param {
+       PIN_CONFIG_GPIO_PIN_INT = PIN_CONFIG_END + 1,
+};
+
+static const struct pinconf_generic_params lpc18xx_params[] = {
+       {"nxp,gpio-pin-interrupt", PIN_CONFIG_GPIO_PIN_INT, 0},
+};
+
+#ifdef CONFIG_DEBUG_FS
+static const struct pin_config_item lpc18xx_conf_items[ARRAY_SIZE(lpc18xx_params)] = {
+       PCONFDUMP(PIN_CONFIG_GPIO_PIN_INT, "gpio pin int", NULL, true),
+};
+#endif
+
 static int lpc18xx_pconf_get_usb1(enum pin_config_param param, int *arg, u32 reg)
 {
        switch (param) {
@@ -693,7 +724,71 @@ static int lpc18xx_pconf_get_i2c0(enum pin_config_param param, int *arg, u32 reg
        return 0;
 }
 
-static int lpc18xx_pconf_get_pin(enum pin_config_param param, int *arg, u32 reg,
+static int lpc18xx_pin_to_gpio(struct pinctrl_dev *pctldev, unsigned pin)
+{
+       struct pinctrl_gpio_range *range;
+
+       range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin);
+       if (!range)
+               return -EINVAL;
+
+       return pin - range->pin_base + range->base;
+}
+
+static int lpc18xx_get_pintsel(void __iomem *addr, u32 val, int *arg)
+{
+       u32 reg_val;
+       int i;
+
+       reg_val = readl(addr);
+       for (i = 0; i < LPC18XX_SCU_IRQ_PER_PINTSEL; i++) {
+               if ((reg_val & LPC18XX_SCU_PINTSEL_VAL_MASK) == val)
+                       return 0;
+
+               reg_val >>= BITS_PER_BYTE;
+               *arg += 1;
+       }
+
+       return -EINVAL;
+}
+
+static u32 lpc18xx_gpio_to_pintsel_val(int gpio)
+{
+       unsigned int gpio_port, gpio_pin;
+
+       gpio_port = gpio / LPC18XX_GPIO_PINS_PER_PORT;
+       gpio_pin  = gpio % LPC18XX_GPIO_PINS_PER_PORT;
+
+       return gpio_pin | (gpio_port << LPC18XX_SCU_PINTSEL_PORT_SHIFT);
+}
+
+static int lpc18xx_pconf_get_gpio_pin_int(struct pinctrl_dev *pctldev,
+                                         int *arg, unsigned pin)
+{
+       struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev);
+       int gpio, ret;
+       u32 val;
+
+       gpio = lpc18xx_pin_to_gpio(pctldev, pin);
+       if (gpio < 0)
+               return -ENOTSUPP;
+
+       val = lpc18xx_gpio_to_pintsel_val(gpio);
+
+       /*
+        * Check if this pin has been enabled as a interrupt in any of the two
+        * PINTSEL registers. *arg indicates which interrupt number (0-7).
+        */
+       *arg = 0;
+       ret = lpc18xx_get_pintsel(scu->base + LPC18XX_SCU_PINTSEL0, val, arg);
+       if (ret == 0)
+               return ret;
+
+       return lpc18xx_get_pintsel(scu->base + LPC18XX_SCU_PINTSEL1, val, arg);
+}
+
+static int lpc18xx_pconf_get_pin(struct pinctrl_dev *pctldev, unsigned param,
+                                int *arg, u32 reg, unsigned pin,
                                 struct lpc18xx_pin_caps *pin_cap)
 {
        switch (param) {
@@ -755,6 +850,9 @@ static int lpc18xx_pconf_get_pin(enum pin_config_param param, int *arg, u32 reg,
                }
                break;
 
+       case PIN_CONFIG_GPIO_PIN_INT:
+               return lpc18xx_pconf_get_gpio_pin_int(pctldev, arg, pin);
+
        default:
                return -ENOTSUPP;
        }
@@ -794,7 +892,7 @@ static int lpc18xx_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
        else if (pin_cap->type == TYPE_USB1)
                ret = lpc18xx_pconf_get_usb1(param, &arg, reg);
        else
-               ret = lpc18xx_pconf_get_pin(param, &arg, reg, pin_cap);
+               ret = lpc18xx_pconf_get_pin(pctldev, param, &arg, reg, pin, pin_cap);
 
        if (ret < 0)
                return ret;
@@ -883,9 +981,34 @@ static int lpc18xx_pconf_set_i2c0(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev,
-                                enum pin_config_param param,
-                                u16 param_val, u32 *reg,
+static int lpc18xx_pconf_set_gpio_pin_int(struct pinctrl_dev *pctldev,
+                                         u16 param_val, unsigned pin)
+{
+       struct lpc18xx_scu_data *scu = pinctrl_dev_get_drvdata(pctldev);
+       u32 val, reg_val, reg_offset = LPC18XX_SCU_PINTSEL0;
+       int gpio;
+
+       if (param_val >= LPC18XX_GPIO_PIN_INT_MAX)
+               return -EINVAL;
+
+       gpio = lpc18xx_pin_to_gpio(pctldev, pin);
+       if (gpio < 0)
+               return -ENOTSUPP;
+
+       val = lpc18xx_gpio_to_pintsel_val(gpio);
+
+       reg_offset += (param_val / LPC18XX_SCU_IRQ_PER_PINTSEL) * sizeof(u32);
+
+       reg_val = readl(scu->base + reg_offset);
+       reg_val &= ~LPC18XX_SCU_PINTSEL_VAL(LPC18XX_SCU_PINTSEL_VAL_MASK, param_val);
+       reg_val |= LPC18XX_SCU_PINTSEL_VAL(val, param_val);
+       writel(reg_val, scu->base + reg_offset);
+
+       return 0;
+}
+
+static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, unsigned param,
+                                u16 param_val, u32 *reg, unsigned pin,
                                 struct lpc18xx_pin_caps *pin_cap)
 {
        switch (param) {
@@ -948,6 +1071,9 @@ static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev,
                *reg |= param_val << LPC18XX_SCU_PIN_EHD_POS;
                break;
 
+       case PIN_CONFIG_GPIO_PIN_INT:
+               return lpc18xx_pconf_set_gpio_pin_int(pctldev, param_val, pin);
+
        default:
                dev_err(pctldev->dev, "Property not supported\n");
                return -ENOTSUPP;
@@ -982,7 +1108,7 @@ static int lpc18xx_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
                else if (pin_cap->type == TYPE_USB1)
                        ret = lpc18xx_pconf_set_usb1(pctldev, param, param_val, &reg);
                else
-                       ret = lpc18xx_pconf_set_pin(pctldev, param, param_val, &reg, pin_cap);
+                       ret = lpc18xx_pconf_set_pin(pctldev, param, param_val, &reg, pin, pin_cap);
 
                if (ret)
                        return ret;
@@ -1136,6 +1262,11 @@ static struct pinctrl_desc lpc18xx_scu_desc = {
        .pctlops = &lpc18xx_pctl_ops,
        .pmxops = &lpc18xx_pmx_ops,
        .confops = &lpc18xx_pconf_ops,
+       .num_custom_params = ARRAY_SIZE(lpc18xx_params),
+       .custom_params = lpc18xx_params,
+#ifdef CONFIG_DEBUG_FS
+       .custom_conf_items = lpc18xx_conf_items,
+#endif
        .owner = THIS_MODULE,
 };
 
@@ -1170,9 +1301,8 @@ static int lpc18xx_create_group_func_map(struct device *dev,
        u16 pins[ARRAY_SIZE(lpc18xx_pins)];
        int func, ngroups, i;
 
-       for (func = 0; func < FUNC_MAX; ngroups = 0, func++) {
-
-               for (i = 0; i < ARRAY_SIZE(lpc18xx_pins); i++) {
+       for (func = 0; func < FUNC_MAX; func++) {
+               for (ngroups = 0, i = 0; i < ARRAY_SIZE(lpc18xx_pins); i++) {
                        if (lpc18xx_valid_pin_function(i, func))
                                pins[ngroups++] = i;
                }
diff --git a/drivers/pinctrl/pinctrl-pic32.c b/drivers/pinctrl/pinctrl-pic32.c
new file mode 100644 (file)
index 0000000..0b07d4b
--- /dev/null
@@ -0,0 +1,2312 @@
+/*
+ * PIC32 pinctrl driver
+ *
+ * Joshua Henderson, <joshua.henderson@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.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach-pic32/pic32.h>
+
+#include "pinctrl-utils.h"
+#include "pinctrl-pic32.h"
+
+#define PINS_PER_BANK          16
+
+#define PIC32_CNCON_EDGE       11
+#define PIC32_CNCON_ON         15
+
+#define PIN_CONFIG_MICROCHIP_DIGITAL   (PIN_CONFIG_END + 1)
+#define PIN_CONFIG_MICROCHIP_ANALOG    (PIN_CONFIG_END + 2)
+
+static const struct pinconf_generic_params pic32_mpp_bindings[] = {
+       {"microchip,digital",   PIN_CONFIG_MICROCHIP_DIGITAL,   0},
+       {"microchip,analog",    PIN_CONFIG_MICROCHIP_ANALOG,    0},
+};
+
+#define GPIO_BANK_START(bank)          ((bank) * PINS_PER_BANK)
+
+struct pic32_function {
+       const char *name;
+       const char * const *groups;
+       unsigned int ngroups;
+};
+
+struct pic32_pin_group {
+       const char *name;
+       unsigned int pin;
+       struct pic32_desc_function *functions;
+};
+
+struct pic32_desc_function {
+       const char *name;
+       u32 muxreg;
+       u32 muxval;
+};
+
+struct pic32_gpio_bank {
+       void __iomem *reg_base;
+       struct gpio_chip gpio_chip;
+       struct irq_chip irq_chip;
+       struct clk *clk;
+};
+
+struct pic32_pinctrl {
+       void __iomem *reg_base;
+       struct device *dev;
+       struct pinctrl_dev *pctldev;
+       const struct pinctrl_pin_desc *pins;
+       unsigned int npins;
+       const struct pic32_function *functions;
+       unsigned int nfunctions;
+       const struct pic32_pin_group *groups;
+       unsigned int ngroups;
+       struct pic32_gpio_bank *gpio_banks;
+       unsigned int nbanks;
+       struct clk *clk;
+};
+
+static const struct pinctrl_pin_desc pic32_pins[] = {
+       PINCTRL_PIN(0, "A0"),
+       PINCTRL_PIN(1, "A1"),
+       PINCTRL_PIN(2, "A2"),
+       PINCTRL_PIN(3, "A3"),
+       PINCTRL_PIN(4, "A4"),
+       PINCTRL_PIN(5, "A5"),
+       PINCTRL_PIN(6, "A6"),
+       PINCTRL_PIN(7, "A7"),
+       PINCTRL_PIN(8, "A8"),
+       PINCTRL_PIN(9, "A9"),
+       PINCTRL_PIN(10, "A10"),
+       PINCTRL_PIN(11, "A11"),
+       PINCTRL_PIN(12, "A12"),
+       PINCTRL_PIN(13, "A13"),
+       PINCTRL_PIN(14, "A14"),
+       PINCTRL_PIN(15, "A15"),
+       PINCTRL_PIN(16, "B0"),
+       PINCTRL_PIN(17, "B1"),
+       PINCTRL_PIN(18, "B2"),
+       PINCTRL_PIN(19, "B3"),
+       PINCTRL_PIN(20, "B4"),
+       PINCTRL_PIN(21, "B5"),
+       PINCTRL_PIN(22, "B6"),
+       PINCTRL_PIN(23, "B7"),
+       PINCTRL_PIN(24, "B8"),
+       PINCTRL_PIN(25, "B9"),
+       PINCTRL_PIN(26, "B10"),
+       PINCTRL_PIN(27, "B11"),
+       PINCTRL_PIN(28, "B12"),
+       PINCTRL_PIN(29, "B13"),
+       PINCTRL_PIN(30, "B14"),
+       PINCTRL_PIN(31, "B15"),
+       PINCTRL_PIN(33, "C1"),
+       PINCTRL_PIN(34, "C2"),
+       PINCTRL_PIN(35, "C3"),
+       PINCTRL_PIN(36, "C4"),
+       PINCTRL_PIN(44, "C12"),
+       PINCTRL_PIN(45, "C13"),
+       PINCTRL_PIN(46, "C14"),
+       PINCTRL_PIN(47, "C15"),
+       PINCTRL_PIN(48, "D0"),
+       PINCTRL_PIN(49, "D1"),
+       PINCTRL_PIN(50, "D2"),
+       PINCTRL_PIN(51, "D3"),
+       PINCTRL_PIN(52, "D4"),
+       PINCTRL_PIN(53, "D5"),
+       PINCTRL_PIN(54, "D6"),
+       PINCTRL_PIN(55, "D7"),
+       PINCTRL_PIN(57, "D9"),
+       PINCTRL_PIN(58, "D10"),
+       PINCTRL_PIN(59, "D11"),
+       PINCTRL_PIN(60, "D12"),
+       PINCTRL_PIN(61, "D13"),
+       PINCTRL_PIN(62, "D14"),
+       PINCTRL_PIN(63, "D15"),
+       PINCTRL_PIN(64, "E0"),
+       PINCTRL_PIN(65, "E1"),
+       PINCTRL_PIN(66, "E2"),
+       PINCTRL_PIN(67, "E3"),
+       PINCTRL_PIN(68, "E4"),
+       PINCTRL_PIN(69, "E5"),
+       PINCTRL_PIN(70, "E6"),
+       PINCTRL_PIN(71, "E7"),
+       PINCTRL_PIN(72, "E8"),
+       PINCTRL_PIN(73, "E9"),
+       PINCTRL_PIN(80, "F0"),
+       PINCTRL_PIN(81, "F1"),
+       PINCTRL_PIN(82, "F2"),
+       PINCTRL_PIN(83, "F3"),
+       PINCTRL_PIN(84, "F4"),
+       PINCTRL_PIN(85, "F5"),
+       PINCTRL_PIN(88, "F8"),
+       PINCTRL_PIN(92, "F12"),
+       PINCTRL_PIN(93, "F13"),
+       PINCTRL_PIN(96, "G0"),
+       PINCTRL_PIN(97, "G1"),
+       PINCTRL_PIN(102, "G6"),
+       PINCTRL_PIN(103, "G7"),
+       PINCTRL_PIN(104, "G8"),
+       PINCTRL_PIN(105, "G9"),
+       PINCTRL_PIN(108, "G12"),
+       PINCTRL_PIN(109, "G13"),
+       PINCTRL_PIN(110, "G14"),
+       PINCTRL_PIN(111, "G15"),
+       PINCTRL_PIN(112, "H0"),
+       PINCTRL_PIN(113, "H1"),
+       PINCTRL_PIN(114, "H2"),
+       PINCTRL_PIN(115, "H3"),
+       PINCTRL_PIN(116, "H4"),
+       PINCTRL_PIN(117, "H5"),
+       PINCTRL_PIN(118, "H6"),
+       PINCTRL_PIN(119, "H7"),
+       PINCTRL_PIN(120, "H8"),
+       PINCTRL_PIN(121, "H9"),
+       PINCTRL_PIN(122, "H10"),
+       PINCTRL_PIN(123, "H11"),
+       PINCTRL_PIN(124, "H12"),
+       PINCTRL_PIN(125, "H13"),
+       PINCTRL_PIN(126, "H14"),
+       PINCTRL_PIN(127, "H15"),
+       PINCTRL_PIN(128, "J0"),
+       PINCTRL_PIN(129, "J1"),
+       PINCTRL_PIN(130, "J2"),
+       PINCTRL_PIN(131, "J3"),
+       PINCTRL_PIN(132, "J4"),
+       PINCTRL_PIN(133, "J5"),
+       PINCTRL_PIN(134, "J6"),
+       PINCTRL_PIN(135, "J7"),
+       PINCTRL_PIN(136, "J8"),
+       PINCTRL_PIN(137, "J9"),
+       PINCTRL_PIN(138, "J10"),
+       PINCTRL_PIN(139, "J11"),
+       PINCTRL_PIN(140, "J12"),
+       PINCTRL_PIN(141, "J13"),
+       PINCTRL_PIN(142, "J14"),
+       PINCTRL_PIN(143, "J15"),
+       PINCTRL_PIN(144, "K0"),
+       PINCTRL_PIN(145, "K1"),
+       PINCTRL_PIN(146, "K2"),
+       PINCTRL_PIN(147, "K3"),
+       PINCTRL_PIN(148, "K4"),
+       PINCTRL_PIN(149, "K5"),
+       PINCTRL_PIN(150, "K6"),
+       PINCTRL_PIN(151, "K7"),
+};
+
+static const char * const pic32_input0_group[] = {
+       "D2", "G8", "F4", "F1", "B9", "B10", "C14", "B5",
+       "C1", "D14", "G1", "A14", "D6",
+};
+
+static const char * const pic32_input1_group[] = {
+       "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13",
+       "B3", "C4", "G0", "A15", "D7",
+};
+
+static const char * const pic32_input2_group[] = {
+       "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7",
+       "F12", "D12", "F8", "C3", "E9",
+};
+
+static const char * const pic32_input3_group[] = {
+       "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13",
+       "F2", "C2", "E8",
+};
+
+static const char * const pic32_output0_group[] = {
+       "D2", "G8", "F4", "D10", "F1", "B9", "B10", "C14",
+       "B5", "C1", "D14", "G1", "A14", "D6",
+};
+
+static const char * const pic32_output0_1_group[] = {
+       "D2", "G8", "F4", "D10", "F1", "B9", "B10", "C14",
+       "B5", "C1", "D14", "G1", "A14", "D6",
+       "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13",
+       "B3", "C4", "D15", "G0", "A15", "D7",
+};
+
+static const char *const pic32_output1_group[] = {
+       "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13",
+       "B3", "C4", "D15", "G0", "A15", "D7",
+};
+
+static const char *const pic32_output1_3_group[] = {
+       "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13",
+       "B3", "C4", "D15", "G0", "A15", "D7",
+       "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13",
+       "C2", "E8", "F2",
+};
+
+static const char * const pic32_output2_group[] = {
+       "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7",
+       "F12", "D12", "F8", "C3", "E9",
+};
+
+static const char * const pic32_output2_3_group[] = {
+       "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7",
+       "F12", "D12", "F8", "C3", "E9",
+       "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13",
+       "C2", "E8", "F2",
+};
+
+static const char * const pic32_output3_group[] = {
+       "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13",
+       "C2", "E8", "F2",
+};
+
+#define FUNCTION(_name, _gr)                                   \
+       {                                                       \
+               .name = #_name,                                 \
+               .groups = pic32_##_gr##_group,                  \
+               .ngroups = ARRAY_SIZE(pic32_##_gr##_group),     \
+       }
+
+static const struct pic32_function pic32_functions[] = {
+       FUNCTION(INT3, input0),
+       FUNCTION(T2CK, input0),
+       FUNCTION(T6CK, input0),
+       FUNCTION(IC3, input0),
+       FUNCTION(IC7, input0),
+       FUNCTION(U1RX, input0),
+       FUNCTION(U2CTS, input0),
+       FUNCTION(U5RX, input0),
+       FUNCTION(U6CTS, input0),
+       FUNCTION(SDI1, input0),
+       FUNCTION(SDI3, input0),
+       FUNCTION(SDI5, input0),
+       FUNCTION(SS6IN, input0),
+       FUNCTION(REFCLKI1, input0),
+       FUNCTION(INT4, input1),
+       FUNCTION(T5CK, input1),
+       FUNCTION(T7CK, input1),
+       FUNCTION(IC4, input1),
+       FUNCTION(IC8, input1),
+       FUNCTION(U3RX, input1),
+       FUNCTION(U4CTS, input1),
+       FUNCTION(SDI2, input1),
+       FUNCTION(SDI4, input1),
+       FUNCTION(C1RX, input1),
+       FUNCTION(REFCLKI4, input1),
+       FUNCTION(INT2, input2),
+       FUNCTION(T3CK, input2),
+       FUNCTION(T8CK, input2),
+       FUNCTION(IC2, input2),
+       FUNCTION(IC5, input2),
+       FUNCTION(IC9, input2),
+       FUNCTION(U1CTS, input2),
+       FUNCTION(U2RX, input2),
+       FUNCTION(U5CTS, input2),
+       FUNCTION(SS1IN, input2),
+       FUNCTION(SS3IN, input2),
+       FUNCTION(SS4IN, input2),
+       FUNCTION(SS5IN, input2),
+       FUNCTION(C2RX, input2),
+       FUNCTION(INT1, input3),
+       FUNCTION(T4CK, input3),
+       FUNCTION(T9CK, input3),
+       FUNCTION(IC1, input3),
+       FUNCTION(IC6, input3),
+       FUNCTION(U3CTS, input3),
+       FUNCTION(U4RX, input3),
+       FUNCTION(U6RX, input3),
+       FUNCTION(SS2IN, input3),
+       FUNCTION(SDI6, input3),
+       FUNCTION(OCFA, input3),
+       FUNCTION(REFCLKI3, input3),
+       FUNCTION(U3TX, output0),
+       FUNCTION(U4RTS, output0),
+       FUNCTION(SDO1, output0_1),
+       FUNCTION(SDO2, output0_1),
+       FUNCTION(SDO3, output0_1),
+       FUNCTION(SDO5, output0_1),
+       FUNCTION(SS6OUT, output0),
+       FUNCTION(OC3, output0),
+       FUNCTION(OC6, output0),
+       FUNCTION(REFCLKO4, output0),
+       FUNCTION(C2OUT, output0),
+       FUNCTION(C1TX, output0),
+       FUNCTION(U1TX, output1),
+       FUNCTION(U2RTS, output1),
+       FUNCTION(U5TX, output1),
+       FUNCTION(U6RTS, output1),
+       FUNCTION(SDO4, output1_3),
+       FUNCTION(OC4, output1),
+       FUNCTION(OC7, output1),
+       FUNCTION(REFCLKO1, output1),
+       FUNCTION(U3RTS, output2),
+       FUNCTION(U4TX, output2),
+       FUNCTION(U6TX, output2_3),
+       FUNCTION(SS1OUT, output2),
+       FUNCTION(SS3OUT, output2),
+       FUNCTION(SS4OUT, output2),
+       FUNCTION(SS5OUT, output2),
+       FUNCTION(SDO6, output2_3),
+       FUNCTION(OC5, output2),
+       FUNCTION(OC8, output2),
+       FUNCTION(C1OUT, output2),
+       FUNCTION(REFCLKO3, output2),
+       FUNCTION(U1RTS, output3),
+       FUNCTION(U2TX, output3),
+       FUNCTION(U5RTS, output3),
+       FUNCTION(SS2OUT, output3),
+       FUNCTION(OC2, output3),
+       FUNCTION(OC1, output3),
+       FUNCTION(OC9, output3),
+       FUNCTION(C2TX, output3),
+};
+
+#define PIC32_PINCTRL_GROUP(_pin, _name, ...)                          \
+       {                                                               \
+               .name = #_name,                                         \
+               .pin = _pin,                                            \
+               .functions = (struct pic32_desc_function[]){            \
+                       __VA_ARGS__, { } },                             \
+       }
+
+#define PIC32_PINCTRL_FUNCTION(_name, _muxreg, _muxval)        \
+       {                                               \
+               .name = #_name,                         \
+               .muxreg = _muxreg,                      \
+               .muxval = _muxval,                      \
+       }
+
+static const struct pic32_pin_group pic32_groups[] = {
+       PIC32_PINCTRL_GROUP(14, A14,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 13),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 13),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 13),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 13),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 13),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 13),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 13),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 13),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 13),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 13),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 13),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 13),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 13),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 13),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPA14R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPA14R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPA14R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPA14R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPA14R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPA14R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPA14R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPA14R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPA14R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPA14R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPA14R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPA14R, 15)),
+       PIC32_PINCTRL_GROUP(15, A15,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 13),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 13),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 13),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 13),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 13),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 13),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 13),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 13),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 13),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 13),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 13),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPA15R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPA15R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPA15R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPA15R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPA15R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPA15R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPA15R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPA15R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPA15R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPA15R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPA15R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPA15R, 15)),
+       PIC32_PINCTRL_GROUP(16, B0,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 5),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 5),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 5),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 5),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 5),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 5),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 5),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 5),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 5),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 5),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 5),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 5),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 5),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPB0R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPB0R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPB0R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPB0R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPB0R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPB0R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPB0R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPB0R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPB0R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPB0R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPB0R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB0R, 15)),
+       PIC32_PINCTRL_GROUP(17, B1,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 5),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 5),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 5),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 5),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 5),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 5),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 5),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 5),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 5),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 5),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPB1R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPB1R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPB1R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPB1R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPB1R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPB1R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPB1R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPB1R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPB1R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPB1R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPB1R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPB1R, 15)),
+       PIC32_PINCTRL_GROUP(18, B2,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 7),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 7),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 7),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 7),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 7),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 7),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 7),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 7),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 7),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 7),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 7),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 7),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPB2R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPB2R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPB2R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPB2R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPB2R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPB2R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPB2R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPB2R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPB2R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPB2R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPB2R, 15)),
+       PIC32_PINCTRL_GROUP(19, B3,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 8),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 8),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 8),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 8),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 8),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 8),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 8),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 8),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 8),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 8),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPB3R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPB3R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPB3R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPB3R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPB3R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPB3R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPB3R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPB3R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPB3R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPB3R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPB3R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPB3R, 15)),
+       PIC32_PINCTRL_GROUP(21, B5,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 8),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 8),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 8),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 8),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 8),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 8),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 8),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 8),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 8),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 8),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 8),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPB5R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPB5R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPB5R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPB5R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPB5R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPB5R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPB5R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPB5R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPB5R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB5R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPB5R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPB5R, 15)),
+       PIC32_PINCTRL_GROUP(22, B6,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 4),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 4),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 4),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 4),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 4),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 4),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 4),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 4),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 4),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 4),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 4),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPB6R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPB6R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPB6R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPB6R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPB6R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPB6R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPB6R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPB6R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPB6R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPB6R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPB6R, 15)),
+       PIC32_PINCTRL_GROUP(23, B7,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 7),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 7),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 7),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 7),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 7),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 7),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 7),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 7),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 7),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 7),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 7),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 7),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 7),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPB7R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPB7R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPB7R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPB7R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPB7R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPB7R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPB7R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPB7R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPB7R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPB7R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPB7R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB7R, 15)),
+       PIC32_PINCTRL_GROUP(24, B8,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 2),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 2),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 2),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 2),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 2),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 2),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 2),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 2),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 2),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 2),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 2),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 2),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 2),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 2),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPB8R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPB8R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPB8R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPB8R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPB8R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPB8R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPB8R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPB8R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPB8R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPB8R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPB8R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB8R, 15)),
+       PIC32_PINCTRL_GROUP(25, B9,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 5),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 5),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 5),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 5),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 5),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 5),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 5),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 5),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 5),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 5),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 5),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPB9R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPB9R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPB9R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPB9R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPB9R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPB9R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPB9R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPB9R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPB9R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB9R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPB9R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPB9R, 15)),
+       PIC32_PINCTRL_GROUP(26, B10,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 6),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 6),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 6),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 6),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 6),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 6),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 6),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 6),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 6),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 6),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 6),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 6),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPB10R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPB10R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPB10R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPB10R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPB10R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPB10R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPB10R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPB10R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPB10R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB10R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPB10R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPB10R, 15)),
+       PIC32_PINCTRL_GROUP(30, B14,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 2),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 2),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 2),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 2),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 2),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 2),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 2),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 2),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 2),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 2),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 2),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 2),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPB14R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPB14R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPB14R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPB14R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPB14R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPB14R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPB14R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPB14R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPB14R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPB14R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPB14R, 15)),
+       PIC32_PINCTRL_GROUP(31, B15,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 3),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 3),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 3),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 3),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 3),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 3),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 3),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 3),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 3),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 3),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 3),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 3),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 3),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 3),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPB15R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPB15R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPB15R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPB15R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPB15R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPB15R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPB15R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPB15R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPB15R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPB15R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPB15R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB15R, 15)),
+       PIC32_PINCTRL_GROUP(33, C1,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 10),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 10),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 10),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 10),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 10),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 10),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 10),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 10),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 10),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 10),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 10),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 10),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 10),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 10),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPC1R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPC1R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPC1R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPC1R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPC1R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPC1R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPC1R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPC1R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPC1R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPC1R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPC1R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPC1R, 15)),
+       PIC32_PINCTRL_GROUP(34, C2,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 12),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 12),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 12),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 12),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 12),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 12),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 12),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 12),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 12),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 12),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 12),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPC2R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPC2R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPC2R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPC2R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPC2R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPC2R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPC2R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPC2R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPC2R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPC2R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPC2R, 15)),
+       PIC32_PINCTRL_GROUP(35, C3,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 12),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 12),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 12),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 12),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 12),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 12),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 12),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 12),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 12),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 12),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 12),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 12),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 12),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 12),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPC3R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPC3R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPC3R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPC3R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPC3R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPC3R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPC3R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPC3R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPC3R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPC3R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPC3R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPC3R, 15)),
+       PIC32_PINCTRL_GROUP(36, C4,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 10),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 10),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 10),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 10),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 10),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 10),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 10),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 10),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 10),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 10),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 10),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPC4R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPC4R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPC4R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPC4R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPC4R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPC4R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPC4R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPC4R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPC4R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPC4R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPC4R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPC4R, 15)),
+       PIC32_PINCTRL_GROUP(45, C13,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 7),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 7),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 7),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 7),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 7),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 7),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 7),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 7),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 7),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 7),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPC13R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPC13R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPC13R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPC13R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPC13R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPC13R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPC13R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPC13R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPC13R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPC13R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPC13R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPC13R, 15)),
+       PIC32_PINCTRL_GROUP(46, C14,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 7),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 7),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 7),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 7),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 7),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 7),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 7),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 7),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 7),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 7),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 7),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPC14R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPC14R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPC14R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPC14R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPC14R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPC14R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPC14R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPC14R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPC14R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPC14R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPC14R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPC14R, 15)),
+       PIC32_PINCTRL_GROUP(48, D0,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 3),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 3),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 3),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 3),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 3),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 3),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 3),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 3),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 3),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 3),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 3),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPD0R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPD0R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPD0R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPD0R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPD0R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPD0R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPD0R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPD0R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPD0R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPD0R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPD0R, 15)),
+       PIC32_PINCTRL_GROUP(50, D2,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 0),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 0),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 0),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 0),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 0),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 0),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 0),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 0),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 0),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 0),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 0),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 0),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 0),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 0),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPD2R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPD2R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPD2R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPD2R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPD2R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPD2R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPD2R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPD2R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPD2R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD2R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPD2R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPD2R, 15)),
+       PIC32_PINCTRL_GROUP(51, D3,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 0),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 0),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 0),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 0),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 0),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 0),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 0),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 0),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 0),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 0),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 0),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPD3R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPD3R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPD3R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPD3R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPD3R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPD3R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPD3R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPD3R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPD3R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPD3R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPD3R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD3R, 15)),
+       PIC32_PINCTRL_GROUP(52, D4,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 4),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 4),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 4),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 4),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 4),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 4),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 4),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 4),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 4),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 4),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 4),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 4),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 4),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPD4R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPD4R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPD4R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPD4R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPD4R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPD4R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPD4R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPD4R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPD4R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPD4R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPD4R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD4R, 15)),
+       PIC32_PINCTRL_GROUP(53, D5,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 6),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 6),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 6),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 6),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 6),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 6),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 6),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 6),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 6),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 6),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 6),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 6),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPD5R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPD5R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPD5R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPD5R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPD5R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPD5R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPD5R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPD5R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPD5R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPD5R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPD5R, 15)),
+       PIC32_PINCTRL_GROUP(54, D6,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 14),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 14),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 14),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 14),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 14),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 14),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 14),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 14),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 14),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 14),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 14),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 14),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 14),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPD6R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPD6R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPD6R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPD6R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPD6R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPD6R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPD6R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPD6R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPD6R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD6R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPD6R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPD6R, 15)),
+       PIC32_PINCTRL_GROUP(55, D7,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 14),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 14),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 14),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 14),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 14),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 14),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 14),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 14),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 14),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPD7R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPD7R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPD7R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPD7R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPD7R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPD7R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPD7R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPD7R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPD7R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPD7R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPD7R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD7R, 15)),
+       PIC32_PINCTRL_GROUP(57, D9,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 0),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 0),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 0),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 0),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 0),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 0),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 0),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 0),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 0),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 0),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 0),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 0),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 0),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 0),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPD9R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPD9R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPD9R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPD9R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPD9R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPD9R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPD9R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPD9R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPD9R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPD9R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPD9R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD9R, 15)),
+       PIC32_PINCTRL_GROUP(58, D10,
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPD10R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPD10R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPD10R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPD10R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPD10R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPD10R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPD10R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPD10R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPD10R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD10R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPD10R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPD10R, 15)),
+       PIC32_PINCTRL_GROUP(59, D11,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 3),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 3),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 3),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 3),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 3),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 3),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 3),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 3),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 3),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 3),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 3),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPD11R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPD11R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPD11R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPD11R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPD11R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPD11R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPD11R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPD11R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPD11R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPD11R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPD11R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD11R, 15)),
+       PIC32_PINCTRL_GROUP(60, D12,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 10),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 10),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 10),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 10),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 10),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 10),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 10),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 10),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 10),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 10),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 10),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 10),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 10),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 10),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPD12R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPD12R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPD12R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPD12R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPD12R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPD12R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPD12R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPD12R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPD12R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPD12R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPD12R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD12R, 15)),
+       PIC32_PINCTRL_GROUP(62, D14,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 11),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 11),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 11),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 11),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 11),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 11),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 11),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 11),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 11),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 11),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 11),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 11),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 11),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 11),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPD14R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPD14R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPD14R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPD14R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPD14R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPD14R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPD14R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPD14R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPD14R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD14R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPD14R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPD14R, 15)),
+       PIC32_PINCTRL_GROUP(63, D15,
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPD15R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPD15R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPD15R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPD15R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPD15R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPD15R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPD15R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPD15R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPD15R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPD15R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPD15R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD15R, 15)),
+       PIC32_PINCTRL_GROUP(67, E3,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 6),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 6),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 6),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 6),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 6),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 6),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 6),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 6),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 6),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 6),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 6),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 6),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 6),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 6),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPE3R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPE3R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPE3R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPE3R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPE3R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPE3R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPE3R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPE3R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPE3R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPE3R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPE3R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPE3R, 15)),
+       PIC32_PINCTRL_GROUP(69, E5,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 6),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 6),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 6),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 6),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 6),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 6),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 6),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 6),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 6),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 6),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPE5R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPE5R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPE5R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPE5R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPE5R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPE5R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPE5R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPE5R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPE5R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPE5R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPE5R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPE5R, 15)),
+       PIC32_PINCTRL_GROUP(72, E8,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 13),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 13),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 13),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 13),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 13),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 13),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 13),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 13),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 13),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 13),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 13),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 13),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPE8R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPE8R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPE8R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPE8R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPE8R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPE8R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPE8R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPE8R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPE8R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPE8R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPE8R, 15)),
+       PIC32_PINCTRL_GROUP(73, E9,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 13),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 13),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 13),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 13),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 13),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 13),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 13),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 13),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 13),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 13),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 13),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 13),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 13),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 13),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPE9R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPE9R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPE9R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPE9R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPE9R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPE9R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPE9R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPE9R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPE9R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPE9R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPE9R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPE9R, 15)),
+       PIC32_PINCTRL_GROUP(80, F0,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 4),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 4),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 4),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 4),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 4),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 4),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 4),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 4),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 4),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 4),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPF0R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPF0R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPF0R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPF0R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPF0R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPF0R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPF0R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPF0R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPF0R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPF0R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPF0R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPF0R, 15)),
+       PIC32_PINCTRL_GROUP(81, F1,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 4),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 4),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 4),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 4),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 4),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 4),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 4),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 4),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 4),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 4),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 4),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPF1R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPF1R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPF1R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPF1R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPF1R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPF1R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPF1R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPF1R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPF1R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPF1R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPF1R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPF1R, 15)),
+       PIC32_PINCTRL_GROUP(82, F2,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 11),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 11),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 11),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 11),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 11),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 11),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 11),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 11),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 11),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 11),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 11),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 11),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPF2R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPF2R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPF2R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPF2R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPF2R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPF2R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPF2R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPF2R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPF2R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPF2R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPF2R, 15)),
+       PIC32_PINCTRL_GROUP(83, F3,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 8),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 8),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 8),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 8),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 8),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 8),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 8),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 8),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 8),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 8),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 8),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 8),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPF3R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPF3R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPF3R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPF3R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPF3R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPF3R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPF3R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPF3R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPF3R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPF3R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPF3R, 15)),
+       PIC32_PINCTRL_GROUP(84, F4,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 2),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 2),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 2),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 2),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 2),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 2),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 2),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 2),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 2),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 2),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 2),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPF4R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPF4R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPF4R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPF4R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPF4R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPF4R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPF4R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPF4R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPF4R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPF4R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPF4R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPF4R, 15)),
+       PIC32_PINCTRL_GROUP(85, F5,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 2),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 2),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 2),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 2),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 2),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 2),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 2),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 2),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 2),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 2),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPF5R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPF5R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPF5R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPF5R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPF5R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPF5R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPF5R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPF5R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPF5R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPF5R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPF5R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPF5R, 15)),
+       PIC32_PINCTRL_GROUP(88, F8,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 11),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 11),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 11),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 11),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 11),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 11),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 11),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 11),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 11),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 11),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 11),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 11),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 11),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 11),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPF8R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPF8R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPF8R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPF8R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPF8R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPF8R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPF8R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPF8R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPF8R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPF8R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPF8R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPF8R, 15)),
+       PIC32_PINCTRL_GROUP(92, F12,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 9),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 9),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 9),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 9),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 9),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 9),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 9),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 9),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 9),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 9),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 9),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 9),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 9),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 9),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPF12R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPF12R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPF12R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPF12R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPF12R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPF12R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPF12R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPF12R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPF12R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPF12R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPF12R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPF12R, 15)),
+       PIC32_PINCTRL_GROUP(93, F13,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 9),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 9),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 9),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 9),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 9),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 9),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 9),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 9),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 9),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 9),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 9),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 9),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPF13R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPF13R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPF13R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPF13R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPF13R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPF13R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPF13R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPF13R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPF13R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPF13R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPF13R, 15)),
+       PIC32_PINCTRL_GROUP(96, G0,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 12),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 12),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 12),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 12),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 12),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 12),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 12),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 12),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 12),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPG0R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPG0R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPG0R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPG0R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPG0R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPG0R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPG0R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPG0R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPG0R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPG0R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPG0R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPG0R, 15)),
+       PIC32_PINCTRL_GROUP(97, G1,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 12),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 12),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 12),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 12),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 12),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 12),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 12),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 12),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 12),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 12),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 12),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 12),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 12),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPG1R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPG1R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPG1R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPG1R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPG1R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPG1R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPG1R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPG1R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPG1R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPG1R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPG1R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPG1R, 15)),
+       PIC32_PINCTRL_GROUP(102, G6,
+                       PIC32_PINCTRL_FUNCTION(INT2, INT2R, 1),
+                       PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 1),
+                       PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 1),
+                       PIC32_PINCTRL_FUNCTION(IC2, IC2R, 1),
+                       PIC32_PINCTRL_FUNCTION(IC5, IC5R, 1),
+                       PIC32_PINCTRL_FUNCTION(IC9, IC9R, 1),
+                       PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 1),
+                       PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 1),
+                       PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 1),
+                       PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 1),
+                       PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 1),
+                       PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 1),
+                       PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 1),
+                       PIC32_PINCTRL_FUNCTION(U3RTS, RPG6R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4TX, RPG6R, 2),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPG6R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS1OUT, RPG6R, 5),
+                       PIC32_PINCTRL_FUNCTION(SS3OUT, RPG6R, 7),
+                       PIC32_PINCTRL_FUNCTION(SS4OUT, RPG6R, 8),
+                       PIC32_PINCTRL_FUNCTION(SS5OUT, RPG6R, 9),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPG6R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC5, RPG6R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC8, RPG6R, 12),
+                       PIC32_PINCTRL_FUNCTION(C1OUT, RPG6R, 14),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO3, RPG6R, 15)),
+       PIC32_PINCTRL_GROUP(103, G7,
+                       PIC32_PINCTRL_FUNCTION(INT4, INT4R, 1),
+                       PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 1),
+                       PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 1),
+                       PIC32_PINCTRL_FUNCTION(IC4, IC4R, 1),
+                       PIC32_PINCTRL_FUNCTION(IC8, IC8R, 1),
+                       PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 1),
+                       PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 1),
+                       PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 1),
+                       PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 1),
+                       PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 1),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 1),
+                       PIC32_PINCTRL_FUNCTION(U1TX, RPG7R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2RTS, RPG7R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5TX, RPG7R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6RTS, RPG7R, 4),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPG7R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPG7R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPG7R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPG7R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPG7R, 9),
+                       PIC32_PINCTRL_FUNCTION(OC4, RPG7R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC7, RPG7R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO1, RPG7R, 15)),
+       PIC32_PINCTRL_GROUP(104, G8,
+                       PIC32_PINCTRL_FUNCTION(INT3, INT3R, 1),
+                       PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 1),
+                       PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 1),
+                       PIC32_PINCTRL_FUNCTION(IC3, IC3R, 1),
+                       PIC32_PINCTRL_FUNCTION(IC7, IC7R, 1),
+                       PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 1),
+                       PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 1),
+                       PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 1),
+                       PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 1),
+                       PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 1),
+                       PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 1),
+                       PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 1),
+                       PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 1),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 1),
+                       PIC32_PINCTRL_FUNCTION(U3TX, RPG8R, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RTS, RPG8R, 2),
+                       PIC32_PINCTRL_FUNCTION(SDO1, RPG8R, 5),
+                       PIC32_PINCTRL_FUNCTION(SDO2, RPG8R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO3, RPG8R, 7),
+                       PIC32_PINCTRL_FUNCTION(SDO5, RPG8R, 9),
+                       PIC32_PINCTRL_FUNCTION(SS6OUT, RPG8R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC3, RPG8R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC6, RPG8R, 12),
+                       PIC32_PINCTRL_FUNCTION(REFCLKO4, RPG8R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2OUT, RPG8R, 14),
+                       PIC32_PINCTRL_FUNCTION(C1TX, RPG8R, 15)),
+       PIC32_PINCTRL_GROUP(105, G9,
+                       PIC32_PINCTRL_FUNCTION(INT1, INT1R, 1),
+                       PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 1),
+                       PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 1),
+                       PIC32_PINCTRL_FUNCTION(IC1, IC1R, 1),
+                       PIC32_PINCTRL_FUNCTION(IC6, IC6R, 1),
+                       PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 1),
+                       PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 1),
+                       PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 1),
+                       PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 1),
+                       PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 1),
+                       PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 1),
+                       PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 1),
+                       PIC32_PINCTRL_FUNCTION(U1RTS, RPG9R, 1),
+                       PIC32_PINCTRL_FUNCTION(U2TX, RPG9R, 2),
+                       PIC32_PINCTRL_FUNCTION(U5RTS, RPG9R, 3),
+                       PIC32_PINCTRL_FUNCTION(U6TX, RPG9R, 4),
+                       PIC32_PINCTRL_FUNCTION(SS2OUT, RPG9R, 6),
+                       PIC32_PINCTRL_FUNCTION(SDO4, RPG9R, 8),
+                       PIC32_PINCTRL_FUNCTION(SDO6, RPG9R, 10),
+                       PIC32_PINCTRL_FUNCTION(OC2, RPG9R, 11),
+                       PIC32_PINCTRL_FUNCTION(OC1, RPG9R, 12),
+                       PIC32_PINCTRL_FUNCTION(OC9, RPG9R, 13),
+                       PIC32_PINCTRL_FUNCTION(C2TX, RPG9R, 15)),
+};
+
+static inline struct pic32_gpio_bank *irqd_to_bank(struct irq_data *d)
+{
+       return gpiochip_get_data(irq_data_get_irq_chip_data(d));
+}
+
+static inline struct pic32_gpio_bank *pctl_to_bank(struct pic32_pinctrl *pctl,
+                                               unsigned pin)
+{
+       return &pctl->gpio_banks[pin / PINS_PER_BANK];
+}
+
+static int pic32_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->ngroups;
+}
+
+static const char *pic32_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+                                                   unsigned group)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->groups[group].name;
+}
+
+static int pic32_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+                                           unsigned group,
+                                           const unsigned **pins,
+                                           unsigned *num_pins)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = &pctl->groups[group].pin;
+       *num_pins = 1;
+
+       return 0;
+}
+
+static const struct pinctrl_ops pic32_pinctrl_ops = {
+       .get_groups_count = pic32_pinctrl_get_groups_count,
+       .get_group_name = pic32_pinctrl_get_group_name,
+       .get_group_pins = pic32_pinctrl_get_group_pins,
+       .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+       .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int pic32_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->nfunctions;
+}
+
+static const char *
+pic32_pinmux_get_function_name(struct pinctrl_dev *pctldev, unsigned func)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->functions[func].name;
+}
+
+static int pic32_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
+                                               unsigned func,
+                                               const char * const **groups,
+                                               unsigned * const num_groups)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = pctl->functions[func].groups;
+       *num_groups = pctl->functions[func].ngroups;
+
+       return 0;
+}
+
+static int pic32_pinmux_enable(struct pinctrl_dev *pctldev,
+                                  unsigned func, unsigned group)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       const struct pic32_pin_group *pg = &pctl->groups[group];
+       const struct pic32_function *pf = &pctl->functions[func];
+       const char *fname = pf->name;
+       struct pic32_desc_function *functions = pg->functions;
+
+       while (functions->name) {
+               if (!strcmp(functions->name, fname)) {
+                       dev_dbg(pctl->dev,
+                               "setting function %s reg 0x%x = %d\n",
+                               fname, functions->muxreg, functions->muxval);
+
+                       writel(functions->muxval, pctl->reg_base + functions->muxreg);
+
+                       return 0;
+               }
+
+               functions++;
+       }
+
+       dev_err(pctl->dev, "cannot mux pin %u to function %u\n", group, func);
+
+       return -EINVAL;
+}
+
+static int pic32_gpio_request_enable(struct pinctrl_dev *pctldev,
+                                    struct pinctrl_gpio_range *range,
+                                    unsigned offset)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct pic32_gpio_bank *bank = gpiochip_get_data(range->gc);
+       u32 mask = BIT(offset - bank->gpio_chip.base);
+
+       dev_dbg(pctl->dev, "requesting gpio %d in bank %d with mask 0x%x\n",
+               offset, bank->gpio_chip.base, mask);
+
+       writel(mask, bank->reg_base + PIC32_CLR(ANSEL_REG));
+
+       return 0;
+}
+
+static int pic32_gpio_direction_input(struct gpio_chip *chip,
+                                         unsigned offset)
+{
+       struct pic32_gpio_bank *bank = gpiochip_get_data(chip);
+       u32 mask = BIT(offset);
+
+       writel(mask, bank->reg_base + PIC32_SET(TRIS_REG));
+
+       return 0;
+}
+
+static int pic32_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct pic32_gpio_bank *bank = gpiochip_get_data(chip);
+
+       return !!(readl(bank->reg_base + PORT_REG) & BIT(offset));
+}
+
+static void pic32_gpio_set(struct gpio_chip *chip, unsigned offset,
+                              int value)
+{
+       struct pic32_gpio_bank *bank = gpiochip_get_data(chip);
+       u32 mask = BIT(offset);
+
+       if (value)
+               writel(mask, bank->reg_base + PIC32_SET(PORT_REG));
+       else
+               writel(mask, bank->reg_base + PIC32_CLR(PORT_REG));
+}
+
+static int pic32_gpio_direction_output(struct gpio_chip *chip,
+                                          unsigned offset, int value)
+{
+       struct pic32_gpio_bank *bank = gpiochip_get_data(chip);
+       u32 mask = BIT(offset);
+
+       pic32_gpio_set(chip, offset, value);
+       writel(mask, bank->reg_base + PIC32_CLR(TRIS_REG));
+
+       return 0;
+}
+
+static int pic32_gpio_set_direction(struct pinctrl_dev *pctldev,
+                                             struct pinctrl_gpio_range *range,
+                                             unsigned offset, bool input)
+{
+       struct gpio_chip *chip = range->gc;
+
+       if (input)
+               pic32_gpio_direction_input(chip, offset);
+       else
+               pic32_gpio_direction_output(chip, offset, 0);
+
+       return 0;
+}
+
+static const struct pinmux_ops pic32_pinmux_ops = {
+       .get_functions_count = pic32_pinmux_get_functions_count,
+       .get_function_name = pic32_pinmux_get_function_name,
+       .get_function_groups = pic32_pinmux_get_function_groups,
+       .set_mux = pic32_pinmux_enable,
+       .gpio_request_enable = pic32_gpio_request_enable,
+       .gpio_set_direction = pic32_gpio_set_direction,
+};
+
+static int pic32_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
+                                unsigned long *config)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct pic32_gpio_bank *bank = pctl_to_bank(pctl, pin);
+       unsigned param = pinconf_to_config_param(*config);
+       u32 mask = BIT(pin - bank->gpio_chip.base);
+       u32 arg;
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_PULL_UP:
+               arg = !!(readl(bank->reg_base + CNPU_REG) & mask);
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               arg = !!(readl(bank->reg_base + CNPD_REG) & mask);
+               break;
+       case PIN_CONFIG_MICROCHIP_DIGITAL:
+               arg = !(readl(bank->reg_base + ANSEL_REG) & mask);
+               break;
+       case PIN_CONFIG_MICROCHIP_ANALOG:
+               arg = !!(readl(bank->reg_base + ANSEL_REG) & mask);
+               break;
+       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+               arg = !!(readl(bank->reg_base + ODCU_REG) & mask);
+               break;
+       case PIN_CONFIG_INPUT_ENABLE:
+               arg = !!(readl(bank->reg_base + TRIS_REG) & mask);
+               break;
+       case PIN_CONFIG_OUTPUT:
+               arg = !(readl(bank->reg_base + TRIS_REG) & mask);
+               break;
+       default:
+               dev_err(pctl->dev, "Property %u not supported\n", param);
+               return -ENOTSUPP;
+       }
+
+       *config = pinconf_to_config_packed(param, arg);
+
+       return 0;
+}
+
+static int pic32_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
+                                unsigned long *configs, unsigned num_configs)
+{
+       struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct pic32_gpio_bank *bank = pctl_to_bank(pctl, pin);
+       unsigned param;
+       u32 arg;
+       unsigned int i;
+       u32 offset = pin - bank->gpio_chip.base;
+       u32 mask = BIT(offset);
+
+       dev_dbg(pctl->dev, "setting pin %d bank %d mask 0x%x\n",
+               pin, bank->gpio_chip.base, mask);
+
+       for (i = 0; i < num_configs; i++) {
+               param = pinconf_to_config_param(configs[i]);
+               arg = pinconf_to_config_argument(configs[i]);
+
+               switch (param) {
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       dev_dbg(pctl->dev, "   pullup\n");
+                       writel(mask, bank->reg_base +PIC32_SET(CNPU_REG));
+                       break;
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       dev_dbg(pctl->dev, "   pulldown\n");
+                       writel(mask, bank->reg_base + PIC32_SET(CNPD_REG));
+                       break;
+               case PIN_CONFIG_MICROCHIP_DIGITAL:
+                       dev_dbg(pctl->dev, "   digital\n");
+                       writel(mask, bank->reg_base + PIC32_CLR(ANSEL_REG));
+                       break;
+               case PIN_CONFIG_MICROCHIP_ANALOG:
+                       dev_dbg(pctl->dev, "   analog\n");
+                       writel(mask, bank->reg_base + PIC32_SET(ANSEL_REG));
+                       break;
+               case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+                       dev_dbg(pctl->dev, "   opendrain\n");
+                       writel(mask, bank->reg_base + PIC32_SET(ODCU_REG));
+                       break;
+               case PIN_CONFIG_INPUT_ENABLE:
+                       pic32_gpio_direction_input(&bank->gpio_chip, offset);
+                       break;
+               case PIN_CONFIG_OUTPUT:
+                       pic32_gpio_direction_output(&bank->gpio_chip,
+                                                   offset, arg);
+                       break;
+               default:
+                       dev_err(pctl->dev, "Property %u not supported\n",
+                               param);
+                       return -ENOTSUPP;
+               }
+       }
+
+       return 0;
+}
+
+static const struct pinconf_ops pic32_pinconf_ops = {
+       .pin_config_get = pic32_pinconf_get,
+       .pin_config_set = pic32_pinconf_set,
+       .is_generic = true,
+};
+
+static struct pinctrl_desc pic32_pinctrl_desc = {
+       .name = "pic32-pinctrl",
+       .pctlops = &pic32_pinctrl_ops,
+       .pmxops = &pic32_pinmux_ops,
+       .confops = &pic32_pinconf_ops,
+       .owner = THIS_MODULE,
+};
+
+static int pic32_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+       struct pic32_gpio_bank *bank = gpiochip_get_data(chip);
+
+       return !!(readl(bank->reg_base + TRIS_REG) & BIT(offset));
+}
+
+static void pic32_gpio_irq_ack(struct irq_data *data)
+{
+       struct pic32_gpio_bank *bank = irqd_to_bank(data);
+
+       writel(0, bank->reg_base + CNF_REG);
+}
+
+static void pic32_gpio_irq_mask(struct irq_data *data)
+{
+       struct pic32_gpio_bank *bank = irqd_to_bank(data);
+
+       writel(BIT(PIC32_CNCON_ON), bank->reg_base + PIC32_CLR(CNCON_REG));
+}
+
+static void pic32_gpio_irq_unmask(struct irq_data *data)
+{
+       struct pic32_gpio_bank *bank = irqd_to_bank(data);
+
+       writel(BIT(PIC32_CNCON_ON), bank->reg_base + PIC32_SET(CNCON_REG));
+}
+
+static unsigned int pic32_gpio_irq_startup(struct irq_data *data)
+{
+       struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+
+       pic32_gpio_direction_input(chip, data->hwirq);
+       pic32_gpio_irq_unmask(data);
+
+       return 0;
+}
+
+static int pic32_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+       struct pic32_gpio_bank *bank = irqd_to_bank(data);
+       u32 mask = BIT(data->hwirq);
+
+       switch (type & IRQ_TYPE_SENSE_MASK) {
+       case IRQ_TYPE_EDGE_RISING:
+               /* enable RISE */
+               writel(mask, bank->reg_base + PIC32_SET(CNEN_REG));
+               /* disable FALL */
+               writel(mask, bank->reg_base + PIC32_CLR(CNNE_REG));
+               /* enable EDGE */
+               writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG));
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               /* disable RISE */
+               writel(mask, bank->reg_base + PIC32_CLR(CNEN_REG));
+               /* enable FALL */
+               writel(mask, bank->reg_base + PIC32_SET(CNNE_REG));
+               /* enable EDGE */
+               writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG));
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               /* enable RISE */
+               writel(mask, bank->reg_base + PIC32_SET(CNEN_REG));
+               /* enable FALL */
+               writel(mask, bank->reg_base + PIC32_SET(CNNE_REG));
+               /* enable EDGE */
+               writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       irq_set_handler_locked(data, handle_edge_irq);
+
+       return 0;
+}
+
+static u32 pic32_gpio_get_pending(struct gpio_chip *gc, unsigned long status)
+{
+       struct pic32_gpio_bank *bank = gpiochip_get_data(gc);
+       u32 pending = 0;
+       u32 cnen_rise, cnne_fall;
+       u32 pin;
+
+       cnen_rise = readl(bank->reg_base + CNEN_REG);
+       cnne_fall = readl(bank->reg_base + CNNE_REG);
+
+       for_each_set_bit(pin, &status, BITS_PER_LONG) {
+               u32 mask = BIT(pin);
+
+               if ((mask & cnen_rise) || (mask && cnne_fall))
+                       pending |= mask;
+       }
+
+       return pending;
+}
+
+static void pic32_gpio_irq_handler(struct irq_desc *desc)
+{
+       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+       struct pic32_gpio_bank *bank = gpiochip_get_data(gc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned long pending;
+       unsigned int pin;
+       u32 stat;
+
+       chained_irq_enter(chip, desc);
+
+       stat = readl(bank->reg_base + CNF_REG);
+       pending = pic32_gpio_get_pending(gc, stat);
+
+       for_each_set_bit(pin, &pending, BITS_PER_LONG)
+               generic_handle_irq(irq_linear_revmap(gc->irqdomain, pin));
+
+       chained_irq_exit(chip, desc);
+}
+
+#define GPIO_BANK(_bank, _npins)                                       \
+       {                                                               \
+               .gpio_chip = {                                          \
+                       .label = "GPIO" #_bank,                         \
+                       .request = gpiochip_generic_request,            \
+                       .free = gpiochip_generic_free,                  \
+                       .get_direction = pic32_gpio_get_direction,      \
+                       .direction_input = pic32_gpio_direction_input,  \
+                       .direction_output = pic32_gpio_direction_output, \
+                       .get = pic32_gpio_get,                          \
+                       .set = pic32_gpio_set,                          \
+                       .ngpio = _npins,                                \
+                       .base = GPIO_BANK_START(_bank),                 \
+                       .owner = THIS_MODULE,                           \
+                       .can_sleep = 0,                                 \
+               },                                                      \
+               .irq_chip = {                                           \
+                       .name = "GPIO" #_bank,                          \
+                       .irq_startup = pic32_gpio_irq_startup,  \
+                       .irq_ack = pic32_gpio_irq_ack,          \
+                       .irq_mask = pic32_gpio_irq_mask,                \
+                       .irq_unmask = pic32_gpio_irq_unmask,            \
+                       .irq_set_type = pic32_gpio_irq_set_type,        \
+               },                                                      \
+       }
+
+static struct pic32_gpio_bank pic32_gpio_banks[] = {
+       GPIO_BANK(0, PINS_PER_BANK),
+       GPIO_BANK(1, PINS_PER_BANK),
+       GPIO_BANK(2, PINS_PER_BANK),
+       GPIO_BANK(3, PINS_PER_BANK),
+       GPIO_BANK(4, PINS_PER_BANK),
+       GPIO_BANK(5, PINS_PER_BANK),
+       GPIO_BANK(6, PINS_PER_BANK),
+       GPIO_BANK(7, PINS_PER_BANK),
+       GPIO_BANK(8, PINS_PER_BANK),
+       GPIO_BANK(9, PINS_PER_BANK),
+};
+
+static int pic32_pinctrl_probe(struct platform_device *pdev)
+{
+       struct pic32_pinctrl *pctl;
+       struct resource *res;
+       int ret;
+
+       pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+       if (!pctl)
+               return -ENOMEM;
+       pctl->dev = &pdev->dev;
+       dev_set_drvdata(&pdev->dev, pctl);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pctl->reg_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pctl->reg_base))
+               return PTR_ERR(pctl->reg_base);
+
+       pctl->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(pctl->clk)) {
+               ret = PTR_ERR(pctl->clk);
+               dev_err(&pdev->dev, "clk get failed\n");
+               return ret;
+       }
+
+       ret = clk_prepare_enable(pctl->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "clk enable failed\n");
+               return ret;
+       }
+
+       pctl->pins = pic32_pins;
+       pctl->npins = ARRAY_SIZE(pic32_pins);
+       pctl->functions = pic32_functions;
+       pctl->nfunctions = ARRAY_SIZE(pic32_functions);
+       pctl->groups = pic32_groups;
+       pctl->ngroups = ARRAY_SIZE(pic32_groups);
+       pctl->gpio_banks = pic32_gpio_banks;
+       pctl->nbanks = ARRAY_SIZE(pic32_gpio_banks);
+
+       pic32_pinctrl_desc.pins = pctl->pins;
+       pic32_pinctrl_desc.npins = pctl->npins;
+       pic32_pinctrl_desc.custom_params = pic32_mpp_bindings;
+       pic32_pinctrl_desc.num_custom_params = ARRAY_SIZE(pic32_mpp_bindings);
+
+       pctl->pctldev = pinctrl_register(&pic32_pinctrl_desc, &pdev->dev, pctl);
+       if (IS_ERR(pctl->pctldev)) {
+               dev_err(&pdev->dev, "Failed to register pinctrl device\n");
+               return PTR_ERR(pctl->pctldev);
+       }
+
+       return 0;
+}
+
+static int pic32_gpio_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct pic32_gpio_bank *bank;
+       u32 id;
+       int irq, ret;
+       struct resource *res;
+
+       if (of_property_read_u32(np, "microchip,gpio-bank", &id)) {
+               dev_err(&pdev->dev, "microchip,gpio-bank property not found\n");
+               return -EINVAL;
+       }
+
+       if (id >= ARRAY_SIZE(pic32_gpio_banks)) {
+               dev_err(&pdev->dev, "invalid microchip,gpio-bank property\n");
+               return -EINVAL;
+       }
+
+       bank = &pic32_gpio_banks[id];
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       bank->reg_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(bank->reg_base))
+               return PTR_ERR(bank->reg_base);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "irq get failed\n");
+               return irq;
+       }
+
+       bank->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(bank->clk)) {
+               ret = PTR_ERR(bank->clk);
+               dev_err(&pdev->dev, "clk get failed\n");
+               return ret;
+       }
+
+       ret = clk_prepare_enable(bank->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "clk enable failed\n");
+               return ret;
+       }
+
+       bank->gpio_chip.parent = &pdev->dev;
+       bank->gpio_chip.of_node = np;
+       ret = gpiochip_add_data(&bank->gpio_chip, bank);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to add GPIO chip %u: %d\n",
+                       id, ret);
+               return ret;
+       }
+
+       ret = gpiochip_irqchip_add(&bank->gpio_chip, &bank->irq_chip,
+                               0, handle_level_irq, IRQ_TYPE_NONE);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to add IRQ chip %u: %d\n",
+                       id, ret);
+               gpiochip_remove(&bank->gpio_chip);
+               return ret;
+       }
+
+       gpiochip_set_chained_irqchip(&bank->gpio_chip, &bank->irq_chip,
+                                    irq, pic32_gpio_irq_handler);
+
+       return 0;
+}
+
+static const struct of_device_id pic32_pinctrl_of_match[] = {
+       { .compatible = "microchip,pic32mzda-pinctrl", },
+       { },
+};
+
+static struct platform_driver pic32_pinctrl_driver = {
+       .driver = {
+               .name = "pic32-pinctrl",
+               .of_match_table = pic32_pinctrl_of_match,
+               .suppress_bind_attrs = true,
+       },
+       .probe = pic32_pinctrl_probe,
+};
+
+static const struct of_device_id pic32_gpio_of_match[] = {
+       { .compatible = "microchip,pic32mzda-gpio", },
+       { },
+};
+
+static struct platform_driver pic32_gpio_driver = {
+       .driver = {
+               .name = "pic32-gpio",
+               .of_match_table = pic32_gpio_of_match,
+               .suppress_bind_attrs = true,
+       },
+       .probe = pic32_gpio_probe,
+};
+
+static int __init pic32_gpio_register(void)
+{
+       return platform_driver_register(&pic32_gpio_driver);
+}
+arch_initcall(pic32_gpio_register);
+
+static int __init pic32_pinctrl_register(void)
+{
+       return platform_driver_register(&pic32_pinctrl_driver);
+}
+arch_initcall(pic32_pinctrl_register);
diff --git a/drivers/pinctrl/pinctrl-pic32.h b/drivers/pinctrl/pinctrl-pic32.h
new file mode 100644 (file)
index 0000000..1282626
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * PIC32 pinctrl driver
+ *
+ * Joshua Henderson, <joshua.henderson@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 PINCTRL_PINCTRL_PIC32_H
+#define PINCTRL_PINCTRL_PIC32_H
+
+/* PORT Registers */
+#define ANSEL_REG      0x00
+#define TRIS_REG       0x10
+#define PORT_REG       0x20
+#define LAT_REG                0x30
+#define ODCU_REG       0x40
+#define CNPU_REG       0x50
+#define CNPD_REG       0x60
+#define CNCON_REG      0x70
+#define CNEN_REG       0x80
+#define CNSTAT_REG     0x90
+#define CNNE_REG       0xA0
+#define CNF_REG                0xB0
+
+/* Input PPS Registers */
+#define INT1R 0x04
+#define INT2R 0x08
+#define INT3R 0x0C
+#define INT4R 0x10
+#define T2CKR 0x18
+#define T3CKR 0x1C
+#define T4CKR 0x20
+#define T5CKR 0x24
+#define T6CKR 0x28
+#define T7CKR 0x2C
+#define T8CKR 0x30
+#define T9CKR 0x34
+#define IC1R 0x38
+#define IC2R 0x3C
+#define IC3R 0x40
+#define IC4R 0x44
+#define IC5R 0x48
+#define IC6R 0x4C
+#define IC7R 0x50
+#define IC8R 0x54
+#define IC9R 0x58
+#define OCFAR 0x60
+#define U1RXR 0x68
+#define U1CTSR 0x6C
+#define U2RXR 0x70
+#define U2CTSR 0x74
+#define U3RXR 0x78
+#define U3CTSR 0x7C
+#define U4RXR 0x80
+#define U4CTSR 0x84
+#define U5RXR 0x88
+#define U5CTSR 0x8C
+#define U6RXR 0x90
+#define U6CTSR 0x94
+#define SDI1R 0x9C
+#define SS1INR 0xA0
+#define SDI2R 0xA8
+#define SS2INR 0xAC
+#define SDI3R 0xB4
+#define SS3INR 0xB8
+#define SDI4R 0xC0
+#define SS4INR 0xC4
+#define SDI5R 0xCC
+#define SS5INR 0xD0
+#define SDI6R 0xD8
+#define SS6INR 0xDC
+#define C1RXR 0xE0
+#define C2RXR 0xE4
+#define REFCLKI1R 0xE8
+#define REFCLKI3R 0xF0
+#define REFCLKI4R 0xF4
+
+/* Output PPS Registers */
+#define RPA14R 0x138
+#define RPA15R 0x13C
+#define RPB0R 0x140
+#define RPB1R 0x144
+#define RPB2R 0x148
+#define RPB3R 0x14C
+#define RPB5R 0x154
+#define RPB6R 0x158
+#define RPB7R 0x15C
+#define RPB8R 0x160
+#define RPB9R 0x164
+#define RPB10R 0x168
+#define RPB14R 0x178
+#define RPB15R 0x17C
+#define RPC1R 0x184
+#define RPC2R 0x188
+#define RPC3R 0x18C
+#define RPC4R 0x190
+#define RPC13R 0x1B4
+#define RPC14R 0x1B8
+#define RPD0R 0x1C0
+#define RPD1R 0x1C4
+#define RPD2R 0x1C8
+#define RPD3R 0x1CC
+#define RPD4R 0x1D0
+#define RPD5R 0x1D4
+#define RPD6R 0x1D8
+#define RPD7R 0x1DC
+#define RPD9R 0x1E4
+#define RPD10R 0x1E8
+#define RPD11R 0x1EC
+#define RPD12R 0x1F0
+#define RPD14R 0x1F8
+#define RPD15R 0x1FC
+#define RPE3R 0x20C
+#define RPE5R 0x214
+#define RPE8R 0x220
+#define RPE9R 0x224
+#define RPF0R 0x240
+#define RPF1R 0x244
+#define RPF2R 0x248
+#define RPF3R 0x24C
+#define RPF4R 0x250
+#define RPF5R 0x254
+#define RPF8R 0x260
+#define RPF12R 0x270
+#define RPF13R 0x274
+#define RPG0R 0x280
+#define RPG1R 0x284
+#define RPG6R 0x298
+#define RPG7R 0x29C
+#define RPG8R 0x2A0
+#define RPG9R 0x2A4
+
+#endif  /* PINCTRL_PINCTRL_PIC32_H */
index 183545a068ad975a938eeaaa07f3f1bdc25b8f6b..bf032b9b4c57e06df4b43c794f484fc539b56e3d 100644 (file)
@@ -64,6 +64,7 @@ enum rockchip_pinctrl_type {
        RK3188,
        RK3288,
        RK3368,
+       RK3399,
 };
 
 /**
@@ -85,6 +86,31 @@ struct rockchip_iomux {
        int                             offset;
 };
 
+/**
+ * enum type index corresponding to rockchip_perpin_drv_list arrays index.
+ */
+enum rockchip_pin_drv_type {
+       DRV_TYPE_IO_DEFAULT = 0,
+       DRV_TYPE_IO_1V8_OR_3V0,
+       DRV_TYPE_IO_1V8_ONLY,
+       DRV_TYPE_IO_1V8_3V0_AUTO,
+       DRV_TYPE_IO_3V3_ONLY,
+       DRV_TYPE_MAX
+};
+
+/**
+ * @drv_type: drive strength variant using rockchip_perpin_drv_type
+ * @offset: if initialized to -1 it will be autocalculated, by specifying
+ *         an initial offset value the relevant source offset can be reset
+ *         to a new value for autocalculating the following drive strength
+ *         registers. if used chips own cal_drv func instead to calculate
+ *         registers offset, the variant could be ignored.
+ */
+struct rockchip_drv {
+       enum rockchip_pin_drv_type      drv_type;
+       int                             offset;
+};
+
 /**
  * @reg_base: register base of the gpio bank
  * @reg_pull: optional separate register for additional pull settings
@@ -96,6 +122,7 @@ struct rockchip_iomux {
  * @name: name of the bank
  * @bank_num: number of the bank, to account for holes
  * @iomux: array describing the 4 iomux sources of the bank
+ * @drv: array describing the 4 drive strength sources of the bank
  * @valid: are all necessary informations present
  * @of_node: dt node of this bank
  * @drvdata: common pinctrl basedata
@@ -115,6 +142,7 @@ struct rockchip_pin_bank {
        char                            *name;
        u8                              bank_num;
        struct rockchip_iomux           iomux[4];
+       struct rockchip_drv             drv[4];
        bool                            valid;
        struct device_node              *of_node;
        struct rockchip_pinctrl         *drvdata;
@@ -151,6 +179,47 @@ struct rockchip_pin_bank {
                },                                                      \
        }
 
+#define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
+       {                                                               \
+               .bank_num       = id,                                   \
+               .nr_pins        = pins,                                 \
+               .name           = label,                                \
+               .iomux          = {                                     \
+                       { .offset = -1 },                               \
+                       { .offset = -1 },                               \
+                       { .offset = -1 },                               \
+                       { .offset = -1 },                               \
+               },                                                      \
+               .drv            = {                                     \
+                       { .drv_type = type0, .offset = -1 },            \
+                       { .drv_type = type1, .offset = -1 },            \
+                       { .drv_type = type2, .offset = -1 },            \
+                       { .drv_type = type3, .offset = -1 },            \
+               },                                                      \
+       }
+
+#define PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(id, pins, label, iom0, iom1,   \
+                                       iom2, iom3, drv0, drv1, drv2,   \
+                                       drv3, offset0, offset1,         \
+                                       offset2, offset3)               \
+       {                                                               \
+               .bank_num       = id,                                   \
+               .nr_pins        = pins,                                 \
+               .name           = label,                                \
+               .iomux          = {                                     \
+                       { .type = iom0, .offset = -1 },                 \
+                       { .type = iom1, .offset = -1 },                 \
+                       { .type = iom2, .offset = -1 },                 \
+                       { .type = iom3, .offset = -1 },                 \
+               },                                                      \
+               .drv            = {                                     \
+                       { .drv_type = drv0, .offset = offset0 },        \
+                       { .drv_type = drv1, .offset = offset1 },        \
+                       { .drv_type = drv2, .offset = offset2 },        \
+                       { .drv_type = drv3, .offset = offset3 },        \
+               },                                                      \
+       }
+
 /**
  */
 struct rockchip_pin_ctrl {
@@ -161,6 +230,9 @@ struct rockchip_pin_ctrl {
        enum rockchip_pinctrl_type      type;
        int                             grf_mux_offset;
        int                             pmu_mux_offset;
+       int                             grf_drv_offset;
+       int                             pmu_drv_offset;
+
        void    (*pull_calc_reg)(struct rockchip_pin_bank *bank,
                                    int pin_num, struct regmap **regmap,
                                    int *reg, u8 *bit);
@@ -705,7 +777,68 @@ static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
        }
 }
 
-static int rockchip_perpin_drv_list[] = { 2, 4, 8, 12 };
+#define RK3399_PULL_GRF_OFFSET         0xe040
+#define RK3399_PULL_PMU_OFFSET         0x40
+#define RK3399_DRV_3BITS_PER_PIN       3
+
+static void rk3399_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+                                        int pin_num, struct regmap **regmap,
+                                        int *reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+
+       /* The bank0:16 and bank1:32 pins are located in PMU */
+       if ((bank->bank_num == 0) || (bank->bank_num == 1)) {
+               *regmap = info->regmap_pmu;
+               *reg = RK3399_PULL_PMU_OFFSET;
+
+               *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+
+               *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+               *bit = pin_num % RK3188_PULL_PINS_PER_REG;
+               *bit *= RK3188_PULL_BITS_PER_PIN;
+       } else {
+               *regmap = info->regmap_base;
+               *reg = RK3399_PULL_GRF_OFFSET;
+
+               /* correct the offset, as we're starting with the 3rd bank */
+               *reg -= 0x20;
+               *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+               *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+               *bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+               *bit *= RK3188_PULL_BITS_PER_PIN;
+       }
+}
+
+static void rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+                                       int pin_num, struct regmap **regmap,
+                                       int *reg, u8 *bit)
+{
+       struct rockchip_pinctrl *info = bank->drvdata;
+       int drv_num = (pin_num / 8);
+
+       /*  The bank0:16 and bank1:32 pins are located in PMU */
+       if ((bank->bank_num == 0) || (bank->bank_num == 1))
+               *regmap = info->regmap_pmu;
+       else
+               *regmap = info->regmap_base;
+
+       *reg = bank->drv[drv_num].offset;
+       if ((bank->drv[drv_num].drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) ||
+           (bank->drv[drv_num].drv_type == DRV_TYPE_IO_3V3_ONLY))
+               *bit = (pin_num % 8) * 3;
+       else
+               *bit = (pin_num % 8) * 2;
+}
+
+static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = {
+       { 2, 4, 8, 12, -1, -1, -1, -1 },
+       { 3, 6, 9, 12, -1, -1, -1, -1 },
+       { 5, 10, 15, 20, -1, -1, -1, -1 },
+       { 4, 6, 8, 10, 12, 14, 16, 18 },
+       { 4, 7, 10, 13, 16, 19, 22, 26 }
+};
 
 static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank,
                                     int pin_num)
@@ -714,19 +847,74 @@ static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank,
        struct rockchip_pin_ctrl *ctrl = info->ctrl;
        struct regmap *regmap;
        int reg, ret;
-       u32 data;
+       u32 data, temp, rmask_bits;
        u8 bit;
+       int drv_type = bank->drv[pin_num / 8].drv_type;
 
        ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
 
+       switch (drv_type) {
+       case DRV_TYPE_IO_1V8_3V0_AUTO:
+       case DRV_TYPE_IO_3V3_ONLY:
+               rmask_bits = RK3399_DRV_3BITS_PER_PIN;
+               switch (bit) {
+               case 0 ... 12:
+                       /* regular case, nothing to do */
+                       break;
+               case 15:
+                       /*
+                        * drive-strength offset is special, as it is
+                        * spread over 2 registers
+                        */
+                       ret = regmap_read(regmap, reg, &data);
+                       if (ret)
+                               return ret;
+
+                       ret = regmap_read(regmap, reg + 0x4, &temp);
+                       if (ret)
+                               return ret;
+
+                       /*
+                        * the bit data[15] contains bit 0 of the value
+                        * while temp[1:0] contains bits 2 and 1
+                        */
+                       data >>= 15;
+                       temp &= 0x3;
+                       temp <<= 1;
+                       data |= temp;
+
+                       return rockchip_perpin_drv_list[drv_type][data];
+               case 18 ... 21:
+                       /* setting fully enclosed in the second register */
+                       reg += 4;
+                       bit -= 16;
+                       break;
+               default:
+                       dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n",
+                               bit, drv_type);
+                       return -EINVAL;
+               }
+
+               break;
+       case DRV_TYPE_IO_DEFAULT:
+       case DRV_TYPE_IO_1V8_OR_3V0:
+       case DRV_TYPE_IO_1V8_ONLY:
+               rmask_bits = RK3288_DRV_BITS_PER_PIN;
+               break;
+       default:
+               dev_err(info->dev, "unsupported pinctrl drive type: %d\n",
+                       drv_type);
+               return -EINVAL;
+       }
+
        ret = regmap_read(regmap, reg, &data);
        if (ret)
                return ret;
 
        data >>= bit;
-       data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1;
+       data &= (1 << rmask_bits) - 1;
 
-       return rockchip_perpin_drv_list[data];
+       return rockchip_perpin_drv_list[drv_type][data];
 }
 
 static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
@@ -737,16 +925,23 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
        struct regmap *regmap;
        unsigned long flags;
        int reg, ret, i;
-       u32 data, rmask;
+       u32 data, rmask, rmask_bits, temp;
        u8 bit;
+       int drv_type = bank->drv[pin_num / 8].drv_type;
+
+       dev_dbg(info->dev, "setting drive of GPIO%d-%d to %d\n",
+               bank->bank_num, pin_num, strength);
 
        ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
 
        ret = -EINVAL;
-       for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list); i++) {
-               if (rockchip_perpin_drv_list[i] == strength) {
+       for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list[drv_type]); i++) {
+               if (rockchip_perpin_drv_list[drv_type][i] == strength) {
                        ret = i;
                        break;
+               } else if (rockchip_perpin_drv_list[drv_type][i] < 0) {
+                       ret = rockchip_perpin_drv_list[drv_type][i];
+                       break;
                }
        }
 
@@ -758,8 +953,64 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
 
        spin_lock_irqsave(&bank->slock, flags);
 
+       switch (drv_type) {
+       case DRV_TYPE_IO_1V8_3V0_AUTO:
+       case DRV_TYPE_IO_3V3_ONLY:
+               rmask_bits = RK3399_DRV_3BITS_PER_PIN;
+               switch (bit) {
+               case 0 ... 12:
+                       /* regular case, nothing to do */
+                       break;
+               case 15:
+                       /*
+                        * drive-strength offset is special, as it is spread
+                        * over 2 registers, the bit data[15] contains bit 0
+                        * of the value while temp[1:0] contains bits 2 and 1
+                        */
+                       data = (ret & 0x1) << 15;
+                       temp = (ret >> 0x1) & 0x3;
+
+                       rmask = BIT(15) | BIT(31);
+                       data |= BIT(31);
+                       ret = regmap_update_bits(regmap, reg, rmask, data);
+                       if (ret) {
+                               spin_unlock_irqrestore(&bank->slock, flags);
+                               return ret;
+                       }
+
+                       rmask = 0x3 | (0x3 << 16);
+                       temp |= (0x3 << 16);
+                       reg += 0x4;
+                       ret = regmap_update_bits(regmap, reg, rmask, temp);
+
+                       spin_unlock_irqrestore(&bank->slock, flags);
+                       return ret;
+               case 18 ... 21:
+                       /* setting fully enclosed in the second register */
+                       reg += 4;
+                       bit -= 16;
+                       break;
+               default:
+                       spin_unlock_irqrestore(&bank->slock, flags);
+                       dev_err(info->dev, "unsupported bit: %d for pinctrl drive type: %d\n",
+                               bit, drv_type);
+                       return -EINVAL;
+               }
+               break;
+       case DRV_TYPE_IO_DEFAULT:
+       case DRV_TYPE_IO_1V8_OR_3V0:
+       case DRV_TYPE_IO_1V8_ONLY:
+               rmask_bits = RK3288_DRV_BITS_PER_PIN;
+               break;
+       default:
+               spin_unlock_irqrestore(&bank->slock, flags);
+               dev_err(info->dev, "unsupported pinctrl drive type: %d\n",
+                       drv_type);
+               return -EINVAL;
+       }
+
        /* enable the write to the equivalent lower bits */
-       data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+       data = ((1 << rmask_bits) - 1) << (bit + 16);
        rmask = data | (data >> 16);
        data |= (ret << bit);
 
@@ -796,6 +1047,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
        case RK3188:
        case RK3288:
        case RK3368:
+       case RK3399:
                data >>= bit;
                data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
 
@@ -852,6 +1104,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
        case RK3188:
        case RK3288:
        case RK3368:
+       case RK3399:
                spin_lock_irqsave(&bank->slock, flags);
 
                /* enable the write to the equivalent lower bits */
@@ -1032,6 +1285,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
        case RK3188:
        case RK3288:
        case RK3368:
+       case RK3399:
                return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT);
        }
 
@@ -1892,7 +2146,7 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
        struct device_node *np;
        struct rockchip_pin_ctrl *ctrl;
        struct rockchip_pin_bank *bank;
-       int grf_offs, pmu_offs, i, j;
+       int grf_offs, pmu_offs, drv_grf_offs, drv_pmu_offs, i, j;
 
        match = of_match_node(rockchip_pinctrl_dt_match, node);
        ctrl = (struct rockchip_pin_ctrl *)match->data;
@@ -1916,6 +2170,8 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
 
        grf_offs = ctrl->grf_mux_offset;
        pmu_offs = ctrl->pmu_mux_offset;
+       drv_pmu_offs = ctrl->pmu_drv_offset;
+       drv_grf_offs = ctrl->grf_drv_offset;
        bank = ctrl->pin_banks;
        for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
                int bank_pins = 0;
@@ -1925,27 +2181,39 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
                bank->pin_base = ctrl->nr_pins;
                ctrl->nr_pins += bank->nr_pins;
 
-               /* calculate iomux offsets */
+               /* calculate iomux and drv offsets */
                for (j = 0; j < 4; j++) {
                        struct rockchip_iomux *iom = &bank->iomux[j];
+                       struct rockchip_drv *drv = &bank->drv[j];
                        int inc;
 
                        if (bank_pins >= bank->nr_pins)
                                break;
 
-                       /* preset offset value, set new start value */
+                       /* preset iomux offset value, set new start value */
                        if (iom->offset >= 0) {
                                if (iom->type & IOMUX_SOURCE_PMU)
                                        pmu_offs = iom->offset;
                                else
                                        grf_offs = iom->offset;
-                       } else { /* set current offset */
+                       } else { /* set current iomux offset */
                                iom->offset = (iom->type & IOMUX_SOURCE_PMU) ?
                                                        pmu_offs : grf_offs;
                        }
 
-                       dev_dbg(d->dev, "bank %d, iomux %d has offset 0x%x\n",
-                                i, j, iom->offset);
+                       /* preset drv offset value, set new start value */
+                       if (drv->offset >= 0) {
+                               if (iom->type & IOMUX_SOURCE_PMU)
+                                       drv_pmu_offs = drv->offset;
+                               else
+                                       drv_grf_offs = drv->offset;
+                       } else { /* set current drv offset */
+                               drv->offset = (iom->type & IOMUX_SOURCE_PMU) ?
+                                               drv_pmu_offs : drv_grf_offs;
+                       }
+
+                       dev_dbg(d->dev, "bank %d, iomux %d has iom_offset 0x%x drv_offset 0x%x\n",
+                               i, j, iom->offset, drv->offset);
 
                        /*
                         * Increase offset according to iomux width.
@@ -1957,6 +2225,21 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(
                        else
                                grf_offs += inc;
 
+                       /*
+                        * Increase offset according to drv width.
+                        * 3bit drive-strenth'es are spread over two registers.
+                        */
+                       if ((drv->drv_type == DRV_TYPE_IO_1V8_3V0_AUTO) ||
+                           (drv->drv_type == DRV_TYPE_IO_3V3_ONLY))
+                               inc = 8;
+                       else
+                               inc = 4;
+
+                       if (iom->type & IOMUX_SOURCE_PMU)
+                               drv_pmu_offs += inc;
+                       else
+                               drv_grf_offs += inc;
+
                        bank_pins += 8;
                }
        }
@@ -2257,6 +2540,62 @@ static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
                .drv_calc_reg           = rk3368_calc_drv_reg_and_bit,
 };
 
+static struct rockchip_pin_bank rk3399_pin_banks[] = {
+       PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+                                       IOMUX_SOURCE_PMU,
+                                       IOMUX_SOURCE_PMU,
+                                       IOMUX_SOURCE_PMU,
+                                       DRV_TYPE_IO_1V8_ONLY,
+                                       DRV_TYPE_IO_1V8_ONLY,
+                                       DRV_TYPE_IO_DEFAULT,
+                                       DRV_TYPE_IO_DEFAULT,
+                                       0x0,
+                                       0x8,
+                                       -1,
+                                       -1
+                                       ),
+       PIN_BANK_IOMUX_DRV_FLAGS_OFFSET(1, 32, "gpio1", IOMUX_SOURCE_PMU,
+                                       IOMUX_SOURCE_PMU,
+                                       IOMUX_SOURCE_PMU,
+                                       IOMUX_SOURCE_PMU,
+                                       DRV_TYPE_IO_1V8_OR_3V0,
+                                       DRV_TYPE_IO_1V8_OR_3V0,
+                                       DRV_TYPE_IO_1V8_OR_3V0,
+                                       DRV_TYPE_IO_1V8_OR_3V0,
+                                       0x20,
+                                       0x28,
+                                       0x30,
+                                       0x38
+                                       ),
+       PIN_BANK_DRV_FLAGS(2, 32, "gpio2", DRV_TYPE_IO_1V8_OR_3V0,
+                          DRV_TYPE_IO_1V8_OR_3V0,
+                          DRV_TYPE_IO_1V8_ONLY,
+                          DRV_TYPE_IO_1V8_ONLY
+                          ),
+       PIN_BANK_DRV_FLAGS(3, 32, "gpio3", DRV_TYPE_IO_3V3_ONLY,
+                          DRV_TYPE_IO_3V3_ONLY,
+                          DRV_TYPE_IO_3V3_ONLY,
+                          DRV_TYPE_IO_1V8_OR_3V0
+                          ),
+       PIN_BANK_DRV_FLAGS(4, 32, "gpio4", DRV_TYPE_IO_1V8_OR_3V0,
+                          DRV_TYPE_IO_1V8_3V0_AUTO,
+                          DRV_TYPE_IO_1V8_OR_3V0,
+                          DRV_TYPE_IO_1V8_OR_3V0
+                          ),
+};
+
+static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
+               .pin_banks              = rk3399_pin_banks,
+               .nr_banks               = ARRAY_SIZE(rk3399_pin_banks),
+               .label                  = "RK3399-GPIO",
+               .type                   = RK3399,
+               .grf_mux_offset         = 0xe000,
+               .pmu_mux_offset         = 0x0,
+               .grf_drv_offset         = 0xe100,
+               .pmu_drv_offset         = 0x80,
+               .pull_calc_reg          = rk3399_calc_pull_reg_and_bit,
+               .drv_calc_reg           = rk3399_calc_drv_reg_and_bit,
+};
 
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
        { .compatible = "rockchip,rk2928-pinctrl",
@@ -2275,6 +2614,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
                .data = (void *)&rk3288_pin_ctrl },
        { .compatible = "rockchip,rk3368-pinctrl",
                .data = (void *)&rk3368_pin_ctrl },
+       { .compatible = "rockchip,rk3399-pinctrl",
+               .data = (void *)&rk3399_pin_ctrl },
        {},
 };
 MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match);
index d24e5f1d15252f29f586badeb94ef620a7d33a73..fb126d56ad40d4c381230978f4da49baca049d40 100644 (file)
@@ -254,6 +254,13 @@ static enum pin_config_param pcs_bias[] = {
        PIN_CONFIG_BIAS_PULL_UP,
 };
 
+/*
+ * This lock class tells lockdep that irqchip core that this single
+ * pinctrl can be in a different category than its parents, so it won't
+ * report false recursion.
+ */
+static struct lock_class_key pcs_lock_class;
+
 /*
  * REVISIT: Reads and writes could eventually use regmap or something
  * generic. But at least on omaps, some mux registers are performance
@@ -1713,6 +1720,7 @@ static int pcs_irqdomain_map(struct irq_domain *d, unsigned int irq,
        irq_set_chip_data(irq, pcs_soc);
        irq_set_chip_and_handler(irq, &pcs->chip,
                                 handle_level_irq);
+       irq_set_lockdep_class(irq, &pcs_lock_class);
        irq_set_noprobe(irq);
 
        return 0;
index fac844a85cb46b14a48a5c6d973a2a57ea630e4e..cab66c64149fc103aedad05784e46a35e95fccd1 100644 (file)
@@ -985,6 +985,7 @@ static struct pinmux_ops st_pmxops = {
        .get_function_groups    = st_pmx_get_groups,
        .set_mux                = st_pmx_set_mux,
        .gpio_set_direction     = st_pmx_set_gpio_direction,
+       .strict                 = true,
 };
 
 /* Pinconf  */
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
deleted file mode 100644 (file)
index bd3aa5a..0000000
+++ /dev/null
@@ -1,985 +0,0 @@
-/*
- * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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/delay.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/phy/phy.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-
-#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
-
-#include "core.h"
-#include "pinctrl-utils.h"
-
-#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
-#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
-#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
-#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
-
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
-
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
-
-#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
-#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
-#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
-#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
-#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
-#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
-
-#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
-#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
-#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
-
-struct tegra_xusb_padctl_function {
-       const char *name;
-       const char * const *groups;
-       unsigned int num_groups;
-};
-
-struct tegra_xusb_padctl_soc {
-       const struct pinctrl_pin_desc *pins;
-       unsigned int num_pins;
-
-       const struct tegra_xusb_padctl_function *functions;
-       unsigned int num_functions;
-
-       const struct tegra_xusb_padctl_lane *lanes;
-       unsigned int num_lanes;
-};
-
-struct tegra_xusb_padctl_lane {
-       const char *name;
-
-       unsigned int offset;
-       unsigned int shift;
-       unsigned int mask;
-       unsigned int iddq;
-
-       const unsigned int *funcs;
-       unsigned int num_funcs;
-};
-
-struct tegra_xusb_padctl {
-       struct device *dev;
-       void __iomem *regs;
-       struct mutex lock;
-       struct reset_control *rst;
-
-       const struct tegra_xusb_padctl_soc *soc;
-       struct pinctrl_dev *pinctrl;
-       struct pinctrl_desc desc;
-
-       struct phy_provider *provider;
-       struct phy *phys[2];
-
-       unsigned int enable;
-};
-
-static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
-                                unsigned long offset)
-{
-       writel(value, padctl->regs + offset);
-}
-
-static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
-                              unsigned long offset)
-{
-       return readl(padctl->regs + offset);
-}
-
-static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-
-       return padctl->soc->num_pins;
-}
-
-static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
-                                                   unsigned int group)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-
-       return padctl->soc->pins[group].name;
-}
-
-static int tegra_xusb_padctl_get_group_pins(struct pinctrl_dev *pinctrl,
-                                           unsigned group,
-                                           const unsigned **pins,
-                                           unsigned *num_pins)
-{
-       /*
-        * For the tegra-xusb pad controller groups are synonomous
-        * with lanes/pins and there is always one lane/pin per group.
-        */
-       *pins = &pinctrl->desc->pins[group].number;
-       *num_pins = 1;
-
-       return 0;
-}
-
-enum tegra_xusb_padctl_param {
-       TEGRA_XUSB_PADCTL_IDDQ,
-};
-
-static const struct tegra_xusb_padctl_property {
-       const char *name;
-       enum tegra_xusb_padctl_param param;
-} properties[] = {
-       { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
-};
-
-#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
-#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16)
-#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff)
-
-static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl,
-                                          struct device_node *np,
-                                          struct pinctrl_map **maps,
-                                          unsigned int *reserved_maps,
-                                          unsigned int *num_maps)
-{
-       unsigned int i, reserve = 0, num_configs = 0;
-       unsigned long config, *configs = NULL;
-       const char *function, *group;
-       struct property *prop;
-       int err = 0;
-       u32 value;
-
-       err = of_property_read_string(np, "nvidia,function", &function);
-       if (err < 0) {
-               if (err != -EINVAL)
-                       return err;
-
-               function = NULL;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(properties); i++) {
-               err = of_property_read_u32(np, properties[i].name, &value);
-               if (err < 0) {
-                       if (err == -EINVAL)
-                               continue;
-
-                       goto out;
-               }
-
-               config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value);
-
-               err = pinctrl_utils_add_config(padctl->pinctrl, &configs,
-                                              &num_configs, config);
-               if (err < 0)
-                       goto out;
-       }
-
-       if (function)
-               reserve++;
-
-       if (num_configs)
-               reserve++;
-
-       err = of_property_count_strings(np, "nvidia,lanes");
-       if (err < 0)
-               goto out;
-
-       reserve *= err;
-
-       err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps,
-                                       num_maps, reserve);
-       if (err < 0)
-               goto out;
-
-       of_property_for_each_string(np, "nvidia,lanes", prop, group) {
-               if (function) {
-                       err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps,
-                                       reserved_maps, num_maps, group,
-                                       function);
-                       if (err < 0)
-                               goto out;
-               }
-
-               if (num_configs) {
-                       err = pinctrl_utils_add_map_configs(padctl->pinctrl,
-                                       maps, reserved_maps, num_maps, group,
-                                       configs, num_configs,
-                                       PIN_MAP_TYPE_CONFIGS_GROUP);
-                       if (err < 0)
-                               goto out;
-               }
-       }
-
-       err = 0;
-
-out:
-       kfree(configs);
-       return err;
-}
-
-static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
-                                           struct device_node *parent,
-                                           struct pinctrl_map **maps,
-                                           unsigned int *num_maps)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-       unsigned int reserved_maps = 0;
-       struct device_node *np;
-       int err;
-
-       *num_maps = 0;
-       *maps = NULL;
-
-       for_each_child_of_node(parent, np) {
-               err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
-                                                     &reserved_maps,
-                                                     num_maps);
-               if (err < 0) {
-                       of_node_put(np);
-                       return err;
-               }
-       }
-
-       return 0;
-}
-
-static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = {
-       .get_groups_count = tegra_xusb_padctl_get_groups_count,
-       .get_group_name = tegra_xusb_padctl_get_group_name,
-       .get_group_pins = tegra_xusb_padctl_get_group_pins,
-       .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map,
-       .dt_free_map = pinctrl_utils_dt_free_map,
-};
-
-static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-
-       return padctl->soc->num_functions;
-}
-
-static const char *
-tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl,
-                                   unsigned int function)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-
-       return padctl->soc->functions[function].name;
-}
-
-static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl,
-                                                unsigned int function,
-                                                const char * const **groups,
-                                                unsigned * const num_groups)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-
-       *num_groups = padctl->soc->functions[function].num_groups;
-       *groups = padctl->soc->functions[function].groups;
-
-       return 0;
-}
-
-static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl,
-                                       unsigned int function,
-                                       unsigned int group)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-       const struct tegra_xusb_padctl_lane *lane;
-       unsigned int i;
-       u32 value;
-
-       lane = &padctl->soc->lanes[group];
-
-       for (i = 0; i < lane->num_funcs; i++)
-               if (lane->funcs[i] == function)
-                       break;
-
-       if (i >= lane->num_funcs)
-               return -EINVAL;
-
-       value = padctl_readl(padctl, lane->offset);
-       value &= ~(lane->mask << lane->shift);
-       value |= i << lane->shift;
-       padctl_writel(padctl, value, lane->offset);
-
-       return 0;
-}
-
-static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = {
-       .get_functions_count = tegra_xusb_padctl_get_functions_count,
-       .get_function_name = tegra_xusb_padctl_get_function_name,
-       .get_function_groups = tegra_xusb_padctl_get_function_groups,
-       .set_mux = tegra_xusb_padctl_pinmux_set,
-};
-
-static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
-                                              unsigned int group,
-                                              unsigned long *config)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-       const struct tegra_xusb_padctl_lane *lane;
-       enum tegra_xusb_padctl_param param;
-       u32 value;
-
-       param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
-       lane = &padctl->soc->lanes[group];
-
-       switch (param) {
-       case TEGRA_XUSB_PADCTL_IDDQ:
-               /* lanes with iddq == 0 don't support this parameter */
-               if (lane->iddq == 0)
-                       return -EINVAL;
-
-               value = padctl_readl(padctl, lane->offset);
-
-               if (value & BIT(lane->iddq))
-                       value = 0;
-               else
-                       value = 1;
-
-               *config = TEGRA_XUSB_PADCTL_PACK(param, value);
-               break;
-
-       default:
-               dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
-                       param);
-               return -ENOTSUPP;
-       }
-
-       return 0;
-}
-
-static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
-                                              unsigned int group,
-                                              unsigned long *configs,
-                                              unsigned int num_configs)
-{
-       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
-       const struct tegra_xusb_padctl_lane *lane;
-       enum tegra_xusb_padctl_param param;
-       unsigned long value;
-       unsigned int i;
-       u32 regval;
-
-       lane = &padctl->soc->lanes[group];
-
-       for (i = 0; i < num_configs; i++) {
-               param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]);
-               value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]);
-
-               switch (param) {
-               case TEGRA_XUSB_PADCTL_IDDQ:
-                       /* lanes with iddq == 0 don't support this parameter */
-                       if (lane->iddq == 0)
-                               return -EINVAL;
-
-                       regval = padctl_readl(padctl, lane->offset);
-
-                       if (value)
-                               regval &= ~BIT(lane->iddq);
-                       else
-                               regval |= BIT(lane->iddq);
-
-                       padctl_writel(padctl, regval, lane->offset);
-                       break;
-
-               default:
-                       dev_err(padctl->dev,
-                               "invalid configuration parameter: %04x\n",
-                               param);
-                       return -ENOTSUPP;
-               }
-       }
-
-       return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static const char *strip_prefix(const char *s)
-{
-       const char *comma = strchr(s, ',');
-       if (!comma)
-               return s;
-
-       return comma + 1;
-}
-
-static void
-tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl,
-                                        struct seq_file *s,
-                                        unsigned int group)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(properties); i++) {
-               unsigned long config, value;
-               int err;
-
-               config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0);
-
-               err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group,
-                                                         &config);
-               if (err < 0)
-                       continue;
-
-               value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
-
-               seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name),
-                          value);
-       }
-}
-
-static void
-tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl,
-                                         struct seq_file *s,
-                                         unsigned long config)
-{
-       enum tegra_xusb_padctl_param param;
-       const char *name = "unknown";
-       unsigned long value;
-       unsigned int i;
-
-       param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config);
-       value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
-
-       for (i = 0; i < ARRAY_SIZE(properties); i++) {
-               if (properties[i].param == param) {
-                       name = properties[i].name;
-                       break;
-               }
-       }
-
-       seq_printf(s, "%s=%lu", strip_prefix(name), value);
-}
-#endif
-
-static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
-       .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get,
-       .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set,
-#ifdef CONFIG_DEBUG_FS
-       .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show,
-       .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show,
-#endif
-};
-
-static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
-{
-       u32 value;
-
-       mutex_lock(&padctl->lock);
-
-       if (padctl->enable++ > 0)
-               goto out;
-
-       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
-       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
-       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
-
-       usleep_range(100, 200);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
-       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
-       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
-
-       usleep_range(100, 200);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
-       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
-       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
-
-out:
-       mutex_unlock(&padctl->lock);
-       return 0;
-}
-
-static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
-{
-       u32 value;
-
-       mutex_lock(&padctl->lock);
-
-       if (WARN_ON(padctl->enable == 0))
-               goto out;
-
-       if (--padctl->enable > 0)
-               goto out;
-
-       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
-       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
-       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
-
-       usleep_range(100, 200);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
-       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
-       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
-
-       usleep_range(100, 200);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
-       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
-       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
-
-out:
-       mutex_unlock(&padctl->lock);
-       return 0;
-}
-
-static int tegra_xusb_phy_init(struct phy *phy)
-{
-       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
-
-       return tegra_xusb_padctl_enable(padctl);
-}
-
-static int tegra_xusb_phy_exit(struct phy *phy)
-{
-       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
-
-       return tegra_xusb_padctl_disable(padctl);
-}
-
-static int pcie_phy_power_on(struct phy *phy)
-{
-       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
-       unsigned long timeout;
-       int err = -ETIMEDOUT;
-       u32 value;
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
-       value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
-       value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
-                XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
-                XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
-       value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
-
-       timeout = jiffies + msecs_to_jiffies(50);
-
-       while (time_before(jiffies, timeout)) {
-               value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
-               if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
-                       err = 0;
-                       break;
-               }
-
-               usleep_range(100, 200);
-       }
-
-       return err;
-}
-
-static int pcie_phy_power_off(struct phy *phy)
-{
-       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
-       u32 value;
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
-       value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
-
-       return 0;
-}
-
-static const struct phy_ops pcie_phy_ops = {
-       .init = tegra_xusb_phy_init,
-       .exit = tegra_xusb_phy_exit,
-       .power_on = pcie_phy_power_on,
-       .power_off = pcie_phy_power_off,
-       .owner = THIS_MODULE,
-};
-
-static int sata_phy_power_on(struct phy *phy)
-{
-       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
-       unsigned long timeout;
-       int err = -ETIMEDOUT;
-       u32 value;
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
-       value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
-       value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
-       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-
-       timeout = jiffies + msecs_to_jiffies(50);
-
-       while (time_before(jiffies, timeout)) {
-               value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-               if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
-                       err = 0;
-                       break;
-               }
-
-               usleep_range(100, 200);
-       }
-
-       return err;
-}
-
-static int sata_phy_power_off(struct phy *phy)
-{
-       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
-       u32 value;
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
-       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
-
-       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
-       value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
-       value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
-       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
-
-       return 0;
-}
-
-static const struct phy_ops sata_phy_ops = {
-       .init = tegra_xusb_phy_init,
-       .exit = tegra_xusb_phy_exit,
-       .power_on = sata_phy_power_on,
-       .power_off = sata_phy_power_off,
-       .owner = THIS_MODULE,
-};
-
-static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
-                                          struct of_phandle_args *args)
-{
-       struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
-       unsigned int index = args->args[0];
-
-       if (args->args_count <= 0)
-               return ERR_PTR(-EINVAL);
-
-       if (index >= ARRAY_SIZE(padctl->phys))
-               return ERR_PTR(-EINVAL);
-
-       return padctl->phys[index];
-}
-
-#define PIN_OTG_0   0
-#define PIN_OTG_1   1
-#define PIN_OTG_2   2
-#define PIN_ULPI_0  3
-#define PIN_HSIC_0  4
-#define PIN_HSIC_1  5
-#define PIN_PCIE_0  6
-#define PIN_PCIE_1  7
-#define PIN_PCIE_2  8
-#define PIN_PCIE_3  9
-#define PIN_PCIE_4 10
-#define PIN_SATA_0 11
-
-static const struct pinctrl_pin_desc tegra124_pins[] = {
-       PINCTRL_PIN(PIN_OTG_0,  "otg-0"),
-       PINCTRL_PIN(PIN_OTG_1,  "otg-1"),
-       PINCTRL_PIN(PIN_OTG_2,  "otg-2"),
-       PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
-       PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
-       PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
-       PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
-       PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
-       PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
-       PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
-       PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
-       PINCTRL_PIN(PIN_SATA_0, "sata-0"),
-};
-
-static const char * const tegra124_snps_groups[] = {
-       "otg-0",
-       "otg-1",
-       "otg-2",
-       "ulpi-0",
-       "hsic-0",
-       "hsic-1",
-};
-
-static const char * const tegra124_xusb_groups[] = {
-       "otg-0",
-       "otg-1",
-       "otg-2",
-       "ulpi-0",
-       "hsic-0",
-       "hsic-1",
-};
-
-static const char * const tegra124_uart_groups[] = {
-       "otg-0",
-       "otg-1",
-       "otg-2",
-};
-
-static const char * const tegra124_pcie_groups[] = {
-       "pcie-0",
-       "pcie-1",
-       "pcie-2",
-       "pcie-3",
-       "pcie-4",
-};
-
-static const char * const tegra124_usb3_groups[] = {
-       "pcie-0",
-       "pcie-1",
-       "sata-0",
-};
-
-static const char * const tegra124_sata_groups[] = {
-       "sata-0",
-};
-
-static const char * const tegra124_rsvd_groups[] = {
-       "otg-0",
-       "otg-1",
-       "otg-2",
-       "pcie-0",
-       "pcie-1",
-       "pcie-2",
-       "pcie-3",
-       "pcie-4",
-       "sata-0",
-};
-
-#define TEGRA124_FUNCTION(_name)                                       \
-       {                                                               \
-               .name = #_name,                                         \
-               .num_groups = ARRAY_SIZE(tegra124_##_name##_groups),    \
-               .groups = tegra124_##_name##_groups,                    \
-       }
-
-static struct tegra_xusb_padctl_function tegra124_functions[] = {
-       TEGRA124_FUNCTION(snps),
-       TEGRA124_FUNCTION(xusb),
-       TEGRA124_FUNCTION(uart),
-       TEGRA124_FUNCTION(pcie),
-       TEGRA124_FUNCTION(usb3),
-       TEGRA124_FUNCTION(sata),
-       TEGRA124_FUNCTION(rsvd),
-};
-
-enum tegra124_function {
-       TEGRA124_FUNC_SNPS,
-       TEGRA124_FUNC_XUSB,
-       TEGRA124_FUNC_UART,
-       TEGRA124_FUNC_PCIE,
-       TEGRA124_FUNC_USB3,
-       TEGRA124_FUNC_SATA,
-       TEGRA124_FUNC_RSVD,
-};
-
-static const unsigned int tegra124_otg_functions[] = {
-       TEGRA124_FUNC_SNPS,
-       TEGRA124_FUNC_XUSB,
-       TEGRA124_FUNC_UART,
-       TEGRA124_FUNC_RSVD,
-};
-
-static const unsigned int tegra124_usb_functions[] = {
-       TEGRA124_FUNC_SNPS,
-       TEGRA124_FUNC_XUSB,
-};
-
-static const unsigned int tegra124_pci_functions[] = {
-       TEGRA124_FUNC_PCIE,
-       TEGRA124_FUNC_USB3,
-       TEGRA124_FUNC_SATA,
-       TEGRA124_FUNC_RSVD,
-};
-
-#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)    \
-       {                                                               \
-               .name = _name,                                          \
-               .offset = _offset,                                      \
-               .shift = _shift,                                        \
-               .mask = _mask,                                          \
-               .iddq = _iddq,                                          \
-               .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \
-               .funcs = tegra124_##_funcs##_functions,                 \
-       }
-
-static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
-       TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
-       TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
-       TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
-       TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
-       TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
-       TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
-       TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
-       TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
-       TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
-       TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
-       TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
-       TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
-};
-
-static const struct tegra_xusb_padctl_soc tegra124_soc = {
-       .num_pins = ARRAY_SIZE(tegra124_pins),
-       .pins = tegra124_pins,
-       .num_functions = ARRAY_SIZE(tegra124_functions),
-       .functions = tegra124_functions,
-       .num_lanes = ARRAY_SIZE(tegra124_lanes),
-       .lanes = tegra124_lanes,
-};
-
-static const struct of_device_id tegra_xusb_padctl_of_match[] = {
-       { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc },
-       { }
-};
-MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
-
-static int tegra_xusb_padctl_probe(struct platform_device *pdev)
-{
-       struct tegra_xusb_padctl *padctl;
-       const struct of_device_id *match;
-       struct resource *res;
-       struct phy *phy;
-       int err;
-
-       padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
-       if (!padctl)
-               return -ENOMEM;
-
-       platform_set_drvdata(pdev, padctl);
-       mutex_init(&padctl->lock);
-       padctl->dev = &pdev->dev;
-
-       match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node);
-       padctl->soc = match->data;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       padctl->regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(padctl->regs))
-               return PTR_ERR(padctl->regs);
-
-       padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
-       if (IS_ERR(padctl->rst))
-               return PTR_ERR(padctl->rst);
-
-       err = reset_control_deassert(padctl->rst);
-       if (err < 0)
-               return err;
-
-       memset(&padctl->desc, 0, sizeof(padctl->desc));
-       padctl->desc.name = dev_name(padctl->dev);
-       padctl->desc.pins = tegra124_pins;
-       padctl->desc.npins = ARRAY_SIZE(tegra124_pins);
-       padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
-       padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops;
-       padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops;
-       padctl->desc.owner = THIS_MODULE;
-
-       padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl);
-       if (IS_ERR(padctl->pinctrl)) {
-               dev_err(&pdev->dev, "failed to register pincontrol\n");
-               err = PTR_ERR(padctl->pinctrl);
-               goto reset;
-       }
-
-       phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops);
-       if (IS_ERR(phy)) {
-               err = PTR_ERR(phy);
-               goto unregister;
-       }
-
-       padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
-       phy_set_drvdata(phy, padctl);
-
-       phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops);
-       if (IS_ERR(phy)) {
-               err = PTR_ERR(phy);
-               goto unregister;
-       }
-
-       padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
-       phy_set_drvdata(phy, padctl);
-
-       padctl->provider = devm_of_phy_provider_register(&pdev->dev,
-                                                        tegra_xusb_padctl_xlate);
-       if (IS_ERR(padctl->provider)) {
-               err = PTR_ERR(padctl->provider);
-               dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
-               goto unregister;
-       }
-
-       return 0;
-
-unregister:
-       pinctrl_unregister(padctl->pinctrl);
-reset:
-       reset_control_assert(padctl->rst);
-       return err;
-}
-
-static int tegra_xusb_padctl_remove(struct platform_device *pdev)
-{
-       struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
-       int err;
-
-       pinctrl_unregister(padctl->pinctrl);
-
-       err = reset_control_assert(padctl->rst);
-       if (err < 0)
-               dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
-
-       return err;
-}
-
-static struct platform_driver tegra_xusb_padctl_driver = {
-       .driver = {
-               .name = "tegra-xusb-padctl",
-               .of_match_table = tegra_xusb_padctl_of_match,
-       },
-       .probe = tegra_xusb_padctl_probe,
-       .remove = tegra_xusb_padctl_remove,
-};
-module_platform_driver(tegra_xusb_padctl_driver);
-
-MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
-MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
deleted file mode 100644 (file)
index 9da4da2..0000000
+++ /dev/null
@@ -1,747 +0,0 @@
-/*
- * Driver for the NVIDIA Tegra pinmux
- *
- * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * Derived from code:
- * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2010 NVIDIA Corporation
- * Copyright (C) 2009-2011 ST-Ericsson AB
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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/err.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/machine.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-#include <linux/pinctrl/pinconf.h>
-#include <linux/slab.h>
-
-#include "core.h"
-#include "pinctrl-tegra.h"
-#include "pinctrl-utils.h"
-
-struct tegra_pmx {
-       struct device *dev;
-       struct pinctrl_dev *pctl;
-
-       const struct tegra_pinctrl_soc_data *soc;
-       const char **group_pins;
-
-       int nbanks;
-       void __iomem **regs;
-};
-
-static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg)
-{
-       return readl(pmx->regs[bank] + reg);
-}
-
-static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
-{
-       writel(val, pmx->regs[bank] + reg);
-}
-
-static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-       return pmx->soc->ngroups;
-}
-
-static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
-                                               unsigned group)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-       return pmx->soc->groups[group].name;
-}
-
-static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
-                                       unsigned group,
-                                       const unsigned **pins,
-                                       unsigned *num_pins)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-       *pins = pmx->soc->groups[group].pins;
-       *num_pins = pmx->soc->groups[group].npins;
-
-       return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
-                                      struct seq_file *s,
-                                      unsigned offset)
-{
-       seq_printf(s, " %s", dev_name(pctldev->dev));
-}
-#endif
-
-static const struct cfg_param {
-       const char *property;
-       enum tegra_pinconf_param param;
-} cfg_params[] = {
-       {"nvidia,pull",                 TEGRA_PINCONF_PARAM_PULL},
-       {"nvidia,tristate",             TEGRA_PINCONF_PARAM_TRISTATE},
-       {"nvidia,enable-input",         TEGRA_PINCONF_PARAM_ENABLE_INPUT},
-       {"nvidia,open-drain",           TEGRA_PINCONF_PARAM_OPEN_DRAIN},
-       {"nvidia,lock",                 TEGRA_PINCONF_PARAM_LOCK},
-       {"nvidia,io-reset",             TEGRA_PINCONF_PARAM_IORESET},
-       {"nvidia,rcv-sel",              TEGRA_PINCONF_PARAM_RCV_SEL},
-       {"nvidia,io-hv",                TEGRA_PINCONF_PARAM_RCV_SEL},
-       {"nvidia,high-speed-mode",      TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE},
-       {"nvidia,schmitt",              TEGRA_PINCONF_PARAM_SCHMITT},
-       {"nvidia,low-power-mode",       TEGRA_PINCONF_PARAM_LOW_POWER_MODE},
-       {"nvidia,pull-down-strength",   TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH},
-       {"nvidia,pull-up-strength",     TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH},
-       {"nvidia,slew-rate-falling",    TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING},
-       {"nvidia,slew-rate-rising",     TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
-       {"nvidia,drive-type",           TEGRA_PINCONF_PARAM_DRIVE_TYPE},
-};
-
-static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
-                                          struct device_node *np,
-                                          struct pinctrl_map **map,
-                                          unsigned *reserved_maps,
-                                          unsigned *num_maps)
-{
-       struct device *dev = pctldev->dev;
-       int ret, i;
-       const char *function;
-       u32 val;
-       unsigned long config;
-       unsigned long *configs = NULL;
-       unsigned num_configs = 0;
-       unsigned reserve;
-       struct property *prop;
-       const char *group;
-
-       ret = of_property_read_string(np, "nvidia,function", &function);
-       if (ret < 0) {
-               /* EINVAL=missing, which is fine since it's optional */
-               if (ret != -EINVAL)
-                       dev_err(dev,
-                               "could not parse property nvidia,function\n");
-               function = NULL;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
-               ret = of_property_read_u32(np, cfg_params[i].property, &val);
-               if (!ret) {
-                       config = TEGRA_PINCONF_PACK(cfg_params[i].param, val);
-                       ret = pinctrl_utils_add_config(pctldev, &configs,
-                                       &num_configs, config);
-                       if (ret < 0)
-                               goto exit;
-               /* EINVAL=missing, which is fine since it's optional */
-               } else if (ret != -EINVAL) {
-                       dev_err(dev, "could not parse property %s\n",
-                               cfg_params[i].property);
-               }
-       }
-
-       reserve = 0;
-       if (function != NULL)
-               reserve++;
-       if (num_configs)
-               reserve++;
-       ret = of_property_count_strings(np, "nvidia,pins");
-       if (ret < 0) {
-               dev_err(dev, "could not parse property nvidia,pins\n");
-               goto exit;
-       }
-       reserve *= ret;
-
-       ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
-                                       num_maps, reserve);
-       if (ret < 0)
-               goto exit;
-
-       of_property_for_each_string(np, "nvidia,pins", prop, group) {
-               if (function) {
-                       ret = pinctrl_utils_add_map_mux(pctldev, map,
-                                       reserved_maps, num_maps, group,
-                                       function);
-                       if (ret < 0)
-                               goto exit;
-               }
-
-               if (num_configs) {
-                       ret = pinctrl_utils_add_map_configs(pctldev, map,
-                                       reserved_maps, num_maps, group,
-                                       configs, num_configs,
-                                       PIN_MAP_TYPE_CONFIGS_GROUP);
-                       if (ret < 0)
-                               goto exit;
-               }
-       }
-
-       ret = 0;
-
-exit:
-       kfree(configs);
-       return ret;
-}
-
-static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-                                       struct device_node *np_config,
-                                       struct pinctrl_map **map,
-                                       unsigned *num_maps)
-{
-       unsigned reserved_maps;
-       struct device_node *np;
-       int ret;
-
-       reserved_maps = 0;
-       *map = NULL;
-       *num_maps = 0;
-
-       for_each_child_of_node(np_config, np) {
-               ret = tegra_pinctrl_dt_subnode_to_map(pctldev, np, map,
-                                                     &reserved_maps, num_maps);
-               if (ret < 0) {
-                       pinctrl_utils_dt_free_map(pctldev, *map,
-                               *num_maps);
-                       of_node_put(np);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static const struct pinctrl_ops tegra_pinctrl_ops = {
-       .get_groups_count = tegra_pinctrl_get_groups_count,
-       .get_group_name = tegra_pinctrl_get_group_name,
-       .get_group_pins = tegra_pinctrl_get_group_pins,
-#ifdef CONFIG_DEBUG_FS
-       .pin_dbg_show = tegra_pinctrl_pin_dbg_show,
-#endif
-       .dt_node_to_map = tegra_pinctrl_dt_node_to_map,
-       .dt_free_map = pinctrl_utils_dt_free_map,
-};
-
-static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-       return pmx->soc->nfunctions;
-}
-
-static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
-                                              unsigned function)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-       return pmx->soc->functions[function].name;
-}
-
-static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
-                                        unsigned function,
-                                        const char * const **groups,
-                                        unsigned * const num_groups)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-
-       *groups = pmx->soc->functions[function].groups;
-       *num_groups = pmx->soc->functions[function].ngroups;
-
-       return 0;
-}
-
-static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev,
-                                unsigned function,
-                                unsigned group)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-       const struct tegra_pingroup *g;
-       int i;
-       u32 val;
-
-       g = &pmx->soc->groups[group];
-
-       if (WARN_ON(g->mux_reg < 0))
-               return -EINVAL;
-
-       for (i = 0; i < ARRAY_SIZE(g->funcs); i++) {
-               if (g->funcs[i] == function)
-                       break;
-       }
-       if (WARN_ON(i == ARRAY_SIZE(g->funcs)))
-               return -EINVAL;
-
-       val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
-       val &= ~(0x3 << g->mux_bit);
-       val |= i << g->mux_bit;
-       pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
-
-       return 0;
-}
-
-static const struct pinmux_ops tegra_pinmux_ops = {
-       .get_functions_count = tegra_pinctrl_get_funcs_count,
-       .get_function_name = tegra_pinctrl_get_func_name,
-       .get_function_groups = tegra_pinctrl_get_func_groups,
-       .set_mux = tegra_pinctrl_set_mux,
-};
-
-static int tegra_pinconf_reg(struct tegra_pmx *pmx,
-                            const struct tegra_pingroup *g,
-                            enum tegra_pinconf_param param,
-                            bool report_err,
-                            s8 *bank, s16 *reg, s8 *bit, s8 *width)
-{
-       switch (param) {
-       case TEGRA_PINCONF_PARAM_PULL:
-               *bank = g->pupd_bank;
-               *reg = g->pupd_reg;
-               *bit = g->pupd_bit;
-               *width = 2;
-               break;
-       case TEGRA_PINCONF_PARAM_TRISTATE:
-               *bank = g->tri_bank;
-               *reg = g->tri_reg;
-               *bit = g->tri_bit;
-               *width = 1;
-               break;
-       case TEGRA_PINCONF_PARAM_ENABLE_INPUT:
-               *bank = g->mux_bank;
-               *reg = g->mux_reg;
-               *bit = g->einput_bit;
-               *width = 1;
-               break;
-       case TEGRA_PINCONF_PARAM_OPEN_DRAIN:
-               *bank = g->mux_bank;
-               *reg = g->mux_reg;
-               *bit = g->odrain_bit;
-               *width = 1;
-               break;
-       case TEGRA_PINCONF_PARAM_LOCK:
-               *bank = g->mux_bank;
-               *reg = g->mux_reg;
-               *bit = g->lock_bit;
-               *width = 1;
-               break;
-       case TEGRA_PINCONF_PARAM_IORESET:
-               *bank = g->mux_bank;
-               *reg = g->mux_reg;
-               *bit = g->ioreset_bit;
-               *width = 1;
-               break;
-       case TEGRA_PINCONF_PARAM_RCV_SEL:
-               *bank = g->mux_bank;
-               *reg = g->mux_reg;
-               *bit = g->rcv_sel_bit;
-               *width = 1;
-               break;
-       case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE:
-               if (pmx->soc->hsm_in_mux) {
-                       *bank = g->mux_bank;
-                       *reg = g->mux_reg;
-               } else {
-                       *bank = g->drv_bank;
-                       *reg = g->drv_reg;
-               }
-               *bit = g->hsm_bit;
-               *width = 1;
-               break;
-       case TEGRA_PINCONF_PARAM_SCHMITT:
-               if (pmx->soc->schmitt_in_mux) {
-                       *bank = g->mux_bank;
-                       *reg = g->mux_reg;
-               } else {
-                       *bank = g->drv_bank;
-                       *reg = g->drv_reg;
-               }
-               *bit = g->schmitt_bit;
-               *width = 1;
-               break;
-       case TEGRA_PINCONF_PARAM_LOW_POWER_MODE:
-               *bank = g->drv_bank;
-               *reg = g->drv_reg;
-               *bit = g->lpmd_bit;
-               *width = 2;
-               break;
-       case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
-               *bank = g->drv_bank;
-               *reg = g->drv_reg;
-               *bit = g->drvdn_bit;
-               *width = g->drvdn_width;
-               break;
-       case TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH:
-               *bank = g->drv_bank;
-               *reg = g->drv_reg;
-               *bit = g->drvup_bit;
-               *width = g->drvup_width;
-               break;
-       case TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING:
-               *bank = g->drv_bank;
-               *reg = g->drv_reg;
-               *bit = g->slwf_bit;
-               *width = g->slwf_width;
-               break;
-       case TEGRA_PINCONF_PARAM_SLEW_RATE_RISING:
-               *bank = g->drv_bank;
-               *reg = g->drv_reg;
-               *bit = g->slwr_bit;
-               *width = g->slwr_width;
-               break;
-       case TEGRA_PINCONF_PARAM_DRIVE_TYPE:
-               if (pmx->soc->drvtype_in_mux) {
-                       *bank = g->mux_bank;
-                       *reg = g->mux_reg;
-               } else {
-                       *bank = g->drv_bank;
-                       *reg = g->drv_reg;
-               }
-               *bit = g->drvtype_bit;
-               *width = 2;
-               break;
-       default:
-               dev_err(pmx->dev, "Invalid config param %04x\n", param);
-               return -ENOTSUPP;
-       }
-
-       if (*reg < 0 || *bit > 31) {
-               if (report_err) {
-                       const char *prop = "unknown";
-                       int i;
-
-                       for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
-                               if (cfg_params[i].param == param) {
-                                       prop = cfg_params[i].property;
-                                       break;
-                               }
-                       }
-
-                       dev_err(pmx->dev,
-                               "Config param %04x (%s) not supported on group %s\n",
-                               param, prop, g->name);
-               }
-               return -ENOTSUPP;
-       }
-
-       return 0;
-}
-
-static int tegra_pinconf_get(struct pinctrl_dev *pctldev,
-                            unsigned pin, unsigned long *config)
-{
-       dev_err(pctldev->dev, "pin_config_get op not supported\n");
-       return -ENOTSUPP;
-}
-
-static int tegra_pinconf_set(struct pinctrl_dev *pctldev,
-                            unsigned pin, unsigned long *configs,
-                            unsigned num_configs)
-{
-       dev_err(pctldev->dev, "pin_config_set op not supported\n");
-       return -ENOTSUPP;
-}
-
-static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
-                                  unsigned group, unsigned long *config)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-       enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(*config);
-       u16 arg;
-       const struct tegra_pingroup *g;
-       int ret;
-       s8 bank, bit, width;
-       s16 reg;
-       u32 val, mask;
-
-       g = &pmx->soc->groups[group];
-
-       ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
-                               &width);
-       if (ret < 0)
-               return ret;
-
-       val = pmx_readl(pmx, bank, reg);
-       mask = (1 << width) - 1;
-       arg = (val >> bit) & mask;
-
-       *config = TEGRA_PINCONF_PACK(param, arg);
-
-       return 0;
-}
-
-static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
-                                  unsigned group, unsigned long *configs,
-                                  unsigned num_configs)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-       enum tegra_pinconf_param param;
-       u16 arg;
-       const struct tegra_pingroup *g;
-       int ret, i;
-       s8 bank, bit, width;
-       s16 reg;
-       u32 val, mask;
-
-       g = &pmx->soc->groups[group];
-
-       for (i = 0; i < num_configs; i++) {
-               param = TEGRA_PINCONF_UNPACK_PARAM(configs[i]);
-               arg = TEGRA_PINCONF_UNPACK_ARG(configs[i]);
-
-               ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
-                                       &width);
-               if (ret < 0)
-                       return ret;
-
-               val = pmx_readl(pmx, bank, reg);
-
-               /* LOCK can't be cleared */
-               if (param == TEGRA_PINCONF_PARAM_LOCK) {
-                       if ((val & BIT(bit)) && !arg) {
-                               dev_err(pctldev->dev, "LOCK bit cannot be cleared\n");
-                               return -EINVAL;
-                       }
-               }
-
-               /* Special-case Boolean values; allow any non-zero as true */
-               if (width == 1)
-                       arg = !!arg;
-
-               /* Range-check user-supplied value */
-               mask = (1 << width) - 1;
-               if (arg & ~mask) {
-                       dev_err(pctldev->dev,
-                               "config %lx: %x too big for %d bit register\n",
-                               configs[i], arg, width);
-                       return -EINVAL;
-               }
-
-               /* Update register */
-               val &= ~(mask << bit);
-               val |= arg << bit;
-               pmx_writel(pmx, val, bank, reg);
-       } /* for each config */
-
-       return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev,
-                                  struct seq_file *s, unsigned offset)
-{
-}
-
-static const char *strip_prefix(const char *s)
-{
-       const char *comma = strchr(s, ',');
-       if (!comma)
-               return s;
-
-       return comma + 1;
-}
-
-static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
-                                        struct seq_file *s, unsigned group)
-{
-       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
-       const struct tegra_pingroup *g;
-       int i, ret;
-       s8 bank, bit, width;
-       s16 reg;
-       u32 val;
-
-       g = &pmx->soc->groups[group];
-
-       for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
-               ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false,
-                                       &bank, &reg, &bit, &width);
-               if (ret < 0)
-                       continue;
-
-               val = pmx_readl(pmx, bank, reg);
-               val >>= bit;
-               val &= (1 << width) - 1;
-
-               seq_printf(s, "\n\t%s=%u",
-                          strip_prefix(cfg_params[i].property), val);
-       }
-}
-
-static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
-                                         struct seq_file *s,
-                                         unsigned long config)
-{
-       enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config);
-       u16 arg = TEGRA_PINCONF_UNPACK_ARG(config);
-       const char *pname = "unknown";
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
-               if (cfg_params[i].param == param) {
-                       pname = cfg_params[i].property;
-                       break;
-               }
-       }
-
-       seq_printf(s, "%s=%d", strip_prefix(pname), arg);
-}
-#endif
-
-static const struct pinconf_ops tegra_pinconf_ops = {
-       .pin_config_get = tegra_pinconf_get,
-       .pin_config_set = tegra_pinconf_set,
-       .pin_config_group_get = tegra_pinconf_group_get,
-       .pin_config_group_set = tegra_pinconf_group_set,
-#ifdef CONFIG_DEBUG_FS
-       .pin_config_dbg_show = tegra_pinconf_dbg_show,
-       .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show,
-       .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show,
-#endif
-};
-
-static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = {
-       .name = "Tegra GPIOs",
-       .id = 0,
-       .base = 0,
-};
-
-static struct pinctrl_desc tegra_pinctrl_desc = {
-       .pctlops = &tegra_pinctrl_ops,
-       .pmxops = &tegra_pinmux_ops,
-       .confops = &tegra_pinconf_ops,
-       .owner = THIS_MODULE,
-};
-
-static bool gpio_node_has_range(void)
-{
-       struct device_node *np;
-       bool has_prop = false;
-
-       np = of_find_compatible_node(NULL, NULL, "nvidia,tegra30-gpio");
-       if (!np)
-               return has_prop;
-
-       has_prop = of_find_property(np, "gpio-ranges", NULL);
-
-       of_node_put(np);
-
-       return has_prop;
-}
-
-int tegra_pinctrl_probe(struct platform_device *pdev,
-                       const struct tegra_pinctrl_soc_data *soc_data)
-{
-       struct tegra_pmx *pmx;
-       struct resource *res;
-       int i;
-       const char **group_pins;
-       int fn, gn, gfn;
-
-       pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
-       if (!pmx) {
-               dev_err(&pdev->dev, "Can't alloc tegra_pmx\n");
-               return -ENOMEM;
-       }
-       pmx->dev = &pdev->dev;
-       pmx->soc = soc_data;
-
-       /*
-        * Each mux group will appear in 4 functions' list of groups.
-        * This over-allocates slightly, since not all groups are mux groups.
-        */
-       pmx->group_pins = devm_kzalloc(&pdev->dev,
-               soc_data->ngroups * 4 * sizeof(*pmx->group_pins),
-               GFP_KERNEL);
-       if (!pmx->group_pins)
-               return -ENOMEM;
-
-       group_pins = pmx->group_pins;
-       for (fn = 0; fn < soc_data->nfunctions; fn++) {
-               struct tegra_function *func = &soc_data->functions[fn];
-
-               func->groups = group_pins;
-
-               for (gn = 0; gn < soc_data->ngroups; gn++) {
-                       const struct tegra_pingroup *g = &soc_data->groups[gn];
-
-                       if (g->mux_reg == -1)
-                               continue;
-
-                       for (gfn = 0; gfn < 4; gfn++)
-                               if (g->funcs[gfn] == fn)
-                                       break;
-                       if (gfn == 4)
-                               continue;
-
-                       BUG_ON(group_pins - pmx->group_pins >=
-                               soc_data->ngroups * 4);
-                       *group_pins++ = g->name;
-                       func->ngroups++;
-               }
-       }
-
-       tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios;
-       tegra_pinctrl_desc.name = dev_name(&pdev->dev);
-       tegra_pinctrl_desc.pins = pmx->soc->pins;
-       tegra_pinctrl_desc.npins = pmx->soc->npins;
-
-       for (i = 0; ; i++) {
-               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-               if (!res)
-                       break;
-       }
-       pmx->nbanks = i;
-
-       pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs),
-                                GFP_KERNEL);
-       if (!pmx->regs) {
-               dev_err(&pdev->dev, "Can't alloc regs pointer\n");
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < pmx->nbanks; i++) {
-               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-               pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(pmx->regs[i]))
-                       return PTR_ERR(pmx->regs[i]);
-       }
-
-       pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx);
-       if (IS_ERR(pmx->pctl)) {
-               dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-               return PTR_ERR(pmx->pctl);
-       }
-
-       if (!gpio_node_has_range())
-               pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range);
-
-       platform_set_drvdata(pdev, pmx);
-
-       dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n");
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
-
-int tegra_pinctrl_remove(struct platform_device *pdev)
-{
-       struct tegra_pmx *pmx = platform_get_drvdata(pdev);
-
-       pinctrl_unregister(pmx->pctl);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(tegra_pinctrl_remove);
diff --git a/drivers/pinctrl/pinctrl-tegra.h b/drivers/pinctrl/pinctrl-tegra.h
deleted file mode 100644 (file)
index 1615db7..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Driver for the NVIDIA Tegra pinmux
- *
- * Copyright (c) 2011, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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 __PINMUX_TEGRA_H__
-#define __PINMUX_TEGRA_H__
-
-enum tegra_pinconf_param {
-       /* argument: tegra_pinconf_pull */
-       TEGRA_PINCONF_PARAM_PULL,
-       /* argument: tegra_pinconf_tristate */
-       TEGRA_PINCONF_PARAM_TRISTATE,
-       /* argument: Boolean */
-       TEGRA_PINCONF_PARAM_ENABLE_INPUT,
-       /* argument: Boolean */
-       TEGRA_PINCONF_PARAM_OPEN_DRAIN,
-       /* argument: Boolean */
-       TEGRA_PINCONF_PARAM_LOCK,
-       /* argument: Boolean */
-       TEGRA_PINCONF_PARAM_IORESET,
-       /* argument: Boolean */
-       TEGRA_PINCONF_PARAM_RCV_SEL,
-       /* argument: Boolean */
-       TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE,
-       /* argument: Boolean */
-       TEGRA_PINCONF_PARAM_SCHMITT,
-       /* argument: Boolean */
-       TEGRA_PINCONF_PARAM_LOW_POWER_MODE,
-       /* argument: Integer, range is HW-dependant */
-       TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH,
-       /* argument: Integer, range is HW-dependant */
-       TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH,
-       /* argument: Integer, range is HW-dependant */
-       TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING,
-       /* argument: Integer, range is HW-dependant */
-       TEGRA_PINCONF_PARAM_SLEW_RATE_RISING,
-       /* argument: Integer, range is HW-dependant */
-       TEGRA_PINCONF_PARAM_DRIVE_TYPE,
-};
-
-enum tegra_pinconf_pull {
-       TEGRA_PINCONFIG_PULL_NONE,
-       TEGRA_PINCONFIG_PULL_DOWN,
-       TEGRA_PINCONFIG_PULL_UP,
-};
-
-enum tegra_pinconf_tristate {
-       TEGRA_PINCONFIG_DRIVEN,
-       TEGRA_PINCONFIG_TRISTATE,
-};
-
-#define TEGRA_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_))
-#define TEGRA_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
-#define TEGRA_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
-
-/**
- * struct tegra_function - Tegra pinctrl mux function
- * @name: The name of the function, exported to pinctrl core.
- * @groups: An array of pin groups that may select this function.
- * @ngroups: The number of entries in @groups.
- */
-struct tegra_function {
-       const char *name;
-       const char **groups;
-       unsigned ngroups;
-};
-
-/**
- * struct tegra_pingroup - Tegra pin group
- * @name               The name of the pin group.
- * @pins               An array of pin IDs included in this pin group.
- * @npins              The number of entries in @pins.
- * @funcs              The mux functions which can be muxed onto this group.
- * @mux_reg:           Mux register offset.
- *                     This register contains the mux, einput, odrain, lock,
- *                     ioreset, rcv_sel parameters.
- * @mux_bank:          Mux register bank.
- * @mux_bit:           Mux register bit.
- * @pupd_reg:          Pull-up/down register offset.
- * @pupd_bank:         Pull-up/down register bank.
- * @pupd_bit:          Pull-up/down register bit.
- * @tri_reg:           Tri-state register offset.
- * @tri_bank:          Tri-state register bank.
- * @tri_bit:           Tri-state register bit.
- * @einput_bit:                Enable-input register bit.
- * @odrain_bit:                Open-drain register bit.
- * @lock_bit:          Lock register bit.
- * @ioreset_bit:       IO reset register bit.
- * @rcv_sel_bit:       Receiver select bit.
- * @drv_reg:           Drive fields register offset.
- *                     This register contains hsm, schmitt, lpmd, drvdn,
- *                     drvup, slwr, slwf, and drvtype parameters.
- * @drv_bank:          Drive fields register bank.
- * @hsm_bit:           High Speed Mode register bit.
- * @schmitt_bit:       Scmitt register bit.
- * @lpmd_bit:          Low Power Mode register bit.
- * @drvdn_bit:         Drive Down register bit.
- * @drvdn_width:       Drive Down field width.
- * @drvup_bit:         Drive Up register bit.
- * @drvup_width:       Drive Up field width.
- * @slwr_bit:          Slew Rising register bit.
- * @slwr_width:                Slew Rising field width.
- * @slwf_bit:          Slew Falling register bit.
- * @slwf_width:                Slew Falling field width.
- * @drvtype_bit:       Drive type register bit.
- *
- * -1 in a *_reg field means that feature is unsupported for this group.
- * *_bank and *_reg values are irrelevant when *_reg is -1.
- * When *_reg is valid, *_bit may be -1 to indicate an unsupported feature.
- *
- * A representation of a group of pins (possibly just one pin) in the Tegra
- * pin controller. Each group allows some parameter or parameters to be
- * configured. The most common is mux function selection. Many others exist
- * such as pull-up/down, tri-state, etc. Tegra's pin controller is complex;
- * certain groups may only support configuring certain parameters, hence
- * each parameter is optional.
- */
-struct tegra_pingroup {
-       const char *name;
-       const unsigned *pins;
-       u8 npins;
-       u8 funcs[4];
-       s16 mux_reg;
-       s16 pupd_reg;
-       s16 tri_reg;
-       s16 drv_reg;
-       u32 mux_bank:2;
-       u32 pupd_bank:2;
-       u32 tri_bank:2;
-       u32 drv_bank:2;
-       s32 mux_bit:6;
-       s32 pupd_bit:6;
-       s32 tri_bit:6;
-       s32 einput_bit:6;
-       s32 odrain_bit:6;
-       s32 lock_bit:6;
-       s32 ioreset_bit:6;
-       s32 rcv_sel_bit:6;
-       s32 hsm_bit:6;
-       s32 schmitt_bit:6;
-       s32 lpmd_bit:6;
-       s32 drvdn_bit:6;
-       s32 drvup_bit:6;
-       s32 slwr_bit:6;
-       s32 slwf_bit:6;
-       s32 drvtype_bit:6;
-       s32 drvdn_width:6;
-       s32 drvup_width:6;
-       s32 slwr_width:6;
-       s32 slwf_width:6;
-};
-
-/**
- * struct tegra_pinctrl_soc_data - Tegra pin controller driver configuration
- * @ngpios:    The number of GPIO pins the pin controller HW affects.
- * @pins:      An array describing all pins the pin controller affects.
- *             All pins which are also GPIOs must be listed first within the
- *             array, and be numbered identically to the GPIO controller's
- *             numbering.
- * @npins:     The numbmer of entries in @pins.
- * @functions: An array describing all mux functions the SoC supports.
- * @nfunctions:        The numbmer of entries in @functions.
- * @groups:    An array describing all pin groups the pin SoC supports.
- * @ngroups:   The numbmer of entries in @groups.
- */
-struct tegra_pinctrl_soc_data {
-       unsigned ngpios;
-       const struct pinctrl_pin_desc *pins;
-       unsigned npins;
-       struct tegra_function *functions;
-       unsigned nfunctions;
-       const struct tegra_pingroup *groups;
-       unsigned ngroups;
-       bool hsm_in_mux;
-       bool schmitt_in_mux;
-       bool drvtype_in_mux;
-};
-
-int tegra_pinctrl_probe(struct platform_device *pdev,
-                       const struct tegra_pinctrl_soc_data *soc_data);
-int tegra_pinctrl_remove(struct platform_device *pdev);
-
-#endif
diff --git a/drivers/pinctrl/pinctrl-tegra114.c b/drivers/pinctrl/pinctrl-tegra114.c
deleted file mode 100644 (file)
index 05e49d5..0000000
+++ /dev/null
@@ -1,1872 +0,0 @@
-/*
- * Pinctrl data for the NVIDIA Tegra114 pinmux
- *
- * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-
-#include "pinctrl-tegra.h"
-
-/*
- * Most pins affected by the pinmux can also be GPIOs. Define these first.
- * These must match how the GPIO driver names/numbers its pins.
- */
-#define _GPIO(offset)                          (offset)
-
-#define TEGRA_PIN_CLK_32K_OUT_PA0              _GPIO(0)
-#define TEGRA_PIN_UART3_CTS_N_PA1              _GPIO(1)
-#define TEGRA_PIN_DAP2_FS_PA2                  _GPIO(2)
-#define TEGRA_PIN_DAP2_SCLK_PA3                        _GPIO(3)
-#define TEGRA_PIN_DAP2_DIN_PA4                 _GPIO(4)
-#define TEGRA_PIN_DAP2_DOUT_PA5                        _GPIO(5)
-#define TEGRA_PIN_SDMMC3_CLK_PA6               _GPIO(6)
-#define TEGRA_PIN_SDMMC3_CMD_PA7               _GPIO(7)
-#define TEGRA_PIN_GMI_A17_PB0                  _GPIO(8)
-#define TEGRA_PIN_GMI_A18_PB1                  _GPIO(9)
-#define TEGRA_PIN_SDMMC3_DAT3_PB4              _GPIO(12)
-#define TEGRA_PIN_SDMMC3_DAT2_PB5              _GPIO(13)
-#define TEGRA_PIN_SDMMC3_DAT1_PB6              _GPIO(14)
-#define TEGRA_PIN_SDMMC3_DAT0_PB7              _GPIO(15)
-#define TEGRA_PIN_UART3_RTS_N_PC0              _GPIO(16)
-#define TEGRA_PIN_UART2_TXD_PC2                        _GPIO(18)
-#define TEGRA_PIN_UART2_RXD_PC3                        _GPIO(19)
-#define TEGRA_PIN_GEN1_I2C_SCL_PC4             _GPIO(20)
-#define TEGRA_PIN_GEN1_I2C_SDA_PC5             _GPIO(21)
-#define TEGRA_PIN_GMI_WP_N_PC7                 _GPIO(23)
-#define TEGRA_PIN_GMI_AD0_PG0                  _GPIO(48)
-#define TEGRA_PIN_GMI_AD1_PG1                  _GPIO(49)
-#define TEGRA_PIN_GMI_AD2_PG2                  _GPIO(50)
-#define TEGRA_PIN_GMI_AD3_PG3                  _GPIO(51)
-#define TEGRA_PIN_GMI_AD4_PG4                  _GPIO(52)
-#define TEGRA_PIN_GMI_AD5_PG5                  _GPIO(53)
-#define TEGRA_PIN_GMI_AD6_PG6                  _GPIO(54)
-#define TEGRA_PIN_GMI_AD7_PG7                  _GPIO(55)
-#define TEGRA_PIN_GMI_AD8_PH0                  _GPIO(56)
-#define TEGRA_PIN_GMI_AD9_PH1                  _GPIO(57)
-#define TEGRA_PIN_GMI_AD10_PH2                 _GPIO(58)
-#define TEGRA_PIN_GMI_AD11_PH3                 _GPIO(59)
-#define TEGRA_PIN_GMI_AD12_PH4                 _GPIO(60)
-#define TEGRA_PIN_GMI_AD13_PH5                 _GPIO(61)
-#define TEGRA_PIN_GMI_AD14_PH6                 _GPIO(62)
-#define TEGRA_PIN_GMI_AD15_PH7                 _GPIO(63)
-#define TEGRA_PIN_GMI_WR_N_PI0                 _GPIO(64)
-#define TEGRA_PIN_GMI_OE_N_PI1                 _GPIO(65)
-#define TEGRA_PIN_GMI_CS6_N_PI3                        _GPIO(67)
-#define TEGRA_PIN_GMI_RST_N_PI4                        _GPIO(68)
-#define TEGRA_PIN_GMI_IORDY_PI5                        _GPIO(69)
-#define TEGRA_PIN_GMI_CS7_N_PI6                        _GPIO(70)
-#define TEGRA_PIN_GMI_WAIT_PI7                 _GPIO(71)
-#define TEGRA_PIN_GMI_CS0_N_PJ0                        _GPIO(72)
-#define TEGRA_PIN_GMI_CS1_N_PJ2                        _GPIO(74)
-#define TEGRA_PIN_GMI_DQS_P_PJ3                        _GPIO(75)
-#define TEGRA_PIN_UART2_CTS_N_PJ5              _GPIO(77)
-#define TEGRA_PIN_UART2_RTS_N_PJ6              _GPIO(78)
-#define TEGRA_PIN_GMI_A16_PJ7                  _GPIO(79)
-#define TEGRA_PIN_GMI_ADV_N_PK0                        _GPIO(80)
-#define TEGRA_PIN_GMI_CLK_PK1                  _GPIO(81)
-#define TEGRA_PIN_GMI_CS4_N_PK2                        _GPIO(82)
-#define TEGRA_PIN_GMI_CS2_N_PK3                        _GPIO(83)
-#define TEGRA_PIN_GMI_CS3_N_PK4                        _GPIO(84)
-#define TEGRA_PIN_SPDIF_OUT_PK5                        _GPIO(85)
-#define TEGRA_PIN_SPDIF_IN_PK6                 _GPIO(86)
-#define TEGRA_PIN_GMI_A19_PK7                  _GPIO(87)
-#define TEGRA_PIN_DAP1_FS_PN0                  _GPIO(104)
-#define TEGRA_PIN_DAP1_DIN_PN1                 _GPIO(105)
-#define TEGRA_PIN_DAP1_DOUT_PN2                        _GPIO(106)
-#define TEGRA_PIN_DAP1_SCLK_PN3                        _GPIO(107)
-#define TEGRA_PIN_USB_VBUS_EN0_PN4             _GPIO(108)
-#define TEGRA_PIN_USB_VBUS_EN1_PN5             _GPIO(109)
-#define TEGRA_PIN_HDMI_INT_PN7                 _GPIO(111)
-#define TEGRA_PIN_ULPI_DATA7_PO0               _GPIO(112)
-#define TEGRA_PIN_ULPI_DATA0_PO1               _GPIO(113)
-#define TEGRA_PIN_ULPI_DATA1_PO2               _GPIO(114)
-#define TEGRA_PIN_ULPI_DATA2_PO3               _GPIO(115)
-#define TEGRA_PIN_ULPI_DATA3_PO4               _GPIO(116)
-#define TEGRA_PIN_ULPI_DATA4_PO5               _GPIO(117)
-#define TEGRA_PIN_ULPI_DATA5_PO6               _GPIO(118)
-#define TEGRA_PIN_ULPI_DATA6_PO7               _GPIO(119)
-#define TEGRA_PIN_DAP3_FS_PP0                  _GPIO(120)
-#define TEGRA_PIN_DAP3_DIN_PP1                 _GPIO(121)
-#define TEGRA_PIN_DAP3_DOUT_PP2                        _GPIO(122)
-#define TEGRA_PIN_DAP3_SCLK_PP3                        _GPIO(123)
-#define TEGRA_PIN_DAP4_FS_PP4                  _GPIO(124)
-#define TEGRA_PIN_DAP4_DIN_PP5                 _GPIO(125)
-#define TEGRA_PIN_DAP4_DOUT_PP6                        _GPIO(126)
-#define TEGRA_PIN_DAP4_SCLK_PP7                        _GPIO(127)
-#define TEGRA_PIN_KB_COL0_PQ0                  _GPIO(128)
-#define TEGRA_PIN_KB_COL1_PQ1                  _GPIO(129)
-#define TEGRA_PIN_KB_COL2_PQ2                  _GPIO(130)
-#define TEGRA_PIN_KB_COL3_PQ3                  _GPIO(131)
-#define TEGRA_PIN_KB_COL4_PQ4                  _GPIO(132)
-#define TEGRA_PIN_KB_COL5_PQ5                  _GPIO(133)
-#define TEGRA_PIN_KB_COL6_PQ6                  _GPIO(134)
-#define TEGRA_PIN_KB_COL7_PQ7                  _GPIO(135)
-#define TEGRA_PIN_KB_ROW0_PR0                  _GPIO(136)
-#define TEGRA_PIN_KB_ROW1_PR1                  _GPIO(137)
-#define TEGRA_PIN_KB_ROW2_PR2                  _GPIO(138)
-#define TEGRA_PIN_KB_ROW3_PR3                  _GPIO(139)
-#define TEGRA_PIN_KB_ROW4_PR4                  _GPIO(140)
-#define TEGRA_PIN_KB_ROW5_PR5                  _GPIO(141)
-#define TEGRA_PIN_KB_ROW6_PR6                  _GPIO(142)
-#define TEGRA_PIN_KB_ROW7_PR7                  _GPIO(143)
-#define TEGRA_PIN_KB_ROW8_PS0                  _GPIO(144)
-#define TEGRA_PIN_KB_ROW9_PS1                  _GPIO(145)
-#define TEGRA_PIN_KB_ROW10_PS2                 _GPIO(146)
-#define TEGRA_PIN_GEN2_I2C_SCL_PT5             _GPIO(157)
-#define TEGRA_PIN_GEN2_I2C_SDA_PT6             _GPIO(158)
-#define TEGRA_PIN_SDMMC4_CMD_PT7               _GPIO(159)
-#define TEGRA_PIN_PU0                          _GPIO(160)
-#define TEGRA_PIN_PU1                          _GPIO(161)
-#define TEGRA_PIN_PU2                          _GPIO(162)
-#define TEGRA_PIN_PU3                          _GPIO(163)
-#define TEGRA_PIN_PU4                          _GPIO(164)
-#define TEGRA_PIN_PU5                          _GPIO(165)
-#define TEGRA_PIN_PU6                          _GPIO(166)
-#define TEGRA_PIN_PV0                          _GPIO(168)
-#define TEGRA_PIN_PV1                          _GPIO(169)
-#define TEGRA_PIN_SDMMC3_CD_N_PV2              _GPIO(170)
-#define TEGRA_PIN_SDMMC1_WP_N_PV3              _GPIO(171)
-#define TEGRA_PIN_DDC_SCL_PV4                  _GPIO(172)
-#define TEGRA_PIN_DDC_SDA_PV5                  _GPIO(173)
-#define TEGRA_PIN_GPIO_W2_AUD_PW2              _GPIO(178)
-#define TEGRA_PIN_GPIO_W3_AUD_PW3              _GPIO(179)
-#define TEGRA_PIN_CLK1_OUT_PW4                 _GPIO(180)
-#define TEGRA_PIN_CLK2_OUT_PW5                 _GPIO(181)
-#define TEGRA_PIN_UART3_TXD_PW6                        _GPIO(182)
-#define TEGRA_PIN_UART3_RXD_PW7                        _GPIO(183)
-#define TEGRA_PIN_DVFS_PWM_PX0                 _GPIO(184)
-#define TEGRA_PIN_GPIO_X1_AUD_PX1              _GPIO(185)
-#define TEGRA_PIN_DVFS_CLK_PX2                 _GPIO(186)
-#define TEGRA_PIN_GPIO_X3_AUD_PX3              _GPIO(187)
-#define TEGRA_PIN_GPIO_X4_AUD_PX4              _GPIO(188)
-#define TEGRA_PIN_GPIO_X5_AUD_PX5              _GPIO(189)
-#define TEGRA_PIN_GPIO_X6_AUD_PX6              _GPIO(190)
-#define TEGRA_PIN_GPIO_X7_AUD_PX7              _GPIO(191)
-#define TEGRA_PIN_ULPI_CLK_PY0                 _GPIO(192)
-#define TEGRA_PIN_ULPI_DIR_PY1                 _GPIO(193)
-#define TEGRA_PIN_ULPI_NXT_PY2                 _GPIO(194)
-#define TEGRA_PIN_ULPI_STP_PY3                 _GPIO(195)
-#define TEGRA_PIN_SDMMC1_DAT3_PY4              _GPIO(196)
-#define TEGRA_PIN_SDMMC1_DAT2_PY5              _GPIO(197)
-#define TEGRA_PIN_SDMMC1_DAT1_PY6              _GPIO(198)
-#define TEGRA_PIN_SDMMC1_DAT0_PY7              _GPIO(199)
-#define TEGRA_PIN_SDMMC1_CLK_PZ0               _GPIO(200)
-#define TEGRA_PIN_SDMMC1_CMD_PZ1               _GPIO(201)
-#define TEGRA_PIN_SYS_CLK_REQ_PZ5              _GPIO(205)
-#define TEGRA_PIN_PWR_I2C_SCL_PZ6              _GPIO(206)
-#define TEGRA_PIN_PWR_I2C_SDA_PZ7              _GPIO(207)
-#define TEGRA_PIN_SDMMC4_DAT0_PAA0             _GPIO(208)
-#define TEGRA_PIN_SDMMC4_DAT1_PAA1             _GPIO(209)
-#define TEGRA_PIN_SDMMC4_DAT2_PAA2             _GPIO(210)
-#define TEGRA_PIN_SDMMC4_DAT3_PAA3             _GPIO(211)
-#define TEGRA_PIN_SDMMC4_DAT4_PAA4             _GPIO(212)
-#define TEGRA_PIN_SDMMC4_DAT5_PAA5             _GPIO(213)
-#define TEGRA_PIN_SDMMC4_DAT6_PAA6             _GPIO(214)
-#define TEGRA_PIN_SDMMC4_DAT7_PAA7             _GPIO(215)
-#define TEGRA_PIN_PBB0                         _GPIO(216)
-#define TEGRA_PIN_CAM_I2C_SCL_PBB1             _GPIO(217)
-#define TEGRA_PIN_CAM_I2C_SDA_PBB2             _GPIO(218)
-#define TEGRA_PIN_PBB3                         _GPIO(219)
-#define TEGRA_PIN_PBB4                         _GPIO(220)
-#define TEGRA_PIN_PBB5                         _GPIO(221)
-#define TEGRA_PIN_PBB6                         _GPIO(222)
-#define TEGRA_PIN_PBB7                         _GPIO(223)
-#define TEGRA_PIN_CAM_MCLK_PCC0                        _GPIO(224)
-#define TEGRA_PIN_PCC1                         _GPIO(225)
-#define TEGRA_PIN_PCC2                         _GPIO(226)
-#define TEGRA_PIN_SDMMC4_CLK_PCC4              _GPIO(228)
-#define TEGRA_PIN_CLK2_REQ_PCC5                        _GPIO(229)
-#define TEGRA_PIN_CLK3_OUT_PEE0                        _GPIO(240)
-#define TEGRA_PIN_CLK3_REQ_PEE1                        _GPIO(241)
-#define TEGRA_PIN_CLK1_REQ_PEE2                        _GPIO(242)
-#define TEGRA_PIN_HDMI_CEC_PEE3                        _GPIO(243)
-#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4       _GPIO(244)
-#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5                _GPIO(245)
-
-/* All non-GPIO pins follow */
-#define NUM_GPIOS                              (TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 + 1)
-#define _PIN(offset)                           (NUM_GPIOS + (offset))
-
-/* Non-GPIO pins */
-#define TEGRA_PIN_CORE_PWR_REQ                 _PIN(0)
-#define TEGRA_PIN_CPU_PWR_REQ                  _PIN(1)
-#define TEGRA_PIN_PWR_INT_N                    _PIN(2)
-#define TEGRA_PIN_RESET_OUT_N                  _PIN(3)
-#define TEGRA_PIN_OWR                          _PIN(4)
-#define TEGRA_PIN_JTAG_RTCK                    _PIN(5)
-#define TEGRA_PIN_CLK_32K_IN                   _PIN(6)
-#define TEGRA_PIN_GMI_CLK_LB                   _PIN(7)
-
-static const struct pinctrl_pin_desc tegra114_pins[] = {
-       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_DQS_P_PJ3, "GMI_DQS_P PJ3"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"),
-       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"),
-       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"),
-       PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"),
-       PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"),
-       PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"),
-       PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"),
-       PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"),
-       PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"),
-       PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"),
-       PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"),
-       PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"),
-       PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"),
-       PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"),
-       PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"),
-       PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"),
-       PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"),
-       PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"),
-       PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"),
-       PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"),
-       PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"),
-       PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"),
-       PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"),
-       PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"),
-       PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"),
-       PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"),
-       PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"),
-       PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"),
-       PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"),
-       PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"),
-       PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"),
-       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
-       PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"),
-       PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"),
-       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"),
-};
-
-static const unsigned clk_32k_out_pa0_pins[] = {
-       TEGRA_PIN_CLK_32K_OUT_PA0,
-};
-
-static const unsigned uart3_cts_n_pa1_pins[] = {
-       TEGRA_PIN_UART3_CTS_N_PA1,
-};
-
-static const unsigned dap2_fs_pa2_pins[] = {
-       TEGRA_PIN_DAP2_FS_PA2,
-};
-
-static const unsigned dap2_sclk_pa3_pins[] = {
-       TEGRA_PIN_DAP2_SCLK_PA3,
-};
-
-static const unsigned dap2_din_pa4_pins[] = {
-       TEGRA_PIN_DAP2_DIN_PA4,
-};
-
-static const unsigned dap2_dout_pa5_pins[] = {
-       TEGRA_PIN_DAP2_DOUT_PA5,
-};
-
-static const unsigned sdmmc3_clk_pa6_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_PA6,
-};
-
-static const unsigned sdmmc3_cmd_pa7_pins[] = {
-       TEGRA_PIN_SDMMC3_CMD_PA7,
-};
-
-static const unsigned gmi_a17_pb0_pins[] = {
-       TEGRA_PIN_GMI_A17_PB0,
-};
-
-static const unsigned gmi_a18_pb1_pins[] = {
-       TEGRA_PIN_GMI_A18_PB1,
-};
-
-static const unsigned sdmmc3_dat3_pb4_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT3_PB4,
-};
-
-static const unsigned sdmmc3_dat2_pb5_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT2_PB5,
-};
-
-static const unsigned sdmmc3_dat1_pb6_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT1_PB6,
-};
-
-static const unsigned sdmmc3_dat0_pb7_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT0_PB7,
-};
-
-static const unsigned uart3_rts_n_pc0_pins[] = {
-       TEGRA_PIN_UART3_RTS_N_PC0,
-};
-
-static const unsigned uart2_txd_pc2_pins[] = {
-       TEGRA_PIN_UART2_TXD_PC2,
-};
-
-static const unsigned uart2_rxd_pc3_pins[] = {
-       TEGRA_PIN_UART2_RXD_PC3,
-};
-
-static const unsigned gen1_i2c_scl_pc4_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SCL_PC4,
-};
-
-static const unsigned gen1_i2c_sda_pc5_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SDA_PC5,
-};
-
-static const unsigned gmi_wp_n_pc7_pins[] = {
-       TEGRA_PIN_GMI_WP_N_PC7,
-};
-
-static const unsigned gmi_ad0_pg0_pins[] = {
-       TEGRA_PIN_GMI_AD0_PG0,
-};
-
-static const unsigned gmi_ad1_pg1_pins[] = {
-       TEGRA_PIN_GMI_AD1_PG1,
-};
-
-static const unsigned gmi_ad2_pg2_pins[] = {
-       TEGRA_PIN_GMI_AD2_PG2,
-};
-
-static const unsigned gmi_ad3_pg3_pins[] = {
-       TEGRA_PIN_GMI_AD3_PG3,
-};
-
-static const unsigned gmi_ad4_pg4_pins[] = {
-       TEGRA_PIN_GMI_AD4_PG4,
-};
-
-static const unsigned gmi_ad5_pg5_pins[] = {
-       TEGRA_PIN_GMI_AD5_PG5,
-};
-
-static const unsigned gmi_ad6_pg6_pins[] = {
-       TEGRA_PIN_GMI_AD6_PG6,
-};
-
-static const unsigned gmi_ad7_pg7_pins[] = {
-       TEGRA_PIN_GMI_AD7_PG7,
-};
-
-static const unsigned gmi_ad8_ph0_pins[] = {
-       TEGRA_PIN_GMI_AD8_PH0,
-};
-
-static const unsigned gmi_ad9_ph1_pins[] = {
-       TEGRA_PIN_GMI_AD9_PH1,
-};
-
-static const unsigned gmi_ad10_ph2_pins[] = {
-       TEGRA_PIN_GMI_AD10_PH2,
-};
-
-static const unsigned gmi_ad11_ph3_pins[] = {
-       TEGRA_PIN_GMI_AD11_PH3,
-};
-
-static const unsigned gmi_ad12_ph4_pins[] = {
-       TEGRA_PIN_GMI_AD12_PH4,
-};
-
-static const unsigned gmi_ad13_ph5_pins[] = {
-       TEGRA_PIN_GMI_AD13_PH5,
-};
-
-static const unsigned gmi_ad14_ph6_pins[] = {
-       TEGRA_PIN_GMI_AD14_PH6,
-};
-
-static const unsigned gmi_ad15_ph7_pins[] = {
-       TEGRA_PIN_GMI_AD15_PH7,
-};
-
-static const unsigned gmi_wr_n_pi0_pins[] = {
-       TEGRA_PIN_GMI_WR_N_PI0,
-};
-
-static const unsigned gmi_oe_n_pi1_pins[] = {
-       TEGRA_PIN_GMI_OE_N_PI1,
-};
-
-static const unsigned gmi_cs6_n_pi3_pins[] = {
-       TEGRA_PIN_GMI_CS6_N_PI3,
-};
-
-static const unsigned gmi_rst_n_pi4_pins[] = {
-       TEGRA_PIN_GMI_RST_N_PI4,
-};
-
-static const unsigned gmi_iordy_pi5_pins[] = {
-       TEGRA_PIN_GMI_IORDY_PI5,
-};
-
-static const unsigned gmi_cs7_n_pi6_pins[] = {
-       TEGRA_PIN_GMI_CS7_N_PI6,
-};
-
-static const unsigned gmi_wait_pi7_pins[] = {
-       TEGRA_PIN_GMI_WAIT_PI7,
-};
-
-static const unsigned gmi_cs0_n_pj0_pins[] = {
-       TEGRA_PIN_GMI_CS0_N_PJ0,
-};
-
-static const unsigned gmi_cs1_n_pj2_pins[] = {
-       TEGRA_PIN_GMI_CS1_N_PJ2,
-};
-
-static const unsigned gmi_dqs_p_pj3_pins[] = {
-       TEGRA_PIN_GMI_DQS_P_PJ3,
-};
-
-static const unsigned uart2_cts_n_pj5_pins[] = {
-       TEGRA_PIN_UART2_CTS_N_PJ5,
-};
-
-static const unsigned uart2_rts_n_pj6_pins[] = {
-       TEGRA_PIN_UART2_RTS_N_PJ6,
-};
-
-static const unsigned gmi_a16_pj7_pins[] = {
-       TEGRA_PIN_GMI_A16_PJ7,
-};
-
-static const unsigned gmi_adv_n_pk0_pins[] = {
-       TEGRA_PIN_GMI_ADV_N_PK0,
-};
-
-static const unsigned gmi_clk_pk1_pins[] = {
-       TEGRA_PIN_GMI_CLK_PK1,
-};
-
-static const unsigned gmi_cs4_n_pk2_pins[] = {
-       TEGRA_PIN_GMI_CS4_N_PK2,
-};
-
-static const unsigned gmi_cs2_n_pk3_pins[] = {
-       TEGRA_PIN_GMI_CS2_N_PK3,
-};
-
-static const unsigned gmi_cs3_n_pk4_pins[] = {
-       TEGRA_PIN_GMI_CS3_N_PK4,
-};
-
-static const unsigned spdif_out_pk5_pins[] = {
-       TEGRA_PIN_SPDIF_OUT_PK5,
-};
-
-static const unsigned spdif_in_pk6_pins[] = {
-       TEGRA_PIN_SPDIF_IN_PK6,
-};
-
-static const unsigned gmi_a19_pk7_pins[] = {
-       TEGRA_PIN_GMI_A19_PK7,
-};
-
-static const unsigned dap1_fs_pn0_pins[] = {
-       TEGRA_PIN_DAP1_FS_PN0,
-};
-
-static const unsigned dap1_din_pn1_pins[] = {
-       TEGRA_PIN_DAP1_DIN_PN1,
-};
-
-static const unsigned dap1_dout_pn2_pins[] = {
-       TEGRA_PIN_DAP1_DOUT_PN2,
-};
-
-static const unsigned dap1_sclk_pn3_pins[] = {
-       TEGRA_PIN_DAP1_SCLK_PN3,
-};
-
-static const unsigned usb_vbus_en0_pn4_pins[] = {
-       TEGRA_PIN_USB_VBUS_EN0_PN4,
-};
-
-static const unsigned usb_vbus_en1_pn5_pins[] = {
-       TEGRA_PIN_USB_VBUS_EN1_PN5,
-};
-
-static const unsigned hdmi_int_pn7_pins[] = {
-       TEGRA_PIN_HDMI_INT_PN7,
-};
-
-static const unsigned ulpi_data7_po0_pins[] = {
-       TEGRA_PIN_ULPI_DATA7_PO0,
-};
-
-static const unsigned ulpi_data0_po1_pins[] = {
-       TEGRA_PIN_ULPI_DATA0_PO1,
-};
-
-static const unsigned ulpi_data1_po2_pins[] = {
-       TEGRA_PIN_ULPI_DATA1_PO2,
-};
-
-static const unsigned ulpi_data2_po3_pins[] = {
-       TEGRA_PIN_ULPI_DATA2_PO3,
-};
-
-static const unsigned ulpi_data3_po4_pins[] = {
-       TEGRA_PIN_ULPI_DATA3_PO4,
-};
-
-static const unsigned ulpi_data4_po5_pins[] = {
-       TEGRA_PIN_ULPI_DATA4_PO5,
-};
-
-static const unsigned ulpi_data5_po6_pins[] = {
-       TEGRA_PIN_ULPI_DATA5_PO6,
-};
-
-static const unsigned ulpi_data6_po7_pins[] = {
-       TEGRA_PIN_ULPI_DATA6_PO7,
-};
-
-static const unsigned dap3_fs_pp0_pins[] = {
-       TEGRA_PIN_DAP3_FS_PP0,
-};
-
-static const unsigned dap3_din_pp1_pins[] = {
-       TEGRA_PIN_DAP3_DIN_PP1,
-};
-
-static const unsigned dap3_dout_pp2_pins[] = {
-       TEGRA_PIN_DAP3_DOUT_PP2,
-};
-
-static const unsigned dap3_sclk_pp3_pins[] = {
-       TEGRA_PIN_DAP3_SCLK_PP3,
-};
-
-static const unsigned dap4_fs_pp4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PP4,
-};
-
-static const unsigned dap4_din_pp5_pins[] = {
-       TEGRA_PIN_DAP4_DIN_PP5,
-};
-
-static const unsigned dap4_dout_pp6_pins[] = {
-       TEGRA_PIN_DAP4_DOUT_PP6,
-};
-
-static const unsigned dap4_sclk_pp7_pins[] = {
-       TEGRA_PIN_DAP4_SCLK_PP7,
-};
-
-static const unsigned kb_col0_pq0_pins[] = {
-       TEGRA_PIN_KB_COL0_PQ0,
-};
-
-static const unsigned kb_col1_pq1_pins[] = {
-       TEGRA_PIN_KB_COL1_PQ1,
-};
-
-static const unsigned kb_col2_pq2_pins[] = {
-       TEGRA_PIN_KB_COL2_PQ2,
-};
-
-static const unsigned kb_col3_pq3_pins[] = {
-       TEGRA_PIN_KB_COL3_PQ3,
-};
-
-static const unsigned kb_col4_pq4_pins[] = {
-       TEGRA_PIN_KB_COL4_PQ4,
-};
-
-static const unsigned kb_col5_pq5_pins[] = {
-       TEGRA_PIN_KB_COL5_PQ5,
-};
-
-static const unsigned kb_col6_pq6_pins[] = {
-       TEGRA_PIN_KB_COL6_PQ6,
-};
-
-static const unsigned kb_col7_pq7_pins[] = {
-       TEGRA_PIN_KB_COL7_PQ7,
-};
-
-static const unsigned kb_row0_pr0_pins[] = {
-       TEGRA_PIN_KB_ROW0_PR0,
-};
-
-static const unsigned kb_row1_pr1_pins[] = {
-       TEGRA_PIN_KB_ROW1_PR1,
-};
-
-static const unsigned kb_row2_pr2_pins[] = {
-       TEGRA_PIN_KB_ROW2_PR2,
-};
-
-static const unsigned kb_row3_pr3_pins[] = {
-       TEGRA_PIN_KB_ROW3_PR3,
-};
-
-static const unsigned kb_row4_pr4_pins[] = {
-       TEGRA_PIN_KB_ROW4_PR4,
-};
-
-static const unsigned kb_row5_pr5_pins[] = {
-       TEGRA_PIN_KB_ROW5_PR5,
-};
-
-static const unsigned kb_row6_pr6_pins[] = {
-       TEGRA_PIN_KB_ROW6_PR6,
-};
-
-static const unsigned kb_row7_pr7_pins[] = {
-       TEGRA_PIN_KB_ROW7_PR7,
-};
-
-static const unsigned kb_row8_ps0_pins[] = {
-       TEGRA_PIN_KB_ROW8_PS0,
-};
-
-static const unsigned kb_row9_ps1_pins[] = {
-       TEGRA_PIN_KB_ROW9_PS1,
-};
-
-static const unsigned kb_row10_ps2_pins[] = {
-       TEGRA_PIN_KB_ROW10_PS2,
-};
-
-static const unsigned gen2_i2c_scl_pt5_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SCL_PT5,
-};
-
-static const unsigned gen2_i2c_sda_pt6_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SDA_PT6,
-};
-
-static const unsigned sdmmc4_cmd_pt7_pins[] = {
-       TEGRA_PIN_SDMMC4_CMD_PT7,
-};
-
-static const unsigned pu0_pins[] = {
-       TEGRA_PIN_PU0,
-};
-
-static const unsigned pu1_pins[] = {
-       TEGRA_PIN_PU1,
-};
-
-static const unsigned pu2_pins[] = {
-       TEGRA_PIN_PU2,
-};
-
-static const unsigned pu3_pins[] = {
-       TEGRA_PIN_PU3,
-};
-
-static const unsigned pu4_pins[] = {
-       TEGRA_PIN_PU4,
-};
-
-static const unsigned pu5_pins[] = {
-       TEGRA_PIN_PU5,
-};
-
-static const unsigned pu6_pins[] = {
-       TEGRA_PIN_PU6,
-};
-
-static const unsigned pv0_pins[] = {
-       TEGRA_PIN_PV0,
-};
-
-static const unsigned pv1_pins[] = {
-       TEGRA_PIN_PV1,
-};
-
-static const unsigned sdmmc3_cd_n_pv2_pins[] = {
-       TEGRA_PIN_SDMMC3_CD_N_PV2,
-};
-
-static const unsigned sdmmc1_wp_n_pv3_pins[] = {
-       TEGRA_PIN_SDMMC1_WP_N_PV3,
-};
-
-static const unsigned ddc_scl_pv4_pins[] = {
-       TEGRA_PIN_DDC_SCL_PV4,
-};
-
-static const unsigned ddc_sda_pv5_pins[] = {
-       TEGRA_PIN_DDC_SDA_PV5,
-};
-
-static const unsigned gpio_w2_aud_pw2_pins[] = {
-       TEGRA_PIN_GPIO_W2_AUD_PW2,
-};
-
-static const unsigned gpio_w3_aud_pw3_pins[] = {
-       TEGRA_PIN_GPIO_W3_AUD_PW3,
-};
-
-static const unsigned clk1_out_pw4_pins[] = {
-       TEGRA_PIN_CLK1_OUT_PW4,
-};
-
-static const unsigned clk2_out_pw5_pins[] = {
-       TEGRA_PIN_CLK2_OUT_PW5,
-};
-
-static const unsigned uart3_txd_pw6_pins[] = {
-       TEGRA_PIN_UART3_TXD_PW6,
-};
-
-static const unsigned uart3_rxd_pw7_pins[] = {
-       TEGRA_PIN_UART3_RXD_PW7,
-};
-
-static const unsigned dvfs_pwm_px0_pins[] = {
-       TEGRA_PIN_DVFS_PWM_PX0,
-};
-
-static const unsigned gpio_x1_aud_px1_pins[] = {
-       TEGRA_PIN_GPIO_X1_AUD_PX1,
-};
-
-static const unsigned dvfs_clk_px2_pins[] = {
-       TEGRA_PIN_DVFS_CLK_PX2,
-};
-
-static const unsigned gpio_x3_aud_px3_pins[] = {
-       TEGRA_PIN_GPIO_X3_AUD_PX3,
-};
-
-static const unsigned gpio_x4_aud_px4_pins[] = {
-       TEGRA_PIN_GPIO_X4_AUD_PX4,
-};
-
-static const unsigned gpio_x5_aud_px5_pins[] = {
-       TEGRA_PIN_GPIO_X5_AUD_PX5,
-};
-
-static const unsigned gpio_x6_aud_px6_pins[] = {
-       TEGRA_PIN_GPIO_X6_AUD_PX6,
-};
-
-static const unsigned gpio_x7_aud_px7_pins[] = {
-       TEGRA_PIN_GPIO_X7_AUD_PX7,
-};
-
-static const unsigned ulpi_clk_py0_pins[] = {
-       TEGRA_PIN_ULPI_CLK_PY0,
-};
-
-static const unsigned ulpi_dir_py1_pins[] = {
-       TEGRA_PIN_ULPI_DIR_PY1,
-};
-
-static const unsigned ulpi_nxt_py2_pins[] = {
-       TEGRA_PIN_ULPI_NXT_PY2,
-};
-
-static const unsigned ulpi_stp_py3_pins[] = {
-       TEGRA_PIN_ULPI_STP_PY3,
-};
-
-static const unsigned sdmmc1_dat3_py4_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT3_PY4,
-};
-
-static const unsigned sdmmc1_dat2_py5_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT2_PY5,
-};
-
-static const unsigned sdmmc1_dat1_py6_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT1_PY6,
-};
-
-static const unsigned sdmmc1_dat0_py7_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT0_PY7,
-};
-
-static const unsigned sdmmc1_clk_pz0_pins[] = {
-       TEGRA_PIN_SDMMC1_CLK_PZ0,
-};
-
-static const unsigned sdmmc1_cmd_pz1_pins[] = {
-       TEGRA_PIN_SDMMC1_CMD_PZ1,
-};
-
-static const unsigned sys_clk_req_pz5_pins[] = {
-       TEGRA_PIN_SYS_CLK_REQ_PZ5,
-};
-
-static const unsigned pwr_i2c_scl_pz6_pins[] = {
-       TEGRA_PIN_PWR_I2C_SCL_PZ6,
-};
-
-static const unsigned pwr_i2c_sda_pz7_pins[] = {
-       TEGRA_PIN_PWR_I2C_SDA_PZ7,
-};
-
-static const unsigned sdmmc4_dat0_paa0_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT0_PAA0,
-};
-
-static const unsigned sdmmc4_dat1_paa1_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT1_PAA1,
-};
-
-static const unsigned sdmmc4_dat2_paa2_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT2_PAA2,
-};
-
-static const unsigned sdmmc4_dat3_paa3_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT3_PAA3,
-};
-
-static const unsigned sdmmc4_dat4_paa4_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT4_PAA4,
-};
-
-static const unsigned sdmmc4_dat5_paa5_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT5_PAA5,
-};
-
-static const unsigned sdmmc4_dat6_paa6_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT6_PAA6,
-};
-
-static const unsigned sdmmc4_dat7_paa7_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT7_PAA7,
-};
-
-static const unsigned pbb0_pins[] = {
-       TEGRA_PIN_PBB0,
-};
-
-static const unsigned cam_i2c_scl_pbb1_pins[] = {
-       TEGRA_PIN_CAM_I2C_SCL_PBB1,
-};
-
-static const unsigned cam_i2c_sda_pbb2_pins[] = {
-       TEGRA_PIN_CAM_I2C_SDA_PBB2,
-};
-
-static const unsigned pbb3_pins[] = {
-       TEGRA_PIN_PBB3,
-};
-
-static const unsigned pbb4_pins[] = {
-       TEGRA_PIN_PBB4,
-};
-
-static const unsigned pbb5_pins[] = {
-       TEGRA_PIN_PBB5,
-};
-
-static const unsigned pbb6_pins[] = {
-       TEGRA_PIN_PBB6,
-};
-
-static const unsigned pbb7_pins[] = {
-       TEGRA_PIN_PBB7,
-};
-
-static const unsigned cam_mclk_pcc0_pins[] = {
-       TEGRA_PIN_CAM_MCLK_PCC0,
-};
-
-static const unsigned pcc1_pins[] = {
-       TEGRA_PIN_PCC1,
-};
-
-static const unsigned pcc2_pins[] = {
-       TEGRA_PIN_PCC2,
-};
-
-static const unsigned sdmmc4_clk_pcc4_pins[] = {
-       TEGRA_PIN_SDMMC4_CLK_PCC4,
-};
-
-static const unsigned clk2_req_pcc5_pins[] = {
-       TEGRA_PIN_CLK2_REQ_PCC5,
-};
-
-static const unsigned clk3_out_pee0_pins[] = {
-       TEGRA_PIN_CLK3_OUT_PEE0,
-};
-
-static const unsigned clk3_req_pee1_pins[] = {
-       TEGRA_PIN_CLK3_REQ_PEE1,
-};
-
-static const unsigned clk1_req_pee2_pins[] = {
-       TEGRA_PIN_CLK1_REQ_PEE2,
-};
-
-static const unsigned hdmi_cec_pee3_pins[] = {
-       TEGRA_PIN_HDMI_CEC_PEE3,
-};
-
-static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4,
-};
-
-static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5,
-};
-
-static const unsigned core_pwr_req_pins[] = {
-       TEGRA_PIN_CORE_PWR_REQ,
-};
-
-static const unsigned cpu_pwr_req_pins[] = {
-       TEGRA_PIN_CPU_PWR_REQ,
-};
-
-static const unsigned pwr_int_n_pins[] = {
-       TEGRA_PIN_PWR_INT_N,
-};
-
-static const unsigned reset_out_n_pins[] = {
-       TEGRA_PIN_RESET_OUT_N,
-};
-
-static const unsigned owr_pins[] = {
-       TEGRA_PIN_OWR,
-};
-
-static const unsigned jtag_rtck_pins[] = {
-       TEGRA_PIN_JTAG_RTCK,
-};
-
-static const unsigned clk_32k_in_pins[] = {
-       TEGRA_PIN_CLK_32K_IN,
-};
-
-static const unsigned gmi_clk_lb_pins[] = {
-       TEGRA_PIN_GMI_CLK_LB,
-};
-
-static const unsigned drive_ao1_pins[] = {
-       TEGRA_PIN_KB_ROW0_PR0,
-       TEGRA_PIN_KB_ROW1_PR1,
-       TEGRA_PIN_KB_ROW2_PR2,
-       TEGRA_PIN_KB_ROW3_PR3,
-       TEGRA_PIN_KB_ROW4_PR4,
-       TEGRA_PIN_KB_ROW5_PR5,
-       TEGRA_PIN_KB_ROW6_PR6,
-       TEGRA_PIN_KB_ROW7_PR7,
-       TEGRA_PIN_PWR_I2C_SCL_PZ6,
-       TEGRA_PIN_PWR_I2C_SDA_PZ7,
-};
-
-static const unsigned drive_ao2_pins[] = {
-       TEGRA_PIN_CLK_32K_OUT_PA0,
-       TEGRA_PIN_KB_COL0_PQ0,
-       TEGRA_PIN_KB_COL1_PQ1,
-       TEGRA_PIN_KB_COL2_PQ2,
-       TEGRA_PIN_KB_COL3_PQ3,
-       TEGRA_PIN_KB_COL4_PQ4,
-       TEGRA_PIN_KB_COL5_PQ5,
-       TEGRA_PIN_KB_COL6_PQ6,
-       TEGRA_PIN_KB_COL7_PQ7,
-       TEGRA_PIN_KB_ROW8_PS0,
-       TEGRA_PIN_KB_ROW9_PS1,
-       TEGRA_PIN_KB_ROW10_PS2,
-       TEGRA_PIN_SYS_CLK_REQ_PZ5,
-       TEGRA_PIN_CORE_PWR_REQ,
-       TEGRA_PIN_CPU_PWR_REQ,
-       TEGRA_PIN_RESET_OUT_N,
-};
-
-static const unsigned drive_at1_pins[] = {
-       TEGRA_PIN_GMI_AD8_PH0,
-       TEGRA_PIN_GMI_AD9_PH1,
-       TEGRA_PIN_GMI_AD10_PH2,
-       TEGRA_PIN_GMI_AD11_PH3,
-       TEGRA_PIN_GMI_AD12_PH4,
-       TEGRA_PIN_GMI_AD13_PH5,
-       TEGRA_PIN_GMI_AD14_PH6,
-       TEGRA_PIN_GMI_AD15_PH7,
-       TEGRA_PIN_GMI_IORDY_PI5,
-       TEGRA_PIN_GMI_CS7_N_PI6,
-};
-
-static const unsigned drive_at2_pins[] = {
-       TEGRA_PIN_GMI_AD0_PG0,
-       TEGRA_PIN_GMI_AD1_PG1,
-       TEGRA_PIN_GMI_AD2_PG2,
-       TEGRA_PIN_GMI_AD3_PG3,
-       TEGRA_PIN_GMI_AD4_PG4,
-       TEGRA_PIN_GMI_AD5_PG5,
-       TEGRA_PIN_GMI_AD6_PG6,
-       TEGRA_PIN_GMI_AD7_PG7,
-       TEGRA_PIN_GMI_WR_N_PI0,
-       TEGRA_PIN_GMI_OE_N_PI1,
-       TEGRA_PIN_GMI_CS6_N_PI3,
-       TEGRA_PIN_GMI_RST_N_PI4,
-       TEGRA_PIN_GMI_WAIT_PI7,
-       TEGRA_PIN_GMI_DQS_P_PJ3,
-       TEGRA_PIN_GMI_ADV_N_PK0,
-       TEGRA_PIN_GMI_CLK_PK1,
-       TEGRA_PIN_GMI_CS4_N_PK2,
-       TEGRA_PIN_GMI_CS2_N_PK3,
-       TEGRA_PIN_GMI_CS3_N_PK4,
-};
-
-static const unsigned drive_at3_pins[] = {
-       TEGRA_PIN_GMI_WP_N_PC7,
-       TEGRA_PIN_GMI_CS0_N_PJ0,
-};
-
-static const unsigned drive_at4_pins[] = {
-       TEGRA_PIN_GMI_A17_PB0,
-       TEGRA_PIN_GMI_A18_PB1,
-       TEGRA_PIN_GMI_CS1_N_PJ2,
-       TEGRA_PIN_GMI_A16_PJ7,
-       TEGRA_PIN_GMI_A19_PK7,
-};
-
-static const unsigned drive_at5_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SCL_PT5,
-       TEGRA_PIN_GEN2_I2C_SDA_PT6,
-};
-
-static const unsigned drive_cdev1_pins[] = {
-       TEGRA_PIN_CLK1_OUT_PW4,
-       TEGRA_PIN_CLK1_REQ_PEE2,
-};
-
-static const unsigned drive_cdev2_pins[] = {
-       TEGRA_PIN_CLK2_OUT_PW5,
-       TEGRA_PIN_CLK2_REQ_PCC5,
-       TEGRA_PIN_SDMMC1_WP_N_PV3,
-};
-
-static const unsigned drive_dap1_pins[] = {
-       TEGRA_PIN_DAP1_FS_PN0,
-       TEGRA_PIN_DAP1_DIN_PN1,
-       TEGRA_PIN_DAP1_DOUT_PN2,
-       TEGRA_PIN_DAP1_SCLK_PN3,
-};
-
-static const unsigned drive_dap2_pins[] = {
-       TEGRA_PIN_DAP2_FS_PA2,
-       TEGRA_PIN_DAP2_SCLK_PA3,
-       TEGRA_PIN_DAP2_DIN_PA4,
-       TEGRA_PIN_DAP2_DOUT_PA5,
-};
-
-static const unsigned drive_dap3_pins[] = {
-       TEGRA_PIN_DAP3_FS_PP0,
-       TEGRA_PIN_DAP3_DIN_PP1,
-       TEGRA_PIN_DAP3_DOUT_PP2,
-       TEGRA_PIN_DAP3_SCLK_PP3,
-};
-
-static const unsigned drive_dap4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PP4,
-       TEGRA_PIN_DAP4_DIN_PP5,
-       TEGRA_PIN_DAP4_DOUT_PP6,
-       TEGRA_PIN_DAP4_SCLK_PP7,
-};
-
-static const unsigned drive_dbg_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SCL_PC4,
-       TEGRA_PIN_GEN1_I2C_SDA_PC5,
-       TEGRA_PIN_PU0,
-       TEGRA_PIN_PU1,
-       TEGRA_PIN_PU2,
-       TEGRA_PIN_PU3,
-       TEGRA_PIN_PU4,
-       TEGRA_PIN_PU5,
-       TEGRA_PIN_PU6,
-};
-
-static const unsigned drive_sdio3_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_PA6,
-       TEGRA_PIN_SDMMC3_CMD_PA7,
-       TEGRA_PIN_SDMMC3_DAT3_PB4,
-       TEGRA_PIN_SDMMC3_DAT2_PB5,
-       TEGRA_PIN_SDMMC3_DAT1_PB6,
-       TEGRA_PIN_SDMMC3_DAT0_PB7,
-       TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4,
-       TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5,
-};
-
-static const unsigned drive_spi_pins[] = {
-       TEGRA_PIN_DVFS_PWM_PX0,
-       TEGRA_PIN_GPIO_X1_AUD_PX1,
-       TEGRA_PIN_DVFS_CLK_PX2,
-       TEGRA_PIN_GPIO_X3_AUD_PX3,
-       TEGRA_PIN_GPIO_X4_AUD_PX4,
-       TEGRA_PIN_GPIO_X5_AUD_PX5,
-       TEGRA_PIN_GPIO_X6_AUD_PX6,
-       TEGRA_PIN_GPIO_X7_AUD_PX7,
-       TEGRA_PIN_GPIO_W2_AUD_PW2,
-       TEGRA_PIN_GPIO_W3_AUD_PW3,
-};
-
-static const unsigned drive_uaa_pins[] = {
-       TEGRA_PIN_ULPI_DATA0_PO1,
-       TEGRA_PIN_ULPI_DATA1_PO2,
-       TEGRA_PIN_ULPI_DATA2_PO3,
-       TEGRA_PIN_ULPI_DATA3_PO4,
-};
-
-static const unsigned drive_uab_pins[] = {
-       TEGRA_PIN_ULPI_DATA7_PO0,
-       TEGRA_PIN_ULPI_DATA4_PO5,
-       TEGRA_PIN_ULPI_DATA5_PO6,
-       TEGRA_PIN_ULPI_DATA6_PO7,
-       TEGRA_PIN_PV0,
-       TEGRA_PIN_PV1,
-};
-
-static const unsigned drive_uart2_pins[] = {
-       TEGRA_PIN_UART2_TXD_PC2,
-       TEGRA_PIN_UART2_RXD_PC3,
-       TEGRA_PIN_UART2_CTS_N_PJ5,
-       TEGRA_PIN_UART2_RTS_N_PJ6,
-};
-
-static const unsigned drive_uart3_pins[] = {
-       TEGRA_PIN_UART3_CTS_N_PA1,
-       TEGRA_PIN_UART3_RTS_N_PC0,
-       TEGRA_PIN_UART3_TXD_PW6,
-       TEGRA_PIN_UART3_RXD_PW7,
-};
-
-static const unsigned drive_sdio1_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT3_PY4,
-       TEGRA_PIN_SDMMC1_DAT2_PY5,
-       TEGRA_PIN_SDMMC1_DAT1_PY6,
-       TEGRA_PIN_SDMMC1_DAT0_PY7,
-       TEGRA_PIN_SDMMC1_CLK_PZ0,
-       TEGRA_PIN_SDMMC1_CMD_PZ1,
-};
-
-static const unsigned drive_ddc_pins[] = {
-       TEGRA_PIN_DDC_SCL_PV4,
-       TEGRA_PIN_DDC_SDA_PV5,
-};
-
-static const unsigned drive_gma_pins[] = {
-       TEGRA_PIN_SDMMC4_CLK_PCC4,
-       TEGRA_PIN_SDMMC4_CMD_PT7,
-       TEGRA_PIN_SDMMC4_DAT0_PAA0,
-       TEGRA_PIN_SDMMC4_DAT1_PAA1,
-       TEGRA_PIN_SDMMC4_DAT2_PAA2,
-       TEGRA_PIN_SDMMC4_DAT3_PAA3,
-       TEGRA_PIN_SDMMC4_DAT4_PAA4,
-       TEGRA_PIN_SDMMC4_DAT5_PAA5,
-       TEGRA_PIN_SDMMC4_DAT6_PAA6,
-       TEGRA_PIN_SDMMC4_DAT7_PAA7,
-};
-
-static const unsigned drive_gme_pins[] = {
-       TEGRA_PIN_PBB0,
-       TEGRA_PIN_CAM_I2C_SCL_PBB1,
-       TEGRA_PIN_CAM_I2C_SDA_PBB2,
-       TEGRA_PIN_PBB3,
-       TEGRA_PIN_PCC2,
-};
-
-static const unsigned drive_gmf_pins[] = {
-       TEGRA_PIN_PBB4,
-       TEGRA_PIN_PBB5,
-       TEGRA_PIN_PBB6,
-       TEGRA_PIN_PBB7,
-};
-
-static const unsigned drive_gmg_pins[] = {
-       TEGRA_PIN_CAM_MCLK_PCC0,
-};
-
-static const unsigned drive_gmh_pins[] = {
-       TEGRA_PIN_PCC1,
-};
-
-static const unsigned drive_owr_pins[] = {
-       TEGRA_PIN_SDMMC3_CD_N_PV2,
-};
-
-static const unsigned drive_uda_pins[] = {
-       TEGRA_PIN_ULPI_CLK_PY0,
-       TEGRA_PIN_ULPI_DIR_PY1,
-       TEGRA_PIN_ULPI_NXT_PY2,
-       TEGRA_PIN_ULPI_STP_PY3,
-};
-
-static const unsigned drive_dev3_pins[] = {
-};
-
-static const unsigned drive_cec_pins[] = {
-};
-
-static const unsigned drive_at6_pins[] = {
-};
-
-static const unsigned drive_dap5_pins[] = {
-};
-
-static const unsigned drive_usb_vbus_en_pins[] = {
-};
-
-static const unsigned drive_ao3_pins[] = {
-};
-
-static const unsigned drive_hv0_pins[] = {
-};
-
-static const unsigned drive_sdio4_pins[] = {
-};
-
-static const unsigned drive_ao0_pins[] = {
-};
-
-enum tegra_mux {
-       TEGRA_MUX_BLINK,
-       TEGRA_MUX_CEC,
-       TEGRA_MUX_CLDVFS,
-       TEGRA_MUX_CLK,
-       TEGRA_MUX_CLK12,
-       TEGRA_MUX_CPU,
-       TEGRA_MUX_DAP,
-       TEGRA_MUX_DAP1,
-       TEGRA_MUX_DAP2,
-       TEGRA_MUX_DEV3,
-       TEGRA_MUX_DISPLAYA,
-       TEGRA_MUX_DISPLAYA_ALT,
-       TEGRA_MUX_DISPLAYB,
-       TEGRA_MUX_DTV,
-       TEGRA_MUX_EMC_DLL,
-       TEGRA_MUX_EXTPERIPH1,
-       TEGRA_MUX_EXTPERIPH2,
-       TEGRA_MUX_EXTPERIPH3,
-       TEGRA_MUX_GMI,
-       TEGRA_MUX_GMI_ALT,
-       TEGRA_MUX_HDA,
-       TEGRA_MUX_HSI,
-       TEGRA_MUX_I2C1,
-       TEGRA_MUX_I2C2,
-       TEGRA_MUX_I2C3,
-       TEGRA_MUX_I2C4,
-       TEGRA_MUX_I2CPWR,
-       TEGRA_MUX_I2S0,
-       TEGRA_MUX_I2S1,
-       TEGRA_MUX_I2S2,
-       TEGRA_MUX_I2S3,
-       TEGRA_MUX_I2S4,
-       TEGRA_MUX_IRDA,
-       TEGRA_MUX_KBC,
-       TEGRA_MUX_NAND,
-       TEGRA_MUX_NAND_ALT,
-       TEGRA_MUX_OWR,
-       TEGRA_MUX_PMI,
-       TEGRA_MUX_PWM0,
-       TEGRA_MUX_PWM1,
-       TEGRA_MUX_PWM2,
-       TEGRA_MUX_PWM3,
-       TEGRA_MUX_PWRON,
-       TEGRA_MUX_RESET_OUT_N,
-       TEGRA_MUX_RSVD1,
-       TEGRA_MUX_RSVD2,
-       TEGRA_MUX_RSVD3,
-       TEGRA_MUX_RSVD4,
-       TEGRA_MUX_RTCK,
-       TEGRA_MUX_SDMMC1,
-       TEGRA_MUX_SDMMC2,
-       TEGRA_MUX_SDMMC3,
-       TEGRA_MUX_SDMMC4,
-       TEGRA_MUX_SOC,
-       TEGRA_MUX_SPDIF,
-       TEGRA_MUX_SPI1,
-       TEGRA_MUX_SPI2,
-       TEGRA_MUX_SPI3,
-       TEGRA_MUX_SPI4,
-       TEGRA_MUX_SPI5,
-       TEGRA_MUX_SPI6,
-       TEGRA_MUX_SYSCLK,
-       TEGRA_MUX_TRACE,
-       TEGRA_MUX_UARTA,
-       TEGRA_MUX_UARTB,
-       TEGRA_MUX_UARTC,
-       TEGRA_MUX_UARTD,
-       TEGRA_MUX_ULPI,
-       TEGRA_MUX_USB,
-       TEGRA_MUX_VGP1,
-       TEGRA_MUX_VGP2,
-       TEGRA_MUX_VGP3,
-       TEGRA_MUX_VGP4,
-       TEGRA_MUX_VGP5,
-       TEGRA_MUX_VGP6,
-       TEGRA_MUX_VI,
-       TEGRA_MUX_VI_ALT1,
-       TEGRA_MUX_VI_ALT3,
-};
-
-#define FUNCTION(fname)                                        \
-       {                                               \
-               .name = #fname,                         \
-       }
-
-static struct tegra_function tegra114_functions[] = {
-       FUNCTION(blink),
-       FUNCTION(cec),
-       FUNCTION(cldvfs),
-       FUNCTION(clk),
-       FUNCTION(clk12),
-       FUNCTION(cpu),
-       FUNCTION(dap),
-       FUNCTION(dap1),
-       FUNCTION(dap2),
-       FUNCTION(dev3),
-       FUNCTION(displaya),
-       FUNCTION(displaya_alt),
-       FUNCTION(displayb),
-       FUNCTION(dtv),
-       FUNCTION(emc_dll),
-       FUNCTION(extperiph1),
-       FUNCTION(extperiph2),
-       FUNCTION(extperiph3),
-       FUNCTION(gmi),
-       FUNCTION(gmi_alt),
-       FUNCTION(hda),
-       FUNCTION(hsi),
-       FUNCTION(i2c1),
-       FUNCTION(i2c2),
-       FUNCTION(i2c3),
-       FUNCTION(i2c4),
-       FUNCTION(i2cpwr),
-       FUNCTION(i2s0),
-       FUNCTION(i2s1),
-       FUNCTION(i2s2),
-       FUNCTION(i2s3),
-       FUNCTION(i2s4),
-       FUNCTION(irda),
-       FUNCTION(kbc),
-       FUNCTION(nand),
-       FUNCTION(nand_alt),
-       FUNCTION(owr),
-       FUNCTION(pmi),
-       FUNCTION(pwm0),
-       FUNCTION(pwm1),
-       FUNCTION(pwm2),
-       FUNCTION(pwm3),
-       FUNCTION(pwron),
-       FUNCTION(reset_out_n),
-       FUNCTION(rsvd1),
-       FUNCTION(rsvd2),
-       FUNCTION(rsvd3),
-       FUNCTION(rsvd4),
-       FUNCTION(rtck),
-       FUNCTION(sdmmc1),
-       FUNCTION(sdmmc2),
-       FUNCTION(sdmmc3),
-       FUNCTION(sdmmc4),
-       FUNCTION(soc),
-       FUNCTION(spdif),
-       FUNCTION(spi1),
-       FUNCTION(spi2),
-       FUNCTION(spi3),
-       FUNCTION(spi4),
-       FUNCTION(spi5),
-       FUNCTION(spi6),
-       FUNCTION(sysclk),
-       FUNCTION(trace),
-       FUNCTION(uarta),
-       FUNCTION(uartb),
-       FUNCTION(uartc),
-       FUNCTION(uartd),
-       FUNCTION(ulpi),
-       FUNCTION(usb),
-       FUNCTION(vgp1),
-       FUNCTION(vgp2),
-       FUNCTION(vgp3),
-       FUNCTION(vgp4),
-       FUNCTION(vgp5),
-       FUNCTION(vgp6),
-       FUNCTION(vi),
-       FUNCTION(vi_alt1),
-       FUNCTION(vi_alt3),
-};
-
-#define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
-#define PINGROUP_REG_A                 0x3000  /* bank 1 */
-
-#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
-#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
-
-#define PINGROUP_BIT_Y(b)              (b)
-#define PINGROUP_BIT_N(b)              (-1)
-
-#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel)         \
-       {                                                               \
-               .name = #pg_name,                                       \
-               .pins = pg_name##_pins,                                 \
-               .npins = ARRAY_SIZE(pg_name##_pins),                    \
-               .funcs = {                                              \
-                       TEGRA_MUX_##f0,                                 \
-                       TEGRA_MUX_##f1,                                 \
-                       TEGRA_MUX_##f2,                                 \
-                       TEGRA_MUX_##f3,                                 \
-               },                                                      \
-               .mux_reg = PINGROUP_REG(r),                             \
-               .mux_bank = 1,                                          \
-               .mux_bit = 0,                                           \
-               .pupd_reg = PINGROUP_REG(r),                            \
-               .pupd_bank = 1,                                         \
-               .pupd_bit = 2,                                          \
-               .tri_reg = PINGROUP_REG(r),                             \
-               .tri_bank = 1,                                          \
-               .tri_bit = 4,                                           \
-               .einput_bit = 5,                                        \
-               .odrain_bit = PINGROUP_BIT_##od(6),                     \
-               .lock_bit = 7,                                          \
-               .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
-               .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9),               \
-               .drv_reg = -1,                                          \
-       }
-
-#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
-                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
-                    slwf_b, slwf_w, drvtype)                           \
-       {                                                               \
-               .name = "drive_" #pg_name,                              \
-               .pins = drive_##pg_name##_pins,                         \
-               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
-               .mux_reg = -1,                                          \
-               .pupd_reg = -1,                                         \
-               .tri_reg = -1,                                          \
-               .einput_bit = -1,                                       \
-               .odrain_bit = -1,                                       \
-               .lock_bit = -1,                                         \
-               .ioreset_bit = -1,                                      \
-               .rcv_sel_bit = -1,                                      \
-               .drv_reg = DRV_PINGROUP_REG(r),                         \
-               .drv_bank = 0,                                          \
-               .hsm_bit = hsm_b,                                       \
-               .schmitt_bit = schmitt_b,                               \
-               .lpmd_bit = lpmd_b,                                     \
-               .drvdn_bit = drvdn_b,                                   \
-               .drvdn_width = drvdn_w,                                 \
-               .drvup_bit = drvup_b,                                   \
-               .drvup_width = drvup_w,                                 \
-               .slwr_bit = slwr_b,                                     \
-               .slwr_width = slwr_w,                                   \
-               .slwf_bit = slwf_b,                                     \
-               .slwf_width = slwf_w,                                   \
-               .drvtype_bit = PINGROUP_BIT_##drvtype(6),               \
-       }
-
-static const struct tegra_pingroup tegra114_groups[] = {
-       /*       pg_name,                f0,         f1,         f2,           f3,          r,      od, ior, rcv_sel */
-       PINGROUP(ulpi_data0_po1,         SPI3,       HSI,        UARTA,        ULPI,        0x3000, N,   N,  N),
-       PINGROUP(ulpi_data1_po2,         SPI3,       HSI,        UARTA,        ULPI,        0x3004, N,   N,  N),
-       PINGROUP(ulpi_data2_po3,         SPI3,       HSI,        UARTA,        ULPI,        0x3008, N,   N,  N),
-       PINGROUP(ulpi_data3_po4,         SPI3,       HSI,        UARTA,        ULPI,        0x300c, N,   N,  N),
-       PINGROUP(ulpi_data4_po5,         SPI2,       HSI,        UARTA,        ULPI,        0x3010, N,   N,  N),
-       PINGROUP(ulpi_data5_po6,         SPI2,       HSI,        UARTA,        ULPI,        0x3014, N,   N,  N),
-       PINGROUP(ulpi_data6_po7,         SPI2,       HSI,        UARTA,        ULPI,        0x3018, N,   N,  N),
-       PINGROUP(ulpi_data7_po0,         SPI2,       HSI,        UARTA,        ULPI,        0x301c, N,   N,  N),
-       PINGROUP(ulpi_clk_py0,           SPI1,       SPI5,       UARTD,        ULPI,        0x3020, N,   N,  N),
-       PINGROUP(ulpi_dir_py1,           SPI1,       SPI5,       UARTD,        ULPI,        0x3024, N,   N,  N),
-       PINGROUP(ulpi_nxt_py2,           SPI1,       SPI5,       UARTD,        ULPI,        0x3028, N,   N,  N),
-       PINGROUP(ulpi_stp_py3,           SPI1,       SPI5,       UARTD,        ULPI,        0x302c, N,   N,  N),
-       PINGROUP(dap3_fs_pp0,            I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3030, N,   N,  N),
-       PINGROUP(dap3_din_pp1,           I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3034, N,   N,  N),
-       PINGROUP(dap3_dout_pp2,          I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3038, N,   N,  N),
-       PINGROUP(dap3_sclk_pp3,          I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x303c, N,   N,  N),
-       PINGROUP(pv0,                    USB,        RSVD2,      RSVD3,        RSVD4,       0x3040, N,   N,  N),
-       PINGROUP(pv1,                    RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3044, N,   N,  N),
-       PINGROUP(sdmmc1_clk_pz0,         SDMMC1,     CLK12,      RSVD3,        RSVD4,       0x3048, N,   N,  N),
-       PINGROUP(sdmmc1_cmd_pz1,         SDMMC1,     SPDIF,      SPI4,         UARTA,       0x304c, N,   N,  N),
-       PINGROUP(sdmmc1_dat3_py4,        SDMMC1,     SPDIF,      SPI4,         UARTA,       0x3050, N,   N,  N),
-       PINGROUP(sdmmc1_dat2_py5,        SDMMC1,     PWM0,       SPI4,         UARTA,       0x3054, N,   N,  N),
-       PINGROUP(sdmmc1_dat1_py6,        SDMMC1,     PWM1,       SPI4,         UARTA,       0x3058, N,   N,  N),
-       PINGROUP(sdmmc1_dat0_py7,        SDMMC1,     RSVD2,      SPI4,         UARTA,       0x305c, N,   N,  N),
-       PINGROUP(clk2_out_pw5,           EXTPERIPH2, RSVD2,      RSVD3,        RSVD4,       0x3068, N,   N,  N),
-       PINGROUP(clk2_req_pcc5,          DAP,        RSVD2,      RSVD3,        RSVD4,       0x306c, N,   N,  N),
-       PINGROUP(hdmi_int_pn7,           RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3110, N,   N,  Y),
-       PINGROUP(ddc_scl_pv4,            I2C4,       RSVD2,      RSVD3,        RSVD4,       0x3114, N,   N,  Y),
-       PINGROUP(ddc_sda_pv5,            I2C4,       RSVD2,      RSVD3,        RSVD4,       0x3118, N,   N,  Y),
-       PINGROUP(uart2_rxd_pc3,          IRDA,       SPDIF,      UARTA,        SPI4,        0x3164, N,   N,  N),
-       PINGROUP(uart2_txd_pc2,          IRDA,       SPDIF,      UARTA,        SPI4,        0x3168, N,   N,  N),
-       PINGROUP(uart2_rts_n_pj6,        UARTA,      UARTB,      RSVD3,        SPI4,        0x316c, N,   N,  N),
-       PINGROUP(uart2_cts_n_pj5,        UARTA,      UARTB,      RSVD3,        SPI4,        0x3170, N,   N,  N),
-       PINGROUP(uart3_txd_pw6,          UARTC,      RSVD2,      RSVD3,        SPI4,        0x3174, N,   N,  N),
-       PINGROUP(uart3_rxd_pw7,          UARTC,      RSVD2,      RSVD3,        SPI4,        0x3178, N,   N,  N),
-       PINGROUP(uart3_cts_n_pa1,        UARTC,      SDMMC1,     DTV,          SPI4,        0x317c, N,   N,  N),
-       PINGROUP(uart3_rts_n_pc0,        UARTC,      PWM0,       DTV,          DISPLAYA,    0x3180, N,   N,  N),
-       PINGROUP(pu0,                    OWR,        UARTA,      RSVD3,        RSVD4,       0x3184, N,   N,  N),
-       PINGROUP(pu1,                    RSVD1,      UARTA,      RSVD3,        RSVD4,       0x3188, N,   N,  N),
-       PINGROUP(pu2,                    RSVD1,      UARTA,      RSVD3,        RSVD4,       0x318c, N,   N,  N),
-       PINGROUP(pu3,                    PWM0,       UARTA,      DISPLAYA,     DISPLAYB,    0x3190, N,   N,  N),
-       PINGROUP(pu4,                    PWM1,       UARTA,      DISPLAYA,     DISPLAYB,    0x3194, N,   N,  N),
-       PINGROUP(pu5,                    PWM2,       UARTA,      DISPLAYA,     DISPLAYB,    0x3198, N,   N,  N),
-       PINGROUP(pu6,                    PWM3,       UARTA,      USB,          DISPLAYB,    0x319c, N,   N,  N),
-       PINGROUP(gen1_i2c_sda_pc5,       I2C1,       RSVD2,      RSVD3,        RSVD4,       0x31a0, Y,   N,  N),
-       PINGROUP(gen1_i2c_scl_pc4,       I2C1,       RSVD2,      RSVD3,        RSVD4,       0x31a4, Y,   N,  N),
-       PINGROUP(dap4_fs_pp4,            I2S3,       RSVD2,      DTV,          RSVD4,       0x31a8, N,   N,  N),
-       PINGROUP(dap4_din_pp5,           I2S3,       RSVD2,      RSVD3,        RSVD4,       0x31ac, N,   N,  N),
-       PINGROUP(dap4_dout_pp6,          I2S3,       RSVD2,      DTV,          RSVD4,       0x31b0, N,   N,  N),
-       PINGROUP(dap4_sclk_pp7,          I2S3,       RSVD2,      RSVD3,        RSVD4,       0x31b4, N,   N,  N),
-       PINGROUP(clk3_out_pee0,          EXTPERIPH3, RSVD2,      RSVD3,        RSVD4,       0x31b8, N,   N,  N),
-       PINGROUP(clk3_req_pee1,          DEV3,       RSVD2,      RSVD3,        RSVD4,       0x31bc, N,   N,  N),
-       PINGROUP(gmi_wp_n_pc7,           RSVD1,      NAND,       GMI,          GMI_ALT,     0x31c0, N,   N,  N),
-       PINGROUP(gmi_iordy_pi5,          SDMMC2,     RSVD2,      GMI,          TRACE,       0x31c4, N,   N,  N),
-       PINGROUP(gmi_wait_pi7,           SPI4,       NAND,       GMI,          DTV,         0x31c8, N,   N,  N),
-       PINGROUP(gmi_adv_n_pk0,          RSVD1,      NAND,       GMI,          TRACE,       0x31cc, N,   N,  N),
-       PINGROUP(gmi_clk_pk1,            SDMMC2,     NAND,       GMI,          TRACE,       0x31d0, N,   N,  N),
-       PINGROUP(gmi_cs0_n_pj0,          RSVD1,      NAND,       GMI,          USB,         0x31d4, N,   N,  N),
-       PINGROUP(gmi_cs1_n_pj2,          RSVD1,      NAND,       GMI,          SOC,         0x31d8, N,   N,  N),
-       PINGROUP(gmi_cs2_n_pk3,          SDMMC2,     NAND,       GMI,          TRACE,       0x31dc, N,   N,  N),
-       PINGROUP(gmi_cs3_n_pk4,          SDMMC2,     NAND,       GMI,          GMI_ALT,     0x31e0, N,   N,  N),
-       PINGROUP(gmi_cs4_n_pk2,          USB,        NAND,       GMI,          TRACE,       0x31e4, N,   N,  N),
-       PINGROUP(gmi_cs6_n_pi3,          NAND,       NAND_ALT,   GMI,          SPI4,        0x31e8, N,   N,  N),
-       PINGROUP(gmi_cs7_n_pi6,          NAND,       NAND_ALT,   GMI,          SDMMC2,      0x31ec, N,   N,  N),
-       PINGROUP(gmi_ad0_pg0,            RSVD1,      NAND,       GMI,          RSVD4,       0x31f0, N,   N,  N),
-       PINGROUP(gmi_ad1_pg1,            RSVD1,      NAND,       GMI,          RSVD4,       0x31f4, N,   N,  N),
-       PINGROUP(gmi_ad2_pg2,            RSVD1,      NAND,       GMI,          RSVD4,       0x31f8, N,   N,  N),
-       PINGROUP(gmi_ad3_pg3,            RSVD1,      NAND,       GMI,          RSVD4,       0x31fc, N,   N,  N),
-       PINGROUP(gmi_ad4_pg4,            RSVD1,      NAND,       GMI,          RSVD4,       0x3200, N,   N,  N),
-       PINGROUP(gmi_ad5_pg5,            RSVD1,      NAND,       GMI,          SPI4,        0x3204, N,   N,  N),
-       PINGROUP(gmi_ad6_pg6,            RSVD1,      NAND,       GMI,          SPI4,        0x3208, N,   N,  N),
-       PINGROUP(gmi_ad7_pg7,            RSVD1,      NAND,       GMI,          SPI4,        0x320c, N,   N,  N),
-       PINGROUP(gmi_ad8_ph0,            PWM0,       NAND,       GMI,          DTV,         0x3210, N,   N,  N),
-       PINGROUP(gmi_ad9_ph1,            PWM1,       NAND,       GMI,          CLDVFS,      0x3214, N,   N,  N),
-       PINGROUP(gmi_ad10_ph2,           PWM2,       NAND,       GMI,          CLDVFS,      0x3218, N,   N,  N),
-       PINGROUP(gmi_ad11_ph3,           PWM3,       NAND,       GMI,          USB,         0x321c, N,   N,  N),
-       PINGROUP(gmi_ad12_ph4,           SDMMC2,     NAND,       GMI,          RSVD4,       0x3220, N,   N,  N),
-       PINGROUP(gmi_ad13_ph5,           SDMMC2,     NAND,       GMI,          RSVD4,       0x3224, N,   N,  N),
-       PINGROUP(gmi_ad14_ph6,           SDMMC2,     NAND,       GMI,          DTV,         0x3228, N,   N,  N),
-       PINGROUP(gmi_ad15_ph7,           SDMMC2,     NAND,       GMI,          DTV,         0x322c, N,   N,  N),
-       PINGROUP(gmi_a16_pj7,            UARTD,      TRACE,      GMI,          GMI_ALT,     0x3230, N,   N,  N),
-       PINGROUP(gmi_a17_pb0,            UARTD,      RSVD2,      GMI,          TRACE,       0x3234, N,   N,  N),
-       PINGROUP(gmi_a18_pb1,            UARTD,      RSVD2,      GMI,          TRACE,       0x3238, N,   N,  N),
-       PINGROUP(gmi_a19_pk7,            UARTD,      SPI4,       GMI,          TRACE,       0x323c, N,   N,  N),
-       PINGROUP(gmi_wr_n_pi0,           RSVD1,      NAND,       GMI,          SPI4,        0x3240, N,   N,  N),
-       PINGROUP(gmi_oe_n_pi1,           RSVD1,      NAND,       GMI,          SOC,         0x3244, N,   N,  N),
-       PINGROUP(gmi_dqs_p_pj3,          SDMMC2,     NAND,       GMI,          TRACE,       0x3248, N,   N,  N),
-       PINGROUP(gmi_rst_n_pi4,          NAND,       NAND_ALT,   GMI,          RSVD4,       0x324c, N,   N,  N),
-       PINGROUP(gen2_i2c_scl_pt5,       I2C2,       RSVD2,      GMI,          RSVD4,       0x3250, Y,   N,  N),
-       PINGROUP(gen2_i2c_sda_pt6,       I2C2,       RSVD2,      GMI,          RSVD4,       0x3254, Y,   N,  N),
-       PINGROUP(sdmmc4_clk_pcc4,        SDMMC4,     RSVD2,      GMI,          RSVD4,       0x3258, N,   Y,  N),
-       PINGROUP(sdmmc4_cmd_pt7,         SDMMC4,     RSVD2,      GMI,          RSVD4,       0x325c, N,   Y,  N),
-       PINGROUP(sdmmc4_dat0_paa0,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3260, N,   Y,  N),
-       PINGROUP(sdmmc4_dat1_paa1,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3264, N,   Y,  N),
-       PINGROUP(sdmmc4_dat2_paa2,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3268, N,   Y,  N),
-       PINGROUP(sdmmc4_dat3_paa3,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x326c, N,   Y,  N),
-       PINGROUP(sdmmc4_dat4_paa4,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3270, N,   Y,  N),
-       PINGROUP(sdmmc4_dat5_paa5,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3274, N,   Y,  N),
-       PINGROUP(sdmmc4_dat6_paa6,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3278, N,   Y,  N),
-       PINGROUP(sdmmc4_dat7_paa7,       SDMMC4,     RSVD2,      GMI,          RSVD4,       0x327c, N,   Y,  N),
-       PINGROUP(cam_mclk_pcc0,          VI,         VI_ALT1,    VI_ALT3,      RSVD4,       0x3284, N,   N,  N),
-       PINGROUP(pcc1,                   I2S4,       RSVD2,      RSVD3,        RSVD4,       0x3288, N,   N,  N),
-       PINGROUP(pbb0,                   I2S4,       VI,         VI_ALT1,      VI_ALT3,     0x328c, N,   N,  N),
-       PINGROUP(cam_i2c_scl_pbb1,       VGP1,       I2C3,       RSVD3,        RSVD4,       0x3290, Y,   N,  N),
-       PINGROUP(cam_i2c_sda_pbb2,       VGP2,       I2C3,       RSVD3,        RSVD4,       0x3294, Y,   N,  N),
-       PINGROUP(pbb3,                   VGP3,       DISPLAYA,   DISPLAYB,     RSVD4,       0x3298, N,   N,  N),
-       PINGROUP(pbb4,                   VGP4,       DISPLAYA,   DISPLAYB,     RSVD4,       0x329c, N,   N,  N),
-       PINGROUP(pbb5,                   VGP5,       DISPLAYA,   DISPLAYB,     RSVD4,       0x32a0, N,   N,  N),
-       PINGROUP(pbb6,                   VGP6,       DISPLAYA,   DISPLAYB,     RSVD4,       0x32a4, N,   N,  N),
-       PINGROUP(pbb7,                   I2S4,       RSVD2,      RSVD3,        RSVD4,       0x32a8, N,   N,  N),
-       PINGROUP(pcc2,                   I2S4,       RSVD2,      RSVD3,        RSVD4,       0x32ac, N,   N,  N),
-       PINGROUP(jtag_rtck,              RTCK,       RSVD2,      RSVD3,        RSVD4,       0x32b0, N,   N,  N),
-       PINGROUP(pwr_i2c_scl_pz6,        I2CPWR,     RSVD2,      RSVD3,        RSVD4,       0x32b4, Y,   N,  N),
-       PINGROUP(pwr_i2c_sda_pz7,        I2CPWR,     RSVD2,      RSVD3,        RSVD4,       0x32b8, Y,   N,  N),
-       PINGROUP(kb_row0_pr0,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32bc, N,   N,  N),
-       PINGROUP(kb_row1_pr1,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32c0, N,   N,  N),
-       PINGROUP(kb_row2_pr2,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32c4, N,   N,  N),
-       PINGROUP(kb_row3_pr3,            KBC,        DISPLAYA,   RSVD3,        DISPLAYB,    0x32c8, N,   N,  N),
-       PINGROUP(kb_row4_pr4,            KBC,        DISPLAYA,   SPI2,         DISPLAYB,    0x32cc, N,   N,  N),
-       PINGROUP(kb_row5_pr5,            KBC,        DISPLAYA,   SPI2,         DISPLAYB,    0x32d0, N,   N,  N),
-       PINGROUP(kb_row6_pr6,            KBC,        DISPLAYA,   DISPLAYA_ALT, DISPLAYB,    0x32d4, N,   N,  N),
-       PINGROUP(kb_row7_pr7,            KBC,        RSVD2,      CLDVFS,       UARTA,       0x32d8, N,   N,  N),
-       PINGROUP(kb_row8_ps0,            KBC,        RSVD2,      CLDVFS,       UARTA,       0x32dc, N,   N,  N),
-       PINGROUP(kb_row9_ps1,            KBC,        RSVD2,      RSVD3,        UARTA,       0x32e0, N,   N,  N),
-       PINGROUP(kb_row10_ps2,           KBC,        RSVD2,      RSVD3,        UARTA,       0x32e4, N,   N,  N),
-       PINGROUP(kb_col0_pq0,            KBC,        USB,        SPI2,         EMC_DLL,     0x32fc, N,   N,  N),
-       PINGROUP(kb_col1_pq1,            KBC,        RSVD2,      SPI2,         EMC_DLL,     0x3300, N,   N,  N),
-       PINGROUP(kb_col2_pq2,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3304, N,   N,  N),
-       PINGROUP(kb_col3_pq3,            KBC,        DISPLAYA,   PWM2,         UARTA,       0x3308, N,   N,  N),
-       PINGROUP(kb_col4_pq4,            KBC,        OWR,        SDMMC3,       UARTA,       0x330c, N,   N,  N),
-       PINGROUP(kb_col5_pq5,            KBC,        RSVD2,      SDMMC1,       RSVD4,       0x3310, N,   N,  N),
-       PINGROUP(kb_col6_pq6,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3314, N,   N,  N),
-       PINGROUP(kb_col7_pq7,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3318, N,   N,  N),
-       PINGROUP(clk_32k_out_pa0,        BLINK,      SOC,        RSVD3,        RSVD4,       0x331c, N,   N,  N),
-       PINGROUP(sys_clk_req_pz5,        SYSCLK,     RSVD2,      RSVD3,        RSVD4,       0x3320, N,   N,  N),
-       PINGROUP(core_pwr_req,           PWRON,      RSVD2,      RSVD3,        RSVD4,       0x3324, N,   N,  N),
-       PINGROUP(cpu_pwr_req,            CPU,        RSVD2,      RSVD3,        RSVD4,       0x3328, N,   N,  N),
-       PINGROUP(pwr_int_n,              PMI,        RSVD2,      RSVD3,        RSVD4,       0x332c, N,   N,  N),
-       PINGROUP(clk_32k_in,             CLK,        RSVD2,      RSVD3,        RSVD4,       0x3330, N,   N,  N),
-       PINGROUP(owr,                    OWR,        RSVD2,      RSVD3,        RSVD4,       0x3334, N,   N,  Y),
-       PINGROUP(dap1_fs_pn0,            I2S0,       HDA,        GMI,          RSVD4,       0x3338, N,   N,  N),
-       PINGROUP(dap1_din_pn1,           I2S0,       HDA,        GMI,          RSVD4,       0x333c, N,   N,  N),
-       PINGROUP(dap1_dout_pn2,          I2S0,       HDA,        GMI,          RSVD4,       0x3340, N,   N,  N),
-       PINGROUP(dap1_sclk_pn3,          I2S0,       HDA,        GMI,          RSVD4,       0x3344, N,   N,  N),
-       PINGROUP(clk1_req_pee2,          DAP,        DAP1,       RSVD3,        RSVD4,       0x3348, N,   N,  N),
-       PINGROUP(clk1_out_pw4,           EXTPERIPH1, DAP2,       RSVD3,        RSVD4,       0x334c, N,   N,  N),
-       PINGROUP(spdif_in_pk6,           SPDIF,      USB,        RSVD3,        RSVD4,       0x3350, N,   N,  N),
-       PINGROUP(spdif_out_pk5,          SPDIF,      RSVD2,      RSVD3,        RSVD4,       0x3354, N,   N,  N),
-       PINGROUP(dap2_fs_pa2,            I2S1,       HDA,        RSVD3,        RSVD4,       0x3358, N,   N,  N),
-       PINGROUP(dap2_din_pa4,           I2S1,       HDA,        RSVD3,        RSVD4,       0x335c, N,   N,  N),
-       PINGROUP(dap2_dout_pa5,          I2S1,       HDA,        RSVD3,        RSVD4,       0x3360, N,   N,  N),
-       PINGROUP(dap2_sclk_pa3,          I2S1,       HDA,        RSVD3,        RSVD4,       0x3364, N,   N,  N),
-       PINGROUP(dvfs_pwm_px0,           SPI6,       CLDVFS,     RSVD3,        RSVD4,       0x3368, N,   N,  N),
-       PINGROUP(gpio_x1_aud_px1,        SPI6,       RSVD2,      RSVD3,        RSVD4,       0x336c, N,   N,  N),
-       PINGROUP(gpio_x3_aud_px3,        SPI6,       SPI1,       RSVD3,        RSVD4,       0x3370, N,   N,  N),
-       PINGROUP(dvfs_clk_px2,           SPI6,       CLDVFS,     RSVD3,        RSVD4,       0x3374, N,   N,  N),
-       PINGROUP(gpio_x4_aud_px4,        RSVD1,      SPI1,       SPI2,         DAP2,        0x3378, N,   N,  N),
-       PINGROUP(gpio_x5_aud_px5,        RSVD1,      SPI1,       SPI2,         RSVD4,       0x337c, N,   N,  N),
-       PINGROUP(gpio_x6_aud_px6,        SPI6,       SPI1,       SPI2,         RSVD4,       0x3380, N,   N,  N),
-       PINGROUP(gpio_x7_aud_px7,        RSVD1,      SPI1,       SPI2,         RSVD4,       0x3384, N,   N,  N),
-       PINGROUP(sdmmc3_clk_pa6,         SDMMC3,     RSVD2,      RSVD3,        SPI3,        0x3390, N,   N,  N),
-       PINGROUP(sdmmc3_cmd_pa7,         SDMMC3,     PWM3,       UARTA,        SPI3,        0x3394, N,   N,  N),
-       PINGROUP(sdmmc3_dat0_pb7,        SDMMC3,     RSVD2,      RSVD3,        SPI3,        0x3398, N,   N,  N),
-       PINGROUP(sdmmc3_dat1_pb6,        SDMMC3,     PWM2,       UARTA,        SPI3,        0x339c, N,   N,  N),
-       PINGROUP(sdmmc3_dat2_pb5,        SDMMC3,     PWM1,       DISPLAYA,     SPI3,        0x33a0, N,   N,  N),
-       PINGROUP(sdmmc3_dat3_pb4,        SDMMC3,     PWM0,       DISPLAYB,     SPI3,        0x33a4, N,   N,  N),
-       PINGROUP(hdmi_cec_pee3,          CEC,        SDMMC3,     RSVD3,        SOC,         0x33e0, Y,   N,  N),
-       PINGROUP(sdmmc1_wp_n_pv3,        SDMMC1,     CLK12,      SPI4,         UARTA,       0x33e4, N,   N,  N),
-       PINGROUP(sdmmc3_cd_n_pv2,        SDMMC3,     OWR,        RSVD3,        RSVD4,       0x33e8, N,   N,  N),
-       PINGROUP(gpio_w2_aud_pw2,        SPI6,       RSVD2,      SPI2,         I2C1,        0x33ec, N,   N,  N),
-       PINGROUP(gpio_w3_aud_pw3,        SPI6,       SPI1,       SPI2,         I2C1,        0x33f0, N,   N,  N),
-       PINGROUP(usb_vbus_en0_pn4,       USB,        RSVD2,      RSVD3,        RSVD4,       0x33f4, Y,   N,  N),
-       PINGROUP(usb_vbus_en1_pn5,       USB,        RSVD2,      RSVD3,        RSVD4,       0x33f8, Y,   N,  N),
-       PINGROUP(sdmmc3_clk_lb_in_pee5,  SDMMC3,     RSVD2,      RSVD3,        RSVD4,       0x33fc, N,   N,  N),
-       PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3,     RSVD2,      RSVD3,        RSVD4,       0x3400, N,   N,  N),
-       PINGROUP(gmi_clk_lb,             SDMMC2,     NAND,       GMI,          RSVD4,       0x3404, N,   N,  N),
-       PINGROUP(reset_out_n,            RSVD1,      RSVD2,      RSVD3,        RESET_OUT_N, 0x3408, N,   N,  N),
-
-       /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */
-       DRV_PINGROUP(ao1,         0x868,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(ao2,         0x86c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(at1,         0x870,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(at2,         0x874,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(at3,         0x878,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(at4,         0x87c,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(at5,         0x880,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(cdev1,       0x884,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(cdev2,       0x888,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dap1,        0x890,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dap2,        0x894,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dap3,        0x898,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dap4,        0x89c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dbg,         0x8a0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(sdio3,       0x8b0,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(spi,         0x8b4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uaa,         0x8b8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uab,         0x8bc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uart2,       0x8c0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uart3,       0x8c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(sdio1,       0x8ec,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(ddc,         0x8fc,  2,  3, -1,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gma,         0x900,  2,  3, -1,  14,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gme,         0x910,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gmf,         0x914,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gmg,         0x918,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gmh,         0x91c,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(owr,         0x920,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uda,         0x924,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dev3,        0x92c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(cec,         0x938,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(at6,         0x994,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(dap5,        0x998,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(usb_vbus_en, 0x99c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(ao3,         0x9a0,  2,  3,  4,  12,  5,  -1, -1,  28,  2,  -1, -1,  N),
-       DRV_PINGROUP(hv0,         0x9a4,  2,  3,  4,  12,  5,  -1, -1,  28,  2,  -1, -1,  N),
-       DRV_PINGROUP(sdio4,       0x9a8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(ao0,         0x9ac,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-};
-
-static const struct tegra_pinctrl_soc_data tegra114_pinctrl = {
-       .ngpios = NUM_GPIOS,
-       .pins = tegra114_pins,
-       .npins = ARRAY_SIZE(tegra114_pins),
-       .functions = tegra114_functions,
-       .nfunctions = ARRAY_SIZE(tegra114_functions),
-       .groups = tegra114_groups,
-       .ngroups = ARRAY_SIZE(tegra114_groups),
-       .hsm_in_mux = false,
-       .schmitt_in_mux = false,
-       .drvtype_in_mux = false,
-};
-
-static int tegra114_pinctrl_probe(struct platform_device *pdev)
-{
-       return tegra_pinctrl_probe(pdev, &tegra114_pinctrl);
-}
-
-static const struct of_device_id tegra114_pinctrl_of_match[] = {
-       { .compatible = "nvidia,tegra114-pinmux", },
-       { },
-};
-MODULE_DEVICE_TABLE(of, tegra114_pinctrl_of_match);
-
-static struct platform_driver tegra114_pinctrl_driver = {
-       .driver = {
-               .name = "tegra114-pinctrl",
-               .of_match_table = tegra114_pinctrl_of_match,
-       },
-       .probe = tegra114_pinctrl_probe,
-       .remove = tegra_pinctrl_remove,
-};
-module_platform_driver(tegra114_pinctrl_driver);
-
-MODULE_AUTHOR("Pritesh Raithatha <praithatha@nvidia.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra114 pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-tegra124.c b/drivers/pinctrl/pinctrl-tegra124.c
deleted file mode 100644 (file)
index 7cd44c7..0000000
+++ /dev/null
@@ -1,2084 +0,0 @@
-/*
- * Pinctrl data for the NVIDIA Tegra124 pinmux
- *
- * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-
-#include "pinctrl-tegra.h"
-
-/*
- * Most pins affected by the pinmux can also be GPIOs. Define these first.
- * These must match how the GPIO driver names/numbers its pins.
- */
-#define _GPIO(offset)                          (offset)
-
-#define TEGRA_PIN_CLK_32K_OUT_PA0              _GPIO(0)
-#define TEGRA_PIN_UART3_CTS_N_PA1              _GPIO(1)
-#define TEGRA_PIN_DAP2_FS_PA2                  _GPIO(2)
-#define TEGRA_PIN_DAP2_SCLK_PA3                        _GPIO(3)
-#define TEGRA_PIN_DAP2_DIN_PA4                 _GPIO(4)
-#define TEGRA_PIN_DAP2_DOUT_PA5                        _GPIO(5)
-#define TEGRA_PIN_SDMMC3_CLK_PA6               _GPIO(6)
-#define TEGRA_PIN_SDMMC3_CMD_PA7               _GPIO(7)
-#define TEGRA_PIN_PB0                          _GPIO(8)
-#define TEGRA_PIN_PB1                          _GPIO(9)
-#define TEGRA_PIN_SDMMC3_DAT3_PB4              _GPIO(12)
-#define TEGRA_PIN_SDMMC3_DAT2_PB5              _GPIO(13)
-#define TEGRA_PIN_SDMMC3_DAT1_PB6              _GPIO(14)
-#define TEGRA_PIN_SDMMC3_DAT0_PB7              _GPIO(15)
-#define TEGRA_PIN_UART3_RTS_N_PC0              _GPIO(16)
-#define TEGRA_PIN_UART2_TXD_PC2                        _GPIO(18)
-#define TEGRA_PIN_UART2_RXD_PC3                        _GPIO(19)
-#define TEGRA_PIN_GEN1_I2C_SCL_PC4             _GPIO(20)
-#define TEGRA_PIN_GEN1_I2C_SDA_PC5             _GPIO(21)
-#define TEGRA_PIN_PC7                          _GPIO(23)
-#define TEGRA_PIN_PG0                          _GPIO(48)
-#define TEGRA_PIN_PG1                          _GPIO(49)
-#define TEGRA_PIN_PG2                          _GPIO(50)
-#define TEGRA_PIN_PG3                          _GPIO(51)
-#define TEGRA_PIN_PG4                          _GPIO(52)
-#define TEGRA_PIN_PG5                          _GPIO(53)
-#define TEGRA_PIN_PG6                          _GPIO(54)
-#define TEGRA_PIN_PG7                          _GPIO(55)
-#define TEGRA_PIN_PH0                          _GPIO(56)
-#define TEGRA_PIN_PH1                          _GPIO(57)
-#define TEGRA_PIN_PH2                          _GPIO(58)
-#define TEGRA_PIN_PH3                          _GPIO(59)
-#define TEGRA_PIN_PH4                          _GPIO(60)
-#define TEGRA_PIN_PH5                          _GPIO(61)
-#define TEGRA_PIN_PH6                          _GPIO(62)
-#define TEGRA_PIN_PH7                          _GPIO(63)
-#define TEGRA_PIN_PI0                          _GPIO(64)
-#define TEGRA_PIN_PI1                          _GPIO(65)
-#define TEGRA_PIN_PI2                          _GPIO(66)
-#define TEGRA_PIN_PI3                          _GPIO(67)
-#define TEGRA_PIN_PI4                          _GPIO(68)
-#define TEGRA_PIN_PI5                          _GPIO(69)
-#define TEGRA_PIN_PI6                          _GPIO(70)
-#define TEGRA_PIN_PI7                          _GPIO(71)
-#define TEGRA_PIN_PJ0                          _GPIO(72)
-#define TEGRA_PIN_PJ2                          _GPIO(74)
-#define TEGRA_PIN_UART2_CTS_N_PJ5              _GPIO(77)
-#define TEGRA_PIN_UART2_RTS_N_PJ6              _GPIO(78)
-#define TEGRA_PIN_PJ7                          _GPIO(79)
-#define TEGRA_PIN_PK0                          _GPIO(80)
-#define TEGRA_PIN_PK1                          _GPIO(81)
-#define TEGRA_PIN_PK2                          _GPIO(82)
-#define TEGRA_PIN_PK3                          _GPIO(83)
-#define TEGRA_PIN_PK4                          _GPIO(84)
-#define TEGRA_PIN_SPDIF_OUT_PK5                        _GPIO(85)
-#define TEGRA_PIN_SPDIF_IN_PK6                 _GPIO(86)
-#define TEGRA_PIN_PK7                          _GPIO(87)
-#define TEGRA_PIN_DAP1_FS_PN0                  _GPIO(104)
-#define TEGRA_PIN_DAP1_DIN_PN1                 _GPIO(105)
-#define TEGRA_PIN_DAP1_DOUT_PN2                        _GPIO(106)
-#define TEGRA_PIN_DAP1_SCLK_PN3                        _GPIO(107)
-#define TEGRA_PIN_USB_VBUS_EN0_PN4             _GPIO(108)
-#define TEGRA_PIN_USB_VBUS_EN1_PN5             _GPIO(109)
-#define TEGRA_PIN_HDMI_INT_PN7                 _GPIO(111)
-#define TEGRA_PIN_ULPI_DATA7_PO0               _GPIO(112)
-#define TEGRA_PIN_ULPI_DATA0_PO1               _GPIO(113)
-#define TEGRA_PIN_ULPI_DATA1_PO2               _GPIO(114)
-#define TEGRA_PIN_ULPI_DATA2_PO3               _GPIO(115)
-#define TEGRA_PIN_ULPI_DATA3_PO4               _GPIO(116)
-#define TEGRA_PIN_ULPI_DATA4_PO5               _GPIO(117)
-#define TEGRA_PIN_ULPI_DATA5_PO6               _GPIO(118)
-#define TEGRA_PIN_ULPI_DATA6_PO7               _GPIO(119)
-#define TEGRA_PIN_DAP3_FS_PP0                  _GPIO(120)
-#define TEGRA_PIN_DAP3_DIN_PP1                 _GPIO(121)
-#define TEGRA_PIN_DAP3_DOUT_PP2                        _GPIO(122)
-#define TEGRA_PIN_DAP3_SCLK_PP3                        _GPIO(123)
-#define TEGRA_PIN_DAP4_FS_PP4                  _GPIO(124)
-#define TEGRA_PIN_DAP4_DIN_PP5                 _GPIO(125)
-#define TEGRA_PIN_DAP4_DOUT_PP6                        _GPIO(126)
-#define TEGRA_PIN_DAP4_SCLK_PP7                        _GPIO(127)
-#define TEGRA_PIN_KB_COL0_PQ0                  _GPIO(128)
-#define TEGRA_PIN_KB_COL1_PQ1                  _GPIO(129)
-#define TEGRA_PIN_KB_COL2_PQ2                  _GPIO(130)
-#define TEGRA_PIN_KB_COL3_PQ3                  _GPIO(131)
-#define TEGRA_PIN_KB_COL4_PQ4                  _GPIO(132)
-#define TEGRA_PIN_KB_COL5_PQ5                  _GPIO(133)
-#define TEGRA_PIN_KB_COL6_PQ6                  _GPIO(134)
-#define TEGRA_PIN_KB_COL7_PQ7                  _GPIO(135)
-#define TEGRA_PIN_KB_ROW0_PR0                  _GPIO(136)
-#define TEGRA_PIN_KB_ROW1_PR1                  _GPIO(137)
-#define TEGRA_PIN_KB_ROW2_PR2                  _GPIO(138)
-#define TEGRA_PIN_KB_ROW3_PR3                  _GPIO(139)
-#define TEGRA_PIN_KB_ROW4_PR4                  _GPIO(140)
-#define TEGRA_PIN_KB_ROW5_PR5                  _GPIO(141)
-#define TEGRA_PIN_KB_ROW6_PR6                  _GPIO(142)
-#define TEGRA_PIN_KB_ROW7_PR7                  _GPIO(143)
-#define TEGRA_PIN_KB_ROW8_PS0                  _GPIO(144)
-#define TEGRA_PIN_KB_ROW9_PS1                  _GPIO(145)
-#define TEGRA_PIN_KB_ROW10_PS2                 _GPIO(146)
-#define TEGRA_PIN_KB_ROW11_PS3                 _GPIO(147)
-#define TEGRA_PIN_KB_ROW12_PS4                 _GPIO(148)
-#define TEGRA_PIN_KB_ROW13_PS5                 _GPIO(149)
-#define TEGRA_PIN_KB_ROW14_PS6                 _GPIO(150)
-#define TEGRA_PIN_KB_ROW15_PS7                 _GPIO(151)
-#define TEGRA_PIN_KB_ROW16_PT0                 _GPIO(152)
-#define TEGRA_PIN_KB_ROW17_PT1                 _GPIO(153)
-#define TEGRA_PIN_GEN2_I2C_SCL_PT5             _GPIO(157)
-#define TEGRA_PIN_GEN2_I2C_SDA_PT6             _GPIO(158)
-#define TEGRA_PIN_SDMMC4_CMD_PT7               _GPIO(159)
-#define TEGRA_PIN_PU0                          _GPIO(160)
-#define TEGRA_PIN_PU1                          _GPIO(161)
-#define TEGRA_PIN_PU2                          _GPIO(162)
-#define TEGRA_PIN_PU3                          _GPIO(163)
-#define TEGRA_PIN_PU4                          _GPIO(164)
-#define TEGRA_PIN_PU5                          _GPIO(165)
-#define TEGRA_PIN_PU6                          _GPIO(166)
-#define TEGRA_PIN_PV0                          _GPIO(168)
-#define TEGRA_PIN_PV1                          _GPIO(169)
-#define TEGRA_PIN_SDMMC3_CD_N_PV2              _GPIO(170)
-#define TEGRA_PIN_SDMMC1_WP_N_PV3              _GPIO(171)
-#define TEGRA_PIN_DDC_SCL_PV4                  _GPIO(172)
-#define TEGRA_PIN_DDC_SDA_PV5                  _GPIO(173)
-#define TEGRA_PIN_GPIO_W2_AUD_PW2              _GPIO(178)
-#define TEGRA_PIN_GPIO_W3_AUD_PW3              _GPIO(179)
-#define TEGRA_PIN_DAP_MCLK1_PW4                        _GPIO(180)
-#define TEGRA_PIN_CLK2_OUT_PW5                 _GPIO(181)
-#define TEGRA_PIN_UART3_TXD_PW6                        _GPIO(182)
-#define TEGRA_PIN_UART3_RXD_PW7                        _GPIO(183)
-#define TEGRA_PIN_DVFS_PWM_PX0                 _GPIO(184)
-#define TEGRA_PIN_GPIO_X1_AUD_PX1              _GPIO(185)
-#define TEGRA_PIN_DVFS_CLK_PX2                 _GPIO(186)
-#define TEGRA_PIN_GPIO_X3_AUD_PX3              _GPIO(187)
-#define TEGRA_PIN_GPIO_X4_AUD_PX4              _GPIO(188)
-#define TEGRA_PIN_GPIO_X5_AUD_PX5              _GPIO(189)
-#define TEGRA_PIN_GPIO_X6_AUD_PX6              _GPIO(190)
-#define TEGRA_PIN_GPIO_X7_AUD_PX7              _GPIO(191)
-#define TEGRA_PIN_ULPI_CLK_PY0                 _GPIO(192)
-#define TEGRA_PIN_ULPI_DIR_PY1                 _GPIO(193)
-#define TEGRA_PIN_ULPI_NXT_PY2                 _GPIO(194)
-#define TEGRA_PIN_ULPI_STP_PY3                 _GPIO(195)
-#define TEGRA_PIN_SDMMC1_DAT3_PY4              _GPIO(196)
-#define TEGRA_PIN_SDMMC1_DAT2_PY5              _GPIO(197)
-#define TEGRA_PIN_SDMMC1_DAT1_PY6              _GPIO(198)
-#define TEGRA_PIN_SDMMC1_DAT0_PY7              _GPIO(199)
-#define TEGRA_PIN_SDMMC1_CLK_PZ0               _GPIO(200)
-#define TEGRA_PIN_SDMMC1_CMD_PZ1               _GPIO(201)
-#define TEGRA_PIN_PWR_I2C_SCL_PZ6              _GPIO(206)
-#define TEGRA_PIN_PWR_I2C_SDA_PZ7              _GPIO(207)
-#define TEGRA_PIN_SDMMC4_DAT0_PAA0             _GPIO(208)
-#define TEGRA_PIN_SDMMC4_DAT1_PAA1             _GPIO(209)
-#define TEGRA_PIN_SDMMC4_DAT2_PAA2             _GPIO(210)
-#define TEGRA_PIN_SDMMC4_DAT3_PAA3             _GPIO(211)
-#define TEGRA_PIN_SDMMC4_DAT4_PAA4             _GPIO(212)
-#define TEGRA_PIN_SDMMC4_DAT5_PAA5             _GPIO(213)
-#define TEGRA_PIN_SDMMC4_DAT6_PAA6             _GPIO(214)
-#define TEGRA_PIN_SDMMC4_DAT7_PAA7             _GPIO(215)
-#define TEGRA_PIN_PBB0                         _GPIO(216)
-#define TEGRA_PIN_CAM_I2C_SCL_PBB1             _GPIO(217)
-#define TEGRA_PIN_CAM_I2C_SDA_PBB2             _GPIO(218)
-#define TEGRA_PIN_PBB3                         _GPIO(219)
-#define TEGRA_PIN_PBB4                         _GPIO(220)
-#define TEGRA_PIN_PBB5                         _GPIO(221)
-#define TEGRA_PIN_PBB6                         _GPIO(222)
-#define TEGRA_PIN_PBB7                         _GPIO(223)
-#define TEGRA_PIN_CAM_MCLK_PCC0                        _GPIO(224)
-#define TEGRA_PIN_PCC1                         _GPIO(225)
-#define TEGRA_PIN_PCC2                         _GPIO(226)
-#define TEGRA_PIN_SDMMC4_CLK_PCC4              _GPIO(228)
-#define TEGRA_PIN_CLK2_REQ_PCC5                        _GPIO(229)
-#define TEGRA_PIN_PEX_L0_RST_N_PDD1            _GPIO(233)
-#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2         _GPIO(234)
-#define TEGRA_PIN_PEX_WAKE_N_PDD3              _GPIO(235)
-#define TEGRA_PIN_PEX_L1_RST_N_PDD5            _GPIO(237)
-#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6         _GPIO(238)
-#define TEGRA_PIN_CLK3_OUT_PEE0                        _GPIO(240)
-#define TEGRA_PIN_CLK3_REQ_PEE1                        _GPIO(241)
-#define TEGRA_PIN_DAP_MCLK1_REQ_PEE2           _GPIO(242)
-#define TEGRA_PIN_HDMI_CEC_PEE3                        _GPIO(243)
-#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4       _GPIO(244)
-#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5                _GPIO(245)
-#define TEGRA_PIN_DP_HPD_PFF0                  _GPIO(248)
-#define TEGRA_PIN_USB_VBUS_EN2_PFF1            _GPIO(249)
-#define TEGRA_PIN_PFF2                         _GPIO(250)
-
-/* All non-GPIO pins follow */
-#define NUM_GPIOS                              (TEGRA_PIN_PFF2 + 1)
-#define _PIN(offset)                           (NUM_GPIOS + (offset))
-
-/* Non-GPIO pins */
-#define TEGRA_PIN_CORE_PWR_REQ                 _PIN(0)
-#define TEGRA_PIN_CPU_PWR_REQ                  _PIN(1)
-#define TEGRA_PIN_PWR_INT_N                    _PIN(2)
-#define TEGRA_PIN_GMI_CLK_LB                   _PIN(3)
-#define TEGRA_PIN_RESET_OUT_N                  _PIN(4)
-#define TEGRA_PIN_OWR                          _PIN(5)
-#define TEGRA_PIN_CLK_32K_IN                   _PIN(6)
-#define TEGRA_PIN_JTAG_RTCK                    _PIN(7)
-#define TEGRA_PIN_DSI_B_CLK_P                  _PIN(8)
-#define TEGRA_PIN_DSI_B_CLK_N                  _PIN(9)
-#define TEGRA_PIN_DSI_B_D0_P                   _PIN(10)
-#define TEGRA_PIN_DSI_B_D0_N                   _PIN(11)
-#define TEGRA_PIN_DSI_B_D1_P                   _PIN(12)
-#define TEGRA_PIN_DSI_B_D1_N                   _PIN(13)
-#define TEGRA_PIN_DSI_B_D2_P                   _PIN(14)
-#define TEGRA_PIN_DSI_B_D2_N                   _PIN(15)
-#define TEGRA_PIN_DSI_B_D3_P                   _PIN(16)
-#define TEGRA_PIN_DSI_B_D3_N                   _PIN(17)
-
-static const struct pinctrl_pin_desc tegra124_pins[] = {
-       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"),
-       PINCTRL_PIN(TEGRA_PIN_PB0, "PB0"),
-       PINCTRL_PIN(TEGRA_PIN_PB1, "PB1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"),
-       PINCTRL_PIN(TEGRA_PIN_PC7, "PC7"),
-       PINCTRL_PIN(TEGRA_PIN_PG0, "PG0"),
-       PINCTRL_PIN(TEGRA_PIN_PG1, "PG1"),
-       PINCTRL_PIN(TEGRA_PIN_PG2, "PG2"),
-       PINCTRL_PIN(TEGRA_PIN_PG3, "PG3"),
-       PINCTRL_PIN(TEGRA_PIN_PG4, "PG4"),
-       PINCTRL_PIN(TEGRA_PIN_PG5, "PG5"),
-       PINCTRL_PIN(TEGRA_PIN_PG6, "PG6"),
-       PINCTRL_PIN(TEGRA_PIN_PG7, "PG7"),
-       PINCTRL_PIN(TEGRA_PIN_PH0, "PH0"),
-       PINCTRL_PIN(TEGRA_PIN_PH1, "PH1"),
-       PINCTRL_PIN(TEGRA_PIN_PH2, "PH2"),
-       PINCTRL_PIN(TEGRA_PIN_PH3, "PH3"),
-       PINCTRL_PIN(TEGRA_PIN_PH4, "PH4"),
-       PINCTRL_PIN(TEGRA_PIN_PH5, "PH5"),
-       PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"),
-       PINCTRL_PIN(TEGRA_PIN_PH7, "PH7"),
-       PINCTRL_PIN(TEGRA_PIN_PI0, "PI0"),
-       PINCTRL_PIN(TEGRA_PIN_PI1, "PI1"),
-       PINCTRL_PIN(TEGRA_PIN_PI2, "PI2"),
-       PINCTRL_PIN(TEGRA_PIN_PI3, "PI3"),
-       PINCTRL_PIN(TEGRA_PIN_PI4, "PI4"),
-       PINCTRL_PIN(TEGRA_PIN_PI5, "PI5"),
-       PINCTRL_PIN(TEGRA_PIN_PI6, "PI6"),
-       PINCTRL_PIN(TEGRA_PIN_PI7, "PI7"),
-       PINCTRL_PIN(TEGRA_PIN_PJ0, "PJ0"),
-       PINCTRL_PIN(TEGRA_PIN_PJ2, "PJ2"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"),
-       PINCTRL_PIN(TEGRA_PIN_PJ7, "PJ7"),
-       PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"),
-       PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"),
-       PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"),
-       PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"),
-       PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"),
-       PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"),
-       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"),
-       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW16_PT0, "KB_ROW16 PT0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW17_PT1, "KB_ROW17 PT1"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"),
-       PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"),
-       PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"),
-       PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"),
-       PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"),
-       PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"),
-       PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"),
-       PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"),
-       PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"),
-       PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"),
-       PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"),
-       PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"),
-       PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"),
-       PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"),
-       PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"),
-       PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"),
-       PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"),
-       PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"),
-       PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"),
-       PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"),
-       PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"),
-       PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"),
-       PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"),
-       PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"),
-       PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"),
-       PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_REQ_PEE2, "DAP_MCLK1_REQ PEE2"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"),
-       PINCTRL_PIN(TEGRA_PIN_DP_HPD_PFF0, "DP_HPD PFF0"),
-       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN2_PFF1, "USB_VBUS_EN2 PFF1"),
-       PINCTRL_PIN(TEGRA_PIN_PFF2, "PFF2"),
-       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"),
-       PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"),
-       PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"),
-       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_P, "DSI_B_CLK_P"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_N, "DSI_B_CLK_N"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_P, "DSI_B_D0_P"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_N, "DSI_B_D0_N"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_P, "DSI_B_D1_P"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_N, "DSI_B_D1_N"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_P, "DSI_B_D2_P"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_N, "DSI_B_D2_N"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_P, "DSI_B_D3_P"),
-       PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_N, "DSI_B_D3_N"),
-};
-
-static const unsigned clk_32k_out_pa0_pins[] = {
-       TEGRA_PIN_CLK_32K_OUT_PA0,
-};
-
-static const unsigned uart3_cts_n_pa1_pins[] = {
-       TEGRA_PIN_UART3_CTS_N_PA1,
-};
-
-static const unsigned dap2_fs_pa2_pins[] = {
-       TEGRA_PIN_DAP2_FS_PA2,
-};
-
-static const unsigned dap2_sclk_pa3_pins[] = {
-       TEGRA_PIN_DAP2_SCLK_PA3,
-};
-
-static const unsigned dap2_din_pa4_pins[] = {
-       TEGRA_PIN_DAP2_DIN_PA4,
-};
-
-static const unsigned dap2_dout_pa5_pins[] = {
-       TEGRA_PIN_DAP2_DOUT_PA5,
-};
-
-static const unsigned sdmmc3_clk_pa6_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_PA6,
-};
-
-static const unsigned sdmmc3_cmd_pa7_pins[] = {
-       TEGRA_PIN_SDMMC3_CMD_PA7,
-};
-
-static const unsigned pb0_pins[] = {
-       TEGRA_PIN_PB0,
-};
-
-static const unsigned pb1_pins[] = {
-       TEGRA_PIN_PB1,
-};
-
-static const unsigned sdmmc3_dat3_pb4_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT3_PB4,
-};
-
-static const unsigned sdmmc3_dat2_pb5_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT2_PB5,
-};
-
-static const unsigned sdmmc3_dat1_pb6_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT1_PB6,
-};
-
-static const unsigned sdmmc3_dat0_pb7_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT0_PB7,
-};
-
-static const unsigned uart3_rts_n_pc0_pins[] = {
-       TEGRA_PIN_UART3_RTS_N_PC0,
-};
-
-static const unsigned uart2_txd_pc2_pins[] = {
-       TEGRA_PIN_UART2_TXD_PC2,
-};
-
-static const unsigned uart2_rxd_pc3_pins[] = {
-       TEGRA_PIN_UART2_RXD_PC3,
-};
-
-static const unsigned gen1_i2c_scl_pc4_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SCL_PC4,
-};
-
-static const unsigned gen1_i2c_sda_pc5_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SDA_PC5,
-};
-
-static const unsigned pc7_pins[] = {
-       TEGRA_PIN_PC7,
-};
-
-static const unsigned pg0_pins[] = {
-       TEGRA_PIN_PG0,
-};
-
-static const unsigned pg1_pins[] = {
-       TEGRA_PIN_PG1,
-};
-
-static const unsigned pg2_pins[] = {
-       TEGRA_PIN_PG2,
-};
-
-static const unsigned pg3_pins[] = {
-       TEGRA_PIN_PG3,
-};
-
-static const unsigned pg4_pins[] = {
-       TEGRA_PIN_PG4,
-};
-
-static const unsigned pg5_pins[] = {
-       TEGRA_PIN_PG5,
-};
-
-static const unsigned pg6_pins[] = {
-       TEGRA_PIN_PG6,
-};
-
-static const unsigned pg7_pins[] = {
-       TEGRA_PIN_PG7,
-};
-
-static const unsigned ph0_pins[] = {
-       TEGRA_PIN_PH0,
-};
-
-static const unsigned ph1_pins[] = {
-       TEGRA_PIN_PH1,
-};
-
-static const unsigned ph2_pins[] = {
-       TEGRA_PIN_PH2,
-};
-
-static const unsigned ph3_pins[] = {
-       TEGRA_PIN_PH3,
-};
-
-static const unsigned ph4_pins[] = {
-       TEGRA_PIN_PH4,
-};
-
-static const unsigned ph5_pins[] = {
-       TEGRA_PIN_PH5,
-};
-
-static const unsigned ph6_pins[] = {
-       TEGRA_PIN_PH6,
-};
-
-static const unsigned ph7_pins[] = {
-       TEGRA_PIN_PH7,
-};
-
-static const unsigned pi0_pins[] = {
-       TEGRA_PIN_PI0,
-};
-
-static const unsigned pi1_pins[] = {
-       TEGRA_PIN_PI1,
-};
-
-static const unsigned pi2_pins[] = {
-       TEGRA_PIN_PI2,
-};
-
-static const unsigned pi3_pins[] = {
-       TEGRA_PIN_PI3,
-};
-
-static const unsigned pi4_pins[] = {
-       TEGRA_PIN_PI4,
-};
-
-static const unsigned pi5_pins[] = {
-       TEGRA_PIN_PI5,
-};
-
-static const unsigned pi6_pins[] = {
-       TEGRA_PIN_PI6,
-};
-
-static const unsigned pi7_pins[] = {
-       TEGRA_PIN_PI7,
-};
-
-static const unsigned pj0_pins[] = {
-       TEGRA_PIN_PJ0,
-};
-
-static const unsigned pj2_pins[] = {
-       TEGRA_PIN_PJ2,
-};
-
-static const unsigned uart2_cts_n_pj5_pins[] = {
-       TEGRA_PIN_UART2_CTS_N_PJ5,
-};
-
-static const unsigned uart2_rts_n_pj6_pins[] = {
-       TEGRA_PIN_UART2_RTS_N_PJ6,
-};
-
-static const unsigned pj7_pins[] = {
-       TEGRA_PIN_PJ7,
-};
-
-static const unsigned pk0_pins[] = {
-       TEGRA_PIN_PK0,
-};
-
-static const unsigned pk1_pins[] = {
-       TEGRA_PIN_PK1,
-};
-
-static const unsigned pk2_pins[] = {
-       TEGRA_PIN_PK2,
-};
-
-static const unsigned pk3_pins[] = {
-       TEGRA_PIN_PK3,
-};
-
-static const unsigned pk4_pins[] = {
-       TEGRA_PIN_PK4,
-};
-
-static const unsigned spdif_out_pk5_pins[] = {
-       TEGRA_PIN_SPDIF_OUT_PK5,
-};
-
-static const unsigned spdif_in_pk6_pins[] = {
-       TEGRA_PIN_SPDIF_IN_PK6,
-};
-
-static const unsigned pk7_pins[] = {
-       TEGRA_PIN_PK7,
-};
-
-static const unsigned dap1_fs_pn0_pins[] = {
-       TEGRA_PIN_DAP1_FS_PN0,
-};
-
-static const unsigned dap1_din_pn1_pins[] = {
-       TEGRA_PIN_DAP1_DIN_PN1,
-};
-
-static const unsigned dap1_dout_pn2_pins[] = {
-       TEGRA_PIN_DAP1_DOUT_PN2,
-};
-
-static const unsigned dap1_sclk_pn3_pins[] = {
-       TEGRA_PIN_DAP1_SCLK_PN3,
-};
-
-static const unsigned usb_vbus_en0_pn4_pins[] = {
-       TEGRA_PIN_USB_VBUS_EN0_PN4,
-};
-
-static const unsigned usb_vbus_en1_pn5_pins[] = {
-       TEGRA_PIN_USB_VBUS_EN1_PN5,
-};
-
-static const unsigned hdmi_int_pn7_pins[] = {
-       TEGRA_PIN_HDMI_INT_PN7,
-};
-
-static const unsigned ulpi_data7_po0_pins[] = {
-       TEGRA_PIN_ULPI_DATA7_PO0,
-};
-
-static const unsigned ulpi_data0_po1_pins[] = {
-       TEGRA_PIN_ULPI_DATA0_PO1,
-};
-
-static const unsigned ulpi_data1_po2_pins[] = {
-       TEGRA_PIN_ULPI_DATA1_PO2,
-};
-
-static const unsigned ulpi_data2_po3_pins[] = {
-       TEGRA_PIN_ULPI_DATA2_PO3,
-};
-
-static const unsigned ulpi_data3_po4_pins[] = {
-       TEGRA_PIN_ULPI_DATA3_PO4,
-};
-
-static const unsigned ulpi_data4_po5_pins[] = {
-       TEGRA_PIN_ULPI_DATA4_PO5,
-};
-
-static const unsigned ulpi_data5_po6_pins[] = {
-       TEGRA_PIN_ULPI_DATA5_PO6,
-};
-
-static const unsigned ulpi_data6_po7_pins[] = {
-       TEGRA_PIN_ULPI_DATA6_PO7,
-};
-
-static const unsigned dap3_fs_pp0_pins[] = {
-       TEGRA_PIN_DAP3_FS_PP0,
-};
-
-static const unsigned dap3_din_pp1_pins[] = {
-       TEGRA_PIN_DAP3_DIN_PP1,
-};
-
-static const unsigned dap3_dout_pp2_pins[] = {
-       TEGRA_PIN_DAP3_DOUT_PP2,
-};
-
-static const unsigned dap3_sclk_pp3_pins[] = {
-       TEGRA_PIN_DAP3_SCLK_PP3,
-};
-
-static const unsigned dap4_fs_pp4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PP4,
-};
-
-static const unsigned dap4_din_pp5_pins[] = {
-       TEGRA_PIN_DAP4_DIN_PP5,
-};
-
-static const unsigned dap4_dout_pp6_pins[] = {
-       TEGRA_PIN_DAP4_DOUT_PP6,
-};
-
-static const unsigned dap4_sclk_pp7_pins[] = {
-       TEGRA_PIN_DAP4_SCLK_PP7,
-};
-
-static const unsigned kb_col0_pq0_pins[] = {
-       TEGRA_PIN_KB_COL0_PQ0,
-};
-
-static const unsigned kb_col1_pq1_pins[] = {
-       TEGRA_PIN_KB_COL1_PQ1,
-};
-
-static const unsigned kb_col2_pq2_pins[] = {
-       TEGRA_PIN_KB_COL2_PQ2,
-};
-
-static const unsigned kb_col3_pq3_pins[] = {
-       TEGRA_PIN_KB_COL3_PQ3,
-};
-
-static const unsigned kb_col4_pq4_pins[] = {
-       TEGRA_PIN_KB_COL4_PQ4,
-};
-
-static const unsigned kb_col5_pq5_pins[] = {
-       TEGRA_PIN_KB_COL5_PQ5,
-};
-
-static const unsigned kb_col6_pq6_pins[] = {
-       TEGRA_PIN_KB_COL6_PQ6,
-};
-
-static const unsigned kb_col7_pq7_pins[] = {
-       TEGRA_PIN_KB_COL7_PQ7,
-};
-
-static const unsigned kb_row0_pr0_pins[] = {
-       TEGRA_PIN_KB_ROW0_PR0,
-};
-
-static const unsigned kb_row1_pr1_pins[] = {
-       TEGRA_PIN_KB_ROW1_PR1,
-};
-
-static const unsigned kb_row2_pr2_pins[] = {
-       TEGRA_PIN_KB_ROW2_PR2,
-};
-
-static const unsigned kb_row3_pr3_pins[] = {
-       TEGRA_PIN_KB_ROW3_PR3,
-};
-
-static const unsigned kb_row4_pr4_pins[] = {
-       TEGRA_PIN_KB_ROW4_PR4,
-};
-
-static const unsigned kb_row5_pr5_pins[] = {
-       TEGRA_PIN_KB_ROW5_PR5,
-};
-
-static const unsigned kb_row6_pr6_pins[] = {
-       TEGRA_PIN_KB_ROW6_PR6,
-};
-
-static const unsigned kb_row7_pr7_pins[] = {
-       TEGRA_PIN_KB_ROW7_PR7,
-};
-
-static const unsigned kb_row8_ps0_pins[] = {
-       TEGRA_PIN_KB_ROW8_PS0,
-};
-
-static const unsigned kb_row9_ps1_pins[] = {
-       TEGRA_PIN_KB_ROW9_PS1,
-};
-
-static const unsigned kb_row10_ps2_pins[] = {
-       TEGRA_PIN_KB_ROW10_PS2,
-};
-
-static const unsigned kb_row11_ps3_pins[] = {
-       TEGRA_PIN_KB_ROW11_PS3,
-};
-
-static const unsigned kb_row12_ps4_pins[] = {
-       TEGRA_PIN_KB_ROW12_PS4,
-};
-
-static const unsigned kb_row13_ps5_pins[] = {
-       TEGRA_PIN_KB_ROW13_PS5,
-};
-
-static const unsigned kb_row14_ps6_pins[] = {
-       TEGRA_PIN_KB_ROW14_PS6,
-};
-
-static const unsigned kb_row15_ps7_pins[] = {
-       TEGRA_PIN_KB_ROW15_PS7,
-};
-
-static const unsigned kb_row16_pt0_pins[] = {
-       TEGRA_PIN_KB_ROW16_PT0,
-};
-
-static const unsigned kb_row17_pt1_pins[] = {
-       TEGRA_PIN_KB_ROW17_PT1,
-};
-
-static const unsigned gen2_i2c_scl_pt5_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SCL_PT5,
-};
-
-static const unsigned gen2_i2c_sda_pt6_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SDA_PT6,
-};
-
-static const unsigned sdmmc4_cmd_pt7_pins[] = {
-       TEGRA_PIN_SDMMC4_CMD_PT7,
-};
-
-static const unsigned pu0_pins[] = {
-       TEGRA_PIN_PU0,
-};
-
-static const unsigned pu1_pins[] = {
-       TEGRA_PIN_PU1,
-};
-
-static const unsigned pu2_pins[] = {
-       TEGRA_PIN_PU2,
-};
-
-static const unsigned pu3_pins[] = {
-       TEGRA_PIN_PU3,
-};
-
-static const unsigned pu4_pins[] = {
-       TEGRA_PIN_PU4,
-};
-
-static const unsigned pu5_pins[] = {
-       TEGRA_PIN_PU5,
-};
-
-static const unsigned pu6_pins[] = {
-       TEGRA_PIN_PU6,
-};
-
-static const unsigned pv0_pins[] = {
-       TEGRA_PIN_PV0,
-};
-
-static const unsigned pv1_pins[] = {
-       TEGRA_PIN_PV1,
-};
-
-static const unsigned sdmmc3_cd_n_pv2_pins[] = {
-       TEGRA_PIN_SDMMC3_CD_N_PV2,
-};
-
-static const unsigned sdmmc1_wp_n_pv3_pins[] = {
-       TEGRA_PIN_SDMMC1_WP_N_PV3,
-};
-
-static const unsigned ddc_scl_pv4_pins[] = {
-       TEGRA_PIN_DDC_SCL_PV4,
-};
-
-static const unsigned ddc_sda_pv5_pins[] = {
-       TEGRA_PIN_DDC_SDA_PV5,
-};
-
-static const unsigned gpio_w2_aud_pw2_pins[] = {
-       TEGRA_PIN_GPIO_W2_AUD_PW2,
-};
-
-static const unsigned gpio_w3_aud_pw3_pins[] = {
-       TEGRA_PIN_GPIO_W3_AUD_PW3,
-};
-
-static const unsigned dap_mclk1_pw4_pins[] = {
-       TEGRA_PIN_DAP_MCLK1_PW4,
-};
-
-static const unsigned clk2_out_pw5_pins[] = {
-       TEGRA_PIN_CLK2_OUT_PW5,
-};
-
-static const unsigned uart3_txd_pw6_pins[] = {
-       TEGRA_PIN_UART3_TXD_PW6,
-};
-
-static const unsigned uart3_rxd_pw7_pins[] = {
-       TEGRA_PIN_UART3_RXD_PW7,
-};
-
-static const unsigned dvfs_pwm_px0_pins[] = {
-       TEGRA_PIN_DVFS_PWM_PX0,
-};
-
-static const unsigned gpio_x1_aud_px1_pins[] = {
-       TEGRA_PIN_GPIO_X1_AUD_PX1,
-};
-
-static const unsigned dvfs_clk_px2_pins[] = {
-       TEGRA_PIN_DVFS_CLK_PX2,
-};
-
-static const unsigned gpio_x3_aud_px3_pins[] = {
-       TEGRA_PIN_GPIO_X3_AUD_PX3,
-};
-
-static const unsigned gpio_x4_aud_px4_pins[] = {
-       TEGRA_PIN_GPIO_X4_AUD_PX4,
-};
-
-static const unsigned gpio_x5_aud_px5_pins[] = {
-       TEGRA_PIN_GPIO_X5_AUD_PX5,
-};
-
-static const unsigned gpio_x6_aud_px6_pins[] = {
-       TEGRA_PIN_GPIO_X6_AUD_PX6,
-};
-
-static const unsigned gpio_x7_aud_px7_pins[] = {
-       TEGRA_PIN_GPIO_X7_AUD_PX7,
-};
-
-static const unsigned ulpi_clk_py0_pins[] = {
-       TEGRA_PIN_ULPI_CLK_PY0,
-};
-
-static const unsigned ulpi_dir_py1_pins[] = {
-       TEGRA_PIN_ULPI_DIR_PY1,
-};
-
-static const unsigned ulpi_nxt_py2_pins[] = {
-       TEGRA_PIN_ULPI_NXT_PY2,
-};
-
-static const unsigned ulpi_stp_py3_pins[] = {
-       TEGRA_PIN_ULPI_STP_PY3,
-};
-
-static const unsigned sdmmc1_dat3_py4_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT3_PY4,
-};
-
-static const unsigned sdmmc1_dat2_py5_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT2_PY5,
-};
-
-static const unsigned sdmmc1_dat1_py6_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT1_PY6,
-};
-
-static const unsigned sdmmc1_dat0_py7_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT0_PY7,
-};
-
-static const unsigned sdmmc1_clk_pz0_pins[] = {
-       TEGRA_PIN_SDMMC1_CLK_PZ0,
-};
-
-static const unsigned sdmmc1_cmd_pz1_pins[] = {
-       TEGRA_PIN_SDMMC1_CMD_PZ1,
-};
-
-static const unsigned pwr_i2c_scl_pz6_pins[] = {
-       TEGRA_PIN_PWR_I2C_SCL_PZ6,
-};
-
-static const unsigned pwr_i2c_sda_pz7_pins[] = {
-       TEGRA_PIN_PWR_I2C_SDA_PZ7,
-};
-
-static const unsigned sdmmc4_dat0_paa0_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT0_PAA0,
-};
-
-static const unsigned sdmmc4_dat1_paa1_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT1_PAA1,
-};
-
-static const unsigned sdmmc4_dat2_paa2_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT2_PAA2,
-};
-
-static const unsigned sdmmc4_dat3_paa3_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT3_PAA3,
-};
-
-static const unsigned sdmmc4_dat4_paa4_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT4_PAA4,
-};
-
-static const unsigned sdmmc4_dat5_paa5_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT5_PAA5,
-};
-
-static const unsigned sdmmc4_dat6_paa6_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT6_PAA6,
-};
-
-static const unsigned sdmmc4_dat7_paa7_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT7_PAA7,
-};
-
-static const unsigned pbb0_pins[] = {
-       TEGRA_PIN_PBB0,
-};
-
-static const unsigned cam_i2c_scl_pbb1_pins[] = {
-       TEGRA_PIN_CAM_I2C_SCL_PBB1,
-};
-
-static const unsigned cam_i2c_sda_pbb2_pins[] = {
-       TEGRA_PIN_CAM_I2C_SDA_PBB2,
-};
-
-static const unsigned pbb3_pins[] = {
-       TEGRA_PIN_PBB3,
-};
-
-static const unsigned pbb4_pins[] = {
-       TEGRA_PIN_PBB4,
-};
-
-static const unsigned pbb5_pins[] = {
-       TEGRA_PIN_PBB5,
-};
-
-static const unsigned pbb6_pins[] = {
-       TEGRA_PIN_PBB6,
-};
-
-static const unsigned pbb7_pins[] = {
-       TEGRA_PIN_PBB7,
-};
-
-static const unsigned cam_mclk_pcc0_pins[] = {
-       TEGRA_PIN_CAM_MCLK_PCC0,
-};
-
-static const unsigned pcc1_pins[] = {
-       TEGRA_PIN_PCC1,
-};
-
-static const unsigned pcc2_pins[] = {
-       TEGRA_PIN_PCC2,
-};
-
-static const unsigned sdmmc4_clk_pcc4_pins[] = {
-       TEGRA_PIN_SDMMC4_CLK_PCC4,
-};
-
-static const unsigned clk2_req_pcc5_pins[] = {
-       TEGRA_PIN_CLK2_REQ_PCC5,
-};
-
-static const unsigned pex_l0_rst_n_pdd1_pins[] = {
-       TEGRA_PIN_PEX_L0_RST_N_PDD1,
-};
-
-static const unsigned pex_l0_clkreq_n_pdd2_pins[] = {
-       TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2,
-};
-
-static const unsigned pex_wake_n_pdd3_pins[] = {
-       TEGRA_PIN_PEX_WAKE_N_PDD3,
-};
-
-static const unsigned pex_l1_rst_n_pdd5_pins[] = {
-       TEGRA_PIN_PEX_L1_RST_N_PDD5,
-};
-
-static const unsigned pex_l1_clkreq_n_pdd6_pins[] = {
-       TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6,
-};
-
-static const unsigned clk3_out_pee0_pins[] = {
-       TEGRA_PIN_CLK3_OUT_PEE0,
-};
-
-static const unsigned clk3_req_pee1_pins[] = {
-       TEGRA_PIN_CLK3_REQ_PEE1,
-};
-
-static const unsigned dap_mclk1_req_pee2_pins[] = {
-       TEGRA_PIN_DAP_MCLK1_REQ_PEE2,
-};
-
-static const unsigned hdmi_cec_pee3_pins[] = {
-       TEGRA_PIN_HDMI_CEC_PEE3,
-};
-
-static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4,
-};
-
-static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5,
-};
-
-static const unsigned dp_hpd_pff0_pins[] = {
-       TEGRA_PIN_DP_HPD_PFF0,
-};
-
-static const unsigned usb_vbus_en2_pff1_pins[] = {
-       TEGRA_PIN_USB_VBUS_EN2_PFF1,
-};
-
-static const unsigned pff2_pins[] = {
-       TEGRA_PIN_PFF2,
-};
-
-static const unsigned core_pwr_req_pins[] = {
-       TEGRA_PIN_CORE_PWR_REQ,
-};
-
-static const unsigned cpu_pwr_req_pins[] = {
-       TEGRA_PIN_CPU_PWR_REQ,
-};
-
-static const unsigned pwr_int_n_pins[] = {
-       TEGRA_PIN_PWR_INT_N,
-};
-
-static const unsigned gmi_clk_lb_pins[] = {
-       TEGRA_PIN_GMI_CLK_LB,
-};
-
-static const unsigned reset_out_n_pins[] = {
-       TEGRA_PIN_RESET_OUT_N,
-};
-
-static const unsigned owr_pins[] = {
-       TEGRA_PIN_OWR,
-};
-
-static const unsigned clk_32k_in_pins[] = {
-       TEGRA_PIN_CLK_32K_IN,
-};
-
-static const unsigned jtag_rtck_pins[] = {
-       TEGRA_PIN_JTAG_RTCK,
-};
-
-static const unsigned drive_ao1_pins[] = {
-       TEGRA_PIN_KB_ROW0_PR0,
-       TEGRA_PIN_KB_ROW1_PR1,
-       TEGRA_PIN_KB_ROW2_PR2,
-       TEGRA_PIN_KB_ROW3_PR3,
-       TEGRA_PIN_KB_ROW4_PR4,
-       TEGRA_PIN_KB_ROW5_PR5,
-       TEGRA_PIN_KB_ROW6_PR6,
-       TEGRA_PIN_KB_ROW7_PR7,
-       TEGRA_PIN_PWR_I2C_SCL_PZ6,
-       TEGRA_PIN_PWR_I2C_SDA_PZ7,
-};
-
-static const unsigned drive_ao2_pins[] = {
-       TEGRA_PIN_CLK_32K_OUT_PA0,
-       TEGRA_PIN_CLK_32K_IN,
-       TEGRA_PIN_KB_COL0_PQ0,
-       TEGRA_PIN_KB_COL1_PQ1,
-       TEGRA_PIN_KB_COL2_PQ2,
-       TEGRA_PIN_KB_COL3_PQ3,
-       TEGRA_PIN_KB_COL4_PQ4,
-       TEGRA_PIN_KB_COL5_PQ5,
-       TEGRA_PIN_KB_COL6_PQ6,
-       TEGRA_PIN_KB_COL7_PQ7,
-       TEGRA_PIN_KB_ROW8_PS0,
-       TEGRA_PIN_KB_ROW9_PS1,
-       TEGRA_PIN_KB_ROW10_PS2,
-       TEGRA_PIN_KB_ROW11_PS3,
-       TEGRA_PIN_KB_ROW12_PS4,
-       TEGRA_PIN_KB_ROW13_PS5,
-       TEGRA_PIN_KB_ROW14_PS6,
-       TEGRA_PIN_KB_ROW15_PS7,
-       TEGRA_PIN_KB_ROW16_PT0,
-       TEGRA_PIN_KB_ROW17_PT1,
-       TEGRA_PIN_SDMMC3_CD_N_PV2,
-       TEGRA_PIN_CORE_PWR_REQ,
-       TEGRA_PIN_CPU_PWR_REQ,
-       TEGRA_PIN_PWR_INT_N,
-};
-
-static const unsigned drive_at1_pins[] = {
-       TEGRA_PIN_PH0,
-       TEGRA_PIN_PH1,
-       TEGRA_PIN_PH2,
-       TEGRA_PIN_PH3,
-};
-
-static const unsigned drive_at2_pins[] = {
-       TEGRA_PIN_PG0,
-       TEGRA_PIN_PG1,
-       TEGRA_PIN_PG2,
-       TEGRA_PIN_PG3,
-       TEGRA_PIN_PG4,
-       TEGRA_PIN_PG5,
-       TEGRA_PIN_PG6,
-       TEGRA_PIN_PG7,
-       TEGRA_PIN_PI0,
-       TEGRA_PIN_PI1,
-       TEGRA_PIN_PI3,
-       TEGRA_PIN_PI4,
-       TEGRA_PIN_PI7,
-       TEGRA_PIN_PK0,
-       TEGRA_PIN_PK2,
-};
-
-static const unsigned drive_at3_pins[] = {
-       TEGRA_PIN_PC7,
-       TEGRA_PIN_PJ0,
-};
-
-static const unsigned drive_at4_pins[] = {
-       TEGRA_PIN_PB0,
-       TEGRA_PIN_PB1,
-       TEGRA_PIN_PJ0,
-       TEGRA_PIN_PJ7,
-       TEGRA_PIN_PK7,
-};
-
-static const unsigned drive_at5_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SCL_PT5,
-       TEGRA_PIN_GEN2_I2C_SDA_PT6,
-};
-
-static const unsigned drive_cdev1_pins[] = {
-       TEGRA_PIN_DAP_MCLK1_PW4,
-       TEGRA_PIN_DAP_MCLK1_REQ_PEE2,
-};
-
-static const unsigned drive_cdev2_pins[] = {
-       TEGRA_PIN_CLK2_OUT_PW5,
-       TEGRA_PIN_CLK2_REQ_PCC5,
-};
-
-static const unsigned drive_dap1_pins[] = {
-       TEGRA_PIN_DAP1_FS_PN0,
-       TEGRA_PIN_DAP1_DIN_PN1,
-       TEGRA_PIN_DAP1_DOUT_PN2,
-       TEGRA_PIN_DAP1_SCLK_PN3,
-};
-
-static const unsigned drive_dap2_pins[] = {
-       TEGRA_PIN_DAP2_FS_PA2,
-       TEGRA_PIN_DAP2_SCLK_PA3,
-       TEGRA_PIN_DAP2_DIN_PA4,
-       TEGRA_PIN_DAP2_DOUT_PA5,
-};
-
-static const unsigned drive_dap3_pins[] = {
-       TEGRA_PIN_DAP3_FS_PP0,
-       TEGRA_PIN_DAP3_DIN_PP1,
-       TEGRA_PIN_DAP3_DOUT_PP2,
-       TEGRA_PIN_DAP3_SCLK_PP3,
-};
-
-static const unsigned drive_dap4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PP4,
-       TEGRA_PIN_DAP4_DIN_PP5,
-       TEGRA_PIN_DAP4_DOUT_PP6,
-       TEGRA_PIN_DAP4_SCLK_PP7,
-};
-
-static const unsigned drive_dbg_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SCL_PC4,
-       TEGRA_PIN_GEN1_I2C_SDA_PC5,
-       TEGRA_PIN_PU0,
-       TEGRA_PIN_PU1,
-       TEGRA_PIN_PU2,
-       TEGRA_PIN_PU3,
-       TEGRA_PIN_PU4,
-       TEGRA_PIN_PU5,
-       TEGRA_PIN_PU6,
-};
-
-static const unsigned drive_sdio3_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_PA6,
-       TEGRA_PIN_SDMMC3_CMD_PA7,
-       TEGRA_PIN_SDMMC3_DAT3_PB4,
-       TEGRA_PIN_SDMMC3_DAT2_PB5,
-       TEGRA_PIN_SDMMC3_DAT1_PB6,
-       TEGRA_PIN_SDMMC3_DAT0_PB7,
-       TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4,
-       TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5,
-};
-
-static const unsigned drive_spi_pins[] = {
-       TEGRA_PIN_DVFS_PWM_PX0,
-       TEGRA_PIN_GPIO_X1_AUD_PX1,
-       TEGRA_PIN_DVFS_CLK_PX2,
-       TEGRA_PIN_GPIO_X3_AUD_PX3,
-       TEGRA_PIN_GPIO_X4_AUD_PX4,
-       TEGRA_PIN_GPIO_X5_AUD_PX5,
-       TEGRA_PIN_GPIO_X6_AUD_PX6,
-       TEGRA_PIN_GPIO_X7_AUD_PX7,
-       TEGRA_PIN_GPIO_W2_AUD_PW2,
-       TEGRA_PIN_GPIO_W3_AUD_PW3,
-};
-
-static const unsigned drive_uaa_pins[] = {
-       TEGRA_PIN_ULPI_DATA0_PO1,
-       TEGRA_PIN_ULPI_DATA1_PO2,
-       TEGRA_PIN_ULPI_DATA2_PO3,
-       TEGRA_PIN_ULPI_DATA3_PO4,
-};
-
-static const unsigned drive_uab_pins[] = {
-       TEGRA_PIN_ULPI_DATA7_PO0,
-       TEGRA_PIN_ULPI_DATA4_PO5,
-       TEGRA_PIN_ULPI_DATA5_PO6,
-       TEGRA_PIN_ULPI_DATA6_PO7,
-       TEGRA_PIN_PV0,
-       TEGRA_PIN_PV1,
-};
-
-static const unsigned drive_uart2_pins[] = {
-       TEGRA_PIN_UART2_TXD_PC2,
-       TEGRA_PIN_UART2_RXD_PC3,
-       TEGRA_PIN_UART2_CTS_N_PJ5,
-       TEGRA_PIN_UART2_RTS_N_PJ6,
-};
-
-static const unsigned drive_uart3_pins[] = {
-       TEGRA_PIN_UART3_CTS_N_PA1,
-       TEGRA_PIN_UART3_RTS_N_PC0,
-       TEGRA_PIN_UART3_TXD_PW6,
-       TEGRA_PIN_UART3_RXD_PW7,
-};
-
-static const unsigned drive_sdio1_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT3_PY4,
-       TEGRA_PIN_SDMMC1_DAT2_PY5,
-       TEGRA_PIN_SDMMC1_DAT1_PY6,
-       TEGRA_PIN_SDMMC1_DAT0_PY7,
-       TEGRA_PIN_SDMMC1_CLK_PZ0,
-       TEGRA_PIN_SDMMC1_CMD_PZ1,
-};
-
-static const unsigned drive_ddc_pins[] = {
-       TEGRA_PIN_DDC_SCL_PV4,
-       TEGRA_PIN_DDC_SDA_PV5,
-};
-
-static const unsigned drive_gma_pins[] = {
-       TEGRA_PIN_SDMMC4_CLK_PCC4,
-       TEGRA_PIN_SDMMC4_CMD_PT7,
-       TEGRA_PIN_SDMMC4_DAT0_PAA0,
-       TEGRA_PIN_SDMMC4_DAT1_PAA1,
-       TEGRA_PIN_SDMMC4_DAT2_PAA2,
-       TEGRA_PIN_SDMMC4_DAT3_PAA3,
-       TEGRA_PIN_SDMMC4_DAT4_PAA4,
-       TEGRA_PIN_SDMMC4_DAT5_PAA5,
-       TEGRA_PIN_SDMMC4_DAT6_PAA6,
-       TEGRA_PIN_SDMMC4_DAT7_PAA7,
-};
-
-static const unsigned drive_gme_pins[] = {
-       TEGRA_PIN_PBB0,
-       TEGRA_PIN_CAM_I2C_SCL_PBB1,
-       TEGRA_PIN_CAM_I2C_SDA_PBB2,
-       TEGRA_PIN_PBB3,
-       TEGRA_PIN_PCC2,
-};
-
-static const unsigned drive_gmf_pins[] = {
-       TEGRA_PIN_PBB4,
-       TEGRA_PIN_PBB5,
-       TEGRA_PIN_PBB6,
-       TEGRA_PIN_PBB7,
-};
-
-static const unsigned drive_gmg_pins[] = {
-       TEGRA_PIN_CAM_MCLK_PCC0,
-};
-
-static const unsigned drive_gmh_pins[] = {
-       TEGRA_PIN_PCC1,
-};
-
-static const unsigned drive_owr_pins[] = {
-       TEGRA_PIN_SDMMC3_CD_N_PV2,
-       TEGRA_PIN_OWR,
-};
-
-static const unsigned drive_uda_pins[] = {
-       TEGRA_PIN_ULPI_CLK_PY0,
-       TEGRA_PIN_ULPI_DIR_PY1,
-       TEGRA_PIN_ULPI_NXT_PY2,
-       TEGRA_PIN_ULPI_STP_PY3,
-};
-
-static const unsigned drive_gpv_pins[] = {
-       TEGRA_PIN_PEX_L0_RST_N_PDD1,
-       TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2,
-       TEGRA_PIN_PEX_WAKE_N_PDD3,
-       TEGRA_PIN_PEX_L1_RST_N_PDD5,
-       TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6,
-       TEGRA_PIN_USB_VBUS_EN2_PFF1,
-       TEGRA_PIN_PFF2,
-};
-
-static const unsigned drive_dev3_pins[] = {
-       TEGRA_PIN_CLK3_OUT_PEE0,
-       TEGRA_PIN_CLK3_REQ_PEE1,
-};
-
-static const unsigned drive_cec_pins[] = {
-       TEGRA_PIN_HDMI_CEC_PEE3,
-};
-
-static const unsigned drive_at6_pins[] = {
-       TEGRA_PIN_PK1,
-       TEGRA_PIN_PK3,
-       TEGRA_PIN_PK4,
-       TEGRA_PIN_PI2,
-       TEGRA_PIN_PI5,
-       TEGRA_PIN_PI6,
-       TEGRA_PIN_PH4,
-       TEGRA_PIN_PH5,
-       TEGRA_PIN_PH6,
-       TEGRA_PIN_PH7,
-};
-
-static const unsigned drive_dap5_pins[] = {
-       TEGRA_PIN_SPDIF_IN_PK6,
-       TEGRA_PIN_SPDIF_OUT_PK5,
-       TEGRA_PIN_DP_HPD_PFF0,
-};
-
-static const unsigned drive_usb_vbus_en_pins[] = {
-       TEGRA_PIN_USB_VBUS_EN0_PN4,
-       TEGRA_PIN_USB_VBUS_EN1_PN5,
-};
-
-static const unsigned drive_ao3_pins[] = {
-       TEGRA_PIN_RESET_OUT_N,
-};
-
-static const unsigned drive_ao0_pins[] = {
-       TEGRA_PIN_JTAG_RTCK,
-};
-
-static const unsigned drive_hv0_pins[] = {
-       TEGRA_PIN_HDMI_INT_PN7,
-};
-
-static const unsigned drive_sdio4_pins[] = {
-       TEGRA_PIN_SDMMC1_WP_N_PV3,
-};
-
-static const unsigned drive_ao4_pins[] = {
-       TEGRA_PIN_JTAG_RTCK,
-};
-
-static const unsigned mipi_pad_ctrl_dsi_b_pins[] = {
-       TEGRA_PIN_DSI_B_CLK_P,
-       TEGRA_PIN_DSI_B_CLK_N,
-       TEGRA_PIN_DSI_B_D0_P,
-       TEGRA_PIN_DSI_B_D0_N,
-       TEGRA_PIN_DSI_B_D1_P,
-       TEGRA_PIN_DSI_B_D1_N,
-       TEGRA_PIN_DSI_B_D2_P,
-       TEGRA_PIN_DSI_B_D2_N,
-       TEGRA_PIN_DSI_B_D3_P,
-       TEGRA_PIN_DSI_B_D3_N,
-};
-
-enum tegra_mux {
-       TEGRA_MUX_BLINK,
-       TEGRA_MUX_CCLA,
-       TEGRA_MUX_CEC,
-       TEGRA_MUX_CLDVFS,
-       TEGRA_MUX_CLK,
-       TEGRA_MUX_CLK12,
-       TEGRA_MUX_CPU,
-       TEGRA_MUX_CSI,
-       TEGRA_MUX_DAP,
-       TEGRA_MUX_DAP1,
-       TEGRA_MUX_DAP2,
-       TEGRA_MUX_DEV3,
-       TEGRA_MUX_DISPLAYA,
-       TEGRA_MUX_DISPLAYA_ALT,
-       TEGRA_MUX_DISPLAYB,
-       TEGRA_MUX_DP,
-       TEGRA_MUX_DSI_B,
-       TEGRA_MUX_DTV,
-       TEGRA_MUX_EXTPERIPH1,
-       TEGRA_MUX_EXTPERIPH2,
-       TEGRA_MUX_EXTPERIPH3,
-       TEGRA_MUX_GMI,
-       TEGRA_MUX_GMI_ALT,
-       TEGRA_MUX_HDA,
-       TEGRA_MUX_HSI,
-       TEGRA_MUX_I2C1,
-       TEGRA_MUX_I2C2,
-       TEGRA_MUX_I2C3,
-       TEGRA_MUX_I2C4,
-       TEGRA_MUX_I2CPWR,
-       TEGRA_MUX_I2S0,
-       TEGRA_MUX_I2S1,
-       TEGRA_MUX_I2S2,
-       TEGRA_MUX_I2S3,
-       TEGRA_MUX_I2S4,
-       TEGRA_MUX_IRDA,
-       TEGRA_MUX_KBC,
-       TEGRA_MUX_OWR,
-       TEGRA_MUX_PE,
-       TEGRA_MUX_PE0,
-       TEGRA_MUX_PE1,
-       TEGRA_MUX_PMI,
-       TEGRA_MUX_PWM0,
-       TEGRA_MUX_PWM1,
-       TEGRA_MUX_PWM2,
-       TEGRA_MUX_PWM3,
-       TEGRA_MUX_PWRON,
-       TEGRA_MUX_RESET_OUT_N,
-       TEGRA_MUX_RSVD1,
-       TEGRA_MUX_RSVD2,
-       TEGRA_MUX_RSVD3,
-       TEGRA_MUX_RSVD4,
-       TEGRA_MUX_RTCK,
-       TEGRA_MUX_SATA,
-       TEGRA_MUX_SDMMC1,
-       TEGRA_MUX_SDMMC2,
-       TEGRA_MUX_SDMMC3,
-       TEGRA_MUX_SDMMC4,
-       TEGRA_MUX_SOC,
-       TEGRA_MUX_SPDIF,
-       TEGRA_MUX_SPI1,
-       TEGRA_MUX_SPI2,
-       TEGRA_MUX_SPI3,
-       TEGRA_MUX_SPI4,
-       TEGRA_MUX_SPI5,
-       TEGRA_MUX_SPI6,
-       TEGRA_MUX_SYS,
-       TEGRA_MUX_TMDS,
-       TEGRA_MUX_TRACE,
-       TEGRA_MUX_UARTA,
-       TEGRA_MUX_UARTB,
-       TEGRA_MUX_UARTC,
-       TEGRA_MUX_UARTD,
-       TEGRA_MUX_ULPI,
-       TEGRA_MUX_USB,
-       TEGRA_MUX_VGP1,
-       TEGRA_MUX_VGP2,
-       TEGRA_MUX_VGP3,
-       TEGRA_MUX_VGP4,
-       TEGRA_MUX_VGP5,
-       TEGRA_MUX_VGP6,
-       TEGRA_MUX_VI,
-       TEGRA_MUX_VI_ALT1,
-       TEGRA_MUX_VI_ALT3,
-       TEGRA_MUX_VIMCLK2,
-       TEGRA_MUX_VIMCLK2_ALT,
-};
-
-#define FUNCTION(fname)                                        \
-       {                                               \
-               .name = #fname,                         \
-       }
-
-static struct tegra_function tegra124_functions[] = {
-       FUNCTION(blink),
-       FUNCTION(ccla),
-       FUNCTION(cec),
-       FUNCTION(cldvfs),
-       FUNCTION(clk),
-       FUNCTION(clk12),
-       FUNCTION(cpu),
-       FUNCTION(csi),
-       FUNCTION(dap),
-       FUNCTION(dap1),
-       FUNCTION(dap2),
-       FUNCTION(dev3),
-       FUNCTION(displaya),
-       FUNCTION(displaya_alt),
-       FUNCTION(displayb),
-       FUNCTION(dp),
-       FUNCTION(dsi_b),
-       FUNCTION(dtv),
-       FUNCTION(extperiph1),
-       FUNCTION(extperiph2),
-       FUNCTION(extperiph3),
-       FUNCTION(gmi),
-       FUNCTION(gmi_alt),
-       FUNCTION(hda),
-       FUNCTION(hsi),
-       FUNCTION(i2c1),
-       FUNCTION(i2c2),
-       FUNCTION(i2c3),
-       FUNCTION(i2c4),
-       FUNCTION(i2cpwr),
-       FUNCTION(i2s0),
-       FUNCTION(i2s1),
-       FUNCTION(i2s2),
-       FUNCTION(i2s3),
-       FUNCTION(i2s4),
-       FUNCTION(irda),
-       FUNCTION(kbc),
-       FUNCTION(owr),
-       FUNCTION(pe),
-       FUNCTION(pe0),
-       FUNCTION(pe1),
-       FUNCTION(pmi),
-       FUNCTION(pwm0),
-       FUNCTION(pwm1),
-       FUNCTION(pwm2),
-       FUNCTION(pwm3),
-       FUNCTION(pwron),
-       FUNCTION(reset_out_n),
-       FUNCTION(rsvd1),
-       FUNCTION(rsvd2),
-       FUNCTION(rsvd3),
-       FUNCTION(rsvd4),
-       FUNCTION(rtck),
-       FUNCTION(sata),
-       FUNCTION(sdmmc1),
-       FUNCTION(sdmmc2),
-       FUNCTION(sdmmc3),
-       FUNCTION(sdmmc4),
-       FUNCTION(soc),
-       FUNCTION(spdif),
-       FUNCTION(spi1),
-       FUNCTION(spi2),
-       FUNCTION(spi3),
-       FUNCTION(spi4),
-       FUNCTION(spi5),
-       FUNCTION(spi6),
-       FUNCTION(sys),
-       FUNCTION(tmds),
-       FUNCTION(trace),
-       FUNCTION(uarta),
-       FUNCTION(uartb),
-       FUNCTION(uartc),
-       FUNCTION(uartd),
-       FUNCTION(ulpi),
-       FUNCTION(usb),
-       FUNCTION(vgp1),
-       FUNCTION(vgp2),
-       FUNCTION(vgp3),
-       FUNCTION(vgp4),
-       FUNCTION(vgp5),
-       FUNCTION(vgp6),
-       FUNCTION(vi),
-       FUNCTION(vi_alt1),
-       FUNCTION(vi_alt3),
-       FUNCTION(vimclk2),
-       FUNCTION(vimclk2_alt),
-};
-
-#define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
-#define PINGROUP_REG_A                 0x3000  /* bank 1 */
-#define MIPI_PAD_CTRL_PINGROUP_REG_A   0x820   /* bank 2 */
-
-#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
-#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
-#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r)        ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A)
-
-#define PINGROUP_BIT_Y(b)              (b)
-#define PINGROUP_BIT_N(b)              (-1)
-
-#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel)         \
-       {                                                               \
-               .name = #pg_name,                                       \
-               .pins = pg_name##_pins,                                 \
-               .npins = ARRAY_SIZE(pg_name##_pins),                    \
-               .funcs = {                                              \
-                       TEGRA_MUX_##f0,                                 \
-                       TEGRA_MUX_##f1,                                 \
-                       TEGRA_MUX_##f2,                                 \
-                       TEGRA_MUX_##f3,                                 \
-               },                                                      \
-               .mux_reg = PINGROUP_REG(r),                             \
-               .mux_bank = 1,                                          \
-               .mux_bit = 0,                                           \
-               .pupd_reg = PINGROUP_REG(r),                            \
-               .pupd_bank = 1,                                         \
-               .pupd_bit = 2,                                          \
-               .tri_reg = PINGROUP_REG(r),                             \
-               .tri_bank = 1,                                          \
-               .tri_bit = 4,                                           \
-               .einput_bit = 5,                                        \
-               .odrain_bit = PINGROUP_BIT_##od(6),                     \
-               .lock_bit = 7,                                          \
-               .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
-               .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9),               \
-               .drv_reg = -1,                                          \
-       }
-
-#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
-                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
-                    slwf_b, slwf_w, drvtype)                           \
-       {                                                               \
-               .name = "drive_" #pg_name,                              \
-               .pins = drive_##pg_name##_pins,                         \
-               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
-               .mux_reg = -1,                                          \
-               .pupd_reg = -1,                                         \
-               .tri_reg = -1,                                          \
-               .einput_bit = -1,                                       \
-               .odrain_bit = -1,                                       \
-               .lock_bit = -1,                                         \
-               .ioreset_bit = -1,                                      \
-               .rcv_sel_bit = -1,                                      \
-               .drv_reg = DRV_PINGROUP_REG(r),                         \
-               .drv_bank = 0,                                          \
-               .hsm_bit = hsm_b,                                       \
-               .schmitt_bit = schmitt_b,                               \
-               .lpmd_bit = lpmd_b,                                     \
-               .drvdn_bit = drvdn_b,                                   \
-               .drvdn_width = drvdn_w,                                 \
-               .drvup_bit = drvup_b,                                   \
-               .drvup_width = drvup_w,                                 \
-               .slwr_bit = slwr_b,                                     \
-               .slwr_width = slwr_w,                                   \
-               .slwf_bit = slwf_b,                                     \
-               .slwf_width = slwf_w,                                   \
-               .drvtype_bit = PINGROUP_BIT_##drvtype(6),               \
-       }
-
-#define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1)                  \
-       {                                                               \
-               .name = "mipi_pad_ctrl_" #pg_name,                      \
-               .pins = mipi_pad_ctrl_##pg_name##_pins,                 \
-               .npins = ARRAY_SIZE(mipi_pad_ctrl_##pg_name##_pins),    \
-               .funcs = {                                              \
-                       TEGRA_MUX_ ## f0,                               \
-                       TEGRA_MUX_ ## f1,                               \
-                       TEGRA_MUX_RSVD3,                                \
-                       TEGRA_MUX_RSVD4,                                \
-               },                                                      \
-               .mux_reg = MIPI_PAD_CTRL_PINGROUP_REG_Y(r),             \
-               .mux_bank = 2,                                          \
-               .mux_bit = b,                                           \
-               .pupd_reg = -1,                                         \
-               .tri_reg = -1,                                          \
-               .einput_bit = -1,                                       \
-               .odrain_bit = -1,                                       \
-               .lock_bit = -1,                                         \
-               .ioreset_bit = -1,                                      \
-               .rcv_sel_bit = -1,                                      \
-               .drv_reg = -1,                                          \
-       }
-
-static const struct tegra_pingroup tegra124_groups[] = {
-       /*       pg_name,                f0,         f1,         f2,           f3,          r,      od, ior, rcv_sel */
-       PINGROUP(ulpi_data0_po1,         SPI3,       HSI,        UARTA,        ULPI,        0x3000, N,   N,  N),
-       PINGROUP(ulpi_data1_po2,         SPI3,       HSI,        UARTA,        ULPI,        0x3004, N,   N,  N),
-       PINGROUP(ulpi_data2_po3,         SPI3,       HSI,        UARTA,        ULPI,        0x3008, N,   N,  N),
-       PINGROUP(ulpi_data3_po4,         SPI3,       HSI,        UARTA,        ULPI,        0x300c, N,   N,  N),
-       PINGROUP(ulpi_data4_po5,         SPI2,       HSI,        UARTA,        ULPI,        0x3010, N,   N,  N),
-       PINGROUP(ulpi_data5_po6,         SPI2,       HSI,        UARTA,        ULPI,        0x3014, N,   N,  N),
-       PINGROUP(ulpi_data6_po7,         SPI2,       HSI,        UARTA,        ULPI,        0x3018, N,   N,  N),
-       PINGROUP(ulpi_data7_po0,         SPI2,       HSI,        UARTA,        ULPI,        0x301c, N,   N,  N),
-       PINGROUP(ulpi_clk_py0,           SPI1,       SPI5,       UARTD,        ULPI,        0x3020, N,   N,  N),
-       PINGROUP(ulpi_dir_py1,           SPI1,       SPI5,       UARTD,        ULPI,        0x3024, N,   N,  N),
-       PINGROUP(ulpi_nxt_py2,           SPI1,       SPI5,       UARTD,        ULPI,        0x3028, N,   N,  N),
-       PINGROUP(ulpi_stp_py3,           SPI1,       SPI5,       UARTD,        ULPI,        0x302c, N,   N,  N),
-       PINGROUP(dap3_fs_pp0,            I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3030, N,   N,  N),
-       PINGROUP(dap3_din_pp1,           I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3034, N,   N,  N),
-       PINGROUP(dap3_dout_pp2,          I2S2,       SPI5,       DISPLAYA,     RSVD4,       0x3038, N,   N,  N),
-       PINGROUP(dap3_sclk_pp3,          I2S2,       SPI5,       RSVD3,        DISPLAYB,    0x303c, N,   N,  N),
-       PINGROUP(pv0,                    RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3040, N,   N,  N),
-       PINGROUP(pv1,                    RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3044, N,   N,  N),
-       PINGROUP(sdmmc1_clk_pz0,         SDMMC1,     CLK12,      RSVD3,        RSVD4,       0x3048, N,   N,  N),
-       PINGROUP(sdmmc1_cmd_pz1,         SDMMC1,     SPDIF,      SPI4,         UARTA,       0x304c, N,   N,  N),
-       PINGROUP(sdmmc1_dat3_py4,        SDMMC1,     SPDIF,      SPI4,         UARTA,       0x3050, N,   N,  N),
-       PINGROUP(sdmmc1_dat2_py5,        SDMMC1,     PWM0,       SPI4,         UARTA,       0x3054, N,   N,  N),
-       PINGROUP(sdmmc1_dat1_py6,        SDMMC1,     PWM1,       SPI4,         UARTA,       0x3058, N,   N,  N),
-       PINGROUP(sdmmc1_dat0_py7,        SDMMC1,     RSVD2,      SPI4,         UARTA,       0x305c, N,   N,  N),
-       PINGROUP(clk2_out_pw5,           EXTPERIPH2, RSVD2,      RSVD3,        RSVD4,       0x3068, N,   N,  N),
-       PINGROUP(clk2_req_pcc5,          DAP,        RSVD2,      RSVD3,        RSVD4,       0x306c, N,   N,  N),
-       PINGROUP(hdmi_int_pn7,           RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3110, N,   N,  Y),
-       PINGROUP(ddc_scl_pv4,            I2C4,       RSVD2,      RSVD3,        RSVD4,       0x3114, N,   N,  Y),
-       PINGROUP(ddc_sda_pv5,            I2C4,       RSVD2,      RSVD3,        RSVD4,       0x3118, N,   N,  Y),
-       PINGROUP(uart2_rxd_pc3,          IRDA,       SPDIF,      UARTA,        SPI4,        0x3164, N,   N,  N),
-       PINGROUP(uart2_txd_pc2,          IRDA,       SPDIF,      UARTA,        SPI4,        0x3168, N,   N,  N),
-       PINGROUP(uart2_rts_n_pj6,        UARTA,      UARTB,      GMI,          SPI4,        0x316c, N,   N,  N),
-       PINGROUP(uart2_cts_n_pj5,        UARTA,      UARTB,      GMI,          SPI4,        0x3170, N,   N,  N),
-       PINGROUP(uart3_txd_pw6,          UARTC,      RSVD2,      GMI,          SPI4,        0x3174, N,   N,  N),
-       PINGROUP(uart3_rxd_pw7,          UARTC,      RSVD2,      GMI,          SPI4,        0x3178, N,   N,  N),
-       PINGROUP(uart3_cts_n_pa1,        UARTC,      SDMMC1,     DTV,          GMI,         0x317c, N,   N,  N),
-       PINGROUP(uart3_rts_n_pc0,        UARTC,      PWM0,       DTV,          GMI,         0x3180, N,   N,  N),
-       PINGROUP(pu0,                    OWR,        UARTA,      GMI,          RSVD4,       0x3184, N,   N,  N),
-       PINGROUP(pu1,                    RSVD1,      UARTA,      GMI,          RSVD4,       0x3188, N,   N,  N),
-       PINGROUP(pu2,                    RSVD1,      UARTA,      GMI,          RSVD4,       0x318c, N,   N,  N),
-       PINGROUP(pu3,                    PWM0,       UARTA,      GMI,          DISPLAYB,    0x3190, N,   N,  N),
-       PINGROUP(pu4,                    PWM1,       UARTA,      GMI,          DISPLAYB,    0x3194, N,   N,  N),
-       PINGROUP(pu5,                    PWM2,       UARTA,      GMI,          DISPLAYB,    0x3198, N,   N,  N),
-       PINGROUP(pu6,                    PWM3,       UARTA,      RSVD3,        GMI,         0x319c, N,   N,  N),
-       PINGROUP(gen1_i2c_sda_pc5,       I2C1,       RSVD2,      RSVD3,        RSVD4,       0x31a0, Y,   N,  N),
-       PINGROUP(gen1_i2c_scl_pc4,       I2C1,       RSVD2,      RSVD3,        RSVD4,       0x31a4, Y,   N,  N),
-       PINGROUP(dap4_fs_pp4,            I2S3,       GMI,        DTV,          RSVD4,       0x31a8, N,   N,  N),
-       PINGROUP(dap4_din_pp5,           I2S3,       GMI,        RSVD3,        RSVD4,       0x31ac, N,   N,  N),
-       PINGROUP(dap4_dout_pp6,          I2S3,       GMI,        DTV,          RSVD4,       0x31b0, N,   N,  N),
-       PINGROUP(dap4_sclk_pp7,          I2S3,       GMI,        RSVD3,        RSVD4,       0x31b4, N,   N,  N),
-       PINGROUP(clk3_out_pee0,          EXTPERIPH3, RSVD2,      RSVD3,        RSVD4,       0x31b8, N,   N,  N),
-       PINGROUP(clk3_req_pee1,          DEV3,       RSVD2,      RSVD3,        RSVD4,       0x31bc, N,   N,  N),
-       PINGROUP(pc7,                    RSVD1,      RSVD2,      GMI,          GMI_ALT,     0x31c0, N,   N,  N),
-       PINGROUP(pi5,                    SDMMC2,     RSVD2,      GMI,          RSVD4,       0x31c4, N,   N,  N),
-       PINGROUP(pi7,                    RSVD1,      TRACE,      GMI,          DTV,         0x31c8, N,   N,  N),
-       PINGROUP(pk0,                    RSVD1,      SDMMC3,     GMI,          SOC,         0x31cc, N,   N,  N),
-       PINGROUP(pk1,                    SDMMC2,     TRACE,      GMI,          RSVD4,       0x31d0, N,   N,  N),
-       PINGROUP(pj0,                    RSVD1,      RSVD2,      GMI,          USB,         0x31d4, N,   N,  N),
-       PINGROUP(pj2,                    RSVD1,      RSVD2,      GMI,          SOC,         0x31d8, N,   N,  N),
-       PINGROUP(pk3,                    SDMMC2,     TRACE,      GMI,          CCLA,        0x31dc, N,   N,  N),
-       PINGROUP(pk4,                    SDMMC2,     RSVD2,      GMI,          GMI_ALT,     0x31e0, N,   N,  N),
-       PINGROUP(pk2,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x31e4, N,   N,  N),
-       PINGROUP(pi3,                    RSVD1,      RSVD2,      GMI,          SPI4,        0x31e8, N,   N,  N),
-       PINGROUP(pi6,                    RSVD1,      RSVD2,      GMI,          SDMMC2,      0x31ec, N,   N,  N),
-       PINGROUP(pg0,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x31f0, N,   N,  N),
-       PINGROUP(pg1,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x31f4, N,   N,  N),
-       PINGROUP(pg2,                    RSVD1,      TRACE,      GMI,          RSVD4,       0x31f8, N,   N,  N),
-       PINGROUP(pg3,                    RSVD1,      TRACE,      GMI,          RSVD4,       0x31fc, N,   N,  N),
-       PINGROUP(pg4,                    RSVD1,      TMDS,       GMI,          SPI4,        0x3200, N,   N,  N),
-       PINGROUP(pg5,                    RSVD1,      RSVD2,      GMI,          SPI4,        0x3204, N,   N,  N),
-       PINGROUP(pg6,                    RSVD1,      RSVD2,      GMI,          SPI4,        0x3208, N,   N,  N),
-       PINGROUP(pg7,                    RSVD1,      RSVD2,      GMI,          SPI4,        0x320c, N,   N,  N),
-       PINGROUP(ph0,                    PWM0,       TRACE,      GMI,          DTV,         0x3210, N,   N,  N),
-       PINGROUP(ph1,                    PWM1,       TMDS,       GMI,          DISPLAYA,    0x3214, N,   N,  N),
-       PINGROUP(ph2,                    PWM2,       TMDS,       GMI,          CLDVFS,      0x3218, N,   N,  N),
-       PINGROUP(ph3,                    PWM3,       SPI4,       GMI,          CLDVFS,      0x321c, N,   N,  N),
-       PINGROUP(ph4,                    SDMMC2,     RSVD2,      GMI,          RSVD4,       0x3220, N,   N,  N),
-       PINGROUP(ph5,                    SDMMC2,     RSVD2,      GMI,          RSVD4,       0x3224, N,   N,  N),
-       PINGROUP(ph6,                    SDMMC2,     TRACE,      GMI,          DTV,         0x3228, N,   N,  N),
-       PINGROUP(ph7,                    SDMMC2,     TRACE,      GMI,          DTV,         0x322c, N,   N,  N),
-       PINGROUP(pj7,                    UARTD,      RSVD2,      GMI,          GMI_ALT,     0x3230, N,   N,  N),
-       PINGROUP(pb0,                    UARTD,      RSVD2,      GMI,          RSVD4,       0x3234, N,   N,  N),
-       PINGROUP(pb1,                    UARTD,      RSVD2,      GMI,          RSVD4,       0x3238, N,   N,  N),
-       PINGROUP(pk7,                    UARTD,      RSVD2,      GMI,          RSVD4,       0x323c, N,   N,  N),
-       PINGROUP(pi0,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x3240, N,   N,  N),
-       PINGROUP(pi1,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x3244, N,   N,  N),
-       PINGROUP(pi2,                    SDMMC2,     TRACE,      GMI,          RSVD4,       0x3248, N,   N,  N),
-       PINGROUP(pi4,                    SPI4,       TRACE,      GMI,          DISPLAYA,    0x324c, N,   N,  N),
-       PINGROUP(gen2_i2c_scl_pt5,       I2C2,       RSVD2,      GMI,          RSVD4,       0x3250, Y,   N,  N),
-       PINGROUP(gen2_i2c_sda_pt6,       I2C2,       RSVD2,      GMI,          RSVD4,       0x3254, Y,   N,  N),
-       PINGROUP(sdmmc4_clk_pcc4,        SDMMC4,     RSVD2,      GMI,          RSVD4,       0x3258, N,   Y,  N),
-       PINGROUP(sdmmc4_cmd_pt7,         SDMMC4,     RSVD2,      GMI,          RSVD4,       0x325c, N,   Y,  N),
-       PINGROUP(sdmmc4_dat0_paa0,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3260, N,   Y,  N),
-       PINGROUP(sdmmc4_dat1_paa1,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3264, N,   Y,  N),
-       PINGROUP(sdmmc4_dat2_paa2,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3268, N,   Y,  N),
-       PINGROUP(sdmmc4_dat3_paa3,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x326c, N,   Y,  N),
-       PINGROUP(sdmmc4_dat4_paa4,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3270, N,   Y,  N),
-       PINGROUP(sdmmc4_dat5_paa5,       SDMMC4,     SPI3,       RSVD3,        RSVD4,       0x3274, N,   Y,  N),
-       PINGROUP(sdmmc4_dat6_paa6,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3278, N,   Y,  N),
-       PINGROUP(sdmmc4_dat7_paa7,       SDMMC4,     RSVD2,      GMI,          RSVD4,       0x327c, N,   Y,  N),
-       PINGROUP(cam_mclk_pcc0,          VI,         VI_ALT1,    VI_ALT3,      SDMMC2,      0x3284, N,   N,  N),
-       PINGROUP(pcc1,                   I2S4,       RSVD2,      RSVD3,        SDMMC2,      0x3288, N,   N,  N),
-       PINGROUP(pbb0,                   VGP6,       VIMCLK2,    SDMMC2,       VIMCLK2_ALT, 0x328c, N,   N,  N),
-       PINGROUP(cam_i2c_scl_pbb1,       VGP1,       I2C3,       RSVD3,        SDMMC2,      0x3290, Y,   N,  N),
-       PINGROUP(cam_i2c_sda_pbb2,       VGP2,       I2C3,       RSVD3,        SDMMC2,      0x3294, Y,   N,  N),
-       PINGROUP(pbb3,                   VGP3,       DISPLAYA,   DISPLAYB,     SDMMC2,      0x3298, N,   N,  N),
-       PINGROUP(pbb4,                   VGP4,       DISPLAYA,   DISPLAYB,     SDMMC2,      0x329c, N,   N,  N),
-       PINGROUP(pbb5,                   VGP5,       DISPLAYA,   RSVD3,        SDMMC2,      0x32a0, N,   N,  N),
-       PINGROUP(pbb6,                   I2S4,       RSVD2,      DISPLAYB,     SDMMC2,      0x32a4, N,   N,  N),
-       PINGROUP(pbb7,                   I2S4,       RSVD2,      RSVD3,        SDMMC2,      0x32a8, N,   N,  N),
-       PINGROUP(pcc2,                   I2S4,       RSVD2,      SDMMC3,       SDMMC2,      0x32ac, N,   N,  N),
-       PINGROUP(jtag_rtck,              RTCK,       RSVD2,      RSVD3,        RSVD4,       0x32b0, N,   N,  N),
-       PINGROUP(pwr_i2c_scl_pz6,        I2CPWR,     RSVD2,      RSVD3,        RSVD4,       0x32b4, Y,   N,  N),
-       PINGROUP(pwr_i2c_sda_pz7,        I2CPWR,     RSVD2,      RSVD3,        RSVD4,       0x32b8, Y,   N,  N),
-       PINGROUP(kb_row0_pr0,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32bc, N,   N,  N),
-       PINGROUP(kb_row1_pr1,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32c0, N,   N,  N),
-       PINGROUP(kb_row2_pr2,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32c4, N,   N,  N),
-       PINGROUP(kb_row3_pr3,            KBC,        DISPLAYA,   SYS,          DISPLAYB,    0x32c8, N,   N,  N),
-       PINGROUP(kb_row4_pr4,            KBC,        DISPLAYA,   RSVD3,        DISPLAYB,    0x32cc, N,   N,  N),
-       PINGROUP(kb_row5_pr5,            KBC,        DISPLAYA,   RSVD3,        DISPLAYB,    0x32d0, N,   N,  N),
-       PINGROUP(kb_row6_pr6,            KBC,        DISPLAYA,   DISPLAYA_ALT, DISPLAYB,    0x32d4, N,   N,  N),
-       PINGROUP(kb_row7_pr7,            KBC,        RSVD2,      CLDVFS,       UARTA,       0x32d8, N,   N,  N),
-       PINGROUP(kb_row8_ps0,            KBC,        RSVD2,      CLDVFS,       UARTA,       0x32dc, N,   N,  N),
-       PINGROUP(kb_row9_ps1,            KBC,        RSVD2,      RSVD3,        UARTA,       0x32e0, N,   N,  N),
-       PINGROUP(kb_row10_ps2,           KBC,        RSVD2,      RSVD3,        UARTA,       0x32e4, N,   N,  N),
-       PINGROUP(kb_row11_ps3,           KBC,        RSVD2,      RSVD3,        IRDA,        0x32e8, N,   N,  N),
-       PINGROUP(kb_row12_ps4,           KBC,        RSVD2,      RSVD3,        IRDA,        0x32ec, N,   N,  N),
-       PINGROUP(kb_row13_ps5,           KBC,        RSVD2,      SPI2,         RSVD4,       0x32f0, N,   N,  N),
-       PINGROUP(kb_row14_ps6,           KBC,        RSVD2,      SPI2,         RSVD4,       0x32f4, N,   N,  N),
-       PINGROUP(kb_row15_ps7,           KBC,        SOC,        RSVD3,        RSVD4,       0x32f8, N,   N,  N),
-       PINGROUP(kb_col0_pq0,            KBC,        RSVD2,      SPI2,         RSVD4,       0x32fc, N,   N,  N),
-       PINGROUP(kb_col1_pq1,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3300, N,   N,  N),
-       PINGROUP(kb_col2_pq2,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3304, N,   N,  N),
-       PINGROUP(kb_col3_pq3,            KBC,        DISPLAYA,   PWM2,         UARTA,       0x3308, N,   N,  N),
-       PINGROUP(kb_col4_pq4,            KBC,        OWR,        SDMMC3,       UARTA,       0x330c, N,   N,  N),
-       PINGROUP(kb_col5_pq5,            KBC,        RSVD2,      SDMMC3,       RSVD4,       0x3310, N,   N,  N),
-       PINGROUP(kb_col6_pq6,            KBC,        RSVD2,      SPI2,         UARTD,       0x3314, N,   N,  N),
-       PINGROUP(kb_col7_pq7,            KBC,        RSVD2,      SPI2,         UARTD,       0x3318, N,   N,  N),
-       PINGROUP(clk_32k_out_pa0,        BLINK,      SOC,        RSVD3,        RSVD4,       0x331c, N,   N,  N),
-       PINGROUP(core_pwr_req,           PWRON,      RSVD2,      RSVD3,        RSVD4,       0x3324, N,   N,  N),
-       PINGROUP(cpu_pwr_req,            CPU,        RSVD2,      RSVD3,        RSVD4,       0x3328, N,   N,  N),
-       PINGROUP(pwr_int_n,              PMI,        RSVD2,      RSVD3,        RSVD4,       0x332c, N,   N,  N),
-       PINGROUP(clk_32k_in,             CLK,        RSVD2,      RSVD3,        RSVD4,       0x3330, N,   N,  N),
-       PINGROUP(owr,                    OWR,        RSVD2,      RSVD3,        RSVD4,       0x3334, N,   N,  Y),
-       PINGROUP(dap1_fs_pn0,            I2S0,       HDA,        GMI,          RSVD4,       0x3338, N,   N,  N),
-       PINGROUP(dap1_din_pn1,           I2S0,       HDA,        GMI,          RSVD4,       0x333c, N,   N,  N),
-       PINGROUP(dap1_dout_pn2,          I2S0,       HDA,        GMI,          SATA,        0x3340, N,   N,  N),
-       PINGROUP(dap1_sclk_pn3,          I2S0,       HDA,        GMI,          RSVD4,       0x3344, N,   N,  N),
-       PINGROUP(dap_mclk1_req_pee2,     DAP,        DAP1,       SATA,         RSVD4,       0x3348, N,   N,  N),
-       PINGROUP(dap_mclk1_pw4,          EXTPERIPH1, DAP2,       RSVD3,        RSVD4,       0x334c, N,   N,  N),
-       PINGROUP(spdif_in_pk6,           SPDIF,      RSVD2,      RSVD3,        I2C3,        0x3350, N,   N,  N),
-       PINGROUP(spdif_out_pk5,          SPDIF,      RSVD2,      RSVD3,        I2C3,        0x3354, N,   N,  N),
-       PINGROUP(dap2_fs_pa2,            I2S1,       HDA,        GMI,          RSVD4,       0x3358, N,   N,  N),
-       PINGROUP(dap2_din_pa4,           I2S1,       HDA,        GMI,          RSVD4,       0x335c, N,   N,  N),
-       PINGROUP(dap2_dout_pa5,          I2S1,       HDA,        GMI,          RSVD4,       0x3360, N,   N,  N),
-       PINGROUP(dap2_sclk_pa3,          I2S1,       HDA,        GMI,          RSVD4,       0x3364, N,   N,  N),
-       PINGROUP(dvfs_pwm_px0,           SPI6,       CLDVFS,     GMI,          RSVD4,       0x3368, N,   N,  N),
-       PINGROUP(gpio_x1_aud_px1,        SPI6,       RSVD2,      GMI,          RSVD4,       0x336c, N,   N,  N),
-       PINGROUP(gpio_x3_aud_px3,        SPI6,       SPI1,       GMI,          RSVD4,       0x3370, N,   N,  N),
-       PINGROUP(dvfs_clk_px2,           SPI6,       CLDVFS,     GMI,          RSVD4,       0x3374, N,   N,  N),
-       PINGROUP(gpio_x4_aud_px4,        GMI,        SPI1,       SPI2,         DAP2,        0x3378, N,   N,  N),
-       PINGROUP(gpio_x5_aud_px5,        GMI,        SPI1,       SPI2,         RSVD4,       0x337c, N,   N,  N),
-       PINGROUP(gpio_x6_aud_px6,        SPI6,       SPI1,       SPI2,         GMI,         0x3380, N,   N,  N),
-       PINGROUP(gpio_x7_aud_px7,        RSVD1,      SPI1,       SPI2,         RSVD4,       0x3384, N,   N,  N),
-       PINGROUP(sdmmc3_clk_pa6,         SDMMC3,     RSVD2,      RSVD3,        SPI3,        0x3390, N,   N,  N),
-       PINGROUP(sdmmc3_cmd_pa7,         SDMMC3,     PWM3,       UARTA,        SPI3,        0x3394, N,   N,  N),
-       PINGROUP(sdmmc3_dat0_pb7,        SDMMC3,     RSVD2,      RSVD3,        SPI3,        0x3398, N,   N,  N),
-       PINGROUP(sdmmc3_dat1_pb6,        SDMMC3,     PWM2,       UARTA,        SPI3,        0x339c, N,   N,  N),
-       PINGROUP(sdmmc3_dat2_pb5,        SDMMC3,     PWM1,       DISPLAYA,     SPI3,        0x33a0, N,   N,  N),
-       PINGROUP(sdmmc3_dat3_pb4,        SDMMC3,     PWM0,       DISPLAYB,     SPI3,        0x33a4, N,   N,  N),
-       PINGROUP(pex_l0_rst_n_pdd1,      PE0,        RSVD2,      RSVD3,        RSVD4,       0x33bc, N,   N,  N),
-       PINGROUP(pex_l0_clkreq_n_pdd2,   PE0,        RSVD2,      RSVD3,        RSVD4,       0x33c0, N,   N,  N),
-       PINGROUP(pex_wake_n_pdd3,        PE,         RSVD2,      RSVD3,        RSVD4,       0x33c4, N,   N,  N),
-       PINGROUP(pex_l1_rst_n_pdd5,      PE1,        RSVD2,      RSVD3,        RSVD4,       0x33cc, N,   N,  N),
-       PINGROUP(pex_l1_clkreq_n_pdd6,   PE1,        RSVD2,      RSVD3,        RSVD4,       0x33d0, N,   N,  N),
-       PINGROUP(hdmi_cec_pee3,          CEC,        RSVD2,      RSVD3,        RSVD4,       0x33e0, Y,   N,  N),
-       PINGROUP(sdmmc1_wp_n_pv3,        SDMMC1,     CLK12,      SPI4,         UARTA,       0x33e4, N,   N,  N),
-       PINGROUP(sdmmc3_cd_n_pv2,        SDMMC3,     OWR,        RSVD3,        RSVD4,       0x33e8, N,   N,  N),
-       PINGROUP(gpio_w2_aud_pw2,        SPI6,       RSVD2,      SPI2,         I2C1,        0x33ec, N,   N,  N),
-       PINGROUP(gpio_w3_aud_pw3,        SPI6,       SPI1,       SPI2,         I2C1,        0x33f0, N,   N,  N),
-       PINGROUP(usb_vbus_en0_pn4,       USB,        RSVD2,      RSVD3,        RSVD4,       0x33f4, Y,   N,  N),
-       PINGROUP(usb_vbus_en1_pn5,       USB,        RSVD2,      RSVD3,        RSVD4,       0x33f8, Y,   N,  N),
-       PINGROUP(sdmmc3_clk_lb_in_pee5,  SDMMC3,     RSVD2,      RSVD3,        RSVD4,       0x33fc, N,   N,  N),
-       PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3,     RSVD2,      RSVD3,        RSVD4,       0x3400, N,   N,  N),
-       PINGROUP(gmi_clk_lb,             SDMMC2,     RSVD2,      GMI,          RSVD4,       0x3404, N,   N,  N),
-       PINGROUP(reset_out_n,            RSVD1,      RSVD2,      RSVD3,        RESET_OUT_N, 0x3408, N,   N,  N),
-       PINGROUP(kb_row16_pt0,           KBC,        RSVD2,      RSVD3,        UARTC,       0x340c, N,   N,  N),
-       PINGROUP(kb_row17_pt1,           KBC,        RSVD2,      RSVD3,        UARTC,       0x3410, N,   N,  N),
-       PINGROUP(usb_vbus_en2_pff1,      USB,        RSVD2,      RSVD3,        RSVD4,       0x3414, Y,   N,  N),
-       PINGROUP(pff2,                   SATA,       RSVD2,      RSVD3,        RSVD4,       0x3418, Y,   N,  N),
-       PINGROUP(dp_hpd_pff0,            DP,         RSVD2,      RSVD3,        RSVD4,       0x3430, N,   N,  N),
-
-       /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */
-       DRV_PINGROUP(ao1,         0x868,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(ao2,         0x86c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(at1,         0x870,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(at2,         0x874,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(at3,         0x878,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(at4,         0x87c,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(at5,         0x880,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(cdev1,       0x884,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(cdev2,       0x888,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dap1,        0x890,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dap2,        0x894,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dap3,        0x898,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dap4,        0x89c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dbg,         0x8a0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(sdio3,       0x8b0,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(spi,         0x8b4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uaa,         0x8b8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uab,         0x8bc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uart2,       0x8c0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uart3,       0x8c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(sdio1,       0x8ec,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(ddc,         0x8fc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gma,         0x900,  2,  3,  4,  14,  5,  20,  5,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(gme,         0x910,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gmf,         0x914,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gmg,         0x918,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gmh,         0x91c,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(owr,         0x920,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(uda,         0x924,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(gpv,         0x928,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(dev3,        0x92c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(cec,         0x938,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(at6,         0x994,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-       DRV_PINGROUP(dap5,        0x998,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(usb_vbus_en, 0x99c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(ao3,         0x9a8,  2,  3,  4,  12,  5,  -1, -1,  28,  2,  -1, -1,  N),
-       DRV_PINGROUP(ao0,         0x9b0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(hv0,         0x9b4,  2,  3,  4,  12,  5,  -1, -1,  28,  2,  -1, -1,  N),
-       DRV_PINGROUP(sdio4,       0x9c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
-       DRV_PINGROUP(ao4,         0x9c8,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
-
-       /*                     pg_name, r,     b, f0,  f1 */
-       MIPI_PAD_CTRL_PINGROUP(dsi_b,   0x820, 1, CSI, DSI_B),
-};
-
-static const struct tegra_pinctrl_soc_data tegra124_pinctrl = {
-       .ngpios = NUM_GPIOS,
-       .pins = tegra124_pins,
-       .npins = ARRAY_SIZE(tegra124_pins),
-       .functions = tegra124_functions,
-       .nfunctions = ARRAY_SIZE(tegra124_functions),
-       .groups = tegra124_groups,
-       .ngroups = ARRAY_SIZE(tegra124_groups),
-       .hsm_in_mux = false,
-       .schmitt_in_mux = false,
-       .drvtype_in_mux = false,
-};
-
-static int tegra124_pinctrl_probe(struct platform_device *pdev)
-{
-       return tegra_pinctrl_probe(pdev, &tegra124_pinctrl);
-}
-
-static const struct of_device_id tegra124_pinctrl_of_match[] = {
-       { .compatible = "nvidia,tegra124-pinmux", },
-       { },
-};
-MODULE_DEVICE_TABLE(of, tegra124_pinctrl_of_match);
-
-static struct platform_driver tegra124_pinctrl_driver = {
-       .driver = {
-               .name = "tegra124-pinctrl",
-               .of_match_table = tegra124_pinctrl_of_match,
-       },
-       .probe = tegra124_pinctrl_probe,
-       .remove = tegra_pinctrl_remove,
-};
-module_platform_driver(tegra124_pinctrl_driver);
-
-MODULE_AUTHOR("Ashwini Ghuge <aghuge@nvidia.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra124 pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
deleted file mode 100644 (file)
index 4833db4..0000000
+++ /dev/null
@@ -1,2252 +0,0 @@
-/*
- * Pinctrl data for the NVIDIA Tegra20 pinmux
- *
- * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * Derived from code:
- * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2010 NVIDIA Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-
-#include "pinctrl-tegra.h"
-
-/*
- * Most pins affected by the pinmux can also be GPIOs. Define these first.
- * These must match how the GPIO driver names/numbers its pins.
- */
-#define _GPIO(offset)                  (offset)
-
-#define TEGRA_PIN_VI_GP6_PA0           _GPIO(0)
-#define TEGRA_PIN_UART3_CTS_N_PA1      _GPIO(1)
-#define TEGRA_PIN_DAP2_FS_PA2          _GPIO(2)
-#define TEGRA_PIN_DAP2_SCLK_PA3                _GPIO(3)
-#define TEGRA_PIN_DAP2_DIN_PA4         _GPIO(4)
-#define TEGRA_PIN_DAP2_DOUT_PA5                _GPIO(5)
-#define TEGRA_PIN_SDIO3_CLK_PA6                _GPIO(6)
-#define TEGRA_PIN_SDIO3_CMD_PA7                _GPIO(7)
-#define TEGRA_PIN_GMI_AD17_PB0         _GPIO(8)
-#define TEGRA_PIN_GMI_AD18_PB1         _GPIO(9)
-#define TEGRA_PIN_LCD_PWR0_PB2         _GPIO(10)
-#define TEGRA_PIN_LCD_PCLK_PB3         _GPIO(11)
-#define TEGRA_PIN_SDIO3_DAT3_PB4       _GPIO(12)
-#define TEGRA_PIN_SDIO3_DAT2_PB5       _GPIO(13)
-#define TEGRA_PIN_SDIO3_DAT1_PB6       _GPIO(14)
-#define TEGRA_PIN_SDIO3_DAT0_PB7       _GPIO(15)
-#define TEGRA_PIN_UART3_RTS_N_PC0      _GPIO(16)
-#define TEGRA_PIN_LCD_PWR1_PC1         _GPIO(17)
-#define TEGRA_PIN_UART2_TXD_PC2                _GPIO(18)
-#define TEGRA_PIN_UART2_RXD_PC3                _GPIO(19)
-#define TEGRA_PIN_GEN1_I2C_SCL_PC4     _GPIO(20)
-#define TEGRA_PIN_GEN1_I2C_SDA_PC5     _GPIO(21)
-#define TEGRA_PIN_LCD_PWR2_PC6         _GPIO(22)
-#define TEGRA_PIN_GMI_WP_N_PC7         _GPIO(23)
-#define TEGRA_PIN_SDIO3_DAT5_PD0       _GPIO(24)
-#define TEGRA_PIN_SDIO3_DAT4_PD1       _GPIO(25)
-#define TEGRA_PIN_VI_GP5_PD2           _GPIO(26)
-#define TEGRA_PIN_SDIO3_DAT6_PD3       _GPIO(27)
-#define TEGRA_PIN_SDIO3_DAT7_PD4       _GPIO(28)
-#define TEGRA_PIN_VI_D1_PD5            _GPIO(29)
-#define TEGRA_PIN_VI_VSYNC_PD6         _GPIO(30)
-#define TEGRA_PIN_VI_HSYNC_PD7         _GPIO(31)
-#define TEGRA_PIN_LCD_D0_PE0           _GPIO(32)
-#define TEGRA_PIN_LCD_D1_PE1           _GPIO(33)
-#define TEGRA_PIN_LCD_D2_PE2           _GPIO(34)
-#define TEGRA_PIN_LCD_D3_PE3           _GPIO(35)
-#define TEGRA_PIN_LCD_D4_PE4           _GPIO(36)
-#define TEGRA_PIN_LCD_D5_PE5           _GPIO(37)
-#define TEGRA_PIN_LCD_D6_PE6           _GPIO(38)
-#define TEGRA_PIN_LCD_D7_PE7           _GPIO(39)
-#define TEGRA_PIN_LCD_D8_PF0           _GPIO(40)
-#define TEGRA_PIN_LCD_D9_PF1           _GPIO(41)
-#define TEGRA_PIN_LCD_D10_PF2          _GPIO(42)
-#define TEGRA_PIN_LCD_D11_PF3          _GPIO(43)
-#define TEGRA_PIN_LCD_D12_PF4          _GPIO(44)
-#define TEGRA_PIN_LCD_D13_PF5          _GPIO(45)
-#define TEGRA_PIN_LCD_D14_PF6          _GPIO(46)
-#define TEGRA_PIN_LCD_D15_PF7          _GPIO(47)
-#define TEGRA_PIN_GMI_AD0_PG0          _GPIO(48)
-#define TEGRA_PIN_GMI_AD1_PG1          _GPIO(49)
-#define TEGRA_PIN_GMI_AD2_PG2          _GPIO(50)
-#define TEGRA_PIN_GMI_AD3_PG3          _GPIO(51)
-#define TEGRA_PIN_GMI_AD4_PG4          _GPIO(52)
-#define TEGRA_PIN_GMI_AD5_PG5          _GPIO(53)
-#define TEGRA_PIN_GMI_AD6_PG6          _GPIO(54)
-#define TEGRA_PIN_GMI_AD7_PG7          _GPIO(55)
-#define TEGRA_PIN_GMI_AD8_PH0          _GPIO(56)
-#define TEGRA_PIN_GMI_AD9_PH1          _GPIO(57)
-#define TEGRA_PIN_GMI_AD10_PH2         _GPIO(58)
-#define TEGRA_PIN_GMI_AD11_PH3         _GPIO(59)
-#define TEGRA_PIN_GMI_AD12_PH4         _GPIO(60)
-#define TEGRA_PIN_GMI_AD13_PH5         _GPIO(61)
-#define TEGRA_PIN_GMI_AD14_PH6         _GPIO(62)
-#define TEGRA_PIN_GMI_AD15_PH7         _GPIO(63)
-#define TEGRA_PIN_GMI_HIOW_N_PI0       _GPIO(64)
-#define TEGRA_PIN_GMI_HIOR_N_PI1       _GPIO(65)
-#define TEGRA_PIN_GMI_CS5_N_PI2                _GPIO(66)
-#define TEGRA_PIN_GMI_CS6_N_PI3                _GPIO(67)
-#define TEGRA_PIN_GMI_RST_N_PI4                _GPIO(68)
-#define TEGRA_PIN_GMI_IORDY_PI5                _GPIO(69)
-#define TEGRA_PIN_GMI_CS7_N_PI6                _GPIO(70)
-#define TEGRA_PIN_GMI_WAIT_PI7         _GPIO(71)
-#define TEGRA_PIN_GMI_CS0_N_PJ0                _GPIO(72)
-#define TEGRA_PIN_LCD_DE_PJ1           _GPIO(73)
-#define TEGRA_PIN_GMI_CS1_N_PJ2                _GPIO(74)
-#define TEGRA_PIN_LCD_HSYNC_PJ3                _GPIO(75)
-#define TEGRA_PIN_LCD_VSYNC_PJ4                _GPIO(76)
-#define TEGRA_PIN_UART2_CTS_N_PJ5      _GPIO(77)
-#define TEGRA_PIN_UART2_RTS_N_PJ6      _GPIO(78)
-#define TEGRA_PIN_GMI_AD16_PJ7         _GPIO(79)
-#define TEGRA_PIN_GMI_ADV_N_PK0                _GPIO(80)
-#define TEGRA_PIN_GMI_CLK_PK1          _GPIO(81)
-#define TEGRA_PIN_GMI_CS4_N_PK2                _GPIO(82)
-#define TEGRA_PIN_GMI_CS2_N_PK3                _GPIO(83)
-#define TEGRA_PIN_GMI_CS3_N_PK4                _GPIO(84)
-#define TEGRA_PIN_SPDIF_OUT_PK5                _GPIO(85)
-#define TEGRA_PIN_SPDIF_IN_PK6         _GPIO(86)
-#define TEGRA_PIN_GMI_AD19_PK7         _GPIO(87)
-#define TEGRA_PIN_VI_D2_PL0            _GPIO(88)
-#define TEGRA_PIN_VI_D3_PL1            _GPIO(89)
-#define TEGRA_PIN_VI_D4_PL2            _GPIO(90)
-#define TEGRA_PIN_VI_D5_PL3            _GPIO(91)
-#define TEGRA_PIN_VI_D6_PL4            _GPIO(92)
-#define TEGRA_PIN_VI_D7_PL5            _GPIO(93)
-#define TEGRA_PIN_VI_D8_PL6            _GPIO(94)
-#define TEGRA_PIN_VI_D9_PL7            _GPIO(95)
-#define TEGRA_PIN_LCD_D16_PM0          _GPIO(96)
-#define TEGRA_PIN_LCD_D17_PM1          _GPIO(97)
-#define TEGRA_PIN_LCD_D18_PM2          _GPIO(98)
-#define TEGRA_PIN_LCD_D19_PM3          _GPIO(99)
-#define TEGRA_PIN_LCD_D20_PM4          _GPIO(100)
-#define TEGRA_PIN_LCD_D21_PM5          _GPIO(101)
-#define TEGRA_PIN_LCD_D22_PM6          _GPIO(102)
-#define TEGRA_PIN_LCD_D23_PM7          _GPIO(103)
-#define TEGRA_PIN_DAP1_FS_PN0          _GPIO(104)
-#define TEGRA_PIN_DAP1_DIN_PN1         _GPIO(105)
-#define TEGRA_PIN_DAP1_DOUT_PN2                _GPIO(106)
-#define TEGRA_PIN_DAP1_SCLK_PN3                _GPIO(107)
-#define TEGRA_PIN_LCD_CS0_N_PN4                _GPIO(108)
-#define TEGRA_PIN_LCD_SDOUT_PN5                _GPIO(109)
-#define TEGRA_PIN_LCD_DC0_PN6          _GPIO(110)
-#define TEGRA_PIN_HDMI_INT_N_PN7       _GPIO(111)
-#define TEGRA_PIN_ULPI_DATA7_PO0       _GPIO(112)
-#define TEGRA_PIN_ULPI_DATA0_PO1       _GPIO(113)
-#define TEGRA_PIN_ULPI_DATA1_PO2       _GPIO(114)
-#define TEGRA_PIN_ULPI_DATA2_PO3       _GPIO(115)
-#define TEGRA_PIN_ULPI_DATA3_PO4       _GPIO(116)
-#define TEGRA_PIN_ULPI_DATA4_PO5       _GPIO(117)
-#define TEGRA_PIN_ULPI_DATA5_PO6       _GPIO(118)
-#define TEGRA_PIN_ULPI_DATA6_PO7       _GPIO(119)
-#define TEGRA_PIN_DAP3_FS_PP0          _GPIO(120)
-#define TEGRA_PIN_DAP3_DIN_PP1         _GPIO(121)
-#define TEGRA_PIN_DAP3_DOUT_PP2                _GPIO(122)
-#define TEGRA_PIN_DAP3_SCLK_PP3                _GPIO(123)
-#define TEGRA_PIN_DAP4_FS_PP4          _GPIO(124)
-#define TEGRA_PIN_DAP4_DIN_PP5         _GPIO(125)
-#define TEGRA_PIN_DAP4_DOUT_PP6                _GPIO(126)
-#define TEGRA_PIN_DAP4_SCLK_PP7                _GPIO(127)
-#define TEGRA_PIN_KB_COL0_PQ0          _GPIO(128)
-#define TEGRA_PIN_KB_COL1_PQ1          _GPIO(129)
-#define TEGRA_PIN_KB_COL2_PQ2          _GPIO(130)
-#define TEGRA_PIN_KB_COL3_PQ3          _GPIO(131)
-#define TEGRA_PIN_KB_COL4_PQ4          _GPIO(132)
-#define TEGRA_PIN_KB_COL5_PQ5          _GPIO(133)
-#define TEGRA_PIN_KB_COL6_PQ6          _GPIO(134)
-#define TEGRA_PIN_KB_COL7_PQ7          _GPIO(135)
-#define TEGRA_PIN_KB_ROW0_PR0          _GPIO(136)
-#define TEGRA_PIN_KB_ROW1_PR1          _GPIO(137)
-#define TEGRA_PIN_KB_ROW2_PR2          _GPIO(138)
-#define TEGRA_PIN_KB_ROW3_PR3          _GPIO(139)
-#define TEGRA_PIN_KB_ROW4_PR4          _GPIO(140)
-#define TEGRA_PIN_KB_ROW5_PR5          _GPIO(141)
-#define TEGRA_PIN_KB_ROW6_PR6          _GPIO(142)
-#define TEGRA_PIN_KB_ROW7_PR7          _GPIO(143)
-#define TEGRA_PIN_KB_ROW8_PS0          _GPIO(144)
-#define TEGRA_PIN_KB_ROW9_PS1          _GPIO(145)
-#define TEGRA_PIN_KB_ROW10_PS2         _GPIO(146)
-#define TEGRA_PIN_KB_ROW11_PS3         _GPIO(147)
-#define TEGRA_PIN_KB_ROW12_PS4         _GPIO(148)
-#define TEGRA_PIN_KB_ROW13_PS5         _GPIO(149)
-#define TEGRA_PIN_KB_ROW14_PS6         _GPIO(150)
-#define TEGRA_PIN_KB_ROW15_PS7         _GPIO(151)
-#define TEGRA_PIN_VI_PCLK_PT0          _GPIO(152)
-#define TEGRA_PIN_VI_MCLK_PT1          _GPIO(153)
-#define TEGRA_PIN_VI_D10_PT2           _GPIO(154)
-#define TEGRA_PIN_VI_D11_PT3           _GPIO(155)
-#define TEGRA_PIN_VI_D0_PT4            _GPIO(156)
-#define TEGRA_PIN_GEN2_I2C_SCL_PT5     _GPIO(157)
-#define TEGRA_PIN_GEN2_I2C_SDA_PT6     _GPIO(158)
-#define TEGRA_PIN_GMI_DPD_PT7          _GPIO(159)
-#define TEGRA_PIN_PU0                  _GPIO(160)
-#define TEGRA_PIN_PU1                  _GPIO(161)
-#define TEGRA_PIN_PU2                  _GPIO(162)
-#define TEGRA_PIN_PU3                  _GPIO(163)
-#define TEGRA_PIN_PU4                  _GPIO(164)
-#define TEGRA_PIN_PU5                  _GPIO(165)
-#define TEGRA_PIN_PU6                  _GPIO(166)
-#define TEGRA_PIN_JTAG_RTCK_PU7                _GPIO(167)
-#define TEGRA_PIN_PV0                  _GPIO(168)
-#define TEGRA_PIN_PV1                  _GPIO(169)
-#define TEGRA_PIN_PV2                  _GPIO(170)
-#define TEGRA_PIN_PV3                  _GPIO(171)
-#define TEGRA_PIN_PV4                  _GPIO(172)
-#define TEGRA_PIN_PV5                  _GPIO(173)
-#define TEGRA_PIN_PV6                  _GPIO(174)
-#define TEGRA_PIN_LCD_DC1_PV7          _GPIO(175)
-#define TEGRA_PIN_LCD_CS1_N_PW0                _GPIO(176)
-#define TEGRA_PIN_LCD_M1_PW1           _GPIO(177)
-#define TEGRA_PIN_SPI2_CS1_N_PW2       _GPIO(178)
-#define TEGRA_PIN_SPI2_CS2_N_PW3       _GPIO(179)
-#define TEGRA_PIN_DAP_MCLK1_PW4                _GPIO(180)
-#define TEGRA_PIN_DAP_MCLK2_PW5                _GPIO(181)
-#define TEGRA_PIN_UART3_TXD_PW6                _GPIO(182)
-#define TEGRA_PIN_UART3_RXD_PW7                _GPIO(183)
-#define TEGRA_PIN_SPI2_MOSI_PX0                _GPIO(184)
-#define TEGRA_PIN_SPI2_MISO_PX1                _GPIO(185)
-#define TEGRA_PIN_SPI2_SCK_PX2         _GPIO(186)
-#define TEGRA_PIN_SPI2_CS0_N_PX3       _GPIO(187)
-#define TEGRA_PIN_SPI1_MOSI_PX4                _GPIO(188)
-#define TEGRA_PIN_SPI1_SCK_PX5         _GPIO(189)
-#define TEGRA_PIN_SPI1_CS0_N_PX6       _GPIO(190)
-#define TEGRA_PIN_SPI1_MISO_PX7                _GPIO(191)
-#define TEGRA_PIN_ULPI_CLK_PY0         _GPIO(192)
-#define TEGRA_PIN_ULPI_DIR_PY1         _GPIO(193)
-#define TEGRA_PIN_ULPI_NXT_PY2         _GPIO(194)
-#define TEGRA_PIN_ULPI_STP_PY3         _GPIO(195)
-#define TEGRA_PIN_SDIO1_DAT3_PY4       _GPIO(196)
-#define TEGRA_PIN_SDIO1_DAT2_PY5       _GPIO(197)
-#define TEGRA_PIN_SDIO1_DAT1_PY6       _GPIO(198)
-#define TEGRA_PIN_SDIO1_DAT0_PY7       _GPIO(199)
-#define TEGRA_PIN_SDIO1_CLK_PZ0                _GPIO(200)
-#define TEGRA_PIN_SDIO1_CMD_PZ1                _GPIO(201)
-#define TEGRA_PIN_LCD_SDIN_PZ2         _GPIO(202)
-#define TEGRA_PIN_LCD_WR_N_PZ3         _GPIO(203)
-#define TEGRA_PIN_LCD_SCK_PZ4          _GPIO(204)
-#define TEGRA_PIN_SYS_CLK_REQ_PZ5      _GPIO(205)
-#define TEGRA_PIN_PWR_I2C_SCL_PZ6      _GPIO(206)
-#define TEGRA_PIN_PWR_I2C_SDA_PZ7      _GPIO(207)
-#define TEGRA_PIN_GMI_AD20_PAA0                _GPIO(208)
-#define TEGRA_PIN_GMI_AD21_PAA1                _GPIO(209)
-#define TEGRA_PIN_GMI_AD22_PAA2                _GPIO(210)
-#define TEGRA_PIN_GMI_AD23_PAA3                _GPIO(211)
-#define TEGRA_PIN_GMI_AD24_PAA4                _GPIO(212)
-#define TEGRA_PIN_GMI_AD25_PAA5                _GPIO(213)
-#define TEGRA_PIN_GMI_AD26_PAA6                _GPIO(214)
-#define TEGRA_PIN_GMI_AD27_PAA7                _GPIO(215)
-#define TEGRA_PIN_LED_BLINK_PBB0       _GPIO(216)
-#define TEGRA_PIN_VI_GP0_PBB1          _GPIO(217)
-#define TEGRA_PIN_CAM_I2C_SCL_PBB2     _GPIO(218)
-#define TEGRA_PIN_CAM_I2C_SDA_PBB3     _GPIO(219)
-#define TEGRA_PIN_VI_GP3_PBB4          _GPIO(220)
-#define TEGRA_PIN_VI_GP4_PBB5          _GPIO(221)
-#define TEGRA_PIN_PBB6                 _GPIO(222)
-#define TEGRA_PIN_PBB7                 _GPIO(223)
-
-/* All non-GPIO pins follow */
-#define NUM_GPIOS                      (TEGRA_PIN_PBB7 + 1)
-#define _PIN(offset)                   (NUM_GPIOS + (offset))
-
-#define TEGRA_PIN_CRT_HSYNC            _PIN(30)
-#define TEGRA_PIN_CRT_VSYNC            _PIN(31)
-#define TEGRA_PIN_DDC_SCL              _PIN(32)
-#define TEGRA_PIN_DDC_SDA              _PIN(33)
-#define TEGRA_PIN_OWC                  _PIN(34)
-#define TEGRA_PIN_CORE_PWR_REQ         _PIN(35)
-#define TEGRA_PIN_CPU_PWR_REQ          _PIN(36)
-#define TEGRA_PIN_PWR_INT_N            _PIN(37)
-#define TEGRA_PIN_CLK_32_K_IN          _PIN(38)
-#define TEGRA_PIN_DDR_COMP_PD          _PIN(39)
-#define TEGRA_PIN_DDR_COMP_PU          _PIN(40)
-#define TEGRA_PIN_DDR_A0               _PIN(41)
-#define TEGRA_PIN_DDR_A1               _PIN(42)
-#define TEGRA_PIN_DDR_A2               _PIN(43)
-#define TEGRA_PIN_DDR_A3               _PIN(44)
-#define TEGRA_PIN_DDR_A4               _PIN(45)
-#define TEGRA_PIN_DDR_A5               _PIN(46)
-#define TEGRA_PIN_DDR_A6               _PIN(47)
-#define TEGRA_PIN_DDR_A7               _PIN(48)
-#define TEGRA_PIN_DDR_A8               _PIN(49)
-#define TEGRA_PIN_DDR_A9               _PIN(50)
-#define TEGRA_PIN_DDR_A10              _PIN(51)
-#define TEGRA_PIN_DDR_A11              _PIN(52)
-#define TEGRA_PIN_DDR_A12              _PIN(53)
-#define TEGRA_PIN_DDR_A13              _PIN(54)
-#define TEGRA_PIN_DDR_A14              _PIN(55)
-#define TEGRA_PIN_DDR_CAS_N            _PIN(56)
-#define TEGRA_PIN_DDR_BA0              _PIN(57)
-#define TEGRA_PIN_DDR_BA1              _PIN(58)
-#define TEGRA_PIN_DDR_BA2              _PIN(59)
-#define TEGRA_PIN_DDR_DQS0P            _PIN(60)
-#define TEGRA_PIN_DDR_DQS0N            _PIN(61)
-#define TEGRA_PIN_DDR_DQS1P            _PIN(62)
-#define TEGRA_PIN_DDR_DQS1N            _PIN(63)
-#define TEGRA_PIN_DDR_DQS2P            _PIN(64)
-#define TEGRA_PIN_DDR_DQS2N            _PIN(65)
-#define TEGRA_PIN_DDR_DQS3P            _PIN(66)
-#define TEGRA_PIN_DDR_DQS3N            _PIN(67)
-#define TEGRA_PIN_DDR_CKE0             _PIN(68)
-#define TEGRA_PIN_DDR_CKE1             _PIN(69)
-#define TEGRA_PIN_DDR_CLK              _PIN(70)
-#define TEGRA_PIN_DDR_CLK_N            _PIN(71)
-#define TEGRA_PIN_DDR_DM0              _PIN(72)
-#define TEGRA_PIN_DDR_DM1              _PIN(73)
-#define TEGRA_PIN_DDR_DM2              _PIN(74)
-#define TEGRA_PIN_DDR_DM3              _PIN(75)
-#define TEGRA_PIN_DDR_ODT              _PIN(76)
-#define TEGRA_PIN_DDR_QUSE0            _PIN(77)
-#define TEGRA_PIN_DDR_QUSE1            _PIN(78)
-#define TEGRA_PIN_DDR_QUSE2            _PIN(79)
-#define TEGRA_PIN_DDR_QUSE3            _PIN(80)
-#define TEGRA_PIN_DDR_RAS_N            _PIN(81)
-#define TEGRA_PIN_DDR_WE_N             _PIN(82)
-#define TEGRA_PIN_DDR_DQ0              _PIN(83)
-#define TEGRA_PIN_DDR_DQ1              _PIN(84)
-#define TEGRA_PIN_DDR_DQ2              _PIN(85)
-#define TEGRA_PIN_DDR_DQ3              _PIN(86)
-#define TEGRA_PIN_DDR_DQ4              _PIN(87)
-#define TEGRA_PIN_DDR_DQ5              _PIN(88)
-#define TEGRA_PIN_DDR_DQ6              _PIN(89)
-#define TEGRA_PIN_DDR_DQ7              _PIN(90)
-#define TEGRA_PIN_DDR_DQ8              _PIN(91)
-#define TEGRA_PIN_DDR_DQ9              _PIN(92)
-#define TEGRA_PIN_DDR_DQ10             _PIN(93)
-#define TEGRA_PIN_DDR_DQ11             _PIN(94)
-#define TEGRA_PIN_DDR_DQ12             _PIN(95)
-#define TEGRA_PIN_DDR_DQ13             _PIN(96)
-#define TEGRA_PIN_DDR_DQ14             _PIN(97)
-#define TEGRA_PIN_DDR_DQ15             _PIN(98)
-#define TEGRA_PIN_DDR_DQ16             _PIN(99)
-#define TEGRA_PIN_DDR_DQ17             _PIN(100)
-#define TEGRA_PIN_DDR_DQ18             _PIN(101)
-#define TEGRA_PIN_DDR_DQ19             _PIN(102)
-#define TEGRA_PIN_DDR_DQ20             _PIN(103)
-#define TEGRA_PIN_DDR_DQ21             _PIN(104)
-#define TEGRA_PIN_DDR_DQ22             _PIN(105)
-#define TEGRA_PIN_DDR_DQ23             _PIN(106)
-#define TEGRA_PIN_DDR_DQ24             _PIN(107)
-#define TEGRA_PIN_DDR_DQ25             _PIN(108)
-#define TEGRA_PIN_DDR_DQ26             _PIN(109)
-#define TEGRA_PIN_DDR_DQ27             _PIN(110)
-#define TEGRA_PIN_DDR_DQ28             _PIN(111)
-#define TEGRA_PIN_DDR_DQ29             _PIN(112)
-#define TEGRA_PIN_DDR_DQ30             _PIN(113)
-#define TEGRA_PIN_DDR_DQ31             _PIN(114)
-#define TEGRA_PIN_DDR_CS0_N            _PIN(115)
-#define TEGRA_PIN_DDR_CS1_N            _PIN(116)
-#define TEGRA_PIN_SYS_RESET            _PIN(117)
-#define TEGRA_PIN_JTAG_TRST_N          _PIN(118)
-#define TEGRA_PIN_JTAG_TDO             _PIN(119)
-#define TEGRA_PIN_JTAG_TMS             _PIN(120)
-#define TEGRA_PIN_JTAG_TCK             _PIN(121)
-#define TEGRA_PIN_JTAG_TDI             _PIN(122)
-#define TEGRA_PIN_TEST_MODE_EN         _PIN(123)
-
-static const struct pinctrl_pin_desc tegra20_pins[] = {
-       PINCTRL_PIN(TEGRA_PIN_VI_GP6_PA0, "VI_GP6 PA0"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_CLK_PA6, "SDIO3_CLK PA6"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_CMD_PA7, "SDIO3_CMD PA7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD17_PB0, "GMI_AD17 PB0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD18_PB1, "GMI_AD18 PB1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT3_PB4, "SDIO3_DAT3 PB4"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT2_PB5, "SDIO3_DAT2 PB5"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT1_PB6, "SDIO3_DAT1 PB6"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT0_PB7, "SDIO3_DAT0 PB7"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT5_PD0, "SDIO3_DAT5 PD0"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT4_PD1, "SDIO3_DAT4 PD1"),
-       PINCTRL_PIN(TEGRA_PIN_VI_GP5_PD2, "VI_GP5 PD2"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT6_PD3, "SDIO3_DAT6 PD3"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT7_PD4, "SDIO3_DAT7 PD4"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"),
-       PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"),
-       PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_HIOW_N_PI0, "GMI_HIOW_N PI0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_HIOR_N_PI1, "GMI_HIOR_N PI1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS5_N_PI2, "GMI_CS5_N PI2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD16_PJ7, "GMI_AD16 PJ7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD19_PK7, "GMI_AD19 PK7"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_N_PN7, "HDMI_INT_N PN7"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"),
-       PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"),
-       PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VD_D10 PT2"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_DPD_PT7, "GMI_DPD PT7"),
-       /* PU0..6: GPIO only */
-       PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"),
-       PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"),
-       PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"),
-       PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"),
-       PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"),
-       PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"),
-       PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"),
-       /* PV0..1: GPIO only */
-       PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"),
-       PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"),
-       /* PV2..3: Balls are named after GPIO not function */
-       PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"),
-       PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"),
-       /* PV4..6: GPIO only */
-       PINCTRL_PIN(TEGRA_PIN_PV4, "PV4"),
-       PINCTRL_PIN(TEGRA_PIN_PV5, "PV5"),
-       PINCTRL_PIN(TEGRA_PIN_PV6, "PV6"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PV7, "LCD_DC1 PV7"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP_MCLK2_PW5, "DAP_MCLK2 PW5"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT3_PY4, "SDIO1_DAT3 PY4"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT2_PY5, "SDIO1_DAT2 PY5"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT1_PY6, "SDIO1_DAT1 PY6"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT0_PY7, "SDIO1_DAT0 PY7"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO1_CLK_PZ0, "SDIO1_CLK PZ0"),
-       PINCTRL_PIN(TEGRA_PIN_SDIO1_CMD_PZ1, "SDIO1_CMD PZ1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"),
-       PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD20_PAA0, "GMI_AD20 PAA0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD21_PAA1, "GMI_AD21 PAA1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD22_PAA2, "GMI_AD22 PAA2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD23_PAA3, "GMI_AD23 PAA3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD24_PAA4, "GMI_AD24 PAA4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD25_PAA5, "GMI_AD25 PAA5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD26_PAA6, "GMI_AD26 PAA6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD27_PAA7, "GMI_AD27 PAA7"),
-       PINCTRL_PIN(TEGRA_PIN_LED_BLINK_PBB0, "LED_BLINK PBB0"),
-       PINCTRL_PIN(TEGRA_PIN_VI_GP0_PBB1, "VI_GP0 PBB1"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB2, "CAM_I2C_SCL PBB2"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB3, "CAM_I2C_SDA PBB3"),
-       PINCTRL_PIN(TEGRA_PIN_VI_GP3_PBB4, "VI_GP3 PBB4"),
-       PINCTRL_PIN(TEGRA_PIN_VI_GP4_PBB5, "VI_GP4 PBB5"),
-       PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"),
-       PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"),
-       PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC, "CRT_HSYNC"),
-       PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC, "CRT_VSYNC"),
-       PINCTRL_PIN(TEGRA_PIN_DDC_SCL, "DDC_SCL"),
-       PINCTRL_PIN(TEGRA_PIN_DDC_SDA, "DDC_SDA"),
-       PINCTRL_PIN(TEGRA_PIN_OWC, "OWC"),
-       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
-       PINCTRL_PIN(TEGRA_PIN_CLK_32_K_IN, "CLK_32_K_IN"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PD, "DDR_COMP_PD"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PU, "DDR_COMP_PU"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A0, "DDR_A0"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A1, "DDR_A1"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A2, "DDR_A2"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A3, "DDR_A3"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A4, "DDR_A4"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A5, "DDR_A5"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A6, "DDR_A6"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A7, "DDR_A7"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A8, "DDR_A8"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A9, "DDR_A9"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A10, "DDR_A10"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A11, "DDR_A11"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A12, "DDR_A12"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A13, "DDR_A13"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_A14, "DDR_A14"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_CAS_N, "DDR_CAS_N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_BA0, "DDR_BA0"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_BA1, "DDR_BA1"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_BA2, "DDR_BA2"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQS0P, "DDR_DQS0P"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQS0N, "DDR_DQS0N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQS1P, "DDR_DQS1P"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQS1N, "DDR_DQS1N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQS2P, "DDR_DQS2P"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQS2N, "DDR_DQS2N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQS3P, "DDR_DQS3P"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQS3N, "DDR_DQS3N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_CKE0, "DDR_CKE0"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_CKE1, "DDR_CKE1"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_CLK, "DDR_CLK"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_CLK_N, "DDR_CLK_N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DM0, "DDR_DM0"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DM1, "DDR_DM1"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DM2, "DDR_DM2"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DM3, "DDR_DM3"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_ODT, "DDR_ODT"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_QUSE0, "DDR_QUSE0"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_QUSE1, "DDR_QUSE1"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_QUSE2, "DDR_QUSE2"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_QUSE3, "DDR_QUSE3"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_RAS_N, "DDR_RAS_N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_WE_N, "DDR_WE_N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ0, "DDR_DQ0"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ1, "DDR_DQ1"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ2, "DDR_DQ2"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ3, "DDR_DQ3"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ4, "DDR_DQ4"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ5, "DDR_DQ5"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ6, "DDR_DQ6"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ7, "DDR_DQ7"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ8, "DDR_DQ8"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ9, "DDR_DQ9"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ10, "DDR_DQ10"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ11, "DDR_DQ11"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ12, "DDR_DQ12"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ13, "DDR_DQ13"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ14, "DDR_DQ14"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ15, "DDR_DQ15"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ16, "DDR_DQ16"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ17, "DDR_DQ17"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ18, "DDR_DQ18"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ19, "DDR_DQ19"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ20, "DDR_DQ20"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ21, "DDR_DQ21"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ22, "DDR_DQ22"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ23, "DDR_DQ23"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ24, "DDR_DQ24"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ25, "DDR_DQ25"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ26, "DDR_DQ26"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ27, "DDR_DQ27"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ28, "DDR_DQ28"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ29, "DDR_DQ29"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ30, "DDR_DQ30"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_DQ31, "DDR_DQ31"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_CS0_N, "DDR_CS0_N"),
-       PINCTRL_PIN(TEGRA_PIN_DDR_CS1_N, "DDR_CS1_N"),
-       PINCTRL_PIN(TEGRA_PIN_SYS_RESET, "SYS_RESET"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"),
-       PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"),
-};
-
-static const unsigned ata_pins[] = {
-       TEGRA_PIN_GMI_CS6_N_PI3,
-       TEGRA_PIN_GMI_CS7_N_PI6,
-       TEGRA_PIN_GMI_RST_N_PI4,
-};
-
-static const unsigned atb_pins[] = {
-       TEGRA_PIN_GMI_CS5_N_PI2,
-       TEGRA_PIN_GMI_DPD_PT7,
-};
-
-static const unsigned atc_pins[] = {
-       TEGRA_PIN_GMI_IORDY_PI5,
-       TEGRA_PIN_GMI_WAIT_PI7,
-       TEGRA_PIN_GMI_ADV_N_PK0,
-       TEGRA_PIN_GMI_CLK_PK1,
-       TEGRA_PIN_GMI_CS2_N_PK3,
-       TEGRA_PIN_GMI_CS3_N_PK4,
-       TEGRA_PIN_GMI_CS4_N_PK2,
-       TEGRA_PIN_GMI_AD0_PG0,
-       TEGRA_PIN_GMI_AD1_PG1,
-       TEGRA_PIN_GMI_AD2_PG2,
-       TEGRA_PIN_GMI_AD3_PG3,
-       TEGRA_PIN_GMI_AD4_PG4,
-       TEGRA_PIN_GMI_AD5_PG5,
-       TEGRA_PIN_GMI_AD6_PG6,
-       TEGRA_PIN_GMI_AD7_PG7,
-       TEGRA_PIN_GMI_HIOW_N_PI0,
-       TEGRA_PIN_GMI_HIOR_N_PI1,
-};
-
-static const unsigned atd_pins[] = {
-       TEGRA_PIN_GMI_AD8_PH0,
-       TEGRA_PIN_GMI_AD9_PH1,
-       TEGRA_PIN_GMI_AD10_PH2,
-       TEGRA_PIN_GMI_AD11_PH3,
-};
-
-static const unsigned ate_pins[] = {
-       TEGRA_PIN_GMI_AD12_PH4,
-       TEGRA_PIN_GMI_AD13_PH5,
-       TEGRA_PIN_GMI_AD14_PH6,
-       TEGRA_PIN_GMI_AD15_PH7,
-};
-
-static const unsigned cdev1_pins[] = {
-       TEGRA_PIN_DAP_MCLK1_PW4,
-};
-
-static const unsigned cdev2_pins[] = {
-       TEGRA_PIN_DAP_MCLK2_PW5,
-};
-
-static const unsigned crtp_pins[] = {
-       TEGRA_PIN_CRT_HSYNC,
-       TEGRA_PIN_CRT_VSYNC,
-};
-
-static const unsigned csus_pins[] = {
-       TEGRA_PIN_VI_MCLK_PT1,
-};
-
-static const unsigned dap1_pins[] = {
-       TEGRA_PIN_DAP1_FS_PN0,
-       TEGRA_PIN_DAP1_DIN_PN1,
-       TEGRA_PIN_DAP1_DOUT_PN2,
-       TEGRA_PIN_DAP1_SCLK_PN3,
-};
-
-static const unsigned dap2_pins[] = {
-       TEGRA_PIN_DAP2_FS_PA2,
-       TEGRA_PIN_DAP2_SCLK_PA3,
-       TEGRA_PIN_DAP2_DIN_PA4,
-       TEGRA_PIN_DAP2_DOUT_PA5,
-};
-
-static const unsigned dap3_pins[] = {
-       TEGRA_PIN_DAP3_FS_PP0,
-       TEGRA_PIN_DAP3_DIN_PP1,
-       TEGRA_PIN_DAP3_DOUT_PP2,
-       TEGRA_PIN_DAP3_SCLK_PP3,
-};
-
-static const unsigned dap4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PP4,
-       TEGRA_PIN_DAP4_DIN_PP5,
-       TEGRA_PIN_DAP4_DOUT_PP6,
-       TEGRA_PIN_DAP4_SCLK_PP7,
-};
-
-static const unsigned ddc_pins[] = {
-       TEGRA_PIN_DDC_SCL,
-       TEGRA_PIN_DDC_SDA,
-};
-
-static const unsigned dta_pins[] = {
-       TEGRA_PIN_VI_D0_PT4,
-       TEGRA_PIN_VI_D1_PD5,
-};
-
-static const unsigned dtb_pins[] = {
-       TEGRA_PIN_VI_D10_PT2,
-       TEGRA_PIN_VI_D11_PT3,
-};
-
-static const unsigned dtc_pins[] = {
-       TEGRA_PIN_VI_HSYNC_PD7,
-       TEGRA_PIN_VI_VSYNC_PD6,
-};
-
-static const unsigned dtd_pins[] = {
-       TEGRA_PIN_VI_PCLK_PT0,
-       TEGRA_PIN_VI_D2_PL0,
-       TEGRA_PIN_VI_D3_PL1,
-       TEGRA_PIN_VI_D4_PL2,
-       TEGRA_PIN_VI_D5_PL3,
-       TEGRA_PIN_VI_D6_PL4,
-       TEGRA_PIN_VI_D7_PL5,
-       TEGRA_PIN_VI_D8_PL6,
-       TEGRA_PIN_VI_D9_PL7,
-};
-
-static const unsigned dte_pins[] = {
-       TEGRA_PIN_VI_GP0_PBB1,
-       TEGRA_PIN_VI_GP3_PBB4,
-       TEGRA_PIN_VI_GP4_PBB5,
-       TEGRA_PIN_VI_GP5_PD2,
-       TEGRA_PIN_VI_GP6_PA0,
-};
-
-static const unsigned dtf_pins[] = {
-       TEGRA_PIN_CAM_I2C_SCL_PBB2,
-       TEGRA_PIN_CAM_I2C_SDA_PBB3,
-};
-
-static const unsigned gma_pins[] = {
-       TEGRA_PIN_GMI_AD20_PAA0,
-       TEGRA_PIN_GMI_AD21_PAA1,
-       TEGRA_PIN_GMI_AD22_PAA2,
-       TEGRA_PIN_GMI_AD23_PAA3,
-};
-
-static const unsigned gmb_pins[] = {
-       TEGRA_PIN_GMI_WP_N_PC7,
-};
-
-static const unsigned gmc_pins[] = {
-       TEGRA_PIN_GMI_AD16_PJ7,
-       TEGRA_PIN_GMI_AD17_PB0,
-       TEGRA_PIN_GMI_AD18_PB1,
-       TEGRA_PIN_GMI_AD19_PK7,
-};
-
-static const unsigned gmd_pins[] = {
-       TEGRA_PIN_GMI_CS0_N_PJ0,
-       TEGRA_PIN_GMI_CS1_N_PJ2,
-};
-
-static const unsigned gme_pins[] = {
-       TEGRA_PIN_GMI_AD24_PAA4,
-       TEGRA_PIN_GMI_AD25_PAA5,
-       TEGRA_PIN_GMI_AD26_PAA6,
-       TEGRA_PIN_GMI_AD27_PAA7,
-};
-
-static const unsigned gpu_pins[] = {
-       TEGRA_PIN_PU0,
-       TEGRA_PIN_PU1,
-       TEGRA_PIN_PU2,
-       TEGRA_PIN_PU3,
-       TEGRA_PIN_PU4,
-       TEGRA_PIN_PU5,
-       TEGRA_PIN_PU6,
-};
-
-static const unsigned gpu7_pins[] = {
-       TEGRA_PIN_JTAG_RTCK_PU7,
-};
-
-static const unsigned gpv_pins[] = {
-       TEGRA_PIN_PV4,
-       TEGRA_PIN_PV5,
-       TEGRA_PIN_PV6,
-};
-
-static const unsigned hdint_pins[] = {
-       TEGRA_PIN_HDMI_INT_N_PN7,
-};
-
-static const unsigned i2cp_pins[] = {
-       TEGRA_PIN_PWR_I2C_SCL_PZ6,
-       TEGRA_PIN_PWR_I2C_SDA_PZ7,
-};
-
-static const unsigned irrx_pins[] = {
-       TEGRA_PIN_UART2_RTS_N_PJ6,
-};
-
-static const unsigned irtx_pins[] = {
-       TEGRA_PIN_UART2_CTS_N_PJ5,
-};
-
-static const unsigned kbca_pins[] = {
-       TEGRA_PIN_KB_ROW0_PR0,
-       TEGRA_PIN_KB_ROW1_PR1,
-       TEGRA_PIN_KB_ROW2_PR2,
-};
-
-static const unsigned kbcb_pins[] = {
-       TEGRA_PIN_KB_ROW7_PR7,
-       TEGRA_PIN_KB_ROW8_PS0,
-       TEGRA_PIN_KB_ROW9_PS1,
-       TEGRA_PIN_KB_ROW10_PS2,
-       TEGRA_PIN_KB_ROW11_PS3,
-       TEGRA_PIN_KB_ROW12_PS4,
-       TEGRA_PIN_KB_ROW13_PS5,
-       TEGRA_PIN_KB_ROW14_PS6,
-       TEGRA_PIN_KB_ROW15_PS7,
-};
-
-static const unsigned kbcc_pins[] = {
-       TEGRA_PIN_KB_COL0_PQ0,
-       TEGRA_PIN_KB_COL1_PQ1,
-};
-
-static const unsigned kbcd_pins[] = {
-       TEGRA_PIN_KB_ROW3_PR3,
-       TEGRA_PIN_KB_ROW4_PR4,
-       TEGRA_PIN_KB_ROW5_PR5,
-       TEGRA_PIN_KB_ROW6_PR6,
-};
-
-static const unsigned kbce_pins[] = {
-       TEGRA_PIN_KB_COL7_PQ7,
-};
-
-static const unsigned kbcf_pins[] = {
-       TEGRA_PIN_KB_COL2_PQ2,
-       TEGRA_PIN_KB_COL3_PQ3,
-       TEGRA_PIN_KB_COL4_PQ4,
-       TEGRA_PIN_KB_COL5_PQ5,
-       TEGRA_PIN_KB_COL6_PQ6,
-};
-
-static const unsigned lcsn_pins[] = {
-       TEGRA_PIN_LCD_CS0_N_PN4,
-};
-
-static const unsigned ld0_pins[] = {
-       TEGRA_PIN_LCD_D0_PE0,
-};
-
-static const unsigned ld1_pins[] = {
-       TEGRA_PIN_LCD_D1_PE1,
-};
-
-static const unsigned ld2_pins[] = {
-       TEGRA_PIN_LCD_D2_PE2,
-};
-
-static const unsigned ld3_pins[] = {
-       TEGRA_PIN_LCD_D3_PE3,
-};
-
-static const unsigned ld4_pins[] = {
-       TEGRA_PIN_LCD_D4_PE4,
-};
-
-static const unsigned ld5_pins[] = {
-       TEGRA_PIN_LCD_D5_PE5,
-};
-
-static const unsigned ld6_pins[] = {
-       TEGRA_PIN_LCD_D6_PE6,
-};
-
-static const unsigned ld7_pins[] = {
-       TEGRA_PIN_LCD_D7_PE7,
-};
-
-static const unsigned ld8_pins[] = {
-       TEGRA_PIN_LCD_D8_PF0,
-};
-
-static const unsigned ld9_pins[] = {
-       TEGRA_PIN_LCD_D9_PF1,
-};
-
-static const unsigned ld10_pins[] = {
-       TEGRA_PIN_LCD_D10_PF2,
-};
-
-static const unsigned ld11_pins[] = {
-       TEGRA_PIN_LCD_D11_PF3,
-};
-
-static const unsigned ld12_pins[] = {
-       TEGRA_PIN_LCD_D12_PF4,
-};
-
-static const unsigned ld13_pins[] = {
-       TEGRA_PIN_LCD_D13_PF5,
-};
-
-static const unsigned ld14_pins[] = {
-       TEGRA_PIN_LCD_D14_PF6,
-};
-
-static const unsigned ld15_pins[] = {
-       TEGRA_PIN_LCD_D15_PF7,
-};
-
-static const unsigned ld16_pins[] = {
-       TEGRA_PIN_LCD_D16_PM0,
-};
-
-static const unsigned ld17_pins[] = {
-       TEGRA_PIN_LCD_D17_PM1,
-};
-
-static const unsigned ldc_pins[] = {
-       TEGRA_PIN_LCD_DC0_PN6,
-};
-
-static const unsigned ldi_pins[] = {
-       TEGRA_PIN_LCD_D22_PM6,
-};
-
-static const unsigned lhp0_pins[] = {
-       TEGRA_PIN_LCD_D21_PM5,
-};
-
-static const unsigned lhp1_pins[] = {
-       TEGRA_PIN_LCD_D18_PM2,
-};
-
-static const unsigned lhp2_pins[] = {
-       TEGRA_PIN_LCD_D19_PM3,
-};
-
-static const unsigned lhs_pins[] = {
-       TEGRA_PIN_LCD_HSYNC_PJ3,
-};
-
-static const unsigned lm0_pins[] = {
-       TEGRA_PIN_LCD_CS1_N_PW0,
-};
-
-static const unsigned lm1_pins[] = {
-       TEGRA_PIN_LCD_M1_PW1,
-};
-
-static const unsigned lpp_pins[] = {
-       TEGRA_PIN_LCD_D23_PM7,
-};
-
-static const unsigned lpw0_pins[] = {
-       TEGRA_PIN_LCD_PWR0_PB2,
-};
-
-static const unsigned lpw1_pins[] = {
-       TEGRA_PIN_LCD_PWR1_PC1,
-};
-
-static const unsigned lpw2_pins[] = {
-       TEGRA_PIN_LCD_PWR2_PC6,
-};
-
-static const unsigned lsc0_pins[] = {
-       TEGRA_PIN_LCD_PCLK_PB3,
-};
-
-static const unsigned lsc1_pins[] = {
-       TEGRA_PIN_LCD_WR_N_PZ3,
-};
-
-static const unsigned lsck_pins[] = {
-       TEGRA_PIN_LCD_SCK_PZ4,
-};
-
-static const unsigned lsda_pins[] = {
-       TEGRA_PIN_LCD_SDOUT_PN5,
-};
-
-static const unsigned lsdi_pins[] = {
-       TEGRA_PIN_LCD_SDIN_PZ2,
-};
-
-static const unsigned lspi_pins[] = {
-       TEGRA_PIN_LCD_DE_PJ1,
-};
-
-static const unsigned lvp0_pins[] = {
-       TEGRA_PIN_LCD_DC1_PV7,
-};
-
-static const unsigned lvp1_pins[] = {
-       TEGRA_PIN_LCD_D20_PM4,
-};
-
-static const unsigned lvs_pins[] = {
-       TEGRA_PIN_LCD_VSYNC_PJ4,
-};
-
-static const unsigned ls_pins[] = {
-       TEGRA_PIN_LCD_PWR0_PB2,
-       TEGRA_PIN_LCD_PWR1_PC1,
-       TEGRA_PIN_LCD_PWR2_PC6,
-       TEGRA_PIN_LCD_SDIN_PZ2,
-       TEGRA_PIN_LCD_SDOUT_PN5,
-       TEGRA_PIN_LCD_WR_N_PZ3,
-       TEGRA_PIN_LCD_CS0_N_PN4,
-       TEGRA_PIN_LCD_DC0_PN6,
-       TEGRA_PIN_LCD_SCK_PZ4,
-};
-
-static const unsigned lc_pins[] = {
-       TEGRA_PIN_LCD_PCLK_PB3,
-       TEGRA_PIN_LCD_DE_PJ1,
-       TEGRA_PIN_LCD_HSYNC_PJ3,
-       TEGRA_PIN_LCD_VSYNC_PJ4,
-       TEGRA_PIN_LCD_CS1_N_PW0,
-       TEGRA_PIN_LCD_M1_PW1,
-       TEGRA_PIN_LCD_DC1_PV7,
-       TEGRA_PIN_HDMI_INT_N_PN7,
-};
-
-static const unsigned ld17_0_pins[] = {
-       TEGRA_PIN_LCD_D0_PE0,
-       TEGRA_PIN_LCD_D1_PE1,
-       TEGRA_PIN_LCD_D2_PE2,
-       TEGRA_PIN_LCD_D3_PE3,
-       TEGRA_PIN_LCD_D4_PE4,
-       TEGRA_PIN_LCD_D5_PE5,
-       TEGRA_PIN_LCD_D6_PE6,
-       TEGRA_PIN_LCD_D7_PE7,
-       TEGRA_PIN_LCD_D8_PF0,
-       TEGRA_PIN_LCD_D9_PF1,
-       TEGRA_PIN_LCD_D10_PF2,
-       TEGRA_PIN_LCD_D11_PF3,
-       TEGRA_PIN_LCD_D12_PF4,
-       TEGRA_PIN_LCD_D13_PF5,
-       TEGRA_PIN_LCD_D14_PF6,
-       TEGRA_PIN_LCD_D15_PF7,
-       TEGRA_PIN_LCD_D16_PM0,
-       TEGRA_PIN_LCD_D17_PM1,
-};
-
-static const unsigned ld19_18_pins[] = {
-       TEGRA_PIN_LCD_D18_PM2,
-       TEGRA_PIN_LCD_D19_PM3,
-};
-
-static const unsigned ld21_20_pins[] = {
-       TEGRA_PIN_LCD_D20_PM4,
-       TEGRA_PIN_LCD_D21_PM5,
-};
-
-static const unsigned ld23_22_pins[] = {
-       TEGRA_PIN_LCD_D22_PM6,
-       TEGRA_PIN_LCD_D23_PM7,
-};
-
-static const unsigned owc_pins[] = {
-       TEGRA_PIN_OWC,
-};
-
-static const unsigned pmc_pins[] = {
-       TEGRA_PIN_LED_BLINK_PBB0,
-       TEGRA_PIN_SYS_CLK_REQ_PZ5,
-       TEGRA_PIN_CORE_PWR_REQ,
-       TEGRA_PIN_CPU_PWR_REQ,
-       TEGRA_PIN_PWR_INT_N,
-};
-
-static const unsigned pta_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SCL_PT5,
-       TEGRA_PIN_GEN2_I2C_SDA_PT6,
-};
-
-static const unsigned rm_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SCL_PC4,
-       TEGRA_PIN_GEN1_I2C_SDA_PC5,
-};
-
-static const unsigned sdb_pins[] = {
-       TEGRA_PIN_SDIO3_CMD_PA7,
-};
-
-static const unsigned sdc_pins[] = {
-       TEGRA_PIN_SDIO3_DAT0_PB7,
-       TEGRA_PIN_SDIO3_DAT1_PB6,
-       TEGRA_PIN_SDIO3_DAT2_PB5,
-       TEGRA_PIN_SDIO3_DAT3_PB4,
-};
-
-static const unsigned sdd_pins[] = {
-       TEGRA_PIN_SDIO3_CLK_PA6,
-};
-
-static const unsigned sdio1_pins[] = {
-       TEGRA_PIN_SDIO1_CLK_PZ0,
-       TEGRA_PIN_SDIO1_CMD_PZ1,
-       TEGRA_PIN_SDIO1_DAT0_PY7,
-       TEGRA_PIN_SDIO1_DAT1_PY6,
-       TEGRA_PIN_SDIO1_DAT2_PY5,
-       TEGRA_PIN_SDIO1_DAT3_PY4,
-};
-
-static const unsigned slxa_pins[] = {
-       TEGRA_PIN_SDIO3_DAT4_PD1,
-};
-
-static const unsigned slxc_pins[] = {
-       TEGRA_PIN_SDIO3_DAT6_PD3,
-};
-
-static const unsigned slxd_pins[] = {
-       TEGRA_PIN_SDIO3_DAT7_PD4,
-};
-
-static const unsigned slxk_pins[] = {
-       TEGRA_PIN_SDIO3_DAT5_PD0,
-};
-
-static const unsigned spdi_pins[] = {
-       TEGRA_PIN_SPDIF_IN_PK6,
-};
-
-static const unsigned spdo_pins[] = {
-       TEGRA_PIN_SPDIF_OUT_PK5,
-};
-
-static const unsigned spia_pins[] = {
-       TEGRA_PIN_SPI2_MOSI_PX0,
-};
-
-static const unsigned spib_pins[] = {
-       TEGRA_PIN_SPI2_MISO_PX1,
-};
-
-static const unsigned spic_pins[] = {
-       TEGRA_PIN_SPI2_CS0_N_PX3,
-       TEGRA_PIN_SPI2_SCK_PX2,
-};
-
-static const unsigned spid_pins[] = {
-       TEGRA_PIN_SPI1_MOSI_PX4,
-};
-
-static const unsigned spie_pins[] = {
-       TEGRA_PIN_SPI1_CS0_N_PX6,
-       TEGRA_PIN_SPI1_SCK_PX5,
-};
-
-static const unsigned spif_pins[] = {
-       TEGRA_PIN_SPI1_MISO_PX7,
-};
-
-static const unsigned spig_pins[] = {
-       TEGRA_PIN_SPI2_CS1_N_PW2,
-};
-
-static const unsigned spih_pins[] = {
-       TEGRA_PIN_SPI2_CS2_N_PW3,
-};
-
-static const unsigned uaa_pins[] = {
-       TEGRA_PIN_ULPI_DATA0_PO1,
-       TEGRA_PIN_ULPI_DATA1_PO2,
-       TEGRA_PIN_ULPI_DATA2_PO3,
-       TEGRA_PIN_ULPI_DATA3_PO4,
-};
-
-static const unsigned uab_pins[] = {
-       TEGRA_PIN_ULPI_DATA4_PO5,
-       TEGRA_PIN_ULPI_DATA5_PO6,
-       TEGRA_PIN_ULPI_DATA6_PO7,
-       TEGRA_PIN_ULPI_DATA7_PO0,
-};
-
-static const unsigned uac_pins[] = {
-       TEGRA_PIN_PV0,
-       TEGRA_PIN_PV1,
-       TEGRA_PIN_PV2,
-       TEGRA_PIN_PV3,
-};
-
-static const unsigned ck32_pins[] = {
-       TEGRA_PIN_CLK_32_K_IN,
-};
-
-static const unsigned uad_pins[] = {
-       TEGRA_PIN_UART2_RXD_PC3,
-       TEGRA_PIN_UART2_TXD_PC2,
-};
-
-static const unsigned uca_pins[] = {
-       TEGRA_PIN_UART3_RXD_PW7,
-       TEGRA_PIN_UART3_TXD_PW6,
-};
-
-static const unsigned ucb_pins[] = {
-       TEGRA_PIN_UART3_CTS_N_PA1,
-       TEGRA_PIN_UART3_RTS_N_PC0,
-};
-
-static const unsigned uda_pins[] = {
-       TEGRA_PIN_ULPI_CLK_PY0,
-       TEGRA_PIN_ULPI_DIR_PY1,
-       TEGRA_PIN_ULPI_NXT_PY2,
-       TEGRA_PIN_ULPI_STP_PY3,
-};
-
-static const unsigned ddrc_pins[] = {
-       TEGRA_PIN_DDR_COMP_PD,
-       TEGRA_PIN_DDR_COMP_PU,
-};
-
-static const unsigned pmca_pins[] = {
-       TEGRA_PIN_LED_BLINK_PBB0,
-};
-
-static const unsigned pmcb_pins[] = {
-       TEGRA_PIN_SYS_CLK_REQ_PZ5,
-};
-
-static const unsigned pmcc_pins[] = {
-       TEGRA_PIN_CORE_PWR_REQ,
-};
-
-static const unsigned pmcd_pins[] = {
-       TEGRA_PIN_CPU_PWR_REQ,
-};
-
-static const unsigned pmce_pins[] = {
-       TEGRA_PIN_PWR_INT_N,
-};
-
-static const unsigned xm2c_pins[] = {
-       TEGRA_PIN_DDR_A0,
-       TEGRA_PIN_DDR_A1,
-       TEGRA_PIN_DDR_A2,
-       TEGRA_PIN_DDR_A3,
-       TEGRA_PIN_DDR_A4,
-       TEGRA_PIN_DDR_A5,
-       TEGRA_PIN_DDR_A6,
-       TEGRA_PIN_DDR_A7,
-       TEGRA_PIN_DDR_A8,
-       TEGRA_PIN_DDR_A9,
-       TEGRA_PIN_DDR_A10,
-       TEGRA_PIN_DDR_A11,
-       TEGRA_PIN_DDR_A12,
-       TEGRA_PIN_DDR_A13,
-       TEGRA_PIN_DDR_A14,
-       TEGRA_PIN_DDR_CAS_N,
-       TEGRA_PIN_DDR_BA0,
-       TEGRA_PIN_DDR_BA1,
-       TEGRA_PIN_DDR_BA2,
-       TEGRA_PIN_DDR_DQS0P,
-       TEGRA_PIN_DDR_DQS0N,
-       TEGRA_PIN_DDR_DQS1P,
-       TEGRA_PIN_DDR_DQS1N,
-       TEGRA_PIN_DDR_DQS2P,
-       TEGRA_PIN_DDR_DQS2N,
-       TEGRA_PIN_DDR_DQS3P,
-       TEGRA_PIN_DDR_DQS3N,
-       TEGRA_PIN_DDR_CS0_N,
-       TEGRA_PIN_DDR_CS1_N,
-       TEGRA_PIN_DDR_CKE0,
-       TEGRA_PIN_DDR_CKE1,
-       TEGRA_PIN_DDR_CLK,
-       TEGRA_PIN_DDR_CLK_N,
-       TEGRA_PIN_DDR_DM0,
-       TEGRA_PIN_DDR_DM1,
-       TEGRA_PIN_DDR_DM2,
-       TEGRA_PIN_DDR_DM3,
-       TEGRA_PIN_DDR_ODT,
-       TEGRA_PIN_DDR_RAS_N,
-       TEGRA_PIN_DDR_WE_N,
-       TEGRA_PIN_DDR_QUSE0,
-       TEGRA_PIN_DDR_QUSE1,
-       TEGRA_PIN_DDR_QUSE2,
-       TEGRA_PIN_DDR_QUSE3,
-};
-
-static const unsigned xm2d_pins[] = {
-       TEGRA_PIN_DDR_DQ0,
-       TEGRA_PIN_DDR_DQ1,
-       TEGRA_PIN_DDR_DQ2,
-       TEGRA_PIN_DDR_DQ3,
-       TEGRA_PIN_DDR_DQ4,
-       TEGRA_PIN_DDR_DQ5,
-       TEGRA_PIN_DDR_DQ6,
-       TEGRA_PIN_DDR_DQ7,
-       TEGRA_PIN_DDR_DQ8,
-       TEGRA_PIN_DDR_DQ9,
-       TEGRA_PIN_DDR_DQ10,
-       TEGRA_PIN_DDR_DQ11,
-       TEGRA_PIN_DDR_DQ12,
-       TEGRA_PIN_DDR_DQ13,
-       TEGRA_PIN_DDR_DQ14,
-       TEGRA_PIN_DDR_DQ15,
-       TEGRA_PIN_DDR_DQ16,
-       TEGRA_PIN_DDR_DQ17,
-       TEGRA_PIN_DDR_DQ18,
-       TEGRA_PIN_DDR_DQ19,
-       TEGRA_PIN_DDR_DQ20,
-       TEGRA_PIN_DDR_DQ21,
-       TEGRA_PIN_DDR_DQ22,
-       TEGRA_PIN_DDR_DQ23,
-       TEGRA_PIN_DDR_DQ24,
-       TEGRA_PIN_DDR_DQ25,
-       TEGRA_PIN_DDR_DQ26,
-       TEGRA_PIN_DDR_DQ27,
-       TEGRA_PIN_DDR_DQ28,
-       TEGRA_PIN_DDR_DQ29,
-       TEGRA_PIN_DDR_DQ30,
-       TEGRA_PIN_DDR_DQ31,
-};
-
-static const unsigned drive_ao1_pins[] = {
-       TEGRA_PIN_SYS_RESET,
-       TEGRA_PIN_PWR_I2C_SCL_PZ6,
-       TEGRA_PIN_PWR_I2C_SDA_PZ7,
-       TEGRA_PIN_KB_ROW0_PR0,
-       TEGRA_PIN_KB_ROW1_PR1,
-       TEGRA_PIN_KB_ROW2_PR2,
-       TEGRA_PIN_KB_ROW3_PR3,
-       TEGRA_PIN_KB_ROW4_PR4,
-       TEGRA_PIN_KB_ROW5_PR5,
-       TEGRA_PIN_KB_ROW6_PR6,
-       TEGRA_PIN_KB_ROW7_PR7,
-};
-
-static const unsigned drive_ao2_pins[] = {
-       TEGRA_PIN_KB_ROW8_PS0,
-       TEGRA_PIN_KB_ROW9_PS1,
-       TEGRA_PIN_KB_ROW10_PS2,
-       TEGRA_PIN_KB_ROW11_PS3,
-       TEGRA_PIN_KB_ROW12_PS4,
-       TEGRA_PIN_KB_ROW13_PS5,
-       TEGRA_PIN_KB_ROW14_PS6,
-       TEGRA_PIN_KB_ROW15_PS7,
-       TEGRA_PIN_KB_COL0_PQ0,
-       TEGRA_PIN_KB_COL1_PQ1,
-       TEGRA_PIN_KB_COL2_PQ2,
-       TEGRA_PIN_KB_COL3_PQ3,
-       TEGRA_PIN_KB_COL4_PQ4,
-       TEGRA_PIN_KB_COL5_PQ5,
-       TEGRA_PIN_KB_COL6_PQ6,
-       TEGRA_PIN_KB_COL7_PQ7,
-       TEGRA_PIN_LED_BLINK_PBB0,
-       TEGRA_PIN_SYS_CLK_REQ_PZ5,
-       TEGRA_PIN_CORE_PWR_REQ,
-       TEGRA_PIN_CPU_PWR_REQ,
-       TEGRA_PIN_PWR_INT_N,
-       TEGRA_PIN_CLK_32_K_IN,
-};
-
-static const unsigned drive_at1_pins[] = {
-       TEGRA_PIN_GMI_IORDY_PI5,
-       TEGRA_PIN_GMI_AD8_PH0,
-       TEGRA_PIN_GMI_AD9_PH1,
-       TEGRA_PIN_GMI_AD10_PH2,
-       TEGRA_PIN_GMI_AD11_PH3,
-       TEGRA_PIN_GMI_AD12_PH4,
-       TEGRA_PIN_GMI_AD13_PH5,
-       TEGRA_PIN_GMI_AD14_PH6,
-       TEGRA_PIN_GMI_AD15_PH7,
-       TEGRA_PIN_GMI_CS7_N_PI6,
-       TEGRA_PIN_GMI_DPD_PT7,
-       TEGRA_PIN_GEN2_I2C_SCL_PT5,
-       TEGRA_PIN_GEN2_I2C_SDA_PT6,
-};
-
-static const unsigned drive_at2_pins[] = {
-       TEGRA_PIN_GMI_WAIT_PI7,
-       TEGRA_PIN_GMI_ADV_N_PK0,
-       TEGRA_PIN_GMI_CLK_PK1,
-       TEGRA_PIN_GMI_CS6_N_PI3,
-       TEGRA_PIN_GMI_CS5_N_PI2,
-       TEGRA_PIN_GMI_CS4_N_PK2,
-       TEGRA_PIN_GMI_CS3_N_PK4,
-       TEGRA_PIN_GMI_CS2_N_PK3,
-       TEGRA_PIN_GMI_AD0_PG0,
-       TEGRA_PIN_GMI_AD1_PG1,
-       TEGRA_PIN_GMI_AD2_PG2,
-       TEGRA_PIN_GMI_AD3_PG3,
-       TEGRA_PIN_GMI_AD4_PG4,
-       TEGRA_PIN_GMI_AD5_PG5,
-       TEGRA_PIN_GMI_AD6_PG6,
-       TEGRA_PIN_GMI_AD7_PG7,
-       TEGRA_PIN_GMI_HIOW_N_PI0,
-       TEGRA_PIN_GMI_HIOR_N_PI1,
-       TEGRA_PIN_GMI_RST_N_PI4,
-};
-
-static const unsigned drive_cdev1_pins[] = {
-       TEGRA_PIN_DAP_MCLK1_PW4,
-};
-
-static const unsigned drive_cdev2_pins[] = {
-       TEGRA_PIN_DAP_MCLK2_PW5,
-};
-
-static const unsigned drive_csus_pins[] = {
-       TEGRA_PIN_VI_MCLK_PT1,
-};
-
-static const unsigned drive_dap1_pins[] = {
-       TEGRA_PIN_DAP1_FS_PN0,
-       TEGRA_PIN_DAP1_DIN_PN1,
-       TEGRA_PIN_DAP1_DOUT_PN2,
-       TEGRA_PIN_DAP1_SCLK_PN3,
-       TEGRA_PIN_SPDIF_OUT_PK5,
-       TEGRA_PIN_SPDIF_IN_PK6,
-};
-
-static const unsigned drive_dap2_pins[] = {
-       TEGRA_PIN_DAP2_FS_PA2,
-       TEGRA_PIN_DAP2_SCLK_PA3,
-       TEGRA_PIN_DAP2_DIN_PA4,
-       TEGRA_PIN_DAP2_DOUT_PA5,
-};
-
-static const unsigned drive_dap3_pins[] = {
-       TEGRA_PIN_DAP3_FS_PP0,
-       TEGRA_PIN_DAP3_DIN_PP1,
-       TEGRA_PIN_DAP3_DOUT_PP2,
-       TEGRA_PIN_DAP3_SCLK_PP3,
-};
-
-static const unsigned drive_dap4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PP4,
-       TEGRA_PIN_DAP4_DIN_PP5,
-       TEGRA_PIN_DAP4_DOUT_PP6,
-       TEGRA_PIN_DAP4_SCLK_PP7,
-};
-
-static const unsigned drive_dbg_pins[] = {
-       TEGRA_PIN_PU0,
-       TEGRA_PIN_PU1,
-       TEGRA_PIN_PU2,
-       TEGRA_PIN_PU3,
-       TEGRA_PIN_PU4,
-       TEGRA_PIN_PU5,
-       TEGRA_PIN_PU6,
-       TEGRA_PIN_JTAG_RTCK_PU7,
-       TEGRA_PIN_GEN1_I2C_SDA_PC5,
-       TEGRA_PIN_GEN1_I2C_SCL_PC4,
-       TEGRA_PIN_JTAG_TRST_N,
-       TEGRA_PIN_JTAG_TDO,
-       TEGRA_PIN_JTAG_TMS,
-       TEGRA_PIN_JTAG_TCK,
-       TEGRA_PIN_JTAG_TDI,
-       TEGRA_PIN_TEST_MODE_EN,
-};
-
-static const unsigned drive_lcd1_pins[] = {
-       TEGRA_PIN_LCD_PWR1_PC1,
-       TEGRA_PIN_LCD_PWR2_PC6,
-       TEGRA_PIN_LCD_SDIN_PZ2,
-       TEGRA_PIN_LCD_SDOUT_PN5,
-       TEGRA_PIN_LCD_WR_N_PZ3,
-       TEGRA_PIN_LCD_CS0_N_PN4,
-       TEGRA_PIN_LCD_DC0_PN6,
-       TEGRA_PIN_LCD_SCK_PZ4,
-};
-
-static const unsigned drive_lcd2_pins[] = {
-       TEGRA_PIN_LCD_PWR0_PB2,
-       TEGRA_PIN_LCD_PCLK_PB3,
-       TEGRA_PIN_LCD_DE_PJ1,
-       TEGRA_PIN_LCD_HSYNC_PJ3,
-       TEGRA_PIN_LCD_VSYNC_PJ4,
-       TEGRA_PIN_LCD_D0_PE0,
-       TEGRA_PIN_LCD_D1_PE1,
-       TEGRA_PIN_LCD_D2_PE2,
-       TEGRA_PIN_LCD_D3_PE3,
-       TEGRA_PIN_LCD_D4_PE4,
-       TEGRA_PIN_LCD_D5_PE5,
-       TEGRA_PIN_LCD_D6_PE6,
-       TEGRA_PIN_LCD_D7_PE7,
-       TEGRA_PIN_LCD_D8_PF0,
-       TEGRA_PIN_LCD_D9_PF1,
-       TEGRA_PIN_LCD_D10_PF2,
-       TEGRA_PIN_LCD_D11_PF3,
-       TEGRA_PIN_LCD_D12_PF4,
-       TEGRA_PIN_LCD_D13_PF5,
-       TEGRA_PIN_LCD_D14_PF6,
-       TEGRA_PIN_LCD_D15_PF7,
-       TEGRA_PIN_LCD_D16_PM0,
-       TEGRA_PIN_LCD_D17_PM1,
-       TEGRA_PIN_LCD_D18_PM2,
-       TEGRA_PIN_LCD_D19_PM3,
-       TEGRA_PIN_LCD_D20_PM4,
-       TEGRA_PIN_LCD_D21_PM5,
-       TEGRA_PIN_LCD_D22_PM6,
-       TEGRA_PIN_LCD_D23_PM7,
-       TEGRA_PIN_LCD_CS1_N_PW0,
-       TEGRA_PIN_LCD_M1_PW1,
-       TEGRA_PIN_LCD_DC1_PV7,
-       TEGRA_PIN_HDMI_INT_N_PN7,
-};
-
-static const unsigned drive_sdmmc2_pins[] = {
-       TEGRA_PIN_SDIO3_DAT4_PD1,
-       TEGRA_PIN_SDIO3_DAT5_PD0,
-       TEGRA_PIN_SDIO3_DAT6_PD3,
-       TEGRA_PIN_SDIO3_DAT7_PD4,
-};
-
-static const unsigned drive_sdmmc3_pins[] = {
-       TEGRA_PIN_SDIO3_CLK_PA6,
-       TEGRA_PIN_SDIO3_CMD_PA7,
-       TEGRA_PIN_SDIO3_DAT0_PB7,
-       TEGRA_PIN_SDIO3_DAT1_PB6,
-       TEGRA_PIN_SDIO3_DAT2_PB5,
-       TEGRA_PIN_SDIO3_DAT3_PB4,
-       TEGRA_PIN_PV4,
-       TEGRA_PIN_PV5,
-       TEGRA_PIN_PV6,
-};
-
-static const unsigned drive_spi_pins[] = {
-       TEGRA_PIN_SPI2_MOSI_PX0,
-       TEGRA_PIN_SPI2_MISO_PX1,
-       TEGRA_PIN_SPI2_SCK_PX2,
-       TEGRA_PIN_SPI2_CS0_N_PX3,
-       TEGRA_PIN_SPI1_MOSI_PX4,
-       TEGRA_PIN_SPI1_SCK_PX5,
-       TEGRA_PIN_SPI1_CS0_N_PX6,
-       TEGRA_PIN_SPI1_MISO_PX7,
-       TEGRA_PIN_SPI2_CS1_N_PW2,
-       TEGRA_PIN_SPI2_CS2_N_PW3,
-};
-
-static const unsigned drive_uaa_pins[] = {
-       TEGRA_PIN_ULPI_DATA0_PO1,
-       TEGRA_PIN_ULPI_DATA1_PO2,
-       TEGRA_PIN_ULPI_DATA2_PO3,
-       TEGRA_PIN_ULPI_DATA3_PO4,
-};
-
-static const unsigned drive_uab_pins[] = {
-       TEGRA_PIN_ULPI_DATA4_PO5,
-       TEGRA_PIN_ULPI_DATA5_PO6,
-       TEGRA_PIN_ULPI_DATA6_PO7,
-       TEGRA_PIN_ULPI_DATA7_PO0,
-       TEGRA_PIN_PV0,
-       TEGRA_PIN_PV1,
-       TEGRA_PIN_PV2,
-       TEGRA_PIN_PV3,
-};
-
-static const unsigned drive_uart2_pins[] = {
-       TEGRA_PIN_UART2_TXD_PC2,
-       TEGRA_PIN_UART2_RXD_PC3,
-       TEGRA_PIN_UART2_RTS_N_PJ6,
-       TEGRA_PIN_UART2_CTS_N_PJ5,
-};
-
-static const unsigned drive_uart3_pins[] = {
-       TEGRA_PIN_UART3_TXD_PW6,
-       TEGRA_PIN_UART3_RXD_PW7,
-       TEGRA_PIN_UART3_RTS_N_PC0,
-       TEGRA_PIN_UART3_CTS_N_PA1,
-};
-
-static const unsigned drive_vi1_pins[] = {
-       TEGRA_PIN_VI_D0_PT4,
-       TEGRA_PIN_VI_D1_PD5,
-       TEGRA_PIN_VI_D2_PL0,
-       TEGRA_PIN_VI_D3_PL1,
-       TEGRA_PIN_VI_D4_PL2,
-       TEGRA_PIN_VI_D5_PL3,
-       TEGRA_PIN_VI_D6_PL4,
-       TEGRA_PIN_VI_D7_PL5,
-       TEGRA_PIN_VI_D8_PL6,
-       TEGRA_PIN_VI_D9_PL7,
-       TEGRA_PIN_VI_D10_PT2,
-       TEGRA_PIN_VI_D11_PT3,
-       TEGRA_PIN_VI_PCLK_PT0,
-       TEGRA_PIN_VI_VSYNC_PD6,
-       TEGRA_PIN_VI_HSYNC_PD7,
-};
-
-static const unsigned drive_vi2_pins[] = {
-       TEGRA_PIN_VI_GP0_PBB1,
-       TEGRA_PIN_CAM_I2C_SCL_PBB2,
-       TEGRA_PIN_CAM_I2C_SDA_PBB3,
-       TEGRA_PIN_VI_GP3_PBB4,
-       TEGRA_PIN_VI_GP4_PBB5,
-       TEGRA_PIN_VI_GP5_PD2,
-       TEGRA_PIN_VI_GP6_PA0,
-};
-
-static const unsigned drive_xm2a_pins[] = {
-       TEGRA_PIN_DDR_A0,
-       TEGRA_PIN_DDR_A1,
-       TEGRA_PIN_DDR_A2,
-       TEGRA_PIN_DDR_A3,
-       TEGRA_PIN_DDR_A4,
-       TEGRA_PIN_DDR_A5,
-       TEGRA_PIN_DDR_A6,
-       TEGRA_PIN_DDR_A7,
-       TEGRA_PIN_DDR_A8,
-       TEGRA_PIN_DDR_A9,
-       TEGRA_PIN_DDR_A10,
-       TEGRA_PIN_DDR_A11,
-       TEGRA_PIN_DDR_A12,
-       TEGRA_PIN_DDR_A13,
-       TEGRA_PIN_DDR_A14,
-       TEGRA_PIN_DDR_BA0,
-       TEGRA_PIN_DDR_BA1,
-       TEGRA_PIN_DDR_BA2,
-       TEGRA_PIN_DDR_CS0_N,
-       TEGRA_PIN_DDR_CS1_N,
-       TEGRA_PIN_DDR_ODT,
-       TEGRA_PIN_DDR_RAS_N,
-       TEGRA_PIN_DDR_CAS_N,
-       TEGRA_PIN_DDR_WE_N,
-       TEGRA_PIN_DDR_CKE0,
-       TEGRA_PIN_DDR_CKE1,
-};
-
-static const unsigned drive_xm2c_pins[] = {
-       TEGRA_PIN_DDR_DQS0P,
-       TEGRA_PIN_DDR_DQS0N,
-       TEGRA_PIN_DDR_DQS1P,
-       TEGRA_PIN_DDR_DQS1N,
-       TEGRA_PIN_DDR_DQS2P,
-       TEGRA_PIN_DDR_DQS2N,
-       TEGRA_PIN_DDR_DQS3P,
-       TEGRA_PIN_DDR_DQS3N,
-       TEGRA_PIN_DDR_QUSE0,
-       TEGRA_PIN_DDR_QUSE1,
-       TEGRA_PIN_DDR_QUSE2,
-       TEGRA_PIN_DDR_QUSE3,
-};
-
-static const unsigned drive_xm2d_pins[] = {
-       TEGRA_PIN_DDR_DQ0,
-       TEGRA_PIN_DDR_DQ1,
-       TEGRA_PIN_DDR_DQ2,
-       TEGRA_PIN_DDR_DQ3,
-       TEGRA_PIN_DDR_DQ4,
-       TEGRA_PIN_DDR_DQ5,
-       TEGRA_PIN_DDR_DQ6,
-       TEGRA_PIN_DDR_DQ7,
-       TEGRA_PIN_DDR_DQ8,
-       TEGRA_PIN_DDR_DQ9,
-       TEGRA_PIN_DDR_DQ10,
-       TEGRA_PIN_DDR_DQ11,
-       TEGRA_PIN_DDR_DQ12,
-       TEGRA_PIN_DDR_DQ13,
-       TEGRA_PIN_DDR_DQ14,
-       TEGRA_PIN_DDR_DQ15,
-       TEGRA_PIN_DDR_DQ16,
-       TEGRA_PIN_DDR_DQ17,
-       TEGRA_PIN_DDR_DQ18,
-       TEGRA_PIN_DDR_DQ19,
-       TEGRA_PIN_DDR_DQ20,
-       TEGRA_PIN_DDR_DQ21,
-       TEGRA_PIN_DDR_DQ22,
-       TEGRA_PIN_DDR_DQ23,
-       TEGRA_PIN_DDR_DQ24,
-       TEGRA_PIN_DDR_DQ25,
-       TEGRA_PIN_DDR_DQ26,
-       TEGRA_PIN_DDR_DQ27,
-       TEGRA_PIN_DDR_DQ28,
-       TEGRA_PIN_DDR_DQ29,
-       TEGRA_PIN_DDR_DQ30,
-       TEGRA_PIN_DDR_DQ31,
-       TEGRA_PIN_DDR_DM0,
-       TEGRA_PIN_DDR_DM1,
-       TEGRA_PIN_DDR_DM2,
-       TEGRA_PIN_DDR_DM3,
-};
-
-static const unsigned drive_xm2clk_pins[] = {
-       TEGRA_PIN_DDR_CLK,
-       TEGRA_PIN_DDR_CLK_N,
-};
-
-static const unsigned drive_sdio1_pins[] = {
-       TEGRA_PIN_SDIO1_CLK_PZ0,
-       TEGRA_PIN_SDIO1_CMD_PZ1,
-       TEGRA_PIN_SDIO1_DAT0_PY7,
-       TEGRA_PIN_SDIO1_DAT1_PY6,
-       TEGRA_PIN_SDIO1_DAT2_PY5,
-       TEGRA_PIN_SDIO1_DAT3_PY4,
-};
-
-static const unsigned drive_crt_pins[] = {
-       TEGRA_PIN_CRT_HSYNC,
-       TEGRA_PIN_CRT_VSYNC,
-};
-
-static const unsigned drive_ddc_pins[] = {
-       TEGRA_PIN_DDC_SCL,
-       TEGRA_PIN_DDC_SDA,
-};
-
-static const unsigned drive_gma_pins[] = {
-       TEGRA_PIN_GMI_AD20_PAA0,
-       TEGRA_PIN_GMI_AD21_PAA1,
-       TEGRA_PIN_GMI_AD22_PAA2,
-       TEGRA_PIN_GMI_AD23_PAA3,
-};
-
-static const unsigned drive_gmb_pins[] = {
-       TEGRA_PIN_GMI_WP_N_PC7,
-};
-
-static const unsigned drive_gmc_pins[] = {
-       TEGRA_PIN_GMI_AD16_PJ7,
-       TEGRA_PIN_GMI_AD17_PB0,
-       TEGRA_PIN_GMI_AD18_PB1,
-       TEGRA_PIN_GMI_AD19_PK7,
-};
-
-static const unsigned drive_gmd_pins[] = {
-       TEGRA_PIN_GMI_CS0_N_PJ0,
-       TEGRA_PIN_GMI_CS1_N_PJ2,
-};
-
-static const unsigned drive_gme_pins[] = {
-       TEGRA_PIN_GMI_AD24_PAA4,
-       TEGRA_PIN_GMI_AD25_PAA5,
-       TEGRA_PIN_GMI_AD26_PAA6,
-       TEGRA_PIN_GMI_AD27_PAA7,
-};
-
-static const unsigned drive_owr_pins[] = {
-       TEGRA_PIN_OWC,
-};
-
-static const unsigned drive_uda_pins[] = {
-       TEGRA_PIN_ULPI_CLK_PY0,
-       TEGRA_PIN_ULPI_DIR_PY1,
-       TEGRA_PIN_ULPI_NXT_PY2,
-       TEGRA_PIN_ULPI_STP_PY3,
-};
-
-enum tegra_mux {
-       TEGRA_MUX_AHB_CLK,
-       TEGRA_MUX_APB_CLK,
-       TEGRA_MUX_AUDIO_SYNC,
-       TEGRA_MUX_CRT,
-       TEGRA_MUX_DAP1,
-       TEGRA_MUX_DAP2,
-       TEGRA_MUX_DAP3,
-       TEGRA_MUX_DAP4,
-       TEGRA_MUX_DAP5,
-       TEGRA_MUX_DISPLAYA,
-       TEGRA_MUX_DISPLAYB,
-       TEGRA_MUX_EMC_TEST0_DLL,
-       TEGRA_MUX_EMC_TEST1_DLL,
-       TEGRA_MUX_GMI,
-       TEGRA_MUX_GMI_INT,
-       TEGRA_MUX_HDMI,
-       TEGRA_MUX_I2CP,
-       TEGRA_MUX_I2C1,
-       TEGRA_MUX_I2C2,
-       TEGRA_MUX_I2C3,
-       TEGRA_MUX_IDE,
-       TEGRA_MUX_IRDA,
-       TEGRA_MUX_KBC,
-       TEGRA_MUX_MIO,
-       TEGRA_MUX_MIPI_HS,
-       TEGRA_MUX_NAND,
-       TEGRA_MUX_OSC,
-       TEGRA_MUX_OWR,
-       TEGRA_MUX_PCIE,
-       TEGRA_MUX_PLLA_OUT,
-       TEGRA_MUX_PLLC_OUT1,
-       TEGRA_MUX_PLLM_OUT1,
-       TEGRA_MUX_PLLP_OUT2,
-       TEGRA_MUX_PLLP_OUT3,
-       TEGRA_MUX_PLLP_OUT4,
-       TEGRA_MUX_PWM,
-       TEGRA_MUX_PWR_INTR,
-       TEGRA_MUX_PWR_ON,
-       TEGRA_MUX_RSVD1,
-       TEGRA_MUX_RSVD2,
-       TEGRA_MUX_RSVD3,
-       TEGRA_MUX_RSVD4,
-       TEGRA_MUX_RTCK,
-       TEGRA_MUX_SDIO1,
-       TEGRA_MUX_SDIO2,
-       TEGRA_MUX_SDIO3,
-       TEGRA_MUX_SDIO4,
-       TEGRA_MUX_SFLASH,
-       TEGRA_MUX_SPDIF,
-       TEGRA_MUX_SPI1,
-       TEGRA_MUX_SPI2,
-       TEGRA_MUX_SPI2_ALT,
-       TEGRA_MUX_SPI3,
-       TEGRA_MUX_SPI4,
-       TEGRA_MUX_TRACE,
-       TEGRA_MUX_TWC,
-       TEGRA_MUX_UARTA,
-       TEGRA_MUX_UARTB,
-       TEGRA_MUX_UARTC,
-       TEGRA_MUX_UARTD,
-       TEGRA_MUX_UARTE,
-       TEGRA_MUX_ULPI,
-       TEGRA_MUX_VI,
-       TEGRA_MUX_VI_SENSOR_CLK,
-       TEGRA_MUX_XIO,
-};
-
-#define FUNCTION(fname)                                        \
-       {                                               \
-               .name = #fname,                         \
-       }
-
-static struct tegra_function tegra20_functions[] = {
-       FUNCTION(ahb_clk),
-       FUNCTION(apb_clk),
-       FUNCTION(audio_sync),
-       FUNCTION(crt),
-       FUNCTION(dap1),
-       FUNCTION(dap2),
-       FUNCTION(dap3),
-       FUNCTION(dap4),
-       FUNCTION(dap5),
-       FUNCTION(displaya),
-       FUNCTION(displayb),
-       FUNCTION(emc_test0_dll),
-       FUNCTION(emc_test1_dll),
-       FUNCTION(gmi),
-       FUNCTION(gmi_int),
-       FUNCTION(hdmi),
-       FUNCTION(i2cp),
-       FUNCTION(i2c1),
-       FUNCTION(i2c2),
-       FUNCTION(i2c3),
-       FUNCTION(ide),
-       FUNCTION(irda),
-       FUNCTION(kbc),
-       FUNCTION(mio),
-       FUNCTION(mipi_hs),
-       FUNCTION(nand),
-       FUNCTION(osc),
-       FUNCTION(owr),
-       FUNCTION(pcie),
-       FUNCTION(plla_out),
-       FUNCTION(pllc_out1),
-       FUNCTION(pllm_out1),
-       FUNCTION(pllp_out2),
-       FUNCTION(pllp_out3),
-       FUNCTION(pllp_out4),
-       FUNCTION(pwm),
-       FUNCTION(pwr_intr),
-       FUNCTION(pwr_on),
-       FUNCTION(rsvd1),
-       FUNCTION(rsvd2),
-       FUNCTION(rsvd3),
-       FUNCTION(rsvd4),
-       FUNCTION(rtck),
-       FUNCTION(sdio1),
-       FUNCTION(sdio2),
-       FUNCTION(sdio3),
-       FUNCTION(sdio4),
-       FUNCTION(sflash),
-       FUNCTION(spdif),
-       FUNCTION(spi1),
-       FUNCTION(spi2),
-       FUNCTION(spi2_alt),
-       FUNCTION(spi3),
-       FUNCTION(spi4),
-       FUNCTION(trace),
-       FUNCTION(twc),
-       FUNCTION(uarta),
-       FUNCTION(uartb),
-       FUNCTION(uartc),
-       FUNCTION(uartd),
-       FUNCTION(uarte),
-       FUNCTION(ulpi),
-       FUNCTION(vi),
-       FUNCTION(vi_sensor_clk),
-       FUNCTION(xio),
-};
-
-#define TRISTATE_REG_A         0x14
-#define PIN_MUX_CTL_REG_A      0x80
-#define PULLUPDOWN_REG_A       0xa0
-#define PINGROUP_REG_A         0x868
-
-/* Pin group with mux control, and typically tri-state and pull-up/down too */
-#define MUX_PG(pg_name, f0, f1, f2, f3,                                \
-              tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)      \
-       {                                                       \
-               .name = #pg_name,                               \
-               .pins = pg_name##_pins,                         \
-               .npins = ARRAY_SIZE(pg_name##_pins),            \
-               .funcs = {                                      \
-                       TEGRA_MUX_ ## f0,                       \
-                       TEGRA_MUX_ ## f1,                       \
-                       TEGRA_MUX_ ## f2,                       \
-                       TEGRA_MUX_ ## f3,                       \
-               },                                              \
-               .mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A),       \
-               .mux_bank = 1,                                  \
-               .mux_bit = mux_b,                               \
-               .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A),      \
-               .pupd_bank = 2,                                 \
-               .pupd_bit = pupd_b,                             \
-               .tri_reg = ((tri_r) - TRISTATE_REG_A),          \
-               .tri_bank = 0,                                  \
-               .tri_bit = tri_b,                               \
-               .einput_bit = -1,                               \
-               .odrain_bit = -1,                               \
-               .lock_bit = -1,                                 \
-               .ioreset_bit = -1,                              \
-               .rcv_sel_bit = -1,                              \
-               .drv_reg = -1,                                  \
-       }
-
-/* Pin groups with only pull up and pull down control */
-#define PULL_PG(pg_name, pupd_r, pupd_b)                       \
-       {                                                       \
-               .name = #pg_name,                               \
-               .pins = pg_name##_pins,                         \
-               .npins = ARRAY_SIZE(pg_name##_pins),            \
-               .mux_reg = -1,                                  \
-               .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A),      \
-               .pupd_bank = 2,                                 \
-               .pupd_bit = pupd_b,                             \
-               .drv_reg = -1,                                  \
-       }
-
-/* Pin groups for drive strength registers (configurable version) */
-#define DRV_PG_EXT(pg_name, r, hsm_b, schmitt_b, lpmd_b,       \
-                  drvdn_b, drvup_b,                            \
-                  slwr_b, slwr_w, slwf_b, slwf_w)              \
-       {                                                       \
-               .name = "drive_" #pg_name,                      \
-               .pins = drive_##pg_name##_pins,                 \
-               .npins = ARRAY_SIZE(drive_##pg_name##_pins),    \
-               .mux_reg = -1,                                  \
-               .pupd_reg = -1,                                 \
-               .tri_reg = -1,                                  \
-               .drv_reg = ((r) - PINGROUP_REG_A),              \
-               .drv_bank = 3,                                  \
-               .hsm_bit = hsm_b,                               \
-               .schmitt_bit = schmitt_b,                       \
-               .lpmd_bit = lpmd_b,                             \
-               .drvdn_bit = drvdn_b,                           \
-               .drvdn_width = 5,                               \
-               .drvup_bit = drvup_b,                           \
-               .drvup_width = 5,                               \
-               .slwr_bit = slwr_b,                             \
-               .slwr_width = slwr_w,                           \
-               .slwf_bit = slwf_b,                             \
-               .slwf_width = slwf_w,                           \
-               .drvtype_bit = -1,                              \
-       }
-
-/* Pin groups for drive strength registers (simple version) */
-#define DRV_PG(pg_name, r) \
-       DRV_PG_EXT(pg_name, r, 2,  3,  4, 12, 20, 28, 2, 30, 2)
-
-static const struct tegra_pingroup tegra20_groups[] = {
-       /*     name,   f0,        f1,        f2,        f3,            tri r/b,  mux r/b,  pupd r/b */
-       MUX_PG(ata,    IDE,       NAND,      GMI,       RSVD4,         0x14, 0,  0x80, 24, 0xa0, 0),
-       MUX_PG(atb,    IDE,       NAND,      GMI,       SDIO4,         0x14, 1,  0x80, 16, 0xa0, 2),
-       MUX_PG(atc,    IDE,       NAND,      GMI,       SDIO4,         0x14, 2,  0x80, 22, 0xa0, 4),
-       MUX_PG(atd,    IDE,       NAND,      GMI,       SDIO4,         0x14, 3,  0x80, 20, 0xa0, 6),
-       MUX_PG(ate,    IDE,       NAND,      GMI,       RSVD4,         0x18, 25, 0x80, 12, 0xa0, 8),
-       MUX_PG(cdev1,  OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    0x14, 4,  0x88, 2,  0xa8, 0),
-       MUX_PG(cdev2,  OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     0x14, 5,  0x88, 4,  0xa8, 2),
-       MUX_PG(crtp,   CRT,       RSVD2,     RSVD3,     RSVD4,         0x20, 14, 0x98, 20, 0xa4, 24),
-       MUX_PG(csus,   PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, 0x14, 6,  0x88, 6,  0xac, 24),
-       MUX_PG(dap1,   DAP1,      RSVD2,     GMI,       SDIO2,         0x14, 7,  0x88, 20, 0xa0, 10),
-       MUX_PG(dap2,   DAP2,      TWC,       RSVD3,     GMI,           0x14, 8,  0x88, 22, 0xa0, 12),
-       MUX_PG(dap3,   DAP3,      RSVD2,     RSVD3,     RSVD4,         0x14, 9,  0x88, 24, 0xa0, 14),
-       MUX_PG(dap4,   DAP4,      RSVD2,     GMI,       RSVD4,         0x14, 10, 0x88, 26, 0xa0, 16),
-       MUX_PG(ddc,    I2C2,      RSVD2,     RSVD3,     RSVD4,         0x18, 31, 0x88, 0,  0xb0, 28),
-       MUX_PG(dta,    RSVD1,     SDIO2,     VI,        RSVD4,         0x14, 11, 0x84, 20, 0xa0, 18),
-       MUX_PG(dtb,    RSVD1,     RSVD2,     VI,        SPI1,          0x14, 12, 0x84, 22, 0xa0, 20),
-       MUX_PG(dtc,    RSVD1,     RSVD2,     VI,        RSVD4,         0x14, 13, 0x84, 26, 0xa0, 22),
-       MUX_PG(dtd,    RSVD1,     SDIO2,     VI,        RSVD4,         0x14, 14, 0x84, 28, 0xa0, 24),
-       MUX_PG(dte,    RSVD1,     RSVD2,     VI,        SPI1,          0x14, 15, 0x84, 30, 0xa0, 26),
-       MUX_PG(dtf,    I2C3,      RSVD2,     VI,        RSVD4,         0x20, 12, 0x98, 30, 0xa0, 28),
-       MUX_PG(gma,    UARTE,     SPI3,      GMI,       SDIO4,         0x14, 28, 0x84, 0,  0xb0, 20),
-       MUX_PG(gmb,    IDE,       NAND,      GMI,       GMI_INT,       0x18, 29, 0x88, 28, 0xb0, 22),
-       MUX_PG(gmc,    UARTD,     SPI4,      GMI,       SFLASH,        0x14, 29, 0x84, 2,  0xb0, 24),
-       MUX_PG(gmd,    RSVD1,     NAND,      GMI,       SFLASH,        0x18, 30, 0x88, 30, 0xb0, 26),
-       MUX_PG(gme,    RSVD1,     DAP5,      GMI,       SDIO4,         0x18, 0,  0x8c, 0,  0xa8, 24),
-       MUX_PG(gpu,    PWM,       UARTA,     GMI,       RSVD4,         0x14, 16, 0x8c, 4,  0xa4, 20),
-       MUX_PG(gpu7,   RTCK,      RSVD2,     RSVD3,     RSVD4,         0x20, 11, 0x98, 28, 0xa4, 6),
-       MUX_PG(gpv,    PCIE,      RSVD2,     RSVD3,     RSVD4,         0x14, 17, 0x8c, 2,  0xa0, 30),
-       MUX_PG(hdint,  HDMI,      RSVD2,     RSVD3,     RSVD4,         0x1c, 23, 0x84, 4,  -1,   -1),
-       MUX_PG(i2cp,   I2CP,      RSVD2,     RSVD3,     RSVD4,         0x14, 18, 0x88, 8,  0xa4, 2),
-       MUX_PG(irrx,   UARTA,     UARTB,     GMI,       SPI4,          0x14, 20, 0x88, 18, 0xa8, 22),
-       MUX_PG(irtx,   UARTA,     UARTB,     GMI,       SPI4,          0x14, 19, 0x88, 16, 0xa8, 20),
-       MUX_PG(kbca,   KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, 0x14, 22, 0x88, 10, 0xa4, 8),
-       MUX_PG(kbcb,   KBC,       NAND,      SDIO2,     MIO,           0x14, 21, 0x88, 12, 0xa4, 10),
-       MUX_PG(kbcc,   KBC,       NAND,      TRACE,     EMC_TEST1_DLL, 0x18, 26, 0x88, 14, 0xa4, 12),
-       MUX_PG(kbcd,   KBC,       NAND,      SDIO2,     MIO,           0x20, 10, 0x98, 26, 0xa4, 14),
-       MUX_PG(kbce,   KBC,       NAND,      OWR,       RSVD4,         0x14, 26, 0x80, 28, 0xb0, 2),
-       MUX_PG(kbcf,   KBC,       NAND,      TRACE,     MIO,           0x14, 27, 0x80, 26, 0xb0, 0),
-       MUX_PG(lcsn,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD4,         0x1c, 31, 0x90, 12, -1,   -1),
-       MUX_PG(ld0,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 0,  0x94, 0,  -1,   -1),
-       MUX_PG(ld1,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 1,  0x94, 2,  -1,   -1),
-       MUX_PG(ld2,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 2,  0x94, 4,  -1,   -1),
-       MUX_PG(ld3,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 3,  0x94, 6,  -1,   -1),
-       MUX_PG(ld4,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 4,  0x94, 8,  -1,   -1),
-       MUX_PG(ld5,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 5,  0x94, 10, -1,   -1),
-       MUX_PG(ld6,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 6,  0x94, 12, -1,   -1),
-       MUX_PG(ld7,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 7,  0x94, 14, -1,   -1),
-       MUX_PG(ld8,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 8,  0x94, 16, -1,   -1),
-       MUX_PG(ld9,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 9,  0x94, 18, -1,   -1),
-       MUX_PG(ld10,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 10, 0x94, 20, -1,   -1),
-       MUX_PG(ld11,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 11, 0x94, 22, -1,   -1),
-       MUX_PG(ld12,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 12, 0x94, 24, -1,   -1),
-       MUX_PG(ld13,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 13, 0x94, 26, -1,   -1),
-       MUX_PG(ld14,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 14, 0x94, 28, -1,   -1),
-       MUX_PG(ld15,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 15, 0x94, 30, -1,   -1),
-       MUX_PG(ld16,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 16, 0x98, 0,  -1,   -1),
-       MUX_PG(ld17,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 17, 0x98, 2,  -1,   -1),
-       MUX_PG(ldc,    DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 30, 0x90, 14, -1,   -1),
-       MUX_PG(ldi,    DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x20, 6,  0x98, 16, -1,   -1),
-       MUX_PG(lhp0,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 18, 0x98, 10, -1,   -1),
-       MUX_PG(lhp1,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 19, 0x98, 4,  -1,   -1),
-       MUX_PG(lhp2,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 20, 0x98, 6,  -1,   -1),
-       MUX_PG(lhs,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x20, 7,  0x90, 22, -1,   -1),
-       MUX_PG(lm0,    DISPLAYA,  DISPLAYB,  SPI3,      RSVD4,         0x1c, 24, 0x90, 26, -1,   -1),
-       MUX_PG(lm1,    DISPLAYA,  DISPLAYB,  RSVD3,     CRT,           0x1c, 25, 0x90, 28, -1,   -1),
-       MUX_PG(lpp,    DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x20, 8,  0x98, 14, -1,   -1),
-       MUX_PG(lpw0,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x20, 3,  0x90, 0,  -1,   -1),
-       MUX_PG(lpw1,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x20, 4,  0x90, 2,  -1,   -1),
-       MUX_PG(lpw2,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x20, 5,  0x90, 4,  -1,   -1),
-       MUX_PG(lsc0,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 27, 0x90, 18, -1,   -1),
-       MUX_PG(lsc1,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x1c, 28, 0x90, 20, -1,   -1),
-       MUX_PG(lsck,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x1c, 29, 0x90, 16, -1,   -1),
-       MUX_PG(lsda,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x20, 1,  0x90, 8,  -1,   -1),
-       MUX_PG(lsdi,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD4,         0x20, 2,  0x90, 6,  -1,   -1),
-       MUX_PG(lspi,   DISPLAYA,  DISPLAYB,  XIO,       HDMI,          0x20, 0,  0x90, 10, -1,   -1),
-       MUX_PG(lvp0,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 21, 0x90, 30, -1,   -1),
-       MUX_PG(lvp1,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 22, 0x98, 8,  -1,   -1),
-       MUX_PG(lvs,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 26, 0x90, 24, -1,   -1),
-       MUX_PG(owc,    OWR,       RSVD2,     RSVD3,     RSVD4,         0x14, 31, 0x84, 8,  0xb0, 30),
-       MUX_PG(pmc,    PWR_ON,    PWR_INTR,  RSVD3,     RSVD4,         0x14, 23, 0x98, 18, -1,   -1),
-       MUX_PG(pta,    I2C2,      HDMI,      GMI,       RSVD4,         0x14, 24, 0x98, 22, 0xa4, 4),
-       MUX_PG(rm,     I2C1,      RSVD2,     RSVD3,     RSVD4,         0x14, 25, 0x80, 14, 0xa4, 0),
-       MUX_PG(sdb,    UARTA,     PWM,       SDIO3,     SPI2,          0x20, 15, 0x8c, 10, -1,   -1),
-       MUX_PG(sdc,    PWM,       TWC,       SDIO3,     SPI3,          0x18, 1,  0x8c, 12, 0xac, 28),
-       MUX_PG(sdd,    UARTA,     PWM,       SDIO3,     SPI3,          0x18, 2,  0x8c, 14, 0xac, 30),
-       MUX_PG(sdio1,  SDIO1,     RSVD2,     UARTE,     UARTA,         0x14, 30, 0x80, 30, 0xb0, 18),
-       MUX_PG(slxa,   PCIE,      SPI4,      SDIO3,     SPI2,          0x18, 3,  0x84, 6,  0xa4, 22),
-       MUX_PG(slxc,   SPDIF,     SPI4,      SDIO3,     SPI2,          0x18, 5,  0x84, 10, 0xa4, 26),
-       MUX_PG(slxd,   SPDIF,     SPI4,      SDIO3,     SPI2,          0x18, 6,  0x84, 12, 0xa4, 28),
-       MUX_PG(slxk,   PCIE,      SPI4,      SDIO3,     SPI2,          0x18, 7,  0x84, 14, 0xa4, 30),
-       MUX_PG(spdi,   SPDIF,     RSVD2,     I2C1,      SDIO2,         0x18, 8,  0x8c, 8,  0xa4, 16),
-       MUX_PG(spdo,   SPDIF,     RSVD2,     I2C1,      SDIO2,         0x18, 9,  0x8c, 6,  0xa4, 18),
-       MUX_PG(spia,   SPI1,      SPI2,      SPI3,      GMI,           0x18, 10, 0x8c, 30, 0xa8, 4),
-       MUX_PG(spib,   SPI1,      SPI2,      SPI3,      GMI,           0x18, 11, 0x8c, 28, 0xa8, 6),
-       MUX_PG(spic,   SPI1,      SPI2,      SPI3,      GMI,           0x18, 12, 0x8c, 26, 0xa8, 8),
-       MUX_PG(spid,   SPI2,      SPI1,      SPI2_ALT,  GMI,           0x18, 13, 0x8c, 24, 0xa8, 10),
-       MUX_PG(spie,   SPI2,      SPI1,      SPI2_ALT,  GMI,           0x18, 14, 0x8c, 22, 0xa8, 12),
-       MUX_PG(spif,   SPI3,      SPI1,      SPI2,      RSVD4,         0x18, 15, 0x8c, 20, 0xa8, 14),
-       MUX_PG(spig,   SPI3,      SPI2,      SPI2_ALT,  I2C1,          0x18, 16, 0x8c, 18, 0xa8, 16),
-       MUX_PG(spih,   SPI3,      SPI2,      SPI2_ALT,  I2C1,          0x18, 17, 0x8c, 16, 0xa8, 18),
-       MUX_PG(uaa,    SPI3,      MIPI_HS,   UARTA,     ULPI,          0x18, 18, 0x80, 0,  0xac, 0),
-       MUX_PG(uab,    SPI2,      MIPI_HS,   UARTA,     ULPI,          0x18, 19, 0x80, 2,  0xac, 2),
-       MUX_PG(uac,    OWR,       RSVD2,     RSVD3,     RSVD4,         0x18, 20, 0x80, 4,  0xac, 4),
-       MUX_PG(uad,    IRDA,      SPDIF,     UARTA,     SPI4,          0x18, 21, 0x80, 6,  0xac, 6),
-       MUX_PG(uca,    UARTC,     RSVD2,     GMI,       RSVD4,         0x18, 22, 0x84, 16, 0xac, 8),
-       MUX_PG(ucb,    UARTC,     PWM,       GMI,       RSVD4,         0x18, 23, 0x84, 18, 0xac, 10),
-       MUX_PG(uda,    SPI1,      RSVD2,     UARTD,     ULPI,          0x20, 13, 0x80, 8,  0xb0, 16),
-       /*      pg_name, pupd_r/b */
-       PULL_PG(ck32,    0xb0, 14),
-       PULL_PG(ddrc,    0xac, 26),
-       PULL_PG(pmca,    0xb0, 4),
-       PULL_PG(pmcb,    0xb0, 6),
-       PULL_PG(pmcc,    0xb0, 8),
-       PULL_PG(pmcd,    0xb0, 10),
-       PULL_PG(pmce,    0xb0, 12),
-       PULL_PG(xm2c,    0xa8, 30),
-       PULL_PG(xm2d,    0xa8, 28),
-       PULL_PG(ls,      0xac, 20),
-       PULL_PG(lc,      0xac, 22),
-       PULL_PG(ld17_0,  0xac, 12),
-       PULL_PG(ld19_18, 0xac, 14),
-       PULL_PG(ld21_20, 0xac, 16),
-       PULL_PG(ld23_22, 0xac, 18),
-       /*     pg_name,    r */
-       DRV_PG(ao1,        0x868),
-       DRV_PG(ao2,        0x86c),
-       DRV_PG(at1,        0x870),
-       DRV_PG(at2,        0x874),
-       DRV_PG(cdev1,      0x878),
-       DRV_PG(cdev2,      0x87c),
-       DRV_PG(csus,       0x880),
-       DRV_PG(dap1,       0x884),
-       DRV_PG(dap2,       0x888),
-       DRV_PG(dap3,       0x88c),
-       DRV_PG(dap4,       0x890),
-       DRV_PG(dbg,        0x894),
-       DRV_PG(lcd1,       0x898),
-       DRV_PG(lcd2,       0x89c),
-       DRV_PG(sdmmc2,     0x8a0),
-       DRV_PG(sdmmc3,     0x8a4),
-       DRV_PG(spi,        0x8a8),
-       DRV_PG(uaa,        0x8ac),
-       DRV_PG(uab,        0x8b0),
-       DRV_PG(uart2,      0x8b4),
-       DRV_PG(uart3,      0x8b8),
-       DRV_PG(vi1,        0x8bc),
-       DRV_PG(vi2,        0x8c0),
-       /*         pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvup_b, slwr_b, slwr_w, slwf_b, slwf_w */
-       DRV_PG_EXT(xm2a,   0x8c4, -1, -1,  4, 14, 19, 24, 4, 28, 4),
-       DRV_PG_EXT(xm2c,   0x8c8, -1,  3, -1, 14, 19, 24, 4, 28, 4),
-       DRV_PG_EXT(xm2d,   0x8cc, -1,  3, -1, 14, 19, 24, 4, 28, 4),
-       DRV_PG_EXT(xm2clk, 0x8d0, -1, -1, -1, 14, 19, 24, 4, 28, 4),
-       /*     pg_name,    r */
-       DRV_PG(sdio1,      0x8e0),
-       DRV_PG(crt,        0x8ec),
-       DRV_PG(ddc,        0x8f0),
-       DRV_PG(gma,        0x8f4),
-       DRV_PG(gmb,        0x8f8),
-       DRV_PG(gmc,        0x8fc),
-       DRV_PG(gmd,        0x900),
-       DRV_PG(gme,        0x904),
-       DRV_PG(owr,        0x908),
-       DRV_PG(uda,        0x90c),
-};
-
-static const struct tegra_pinctrl_soc_data tegra20_pinctrl = {
-       .ngpios = NUM_GPIOS,
-       .pins = tegra20_pins,
-       .npins = ARRAY_SIZE(tegra20_pins),
-       .functions = tegra20_functions,
-       .nfunctions = ARRAY_SIZE(tegra20_functions),
-       .groups = tegra20_groups,
-       .ngroups = ARRAY_SIZE(tegra20_groups),
-       .hsm_in_mux = false,
-       .schmitt_in_mux = false,
-       .drvtype_in_mux = false,
-};
-
-static int tegra20_pinctrl_probe(struct platform_device *pdev)
-{
-       return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
-}
-
-static const struct of_device_id tegra20_pinctrl_of_match[] = {
-       { .compatible = "nvidia,tegra20-pinmux", },
-       { },
-};
-
-static struct platform_driver tegra20_pinctrl_driver = {
-       .driver = {
-               .name = "tegra20-pinctrl",
-               .of_match_table = tegra20_pinctrl_of_match,
-       },
-       .probe = tegra20_pinctrl_probe,
-       .remove = tegra_pinctrl_remove,
-};
-module_platform_driver(tegra20_pinctrl_driver);
-
-MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match);
diff --git a/drivers/pinctrl/pinctrl-tegra210.c b/drivers/pinctrl/pinctrl-tegra210.c
deleted file mode 100644 (file)
index 252b464..0000000
+++ /dev/null
@@ -1,1588 +0,0 @@
-/*
- * Pinctrl data for the NVIDIA Tegra210 pinmux
- *
- * Copyright (c) 2015, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-
-#include "pinctrl-tegra.h"
-
-/*
- * Most pins affected by the pinmux can also be GPIOs. Define these first.
- * These must match how the GPIO driver names/numbers its pins.
- */
-#define _GPIO(offset)                          (offset)
-
-#define TEGRA_PIN_PEX_L0_RST_N_PA0             _GPIO(0)
-#define TEGRA_PIN_PEX_L0_CLKREQ_N_PA1          _GPIO(1)
-#define TEGRA_PIN_PEX_WAKE_N_PA2               _GPIO(2)
-#define TEGRA_PIN_PEX_L1_RST_N_PA3             _GPIO(3)
-#define TEGRA_PIN_PEX_L1_CLKREQ_N_PA4          _GPIO(4)
-#define TEGRA_PIN_SATA_LED_ACTIVE_PA5          _GPIO(5)
-#define TEGRA_PIN_PA6                          _GPIO(6)
-#define TEGRA_PIN_DAP1_FS_PB0                  _GPIO(8)
-#define TEGRA_PIN_DAP1_DIN_PB1                 _GPIO(9)
-#define TEGRA_PIN_DAP1_DOUT_PB2                        _GPIO(10)
-#define TEGRA_PIN_DAP1_SCLK_PB3                        _GPIO(11)
-#define TEGRA_PIN_SPI2_MOSI_PB4                        _GPIO(12)
-#define TEGRA_PIN_SPI2_MISO_PB5                        _GPIO(13)
-#define TEGRA_PIN_SPI2_SCK_PB6                 _GPIO(14)
-#define TEGRA_PIN_SPI2_CS0_PB7                 _GPIO(15)
-#define TEGRA_PIN_SPI1_MOSI_PC0                        _GPIO(16)
-#define TEGRA_PIN_SPI1_MISO_PC1                        _GPIO(17)
-#define TEGRA_PIN_SPI1_SCK_PC2                 _GPIO(18)
-#define TEGRA_PIN_SPI1_CS0_PC3                 _GPIO(19)
-#define TEGRA_PIN_SPI1_CS1_PC4                 _GPIO(20)
-#define TEGRA_PIN_SPI4_SCK_PC5                 _GPIO(21)
-#define TEGRA_PIN_SPI4_CS0_PC6                 _GPIO(22)
-#define TEGRA_PIN_SPI4_MOSI_PC7                        _GPIO(23)
-#define TEGRA_PIN_SPI4_MISO_PD0                        _GPIO(24)
-#define TEGRA_PIN_UART3_TX_PD1                 _GPIO(25)
-#define TEGRA_PIN_UART3_RX_PD2                 _GPIO(26)
-#define TEGRA_PIN_UART3_RTS_PD3                        _GPIO(27)
-#define TEGRA_PIN_UART3_CTS_PD4                        _GPIO(28)
-#define TEGRA_PIN_DMIC1_CLK_PE0                        _GPIO(32)
-#define TEGRA_PIN_DMIC1_DAT_PE1                        _GPIO(33)
-#define TEGRA_PIN_DMIC2_CLK_PE2                        _GPIO(34)
-#define TEGRA_PIN_DMIC2_DAT_PE3                        _GPIO(35)
-#define TEGRA_PIN_DMIC3_CLK_PE4                        _GPIO(36)
-#define TEGRA_PIN_DMIC3_DAT_PE5                        _GPIO(37)
-#define TEGRA_PIN_PE6                          _GPIO(38)
-#define TEGRA_PIN_PE7                          _GPIO(39)
-#define TEGRA_PIN_GEN3_I2C_SCL_PF0             _GPIO(40)
-#define TEGRA_PIN_GEN3_I2C_SDA_PF1             _GPIO(41)
-#define TEGRA_PIN_UART2_TX_PG0                 _GPIO(48)
-#define TEGRA_PIN_UART2_RX_PG1                 _GPIO(49)
-#define TEGRA_PIN_UART2_RTS_PG2                        _GPIO(50)
-#define TEGRA_PIN_UART2_CTS_PG3                        _GPIO(51)
-#define TEGRA_PIN_WIFI_EN_PH0                  _GPIO(56)
-#define TEGRA_PIN_WIFI_RST_PH1                 _GPIO(57)
-#define TEGRA_PIN_WIFI_WAKE_AP_PH2             _GPIO(58)
-#define TEGRA_PIN_AP_WAKE_BT_PH3               _GPIO(59)
-#define TEGRA_PIN_BT_RST_PH4                   _GPIO(60)
-#define TEGRA_PIN_BT_WAKE_AP_PH5               _GPIO(61)
-#define TEGRA_PIN_PH6                          _GPIO(62)
-#define TEGRA_PIN_AP_WAKE_NFC_PH7              _GPIO(63)
-#define TEGRA_PIN_NFC_EN_PI0                   _GPIO(64)
-#define TEGRA_PIN_NFC_INT_PI1                  _GPIO(65)
-#define TEGRA_PIN_GPS_EN_PI2                   _GPIO(66)
-#define TEGRA_PIN_GPS_RST_PI3                  _GPIO(67)
-#define TEGRA_PIN_UART4_TX_PI4                 _GPIO(68)
-#define TEGRA_PIN_UART4_RX_PI5                 _GPIO(69)
-#define TEGRA_PIN_UART4_RTS_PI6                        _GPIO(70)
-#define TEGRA_PIN_UART4_CTS_PI7                        _GPIO(71)
-#define TEGRA_PIN_GEN1_I2C_SDA_PJ0             _GPIO(72)
-#define TEGRA_PIN_GEN1_I2C_SCL_PJ1             _GPIO(73)
-#define TEGRA_PIN_GEN2_I2C_SCL_PJ2             _GPIO(74)
-#define TEGRA_PIN_GEN2_I2C_SDA_PJ3             _GPIO(75)
-#define TEGRA_PIN_DAP4_FS_PJ4                  _GPIO(76)
-#define TEGRA_PIN_DAP4_DIN_PJ5                 _GPIO(77)
-#define TEGRA_PIN_DAP4_DOUT_PJ6                        _GPIO(78)
-#define TEGRA_PIN_DAP4_SCLK_PJ7                        _GPIO(79)
-#define TEGRA_PIN_PK0                          _GPIO(80)
-#define TEGRA_PIN_PK1                          _GPIO(81)
-#define TEGRA_PIN_PK2                          _GPIO(82)
-#define TEGRA_PIN_PK3                          _GPIO(83)
-#define TEGRA_PIN_PK4                          _GPIO(84)
-#define TEGRA_PIN_PK5                          _GPIO(85)
-#define TEGRA_PIN_PK6                          _GPIO(86)
-#define TEGRA_PIN_PK7                          _GPIO(87)
-#define TEGRA_PIN_PL0                          _GPIO(88)
-#define TEGRA_PIN_PL1                          _GPIO(89)
-#define TEGRA_PIN_SDMMC1_CLK_PM0               _GPIO(96)
-#define TEGRA_PIN_SDMMC1_CMD_PM1               _GPIO(97)
-#define TEGRA_PIN_SDMMC1_DAT3_PM2              _GPIO(98)
-#define TEGRA_PIN_SDMMC1_DAT2_PM3              _GPIO(99)
-#define TEGRA_PIN_SDMMC1_DAT1_PM4              _GPIO(100)
-#define TEGRA_PIN_SDMMC1_DAT0_PM5              _GPIO(101)
-#define TEGRA_PIN_SDMMC3_CLK_PP0               _GPIO(120)
-#define TEGRA_PIN_SDMMC3_CMD_PP1               _GPIO(121)
-#define TEGRA_PIN_SDMMC3_DAT3_PP2              _GPIO(122)
-#define TEGRA_PIN_SDMMC3_DAT2_PP3              _GPIO(123)
-#define TEGRA_PIN_SDMMC3_DAT1_PP4              _GPIO(124)
-#define TEGRA_PIN_SDMMC3_DAT0_PP5              _GPIO(125)
-#define TEGRA_PIN_CAM1_MCLK_PS0                        _GPIO(144)
-#define TEGRA_PIN_CAM2_MCLK_PS1                        _GPIO(145)
-#define TEGRA_PIN_CAM_I2C_SCL_PS2              _GPIO(146)
-#define TEGRA_PIN_CAM_I2C_SDA_PS3              _GPIO(147)
-#define TEGRA_PIN_CAM_RST_PS4                  _GPIO(148)
-#define TEGRA_PIN_CAM_AF_EN_PS5                        _GPIO(149)
-#define TEGRA_PIN_CAM_FLASH_EN_PS6             _GPIO(150)
-#define TEGRA_PIN_CAM1_PWDN_PS7                        _GPIO(151)
-#define TEGRA_PIN_CAM2_PWDN_PT0                        _GPIO(152)
-#define TEGRA_PIN_CAM1_STROBE_PT1              _GPIO(153)
-#define TEGRA_PIN_UART1_TX_PU0                 _GPIO(160)
-#define TEGRA_PIN_UART1_RX_PU1                 _GPIO(161)
-#define TEGRA_PIN_UART1_RTS_PU2                        _GPIO(162)
-#define TEGRA_PIN_UART1_CTS_PU3                        _GPIO(163)
-#define TEGRA_PIN_LCD_BL_PWM_PV0               _GPIO(168)
-#define TEGRA_PIN_LCD_BL_EN_PV1                        _GPIO(169)
-#define TEGRA_PIN_LCD_RST_PV2                  _GPIO(170)
-#define TEGRA_PIN_LCD_GPIO1_PV3                        _GPIO(171)
-#define TEGRA_PIN_LCD_GPIO2_PV4                        _GPIO(172)
-#define TEGRA_PIN_AP_READY_PV5                 _GPIO(173)
-#define TEGRA_PIN_TOUCH_RST_PV6                        _GPIO(174)
-#define TEGRA_PIN_TOUCH_CLK_PV7                        _GPIO(175)
-#define TEGRA_PIN_MODEM_WAKE_AP_PX0            _GPIO(184)
-#define TEGRA_PIN_TOUCH_INT_PX1                        _GPIO(185)
-#define TEGRA_PIN_MOTION_INT_PX2               _GPIO(186)
-#define TEGRA_PIN_ALS_PROX_INT_PX3             _GPIO(187)
-#define TEGRA_PIN_TEMP_ALERT_PX4               _GPIO(188)
-#define TEGRA_PIN_BUTTON_POWER_ON_PX5          _GPIO(189)
-#define TEGRA_PIN_BUTTON_VOL_UP_PX6            _GPIO(190)
-#define TEGRA_PIN_BUTTON_VOL_DOWN_PX7          _GPIO(191)
-#define TEGRA_PIN_BUTTON_SLIDE_SW_PY0          _GPIO(192)
-#define TEGRA_PIN_BUTTON_HOME_PY1              _GPIO(193)
-#define TEGRA_PIN_LCD_TE_PY2                   _GPIO(194)
-#define TEGRA_PIN_PWR_I2C_SCL_PY3              _GPIO(195)
-#define TEGRA_PIN_PWR_I2C_SDA_PY4              _GPIO(196)
-#define TEGRA_PIN_CLK_32K_OUT_PY5              _GPIO(197)
-#define TEGRA_PIN_PZ0                          _GPIO(200)
-#define TEGRA_PIN_PZ1                          _GPIO(201)
-#define TEGRA_PIN_PZ2                          _GPIO(202)
-#define TEGRA_PIN_PZ3                          _GPIO(203)
-#define TEGRA_PIN_PZ4                          _GPIO(204)
-#define TEGRA_PIN_PZ5                          _GPIO(205)
-#define TEGRA_PIN_DAP2_FS_PAA0                 _GPIO(208)
-#define TEGRA_PIN_DAP2_SCLK_PAA1               _GPIO(209)
-#define TEGRA_PIN_DAP2_DIN_PAA2                        _GPIO(210)
-#define TEGRA_PIN_DAP2_DOUT_PAA3               _GPIO(211)
-#define TEGRA_PIN_AUD_MCLK_PBB0                        _GPIO(216)
-#define TEGRA_PIN_DVFS_PWM_PBB1                        _GPIO(217)
-#define TEGRA_PIN_DVFS_CLK_PBB2                        _GPIO(218)
-#define TEGRA_PIN_GPIO_X1_AUD_PBB3             _GPIO(219)
-#define TEGRA_PIN_GPIO_X3_AUD_PBB4             _GPIO(220)
-#define TEGRA_PIN_HDMI_CEC_PCC0                        _GPIO(224)
-#define TEGRA_PIN_HDMI_INT_DP_HPD_PCC1         _GPIO(225)
-#define TEGRA_PIN_SPDIF_OUT_PCC2               _GPIO(226)
-#define TEGRA_PIN_SPDIF_IN_PCC3                        _GPIO(227)
-#define TEGRA_PIN_USB_VBUS_EN0_PCC4            _GPIO(228)
-#define TEGRA_PIN_USB_VBUS_EN1_PCC5            _GPIO(229)
-#define TEGRA_PIN_DP_HPD0_PCC6                 _GPIO(230)
-#define TEGRA_PIN_PCC7                         _GPIO(231)
-#define TEGRA_PIN_SPI2_CS1_PDD0                        _GPIO(232)
-#define TEGRA_PIN_QSPI_SCK_PEE0                        _GPIO(240)
-#define TEGRA_PIN_QSPI_CS_N_PEE1               _GPIO(241)
-#define TEGRA_PIN_QSPI_IO0_PEE2                        _GPIO(242)
-#define TEGRA_PIN_QSPI_IO1_PEE3                        _GPIO(243)
-#define TEGRA_PIN_QSPI_IO2_PEE4                        _GPIO(244)
-#define TEGRA_PIN_QSPI_IO3_PEE5                        _GPIO(245)
-
-/* All non-GPIO pins follow */
-#define NUM_GPIOS                              (TEGRA_PIN_QSPI_IO3_PEE5 + 1)
-#define _PIN(offset)                           (NUM_GPIOS + (offset))
-
-/* Non-GPIO pins */
-#define TEGRA_PIN_CORE_PWR_REQ                 _PIN(0)
-#define TEGRA_PIN_CPU_PWR_REQ                  _PIN(1)
-#define TEGRA_PIN_PWR_INT_N                    _PIN(2)
-#define TEGRA_PIN_CLK_32K_IN                   _PIN(3)
-#define TEGRA_PIN_JTAG_RTCK                    _PIN(4)
-#define TEGRA_PIN_BATT_BCL                     _PIN(5)
-#define TEGRA_PIN_CLK_REQ                      _PIN(6)
-#define TEGRA_PIN_SHUTDOWN                     _PIN(7)
-
-static const struct pinctrl_pin_desc tegra210_pins[] = {
-       PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PA0, "PEX_L0_RST_N PA0"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, "PEX_L0_CLKREQ_N PA1"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PA2, "PEX_WAKE_N PA2"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PA3, "PEX_L1_RST_N PA3"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, "PEX_L1_CLKREQ_N PA4"),
-       PINCTRL_PIN(TEGRA_PIN_SATA_LED_ACTIVE_PA5, "SATA_LED_ACTIVE PA5"),
-       PINCTRL_PIN(TEGRA_PIN_PA6, "PA6"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PB0, "DAP1_FS PB0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PB1, "DAP1_DIN PB1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PB2, "DAP1_DOUT PB2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PB3, "DAP1_SCLK PB3"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PB4, "SPI2_MOSI PB4"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PB5, "SPI2_MISO PB5"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PB6, "SPI2_SCK PB6"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PB7, "SPI2_CS0 PB7"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PC0, "SPI1_MOSI PC0"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PC1, "SPI1_MISO PC1"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PC2, "SPI1_SCK PC2"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PC3, "SPI1_CS0 PC3"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PC4, "SPI1_CS1 PC4"),
-       PINCTRL_PIN(TEGRA_PIN_SPI4_SCK_PC5, "SPI4_SCK PC5"),
-       PINCTRL_PIN(TEGRA_PIN_SPI4_CS0_PC6, "SPI4_CS0 PC6"),
-       PINCTRL_PIN(TEGRA_PIN_SPI4_MOSI_PC7, "SPI4_MOSI PC7"),
-       PINCTRL_PIN(TEGRA_PIN_SPI4_MISO_PD0, "SPI4_MISO PD0"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_TX_PD1, "UART3_TX PD1"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RX_PD2, "UART3_RX PD2"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_PD3, "UART3_RTS PD3"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_PD4, "UART3_CTS PD4"),
-       PINCTRL_PIN(TEGRA_PIN_DMIC1_CLK_PE0, "DMIC1_CLK PE0"),
-       PINCTRL_PIN(TEGRA_PIN_DMIC1_DAT_PE1, "DMIC1_DAT PE1"),
-       PINCTRL_PIN(TEGRA_PIN_DMIC2_CLK_PE2, "DMIC2_CLK PE2"),
-       PINCTRL_PIN(TEGRA_PIN_DMIC2_DAT_PE3, "DMIC2_DAT PE3"),
-       PINCTRL_PIN(TEGRA_PIN_DMIC3_CLK_PE4, "DMIC3_CLK PE4"),
-       PINCTRL_PIN(TEGRA_PIN_DMIC3_DAT_PE5, "DMIC3_DAT PE5"),
-       PINCTRL_PIN(TEGRA_PIN_PE6, "PE6"),
-       PINCTRL_PIN(TEGRA_PIN_PE7, "PE7"),
-       PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SCL_PF0, "GEN3_I2C_SCL PF0"),
-       PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SDA_PF1, "GEN3_I2C_SDA PF1"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_TX_PG0, "UART2_TX PG0"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RX_PG1, "UART2_RX PG1"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PG2, "UART2_RTS PG2"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PG3, "UART2_CTS PG3"),
-       PINCTRL_PIN(TEGRA_PIN_WIFI_EN_PH0, "WIFI_EN PH0"),
-       PINCTRL_PIN(TEGRA_PIN_WIFI_RST_PH1, "WIFI_RST PH1"),
-       PINCTRL_PIN(TEGRA_PIN_WIFI_WAKE_AP_PH2, "WIFI_WAKE_AP PH2"),
-       PINCTRL_PIN(TEGRA_PIN_AP_WAKE_BT_PH3, "AP_WAKE_BT PH3"),
-       PINCTRL_PIN(TEGRA_PIN_BT_RST_PH4, "BT_RST PH4"),
-       PINCTRL_PIN(TEGRA_PIN_BT_WAKE_AP_PH5, "BT_WAKE_AP PH5"),
-       PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"),
-       PINCTRL_PIN(TEGRA_PIN_AP_WAKE_NFC_PH7, "AP_WAKE_NFC PH7"),
-       PINCTRL_PIN(TEGRA_PIN_NFC_EN_PI0, "NFC_EN PI0"),
-       PINCTRL_PIN(TEGRA_PIN_NFC_INT_PI1, "NFC_INT PI1"),
-       PINCTRL_PIN(TEGRA_PIN_GPS_EN_PI2, "GPS_EN PI2"),
-       PINCTRL_PIN(TEGRA_PIN_GPS_RST_PI3, "GPS_RST PI3"),
-       PINCTRL_PIN(TEGRA_PIN_UART4_TX_PI4, "UART4_TX PI4"),
-       PINCTRL_PIN(TEGRA_PIN_UART4_RX_PI5, "UART4_RX PI5"),
-       PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PI6, "UART4_RTS PI6"),
-       PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PI7, "UART4_CTS PI7"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PJ0, "GEN1_I2C_SDA PJ0"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PJ1, "GEN1_I2C_SCL PJ1"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PJ2, "GEN2_I2C_SCL PJ2"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PJ3, "GEN2_I2C_SDA PJ3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PJ4, "DAP4_FS PJ4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PJ5, "DAP4_DIN PJ5"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PJ6, "DAP4_DOUT PJ6"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PJ7, "DAP4_SCLK PJ7"),
-       PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"),
-       PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"),
-       PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"),
-       PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"),
-       PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"),
-       PINCTRL_PIN(TEGRA_PIN_PK5, "PK5"),
-       PINCTRL_PIN(TEGRA_PIN_PK6, "PK6"),
-       PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"),
-       PINCTRL_PIN(TEGRA_PIN_PL0, "PL0"),
-       PINCTRL_PIN(TEGRA_PIN_PL1, "PL1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PM0, "SDMMC1_CLK PM0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PM1, "SDMMC1_CMD PM1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PM2, "SDMMC1_DAT3 PM2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PM3, "SDMMC1_DAT2 PM3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PM4, "SDMMC1_DAT1 PM4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PM5, "SDMMC1_DAT0 PM5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PP0, "SDMMC3_CLK PP0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PP1, "SDMMC3_CMD PP1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PP2, "SDMMC3_DAT3 PP2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PP3, "SDMMC3_DAT2 PP3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PP4, "SDMMC3_DAT1 PP4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PP5, "SDMMC3_DAT0 PP5"),
-       PINCTRL_PIN(TEGRA_PIN_CAM1_MCLK_PS0, "CAM1_MCLK PS0"),
-       PINCTRL_PIN(TEGRA_PIN_CAM2_MCLK_PS1, "CAM2_MCLK PS1"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PS2, "CAM_I2C_SCL PS2"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PS3, "CAM_I2C_SDA PS3"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_RST_PS4, "CAM_RST PS4"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_AF_EN_PS5, "CAM_AF_EN PS5"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_FLASH_EN_PS6, "CAM_FLASH_EN PS6"),
-       PINCTRL_PIN(TEGRA_PIN_CAM1_PWDN_PS7, "CAM1_PWDN PS7"),
-       PINCTRL_PIN(TEGRA_PIN_CAM2_PWDN_PT0, "CAM2_PWDN PT0"),
-       PINCTRL_PIN(TEGRA_PIN_CAM1_STROBE_PT1, "CAM1_STROBE PT1"),
-       PINCTRL_PIN(TEGRA_PIN_UART1_TX_PU0, "UART1_TX PU0"),
-       PINCTRL_PIN(TEGRA_PIN_UART1_RX_PU1, "UART1_RX PU1"),
-       PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PU2, "UART1_RTS PU2"),
-       PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PU3, "UART1_CTS PU3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_BL_PWM_PV0, "LCD_BL_PWM PV0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_BL_EN_PV1, "LCD_BL_EN PV1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_RST_PV2, "LCD_RST PV2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_GPIO1_PV3, "LCD_GPIO1 PV3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_GPIO2_PV4, "LCD_GPIO2 PV4"),
-       PINCTRL_PIN(TEGRA_PIN_AP_READY_PV5, "AP_READY PV5"),
-       PINCTRL_PIN(TEGRA_PIN_TOUCH_RST_PV6, "TOUCH_RST PV6"),
-       PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PV7, "TOUCH_CLK PV7"),
-       PINCTRL_PIN(TEGRA_PIN_MODEM_WAKE_AP_PX0, "MODEM_WAKE_AP PX0"),
-       PINCTRL_PIN(TEGRA_PIN_TOUCH_INT_PX1, "TOUCH_INT PX1"),
-       PINCTRL_PIN(TEGRA_PIN_MOTION_INT_PX2, "MOTION_INT PX2"),
-       PINCTRL_PIN(TEGRA_PIN_ALS_PROX_INT_PX3, "ALS_PROX_INT PX3"),
-       PINCTRL_PIN(TEGRA_PIN_TEMP_ALERT_PX4, "TEMP_ALERT PX4"),
-       PINCTRL_PIN(TEGRA_PIN_BUTTON_POWER_ON_PX5, "BUTTON_POWER_ON PX5"),
-       PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_UP_PX6, "BUTTON_VOL_UP PX6"),
-       PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_DOWN_PX7, "BUTTON_VOL_DOWN PX7"),
-       PINCTRL_PIN(TEGRA_PIN_BUTTON_SLIDE_SW_PY0, "BUTTON_SLIDE_SW PY0"),
-       PINCTRL_PIN(TEGRA_PIN_BUTTON_HOME_PY1, "BUTTON_HOME PY1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_TE_PY2, "LCD_TE PY2"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PY3, "PWR_I2C_SCL PY3"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PY4, "PWR_I2C_SDA PY4"),
-       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PY5, "CLK_32K_OUT PY5"),
-       PINCTRL_PIN(TEGRA_PIN_PZ0, "PZ0"),
-       PINCTRL_PIN(TEGRA_PIN_PZ1, "PZ1"),
-       PINCTRL_PIN(TEGRA_PIN_PZ2, "PZ2"),
-       PINCTRL_PIN(TEGRA_PIN_PZ3, "PZ3"),
-       PINCTRL_PIN(TEGRA_PIN_PZ4, "PZ4"),
-       PINCTRL_PIN(TEGRA_PIN_PZ5, "PZ5"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PAA0, "DAP2_FS PAA0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PAA1, "DAP2_SCLK PAA1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PAA2, "DAP2_DIN PAA2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PAA3, "DAP2_DOUT PAA3"),
-       PINCTRL_PIN(TEGRA_PIN_AUD_MCLK_PBB0, "AUD_MCLK PBB0"),
-       PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PBB1, "DVFS_PWM PBB1"),
-       PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PBB2, "DVFS_CLK PBB2"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PBB3, "GPIO_X1_AUD PBB3"),
-       PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PBB4, "GPIO_X3_AUD PBB4"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PCC0, "HDMI_CEC PCC0"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, "HDMI_INT_DP_HPD PCC1"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PCC2, "SPDIF_OUT PCC2"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PCC3, "SPDIF_IN PCC3"),
-       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PCC4, "USB_VBUS_EN0 PCC4"),
-       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PCC5, "USB_VBUS_EN1 PCC5"),
-       PINCTRL_PIN(TEGRA_PIN_DP_HPD0_PCC6, "DP_HPD0 PCC6"),
-       PINCTRL_PIN(TEGRA_PIN_PCC7, "PCC7"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_PDD0, "SPI2_CS1 PDD0"),
-       PINCTRL_PIN(TEGRA_PIN_QSPI_SCK_PEE0, "QSPI_SCK PEE0"),
-       PINCTRL_PIN(TEGRA_PIN_QSPI_CS_N_PEE1, "QSPI_CS_N PEE1"),
-       PINCTRL_PIN(TEGRA_PIN_QSPI_IO0_PEE2, "QSPI_IO0 PEE2"),
-       PINCTRL_PIN(TEGRA_PIN_QSPI_IO1_PEE3, "QSPI_IO1 PEE3"),
-       PINCTRL_PIN(TEGRA_PIN_QSPI_IO2_PEE4, "QSPI_IO2 PEE4"),
-       PINCTRL_PIN(TEGRA_PIN_QSPI_IO3_PEE5, "QSPI_IO3 PEE5"),
-       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
-       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"),
-       PINCTRL_PIN(TEGRA_PIN_BATT_BCL, "BATT_BCL"),
-       PINCTRL_PIN(TEGRA_PIN_CLK_REQ, "CLK_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_SHUTDOWN, "SHUTDOWN"),
-};
-
-static const unsigned pex_l0_rst_n_pa0_pins[] = {
-       TEGRA_PIN_PEX_L0_RST_N_PA0,
-};
-
-static const unsigned pex_l0_clkreq_n_pa1_pins[] = {
-       TEGRA_PIN_PEX_L0_CLKREQ_N_PA1,
-};
-
-static const unsigned pex_wake_n_pa2_pins[] = {
-       TEGRA_PIN_PEX_WAKE_N_PA2,
-};
-
-static const unsigned pex_l1_rst_n_pa3_pins[] = {
-       TEGRA_PIN_PEX_L1_RST_N_PA3,
-};
-
-static const unsigned pex_l1_clkreq_n_pa4_pins[] = {
-       TEGRA_PIN_PEX_L1_CLKREQ_N_PA4,
-};
-
-static const unsigned sata_led_active_pa5_pins[] = {
-       TEGRA_PIN_SATA_LED_ACTIVE_PA5,
-};
-
-static const unsigned pa6_pins[] = {
-       TEGRA_PIN_PA6,
-};
-
-static const unsigned dap1_fs_pb0_pins[] = {
-       TEGRA_PIN_DAP1_FS_PB0,
-};
-
-static const unsigned dap1_din_pb1_pins[] = {
-       TEGRA_PIN_DAP1_DIN_PB1,
-};
-
-static const unsigned dap1_dout_pb2_pins[] = {
-       TEGRA_PIN_DAP1_DOUT_PB2,
-};
-
-static const unsigned dap1_sclk_pb3_pins[] = {
-       TEGRA_PIN_DAP1_SCLK_PB3,
-};
-
-static const unsigned spi2_mosi_pb4_pins[] = {
-       TEGRA_PIN_SPI2_MOSI_PB4,
-};
-
-static const unsigned spi2_miso_pb5_pins[] = {
-       TEGRA_PIN_SPI2_MISO_PB5,
-};
-
-static const unsigned spi2_sck_pb6_pins[] = {
-       TEGRA_PIN_SPI2_SCK_PB6,
-};
-
-static const unsigned spi2_cs0_pb7_pins[] = {
-       TEGRA_PIN_SPI2_CS0_PB7,
-};
-
-static const unsigned spi1_mosi_pc0_pins[] = {
-       TEGRA_PIN_SPI1_MOSI_PC0,
-};
-
-static const unsigned spi1_miso_pc1_pins[] = {
-       TEGRA_PIN_SPI1_MISO_PC1,
-};
-
-static const unsigned spi1_sck_pc2_pins[] = {
-       TEGRA_PIN_SPI1_SCK_PC2,
-};
-
-static const unsigned spi1_cs0_pc3_pins[] = {
-       TEGRA_PIN_SPI1_CS0_PC3,
-};
-
-static const unsigned spi1_cs1_pc4_pins[] = {
-       TEGRA_PIN_SPI1_CS1_PC4,
-};
-
-static const unsigned spi4_sck_pc5_pins[] = {
-       TEGRA_PIN_SPI4_SCK_PC5,
-};
-
-static const unsigned spi4_cs0_pc6_pins[] = {
-       TEGRA_PIN_SPI4_CS0_PC6,
-};
-
-static const unsigned spi4_mosi_pc7_pins[] = {
-       TEGRA_PIN_SPI4_MOSI_PC7,
-};
-
-static const unsigned spi4_miso_pd0_pins[] = {
-       TEGRA_PIN_SPI4_MISO_PD0,
-};
-
-static const unsigned uart3_tx_pd1_pins[] = {
-       TEGRA_PIN_UART3_TX_PD1,
-};
-
-static const unsigned uart3_rx_pd2_pins[] = {
-       TEGRA_PIN_UART3_RX_PD2,
-};
-
-static const unsigned uart3_rts_pd3_pins[] = {
-       TEGRA_PIN_UART3_RTS_PD3,
-};
-
-static const unsigned uart3_cts_pd4_pins[] = {
-       TEGRA_PIN_UART3_CTS_PD4,
-};
-
-static const unsigned dmic1_clk_pe0_pins[] = {
-       TEGRA_PIN_DMIC1_CLK_PE0,
-};
-
-static const unsigned dmic1_dat_pe1_pins[] = {
-       TEGRA_PIN_DMIC1_DAT_PE1,
-};
-
-static const unsigned dmic2_clk_pe2_pins[] = {
-       TEGRA_PIN_DMIC2_CLK_PE2,
-};
-
-static const unsigned dmic2_dat_pe3_pins[] = {
-       TEGRA_PIN_DMIC2_DAT_PE3,
-};
-
-static const unsigned dmic3_clk_pe4_pins[] = {
-       TEGRA_PIN_DMIC3_CLK_PE4,
-};
-
-static const unsigned dmic3_dat_pe5_pins[] = {
-       TEGRA_PIN_DMIC3_DAT_PE5,
-};
-
-static const unsigned pe6_pins[] = {
-       TEGRA_PIN_PE6,
-};
-
-static const unsigned pe7_pins[] = {
-       TEGRA_PIN_PE7,
-};
-
-static const unsigned gen3_i2c_scl_pf0_pins[] = {
-       TEGRA_PIN_GEN3_I2C_SCL_PF0,
-};
-
-static const unsigned gen3_i2c_sda_pf1_pins[] = {
-       TEGRA_PIN_GEN3_I2C_SDA_PF1,
-};
-
-static const unsigned uart2_tx_pg0_pins[] = {
-       TEGRA_PIN_UART2_TX_PG0,
-};
-
-static const unsigned uart2_rx_pg1_pins[] = {
-       TEGRA_PIN_UART2_RX_PG1,
-};
-
-static const unsigned uart2_rts_pg2_pins[] = {
-       TEGRA_PIN_UART2_RTS_PG2,
-};
-
-static const unsigned uart2_cts_pg3_pins[] = {
-       TEGRA_PIN_UART2_CTS_PG3,
-};
-
-static const unsigned wifi_en_ph0_pins[] = {
-       TEGRA_PIN_WIFI_EN_PH0,
-};
-
-static const unsigned wifi_rst_ph1_pins[] = {
-       TEGRA_PIN_WIFI_RST_PH1,
-};
-
-static const unsigned wifi_wake_ap_ph2_pins[] = {
-       TEGRA_PIN_WIFI_WAKE_AP_PH2,
-};
-
-static const unsigned ap_wake_bt_ph3_pins[] = {
-       TEGRA_PIN_AP_WAKE_BT_PH3,
-};
-
-static const unsigned bt_rst_ph4_pins[] = {
-       TEGRA_PIN_BT_RST_PH4,
-};
-
-static const unsigned bt_wake_ap_ph5_pins[] = {
-       TEGRA_PIN_BT_WAKE_AP_PH5,
-};
-
-static const unsigned ph6_pins[] = {
-       TEGRA_PIN_PH6,
-};
-
-static const unsigned ap_wake_nfc_ph7_pins[] = {
-       TEGRA_PIN_AP_WAKE_NFC_PH7,
-};
-
-static const unsigned nfc_en_pi0_pins[] = {
-       TEGRA_PIN_NFC_EN_PI0,
-};
-
-static const unsigned nfc_int_pi1_pins[] = {
-       TEGRA_PIN_NFC_INT_PI1,
-};
-
-static const unsigned gps_en_pi2_pins[] = {
-       TEGRA_PIN_GPS_EN_PI2,
-};
-
-static const unsigned gps_rst_pi3_pins[] = {
-       TEGRA_PIN_GPS_RST_PI3,
-};
-
-static const unsigned uart4_tx_pi4_pins[] = {
-       TEGRA_PIN_UART4_TX_PI4,
-};
-
-static const unsigned uart4_rx_pi5_pins[] = {
-       TEGRA_PIN_UART4_RX_PI5,
-};
-
-static const unsigned uart4_rts_pi6_pins[] = {
-       TEGRA_PIN_UART4_RTS_PI6,
-};
-
-static const unsigned uart4_cts_pi7_pins[] = {
-       TEGRA_PIN_UART4_CTS_PI7,
-};
-
-static const unsigned gen1_i2c_sda_pj0_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SDA_PJ0,
-};
-
-static const unsigned gen1_i2c_scl_pj1_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SCL_PJ1,
-};
-
-static const unsigned gen2_i2c_scl_pj2_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SCL_PJ2,
-};
-
-static const unsigned gen2_i2c_sda_pj3_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SDA_PJ3,
-};
-
-static const unsigned dap4_fs_pj4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PJ4,
-};
-
-static const unsigned dap4_din_pj5_pins[] = {
-       TEGRA_PIN_DAP4_DIN_PJ5,
-};
-
-static const unsigned dap4_dout_pj6_pins[] = {
-       TEGRA_PIN_DAP4_DOUT_PJ6,
-};
-
-static const unsigned dap4_sclk_pj7_pins[] = {
-       TEGRA_PIN_DAP4_SCLK_PJ7,
-};
-
-static const unsigned pk0_pins[] = {
-       TEGRA_PIN_PK0,
-};
-
-static const unsigned pk1_pins[] = {
-       TEGRA_PIN_PK1,
-};
-
-static const unsigned pk2_pins[] = {
-       TEGRA_PIN_PK2,
-};
-
-static const unsigned pk3_pins[] = {
-       TEGRA_PIN_PK3,
-};
-
-static const unsigned pk4_pins[] = {
-       TEGRA_PIN_PK4,
-};
-
-static const unsigned pk5_pins[] = {
-       TEGRA_PIN_PK5,
-};
-
-static const unsigned pk6_pins[] = {
-       TEGRA_PIN_PK6,
-};
-
-static const unsigned pk7_pins[] = {
-       TEGRA_PIN_PK7,
-};
-
-static const unsigned pl0_pins[] = {
-       TEGRA_PIN_PL0,
-};
-
-static const unsigned pl1_pins[] = {
-       TEGRA_PIN_PL1,
-};
-
-static const unsigned sdmmc1_clk_pm0_pins[] = {
-       TEGRA_PIN_SDMMC1_CLK_PM0,
-};
-
-static const unsigned sdmmc1_cmd_pm1_pins[] = {
-       TEGRA_PIN_SDMMC1_CMD_PM1,
-};
-
-static const unsigned sdmmc1_dat3_pm2_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT3_PM2,
-};
-
-static const unsigned sdmmc1_dat2_pm3_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT2_PM3,
-};
-
-static const unsigned sdmmc1_dat1_pm4_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT1_PM4,
-};
-
-static const unsigned sdmmc1_dat0_pm5_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT0_PM5,
-};
-
-static const unsigned sdmmc3_clk_pp0_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_PP0,
-};
-
-static const unsigned sdmmc3_cmd_pp1_pins[] = {
-       TEGRA_PIN_SDMMC3_CMD_PP1,
-};
-
-static const unsigned sdmmc3_dat3_pp2_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT3_PP2,
-};
-
-static const unsigned sdmmc3_dat2_pp3_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT2_PP3,
-};
-
-static const unsigned sdmmc3_dat1_pp4_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT1_PP4,
-};
-
-static const unsigned sdmmc3_dat0_pp5_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT0_PP5,
-};
-
-static const unsigned cam1_mclk_ps0_pins[] = {
-       TEGRA_PIN_CAM1_MCLK_PS0,
-};
-
-static const unsigned cam2_mclk_ps1_pins[] = {
-       TEGRA_PIN_CAM2_MCLK_PS1,
-};
-
-static const unsigned cam_i2c_scl_ps2_pins[] = {
-       TEGRA_PIN_CAM_I2C_SCL_PS2,
-};
-
-static const unsigned cam_i2c_sda_ps3_pins[] = {
-       TEGRA_PIN_CAM_I2C_SDA_PS3,
-};
-
-static const unsigned cam_rst_ps4_pins[] = {
-       TEGRA_PIN_CAM_RST_PS4,
-};
-
-static const unsigned cam_af_en_ps5_pins[] = {
-       TEGRA_PIN_CAM_AF_EN_PS5,
-};
-
-static const unsigned cam_flash_en_ps6_pins[] = {
-       TEGRA_PIN_CAM_FLASH_EN_PS6,
-};
-
-static const unsigned cam1_pwdn_ps7_pins[] = {
-       TEGRA_PIN_CAM1_PWDN_PS7,
-};
-
-static const unsigned cam2_pwdn_pt0_pins[] = {
-       TEGRA_PIN_CAM2_PWDN_PT0,
-};
-
-static const unsigned cam1_strobe_pt1_pins[] = {
-       TEGRA_PIN_CAM1_STROBE_PT1,
-};
-
-static const unsigned uart1_tx_pu0_pins[] = {
-       TEGRA_PIN_UART1_TX_PU0,
-};
-
-static const unsigned uart1_rx_pu1_pins[] = {
-       TEGRA_PIN_UART1_RX_PU1,
-};
-
-static const unsigned uart1_rts_pu2_pins[] = {
-       TEGRA_PIN_UART1_RTS_PU2,
-};
-
-static const unsigned uart1_cts_pu3_pins[] = {
-       TEGRA_PIN_UART1_CTS_PU3,
-};
-
-static const unsigned lcd_bl_pwm_pv0_pins[] = {
-       TEGRA_PIN_LCD_BL_PWM_PV0,
-};
-
-static const unsigned lcd_bl_en_pv1_pins[] = {
-       TEGRA_PIN_LCD_BL_EN_PV1,
-};
-
-static const unsigned lcd_rst_pv2_pins[] = {
-       TEGRA_PIN_LCD_RST_PV2,
-};
-
-static const unsigned lcd_gpio1_pv3_pins[] = {
-       TEGRA_PIN_LCD_GPIO1_PV3,
-};
-
-static const unsigned lcd_gpio2_pv4_pins[] = {
-       TEGRA_PIN_LCD_GPIO2_PV4,
-};
-
-static const unsigned ap_ready_pv5_pins[] = {
-       TEGRA_PIN_AP_READY_PV5,
-};
-
-static const unsigned touch_rst_pv6_pins[] = {
-       TEGRA_PIN_TOUCH_RST_PV6,
-};
-
-static const unsigned touch_clk_pv7_pins[] = {
-       TEGRA_PIN_TOUCH_CLK_PV7,
-};
-
-static const unsigned modem_wake_ap_px0_pins[] = {
-       TEGRA_PIN_MODEM_WAKE_AP_PX0,
-};
-
-static const unsigned touch_int_px1_pins[] = {
-       TEGRA_PIN_TOUCH_INT_PX1,
-};
-
-static const unsigned motion_int_px2_pins[] = {
-       TEGRA_PIN_MOTION_INT_PX2,
-};
-
-static const unsigned als_prox_int_px3_pins[] = {
-       TEGRA_PIN_ALS_PROX_INT_PX3,
-};
-
-static const unsigned temp_alert_px4_pins[] = {
-       TEGRA_PIN_TEMP_ALERT_PX4,
-};
-
-static const unsigned button_power_on_px5_pins[] = {
-       TEGRA_PIN_BUTTON_POWER_ON_PX5,
-};
-
-static const unsigned button_vol_up_px6_pins[] = {
-       TEGRA_PIN_BUTTON_VOL_UP_PX6,
-};
-
-static const unsigned button_vol_down_px7_pins[] = {
-       TEGRA_PIN_BUTTON_VOL_DOWN_PX7,
-};
-
-static const unsigned button_slide_sw_py0_pins[] = {
-       TEGRA_PIN_BUTTON_SLIDE_SW_PY0,
-};
-
-static const unsigned button_home_py1_pins[] = {
-       TEGRA_PIN_BUTTON_HOME_PY1,
-};
-
-static const unsigned lcd_te_py2_pins[] = {
-       TEGRA_PIN_LCD_TE_PY2,
-};
-
-static const unsigned pwr_i2c_scl_py3_pins[] = {
-       TEGRA_PIN_PWR_I2C_SCL_PY3,
-};
-
-static const unsigned pwr_i2c_sda_py4_pins[] = {
-       TEGRA_PIN_PWR_I2C_SDA_PY4,
-};
-
-static const unsigned clk_32k_out_py5_pins[] = {
-       TEGRA_PIN_CLK_32K_OUT_PY5,
-};
-
-static const unsigned pz0_pins[] = {
-       TEGRA_PIN_PZ0,
-};
-
-static const unsigned pz1_pins[] = {
-       TEGRA_PIN_PZ1,
-};
-
-static const unsigned pz2_pins[] = {
-       TEGRA_PIN_PZ2,
-};
-
-static const unsigned pz3_pins[] = {
-       TEGRA_PIN_PZ3,
-};
-
-static const unsigned pz4_pins[] = {
-       TEGRA_PIN_PZ4,
-};
-
-static const unsigned pz5_pins[] = {
-       TEGRA_PIN_PZ5,
-};
-
-static const unsigned dap2_fs_paa0_pins[] = {
-       TEGRA_PIN_DAP2_FS_PAA0,
-};
-
-static const unsigned dap2_sclk_paa1_pins[] = {
-       TEGRA_PIN_DAP2_SCLK_PAA1,
-};
-
-static const unsigned dap2_din_paa2_pins[] = {
-       TEGRA_PIN_DAP2_DIN_PAA2,
-};
-
-static const unsigned dap2_dout_paa3_pins[] = {
-       TEGRA_PIN_DAP2_DOUT_PAA3,
-};
-
-static const unsigned aud_mclk_pbb0_pins[] = {
-       TEGRA_PIN_AUD_MCLK_PBB0,
-};
-
-static const unsigned dvfs_pwm_pbb1_pins[] = {
-       TEGRA_PIN_DVFS_PWM_PBB1,
-};
-
-static const unsigned dvfs_clk_pbb2_pins[] = {
-       TEGRA_PIN_DVFS_CLK_PBB2,
-};
-
-static const unsigned gpio_x1_aud_pbb3_pins[] = {
-       TEGRA_PIN_GPIO_X1_AUD_PBB3,
-};
-
-static const unsigned gpio_x3_aud_pbb4_pins[] = {
-       TEGRA_PIN_GPIO_X3_AUD_PBB4,
-};
-
-static const unsigned hdmi_cec_pcc0_pins[] = {
-       TEGRA_PIN_HDMI_CEC_PCC0,
-};
-
-static const unsigned hdmi_int_dp_hpd_pcc1_pins[] = {
-       TEGRA_PIN_HDMI_INT_DP_HPD_PCC1,
-};
-
-static const unsigned spdif_out_pcc2_pins[] = {
-       TEGRA_PIN_SPDIF_OUT_PCC2,
-};
-
-static const unsigned spdif_in_pcc3_pins[] = {
-       TEGRA_PIN_SPDIF_IN_PCC3,
-};
-
-static const unsigned usb_vbus_en0_pcc4_pins[] = {
-       TEGRA_PIN_USB_VBUS_EN0_PCC4,
-};
-
-static const unsigned usb_vbus_en1_pcc5_pins[] = {
-       TEGRA_PIN_USB_VBUS_EN1_PCC5,
-};
-
-static const unsigned dp_hpd0_pcc6_pins[] = {
-       TEGRA_PIN_DP_HPD0_PCC6,
-};
-
-static const unsigned pcc7_pins[] = {
-       TEGRA_PIN_PCC7,
-};
-
-static const unsigned spi2_cs1_pdd0_pins[] = {
-       TEGRA_PIN_SPI2_CS1_PDD0,
-};
-
-static const unsigned qspi_sck_pee0_pins[] = {
-       TEGRA_PIN_QSPI_SCK_PEE0,
-};
-
-static const unsigned qspi_cs_n_pee1_pins[] = {
-       TEGRA_PIN_QSPI_CS_N_PEE1,
-};
-
-static const unsigned qspi_io0_pee2_pins[] = {
-       TEGRA_PIN_QSPI_IO0_PEE2,
-};
-
-static const unsigned qspi_io1_pee3_pins[] = {
-       TEGRA_PIN_QSPI_IO1_PEE3,
-};
-
-static const unsigned qspi_io2_pee4_pins[] = {
-       TEGRA_PIN_QSPI_IO2_PEE4,
-};
-
-static const unsigned qspi_io3_pee5_pins[] = {
-       TEGRA_PIN_QSPI_IO3_PEE5,
-};
-
-static const unsigned core_pwr_req_pins[] = {
-       TEGRA_PIN_CORE_PWR_REQ,
-};
-
-static const unsigned cpu_pwr_req_pins[] = {
-       TEGRA_PIN_CPU_PWR_REQ,
-};
-
-static const unsigned pwr_int_n_pins[] = {
-       TEGRA_PIN_PWR_INT_N,
-};
-
-static const unsigned clk_32k_in_pins[] = {
-       TEGRA_PIN_CLK_32K_IN,
-};
-
-static const unsigned jtag_rtck_pins[] = {
-       TEGRA_PIN_JTAG_RTCK,
-};
-
-static const unsigned batt_bcl_pins[] = {
-       TEGRA_PIN_BATT_BCL,
-};
-
-static const unsigned clk_req_pins[] = {
-       TEGRA_PIN_CLK_REQ,
-};
-
-static const unsigned shutdown_pins[] = {
-       TEGRA_PIN_SHUTDOWN,
-};
-
-static const unsigned drive_pa6_pins[] = {
-       TEGRA_PIN_PA6,
-};
-
-static const unsigned drive_pcc7_pins[] = {
-       TEGRA_PIN_PCC7,
-};
-
-static const unsigned drive_pe6_pins[] = {
-       TEGRA_PIN_PE6,
-};
-
-static const unsigned drive_pe7_pins[] = {
-       TEGRA_PIN_PE7,
-};
-
-static const unsigned drive_ph6_pins[] = {
-       TEGRA_PIN_PH6,
-};
-
-static const unsigned drive_pk0_pins[] = {
-       TEGRA_PIN_PK0,
-};
-
-static const unsigned drive_pk1_pins[] = {
-       TEGRA_PIN_PK1,
-};
-
-static const unsigned drive_pk2_pins[] = {
-       TEGRA_PIN_PK2,
-};
-
-static const unsigned drive_pk3_pins[] = {
-       TEGRA_PIN_PK3,
-};
-
-static const unsigned drive_pk4_pins[] = {
-       TEGRA_PIN_PK4,
-};
-
-static const unsigned drive_pk5_pins[] = {
-       TEGRA_PIN_PK5,
-};
-
-static const unsigned drive_pk6_pins[] = {
-       TEGRA_PIN_PK6,
-};
-
-static const unsigned drive_pk7_pins[] = {
-       TEGRA_PIN_PK7,
-};
-
-static const unsigned drive_pl0_pins[] = {
-       TEGRA_PIN_PL0,
-};
-
-static const unsigned drive_pl1_pins[] = {
-       TEGRA_PIN_PL1,
-};
-
-static const unsigned drive_pz0_pins[] = {
-       TEGRA_PIN_PZ0,
-};
-
-static const unsigned drive_pz1_pins[] = {
-       TEGRA_PIN_PZ1,
-};
-
-static const unsigned drive_pz2_pins[] = {
-       TEGRA_PIN_PZ2,
-};
-
-static const unsigned drive_pz3_pins[] = {
-       TEGRA_PIN_PZ3,
-};
-
-static const unsigned drive_pz4_pins[] = {
-       TEGRA_PIN_PZ4,
-};
-
-static const unsigned drive_pz5_pins[] = {
-       TEGRA_PIN_PZ5,
-};
-
-static const unsigned drive_sdmmc1_pins[] = {
-       TEGRA_PIN_SDMMC1_CLK_PM0,
-       TEGRA_PIN_SDMMC1_CMD_PM1,
-       TEGRA_PIN_SDMMC1_DAT3_PM2,
-       TEGRA_PIN_SDMMC1_DAT2_PM3,
-       TEGRA_PIN_SDMMC1_DAT1_PM4,
-       TEGRA_PIN_SDMMC1_DAT0_PM5,
-};
-
-static const unsigned drive_sdmmc2_pins[] = {
-};
-
-static const unsigned drive_sdmmc3_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_PP0,
-       TEGRA_PIN_SDMMC3_CMD_PP1,
-       TEGRA_PIN_SDMMC3_DAT3_PP2,
-       TEGRA_PIN_SDMMC3_DAT2_PP3,
-       TEGRA_PIN_SDMMC3_DAT1_PP4,
-       TEGRA_PIN_SDMMC3_DAT0_PP5,
-};
-
-static const unsigned drive_sdmmc4_pins[] = {
-};
-
-enum tegra_mux {
-       TEGRA_MUX_AUD,
-       TEGRA_MUX_BCL,
-       TEGRA_MUX_BLINK,
-       TEGRA_MUX_CCLA,
-       TEGRA_MUX_CEC,
-       TEGRA_MUX_CLDVFS,
-       TEGRA_MUX_CLK,
-       TEGRA_MUX_CORE,
-       TEGRA_MUX_CPU,
-       TEGRA_MUX_DISPLAYA,
-       TEGRA_MUX_DISPLAYB,
-       TEGRA_MUX_DMIC1,
-       TEGRA_MUX_DMIC2,
-       TEGRA_MUX_DMIC3,
-       TEGRA_MUX_DP,
-       TEGRA_MUX_DTV,
-       TEGRA_MUX_EXTPERIPH3,
-       TEGRA_MUX_I2C1,
-       TEGRA_MUX_I2C2,
-       TEGRA_MUX_I2C3,
-       TEGRA_MUX_I2CPMU,
-       TEGRA_MUX_I2CVI,
-       TEGRA_MUX_I2S1,
-       TEGRA_MUX_I2S2,
-       TEGRA_MUX_I2S3,
-       TEGRA_MUX_I2S4A,
-       TEGRA_MUX_I2S4B,
-       TEGRA_MUX_I2S5A,
-       TEGRA_MUX_I2S5B,
-       TEGRA_MUX_IQC0,
-       TEGRA_MUX_IQC1,
-       TEGRA_MUX_JTAG,
-       TEGRA_MUX_PE,
-       TEGRA_MUX_PE0,
-       TEGRA_MUX_PE1,
-       TEGRA_MUX_PMI,
-       TEGRA_MUX_PWM0,
-       TEGRA_MUX_PWM1,
-       TEGRA_MUX_PWM2,
-       TEGRA_MUX_PWM3,
-       TEGRA_MUX_QSPI,
-       TEGRA_MUX_RSVD0,
-       TEGRA_MUX_RSVD1,
-       TEGRA_MUX_RSVD2,
-       TEGRA_MUX_RSVD3,
-       TEGRA_MUX_SATA,
-       TEGRA_MUX_SDMMC1,
-       TEGRA_MUX_SDMMC3,
-       TEGRA_MUX_SHUTDOWN,
-       TEGRA_MUX_SOC,
-       TEGRA_MUX_SOR0,
-       TEGRA_MUX_SOR1,
-       TEGRA_MUX_SPDIF,
-       TEGRA_MUX_SPI1,
-       TEGRA_MUX_SPI2,
-       TEGRA_MUX_SPI3,
-       TEGRA_MUX_SPI4,
-       TEGRA_MUX_SYS,
-       TEGRA_MUX_TOUCH,
-       TEGRA_MUX_UART,
-       TEGRA_MUX_UARTA,
-       TEGRA_MUX_UARTB,
-       TEGRA_MUX_UARTC,
-       TEGRA_MUX_UARTD,
-       TEGRA_MUX_USB,
-       TEGRA_MUX_VGP1,
-       TEGRA_MUX_VGP2,
-       TEGRA_MUX_VGP3,
-       TEGRA_MUX_VGP4,
-       TEGRA_MUX_VGP5,
-       TEGRA_MUX_VGP6,
-       TEGRA_MUX_VIMCLK,
-       TEGRA_MUX_VIMCLK2,
-};
-
-#define FUNCTION(fname)                                        \
-       {                                               \
-               .name = #fname,                         \
-       }
-
-static struct tegra_function tegra210_functions[] = {
-       FUNCTION(aud),
-       FUNCTION(bcl),
-       FUNCTION(blink),
-       FUNCTION(ccla),
-       FUNCTION(cec),
-       FUNCTION(cldvfs),
-       FUNCTION(clk),
-       FUNCTION(core),
-       FUNCTION(cpu),
-       FUNCTION(displaya),
-       FUNCTION(displayb),
-       FUNCTION(dmic1),
-       FUNCTION(dmic2),
-       FUNCTION(dmic3),
-       FUNCTION(dp),
-       FUNCTION(dtv),
-       FUNCTION(extperiph3),
-       FUNCTION(i2c1),
-       FUNCTION(i2c2),
-       FUNCTION(i2c3),
-       FUNCTION(i2cpmu),
-       FUNCTION(i2cvi),
-       FUNCTION(i2s1),
-       FUNCTION(i2s2),
-       FUNCTION(i2s3),
-       FUNCTION(i2s4a),
-       FUNCTION(i2s4b),
-       FUNCTION(i2s5a),
-       FUNCTION(i2s5b),
-       FUNCTION(iqc0),
-       FUNCTION(iqc1),
-       FUNCTION(jtag),
-       FUNCTION(pe),
-       FUNCTION(pe0),
-       FUNCTION(pe1),
-       FUNCTION(pmi),
-       FUNCTION(pwm0),
-       FUNCTION(pwm1),
-       FUNCTION(pwm2),
-       FUNCTION(pwm3),
-       FUNCTION(qspi),
-       FUNCTION(rsvd0),
-       FUNCTION(rsvd1),
-       FUNCTION(rsvd2),
-       FUNCTION(rsvd3),
-       FUNCTION(sata),
-       FUNCTION(sdmmc1),
-       FUNCTION(sdmmc3),
-       FUNCTION(shutdown),
-       FUNCTION(soc),
-       FUNCTION(sor0),
-       FUNCTION(sor1),
-       FUNCTION(spdif),
-       FUNCTION(spi1),
-       FUNCTION(spi2),
-       FUNCTION(spi3),
-       FUNCTION(spi4),
-       FUNCTION(sys),
-       FUNCTION(touch),
-       FUNCTION(uart),
-       FUNCTION(uarta),
-       FUNCTION(uartb),
-       FUNCTION(uartc),
-       FUNCTION(uartd),
-       FUNCTION(usb),
-       FUNCTION(vgp1),
-       FUNCTION(vgp2),
-       FUNCTION(vgp3),
-       FUNCTION(vgp4),
-       FUNCTION(vgp5),
-       FUNCTION(vgp6),
-       FUNCTION(vimclk),
-       FUNCTION(vimclk2),
-};
-
-#define DRV_PINGROUP_REG_A             0x8d4   /* bank 0 */
-#define PINGROUP_REG_A                 0x3000  /* bank 1 */
-
-#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
-#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
-
-#define PINGROUP_BIT_Y(b)              (b)
-#define PINGROUP_BIT_N(b)              (-1)
-
-#define PINGROUP(pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv,    \
-                rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b,      \
-                slwr_w, slwf_b, slwf_w)                                \
-       {                                                               \
-               .name = #pg_name,                                       \
-               .pins = pg_name##_pins,                                 \
-               .npins = ARRAY_SIZE(pg_name##_pins),                    \
-               .funcs = {                                              \
-                       TEGRA_MUX_##f0,                                 \
-                       TEGRA_MUX_##f1,                                 \
-                       TEGRA_MUX_##f2,                                 \
-                       TEGRA_MUX_##f3,                                 \
-               },                                                      \
-               .mux_reg = PINGROUP_REG(r),                             \
-               .mux_bank = 1,                                          \
-               .mux_bit = 0,                                           \
-               .pupd_reg = PINGROUP_REG(r),                            \
-               .pupd_bank = 1,                                         \
-               .pupd_bit = 2,                                          \
-               .tri_reg = PINGROUP_REG(r),                             \
-               .tri_bank = 1,                                          \
-               .tri_bit = 4,                                           \
-               .einput_bit = 6,                                        \
-               .odrain_bit = 11,                                       \
-               .lock_bit = 7,                                          \
-               .ioreset_bit = -1,                                      \
-               .rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10),              \
-               .hsm_bit = PINGROUP_BIT_##hsm(9),                       \
-               .schmitt_bit = 12,                                      \
-               .drvtype_bit = PINGROUP_BIT_##drvtype(13),              \
-               .drv_reg = DRV_PINGROUP_REG(rdrv),                      \
-               .drv_bank = 0,                                          \
-               .lpmd_bit = -1,                                         \
-               .drvdn_bit = drvdn_b,                                   \
-               .drvdn_width = drvdn_w,                                 \
-               .drvup_bit = drvup_b,                                   \
-               .drvup_width = drvup_w,                                 \
-               .slwr_bit = slwr_b,                                     \
-               .slwr_width = slwr_w,                                   \
-               .slwf_bit = slwf_b,                                     \
-               .slwf_width = slwf_w,                                   \
-       }
-
-#define DRV_PINGROUP(pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w,   \
-                    slwr_b, slwr_w, slwf_b, slwf_w)                    \
-       {                                                               \
-               .name = "drive_" #pg_name,                              \
-               .pins = drive_##pg_name##_pins,                         \
-               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
-               .mux_reg = -1,                                          \
-               .pupd_reg = -1,                                         \
-               .tri_reg = -1,                                          \
-               .einput_bit = -1,                                       \
-               .odrain_bit = -1,                                       \
-               .lock_bit = -1,                                         \
-               .ioreset_bit = -1,                                      \
-               .rcv_sel_bit = -1,                                      \
-               .drv_reg = DRV_PINGROUP_REG(r),                         \
-               .drv_bank = 0,                                          \
-               .hsm_bit = -1,                                          \
-               .schmitt_bit = -1,                                      \
-               .lpmd_bit = -1,                                         \
-               .drvdn_bit = drvdn_b,                                   \
-               .drvdn_width = drvdn_w,                                 \
-               .drvup_bit = drvup_b,                                   \
-               .drvup_width = drvup_w,                                 \
-               .slwr_bit = slwr_b,                                     \
-               .slwr_width = slwr_w,                                   \
-               .slwf_bit = slwf_b,                                     \
-               .slwf_width = slwf_w,                                   \
-               .drvtype_bit = -1,                                      \
-       }
-
-static const struct tegra_pingroup tegra210_groups[] = {
-       /*       pg_name,              f0,         f1,     f2,    f3,    r,      hsm, drvtype, e_io_hv, rdrv,  drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
-       PINGROUP(sdmmc1_clk_pm0,       SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x3000, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc1_cmd_pm1,       SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3004, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc1_dat3_pm2,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3008, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc1_dat2_pm3,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x300c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc1_dat1_pm4,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3010, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc1_dat0_pm5,      SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x3014, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc3_clk_pp0,       SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x301c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc3_cmd_pp1,       SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3020, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc3_dat0_pp5,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3024, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc3_dat1_pp4,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3028, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc3_dat2_pp3,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x302c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(sdmmc3_dat3_pp2,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3030, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pex_l0_rst_n_pa0,     PE0,        RSVD1,  RSVD2, RSVD3, 0x3038, N,   N,       Y,       0xa5c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pex_l0_clkreq_n_pa1,  PE0,        RSVD1,  RSVD2, RSVD3, 0x303c, N,   N,       Y,       0xa58, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pex_wake_n_pa2,       PE,         RSVD1,  RSVD2, RSVD3, 0x3040, N,   N,       Y,       0xa68, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pex_l1_rst_n_pa3,     PE1,        RSVD1,  RSVD2, RSVD3, 0x3044, N,   N,       Y,       0xa64, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pex_l1_clkreq_n_pa4,  PE1,        RSVD1,  RSVD2, RSVD3, 0x3048, N,   N,       Y,       0xa60, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(sata_led_active_pa5,  SATA,       RSVD1,  RSVD2, RSVD3, 0x304c, N,   N,       N,       0xa94, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(spi1_mosi_pc0,        SPI1,       RSVD1,  RSVD2, RSVD3, 0x3050, Y,   Y,       N,       0xae0, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi1_miso_pc1,        SPI1,       RSVD1,  RSVD2, RSVD3, 0x3054, Y,   Y,       N,       0xadc, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi1_sck_pc2,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x3058, Y,   Y,       N,       0xae4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi1_cs0_pc3,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x305c, Y,   Y,       N,       0xad4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi1_cs1_pc4,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x3060, Y,   Y,       N,       0xad8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi2_mosi_pb4,        SPI2,       DTV,    RSVD2, RSVD3, 0x3064, Y,   Y,       N,       0xaf4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi2_miso_pb5,        SPI2,       DTV,    RSVD2, RSVD3, 0x3068, Y,   Y,       N,       0xaf0, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi2_sck_pb6,         SPI2,       DTV,    RSVD2, RSVD3, 0x306c, Y,   Y,       N,       0xaf8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi2_cs0_pb7,         SPI2,       DTV,    RSVD2, RSVD3, 0x3070, Y,   Y,       N,       0xae8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi2_cs1_pdd0,        SPI2,       RSVD1,  RSVD2, RSVD3, 0x3074, Y,   Y,       N,       0xaec, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi4_mosi_pc7,        SPI4,       RSVD1,  RSVD2, RSVD3, 0x3078, Y,   Y,       N,       0xb04, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi4_miso_pd0,        SPI4,       RSVD1,  RSVD2, RSVD3, 0x307c, Y,   Y,       N,       0xb00, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi4_sck_pc5,         SPI4,       RSVD1,  RSVD2, RSVD3, 0x3080, Y,   Y,       N,       0xb08, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(spi4_cs0_pc6,         SPI4,       RSVD1,  RSVD2, RSVD3, 0x3084, Y,   Y,       N,       0xafc, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(qspi_sck_pee0,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3088, Y,   Y,       N,       0xa90, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(qspi_cs_n_pee1,       QSPI,       RSVD1,  RSVD2, RSVD3, 0x308c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(qspi_io0_pee2,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3090, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(qspi_io1_pee3,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3094, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(qspi_io2_pee4,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3098, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(qspi_io3_pee5,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x309c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(dmic1_clk_pe0,        DMIC1,      I2S3,   RSVD2, RSVD3, 0x30a4, N,   N,       N,       0x984, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dmic1_dat_pe1,        DMIC1,      I2S3,   RSVD2, RSVD3, 0x30a8, N,   N,       N,       0x988, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dmic2_clk_pe2,        DMIC2,      I2S3,   RSVD2, RSVD3, 0x30ac, N,   N,       N,       0x98c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dmic2_dat_pe3,        DMIC2,      I2S3,   RSVD2, RSVD3, 0x30b0, N,   N,       N,       0x990, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dmic3_clk_pe4,        DMIC3,      I2S5A,  RSVD2, RSVD3, 0x30b4, N,   N,       N,       0x994, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dmic3_dat_pe5,        DMIC3,      I2S5A,  RSVD2, RSVD3, 0x30b8, N,   N,       N,       0x998, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gen1_i2c_scl_pj1,     I2C1,       RSVD1,  RSVD2, RSVD3, 0x30bc, N,   N,       Y,       0x9a8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gen1_i2c_sda_pj0,     I2C1,       RSVD1,  RSVD2, RSVD3, 0x30c0, N,   N,       Y,       0x9ac, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gen2_i2c_scl_pj2,     I2C2,       RSVD1,  RSVD2, RSVD3, 0x30c4, N,   N,       Y,       0x9b0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gen2_i2c_sda_pj3,     I2C2,       RSVD1,  RSVD2, RSVD3, 0x30c8, N,   N,       Y,       0x9b4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gen3_i2c_scl_pf0,     I2C3,       RSVD1,  RSVD2, RSVD3, 0x30cc, N,   N,       Y,       0x9b8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gen3_i2c_sda_pf1,     I2C3,       RSVD1,  RSVD2, RSVD3, 0x30d0, N,   N,       Y,       0x9bc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam_i2c_scl_ps2,      I2C3,       I2CVI,  RSVD2, RSVD3, 0x30d4, N,   N,       Y,       0x934, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam_i2c_sda_ps3,      I2C3,       I2CVI,  RSVD2, RSVD3, 0x30d8, N,   N,       Y,       0x938, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pwr_i2c_scl_py3,      I2CPMU,     RSVD1,  RSVD2, RSVD3, 0x30dc, N,   N,       Y,       0xa6c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pwr_i2c_sda_py4,      I2CPMU,     RSVD1,  RSVD2, RSVD3, 0x30e0, N,   N,       Y,       0xa70, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart1_tx_pu0,         UARTA,      RSVD1,  RSVD2, RSVD3, 0x30e4, N,   N,       N,       0xb28, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart1_rx_pu1,         UARTA,      RSVD1,  RSVD2, RSVD3, 0x30e8, N,   N,       N,       0xb24, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart1_rts_pu2,        UARTA,      RSVD1,  RSVD2, RSVD3, 0x30ec, N,   N,       N,       0xb20, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart1_cts_pu3,        UARTA,      RSVD1,  RSVD2, RSVD3, 0x30f0, N,   N,       N,       0xb1c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart2_tx_pg0,         UARTB,      I2S4A,  SPDIF, UART,  0x30f4, N,   N,       N,       0xb38, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart2_rx_pg1,         UARTB,      I2S4A,  SPDIF, UART,  0x30f8, N,   N,       N,       0xb34, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart2_rts_pg2,        UARTB,      I2S4A,  RSVD2, UART,  0x30fc, N,   N,       N,       0xb30, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart2_cts_pg3,        UARTB,      I2S4A,  RSVD2, UART,  0x3100, N,   N,       N,       0xb2c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart3_tx_pd1,         UARTC,      SPI4,   RSVD2, RSVD3, 0x3104, N,   N,       N,       0xb48, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart3_rx_pd2,         UARTC,      SPI4,   RSVD2, RSVD3, 0x3108, N,   N,       N,       0xb44, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart3_rts_pd3,        UARTC,      SPI4,   RSVD2, RSVD3, 0x310c, N,   N,       N,       0xb40, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart3_cts_pd4,        UARTC,      SPI4,   RSVD2, RSVD3, 0x3110, N,   N,       N,       0xb3c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart4_tx_pi4,         UARTD,      UART,   RSVD2, RSVD3, 0x3114, N,   N,       N,       0xb58, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart4_rx_pi5,         UARTD,      UART,   RSVD2, RSVD3, 0x3118, N,   N,       N,       0xb54, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart4_rts_pi6,        UARTD,      UART,   RSVD2, RSVD3, 0x311c, N,   N,       N,       0xb50, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(uart4_cts_pi7,        UARTD,      UART,   RSVD2, RSVD3, 0x3120, N,   N,       N,       0xb4c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dap1_fs_pb0,          I2S1,       RSVD1,  RSVD2, RSVD3, 0x3124, Y,   Y,       N,       0x95c, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(dap1_din_pb1,         I2S1,       RSVD1,  RSVD2, RSVD3, 0x3128, Y,   Y,       N,       0x954, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(dap1_dout_pb2,        I2S1,       RSVD1,  RSVD2, RSVD3, 0x312c, Y,   Y,       N,       0x958, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(dap1_sclk_pb3,        I2S1,       RSVD1,  RSVD2, RSVD3, 0x3130, Y,   Y,       N,       0x960, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(dap2_fs_paa0,         I2S2,       RSVD1,  RSVD2, RSVD3, 0x3134, Y,   Y,       N,       0x96c, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(dap2_din_paa2,        I2S2,       RSVD1,  RSVD2, RSVD3, 0x3138, Y,   Y,       N,       0x964, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(dap2_dout_paa3,       I2S2,       RSVD1,  RSVD2, RSVD3, 0x313c, Y,   Y,       N,       0x968, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(dap2_sclk_paa1,       I2S2,       RSVD1,  RSVD2, RSVD3, 0x3140, Y,   Y,       N,       0x970, -1,      -1,      -1,      -1,      28,     2,      30,     2),
-       PINGROUP(dap4_fs_pj4,          I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3144, N,   N,       N,       0x97c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dap4_din_pj5,         I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3148, N,   N,       N,       0x974, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dap4_dout_pj6,        I2S4B,      RSVD1,  RSVD2, RSVD3, 0x314c, N,   N,       N,       0x978, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dap4_sclk_pj7,        I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3150, N,   N,       N,       0x980, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam1_mclk_ps0,        EXTPERIPH3, RSVD1,  RSVD2, RSVD3, 0x3154, N,   N,       N,       0x918, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam2_mclk_ps1,        EXTPERIPH3, RSVD1,  RSVD2, RSVD3, 0x3158, N,   N,       N,       0x924, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(jtag_rtck,            JTAG,       RSVD1,  RSVD2, RSVD3, 0x315c, N,   N,       N,       0xa2c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(clk_32k_in,           CLK,        RSVD1,  RSVD2, RSVD3, 0x3160, N,   N,       N,       0x940, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(clk_32k_out_py5,      SOC,        BLINK,  RSVD2, RSVD3, 0x3164, N,   N,       N,       0x944, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(batt_bcl,             BCL,        RSVD1,  RSVD2, RSVD3, 0x3168, N,   N,       Y,       0x8f8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(clk_req,              SYS,        RSVD1,  RSVD2, RSVD3, 0x316c, N,   N,       N,       0x948, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cpu_pwr_req,          CPU,        RSVD1,  RSVD2, RSVD3, 0x3170, N,   N,       N,       0x950, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pwr_int_n,            PMI,        RSVD1,  RSVD2, RSVD3, 0x3174, N,   N,       N,       0xa74, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(shutdown,             SHUTDOWN,   RSVD1,  RSVD2, RSVD3, 0x3178, N,   N,       N,       0xac8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(core_pwr_req,         CORE,       RSVD1,  RSVD2, RSVD3, 0x317c, N,   N,       N,       0x94c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(aud_mclk_pbb0,        AUD,        RSVD1,  RSVD2, RSVD3, 0x3180, N,   N,       N,       0x8f4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dvfs_pwm_pbb1,        RSVD0,      CLDVFS, SPI3,  RSVD3, 0x3184, N,   N,       N,       0x9a4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dvfs_clk_pbb2,        RSVD0,      CLDVFS, SPI3,  RSVD3, 0x3188, N,   N,       N,       0x9a0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gpio_x1_aud_pbb3,     RSVD0,      RSVD1,  SPI3,  RSVD3, 0x318c, N,   N,       N,       0xa14, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gpio_x3_aud_pbb4,     RSVD0,      RSVD1,  SPI3,  RSVD3, 0x3190, N,   N,       N,       0xa18, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pcc7,                 RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3194, N,   N,       Y,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(hdmi_cec_pcc0,        CEC,        RSVD1,  RSVD2, RSVD3, 0x3198, N,   N,       Y,       0xa24, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(hdmi_int_dp_hpd_pcc1, DP,         RSVD1,  RSVD2, RSVD3, 0x319c, N,   N,       Y,       0xa28, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(spdif_out_pcc2,       SPDIF,      RSVD1,  RSVD2, RSVD3, 0x31a0, N,   N,       N,       0xad0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(spdif_in_pcc3,        SPDIF,      RSVD1,  RSVD2, RSVD3, 0x31a4, N,   N,       N,       0xacc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(usb_vbus_en0_pcc4,    USB,        RSVD1,  RSVD2, RSVD3, 0x31a8, N,   N,       Y,       0xb5c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(usb_vbus_en1_pcc5,    USB,        RSVD1,  RSVD2, RSVD3, 0x31ac, N,   N,       Y,       0xb60, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(dp_hpd0_pcc6,         DP,         RSVD1,  RSVD2, RSVD3, 0x31b0, N,   N,       N,       0x99c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(wifi_en_ph0,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31b4, N,   N,       N,       0xb64, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(wifi_rst_ph1,         RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31b8, N,   N,       N,       0xb68, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(wifi_wake_ap_ph2,     RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31bc, N,   N,       N,       0xb6c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(ap_wake_bt_ph3,       RSVD0,      UARTB,  SPDIF, RSVD3, 0x31c0, N,   N,       N,       0x8ec, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(bt_rst_ph4,           RSVD0,      UARTB,  SPDIF, RSVD3, 0x31c4, N,   N,       N,       0x8fc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(bt_wake_ap_ph5,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31c8, N,   N,       N,       0x900, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(ap_wake_nfc_ph7,      RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31cc, N,   N,       N,       0x8f0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(nfc_en_pi0,           RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d0, N,   N,       N,       0xa50, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(nfc_int_pi1,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d4, N,   N,       N,       0xa54, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gps_en_pi2,           RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d8, N,   N,       N,       0xa1c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(gps_rst_pi3,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31dc, N,   N,       N,       0xa20, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam_rst_ps4,          VGP1,       RSVD1,  RSVD2, RSVD3, 0x31e0, N,   N,       N,       0x93c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam_af_en_ps5,        VIMCLK,     VGP2,   RSVD2, RSVD3, 0x31e4, N,   N,       N,       0x92c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam_flash_en_ps6,     VIMCLK,     VGP3,   RSVD2, RSVD3, 0x31e8, N,   N,       N,       0x930, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam1_pwdn_ps7,        VGP4,       RSVD1,  RSVD2, RSVD3, 0x31ec, N,   N,       N,       0x91c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam2_pwdn_pt0,        VGP5,       RSVD1,  RSVD2, RSVD3, 0x31f0, N,   N,       N,       0x928, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(cam1_strobe_pt1,      VGP6,       RSVD1,  RSVD2, RSVD3, 0x31f4, N,   N,       N,       0x920, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(lcd_te_py2,           DISPLAYA,   RSVD1,  RSVD2, RSVD3, 0x31f8, N,   N,       N,       0xa44, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(lcd_bl_pwm_pv0,       DISPLAYA,   PWM0,   SOR0,  RSVD3, 0x31fc, N,   N,       N,       0xa34, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(lcd_bl_en_pv1,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3200, N,   N,       N,       0xa30, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(lcd_rst_pv2,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3204, N,   N,       N,       0xa40, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(lcd_gpio1_pv3,        DISPLAYB,   RSVD1,  RSVD2, RSVD3, 0x3208, N,   N,       N,       0xa38, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(lcd_gpio2_pv4,        DISPLAYB,   PWM1,   RSVD2, SOR1,  0x320c, N,   N,       N,       0xa3c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(ap_ready_pv5,         RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3210, N,   N,       N,       0x8e8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(touch_rst_pv6,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3214, N,   N,       N,       0xb18, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(touch_clk_pv7,        TOUCH,      RSVD1,  RSVD2, RSVD3, 0x3218, N,   N,       N,       0xb10, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(modem_wake_ap_px0,    RSVD0,      RSVD1,  RSVD2, RSVD3, 0x321c, N,   N,       N,       0xa48, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(touch_int_px1,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3220, N,   N,       N,       0xb14, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(motion_int_px2,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3224, N,   N,       N,       0xa4c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(als_prox_int_px3,     RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3228, N,   N,       N,       0x8e4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(temp_alert_px4,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x322c, N,   N,       N,       0xb0c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(button_power_on_px5,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3230, N,   N,       N,       0x908, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(button_vol_up_px6,    RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3234, N,   N,       N,       0x914, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(button_vol_down_px7,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3238, N,   N,       N,       0x910, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(button_slide_sw_py0,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x323c, N,   N,       N,       0x90c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(button_home_py1,      RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3240, N,   N,       N,       0x904, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
-       PINGROUP(pa6,                  SATA,       RSVD1,  RSVD2, RSVD3, 0x3244, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pe6,                  RSVD0,      I2S5A,  PWM2,  RSVD3, 0x3248, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pe7,                  RSVD0,      I2S5A,  PWM3,  RSVD3, 0x324c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(ph6,                  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3250, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pk0,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3254, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pk1,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3258, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pk2,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x325c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pk3,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3260, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pk4,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3264, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pk5,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3268, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pk6,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x326c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pk7,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3270, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pl0,                  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3274, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pl1,                  SOC,        RSVD1,  RSVD2, RSVD3, 0x3278, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pz0,                  VIMCLK2,    RSVD1,  RSVD2, RSVD3, 0x327c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pz1,                  VIMCLK2,    SDMMC1, RSVD2, RSVD3, 0x3280, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pz2,                  SDMMC3,     CCLA,   RSVD2, RSVD3, 0x3284, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pz3,                  SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3288, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pz4,                  SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x328c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-       PINGROUP(pz5,                  SOC,        RSVD1,  RSVD2, RSVD3, 0x3290, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
-
-       /* pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
-       DRV_PINGROUP(pa6,    0x9c0, 12, 5,  20, 5,  -1, -1, -1, -1),
-       DRV_PINGROUP(pcc7,   0x9c4, 12, 5,  20, 5,  -1, -1, -1, -1),
-       DRV_PINGROUP(pe6,    0x9c8, 12, 5,  20, 5,  -1, -1, -1, -1),
-       DRV_PINGROUP(pe7,    0x9cc, 12, 5,  20, 5,  -1, -1, -1, -1),
-       DRV_PINGROUP(ph6,    0x9d0, 12, 5,  20, 5,  -1, -1, -1, -1),
-       DRV_PINGROUP(pk0,    0x9d4, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pk1,    0x9d8, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pk2,    0x9dc, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pk3,    0x9e0, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pk4,    0x9e4, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pk5,    0x9e8, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pk6,    0x9ec, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pk7,    0x9f0, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pl0,    0x9f4, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pl1,    0x9f8, -1, -1, -1, -1, 28, 2,  30, 2),
-       DRV_PINGROUP(pz0,    0x9fc, 12, 7,  20, 7,  -1, -1, -1, -1),
-       DRV_PINGROUP(pz1,    0xa00, 12, 7,  20, 7,  -1, -1, -1, -1),
-       DRV_PINGROUP(pz2,    0xa04, 12, 7,  20, 7,  -1, -1, -1, -1),
-       DRV_PINGROUP(pz3,    0xa08, 12, 7,  20, 7,  -1, -1, -1, -1),
-       DRV_PINGROUP(pz4,    0xa0c, 12, 7,  20, 7,  -1, -1, -1, -1),
-       DRV_PINGROUP(pz5,    0xa10, 12, 7,  20, 7,  -1, -1, -1, -1),
-       DRV_PINGROUP(sdmmc1, 0xa98, 12, 7,  20, 7,  28, 2,  30, 2),
-       DRV_PINGROUP(sdmmc2, 0xa9c, 2,  6,  8,  6,  28, 2,  30, 2),
-       DRV_PINGROUP(sdmmc3, 0xab0, 12, 7,  20, 7,  28, 2,  30, 2),
-       DRV_PINGROUP(sdmmc4, 0xab4, 2,  6,  8,  6,  28, 2,  30, 2),
-};
-
-static const struct tegra_pinctrl_soc_data tegra210_pinctrl = {
-       .ngpios = NUM_GPIOS,
-       .pins = tegra210_pins,
-       .npins = ARRAY_SIZE(tegra210_pins),
-       .functions = tegra210_functions,
-       .nfunctions = ARRAY_SIZE(tegra210_functions),
-       .groups = tegra210_groups,
-       .ngroups = ARRAY_SIZE(tegra210_groups),
-       .hsm_in_mux = true,
-       .schmitt_in_mux = true,
-       .drvtype_in_mux = true,
-};
-
-static int tegra210_pinctrl_probe(struct platform_device *pdev)
-{
-       return tegra_pinctrl_probe(pdev, &tegra210_pinctrl);
-}
-
-static const struct of_device_id tegra210_pinctrl_of_match[] = {
-       { .compatible = "nvidia,tegra210-pinmux", },
-       { },
-};
-MODULE_DEVICE_TABLE(of, tegra210_pinctrl_of_match);
-
-static struct platform_driver tegra210_pinctrl_driver = {
-       .driver = {
-               .name = "tegra210-pinctrl",
-               .of_match_table = tegra210_pinctrl_of_match,
-       },
-       .probe = tegra210_pinctrl_probe,
-       .remove = tegra_pinctrl_remove,
-};
-module_platform_driver(tegra210_pinctrl_driver);
-
-MODULE_AUTHOR("NVIDIA");
-MODULE_DESCRIPTION("NVIDIA Tegra210 pinctrl driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c
deleted file mode 100644 (file)
index 47b2fd8..0000000
+++ /dev/null
@@ -1,2507 +0,0 @@
-/*
- * Pinctrl data for the NVIDIA Tegra30 pinmux
- *
- * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * 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/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-
-#include "pinctrl-tegra.h"
-
-/*
- * Most pins affected by the pinmux can also be GPIOs. Define these first.
- * These must match how the GPIO driver names/numbers its pins.
- */
-#define _GPIO(offset)                  (offset)
-
-#define TEGRA_PIN_CLK_32K_OUT_PA0      _GPIO(0)
-#define TEGRA_PIN_UART3_CTS_N_PA1      _GPIO(1)
-#define TEGRA_PIN_DAP2_FS_PA2          _GPIO(2)
-#define TEGRA_PIN_DAP2_SCLK_PA3                _GPIO(3)
-#define TEGRA_PIN_DAP2_DIN_PA4         _GPIO(4)
-#define TEGRA_PIN_DAP2_DOUT_PA5                _GPIO(5)
-#define TEGRA_PIN_SDMMC3_CLK_PA6       _GPIO(6)
-#define TEGRA_PIN_SDMMC3_CMD_PA7       _GPIO(7)
-#define TEGRA_PIN_GMI_A17_PB0          _GPIO(8)
-#define TEGRA_PIN_GMI_A18_PB1          _GPIO(9)
-#define TEGRA_PIN_LCD_PWR0_PB2         _GPIO(10)
-#define TEGRA_PIN_LCD_PCLK_PB3         _GPIO(11)
-#define TEGRA_PIN_SDMMC3_DAT3_PB4      _GPIO(12)
-#define TEGRA_PIN_SDMMC3_DAT2_PB5      _GPIO(13)
-#define TEGRA_PIN_SDMMC3_DAT1_PB6      _GPIO(14)
-#define TEGRA_PIN_SDMMC3_DAT0_PB7      _GPIO(15)
-#define TEGRA_PIN_UART3_RTS_N_PC0      _GPIO(16)
-#define TEGRA_PIN_LCD_PWR1_PC1         _GPIO(17)
-#define TEGRA_PIN_UART2_TXD_PC2                _GPIO(18)
-#define TEGRA_PIN_UART2_RXD_PC3                _GPIO(19)
-#define TEGRA_PIN_GEN1_I2C_SCL_PC4     _GPIO(20)
-#define TEGRA_PIN_GEN1_I2C_SDA_PC5     _GPIO(21)
-#define TEGRA_PIN_LCD_PWR2_PC6         _GPIO(22)
-#define TEGRA_PIN_GMI_WP_N_PC7         _GPIO(23)
-#define TEGRA_PIN_SDMMC3_DAT5_PD0      _GPIO(24)
-#define TEGRA_PIN_SDMMC3_DAT4_PD1      _GPIO(25)
-#define TEGRA_PIN_LCD_DC1_PD2          _GPIO(26)
-#define TEGRA_PIN_SDMMC3_DAT6_PD3      _GPIO(27)
-#define TEGRA_PIN_SDMMC3_DAT7_PD4      _GPIO(28)
-#define TEGRA_PIN_VI_D1_PD5            _GPIO(29)
-#define TEGRA_PIN_VI_VSYNC_PD6         _GPIO(30)
-#define TEGRA_PIN_VI_HSYNC_PD7         _GPIO(31)
-#define TEGRA_PIN_LCD_D0_PE0           _GPIO(32)
-#define TEGRA_PIN_LCD_D1_PE1           _GPIO(33)
-#define TEGRA_PIN_LCD_D2_PE2           _GPIO(34)
-#define TEGRA_PIN_LCD_D3_PE3           _GPIO(35)
-#define TEGRA_PIN_LCD_D4_PE4           _GPIO(36)
-#define TEGRA_PIN_LCD_D5_PE5           _GPIO(37)
-#define TEGRA_PIN_LCD_D6_PE6           _GPIO(38)
-#define TEGRA_PIN_LCD_D7_PE7           _GPIO(39)
-#define TEGRA_PIN_LCD_D8_PF0           _GPIO(40)
-#define TEGRA_PIN_LCD_D9_PF1           _GPIO(41)
-#define TEGRA_PIN_LCD_D10_PF2          _GPIO(42)
-#define TEGRA_PIN_LCD_D11_PF3          _GPIO(43)
-#define TEGRA_PIN_LCD_D12_PF4          _GPIO(44)
-#define TEGRA_PIN_LCD_D13_PF5          _GPIO(45)
-#define TEGRA_PIN_LCD_D14_PF6          _GPIO(46)
-#define TEGRA_PIN_LCD_D15_PF7          _GPIO(47)
-#define TEGRA_PIN_GMI_AD0_PG0          _GPIO(48)
-#define TEGRA_PIN_GMI_AD1_PG1          _GPIO(49)
-#define TEGRA_PIN_GMI_AD2_PG2          _GPIO(50)
-#define TEGRA_PIN_GMI_AD3_PG3          _GPIO(51)
-#define TEGRA_PIN_GMI_AD4_PG4          _GPIO(52)
-#define TEGRA_PIN_GMI_AD5_PG5          _GPIO(53)
-#define TEGRA_PIN_GMI_AD6_PG6          _GPIO(54)
-#define TEGRA_PIN_GMI_AD7_PG7          _GPIO(55)
-#define TEGRA_PIN_GMI_AD8_PH0          _GPIO(56)
-#define TEGRA_PIN_GMI_AD9_PH1          _GPIO(57)
-#define TEGRA_PIN_GMI_AD10_PH2         _GPIO(58)
-#define TEGRA_PIN_GMI_AD11_PH3         _GPIO(59)
-#define TEGRA_PIN_GMI_AD12_PH4         _GPIO(60)
-#define TEGRA_PIN_GMI_AD13_PH5         _GPIO(61)
-#define TEGRA_PIN_GMI_AD14_PH6         _GPIO(62)
-#define TEGRA_PIN_GMI_AD15_PH7         _GPIO(63)
-#define TEGRA_PIN_GMI_WR_N_PI0         _GPIO(64)
-#define TEGRA_PIN_GMI_OE_N_PI1         _GPIO(65)
-#define TEGRA_PIN_GMI_DQS_PI2          _GPIO(66)
-#define TEGRA_PIN_GMI_CS6_N_PI3                _GPIO(67)
-#define TEGRA_PIN_GMI_RST_N_PI4                _GPIO(68)
-#define TEGRA_PIN_GMI_IORDY_PI5                _GPIO(69)
-#define TEGRA_PIN_GMI_CS7_N_PI6                _GPIO(70)
-#define TEGRA_PIN_GMI_WAIT_PI7         _GPIO(71)
-#define TEGRA_PIN_GMI_CS0_N_PJ0                _GPIO(72)
-#define TEGRA_PIN_LCD_DE_PJ1           _GPIO(73)
-#define TEGRA_PIN_GMI_CS1_N_PJ2                _GPIO(74)
-#define TEGRA_PIN_LCD_HSYNC_PJ3                _GPIO(75)
-#define TEGRA_PIN_LCD_VSYNC_PJ4                _GPIO(76)
-#define TEGRA_PIN_UART2_CTS_N_PJ5      _GPIO(77)
-#define TEGRA_PIN_UART2_RTS_N_PJ6      _GPIO(78)
-#define TEGRA_PIN_GMI_A16_PJ7          _GPIO(79)
-#define TEGRA_PIN_GMI_ADV_N_PK0                _GPIO(80)
-#define TEGRA_PIN_GMI_CLK_PK1          _GPIO(81)
-#define TEGRA_PIN_GMI_CS4_N_PK2                _GPIO(82)
-#define TEGRA_PIN_GMI_CS2_N_PK3                _GPIO(83)
-#define TEGRA_PIN_GMI_CS3_N_PK4                _GPIO(84)
-#define TEGRA_PIN_SPDIF_OUT_PK5                _GPIO(85)
-#define TEGRA_PIN_SPDIF_IN_PK6         _GPIO(86)
-#define TEGRA_PIN_GMI_A19_PK7          _GPIO(87)
-#define TEGRA_PIN_VI_D2_PL0            _GPIO(88)
-#define TEGRA_PIN_VI_D3_PL1            _GPIO(89)
-#define TEGRA_PIN_VI_D4_PL2            _GPIO(90)
-#define TEGRA_PIN_VI_D5_PL3            _GPIO(91)
-#define TEGRA_PIN_VI_D6_PL4            _GPIO(92)
-#define TEGRA_PIN_VI_D7_PL5            _GPIO(93)
-#define TEGRA_PIN_VI_D8_PL6            _GPIO(94)
-#define TEGRA_PIN_VI_D9_PL7            _GPIO(95)
-#define TEGRA_PIN_LCD_D16_PM0          _GPIO(96)
-#define TEGRA_PIN_LCD_D17_PM1          _GPIO(97)
-#define TEGRA_PIN_LCD_D18_PM2          _GPIO(98)
-#define TEGRA_PIN_LCD_D19_PM3          _GPIO(99)
-#define TEGRA_PIN_LCD_D20_PM4          _GPIO(100)
-#define TEGRA_PIN_LCD_D21_PM5          _GPIO(101)
-#define TEGRA_PIN_LCD_D22_PM6          _GPIO(102)
-#define TEGRA_PIN_LCD_D23_PM7          _GPIO(103)
-#define TEGRA_PIN_DAP1_FS_PN0          _GPIO(104)
-#define TEGRA_PIN_DAP1_DIN_PN1         _GPIO(105)
-#define TEGRA_PIN_DAP1_DOUT_PN2                _GPIO(106)
-#define TEGRA_PIN_DAP1_SCLK_PN3                _GPIO(107)
-#define TEGRA_PIN_LCD_CS0_N_PN4                _GPIO(108)
-#define TEGRA_PIN_LCD_SDOUT_PN5                _GPIO(109)
-#define TEGRA_PIN_LCD_DC0_PN6          _GPIO(110)
-#define TEGRA_PIN_HDMI_INT_PN7         _GPIO(111)
-#define TEGRA_PIN_ULPI_DATA7_PO0       _GPIO(112)
-#define TEGRA_PIN_ULPI_DATA0_PO1       _GPIO(113)
-#define TEGRA_PIN_ULPI_DATA1_PO2       _GPIO(114)
-#define TEGRA_PIN_ULPI_DATA2_PO3       _GPIO(115)
-#define TEGRA_PIN_ULPI_DATA3_PO4       _GPIO(116)
-#define TEGRA_PIN_ULPI_DATA4_PO5       _GPIO(117)
-#define TEGRA_PIN_ULPI_DATA5_PO6       _GPIO(118)
-#define TEGRA_PIN_ULPI_DATA6_PO7       _GPIO(119)
-#define TEGRA_PIN_DAP3_FS_PP0          _GPIO(120)
-#define TEGRA_PIN_DAP3_DIN_PP1         _GPIO(121)
-#define TEGRA_PIN_DAP3_DOUT_PP2                _GPIO(122)
-#define TEGRA_PIN_DAP3_SCLK_PP3                _GPIO(123)
-#define TEGRA_PIN_DAP4_FS_PP4          _GPIO(124)
-#define TEGRA_PIN_DAP4_DIN_PP5         _GPIO(125)
-#define TEGRA_PIN_DAP4_DOUT_PP6                _GPIO(126)
-#define TEGRA_PIN_DAP4_SCLK_PP7                _GPIO(127)
-#define TEGRA_PIN_KB_COL0_PQ0          _GPIO(128)
-#define TEGRA_PIN_KB_COL1_PQ1          _GPIO(129)
-#define TEGRA_PIN_KB_COL2_PQ2          _GPIO(130)
-#define TEGRA_PIN_KB_COL3_PQ3          _GPIO(131)
-#define TEGRA_PIN_KB_COL4_PQ4          _GPIO(132)
-#define TEGRA_PIN_KB_COL5_PQ5          _GPIO(133)
-#define TEGRA_PIN_KB_COL6_PQ6          _GPIO(134)
-#define TEGRA_PIN_KB_COL7_PQ7          _GPIO(135)
-#define TEGRA_PIN_KB_ROW0_PR0          _GPIO(136)
-#define TEGRA_PIN_KB_ROW1_PR1          _GPIO(137)
-#define TEGRA_PIN_KB_ROW2_PR2          _GPIO(138)
-#define TEGRA_PIN_KB_ROW3_PR3          _GPIO(139)
-#define TEGRA_PIN_KB_ROW4_PR4          _GPIO(140)
-#define TEGRA_PIN_KB_ROW5_PR5          _GPIO(141)
-#define TEGRA_PIN_KB_ROW6_PR6          _GPIO(142)
-#define TEGRA_PIN_KB_ROW7_PR7          _GPIO(143)
-#define TEGRA_PIN_KB_ROW8_PS0          _GPIO(144)
-#define TEGRA_PIN_KB_ROW9_PS1          _GPIO(145)
-#define TEGRA_PIN_KB_ROW10_PS2         _GPIO(146)
-#define TEGRA_PIN_KB_ROW11_PS3         _GPIO(147)
-#define TEGRA_PIN_KB_ROW12_PS4         _GPIO(148)
-#define TEGRA_PIN_KB_ROW13_PS5         _GPIO(149)
-#define TEGRA_PIN_KB_ROW14_PS6         _GPIO(150)
-#define TEGRA_PIN_KB_ROW15_PS7         _GPIO(151)
-#define TEGRA_PIN_VI_PCLK_PT0          _GPIO(152)
-#define TEGRA_PIN_VI_MCLK_PT1          _GPIO(153)
-#define TEGRA_PIN_VI_D10_PT2           _GPIO(154)
-#define TEGRA_PIN_VI_D11_PT3           _GPIO(155)
-#define TEGRA_PIN_VI_D0_PT4            _GPIO(156)
-#define TEGRA_PIN_GEN2_I2C_SCL_PT5     _GPIO(157)
-#define TEGRA_PIN_GEN2_I2C_SDA_PT6     _GPIO(158)
-#define TEGRA_PIN_SDMMC4_CMD_PT7       _GPIO(159)
-#define TEGRA_PIN_PU0                  _GPIO(160)
-#define TEGRA_PIN_PU1                  _GPIO(161)
-#define TEGRA_PIN_PU2                  _GPIO(162)
-#define TEGRA_PIN_PU3                  _GPIO(163)
-#define TEGRA_PIN_PU4                  _GPIO(164)
-#define TEGRA_PIN_PU5                  _GPIO(165)
-#define TEGRA_PIN_PU6                  _GPIO(166)
-#define TEGRA_PIN_JTAG_RTCK_PU7                _GPIO(167)
-#define TEGRA_PIN_PV0                  _GPIO(168)
-#define TEGRA_PIN_PV1                  _GPIO(169)
-#define TEGRA_PIN_PV2                  _GPIO(170)
-#define TEGRA_PIN_PV3                  _GPIO(171)
-#define TEGRA_PIN_DDC_SCL_PV4          _GPIO(172)
-#define TEGRA_PIN_DDC_SDA_PV5          _GPIO(173)
-#define TEGRA_PIN_CRT_HSYNC_PV6                _GPIO(174)
-#define TEGRA_PIN_CRT_VSYNC_PV7                _GPIO(175)
-#define TEGRA_PIN_LCD_CS1_N_PW0                _GPIO(176)
-#define TEGRA_PIN_LCD_M1_PW1           _GPIO(177)
-#define TEGRA_PIN_SPI2_CS1_N_PW2       _GPIO(178)
-#define TEGRA_PIN_SPI2_CS2_N_PW3       _GPIO(179)
-#define TEGRA_PIN_CLK1_OUT_PW4         _GPIO(180)
-#define TEGRA_PIN_CLK2_OUT_PW5         _GPIO(181)
-#define TEGRA_PIN_UART3_TXD_PW6                _GPIO(182)
-#define TEGRA_PIN_UART3_RXD_PW7                _GPIO(183)
-#define TEGRA_PIN_SPI2_MOSI_PX0                _GPIO(184)
-#define TEGRA_PIN_SPI2_MISO_PX1                _GPIO(185)
-#define TEGRA_PIN_SPI2_SCK_PX2         _GPIO(186)
-#define TEGRA_PIN_SPI2_CS0_N_PX3       _GPIO(187)
-#define TEGRA_PIN_SPI1_MOSI_PX4                _GPIO(188)
-#define TEGRA_PIN_SPI1_SCK_PX5         _GPIO(189)
-#define TEGRA_PIN_SPI1_CS0_N_PX6       _GPIO(190)
-#define TEGRA_PIN_SPI1_MISO_PX7                _GPIO(191)
-#define TEGRA_PIN_ULPI_CLK_PY0         _GPIO(192)
-#define TEGRA_PIN_ULPI_DIR_PY1         _GPIO(193)
-#define TEGRA_PIN_ULPI_NXT_PY2         _GPIO(194)
-#define TEGRA_PIN_ULPI_STP_PY3         _GPIO(195)
-#define TEGRA_PIN_SDMMC1_DAT3_PY4      _GPIO(196)
-#define TEGRA_PIN_SDMMC1_DAT2_PY5      _GPIO(197)
-#define TEGRA_PIN_SDMMC1_DAT1_PY6      _GPIO(198)
-#define TEGRA_PIN_SDMMC1_DAT0_PY7      _GPIO(199)
-#define TEGRA_PIN_SDMMC1_CLK_PZ0       _GPIO(200)
-#define TEGRA_PIN_SDMMC1_CMD_PZ1       _GPIO(201)
-#define TEGRA_PIN_LCD_SDIN_PZ2         _GPIO(202)
-#define TEGRA_PIN_LCD_WR_N_PZ3         _GPIO(203)
-#define TEGRA_PIN_LCD_SCK_PZ4          _GPIO(204)
-#define TEGRA_PIN_SYS_CLK_REQ_PZ5      _GPIO(205)
-#define TEGRA_PIN_PWR_I2C_SCL_PZ6      _GPIO(206)
-#define TEGRA_PIN_PWR_I2C_SDA_PZ7      _GPIO(207)
-#define TEGRA_PIN_SDMMC4_DAT0_PAA0     _GPIO(208)
-#define TEGRA_PIN_SDMMC4_DAT1_PAA1     _GPIO(209)
-#define TEGRA_PIN_SDMMC4_DAT2_PAA2     _GPIO(210)
-#define TEGRA_PIN_SDMMC4_DAT3_PAA3     _GPIO(211)
-#define TEGRA_PIN_SDMMC4_DAT4_PAA4     _GPIO(212)
-#define TEGRA_PIN_SDMMC4_DAT5_PAA5     _GPIO(213)
-#define TEGRA_PIN_SDMMC4_DAT6_PAA6     _GPIO(214)
-#define TEGRA_PIN_SDMMC4_DAT7_PAA7     _GPIO(215)
-#define TEGRA_PIN_PBB0                 _GPIO(216)
-#define TEGRA_PIN_CAM_I2C_SCL_PBB1     _GPIO(217)
-#define TEGRA_PIN_CAM_I2C_SDA_PBB2     _GPIO(218)
-#define TEGRA_PIN_PBB3                 _GPIO(219)
-#define TEGRA_PIN_PBB4                 _GPIO(220)
-#define TEGRA_PIN_PBB5                 _GPIO(221)
-#define TEGRA_PIN_PBB6                 _GPIO(222)
-#define TEGRA_PIN_PBB7                 _GPIO(223)
-#define TEGRA_PIN_CAM_MCLK_PCC0                _GPIO(224)
-#define TEGRA_PIN_PCC1                 _GPIO(225)
-#define TEGRA_PIN_PCC2                 _GPIO(226)
-#define TEGRA_PIN_SDMMC4_RST_N_PCC3    _GPIO(227)
-#define TEGRA_PIN_SDMMC4_CLK_PCC4      _GPIO(228)
-#define TEGRA_PIN_CLK2_REQ_PCC5                _GPIO(229)
-#define TEGRA_PIN_PEX_L2_RST_N_PCC6    _GPIO(230)
-#define TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7 _GPIO(231)
-#define TEGRA_PIN_PEX_L0_PRSNT_N_PDD0  _GPIO(232)
-#define TEGRA_PIN_PEX_L0_RST_N_PDD1    _GPIO(233)
-#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234)
-#define TEGRA_PIN_PEX_WAKE_N_PDD3      _GPIO(235)
-#define TEGRA_PIN_PEX_L1_PRSNT_N_PDD4  _GPIO(236)
-#define TEGRA_PIN_PEX_L1_RST_N_PDD5    _GPIO(237)
-#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238)
-#define TEGRA_PIN_PEX_L2_PRSNT_N_PDD7  _GPIO(239)
-#define TEGRA_PIN_CLK3_OUT_PEE0                _GPIO(240)
-#define TEGRA_PIN_CLK3_REQ_PEE1                _GPIO(241)
-#define TEGRA_PIN_CLK1_REQ_PEE2                _GPIO(242)
-#define TEGRA_PIN_HDMI_CEC_PEE3                _GPIO(243)
-#define TEGRA_PIN_PEE4                 _GPIO(244)
-#define TEGRA_PIN_PEE5                 _GPIO(245)
-#define TEGRA_PIN_PEE6                 _GPIO(246)
-#define TEGRA_PIN_PEE7                 _GPIO(247)
-
-/* All non-GPIO pins follow */
-#define NUM_GPIOS                      (TEGRA_PIN_PEE7 + 1)
-#define _PIN(offset)                   (NUM_GPIOS + (offset))
-
-/* Non-GPIO pins */
-#define TEGRA_PIN_CLK_32K_IN           _PIN(0)
-#define TEGRA_PIN_CORE_PWR_REQ         _PIN(1)
-#define TEGRA_PIN_CPU_PWR_REQ          _PIN(2)
-#define TEGRA_PIN_JTAG_TCK             _PIN(3)
-#define TEGRA_PIN_JTAG_TDI             _PIN(4)
-#define TEGRA_PIN_JTAG_TDO             _PIN(5)
-#define TEGRA_PIN_JTAG_TMS             _PIN(6)
-#define TEGRA_PIN_JTAG_TRST_N          _PIN(7)
-#define TEGRA_PIN_OWR                  _PIN(8)
-#define TEGRA_PIN_PWR_INT_N            _PIN(9)
-#define TEGRA_PIN_SYS_RESET_N          _PIN(10)
-#define TEGRA_PIN_TEST_MODE_EN         _PIN(11)
-
-static const struct pinctrl_pin_desc tegra30_pins[] = {
-       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"),
-       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT5_PD0, "SDMMC3_DAT5 PD0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT4_PD1, "SDMMC3_DAT4 PD1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PD2, "LCD_DC1 PD2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT6_PD3, "SDMMC3_DAT6 PD3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT7_PD4, "SDMMC3_DAT7 PD4"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"),
-       PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"),
-       PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_DQS_PI2, "GMI_DQS PI2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"),
-       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"),
-       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"),
-       PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"),
-       PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"),
-       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"),
-       PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"),
-       PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"),
-       PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VI_D10 PT2"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"),
-       PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"),
-       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"),
-       PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"),
-       PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"),
-       PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"),
-       PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"),
-       PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"),
-       PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"),
-       PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"),
-       PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"),
-       PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"),
-       PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"),
-       PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"),
-       PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"),
-       PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"),
-       PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC_PV6, "CRT_HSYNC PV6"),
-       PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC_PV7, "CRT_VSYNC PV7"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"),
-       PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"),
-       PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"),
-       PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"),
-       PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"),
-       PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"),
-       PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"),
-       PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"),
-       PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"),
-       PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"),
-       PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"),
-       PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"),
-       PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"),
-       PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"),
-       PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"),
-       PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"),
-       PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"),
-       PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_RST_N_PCC3, "SDMMC4_RST_N PCC3"),
-       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"),
-       PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PCC6, "PEX_L2_RST_N PCC6"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, "PEX_L2_CLKREQ_N PCC7"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, "PEX_L0_PRSNT_N PDD0"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, "PEX_L1_PRSNT_N PDD4"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"),
-       PINCTRL_PIN(TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, "PEX_L2_PRSNT_N PDD7"),
-       PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"),
-       PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"),
-       PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"),
-       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"),
-       PINCTRL_PIN(TEGRA_PIN_PEE4, "PEE4"),
-       PINCTRL_PIN(TEGRA_PIN_PEE5, "PEE5"),
-       PINCTRL_PIN(TEGRA_PIN_PEE6, "PEE6"),
-       PINCTRL_PIN(TEGRA_PIN_PEE7, "PEE7"),
-       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
-       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"),
-       PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"),
-       PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"),
-       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
-       PINCTRL_PIN(TEGRA_PIN_SYS_RESET_N, "SYS_RESET_N"),
-       PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"),
-};
-
-static const unsigned clk_32k_out_pa0_pins[] = {
-       TEGRA_PIN_CLK_32K_OUT_PA0,
-};
-
-static const unsigned uart3_cts_n_pa1_pins[] = {
-       TEGRA_PIN_UART3_CTS_N_PA1,
-};
-
-static const unsigned dap2_fs_pa2_pins[] = {
-       TEGRA_PIN_DAP2_FS_PA2,
-};
-
-static const unsigned dap2_sclk_pa3_pins[] = {
-       TEGRA_PIN_DAP2_SCLK_PA3,
-};
-
-static const unsigned dap2_din_pa4_pins[] = {
-       TEGRA_PIN_DAP2_DIN_PA4,
-};
-
-static const unsigned dap2_dout_pa5_pins[] = {
-       TEGRA_PIN_DAP2_DOUT_PA5,
-};
-
-static const unsigned sdmmc3_clk_pa6_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_PA6,
-};
-
-static const unsigned sdmmc3_cmd_pa7_pins[] = {
-       TEGRA_PIN_SDMMC3_CMD_PA7,
-};
-
-static const unsigned gmi_a17_pb0_pins[] = {
-       TEGRA_PIN_GMI_A17_PB0,
-};
-
-static const unsigned gmi_a18_pb1_pins[] = {
-       TEGRA_PIN_GMI_A18_PB1,
-};
-
-static const unsigned lcd_pwr0_pb2_pins[] = {
-       TEGRA_PIN_LCD_PWR0_PB2,
-};
-
-static const unsigned lcd_pclk_pb3_pins[] = {
-       TEGRA_PIN_LCD_PCLK_PB3,
-};
-
-static const unsigned sdmmc3_dat3_pb4_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT3_PB4,
-};
-
-static const unsigned sdmmc3_dat2_pb5_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT2_PB5,
-};
-
-static const unsigned sdmmc3_dat1_pb6_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT1_PB6,
-};
-
-static const unsigned sdmmc3_dat0_pb7_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT0_PB7,
-};
-
-static const unsigned uart3_rts_n_pc0_pins[] = {
-       TEGRA_PIN_UART3_RTS_N_PC0,
-};
-
-static const unsigned lcd_pwr1_pc1_pins[] = {
-       TEGRA_PIN_LCD_PWR1_PC1,
-};
-
-static const unsigned uart2_txd_pc2_pins[] = {
-       TEGRA_PIN_UART2_TXD_PC2,
-};
-
-static const unsigned uart2_rxd_pc3_pins[] = {
-       TEGRA_PIN_UART2_RXD_PC3,
-};
-
-static const unsigned gen1_i2c_scl_pc4_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SCL_PC4,
-};
-
-static const unsigned gen1_i2c_sda_pc5_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SDA_PC5,
-};
-
-static const unsigned lcd_pwr2_pc6_pins[] = {
-       TEGRA_PIN_LCD_PWR2_PC6,
-};
-
-static const unsigned gmi_wp_n_pc7_pins[] = {
-       TEGRA_PIN_GMI_WP_N_PC7,
-};
-
-static const unsigned sdmmc3_dat5_pd0_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT5_PD0,
-};
-
-static const unsigned sdmmc3_dat4_pd1_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT4_PD1,
-};
-
-static const unsigned lcd_dc1_pd2_pins[] = {
-       TEGRA_PIN_LCD_DC1_PD2,
-};
-
-static const unsigned sdmmc3_dat6_pd3_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT6_PD3,
-};
-
-static const unsigned sdmmc3_dat7_pd4_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT7_PD4,
-};
-
-static const unsigned vi_d1_pd5_pins[] = {
-       TEGRA_PIN_VI_D1_PD5,
-};
-
-static const unsigned vi_vsync_pd6_pins[] = {
-       TEGRA_PIN_VI_VSYNC_PD6,
-};
-
-static const unsigned vi_hsync_pd7_pins[] = {
-       TEGRA_PIN_VI_HSYNC_PD7,
-};
-
-static const unsigned lcd_d0_pe0_pins[] = {
-       TEGRA_PIN_LCD_D0_PE0,
-};
-
-static const unsigned lcd_d1_pe1_pins[] = {
-       TEGRA_PIN_LCD_D1_PE1,
-};
-
-static const unsigned lcd_d2_pe2_pins[] = {
-       TEGRA_PIN_LCD_D2_PE2,
-};
-
-static const unsigned lcd_d3_pe3_pins[] = {
-       TEGRA_PIN_LCD_D3_PE3,
-};
-
-static const unsigned lcd_d4_pe4_pins[] = {
-       TEGRA_PIN_LCD_D4_PE4,
-};
-
-static const unsigned lcd_d5_pe5_pins[] = {
-       TEGRA_PIN_LCD_D5_PE5,
-};
-
-static const unsigned lcd_d6_pe6_pins[] = {
-       TEGRA_PIN_LCD_D6_PE6,
-};
-
-static const unsigned lcd_d7_pe7_pins[] = {
-       TEGRA_PIN_LCD_D7_PE7,
-};
-
-static const unsigned lcd_d8_pf0_pins[] = {
-       TEGRA_PIN_LCD_D8_PF0,
-};
-
-static const unsigned lcd_d9_pf1_pins[] = {
-       TEGRA_PIN_LCD_D9_PF1,
-};
-
-static const unsigned lcd_d10_pf2_pins[] = {
-       TEGRA_PIN_LCD_D10_PF2,
-};
-
-static const unsigned lcd_d11_pf3_pins[] = {
-       TEGRA_PIN_LCD_D11_PF3,
-};
-
-static const unsigned lcd_d12_pf4_pins[] = {
-       TEGRA_PIN_LCD_D12_PF4,
-};
-
-static const unsigned lcd_d13_pf5_pins[] = {
-       TEGRA_PIN_LCD_D13_PF5,
-};
-
-static const unsigned lcd_d14_pf6_pins[] = {
-       TEGRA_PIN_LCD_D14_PF6,
-};
-
-static const unsigned lcd_d15_pf7_pins[] = {
-       TEGRA_PIN_LCD_D15_PF7,
-};
-
-static const unsigned gmi_ad0_pg0_pins[] = {
-       TEGRA_PIN_GMI_AD0_PG0,
-};
-
-static const unsigned gmi_ad1_pg1_pins[] = {
-       TEGRA_PIN_GMI_AD1_PG1,
-};
-
-static const unsigned gmi_ad2_pg2_pins[] = {
-       TEGRA_PIN_GMI_AD2_PG2,
-};
-
-static const unsigned gmi_ad3_pg3_pins[] = {
-       TEGRA_PIN_GMI_AD3_PG3,
-};
-
-static const unsigned gmi_ad4_pg4_pins[] = {
-       TEGRA_PIN_GMI_AD4_PG4,
-};
-
-static const unsigned gmi_ad5_pg5_pins[] = {
-       TEGRA_PIN_GMI_AD5_PG5,
-};
-
-static const unsigned gmi_ad6_pg6_pins[] = {
-       TEGRA_PIN_GMI_AD6_PG6,
-};
-
-static const unsigned gmi_ad7_pg7_pins[] = {
-       TEGRA_PIN_GMI_AD7_PG7,
-};
-
-static const unsigned gmi_ad8_ph0_pins[] = {
-       TEGRA_PIN_GMI_AD8_PH0,
-};
-
-static const unsigned gmi_ad9_ph1_pins[] = {
-       TEGRA_PIN_GMI_AD9_PH1,
-};
-
-static const unsigned gmi_ad10_ph2_pins[] = {
-       TEGRA_PIN_GMI_AD10_PH2,
-};
-
-static const unsigned gmi_ad11_ph3_pins[] = {
-       TEGRA_PIN_GMI_AD11_PH3,
-};
-
-static const unsigned gmi_ad12_ph4_pins[] = {
-       TEGRA_PIN_GMI_AD12_PH4,
-};
-
-static const unsigned gmi_ad13_ph5_pins[] = {
-       TEGRA_PIN_GMI_AD13_PH5,
-};
-
-static const unsigned gmi_ad14_ph6_pins[] = {
-       TEGRA_PIN_GMI_AD14_PH6,
-};
-
-static const unsigned gmi_ad15_ph7_pins[] = {
-       TEGRA_PIN_GMI_AD15_PH7,
-};
-
-static const unsigned gmi_wr_n_pi0_pins[] = {
-       TEGRA_PIN_GMI_WR_N_PI0,
-};
-
-static const unsigned gmi_oe_n_pi1_pins[] = {
-       TEGRA_PIN_GMI_OE_N_PI1,
-};
-
-static const unsigned gmi_dqs_pi2_pins[] = {
-       TEGRA_PIN_GMI_DQS_PI2,
-};
-
-static const unsigned gmi_cs6_n_pi3_pins[] = {
-       TEGRA_PIN_GMI_CS6_N_PI3,
-};
-
-static const unsigned gmi_rst_n_pi4_pins[] = {
-       TEGRA_PIN_GMI_RST_N_PI4,
-};
-
-static const unsigned gmi_iordy_pi5_pins[] = {
-       TEGRA_PIN_GMI_IORDY_PI5,
-};
-
-static const unsigned gmi_cs7_n_pi6_pins[] = {
-       TEGRA_PIN_GMI_CS7_N_PI6,
-};
-
-static const unsigned gmi_wait_pi7_pins[] = {
-       TEGRA_PIN_GMI_WAIT_PI7,
-};
-
-static const unsigned gmi_cs0_n_pj0_pins[] = {
-       TEGRA_PIN_GMI_CS0_N_PJ0,
-};
-
-static const unsigned lcd_de_pj1_pins[] = {
-       TEGRA_PIN_LCD_DE_PJ1,
-};
-
-static const unsigned gmi_cs1_n_pj2_pins[] = {
-       TEGRA_PIN_GMI_CS1_N_PJ2,
-};
-
-static const unsigned lcd_hsync_pj3_pins[] = {
-       TEGRA_PIN_LCD_HSYNC_PJ3,
-};
-
-static const unsigned lcd_vsync_pj4_pins[] = {
-       TEGRA_PIN_LCD_VSYNC_PJ4,
-};
-
-static const unsigned uart2_cts_n_pj5_pins[] = {
-       TEGRA_PIN_UART2_CTS_N_PJ5,
-};
-
-static const unsigned uart2_rts_n_pj6_pins[] = {
-       TEGRA_PIN_UART2_RTS_N_PJ6,
-};
-
-static const unsigned gmi_a16_pj7_pins[] = {
-       TEGRA_PIN_GMI_A16_PJ7,
-};
-
-static const unsigned gmi_adv_n_pk0_pins[] = {
-       TEGRA_PIN_GMI_ADV_N_PK0,
-};
-
-static const unsigned gmi_clk_pk1_pins[] = {
-       TEGRA_PIN_GMI_CLK_PK1,
-};
-
-static const unsigned gmi_cs4_n_pk2_pins[] = {
-       TEGRA_PIN_GMI_CS4_N_PK2,
-};
-
-static const unsigned gmi_cs2_n_pk3_pins[] = {
-       TEGRA_PIN_GMI_CS2_N_PK3,
-};
-
-static const unsigned gmi_cs3_n_pk4_pins[] = {
-       TEGRA_PIN_GMI_CS3_N_PK4,
-};
-
-static const unsigned spdif_out_pk5_pins[] = {
-       TEGRA_PIN_SPDIF_OUT_PK5,
-};
-
-static const unsigned spdif_in_pk6_pins[] = {
-       TEGRA_PIN_SPDIF_IN_PK6,
-};
-
-static const unsigned gmi_a19_pk7_pins[] = {
-       TEGRA_PIN_GMI_A19_PK7,
-};
-
-static const unsigned vi_d2_pl0_pins[] = {
-       TEGRA_PIN_VI_D2_PL0,
-};
-
-static const unsigned vi_d3_pl1_pins[] = {
-       TEGRA_PIN_VI_D3_PL1,
-};
-
-static const unsigned vi_d4_pl2_pins[] = {
-       TEGRA_PIN_VI_D4_PL2,
-};
-
-static const unsigned vi_d5_pl3_pins[] = {
-       TEGRA_PIN_VI_D5_PL3,
-};
-
-static const unsigned vi_d6_pl4_pins[] = {
-       TEGRA_PIN_VI_D6_PL4,
-};
-
-static const unsigned vi_d7_pl5_pins[] = {
-       TEGRA_PIN_VI_D7_PL5,
-};
-
-static const unsigned vi_d8_pl6_pins[] = {
-       TEGRA_PIN_VI_D8_PL6,
-};
-
-static const unsigned vi_d9_pl7_pins[] = {
-       TEGRA_PIN_VI_D9_PL7,
-};
-
-static const unsigned lcd_d16_pm0_pins[] = {
-       TEGRA_PIN_LCD_D16_PM0,
-};
-
-static const unsigned lcd_d17_pm1_pins[] = {
-       TEGRA_PIN_LCD_D17_PM1,
-};
-
-static const unsigned lcd_d18_pm2_pins[] = {
-       TEGRA_PIN_LCD_D18_PM2,
-};
-
-static const unsigned lcd_d19_pm3_pins[] = {
-       TEGRA_PIN_LCD_D19_PM3,
-};
-
-static const unsigned lcd_d20_pm4_pins[] = {
-       TEGRA_PIN_LCD_D20_PM4,
-};
-
-static const unsigned lcd_d21_pm5_pins[] = {
-       TEGRA_PIN_LCD_D21_PM5,
-};
-
-static const unsigned lcd_d22_pm6_pins[] = {
-       TEGRA_PIN_LCD_D22_PM6,
-};
-
-static const unsigned lcd_d23_pm7_pins[] = {
-       TEGRA_PIN_LCD_D23_PM7,
-};
-
-static const unsigned dap1_fs_pn0_pins[] = {
-       TEGRA_PIN_DAP1_FS_PN0,
-};
-
-static const unsigned dap1_din_pn1_pins[] = {
-       TEGRA_PIN_DAP1_DIN_PN1,
-};
-
-static const unsigned dap1_dout_pn2_pins[] = {
-       TEGRA_PIN_DAP1_DOUT_PN2,
-};
-
-static const unsigned dap1_sclk_pn3_pins[] = {
-       TEGRA_PIN_DAP1_SCLK_PN3,
-};
-
-static const unsigned lcd_cs0_n_pn4_pins[] = {
-       TEGRA_PIN_LCD_CS0_N_PN4,
-};
-
-static const unsigned lcd_sdout_pn5_pins[] = {
-       TEGRA_PIN_LCD_SDOUT_PN5,
-};
-
-static const unsigned lcd_dc0_pn6_pins[] = {
-       TEGRA_PIN_LCD_DC0_PN6,
-};
-
-static const unsigned hdmi_int_pn7_pins[] = {
-       TEGRA_PIN_HDMI_INT_PN7,
-};
-
-static const unsigned ulpi_data7_po0_pins[] = {
-       TEGRA_PIN_ULPI_DATA7_PO0,
-};
-
-static const unsigned ulpi_data0_po1_pins[] = {
-       TEGRA_PIN_ULPI_DATA0_PO1,
-};
-
-static const unsigned ulpi_data1_po2_pins[] = {
-       TEGRA_PIN_ULPI_DATA1_PO2,
-};
-
-static const unsigned ulpi_data2_po3_pins[] = {
-       TEGRA_PIN_ULPI_DATA2_PO3,
-};
-
-static const unsigned ulpi_data3_po4_pins[] = {
-       TEGRA_PIN_ULPI_DATA3_PO4,
-};
-
-static const unsigned ulpi_data4_po5_pins[] = {
-       TEGRA_PIN_ULPI_DATA4_PO5,
-};
-
-static const unsigned ulpi_data5_po6_pins[] = {
-       TEGRA_PIN_ULPI_DATA5_PO6,
-};
-
-static const unsigned ulpi_data6_po7_pins[] = {
-       TEGRA_PIN_ULPI_DATA6_PO7,
-};
-
-static const unsigned dap3_fs_pp0_pins[] = {
-       TEGRA_PIN_DAP3_FS_PP0,
-};
-
-static const unsigned dap3_din_pp1_pins[] = {
-       TEGRA_PIN_DAP3_DIN_PP1,
-};
-
-static const unsigned dap3_dout_pp2_pins[] = {
-       TEGRA_PIN_DAP3_DOUT_PP2,
-};
-
-static const unsigned dap3_sclk_pp3_pins[] = {
-       TEGRA_PIN_DAP3_SCLK_PP3,
-};
-
-static const unsigned dap4_fs_pp4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PP4,
-};
-
-static const unsigned dap4_din_pp5_pins[] = {
-       TEGRA_PIN_DAP4_DIN_PP5,
-};
-
-static const unsigned dap4_dout_pp6_pins[] = {
-       TEGRA_PIN_DAP4_DOUT_PP6,
-};
-
-static const unsigned dap4_sclk_pp7_pins[] = {
-       TEGRA_PIN_DAP4_SCLK_PP7,
-};
-
-static const unsigned kb_col0_pq0_pins[] = {
-       TEGRA_PIN_KB_COL0_PQ0,
-};
-
-static const unsigned kb_col1_pq1_pins[] = {
-       TEGRA_PIN_KB_COL1_PQ1,
-};
-
-static const unsigned kb_col2_pq2_pins[] = {
-       TEGRA_PIN_KB_COL2_PQ2,
-};
-
-static const unsigned kb_col3_pq3_pins[] = {
-       TEGRA_PIN_KB_COL3_PQ3,
-};
-
-static const unsigned kb_col4_pq4_pins[] = {
-       TEGRA_PIN_KB_COL4_PQ4,
-};
-
-static const unsigned kb_col5_pq5_pins[] = {
-       TEGRA_PIN_KB_COL5_PQ5,
-};
-
-static const unsigned kb_col6_pq6_pins[] = {
-       TEGRA_PIN_KB_COL6_PQ6,
-};
-
-static const unsigned kb_col7_pq7_pins[] = {
-       TEGRA_PIN_KB_COL7_PQ7,
-};
-
-static const unsigned kb_row0_pr0_pins[] = {
-       TEGRA_PIN_KB_ROW0_PR0,
-};
-
-static const unsigned kb_row1_pr1_pins[] = {
-       TEGRA_PIN_KB_ROW1_PR1,
-};
-
-static const unsigned kb_row2_pr2_pins[] = {
-       TEGRA_PIN_KB_ROW2_PR2,
-};
-
-static const unsigned kb_row3_pr3_pins[] = {
-       TEGRA_PIN_KB_ROW3_PR3,
-};
-
-static const unsigned kb_row4_pr4_pins[] = {
-       TEGRA_PIN_KB_ROW4_PR4,
-};
-
-static const unsigned kb_row5_pr5_pins[] = {
-       TEGRA_PIN_KB_ROW5_PR5,
-};
-
-static const unsigned kb_row6_pr6_pins[] = {
-       TEGRA_PIN_KB_ROW6_PR6,
-};
-
-static const unsigned kb_row7_pr7_pins[] = {
-       TEGRA_PIN_KB_ROW7_PR7,
-};
-
-static const unsigned kb_row8_ps0_pins[] = {
-       TEGRA_PIN_KB_ROW8_PS0,
-};
-
-static const unsigned kb_row9_ps1_pins[] = {
-       TEGRA_PIN_KB_ROW9_PS1,
-};
-
-static const unsigned kb_row10_ps2_pins[] = {
-       TEGRA_PIN_KB_ROW10_PS2,
-};
-
-static const unsigned kb_row11_ps3_pins[] = {
-       TEGRA_PIN_KB_ROW11_PS3,
-};
-
-static const unsigned kb_row12_ps4_pins[] = {
-       TEGRA_PIN_KB_ROW12_PS4,
-};
-
-static const unsigned kb_row13_ps5_pins[] = {
-       TEGRA_PIN_KB_ROW13_PS5,
-};
-
-static const unsigned kb_row14_ps6_pins[] = {
-       TEGRA_PIN_KB_ROW14_PS6,
-};
-
-static const unsigned kb_row15_ps7_pins[] = {
-       TEGRA_PIN_KB_ROW15_PS7,
-};
-
-static const unsigned vi_pclk_pt0_pins[] = {
-       TEGRA_PIN_VI_PCLK_PT0,
-};
-
-static const unsigned vi_mclk_pt1_pins[] = {
-       TEGRA_PIN_VI_MCLK_PT1,
-};
-
-static const unsigned vi_d10_pt2_pins[] = {
-       TEGRA_PIN_VI_D10_PT2,
-};
-
-static const unsigned vi_d11_pt3_pins[] = {
-       TEGRA_PIN_VI_D11_PT3,
-};
-
-static const unsigned vi_d0_pt4_pins[] = {
-       TEGRA_PIN_VI_D0_PT4,
-};
-
-static const unsigned gen2_i2c_scl_pt5_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SCL_PT5,
-};
-
-static const unsigned gen2_i2c_sda_pt6_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SDA_PT6,
-};
-
-static const unsigned sdmmc4_cmd_pt7_pins[] = {
-       TEGRA_PIN_SDMMC4_CMD_PT7,
-};
-
-static const unsigned pu0_pins[] = {
-       TEGRA_PIN_PU0,
-};
-
-static const unsigned pu1_pins[] = {
-       TEGRA_PIN_PU1,
-};
-
-static const unsigned pu2_pins[] = {
-       TEGRA_PIN_PU2,
-};
-
-static const unsigned pu3_pins[] = {
-       TEGRA_PIN_PU3,
-};
-
-static const unsigned pu4_pins[] = {
-       TEGRA_PIN_PU4,
-};
-
-static const unsigned pu5_pins[] = {
-       TEGRA_PIN_PU5,
-};
-
-static const unsigned pu6_pins[] = {
-       TEGRA_PIN_PU6,
-};
-
-static const unsigned jtag_rtck_pu7_pins[] = {
-       TEGRA_PIN_JTAG_RTCK_PU7,
-};
-
-static const unsigned pv0_pins[] = {
-       TEGRA_PIN_PV0,
-};
-
-static const unsigned pv1_pins[] = {
-       TEGRA_PIN_PV1,
-};
-
-static const unsigned pv2_pins[] = {
-       TEGRA_PIN_PV2,
-};
-
-static const unsigned pv3_pins[] = {
-       TEGRA_PIN_PV3,
-};
-
-static const unsigned ddc_scl_pv4_pins[] = {
-       TEGRA_PIN_DDC_SCL_PV4,
-};
-
-static const unsigned ddc_sda_pv5_pins[] = {
-       TEGRA_PIN_DDC_SDA_PV5,
-};
-
-static const unsigned crt_hsync_pv6_pins[] = {
-       TEGRA_PIN_CRT_HSYNC_PV6,
-};
-
-static const unsigned crt_vsync_pv7_pins[] = {
-       TEGRA_PIN_CRT_VSYNC_PV7,
-};
-
-static const unsigned lcd_cs1_n_pw0_pins[] = {
-       TEGRA_PIN_LCD_CS1_N_PW0,
-};
-
-static const unsigned lcd_m1_pw1_pins[] = {
-       TEGRA_PIN_LCD_M1_PW1,
-};
-
-static const unsigned spi2_cs1_n_pw2_pins[] = {
-       TEGRA_PIN_SPI2_CS1_N_PW2,
-};
-
-static const unsigned spi2_cs2_n_pw3_pins[] = {
-       TEGRA_PIN_SPI2_CS2_N_PW3,
-};
-
-static const unsigned clk1_out_pw4_pins[] = {
-       TEGRA_PIN_CLK1_OUT_PW4,
-};
-
-static const unsigned clk2_out_pw5_pins[] = {
-       TEGRA_PIN_CLK2_OUT_PW5,
-};
-
-static const unsigned uart3_txd_pw6_pins[] = {
-       TEGRA_PIN_UART3_TXD_PW6,
-};
-
-static const unsigned uart3_rxd_pw7_pins[] = {
-       TEGRA_PIN_UART3_RXD_PW7,
-};
-
-static const unsigned spi2_mosi_px0_pins[] = {
-       TEGRA_PIN_SPI2_MOSI_PX0,
-};
-
-static const unsigned spi2_miso_px1_pins[] = {
-       TEGRA_PIN_SPI2_MISO_PX1,
-};
-
-static const unsigned spi2_sck_px2_pins[] = {
-       TEGRA_PIN_SPI2_SCK_PX2,
-};
-
-static const unsigned spi2_cs0_n_px3_pins[] = {
-       TEGRA_PIN_SPI2_CS0_N_PX3,
-};
-
-static const unsigned spi1_mosi_px4_pins[] = {
-       TEGRA_PIN_SPI1_MOSI_PX4,
-};
-
-static const unsigned spi1_sck_px5_pins[] = {
-       TEGRA_PIN_SPI1_SCK_PX5,
-};
-
-static const unsigned spi1_cs0_n_px6_pins[] = {
-       TEGRA_PIN_SPI1_CS0_N_PX6,
-};
-
-static const unsigned spi1_miso_px7_pins[] = {
-       TEGRA_PIN_SPI1_MISO_PX7,
-};
-
-static const unsigned ulpi_clk_py0_pins[] = {
-       TEGRA_PIN_ULPI_CLK_PY0,
-};
-
-static const unsigned ulpi_dir_py1_pins[] = {
-       TEGRA_PIN_ULPI_DIR_PY1,
-};
-
-static const unsigned ulpi_nxt_py2_pins[] = {
-       TEGRA_PIN_ULPI_NXT_PY2,
-};
-
-static const unsigned ulpi_stp_py3_pins[] = {
-       TEGRA_PIN_ULPI_STP_PY3,
-};
-
-static const unsigned sdmmc1_dat3_py4_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT3_PY4,
-};
-
-static const unsigned sdmmc1_dat2_py5_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT2_PY5,
-};
-
-static const unsigned sdmmc1_dat1_py6_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT1_PY6,
-};
-
-static const unsigned sdmmc1_dat0_py7_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT0_PY7,
-};
-
-static const unsigned sdmmc1_clk_pz0_pins[] = {
-       TEGRA_PIN_SDMMC1_CLK_PZ0,
-};
-
-static const unsigned sdmmc1_cmd_pz1_pins[] = {
-       TEGRA_PIN_SDMMC1_CMD_PZ1,
-};
-
-static const unsigned lcd_sdin_pz2_pins[] = {
-       TEGRA_PIN_LCD_SDIN_PZ2,
-};
-
-static const unsigned lcd_wr_n_pz3_pins[] = {
-       TEGRA_PIN_LCD_WR_N_PZ3,
-};
-
-static const unsigned lcd_sck_pz4_pins[] = {
-       TEGRA_PIN_LCD_SCK_PZ4,
-};
-
-static const unsigned sys_clk_req_pz5_pins[] = {
-       TEGRA_PIN_SYS_CLK_REQ_PZ5,
-};
-
-static const unsigned pwr_i2c_scl_pz6_pins[] = {
-       TEGRA_PIN_PWR_I2C_SCL_PZ6,
-};
-
-static const unsigned pwr_i2c_sda_pz7_pins[] = {
-       TEGRA_PIN_PWR_I2C_SDA_PZ7,
-};
-
-static const unsigned sdmmc4_dat0_paa0_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT0_PAA0,
-};
-
-static const unsigned sdmmc4_dat1_paa1_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT1_PAA1,
-};
-
-static const unsigned sdmmc4_dat2_paa2_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT2_PAA2,
-};
-
-static const unsigned sdmmc4_dat3_paa3_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT3_PAA3,
-};
-
-static const unsigned sdmmc4_dat4_paa4_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT4_PAA4,
-};
-
-static const unsigned sdmmc4_dat5_paa5_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT5_PAA5,
-};
-
-static const unsigned sdmmc4_dat6_paa6_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT6_PAA6,
-};
-
-static const unsigned sdmmc4_dat7_paa7_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT7_PAA7,
-};
-
-static const unsigned pbb0_pins[] = {
-       TEGRA_PIN_PBB0,
-};
-
-static const unsigned cam_i2c_scl_pbb1_pins[] = {
-       TEGRA_PIN_CAM_I2C_SCL_PBB1,
-};
-
-static const unsigned cam_i2c_sda_pbb2_pins[] = {
-       TEGRA_PIN_CAM_I2C_SDA_PBB2,
-};
-
-static const unsigned pbb3_pins[] = {
-       TEGRA_PIN_PBB3,
-};
-
-static const unsigned pbb4_pins[] = {
-       TEGRA_PIN_PBB4,
-};
-
-static const unsigned pbb5_pins[] = {
-       TEGRA_PIN_PBB5,
-};
-
-static const unsigned pbb6_pins[] = {
-       TEGRA_PIN_PBB6,
-};
-
-static const unsigned pbb7_pins[] = {
-       TEGRA_PIN_PBB7,
-};
-
-static const unsigned cam_mclk_pcc0_pins[] = {
-       TEGRA_PIN_CAM_MCLK_PCC0,
-};
-
-static const unsigned pcc1_pins[] = {
-       TEGRA_PIN_PCC1,
-};
-
-static const unsigned pcc2_pins[] = {
-       TEGRA_PIN_PCC2,
-};
-
-static const unsigned sdmmc4_rst_n_pcc3_pins[] = {
-       TEGRA_PIN_SDMMC4_RST_N_PCC3,
-};
-
-static const unsigned sdmmc4_clk_pcc4_pins[] = {
-       TEGRA_PIN_SDMMC4_CLK_PCC4,
-};
-
-static const unsigned clk2_req_pcc5_pins[] = {
-       TEGRA_PIN_CLK2_REQ_PCC5,
-};
-
-static const unsigned pex_l2_rst_n_pcc6_pins[] = {
-       TEGRA_PIN_PEX_L2_RST_N_PCC6,
-};
-
-static const unsigned pex_l2_clkreq_n_pcc7_pins[] = {
-       TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7,
-};
-
-static const unsigned pex_l0_prsnt_n_pdd0_pins[] = {
-       TEGRA_PIN_PEX_L0_PRSNT_N_PDD0,
-};
-
-static const unsigned pex_l0_rst_n_pdd1_pins[] = {
-       TEGRA_PIN_PEX_L0_RST_N_PDD1,
-};
-
-static const unsigned pex_l0_clkreq_n_pdd2_pins[] = {
-       TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2,
-};
-
-static const unsigned pex_wake_n_pdd3_pins[] = {
-       TEGRA_PIN_PEX_WAKE_N_PDD3,
-};
-
-static const unsigned pex_l1_prsnt_n_pdd4_pins[] = {
-       TEGRA_PIN_PEX_L1_PRSNT_N_PDD4,
-};
-
-static const unsigned pex_l1_rst_n_pdd5_pins[] = {
-       TEGRA_PIN_PEX_L1_RST_N_PDD5,
-};
-
-static const unsigned pex_l1_clkreq_n_pdd6_pins[] = {
-       TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6,
-};
-
-static const unsigned pex_l2_prsnt_n_pdd7_pins[] = {
-       TEGRA_PIN_PEX_L2_PRSNT_N_PDD7,
-};
-
-static const unsigned clk3_out_pee0_pins[] = {
-       TEGRA_PIN_CLK3_OUT_PEE0,
-};
-
-static const unsigned clk3_req_pee1_pins[] = {
-       TEGRA_PIN_CLK3_REQ_PEE1,
-};
-
-static const unsigned clk1_req_pee2_pins[] = {
-       TEGRA_PIN_CLK1_REQ_PEE2,
-};
-
-static const unsigned hdmi_cec_pee3_pins[] = {
-       TEGRA_PIN_HDMI_CEC_PEE3,
-};
-
-static const unsigned clk_32k_in_pins[] = {
-       TEGRA_PIN_CLK_32K_IN,
-};
-
-static const unsigned core_pwr_req_pins[] = {
-       TEGRA_PIN_CORE_PWR_REQ,
-};
-
-static const unsigned cpu_pwr_req_pins[] = {
-       TEGRA_PIN_CPU_PWR_REQ,
-};
-
-static const unsigned owr_pins[] = {
-       TEGRA_PIN_OWR,
-};
-
-static const unsigned pwr_int_n_pins[] = {
-       TEGRA_PIN_PWR_INT_N,
-};
-
-static const unsigned drive_ao1_pins[] = {
-       TEGRA_PIN_KB_ROW0_PR0,
-       TEGRA_PIN_KB_ROW1_PR1,
-       TEGRA_PIN_KB_ROW2_PR2,
-       TEGRA_PIN_KB_ROW3_PR3,
-       TEGRA_PIN_KB_ROW4_PR4,
-       TEGRA_PIN_KB_ROW5_PR5,
-       TEGRA_PIN_KB_ROW6_PR6,
-       TEGRA_PIN_KB_ROW7_PR7,
-       TEGRA_PIN_PWR_I2C_SCL_PZ6,
-       TEGRA_PIN_PWR_I2C_SDA_PZ7,
-       TEGRA_PIN_SYS_RESET_N,
-};
-
-static const unsigned drive_ao2_pins[] = {
-       TEGRA_PIN_CLK_32K_OUT_PA0,
-       TEGRA_PIN_KB_COL0_PQ0,
-       TEGRA_PIN_KB_COL1_PQ1,
-       TEGRA_PIN_KB_COL2_PQ2,
-       TEGRA_PIN_KB_COL3_PQ3,
-       TEGRA_PIN_KB_COL4_PQ4,
-       TEGRA_PIN_KB_COL5_PQ5,
-       TEGRA_PIN_KB_COL6_PQ6,
-       TEGRA_PIN_KB_COL7_PQ7,
-       TEGRA_PIN_KB_ROW8_PS0,
-       TEGRA_PIN_KB_ROW9_PS1,
-       TEGRA_PIN_KB_ROW10_PS2,
-       TEGRA_PIN_KB_ROW11_PS3,
-       TEGRA_PIN_KB_ROW12_PS4,
-       TEGRA_PIN_KB_ROW13_PS5,
-       TEGRA_PIN_KB_ROW14_PS6,
-       TEGRA_PIN_KB_ROW15_PS7,
-       TEGRA_PIN_SYS_CLK_REQ_PZ5,
-       TEGRA_PIN_CLK_32K_IN,
-       TEGRA_PIN_CORE_PWR_REQ,
-       TEGRA_PIN_CPU_PWR_REQ,
-       TEGRA_PIN_PWR_INT_N,
-};
-
-static const unsigned drive_at1_pins[] = {
-       TEGRA_PIN_GMI_AD8_PH0,
-       TEGRA_PIN_GMI_AD9_PH1,
-       TEGRA_PIN_GMI_AD10_PH2,
-       TEGRA_PIN_GMI_AD11_PH3,
-       TEGRA_PIN_GMI_AD12_PH4,
-       TEGRA_PIN_GMI_AD13_PH5,
-       TEGRA_PIN_GMI_AD14_PH6,
-       TEGRA_PIN_GMI_AD15_PH7,
-       TEGRA_PIN_GMI_IORDY_PI5,
-       TEGRA_PIN_GMI_CS7_N_PI6,
-};
-
-static const unsigned drive_at2_pins[] = {
-       TEGRA_PIN_GMI_AD0_PG0,
-       TEGRA_PIN_GMI_AD1_PG1,
-       TEGRA_PIN_GMI_AD2_PG2,
-       TEGRA_PIN_GMI_AD3_PG3,
-       TEGRA_PIN_GMI_AD4_PG4,
-       TEGRA_PIN_GMI_AD5_PG5,
-       TEGRA_PIN_GMI_AD6_PG6,
-       TEGRA_PIN_GMI_AD7_PG7,
-       TEGRA_PIN_GMI_WR_N_PI0,
-       TEGRA_PIN_GMI_OE_N_PI1,
-       TEGRA_PIN_GMI_DQS_PI2,
-       TEGRA_PIN_GMI_CS6_N_PI3,
-       TEGRA_PIN_GMI_RST_N_PI4,
-       TEGRA_PIN_GMI_WAIT_PI7,
-       TEGRA_PIN_GMI_ADV_N_PK0,
-       TEGRA_PIN_GMI_CLK_PK1,
-       TEGRA_PIN_GMI_CS4_N_PK2,
-       TEGRA_PIN_GMI_CS2_N_PK3,
-       TEGRA_PIN_GMI_CS3_N_PK4,
-};
-
-static const unsigned drive_at3_pins[] = {
-       TEGRA_PIN_GMI_WP_N_PC7,
-       TEGRA_PIN_GMI_CS0_N_PJ0,
-};
-
-static const unsigned drive_at4_pins[] = {
-       TEGRA_PIN_GMI_A17_PB0,
-       TEGRA_PIN_GMI_A18_PB1,
-       TEGRA_PIN_GMI_CS1_N_PJ2,
-       TEGRA_PIN_GMI_A16_PJ7,
-       TEGRA_PIN_GMI_A19_PK7,
-};
-
-static const unsigned drive_at5_pins[] = {
-       TEGRA_PIN_GEN2_I2C_SCL_PT5,
-       TEGRA_PIN_GEN2_I2C_SDA_PT6,
-};
-
-static const unsigned drive_cdev1_pins[] = {
-       TEGRA_PIN_CLK1_OUT_PW4,
-       TEGRA_PIN_CLK1_REQ_PEE2,
-};
-
-static const unsigned drive_cdev2_pins[] = {
-       TEGRA_PIN_CLK2_OUT_PW5,
-       TEGRA_PIN_CLK2_REQ_PCC5,
-};
-
-static const unsigned drive_cec_pins[] = {
-       TEGRA_PIN_HDMI_CEC_PEE3,
-};
-
-static const unsigned drive_crt_pins[] = {
-       TEGRA_PIN_CRT_HSYNC_PV6,
-       TEGRA_PIN_CRT_VSYNC_PV7,
-};
-
-static const unsigned drive_csus_pins[] = {
-       TEGRA_PIN_VI_MCLK_PT1,
-};
-
-static const unsigned drive_dap1_pins[] = {
-       TEGRA_PIN_SPDIF_OUT_PK5,
-       TEGRA_PIN_SPDIF_IN_PK6,
-       TEGRA_PIN_DAP1_FS_PN0,
-       TEGRA_PIN_DAP1_DIN_PN1,
-       TEGRA_PIN_DAP1_DOUT_PN2,
-       TEGRA_PIN_DAP1_SCLK_PN3,
-};
-
-static const unsigned drive_dap2_pins[] = {
-       TEGRA_PIN_DAP2_FS_PA2,
-       TEGRA_PIN_DAP2_SCLK_PA3,
-       TEGRA_PIN_DAP2_DIN_PA4,
-       TEGRA_PIN_DAP2_DOUT_PA5,
-};
-
-static const unsigned drive_dap3_pins[] = {
-       TEGRA_PIN_DAP3_FS_PP0,
-       TEGRA_PIN_DAP3_DIN_PP1,
-       TEGRA_PIN_DAP3_DOUT_PP2,
-       TEGRA_PIN_DAP3_SCLK_PP3,
-};
-
-static const unsigned drive_dap4_pins[] = {
-       TEGRA_PIN_DAP4_FS_PP4,
-       TEGRA_PIN_DAP4_DIN_PP5,
-       TEGRA_PIN_DAP4_DOUT_PP6,
-       TEGRA_PIN_DAP4_SCLK_PP7,
-};
-
-static const unsigned drive_dbg_pins[] = {
-       TEGRA_PIN_GEN1_I2C_SCL_PC4,
-       TEGRA_PIN_GEN1_I2C_SDA_PC5,
-       TEGRA_PIN_PU0,
-       TEGRA_PIN_PU1,
-       TEGRA_PIN_PU2,
-       TEGRA_PIN_PU3,
-       TEGRA_PIN_PU4,
-       TEGRA_PIN_PU5,
-       TEGRA_PIN_PU6,
-       TEGRA_PIN_JTAG_RTCK_PU7,
-       TEGRA_PIN_JTAG_TCK,
-       TEGRA_PIN_JTAG_TDI,
-       TEGRA_PIN_JTAG_TDO,
-       TEGRA_PIN_JTAG_TMS,
-       TEGRA_PIN_JTAG_TRST_N,
-       TEGRA_PIN_TEST_MODE_EN,
-};
-
-static const unsigned drive_ddc_pins[] = {
-       TEGRA_PIN_DDC_SCL_PV4,
-       TEGRA_PIN_DDC_SDA_PV5,
-};
-
-static const unsigned drive_dev3_pins[] = {
-       TEGRA_PIN_CLK3_OUT_PEE0,
-       TEGRA_PIN_CLK3_REQ_PEE1,
-};
-
-static const unsigned drive_gma_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT0_PAA0,
-       TEGRA_PIN_SDMMC4_DAT1_PAA1,
-       TEGRA_PIN_SDMMC4_DAT2_PAA2,
-       TEGRA_PIN_SDMMC4_DAT3_PAA3,
-       TEGRA_PIN_SDMMC4_RST_N_PCC3,
-};
-
-static const unsigned drive_gmb_pins[] = {
-       TEGRA_PIN_SDMMC4_DAT4_PAA4,
-       TEGRA_PIN_SDMMC4_DAT5_PAA5,
-       TEGRA_PIN_SDMMC4_DAT6_PAA6,
-       TEGRA_PIN_SDMMC4_DAT7_PAA7,
-};
-
-static const unsigned drive_gmc_pins[] = {
-       TEGRA_PIN_SDMMC4_CLK_PCC4,
-};
-
-static const unsigned drive_gmd_pins[] = {
-       TEGRA_PIN_SDMMC4_CMD_PT7,
-};
-
-static const unsigned drive_gme_pins[] = {
-       TEGRA_PIN_PBB0,
-       TEGRA_PIN_CAM_I2C_SCL_PBB1,
-       TEGRA_PIN_CAM_I2C_SDA_PBB2,
-       TEGRA_PIN_PBB3,
-       TEGRA_PIN_PCC2,
-};
-
-static const unsigned drive_gmf_pins[] = {
-       TEGRA_PIN_PBB4,
-       TEGRA_PIN_PBB5,
-       TEGRA_PIN_PBB6,
-       TEGRA_PIN_PBB7,
-};
-
-static const unsigned drive_gmg_pins[] = {
-       TEGRA_PIN_CAM_MCLK_PCC0,
-};
-
-static const unsigned drive_gmh_pins[] = {
-       TEGRA_PIN_PCC1,
-};
-
-static const unsigned drive_gpv_pins[] = {
-       TEGRA_PIN_PEX_L2_RST_N_PCC6,
-       TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7,
-       TEGRA_PIN_PEX_L0_PRSNT_N_PDD0,
-       TEGRA_PIN_PEX_L0_RST_N_PDD1,
-       TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2,
-       TEGRA_PIN_PEX_WAKE_N_PDD3,
-       TEGRA_PIN_PEX_L1_PRSNT_N_PDD4,
-       TEGRA_PIN_PEX_L1_RST_N_PDD5,
-       TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6,
-       TEGRA_PIN_PEX_L2_PRSNT_N_PDD7,
-};
-
-static const unsigned drive_lcd1_pins[] = {
-       TEGRA_PIN_LCD_PWR1_PC1,
-       TEGRA_PIN_LCD_PWR2_PC6,
-       TEGRA_PIN_LCD_CS0_N_PN4,
-       TEGRA_PIN_LCD_SDOUT_PN5,
-       TEGRA_PIN_LCD_DC0_PN6,
-       TEGRA_PIN_LCD_SDIN_PZ2,
-       TEGRA_PIN_LCD_WR_N_PZ3,
-       TEGRA_PIN_LCD_SCK_PZ4,
-};
-
-static const unsigned drive_lcd2_pins[] = {
-       TEGRA_PIN_LCD_PWR0_PB2,
-       TEGRA_PIN_LCD_PCLK_PB3,
-       TEGRA_PIN_LCD_DC1_PD2,
-       TEGRA_PIN_LCD_D0_PE0,
-       TEGRA_PIN_LCD_D1_PE1,
-       TEGRA_PIN_LCD_D2_PE2,
-       TEGRA_PIN_LCD_D3_PE3,
-       TEGRA_PIN_LCD_D4_PE4,
-       TEGRA_PIN_LCD_D5_PE5,
-       TEGRA_PIN_LCD_D6_PE6,
-       TEGRA_PIN_LCD_D7_PE7,
-       TEGRA_PIN_LCD_D8_PF0,
-       TEGRA_PIN_LCD_D9_PF1,
-       TEGRA_PIN_LCD_D10_PF2,
-       TEGRA_PIN_LCD_D11_PF3,
-       TEGRA_PIN_LCD_D12_PF4,
-       TEGRA_PIN_LCD_D13_PF5,
-       TEGRA_PIN_LCD_D14_PF6,
-       TEGRA_PIN_LCD_D15_PF7,
-       TEGRA_PIN_LCD_DE_PJ1,
-       TEGRA_PIN_LCD_HSYNC_PJ3,
-       TEGRA_PIN_LCD_VSYNC_PJ4,
-       TEGRA_PIN_LCD_D16_PM0,
-       TEGRA_PIN_LCD_D17_PM1,
-       TEGRA_PIN_LCD_D18_PM2,
-       TEGRA_PIN_LCD_D19_PM3,
-       TEGRA_PIN_LCD_D20_PM4,
-       TEGRA_PIN_LCD_D21_PM5,
-       TEGRA_PIN_LCD_D22_PM6,
-       TEGRA_PIN_LCD_D23_PM7,
-       TEGRA_PIN_HDMI_INT_PN7,
-       TEGRA_PIN_LCD_CS1_N_PW0,
-       TEGRA_PIN_LCD_M1_PW1,
-};
-
-static const unsigned drive_owr_pins[] = {
-       TEGRA_PIN_OWR,
-};
-
-static const unsigned drive_sdio1_pins[] = {
-       TEGRA_PIN_SDMMC1_DAT3_PY4,
-       TEGRA_PIN_SDMMC1_DAT2_PY5,
-       TEGRA_PIN_SDMMC1_DAT1_PY6,
-       TEGRA_PIN_SDMMC1_DAT0_PY7,
-       TEGRA_PIN_SDMMC1_CLK_PZ0,
-       TEGRA_PIN_SDMMC1_CMD_PZ1,
-};
-
-static const unsigned drive_sdio2_pins[] = {
-       TEGRA_PIN_SDMMC3_DAT5_PD0,
-       TEGRA_PIN_SDMMC3_DAT4_PD1,
-       TEGRA_PIN_SDMMC3_DAT6_PD3,
-       TEGRA_PIN_SDMMC3_DAT7_PD4,
-};
-
-static const unsigned drive_sdio3_pins[] = {
-       TEGRA_PIN_SDMMC3_CLK_PA6,
-       TEGRA_PIN_SDMMC3_CMD_PA7,
-       TEGRA_PIN_SDMMC3_DAT3_PB4,
-       TEGRA_PIN_SDMMC3_DAT2_PB5,
-       TEGRA_PIN_SDMMC3_DAT1_PB6,
-       TEGRA_PIN_SDMMC3_DAT0_PB7,
-};
-
-static const unsigned drive_spi_pins[] = {
-       TEGRA_PIN_SPI2_CS1_N_PW2,
-       TEGRA_PIN_SPI2_CS2_N_PW3,
-       TEGRA_PIN_SPI2_MOSI_PX0,
-       TEGRA_PIN_SPI2_MISO_PX1,
-       TEGRA_PIN_SPI2_SCK_PX2,
-       TEGRA_PIN_SPI2_CS0_N_PX3,
-       TEGRA_PIN_SPI1_MOSI_PX4,
-       TEGRA_PIN_SPI1_SCK_PX5,
-       TEGRA_PIN_SPI1_CS0_N_PX6,
-       TEGRA_PIN_SPI1_MISO_PX7,
-};
-
-static const unsigned drive_uaa_pins[] = {
-       TEGRA_PIN_ULPI_DATA0_PO1,
-       TEGRA_PIN_ULPI_DATA1_PO2,
-       TEGRA_PIN_ULPI_DATA2_PO3,
-       TEGRA_PIN_ULPI_DATA3_PO4,
-};
-
-static const unsigned drive_uab_pins[] = {
-       TEGRA_PIN_ULPI_DATA7_PO0,
-       TEGRA_PIN_ULPI_DATA4_PO5,
-       TEGRA_PIN_ULPI_DATA5_PO6,
-       TEGRA_PIN_ULPI_DATA6_PO7,
-       TEGRA_PIN_PV0,
-       TEGRA_PIN_PV1,
-       TEGRA_PIN_PV2,
-       TEGRA_PIN_PV3,
-};
-
-static const unsigned drive_uart2_pins[] = {
-       TEGRA_PIN_UART2_TXD_PC2,
-       TEGRA_PIN_UART2_RXD_PC3,
-       TEGRA_PIN_UART2_CTS_N_PJ5,
-       TEGRA_PIN_UART2_RTS_N_PJ6,
-};
-
-static const unsigned drive_uart3_pins[] = {
-       TEGRA_PIN_UART3_CTS_N_PA1,
-       TEGRA_PIN_UART3_RTS_N_PC0,
-       TEGRA_PIN_UART3_TXD_PW6,
-       TEGRA_PIN_UART3_RXD_PW7,
-};
-
-static const unsigned drive_uda_pins[] = {
-       TEGRA_PIN_ULPI_CLK_PY0,
-       TEGRA_PIN_ULPI_DIR_PY1,
-       TEGRA_PIN_ULPI_NXT_PY2,
-       TEGRA_PIN_ULPI_STP_PY3,
-};
-
-static const unsigned drive_vi1_pins[] = {
-       TEGRA_PIN_VI_D1_PD5,
-       TEGRA_PIN_VI_VSYNC_PD6,
-       TEGRA_PIN_VI_HSYNC_PD7,
-       TEGRA_PIN_VI_D2_PL0,
-       TEGRA_PIN_VI_D3_PL1,
-       TEGRA_PIN_VI_D4_PL2,
-       TEGRA_PIN_VI_D5_PL3,
-       TEGRA_PIN_VI_D6_PL4,
-       TEGRA_PIN_VI_D7_PL5,
-       TEGRA_PIN_VI_D8_PL6,
-       TEGRA_PIN_VI_D9_PL7,
-       TEGRA_PIN_VI_PCLK_PT0,
-       TEGRA_PIN_VI_D10_PT2,
-       TEGRA_PIN_VI_D11_PT3,
-       TEGRA_PIN_VI_D0_PT4,
-};
-
-enum tegra_mux {
-       TEGRA_MUX_BLINK,
-       TEGRA_MUX_CEC,
-       TEGRA_MUX_CLK_12M_OUT,
-       TEGRA_MUX_CLK_32K_IN,
-       TEGRA_MUX_CORE_PWR_REQ,
-       TEGRA_MUX_CPU_PWR_REQ,
-       TEGRA_MUX_CRT,
-       TEGRA_MUX_DAP,
-       TEGRA_MUX_DDR,
-       TEGRA_MUX_DEV3,
-       TEGRA_MUX_DISPLAYA,
-       TEGRA_MUX_DISPLAYB,
-       TEGRA_MUX_DTV,
-       TEGRA_MUX_EXTPERIPH1,
-       TEGRA_MUX_EXTPERIPH2,
-       TEGRA_MUX_EXTPERIPH3,
-       TEGRA_MUX_GMI,
-       TEGRA_MUX_GMI_ALT,
-       TEGRA_MUX_HDA,
-       TEGRA_MUX_HDCP,
-       TEGRA_MUX_HDMI,
-       TEGRA_MUX_HSI,
-       TEGRA_MUX_I2C1,
-       TEGRA_MUX_I2C2,
-       TEGRA_MUX_I2C3,
-       TEGRA_MUX_I2C4,
-       TEGRA_MUX_I2CPWR,
-       TEGRA_MUX_I2S0,
-       TEGRA_MUX_I2S1,
-       TEGRA_MUX_I2S2,
-       TEGRA_MUX_I2S3,
-       TEGRA_MUX_I2S4,
-       TEGRA_MUX_INVALID,
-       TEGRA_MUX_KBC,
-       TEGRA_MUX_MIO,
-       TEGRA_MUX_NAND,
-       TEGRA_MUX_NAND_ALT,
-       TEGRA_MUX_OWR,
-       TEGRA_MUX_PCIE,
-       TEGRA_MUX_PWM0,
-       TEGRA_MUX_PWM1,
-       TEGRA_MUX_PWM2,
-       TEGRA_MUX_PWM3,
-       TEGRA_MUX_PWR_INT_N,
-       TEGRA_MUX_RSVD1,
-       TEGRA_MUX_RSVD2,
-       TEGRA_MUX_RSVD3,
-       TEGRA_MUX_RSVD4,
-       TEGRA_MUX_RTCK,
-       TEGRA_MUX_SATA,
-       TEGRA_MUX_SDMMC1,
-       TEGRA_MUX_SDMMC2,
-       TEGRA_MUX_SDMMC3,
-       TEGRA_MUX_SDMMC4,
-       TEGRA_MUX_SPDIF,
-       TEGRA_MUX_SPI1,
-       TEGRA_MUX_SPI2,
-       TEGRA_MUX_SPI2_ALT,
-       TEGRA_MUX_SPI3,
-       TEGRA_MUX_SPI4,
-       TEGRA_MUX_SPI5,
-       TEGRA_MUX_SPI6,
-       TEGRA_MUX_SYSCLK,
-       TEGRA_MUX_TEST,
-       TEGRA_MUX_TRACE,
-       TEGRA_MUX_UARTA,
-       TEGRA_MUX_UARTB,
-       TEGRA_MUX_UARTC,
-       TEGRA_MUX_UARTD,
-       TEGRA_MUX_UARTE,
-       TEGRA_MUX_ULPI,
-       TEGRA_MUX_VGP1,
-       TEGRA_MUX_VGP2,
-       TEGRA_MUX_VGP3,
-       TEGRA_MUX_VGP4,
-       TEGRA_MUX_VGP5,
-       TEGRA_MUX_VGP6,
-       TEGRA_MUX_VI,
-       TEGRA_MUX_VI_ALT1,
-       TEGRA_MUX_VI_ALT2,
-       TEGRA_MUX_VI_ALT3,
-};
-
-#define FUNCTION(fname)                                        \
-       {                                               \
-               .name = #fname,                         \
-       }
-
-static struct tegra_function tegra30_functions[] = {
-       FUNCTION(blink),
-       FUNCTION(cec),
-       FUNCTION(clk_12m_out),
-       FUNCTION(clk_32k_in),
-       FUNCTION(core_pwr_req),
-       FUNCTION(cpu_pwr_req),
-       FUNCTION(crt),
-       FUNCTION(dap),
-       FUNCTION(ddr),
-       FUNCTION(dev3),
-       FUNCTION(displaya),
-       FUNCTION(displayb),
-       FUNCTION(dtv),
-       FUNCTION(extperiph1),
-       FUNCTION(extperiph2),
-       FUNCTION(extperiph3),
-       FUNCTION(gmi),
-       FUNCTION(gmi_alt),
-       FUNCTION(hda),
-       FUNCTION(hdcp),
-       FUNCTION(hdmi),
-       FUNCTION(hsi),
-       FUNCTION(i2c1),
-       FUNCTION(i2c2),
-       FUNCTION(i2c3),
-       FUNCTION(i2c4),
-       FUNCTION(i2cpwr),
-       FUNCTION(i2s0),
-       FUNCTION(i2s1),
-       FUNCTION(i2s2),
-       FUNCTION(i2s3),
-       FUNCTION(i2s4),
-       FUNCTION(invalid),
-       FUNCTION(kbc),
-       FUNCTION(mio),
-       FUNCTION(nand),
-       FUNCTION(nand_alt),
-       FUNCTION(owr),
-       FUNCTION(pcie),
-       FUNCTION(pwm0),
-       FUNCTION(pwm1),
-       FUNCTION(pwm2),
-       FUNCTION(pwm3),
-       FUNCTION(pwr_int_n),
-       FUNCTION(rsvd1),
-       FUNCTION(rsvd2),
-       FUNCTION(rsvd3),
-       FUNCTION(rsvd4),
-       FUNCTION(rtck),
-       FUNCTION(sata),
-       FUNCTION(sdmmc1),
-       FUNCTION(sdmmc2),
-       FUNCTION(sdmmc3),
-       FUNCTION(sdmmc4),
-       FUNCTION(spdif),
-       FUNCTION(spi1),
-       FUNCTION(spi2),
-       FUNCTION(spi2_alt),
-       FUNCTION(spi3),
-       FUNCTION(spi4),
-       FUNCTION(spi5),
-       FUNCTION(spi6),
-       FUNCTION(sysclk),
-       FUNCTION(test),
-       FUNCTION(trace),
-       FUNCTION(uarta),
-       FUNCTION(uartb),
-       FUNCTION(uartc),
-       FUNCTION(uartd),
-       FUNCTION(uarte),
-       FUNCTION(ulpi),
-       FUNCTION(vgp1),
-       FUNCTION(vgp2),
-       FUNCTION(vgp3),
-       FUNCTION(vgp4),
-       FUNCTION(vgp5),
-       FUNCTION(vgp6),
-       FUNCTION(vi),
-       FUNCTION(vi_alt1),
-       FUNCTION(vi_alt2),
-       FUNCTION(vi_alt3),
-};
-
-#define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
-#define PINGROUP_REG_A                 0x3000  /* bank 1 */
-
-#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
-#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
-
-#define PINGROUP_BIT_Y(b)              (b)
-#define PINGROUP_BIT_N(b)              (-1)
-
-#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior)                  \
-       {                                                               \
-               .name = #pg_name,                                       \
-               .pins = pg_name##_pins,                                 \
-               .npins = ARRAY_SIZE(pg_name##_pins),                    \
-               .funcs = {                                              \
-                       TEGRA_MUX_##f0,                                 \
-                       TEGRA_MUX_##f1,                                 \
-                       TEGRA_MUX_##f2,                                 \
-                       TEGRA_MUX_##f3,                                 \
-               },                                                      \
-               .mux_reg = PINGROUP_REG(r),                             \
-               .mux_bank = 1,                                          \
-               .mux_bit = 0,                                           \
-               .pupd_reg = PINGROUP_REG(r),                            \
-               .pupd_bank = 1,                                         \
-               .pupd_bit = 2,                                          \
-               .tri_reg = PINGROUP_REG(r),                             \
-               .tri_bank = 1,                                          \
-               .tri_bit = 4,                                           \
-               .einput_bit = 5,                                        \
-               .odrain_bit = PINGROUP_BIT_##od(6),                     \
-               .lock_bit = 7,                                          \
-               .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
-               .rcv_sel_bit = -1,                                      \
-               .drv_reg = -1,                                          \
-       }
-
-#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
-                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
-                    slwf_b, slwf_w)                                    \
-       {                                                               \
-               .name = "drive_" #pg_name,                              \
-               .pins = drive_##pg_name##_pins,                         \
-               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
-               .mux_reg = -1,                                          \
-               .pupd_reg = -1,                                         \
-               .tri_reg = -1,                                          \
-               .einput_bit = -1,                                       \
-               .odrain_bit = -1,                                       \
-               .lock_bit = -1,                                         \
-               .ioreset_bit = -1,                                      \
-               .rcv_sel_bit = -1,                                      \
-               .drv_reg = DRV_PINGROUP_REG(r),                         \
-               .drv_bank = 0,                                          \
-               .hsm_bit = hsm_b,                                       \
-               .schmitt_bit = schmitt_b,                               \
-               .lpmd_bit = lpmd_b,                                     \
-               .drvdn_bit = drvdn_b,                                   \
-               .drvdn_width = drvdn_w,                                 \
-               .drvup_bit = drvup_b,                                   \
-               .drvup_width = drvup_w,                                 \
-               .slwr_bit = slwr_b,                                     \
-               .slwr_width = slwr_w,                                   \
-               .slwf_bit = slwf_b,                                     \
-               .slwf_width = slwf_w,                                   \
-               .drvtype_bit = -1,                                      \
-       }
-
-static const struct tegra_pingroup tegra30_groups[] = {
-       /*       pg_name,              f0,           f1,           f2,           f3,           r,      od, ior */
-       PINGROUP(clk_32k_out_pa0,      BLINK,        RSVD2,        RSVD3,        RSVD4,        0x331c, N, N),
-       PINGROUP(uart3_cts_n_pa1,      UARTC,        RSVD2,        GMI,          RSVD4,        0x317c, N, N),
-       PINGROUP(dap2_fs_pa2,          I2S1,         HDA,          RSVD3,        GMI,          0x3358, N, N),
-       PINGROUP(dap2_sclk_pa3,        I2S1,         HDA,          RSVD3,        GMI,          0x3364, N, N),
-       PINGROUP(dap2_din_pa4,         I2S1,         HDA,          RSVD3,        GMI,          0x335c, N, N),
-       PINGROUP(dap2_dout_pa5,        I2S1,         HDA,          RSVD3,        GMI,          0x3360, N, N),
-       PINGROUP(sdmmc3_clk_pa6,       UARTA,        PWM2,         SDMMC3,       SPI3,         0x3390, N, N),
-       PINGROUP(sdmmc3_cmd_pa7,       UARTA,        PWM3,         SDMMC3,       SPI2,         0x3394, N, N),
-       PINGROUP(gmi_a17_pb0,          UARTD,        SPI4,         GMI,          DTV,          0x3234, N, N),
-       PINGROUP(gmi_a18_pb1,          UARTD,        SPI4,         GMI,          DTV,          0x3238, N, N),
-       PINGROUP(lcd_pwr0_pb2,         DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x3090, N, N),
-       PINGROUP(lcd_pclk_pb3,         DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3094, N, N),
-       PINGROUP(sdmmc3_dat3_pb4,      RSVD1,        PWM0,         SDMMC3,       SPI3,         0x33a4, N, N),
-       PINGROUP(sdmmc3_dat2_pb5,      RSVD1,        PWM1,         SDMMC3,       SPI3,         0x33a0, N, N),
-       PINGROUP(sdmmc3_dat1_pb6,      RSVD1,        RSVD2,        SDMMC3,       SPI3,         0x339c, N, N),
-       PINGROUP(sdmmc3_dat0_pb7,      RSVD1,        RSVD2,        SDMMC3,       SPI3,         0x3398, N, N),
-       PINGROUP(uart3_rts_n_pc0,      UARTC,        PWM0,         GMI,          RSVD4,        0x3180, N, N),
-       PINGROUP(lcd_pwr1_pc1,         DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3070, N, N),
-       PINGROUP(uart2_txd_pc2,        UARTB,        SPDIF,        UARTA,        SPI4,         0x3168, N, N),
-       PINGROUP(uart2_rxd_pc3,        UARTB,        SPDIF,        UARTA,        SPI4,         0x3164, N, N),
-       PINGROUP(gen1_i2c_scl_pc4,     I2C1,         RSVD2,        RSVD3,        RSVD4,        0x31a4, Y, N),
-       PINGROUP(gen1_i2c_sda_pc5,     I2C1,         RSVD2,        RSVD3,        RSVD4,        0x31a0, Y, N),
-       PINGROUP(lcd_pwr2_pc6,         DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x3074, N, N),
-       PINGROUP(gmi_wp_n_pc7,         RSVD1,        NAND,         GMI,          GMI_ALT,      0x31c0, N, N),
-       PINGROUP(sdmmc3_dat5_pd0,      PWM0,         SPI4,         SDMMC3,       SPI2,         0x33ac, N, N),
-       PINGROUP(sdmmc3_dat4_pd1,      PWM1,         SPI4,         SDMMC3,       SPI2,         0x33a8, N, N),
-       PINGROUP(lcd_dc1_pd2,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x310c, N, N),
-       PINGROUP(sdmmc3_dat6_pd3,      SPDIF,        SPI4,         SDMMC3,       SPI2,         0x33b0, N, N),
-       PINGROUP(sdmmc3_dat7_pd4,      SPDIF,        SPI4,         SDMMC3,       SPI2,         0x33b4, N, N),
-       PINGROUP(vi_d1_pd5,            DDR,          SDMMC2,       VI,           RSVD4,        0x3128, N, Y),
-       PINGROUP(vi_vsync_pd6,         DDR,          RSVD2,        VI,           RSVD4,        0x315c, N, Y),
-       PINGROUP(vi_hsync_pd7,         DDR,          RSVD2,        VI,           RSVD4,        0x3160, N, Y),
-       PINGROUP(lcd_d0_pe0,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30a4, N, N),
-       PINGROUP(lcd_d1_pe1,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30a8, N, N),
-       PINGROUP(lcd_d2_pe2,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30ac, N, N),
-       PINGROUP(lcd_d3_pe3,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30b0, N, N),
-       PINGROUP(lcd_d4_pe4,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30b4, N, N),
-       PINGROUP(lcd_d5_pe5,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30b8, N, N),
-       PINGROUP(lcd_d6_pe6,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30bc, N, N),
-       PINGROUP(lcd_d7_pe7,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30c0, N, N),
-       PINGROUP(lcd_d8_pf0,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30c4, N, N),
-       PINGROUP(lcd_d9_pf1,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30c8, N, N),
-       PINGROUP(lcd_d10_pf2,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30cc, N, N),
-       PINGROUP(lcd_d11_pf3,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30d0, N, N),
-       PINGROUP(lcd_d12_pf4,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30d4, N, N),
-       PINGROUP(lcd_d13_pf5,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30d8, N, N),
-       PINGROUP(lcd_d14_pf6,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30dc, N, N),
-       PINGROUP(lcd_d15_pf7,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30e0, N, N),
-       PINGROUP(gmi_ad0_pg0,          RSVD1,        NAND,         GMI,          RSVD4,        0x31f0, N, N),
-       PINGROUP(gmi_ad1_pg1,          RSVD1,        NAND,         GMI,          RSVD4,        0x31f4, N, N),
-       PINGROUP(gmi_ad2_pg2,          RSVD1,        NAND,         GMI,          RSVD4,        0x31f8, N, N),
-       PINGROUP(gmi_ad3_pg3,          RSVD1,        NAND,         GMI,          RSVD4,        0x31fc, N, N),
-       PINGROUP(gmi_ad4_pg4,          RSVD1,        NAND,         GMI,          RSVD4,        0x3200, N, N),
-       PINGROUP(gmi_ad5_pg5,          RSVD1,        NAND,         GMI,          RSVD4,        0x3204, N, N),
-       PINGROUP(gmi_ad6_pg6,          RSVD1,        NAND,         GMI,          RSVD4,        0x3208, N, N),
-       PINGROUP(gmi_ad7_pg7,          RSVD1,        NAND,         GMI,          RSVD4,        0x320c, N, N),
-       PINGROUP(gmi_ad8_ph0,          PWM0,         NAND,         GMI,          RSVD4,        0x3210, N, N),
-       PINGROUP(gmi_ad9_ph1,          PWM1,         NAND,         GMI,          RSVD4,        0x3214, N, N),
-       PINGROUP(gmi_ad10_ph2,         PWM2,         NAND,         GMI,          RSVD4,        0x3218, N, N),
-       PINGROUP(gmi_ad11_ph3,         PWM3,         NAND,         GMI,          RSVD4,        0x321c, N, N),
-       PINGROUP(gmi_ad12_ph4,         RSVD1,        NAND,         GMI,          RSVD4,        0x3220, N, N),
-       PINGROUP(gmi_ad13_ph5,         RSVD1,        NAND,         GMI,          RSVD4,        0x3224, N, N),
-       PINGROUP(gmi_ad14_ph6,         RSVD1,        NAND,         GMI,          RSVD4,        0x3228, N, N),
-       PINGROUP(gmi_ad15_ph7,         RSVD1,        NAND,         GMI,          RSVD4,        0x322c, N, N),
-       PINGROUP(gmi_wr_n_pi0,         RSVD1,        NAND,         GMI,          RSVD4,        0x3240, N, N),
-       PINGROUP(gmi_oe_n_pi1,         RSVD1,        NAND,         GMI,          RSVD4,        0x3244, N, N),
-       PINGROUP(gmi_dqs_pi2,          RSVD1,        NAND,         GMI,          RSVD4,        0x3248, N, N),
-       PINGROUP(gmi_cs6_n_pi3,        NAND,         NAND_ALT,     GMI,          SATA,         0x31e8, N, N),
-       PINGROUP(gmi_rst_n_pi4,        NAND,         NAND_ALT,     GMI,          RSVD4,        0x324c, N, N),
-       PINGROUP(gmi_iordy_pi5,        RSVD1,        NAND,         GMI,          RSVD4,        0x31c4, N, N),
-       PINGROUP(gmi_cs7_n_pi6,        NAND,         NAND_ALT,     GMI,          GMI_ALT,      0x31ec, N, N),
-       PINGROUP(gmi_wait_pi7,         RSVD1,        NAND,         GMI,          RSVD4,        0x31c8, N, N),
-       PINGROUP(gmi_cs0_n_pj0,        RSVD1,        NAND,         GMI,          DTV,          0x31d4, N, N),
-       PINGROUP(lcd_de_pj1,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3098, N, N),
-       PINGROUP(gmi_cs1_n_pj2,        RSVD1,        NAND,         GMI,          DTV,          0x31d8, N, N),
-       PINGROUP(lcd_hsync_pj3,        DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x309c, N, N),
-       PINGROUP(lcd_vsync_pj4,        DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30a0, N, N),
-       PINGROUP(uart2_cts_n_pj5,      UARTA,        UARTB,        GMI,          SPI4,         0x3170, N, N),
-       PINGROUP(uart2_rts_n_pj6,      UARTA,        UARTB,        GMI,          SPI4,         0x316c, N, N),
-       PINGROUP(gmi_a16_pj7,          UARTD,        SPI4,         GMI,          GMI_ALT,      0x3230, N, N),
-       PINGROUP(gmi_adv_n_pk0,        RSVD1,        NAND,         GMI,          RSVD4,        0x31cc, N, N),
-       PINGROUP(gmi_clk_pk1,          RSVD1,        NAND,         GMI,          RSVD4,        0x31d0, N, N),
-       PINGROUP(gmi_cs4_n_pk2,        RSVD1,        NAND,         GMI,          RSVD4,        0x31e4, N, N),
-       PINGROUP(gmi_cs2_n_pk3,        RSVD1,        NAND,         GMI,          RSVD4,        0x31dc, N, N),
-       PINGROUP(gmi_cs3_n_pk4,        RSVD1,        NAND,         GMI,          GMI_ALT,      0x31e0, N, N),
-       PINGROUP(spdif_out_pk5,        SPDIF,        RSVD2,        I2C1,         SDMMC2,       0x3354, N, N),
-       PINGROUP(spdif_in_pk6,         SPDIF,        HDA,          I2C1,         SDMMC2,       0x3350, N, N),
-       PINGROUP(gmi_a19_pk7,          UARTD,        SPI4,         GMI,          RSVD4,        0x323c, N, N),
-       PINGROUP(vi_d2_pl0,            DDR,          SDMMC2,       VI,           RSVD4,        0x312c, N, Y),
-       PINGROUP(vi_d3_pl1,            DDR,          SDMMC2,       VI,           RSVD4,        0x3130, N, Y),
-       PINGROUP(vi_d4_pl2,            DDR,          SDMMC2,       VI,           RSVD4,        0x3134, N, Y),
-       PINGROUP(vi_d5_pl3,            DDR,          SDMMC2,       VI,           RSVD4,        0x3138, N, Y),
-       PINGROUP(vi_d6_pl4,            DDR,          SDMMC2,       VI,           RSVD4,        0x313c, N, Y),
-       PINGROUP(vi_d7_pl5,            DDR,          SDMMC2,       VI,           RSVD4,        0x3140, N, Y),
-       PINGROUP(vi_d8_pl6,            DDR,          SDMMC2,       VI,           RSVD4,        0x3144, N, Y),
-       PINGROUP(vi_d9_pl7,            DDR,          SDMMC2,       VI,           RSVD4,        0x3148, N, Y),
-       PINGROUP(lcd_d16_pm0,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30e4, N, N),
-       PINGROUP(lcd_d17_pm1,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30e8, N, N),
-       PINGROUP(lcd_d18_pm2,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30ec, N, N),
-       PINGROUP(lcd_d19_pm3,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30f0, N, N),
-       PINGROUP(lcd_d20_pm4,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30f4, N, N),
-       PINGROUP(lcd_d21_pm5,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30f8, N, N),
-       PINGROUP(lcd_d22_pm6,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30fc, N, N),
-       PINGROUP(lcd_d23_pm7,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3100, N, N),
-       PINGROUP(dap1_fs_pn0,          I2S0,         HDA,          GMI,          SDMMC2,       0x3338, N, N),
-       PINGROUP(dap1_din_pn1,         I2S0,         HDA,          GMI,          SDMMC2,       0x333c, N, N),
-       PINGROUP(dap1_dout_pn2,        I2S0,         HDA,          GMI,          SDMMC2,       0x3340, N, N),
-       PINGROUP(dap1_sclk_pn3,        I2S0,         HDA,          GMI,          SDMMC2,       0x3344, N, N),
-       PINGROUP(lcd_cs0_n_pn4,        DISPLAYA,     DISPLAYB,     SPI5,         RSVD4,        0x3084, N, N),
-       PINGROUP(lcd_sdout_pn5,        DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x307c, N, N),
-       PINGROUP(lcd_dc0_pn6,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3088, N, N),
-       PINGROUP(hdmi_int_pn7,         HDMI,         RSVD2,        RSVD3,        RSVD4,        0x3110, N, N),
-       PINGROUP(ulpi_data7_po0,       SPI2,         HSI,          UARTA,        ULPI,         0x301c, N, N),
-       PINGROUP(ulpi_data0_po1,       SPI3,         HSI,          UARTA,        ULPI,         0x3000, N, N),
-       PINGROUP(ulpi_data1_po2,       SPI3,         HSI,          UARTA,        ULPI,         0x3004, N, N),
-       PINGROUP(ulpi_data2_po3,       SPI3,         HSI,          UARTA,        ULPI,         0x3008, N, N),
-       PINGROUP(ulpi_data3_po4,       SPI3,         HSI,          UARTA,        ULPI,         0x300c, N, N),
-       PINGROUP(ulpi_data4_po5,       SPI2,         HSI,          UARTA,        ULPI,         0x3010, N, N),
-       PINGROUP(ulpi_data5_po6,       SPI2,         HSI,          UARTA,        ULPI,         0x3014, N, N),
-       PINGROUP(ulpi_data6_po7,       SPI2,         HSI,          UARTA,        ULPI,         0x3018, N, N),
-       PINGROUP(dap3_fs_pp0,          I2S2,         RSVD2,        DISPLAYA,     DISPLAYB,     0x3030, N, N),
-       PINGROUP(dap3_din_pp1,         I2S2,         RSVD2,        DISPLAYA,     DISPLAYB,     0x3034, N, N),
-       PINGROUP(dap3_dout_pp2,        I2S2,         RSVD2,        DISPLAYA,     DISPLAYB,     0x3038, N, N),
-       PINGROUP(dap3_sclk_pp3,        I2S2,         RSVD2,        DISPLAYA,     DISPLAYB,     0x303c, N, N),
-       PINGROUP(dap4_fs_pp4,          I2S3,         RSVD2,        GMI,          RSVD4,        0x31a8, N, N),
-       PINGROUP(dap4_din_pp5,         I2S3,         RSVD2,        GMI,          RSVD4,        0x31ac, N, N),
-       PINGROUP(dap4_dout_pp6,        I2S3,         RSVD2,        GMI,          RSVD4,        0x31b0, N, N),
-       PINGROUP(dap4_sclk_pp7,        I2S3,         RSVD2,        GMI,          RSVD4,        0x31b4, N, N),
-       PINGROUP(kb_col0_pq0,          KBC,          NAND,         TRACE,        TEST,         0x32fc, N, N),
-       PINGROUP(kb_col1_pq1,          KBC,          NAND,         TRACE,        TEST,         0x3300, N, N),
-       PINGROUP(kb_col2_pq2,          KBC,          NAND,         TRACE,        RSVD4,        0x3304, N, N),
-       PINGROUP(kb_col3_pq3,          KBC,          NAND,         TRACE,        RSVD4,        0x3308, N, N),
-       PINGROUP(kb_col4_pq4,          KBC,          NAND,         TRACE,        RSVD4,        0x330c, N, N),
-       PINGROUP(kb_col5_pq5,          KBC,          NAND,         TRACE,        RSVD4,        0x3310, N, N),
-       PINGROUP(kb_col6_pq6,          KBC,          NAND,         TRACE,        MIO,          0x3314, N, N),
-       PINGROUP(kb_col7_pq7,          KBC,          NAND,         TRACE,        MIO,          0x3318, N, N),
-       PINGROUP(kb_row0_pr0,          KBC,          NAND,         RSVD3,        RSVD4,        0x32bc, N, N),
-       PINGROUP(kb_row1_pr1,          KBC,          NAND,         RSVD3,        RSVD4,        0x32c0, N, N),
-       PINGROUP(kb_row2_pr2,          KBC,          NAND,         RSVD3,        RSVD4,        0x32c4, N, N),
-       PINGROUP(kb_row3_pr3,          KBC,          NAND,         RSVD3,        INVALID,      0x32c8, N, N),
-       PINGROUP(kb_row4_pr4,          KBC,          NAND,         TRACE,        RSVD4,        0x32cc, N, N),
-       PINGROUP(kb_row5_pr5,          KBC,          NAND,         TRACE,        OWR,          0x32d0, N, N),
-       PINGROUP(kb_row6_pr6,          KBC,          NAND,         SDMMC2,       MIO,          0x32d4, N, N),
-       PINGROUP(kb_row7_pr7,          KBC,          NAND,         SDMMC2,       MIO,          0x32d8, N, N),
-       PINGROUP(kb_row8_ps0,          KBC,          NAND,         SDMMC2,       MIO,          0x32dc, N, N),
-       PINGROUP(kb_row9_ps1,          KBC,          NAND,         SDMMC2,       MIO,          0x32e0, N, N),
-       PINGROUP(kb_row10_ps2,         KBC,          NAND,         SDMMC2,       MIO,          0x32e4, N, N),
-       PINGROUP(kb_row11_ps3,         KBC,          NAND,         SDMMC2,       MIO,          0x32e8, N, N),
-       PINGROUP(kb_row12_ps4,         KBC,          NAND,         SDMMC2,       MIO,          0x32ec, N, N),
-       PINGROUP(kb_row13_ps5,         KBC,          NAND,         SDMMC2,       MIO,          0x32f0, N, N),
-       PINGROUP(kb_row14_ps6,         KBC,          NAND,         SDMMC2,       MIO,          0x32f4, N, N),
-       PINGROUP(kb_row15_ps7,         KBC,          NAND,         SDMMC2,       MIO,          0x32f8, N, N),
-       PINGROUP(vi_pclk_pt0,          RSVD1,        SDMMC2,       VI,           RSVD4,        0x3154, N, Y),
-       PINGROUP(vi_mclk_pt1,          VI,           VI_ALT1,      VI_ALT2,      VI_ALT3,      0x3158, N, Y),
-       PINGROUP(vi_d10_pt2,           DDR,          RSVD2,        VI,           RSVD4,        0x314c, N, Y),
-       PINGROUP(vi_d11_pt3,           DDR,          RSVD2,        VI,           RSVD4,        0x3150, N, Y),
-       PINGROUP(vi_d0_pt4,            DDR,          RSVD2,        VI,           RSVD4,        0x3124, N, Y),
-       PINGROUP(gen2_i2c_scl_pt5,     I2C2,         HDCP,         GMI,          RSVD4,        0x3250, Y, N),
-       PINGROUP(gen2_i2c_sda_pt6,     I2C2,         HDCP,         GMI,          RSVD4,        0x3254, Y, N),
-       PINGROUP(sdmmc4_cmd_pt7,       I2C3,         NAND,         GMI,          SDMMC4,       0x325c, N, Y),
-       PINGROUP(pu0,                  OWR,          UARTA,        GMI,          RSVD4,        0x3184, N, N),
-       PINGROUP(pu1,                  RSVD1,        UARTA,        GMI,          RSVD4,        0x3188, N, N),
-       PINGROUP(pu2,                  RSVD1,        UARTA,        GMI,          RSVD4,        0x318c, N, N),
-       PINGROUP(pu3,                  PWM0,         UARTA,        GMI,          RSVD4,        0x3190, N, N),
-       PINGROUP(pu4,                  PWM1,         UARTA,        GMI,          RSVD4,        0x3194, N, N),
-       PINGROUP(pu5,                  PWM2,         UARTA,        GMI,          RSVD4,        0x3198, N, N),
-       PINGROUP(pu6,                  PWM3,         UARTA,        GMI,          RSVD4,        0x319c, N, N),
-       PINGROUP(jtag_rtck_pu7,        RTCK,         RSVD2,        RSVD3,        RSVD4,        0x32b0, N, N),
-       PINGROUP(pv0,                  RSVD1,        RSVD2,        RSVD3,        RSVD4,        0x3040, N, N),
-       PINGROUP(pv1,                  RSVD1,        RSVD2,        RSVD3,        RSVD4,        0x3044, N, N),
-       PINGROUP(pv2,                  OWR,          RSVD2,        RSVD3,        RSVD4,        0x3060, N, N),
-       PINGROUP(pv3,                  CLK_12M_OUT,  RSVD2,        RSVD3,        RSVD4,        0x3064, N, N),
-       PINGROUP(ddc_scl_pv4,          I2C4,         RSVD2,        RSVD3,        RSVD4,        0x3114, N, N),
-       PINGROUP(ddc_sda_pv5,          I2C4,         RSVD2,        RSVD3,        RSVD4,        0x3118, N, N),
-       PINGROUP(crt_hsync_pv6,        CRT,          RSVD2,        RSVD3,        RSVD4,        0x311c, N, N),
-       PINGROUP(crt_vsync_pv7,        CRT,          RSVD2,        RSVD3,        RSVD4,        0x3120, N, N),
-       PINGROUP(lcd_cs1_n_pw0,        DISPLAYA,     DISPLAYB,     SPI5,         RSVD4,        0x3104, N, N),
-       PINGROUP(lcd_m1_pw1,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3108, N, N),
-       PINGROUP(spi2_cs1_n_pw2,       SPI3,         SPI2,         SPI2_ALT,     I2C1,         0x3388, N, N),
-       PINGROUP(spi2_cs2_n_pw3,       SPI3,         SPI2,         SPI2_ALT,     I2C1,         0x338c, N, N),
-       PINGROUP(clk1_out_pw4,         EXTPERIPH1,   RSVD2,        RSVD3,        RSVD4,        0x334c, N, N),
-       PINGROUP(clk2_out_pw5,         EXTPERIPH2,   RSVD2,        RSVD3,        RSVD4,        0x3068, N, N),
-       PINGROUP(uart3_txd_pw6,        UARTC,        RSVD2,        GMI,          RSVD4,        0x3174, N, N),
-       PINGROUP(uart3_rxd_pw7,        UARTC,        RSVD2,        GMI,          RSVD4,        0x3178, N, N),
-       PINGROUP(spi2_mosi_px0,        SPI6,         SPI2,         SPI3,         GMI,          0x3368, N, N),
-       PINGROUP(spi2_miso_px1,        SPI6,         SPI2,         SPI3,         GMI,          0x336c, N, N),
-       PINGROUP(spi2_sck_px2,         SPI6,         SPI2,         SPI3,         GMI,          0x3374, N, N),
-       PINGROUP(spi2_cs0_n_px3,       SPI6,         SPI2,         SPI3,         GMI,          0x3370, N, N),
-       PINGROUP(spi1_mosi_px4,        SPI2,         SPI1,         SPI2_ALT,     GMI,          0x3378, N, N),
-       PINGROUP(spi1_sck_px5,         SPI2,         SPI1,         SPI2_ALT,     GMI,          0x337c, N, N),
-       PINGROUP(spi1_cs0_n_px6,       SPI2,         SPI1,         SPI2_ALT,     GMI,          0x3380, N, N),
-       PINGROUP(spi1_miso_px7,        SPI3,         SPI1,         SPI2_ALT,     RSVD4,        0x3384, N, N),
-       PINGROUP(ulpi_clk_py0,         SPI1,         RSVD2,        UARTD,        ULPI,         0x3020, N, N),
-       PINGROUP(ulpi_dir_py1,         SPI1,         RSVD2,        UARTD,        ULPI,         0x3024, N, N),
-       PINGROUP(ulpi_nxt_py2,         SPI1,         RSVD2,        UARTD,        ULPI,         0x3028, N, N),
-       PINGROUP(ulpi_stp_py3,         SPI1,         RSVD2,        UARTD,        ULPI,         0x302c, N, N),
-       PINGROUP(sdmmc1_dat3_py4,      SDMMC1,       RSVD2,        UARTE,        UARTA,        0x3050, N, N),
-       PINGROUP(sdmmc1_dat2_py5,      SDMMC1,       RSVD2,        UARTE,        UARTA,        0x3054, N, N),
-       PINGROUP(sdmmc1_dat1_py6,      SDMMC1,       RSVD2,        UARTE,        UARTA,        0x3058, N, N),
-       PINGROUP(sdmmc1_dat0_py7,      SDMMC1,       RSVD2,        UARTE,        UARTA,        0x305c, N, N),
-       PINGROUP(sdmmc1_clk_pz0,       SDMMC1,       RSVD2,        RSVD3,        UARTA,        0x3048, N, N),
-       PINGROUP(sdmmc1_cmd_pz1,       SDMMC1,       RSVD2,        RSVD3,        UARTA,        0x304c, N, N),
-       PINGROUP(lcd_sdin_pz2,         DISPLAYA,     DISPLAYB,     SPI5,         RSVD4,        0x3078, N, N),
-       PINGROUP(lcd_wr_n_pz3,         DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x3080, N, N),
-       PINGROUP(lcd_sck_pz4,          DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x308c, N, N),
-       PINGROUP(sys_clk_req_pz5,      SYSCLK,       RSVD2,        RSVD3,        RSVD4,        0x3320, N, N),
-       PINGROUP(pwr_i2c_scl_pz6,      I2CPWR,       RSVD2,        RSVD3,        RSVD4,        0x32b4, Y, N),
-       PINGROUP(pwr_i2c_sda_pz7,      I2CPWR,       RSVD2,        RSVD3,        RSVD4,        0x32b8, Y, N),
-       PINGROUP(sdmmc4_dat0_paa0,     UARTE,        SPI3,         GMI,          SDMMC4,       0x3260, N, Y),
-       PINGROUP(sdmmc4_dat1_paa1,     UARTE,        SPI3,         GMI,          SDMMC4,       0x3264, N, Y),
-       PINGROUP(sdmmc4_dat2_paa2,     UARTE,        SPI3,         GMI,          SDMMC4,       0x3268, N, Y),
-       PINGROUP(sdmmc4_dat3_paa3,     UARTE,        SPI3,         GMI,          SDMMC4,       0x326c, N, Y),
-       PINGROUP(sdmmc4_dat4_paa4,     I2C3,         I2S4,         GMI,          SDMMC4,       0x3270, N, Y),
-       PINGROUP(sdmmc4_dat5_paa5,     VGP3,         I2S4,         GMI,          SDMMC4,       0x3274, N, Y),
-       PINGROUP(sdmmc4_dat6_paa6,     VGP4,         I2S4,         GMI,          SDMMC4,       0x3278, N, Y),
-       PINGROUP(sdmmc4_dat7_paa7,     VGP5,         I2S4,         GMI,          SDMMC4,       0x327c, N, Y),
-       PINGROUP(pbb0,                 I2S4,         RSVD2,        RSVD3,        SDMMC4,       0x328c, N, N),
-       PINGROUP(cam_i2c_scl_pbb1,     VGP1,         I2C3,         RSVD3,        SDMMC4,       0x3290, Y, N),
-       PINGROUP(cam_i2c_sda_pbb2,     VGP2,         I2C3,         RSVD3,        SDMMC4,       0x3294, Y, N),
-       PINGROUP(pbb3,                 VGP3,         DISPLAYA,     DISPLAYB,     SDMMC4,       0x3298, N, N),
-       PINGROUP(pbb4,                 VGP4,         DISPLAYA,     DISPLAYB,     SDMMC4,       0x329c, N, N),
-       PINGROUP(pbb5,                 VGP5,         DISPLAYA,     DISPLAYB,     SDMMC4,       0x32a0, N, N),
-       PINGROUP(pbb6,                 VGP6,         DISPLAYA,     DISPLAYB,     SDMMC4,       0x32a4, N, N),
-       PINGROUP(pbb7,                 I2S4,         RSVD2,        RSVD3,        SDMMC4,       0x32a8, N, N),
-       PINGROUP(cam_mclk_pcc0,        VI,           VI_ALT1,      VI_ALT3,      SDMMC4,       0x3284, N, N),
-       PINGROUP(pcc1,                 I2S4,         RSVD2,        RSVD3,        SDMMC4,       0x3288, N, N),
-       PINGROUP(pcc2,                 I2S4,         RSVD2,        RSVD3,        RSVD4,        0x32ac, N, N),
-       PINGROUP(sdmmc4_rst_n_pcc3,    VGP6,         RSVD2,        RSVD3,        SDMMC4,       0x3280, N, Y),
-       PINGROUP(sdmmc4_clk_pcc4,      INVALID,      NAND,         GMI,          SDMMC4,       0x3258, N, Y),
-       PINGROUP(clk2_req_pcc5,        DAP,          RSVD2,        RSVD3,        RSVD4,        0x306c, N, N),
-       PINGROUP(pex_l2_rst_n_pcc6,    PCIE,         HDA,          RSVD3,        RSVD4,        0x33d8, N, N),
-       PINGROUP(pex_l2_clkreq_n_pcc7, PCIE,         HDA,          RSVD3,        RSVD4,        0x33dc, N, N),
-       PINGROUP(pex_l0_prsnt_n_pdd0,  PCIE,         HDA,          RSVD3,        RSVD4,        0x33b8, N, N),
-       PINGROUP(pex_l0_rst_n_pdd1,    PCIE,         HDA,          RSVD3,        RSVD4,        0x33bc, N, N),
-       PINGROUP(pex_l0_clkreq_n_pdd2, PCIE,         HDA,          RSVD3,        RSVD4,        0x33c0, N, N),
-       PINGROUP(pex_wake_n_pdd3,      PCIE,         HDA,          RSVD3,        RSVD4,        0x33c4, N, N),
-       PINGROUP(pex_l1_prsnt_n_pdd4,  PCIE,         HDA,          RSVD3,        RSVD4,        0x33c8, N, N),
-       PINGROUP(pex_l1_rst_n_pdd5,    PCIE,         HDA,          RSVD3,        RSVD4,        0x33cc, N, N),
-       PINGROUP(pex_l1_clkreq_n_pdd6, PCIE,         HDA,          RSVD3,        RSVD4,        0x33d0, N, N),
-       PINGROUP(pex_l2_prsnt_n_pdd7,  PCIE,         HDA,          RSVD3,        RSVD4,        0x33d4, N, N),
-       PINGROUP(clk3_out_pee0,        EXTPERIPH3,   RSVD2,        RSVD3,        RSVD4,        0x31b8, N, N),
-       PINGROUP(clk3_req_pee1,        DEV3,         RSVD2,        RSVD3,        RSVD4,        0x31bc, N, N),
-       PINGROUP(clk1_req_pee2,        DAP,          HDA,          RSVD3,        RSVD4,        0x3348, N, N),
-       PINGROUP(hdmi_cec_pee3,        CEC,          RSVD2,        RSVD3,        RSVD4,        0x33e0, Y, N),
-       PINGROUP(clk_32k_in,           CLK_32K_IN,   RSVD2,        RSVD3,        RSVD4,        0x3330, N, N),
-       PINGROUP(core_pwr_req,         CORE_PWR_REQ, RSVD2,        RSVD3,        RSVD4,        0x3324, N, N),
-       PINGROUP(cpu_pwr_req,          CPU_PWR_REQ,  RSVD2,        RSVD3,        RSVD4,        0x3328, N, N),
-       PINGROUP(owr,                  OWR,          CEC,          RSVD3,        RSVD4,        0x3334, N, N),
-       PINGROUP(pwr_int_n,            PWR_INT_N,    RSVD2,        RSVD3,        RSVD4,        0x332c, N, N),
-       /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
-       DRV_PINGROUP(ao1,   0x868,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(ao2,   0x86c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(at1,   0x870,  2,  3,  4,  14,  5,  19,  5,  24,  2,  28,  2),
-       DRV_PINGROUP(at2,   0x874,  2,  3,  4,  14,  5,  19,  5,  24,  2,  28,  2),
-       DRV_PINGROUP(at3,   0x878,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(at4,   0x87c,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(at5,   0x880,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(cdev1, 0x884,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(cdev2, 0x888,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(cec,   0x938,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(crt,   0x8f8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(csus,  0x88c, -1, -1, -1,  12,  5,  19,  5,  24,  4,  28,  4),
-       DRV_PINGROUP(dap1,  0x890,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(dap2,  0x894,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(dap3,  0x898,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(dap4,  0x89c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(dbg,   0x8a0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(ddc,   0x8fc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(dev3,  0x92c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(gma,   0x900, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
-       DRV_PINGROUP(gmb,   0x904, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
-       DRV_PINGROUP(gmc,   0x908, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
-       DRV_PINGROUP(gmd,   0x90c, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
-       DRV_PINGROUP(gme,   0x910,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(gmf,   0x914,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(gmg,   0x918,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(gmh,   0x91c,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(gpv,   0x928,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(lcd1,  0x8a4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(lcd2,  0x8a8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(owr,   0x920,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(sdio1, 0x8ec,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2),
-       DRV_PINGROUP(sdio2, 0x8ac,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2),
-       DRV_PINGROUP(sdio3, 0x8b0,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2),
-       DRV_PINGROUP(spi,   0x8b4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(uaa,   0x8b8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(uab,   0x8bc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(uart2, 0x8c0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(uart3, 0x8c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(uda,   0x924,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
-       DRV_PINGROUP(vi1,   0x8c8, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
-};
-
-static const struct tegra_pinctrl_soc_data tegra30_pinctrl = {
-       .ngpios = NUM_GPIOS,
-       .pins = tegra30_pins,
-       .npins = ARRAY_SIZE(tegra30_pins),
-       .functions = tegra30_functions,
-       .nfunctions = ARRAY_SIZE(tegra30_functions),
-       .groups = tegra30_groups,
-       .ngroups = ARRAY_SIZE(tegra30_groups),
-       .hsm_in_mux = false,
-       .schmitt_in_mux = false,
-       .drvtype_in_mux = false,
-};
-
-static int tegra30_pinctrl_probe(struct platform_device *pdev)
-{
-       return tegra_pinctrl_probe(pdev, &tegra30_pinctrl);
-}
-
-static const struct of_device_id tegra30_pinctrl_of_match[] = {
-       { .compatible = "nvidia,tegra30-pinmux", },
-       { },
-};
-MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match);
-
-static struct platform_driver tegra30_pinctrl_driver = {
-       .driver = {
-               .name = "tegra30-pinctrl",
-               .of_match_table = tegra30_pinctrl_of_match,
-       },
-       .probe = tegra30_pinctrl_probe,
-       .remove = tegra_pinctrl_remove,
-};
-module_platform_driver(tegra30_pinctrl_driver);
-
-MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
-MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver");
-MODULE_LICENSE("GPL v2");
index d57b5eca7b98350ecc2e9b708f05e7457a26db16..76f1abd71e31f351c687112db3600e1b9551c97f 100644 (file)
@@ -590,7 +590,7 @@ static const char * const usb1_groups[] = {"usb1_0_grp"};
 static const char * const mdio0_groups[] = {"mdio0_0_grp"};
 static const char * const mdio1_groups[] = {"mdio1_0_grp"};
 static const char * const qspi0_groups[] = {"qspi0_0_grp"};
-static const char * const qspi1_groups[] = {"qspi0_1_grp"};
+static const char * const qspi1_groups[] = {"qspi1_0_grp"};
 static const char * const qspi_fbclk_groups[] = {"qspi_fbclk_grp"};
 static const char * const qspi_cs1_groups[] = {"qspi_cs1_grp"};
 static const char * const spi0_groups[] = {"spi0_0_grp", "spi0_1_grp",
index 216f227c60092f580df47bc5e5f7c64828419d80..f553313bc2efbcc912be92f5e9a3bc992581de65 100644 (file)
@@ -426,7 +426,7 @@ int pxa2xx_pinctrl_init(struct platform_device *pdev,
 
        return 0;
 }
-EXPORT_SYMBOL(pxa2xx_pinctrl_init);
+EXPORT_SYMBOL_GPL(pxa2xx_pinctrl_init);
 
 int pxa2xx_pinctrl_exit(struct platform_device *pdev)
 {
@@ -435,3 +435,4 @@ int pxa2xx_pinctrl_exit(struct platform_device *pdev)
        pinctrl_unregister(pctl->pctl_dev);
        return 0;
 }
+EXPORT_SYMBOL_GPL(pxa2xx_pinctrl_exit);
index eeac8cba8a2109fc70e5955fe24ae6c8fbf770d2..67bc70dcda64ae5295c9798d23e525aab4f71370 100644 (file)
@@ -23,6 +23,14 @@ config PINCTRL_APQ8084
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
          Qualcomm TLMM block found in the Qualcomm APQ8084 platform.
 
+config PINCTRL_IPQ4019
+       tristate "Qualcomm IPQ4019 pin controller driver"
+       depends on GPIOLIB && OF
+       select PINCTRL_MSM
+       help
+         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+         Qualcomm TLMM block found in the Qualcomm IPQ4019 platform.
+
 config PINCTRL_IPQ8064
        tristate "Qualcomm IPQ8064 pin controller driver"
        depends on GPIOLIB && OF
index dfb50a9fe04ad23c770ba1c1b24d2a6aa9ce7e8a..c964a2c4b90ad4bd36d97d319016e51eb8e3753d 100644 (file)
@@ -2,6 +2,7 @@
 obj-$(CONFIG_PINCTRL_MSM)      += pinctrl-msm.o
 obj-$(CONFIG_PINCTRL_APQ8064)  += pinctrl-apq8064.o
 obj-$(CONFIG_PINCTRL_APQ8084)  += pinctrl-apq8084.o
+obj-$(CONFIG_PINCTRL_IPQ4019)  += pinctrl-ipq4019.o
 obj-$(CONFIG_PINCTRL_IPQ8064)  += pinctrl-ipq8064.o
 obj-$(CONFIG_PINCTRL_MSM8660)  += pinctrl-msm8660.o
 obj-$(CONFIG_PINCTRL_MSM8960)  += pinctrl-msm8960.o
diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c
new file mode 100644 (file)
index 0000000..b5d81ce
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+static const struct pinctrl_pin_desc ipq4019_pins[] = {
+       PINCTRL_PIN(0, "GPIO_0"),
+       PINCTRL_PIN(1, "GPIO_1"),
+       PINCTRL_PIN(2, "GPIO_2"),
+       PINCTRL_PIN(3, "GPIO_3"),
+       PINCTRL_PIN(4, "GPIO_4"),
+       PINCTRL_PIN(5, "GPIO_5"),
+       PINCTRL_PIN(6, "GPIO_6"),
+       PINCTRL_PIN(7, "GPIO_7"),
+       PINCTRL_PIN(8, "GPIO_8"),
+       PINCTRL_PIN(9, "GPIO_9"),
+       PINCTRL_PIN(10, "GPIO_10"),
+       PINCTRL_PIN(11, "GPIO_11"),
+       PINCTRL_PIN(12, "GPIO_12"),
+       PINCTRL_PIN(13, "GPIO_13"),
+       PINCTRL_PIN(14, "GPIO_14"),
+       PINCTRL_PIN(15, "GPIO_15"),
+       PINCTRL_PIN(16, "GPIO_16"),
+       PINCTRL_PIN(17, "GPIO_17"),
+       PINCTRL_PIN(18, "GPIO_18"),
+       PINCTRL_PIN(19, "GPIO_19"),
+       PINCTRL_PIN(20, "GPIO_20"),
+       PINCTRL_PIN(21, "GPIO_21"),
+       PINCTRL_PIN(22, "GPIO_22"),
+       PINCTRL_PIN(23, "GPIO_23"),
+       PINCTRL_PIN(24, "GPIO_24"),
+       PINCTRL_PIN(25, "GPIO_25"),
+       PINCTRL_PIN(26, "GPIO_26"),
+       PINCTRL_PIN(27, "GPIO_27"),
+       PINCTRL_PIN(28, "GPIO_28"),
+       PINCTRL_PIN(29, "GPIO_29"),
+       PINCTRL_PIN(30, "GPIO_30"),
+       PINCTRL_PIN(31, "GPIO_31"),
+       PINCTRL_PIN(32, "GPIO_32"),
+       PINCTRL_PIN(33, "GPIO_33"),
+       PINCTRL_PIN(34, "GPIO_34"),
+       PINCTRL_PIN(35, "GPIO_35"),
+       PINCTRL_PIN(36, "GPIO_36"),
+       PINCTRL_PIN(37, "GPIO_37"),
+       PINCTRL_PIN(38, "GPIO_38"),
+       PINCTRL_PIN(39, "GPIO_39"),
+       PINCTRL_PIN(40, "GPIO_40"),
+       PINCTRL_PIN(41, "GPIO_41"),
+       PINCTRL_PIN(42, "GPIO_42"),
+       PINCTRL_PIN(43, "GPIO_43"),
+       PINCTRL_PIN(44, "GPIO_44"),
+       PINCTRL_PIN(45, "GPIO_45"),
+       PINCTRL_PIN(46, "GPIO_46"),
+       PINCTRL_PIN(47, "GPIO_47"),
+       PINCTRL_PIN(48, "GPIO_48"),
+       PINCTRL_PIN(49, "GPIO_49"),
+       PINCTRL_PIN(50, "GPIO_50"),
+       PINCTRL_PIN(51, "GPIO_51"),
+       PINCTRL_PIN(52, "GPIO_52"),
+       PINCTRL_PIN(53, "GPIO_53"),
+       PINCTRL_PIN(54, "GPIO_54"),
+       PINCTRL_PIN(55, "GPIO_55"),
+       PINCTRL_PIN(56, "GPIO_56"),
+       PINCTRL_PIN(57, "GPIO_57"),
+       PINCTRL_PIN(58, "GPIO_58"),
+       PINCTRL_PIN(59, "GPIO_59"),
+       PINCTRL_PIN(60, "GPIO_60"),
+       PINCTRL_PIN(61, "GPIO_61"),
+       PINCTRL_PIN(62, "GPIO_62"),
+       PINCTRL_PIN(63, "GPIO_63"),
+       PINCTRL_PIN(64, "GPIO_64"),
+       PINCTRL_PIN(65, "GPIO_65"),
+       PINCTRL_PIN(66, "GPIO_66"),
+       PINCTRL_PIN(67, "GPIO_67"),
+       PINCTRL_PIN(68, "GPIO_68"),
+       PINCTRL_PIN(69, "GPIO_69"),
+       PINCTRL_PIN(70, "GPIO_70"),
+       PINCTRL_PIN(71, "GPIO_71"),
+       PINCTRL_PIN(72, "GPIO_72"),
+       PINCTRL_PIN(73, "GPIO_73"),
+       PINCTRL_PIN(74, "GPIO_74"),
+       PINCTRL_PIN(75, "GPIO_75"),
+       PINCTRL_PIN(76, "GPIO_76"),
+       PINCTRL_PIN(77, "GPIO_77"),
+       PINCTRL_PIN(78, "GPIO_78"),
+       PINCTRL_PIN(79, "GPIO_79"),
+       PINCTRL_PIN(80, "GPIO_80"),
+       PINCTRL_PIN(81, "GPIO_81"),
+       PINCTRL_PIN(82, "GPIO_82"),
+       PINCTRL_PIN(83, "GPIO_83"),
+       PINCTRL_PIN(84, "GPIO_84"),
+       PINCTRL_PIN(85, "GPIO_85"),
+       PINCTRL_PIN(86, "GPIO_86"),
+       PINCTRL_PIN(87, "GPIO_87"),
+       PINCTRL_PIN(88, "GPIO_88"),
+       PINCTRL_PIN(89, "GPIO_89"),
+       PINCTRL_PIN(90, "GPIO_90"),
+       PINCTRL_PIN(91, "GPIO_91"),
+       PINCTRL_PIN(92, "GPIO_92"),
+       PINCTRL_PIN(93, "GPIO_93"),
+       PINCTRL_PIN(94, "GPIO_94"),
+       PINCTRL_PIN(95, "GPIO_95"),
+       PINCTRL_PIN(96, "GPIO_96"),
+       PINCTRL_PIN(97, "GPIO_97"),
+       PINCTRL_PIN(98, "GPIO_98"),
+       PINCTRL_PIN(99, "GPIO_99"),
+};
+
+#define DECLARE_QCA_GPIO_PINS(pin) \
+       static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_QCA_GPIO_PINS(0);
+DECLARE_QCA_GPIO_PINS(1);
+DECLARE_QCA_GPIO_PINS(2);
+DECLARE_QCA_GPIO_PINS(3);
+DECLARE_QCA_GPIO_PINS(4);
+DECLARE_QCA_GPIO_PINS(5);
+DECLARE_QCA_GPIO_PINS(6);
+DECLARE_QCA_GPIO_PINS(7);
+DECLARE_QCA_GPIO_PINS(8);
+DECLARE_QCA_GPIO_PINS(9);
+DECLARE_QCA_GPIO_PINS(10);
+DECLARE_QCA_GPIO_PINS(11);
+DECLARE_QCA_GPIO_PINS(12);
+DECLARE_QCA_GPIO_PINS(13);
+DECLARE_QCA_GPIO_PINS(14);
+DECLARE_QCA_GPIO_PINS(15);
+DECLARE_QCA_GPIO_PINS(16);
+DECLARE_QCA_GPIO_PINS(17);
+DECLARE_QCA_GPIO_PINS(18);
+DECLARE_QCA_GPIO_PINS(19);
+DECLARE_QCA_GPIO_PINS(20);
+DECLARE_QCA_GPIO_PINS(21);
+DECLARE_QCA_GPIO_PINS(22);
+DECLARE_QCA_GPIO_PINS(23);
+DECLARE_QCA_GPIO_PINS(24);
+DECLARE_QCA_GPIO_PINS(25);
+DECLARE_QCA_GPIO_PINS(26);
+DECLARE_QCA_GPIO_PINS(27);
+DECLARE_QCA_GPIO_PINS(28);
+DECLARE_QCA_GPIO_PINS(29);
+DECLARE_QCA_GPIO_PINS(30);
+DECLARE_QCA_GPIO_PINS(31);
+DECLARE_QCA_GPIO_PINS(32);
+DECLARE_QCA_GPIO_PINS(33);
+DECLARE_QCA_GPIO_PINS(34);
+DECLARE_QCA_GPIO_PINS(35);
+DECLARE_QCA_GPIO_PINS(36);
+DECLARE_QCA_GPIO_PINS(37);
+DECLARE_QCA_GPIO_PINS(38);
+DECLARE_QCA_GPIO_PINS(39);
+DECLARE_QCA_GPIO_PINS(40);
+DECLARE_QCA_GPIO_PINS(41);
+DECLARE_QCA_GPIO_PINS(42);
+DECLARE_QCA_GPIO_PINS(43);
+DECLARE_QCA_GPIO_PINS(44);
+DECLARE_QCA_GPIO_PINS(45);
+DECLARE_QCA_GPIO_PINS(46);
+DECLARE_QCA_GPIO_PINS(47);
+DECLARE_QCA_GPIO_PINS(48);
+DECLARE_QCA_GPIO_PINS(49);
+DECLARE_QCA_GPIO_PINS(50);
+DECLARE_QCA_GPIO_PINS(51);
+DECLARE_QCA_GPIO_PINS(52);
+DECLARE_QCA_GPIO_PINS(53);
+DECLARE_QCA_GPIO_PINS(54);
+DECLARE_QCA_GPIO_PINS(55);
+DECLARE_QCA_GPIO_PINS(56);
+DECLARE_QCA_GPIO_PINS(57);
+DECLARE_QCA_GPIO_PINS(58);
+DECLARE_QCA_GPIO_PINS(59);
+DECLARE_QCA_GPIO_PINS(60);
+DECLARE_QCA_GPIO_PINS(61);
+DECLARE_QCA_GPIO_PINS(62);
+DECLARE_QCA_GPIO_PINS(63);
+DECLARE_QCA_GPIO_PINS(64);
+DECLARE_QCA_GPIO_PINS(65);
+DECLARE_QCA_GPIO_PINS(66);
+DECLARE_QCA_GPIO_PINS(67);
+DECLARE_QCA_GPIO_PINS(68);
+DECLARE_QCA_GPIO_PINS(69);
+DECLARE_QCA_GPIO_PINS(70);
+DECLARE_QCA_GPIO_PINS(71);
+DECLARE_QCA_GPIO_PINS(72);
+DECLARE_QCA_GPIO_PINS(73);
+DECLARE_QCA_GPIO_PINS(74);
+DECLARE_QCA_GPIO_PINS(75);
+DECLARE_QCA_GPIO_PINS(76);
+DECLARE_QCA_GPIO_PINS(77);
+DECLARE_QCA_GPIO_PINS(78);
+DECLARE_QCA_GPIO_PINS(79);
+DECLARE_QCA_GPIO_PINS(80);
+DECLARE_QCA_GPIO_PINS(81);
+DECLARE_QCA_GPIO_PINS(82);
+DECLARE_QCA_GPIO_PINS(83);
+DECLARE_QCA_GPIO_PINS(84);
+DECLARE_QCA_GPIO_PINS(85);
+DECLARE_QCA_GPIO_PINS(86);
+DECLARE_QCA_GPIO_PINS(87);
+DECLARE_QCA_GPIO_PINS(88);
+DECLARE_QCA_GPIO_PINS(89);
+DECLARE_QCA_GPIO_PINS(90);
+DECLARE_QCA_GPIO_PINS(91);
+DECLARE_QCA_GPIO_PINS(92);
+DECLARE_QCA_GPIO_PINS(93);
+DECLARE_QCA_GPIO_PINS(94);
+DECLARE_QCA_GPIO_PINS(95);
+DECLARE_QCA_GPIO_PINS(96);
+DECLARE_QCA_GPIO_PINS(97);
+DECLARE_QCA_GPIO_PINS(98);
+DECLARE_QCA_GPIO_PINS(99);
+
+#define FUNCTION(fname)                                        \
+       [qca_mux_##fname] = {                           \
+               .name = #fname,                         \
+               .groups = fname##_groups,               \
+               .ngroups = ARRAY_SIZE(fname##_groups),  \
+       }
+
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14) \
+       {                                               \
+               .name = "gpio" #id,                     \
+               .pins = gpio##id##_pins,                \
+               .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \
+               .funcs = (int[]){                       \
+                       qca_mux_NA, /* gpio mode */     \
+                       qca_mux_##f1,                   \
+                       qca_mux_##f2,                   \
+                       qca_mux_##f3,                   \
+                       qca_mux_##f4,                   \
+                       qca_mux_##f5,                   \
+                       qca_mux_##f6,                   \
+                       qca_mux_##f7,                   \
+                       qca_mux_##f8,                   \
+                       qca_mux_##f9,                   \
+                       qca_mux_##f10,                  \
+                       qca_mux_##f11,                  \
+                       qca_mux_##f12,                  \
+                       qca_mux_##f13,                  \
+                       qca_mux_##f14                   \
+               },                                      \
+               .nfuncs = 15,                           \
+               .ctl_reg = 0x1000 + 0x10 * id,          \
+               .io_reg = 0x1004 + 0x10 * id,           \
+               .intr_cfg_reg = 0x1008 + 0x10 * id,     \
+               .intr_status_reg = 0x100c + 0x10 * id,  \
+               .intr_target_reg = 0x400 + 0x4 * id,    \
+               .mux_bit = 2,                   \
+               .pull_bit = 0,                  \
+               .drv_bit = 6,                   \
+               .oe_bit = 9,                    \
+               .in_bit = 0,                    \
+               .out_bit = 1,                   \
+               .intr_enable_bit = 0,           \
+               .intr_status_bit = 0,           \
+               .intr_target_bit = 5,           \
+               .intr_raw_status_bit = 4,       \
+               .intr_polarity_bit = 1,         \
+               .intr_detection_bit = 2,        \
+               .intr_detection_width = 2,      \
+       }
+
+
+enum ipq4019_functions {
+       qca_mux_gpio,
+       qca_mux_blsp_uart1,
+       qca_mux_blsp_i2c0,
+       qca_mux_blsp_i2c1,
+       qca_mux_blsp_uart0,
+       qca_mux_blsp_spi1,
+       qca_mux_blsp_spi0,
+       qca_mux_NA,
+};
+
+static const char * const gpio_groups[] = {
+       "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+       "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+       "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+       "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+       "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+       "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+       "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+       "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+       "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+       "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+       "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+       "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+       "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+       "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+       "gpio99",
+};
+
+static const char * const blsp_uart1_groups[] = {
+       "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const blsp_i2c0_groups[] = {
+       "gpio10", "gpio11", "gpio20", "gpio21", "gpio58", "gpio59",
+};
+static const char * const blsp_spi0_groups[] = {
+       "gpio12", "gpio13", "gpio14", "gpio15", "gpio45",
+       "gpio54", "gpio55", "gpio56", "gpio57",
+};
+static const char * const blsp_i2c1_groups[] = {
+       "gpio12", "gpio13", "gpio34", "gpio35",
+};
+static const char * const blsp_uart0_groups[] = {
+       "gpio16", "gpio17", "gpio60", "gpio61",
+};
+static const char * const blsp_spi1_groups[] = {
+       "gpio44", "gpio45", "gpio46", "gpio47",
+};
+
+static const struct msm_function ipq4019_functions[] = {
+       FUNCTION(gpio),
+       FUNCTION(blsp_uart1),
+       FUNCTION(blsp_i2c0),
+       FUNCTION(blsp_i2c1),
+       FUNCTION(blsp_uart0),
+       FUNCTION(blsp_spi1),
+       FUNCTION(blsp_spi0),
+};
+
+static const struct msm_pingroup ipq4019_groups[] = {
+       PINGROUP(0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(4, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(5, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(6, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(7, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(8, blsp_uart1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(9, blsp_uart1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(10, blsp_uart1, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(11, blsp_uart1, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(12, blsp_spi0, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(13, blsp_spi0, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(14, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(15, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(16, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(17, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(18, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(19, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(20, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(21, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(22, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(23, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(24, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(25, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(26, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(27, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(28, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(29, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(30, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(31, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(32, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(33, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(34, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(35, blsp_i2c1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(36, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(37, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(38, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(39, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(40, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(41, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(42, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(43, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(44, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(45, NA, blsp_spi1, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(46, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(47, NA, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(48, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(49, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(50, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(51, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(52, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(53, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(54, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(55, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(56, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(57, NA, blsp_spi0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(58, NA, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(59, NA, blsp_i2c0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(60, NA, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(61, NA, blsp_uart0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(62, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(63, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(65, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(67, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(68, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+       PINGROUP(69, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+};
+
+static const struct msm_pinctrl_soc_data ipq4019_pinctrl = {
+       .pins = ipq4019_pins,
+       .npins = ARRAY_SIZE(ipq4019_pins),
+       .functions = ipq4019_functions,
+       .nfunctions = ARRAY_SIZE(ipq4019_functions),
+       .groups = ipq4019_groups,
+       .ngroups = ARRAY_SIZE(ipq4019_groups),
+       .ngpios = 70,
+};
+
+static int ipq4019_pinctrl_probe(struct platform_device *pdev)
+{
+       return msm_pinctrl_probe(pdev, &ipq4019_pinctrl);
+}
+
+static const struct of_device_id ipq4019_pinctrl_of_match[] = {
+       { .compatible = "qcom,ipq4019-pinctrl", },
+       { },
+};
+
+static struct platform_driver ipq4019_pinctrl_driver = {
+       .driver = {
+               .name = "ipq4019-pinctrl",
+               .of_match_table = ipq4019_pinctrl_of_match,
+       },
+       .probe = ipq4019_pinctrl_probe,
+       .remove = msm_pinctrl_remove,
+};
+
+static int __init ipq4019_pinctrl_init(void)
+{
+       return platform_driver_register(&ipq4019_pinctrl_driver);
+}
+arch_initcall(ipq4019_pinctrl_init);
+
+static void __exit ipq4019_pinctrl_exit(void)
+{
+       platform_driver_unregister(&ipq4019_pinctrl_driver);
+}
+module_exit(ipq4019_pinctrl_exit);
+
+MODULE_DESCRIPTION("Qualcomm ipq4019 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, ipq4019_pinctrl_of_match);
index 2f18323571a6d9dd8e61a219dc970c72bc88875c..2a3e5490a4834ad5a2e3ba2d6ee023228a4f4d6d 100644 (file)
  * @output_enabled: Set to true if MPP output logic is enabled.
  * @input_enabled: Set to true if MPP input buffer logic is enabled.
  * @paired: Pin operates in paired mode
+ * @has_pullup: Pin has support to configure pullup
  * @num_sources: Number of power-sources supported by this MPP.
  * @power_source: Current power-source used.
  * @amux_input: Set the source for analog input.
@@ -134,6 +135,7 @@ struct pmic_mpp_pad {
        bool            output_enabled;
        bool            input_enabled;
        bool            paired;
+       bool            has_pullup;
        unsigned int    num_sources;
        unsigned int    power_source;
        unsigned int    amux_input;
@@ -477,11 +479,14 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
        if (ret < 0)
                return ret;
 
-       val = pad->pullup << PMIC_MPP_REG_PULL_SHIFT;
+       if (pad->has_pullup) {
+               val = pad->pullup << PMIC_MPP_REG_PULL_SHIFT;
 
-       ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_PULL_CTL, val);
-       if (ret < 0)
-               return ret;
+               ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_PULL_CTL,
+                                    val);
+               if (ret < 0)
+                       return ret;
+       }
 
        val = pad->amux_input & PMIC_MPP_REG_AIN_ROUTE_MASK;
 
@@ -534,7 +539,8 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev,
                seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]);
                seq_printf(s, " vin-%d", pad->power_source);
                seq_printf(s, " %d", pad->aout_level);
-               seq_printf(s, " %-8s", biases[pad->pullup]);
+               if (pad->has_pullup)
+                       seq_printf(s, " %-8s", biases[pad->pullup]);
                seq_printf(s, " %-4s", pad->out_value ? "high" : "low");
                if (pad->dtest)
                        seq_printf(s, " dtest%d", pad->dtest);
@@ -748,12 +754,16 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state,
        pad->power_source = val >> PMIC_MPP_REG_VIN_SHIFT;
        pad->power_source &= PMIC_MPP_REG_VIN_MASK;
 
-       val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_PULL_CTL);
-       if (val < 0)
-               return val;
+       if (subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT &&
+           subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK) {
+               val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_PULL_CTL);
+               if (val < 0)
+                       return val;
 
-       pad->pullup = val >> PMIC_MPP_REG_PULL_SHIFT;
-       pad->pullup &= PMIC_MPP_REG_PULL_MASK;
+               pad->pullup = val >> PMIC_MPP_REG_PULL_SHIFT;
+               pad->pullup &= PMIC_MPP_REG_PULL_MASK;
+               pad->has_pullup = true;
+       }
 
        val = pmic_mpp_read(state, pad, PMIC_MPP_REG_AIN_CTL);
        if (val < 0)
index 35d6e95fa21fbbdd6cdf8bb9847bffad13ad88ce..415dd80230635ce023f63b5cb0323f9f54bf45c5 100644 (file)
@@ -2,10 +2,9 @@
 # Renesas SH and SH Mobile PINCTRL drivers
 #
 
-if ARCH_SHMOBILE || SUPERH
+if ARCH_RENESAS || SUPERH
 
 config PINCTRL_SH_PFC
-       select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
@@ -13,12 +12,12 @@ config PINCTRL_SH_PFC
        help
          This enables pin control drivers for SH and SH Mobile platforms
 
-config GPIO_SH_PFC
-       bool "SuperH PFC GPIO support"
-       depends on PINCTRL_SH_PFC && GPIOLIB
+config PINCTRL_SH_PFC_GPIO
+       select GPIOLIB
+       select PINCTRL_SH_PFC
+       bool
        help
-         This enables support for GPIOs within the SoC's pin function
-         controller.
+         This enables pin control and GPIO drivers for SH/SH Mobile platforms
 
 config PINCTRL_PFC_EMEV2
        def_bool y
@@ -28,12 +27,12 @@ config PINCTRL_PFC_EMEV2
 config PINCTRL_PFC_R8A73A4
        def_bool y
        depends on ARCH_R8A73A4
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_R8A7740
        def_bool y
        depends on ARCH_R8A7740
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_R8A7778
        def_bool y
@@ -73,79 +72,66 @@ config PINCTRL_PFC_R8A7795
 config PINCTRL_PFC_SH7203
        def_bool y
        depends on CPU_SUBTYPE_SH7203
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7264
        def_bool y
        depends on CPU_SUBTYPE_SH7264
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7269
        def_bool y
        depends on CPU_SUBTYPE_SH7269
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH73A0
        def_bool y
        depends on ARCH_SH73A0
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
        select REGULATOR
 
 config PINCTRL_PFC_SH7720
        def_bool y
        depends on CPU_SUBTYPE_SH7720
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7722
        def_bool y
        depends on CPU_SUBTYPE_SH7722
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7723
        def_bool y
        depends on CPU_SUBTYPE_SH7723
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7724
        def_bool y
        depends on CPU_SUBTYPE_SH7724
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7734
        def_bool y
        depends on CPU_SUBTYPE_SH7734
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7757
        def_bool y
        depends on CPU_SUBTYPE_SH7757
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7785
        def_bool y
        depends on CPU_SUBTYPE_SH7785
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SH7786
        def_bool y
        depends on CPU_SUBTYPE_SH7786
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
+       select PINCTRL_SH_PFC_GPIO
 
 config PINCTRL_PFC_SHX3
        def_bool y
        depends on CPU_SUBTYPE_SHX3
-       depends on GPIOLIB
-       select PINCTRL_SH_PFC
-
+       select PINCTRL_SH_PFC_GPIO
 endif
index 173305fa3811755a845ae39a81a11f2610ea1552..8a2c8710fc9375e6798bfeab6653a7bdfb0257f4 100644 (file)
@@ -1,8 +1,5 @@
-sh-pfc-objs                    = core.o pinctrl.o
-ifeq ($(CONFIG_GPIO_SH_PFC),y)
-sh-pfc-objs                    += gpio.o
-endif
-obj-$(CONFIG_PINCTRL_SH_PFC)   += sh-pfc.o
+obj-$(CONFIG_PINCTRL_SH_PFC)   += core.o pinctrl.o
+obj-$(CONFIG_PINCTRL_SH_PFC_GPIO)      += gpio.o
 obj-$(CONFIG_PINCTRL_PFC_EMEV2)        += pfc-emev2.o
 obj-$(CONFIG_PINCTRL_PFC_R8A73A4)      += pfc-r8a73a4.o
 obj-$(CONFIG_PINCTRL_PFC_R8A7740)      += pfc-r8a7740.o
index 181ea98a63b7ab02d367581b4027997ea0f6a574..dc3609f0c60b6b50d10c76bba38b4f73952d5c1e 100644 (file)
@@ -1,5 +1,7 @@
 /*
- * SuperH Pin Function Controller support.
+ * Pin Control and GPIO driver for SuperH Pin Function Controller.
+ *
+ * Authors: Magnus Damm, Paul Mundt, Laurent Pinchart
  *
  * Copyright (C) 2008 Magnus Damm
  * Copyright (C) 2009 - 2012 Paul Mundt
@@ -17,7 +19,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/pinctrl/machine.h>
@@ -503,7 +505,6 @@ static const struct of_device_id sh_pfc_of_table[] = {
 #endif
        { },
 };
-MODULE_DEVICE_TABLE(of, sh_pfc_of_table);
 #endif
 
 static int sh_pfc_probe(struct platform_device *pdev)
@@ -518,7 +519,7 @@ static int sh_pfc_probe(struct platform_device *pdev)
 
 #ifdef CONFIG_OF
        if (np)
-               info = of_match_device(sh_pfc_of_table, &pdev->dev)->data;
+               info = of_device_get_match_data(&pdev->dev);
        else
 #endif
                info = platid ? (const void *)platid->driver_data : NULL;
@@ -558,7 +559,7 @@ static int sh_pfc_probe(struct platform_device *pdev)
        if (unlikely(ret != 0))
                return ret;
 
-#ifdef CONFIG_GPIO_SH_PFC
+#ifdef CONFIG_PINCTRL_SH_PFC_GPIO
        /*
         * Then the GPIO chip
         */
@@ -584,7 +585,7 @@ static int sh_pfc_remove(struct platform_device *pdev)
 {
        struct sh_pfc *pfc = platform_get_drvdata(pdev);
 
-#ifdef CONFIG_GPIO_SH_PFC
+#ifdef CONFIG_PINCTRL_SH_PFC_GPIO
        sh_pfc_unregister_gpiochip(pfc);
 #endif
        sh_pfc_unregister_pinctrl(pfc);
@@ -632,7 +633,6 @@ static const struct platform_device_id sh_pfc_id_table[] = {
        { "sh-pfc", 0 },
        { },
 };
-MODULE_DEVICE_TABLE(platform, sh_pfc_id_table);
 
 static struct platform_driver sh_pfc_driver = {
        .probe          = sh_pfc_probe,
@@ -649,13 +649,3 @@ static int __init sh_pfc_init(void)
        return platform_driver_register(&sh_pfc_driver);
 }
 postcore_initcall(sh_pfc_init);
-
-static void __exit sh_pfc_exit(void)
-{
-       platform_driver_unregister(&sh_pfc_driver);
-}
-module_exit(sh_pfc_exit);
-
-MODULE_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart");
-MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller");
-MODULE_LICENSE("GPL v2");
index ad09a670c2ffbe70bd3505e75609b8c9b02fe9de..411d0887ba19bae6e48ff0eb04cae9bfa5537327 100644 (file)
@@ -561,82 +561,82 @@ static const u16 pinmux_data[] = {
        PINMUX_SINGLE(AVS2),
 
        /* IPSR0 */
-       PINMUX_IPSR_DATA(IP0_1_0,       PRESETOUT),
-       PINMUX_IPSR_DATA(IP0_1_0,       PWM1),
+       PINMUX_IPSR_GPSR(IP0_1_0,       PRESETOUT),
+       PINMUX_IPSR_GPSR(IP0_1_0,       PWM1),
 
-       PINMUX_IPSR_DATA(IP0_4_2,       AUDATA0),
-       PINMUX_IPSR_DATA(IP0_4_2,       ARM_TRACEDATA_0),
+       PINMUX_IPSR_GPSR(IP0_4_2,       AUDATA0),
+       PINMUX_IPSR_GPSR(IP0_4_2,       ARM_TRACEDATA_0),
        PINMUX_IPSR_MSEL(IP0_4_2,       GPSCLK_C,       SEL_GPS_C),
-       PINMUX_IPSR_DATA(IP0_4_2,       USB_OVC0),
-       PINMUX_IPSR_DATA(IP0_4_2,       TX2_E),
+       PINMUX_IPSR_GPSR(IP0_4_2,       USB_OVC0),
+       PINMUX_IPSR_GPSR(IP0_4_2,       TX2_E),
        PINMUX_IPSR_MSEL(IP0_4_2,       SDA2_B,         SEL_I2C2_B),
 
-       PINMUX_IPSR_DATA(IP0_7_5,       AUDATA1),
-       PINMUX_IPSR_DATA(IP0_7_5,       ARM_TRACEDATA_1),
+       PINMUX_IPSR_GPSR(IP0_7_5,       AUDATA1),
+       PINMUX_IPSR_GPSR(IP0_7_5,       ARM_TRACEDATA_1),
        PINMUX_IPSR_MSEL(IP0_7_5,       GPSIN_C,        SEL_GPS_C),
-       PINMUX_IPSR_DATA(IP0_7_5,       USB_OVC1),
+       PINMUX_IPSR_GPSR(IP0_7_5,       USB_OVC1),
        PINMUX_IPSR_MSEL(IP0_7_5,       RX2_E,          SEL_SCIF2_E),
        PINMUX_IPSR_MSEL(IP0_7_5,       SCL2_B,         SEL_I2C2_B),
 
        PINMUX_IPSR_MSEL(IP0_11_8,      SD1_DAT2_A,     SEL_SD1_A),
-       PINMUX_IPSR_DATA(IP0_11_8,      MMC_D2),
-       PINMUX_IPSR_DATA(IP0_11_8,      BS),
-       PINMUX_IPSR_DATA(IP0_11_8,      ATADIR0_A),
-       PINMUX_IPSR_DATA(IP0_11_8,      SDSELF_A),
-       PINMUX_IPSR_DATA(IP0_11_8,      PWM4_B),
+       PINMUX_IPSR_GPSR(IP0_11_8,      MMC_D2),
+       PINMUX_IPSR_GPSR(IP0_11_8,      BS),
+       PINMUX_IPSR_GPSR(IP0_11_8,      ATADIR0_A),
+       PINMUX_IPSR_GPSR(IP0_11_8,      SDSELF_A),
+       PINMUX_IPSR_GPSR(IP0_11_8,      PWM4_B),
 
        PINMUX_IPSR_MSEL(IP0_14_12,     SD1_DAT3_A,     SEL_SD1_A),
-       PINMUX_IPSR_DATA(IP0_14_12,     MMC_D3),
-       PINMUX_IPSR_DATA(IP0_14_12,     A0),
-       PINMUX_IPSR_DATA(IP0_14_12,     ATAG0_A),
+       PINMUX_IPSR_GPSR(IP0_14_12,     MMC_D3),
+       PINMUX_IPSR_GPSR(IP0_14_12,     A0),
+       PINMUX_IPSR_GPSR(IP0_14_12,     ATAG0_A),
        PINMUX_IPSR_MSEL(IP0_14_12,     REMOCON_B,      SEL_REMOCON_B),
 
-       PINMUX_IPSR_DATA(IP0_15,        A4),
-       PINMUX_IPSR_DATA(IP0_16,        A5),
-       PINMUX_IPSR_DATA(IP0_17,        A6),
-       PINMUX_IPSR_DATA(IP0_18,        A7),
-       PINMUX_IPSR_DATA(IP0_19,        A8),
-       PINMUX_IPSR_DATA(IP0_20,        A9),
-       PINMUX_IPSR_DATA(IP0_21,        A10),
-       PINMUX_IPSR_DATA(IP0_22,        A11),
-       PINMUX_IPSR_DATA(IP0_23,        A12),
-       PINMUX_IPSR_DATA(IP0_24,        A13),
-       PINMUX_IPSR_DATA(IP0_25,        A14),
-       PINMUX_IPSR_DATA(IP0_26,        A15),
-       PINMUX_IPSR_DATA(IP0_27,        A16),
-       PINMUX_IPSR_DATA(IP0_28,        A17),
-       PINMUX_IPSR_DATA(IP0_29,        A18),
-       PINMUX_IPSR_DATA(IP0_30,        A19),
+       PINMUX_IPSR_GPSR(IP0_15,        A4),
+       PINMUX_IPSR_GPSR(IP0_16,        A5),
+       PINMUX_IPSR_GPSR(IP0_17,        A6),
+       PINMUX_IPSR_GPSR(IP0_18,        A7),
+       PINMUX_IPSR_GPSR(IP0_19,        A8),
+       PINMUX_IPSR_GPSR(IP0_20,        A9),
+       PINMUX_IPSR_GPSR(IP0_21,        A10),
+       PINMUX_IPSR_GPSR(IP0_22,        A11),
+       PINMUX_IPSR_GPSR(IP0_23,        A12),
+       PINMUX_IPSR_GPSR(IP0_24,        A13),
+       PINMUX_IPSR_GPSR(IP0_25,        A14),
+       PINMUX_IPSR_GPSR(IP0_26,        A15),
+       PINMUX_IPSR_GPSR(IP0_27,        A16),
+       PINMUX_IPSR_GPSR(IP0_28,        A17),
+       PINMUX_IPSR_GPSR(IP0_29,        A18),
+       PINMUX_IPSR_GPSR(IP0_30,        A19),
 
        /* IPSR1 */
-       PINMUX_IPSR_DATA(IP1_0,         A20),
+       PINMUX_IPSR_GPSR(IP1_0,         A20),
        PINMUX_IPSR_MSEL(IP1_0,         HSPI_CS1_B,     SEL_HSPI1_B),
 
-       PINMUX_IPSR_DATA(IP1_1,         A21),
+       PINMUX_IPSR_GPSR(IP1_1,         A21),
        PINMUX_IPSR_MSEL(IP1_1,         HSPI_CLK1_B,    SEL_HSPI1_B),
 
-       PINMUX_IPSR_DATA(IP1_4_2,       A22),
+       PINMUX_IPSR_GPSR(IP1_4_2,       A22),
        PINMUX_IPSR_MSEL(IP1_4_2,       HRTS0_B,        SEL_HSCIF0_B),
        PINMUX_IPSR_MSEL(IP1_4_2,       RX2_B,          SEL_SCIF2_B),
        PINMUX_IPSR_MSEL(IP1_4_2,       DREQ2_A,        SEL_DREQ2_A),
 
-       PINMUX_IPSR_DATA(IP1_7_5,       A23),
-       PINMUX_IPSR_DATA(IP1_7_5,       HTX0_B),
-       PINMUX_IPSR_DATA(IP1_7_5,       TX2_B),
-       PINMUX_IPSR_DATA(IP1_7_5,       DACK2_A),
+       PINMUX_IPSR_GPSR(IP1_7_5,       A23),
+       PINMUX_IPSR_GPSR(IP1_7_5,       HTX0_B),
+       PINMUX_IPSR_GPSR(IP1_7_5,       TX2_B),
+       PINMUX_IPSR_GPSR(IP1_7_5,       DACK2_A),
        PINMUX_IPSR_MSEL(IP1_7_5,       TS_SDEN0_A,     SEL_TSIF0_A),
 
        PINMUX_IPSR_MSEL(IP1_10_8,      SD1_CD_A,       SEL_SD1_A),
-       PINMUX_IPSR_DATA(IP1_10_8,      MMC_D6),
-       PINMUX_IPSR_DATA(IP1_10_8,      A24),
+       PINMUX_IPSR_GPSR(IP1_10_8,      MMC_D6),
+       PINMUX_IPSR_GPSR(IP1_10_8,      A24),
        PINMUX_IPSR_MSEL(IP1_10_8,      DREQ1_A,        SEL_DREQ1_A),
        PINMUX_IPSR_MSEL(IP1_10_8,      HRX0_B,         SEL_HSCIF0_B),
        PINMUX_IPSR_MSEL(IP1_10_8,      TS_SPSYNC0_A,   SEL_TSIF0_A),
 
        PINMUX_IPSR_MSEL(IP1_14_11,     SD1_WP_A,       SEL_SD1_A),
-       PINMUX_IPSR_DATA(IP1_14_11,     MMC_D7),
-       PINMUX_IPSR_DATA(IP1_14_11,     A25),
-       PINMUX_IPSR_DATA(IP1_14_11,     DACK1_A),
+       PINMUX_IPSR_GPSR(IP1_14_11,     MMC_D7),
+       PINMUX_IPSR_GPSR(IP1_14_11,     A25),
+       PINMUX_IPSR_GPSR(IP1_14_11,     DACK1_A),
        PINMUX_IPSR_MSEL(IP1_14_11,     HCTS0_B,        SEL_HSCIF0_B),
        PINMUX_IPSR_MSEL(IP1_14_11,     RX3_C,          SEL_SCIF3_C),
        PINMUX_IPSR_MSEL(IP1_14_11,     TS_SDAT0_A,     SEL_TSIF0_A),
@@ -654,54 +654,54 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_NOGM(IP1_20_18,     SDA2_A,         SEL_I2C2_A),
        PINMUX_IPSR_NOGM(IP1_20_18,     SCK2_B,         SEL_SCIF2_B),
 
-       PINMUX_IPSR_DATA(IP1_23_21,     MMC_D5),
-       PINMUX_IPSR_DATA(IP1_23_21,     ATADIR0_B),
-       PINMUX_IPSR_DATA(IP1_23_21,     RD_WR),
+       PINMUX_IPSR_GPSR(IP1_23_21,     MMC_D5),
+       PINMUX_IPSR_GPSR(IP1_23_21,     ATADIR0_B),
+       PINMUX_IPSR_GPSR(IP1_23_21,     RD_WR),
 
-       PINMUX_IPSR_DATA(IP1_24,        WE1),
-       PINMUX_IPSR_DATA(IP1_24,        ATAWR0_B),
+       PINMUX_IPSR_GPSR(IP1_24,        WE1),
+       PINMUX_IPSR_GPSR(IP1_24,        ATAWR0_B),
 
        PINMUX_IPSR_MSEL(IP1_27_25,     SSI_WS1_B,      SEL_SSI1_B),
-       PINMUX_IPSR_DATA(IP1_27_25,     EX_CS0),
+       PINMUX_IPSR_GPSR(IP1_27_25,     EX_CS0),
        PINMUX_IPSR_MSEL(IP1_27_25,     SCL2_A,         SEL_I2C2_A),
-       PINMUX_IPSR_DATA(IP1_27_25,     TX3_C),
+       PINMUX_IPSR_GPSR(IP1_27_25,     TX3_C),
        PINMUX_IPSR_MSEL(IP1_27_25,     TS_SCK0_A,      SEL_TSIF0_A),
 
-       PINMUX_IPSR_DATA(IP1_29_28,     EX_CS1),
-       PINMUX_IPSR_DATA(IP1_29_28,     MMC_D4),
+       PINMUX_IPSR_GPSR(IP1_29_28,     EX_CS1),
+       PINMUX_IPSR_GPSR(IP1_29_28,     MMC_D4),
 
        /* IPSR2 */
-       PINMUX_IPSR_DATA(IP2_2_0,       SD1_CLK_A),
-       PINMUX_IPSR_DATA(IP2_2_0,       MMC_CLK),
-       PINMUX_IPSR_DATA(IP2_2_0,       ATACS00),
-       PINMUX_IPSR_DATA(IP2_2_0,       EX_CS2),
+       PINMUX_IPSR_GPSR(IP2_2_0,       SD1_CLK_A),
+       PINMUX_IPSR_GPSR(IP2_2_0,       MMC_CLK),
+       PINMUX_IPSR_GPSR(IP2_2_0,       ATACS00),
+       PINMUX_IPSR_GPSR(IP2_2_0,       EX_CS2),
 
        PINMUX_IPSR_MSEL(IP2_5_3,       SD1_CMD_A,      SEL_SD1_A),
-       PINMUX_IPSR_DATA(IP2_5_3,       MMC_CMD),
-       PINMUX_IPSR_DATA(IP2_5_3,       ATACS10),
-       PINMUX_IPSR_DATA(IP2_5_3,       EX_CS3),
+       PINMUX_IPSR_GPSR(IP2_5_3,       MMC_CMD),
+       PINMUX_IPSR_GPSR(IP2_5_3,       ATACS10),
+       PINMUX_IPSR_GPSR(IP2_5_3,       EX_CS3),
 
        PINMUX_IPSR_MSEL(IP2_8_6,       SD1_DAT0_A,     SEL_SD1_A),
-       PINMUX_IPSR_DATA(IP2_8_6,       MMC_D0),
-       PINMUX_IPSR_DATA(IP2_8_6,       ATARD0),
-       PINMUX_IPSR_DATA(IP2_8_6,       EX_CS4),
+       PINMUX_IPSR_GPSR(IP2_8_6,       MMC_D0),
+       PINMUX_IPSR_GPSR(IP2_8_6,       ATARD0),
+       PINMUX_IPSR_GPSR(IP2_8_6,       EX_CS4),
        PINMUX_IPSR_MSEL(IP2_8_6,       EX_WAIT1_A,     SEL_WAIT1_A),
 
        PINMUX_IPSR_MSEL(IP2_11_9,      SD1_DAT1_A,     SEL_SD1_A),
-       PINMUX_IPSR_DATA(IP2_11_9,      MMC_D1),
-       PINMUX_IPSR_DATA(IP2_11_9,      ATAWR0_A),
-       PINMUX_IPSR_DATA(IP2_11_9,      EX_CS5),
+       PINMUX_IPSR_GPSR(IP2_11_9,      MMC_D1),
+       PINMUX_IPSR_GPSR(IP2_11_9,      ATAWR0_A),
+       PINMUX_IPSR_GPSR(IP2_11_9,      EX_CS5),
        PINMUX_IPSR_MSEL(IP2_11_9,      EX_WAIT2_A,     SEL_WAIT2_A),
 
        PINMUX_IPSR_MSEL(IP2_13_12,     DREQ0_A,        SEL_DREQ0_A),
        PINMUX_IPSR_MSEL(IP2_13_12,     RX3_A,          SEL_SCIF3_A),
 
-       PINMUX_IPSR_DATA(IP2_16_14,     DACK0),
-       PINMUX_IPSR_DATA(IP2_16_14,     TX3_A),
-       PINMUX_IPSR_DATA(IP2_16_14,     DRACK0),
+       PINMUX_IPSR_GPSR(IP2_16_14,     DACK0),
+       PINMUX_IPSR_GPSR(IP2_16_14,     TX3_A),
+       PINMUX_IPSR_GPSR(IP2_16_14,     DRACK0),
 
-       PINMUX_IPSR_DATA(IP2_17,        EX_WAIT0),
-       PINMUX_IPSR_DATA(IP2_17,        PWM0_C),
+       PINMUX_IPSR_GPSR(IP2_17,        EX_WAIT0),
+       PINMUX_IPSR_GPSR(IP2_17,        PWM0_C),
 
        PINMUX_IPSR_NOGP(IP2_18,        D0),
        PINMUX_IPSR_NOGP(IP2_19,        D1),
@@ -716,33 +716,33 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_NOGP(IP2_28,        D10),
        PINMUX_IPSR_NOGP(IP2_29,        D11),
 
-       PINMUX_IPSR_DATA(IP2_30,        RD_WR_B),
-       PINMUX_IPSR_DATA(IP2_30,        IRQ0),
+       PINMUX_IPSR_GPSR(IP2_30,        RD_WR_B),
+       PINMUX_IPSR_GPSR(IP2_30,        IRQ0),
 
-       PINMUX_IPSR_DATA(IP2_31,        MLB_CLK),
+       PINMUX_IPSR_GPSR(IP2_31,        MLB_CLK),
        PINMUX_IPSR_MSEL(IP2_31,        IRQ1_A,         SEL_IRQ1_A),
 
        /* IPSR3 */
-       PINMUX_IPSR_DATA(IP3_1_0,       MLB_SIG),
+       PINMUX_IPSR_GPSR(IP3_1_0,       MLB_SIG),
        PINMUX_IPSR_MSEL(IP3_1_0,       RX5_B,          SEL_SCIF5_B),
        PINMUX_IPSR_MSEL(IP3_1_0,       SDA3_A,         SEL_I2C3_A),
        PINMUX_IPSR_MSEL(IP3_1_0,       IRQ2_A,         SEL_IRQ2_A),
 
-       PINMUX_IPSR_DATA(IP3_4_2,       MLB_DAT),
-       PINMUX_IPSR_DATA(IP3_4_2,       TX5_B),
+       PINMUX_IPSR_GPSR(IP3_4_2,       MLB_DAT),
+       PINMUX_IPSR_GPSR(IP3_4_2,       TX5_B),
        PINMUX_IPSR_MSEL(IP3_4_2,       SCL3_A,         SEL_I2C3_A),
        PINMUX_IPSR_MSEL(IP3_4_2,       IRQ3_A,         SEL_IRQ3_A),
-       PINMUX_IPSR_DATA(IP3_4_2,       SDSELF_B),
+       PINMUX_IPSR_GPSR(IP3_4_2,       SDSELF_B),
 
        PINMUX_IPSR_MSEL(IP3_7_5,       SD1_CMD_B,      SEL_SD1_B),
-       PINMUX_IPSR_DATA(IP3_7_5,       SCIF_CLK),
-       PINMUX_IPSR_DATA(IP3_7_5,       AUDIO_CLKOUT_B),
+       PINMUX_IPSR_GPSR(IP3_7_5,       SCIF_CLK),
+       PINMUX_IPSR_GPSR(IP3_7_5,       AUDIO_CLKOUT_B),
        PINMUX_IPSR_MSEL(IP3_7_5,       CAN_CLK_B,      SEL_CANCLK_B),
        PINMUX_IPSR_MSEL(IP3_7_5,       SDA3_B,         SEL_I2C3_B),
 
-       PINMUX_IPSR_DATA(IP3_9_8,       SD1_CLK_B),
-       PINMUX_IPSR_DATA(IP3_9_8,       HTX0_A),
-       PINMUX_IPSR_DATA(IP3_9_8,       TX0_A),
+       PINMUX_IPSR_GPSR(IP3_9_8,       SD1_CLK_B),
+       PINMUX_IPSR_GPSR(IP3_9_8,       HTX0_A),
+       PINMUX_IPSR_GPSR(IP3_9_8,       TX0_A),
 
        PINMUX_IPSR_MSEL(IP3_12_10,     SD1_DAT0_B,     SEL_SD1_B),
        PINMUX_IPSR_MSEL(IP3_12_10,     HRX0_A,         SEL_HSCIF0_A),
@@ -750,513 +750,513 @@ static const u16 pinmux_data[] = {
 
        PINMUX_IPSR_MSEL(IP3_15_13,     SD1_DAT1_B,     SEL_SD1_B),
        PINMUX_IPSR_MSEL(IP3_15_13,     HSCK0,          SEL_HSCIF0_A),
-       PINMUX_IPSR_DATA(IP3_15_13,     SCK0),
+       PINMUX_IPSR_GPSR(IP3_15_13,     SCK0),
        PINMUX_IPSR_MSEL(IP3_15_13,     SCL3_B,         SEL_I2C3_B),
 
        PINMUX_IPSR_MSEL(IP3_18_16,     SD1_DAT2_B,     SEL_SD1_B),
        PINMUX_IPSR_MSEL(IP3_18_16,     HCTS0_A,        SEL_HSCIF0_A),
-       PINMUX_IPSR_DATA(IP3_18_16,     CTS0),
+       PINMUX_IPSR_GPSR(IP3_18_16,     CTS0),
 
        PINMUX_IPSR_MSEL(IP3_20_19,     SD1_DAT3_B,     SEL_SD1_B),
        PINMUX_IPSR_MSEL(IP3_20_19,     HRTS0_A,        SEL_HSCIF0_A),
-       PINMUX_IPSR_DATA(IP3_20_19,     RTS0),
+       PINMUX_IPSR_GPSR(IP3_20_19,     RTS0),
 
-       PINMUX_IPSR_DATA(IP3_23_21,     SSI_SCK4),
-       PINMUX_IPSR_DATA(IP3_23_21,     DU0_DR0),
-       PINMUX_IPSR_DATA(IP3_23_21,     LCDOUT0),
-       PINMUX_IPSR_DATA(IP3_23_21,     AUDATA2),
-       PINMUX_IPSR_DATA(IP3_23_21,     ARM_TRACEDATA_2),
+       PINMUX_IPSR_GPSR(IP3_23_21,     SSI_SCK4),
+       PINMUX_IPSR_GPSR(IP3_23_21,     DU0_DR0),
+       PINMUX_IPSR_GPSR(IP3_23_21,     LCDOUT0),
+       PINMUX_IPSR_GPSR(IP3_23_21,     AUDATA2),
+       PINMUX_IPSR_GPSR(IP3_23_21,     ARM_TRACEDATA_2),
        PINMUX_IPSR_MSEL(IP3_23_21,     SDA3_C,         SEL_I2C3_C),
-       PINMUX_IPSR_DATA(IP3_23_21,     ADICHS1),
+       PINMUX_IPSR_GPSR(IP3_23_21,     ADICHS1),
        PINMUX_IPSR_MSEL(IP3_23_21,     TS_SDEN0_B,     SEL_TSIF0_B),
 
-       PINMUX_IPSR_DATA(IP3_26_24,     SSI_WS4),
-       PINMUX_IPSR_DATA(IP3_26_24,     DU0_DR1),
-       PINMUX_IPSR_DATA(IP3_26_24,     LCDOUT1),
-       PINMUX_IPSR_DATA(IP3_26_24,     AUDATA3),
-       PINMUX_IPSR_DATA(IP3_26_24,     ARM_TRACEDATA_3),
+       PINMUX_IPSR_GPSR(IP3_26_24,     SSI_WS4),
+       PINMUX_IPSR_GPSR(IP3_26_24,     DU0_DR1),
+       PINMUX_IPSR_GPSR(IP3_26_24,     LCDOUT1),
+       PINMUX_IPSR_GPSR(IP3_26_24,     AUDATA3),
+       PINMUX_IPSR_GPSR(IP3_26_24,     ARM_TRACEDATA_3),
        PINMUX_IPSR_MSEL(IP3_26_24,     SCL3_C,         SEL_I2C3_C),
-       PINMUX_IPSR_DATA(IP3_26_24,     ADICHS2),
+       PINMUX_IPSR_GPSR(IP3_26_24,     ADICHS2),
        PINMUX_IPSR_MSEL(IP3_26_24,     TS_SPSYNC0_B,   SEL_TSIF0_B),
 
-       PINMUX_IPSR_DATA(IP3_27,        DU0_DR2),
-       PINMUX_IPSR_DATA(IP3_27,        LCDOUT2),
+       PINMUX_IPSR_GPSR(IP3_27,        DU0_DR2),
+       PINMUX_IPSR_GPSR(IP3_27,        LCDOUT2),
 
-       PINMUX_IPSR_DATA(IP3_28,        DU0_DR3),
-       PINMUX_IPSR_DATA(IP3_28,        LCDOUT3),
+       PINMUX_IPSR_GPSR(IP3_28,        DU0_DR3),
+       PINMUX_IPSR_GPSR(IP3_28,        LCDOUT3),
 
-       PINMUX_IPSR_DATA(IP3_29,        DU0_DR4),
-       PINMUX_IPSR_DATA(IP3_29,        LCDOUT4),
+       PINMUX_IPSR_GPSR(IP3_29,        DU0_DR4),
+       PINMUX_IPSR_GPSR(IP3_29,        LCDOUT4),
 
-       PINMUX_IPSR_DATA(IP3_30,        DU0_DR5),
-       PINMUX_IPSR_DATA(IP3_30,        LCDOUT5),
+       PINMUX_IPSR_GPSR(IP3_30,        DU0_DR5),
+       PINMUX_IPSR_GPSR(IP3_30,        LCDOUT5),
 
-       PINMUX_IPSR_DATA(IP3_31,        DU0_DR6),
-       PINMUX_IPSR_DATA(IP3_31,        LCDOUT6),
+       PINMUX_IPSR_GPSR(IP3_31,        DU0_DR6),
+       PINMUX_IPSR_GPSR(IP3_31,        LCDOUT6),
 
        /* IPSR4 */
-       PINMUX_IPSR_DATA(IP4_0,         DU0_DR7),
-       PINMUX_IPSR_DATA(IP4_0,         LCDOUT7),
-
-       PINMUX_IPSR_DATA(IP4_3_1,       DU0_DG0),
-       PINMUX_IPSR_DATA(IP4_3_1,       LCDOUT8),
-       PINMUX_IPSR_DATA(IP4_3_1,       AUDATA4),
-       PINMUX_IPSR_DATA(IP4_3_1,       ARM_TRACEDATA_4),
-       PINMUX_IPSR_DATA(IP4_3_1,       TX1_D),
-       PINMUX_IPSR_DATA(IP4_3_1,       CAN0_TX_A),
-       PINMUX_IPSR_DATA(IP4_3_1,       ADICHS0),
-
-       PINMUX_IPSR_DATA(IP4_6_4,       DU0_DG1),
-       PINMUX_IPSR_DATA(IP4_6_4,       LCDOUT9),
-       PINMUX_IPSR_DATA(IP4_6_4,       AUDATA5),
-       PINMUX_IPSR_DATA(IP4_6_4,       ARM_TRACEDATA_5),
+       PINMUX_IPSR_GPSR(IP4_0,         DU0_DR7),
+       PINMUX_IPSR_GPSR(IP4_0,         LCDOUT7),
+
+       PINMUX_IPSR_GPSR(IP4_3_1,       DU0_DG0),
+       PINMUX_IPSR_GPSR(IP4_3_1,       LCDOUT8),
+       PINMUX_IPSR_GPSR(IP4_3_1,       AUDATA4),
+       PINMUX_IPSR_GPSR(IP4_3_1,       ARM_TRACEDATA_4),
+       PINMUX_IPSR_GPSR(IP4_3_1,       TX1_D),
+       PINMUX_IPSR_GPSR(IP4_3_1,       CAN0_TX_A),
+       PINMUX_IPSR_GPSR(IP4_3_1,       ADICHS0),
+
+       PINMUX_IPSR_GPSR(IP4_6_4,       DU0_DG1),
+       PINMUX_IPSR_GPSR(IP4_6_4,       LCDOUT9),
+       PINMUX_IPSR_GPSR(IP4_6_4,       AUDATA5),
+       PINMUX_IPSR_GPSR(IP4_6_4,       ARM_TRACEDATA_5),
        PINMUX_IPSR_MSEL(IP4_6_4,       RX1_D,          SEL_SCIF1_D),
        PINMUX_IPSR_MSEL(IP4_6_4,       CAN0_RX_A,      SEL_CAN0_A),
-       PINMUX_IPSR_DATA(IP4_6_4,       ADIDATA),
+       PINMUX_IPSR_GPSR(IP4_6_4,       ADIDATA),
 
-       PINMUX_IPSR_DATA(IP4_7,         DU0_DG2),
-       PINMUX_IPSR_DATA(IP4_7,         LCDOUT10),
+       PINMUX_IPSR_GPSR(IP4_7,         DU0_DG2),
+       PINMUX_IPSR_GPSR(IP4_7,         LCDOUT10),
 
-       PINMUX_IPSR_DATA(IP4_8,         DU0_DG3),
-       PINMUX_IPSR_DATA(IP4_8,         LCDOUT11),
+       PINMUX_IPSR_GPSR(IP4_8,         DU0_DG3),
+       PINMUX_IPSR_GPSR(IP4_8,         LCDOUT11),
 
-       PINMUX_IPSR_DATA(IP4_10_9,      DU0_DG4),
-       PINMUX_IPSR_DATA(IP4_10_9,      LCDOUT12),
+       PINMUX_IPSR_GPSR(IP4_10_9,      DU0_DG4),
+       PINMUX_IPSR_GPSR(IP4_10_9,      LCDOUT12),
        PINMUX_IPSR_MSEL(IP4_10_9,      RX0_B,          SEL_SCIF0_B),
 
-       PINMUX_IPSR_DATA(IP4_12_11,     DU0_DG5),
-       PINMUX_IPSR_DATA(IP4_12_11,     LCDOUT13),
-       PINMUX_IPSR_DATA(IP4_12_11,     TX0_B),
+       PINMUX_IPSR_GPSR(IP4_12_11,     DU0_DG5),
+       PINMUX_IPSR_GPSR(IP4_12_11,     LCDOUT13),
+       PINMUX_IPSR_GPSR(IP4_12_11,     TX0_B),
 
-       PINMUX_IPSR_DATA(IP4_14_13,     DU0_DG6),
-       PINMUX_IPSR_DATA(IP4_14_13,     LCDOUT14),
+       PINMUX_IPSR_GPSR(IP4_14_13,     DU0_DG6),
+       PINMUX_IPSR_GPSR(IP4_14_13,     LCDOUT14),
        PINMUX_IPSR_MSEL(IP4_14_13,     RX4_A,          SEL_SCIF4_A),
 
-       PINMUX_IPSR_DATA(IP4_16_15,     DU0_DG7),
-       PINMUX_IPSR_DATA(IP4_16_15,     LCDOUT15),
-       PINMUX_IPSR_DATA(IP4_16_15,     TX4_A),
+       PINMUX_IPSR_GPSR(IP4_16_15,     DU0_DG7),
+       PINMUX_IPSR_GPSR(IP4_16_15,     LCDOUT15),
+       PINMUX_IPSR_GPSR(IP4_16_15,     TX4_A),
 
        PINMUX_IPSR_MSEL(IP4_20_17,     SSI_SCK2_B,     SEL_SSI2_B),
        PINMUX_DATA(VI0_R0_B_MARK,      FN_IP4_20_17,   FN_VI0_R0_B,    FN_SEL_VI0_B), /* see sel_vi0 */
        PINMUX_DATA(VI0_R0_D_MARK,      FN_IP4_20_17,   FN_VI0_R0_B,    FN_SEL_VI0_D), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP4_20_17,     DU0_DB0),
-       PINMUX_IPSR_DATA(IP4_20_17,     LCDOUT16),
-       PINMUX_IPSR_DATA(IP4_20_17,     AUDATA6),
-       PINMUX_IPSR_DATA(IP4_20_17,     ARM_TRACEDATA_6),
+       PINMUX_IPSR_GPSR(IP4_20_17,     DU0_DB0),
+       PINMUX_IPSR_GPSR(IP4_20_17,     LCDOUT16),
+       PINMUX_IPSR_GPSR(IP4_20_17,     AUDATA6),
+       PINMUX_IPSR_GPSR(IP4_20_17,     ARM_TRACEDATA_6),
        PINMUX_IPSR_MSEL(IP4_20_17,     GPSCLK_A,       SEL_GPS_A),
-       PINMUX_IPSR_DATA(IP4_20_17,     PWM0_A),
-       PINMUX_IPSR_DATA(IP4_20_17,     ADICLK),
+       PINMUX_IPSR_GPSR(IP4_20_17,     PWM0_A),
+       PINMUX_IPSR_GPSR(IP4_20_17,     ADICLK),
        PINMUX_IPSR_MSEL(IP4_20_17,     TS_SDAT0_B,     SEL_TSIF0_B),
 
-       PINMUX_IPSR_DATA(IP4_24_21,     AUDIO_CLKC),
+       PINMUX_IPSR_GPSR(IP4_24_21,     AUDIO_CLKC),
        PINMUX_DATA(VI0_R1_B_MARK,      FN_IP4_24_21,   FN_VI0_R1_B,    FN_SEL_VI0_B), /* see sel_vi0 */
        PINMUX_DATA(VI0_R1_D_MARK,      FN_IP4_24_21,   FN_VI0_R1_B,    FN_SEL_VI0_D), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP4_24_21,     DU0_DB1),
-       PINMUX_IPSR_DATA(IP4_24_21,     LCDOUT17),
-       PINMUX_IPSR_DATA(IP4_24_21,     AUDATA7),
-       PINMUX_IPSR_DATA(IP4_24_21,     ARM_TRACEDATA_7),
+       PINMUX_IPSR_GPSR(IP4_24_21,     DU0_DB1),
+       PINMUX_IPSR_GPSR(IP4_24_21,     LCDOUT17),
+       PINMUX_IPSR_GPSR(IP4_24_21,     AUDATA7),
+       PINMUX_IPSR_GPSR(IP4_24_21,     ARM_TRACEDATA_7),
        PINMUX_IPSR_MSEL(IP4_24_21,     GPSIN_A,        SEL_GPS_A),
-       PINMUX_IPSR_DATA(IP4_24_21,     ADICS_SAMP),
+       PINMUX_IPSR_GPSR(IP4_24_21,     ADICS_SAMP),
        PINMUX_IPSR_MSEL(IP4_24_21,     TS_SCK0_B,      SEL_TSIF0_B),
 
        PINMUX_DATA(VI0_R2_B_MARK,      FN_IP4_26_25,   FN_VI0_R2_B,    FN_SEL_VI0_B), /* see sel_vi0 */
        PINMUX_DATA(VI0_R2_D_MARK,      FN_IP4_26_25,   FN_VI0_R2_B,    FN_SEL_VI0_D), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP4_26_25,     DU0_DB2),
-       PINMUX_IPSR_DATA(IP4_26_25,     LCDOUT18),
+       PINMUX_IPSR_GPSR(IP4_26_25,     DU0_DB2),
+       PINMUX_IPSR_GPSR(IP4_26_25,     LCDOUT18),
 
        PINMUX_IPSR_MSEL(IP4_28_27,     VI0_R3_B,       SEL_VI0_B),
-       PINMUX_IPSR_DATA(IP4_28_27,     DU0_DB3),
-       PINMUX_IPSR_DATA(IP4_28_27,     LCDOUT19),
+       PINMUX_IPSR_GPSR(IP4_28_27,     DU0_DB3),
+       PINMUX_IPSR_GPSR(IP4_28_27,     LCDOUT19),
 
        PINMUX_DATA(VI0_R4_B_MARK,      FN_IP4_30_29,   FN_VI0_R4_B,    FN_SEL_VI0_B), /* see sel_vi0 */
        PINMUX_DATA(VI0_R4_D_MARK,      FN_IP4_30_29,   FN_VI0_R4_B,    FN_SEL_VI0_D), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP4_30_29,     DU0_DB4),
-       PINMUX_IPSR_DATA(IP4_30_29,     LCDOUT20),
+       PINMUX_IPSR_GPSR(IP4_30_29,     DU0_DB4),
+       PINMUX_IPSR_GPSR(IP4_30_29,     LCDOUT20),
 
        /* IPSR5 */
        PINMUX_DATA(VI0_R5_B_MARK,      FN_IP5_1_0,     FN_VI0_R5_B,    FN_SEL_VI0_B), /* see sel_vi0 */
        PINMUX_DATA(VI0_R5_D_MARK,      FN_IP5_1_0,     FN_VI0_R5_B,    FN_SEL_VI0_D), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP5_1_0,       DU0_DB5),
-       PINMUX_IPSR_DATA(IP5_1_0,       LCDOUT21),
+       PINMUX_IPSR_GPSR(IP5_1_0,       DU0_DB5),
+       PINMUX_IPSR_GPSR(IP5_1_0,       LCDOUT21),
 
        PINMUX_IPSR_MSEL(IP5_3_2,       VI1_DATA10_B,   SEL_VI1_B),
-       PINMUX_IPSR_DATA(IP5_3_2,       DU0_DB6),
-       PINMUX_IPSR_DATA(IP5_3_2,       LCDOUT22),
+       PINMUX_IPSR_GPSR(IP5_3_2,       DU0_DB6),
+       PINMUX_IPSR_GPSR(IP5_3_2,       LCDOUT22),
 
        PINMUX_IPSR_MSEL(IP5_5_4,       VI1_DATA11_B,   SEL_VI1_B),
-       PINMUX_IPSR_DATA(IP5_5_4,       DU0_DB7),
-       PINMUX_IPSR_DATA(IP5_5_4,       LCDOUT23),
+       PINMUX_IPSR_GPSR(IP5_5_4,       DU0_DB7),
+       PINMUX_IPSR_GPSR(IP5_5_4,       LCDOUT23),
 
-       PINMUX_IPSR_DATA(IP5_6,         DU0_DOTCLKIN),
-       PINMUX_IPSR_DATA(IP5_6,         QSTVA_QVS),
+       PINMUX_IPSR_GPSR(IP5_6,         DU0_DOTCLKIN),
+       PINMUX_IPSR_GPSR(IP5_6,         QSTVA_QVS),
 
-       PINMUX_IPSR_DATA(IP5_7,         DU0_DOTCLKO_UT0),
-       PINMUX_IPSR_DATA(IP5_7,         QCLK),
+       PINMUX_IPSR_GPSR(IP5_7,         DU0_DOTCLKO_UT0),
+       PINMUX_IPSR_GPSR(IP5_7,         QCLK),
 
-       PINMUX_IPSR_DATA(IP5_9_8,       DU0_DOTCLKO_UT1),
-       PINMUX_IPSR_DATA(IP5_9_8,       QSTVB_QVE),
-       PINMUX_IPSR_DATA(IP5_9_8,       AUDIO_CLKOUT_A),
+       PINMUX_IPSR_GPSR(IP5_9_8,       DU0_DOTCLKO_UT1),
+       PINMUX_IPSR_GPSR(IP5_9_8,       QSTVB_QVE),
+       PINMUX_IPSR_GPSR(IP5_9_8,       AUDIO_CLKOUT_A),
        PINMUX_IPSR_MSEL(IP5_9_8,       REMOCON_C,      SEL_REMOCON_C),
 
        PINMUX_IPSR_MSEL(IP5_11_10,     SSI_WS2_B,      SEL_SSI2_B),
-       PINMUX_IPSR_DATA(IP5_11_10,     DU0_EXHSYNC_DU0_HSYNC),
-       PINMUX_IPSR_DATA(IP5_11_10,     QSTH_QHS),
+       PINMUX_IPSR_GPSR(IP5_11_10,     DU0_EXHSYNC_DU0_HSYNC),
+       PINMUX_IPSR_GPSR(IP5_11_10,     QSTH_QHS),
 
-       PINMUX_IPSR_DATA(IP5_12,        DU0_EXVSYNC_DU0_VSYNC),
-       PINMUX_IPSR_DATA(IP5_12,        QSTB_QHE),
+       PINMUX_IPSR_GPSR(IP5_12,        DU0_EXVSYNC_DU0_VSYNC),
+       PINMUX_IPSR_GPSR(IP5_12,        QSTB_QHE),
 
-       PINMUX_IPSR_DATA(IP5_14_13,     DU0_EXODDF_DU0_ODDF_DISP_CDE),
-       PINMUX_IPSR_DATA(IP5_14_13,     QCPV_QDE),
+       PINMUX_IPSR_GPSR(IP5_14_13,     DU0_EXODDF_DU0_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP5_14_13,     QCPV_QDE),
        PINMUX_IPSR_MSEL(IP5_14_13,     FMCLK_D,        SEL_FM_D),
 
        PINMUX_IPSR_MSEL(IP5_17_15,     SSI_SCK1_A,     SEL_SSI1_A),
-       PINMUX_IPSR_DATA(IP5_17_15,     DU0_DISP),
-       PINMUX_IPSR_DATA(IP5_17_15,     QPOLA),
-       PINMUX_IPSR_DATA(IP5_17_15,     AUDCK),
-       PINMUX_IPSR_DATA(IP5_17_15,     ARM_TRACECLK),
-       PINMUX_IPSR_DATA(IP5_17_15,     BPFCLK_D),
+       PINMUX_IPSR_GPSR(IP5_17_15,     DU0_DISP),
+       PINMUX_IPSR_GPSR(IP5_17_15,     QPOLA),
+       PINMUX_IPSR_GPSR(IP5_17_15,     AUDCK),
+       PINMUX_IPSR_GPSR(IP5_17_15,     ARM_TRACECLK),
+       PINMUX_IPSR_GPSR(IP5_17_15,     BPFCLK_D),
 
        PINMUX_IPSR_MSEL(IP5_20_18,     SSI_WS1_A,      SEL_SSI1_A),
-       PINMUX_IPSR_DATA(IP5_20_18,     DU0_CDE),
-       PINMUX_IPSR_DATA(IP5_20_18,     QPOLB),
-       PINMUX_IPSR_DATA(IP5_20_18,     AUDSYNC),
-       PINMUX_IPSR_DATA(IP5_20_18,     ARM_TRACECTL),
+       PINMUX_IPSR_GPSR(IP5_20_18,     DU0_CDE),
+       PINMUX_IPSR_GPSR(IP5_20_18,     QPOLB),
+       PINMUX_IPSR_GPSR(IP5_20_18,     AUDSYNC),
+       PINMUX_IPSR_GPSR(IP5_20_18,     ARM_TRACECTL),
        PINMUX_IPSR_MSEL(IP5_20_18,     FMIN_D,         SEL_FM_D),
 
        PINMUX_IPSR_MSEL(IP5_22_21,     SD1_CD_B,       SEL_SD1_B),
-       PINMUX_IPSR_DATA(IP5_22_21,     SSI_SCK78),
+       PINMUX_IPSR_GPSR(IP5_22_21,     SSI_SCK78),
        PINMUX_IPSR_MSEL(IP5_22_21,     HSPI_RX0_B,     SEL_HSPI0_B),
-       PINMUX_IPSR_DATA(IP5_22_21,     TX1_B),
+       PINMUX_IPSR_GPSR(IP5_22_21,     TX1_B),
 
        PINMUX_IPSR_MSEL(IP5_25_23,     SD1_WP_B,       SEL_SD1_B),
-       PINMUX_IPSR_DATA(IP5_25_23,     SSI_WS78),
+       PINMUX_IPSR_GPSR(IP5_25_23,     SSI_WS78),
        PINMUX_IPSR_MSEL(IP5_25_23,     HSPI_CLK0_B,    SEL_HSPI0_B),
        PINMUX_IPSR_MSEL(IP5_25_23,     RX1_B,          SEL_SCIF1_B),
        PINMUX_IPSR_MSEL(IP5_25_23,     CAN_CLK_D,      SEL_CANCLK_D),
 
-       PINMUX_IPSR_DATA(IP5_28_26,     SSI_SDATA8),
+       PINMUX_IPSR_GPSR(IP5_28_26,     SSI_SDATA8),
        PINMUX_IPSR_MSEL(IP5_28_26,     SSI_SCK2_A,     SEL_SSI2_A),
        PINMUX_IPSR_MSEL(IP5_28_26,     HSPI_CS0_B,     SEL_HSPI0_B),
-       PINMUX_IPSR_DATA(IP5_28_26,     TX2_A),
-       PINMUX_IPSR_DATA(IP5_28_26,     CAN0_TX_B),
+       PINMUX_IPSR_GPSR(IP5_28_26,     TX2_A),
+       PINMUX_IPSR_GPSR(IP5_28_26,     CAN0_TX_B),
 
-       PINMUX_IPSR_DATA(IP5_30_29,     SSI_SDATA7),
-       PINMUX_IPSR_DATA(IP5_30_29,     HSPI_TX0_B),
+       PINMUX_IPSR_GPSR(IP5_30_29,     SSI_SDATA7),
+       PINMUX_IPSR_GPSR(IP5_30_29,     HSPI_TX0_B),
        PINMUX_IPSR_MSEL(IP5_30_29,     RX2_A,          SEL_SCIF2_A),
        PINMUX_IPSR_MSEL(IP5_30_29,     CAN0_RX_B,      SEL_CAN0_B),
 
        /* IPSR6 */
-       PINMUX_IPSR_DATA(IP6_1_0,       SSI_SCK6),
+       PINMUX_IPSR_GPSR(IP6_1_0,       SSI_SCK6),
        PINMUX_IPSR_MSEL(IP6_1_0,       HSPI_RX2_A,     SEL_HSPI2_A),
        PINMUX_IPSR_MSEL(IP6_1_0,       FMCLK_B,        SEL_FM_B),
-       PINMUX_IPSR_DATA(IP6_1_0,       CAN1_TX_B),
+       PINMUX_IPSR_GPSR(IP6_1_0,       CAN1_TX_B),
 
-       PINMUX_IPSR_DATA(IP6_4_2,       SSI_WS6),
+       PINMUX_IPSR_GPSR(IP6_4_2,       SSI_WS6),
        PINMUX_IPSR_MSEL(IP6_4_2,       HSPI_CLK2_A,    SEL_HSPI2_A),
-       PINMUX_IPSR_DATA(IP6_4_2,       BPFCLK_B),
+       PINMUX_IPSR_GPSR(IP6_4_2,       BPFCLK_B),
        PINMUX_IPSR_MSEL(IP6_4_2,       CAN1_RX_B,      SEL_CAN1_B),
 
-       PINMUX_IPSR_DATA(IP6_6_5,       SSI_SDATA6),
-       PINMUX_IPSR_DATA(IP6_6_5,       HSPI_TX2_A),
+       PINMUX_IPSR_GPSR(IP6_6_5,       SSI_SDATA6),
+       PINMUX_IPSR_GPSR(IP6_6_5,       HSPI_TX2_A),
        PINMUX_IPSR_MSEL(IP6_6_5,       FMIN_B,         SEL_FM_B),
 
-       PINMUX_IPSR_DATA(IP6_7,         SSI_SCK5),
+       PINMUX_IPSR_GPSR(IP6_7,         SSI_SCK5),
        PINMUX_IPSR_MSEL(IP6_7,         RX4_C,          SEL_SCIF4_C),
 
-       PINMUX_IPSR_DATA(IP6_8,         SSI_WS5),
-       PINMUX_IPSR_DATA(IP6_8,         TX4_C),
+       PINMUX_IPSR_GPSR(IP6_8,         SSI_WS5),
+       PINMUX_IPSR_GPSR(IP6_8,         TX4_C),
 
-       PINMUX_IPSR_DATA(IP6_9,         SSI_SDATA5),
+       PINMUX_IPSR_GPSR(IP6_9,         SSI_SDATA5),
        PINMUX_IPSR_MSEL(IP6_9,         RX0_D,          SEL_SCIF0_D),
 
-       PINMUX_IPSR_DATA(IP6_10,        SSI_WS34),
-       PINMUX_IPSR_DATA(IP6_10,        ARM_TRACEDATA_8),
+       PINMUX_IPSR_GPSR(IP6_10,        SSI_WS34),
+       PINMUX_IPSR_GPSR(IP6_10,        ARM_TRACEDATA_8),
 
-       PINMUX_IPSR_DATA(IP6_12_11,     SSI_SDATA4),
+       PINMUX_IPSR_GPSR(IP6_12_11,     SSI_SDATA4),
        PINMUX_IPSR_MSEL(IP6_12_11,     SSI_WS2_A,      SEL_SSI2_A),
-       PINMUX_IPSR_DATA(IP6_12_11,     ARM_TRACEDATA_9),
+       PINMUX_IPSR_GPSR(IP6_12_11,     ARM_TRACEDATA_9),
 
-       PINMUX_IPSR_DATA(IP6_13,        SSI_SDATA3),
-       PINMUX_IPSR_DATA(IP6_13,        ARM_TRACEDATA_10),
+       PINMUX_IPSR_GPSR(IP6_13,        SSI_SDATA3),
+       PINMUX_IPSR_GPSR(IP6_13,        ARM_TRACEDATA_10),
 
-       PINMUX_IPSR_DATA(IP6_15_14,     SSI_SCK012),
-       PINMUX_IPSR_DATA(IP6_15_14,     ARM_TRACEDATA_11),
-       PINMUX_IPSR_DATA(IP6_15_14,     TX0_D),
+       PINMUX_IPSR_GPSR(IP6_15_14,     SSI_SCK012),
+       PINMUX_IPSR_GPSR(IP6_15_14,     ARM_TRACEDATA_11),
+       PINMUX_IPSR_GPSR(IP6_15_14,     TX0_D),
 
-       PINMUX_IPSR_DATA(IP6_16,        SSI_WS012),
-       PINMUX_IPSR_DATA(IP6_16,        ARM_TRACEDATA_12),
+       PINMUX_IPSR_GPSR(IP6_16,        SSI_WS012),
+       PINMUX_IPSR_GPSR(IP6_16,        ARM_TRACEDATA_12),
 
-       PINMUX_IPSR_DATA(IP6_18_17,     SSI_SDATA2),
+       PINMUX_IPSR_GPSR(IP6_18_17,     SSI_SDATA2),
        PINMUX_IPSR_MSEL(IP6_18_17,     HSPI_CS2_A,     SEL_HSPI2_A),
-       PINMUX_IPSR_DATA(IP6_18_17,     ARM_TRACEDATA_13),
+       PINMUX_IPSR_GPSR(IP6_18_17,     ARM_TRACEDATA_13),
        PINMUX_IPSR_MSEL(IP6_18_17,     SDA1_A,         SEL_I2C1_A),
 
-       PINMUX_IPSR_DATA(IP6_20_19,     SSI_SDATA1),
-       PINMUX_IPSR_DATA(IP6_20_19,     ARM_TRACEDATA_14),
+       PINMUX_IPSR_GPSR(IP6_20_19,     SSI_SDATA1),
+       PINMUX_IPSR_GPSR(IP6_20_19,     ARM_TRACEDATA_14),
        PINMUX_IPSR_MSEL(IP6_20_19,     SCL1_A,         SEL_I2C1_A),
        PINMUX_IPSR_MSEL(IP6_20_19,     SCK2_A,         SEL_SCIF2_A),
 
-       PINMUX_IPSR_DATA(IP6_21,        SSI_SDATA0),
-       PINMUX_IPSR_DATA(IP6_21,        ARM_TRACEDATA_15),
+       PINMUX_IPSR_GPSR(IP6_21,        SSI_SDATA0),
+       PINMUX_IPSR_GPSR(IP6_21,        ARM_TRACEDATA_15),
 
-       PINMUX_IPSR_DATA(IP6_23_22,     SD0_CLK),
-       PINMUX_IPSR_DATA(IP6_23_22,     SUB_TDO),
+       PINMUX_IPSR_GPSR(IP6_23_22,     SD0_CLK),
+       PINMUX_IPSR_GPSR(IP6_23_22,     SUB_TDO),
 
-       PINMUX_IPSR_DATA(IP6_25_24,     SD0_CMD),
-       PINMUX_IPSR_DATA(IP6_25_24,     SUB_TRST),
+       PINMUX_IPSR_GPSR(IP6_25_24,     SD0_CMD),
+       PINMUX_IPSR_GPSR(IP6_25_24,     SUB_TRST),
 
-       PINMUX_IPSR_DATA(IP6_27_26,     SD0_DAT0),
-       PINMUX_IPSR_DATA(IP6_27_26,     SUB_TMS),
+       PINMUX_IPSR_GPSR(IP6_27_26,     SD0_DAT0),
+       PINMUX_IPSR_GPSR(IP6_27_26,     SUB_TMS),
 
-       PINMUX_IPSR_DATA(IP6_29_28,     SD0_DAT1),
-       PINMUX_IPSR_DATA(IP6_29_28,     SUB_TCK),
+       PINMUX_IPSR_GPSR(IP6_29_28,     SD0_DAT1),
+       PINMUX_IPSR_GPSR(IP6_29_28,     SUB_TCK),
 
-       PINMUX_IPSR_DATA(IP6_31_30,     SD0_DAT2),
-       PINMUX_IPSR_DATA(IP6_31_30,     SUB_TDI),
+       PINMUX_IPSR_GPSR(IP6_31_30,     SD0_DAT2),
+       PINMUX_IPSR_GPSR(IP6_31_30,     SUB_TDI),
 
        /* IPSR7 */
-       PINMUX_IPSR_DATA(IP7_1_0,       SD0_DAT3),
+       PINMUX_IPSR_GPSR(IP7_1_0,       SD0_DAT3),
        PINMUX_IPSR_MSEL(IP7_1_0,       IRQ1_B,         SEL_IRQ1_B),
 
-       PINMUX_IPSR_DATA(IP7_3_2,       SD0_CD),
-       PINMUX_IPSR_DATA(IP7_3_2,       TX5_A),
+       PINMUX_IPSR_GPSR(IP7_3_2,       SD0_CD),
+       PINMUX_IPSR_GPSR(IP7_3_2,       TX5_A),
 
-       PINMUX_IPSR_DATA(IP7_5_4,       SD0_WP),
+       PINMUX_IPSR_GPSR(IP7_5_4,       SD0_WP),
        PINMUX_IPSR_MSEL(IP7_5_4,       RX5_A,          SEL_SCIF5_A),
 
-       PINMUX_IPSR_DATA(IP7_8_6,       VI1_CLKENB),
+       PINMUX_IPSR_GPSR(IP7_8_6,       VI1_CLKENB),
        PINMUX_IPSR_MSEL(IP7_8_6,       HSPI_CLK0_A,    SEL_HSPI0_A),
-       PINMUX_IPSR_DATA(IP7_8_6,       HTX1_A),
+       PINMUX_IPSR_GPSR(IP7_8_6,       HTX1_A),
        PINMUX_IPSR_MSEL(IP7_8_6,       RTS1_C,         SEL_SCIF1_C),
 
-       PINMUX_IPSR_DATA(IP7_11_9,      VI1_FIELD),
+       PINMUX_IPSR_GPSR(IP7_11_9,      VI1_FIELD),
        PINMUX_IPSR_MSEL(IP7_11_9,      HSPI_CS0_A,     SEL_HSPI0_A),
        PINMUX_IPSR_MSEL(IP7_11_9,      HRX1_A,         SEL_HSCIF1_A),
        PINMUX_IPSR_MSEL(IP7_11_9,      SCK1_C,         SEL_SCIF1_C),
 
-       PINMUX_IPSR_DATA(IP7_14_12,     VI1_HSYNC),
+       PINMUX_IPSR_GPSR(IP7_14_12,     VI1_HSYNC),
        PINMUX_IPSR_MSEL(IP7_14_12,     HSPI_RX0_A,     SEL_HSPI0_A),
        PINMUX_IPSR_MSEL(IP7_14_12,     HRTS1_A,        SEL_HSCIF1_A),
        PINMUX_IPSR_MSEL(IP7_14_12,     FMCLK_A,        SEL_FM_A),
        PINMUX_IPSR_MSEL(IP7_14_12,     RX1_C,          SEL_SCIF1_C),
 
-       PINMUX_IPSR_DATA(IP7_17_15,     VI1_VSYNC),
-       PINMUX_IPSR_DATA(IP7_17_15,     HSPI_TX0),
+       PINMUX_IPSR_GPSR(IP7_17_15,     VI1_VSYNC),
+       PINMUX_IPSR_GPSR(IP7_17_15,     HSPI_TX0),
        PINMUX_IPSR_MSEL(IP7_17_15,     HCTS1_A,        SEL_HSCIF1_A),
-       PINMUX_IPSR_DATA(IP7_17_15,     BPFCLK_A),
-       PINMUX_IPSR_DATA(IP7_17_15,     TX1_C),
+       PINMUX_IPSR_GPSR(IP7_17_15,     BPFCLK_A),
+       PINMUX_IPSR_GPSR(IP7_17_15,     TX1_C),
 
-       PINMUX_IPSR_DATA(IP7_20_18,     TCLK0),
+       PINMUX_IPSR_GPSR(IP7_20_18,     TCLK0),
        PINMUX_IPSR_MSEL(IP7_20_18,     HSCK1_A,        SEL_HSCIF1_A),
        PINMUX_IPSR_MSEL(IP7_20_18,     FMIN_A,         SEL_FM_A),
        PINMUX_IPSR_MSEL(IP7_20_18,     IRQ2_C,         SEL_IRQ2_C),
        PINMUX_IPSR_MSEL(IP7_20_18,     CTS1_C,         SEL_SCIF1_C),
-       PINMUX_IPSR_DATA(IP7_20_18,     SPEEDIN),
+       PINMUX_IPSR_GPSR(IP7_20_18,     SPEEDIN),
 
-       PINMUX_IPSR_DATA(IP7_21,        VI0_CLK),
+       PINMUX_IPSR_GPSR(IP7_21,        VI0_CLK),
        PINMUX_IPSR_MSEL(IP7_21,        CAN_CLK_A,      SEL_CANCLK_A),
 
-       PINMUX_IPSR_DATA(IP7_24_22,     VI0_CLKENB),
+       PINMUX_IPSR_GPSR(IP7_24_22,     VI0_CLKENB),
        PINMUX_IPSR_MSEL(IP7_24_22,     SD2_DAT2_B,     SEL_SD2_B),
-       PINMUX_IPSR_DATA(IP7_24_22,     VI1_DATA0),
-       PINMUX_IPSR_DATA(IP7_24_22,     DU1_DG6),
+       PINMUX_IPSR_GPSR(IP7_24_22,     VI1_DATA0),
+       PINMUX_IPSR_GPSR(IP7_24_22,     DU1_DG6),
        PINMUX_IPSR_MSEL(IP7_24_22,     HSPI_RX1_A,     SEL_HSPI1_A),
        PINMUX_IPSR_MSEL(IP7_24_22,     RX4_B,          SEL_SCIF4_B),
 
-       PINMUX_IPSR_DATA(IP7_28_25,     VI0_FIELD),
+       PINMUX_IPSR_GPSR(IP7_28_25,     VI0_FIELD),
        PINMUX_IPSR_MSEL(IP7_28_25,     SD2_DAT3_B,     SEL_SD2_B),
        PINMUX_DATA(VI0_R3_C_MARK,      FN_IP7_28_25,   FN_VI0_R3_C,    FN_SEL_VI0_C), /* see sel_vi0 */
        PINMUX_DATA(VI0_R3_D_MARK,      FN_IP7_28_25,   FN_VI0_R3_C,    FN_SEL_VI0_D), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP7_28_25,     VI1_DATA1),
-       PINMUX_IPSR_DATA(IP7_28_25,     DU1_DG7),
+       PINMUX_IPSR_GPSR(IP7_28_25,     VI1_DATA1),
+       PINMUX_IPSR_GPSR(IP7_28_25,     DU1_DG7),
        PINMUX_IPSR_MSEL(IP7_28_25,     HSPI_CLK1_A,    SEL_HSPI1_A),
-       PINMUX_IPSR_DATA(IP7_28_25,     TX4_B),
+       PINMUX_IPSR_GPSR(IP7_28_25,     TX4_B),
 
-       PINMUX_IPSR_DATA(IP7_31_29,     VI0_HSYNC),
+       PINMUX_IPSR_GPSR(IP7_31_29,     VI0_HSYNC),
        PINMUX_IPSR_MSEL(IP7_31_29,     SD2_CD_B,       SEL_SD2_B),
-       PINMUX_IPSR_DATA(IP7_31_29,     VI1_DATA2),
-       PINMUX_IPSR_DATA(IP7_31_29,     DU1_DR2),
+       PINMUX_IPSR_GPSR(IP7_31_29,     VI1_DATA2),
+       PINMUX_IPSR_GPSR(IP7_31_29,     DU1_DR2),
        PINMUX_IPSR_MSEL(IP7_31_29,     HSPI_CS1_A,     SEL_HSPI1_A),
        PINMUX_IPSR_MSEL(IP7_31_29,     RX3_B,          SEL_SCIF3_B),
 
        /* IPSR8 */
-       PINMUX_IPSR_DATA(IP8_2_0,       VI0_VSYNC),
+       PINMUX_IPSR_GPSR(IP8_2_0,       VI0_VSYNC),
        PINMUX_IPSR_MSEL(IP8_2_0,       SD2_WP_B,       SEL_SD2_B),
-       PINMUX_IPSR_DATA(IP8_2_0,       VI1_DATA3),
-       PINMUX_IPSR_DATA(IP8_2_0,       DU1_DR3),
-       PINMUX_IPSR_DATA(IP8_2_0,       HSPI_TX1_A),
-       PINMUX_IPSR_DATA(IP8_2_0,       TX3_B),
+       PINMUX_IPSR_GPSR(IP8_2_0,       VI1_DATA3),
+       PINMUX_IPSR_GPSR(IP8_2_0,       DU1_DR3),
+       PINMUX_IPSR_GPSR(IP8_2_0,       HSPI_TX1_A),
+       PINMUX_IPSR_GPSR(IP8_2_0,       TX3_B),
 
-       PINMUX_IPSR_DATA(IP8_5_3,       VI0_DATA0_VI0_B0),
-       PINMUX_IPSR_DATA(IP8_5_3,       DU1_DG2),
+       PINMUX_IPSR_GPSR(IP8_5_3,       VI0_DATA0_VI0_B0),
+       PINMUX_IPSR_GPSR(IP8_5_3,       DU1_DG2),
        PINMUX_IPSR_MSEL(IP8_5_3,       IRQ2_B,         SEL_IRQ2_B),
        PINMUX_IPSR_MSEL(IP8_5_3,       RX3_D,          SEL_SCIF3_D),
 
-       PINMUX_IPSR_DATA(IP8_8_6,       VI0_DATA1_VI0_B1),
-       PINMUX_IPSR_DATA(IP8_8_6,       DU1_DG3),
+       PINMUX_IPSR_GPSR(IP8_8_6,       VI0_DATA1_VI0_B1),
+       PINMUX_IPSR_GPSR(IP8_8_6,       DU1_DG3),
        PINMUX_IPSR_MSEL(IP8_8_6,       IRQ3_B,         SEL_IRQ3_B),
-       PINMUX_IPSR_DATA(IP8_8_6,       TX3_D),
+       PINMUX_IPSR_GPSR(IP8_8_6,       TX3_D),
 
-       PINMUX_IPSR_DATA(IP8_10_9,      VI0_DATA2_VI0_B2),
-       PINMUX_IPSR_DATA(IP8_10_9,      DU1_DG4),
+       PINMUX_IPSR_GPSR(IP8_10_9,      VI0_DATA2_VI0_B2),
+       PINMUX_IPSR_GPSR(IP8_10_9,      DU1_DG4),
        PINMUX_IPSR_MSEL(IP8_10_9,      RX0_C,          SEL_SCIF0_C),
 
-       PINMUX_IPSR_DATA(IP8_13_11,     VI0_DATA3_VI0_B3),
-       PINMUX_IPSR_DATA(IP8_13_11,     DU1_DG5),
-       PINMUX_IPSR_DATA(IP8_13_11,     TX1_A),
-       PINMUX_IPSR_DATA(IP8_13_11,     TX0_C),
+       PINMUX_IPSR_GPSR(IP8_13_11,     VI0_DATA3_VI0_B3),
+       PINMUX_IPSR_GPSR(IP8_13_11,     DU1_DG5),
+       PINMUX_IPSR_GPSR(IP8_13_11,     TX1_A),
+       PINMUX_IPSR_GPSR(IP8_13_11,     TX0_C),
 
-       PINMUX_IPSR_DATA(IP8_15_14,     VI0_DATA4_VI0_B4),
-       PINMUX_IPSR_DATA(IP8_15_14,     DU1_DB2),
+       PINMUX_IPSR_GPSR(IP8_15_14,     VI0_DATA4_VI0_B4),
+       PINMUX_IPSR_GPSR(IP8_15_14,     DU1_DB2),
        PINMUX_IPSR_MSEL(IP8_15_14,     RX1_A,          SEL_SCIF1_A),
 
-       PINMUX_IPSR_DATA(IP8_18_16,     VI0_DATA5_VI0_B5),
-       PINMUX_IPSR_DATA(IP8_18_16,     DU1_DB3),
+       PINMUX_IPSR_GPSR(IP8_18_16,     VI0_DATA5_VI0_B5),
+       PINMUX_IPSR_GPSR(IP8_18_16,     DU1_DB3),
        PINMUX_IPSR_MSEL(IP8_18_16,     SCK1_A,         SEL_SCIF1_A),
-       PINMUX_IPSR_DATA(IP8_18_16,     PWM4),
+       PINMUX_IPSR_GPSR(IP8_18_16,     PWM4),
        PINMUX_IPSR_MSEL(IP8_18_16,     HSCK1_B,        SEL_HSCIF1_B),
 
-       PINMUX_IPSR_DATA(IP8_21_19,     VI0_DATA6_VI0_G0),
-       PINMUX_IPSR_DATA(IP8_21_19,     DU1_DB4),
+       PINMUX_IPSR_GPSR(IP8_21_19,     VI0_DATA6_VI0_G0),
+       PINMUX_IPSR_GPSR(IP8_21_19,     DU1_DB4),
        PINMUX_IPSR_MSEL(IP8_21_19,     CTS1_A,         SEL_SCIF1_A),
-       PINMUX_IPSR_DATA(IP8_21_19,     PWM5),
+       PINMUX_IPSR_GPSR(IP8_21_19,     PWM5),
 
-       PINMUX_IPSR_DATA(IP8_23_22,     VI0_DATA7_VI0_G1),
-       PINMUX_IPSR_DATA(IP8_23_22,     DU1_DB5),
+       PINMUX_IPSR_GPSR(IP8_23_22,     VI0_DATA7_VI0_G1),
+       PINMUX_IPSR_GPSR(IP8_23_22,     DU1_DB5),
        PINMUX_IPSR_MSEL(IP8_23_22,     RTS1_A,         SEL_SCIF1_A),
 
-       PINMUX_IPSR_DATA(IP8_26_24,     VI0_G2),
-       PINMUX_IPSR_DATA(IP8_26_24,     SD2_CLK_B),
-       PINMUX_IPSR_DATA(IP8_26_24,     VI1_DATA4),
-       PINMUX_IPSR_DATA(IP8_26_24,     DU1_DR4),
-       PINMUX_IPSR_DATA(IP8_26_24,     HTX1_B),
+       PINMUX_IPSR_GPSR(IP8_26_24,     VI0_G2),
+       PINMUX_IPSR_GPSR(IP8_26_24,     SD2_CLK_B),
+       PINMUX_IPSR_GPSR(IP8_26_24,     VI1_DATA4),
+       PINMUX_IPSR_GPSR(IP8_26_24,     DU1_DR4),
+       PINMUX_IPSR_GPSR(IP8_26_24,     HTX1_B),
 
-       PINMUX_IPSR_DATA(IP8_29_27,     VI0_G3),
+       PINMUX_IPSR_GPSR(IP8_29_27,     VI0_G3),
        PINMUX_IPSR_MSEL(IP8_29_27,     SD2_CMD_B,      SEL_SD2_B),
-       PINMUX_IPSR_DATA(IP8_29_27,     VI1_DATA5),
-       PINMUX_IPSR_DATA(IP8_29_27,     DU1_DR5),
+       PINMUX_IPSR_GPSR(IP8_29_27,     VI1_DATA5),
+       PINMUX_IPSR_GPSR(IP8_29_27,     DU1_DR5),
        PINMUX_IPSR_MSEL(IP8_29_27,     HRX1_B,         SEL_HSCIF1_B),
 
        /* IPSR9 */
-       PINMUX_IPSR_DATA(IP9_2_0,       VI0_G4),
+       PINMUX_IPSR_GPSR(IP9_2_0,       VI0_G4),
        PINMUX_IPSR_MSEL(IP9_2_0,       SD2_DAT0_B,     SEL_SD2_B),
-       PINMUX_IPSR_DATA(IP9_2_0,       VI1_DATA6),
-       PINMUX_IPSR_DATA(IP9_2_0,       DU1_DR6),
+       PINMUX_IPSR_GPSR(IP9_2_0,       VI1_DATA6),
+       PINMUX_IPSR_GPSR(IP9_2_0,       DU1_DR6),
        PINMUX_IPSR_MSEL(IP9_2_0,       HRTS1_B,        SEL_HSCIF1_B),
 
-       PINMUX_IPSR_DATA(IP9_5_3,       VI0_G5),
+       PINMUX_IPSR_GPSR(IP9_5_3,       VI0_G5),
        PINMUX_IPSR_MSEL(IP9_5_3,       SD2_DAT1_B,     SEL_SD2_B),
-       PINMUX_IPSR_DATA(IP9_5_3,       VI1_DATA7),
-       PINMUX_IPSR_DATA(IP9_5_3,       DU1_DR7),
+       PINMUX_IPSR_GPSR(IP9_5_3,       VI1_DATA7),
+       PINMUX_IPSR_GPSR(IP9_5_3,       DU1_DR7),
        PINMUX_IPSR_MSEL(IP9_5_3,       HCTS1_B,        SEL_HSCIF1_B),
 
        PINMUX_DATA(VI0_R0_A_MARK,      FN_IP9_8_6,     FN_VI0_R0_A,    FN_SEL_VI0_A), /* see sel_vi0 */
        PINMUX_DATA(VI0_R0_C_MARK,      FN_IP9_8_6,     FN_VI0_R0_A,    FN_SEL_VI0_C), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP9_8_6,       VI1_CLK),
-       PINMUX_IPSR_DATA(IP9_8_6,       ETH_REF_CLK),
-       PINMUX_IPSR_DATA(IP9_8_6,       DU1_DOTCLKIN),
+       PINMUX_IPSR_GPSR(IP9_8_6,       VI1_CLK),
+       PINMUX_IPSR_GPSR(IP9_8_6,       ETH_REF_CLK),
+       PINMUX_IPSR_GPSR(IP9_8_6,       DU1_DOTCLKIN),
 
        PINMUX_DATA(VI0_R1_A_MARK,      FN_IP9_11_9,    FN_VI0_R1_A,    FN_SEL_VI0_A), /* see sel_vi0 */
        PINMUX_DATA(VI0_R1_C_MARK,      FN_IP9_11_9,    FN_VI0_R1_A,    FN_SEL_VI0_C), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP9_11_9,      VI1_DATA8),
-       PINMUX_IPSR_DATA(IP9_11_9,      DU1_DB6),
-       PINMUX_IPSR_DATA(IP9_11_9,      ETH_TXD0),
-       PINMUX_IPSR_DATA(IP9_11_9,      PWM2),
-       PINMUX_IPSR_DATA(IP9_11_9,      TCLK1),
+       PINMUX_IPSR_GPSR(IP9_11_9,      VI1_DATA8),
+       PINMUX_IPSR_GPSR(IP9_11_9,      DU1_DB6),
+       PINMUX_IPSR_GPSR(IP9_11_9,      ETH_TXD0),
+       PINMUX_IPSR_GPSR(IP9_11_9,      PWM2),
+       PINMUX_IPSR_GPSR(IP9_11_9,      TCLK1),
 
        PINMUX_DATA(VI0_R2_A_MARK,      FN_IP9_14_12,   FN_VI0_R2_A,    FN_SEL_VI0_A), /* see sel_vi0 */
        PINMUX_DATA(VI0_R2_C_MARK,      FN_IP9_14_12,   FN_VI0_R2_A,    FN_SEL_VI0_C), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP9_14_12,     VI1_DATA9),
-       PINMUX_IPSR_DATA(IP9_14_12,     DU1_DB7),
-       PINMUX_IPSR_DATA(IP9_14_12,     ETH_TXD1),
-       PINMUX_IPSR_DATA(IP9_14_12,     PWM3),
+       PINMUX_IPSR_GPSR(IP9_14_12,     VI1_DATA9),
+       PINMUX_IPSR_GPSR(IP9_14_12,     DU1_DB7),
+       PINMUX_IPSR_GPSR(IP9_14_12,     ETH_TXD1),
+       PINMUX_IPSR_GPSR(IP9_14_12,     PWM3),
 
        PINMUX_IPSR_MSEL(IP9_17_15,     VI0_R3_A,       SEL_VI0_A),
-       PINMUX_IPSR_DATA(IP9_17_15,     ETH_CRS_DV),
-       PINMUX_IPSR_DATA(IP9_17_15,     IECLK),
+       PINMUX_IPSR_GPSR(IP9_17_15,     ETH_CRS_DV),
+       PINMUX_IPSR_GPSR(IP9_17_15,     IECLK),
        PINMUX_IPSR_MSEL(IP9_17_15,     SCK2_C,         SEL_SCIF2_C),
 
        PINMUX_DATA(VI0_R4_A_MARK,      FN_IP9_20_18,   FN_VI0_R4_A,    FN_SEL_VI0_A), /* see sel_vi0 */
        PINMUX_DATA(VI0_R3_C_MARK,      FN_IP9_20_18,   FN_VI0_R4_A,    FN_SEL_VI0_C), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP9_20_18,     ETH_TX_EN),
-       PINMUX_IPSR_DATA(IP9_20_18,     IETX),
-       PINMUX_IPSR_DATA(IP9_20_18,     TX2_C),
+       PINMUX_IPSR_GPSR(IP9_20_18,     ETH_TX_EN),
+       PINMUX_IPSR_GPSR(IP9_20_18,     IETX),
+       PINMUX_IPSR_GPSR(IP9_20_18,     TX2_C),
 
        PINMUX_DATA(VI0_R5_A_MARK,      FN_IP9_23_21,   FN_VI0_R5_A,    FN_SEL_VI0_A), /* see sel_vi0 */
        PINMUX_DATA(VI0_R5_C_MARK,      FN_IP9_23_21,   FN_VI0_R5_A,    FN_SEL_VI0_C), /* see sel_vi0 */
-       PINMUX_IPSR_DATA(IP9_23_21,     ETH_RX_ER),
+       PINMUX_IPSR_GPSR(IP9_23_21,     ETH_RX_ER),
        PINMUX_IPSR_MSEL(IP9_23_21,     FMCLK_C,        SEL_FM_C),
-       PINMUX_IPSR_DATA(IP9_23_21,     IERX),
+       PINMUX_IPSR_GPSR(IP9_23_21,     IERX),
        PINMUX_IPSR_MSEL(IP9_23_21,     RX2_C,          SEL_SCIF2_C),
 
        PINMUX_IPSR_MSEL(IP9_26_24,     VI1_DATA10_A,   SEL_VI1_A),
-       PINMUX_IPSR_DATA(IP9_26_24,     DU1_DOTCLKOUT),
-       PINMUX_IPSR_DATA(IP9_26_24,     ETH_RXD0),
-       PINMUX_IPSR_DATA(IP9_26_24,     BPFCLK_C),
-       PINMUX_IPSR_DATA(IP9_26_24,     TX2_D),
+       PINMUX_IPSR_GPSR(IP9_26_24,     DU1_DOTCLKOUT),
+       PINMUX_IPSR_GPSR(IP9_26_24,     ETH_RXD0),
+       PINMUX_IPSR_GPSR(IP9_26_24,     BPFCLK_C),
+       PINMUX_IPSR_GPSR(IP9_26_24,     TX2_D),
        PINMUX_IPSR_MSEL(IP9_26_24,     SDA2_C,         SEL_I2C2_C),
 
        PINMUX_IPSR_MSEL(IP9_29_27,     VI1_DATA11_A,   SEL_VI1_A),
-       PINMUX_IPSR_DATA(IP9_29_27,     DU1_EXHSYNC_DU1_HSYNC),
-       PINMUX_IPSR_DATA(IP9_29_27,     ETH_RXD1),
+       PINMUX_IPSR_GPSR(IP9_29_27,     DU1_EXHSYNC_DU1_HSYNC),
+       PINMUX_IPSR_GPSR(IP9_29_27,     ETH_RXD1),
        PINMUX_IPSR_MSEL(IP9_29_27,     FMIN_C,         SEL_FM_C),
        PINMUX_IPSR_MSEL(IP9_29_27,     RX2_D,          SEL_SCIF2_D),
        PINMUX_IPSR_MSEL(IP9_29_27,     SCL2_C,         SEL_I2C2_C),
 
        /* IPSR10 */
-       PINMUX_IPSR_DATA(IP10_2_0,      SD2_CLK_A),
-       PINMUX_IPSR_DATA(IP10_2_0,      DU1_EXVSYNC_DU1_VSYNC),
-       PINMUX_IPSR_DATA(IP10_2_0,      ATARD1),
-       PINMUX_IPSR_DATA(IP10_2_0,      ETH_MDC),
+       PINMUX_IPSR_GPSR(IP10_2_0,      SD2_CLK_A),
+       PINMUX_IPSR_GPSR(IP10_2_0,      DU1_EXVSYNC_DU1_VSYNC),
+       PINMUX_IPSR_GPSR(IP10_2_0,      ATARD1),
+       PINMUX_IPSR_GPSR(IP10_2_0,      ETH_MDC),
        PINMUX_IPSR_MSEL(IP10_2_0,      SDA1_B,         SEL_I2C1_B),
 
        PINMUX_IPSR_MSEL(IP10_5_3,      SD2_CMD_A,      SEL_SD2_A),
-       PINMUX_IPSR_DATA(IP10_5_3,      DU1_EXODDF_DU1_ODDF_DISP_CDE),
-       PINMUX_IPSR_DATA(IP10_5_3,      ATAWR1),
-       PINMUX_IPSR_DATA(IP10_5_3,      ETH_MDIO),
+       PINMUX_IPSR_GPSR(IP10_5_3,      DU1_EXODDF_DU1_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP10_5_3,      ATAWR1),
+       PINMUX_IPSR_GPSR(IP10_5_3,      ETH_MDIO),
        PINMUX_IPSR_MSEL(IP10_5_3,      SCL1_B,         SEL_I2C1_B),
 
        PINMUX_IPSR_MSEL(IP10_8_6,      SD2_DAT0_A,     SEL_SD2_A),
-       PINMUX_IPSR_DATA(IP10_8_6,      DU1_DISP),
-       PINMUX_IPSR_DATA(IP10_8_6,      ATACS01),
+       PINMUX_IPSR_GPSR(IP10_8_6,      DU1_DISP),
+       PINMUX_IPSR_GPSR(IP10_8_6,      ATACS01),
        PINMUX_IPSR_MSEL(IP10_8_6,      DREQ1_B,        SEL_DREQ1_B),
-       PINMUX_IPSR_DATA(IP10_8_6,      ETH_LINK),
+       PINMUX_IPSR_GPSR(IP10_8_6,      ETH_LINK),
        PINMUX_IPSR_MSEL(IP10_8_6,      CAN1_RX_A,      SEL_CAN1_A),
 
        PINMUX_IPSR_MSEL(IP10_12_9,     SD2_DAT1_A,     SEL_SD2_A),
-       PINMUX_IPSR_DATA(IP10_12_9,     DU1_CDE),
-       PINMUX_IPSR_DATA(IP10_12_9,     ATACS11),
-       PINMUX_IPSR_DATA(IP10_12_9,     DACK1_B),
-       PINMUX_IPSR_DATA(IP10_12_9,     ETH_MAGIC),
-       PINMUX_IPSR_DATA(IP10_12_9,     CAN1_TX_A),
-       PINMUX_IPSR_DATA(IP10_12_9,     PWM6),
+       PINMUX_IPSR_GPSR(IP10_12_9,     DU1_CDE),
+       PINMUX_IPSR_GPSR(IP10_12_9,     ATACS11),
+       PINMUX_IPSR_GPSR(IP10_12_9,     DACK1_B),
+       PINMUX_IPSR_GPSR(IP10_12_9,     ETH_MAGIC),
+       PINMUX_IPSR_GPSR(IP10_12_9,     CAN1_TX_A),
+       PINMUX_IPSR_GPSR(IP10_12_9,     PWM6),
 
        PINMUX_IPSR_MSEL(IP10_15_13,    SD2_DAT2_A,     SEL_SD2_A),
-       PINMUX_IPSR_DATA(IP10_15_13,    VI1_DATA12),
+       PINMUX_IPSR_GPSR(IP10_15_13,    VI1_DATA12),
        PINMUX_IPSR_MSEL(IP10_15_13,    DREQ2_B,        SEL_DREQ2_B),
-       PINMUX_IPSR_DATA(IP10_15_13,    ATADIR1),
+       PINMUX_IPSR_GPSR(IP10_15_13,    ATADIR1),
        PINMUX_IPSR_MSEL(IP10_15_13,    HSPI_CLK2_B,    SEL_HSPI2_B),
        PINMUX_IPSR_MSEL(IP10_15_13,    GPSCLK_B,       SEL_GPS_B),
 
        PINMUX_IPSR_MSEL(IP10_18_16,    SD2_DAT3_A,     SEL_SD2_A),
-       PINMUX_IPSR_DATA(IP10_18_16,    VI1_DATA13),
-       PINMUX_IPSR_DATA(IP10_18_16,    DACK2_B),
-       PINMUX_IPSR_DATA(IP10_18_16,    ATAG1),
+       PINMUX_IPSR_GPSR(IP10_18_16,    VI1_DATA13),
+       PINMUX_IPSR_GPSR(IP10_18_16,    DACK2_B),
+       PINMUX_IPSR_GPSR(IP10_18_16,    ATAG1),
        PINMUX_IPSR_MSEL(IP10_18_16,    HSPI_CS2_B,     SEL_HSPI2_B),
        PINMUX_IPSR_MSEL(IP10_18_16,    GPSIN_B,        SEL_GPS_B),
 
        PINMUX_IPSR_MSEL(IP10_21_19,    SD2_CD_A,       SEL_SD2_A),
-       PINMUX_IPSR_DATA(IP10_21_19,    VI1_DATA14),
+       PINMUX_IPSR_GPSR(IP10_21_19,    VI1_DATA14),
        PINMUX_IPSR_MSEL(IP10_21_19,    EX_WAIT1_B,     SEL_WAIT1_B),
        PINMUX_IPSR_MSEL(IP10_21_19,    DREQ0_B,        SEL_DREQ0_B),
        PINMUX_IPSR_MSEL(IP10_21_19,    HSPI_RX2_B,     SEL_HSPI2_B),
        PINMUX_IPSR_MSEL(IP10_21_19,    REMOCON_A,      SEL_REMOCON_A),
 
        PINMUX_IPSR_MSEL(IP10_24_22,    SD2_WP_A,       SEL_SD2_A),
-       PINMUX_IPSR_DATA(IP10_24_22,    VI1_DATA15),
+       PINMUX_IPSR_GPSR(IP10_24_22,    VI1_DATA15),
        PINMUX_IPSR_MSEL(IP10_24_22,    EX_WAIT2_B,     SEL_WAIT2_B),
-       PINMUX_IPSR_DATA(IP10_24_22,    DACK0_B),
-       PINMUX_IPSR_DATA(IP10_24_22,    HSPI_TX2_B),
+       PINMUX_IPSR_GPSR(IP10_24_22,    DACK0_B),
+       PINMUX_IPSR_GPSR(IP10_24_22,    HSPI_TX2_B),
        PINMUX_IPSR_MSEL(IP10_24_22,    CAN_CLK_C,      SEL_CANCLK_C),
 };
 
index bd17eccb6a8901a8880dcaeb7e87fbcccc040f2b..5bef934f823df69976fc528e15d0965d9bd6fb07 100644 (file)
@@ -611,577 +611,577 @@ static const u16 pinmux_data[] = {
        PINMUX_SINGLE(USB_PENC0),
        PINMUX_SINGLE(USB_PENC1),
 
-       PINMUX_IPSR_DATA(IP0_2_0, USB_PENC2),
+       PINMUX_IPSR_GPSR(IP0_2_0, USB_PENC2),
        PINMUX_IPSR_MSEL(IP0_2_0, SCK0, SEL_SCIF0_0),
-       PINMUX_IPSR_DATA(IP0_2_0, PWM1),
+       PINMUX_IPSR_GPSR(IP0_2_0, PWM1),
        PINMUX_IPSR_MSEL(IP0_2_0, PWMFSW0, SEL_PWMFSW_0),
        PINMUX_IPSR_MSEL(IP0_2_0, SCIF_CLK, SEL_SCIF_0),
        PINMUX_IPSR_MSEL(IP0_2_0, TCLK0_C, SEL_TMU0_2),
-       PINMUX_IPSR_DATA(IP0_5_3, BS),
-       PINMUX_IPSR_DATA(IP0_5_3, SD1_DAT2),
-       PINMUX_IPSR_DATA(IP0_5_3, MMC0_D2),
-       PINMUX_IPSR_DATA(IP0_5_3, FD2),
-       PINMUX_IPSR_DATA(IP0_5_3, ATADIR0),
-       PINMUX_IPSR_DATA(IP0_5_3, SDSELF),
+       PINMUX_IPSR_GPSR(IP0_5_3, BS),
+       PINMUX_IPSR_GPSR(IP0_5_3, SD1_DAT2),
+       PINMUX_IPSR_GPSR(IP0_5_3, MMC0_D2),
+       PINMUX_IPSR_GPSR(IP0_5_3, FD2),
+       PINMUX_IPSR_GPSR(IP0_5_3, ATADIR0),
+       PINMUX_IPSR_GPSR(IP0_5_3, SDSELF),
        PINMUX_IPSR_MSEL(IP0_5_3, HCTS1, SEL_HSCIF1_0),
-       PINMUX_IPSR_DATA(IP0_5_3, TX4_C),
-       PINMUX_IPSR_DATA(IP0_7_6, A0),
-       PINMUX_IPSR_DATA(IP0_7_6, SD1_DAT3),
-       PINMUX_IPSR_DATA(IP0_7_6, MMC0_D3),
-       PINMUX_IPSR_DATA(IP0_7_6, FD3),
-       PINMUX_IPSR_DATA(IP0_9_8, A20),
-       PINMUX_IPSR_DATA(IP0_9_8, TX5_D),
-       PINMUX_IPSR_DATA(IP0_9_8, HSPI_TX2_B),
-       PINMUX_IPSR_DATA(IP0_11_10, A21),
+       PINMUX_IPSR_GPSR(IP0_5_3, TX4_C),
+       PINMUX_IPSR_GPSR(IP0_7_6, A0),
+       PINMUX_IPSR_GPSR(IP0_7_6, SD1_DAT3),
+       PINMUX_IPSR_GPSR(IP0_7_6, MMC0_D3),
+       PINMUX_IPSR_GPSR(IP0_7_6, FD3),
+       PINMUX_IPSR_GPSR(IP0_9_8, A20),
+       PINMUX_IPSR_GPSR(IP0_9_8, TX5_D),
+       PINMUX_IPSR_GPSR(IP0_9_8, HSPI_TX2_B),
+       PINMUX_IPSR_GPSR(IP0_11_10, A21),
        PINMUX_IPSR_MSEL(IP0_11_10, SCK5_D, SEL_SCIF5_3),
        PINMUX_IPSR_MSEL(IP0_11_10, HSPI_CLK2_B, SEL_HSPI2_1),
-       PINMUX_IPSR_DATA(IP0_13_12, A22),
+       PINMUX_IPSR_GPSR(IP0_13_12, A22),
        PINMUX_IPSR_MSEL(IP0_13_12, RX5_D, SEL_SCIF5_3),
        PINMUX_IPSR_MSEL(IP0_13_12, HSPI_RX2_B, SEL_HSPI2_1),
-       PINMUX_IPSR_DATA(IP0_13_12, VI1_R0),
-       PINMUX_IPSR_DATA(IP0_15_14, A23),
-       PINMUX_IPSR_DATA(IP0_15_14, FCLE),
+       PINMUX_IPSR_GPSR(IP0_13_12, VI1_R0),
+       PINMUX_IPSR_GPSR(IP0_15_14, A23),
+       PINMUX_IPSR_GPSR(IP0_15_14, FCLE),
        PINMUX_IPSR_MSEL(IP0_15_14, HSPI_CLK2, SEL_HSPI2_0),
-       PINMUX_IPSR_DATA(IP0_15_14, VI1_R1),
-       PINMUX_IPSR_DATA(IP0_18_16, A24),
-       PINMUX_IPSR_DATA(IP0_18_16, SD1_CD),
-       PINMUX_IPSR_DATA(IP0_18_16, MMC0_D4),
-       PINMUX_IPSR_DATA(IP0_18_16, FD4),
+       PINMUX_IPSR_GPSR(IP0_15_14, VI1_R1),
+       PINMUX_IPSR_GPSR(IP0_18_16, A24),
+       PINMUX_IPSR_GPSR(IP0_18_16, SD1_CD),
+       PINMUX_IPSR_GPSR(IP0_18_16, MMC0_D4),
+       PINMUX_IPSR_GPSR(IP0_18_16, FD4),
        PINMUX_IPSR_MSEL(IP0_18_16, HSPI_CS2, SEL_HSPI2_0),
-       PINMUX_IPSR_DATA(IP0_18_16, VI1_R2),
+       PINMUX_IPSR_GPSR(IP0_18_16, VI1_R2),
        PINMUX_IPSR_MSEL(IP0_18_16, SSI_WS78_B, SEL_SSI7_1),
-       PINMUX_IPSR_DATA(IP0_22_19, A25),
-       PINMUX_IPSR_DATA(IP0_22_19, SD1_WP),
-       PINMUX_IPSR_DATA(IP0_22_19, MMC0_D5),
-       PINMUX_IPSR_DATA(IP0_22_19, FD5),
+       PINMUX_IPSR_GPSR(IP0_22_19, A25),
+       PINMUX_IPSR_GPSR(IP0_22_19, SD1_WP),
+       PINMUX_IPSR_GPSR(IP0_22_19, MMC0_D5),
+       PINMUX_IPSR_GPSR(IP0_22_19, FD5),
        PINMUX_IPSR_MSEL(IP0_22_19, HSPI_RX2, SEL_HSPI2_0),
-       PINMUX_IPSR_DATA(IP0_22_19, VI1_R3),
-       PINMUX_IPSR_DATA(IP0_22_19, TX5_B),
+       PINMUX_IPSR_GPSR(IP0_22_19, VI1_R3),
+       PINMUX_IPSR_GPSR(IP0_22_19, TX5_B),
        PINMUX_IPSR_MSEL(IP0_22_19, SSI_SDATA7_B, SEL_SSI7_1),
        PINMUX_IPSR_MSEL(IP0_22_19, CTS0_B, SEL_SCIF0_1),
-       PINMUX_IPSR_DATA(IP0_24_23, CLKOUT),
-       PINMUX_IPSR_DATA(IP0_24_23, TX3C_IRDA_TX_C),
-       PINMUX_IPSR_DATA(IP0_24_23, PWM0_B),
-       PINMUX_IPSR_DATA(IP0_25, CS0),
+       PINMUX_IPSR_GPSR(IP0_24_23, CLKOUT),
+       PINMUX_IPSR_GPSR(IP0_24_23, TX3C_IRDA_TX_C),
+       PINMUX_IPSR_GPSR(IP0_24_23, PWM0_B),
+       PINMUX_IPSR_GPSR(IP0_25, CS0),
        PINMUX_IPSR_MSEL(IP0_25, HSPI_CS2_B, SEL_HSPI2_1),
-       PINMUX_IPSR_DATA(IP0_27_26, CS1_A26),
-       PINMUX_IPSR_DATA(IP0_27_26, HSPI_TX2),
-       PINMUX_IPSR_DATA(IP0_27_26, SDSELF_B),
-       PINMUX_IPSR_DATA(IP0_30_28, RD_WR),
-       PINMUX_IPSR_DATA(IP0_30_28, FWE),
-       PINMUX_IPSR_DATA(IP0_30_28, ATAG0),
-       PINMUX_IPSR_DATA(IP0_30_28, VI1_R7),
+       PINMUX_IPSR_GPSR(IP0_27_26, CS1_A26),
+       PINMUX_IPSR_GPSR(IP0_27_26, HSPI_TX2),
+       PINMUX_IPSR_GPSR(IP0_27_26, SDSELF_B),
+       PINMUX_IPSR_GPSR(IP0_30_28, RD_WR),
+       PINMUX_IPSR_GPSR(IP0_30_28, FWE),
+       PINMUX_IPSR_GPSR(IP0_30_28, ATAG0),
+       PINMUX_IPSR_GPSR(IP0_30_28, VI1_R7),
        PINMUX_IPSR_MSEL(IP0_30_28, HRTS1, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP0_30_28, RX4_C, SEL_SCIF4_2),
 
-       PINMUX_IPSR_DATA(IP1_1_0, EX_CS0),
+       PINMUX_IPSR_GPSR(IP1_1_0, EX_CS0),
        PINMUX_IPSR_MSEL(IP1_1_0, RX3_C_IRDA_RX_C, SEL_SCIF3_2),
-       PINMUX_IPSR_DATA(IP1_1_0, MMC0_D6),
-       PINMUX_IPSR_DATA(IP1_1_0, FD6),
-       PINMUX_IPSR_DATA(IP1_3_2, EX_CS1),
-       PINMUX_IPSR_DATA(IP1_3_2, MMC0_D7),
-       PINMUX_IPSR_DATA(IP1_3_2, FD7),
-       PINMUX_IPSR_DATA(IP1_6_4, EX_CS2),
-       PINMUX_IPSR_DATA(IP1_6_4, SD1_CLK),
-       PINMUX_IPSR_DATA(IP1_6_4, MMC0_CLK),
-       PINMUX_IPSR_DATA(IP1_6_4, FALE),
-       PINMUX_IPSR_DATA(IP1_6_4, ATACS00),
-       PINMUX_IPSR_DATA(IP1_10_7, EX_CS3),
-       PINMUX_IPSR_DATA(IP1_10_7, SD1_CMD),
-       PINMUX_IPSR_DATA(IP1_10_7, MMC0_CMD),
-       PINMUX_IPSR_DATA(IP1_10_7, FRE),
-       PINMUX_IPSR_DATA(IP1_10_7, ATACS10),
-       PINMUX_IPSR_DATA(IP1_10_7, VI1_R4),
+       PINMUX_IPSR_GPSR(IP1_1_0, MMC0_D6),
+       PINMUX_IPSR_GPSR(IP1_1_0, FD6),
+       PINMUX_IPSR_GPSR(IP1_3_2, EX_CS1),
+       PINMUX_IPSR_GPSR(IP1_3_2, MMC0_D7),
+       PINMUX_IPSR_GPSR(IP1_3_2, FD7),
+       PINMUX_IPSR_GPSR(IP1_6_4, EX_CS2),
+       PINMUX_IPSR_GPSR(IP1_6_4, SD1_CLK),
+       PINMUX_IPSR_GPSR(IP1_6_4, MMC0_CLK),
+       PINMUX_IPSR_GPSR(IP1_6_4, FALE),
+       PINMUX_IPSR_GPSR(IP1_6_4, ATACS00),
+       PINMUX_IPSR_GPSR(IP1_10_7, EX_CS3),
+       PINMUX_IPSR_GPSR(IP1_10_7, SD1_CMD),
+       PINMUX_IPSR_GPSR(IP1_10_7, MMC0_CMD),
+       PINMUX_IPSR_GPSR(IP1_10_7, FRE),
+       PINMUX_IPSR_GPSR(IP1_10_7, ATACS10),
+       PINMUX_IPSR_GPSR(IP1_10_7, VI1_R4),
        PINMUX_IPSR_MSEL(IP1_10_7, RX5_B, SEL_SCIF5_1),
        PINMUX_IPSR_MSEL(IP1_10_7, HSCK1, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP1_10_7, SSI_SDATA8_B, SEL_SSI8_1),
        PINMUX_IPSR_MSEL(IP1_10_7, RTS0_B_TANS_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP1_10_7, SSI_SDATA9, SEL_SSI9_0),
-       PINMUX_IPSR_DATA(IP1_14_11, EX_CS4),
-       PINMUX_IPSR_DATA(IP1_14_11, SD1_DAT0),
-       PINMUX_IPSR_DATA(IP1_14_11, MMC0_D0),
-       PINMUX_IPSR_DATA(IP1_14_11, FD0),
-       PINMUX_IPSR_DATA(IP1_14_11, ATARD0),
-       PINMUX_IPSR_DATA(IP1_14_11, VI1_R5),
+       PINMUX_IPSR_GPSR(IP1_14_11, EX_CS4),
+       PINMUX_IPSR_GPSR(IP1_14_11, SD1_DAT0),
+       PINMUX_IPSR_GPSR(IP1_14_11, MMC0_D0),
+       PINMUX_IPSR_GPSR(IP1_14_11, FD0),
+       PINMUX_IPSR_GPSR(IP1_14_11, ATARD0),
+       PINMUX_IPSR_GPSR(IP1_14_11, VI1_R5),
        PINMUX_IPSR_MSEL(IP1_14_11, SCK5_B, SEL_SCIF5_1),
-       PINMUX_IPSR_DATA(IP1_14_11, HTX1),
-       PINMUX_IPSR_DATA(IP1_14_11, TX2_E),
-       PINMUX_IPSR_DATA(IP1_14_11, TX0_B),
+       PINMUX_IPSR_GPSR(IP1_14_11, HTX1),
+       PINMUX_IPSR_GPSR(IP1_14_11, TX2_E),
+       PINMUX_IPSR_GPSR(IP1_14_11, TX0_B),
        PINMUX_IPSR_MSEL(IP1_14_11, SSI_SCK9, SEL_SSI9_0),
-       PINMUX_IPSR_DATA(IP1_18_15, EX_CS5),
-       PINMUX_IPSR_DATA(IP1_18_15, SD1_DAT1),
-       PINMUX_IPSR_DATA(IP1_18_15, MMC0_D1),
-       PINMUX_IPSR_DATA(IP1_18_15, FD1),
-       PINMUX_IPSR_DATA(IP1_18_15, ATAWR0),
-       PINMUX_IPSR_DATA(IP1_18_15, VI1_R6),
+       PINMUX_IPSR_GPSR(IP1_18_15, EX_CS5),
+       PINMUX_IPSR_GPSR(IP1_18_15, SD1_DAT1),
+       PINMUX_IPSR_GPSR(IP1_18_15, MMC0_D1),
+       PINMUX_IPSR_GPSR(IP1_18_15, FD1),
+       PINMUX_IPSR_GPSR(IP1_18_15, ATAWR0),
+       PINMUX_IPSR_GPSR(IP1_18_15, VI1_R6),
        PINMUX_IPSR_MSEL(IP1_18_15, HRX1, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP1_18_15, RX2_E, SEL_SCIF2_4),
        PINMUX_IPSR_MSEL(IP1_18_15, RX0_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP1_18_15, SSI_WS9, SEL_SSI9_0),
-       PINMUX_IPSR_DATA(IP1_20_19, MLB_CLK),
-       PINMUX_IPSR_DATA(IP1_20_19, PWM2),
+       PINMUX_IPSR_GPSR(IP1_20_19, MLB_CLK),
+       PINMUX_IPSR_GPSR(IP1_20_19, PWM2),
        PINMUX_IPSR_MSEL(IP1_20_19, SCK4, SEL_SCIF4_0),
-       PINMUX_IPSR_DATA(IP1_22_21, MLB_SIG),
-       PINMUX_IPSR_DATA(IP1_22_21, PWM3),
-       PINMUX_IPSR_DATA(IP1_22_21, TX4),
-       PINMUX_IPSR_DATA(IP1_24_23, MLB_DAT),
-       PINMUX_IPSR_DATA(IP1_24_23, PWM4),
+       PINMUX_IPSR_GPSR(IP1_22_21, MLB_SIG),
+       PINMUX_IPSR_GPSR(IP1_22_21, PWM3),
+       PINMUX_IPSR_GPSR(IP1_22_21, TX4),
+       PINMUX_IPSR_GPSR(IP1_24_23, MLB_DAT),
+       PINMUX_IPSR_GPSR(IP1_24_23, PWM4),
        PINMUX_IPSR_MSEL(IP1_24_23, RX4, SEL_SCIF4_0),
-       PINMUX_IPSR_DATA(IP1_28_25, HTX0),
-       PINMUX_IPSR_DATA(IP1_28_25, TX1),
-       PINMUX_IPSR_DATA(IP1_28_25, SDATA),
+       PINMUX_IPSR_GPSR(IP1_28_25, HTX0),
+       PINMUX_IPSR_GPSR(IP1_28_25, TX1),
+       PINMUX_IPSR_GPSR(IP1_28_25, SDATA),
        PINMUX_IPSR_MSEL(IP1_28_25, CTS0_C, SEL_SCIF0_2),
-       PINMUX_IPSR_DATA(IP1_28_25, SUB_TCK),
-       PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE2),
-       PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE10),
-       PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE18),
-       PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE26),
-       PINMUX_IPSR_DATA(IP1_28_25, CC5_STATE34),
+       PINMUX_IPSR_GPSR(IP1_28_25, SUB_TCK),
+       PINMUX_IPSR_GPSR(IP1_28_25, CC5_STATE2),
+       PINMUX_IPSR_GPSR(IP1_28_25, CC5_STATE10),
+       PINMUX_IPSR_GPSR(IP1_28_25, CC5_STATE18),
+       PINMUX_IPSR_GPSR(IP1_28_25, CC5_STATE26),
+       PINMUX_IPSR_GPSR(IP1_28_25, CC5_STATE34),
 
        PINMUX_IPSR_MSEL(IP2_3_0, HRX0, SEL_HSCIF0_0),
        PINMUX_IPSR_MSEL(IP2_3_0, RX1, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP2_3_0, SCKZ),
+       PINMUX_IPSR_GPSR(IP2_3_0, SCKZ),
        PINMUX_IPSR_MSEL(IP2_3_0, RTS0_C_TANS_C, SEL_SCIF0_2),
-       PINMUX_IPSR_DATA(IP2_3_0, SUB_TDI),
-       PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE3),
-       PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE11),
-       PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE19),
-       PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE27),
-       PINMUX_IPSR_DATA(IP2_3_0, CC5_STATE35),
+       PINMUX_IPSR_GPSR(IP2_3_0, SUB_TDI),
+       PINMUX_IPSR_GPSR(IP2_3_0, CC5_STATE3),
+       PINMUX_IPSR_GPSR(IP2_3_0, CC5_STATE11),
+       PINMUX_IPSR_GPSR(IP2_3_0, CC5_STATE19),
+       PINMUX_IPSR_GPSR(IP2_3_0, CC5_STATE27),
+       PINMUX_IPSR_GPSR(IP2_3_0, CC5_STATE35),
        PINMUX_IPSR_MSEL(IP2_7_4, HSCK0, SEL_HSCIF0_0),
        PINMUX_IPSR_MSEL(IP2_7_4, SCK1, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP2_7_4, MTS),
-       PINMUX_IPSR_DATA(IP2_7_4, PWM5),
+       PINMUX_IPSR_GPSR(IP2_7_4, MTS),
+       PINMUX_IPSR_GPSR(IP2_7_4, PWM5),
        PINMUX_IPSR_MSEL(IP2_7_4, SCK0_C, SEL_SCIF0_2),
        PINMUX_IPSR_MSEL(IP2_7_4, SSI_SDATA9_B, SEL_SSI9_1),
-       PINMUX_IPSR_DATA(IP2_7_4, SUB_TDO),
-       PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE0),
-       PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE8),
-       PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE16),
-       PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE24),
-       PINMUX_IPSR_DATA(IP2_7_4, CC5_STATE32),
+       PINMUX_IPSR_GPSR(IP2_7_4, SUB_TDO),
+       PINMUX_IPSR_GPSR(IP2_7_4, CC5_STATE0),
+       PINMUX_IPSR_GPSR(IP2_7_4, CC5_STATE8),
+       PINMUX_IPSR_GPSR(IP2_7_4, CC5_STATE16),
+       PINMUX_IPSR_GPSR(IP2_7_4, CC5_STATE24),
+       PINMUX_IPSR_GPSR(IP2_7_4, CC5_STATE32),
        PINMUX_IPSR_MSEL(IP2_11_8, HCTS0, SEL_HSCIF0_0),
        PINMUX_IPSR_MSEL(IP2_11_8, CTS1, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP2_11_8, STM),
-       PINMUX_IPSR_DATA(IP2_11_8, PWM0_D),
+       PINMUX_IPSR_GPSR(IP2_11_8, STM),
+       PINMUX_IPSR_GPSR(IP2_11_8, PWM0_D),
        PINMUX_IPSR_MSEL(IP2_11_8, RX0_C, SEL_SCIF0_2),
        PINMUX_IPSR_MSEL(IP2_11_8, SCIF_CLK_C, SEL_SCIF_2),
-       PINMUX_IPSR_DATA(IP2_11_8, SUB_TRST),
+       PINMUX_IPSR_GPSR(IP2_11_8, SUB_TRST),
        PINMUX_IPSR_MSEL(IP2_11_8, TCLK1_B, SEL_TMU1_1),
-       PINMUX_IPSR_DATA(IP2_11_8, CC5_OSCOUT),
+       PINMUX_IPSR_GPSR(IP2_11_8, CC5_OSCOUT),
        PINMUX_IPSR_MSEL(IP2_15_12, HRTS0, SEL_HSCIF0_0),
        PINMUX_IPSR_MSEL(IP2_15_12, RTS1_TANS, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP2_15_12, MDATA),
-       PINMUX_IPSR_DATA(IP2_15_12, TX0_C),
-       PINMUX_IPSR_DATA(IP2_15_12, SUB_TMS),
-       PINMUX_IPSR_DATA(IP2_15_12, CC5_STATE1),
-       PINMUX_IPSR_DATA(IP2_15_12, CC5_STATE9),
-       PINMUX_IPSR_DATA(IP2_15_12, CC5_STATE17),
-       PINMUX_IPSR_DATA(IP2_15_12, CC5_STATE25),
-       PINMUX_IPSR_DATA(IP2_15_12, CC5_STATE33),
-       PINMUX_IPSR_DATA(IP2_18_16, DU0_DR0),
-       PINMUX_IPSR_DATA(IP2_18_16, LCDOUT0),
+       PINMUX_IPSR_GPSR(IP2_15_12, MDATA),
+       PINMUX_IPSR_GPSR(IP2_15_12, TX0_C),
+       PINMUX_IPSR_GPSR(IP2_15_12, SUB_TMS),
+       PINMUX_IPSR_GPSR(IP2_15_12, CC5_STATE1),
+       PINMUX_IPSR_GPSR(IP2_15_12, CC5_STATE9),
+       PINMUX_IPSR_GPSR(IP2_15_12, CC5_STATE17),
+       PINMUX_IPSR_GPSR(IP2_15_12, CC5_STATE25),
+       PINMUX_IPSR_GPSR(IP2_15_12, CC5_STATE33),
+       PINMUX_IPSR_GPSR(IP2_18_16, DU0_DR0),
+       PINMUX_IPSR_GPSR(IP2_18_16, LCDOUT0),
        PINMUX_IPSR_MSEL(IP2_18_16, DREQ0, SEL_EXBUS0_0),
        PINMUX_IPSR_MSEL(IP2_18_16, GPS_CLK_B, SEL_GPS_1),
-       PINMUX_IPSR_DATA(IP2_18_16, AUDATA0),
-       PINMUX_IPSR_DATA(IP2_18_16, TX5_C),
-       PINMUX_IPSR_DATA(IP2_21_19, DU0_DR1),
-       PINMUX_IPSR_DATA(IP2_21_19, LCDOUT1),
-       PINMUX_IPSR_DATA(IP2_21_19, DACK0),
-       PINMUX_IPSR_DATA(IP2_21_19, DRACK0),
+       PINMUX_IPSR_GPSR(IP2_18_16, AUDATA0),
+       PINMUX_IPSR_GPSR(IP2_18_16, TX5_C),
+       PINMUX_IPSR_GPSR(IP2_21_19, DU0_DR1),
+       PINMUX_IPSR_GPSR(IP2_21_19, LCDOUT1),
+       PINMUX_IPSR_GPSR(IP2_21_19, DACK0),
+       PINMUX_IPSR_GPSR(IP2_21_19, DRACK0),
        PINMUX_IPSR_MSEL(IP2_21_19, GPS_SIGN_B, SEL_GPS_1),
-       PINMUX_IPSR_DATA(IP2_21_19, AUDATA1),
+       PINMUX_IPSR_GPSR(IP2_21_19, AUDATA1),
        PINMUX_IPSR_MSEL(IP2_21_19, RX5_C, SEL_SCIF5_2),
-       PINMUX_IPSR_DATA(IP2_22, DU0_DR2),
-       PINMUX_IPSR_DATA(IP2_22, LCDOUT2),
-       PINMUX_IPSR_DATA(IP2_23, DU0_DR3),
-       PINMUX_IPSR_DATA(IP2_23, LCDOUT3),
-       PINMUX_IPSR_DATA(IP2_24, DU0_DR4),
-       PINMUX_IPSR_DATA(IP2_24, LCDOUT4),
-       PINMUX_IPSR_DATA(IP2_25, DU0_DR5),
-       PINMUX_IPSR_DATA(IP2_25, LCDOUT5),
-       PINMUX_IPSR_DATA(IP2_26, DU0_DR6),
-       PINMUX_IPSR_DATA(IP2_26, LCDOUT6),
-       PINMUX_IPSR_DATA(IP2_27, DU0_DR7),
-       PINMUX_IPSR_DATA(IP2_27, LCDOUT7),
-       PINMUX_IPSR_DATA(IP2_30_28, DU0_DG0),
-       PINMUX_IPSR_DATA(IP2_30_28, LCDOUT8),
+       PINMUX_IPSR_GPSR(IP2_22, DU0_DR2),
+       PINMUX_IPSR_GPSR(IP2_22, LCDOUT2),
+       PINMUX_IPSR_GPSR(IP2_23, DU0_DR3),
+       PINMUX_IPSR_GPSR(IP2_23, LCDOUT3),
+       PINMUX_IPSR_GPSR(IP2_24, DU0_DR4),
+       PINMUX_IPSR_GPSR(IP2_24, LCDOUT4),
+       PINMUX_IPSR_GPSR(IP2_25, DU0_DR5),
+       PINMUX_IPSR_GPSR(IP2_25, LCDOUT5),
+       PINMUX_IPSR_GPSR(IP2_26, DU0_DR6),
+       PINMUX_IPSR_GPSR(IP2_26, LCDOUT6),
+       PINMUX_IPSR_GPSR(IP2_27, DU0_DR7),
+       PINMUX_IPSR_GPSR(IP2_27, LCDOUT7),
+       PINMUX_IPSR_GPSR(IP2_30_28, DU0_DG0),
+       PINMUX_IPSR_GPSR(IP2_30_28, LCDOUT8),
        PINMUX_IPSR_MSEL(IP2_30_28, DREQ1, SEL_EXBUS1_0),
        PINMUX_IPSR_MSEL(IP2_30_28, SCL2, SEL_I2C2_0),
-       PINMUX_IPSR_DATA(IP2_30_28, AUDATA2),
+       PINMUX_IPSR_GPSR(IP2_30_28, AUDATA2),
 
-       PINMUX_IPSR_DATA(IP3_2_0, DU0_DG1),
-       PINMUX_IPSR_DATA(IP3_2_0, LCDOUT9),
-       PINMUX_IPSR_DATA(IP3_2_0, DACK1),
+       PINMUX_IPSR_GPSR(IP3_2_0, DU0_DG1),
+       PINMUX_IPSR_GPSR(IP3_2_0, LCDOUT9),
+       PINMUX_IPSR_GPSR(IP3_2_0, DACK1),
        PINMUX_IPSR_MSEL(IP3_2_0, SDA2, SEL_I2C2_0),
-       PINMUX_IPSR_DATA(IP3_2_0, AUDATA3),
-       PINMUX_IPSR_DATA(IP3_3, DU0_DG2),
-       PINMUX_IPSR_DATA(IP3_3, LCDOUT10),
-       PINMUX_IPSR_DATA(IP3_4, DU0_DG3),
-       PINMUX_IPSR_DATA(IP3_4, LCDOUT11),
-       PINMUX_IPSR_DATA(IP3_5, DU0_DG4),
-       PINMUX_IPSR_DATA(IP3_5, LCDOUT12),
-       PINMUX_IPSR_DATA(IP3_6, DU0_DG5),
-       PINMUX_IPSR_DATA(IP3_6, LCDOUT13),
-       PINMUX_IPSR_DATA(IP3_7, DU0_DG6),
-       PINMUX_IPSR_DATA(IP3_7, LCDOUT14),
-       PINMUX_IPSR_DATA(IP3_8, DU0_DG7),
-       PINMUX_IPSR_DATA(IP3_8, LCDOUT15),
-       PINMUX_IPSR_DATA(IP3_11_9, DU0_DB0),
-       PINMUX_IPSR_DATA(IP3_11_9, LCDOUT16),
-       PINMUX_IPSR_DATA(IP3_11_9, EX_WAIT1),
+       PINMUX_IPSR_GPSR(IP3_2_0, AUDATA3),
+       PINMUX_IPSR_GPSR(IP3_3, DU0_DG2),
+       PINMUX_IPSR_GPSR(IP3_3, LCDOUT10),
+       PINMUX_IPSR_GPSR(IP3_4, DU0_DG3),
+       PINMUX_IPSR_GPSR(IP3_4, LCDOUT11),
+       PINMUX_IPSR_GPSR(IP3_5, DU0_DG4),
+       PINMUX_IPSR_GPSR(IP3_5, LCDOUT12),
+       PINMUX_IPSR_GPSR(IP3_6, DU0_DG5),
+       PINMUX_IPSR_GPSR(IP3_6, LCDOUT13),
+       PINMUX_IPSR_GPSR(IP3_7, DU0_DG6),
+       PINMUX_IPSR_GPSR(IP3_7, LCDOUT14),
+       PINMUX_IPSR_GPSR(IP3_8, DU0_DG7),
+       PINMUX_IPSR_GPSR(IP3_8, LCDOUT15),
+       PINMUX_IPSR_GPSR(IP3_11_9, DU0_DB0),
+       PINMUX_IPSR_GPSR(IP3_11_9, LCDOUT16),
+       PINMUX_IPSR_GPSR(IP3_11_9, EX_WAIT1),
        PINMUX_IPSR_MSEL(IP3_11_9, SCL1, SEL_I2C1_0),
        PINMUX_IPSR_MSEL(IP3_11_9, TCLK1, SEL_TMU1_0),
-       PINMUX_IPSR_DATA(IP3_11_9, AUDATA4),
-       PINMUX_IPSR_DATA(IP3_14_12, DU0_DB1),
-       PINMUX_IPSR_DATA(IP3_14_12, LCDOUT17),
-       PINMUX_IPSR_DATA(IP3_14_12, EX_WAIT2),
+       PINMUX_IPSR_GPSR(IP3_11_9, AUDATA4),
+       PINMUX_IPSR_GPSR(IP3_14_12, DU0_DB1),
+       PINMUX_IPSR_GPSR(IP3_14_12, LCDOUT17),
+       PINMUX_IPSR_GPSR(IP3_14_12, EX_WAIT2),
        PINMUX_IPSR_MSEL(IP3_14_12, SDA1, SEL_I2C1_0),
        PINMUX_IPSR_MSEL(IP3_14_12, GPS_MAG_B, SEL_GPS_1),
-       PINMUX_IPSR_DATA(IP3_14_12, AUDATA5),
+       PINMUX_IPSR_GPSR(IP3_14_12, AUDATA5),
        PINMUX_IPSR_MSEL(IP3_14_12, SCK5_C, SEL_SCIF5_2),
-       PINMUX_IPSR_DATA(IP3_15, DU0_DB2),
-       PINMUX_IPSR_DATA(IP3_15, LCDOUT18),
-       PINMUX_IPSR_DATA(IP3_16, DU0_DB3),
-       PINMUX_IPSR_DATA(IP3_16, LCDOUT19),
-       PINMUX_IPSR_DATA(IP3_17, DU0_DB4),
-       PINMUX_IPSR_DATA(IP3_17, LCDOUT20),
-       PINMUX_IPSR_DATA(IP3_18, DU0_DB5),
-       PINMUX_IPSR_DATA(IP3_18, LCDOUT21),
-       PINMUX_IPSR_DATA(IP3_19, DU0_DB6),
-       PINMUX_IPSR_DATA(IP3_19, LCDOUT22),
-       PINMUX_IPSR_DATA(IP3_20, DU0_DB7),
-       PINMUX_IPSR_DATA(IP3_20, LCDOUT23),
-       PINMUX_IPSR_DATA(IP3_22_21, DU0_DOTCLKIN),
-       PINMUX_IPSR_DATA(IP3_22_21, QSTVA_QVS),
-       PINMUX_IPSR_DATA(IP3_22_21, TX3_D_IRDA_TX_D),
+       PINMUX_IPSR_GPSR(IP3_15, DU0_DB2),
+       PINMUX_IPSR_GPSR(IP3_15, LCDOUT18),
+       PINMUX_IPSR_GPSR(IP3_16, DU0_DB3),
+       PINMUX_IPSR_GPSR(IP3_16, LCDOUT19),
+       PINMUX_IPSR_GPSR(IP3_17, DU0_DB4),
+       PINMUX_IPSR_GPSR(IP3_17, LCDOUT20),
+       PINMUX_IPSR_GPSR(IP3_18, DU0_DB5),
+       PINMUX_IPSR_GPSR(IP3_18, LCDOUT21),
+       PINMUX_IPSR_GPSR(IP3_19, DU0_DB6),
+       PINMUX_IPSR_GPSR(IP3_19, LCDOUT22),
+       PINMUX_IPSR_GPSR(IP3_20, DU0_DB7),
+       PINMUX_IPSR_GPSR(IP3_20, LCDOUT23),
+       PINMUX_IPSR_GPSR(IP3_22_21, DU0_DOTCLKIN),
+       PINMUX_IPSR_GPSR(IP3_22_21, QSTVA_QVS),
+       PINMUX_IPSR_GPSR(IP3_22_21, TX3_D_IRDA_TX_D),
        PINMUX_IPSR_MSEL(IP3_22_21, SCL3_B, SEL_I2C3_1),
-       PINMUX_IPSR_DATA(IP3_23, DU0_DOTCLKOUT0),
-       PINMUX_IPSR_DATA(IP3_23, QCLK),
-       PINMUX_IPSR_DATA(IP3_26_24, DU0_DOTCLKOUT1),
-       PINMUX_IPSR_DATA(IP3_26_24, QSTVB_QVE),
+       PINMUX_IPSR_GPSR(IP3_23, DU0_DOTCLKOUT0),
+       PINMUX_IPSR_GPSR(IP3_23, QCLK),
+       PINMUX_IPSR_GPSR(IP3_26_24, DU0_DOTCLKOUT1),
+       PINMUX_IPSR_GPSR(IP3_26_24, QSTVB_QVE),
        PINMUX_IPSR_MSEL(IP3_26_24, RX3_D_IRDA_RX_D, SEL_SCIF3_3),
        PINMUX_IPSR_MSEL(IP3_26_24, SDA3_B, SEL_I2C3_1),
        PINMUX_IPSR_MSEL(IP3_26_24, SDA2_C, SEL_I2C2_2),
-       PINMUX_IPSR_DATA(IP3_26_24, DACK0_B),
-       PINMUX_IPSR_DATA(IP3_26_24, DRACK0_B),
-       PINMUX_IPSR_DATA(IP3_27, DU0_EXHSYNC_DU0_HSYNC),
-       PINMUX_IPSR_DATA(IP3_27, QSTH_QHS),
-       PINMUX_IPSR_DATA(IP3_28, DU0_EXVSYNC_DU0_VSYNC),
-       PINMUX_IPSR_DATA(IP3_28, QSTB_QHE),
-       PINMUX_IPSR_DATA(IP3_31_29, DU0_EXODDF_DU0_ODDF_DISP_CDE),
-       PINMUX_IPSR_DATA(IP3_31_29, QCPV_QDE),
-       PINMUX_IPSR_DATA(IP3_31_29, CAN1_TX),
-       PINMUX_IPSR_DATA(IP3_31_29, TX2_C),
+       PINMUX_IPSR_GPSR(IP3_26_24, DACK0_B),
+       PINMUX_IPSR_GPSR(IP3_26_24, DRACK0_B),
+       PINMUX_IPSR_GPSR(IP3_27, DU0_EXHSYNC_DU0_HSYNC),
+       PINMUX_IPSR_GPSR(IP3_27, QSTH_QHS),
+       PINMUX_IPSR_GPSR(IP3_28, DU0_EXVSYNC_DU0_VSYNC),
+       PINMUX_IPSR_GPSR(IP3_28, QSTB_QHE),
+       PINMUX_IPSR_GPSR(IP3_31_29, DU0_EXODDF_DU0_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP3_31_29, QCPV_QDE),
+       PINMUX_IPSR_GPSR(IP3_31_29, CAN1_TX),
+       PINMUX_IPSR_GPSR(IP3_31_29, TX2_C),
        PINMUX_IPSR_MSEL(IP3_31_29, SCL2_C, SEL_I2C2_2),
-       PINMUX_IPSR_DATA(IP3_31_29, REMOCON),
+       PINMUX_IPSR_GPSR(IP3_31_29, REMOCON),
 
-       PINMUX_IPSR_DATA(IP4_1_0, DU0_DISP),
-       PINMUX_IPSR_DATA(IP4_1_0, QPOLA),
+       PINMUX_IPSR_GPSR(IP4_1_0, DU0_DISP),
+       PINMUX_IPSR_GPSR(IP4_1_0, QPOLA),
        PINMUX_IPSR_MSEL(IP4_1_0, CAN_CLK_C, SEL_CANCLK_2),
        PINMUX_IPSR_MSEL(IP4_1_0, SCK2_C, SEL_SCIF2_2),
-       PINMUX_IPSR_DATA(IP4_4_2, DU0_CDE),
-       PINMUX_IPSR_DATA(IP4_4_2, QPOLB),
-       PINMUX_IPSR_DATA(IP4_4_2, CAN1_RX),
+       PINMUX_IPSR_GPSR(IP4_4_2, DU0_CDE),
+       PINMUX_IPSR_GPSR(IP4_4_2, QPOLB),
+       PINMUX_IPSR_GPSR(IP4_4_2, CAN1_RX),
        PINMUX_IPSR_MSEL(IP4_4_2, RX2_C, SEL_SCIF2_2),
        PINMUX_IPSR_MSEL(IP4_4_2, DREQ0_B, SEL_EXBUS0_1),
        PINMUX_IPSR_MSEL(IP4_4_2, SSI_SCK78_B, SEL_SSI7_1),
        PINMUX_IPSR_MSEL(IP4_4_2, SCK0_B, SEL_SCIF0_1),
-       PINMUX_IPSR_DATA(IP4_7_5, DU1_DR0),
-       PINMUX_IPSR_DATA(IP4_7_5, VI2_DATA0_VI2_B0),
-       PINMUX_IPSR_DATA(IP4_7_5, PWM6),
-       PINMUX_IPSR_DATA(IP4_7_5, SD3_CLK),
-       PINMUX_IPSR_DATA(IP4_7_5, TX3_E_IRDA_TX_E),
-       PINMUX_IPSR_DATA(IP4_7_5, AUDCK),
+       PINMUX_IPSR_GPSR(IP4_7_5, DU1_DR0),
+       PINMUX_IPSR_GPSR(IP4_7_5, VI2_DATA0_VI2_B0),
+       PINMUX_IPSR_GPSR(IP4_7_5, PWM6),
+       PINMUX_IPSR_GPSR(IP4_7_5, SD3_CLK),
+       PINMUX_IPSR_GPSR(IP4_7_5, TX3_E_IRDA_TX_E),
+       PINMUX_IPSR_GPSR(IP4_7_5, AUDCK),
        PINMUX_IPSR_MSEL(IP4_7_5, PWMFSW0_B, SEL_PWMFSW_1),
-       PINMUX_IPSR_DATA(IP4_10_8, DU1_DR1),
-       PINMUX_IPSR_DATA(IP4_10_8, VI2_DATA1_VI2_B1),
-       PINMUX_IPSR_DATA(IP4_10_8, PWM0),
-       PINMUX_IPSR_DATA(IP4_10_8, SD3_CMD),
+       PINMUX_IPSR_GPSR(IP4_10_8, DU1_DR1),
+       PINMUX_IPSR_GPSR(IP4_10_8, VI2_DATA1_VI2_B1),
+       PINMUX_IPSR_GPSR(IP4_10_8, PWM0),
+       PINMUX_IPSR_GPSR(IP4_10_8, SD3_CMD),
        PINMUX_IPSR_MSEL(IP4_10_8, RX3_E_IRDA_RX_E, SEL_SCIF3_4),
-       PINMUX_IPSR_DATA(IP4_10_8, AUDSYNC),
+       PINMUX_IPSR_GPSR(IP4_10_8, AUDSYNC),
        PINMUX_IPSR_MSEL(IP4_10_8, CTS0_D, SEL_SCIF0_3),
-       PINMUX_IPSR_DATA(IP4_11, DU1_DR2),
-       PINMUX_IPSR_DATA(IP4_11, VI2_G0),
-       PINMUX_IPSR_DATA(IP4_12, DU1_DR3),
-       PINMUX_IPSR_DATA(IP4_12, VI2_G1),
-       PINMUX_IPSR_DATA(IP4_13, DU1_DR4),
-       PINMUX_IPSR_DATA(IP4_13, VI2_G2),
-       PINMUX_IPSR_DATA(IP4_14, DU1_DR5),
-       PINMUX_IPSR_DATA(IP4_14, VI2_G3),
-       PINMUX_IPSR_DATA(IP4_15, DU1_DR6),
-       PINMUX_IPSR_DATA(IP4_15, VI2_G4),
-       PINMUX_IPSR_DATA(IP4_16, DU1_DR7),
-       PINMUX_IPSR_DATA(IP4_16, VI2_G5),
-       PINMUX_IPSR_DATA(IP4_19_17, DU1_DG0),
-       PINMUX_IPSR_DATA(IP4_19_17, VI2_DATA2_VI2_B2),
+       PINMUX_IPSR_GPSR(IP4_11, DU1_DR2),
+       PINMUX_IPSR_GPSR(IP4_11, VI2_G0),
+       PINMUX_IPSR_GPSR(IP4_12, DU1_DR3),
+       PINMUX_IPSR_GPSR(IP4_12, VI2_G1),
+       PINMUX_IPSR_GPSR(IP4_13, DU1_DR4),
+       PINMUX_IPSR_GPSR(IP4_13, VI2_G2),
+       PINMUX_IPSR_GPSR(IP4_14, DU1_DR5),
+       PINMUX_IPSR_GPSR(IP4_14, VI2_G3),
+       PINMUX_IPSR_GPSR(IP4_15, DU1_DR6),
+       PINMUX_IPSR_GPSR(IP4_15, VI2_G4),
+       PINMUX_IPSR_GPSR(IP4_16, DU1_DR7),
+       PINMUX_IPSR_GPSR(IP4_16, VI2_G5),
+       PINMUX_IPSR_GPSR(IP4_19_17, DU1_DG0),
+       PINMUX_IPSR_GPSR(IP4_19_17, VI2_DATA2_VI2_B2),
        PINMUX_IPSR_MSEL(IP4_19_17, SCL1_B, SEL_I2C1_1),
-       PINMUX_IPSR_DATA(IP4_19_17, SD3_DAT2),
+       PINMUX_IPSR_GPSR(IP4_19_17, SD3_DAT2),
        PINMUX_IPSR_MSEL(IP4_19_17, SCK3_E, SEL_SCIF3_4),
-       PINMUX_IPSR_DATA(IP4_19_17, AUDATA6),
-       PINMUX_IPSR_DATA(IP4_19_17, TX0_D),
-       PINMUX_IPSR_DATA(IP4_22_20, DU1_DG1),
-       PINMUX_IPSR_DATA(IP4_22_20, VI2_DATA3_VI2_B3),
+       PINMUX_IPSR_GPSR(IP4_19_17, AUDATA6),
+       PINMUX_IPSR_GPSR(IP4_19_17, TX0_D),
+       PINMUX_IPSR_GPSR(IP4_22_20, DU1_DG1),
+       PINMUX_IPSR_GPSR(IP4_22_20, VI2_DATA3_VI2_B3),
        PINMUX_IPSR_MSEL(IP4_22_20, SDA1_B, SEL_I2C1_1),
-       PINMUX_IPSR_DATA(IP4_22_20, SD3_DAT3),
+       PINMUX_IPSR_GPSR(IP4_22_20, SD3_DAT3),
        PINMUX_IPSR_MSEL(IP4_22_20, SCK5, SEL_SCIF5_0),
-       PINMUX_IPSR_DATA(IP4_22_20, AUDATA7),
+       PINMUX_IPSR_GPSR(IP4_22_20, AUDATA7),
        PINMUX_IPSR_MSEL(IP4_22_20, RX0_D, SEL_SCIF0_3),
-       PINMUX_IPSR_DATA(IP4_23, DU1_DG2),
-       PINMUX_IPSR_DATA(IP4_23, VI2_G6),
-       PINMUX_IPSR_DATA(IP4_24, DU1_DG3),
-       PINMUX_IPSR_DATA(IP4_24, VI2_G7),
-       PINMUX_IPSR_DATA(IP4_25, DU1_DG4),
-       PINMUX_IPSR_DATA(IP4_25, VI2_R0),
-       PINMUX_IPSR_DATA(IP4_26, DU1_DG5),
-       PINMUX_IPSR_DATA(IP4_26, VI2_R1),
-       PINMUX_IPSR_DATA(IP4_27, DU1_DG6),
-       PINMUX_IPSR_DATA(IP4_27, VI2_R2),
-       PINMUX_IPSR_DATA(IP4_28, DU1_DG7),
-       PINMUX_IPSR_DATA(IP4_28, VI2_R3),
-       PINMUX_IPSR_DATA(IP4_31_29, DU1_DB0),
-       PINMUX_IPSR_DATA(IP4_31_29, VI2_DATA4_VI2_B4),
+       PINMUX_IPSR_GPSR(IP4_23, DU1_DG2),
+       PINMUX_IPSR_GPSR(IP4_23, VI2_G6),
+       PINMUX_IPSR_GPSR(IP4_24, DU1_DG3),
+       PINMUX_IPSR_GPSR(IP4_24, VI2_G7),
+       PINMUX_IPSR_GPSR(IP4_25, DU1_DG4),
+       PINMUX_IPSR_GPSR(IP4_25, VI2_R0),
+       PINMUX_IPSR_GPSR(IP4_26, DU1_DG5),
+       PINMUX_IPSR_GPSR(IP4_26, VI2_R1),
+       PINMUX_IPSR_GPSR(IP4_27, DU1_DG6),
+       PINMUX_IPSR_GPSR(IP4_27, VI2_R2),
+       PINMUX_IPSR_GPSR(IP4_28, DU1_DG7),
+       PINMUX_IPSR_GPSR(IP4_28, VI2_R3),
+       PINMUX_IPSR_GPSR(IP4_31_29, DU1_DB0),
+       PINMUX_IPSR_GPSR(IP4_31_29, VI2_DATA4_VI2_B4),
        PINMUX_IPSR_MSEL(IP4_31_29, SCL2_B, SEL_I2C2_1),
-       PINMUX_IPSR_DATA(IP4_31_29, SD3_DAT0),
-       PINMUX_IPSR_DATA(IP4_31_29, TX5),
+       PINMUX_IPSR_GPSR(IP4_31_29, SD3_DAT0),
+       PINMUX_IPSR_GPSR(IP4_31_29, TX5),
        PINMUX_IPSR_MSEL(IP4_31_29, SCK0_D, SEL_SCIF0_3),
 
-       PINMUX_IPSR_DATA(IP5_2_0, DU1_DB1),
-       PINMUX_IPSR_DATA(IP5_2_0, VI2_DATA5_VI2_B5),
+       PINMUX_IPSR_GPSR(IP5_2_0, DU1_DB1),
+       PINMUX_IPSR_GPSR(IP5_2_0, VI2_DATA5_VI2_B5),
        PINMUX_IPSR_MSEL(IP5_2_0, SDA2_B, SEL_I2C2_1),
-       PINMUX_IPSR_DATA(IP5_2_0, SD3_DAT1),
+       PINMUX_IPSR_GPSR(IP5_2_0, SD3_DAT1),
        PINMUX_IPSR_MSEL(IP5_2_0, RX5, SEL_SCIF5_0),
        PINMUX_IPSR_MSEL(IP5_2_0, RTS0_D_TANS_D, SEL_SCIF0_3),
-       PINMUX_IPSR_DATA(IP5_3, DU1_DB2),
-       PINMUX_IPSR_DATA(IP5_3, VI2_R4),
-       PINMUX_IPSR_DATA(IP5_4, DU1_DB3),
-       PINMUX_IPSR_DATA(IP5_4, VI2_R5),
-       PINMUX_IPSR_DATA(IP5_5, DU1_DB4),
-       PINMUX_IPSR_DATA(IP5_5, VI2_R6),
-       PINMUX_IPSR_DATA(IP5_6, DU1_DB5),
-       PINMUX_IPSR_DATA(IP5_6, VI2_R7),
-       PINMUX_IPSR_DATA(IP5_7, DU1_DB6),
+       PINMUX_IPSR_GPSR(IP5_3, DU1_DB2),
+       PINMUX_IPSR_GPSR(IP5_3, VI2_R4),
+       PINMUX_IPSR_GPSR(IP5_4, DU1_DB3),
+       PINMUX_IPSR_GPSR(IP5_4, VI2_R5),
+       PINMUX_IPSR_GPSR(IP5_5, DU1_DB4),
+       PINMUX_IPSR_GPSR(IP5_5, VI2_R6),
+       PINMUX_IPSR_GPSR(IP5_6, DU1_DB5),
+       PINMUX_IPSR_GPSR(IP5_6, VI2_R7),
+       PINMUX_IPSR_GPSR(IP5_7, DU1_DB6),
        PINMUX_IPSR_MSEL(IP5_7, SCL2_D, SEL_I2C2_3),
-       PINMUX_IPSR_DATA(IP5_8, DU1_DB7),
+       PINMUX_IPSR_GPSR(IP5_8, DU1_DB7),
        PINMUX_IPSR_MSEL(IP5_8, SDA2_D, SEL_I2C2_3),
-       PINMUX_IPSR_DATA(IP5_10_9, DU1_DOTCLKIN),
-       PINMUX_IPSR_DATA(IP5_10_9, VI2_CLKENB),
+       PINMUX_IPSR_GPSR(IP5_10_9, DU1_DOTCLKIN),
+       PINMUX_IPSR_GPSR(IP5_10_9, VI2_CLKENB),
        PINMUX_IPSR_MSEL(IP5_10_9, HSPI_CS1, SEL_HSPI1_0),
        PINMUX_IPSR_MSEL(IP5_10_9, SCL1_D, SEL_I2C1_3),
-       PINMUX_IPSR_DATA(IP5_12_11, DU1_DOTCLKOUT),
-       PINMUX_IPSR_DATA(IP5_12_11, VI2_FIELD),
+       PINMUX_IPSR_GPSR(IP5_12_11, DU1_DOTCLKOUT),
+       PINMUX_IPSR_GPSR(IP5_12_11, VI2_FIELD),
        PINMUX_IPSR_MSEL(IP5_12_11, SDA1_D, SEL_I2C1_3),
-       PINMUX_IPSR_DATA(IP5_14_13, DU1_EXHSYNC_DU1_HSYNC),
-       PINMUX_IPSR_DATA(IP5_14_13, VI2_HSYNC),
-       PINMUX_IPSR_DATA(IP5_14_13, VI3_HSYNC),
-       PINMUX_IPSR_DATA(IP5_16_15, DU1_EXVSYNC_DU1_VSYNC),
-       PINMUX_IPSR_DATA(IP5_16_15, VI2_VSYNC),
-       PINMUX_IPSR_DATA(IP5_16_15, VI3_VSYNC),
-       PINMUX_IPSR_DATA(IP5_20_17, DU1_EXODDF_DU1_ODDF_DISP_CDE),
-       PINMUX_IPSR_DATA(IP5_20_17, VI2_CLK),
-       PINMUX_IPSR_DATA(IP5_20_17, TX3_B_IRDA_TX_B),
-       PINMUX_IPSR_DATA(IP5_20_17, SD3_CD),
-       PINMUX_IPSR_DATA(IP5_20_17, HSPI_TX1),
-       PINMUX_IPSR_DATA(IP5_20_17, VI1_CLKENB),
-       PINMUX_IPSR_DATA(IP5_20_17, VI3_CLKENB),
-       PINMUX_IPSR_DATA(IP5_20_17, AUDIO_CLKC),
-       PINMUX_IPSR_DATA(IP5_20_17, TX2_D),
-       PINMUX_IPSR_DATA(IP5_20_17, SPEEDIN),
+       PINMUX_IPSR_GPSR(IP5_14_13, DU1_EXHSYNC_DU1_HSYNC),
+       PINMUX_IPSR_GPSR(IP5_14_13, VI2_HSYNC),
+       PINMUX_IPSR_GPSR(IP5_14_13, VI3_HSYNC),
+       PINMUX_IPSR_GPSR(IP5_16_15, DU1_EXVSYNC_DU1_VSYNC),
+       PINMUX_IPSR_GPSR(IP5_16_15, VI2_VSYNC),
+       PINMUX_IPSR_GPSR(IP5_16_15, VI3_VSYNC),
+       PINMUX_IPSR_GPSR(IP5_20_17, DU1_EXODDF_DU1_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP5_20_17, VI2_CLK),
+       PINMUX_IPSR_GPSR(IP5_20_17, TX3_B_IRDA_TX_B),
+       PINMUX_IPSR_GPSR(IP5_20_17, SD3_CD),
+       PINMUX_IPSR_GPSR(IP5_20_17, HSPI_TX1),
+       PINMUX_IPSR_GPSR(IP5_20_17, VI1_CLKENB),
+       PINMUX_IPSR_GPSR(IP5_20_17, VI3_CLKENB),
+       PINMUX_IPSR_GPSR(IP5_20_17, AUDIO_CLKC),
+       PINMUX_IPSR_GPSR(IP5_20_17, TX2_D),
+       PINMUX_IPSR_GPSR(IP5_20_17, SPEEDIN),
        PINMUX_IPSR_MSEL(IP5_20_17, GPS_SIGN_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP5_23_21, DU1_DISP),
-       PINMUX_IPSR_DATA(IP5_23_21, VI2_DATA6_VI2_B6),
+       PINMUX_IPSR_GPSR(IP5_23_21, DU1_DISP),
+       PINMUX_IPSR_GPSR(IP5_23_21, VI2_DATA6_VI2_B6),
        PINMUX_IPSR_MSEL(IP5_23_21, TCLK0, SEL_TMU0_0),
-       PINMUX_IPSR_DATA(IP5_23_21, QSTVA_B_QVS_B),
+       PINMUX_IPSR_GPSR(IP5_23_21, QSTVA_B_QVS_B),
        PINMUX_IPSR_MSEL(IP5_23_21, HSPI_CLK1, SEL_HSPI1_0),
        PINMUX_IPSR_MSEL(IP5_23_21, SCK2_D, SEL_SCIF2_3),
-       PINMUX_IPSR_DATA(IP5_23_21, AUDIO_CLKOUT_B),
+       PINMUX_IPSR_GPSR(IP5_23_21, AUDIO_CLKOUT_B),
        PINMUX_IPSR_MSEL(IP5_23_21, GPS_MAG_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP5_27_24, DU1_CDE),
-       PINMUX_IPSR_DATA(IP5_27_24, VI2_DATA7_VI2_B7),
+       PINMUX_IPSR_GPSR(IP5_27_24, DU1_CDE),
+       PINMUX_IPSR_GPSR(IP5_27_24, VI2_DATA7_VI2_B7),
        PINMUX_IPSR_MSEL(IP5_27_24, RX3_B_IRDA_RX_B, SEL_SCIF3_1),
-       PINMUX_IPSR_DATA(IP5_27_24, SD3_WP),
+       PINMUX_IPSR_GPSR(IP5_27_24, SD3_WP),
        PINMUX_IPSR_MSEL(IP5_27_24, HSPI_RX1, SEL_HSPI1_0),
-       PINMUX_IPSR_DATA(IP5_27_24, VI1_FIELD),
-       PINMUX_IPSR_DATA(IP5_27_24, VI3_FIELD),
-       PINMUX_IPSR_DATA(IP5_27_24, AUDIO_CLKOUT),
+       PINMUX_IPSR_GPSR(IP5_27_24, VI1_FIELD),
+       PINMUX_IPSR_GPSR(IP5_27_24, VI3_FIELD),
+       PINMUX_IPSR_GPSR(IP5_27_24, AUDIO_CLKOUT),
        PINMUX_IPSR_MSEL(IP5_27_24, RX2_D, SEL_SCIF2_3),
        PINMUX_IPSR_MSEL(IP5_27_24, GPS_CLK_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP5_27_24, GPS_CLK_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP5_28, AUDIO_CLKA),
-       PINMUX_IPSR_DATA(IP5_28, CAN_TXCLK),
-       PINMUX_IPSR_DATA(IP5_30_29, AUDIO_CLKB),
-       PINMUX_IPSR_DATA(IP5_30_29, USB_OVC2),
-       PINMUX_IPSR_DATA(IP5_30_29, CAN_DEBUGOUT0),
-       PINMUX_IPSR_DATA(IP5_30_29, MOUT0),
-
-       PINMUX_IPSR_DATA(IP6_1_0, SSI_SCK0129),
-       PINMUX_IPSR_DATA(IP6_1_0, CAN_DEBUGOUT1),
-       PINMUX_IPSR_DATA(IP6_1_0, MOUT1),
-       PINMUX_IPSR_DATA(IP6_3_2, SSI_WS0129),
-       PINMUX_IPSR_DATA(IP6_3_2, CAN_DEBUGOUT2),
-       PINMUX_IPSR_DATA(IP6_3_2, MOUT2),
-       PINMUX_IPSR_DATA(IP6_5_4, SSI_SDATA0),
-       PINMUX_IPSR_DATA(IP6_5_4, CAN_DEBUGOUT3),
-       PINMUX_IPSR_DATA(IP6_5_4, MOUT5),
-       PINMUX_IPSR_DATA(IP6_7_6, SSI_SDATA1),
-       PINMUX_IPSR_DATA(IP6_7_6, CAN_DEBUGOUT4),
-       PINMUX_IPSR_DATA(IP6_7_6, MOUT6),
-       PINMUX_IPSR_DATA(IP6_8, SSI_SDATA2),
-       PINMUX_IPSR_DATA(IP6_8, CAN_DEBUGOUT5),
-       PINMUX_IPSR_DATA(IP6_11_9, SSI_SCK34),
-       PINMUX_IPSR_DATA(IP6_11_9, CAN_DEBUGOUT6),
-       PINMUX_IPSR_DATA(IP6_11_9, CAN0_TX_B),
+       PINMUX_IPSR_GPSR(IP5_28, AUDIO_CLKA),
+       PINMUX_IPSR_GPSR(IP5_28, CAN_TXCLK),
+       PINMUX_IPSR_GPSR(IP5_30_29, AUDIO_CLKB),
+       PINMUX_IPSR_GPSR(IP5_30_29, USB_OVC2),
+       PINMUX_IPSR_GPSR(IP5_30_29, CAN_DEBUGOUT0),
+       PINMUX_IPSR_GPSR(IP5_30_29, MOUT0),
+
+       PINMUX_IPSR_GPSR(IP6_1_0, SSI_SCK0129),
+       PINMUX_IPSR_GPSR(IP6_1_0, CAN_DEBUGOUT1),
+       PINMUX_IPSR_GPSR(IP6_1_0, MOUT1),
+       PINMUX_IPSR_GPSR(IP6_3_2, SSI_WS0129),
+       PINMUX_IPSR_GPSR(IP6_3_2, CAN_DEBUGOUT2),
+       PINMUX_IPSR_GPSR(IP6_3_2, MOUT2),
+       PINMUX_IPSR_GPSR(IP6_5_4, SSI_SDATA0),
+       PINMUX_IPSR_GPSR(IP6_5_4, CAN_DEBUGOUT3),
+       PINMUX_IPSR_GPSR(IP6_5_4, MOUT5),
+       PINMUX_IPSR_GPSR(IP6_7_6, SSI_SDATA1),
+       PINMUX_IPSR_GPSR(IP6_7_6, CAN_DEBUGOUT4),
+       PINMUX_IPSR_GPSR(IP6_7_6, MOUT6),
+       PINMUX_IPSR_GPSR(IP6_8, SSI_SDATA2),
+       PINMUX_IPSR_GPSR(IP6_8, CAN_DEBUGOUT5),
+       PINMUX_IPSR_GPSR(IP6_11_9, SSI_SCK34),
+       PINMUX_IPSR_GPSR(IP6_11_9, CAN_DEBUGOUT6),
+       PINMUX_IPSR_GPSR(IP6_11_9, CAN0_TX_B),
        PINMUX_IPSR_MSEL(IP6_11_9, IERX, SEL_IE_0),
        PINMUX_IPSR_MSEL(IP6_11_9, SSI_SCK9_C, SEL_SSI9_2),
-       PINMUX_IPSR_DATA(IP6_14_12, SSI_WS34),
-       PINMUX_IPSR_DATA(IP6_14_12, CAN_DEBUGOUT7),
+       PINMUX_IPSR_GPSR(IP6_14_12, SSI_WS34),
+       PINMUX_IPSR_GPSR(IP6_14_12, CAN_DEBUGOUT7),
        PINMUX_IPSR_MSEL(IP6_14_12, CAN0_RX_B, SEL_CAN0_1),
-       PINMUX_IPSR_DATA(IP6_14_12, IETX),
+       PINMUX_IPSR_GPSR(IP6_14_12, IETX),
        PINMUX_IPSR_MSEL(IP6_14_12, SSI_WS9_C, SEL_SSI9_2),
-       PINMUX_IPSR_DATA(IP6_17_15, SSI_SDATA3),
-       PINMUX_IPSR_DATA(IP6_17_15, PWM0_C),
-       PINMUX_IPSR_DATA(IP6_17_15, CAN_DEBUGOUT8),
+       PINMUX_IPSR_GPSR(IP6_17_15, SSI_SDATA3),
+       PINMUX_IPSR_GPSR(IP6_17_15, PWM0_C),
+       PINMUX_IPSR_GPSR(IP6_17_15, CAN_DEBUGOUT8),
        PINMUX_IPSR_MSEL(IP6_17_15, CAN_CLK_B, SEL_CANCLK_1),
        PINMUX_IPSR_MSEL(IP6_17_15, IECLK, SEL_IE_0),
        PINMUX_IPSR_MSEL(IP6_17_15, SCIF_CLK_B, SEL_SCIF_1),
        PINMUX_IPSR_MSEL(IP6_17_15, TCLK0_B, SEL_TMU0_1),
-       PINMUX_IPSR_DATA(IP6_19_18, SSI_SDATA4),
-       PINMUX_IPSR_DATA(IP6_19_18, CAN_DEBUGOUT9),
+       PINMUX_IPSR_GPSR(IP6_19_18, SSI_SDATA4),
+       PINMUX_IPSR_GPSR(IP6_19_18, CAN_DEBUGOUT9),
        PINMUX_IPSR_MSEL(IP6_19_18, SSI_SDATA9_C, SEL_SSI9_2),
-       PINMUX_IPSR_DATA(IP6_22_20, SSI_SCK5),
-       PINMUX_IPSR_DATA(IP6_22_20, ADICLK),
-       PINMUX_IPSR_DATA(IP6_22_20, CAN_DEBUGOUT10),
+       PINMUX_IPSR_GPSR(IP6_22_20, SSI_SCK5),
+       PINMUX_IPSR_GPSR(IP6_22_20, ADICLK),
+       PINMUX_IPSR_GPSR(IP6_22_20, CAN_DEBUGOUT10),
        PINMUX_IPSR_MSEL(IP6_22_20, SCK3, SEL_SCIF3_0),
        PINMUX_IPSR_MSEL(IP6_22_20, TCLK0_D, SEL_TMU0_3),
-       PINMUX_IPSR_DATA(IP6_24_23, SSI_WS5),
+       PINMUX_IPSR_GPSR(IP6_24_23, SSI_WS5),
        PINMUX_IPSR_MSEL(IP6_24_23, ADICS_SAMP, SEL_ADI_0),
-       PINMUX_IPSR_DATA(IP6_24_23, CAN_DEBUGOUT11),
-       PINMUX_IPSR_DATA(IP6_24_23, TX3_IRDA_TX),
-       PINMUX_IPSR_DATA(IP6_26_25, SSI_SDATA5),
+       PINMUX_IPSR_GPSR(IP6_24_23, CAN_DEBUGOUT11),
+       PINMUX_IPSR_GPSR(IP6_24_23, TX3_IRDA_TX),
+       PINMUX_IPSR_GPSR(IP6_26_25, SSI_SDATA5),
        PINMUX_IPSR_MSEL(IP6_26_25, ADIDATA, SEL_ADI_0),
-       PINMUX_IPSR_DATA(IP6_26_25, CAN_DEBUGOUT12),
+       PINMUX_IPSR_GPSR(IP6_26_25, CAN_DEBUGOUT12),
        PINMUX_IPSR_MSEL(IP6_26_25, RX3_IRDA_RX, SEL_SCIF3_0),
-       PINMUX_IPSR_DATA(IP6_30_29, SSI_SCK6),
-       PINMUX_IPSR_DATA(IP6_30_29, ADICHS0),
-       PINMUX_IPSR_DATA(IP6_30_29, CAN0_TX),
+       PINMUX_IPSR_GPSR(IP6_30_29, SSI_SCK6),
+       PINMUX_IPSR_GPSR(IP6_30_29, ADICHS0),
+       PINMUX_IPSR_GPSR(IP6_30_29, CAN0_TX),
        PINMUX_IPSR_MSEL(IP6_30_29, IERX_B, SEL_IE_1),
 
-       PINMUX_IPSR_DATA(IP7_1_0, SSI_WS6),
-       PINMUX_IPSR_DATA(IP7_1_0, ADICHS1),
+       PINMUX_IPSR_GPSR(IP7_1_0, SSI_WS6),
+       PINMUX_IPSR_GPSR(IP7_1_0, ADICHS1),
        PINMUX_IPSR_MSEL(IP7_1_0, CAN0_RX, SEL_CAN0_0),
-       PINMUX_IPSR_DATA(IP7_1_0, IETX_B),
-       PINMUX_IPSR_DATA(IP7_3_2, SSI_SDATA6),
-       PINMUX_IPSR_DATA(IP7_3_2, ADICHS2),
+       PINMUX_IPSR_GPSR(IP7_1_0, IETX_B),
+       PINMUX_IPSR_GPSR(IP7_3_2, SSI_SDATA6),
+       PINMUX_IPSR_GPSR(IP7_3_2, ADICHS2),
        PINMUX_IPSR_MSEL(IP7_3_2, CAN_CLK, SEL_CANCLK_0),
        PINMUX_IPSR_MSEL(IP7_3_2, IECLK_B, SEL_IE_1),
        PINMUX_IPSR_MSEL(IP7_6_4, SSI_SCK78, SEL_SSI7_0),
-       PINMUX_IPSR_DATA(IP7_6_4, CAN_DEBUGOUT13),
+       PINMUX_IPSR_GPSR(IP7_6_4, CAN_DEBUGOUT13),
        PINMUX_IPSR_MSEL(IP7_6_4, IRQ0_B, SEL_INT0_1),
        PINMUX_IPSR_MSEL(IP7_6_4, SSI_SCK9_B, SEL_SSI9_1),
        PINMUX_IPSR_MSEL(IP7_6_4, HSPI_CLK1_C, SEL_HSPI1_2),
        PINMUX_IPSR_MSEL(IP7_9_7, SSI_WS78, SEL_SSI7_0),
-       PINMUX_IPSR_DATA(IP7_9_7, CAN_DEBUGOUT14),
+       PINMUX_IPSR_GPSR(IP7_9_7, CAN_DEBUGOUT14),
        PINMUX_IPSR_MSEL(IP7_9_7, IRQ1_B, SEL_INT1_1),
        PINMUX_IPSR_MSEL(IP7_9_7, SSI_WS9_B, SEL_SSI9_1),
        PINMUX_IPSR_MSEL(IP7_9_7, HSPI_CS1_C, SEL_HSPI1_2),
        PINMUX_IPSR_MSEL(IP7_12_10, SSI_SDATA7, SEL_SSI7_0),
-       PINMUX_IPSR_DATA(IP7_12_10, CAN_DEBUGOUT15),
+       PINMUX_IPSR_GPSR(IP7_12_10, CAN_DEBUGOUT15),
        PINMUX_IPSR_MSEL(IP7_12_10, IRQ2_B, SEL_INT2_1),
        PINMUX_IPSR_MSEL(IP7_12_10, TCLK1_C, SEL_TMU1_2),
-       PINMUX_IPSR_DATA(IP7_12_10, HSPI_TX1_C),
+       PINMUX_IPSR_GPSR(IP7_12_10, HSPI_TX1_C),
        PINMUX_IPSR_MSEL(IP7_14_13, SSI_SDATA8, SEL_SSI8_0),
-       PINMUX_IPSR_DATA(IP7_14_13, VSP),
+       PINMUX_IPSR_GPSR(IP7_14_13, VSP),
        PINMUX_IPSR_MSEL(IP7_14_13, IRQ3_B, SEL_INT3_1),
        PINMUX_IPSR_MSEL(IP7_14_13, HSPI_RX1_C, SEL_HSPI1_2),
-       PINMUX_IPSR_DATA(IP7_16_15, SD0_CLK),
-       PINMUX_IPSR_DATA(IP7_16_15, ATACS01),
+       PINMUX_IPSR_GPSR(IP7_16_15, SD0_CLK),
+       PINMUX_IPSR_GPSR(IP7_16_15, ATACS01),
        PINMUX_IPSR_MSEL(IP7_16_15, SCK1_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP7_18_17, SD0_CMD),
-       PINMUX_IPSR_DATA(IP7_18_17, ATACS11),
-       PINMUX_IPSR_DATA(IP7_18_17, TX1_B),
-       PINMUX_IPSR_DATA(IP7_18_17, CC5_TDO),
-       PINMUX_IPSR_DATA(IP7_20_19, SD0_DAT0),
-       PINMUX_IPSR_DATA(IP7_20_19, ATADIR1),
+       PINMUX_IPSR_GPSR(IP7_18_17, SD0_CMD),
+       PINMUX_IPSR_GPSR(IP7_18_17, ATACS11),
+       PINMUX_IPSR_GPSR(IP7_18_17, TX1_B),
+       PINMUX_IPSR_GPSR(IP7_18_17, CC5_TDO),
+       PINMUX_IPSR_GPSR(IP7_20_19, SD0_DAT0),
+       PINMUX_IPSR_GPSR(IP7_20_19, ATADIR1),
        PINMUX_IPSR_MSEL(IP7_20_19, RX1_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP7_20_19, CC5_TRST),
-       PINMUX_IPSR_DATA(IP7_22_21, SD0_DAT1),
-       PINMUX_IPSR_DATA(IP7_22_21, ATAG1),
+       PINMUX_IPSR_GPSR(IP7_20_19, CC5_TRST),
+       PINMUX_IPSR_GPSR(IP7_22_21, SD0_DAT1),
+       PINMUX_IPSR_GPSR(IP7_22_21, ATAG1),
        PINMUX_IPSR_MSEL(IP7_22_21, SCK2_B, SEL_SCIF2_1),
-       PINMUX_IPSR_DATA(IP7_22_21, CC5_TMS),
-       PINMUX_IPSR_DATA(IP7_24_23, SD0_DAT2),
-       PINMUX_IPSR_DATA(IP7_24_23, ATARD1),
-       PINMUX_IPSR_DATA(IP7_24_23, TX2_B),
-       PINMUX_IPSR_DATA(IP7_24_23, CC5_TCK),
-       PINMUX_IPSR_DATA(IP7_26_25, SD0_DAT3),
-       PINMUX_IPSR_DATA(IP7_26_25, ATAWR1),
+       PINMUX_IPSR_GPSR(IP7_22_21, CC5_TMS),
+       PINMUX_IPSR_GPSR(IP7_24_23, SD0_DAT2),
+       PINMUX_IPSR_GPSR(IP7_24_23, ATARD1),
+       PINMUX_IPSR_GPSR(IP7_24_23, TX2_B),
+       PINMUX_IPSR_GPSR(IP7_24_23, CC5_TCK),
+       PINMUX_IPSR_GPSR(IP7_26_25, SD0_DAT3),
+       PINMUX_IPSR_GPSR(IP7_26_25, ATAWR1),
        PINMUX_IPSR_MSEL(IP7_26_25, RX2_B, SEL_SCIF2_1),
-       PINMUX_IPSR_DATA(IP7_26_25, CC5_TDI),
-       PINMUX_IPSR_DATA(IP7_28_27, SD0_CD),
+       PINMUX_IPSR_GPSR(IP7_26_25, CC5_TDI),
+       PINMUX_IPSR_GPSR(IP7_28_27, SD0_CD),
        PINMUX_IPSR_MSEL(IP7_28_27, DREQ2, SEL_EXBUS2_0),
        PINMUX_IPSR_MSEL(IP7_28_27, RTS1_B_TANS_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP7_30_29, SD0_WP),
-       PINMUX_IPSR_DATA(IP7_30_29, DACK2),
+       PINMUX_IPSR_GPSR(IP7_30_29, SD0_WP),
+       PINMUX_IPSR_GPSR(IP7_30_29, DACK2),
        PINMUX_IPSR_MSEL(IP7_30_29, CTS1_B, SEL_SCIF1_1),
 
-       PINMUX_IPSR_DATA(IP8_3_0, HSPI_CLK0),
+       PINMUX_IPSR_GPSR(IP8_3_0, HSPI_CLK0),
        PINMUX_IPSR_MSEL(IP8_3_0, CTS0, SEL_SCIF0_0),
-       PINMUX_IPSR_DATA(IP8_3_0, USB_OVC0),
-       PINMUX_IPSR_DATA(IP8_3_0, AD_CLK),
-       PINMUX_IPSR_DATA(IP8_3_0, CC5_STATE4),
-       PINMUX_IPSR_DATA(IP8_3_0, CC5_STATE12),
-       PINMUX_IPSR_DATA(IP8_3_0, CC5_STATE20),
-       PINMUX_IPSR_DATA(IP8_3_0, CC5_STATE28),
-       PINMUX_IPSR_DATA(IP8_3_0, CC5_STATE36),
-       PINMUX_IPSR_DATA(IP8_7_4, HSPI_CS0),
+       PINMUX_IPSR_GPSR(IP8_3_0, USB_OVC0),
+       PINMUX_IPSR_GPSR(IP8_3_0, AD_CLK),
+       PINMUX_IPSR_GPSR(IP8_3_0, CC5_STATE4),
+       PINMUX_IPSR_GPSR(IP8_3_0, CC5_STATE12),
+       PINMUX_IPSR_GPSR(IP8_3_0, CC5_STATE20),
+       PINMUX_IPSR_GPSR(IP8_3_0, CC5_STATE28),
+       PINMUX_IPSR_GPSR(IP8_3_0, CC5_STATE36),
+       PINMUX_IPSR_GPSR(IP8_7_4, HSPI_CS0),
        PINMUX_IPSR_MSEL(IP8_7_4, RTS0_TANS, SEL_SCIF0_0),
-       PINMUX_IPSR_DATA(IP8_7_4, USB_OVC1),
-       PINMUX_IPSR_DATA(IP8_7_4, AD_DI),
-       PINMUX_IPSR_DATA(IP8_7_4, CC5_STATE5),
-       PINMUX_IPSR_DATA(IP8_7_4, CC5_STATE13),
-       PINMUX_IPSR_DATA(IP8_7_4, CC5_STATE21),
-       PINMUX_IPSR_DATA(IP8_7_4, CC5_STATE29),
-       PINMUX_IPSR_DATA(IP8_7_4, CC5_STATE37),
-       PINMUX_IPSR_DATA(IP8_11_8, HSPI_TX0),
-       PINMUX_IPSR_DATA(IP8_11_8, TX0),
-       PINMUX_IPSR_DATA(IP8_11_8, CAN_DEBUG_HW_TRIGGER),
-       PINMUX_IPSR_DATA(IP8_11_8, AD_DO),
-       PINMUX_IPSR_DATA(IP8_11_8, CC5_STATE6),
-       PINMUX_IPSR_DATA(IP8_11_8, CC5_STATE14),
-       PINMUX_IPSR_DATA(IP8_11_8, CC5_STATE22),
-       PINMUX_IPSR_DATA(IP8_11_8, CC5_STATE30),
-       PINMUX_IPSR_DATA(IP8_11_8, CC5_STATE38),
-       PINMUX_IPSR_DATA(IP8_15_12, HSPI_RX0),
+       PINMUX_IPSR_GPSR(IP8_7_4, USB_OVC1),
+       PINMUX_IPSR_GPSR(IP8_7_4, AD_DI),
+       PINMUX_IPSR_GPSR(IP8_7_4, CC5_STATE5),
+       PINMUX_IPSR_GPSR(IP8_7_4, CC5_STATE13),
+       PINMUX_IPSR_GPSR(IP8_7_4, CC5_STATE21),
+       PINMUX_IPSR_GPSR(IP8_7_4, CC5_STATE29),
+       PINMUX_IPSR_GPSR(IP8_7_4, CC5_STATE37),
+       PINMUX_IPSR_GPSR(IP8_11_8, HSPI_TX0),
+       PINMUX_IPSR_GPSR(IP8_11_8, TX0),
+       PINMUX_IPSR_GPSR(IP8_11_8, CAN_DEBUG_HW_TRIGGER),
+       PINMUX_IPSR_GPSR(IP8_11_8, AD_DO),
+       PINMUX_IPSR_GPSR(IP8_11_8, CC5_STATE6),
+       PINMUX_IPSR_GPSR(IP8_11_8, CC5_STATE14),
+       PINMUX_IPSR_GPSR(IP8_11_8, CC5_STATE22),
+       PINMUX_IPSR_GPSR(IP8_11_8, CC5_STATE30),
+       PINMUX_IPSR_GPSR(IP8_11_8, CC5_STATE38),
+       PINMUX_IPSR_GPSR(IP8_15_12, HSPI_RX0),
        PINMUX_IPSR_MSEL(IP8_15_12, RX0, SEL_SCIF0_0),
-       PINMUX_IPSR_DATA(IP8_15_12, CAN_STEP0),
-       PINMUX_IPSR_DATA(IP8_15_12, AD_NCS),
-       PINMUX_IPSR_DATA(IP8_15_12, CC5_STATE7),
-       PINMUX_IPSR_DATA(IP8_15_12, CC5_STATE15),
-       PINMUX_IPSR_DATA(IP8_15_12, CC5_STATE23),
-       PINMUX_IPSR_DATA(IP8_15_12, CC5_STATE31),
-       PINMUX_IPSR_DATA(IP8_15_12, CC5_STATE39),
-       PINMUX_IPSR_DATA(IP8_17_16, FMCLK),
-       PINMUX_IPSR_DATA(IP8_17_16, RDS_CLK),
-       PINMUX_IPSR_DATA(IP8_17_16, PCMOE),
-       PINMUX_IPSR_DATA(IP8_18, BPFCLK),
-       PINMUX_IPSR_DATA(IP8_18, PCMWE),
-       PINMUX_IPSR_DATA(IP8_19, FMIN),
-       PINMUX_IPSR_DATA(IP8_19, RDS_DATA),
-       PINMUX_IPSR_DATA(IP8_20, VI0_CLK),
-       PINMUX_IPSR_DATA(IP8_20, MMC1_CLK),
-       PINMUX_IPSR_DATA(IP8_22_21, VI0_CLKENB),
-       PINMUX_IPSR_DATA(IP8_22_21, TX1_C),
-       PINMUX_IPSR_DATA(IP8_22_21, HTX1_B),
-       PINMUX_IPSR_DATA(IP8_22_21, MT1_SYNC),
-       PINMUX_IPSR_DATA(IP8_24_23, VI0_FIELD),
+       PINMUX_IPSR_GPSR(IP8_15_12, CAN_STEP0),
+       PINMUX_IPSR_GPSR(IP8_15_12, AD_NCS),
+       PINMUX_IPSR_GPSR(IP8_15_12, CC5_STATE7),
+       PINMUX_IPSR_GPSR(IP8_15_12, CC5_STATE15),
+       PINMUX_IPSR_GPSR(IP8_15_12, CC5_STATE23),
+       PINMUX_IPSR_GPSR(IP8_15_12, CC5_STATE31),
+       PINMUX_IPSR_GPSR(IP8_15_12, CC5_STATE39),
+       PINMUX_IPSR_GPSR(IP8_17_16, FMCLK),
+       PINMUX_IPSR_GPSR(IP8_17_16, RDS_CLK),
+       PINMUX_IPSR_GPSR(IP8_17_16, PCMOE),
+       PINMUX_IPSR_GPSR(IP8_18, BPFCLK),
+       PINMUX_IPSR_GPSR(IP8_18, PCMWE),
+       PINMUX_IPSR_GPSR(IP8_19, FMIN),
+       PINMUX_IPSR_GPSR(IP8_19, RDS_DATA),
+       PINMUX_IPSR_GPSR(IP8_20, VI0_CLK),
+       PINMUX_IPSR_GPSR(IP8_20, MMC1_CLK),
+       PINMUX_IPSR_GPSR(IP8_22_21, VI0_CLKENB),
+       PINMUX_IPSR_GPSR(IP8_22_21, TX1_C),
+       PINMUX_IPSR_GPSR(IP8_22_21, HTX1_B),
+       PINMUX_IPSR_GPSR(IP8_22_21, MT1_SYNC),
+       PINMUX_IPSR_GPSR(IP8_24_23, VI0_FIELD),
        PINMUX_IPSR_MSEL(IP8_24_23, RX1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP8_24_23, HRX1_B, SEL_HSCIF1_1),
-       PINMUX_IPSR_DATA(IP8_27_25, VI0_HSYNC),
+       PINMUX_IPSR_GPSR(IP8_27_25, VI0_HSYNC),
        PINMUX_IPSR_MSEL(IP8_27_25, VI0_DATA0_B_VI0_B0_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP8_27_25, CTS1_C, SEL_SCIF1_2),
-       PINMUX_IPSR_DATA(IP8_27_25, TX4_D),
-       PINMUX_IPSR_DATA(IP8_27_25, MMC1_CMD),
+       PINMUX_IPSR_GPSR(IP8_27_25, TX4_D),
+       PINMUX_IPSR_GPSR(IP8_27_25, MMC1_CMD),
        PINMUX_IPSR_MSEL(IP8_27_25, HSCK1_B, SEL_HSCIF1_1),
-       PINMUX_IPSR_DATA(IP8_30_28, VI0_VSYNC),
+       PINMUX_IPSR_GPSR(IP8_30_28, VI0_VSYNC),
        PINMUX_IPSR_MSEL(IP8_30_28, VI0_DATA1_B_VI0_B1_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP8_30_28, RTS1_C_TANS_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP8_30_28, RX4_D, SEL_SCIF4_3),
@@ -1189,216 +1189,216 @@ static const u16 pinmux_data[] = {
 
        PINMUX_IPSR_MSEL(IP9_1_0, VI0_DATA0_VI0_B0, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP9_1_0, HRTS1_B, SEL_HSCIF1_1),
-       PINMUX_IPSR_DATA(IP9_1_0, MT1_VCXO),
+       PINMUX_IPSR_GPSR(IP9_1_0, MT1_VCXO),
        PINMUX_IPSR_MSEL(IP9_3_2, VI0_DATA1_VI0_B1, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP9_3_2, HCTS1_B, SEL_HSCIF1_1),
-       PINMUX_IPSR_DATA(IP9_3_2, MT1_PWM),
-       PINMUX_IPSR_DATA(IP9_4, VI0_DATA2_VI0_B2),
-       PINMUX_IPSR_DATA(IP9_4, MMC1_D0),
-       PINMUX_IPSR_DATA(IP9_5, VI0_DATA3_VI0_B3),
-       PINMUX_IPSR_DATA(IP9_5, MMC1_D1),
-       PINMUX_IPSR_DATA(IP9_6, VI0_DATA4_VI0_B4),
-       PINMUX_IPSR_DATA(IP9_6, MMC1_D2),
-       PINMUX_IPSR_DATA(IP9_7, VI0_DATA5_VI0_B5),
-       PINMUX_IPSR_DATA(IP9_7, MMC1_D3),
-       PINMUX_IPSR_DATA(IP9_9_8, VI0_DATA6_VI0_B6),
-       PINMUX_IPSR_DATA(IP9_9_8, MMC1_D4),
-       PINMUX_IPSR_DATA(IP9_9_8, ARM_TRACEDATA_0),
-       PINMUX_IPSR_DATA(IP9_11_10, VI0_DATA7_VI0_B7),
-       PINMUX_IPSR_DATA(IP9_11_10, MMC1_D5),
-       PINMUX_IPSR_DATA(IP9_11_10, ARM_TRACEDATA_1),
-       PINMUX_IPSR_DATA(IP9_13_12, VI0_G0),
+       PINMUX_IPSR_GPSR(IP9_3_2, MT1_PWM),
+       PINMUX_IPSR_GPSR(IP9_4, VI0_DATA2_VI0_B2),
+       PINMUX_IPSR_GPSR(IP9_4, MMC1_D0),
+       PINMUX_IPSR_GPSR(IP9_5, VI0_DATA3_VI0_B3),
+       PINMUX_IPSR_GPSR(IP9_5, MMC1_D1),
+       PINMUX_IPSR_GPSR(IP9_6, VI0_DATA4_VI0_B4),
+       PINMUX_IPSR_GPSR(IP9_6, MMC1_D2),
+       PINMUX_IPSR_GPSR(IP9_7, VI0_DATA5_VI0_B5),
+       PINMUX_IPSR_GPSR(IP9_7, MMC1_D3),
+       PINMUX_IPSR_GPSR(IP9_9_8, VI0_DATA6_VI0_B6),
+       PINMUX_IPSR_GPSR(IP9_9_8, MMC1_D4),
+       PINMUX_IPSR_GPSR(IP9_9_8, ARM_TRACEDATA_0),
+       PINMUX_IPSR_GPSR(IP9_11_10, VI0_DATA7_VI0_B7),
+       PINMUX_IPSR_GPSR(IP9_11_10, MMC1_D5),
+       PINMUX_IPSR_GPSR(IP9_11_10, ARM_TRACEDATA_1),
+       PINMUX_IPSR_GPSR(IP9_13_12, VI0_G0),
        PINMUX_IPSR_MSEL(IP9_13_12, SSI_SCK78_C, SEL_SSI7_2),
        PINMUX_IPSR_MSEL(IP9_13_12, IRQ0, SEL_INT0_0),
-       PINMUX_IPSR_DATA(IP9_13_12, ARM_TRACEDATA_2),
-       PINMUX_IPSR_DATA(IP9_15_14, VI0_G1),
+       PINMUX_IPSR_GPSR(IP9_13_12, ARM_TRACEDATA_2),
+       PINMUX_IPSR_GPSR(IP9_15_14, VI0_G1),
        PINMUX_IPSR_MSEL(IP9_15_14, SSI_WS78_C, SEL_SSI7_2),
        PINMUX_IPSR_MSEL(IP9_15_14, IRQ1, SEL_INT1_0),
-       PINMUX_IPSR_DATA(IP9_15_14, ARM_TRACEDATA_3),
-       PINMUX_IPSR_DATA(IP9_18_16, VI0_G2),
-       PINMUX_IPSR_DATA(IP9_18_16, ETH_TXD1),
-       PINMUX_IPSR_DATA(IP9_18_16, MMC1_D6),
-       PINMUX_IPSR_DATA(IP9_18_16, ARM_TRACEDATA_4),
-       PINMUX_IPSR_DATA(IP9_18_16, TS_SPSYNC0),
-       PINMUX_IPSR_DATA(IP9_21_19, VI0_G3),
-       PINMUX_IPSR_DATA(IP9_21_19, ETH_CRS_DV),
-       PINMUX_IPSR_DATA(IP9_21_19, MMC1_D7),
-       PINMUX_IPSR_DATA(IP9_21_19, ARM_TRACEDATA_5),
-       PINMUX_IPSR_DATA(IP9_21_19, TS_SDAT0),
-       PINMUX_IPSR_DATA(IP9_23_22, VI0_G4),
-       PINMUX_IPSR_DATA(IP9_23_22, ETH_TX_EN),
+       PINMUX_IPSR_GPSR(IP9_15_14, ARM_TRACEDATA_3),
+       PINMUX_IPSR_GPSR(IP9_18_16, VI0_G2),
+       PINMUX_IPSR_GPSR(IP9_18_16, ETH_TXD1),
+       PINMUX_IPSR_GPSR(IP9_18_16, MMC1_D6),
+       PINMUX_IPSR_GPSR(IP9_18_16, ARM_TRACEDATA_4),
+       PINMUX_IPSR_GPSR(IP9_18_16, TS_SPSYNC0),
+       PINMUX_IPSR_GPSR(IP9_21_19, VI0_G3),
+       PINMUX_IPSR_GPSR(IP9_21_19, ETH_CRS_DV),
+       PINMUX_IPSR_GPSR(IP9_21_19, MMC1_D7),
+       PINMUX_IPSR_GPSR(IP9_21_19, ARM_TRACEDATA_5),
+       PINMUX_IPSR_GPSR(IP9_21_19, TS_SDAT0),
+       PINMUX_IPSR_GPSR(IP9_23_22, VI0_G4),
+       PINMUX_IPSR_GPSR(IP9_23_22, ETH_TX_EN),
        PINMUX_IPSR_MSEL(IP9_23_22, SD2_DAT0_B, SEL_SD2_1),
-       PINMUX_IPSR_DATA(IP9_23_22, ARM_TRACEDATA_6),
-       PINMUX_IPSR_DATA(IP9_25_24, VI0_G5),
-       PINMUX_IPSR_DATA(IP9_25_24, ETH_RX_ER),
+       PINMUX_IPSR_GPSR(IP9_23_22, ARM_TRACEDATA_6),
+       PINMUX_IPSR_GPSR(IP9_25_24, VI0_G5),
+       PINMUX_IPSR_GPSR(IP9_25_24, ETH_RX_ER),
        PINMUX_IPSR_MSEL(IP9_25_24, SD2_DAT1_B, SEL_SD2_1),
-       PINMUX_IPSR_DATA(IP9_25_24, ARM_TRACEDATA_7),
-       PINMUX_IPSR_DATA(IP9_27_26, VI0_G6),
-       PINMUX_IPSR_DATA(IP9_27_26, ETH_RXD0),
+       PINMUX_IPSR_GPSR(IP9_25_24, ARM_TRACEDATA_7),
+       PINMUX_IPSR_GPSR(IP9_27_26, VI0_G6),
+       PINMUX_IPSR_GPSR(IP9_27_26, ETH_RXD0),
        PINMUX_IPSR_MSEL(IP9_27_26, SD2_DAT2_B, SEL_SD2_1),
-       PINMUX_IPSR_DATA(IP9_27_26, ARM_TRACEDATA_8),
-       PINMUX_IPSR_DATA(IP9_29_28, VI0_G7),
-       PINMUX_IPSR_DATA(IP9_29_28, ETH_RXD1),
+       PINMUX_IPSR_GPSR(IP9_27_26, ARM_TRACEDATA_8),
+       PINMUX_IPSR_GPSR(IP9_29_28, VI0_G7),
+       PINMUX_IPSR_GPSR(IP9_29_28, ETH_RXD1),
        PINMUX_IPSR_MSEL(IP9_29_28, SD2_DAT3_B, SEL_SD2_1),
-       PINMUX_IPSR_DATA(IP9_29_28, ARM_TRACEDATA_9),
+       PINMUX_IPSR_GPSR(IP9_29_28, ARM_TRACEDATA_9),
 
-       PINMUX_IPSR_DATA(IP10_2_0, VI0_R0),
+       PINMUX_IPSR_GPSR(IP10_2_0, VI0_R0),
        PINMUX_IPSR_MSEL(IP10_2_0, SSI_SDATA7_C, SEL_SSI7_2),
        PINMUX_IPSR_MSEL(IP10_2_0, SCK1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP10_2_0, DREQ1_B, SEL_EXBUS1_0),
-       PINMUX_IPSR_DATA(IP10_2_0, ARM_TRACEDATA_10),
+       PINMUX_IPSR_GPSR(IP10_2_0, ARM_TRACEDATA_10),
        PINMUX_IPSR_MSEL(IP10_2_0, DREQ0_C, SEL_EXBUS0_2),
-       PINMUX_IPSR_DATA(IP10_5_3, VI0_R1),
+       PINMUX_IPSR_GPSR(IP10_5_3, VI0_R1),
        PINMUX_IPSR_MSEL(IP10_5_3, SSI_SDATA8_C, SEL_SSI8_2),
-       PINMUX_IPSR_DATA(IP10_5_3, DACK1_B),
-       PINMUX_IPSR_DATA(IP10_5_3, ARM_TRACEDATA_11),
-       PINMUX_IPSR_DATA(IP10_5_3, DACK0_C),
-       PINMUX_IPSR_DATA(IP10_5_3, DRACK0_C),
-       PINMUX_IPSR_DATA(IP10_8_6, VI0_R2),
-       PINMUX_IPSR_DATA(IP10_8_6, ETH_LINK),
-       PINMUX_IPSR_DATA(IP10_8_6, SD2_CLK_B),
+       PINMUX_IPSR_GPSR(IP10_5_3, DACK1_B),
+       PINMUX_IPSR_GPSR(IP10_5_3, ARM_TRACEDATA_11),
+       PINMUX_IPSR_GPSR(IP10_5_3, DACK0_C),
+       PINMUX_IPSR_GPSR(IP10_5_3, DRACK0_C),
+       PINMUX_IPSR_GPSR(IP10_8_6, VI0_R2),
+       PINMUX_IPSR_GPSR(IP10_8_6, ETH_LINK),
+       PINMUX_IPSR_GPSR(IP10_8_6, SD2_CLK_B),
        PINMUX_IPSR_MSEL(IP10_8_6, IRQ2, SEL_INT2_0),
-       PINMUX_IPSR_DATA(IP10_8_6, ARM_TRACEDATA_12),
-       PINMUX_IPSR_DATA(IP10_11_9, VI0_R3),
-       PINMUX_IPSR_DATA(IP10_11_9, ETH_MAGIC),
+       PINMUX_IPSR_GPSR(IP10_8_6, ARM_TRACEDATA_12),
+       PINMUX_IPSR_GPSR(IP10_11_9, VI0_R3),
+       PINMUX_IPSR_GPSR(IP10_11_9, ETH_MAGIC),
        PINMUX_IPSR_MSEL(IP10_11_9, SD2_CMD_B, SEL_SD2_1),
        PINMUX_IPSR_MSEL(IP10_11_9, IRQ3, SEL_INT3_0),
-       PINMUX_IPSR_DATA(IP10_11_9, ARM_TRACEDATA_13),
-       PINMUX_IPSR_DATA(IP10_14_12, VI0_R4),
-       PINMUX_IPSR_DATA(IP10_14_12, ETH_REFCLK),
+       PINMUX_IPSR_GPSR(IP10_11_9, ARM_TRACEDATA_13),
+       PINMUX_IPSR_GPSR(IP10_14_12, VI0_R4),
+       PINMUX_IPSR_GPSR(IP10_14_12, ETH_REFCLK),
        PINMUX_IPSR_MSEL(IP10_14_12, SD2_CD_B, SEL_SD2_1),
        PINMUX_IPSR_MSEL(IP10_14_12, HSPI_CLK1_B, SEL_HSPI1_1),
-       PINMUX_IPSR_DATA(IP10_14_12, ARM_TRACEDATA_14),
-       PINMUX_IPSR_DATA(IP10_14_12, MT1_CLK),
-       PINMUX_IPSR_DATA(IP10_14_12, TS_SCK0),
-       PINMUX_IPSR_DATA(IP10_17_15, VI0_R5),
-       PINMUX_IPSR_DATA(IP10_17_15, ETH_TXD0),
+       PINMUX_IPSR_GPSR(IP10_14_12, ARM_TRACEDATA_14),
+       PINMUX_IPSR_GPSR(IP10_14_12, MT1_CLK),
+       PINMUX_IPSR_GPSR(IP10_14_12, TS_SCK0),
+       PINMUX_IPSR_GPSR(IP10_17_15, VI0_R5),
+       PINMUX_IPSR_GPSR(IP10_17_15, ETH_TXD0),
        PINMUX_IPSR_MSEL(IP10_17_15, SD2_WP_B, SEL_SD2_1),
        PINMUX_IPSR_MSEL(IP10_17_15, HSPI_CS1_B, SEL_HSPI1_1),
-       PINMUX_IPSR_DATA(IP10_17_15, ARM_TRACEDATA_15),
-       PINMUX_IPSR_DATA(IP10_17_15, MT1_D),
-       PINMUX_IPSR_DATA(IP10_17_15, TS_SDEN0),
-       PINMUX_IPSR_DATA(IP10_20_18, VI0_R6),
-       PINMUX_IPSR_DATA(IP10_20_18, ETH_MDC),
+       PINMUX_IPSR_GPSR(IP10_17_15, ARM_TRACEDATA_15),
+       PINMUX_IPSR_GPSR(IP10_17_15, MT1_D),
+       PINMUX_IPSR_GPSR(IP10_17_15, TS_SDEN0),
+       PINMUX_IPSR_GPSR(IP10_20_18, VI0_R6),
+       PINMUX_IPSR_GPSR(IP10_20_18, ETH_MDC),
        PINMUX_IPSR_MSEL(IP10_20_18, DREQ2_C, SEL_EXBUS2_2),
-       PINMUX_IPSR_DATA(IP10_20_18, HSPI_TX1_B),
-       PINMUX_IPSR_DATA(IP10_20_18, TRACECLK),
-       PINMUX_IPSR_DATA(IP10_20_18, MT1_BEN),
+       PINMUX_IPSR_GPSR(IP10_20_18, HSPI_TX1_B),
+       PINMUX_IPSR_GPSR(IP10_20_18, TRACECLK),
+       PINMUX_IPSR_GPSR(IP10_20_18, MT1_BEN),
        PINMUX_IPSR_MSEL(IP10_20_18, PWMFSW0_D, SEL_PWMFSW_3),
-       PINMUX_IPSR_DATA(IP10_23_21, VI0_R7),
-       PINMUX_IPSR_DATA(IP10_23_21, ETH_MDIO),
-       PINMUX_IPSR_DATA(IP10_23_21, DACK2_C),
+       PINMUX_IPSR_GPSR(IP10_23_21, VI0_R7),
+       PINMUX_IPSR_GPSR(IP10_23_21, ETH_MDIO),
+       PINMUX_IPSR_GPSR(IP10_23_21, DACK2_C),
        PINMUX_IPSR_MSEL(IP10_23_21, HSPI_RX1_B, SEL_HSPI1_1),
        PINMUX_IPSR_MSEL(IP10_23_21, SCIF_CLK_D, SEL_SCIF_3),
-       PINMUX_IPSR_DATA(IP10_23_21, TRACECTL),
-       PINMUX_IPSR_DATA(IP10_23_21, MT1_PEN),
-       PINMUX_IPSR_DATA(IP10_25_24, VI1_CLK),
+       PINMUX_IPSR_GPSR(IP10_23_21, TRACECTL),
+       PINMUX_IPSR_GPSR(IP10_23_21, MT1_PEN),
+       PINMUX_IPSR_GPSR(IP10_25_24, VI1_CLK),
        PINMUX_IPSR_MSEL(IP10_25_24, SIM_D, SEL_SIM_0),
        PINMUX_IPSR_MSEL(IP10_25_24, SDA3, SEL_I2C3_0),
-       PINMUX_IPSR_DATA(IP10_28_26, VI1_HSYNC),
-       PINMUX_IPSR_DATA(IP10_28_26, VI3_CLK),
-       PINMUX_IPSR_DATA(IP10_28_26, SSI_SCK4),
+       PINMUX_IPSR_GPSR(IP10_28_26, VI1_HSYNC),
+       PINMUX_IPSR_GPSR(IP10_28_26, VI3_CLK),
+       PINMUX_IPSR_GPSR(IP10_28_26, SSI_SCK4),
        PINMUX_IPSR_MSEL(IP10_28_26, GPS_SIGN_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP10_28_26, PWMFSW0_E, SEL_PWMFSW_4),
-       PINMUX_IPSR_DATA(IP10_31_29, VI1_VSYNC),
-       PINMUX_IPSR_DATA(IP10_31_29, AUDIO_CLKOUT_C),
-       PINMUX_IPSR_DATA(IP10_31_29, SSI_WS4),
-       PINMUX_IPSR_DATA(IP10_31_29, SIM_CLK),
+       PINMUX_IPSR_GPSR(IP10_31_29, VI1_VSYNC),
+       PINMUX_IPSR_GPSR(IP10_31_29, AUDIO_CLKOUT_C),
+       PINMUX_IPSR_GPSR(IP10_31_29, SSI_WS4),
+       PINMUX_IPSR_GPSR(IP10_31_29, SIM_CLK),
        PINMUX_IPSR_MSEL(IP10_31_29, GPS_MAG_C, SEL_GPS_2),
-       PINMUX_IPSR_DATA(IP10_31_29, SPV_TRST),
+       PINMUX_IPSR_GPSR(IP10_31_29, SPV_TRST),
        PINMUX_IPSR_MSEL(IP10_31_29, SCL3, SEL_I2C3_0),
 
-       PINMUX_IPSR_DATA(IP11_2_0, VI1_DATA0_VI1_B0),
+       PINMUX_IPSR_GPSR(IP11_2_0, VI1_DATA0_VI1_B0),
        PINMUX_IPSR_MSEL(IP11_2_0, SD2_DAT0, SEL_SD2_0),
-       PINMUX_IPSR_DATA(IP11_2_0, SIM_RST),
-       PINMUX_IPSR_DATA(IP11_2_0, SPV_TCK),
-       PINMUX_IPSR_DATA(IP11_2_0, ADICLK_B),
-       PINMUX_IPSR_DATA(IP11_5_3, VI1_DATA1_VI1_B1),
+       PINMUX_IPSR_GPSR(IP11_2_0, SIM_RST),
+       PINMUX_IPSR_GPSR(IP11_2_0, SPV_TCK),
+       PINMUX_IPSR_GPSR(IP11_2_0, ADICLK_B),
+       PINMUX_IPSR_GPSR(IP11_5_3, VI1_DATA1_VI1_B1),
        PINMUX_IPSR_MSEL(IP11_5_3, SD2_DAT1, SEL_SD2_0),
-       PINMUX_IPSR_DATA(IP11_5_3, MT0_CLK),
-       PINMUX_IPSR_DATA(IP11_5_3, SPV_TMS),
+       PINMUX_IPSR_GPSR(IP11_5_3, MT0_CLK),
+       PINMUX_IPSR_GPSR(IP11_5_3, SPV_TMS),
        PINMUX_IPSR_MSEL(IP11_5_3, ADICS_B_SAMP_B, SEL_ADI_1),
-       PINMUX_IPSR_DATA(IP11_8_6, VI1_DATA2_VI1_B2),
+       PINMUX_IPSR_GPSR(IP11_8_6, VI1_DATA2_VI1_B2),
        PINMUX_IPSR_MSEL(IP11_8_6, SD2_DAT2, SEL_SD2_0),
-       PINMUX_IPSR_DATA(IP11_8_6, MT0_D),
-       PINMUX_IPSR_DATA(IP11_8_6, SPVTDI),
+       PINMUX_IPSR_GPSR(IP11_8_6, MT0_D),
+       PINMUX_IPSR_GPSR(IP11_8_6, SPVTDI),
        PINMUX_IPSR_MSEL(IP11_8_6, ADIDATA_B, SEL_ADI_1),
-       PINMUX_IPSR_DATA(IP11_11_9, VI1_DATA3_VI1_B3),
+       PINMUX_IPSR_GPSR(IP11_11_9, VI1_DATA3_VI1_B3),
        PINMUX_IPSR_MSEL(IP11_11_9, SD2_DAT3, SEL_SD2_0),
-       PINMUX_IPSR_DATA(IP11_11_9, MT0_BEN),
-       PINMUX_IPSR_DATA(IP11_11_9, SPV_TDO),
-       PINMUX_IPSR_DATA(IP11_11_9, ADICHS0_B),
-       PINMUX_IPSR_DATA(IP11_14_12, VI1_DATA4_VI1_B4),
-       PINMUX_IPSR_DATA(IP11_14_12, SD2_CLK),
-       PINMUX_IPSR_DATA(IP11_14_12, MT0_PEN),
-       PINMUX_IPSR_DATA(IP11_14_12, SPA_TRST),
+       PINMUX_IPSR_GPSR(IP11_11_9, MT0_BEN),
+       PINMUX_IPSR_GPSR(IP11_11_9, SPV_TDO),
+       PINMUX_IPSR_GPSR(IP11_11_9, ADICHS0_B),
+       PINMUX_IPSR_GPSR(IP11_14_12, VI1_DATA4_VI1_B4),
+       PINMUX_IPSR_GPSR(IP11_14_12, SD2_CLK),
+       PINMUX_IPSR_GPSR(IP11_14_12, MT0_PEN),
+       PINMUX_IPSR_GPSR(IP11_14_12, SPA_TRST),
        PINMUX_IPSR_MSEL(IP11_14_12, HSPI_CLK1_D, SEL_HSPI1_3),
-       PINMUX_IPSR_DATA(IP11_14_12, ADICHS1_B),
-       PINMUX_IPSR_DATA(IP11_17_15, VI1_DATA5_VI1_B5),
+       PINMUX_IPSR_GPSR(IP11_14_12, ADICHS1_B),
+       PINMUX_IPSR_GPSR(IP11_17_15, VI1_DATA5_VI1_B5),
        PINMUX_IPSR_MSEL(IP11_17_15, SD2_CMD, SEL_SD2_0),
-       PINMUX_IPSR_DATA(IP11_17_15, MT0_SYNC),
-       PINMUX_IPSR_DATA(IP11_17_15, SPA_TCK),
+       PINMUX_IPSR_GPSR(IP11_17_15, MT0_SYNC),
+       PINMUX_IPSR_GPSR(IP11_17_15, SPA_TCK),
        PINMUX_IPSR_MSEL(IP11_17_15, HSPI_CS1_D, SEL_HSPI1_3),
-       PINMUX_IPSR_DATA(IP11_17_15, ADICHS2_B),
-       PINMUX_IPSR_DATA(IP11_20_18, VI1_DATA6_VI1_B6),
+       PINMUX_IPSR_GPSR(IP11_17_15, ADICHS2_B),
+       PINMUX_IPSR_GPSR(IP11_20_18, VI1_DATA6_VI1_B6),
        PINMUX_IPSR_MSEL(IP11_20_18, SD2_CD, SEL_SD2_0),
-       PINMUX_IPSR_DATA(IP11_20_18, MT0_VCXO),
-       PINMUX_IPSR_DATA(IP11_20_18, SPA_TMS),
-       PINMUX_IPSR_DATA(IP11_20_18, HSPI_TX1_D),
-       PINMUX_IPSR_DATA(IP11_23_21, VI1_DATA7_VI1_B7),
+       PINMUX_IPSR_GPSR(IP11_20_18, MT0_VCXO),
+       PINMUX_IPSR_GPSR(IP11_20_18, SPA_TMS),
+       PINMUX_IPSR_GPSR(IP11_20_18, HSPI_TX1_D),
+       PINMUX_IPSR_GPSR(IP11_23_21, VI1_DATA7_VI1_B7),
        PINMUX_IPSR_MSEL(IP11_23_21, SD2_WP, SEL_SD2_0),
-       PINMUX_IPSR_DATA(IP11_23_21, MT0_PWM),
-       PINMUX_IPSR_DATA(IP11_23_21, SPA_TDI),
+       PINMUX_IPSR_GPSR(IP11_23_21, MT0_PWM),
+       PINMUX_IPSR_GPSR(IP11_23_21, SPA_TDI),
        PINMUX_IPSR_MSEL(IP11_23_21, HSPI_RX1_D, SEL_HSPI1_3),
-       PINMUX_IPSR_DATA(IP11_26_24, VI1_G0),
-       PINMUX_IPSR_DATA(IP11_26_24, VI3_DATA0),
-       PINMUX_IPSR_DATA(IP11_26_24, TS_SCK1),
+       PINMUX_IPSR_GPSR(IP11_26_24, VI1_G0),
+       PINMUX_IPSR_GPSR(IP11_26_24, VI3_DATA0),
+       PINMUX_IPSR_GPSR(IP11_26_24, TS_SCK1),
        PINMUX_IPSR_MSEL(IP11_26_24, DREQ2_B, SEL_EXBUS2_1),
-       PINMUX_IPSR_DATA(IP11_26_24, TX2),
-       PINMUX_IPSR_DATA(IP11_26_24, SPA_TDO),
+       PINMUX_IPSR_GPSR(IP11_26_24, TX2),
+       PINMUX_IPSR_GPSR(IP11_26_24, SPA_TDO),
        PINMUX_IPSR_MSEL(IP11_26_24, HCTS0_B, SEL_HSCIF0_1),
-       PINMUX_IPSR_DATA(IP11_29_27, VI1_G1),
-       PINMUX_IPSR_DATA(IP11_29_27, VI3_DATA1),
-       PINMUX_IPSR_DATA(IP11_29_27, SSI_SCK1),
-       PINMUX_IPSR_DATA(IP11_29_27, TS_SDEN1),
-       PINMUX_IPSR_DATA(IP11_29_27, DACK2_B),
+       PINMUX_IPSR_GPSR(IP11_29_27, VI1_G1),
+       PINMUX_IPSR_GPSR(IP11_29_27, VI3_DATA1),
+       PINMUX_IPSR_GPSR(IP11_29_27, SSI_SCK1),
+       PINMUX_IPSR_GPSR(IP11_29_27, TS_SDEN1),
+       PINMUX_IPSR_GPSR(IP11_29_27, DACK2_B),
        PINMUX_IPSR_MSEL(IP11_29_27, RX2, SEL_SCIF2_0),
        PINMUX_IPSR_MSEL(IP11_29_27, HRTS0_B, SEL_HSCIF0_1),
 
-       PINMUX_IPSR_DATA(IP12_2_0, VI1_G2),
-       PINMUX_IPSR_DATA(IP12_2_0, VI3_DATA2),
-       PINMUX_IPSR_DATA(IP12_2_0, SSI_WS1),
-       PINMUX_IPSR_DATA(IP12_2_0, TS_SPSYNC1),
+       PINMUX_IPSR_GPSR(IP12_2_0, VI1_G2),
+       PINMUX_IPSR_GPSR(IP12_2_0, VI3_DATA2),
+       PINMUX_IPSR_GPSR(IP12_2_0, SSI_WS1),
+       PINMUX_IPSR_GPSR(IP12_2_0, TS_SPSYNC1),
        PINMUX_IPSR_MSEL(IP12_2_0, SCK2, SEL_SCIF2_0),
        PINMUX_IPSR_MSEL(IP12_2_0, HSCK0_B, SEL_HSCIF0_1),
-       PINMUX_IPSR_DATA(IP12_5_3, VI1_G3),
-       PINMUX_IPSR_DATA(IP12_5_3, VI3_DATA3),
-       PINMUX_IPSR_DATA(IP12_5_3, SSI_SCK2),
-       PINMUX_IPSR_DATA(IP12_5_3, TS_SDAT1),
+       PINMUX_IPSR_GPSR(IP12_5_3, VI1_G3),
+       PINMUX_IPSR_GPSR(IP12_5_3, VI3_DATA3),
+       PINMUX_IPSR_GPSR(IP12_5_3, SSI_SCK2),
+       PINMUX_IPSR_GPSR(IP12_5_3, TS_SDAT1),
        PINMUX_IPSR_MSEL(IP12_5_3, SCL1_C, SEL_I2C1_2),
-       PINMUX_IPSR_DATA(IP12_5_3, HTX0_B),
-       PINMUX_IPSR_DATA(IP12_8_6, VI1_G4),
-       PINMUX_IPSR_DATA(IP12_8_6, VI3_DATA4),
-       PINMUX_IPSR_DATA(IP12_8_6, SSI_WS2),
+       PINMUX_IPSR_GPSR(IP12_5_3, HTX0_B),
+       PINMUX_IPSR_GPSR(IP12_8_6, VI1_G4),
+       PINMUX_IPSR_GPSR(IP12_8_6, VI3_DATA4),
+       PINMUX_IPSR_GPSR(IP12_8_6, SSI_WS2),
        PINMUX_IPSR_MSEL(IP12_8_6, SDA1_C, SEL_I2C1_2),
-       PINMUX_IPSR_DATA(IP12_8_6, SIM_RST_B),
+       PINMUX_IPSR_GPSR(IP12_8_6, SIM_RST_B),
        PINMUX_IPSR_MSEL(IP12_8_6, HRX0_B, SEL_HSCIF0_1),
-       PINMUX_IPSR_DATA(IP12_11_9, VI1_G5),
-       PINMUX_IPSR_DATA(IP12_11_9, VI3_DATA5),
+       PINMUX_IPSR_GPSR(IP12_11_9, VI1_G5),
+       PINMUX_IPSR_GPSR(IP12_11_9, VI3_DATA5),
        PINMUX_IPSR_MSEL(IP12_11_9, GPS_CLK, SEL_GPS_0),
-       PINMUX_IPSR_DATA(IP12_11_9, FSE),
-       PINMUX_IPSR_DATA(IP12_11_9, TX4_B),
+       PINMUX_IPSR_GPSR(IP12_11_9, FSE),
+       PINMUX_IPSR_GPSR(IP12_11_9, TX4_B),
        PINMUX_IPSR_MSEL(IP12_11_9, SIM_D_B, SEL_SIM_1),
-       PINMUX_IPSR_DATA(IP12_14_12, VI1_G6),
-       PINMUX_IPSR_DATA(IP12_14_12, VI3_DATA6),
+       PINMUX_IPSR_GPSR(IP12_14_12, VI1_G6),
+       PINMUX_IPSR_GPSR(IP12_14_12, VI3_DATA6),
        PINMUX_IPSR_MSEL(IP12_14_12, GPS_SIGN, SEL_GPS_0),
-       PINMUX_IPSR_DATA(IP12_14_12, FRB),
+       PINMUX_IPSR_GPSR(IP12_14_12, FRB),
        PINMUX_IPSR_MSEL(IP12_14_12, RX4_B, SEL_SCIF4_1),
-       PINMUX_IPSR_DATA(IP12_14_12, SIM_CLK_B),
-       PINMUX_IPSR_DATA(IP12_17_15, VI1_G7),
-       PINMUX_IPSR_DATA(IP12_17_15, VI3_DATA7),
+       PINMUX_IPSR_GPSR(IP12_14_12, SIM_CLK_B),
+       PINMUX_IPSR_GPSR(IP12_17_15, VI1_G7),
+       PINMUX_IPSR_GPSR(IP12_17_15, VI3_DATA7),
        PINMUX_IPSR_MSEL(IP12_17_15, GPS_MAG, SEL_GPS_0),
-       PINMUX_IPSR_DATA(IP12_17_15, FCE),
+       PINMUX_IPSR_GPSR(IP12_17_15, FCE),
        PINMUX_IPSR_MSEL(IP12_17_15, SCK4_B, SEL_SCIF4_1),
 };
 
index a8b629bc7a557b2f7eccdf459f3700cd36e0d3a9..0f4d48f9400ba001bf4528086657eb89e3246487 100644 (file)
@@ -799,47 +799,47 @@ static const u16 pinmux_data[] = {
        PINMUX_SINGLE(DU_DOTCLKIN0),
        PINMUX_SINGLE(DU_DOTCLKIN2),
 
-       PINMUX_IPSR_DATA(IP0_2_0, D0),
+       PINMUX_IPSR_GPSR(IP0_2_0, D0),
        PINMUX_IPSR_MSEL(IP0_2_0, MSIOF3_SCK_B, SEL_SOF3_1),
        PINMUX_IPSR_MSEL(IP0_2_0, VI3_DATA0, SEL_VI3_0),
        PINMUX_IPSR_MSEL(IP0_2_0, VI0_G4, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP0_2_0, VI0_G4_B, SEL_VI0_1),
-       PINMUX_IPSR_DATA(IP0_5_3, D1),
+       PINMUX_IPSR_GPSR(IP0_5_3, D1),
        PINMUX_IPSR_MSEL(IP0_5_3, MSIOF3_SYNC_B, SEL_SOF3_1),
        PINMUX_IPSR_MSEL(IP0_5_3, VI3_DATA1, SEL_VI3_0),
        PINMUX_IPSR_MSEL(IP0_5_3, VI0_G5, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP0_5_3, VI0_G5_B, SEL_VI0_1),
-       PINMUX_IPSR_DATA(IP0_8_6, D2),
+       PINMUX_IPSR_GPSR(IP0_8_6, D2),
        PINMUX_IPSR_MSEL(IP0_8_6, MSIOF3_RXD_B, SEL_SOF3_1),
        PINMUX_IPSR_MSEL(IP0_8_6, VI3_DATA2, SEL_VI3_0),
        PINMUX_IPSR_MSEL(IP0_8_6, VI0_G6, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP0_8_6, VI0_G6_B, SEL_VI0_1),
-       PINMUX_IPSR_DATA(IP0_11_9, D3),
+       PINMUX_IPSR_GPSR(IP0_11_9, D3),
        PINMUX_IPSR_MSEL(IP0_11_9, MSIOF3_TXD_B, SEL_SOF3_1),
        PINMUX_IPSR_MSEL(IP0_11_9, VI3_DATA3, SEL_VI3_0),
        PINMUX_IPSR_MSEL(IP0_11_9, VI0_G7, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP0_11_9, VI0_G7_B, SEL_VI0_1),
-       PINMUX_IPSR_DATA(IP0_15_12, D4),
+       PINMUX_IPSR_GPSR(IP0_15_12, D4),
        PINMUX_IPSR_MSEL(IP0_15_12, SCIFB1_RXD_F, SEL_SCIFB1_5),
        PINMUX_IPSR_MSEL(IP0_15_12, SCIFB0_RXD_C, SEL_SCIFB_2),
        PINMUX_IPSR_MSEL(IP0_15_12, VI3_DATA4, SEL_VI3_0),
        PINMUX_IPSR_MSEL(IP0_15_12, VI0_R0, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP0_15_12, VI0_R0_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP0_15_12, RX0_B, SEL_SCIF0_1),
-       PINMUX_IPSR_DATA(IP0_19_16, D5),
+       PINMUX_IPSR_GPSR(IP0_19_16, D5),
        PINMUX_IPSR_MSEL(IP0_19_16, SCIFB1_TXD_F, SEL_SCIFB1_5),
        PINMUX_IPSR_MSEL(IP0_19_16, SCIFB0_TXD_C, SEL_SCIFB_2),
        PINMUX_IPSR_MSEL(IP0_19_16, VI3_DATA5, SEL_VI3_0),
        PINMUX_IPSR_MSEL(IP0_19_16, VI0_R1, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP0_19_16, VI0_R1_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP0_19_16, TX0_B, SEL_SCIF0_1),
-       PINMUX_IPSR_DATA(IP0_22_20, D6),
+       PINMUX_IPSR_GPSR(IP0_22_20, D6),
        PINMUX_IPSR_MSEL(IP0_22_20, IIC2_SCL_C, SEL_IIC2_2),
        PINMUX_IPSR_MSEL(IP0_22_20, VI3_DATA6, SEL_VI3_0),
        PINMUX_IPSR_MSEL(IP0_22_20, VI0_R2, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP0_22_20, VI0_R2_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP0_22_20, I2C2_SCL_C, SEL_I2C2_2),
-       PINMUX_IPSR_DATA(IP0_26_23, D7),
+       PINMUX_IPSR_GPSR(IP0_26_23, D7),
        PINMUX_IPSR_MSEL(IP0_26_23, AD_DI_B, SEL_ADI_1),
        PINMUX_IPSR_MSEL(IP0_26_23, IIC2_SDA_C, SEL_IIC2_2),
        PINMUX_IPSR_MSEL(IP0_26_23, VI3_DATA7, SEL_VI3_0),
@@ -847,81 +847,81 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP0_26_23, VI0_R3_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP0_26_23, I2C2_SDA_C, SEL_I2C2_2),
        PINMUX_IPSR_MSEL(IP0_26_23, TCLK1, SEL_TMU1_0),
-       PINMUX_IPSR_DATA(IP0_30_27, D8),
+       PINMUX_IPSR_GPSR(IP0_30_27, D8),
        PINMUX_IPSR_MSEL(IP0_30_27, SCIFA1_SCK_C, SEL_SCIFA1_2),
-       PINMUX_IPSR_DATA(IP0_30_27, AVB_TXD0),
+       PINMUX_IPSR_GPSR(IP0_30_27, AVB_TXD0),
        PINMUX_IPSR_MSEL(IP0_30_27, VI0_G0, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP0_30_27, VI0_G0_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP0_30_27, VI2_DATA0_VI2_B0, SEL_VI2_0),
 
-       PINMUX_IPSR_DATA(IP1_3_0, D9),
+       PINMUX_IPSR_GPSR(IP1_3_0, D9),
        PINMUX_IPSR_MSEL(IP1_3_0, SCIFA1_RXD_C, SEL_SCIFA1_2),
-       PINMUX_IPSR_DATA(IP1_3_0, AVB_TXD1),
+       PINMUX_IPSR_GPSR(IP1_3_0, AVB_TXD1),
        PINMUX_IPSR_MSEL(IP1_3_0, VI0_G1, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP1_3_0, VI0_G1_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP1_3_0, VI2_DATA1_VI2_B1, SEL_VI2_0),
-       PINMUX_IPSR_DATA(IP1_7_4, D10),
+       PINMUX_IPSR_GPSR(IP1_7_4, D10),
        PINMUX_IPSR_MSEL(IP1_7_4, SCIFA1_TXD_C, SEL_SCIFA1_2),
-       PINMUX_IPSR_DATA(IP1_7_4, AVB_TXD2),
+       PINMUX_IPSR_GPSR(IP1_7_4, AVB_TXD2),
        PINMUX_IPSR_MSEL(IP1_7_4, VI0_G2, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP1_7_4, VI0_G2_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP1_7_4, VI2_DATA2_VI2_B2, SEL_VI2_0),
-       PINMUX_IPSR_DATA(IP1_11_8, D11),
+       PINMUX_IPSR_GPSR(IP1_11_8, D11),
        PINMUX_IPSR_MSEL(IP1_11_8, SCIFA1_CTS_N_C, SEL_SCIFA1_2),
-       PINMUX_IPSR_DATA(IP1_11_8, AVB_TXD3),
+       PINMUX_IPSR_GPSR(IP1_11_8, AVB_TXD3),
        PINMUX_IPSR_MSEL(IP1_11_8, VI0_G3, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP1_11_8, VI0_G3_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP1_11_8, VI2_DATA3_VI2_B3, SEL_VI2_0),
-       PINMUX_IPSR_DATA(IP1_14_12, D12),
+       PINMUX_IPSR_GPSR(IP1_14_12, D12),
        PINMUX_IPSR_MSEL(IP1_14_12, SCIFA1_RTS_N_C, SEL_SCIFA1_2),
-       PINMUX_IPSR_DATA(IP1_14_12, AVB_TXD4),
+       PINMUX_IPSR_GPSR(IP1_14_12, AVB_TXD4),
        PINMUX_IPSR_MSEL(IP1_14_12, VI0_HSYNC_N, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP1_14_12, VI0_HSYNC_N_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP1_14_12, VI2_DATA4_VI2_B4, SEL_VI2_0),
-       PINMUX_IPSR_DATA(IP1_17_15, D13),
-       PINMUX_IPSR_DATA(IP1_17_15, AVB_TXD5),
+       PINMUX_IPSR_GPSR(IP1_17_15, D13),
+       PINMUX_IPSR_GPSR(IP1_17_15, AVB_TXD5),
        PINMUX_IPSR_MSEL(IP1_17_15, VI0_VSYNC_N, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP1_17_15, VI0_VSYNC_N_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP1_17_15, VI2_DATA5_VI2_B5, SEL_VI2_0),
-       PINMUX_IPSR_DATA(IP1_21_18, D14),
+       PINMUX_IPSR_GPSR(IP1_21_18, D14),
        PINMUX_IPSR_MSEL(IP1_21_18, SCIFB1_RXD_C, SEL_SCIFB1_2),
-       PINMUX_IPSR_DATA(IP1_21_18, AVB_TXD6),
+       PINMUX_IPSR_GPSR(IP1_21_18, AVB_TXD6),
        PINMUX_IPSR_MSEL(IP1_21_18, RX1_B, SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP1_21_18, VI0_CLKENB, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP1_21_18, VI0_CLKENB_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP1_21_18, VI2_DATA6_VI2_B6, SEL_VI2_0),
-       PINMUX_IPSR_DATA(IP1_25_22, D15),
+       PINMUX_IPSR_GPSR(IP1_25_22, D15),
        PINMUX_IPSR_MSEL(IP1_25_22, SCIFB1_TXD_C, SEL_SCIFB1_2),
-       PINMUX_IPSR_DATA(IP1_25_22, AVB_TXD7),
+       PINMUX_IPSR_GPSR(IP1_25_22, AVB_TXD7),
        PINMUX_IPSR_MSEL(IP1_25_22, TX1_B, SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP1_25_22, VI0_FIELD, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP1_25_22, VI0_FIELD_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP1_25_22, VI2_DATA7_VI2_B7, SEL_VI2_0),
-       PINMUX_IPSR_DATA(IP1_27_26, A0),
-       PINMUX_IPSR_DATA(IP1_27_26, PWM3),
-       PINMUX_IPSR_DATA(IP1_29_28, A1),
-       PINMUX_IPSR_DATA(IP1_29_28, PWM4),
+       PINMUX_IPSR_GPSR(IP1_27_26, A0),
+       PINMUX_IPSR_GPSR(IP1_27_26, PWM3),
+       PINMUX_IPSR_GPSR(IP1_29_28, A1),
+       PINMUX_IPSR_GPSR(IP1_29_28, PWM4),
 
-       PINMUX_IPSR_DATA(IP2_2_0, A2),
-       PINMUX_IPSR_DATA(IP2_2_0, PWM5),
+       PINMUX_IPSR_GPSR(IP2_2_0, A2),
+       PINMUX_IPSR_GPSR(IP2_2_0, PWM5),
        PINMUX_IPSR_MSEL(IP2_2_0, MSIOF1_SS1_B, SEL_SOF1_1),
-       PINMUX_IPSR_DATA(IP2_5_3, A3),
-       PINMUX_IPSR_DATA(IP2_5_3, PWM6),
+       PINMUX_IPSR_GPSR(IP2_5_3, A3),
+       PINMUX_IPSR_GPSR(IP2_5_3, PWM6),
        PINMUX_IPSR_MSEL(IP2_5_3, MSIOF1_SS2_B, SEL_SOF1_1),
-       PINMUX_IPSR_DATA(IP2_8_6, A4),
+       PINMUX_IPSR_GPSR(IP2_8_6, A4),
        PINMUX_IPSR_MSEL(IP2_8_6, MSIOF1_TXD_B, SEL_SOF1_1),
-       PINMUX_IPSR_DATA(IP2_8_6, TPU0TO0),
-       PINMUX_IPSR_DATA(IP2_11_9, A5),
+       PINMUX_IPSR_GPSR(IP2_8_6, TPU0TO0),
+       PINMUX_IPSR_GPSR(IP2_11_9, A5),
        PINMUX_IPSR_MSEL(IP2_11_9, SCIFA1_TXD_B, SEL_SCIFA1_1),
-       PINMUX_IPSR_DATA(IP2_11_9, TPU0TO1),
-       PINMUX_IPSR_DATA(IP2_14_12, A6),
+       PINMUX_IPSR_GPSR(IP2_11_9, TPU0TO1),
+       PINMUX_IPSR_GPSR(IP2_14_12, A6),
        PINMUX_IPSR_MSEL(IP2_14_12, SCIFA1_RTS_N_B, SEL_SCIFA1_1),
-       PINMUX_IPSR_DATA(IP2_14_12, TPU0TO2),
-       PINMUX_IPSR_DATA(IP2_17_15, A7),
+       PINMUX_IPSR_GPSR(IP2_14_12, TPU0TO2),
+       PINMUX_IPSR_GPSR(IP2_17_15, A7),
        PINMUX_IPSR_MSEL(IP2_17_15, SCIFA1_SCK_B, SEL_SCIFA1_1),
-       PINMUX_IPSR_DATA(IP2_17_15, AUDIO_CLKOUT_B),
-       PINMUX_IPSR_DATA(IP2_17_15, TPU0TO3),
-       PINMUX_IPSR_DATA(IP2_21_18, A8),
+       PINMUX_IPSR_GPSR(IP2_17_15, AUDIO_CLKOUT_B),
+       PINMUX_IPSR_GPSR(IP2_17_15, TPU0TO3),
+       PINMUX_IPSR_GPSR(IP2_21_18, A8),
        PINMUX_IPSR_MSEL(IP2_21_18, SCIFA1_RXD_B, SEL_SCIFA1_1),
        PINMUX_IPSR_MSEL(IP2_21_18, SSI_SCK5_B, SEL_SSI5_1),
        PINMUX_IPSR_MSEL(IP2_21_18, VI0_R4, SEL_VI0_0),
@@ -929,7 +929,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP2_21_18, SCIFB2_RXD_C, SEL_SCIFB2_2),
        PINMUX_IPSR_MSEL(IP2_21_18, RX2_B, SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP2_21_18, VI2_DATA0_VI2_B0_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP2_25_22, A9),
+       PINMUX_IPSR_GPSR(IP2_25_22, A9),
        PINMUX_IPSR_MSEL(IP2_25_22, SCIFA1_CTS_N_B, SEL_SCIFA1_1),
        PINMUX_IPSR_MSEL(IP2_25_22, SSI_WS5_B, SEL_SSI5_1),
        PINMUX_IPSR_MSEL(IP2_25_22, VI0_R5, SEL_VI0_0),
@@ -937,392 +937,392 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP2_25_22, SCIFB2_TXD_C, SEL_SCIFB2_2),
        PINMUX_IPSR_MSEL(IP2_25_22, TX2_B, SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP2_25_22, VI2_DATA1_VI2_B1_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP2_28_26, A10),
+       PINMUX_IPSR_GPSR(IP2_28_26, A10),
        PINMUX_IPSR_MSEL(IP2_28_26, SSI_SDATA5_B, SEL_SSI5_1),
-       PINMUX_IPSR_DATA(IP2_28_26, MSIOF2_SYNC),
+       PINMUX_IPSR_GPSR(IP2_28_26, MSIOF2_SYNC),
        PINMUX_IPSR_MSEL(IP2_28_26, VI0_R6, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP2_28_26, VI0_R6_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP2_28_26, VI2_DATA2_VI2_B2_B, SEL_VI2_1),
 
-       PINMUX_IPSR_DATA(IP3_3_0, A11),
+       PINMUX_IPSR_GPSR(IP3_3_0, A11),
        PINMUX_IPSR_MSEL(IP3_3_0, SCIFB2_CTS_N_B, SEL_SCIFB2_1),
-       PINMUX_IPSR_DATA(IP3_3_0, MSIOF2_SCK),
+       PINMUX_IPSR_GPSR(IP3_3_0, MSIOF2_SCK),
        PINMUX_IPSR_MSEL(IP3_3_0, VI1_R0, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP3_3_0, VI1_R0_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP3_3_0, VI2_G0),
+       PINMUX_IPSR_GPSR(IP3_3_0, VI2_G0),
        PINMUX_IPSR_MSEL(IP3_3_0, VI2_DATA3_VI2_B3_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP3_7_4, A12),
+       PINMUX_IPSR_GPSR(IP3_7_4, A12),
        PINMUX_IPSR_MSEL(IP3_7_4, SCIFB2_RXD_B, SEL_SCIFB2_1),
-       PINMUX_IPSR_DATA(IP3_7_4, MSIOF2_TXD),
+       PINMUX_IPSR_GPSR(IP3_7_4, MSIOF2_TXD),
        PINMUX_IPSR_MSEL(IP3_7_4, VI1_R1, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP3_7_4, VI1_R1_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP3_7_4, VI2_G1),
+       PINMUX_IPSR_GPSR(IP3_7_4, VI2_G1),
        PINMUX_IPSR_MSEL(IP3_7_4, VI2_DATA4_VI2_B4_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP3_11_8, A13),
+       PINMUX_IPSR_GPSR(IP3_11_8, A13),
        PINMUX_IPSR_MSEL(IP3_11_8, SCIFB2_RTS_N_B, SEL_SCIFB2_1),
-       PINMUX_IPSR_DATA(IP3_11_8, EX_WAIT2),
-       PINMUX_IPSR_DATA(IP3_11_8, MSIOF2_RXD),
+       PINMUX_IPSR_GPSR(IP3_11_8, EX_WAIT2),
+       PINMUX_IPSR_GPSR(IP3_11_8, MSIOF2_RXD),
        PINMUX_IPSR_MSEL(IP3_11_8, VI1_R2, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP3_11_8, VI1_R2_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP3_11_8, VI2_G2),
+       PINMUX_IPSR_GPSR(IP3_11_8, VI2_G2),
        PINMUX_IPSR_MSEL(IP3_11_8, VI2_DATA5_VI2_B5_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP3_14_12, A14),
+       PINMUX_IPSR_GPSR(IP3_14_12, A14),
        PINMUX_IPSR_MSEL(IP3_14_12, SCIFB2_TXD_B, SEL_SCIFB2_1),
-       PINMUX_IPSR_DATA(IP3_14_12, ATACS11_N),
-       PINMUX_IPSR_DATA(IP3_14_12, MSIOF2_SS1),
-       PINMUX_IPSR_DATA(IP3_17_15, A15),
+       PINMUX_IPSR_GPSR(IP3_14_12, ATACS11_N),
+       PINMUX_IPSR_GPSR(IP3_14_12, MSIOF2_SS1),
+       PINMUX_IPSR_GPSR(IP3_17_15, A15),
        PINMUX_IPSR_MSEL(IP3_17_15, SCIFB2_SCK_B, SEL_SCIFB2_1),
-       PINMUX_IPSR_DATA(IP3_17_15, ATARD1_N),
-       PINMUX_IPSR_DATA(IP3_17_15, MSIOF2_SS2),
-       PINMUX_IPSR_DATA(IP3_19_18, A16),
-       PINMUX_IPSR_DATA(IP3_19_18, ATAWR1_N),
-       PINMUX_IPSR_DATA(IP3_22_20, A17),
+       PINMUX_IPSR_GPSR(IP3_17_15, ATARD1_N),
+       PINMUX_IPSR_GPSR(IP3_17_15, MSIOF2_SS2),
+       PINMUX_IPSR_GPSR(IP3_19_18, A16),
+       PINMUX_IPSR_GPSR(IP3_19_18, ATAWR1_N),
+       PINMUX_IPSR_GPSR(IP3_22_20, A17),
        PINMUX_IPSR_MSEL(IP3_22_20, AD_DO_B, SEL_ADI_1),
-       PINMUX_IPSR_DATA(IP3_22_20, ATADIR1_N),
-       PINMUX_IPSR_DATA(IP3_25_23, A18),
+       PINMUX_IPSR_GPSR(IP3_22_20, ATADIR1_N),
+       PINMUX_IPSR_GPSR(IP3_25_23, A18),
        PINMUX_IPSR_MSEL(IP3_25_23, AD_CLK_B, SEL_ADI_1),
-       PINMUX_IPSR_DATA(IP3_25_23, ATAG1_N),
-       PINMUX_IPSR_DATA(IP3_28_26, A19),
+       PINMUX_IPSR_GPSR(IP3_25_23, ATAG1_N),
+       PINMUX_IPSR_GPSR(IP3_28_26, A19),
        PINMUX_IPSR_MSEL(IP3_28_26, AD_NCS_N_B, SEL_ADI_1),
-       PINMUX_IPSR_DATA(IP3_28_26, ATACS01_N),
+       PINMUX_IPSR_GPSR(IP3_28_26, ATACS01_N),
        PINMUX_IPSR_MSEL(IP3_28_26, EX_WAIT0_B, SEL_LBS_1),
-       PINMUX_IPSR_DATA(IP3_31_29, A20),
-       PINMUX_IPSR_DATA(IP3_31_29, SPCLK),
+       PINMUX_IPSR_GPSR(IP3_31_29, A20),
+       PINMUX_IPSR_GPSR(IP3_31_29, SPCLK),
        PINMUX_IPSR_MSEL(IP3_31_29, VI1_R3, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP3_31_29, VI1_R3_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP3_31_29, VI2_G4),
+       PINMUX_IPSR_GPSR(IP3_31_29, VI2_G4),
 
-       PINMUX_IPSR_DATA(IP4_2_0, A21),
-       PINMUX_IPSR_DATA(IP4_2_0, MOSI_IO0),
+       PINMUX_IPSR_GPSR(IP4_2_0, A21),
+       PINMUX_IPSR_GPSR(IP4_2_0, MOSI_IO0),
        PINMUX_IPSR_MSEL(IP4_2_0, VI1_R4, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_2_0, VI1_R4_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP4_2_0, VI2_G5),
-       PINMUX_IPSR_DATA(IP4_5_3, A22),
-       PINMUX_IPSR_DATA(IP4_5_3, MISO_IO1),
+       PINMUX_IPSR_GPSR(IP4_2_0, VI2_G5),
+       PINMUX_IPSR_GPSR(IP4_5_3, A22),
+       PINMUX_IPSR_GPSR(IP4_5_3, MISO_IO1),
        PINMUX_IPSR_MSEL(IP4_5_3, VI1_R5, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_5_3, VI1_R5_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP4_5_3, VI2_G6),
-       PINMUX_IPSR_DATA(IP4_8_6, A23),
-       PINMUX_IPSR_DATA(IP4_8_6, IO2),
+       PINMUX_IPSR_GPSR(IP4_5_3, VI2_G6),
+       PINMUX_IPSR_GPSR(IP4_8_6, A23),
+       PINMUX_IPSR_GPSR(IP4_8_6, IO2),
        PINMUX_IPSR_MSEL(IP4_8_6, VI1_G7, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_8_6, VI1_G7_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP4_8_6, VI2_G7),
-       PINMUX_IPSR_DATA(IP4_11_9, A24),
-       PINMUX_IPSR_DATA(IP4_11_9, IO3),
+       PINMUX_IPSR_GPSR(IP4_8_6, VI2_G7),
+       PINMUX_IPSR_GPSR(IP4_11_9, A24),
+       PINMUX_IPSR_GPSR(IP4_11_9, IO3),
        PINMUX_IPSR_MSEL(IP4_11_9, VI1_R7, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_11_9, VI1_R7_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP4_11_9, VI2_CLKENB, SEL_VI2_0),
        PINMUX_IPSR_MSEL(IP4_11_9, VI2_CLKENB_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP4_14_12, A25),
-       PINMUX_IPSR_DATA(IP4_14_12, SSL),
+       PINMUX_IPSR_GPSR(IP4_14_12, A25),
+       PINMUX_IPSR_GPSR(IP4_14_12, SSL),
        PINMUX_IPSR_MSEL(IP4_14_12, VI1_G6, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_14_12, VI1_G6_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP4_14_12, VI2_FIELD, SEL_VI2_0),
        PINMUX_IPSR_MSEL(IP4_14_12, VI2_FIELD_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP4_17_15, CS0_N),
+       PINMUX_IPSR_GPSR(IP4_17_15, CS0_N),
        PINMUX_IPSR_MSEL(IP4_17_15, VI1_R6, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_17_15, VI1_R6_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP4_17_15, VI2_G3),
+       PINMUX_IPSR_GPSR(IP4_17_15, VI2_G3),
        PINMUX_IPSR_MSEL(IP4_17_15, MSIOF0_SS2_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP4_20_18, CS1_N_A26),
-       PINMUX_IPSR_DATA(IP4_20_18, SPEEDIN),
+       PINMUX_IPSR_GPSR(IP4_20_18, CS1_N_A26),
+       PINMUX_IPSR_GPSR(IP4_20_18, SPEEDIN),
        PINMUX_IPSR_MSEL(IP4_20_18, VI0_R7, SEL_VI0_0),
        PINMUX_IPSR_MSEL(IP4_20_18, VI0_R7_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP4_20_18, VI2_CLK, SEL_VI2_0),
        PINMUX_IPSR_MSEL(IP4_20_18, VI2_CLK_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP4_23_21, EX_CS0_N),
+       PINMUX_IPSR_GPSR(IP4_23_21, EX_CS0_N),
        PINMUX_IPSR_MSEL(IP4_23_21, HRX1_B, SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP4_23_21, VI1_G5, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_23_21, VI1_G5_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP4_23_21, VI2_R0),
+       PINMUX_IPSR_GPSR(IP4_23_21, VI2_R0),
        PINMUX_IPSR_MSEL(IP4_23_21, HTX0_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP4_23_21, MSIOF0_SS1_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP4_26_24, EX_CS1_N),
-       PINMUX_IPSR_DATA(IP4_26_24, GPS_CLK),
+       PINMUX_IPSR_GPSR(IP4_26_24, EX_CS1_N),
+       PINMUX_IPSR_GPSR(IP4_26_24, GPS_CLK),
        PINMUX_IPSR_MSEL(IP4_26_24, HCTS1_N_B, SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP4_26_24, VI1_FIELD, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_26_24, VI1_FIELD_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP4_26_24, VI2_R1),
-       PINMUX_IPSR_DATA(IP4_29_27, EX_CS2_N),
-       PINMUX_IPSR_DATA(IP4_29_27, GPS_SIGN),
+       PINMUX_IPSR_GPSR(IP4_26_24, VI2_R1),
+       PINMUX_IPSR_GPSR(IP4_29_27, EX_CS2_N),
+       PINMUX_IPSR_GPSR(IP4_29_27, GPS_SIGN),
        PINMUX_IPSR_MSEL(IP4_29_27, HRTS1_N_B, SEL_HSCIF1_1),
-       PINMUX_IPSR_DATA(IP4_29_27, VI3_CLKENB),
+       PINMUX_IPSR_GPSR(IP4_29_27, VI3_CLKENB),
        PINMUX_IPSR_MSEL(IP4_29_27, VI1_G0, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP4_29_27, VI1_G0_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP4_29_27, VI2_R2),
+       PINMUX_IPSR_GPSR(IP4_29_27, VI2_R2),
 
-       PINMUX_IPSR_DATA(IP5_2_0, EX_CS3_N),
-       PINMUX_IPSR_DATA(IP5_2_0, GPS_MAG),
-       PINMUX_IPSR_DATA(IP5_2_0, VI3_FIELD),
+       PINMUX_IPSR_GPSR(IP5_2_0, EX_CS3_N),
+       PINMUX_IPSR_GPSR(IP5_2_0, GPS_MAG),
+       PINMUX_IPSR_GPSR(IP5_2_0, VI3_FIELD),
        PINMUX_IPSR_MSEL(IP5_2_0, VI1_G1, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP5_2_0, VI1_G1_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP5_2_0, VI2_R3),
-       PINMUX_IPSR_DATA(IP5_5_3, EX_CS4_N),
+       PINMUX_IPSR_GPSR(IP5_2_0, VI2_R3),
+       PINMUX_IPSR_GPSR(IP5_5_3, EX_CS4_N),
        PINMUX_IPSR_MSEL(IP5_5_3, MSIOF1_SCK_B, SEL_SOF1_1),
-       PINMUX_IPSR_DATA(IP5_5_3, VI3_HSYNC_N),
+       PINMUX_IPSR_GPSR(IP5_5_3, VI3_HSYNC_N),
        PINMUX_IPSR_MSEL(IP5_5_3, VI2_HSYNC_N, SEL_VI2_0),
        PINMUX_IPSR_MSEL(IP5_5_3, IIC1_SCL, SEL_IIC1_0),
        PINMUX_IPSR_MSEL(IP5_5_3, VI2_HSYNC_N_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP5_5_3, INTC_EN0_N),
+       PINMUX_IPSR_GPSR(IP5_5_3, INTC_EN0_N),
        PINMUX_IPSR_MSEL(IP5_5_3, I2C1_SCL, SEL_I2C1_0),
-       PINMUX_IPSR_DATA(IP5_9_6, EX_CS5_N),
+       PINMUX_IPSR_GPSR(IP5_9_6, EX_CS5_N),
        PINMUX_IPSR_MSEL(IP5_9_6, CAN0_RX, SEL_CAN0_0),
        PINMUX_IPSR_MSEL(IP5_9_6, MSIOF1_RXD_B, SEL_SOF1_1),
-       PINMUX_IPSR_DATA(IP5_9_6, VI3_VSYNC_N),
+       PINMUX_IPSR_GPSR(IP5_9_6, VI3_VSYNC_N),
        PINMUX_IPSR_MSEL(IP5_9_6, VI1_G2, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP5_9_6, VI1_G2_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP5_9_6, VI2_R4),
+       PINMUX_IPSR_GPSR(IP5_9_6, VI2_R4),
        PINMUX_IPSR_MSEL(IP5_9_6, IIC1_SDA, SEL_IIC1_0),
-       PINMUX_IPSR_DATA(IP5_9_6, INTC_EN1_N),
+       PINMUX_IPSR_GPSR(IP5_9_6, INTC_EN1_N),
        PINMUX_IPSR_MSEL(IP5_9_6, I2C1_SDA, SEL_I2C1_0),
-       PINMUX_IPSR_DATA(IP5_12_10, BS_N),
+       PINMUX_IPSR_GPSR(IP5_12_10, BS_N),
        PINMUX_IPSR_MSEL(IP5_12_10, IETX, SEL_IEB_0),
        PINMUX_IPSR_MSEL(IP5_12_10, HTX1_B, SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP5_12_10, CAN1_TX, SEL_CAN1_0),
-       PINMUX_IPSR_DATA(IP5_12_10, DRACK0),
+       PINMUX_IPSR_GPSR(IP5_12_10, DRACK0),
        PINMUX_IPSR_MSEL(IP5_12_10, IETX_C, SEL_IEB_2),
-       PINMUX_IPSR_DATA(IP5_14_13, RD_N),
+       PINMUX_IPSR_GPSR(IP5_14_13, RD_N),
        PINMUX_IPSR_MSEL(IP5_14_13, CAN0_TX, SEL_CAN0_0),
        PINMUX_IPSR_MSEL(IP5_14_13, SCIFA0_SCK_B, SEL_SCFA_1),
-       PINMUX_IPSR_DATA(IP5_17_15, RD_WR_N),
+       PINMUX_IPSR_GPSR(IP5_17_15, RD_WR_N),
        PINMUX_IPSR_MSEL(IP5_17_15, VI1_G3, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP5_17_15, VI1_G3_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP5_17_15, VI2_R5),
+       PINMUX_IPSR_GPSR(IP5_17_15, VI2_R5),
        PINMUX_IPSR_MSEL(IP5_17_15, SCIFA0_RXD_B, SEL_SCFA_1),
-       PINMUX_IPSR_DATA(IP5_17_15, INTC_IRQ4_N),
-       PINMUX_IPSR_DATA(IP5_20_18, WE0_N),
+       PINMUX_IPSR_GPSR(IP5_17_15, INTC_IRQ4_N),
+       PINMUX_IPSR_GPSR(IP5_20_18, WE0_N),
        PINMUX_IPSR_MSEL(IP5_20_18, IECLK, SEL_IEB_0),
        PINMUX_IPSR_MSEL(IP5_20_18, CAN_CLK, SEL_CANCLK_0),
        PINMUX_IPSR_MSEL(IP5_20_18, VI2_VSYNC_N, SEL_VI2_0),
        PINMUX_IPSR_MSEL(IP5_20_18, SCIFA0_TXD_B, SEL_SCFA_1),
        PINMUX_IPSR_MSEL(IP5_20_18, VI2_VSYNC_N_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP5_23_21, WE1_N),
+       PINMUX_IPSR_GPSR(IP5_23_21, WE1_N),
        PINMUX_IPSR_MSEL(IP5_23_21, IERX, SEL_IEB_0),
        PINMUX_IPSR_MSEL(IP5_23_21, CAN1_RX, SEL_CAN1_0),
        PINMUX_IPSR_MSEL(IP5_23_21, VI1_G4, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP5_23_21, VI1_G4_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP5_23_21, VI2_R6),
+       PINMUX_IPSR_GPSR(IP5_23_21, VI2_R6),
        PINMUX_IPSR_MSEL(IP5_23_21, SCIFA0_CTS_N_B, SEL_SCFA_1),
        PINMUX_IPSR_MSEL(IP5_23_21, IERX_C, SEL_IEB_2),
        PINMUX_IPSR_MSEL(IP5_26_24, EX_WAIT0, SEL_LBS_0),
-       PINMUX_IPSR_DATA(IP5_26_24, IRQ3),
-       PINMUX_IPSR_DATA(IP5_26_24, INTC_IRQ3_N),
+       PINMUX_IPSR_GPSR(IP5_26_24, IRQ3),
+       PINMUX_IPSR_GPSR(IP5_26_24, INTC_IRQ3_N),
        PINMUX_IPSR_MSEL(IP5_26_24, VI3_CLK, SEL_VI3_0),
        PINMUX_IPSR_MSEL(IP5_26_24, SCIFA0_RTS_N_B, SEL_SCFA_1),
        PINMUX_IPSR_MSEL(IP5_26_24, HRX0_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP5_26_24, MSIOF0_SCK_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP5_29_27, DREQ0_N),
+       PINMUX_IPSR_GPSR(IP5_29_27, DREQ0_N),
        PINMUX_IPSR_MSEL(IP5_29_27, VI1_HSYNC_N, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP5_29_27, VI1_HSYNC_N_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP5_29_27, VI2_R7),
+       PINMUX_IPSR_GPSR(IP5_29_27, VI2_R7),
        PINMUX_IPSR_MSEL(IP5_29_27, SSI_SCK78_C, SEL_SSI7_2),
        PINMUX_IPSR_MSEL(IP5_29_27, SSI_WS78_B, SEL_SSI7_1),
 
-       PINMUX_IPSR_DATA(IP6_2_0, DACK0),
-       PINMUX_IPSR_DATA(IP6_2_0, IRQ0),
-       PINMUX_IPSR_DATA(IP6_2_0, INTC_IRQ0_N),
+       PINMUX_IPSR_GPSR(IP6_2_0, DACK0),
+       PINMUX_IPSR_GPSR(IP6_2_0, IRQ0),
+       PINMUX_IPSR_GPSR(IP6_2_0, INTC_IRQ0_N),
        PINMUX_IPSR_MSEL(IP6_2_0, SSI_SCK6_B, SEL_SSI6_1),
        PINMUX_IPSR_MSEL(IP6_2_0, VI1_VSYNC_N, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP6_2_0, VI1_VSYNC_N_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP6_2_0, SSI_WS78_C, SEL_SSI7_2),
-       PINMUX_IPSR_DATA(IP6_5_3, DREQ1_N),
+       PINMUX_IPSR_GPSR(IP6_5_3, DREQ1_N),
        PINMUX_IPSR_MSEL(IP6_5_3, VI1_CLKENB, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP6_5_3, VI1_CLKENB_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP6_5_3, SSI_SDATA7_C, SEL_SSI7_2),
        PINMUX_IPSR_MSEL(IP6_5_3, SSI_SCK78_B, SEL_SSI7_1),
-       PINMUX_IPSR_DATA(IP6_8_6, DACK1),
-       PINMUX_IPSR_DATA(IP6_8_6, IRQ1),
-       PINMUX_IPSR_DATA(IP6_8_6, INTC_IRQ1_N),
+       PINMUX_IPSR_GPSR(IP6_8_6, DACK1),
+       PINMUX_IPSR_GPSR(IP6_8_6, IRQ1),
+       PINMUX_IPSR_GPSR(IP6_8_6, INTC_IRQ1_N),
        PINMUX_IPSR_MSEL(IP6_8_6, SSI_WS6_B, SEL_SSI6_1),
        PINMUX_IPSR_MSEL(IP6_8_6, SSI_SDATA8_C, SEL_SSI8_2),
-       PINMUX_IPSR_DATA(IP6_10_9, DREQ2_N),
+       PINMUX_IPSR_GPSR(IP6_10_9, DREQ2_N),
        PINMUX_IPSR_MSEL(IP6_10_9, HSCK1_B, SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP6_10_9, HCTS0_N_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP6_10_9, MSIOF0_TXD_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP6_13_11, DACK2),
-       PINMUX_IPSR_DATA(IP6_13_11, IRQ2),
-       PINMUX_IPSR_DATA(IP6_13_11, INTC_IRQ2_N),
+       PINMUX_IPSR_GPSR(IP6_13_11, DACK2),
+       PINMUX_IPSR_GPSR(IP6_13_11, IRQ2),
+       PINMUX_IPSR_GPSR(IP6_13_11, INTC_IRQ2_N),
        PINMUX_IPSR_MSEL(IP6_13_11, SSI_SDATA6_B, SEL_SSI6_1),
        PINMUX_IPSR_MSEL(IP6_13_11, HRTS0_N_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP6_13_11, MSIOF0_RXD_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP6_16_14, ETH_CRS_DV),
+       PINMUX_IPSR_GPSR(IP6_16_14, ETH_CRS_DV),
        PINMUX_IPSR_MSEL(IP6_16_14, STP_ISCLK_0_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP6_16_14, TS_SDEN0_D, SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP6_16_14, GLO_Q0_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP6_16_14, IIC2_SCL_E, SEL_IIC2_4),
        PINMUX_IPSR_MSEL(IP6_16_14, I2C2_SCL_E, SEL_I2C2_4),
-       PINMUX_IPSR_DATA(IP6_19_17, ETH_RX_ER),
+       PINMUX_IPSR_GPSR(IP6_19_17, ETH_RX_ER),
        PINMUX_IPSR_MSEL(IP6_19_17, STP_ISD_0_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP6_19_17, TS_SPSYNC0_D, SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP6_19_17, GLO_Q1_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP6_19_17, IIC2_SDA_E, SEL_IIC2_4),
        PINMUX_IPSR_MSEL(IP6_19_17, I2C2_SDA_E, SEL_I2C2_4),
-       PINMUX_IPSR_DATA(IP6_22_20, ETH_RXD0),
+       PINMUX_IPSR_GPSR(IP6_22_20, ETH_RXD0),
        PINMUX_IPSR_MSEL(IP6_22_20, STP_ISEN_0_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP6_22_20, TS_SDAT0_D, SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP6_22_20, GLO_I0_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP6_22_20, SCIFB1_SCK_G, SEL_SCIFB1_6),
        PINMUX_IPSR_MSEL(IP6_22_20, SCK1_E, SEL_SCIF1_4),
-       PINMUX_IPSR_DATA(IP6_25_23, ETH_RXD1),
+       PINMUX_IPSR_GPSR(IP6_25_23, ETH_RXD1),
        PINMUX_IPSR_MSEL(IP6_25_23, HRX0_E, SEL_HSCIF0_4),
        PINMUX_IPSR_MSEL(IP6_25_23, STP_ISSYNC_0_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP6_25_23, TS_SCK0_D, SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP6_25_23, GLO_I1_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP6_25_23, SCIFB1_RXD_G, SEL_SCIFB1_6),
        PINMUX_IPSR_MSEL(IP6_25_23, RX1_E, SEL_SCIF1_4),
-       PINMUX_IPSR_DATA(IP6_28_26, ETH_LINK),
+       PINMUX_IPSR_GPSR(IP6_28_26, ETH_LINK),
        PINMUX_IPSR_MSEL(IP6_28_26, HTX0_E, SEL_HSCIF0_4),
        PINMUX_IPSR_MSEL(IP6_28_26, STP_IVCXO27_0_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP6_28_26, SCIFB1_TXD_G, SEL_SCIFB1_6),
        PINMUX_IPSR_MSEL(IP6_28_26, TX1_E, SEL_SCIF1_4),
-       PINMUX_IPSR_DATA(IP6_31_29, ETH_REF_CLK),
+       PINMUX_IPSR_GPSR(IP6_31_29, ETH_REF_CLK),
        PINMUX_IPSR_MSEL(IP6_31_29, HCTS0_N_E, SEL_HSCIF0_4),
        PINMUX_IPSR_MSEL(IP6_31_29, STP_IVCXO27_1_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP6_31_29, HRX0_F, SEL_HSCIF0_5),
 
-       PINMUX_IPSR_DATA(IP7_2_0, ETH_MDIO),
+       PINMUX_IPSR_GPSR(IP7_2_0, ETH_MDIO),
        PINMUX_IPSR_MSEL(IP7_2_0, HRTS0_N_E, SEL_HSCIF0_4),
        PINMUX_IPSR_MSEL(IP7_2_0, SIM0_D_C, SEL_SIM_2),
        PINMUX_IPSR_MSEL(IP7_2_0, HCTS0_N_F, SEL_HSCIF0_5),
-       PINMUX_IPSR_DATA(IP7_5_3, ETH_TXD1),
+       PINMUX_IPSR_GPSR(IP7_5_3, ETH_TXD1),
        PINMUX_IPSR_MSEL(IP7_5_3, HTX0_F, SEL_HSCIF0_5),
        PINMUX_IPSR_MSEL(IP7_5_3, BPFCLK_G, SEL_FM_6),
-       PINMUX_IPSR_DATA(IP7_7_6, ETH_TX_EN),
+       PINMUX_IPSR_GPSR(IP7_7_6, ETH_TX_EN),
        PINMUX_IPSR_MSEL(IP7_7_6, SIM0_CLK_C, SEL_SIM_2),
        PINMUX_IPSR_MSEL(IP7_7_6, HRTS0_N_F, SEL_HSCIF0_5),
-       PINMUX_IPSR_DATA(IP7_9_8, ETH_MAGIC),
+       PINMUX_IPSR_GPSR(IP7_9_8, ETH_MAGIC),
        PINMUX_IPSR_MSEL(IP7_9_8, SIM0_RST_C, SEL_SIM_2),
-       PINMUX_IPSR_DATA(IP7_12_10, ETH_TXD0),
+       PINMUX_IPSR_GPSR(IP7_12_10, ETH_TXD0),
        PINMUX_IPSR_MSEL(IP7_12_10, STP_ISCLK_1_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP7_12_10, TS_SDEN1_C, SEL_TSIF1_2),
        PINMUX_IPSR_MSEL(IP7_12_10, GLO_SCLK_C, SEL_GPS_2),
-       PINMUX_IPSR_DATA(IP7_15_13, ETH_MDC),
+       PINMUX_IPSR_GPSR(IP7_15_13, ETH_MDC),
        PINMUX_IPSR_MSEL(IP7_15_13, STP_ISD_1_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP7_15_13, TS_SPSYNC1_C, SEL_TSIF1_2),
        PINMUX_IPSR_MSEL(IP7_15_13, GLO_SDATA_C, SEL_GPS_2),
-       PINMUX_IPSR_DATA(IP7_18_16, PWM0),
+       PINMUX_IPSR_GPSR(IP7_18_16, PWM0),
        PINMUX_IPSR_MSEL(IP7_18_16, SCIFA2_SCK_C, SEL_SCIFA2_2),
        PINMUX_IPSR_MSEL(IP7_18_16, STP_ISEN_1_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP7_18_16, TS_SDAT1_C, SEL_TSIF1_2),
        PINMUX_IPSR_MSEL(IP7_18_16, GLO_SS_C, SEL_GPS_2),
-       PINMUX_IPSR_DATA(IP7_21_19, PWM1),
+       PINMUX_IPSR_GPSR(IP7_21_19, PWM1),
        PINMUX_IPSR_MSEL(IP7_21_19, SCIFA2_TXD_C, SEL_SCIFA2_2),
        PINMUX_IPSR_MSEL(IP7_21_19, STP_ISSYNC_1_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP7_21_19, TS_SCK1_C, SEL_TSIF1_2),
        PINMUX_IPSR_MSEL(IP7_21_19, GLO_RFON_C, SEL_GPS_2),
-       PINMUX_IPSR_DATA(IP7_21_19, PCMOE_N),
-       PINMUX_IPSR_DATA(IP7_24_22, PWM2),
-       PINMUX_IPSR_DATA(IP7_24_22, PWMFSW0),
+       PINMUX_IPSR_GPSR(IP7_21_19, PCMOE_N),
+       PINMUX_IPSR_GPSR(IP7_24_22, PWM2),
+       PINMUX_IPSR_GPSR(IP7_24_22, PWMFSW0),
        PINMUX_IPSR_MSEL(IP7_24_22, SCIFA2_RXD_C, SEL_SCIFA2_2),
-       PINMUX_IPSR_DATA(IP7_24_22, PCMWE_N),
+       PINMUX_IPSR_GPSR(IP7_24_22, PCMWE_N),
        PINMUX_IPSR_MSEL(IP7_24_22, IECLK_C, SEL_IEB_2),
-       PINMUX_IPSR_DATA(IP7_26_25, DU_DOTCLKIN1),
-       PINMUX_IPSR_DATA(IP7_26_25, AUDIO_CLKC),
-       PINMUX_IPSR_DATA(IP7_26_25, AUDIO_CLKOUT_C),
+       PINMUX_IPSR_GPSR(IP7_26_25, DU_DOTCLKIN1),
+       PINMUX_IPSR_GPSR(IP7_26_25, AUDIO_CLKC),
+       PINMUX_IPSR_GPSR(IP7_26_25, AUDIO_CLKOUT_C),
        PINMUX_IPSR_MSEL(IP7_28_27, VI0_CLK, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP7_28_27, ATACS00_N),
-       PINMUX_IPSR_DATA(IP7_28_27, AVB_RXD1),
+       PINMUX_IPSR_GPSR(IP7_28_27, ATACS00_N),
+       PINMUX_IPSR_GPSR(IP7_28_27, AVB_RXD1),
        PINMUX_IPSR_MSEL(IP7_30_29, VI0_DATA0_VI0_B0, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP7_30_29, ATACS10_N),
-       PINMUX_IPSR_DATA(IP7_30_29, AVB_RXD2),
+       PINMUX_IPSR_GPSR(IP7_30_29, ATACS10_N),
+       PINMUX_IPSR_GPSR(IP7_30_29, AVB_RXD2),
 
        PINMUX_IPSR_MSEL(IP8_1_0, VI0_DATA1_VI0_B1, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP8_1_0, ATARD0_N),
-       PINMUX_IPSR_DATA(IP8_1_0, AVB_RXD3),
+       PINMUX_IPSR_GPSR(IP8_1_0, ATARD0_N),
+       PINMUX_IPSR_GPSR(IP8_1_0, AVB_RXD3),
        PINMUX_IPSR_MSEL(IP8_3_2, VI0_DATA2_VI0_B2, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP8_3_2, ATAWR0_N),
-       PINMUX_IPSR_DATA(IP8_3_2, AVB_RXD4),
+       PINMUX_IPSR_GPSR(IP8_3_2, ATAWR0_N),
+       PINMUX_IPSR_GPSR(IP8_3_2, AVB_RXD4),
        PINMUX_IPSR_MSEL(IP8_5_4, VI0_DATA3_VI0_B3, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP8_5_4, ATADIR0_N),
-       PINMUX_IPSR_DATA(IP8_5_4, AVB_RXD5),
+       PINMUX_IPSR_GPSR(IP8_5_4, ATADIR0_N),
+       PINMUX_IPSR_GPSR(IP8_5_4, AVB_RXD5),
        PINMUX_IPSR_MSEL(IP8_7_6, VI0_DATA4_VI0_B4, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP8_7_6, ATAG0_N),
-       PINMUX_IPSR_DATA(IP8_7_6, AVB_RXD6),
+       PINMUX_IPSR_GPSR(IP8_7_6, ATAG0_N),
+       PINMUX_IPSR_GPSR(IP8_7_6, AVB_RXD6),
        PINMUX_IPSR_MSEL(IP8_9_8, VI0_DATA5_VI0_B5, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP8_9_8, EX_WAIT1),
-       PINMUX_IPSR_DATA(IP8_9_8, AVB_RXD7),
+       PINMUX_IPSR_GPSR(IP8_9_8, EX_WAIT1),
+       PINMUX_IPSR_GPSR(IP8_9_8, AVB_RXD7),
        PINMUX_IPSR_MSEL(IP8_11_10, VI0_DATA6_VI0_B6, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP8_11_10, AVB_RX_ER),
+       PINMUX_IPSR_GPSR(IP8_11_10, AVB_RX_ER),
        PINMUX_IPSR_MSEL(IP8_13_12, VI0_DATA7_VI0_B7, SEL_VI0_0),
-       PINMUX_IPSR_DATA(IP8_13_12, AVB_RX_CLK),
+       PINMUX_IPSR_GPSR(IP8_13_12, AVB_RX_CLK),
        PINMUX_IPSR_MSEL(IP8_15_14, VI1_CLK, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP8_15_14, AVB_RX_DV),
+       PINMUX_IPSR_GPSR(IP8_15_14, AVB_RX_DV),
        PINMUX_IPSR_MSEL(IP8_17_16, VI1_DATA0_VI1_B0, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP8_17_16, SCIFA1_SCK_D, SEL_SCIFA1_3),
-       PINMUX_IPSR_DATA(IP8_17_16, AVB_CRS),
+       PINMUX_IPSR_GPSR(IP8_17_16, AVB_CRS),
        PINMUX_IPSR_MSEL(IP8_19_18, VI1_DATA1_VI1_B1, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP8_19_18, SCIFA1_RXD_D, SEL_SCIFA1_3),
-       PINMUX_IPSR_DATA(IP8_19_18, AVB_MDC),
+       PINMUX_IPSR_GPSR(IP8_19_18, AVB_MDC),
        PINMUX_IPSR_MSEL(IP8_21_20, VI1_DATA2_VI1_B2, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP8_21_20, SCIFA1_TXD_D, SEL_SCIFA1_3),
-       PINMUX_IPSR_DATA(IP8_21_20, AVB_MDIO),
+       PINMUX_IPSR_GPSR(IP8_21_20, AVB_MDIO),
        PINMUX_IPSR_MSEL(IP8_23_22, VI1_DATA3_VI1_B3, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP8_23_22, SCIFA1_CTS_N_D, SEL_SCIFA1_3),
-       PINMUX_IPSR_DATA(IP8_23_22, AVB_GTX_CLK),
+       PINMUX_IPSR_GPSR(IP8_23_22, AVB_GTX_CLK),
        PINMUX_IPSR_MSEL(IP8_25_24, VI1_DATA4_VI1_B4, SEL_VI1_0),
        PINMUX_IPSR_MSEL(IP8_25_24, SCIFA1_RTS_N_D, SEL_SCIFA1_3),
-       PINMUX_IPSR_DATA(IP8_25_24, AVB_MAGIC),
+       PINMUX_IPSR_GPSR(IP8_25_24, AVB_MAGIC),
        PINMUX_IPSR_MSEL(IP8_26, VI1_DATA5_VI1_B5, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP8_26, AVB_PHY_INT),
+       PINMUX_IPSR_GPSR(IP8_26, AVB_PHY_INT),
        PINMUX_IPSR_MSEL(IP8_27, VI1_DATA6_VI1_B6, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP8_27, AVB_GTXREFCLK),
-       PINMUX_IPSR_DATA(IP8_28, SD0_CLK),
+       PINMUX_IPSR_GPSR(IP8_27, AVB_GTXREFCLK),
+       PINMUX_IPSR_GPSR(IP8_28, SD0_CLK),
        PINMUX_IPSR_MSEL(IP8_28, VI1_DATA0_VI1_B0_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP8_30_29, SD0_CMD),
+       PINMUX_IPSR_GPSR(IP8_30_29, SD0_CMD),
        PINMUX_IPSR_MSEL(IP8_30_29, SCIFB1_SCK_B, SEL_SCIFB1_1),
        PINMUX_IPSR_MSEL(IP8_30_29, VI1_DATA1_VI1_B1_B, SEL_VI1_1),
 
-       PINMUX_IPSR_DATA(IP9_1_0, SD0_DAT0),
+       PINMUX_IPSR_GPSR(IP9_1_0, SD0_DAT0),
        PINMUX_IPSR_MSEL(IP9_1_0, SCIFB1_RXD_B, SEL_SCIFB1_1),
        PINMUX_IPSR_MSEL(IP9_1_0, VI1_DATA2_VI1_B2_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP9_3_2, SD0_DAT1),
+       PINMUX_IPSR_GPSR(IP9_3_2, SD0_DAT1),
        PINMUX_IPSR_MSEL(IP9_3_2, SCIFB1_TXD_B, SEL_SCIFB1_1),
        PINMUX_IPSR_MSEL(IP9_3_2, VI1_DATA3_VI1_B3_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP9_5_4, SD0_DAT2),
+       PINMUX_IPSR_GPSR(IP9_5_4, SD0_DAT2),
        PINMUX_IPSR_MSEL(IP9_5_4, SCIFB1_CTS_N_B, SEL_SCIFB1_1),
        PINMUX_IPSR_MSEL(IP9_5_4, VI1_DATA4_VI1_B4_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP9_7_6, SD0_DAT3),
+       PINMUX_IPSR_GPSR(IP9_7_6, SD0_DAT3),
        PINMUX_IPSR_MSEL(IP9_7_6, SCIFB1_RTS_N_B, SEL_SCIFB1_1),
        PINMUX_IPSR_MSEL(IP9_7_6, VI1_DATA5_VI1_B5_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP9_11_8, SD0_CD),
-       PINMUX_IPSR_DATA(IP9_11_8, MMC0_D6),
+       PINMUX_IPSR_GPSR(IP9_11_8, SD0_CD),
+       PINMUX_IPSR_GPSR(IP9_11_8, MMC0_D6),
        PINMUX_IPSR_MSEL(IP9_11_8, TS_SDEN0_B, SEL_TSIF0_1),
-       PINMUX_IPSR_DATA(IP9_11_8, USB0_EXTP),
+       PINMUX_IPSR_GPSR(IP9_11_8, USB0_EXTP),
        PINMUX_IPSR_MSEL(IP9_11_8, GLO_SCLK, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP9_11_8, VI1_DATA6_VI1_B6_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP9_11_8, IIC1_SCL_B, SEL_IIC1_1),
        PINMUX_IPSR_MSEL(IP9_11_8, I2C1_SCL_B, SEL_I2C1_1),
        PINMUX_IPSR_MSEL(IP9_11_8, VI2_DATA6_VI2_B6_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP9_15_12, SD0_WP),
-       PINMUX_IPSR_DATA(IP9_15_12, MMC0_D7),
+       PINMUX_IPSR_GPSR(IP9_15_12, SD0_WP),
+       PINMUX_IPSR_GPSR(IP9_15_12, MMC0_D7),
        PINMUX_IPSR_MSEL(IP9_15_12, TS_SPSYNC0_B, SEL_TSIF0_1),
-       PINMUX_IPSR_DATA(IP9_15_12, USB0_IDIN),
+       PINMUX_IPSR_GPSR(IP9_15_12, USB0_IDIN),
        PINMUX_IPSR_MSEL(IP9_15_12, GLO_SDATA, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP9_15_12, VI1_DATA7_VI1_B7_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP9_15_12, IIC1_SDA_B, SEL_IIC1_1),
        PINMUX_IPSR_MSEL(IP9_15_12, I2C1_SDA_B, SEL_I2C1_1),
        PINMUX_IPSR_MSEL(IP9_15_12, VI2_DATA7_VI2_B7_B, SEL_VI2_1),
-       PINMUX_IPSR_DATA(IP9_17_16, SD1_CLK),
-       PINMUX_IPSR_DATA(IP9_17_16, AVB_TX_EN),
-       PINMUX_IPSR_DATA(IP9_19_18, SD1_CMD),
-       PINMUX_IPSR_DATA(IP9_19_18, AVB_TX_ER),
+       PINMUX_IPSR_GPSR(IP9_17_16, SD1_CLK),
+       PINMUX_IPSR_GPSR(IP9_17_16, AVB_TX_EN),
+       PINMUX_IPSR_GPSR(IP9_19_18, SD1_CMD),
+       PINMUX_IPSR_GPSR(IP9_19_18, AVB_TX_ER),
        PINMUX_IPSR_MSEL(IP9_19_18, SCIFB0_SCK_B, SEL_SCIFB_1),
-       PINMUX_IPSR_DATA(IP9_21_20, SD1_DAT0),
-       PINMUX_IPSR_DATA(IP9_21_20, AVB_TX_CLK),
+       PINMUX_IPSR_GPSR(IP9_21_20, SD1_DAT0),
+       PINMUX_IPSR_GPSR(IP9_21_20, AVB_TX_CLK),
        PINMUX_IPSR_MSEL(IP9_21_20, SCIFB0_RXD_B, SEL_SCIFB_1),
-       PINMUX_IPSR_DATA(IP9_23_22, SD1_DAT1),
-       PINMUX_IPSR_DATA(IP9_23_22, AVB_LINK),
+       PINMUX_IPSR_GPSR(IP9_23_22, SD1_DAT1),
+       PINMUX_IPSR_GPSR(IP9_23_22, AVB_LINK),
        PINMUX_IPSR_MSEL(IP9_23_22, SCIFB0_TXD_B, SEL_SCIFB_1),
-       PINMUX_IPSR_DATA(IP9_25_24, SD1_DAT2),
-       PINMUX_IPSR_DATA(IP9_25_24, AVB_COL),
+       PINMUX_IPSR_GPSR(IP9_25_24, SD1_DAT2),
+       PINMUX_IPSR_GPSR(IP9_25_24, AVB_COL),
        PINMUX_IPSR_MSEL(IP9_25_24, SCIFB0_CTS_N_B, SEL_SCIFB_1),
-       PINMUX_IPSR_DATA(IP9_27_26, SD1_DAT3),
-       PINMUX_IPSR_DATA(IP9_27_26, AVB_RXD0),
+       PINMUX_IPSR_GPSR(IP9_27_26, SD1_DAT3),
+       PINMUX_IPSR_GPSR(IP9_27_26, AVB_RXD0),
        PINMUX_IPSR_MSEL(IP9_27_26, SCIFB0_RTS_N_B, SEL_SCIFB_1),
-       PINMUX_IPSR_DATA(IP9_31_28, SD1_CD),
-       PINMUX_IPSR_DATA(IP9_31_28, MMC1_D6),
+       PINMUX_IPSR_GPSR(IP9_31_28, SD1_CD),
+       PINMUX_IPSR_GPSR(IP9_31_28, MMC1_D6),
        PINMUX_IPSR_MSEL(IP9_31_28, TS_SDEN1, SEL_TSIF1_0),
-       PINMUX_IPSR_DATA(IP9_31_28, USB1_EXTP),
+       PINMUX_IPSR_GPSR(IP9_31_28, USB1_EXTP),
        PINMUX_IPSR_MSEL(IP9_31_28, GLO_SS, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP9_31_28, VI0_CLK_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP9_31_28, IIC2_SCL_D, SEL_IIC2_3),
@@ -1330,24 +1330,24 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP9_31_28, SIM0_CLK_B, SEL_SIM_1),
        PINMUX_IPSR_MSEL(IP9_31_28, VI3_CLK_B, SEL_VI3_1),
 
-       PINMUX_IPSR_DATA(IP10_3_0, SD1_WP),
-       PINMUX_IPSR_DATA(IP10_3_0, MMC1_D7),
+       PINMUX_IPSR_GPSR(IP10_3_0, SD1_WP),
+       PINMUX_IPSR_GPSR(IP10_3_0, MMC1_D7),
        PINMUX_IPSR_MSEL(IP10_3_0, TS_SPSYNC1, SEL_TSIF1_0),
-       PINMUX_IPSR_DATA(IP10_3_0, USB1_IDIN),
+       PINMUX_IPSR_GPSR(IP10_3_0, USB1_IDIN),
        PINMUX_IPSR_MSEL(IP10_3_0, GLO_RFON, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP10_3_0, VI1_CLK_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP10_3_0, IIC2_SDA_D, SEL_IIC2_3),
        PINMUX_IPSR_MSEL(IP10_3_0, I2C2_SDA_D, SEL_I2C2_3),
        PINMUX_IPSR_MSEL(IP10_3_0, SIM0_D_B, SEL_SIM_1),
-       PINMUX_IPSR_DATA(IP10_6_4, SD2_CLK),
-       PINMUX_IPSR_DATA(IP10_6_4, MMC0_CLK),
+       PINMUX_IPSR_GPSR(IP10_6_4, SD2_CLK),
+       PINMUX_IPSR_GPSR(IP10_6_4, MMC0_CLK),
        PINMUX_IPSR_MSEL(IP10_6_4, SIM0_CLK, SEL_SIM_0),
        PINMUX_IPSR_MSEL(IP10_6_4, VI0_DATA0_VI0_B0_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP10_6_4, TS_SDEN0_C, SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP10_6_4, GLO_SCLK_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_6_4, VI3_DATA0_B, SEL_VI3_1),
-       PINMUX_IPSR_DATA(IP10_10_7, SD2_CMD),
-       PINMUX_IPSR_DATA(IP10_10_7, MMC0_CMD),
+       PINMUX_IPSR_GPSR(IP10_10_7, SD2_CMD),
+       PINMUX_IPSR_GPSR(IP10_10_7, MMC0_CMD),
        PINMUX_IPSR_MSEL(IP10_10_7, SIM0_D, SEL_SIM_0),
        PINMUX_IPSR_MSEL(IP10_10_7, VI0_DATA1_VI0_B1_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP10_10_7, SCIFB1_SCK_E, SEL_SCIFB1_4),
@@ -1355,8 +1355,8 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP10_10_7, TS_SPSYNC0_C, SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP10_10_7, GLO_SDATA_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_10_7, VI3_DATA1_B, SEL_VI3_1),
-       PINMUX_IPSR_DATA(IP10_14_11, SD2_DAT0),
-       PINMUX_IPSR_DATA(IP10_14_11, MMC0_D0),
+       PINMUX_IPSR_GPSR(IP10_14_11, SD2_DAT0),
+       PINMUX_IPSR_GPSR(IP10_14_11, MMC0_D0),
        PINMUX_IPSR_MSEL(IP10_14_11, FMCLK_B, SEL_FM_1),
        PINMUX_IPSR_MSEL(IP10_14_11, VI0_DATA2_VI0_B2_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP10_14_11, SCIFB1_RXD_E, SEL_SCIFB1_4),
@@ -1364,8 +1364,8 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP10_14_11, TS_SDAT0_C, SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP10_14_11, GLO_SS_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_14_11, VI3_DATA2_B, SEL_VI3_1),
-       PINMUX_IPSR_DATA(IP10_18_15, SD2_DAT1),
-       PINMUX_IPSR_DATA(IP10_18_15, MMC0_D1),
+       PINMUX_IPSR_GPSR(IP10_18_15, SD2_DAT1),
+       PINMUX_IPSR_GPSR(IP10_18_15, MMC0_D1),
        PINMUX_IPSR_MSEL(IP10_18_15, FMIN_B, SEL_FM_1),
        PINMUX_IPSR_MSEL(IP10_18_15, VI0_DATA3_VI0_B3_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP10_18_15, SCIFB1_TXD_E, SEL_SCIFB1_4),
@@ -1373,26 +1373,26 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP10_18_15, TS_SCK0_C, SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP10_18_15, GLO_RFON_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_18_15, VI3_DATA3_B, SEL_VI3_1),
-       PINMUX_IPSR_DATA(IP10_22_19, SD2_DAT2),
-       PINMUX_IPSR_DATA(IP10_22_19, MMC0_D2),
+       PINMUX_IPSR_GPSR(IP10_22_19, SD2_DAT2),
+       PINMUX_IPSR_GPSR(IP10_22_19, MMC0_D2),
        PINMUX_IPSR_MSEL(IP10_22_19, BPFCLK_B, SEL_FM_1),
        PINMUX_IPSR_MSEL(IP10_22_19, VI0_DATA4_VI0_B4_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP10_22_19, HRX0_D, SEL_HSCIF0_3),
        PINMUX_IPSR_MSEL(IP10_22_19, TS_SDEN1_B, SEL_TSIF1_1),
        PINMUX_IPSR_MSEL(IP10_22_19, GLO_Q0_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_22_19, VI3_DATA4_B, SEL_VI3_1),
-       PINMUX_IPSR_DATA(IP10_25_23, SD2_DAT3),
-       PINMUX_IPSR_DATA(IP10_25_23, MMC0_D3),
+       PINMUX_IPSR_GPSR(IP10_25_23, SD2_DAT3),
+       PINMUX_IPSR_GPSR(IP10_25_23, MMC0_D3),
        PINMUX_IPSR_MSEL(IP10_25_23, SIM0_RST, SEL_SIM_0),
        PINMUX_IPSR_MSEL(IP10_25_23, VI0_DATA5_VI0_B5_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP10_25_23, HTX0_D, SEL_HSCIF0_3),
        PINMUX_IPSR_MSEL(IP10_25_23, TS_SPSYNC1_B, SEL_TSIF1_1),
        PINMUX_IPSR_MSEL(IP10_25_23, GLO_Q1_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_25_23, VI3_DATA5_B, SEL_VI3_1),
-       PINMUX_IPSR_DATA(IP10_29_26, SD2_CD),
-       PINMUX_IPSR_DATA(IP10_29_26, MMC0_D4),
+       PINMUX_IPSR_GPSR(IP10_29_26, SD2_CD),
+       PINMUX_IPSR_GPSR(IP10_29_26, MMC0_D4),
        PINMUX_IPSR_MSEL(IP10_29_26, TS_SDAT0_B, SEL_TSIF0_1),
-       PINMUX_IPSR_DATA(IP10_29_26, USB2_EXTP),
+       PINMUX_IPSR_GPSR(IP10_29_26, USB2_EXTP),
        PINMUX_IPSR_MSEL(IP10_29_26, GLO_I0, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP10_29_26, VI0_DATA6_VI0_B6_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP10_29_26, HCTS0_N_D, SEL_HSCIF0_3),
@@ -1400,164 +1400,164 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP10_29_26, GLO_I0_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_29_26, VI3_DATA6_B, SEL_VI3_1),
 
-       PINMUX_IPSR_DATA(IP11_3_0, SD2_WP),
-       PINMUX_IPSR_DATA(IP11_3_0, MMC0_D5),
+       PINMUX_IPSR_GPSR(IP11_3_0, SD2_WP),
+       PINMUX_IPSR_GPSR(IP11_3_0, MMC0_D5),
        PINMUX_IPSR_MSEL(IP11_3_0, TS_SCK0_B, SEL_TSIF0_1),
-       PINMUX_IPSR_DATA(IP11_3_0, USB2_IDIN),
+       PINMUX_IPSR_GPSR(IP11_3_0, USB2_IDIN),
        PINMUX_IPSR_MSEL(IP11_3_0, GLO_I1, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP11_3_0, VI0_DATA7_VI0_B7_B, SEL_VI0_1),
        PINMUX_IPSR_MSEL(IP11_3_0, HRTS0_N_D, SEL_HSCIF0_3),
        PINMUX_IPSR_MSEL(IP11_3_0, TS_SCK1_B, SEL_TSIF1_1),
        PINMUX_IPSR_MSEL(IP11_3_0, GLO_I1_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP11_3_0, VI3_DATA7_B, SEL_VI3_1),
-       PINMUX_IPSR_DATA(IP11_4, SD3_CLK),
-       PINMUX_IPSR_DATA(IP11_4, MMC1_CLK),
-       PINMUX_IPSR_DATA(IP11_6_5, SD3_CMD),
-       PINMUX_IPSR_DATA(IP11_6_5, MMC1_CMD),
-       PINMUX_IPSR_DATA(IP11_6_5, MTS_N),
-       PINMUX_IPSR_DATA(IP11_8_7, SD3_DAT0),
-       PINMUX_IPSR_DATA(IP11_8_7, MMC1_D0),
-       PINMUX_IPSR_DATA(IP11_8_7, STM_N),
-       PINMUX_IPSR_DATA(IP11_10_9, SD3_DAT1),
-       PINMUX_IPSR_DATA(IP11_10_9, MMC1_D1),
-       PINMUX_IPSR_DATA(IP11_10_9, MDATA),
-       PINMUX_IPSR_DATA(IP11_12_11, SD3_DAT2),
-       PINMUX_IPSR_DATA(IP11_12_11, MMC1_D2),
-       PINMUX_IPSR_DATA(IP11_12_11, SDATA),
-       PINMUX_IPSR_DATA(IP11_14_13, SD3_DAT3),
-       PINMUX_IPSR_DATA(IP11_14_13, MMC1_D3),
-       PINMUX_IPSR_DATA(IP11_14_13, SCKZ),
-       PINMUX_IPSR_DATA(IP11_17_15, SD3_CD),
-       PINMUX_IPSR_DATA(IP11_17_15, MMC1_D4),
+       PINMUX_IPSR_GPSR(IP11_4, SD3_CLK),
+       PINMUX_IPSR_GPSR(IP11_4, MMC1_CLK),
+       PINMUX_IPSR_GPSR(IP11_6_5, SD3_CMD),
+       PINMUX_IPSR_GPSR(IP11_6_5, MMC1_CMD),
+       PINMUX_IPSR_GPSR(IP11_6_5, MTS_N),
+       PINMUX_IPSR_GPSR(IP11_8_7, SD3_DAT0),
+       PINMUX_IPSR_GPSR(IP11_8_7, MMC1_D0),
+       PINMUX_IPSR_GPSR(IP11_8_7, STM_N),
+       PINMUX_IPSR_GPSR(IP11_10_9, SD3_DAT1),
+       PINMUX_IPSR_GPSR(IP11_10_9, MMC1_D1),
+       PINMUX_IPSR_GPSR(IP11_10_9, MDATA),
+       PINMUX_IPSR_GPSR(IP11_12_11, SD3_DAT2),
+       PINMUX_IPSR_GPSR(IP11_12_11, MMC1_D2),
+       PINMUX_IPSR_GPSR(IP11_12_11, SDATA),
+       PINMUX_IPSR_GPSR(IP11_14_13, SD3_DAT3),
+       PINMUX_IPSR_GPSR(IP11_14_13, MMC1_D3),
+       PINMUX_IPSR_GPSR(IP11_14_13, SCKZ),
+       PINMUX_IPSR_GPSR(IP11_17_15, SD3_CD),
+       PINMUX_IPSR_GPSR(IP11_17_15, MMC1_D4),
        PINMUX_IPSR_MSEL(IP11_17_15, TS_SDAT1, SEL_TSIF1_0),
-       PINMUX_IPSR_DATA(IP11_17_15, VSP),
+       PINMUX_IPSR_GPSR(IP11_17_15, VSP),
        PINMUX_IPSR_MSEL(IP11_17_15, GLO_Q0, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP11_17_15, SIM0_RST_B, SEL_SIM_1),
-       PINMUX_IPSR_DATA(IP11_21_18, SD3_WP),
-       PINMUX_IPSR_DATA(IP11_21_18, MMC1_D5),
+       PINMUX_IPSR_GPSR(IP11_21_18, SD3_WP),
+       PINMUX_IPSR_GPSR(IP11_21_18, MMC1_D5),
        PINMUX_IPSR_MSEL(IP11_21_18, TS_SCK1, SEL_TSIF1_0),
        PINMUX_IPSR_MSEL(IP11_21_18, GLO_Q1, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP11_21_18, FMIN_C, SEL_FM_2),
        PINMUX_IPSR_MSEL(IP11_21_18, FMIN_E, SEL_FM_4),
        PINMUX_IPSR_MSEL(IP11_21_18, FMIN_F, SEL_FM_5),
-       PINMUX_IPSR_DATA(IP11_23_22, MLB_CLK),
+       PINMUX_IPSR_GPSR(IP11_23_22, MLB_CLK),
        PINMUX_IPSR_MSEL(IP11_23_22, IIC2_SCL_B, SEL_IIC2_1),
        PINMUX_IPSR_MSEL(IP11_23_22, I2C2_SCL_B, SEL_I2C2_1),
-       PINMUX_IPSR_DATA(IP11_26_24, MLB_SIG),
+       PINMUX_IPSR_GPSR(IP11_26_24, MLB_SIG),
        PINMUX_IPSR_MSEL(IP11_26_24, SCIFB1_RXD_D, SEL_SCIFB1_3),
        PINMUX_IPSR_MSEL(IP11_26_24, RX1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP11_26_24, IIC2_SDA_B, SEL_IIC2_1),
        PINMUX_IPSR_MSEL(IP11_26_24, I2C2_SDA_B, SEL_I2C2_1),
-       PINMUX_IPSR_DATA(IP11_29_27, MLB_DAT),
+       PINMUX_IPSR_GPSR(IP11_29_27, MLB_DAT),
        PINMUX_IPSR_MSEL(IP11_29_27, SCIFB1_TXD_D, SEL_SCIFB1_3),
        PINMUX_IPSR_MSEL(IP11_29_27, TX1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP11_29_27, BPFCLK_C, SEL_FM_2),
-       PINMUX_IPSR_DATA(IP11_31_30, SSI_SCK0129),
+       PINMUX_IPSR_GPSR(IP11_31_30, SSI_SCK0129),
        PINMUX_IPSR_MSEL(IP11_31_30, CAN_CLK_B, SEL_CANCLK_1),
-       PINMUX_IPSR_DATA(IP11_31_30, MOUT0),
+       PINMUX_IPSR_GPSR(IP11_31_30, MOUT0),
 
-       PINMUX_IPSR_DATA(IP12_1_0, SSI_WS0129),
+       PINMUX_IPSR_GPSR(IP12_1_0, SSI_WS0129),
        PINMUX_IPSR_MSEL(IP12_1_0, CAN0_TX_B, SEL_CAN0_1),
-       PINMUX_IPSR_DATA(IP12_1_0, MOUT1),
-       PINMUX_IPSR_DATA(IP12_3_2, SSI_SDATA0),
+       PINMUX_IPSR_GPSR(IP12_1_0, MOUT1),
+       PINMUX_IPSR_GPSR(IP12_3_2, SSI_SDATA0),
        PINMUX_IPSR_MSEL(IP12_3_2, CAN0_RX_B, SEL_CAN0_1),
-       PINMUX_IPSR_DATA(IP12_3_2, MOUT2),
-       PINMUX_IPSR_DATA(IP12_5_4, SSI_SDATA1),
+       PINMUX_IPSR_GPSR(IP12_3_2, MOUT2),
+       PINMUX_IPSR_GPSR(IP12_5_4, SSI_SDATA1),
        PINMUX_IPSR_MSEL(IP12_5_4, CAN1_TX_B, SEL_CAN1_1),
-       PINMUX_IPSR_DATA(IP12_5_4, MOUT5),
-       PINMUX_IPSR_DATA(IP12_7_6, SSI_SDATA2),
+       PINMUX_IPSR_GPSR(IP12_5_4, MOUT5),
+       PINMUX_IPSR_GPSR(IP12_7_6, SSI_SDATA2),
        PINMUX_IPSR_MSEL(IP12_7_6, CAN1_RX_B, SEL_CAN1_1),
-       PINMUX_IPSR_DATA(IP12_7_6, SSI_SCK1),
-       PINMUX_IPSR_DATA(IP12_7_6, MOUT6),
-       PINMUX_IPSR_DATA(IP12_10_8, SSI_SCK34),
-       PINMUX_IPSR_DATA(IP12_10_8, STP_OPWM_0),
+       PINMUX_IPSR_GPSR(IP12_7_6, SSI_SCK1),
+       PINMUX_IPSR_GPSR(IP12_7_6, MOUT6),
+       PINMUX_IPSR_GPSR(IP12_10_8, SSI_SCK34),
+       PINMUX_IPSR_GPSR(IP12_10_8, STP_OPWM_0),
        PINMUX_IPSR_MSEL(IP12_10_8, SCIFB0_SCK, SEL_SCIFB_0),
        PINMUX_IPSR_MSEL(IP12_10_8, MSIOF1_SCK, SEL_SOF1_0),
-       PINMUX_IPSR_DATA(IP12_10_8, CAN_DEBUG_HW_TRIGGER),
-       PINMUX_IPSR_DATA(IP12_13_11, SSI_WS34),
+       PINMUX_IPSR_GPSR(IP12_10_8, CAN_DEBUG_HW_TRIGGER),
+       PINMUX_IPSR_GPSR(IP12_13_11, SSI_WS34),
        PINMUX_IPSR_MSEL(IP12_13_11, STP_IVCXO27_0, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP12_13_11, SCIFB0_RXD, SEL_SCIFB_0),
-       PINMUX_IPSR_DATA(IP12_13_11, MSIOF1_SYNC),
-       PINMUX_IPSR_DATA(IP12_13_11, CAN_STEP0),
-       PINMUX_IPSR_DATA(IP12_16_14, SSI_SDATA3),
+       PINMUX_IPSR_GPSR(IP12_13_11, MSIOF1_SYNC),
+       PINMUX_IPSR_GPSR(IP12_13_11, CAN_STEP0),
+       PINMUX_IPSR_GPSR(IP12_16_14, SSI_SDATA3),
        PINMUX_IPSR_MSEL(IP12_16_14, STP_ISCLK_0, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP12_16_14, SCIFB0_TXD, SEL_SCIFB_0),
        PINMUX_IPSR_MSEL(IP12_16_14, MSIOF1_SS1, SEL_SOF1_0),
-       PINMUX_IPSR_DATA(IP12_16_14, CAN_TXCLK),
-       PINMUX_IPSR_DATA(IP12_19_17, SSI_SCK4),
+       PINMUX_IPSR_GPSR(IP12_16_14, CAN_TXCLK),
+       PINMUX_IPSR_GPSR(IP12_19_17, SSI_SCK4),
        PINMUX_IPSR_MSEL(IP12_19_17, STP_ISD_0, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP12_19_17, SCIFB0_CTS_N, SEL_SCIFB_0),
        PINMUX_IPSR_MSEL(IP12_19_17, MSIOF1_SS2, SEL_SOF1_0),
        PINMUX_IPSR_MSEL(IP12_19_17, SSI_SCK5_C, SEL_SSI5_2),
-       PINMUX_IPSR_DATA(IP12_19_17, CAN_DEBUGOUT0),
-       PINMUX_IPSR_DATA(IP12_22_20, SSI_WS4),
+       PINMUX_IPSR_GPSR(IP12_19_17, CAN_DEBUGOUT0),
+       PINMUX_IPSR_GPSR(IP12_22_20, SSI_WS4),
        PINMUX_IPSR_MSEL(IP12_22_20, STP_ISEN_0, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP12_22_20, SCIFB0_RTS_N, SEL_SCIFB_0),
        PINMUX_IPSR_MSEL(IP12_22_20, MSIOF1_TXD, SEL_SOF1_0),
        PINMUX_IPSR_MSEL(IP12_22_20, SSI_WS5_C, SEL_SSI5_2),
-       PINMUX_IPSR_DATA(IP12_22_20, CAN_DEBUGOUT1),
-       PINMUX_IPSR_DATA(IP12_24_23, SSI_SDATA4),
+       PINMUX_IPSR_GPSR(IP12_22_20, CAN_DEBUGOUT1),
+       PINMUX_IPSR_GPSR(IP12_24_23, SSI_SDATA4),
        PINMUX_IPSR_MSEL(IP12_24_23, STP_ISSYNC_0, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP12_24_23, MSIOF1_RXD, SEL_SOF1_0),
-       PINMUX_IPSR_DATA(IP12_24_23, CAN_DEBUGOUT2),
+       PINMUX_IPSR_GPSR(IP12_24_23, CAN_DEBUGOUT2),
        PINMUX_IPSR_MSEL(IP12_27_25, SSI_SCK5, SEL_SSI5_0),
        PINMUX_IPSR_MSEL(IP12_27_25, SCIFB1_SCK, SEL_SCIFB1_0),
        PINMUX_IPSR_MSEL(IP12_27_25, IERX_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP12_27_25, DU2_EXHSYNC_DU2_HSYNC),
-       PINMUX_IPSR_DATA(IP12_27_25, QSTH_QHS),
-       PINMUX_IPSR_DATA(IP12_27_25, CAN_DEBUGOUT3),
+       PINMUX_IPSR_GPSR(IP12_27_25, DU2_EXHSYNC_DU2_HSYNC),
+       PINMUX_IPSR_GPSR(IP12_27_25, QSTH_QHS),
+       PINMUX_IPSR_GPSR(IP12_27_25, CAN_DEBUGOUT3),
        PINMUX_IPSR_MSEL(IP12_30_28, SSI_WS5, SEL_SSI5_0),
        PINMUX_IPSR_MSEL(IP12_30_28, SCIFB1_RXD, SEL_SCIFB1_0),
        PINMUX_IPSR_MSEL(IP12_30_28, IECLK_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP12_30_28, DU2_EXVSYNC_DU2_VSYNC),
-       PINMUX_IPSR_DATA(IP12_30_28, QSTB_QHE),
-       PINMUX_IPSR_DATA(IP12_30_28, CAN_DEBUGOUT4),
+       PINMUX_IPSR_GPSR(IP12_30_28, DU2_EXVSYNC_DU2_VSYNC),
+       PINMUX_IPSR_GPSR(IP12_30_28, QSTB_QHE),
+       PINMUX_IPSR_GPSR(IP12_30_28, CAN_DEBUGOUT4),
 
        PINMUX_IPSR_MSEL(IP13_2_0, SSI_SDATA5, SEL_SSI5_0),
        PINMUX_IPSR_MSEL(IP13_2_0, SCIFB1_TXD, SEL_SCIFB1_0),
        PINMUX_IPSR_MSEL(IP13_2_0, IETX_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP13_2_0, DU2_DR2),
-       PINMUX_IPSR_DATA(IP13_2_0, LCDOUT2),
-       PINMUX_IPSR_DATA(IP13_2_0, CAN_DEBUGOUT5),
+       PINMUX_IPSR_GPSR(IP13_2_0, DU2_DR2),
+       PINMUX_IPSR_GPSR(IP13_2_0, LCDOUT2),
+       PINMUX_IPSR_GPSR(IP13_2_0, CAN_DEBUGOUT5),
        PINMUX_IPSR_MSEL(IP13_6_3, SSI_SCK6, SEL_SSI6_0),
        PINMUX_IPSR_MSEL(IP13_6_3, SCIFB1_CTS_N, SEL_SCIFB1_0),
        PINMUX_IPSR_MSEL(IP13_6_3, BPFCLK_D, SEL_FM_3),
-       PINMUX_IPSR_DATA(IP13_6_3, DU2_DR3),
-       PINMUX_IPSR_DATA(IP13_6_3, LCDOUT3),
-       PINMUX_IPSR_DATA(IP13_6_3, CAN_DEBUGOUT6),
+       PINMUX_IPSR_GPSR(IP13_6_3, DU2_DR3),
+       PINMUX_IPSR_GPSR(IP13_6_3, LCDOUT3),
+       PINMUX_IPSR_GPSR(IP13_6_3, CAN_DEBUGOUT6),
        PINMUX_IPSR_MSEL(IP13_6_3, BPFCLK_F, SEL_FM_5),
        PINMUX_IPSR_MSEL(IP13_9_7, SSI_WS6, SEL_SSI6_0),
        PINMUX_IPSR_MSEL(IP13_9_7, SCIFB1_RTS_N, SEL_SCIFB1_0),
        PINMUX_IPSR_MSEL(IP13_9_7, CAN0_TX_D, SEL_CAN0_3),
-       PINMUX_IPSR_DATA(IP13_9_7, DU2_DR4),
-       PINMUX_IPSR_DATA(IP13_9_7, LCDOUT4),
-       PINMUX_IPSR_DATA(IP13_9_7, CAN_DEBUGOUT7),
+       PINMUX_IPSR_GPSR(IP13_9_7, DU2_DR4),
+       PINMUX_IPSR_GPSR(IP13_9_7, LCDOUT4),
+       PINMUX_IPSR_GPSR(IP13_9_7, CAN_DEBUGOUT7),
        PINMUX_IPSR_MSEL(IP13_12_10, SSI_SDATA6, SEL_SSI6_0),
        PINMUX_IPSR_MSEL(IP13_12_10, FMIN_D, SEL_FM_3),
-       PINMUX_IPSR_DATA(IP13_12_10, DU2_DR5),
-       PINMUX_IPSR_DATA(IP13_12_10, LCDOUT5),
-       PINMUX_IPSR_DATA(IP13_12_10, CAN_DEBUGOUT8),
+       PINMUX_IPSR_GPSR(IP13_12_10, DU2_DR5),
+       PINMUX_IPSR_GPSR(IP13_12_10, LCDOUT5),
+       PINMUX_IPSR_GPSR(IP13_12_10, CAN_DEBUGOUT8),
        PINMUX_IPSR_MSEL(IP13_15_13, SSI_SCK78, SEL_SSI7_0),
        PINMUX_IPSR_MSEL(IP13_15_13, STP_IVCXO27_1, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP13_15_13, SCK1, SEL_SCIF1_0),
        PINMUX_IPSR_MSEL(IP13_15_13, SCIFA1_SCK, SEL_SCIFA1_0),
-       PINMUX_IPSR_DATA(IP13_15_13, DU2_DR6),
-       PINMUX_IPSR_DATA(IP13_15_13, LCDOUT6),
-       PINMUX_IPSR_DATA(IP13_15_13, CAN_DEBUGOUT9),
+       PINMUX_IPSR_GPSR(IP13_15_13, DU2_DR6),
+       PINMUX_IPSR_GPSR(IP13_15_13, LCDOUT6),
+       PINMUX_IPSR_GPSR(IP13_15_13, CAN_DEBUGOUT9),
        PINMUX_IPSR_MSEL(IP13_18_16, SSI_WS78, SEL_SSI7_0),
        PINMUX_IPSR_MSEL(IP13_18_16, STP_ISCLK_1, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP13_18_16, SCIFB2_SCK, SEL_SCIFB2_0),
-       PINMUX_IPSR_DATA(IP13_18_16, SCIFA2_CTS_N),
-       PINMUX_IPSR_DATA(IP13_18_16, DU2_DR7),
-       PINMUX_IPSR_DATA(IP13_18_16, LCDOUT7),
-       PINMUX_IPSR_DATA(IP13_18_16, CAN_DEBUGOUT10),
+       PINMUX_IPSR_GPSR(IP13_18_16, SCIFA2_CTS_N),
+       PINMUX_IPSR_GPSR(IP13_18_16, DU2_DR7),
+       PINMUX_IPSR_GPSR(IP13_18_16, LCDOUT7),
+       PINMUX_IPSR_GPSR(IP13_18_16, CAN_DEBUGOUT10),
        PINMUX_IPSR_MSEL(IP13_22_19, SSI_SDATA7, SEL_SSI7_0),
        PINMUX_IPSR_MSEL(IP13_22_19, STP_ISD_1, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP13_22_19, SCIFB2_RXD, SEL_SCIFB2_0),
-       PINMUX_IPSR_DATA(IP13_22_19, SCIFA2_RTS_N),
-       PINMUX_IPSR_DATA(IP13_22_19, TCLK2),
-       PINMUX_IPSR_DATA(IP13_22_19, QSTVA_QVS),
-       PINMUX_IPSR_DATA(IP13_22_19, CAN_DEBUGOUT11),
+       PINMUX_IPSR_GPSR(IP13_22_19, SCIFA2_RTS_N),
+       PINMUX_IPSR_GPSR(IP13_22_19, TCLK2),
+       PINMUX_IPSR_GPSR(IP13_22_19, QSTVA_QVS),
+       PINMUX_IPSR_GPSR(IP13_22_19, CAN_DEBUGOUT11),
        PINMUX_IPSR_MSEL(IP13_22_19, BPFCLK_E, SEL_FM_4),
        PINMUX_IPSR_MSEL(IP13_22_19, SSI_SDATA7_B, SEL_SSI7_1),
        PINMUX_IPSR_MSEL(IP13_22_19, FMIN_G, SEL_FM_6),
@@ -1565,161 +1565,161 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP13_25_23, STP_ISEN_1, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP13_25_23, SCIFB2_TXD, SEL_SCIFB2_0),
        PINMUX_IPSR_MSEL(IP13_25_23, CAN0_TX_C, SEL_CAN0_2),
-       PINMUX_IPSR_DATA(IP13_25_23, CAN_DEBUGOUT12),
+       PINMUX_IPSR_GPSR(IP13_25_23, CAN_DEBUGOUT12),
        PINMUX_IPSR_MSEL(IP13_25_23, SSI_SDATA8_B, SEL_SSI8_1),
-       PINMUX_IPSR_DATA(IP13_28_26, SSI_SDATA9),
+       PINMUX_IPSR_GPSR(IP13_28_26, SSI_SDATA9),
        PINMUX_IPSR_MSEL(IP13_28_26, STP_ISSYNC_1, SEL_SSP_0),
        PINMUX_IPSR_MSEL(IP13_28_26, SCIFB2_CTS_N, SEL_SCIFB2_0),
-       PINMUX_IPSR_DATA(IP13_28_26, SSI_WS1),
+       PINMUX_IPSR_GPSR(IP13_28_26, SSI_WS1),
        PINMUX_IPSR_MSEL(IP13_28_26, SSI_SDATA5_C, SEL_SSI5_2),
-       PINMUX_IPSR_DATA(IP13_28_26, CAN_DEBUGOUT13),
-       PINMUX_IPSR_DATA(IP13_30_29, AUDIO_CLKA),
+       PINMUX_IPSR_GPSR(IP13_28_26, CAN_DEBUGOUT13),
+       PINMUX_IPSR_GPSR(IP13_30_29, AUDIO_CLKA),
        PINMUX_IPSR_MSEL(IP13_30_29, SCIFB2_RTS_N, SEL_SCIFB2_0),
-       PINMUX_IPSR_DATA(IP13_30_29, CAN_DEBUGOUT14),
+       PINMUX_IPSR_GPSR(IP13_30_29, CAN_DEBUGOUT14),
 
-       PINMUX_IPSR_DATA(IP14_2_0, AUDIO_CLKB),
+       PINMUX_IPSR_GPSR(IP14_2_0, AUDIO_CLKB),
        PINMUX_IPSR_MSEL(IP14_2_0, SCIF_CLK, SEL_SCIFCLK_0),
        PINMUX_IPSR_MSEL(IP14_2_0, CAN0_RX_D, SEL_CAN0_3),
-       PINMUX_IPSR_DATA(IP14_2_0, DVC_MUTE),
+       PINMUX_IPSR_GPSR(IP14_2_0, DVC_MUTE),
        PINMUX_IPSR_MSEL(IP14_2_0, CAN0_RX_C, SEL_CAN0_2),
-       PINMUX_IPSR_DATA(IP14_2_0, CAN_DEBUGOUT15),
-       PINMUX_IPSR_DATA(IP14_2_0, REMOCON),
+       PINMUX_IPSR_GPSR(IP14_2_0, CAN_DEBUGOUT15),
+       PINMUX_IPSR_GPSR(IP14_2_0, REMOCON),
        PINMUX_IPSR_MSEL(IP14_5_3, SCIFA0_SCK, SEL_SCFA_0),
        PINMUX_IPSR_MSEL(IP14_5_3, HSCK1, SEL_HSCIF1_0),
-       PINMUX_IPSR_DATA(IP14_5_3, SCK0),
-       PINMUX_IPSR_DATA(IP14_5_3, MSIOF3_SS2),
-       PINMUX_IPSR_DATA(IP14_5_3, DU2_DG2),
-       PINMUX_IPSR_DATA(IP14_5_3, LCDOUT10),
+       PINMUX_IPSR_GPSR(IP14_5_3, SCK0),
+       PINMUX_IPSR_GPSR(IP14_5_3, MSIOF3_SS2),
+       PINMUX_IPSR_GPSR(IP14_5_3, DU2_DG2),
+       PINMUX_IPSR_GPSR(IP14_5_3, LCDOUT10),
        PINMUX_IPSR_MSEL(IP14_5_3, IIC1_SDA_C, SEL_IIC1_2),
        PINMUX_IPSR_MSEL(IP14_5_3, I2C1_SDA_C, SEL_I2C1_2),
        PINMUX_IPSR_MSEL(IP14_8_6, SCIFA0_RXD, SEL_SCFA_0),
        PINMUX_IPSR_MSEL(IP14_8_6, HRX1, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP14_8_6, RX0, SEL_SCIF0_0),
-       PINMUX_IPSR_DATA(IP14_8_6, DU2_DR0),
-       PINMUX_IPSR_DATA(IP14_8_6, LCDOUT0),
+       PINMUX_IPSR_GPSR(IP14_8_6, DU2_DR0),
+       PINMUX_IPSR_GPSR(IP14_8_6, LCDOUT0),
        PINMUX_IPSR_MSEL(IP14_11_9, SCIFA0_TXD, SEL_SCFA_0),
        PINMUX_IPSR_MSEL(IP14_11_9, HTX1, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP14_11_9, TX0, SEL_SCIF0_0),
-       PINMUX_IPSR_DATA(IP14_11_9, DU2_DR1),
-       PINMUX_IPSR_DATA(IP14_11_9, LCDOUT1),
+       PINMUX_IPSR_GPSR(IP14_11_9, DU2_DR1),
+       PINMUX_IPSR_GPSR(IP14_11_9, LCDOUT1),
        PINMUX_IPSR_MSEL(IP14_15_12, SCIFA0_CTS_N, SEL_SCFA_0),
        PINMUX_IPSR_MSEL(IP14_15_12, HCTS1_N, SEL_HSCIF1_0),
-       PINMUX_IPSR_DATA(IP14_15_12, CTS0_N),
+       PINMUX_IPSR_GPSR(IP14_15_12, CTS0_N),
        PINMUX_IPSR_MSEL(IP14_15_12, MSIOF3_SYNC, SEL_SOF3_0),
-       PINMUX_IPSR_DATA(IP14_15_12, DU2_DG3),
-       PINMUX_IPSR_DATA(IP14_15_12, LCDOUT11),
-       PINMUX_IPSR_DATA(IP14_15_12, PWM0_B),
+       PINMUX_IPSR_GPSR(IP14_15_12, DU2_DG3),
+       PINMUX_IPSR_GPSR(IP14_15_12, LCDOUT11),
+       PINMUX_IPSR_GPSR(IP14_15_12, PWM0_B),
        PINMUX_IPSR_MSEL(IP14_15_12, IIC1_SCL_C, SEL_IIC1_2),
        PINMUX_IPSR_MSEL(IP14_15_12, I2C1_SCL_C, SEL_I2C1_2),
        PINMUX_IPSR_MSEL(IP14_18_16, SCIFA0_RTS_N, SEL_SCFA_0),
        PINMUX_IPSR_MSEL(IP14_18_16, HRTS1_N, SEL_HSCIF1_0),
-       PINMUX_IPSR_DATA(IP14_18_16, RTS0_N),
-       PINMUX_IPSR_DATA(IP14_18_16, MSIOF3_SS1),
-       PINMUX_IPSR_DATA(IP14_18_16, DU2_DG0),
-       PINMUX_IPSR_DATA(IP14_18_16, LCDOUT8),
-       PINMUX_IPSR_DATA(IP14_18_16, PWM1_B),
+       PINMUX_IPSR_GPSR(IP14_18_16, RTS0_N),
+       PINMUX_IPSR_GPSR(IP14_18_16, MSIOF3_SS1),
+       PINMUX_IPSR_GPSR(IP14_18_16, DU2_DG0),
+       PINMUX_IPSR_GPSR(IP14_18_16, LCDOUT8),
+       PINMUX_IPSR_GPSR(IP14_18_16, PWM1_B),
        PINMUX_IPSR_MSEL(IP14_21_19, SCIFA1_RXD, SEL_SCIFA1_0),
        PINMUX_IPSR_MSEL(IP14_21_19, AD_DI, SEL_ADI_0),
        PINMUX_IPSR_MSEL(IP14_21_19, RX1, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP14_21_19, DU2_EXODDF_DU2_ODDF_DISP_CDE),
-       PINMUX_IPSR_DATA(IP14_21_19, QCPV_QDE),
+       PINMUX_IPSR_GPSR(IP14_21_19, DU2_EXODDF_DU2_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP14_21_19, QCPV_QDE),
        PINMUX_IPSR_MSEL(IP14_24_22, SCIFA1_TXD, SEL_SCIFA1_0),
        PINMUX_IPSR_MSEL(IP14_24_22, AD_DO, SEL_ADI_0),
        PINMUX_IPSR_MSEL(IP14_24_22, TX1, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP14_24_22, DU2_DG1),
-       PINMUX_IPSR_DATA(IP14_24_22, LCDOUT9),
+       PINMUX_IPSR_GPSR(IP14_24_22, DU2_DG1),
+       PINMUX_IPSR_GPSR(IP14_24_22, LCDOUT9),
        PINMUX_IPSR_MSEL(IP14_27_25, SCIFA1_CTS_N, SEL_SCIFA1_0),
        PINMUX_IPSR_MSEL(IP14_27_25, AD_CLK, SEL_ADI_0),
-       PINMUX_IPSR_DATA(IP14_27_25, CTS1_N),
+       PINMUX_IPSR_GPSR(IP14_27_25, CTS1_N),
        PINMUX_IPSR_MSEL(IP14_27_25, MSIOF3_RXD, SEL_SOF3_0),
-       PINMUX_IPSR_DATA(IP14_27_25, DU0_DOTCLKOUT),
-       PINMUX_IPSR_DATA(IP14_27_25, QCLK),
+       PINMUX_IPSR_GPSR(IP14_27_25, DU0_DOTCLKOUT),
+       PINMUX_IPSR_GPSR(IP14_27_25, QCLK),
        PINMUX_IPSR_MSEL(IP14_30_28, SCIFA1_RTS_N, SEL_SCIFA1_0),
        PINMUX_IPSR_MSEL(IP14_30_28, AD_NCS_N, SEL_ADI_0),
-       PINMUX_IPSR_DATA(IP14_30_28, RTS1_N),
+       PINMUX_IPSR_GPSR(IP14_30_28, RTS1_N),
        PINMUX_IPSR_MSEL(IP14_30_28, MSIOF3_TXD, SEL_SOF3_0),
-       PINMUX_IPSR_DATA(IP14_30_28, DU1_DOTCLKOUT),
-       PINMUX_IPSR_DATA(IP14_30_28, QSTVB_QVE),
+       PINMUX_IPSR_GPSR(IP14_30_28, DU1_DOTCLKOUT),
+       PINMUX_IPSR_GPSR(IP14_30_28, QSTVB_QVE),
        PINMUX_IPSR_MSEL(IP14_30_28, HRTS0_N_C, SEL_HSCIF0_2),
 
        PINMUX_IPSR_MSEL(IP15_2_0, SCIFA2_SCK, SEL_SCIFA2_0),
        PINMUX_IPSR_MSEL(IP15_2_0, FMCLK, SEL_FM_0),
-       PINMUX_IPSR_DATA(IP15_2_0, SCK2),
+       PINMUX_IPSR_GPSR(IP15_2_0, SCK2),
        PINMUX_IPSR_MSEL(IP15_2_0, MSIOF3_SCK, SEL_SOF3_0),
-       PINMUX_IPSR_DATA(IP15_2_0, DU2_DG7),
-       PINMUX_IPSR_DATA(IP15_2_0, LCDOUT15),
+       PINMUX_IPSR_GPSR(IP15_2_0, DU2_DG7),
+       PINMUX_IPSR_GPSR(IP15_2_0, LCDOUT15),
        PINMUX_IPSR_MSEL(IP15_2_0, SCIF_CLK_B, SEL_SCIFCLK_1),
        PINMUX_IPSR_MSEL(IP15_5_3, SCIFA2_RXD, SEL_SCIFA2_0),
        PINMUX_IPSR_MSEL(IP15_5_3, FMIN, SEL_FM_0),
        PINMUX_IPSR_MSEL(IP15_5_3, TX2, SEL_SCIF2_0),
-       PINMUX_IPSR_DATA(IP15_5_3, DU2_DB0),
-       PINMUX_IPSR_DATA(IP15_5_3, LCDOUT16),
+       PINMUX_IPSR_GPSR(IP15_5_3, DU2_DB0),
+       PINMUX_IPSR_GPSR(IP15_5_3, LCDOUT16),
        PINMUX_IPSR_MSEL(IP15_5_3, IIC2_SCL, SEL_IIC2_0),
        PINMUX_IPSR_MSEL(IP15_5_3, I2C2_SCL, SEL_I2C2_0),
        PINMUX_IPSR_MSEL(IP15_8_6, SCIFA2_TXD, SEL_SCIFA2_0),
        PINMUX_IPSR_MSEL(IP15_8_6, BPFCLK, SEL_FM_0),
        PINMUX_IPSR_MSEL(IP15_8_6, RX2, SEL_SCIF2_0),
-       PINMUX_IPSR_DATA(IP15_8_6, DU2_DB1),
-       PINMUX_IPSR_DATA(IP15_8_6, LCDOUT17),
+       PINMUX_IPSR_GPSR(IP15_8_6, DU2_DB1),
+       PINMUX_IPSR_GPSR(IP15_8_6, LCDOUT17),
        PINMUX_IPSR_MSEL(IP15_8_6, IIC2_SDA, SEL_IIC2_0),
        PINMUX_IPSR_MSEL(IP15_8_6, I2C2_SDA, SEL_I2C2_0),
-       PINMUX_IPSR_DATA(IP15_11_9, HSCK0),
+       PINMUX_IPSR_GPSR(IP15_11_9, HSCK0),
        PINMUX_IPSR_MSEL(IP15_11_9, TS_SDEN0, SEL_TSIF0_0),
-       PINMUX_IPSR_DATA(IP15_11_9, DU2_DG4),
-       PINMUX_IPSR_DATA(IP15_11_9, LCDOUT12),
+       PINMUX_IPSR_GPSR(IP15_11_9, DU2_DG4),
+       PINMUX_IPSR_GPSR(IP15_11_9, LCDOUT12),
        PINMUX_IPSR_MSEL(IP15_11_9, HCTS0_N_C, SEL_HSCIF0_2),
        PINMUX_IPSR_MSEL(IP15_13_12, HRX0, SEL_HSCIF0_0),
-       PINMUX_IPSR_DATA(IP15_13_12, DU2_DB2),
-       PINMUX_IPSR_DATA(IP15_13_12, LCDOUT18),
+       PINMUX_IPSR_GPSR(IP15_13_12, DU2_DB2),
+       PINMUX_IPSR_GPSR(IP15_13_12, LCDOUT18),
        PINMUX_IPSR_MSEL(IP15_15_14, HTX0, SEL_HSCIF0_0),
-       PINMUX_IPSR_DATA(IP15_15_14, DU2_DB3),
-       PINMUX_IPSR_DATA(IP15_15_14, LCDOUT19),
+       PINMUX_IPSR_GPSR(IP15_15_14, DU2_DB3),
+       PINMUX_IPSR_GPSR(IP15_15_14, LCDOUT19),
        PINMUX_IPSR_MSEL(IP15_17_16, HCTS0_N, SEL_HSCIF0_0),
-       PINMUX_IPSR_DATA(IP15_17_16, SSI_SCK9),
-       PINMUX_IPSR_DATA(IP15_17_16, DU2_DB4),
-       PINMUX_IPSR_DATA(IP15_17_16, LCDOUT20),
+       PINMUX_IPSR_GPSR(IP15_17_16, SSI_SCK9),
+       PINMUX_IPSR_GPSR(IP15_17_16, DU2_DB4),
+       PINMUX_IPSR_GPSR(IP15_17_16, LCDOUT20),
        PINMUX_IPSR_MSEL(IP15_19_18, HRTS0_N, SEL_HSCIF0_0),
-       PINMUX_IPSR_DATA(IP15_19_18, SSI_WS9),
-       PINMUX_IPSR_DATA(IP15_19_18, DU2_DB5),
-       PINMUX_IPSR_DATA(IP15_19_18, LCDOUT21),
+       PINMUX_IPSR_GPSR(IP15_19_18, SSI_WS9),
+       PINMUX_IPSR_GPSR(IP15_19_18, DU2_DB5),
+       PINMUX_IPSR_GPSR(IP15_19_18, LCDOUT21),
        PINMUX_IPSR_MSEL(IP15_22_20, MSIOF0_SCK, SEL_SOF0_0),
        PINMUX_IPSR_MSEL(IP15_22_20, TS_SDAT0, SEL_TSIF0_0),
-       PINMUX_IPSR_DATA(IP15_22_20, ADICLK),
-       PINMUX_IPSR_DATA(IP15_22_20, DU2_DB6),
-       PINMUX_IPSR_DATA(IP15_22_20, LCDOUT22),
-       PINMUX_IPSR_DATA(IP15_25_23, MSIOF0_SYNC),
+       PINMUX_IPSR_GPSR(IP15_22_20, ADICLK),
+       PINMUX_IPSR_GPSR(IP15_22_20, DU2_DB6),
+       PINMUX_IPSR_GPSR(IP15_22_20, LCDOUT22),
+       PINMUX_IPSR_GPSR(IP15_25_23, MSIOF0_SYNC),
        PINMUX_IPSR_MSEL(IP15_25_23, TS_SCK0, SEL_TSIF0_0),
-       PINMUX_IPSR_DATA(IP15_25_23, SSI_SCK2),
-       PINMUX_IPSR_DATA(IP15_25_23, ADIDATA),
-       PINMUX_IPSR_DATA(IP15_25_23, DU2_DB7),
-       PINMUX_IPSR_DATA(IP15_25_23, LCDOUT23),
+       PINMUX_IPSR_GPSR(IP15_25_23, SSI_SCK2),
+       PINMUX_IPSR_GPSR(IP15_25_23, ADIDATA),
+       PINMUX_IPSR_GPSR(IP15_25_23, DU2_DB7),
+       PINMUX_IPSR_GPSR(IP15_25_23, LCDOUT23),
        PINMUX_IPSR_MSEL(IP15_25_23, HRX0_C, SEL_SCIFA2_1),
        PINMUX_IPSR_MSEL(IP15_27_26, MSIOF0_SS1, SEL_SOF0_0),
-       PINMUX_IPSR_DATA(IP15_27_26, ADICHS0),
-       PINMUX_IPSR_DATA(IP15_27_26, DU2_DG5),
-       PINMUX_IPSR_DATA(IP15_27_26, LCDOUT13),
+       PINMUX_IPSR_GPSR(IP15_27_26, ADICHS0),
+       PINMUX_IPSR_GPSR(IP15_27_26, DU2_DG5),
+       PINMUX_IPSR_GPSR(IP15_27_26, LCDOUT13),
        PINMUX_IPSR_MSEL(IP15_29_28, MSIOF0_TXD, SEL_SOF0_0),
-       PINMUX_IPSR_DATA(IP15_29_28, ADICHS1),
-       PINMUX_IPSR_DATA(IP15_29_28, DU2_DG6),
-       PINMUX_IPSR_DATA(IP15_29_28, LCDOUT14),
+       PINMUX_IPSR_GPSR(IP15_29_28, ADICHS1),
+       PINMUX_IPSR_GPSR(IP15_29_28, DU2_DG6),
+       PINMUX_IPSR_GPSR(IP15_29_28, LCDOUT14),
 
        PINMUX_IPSR_MSEL(IP16_2_0, MSIOF0_SS2, SEL_SOF0_0),
-       PINMUX_IPSR_DATA(IP16_2_0, AUDIO_CLKOUT),
-       PINMUX_IPSR_DATA(IP16_2_0, ADICHS2),
-       PINMUX_IPSR_DATA(IP16_2_0, DU2_DISP),
-       PINMUX_IPSR_DATA(IP16_2_0, QPOLA),
+       PINMUX_IPSR_GPSR(IP16_2_0, AUDIO_CLKOUT),
+       PINMUX_IPSR_GPSR(IP16_2_0, ADICHS2),
+       PINMUX_IPSR_GPSR(IP16_2_0, DU2_DISP),
+       PINMUX_IPSR_GPSR(IP16_2_0, QPOLA),
        PINMUX_IPSR_MSEL(IP16_2_0, HTX0_C, SEL_HSCIF0_2),
        PINMUX_IPSR_MSEL(IP16_2_0, SCIFA2_TXD_B, SEL_SCIFA2_1),
        PINMUX_IPSR_MSEL(IP16_5_3, MSIOF0_RXD, SEL_SOF0_0),
        PINMUX_IPSR_MSEL(IP16_5_3, TS_SPSYNC0, SEL_TSIF0_0),
-       PINMUX_IPSR_DATA(IP16_5_3, SSI_WS2),
-       PINMUX_IPSR_DATA(IP16_5_3, ADICS_SAMP),
-       PINMUX_IPSR_DATA(IP16_5_3, DU2_CDE),
-       PINMUX_IPSR_DATA(IP16_5_3, QPOLB),
+       PINMUX_IPSR_GPSR(IP16_5_3, SSI_WS2),
+       PINMUX_IPSR_GPSR(IP16_5_3, ADICS_SAMP),
+       PINMUX_IPSR_GPSR(IP16_5_3, DU2_CDE),
+       PINMUX_IPSR_GPSR(IP16_5_3, QPOLB),
        PINMUX_IPSR_MSEL(IP16_5_3, SCIFA2_RXD_B, SEL_HSCIF0_2),
-       PINMUX_IPSR_DATA(IP16_6, USB1_PWEN),
-       PINMUX_IPSR_DATA(IP16_6, AUDIO_CLKOUT_D),
-       PINMUX_IPSR_DATA(IP16_7, USB1_OVC),
+       PINMUX_IPSR_GPSR(IP16_6, USB1_PWEN),
+       PINMUX_IPSR_GPSR(IP16_6, AUDIO_CLKOUT_D),
+       PINMUX_IPSR_GPSR(IP16_7, USB1_OVC),
        PINMUX_IPSR_MSEL(IP16_7, TCLK1_B, SEL_TMU1_1),
 
        PINMUX_DATA(IIC0_SCL_MARK, FN_SEL_IIC0_0),
index 4cfbb94ad5d0bcc035439cfdf8b8bcf8a9bb9312..01abbd5b4e49a783a5181791a4482cc83a2675c9 100644 (file)
@@ -792,171 +792,171 @@ static const u16 pinmux_data[] = {
        PINMUX_SINGLE(SD1_CLK),
 
        /* IPSR0 */
-       PINMUX_IPSR_DATA(IP0_0, D0),
-       PINMUX_IPSR_DATA(IP0_1, D1),
-       PINMUX_IPSR_DATA(IP0_2, D2),
-       PINMUX_IPSR_DATA(IP0_3, D3),
-       PINMUX_IPSR_DATA(IP0_4, D4),
-       PINMUX_IPSR_DATA(IP0_5, D5),
-       PINMUX_IPSR_DATA(IP0_6, D6),
-       PINMUX_IPSR_DATA(IP0_7, D7),
-       PINMUX_IPSR_DATA(IP0_8, D8),
-       PINMUX_IPSR_DATA(IP0_9, D9),
-       PINMUX_IPSR_DATA(IP0_10, D10),
-       PINMUX_IPSR_DATA(IP0_11, D11),
-       PINMUX_IPSR_DATA(IP0_12, D12),
-       PINMUX_IPSR_DATA(IP0_13, D13),
-       PINMUX_IPSR_DATA(IP0_14, D14),
-       PINMUX_IPSR_DATA(IP0_15, D15),
-       PINMUX_IPSR_DATA(IP0_18_16, A0),
+       PINMUX_IPSR_GPSR(IP0_0, D0),
+       PINMUX_IPSR_GPSR(IP0_1, D1),
+       PINMUX_IPSR_GPSR(IP0_2, D2),
+       PINMUX_IPSR_GPSR(IP0_3, D3),
+       PINMUX_IPSR_GPSR(IP0_4, D4),
+       PINMUX_IPSR_GPSR(IP0_5, D5),
+       PINMUX_IPSR_GPSR(IP0_6, D6),
+       PINMUX_IPSR_GPSR(IP0_7, D7),
+       PINMUX_IPSR_GPSR(IP0_8, D8),
+       PINMUX_IPSR_GPSR(IP0_9, D9),
+       PINMUX_IPSR_GPSR(IP0_10, D10),
+       PINMUX_IPSR_GPSR(IP0_11, D11),
+       PINMUX_IPSR_GPSR(IP0_12, D12),
+       PINMUX_IPSR_GPSR(IP0_13, D13),
+       PINMUX_IPSR_GPSR(IP0_14, D14),
+       PINMUX_IPSR_GPSR(IP0_15, D15),
+       PINMUX_IPSR_GPSR(IP0_18_16, A0),
        PINMUX_IPSR_MSEL(IP0_18_16, ATAWR0_N_C, SEL_LBS_2),
        PINMUX_IPSR_MSEL(IP0_18_16, MSIOF0_SCK_B, SEL_SOF0_1),
        PINMUX_IPSR_MSEL(IP0_18_16, SCL0_C, SEL_IIC0_2),
-       PINMUX_IPSR_DATA(IP0_18_16, PWM2_B),
-       PINMUX_IPSR_DATA(IP0_20_19, A1),
+       PINMUX_IPSR_GPSR(IP0_18_16, PWM2_B),
+       PINMUX_IPSR_GPSR(IP0_20_19, A1),
        PINMUX_IPSR_MSEL(IP0_20_19, MSIOF0_SYNC_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP0_22_21, A2),
+       PINMUX_IPSR_GPSR(IP0_22_21, A2),
        PINMUX_IPSR_MSEL(IP0_22_21, MSIOF0_SS1_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP0_24_23, A3),
+       PINMUX_IPSR_GPSR(IP0_24_23, A3),
        PINMUX_IPSR_MSEL(IP0_24_23, MSIOF0_SS2_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP0_26_25, A4),
+       PINMUX_IPSR_GPSR(IP0_26_25, A4),
        PINMUX_IPSR_MSEL(IP0_26_25, MSIOF0_TXD_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP0_28_27, A5),
+       PINMUX_IPSR_GPSR(IP0_28_27, A5),
        PINMUX_IPSR_MSEL(IP0_28_27, MSIOF0_RXD_B, SEL_SOF0_1),
-       PINMUX_IPSR_DATA(IP0_30_29, A6),
+       PINMUX_IPSR_GPSR(IP0_30_29, A6),
        PINMUX_IPSR_MSEL(IP0_30_29, MSIOF1_SCK, SEL_SOF1_0),
 
        /* IPSR1 */
-       PINMUX_IPSR_DATA(IP1_1_0, A7),
+       PINMUX_IPSR_GPSR(IP1_1_0, A7),
        PINMUX_IPSR_MSEL(IP1_1_0, MSIOF1_SYNC, SEL_SOF1_0),
-       PINMUX_IPSR_DATA(IP1_3_2, A8),
+       PINMUX_IPSR_GPSR(IP1_3_2, A8),
        PINMUX_IPSR_MSEL(IP1_3_2, MSIOF1_SS1, SEL_SOF1_0),
        PINMUX_IPSR_MSEL(IP1_3_2, SCL0, SEL_IIC0_0),
-       PINMUX_IPSR_DATA(IP1_5_4, A9),
+       PINMUX_IPSR_GPSR(IP1_5_4, A9),
        PINMUX_IPSR_MSEL(IP1_5_4, MSIOF1_SS2, SEL_SOF1_0),
        PINMUX_IPSR_MSEL(IP1_5_4, SDA0, SEL_IIC0_0),
-       PINMUX_IPSR_DATA(IP1_7_6, A10),
+       PINMUX_IPSR_GPSR(IP1_7_6, A10),
        PINMUX_IPSR_MSEL(IP1_7_6, MSIOF1_TXD, SEL_SOF1_0),
        PINMUX_IPSR_MSEL(IP1_7_6, MSIOF1_TXD_D, SEL_SOF1_3),
-       PINMUX_IPSR_DATA(IP1_10_8, A11),
+       PINMUX_IPSR_GPSR(IP1_10_8, A11),
        PINMUX_IPSR_MSEL(IP1_10_8, MSIOF1_RXD, SEL_SOF1_0),
        PINMUX_IPSR_MSEL(IP1_10_8, SCL3_D, SEL_IIC3_3),
        PINMUX_IPSR_MSEL(IP1_10_8, MSIOF1_RXD_D, SEL_SOF1_3),
-       PINMUX_IPSR_DATA(IP1_13_11, A12),
+       PINMUX_IPSR_GPSR(IP1_13_11, A12),
        PINMUX_IPSR_MSEL(IP1_13_11, FMCLK, SEL_FM_0),
        PINMUX_IPSR_MSEL(IP1_13_11, SDA3_D, SEL_IIC3_3),
        PINMUX_IPSR_MSEL(IP1_13_11, MSIOF1_SCK_D, SEL_SOF1_3),
-       PINMUX_IPSR_DATA(IP1_16_14, A13),
+       PINMUX_IPSR_GPSR(IP1_16_14, A13),
        PINMUX_IPSR_MSEL(IP1_16_14, ATAG0_N_C, SEL_LBS_2),
        PINMUX_IPSR_MSEL(IP1_16_14, BPFCLK, SEL_FM_0),
        PINMUX_IPSR_MSEL(IP1_16_14, MSIOF1_SS1_D, SEL_SOF1_3),
-       PINMUX_IPSR_DATA(IP1_19_17, A14),
+       PINMUX_IPSR_GPSR(IP1_19_17, A14),
        PINMUX_IPSR_MSEL(IP1_19_17, ATADIR0_N_C, SEL_LBS_2),
        PINMUX_IPSR_MSEL(IP1_19_17, FMIN, SEL_FM_0),
        PINMUX_IPSR_MSEL(IP1_19_17, FMIN_C, SEL_FM_2),
        PINMUX_IPSR_MSEL(IP1_19_17, MSIOF1_SYNC_D, SEL_SOF1_3),
-       PINMUX_IPSR_DATA(IP1_22_20, A15),
+       PINMUX_IPSR_GPSR(IP1_22_20, A15),
        PINMUX_IPSR_MSEL(IP1_22_20, BPFCLK_C, SEL_FM_2),
-       PINMUX_IPSR_DATA(IP1_25_23, A16),
+       PINMUX_IPSR_GPSR(IP1_25_23, A16),
        PINMUX_IPSR_MSEL(IP1_25_23, DREQ2_B, SEL_LBS_1),
        PINMUX_IPSR_MSEL(IP1_25_23, FMCLK_C, SEL_FM_2),
        PINMUX_IPSR_MSEL(IP1_25_23, SCIFA1_SCK_B, SEL_SCIFA1_1),
-       PINMUX_IPSR_DATA(IP1_28_26, A17),
+       PINMUX_IPSR_GPSR(IP1_28_26, A17),
        PINMUX_IPSR_MSEL(IP1_28_26, DACK2_B, SEL_LBS_1),
        PINMUX_IPSR_MSEL(IP1_28_26, SDA0_C, SEL_IIC0_2),
-       PINMUX_IPSR_DATA(IP1_31_29, A18),
+       PINMUX_IPSR_GPSR(IP1_31_29, A18),
        PINMUX_IPSR_MSEL(IP1_31_29, DREQ1, SEL_LBS_0),
        PINMUX_IPSR_MSEL(IP1_31_29, SCIFA1_RXD_C, SEL_SCIFA1_2),
        PINMUX_IPSR_MSEL(IP1_31_29, SCIFB1_RXD_C, SEL_SCIFB1_2),
 
        /* IPSR2 */
-       PINMUX_IPSR_DATA(IP2_2_0, A19),
-       PINMUX_IPSR_DATA(IP2_2_0, DACK1),
+       PINMUX_IPSR_GPSR(IP2_2_0, A19),
+       PINMUX_IPSR_GPSR(IP2_2_0, DACK1),
        PINMUX_IPSR_MSEL(IP2_2_0, SCIFA1_TXD_C, SEL_SCIFA1_2),
        PINMUX_IPSR_MSEL(IP2_2_0, SCIFB1_TXD_C, SEL_SCIFB1_2),
        PINMUX_IPSR_MSEL(IP2_2_0, SCIFB1_SCK_B, SEL_SCIFB1_1),
-       PINMUX_IPSR_DATA(IP2_2_0, A20),
+       PINMUX_IPSR_GPSR(IP2_2_0, A20),
        PINMUX_IPSR_MSEL(IP2_4_3, SPCLK, SEL_QSP_0),
-       PINMUX_IPSR_DATA(IP2_6_5, A21),
+       PINMUX_IPSR_GPSR(IP2_6_5, A21),
        PINMUX_IPSR_MSEL(IP2_6_5, ATAWR0_N_B, SEL_LBS_1),
        PINMUX_IPSR_MSEL(IP2_6_5, MOSI_IO0, SEL_QSP_0),
-       PINMUX_IPSR_DATA(IP2_9_7, A22),
+       PINMUX_IPSR_GPSR(IP2_9_7, A22),
        PINMUX_IPSR_MSEL(IP2_9_7, MISO_IO1, SEL_QSP_0),
        PINMUX_IPSR_MSEL(IP2_9_7, FMCLK_B, SEL_FM_1),
        PINMUX_IPSR_MSEL(IP2_9_7, TX0, SEL_SCIF0_0),
        PINMUX_IPSR_MSEL(IP2_9_7, SCIFA0_TXD, SEL_SCFA_0),
-       PINMUX_IPSR_DATA(IP2_12_10, A23),
+       PINMUX_IPSR_GPSR(IP2_12_10, A23),
        PINMUX_IPSR_MSEL(IP2_12_10, IO2, SEL_QSP_0),
        PINMUX_IPSR_MSEL(IP2_12_10, BPFCLK_B, SEL_FM_1),
        PINMUX_IPSR_MSEL(IP2_12_10, RX0, SEL_SCIF0_0),
        PINMUX_IPSR_MSEL(IP2_12_10, SCIFA0_RXD, SEL_SCFA_0),
-       PINMUX_IPSR_DATA(IP2_15_13, A24),
+       PINMUX_IPSR_GPSR(IP2_15_13, A24),
        PINMUX_IPSR_MSEL(IP2_15_13, DREQ2, SEL_LBS_0),
        PINMUX_IPSR_MSEL(IP2_15_13, IO3, SEL_QSP_0),
        PINMUX_IPSR_MSEL(IP2_15_13, TX1, SEL_SCIF1_0),
        PINMUX_IPSR_MSEL(IP2_15_13, SCIFA1_TXD, SEL_SCIFA1_0),
-       PINMUX_IPSR_DATA(IP2_18_16, A25),
+       PINMUX_IPSR_GPSR(IP2_18_16, A25),
        PINMUX_IPSR_MSEL(IP2_18_16, DACK2, SEL_LBS_0),
        PINMUX_IPSR_MSEL(IP2_18_16, SSL, SEL_QSP_0),
        PINMUX_IPSR_MSEL(IP2_18_16, DREQ1_C, SEL_LBS_2),
        PINMUX_IPSR_MSEL(IP2_18_16, RX1, SEL_SCIF1_0),
        PINMUX_IPSR_MSEL(IP2_18_16, SCIFA1_RXD, SEL_SCIFA1_0),
-       PINMUX_IPSR_DATA(IP2_20_19, CS0_N),
+       PINMUX_IPSR_GPSR(IP2_20_19, CS0_N),
        PINMUX_IPSR_MSEL(IP2_20_19, ATAG0_N_B, SEL_LBS_1),
        PINMUX_IPSR_MSEL(IP2_20_19, SCL1, SEL_IIC1_0),
-       PINMUX_IPSR_DATA(IP2_22_21, CS1_N_A26),
+       PINMUX_IPSR_GPSR(IP2_22_21, CS1_N_A26),
        PINMUX_IPSR_MSEL(IP2_22_21, ATADIR0_N_B, SEL_LBS_1),
        PINMUX_IPSR_MSEL(IP2_22_21, SDA1, SEL_IIC1_0),
-       PINMUX_IPSR_DATA(IP2_24_23, EX_CS1_N),
+       PINMUX_IPSR_GPSR(IP2_24_23, EX_CS1_N),
        PINMUX_IPSR_MSEL(IP2_24_23, MSIOF2_SCK, SEL_SOF2_0),
-       PINMUX_IPSR_DATA(IP2_26_25, EX_CS2_N),
+       PINMUX_IPSR_GPSR(IP2_26_25, EX_CS2_N),
        PINMUX_IPSR_MSEL(IP2_26_25, ATAWR0_N, SEL_LBS_0),
        PINMUX_IPSR_MSEL(IP2_26_25, MSIOF2_SYNC, SEL_SOF2_0),
-       PINMUX_IPSR_DATA(IP2_29_27, EX_CS3_N),
+       PINMUX_IPSR_GPSR(IP2_29_27, EX_CS3_N),
        PINMUX_IPSR_MSEL(IP2_29_27, ATADIR0_N, SEL_LBS_0),
        PINMUX_IPSR_MSEL(IP2_29_27, MSIOF2_TXD, SEL_SOF2_0),
        PINMUX_IPSR_MSEL(IP2_29_27, ATAG0_N, SEL_LBS_0),
-       PINMUX_IPSR_DATA(IP2_29_27, EX_WAIT1),
+       PINMUX_IPSR_GPSR(IP2_29_27, EX_WAIT1),
 
        /* IPSR3 */
-       PINMUX_IPSR_DATA(IP3_2_0, EX_CS4_N),
+       PINMUX_IPSR_GPSR(IP3_2_0, EX_CS4_N),
        PINMUX_IPSR_MSEL(IP3_2_0, ATARD0_N, SEL_LBS_0),
        PINMUX_IPSR_MSEL(IP3_2_0, MSIOF2_RXD, SEL_SOF2_0),
-       PINMUX_IPSR_DATA(IP3_2_0, EX_WAIT2),
-       PINMUX_IPSR_DATA(IP3_5_3, EX_CS5_N),
-       PINMUX_IPSR_DATA(IP3_5_3, ATACS00_N),
+       PINMUX_IPSR_GPSR(IP3_2_0, EX_WAIT2),
+       PINMUX_IPSR_GPSR(IP3_5_3, EX_CS5_N),
+       PINMUX_IPSR_GPSR(IP3_5_3, ATACS00_N),
        PINMUX_IPSR_MSEL(IP3_5_3, MSIOF2_SS1, SEL_SOF2_0),
        PINMUX_IPSR_MSEL(IP3_5_3, HRX1_B, SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP3_5_3, SCIFB1_RXD_B, SEL_SCIFB1_1),
-       PINMUX_IPSR_DATA(IP3_5_3, PWM1),
-       PINMUX_IPSR_DATA(IP3_5_3, TPU_TO1),
-       PINMUX_IPSR_DATA(IP3_8_6, BS_N),
-       PINMUX_IPSR_DATA(IP3_8_6, ATACS10_N),
+       PINMUX_IPSR_GPSR(IP3_5_3, PWM1),
+       PINMUX_IPSR_GPSR(IP3_5_3, TPU_TO1),
+       PINMUX_IPSR_GPSR(IP3_8_6, BS_N),
+       PINMUX_IPSR_GPSR(IP3_8_6, ATACS10_N),
        PINMUX_IPSR_MSEL(IP3_8_6, MSIOF2_SS2, SEL_SOF2_0),
        PINMUX_IPSR_MSEL(IP3_8_6, HTX1_B, SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP3_8_6, SCIFB1_TXD_B, SEL_SCIFB1_1),
-       PINMUX_IPSR_DATA(IP3_8_6, PWM2),
-       PINMUX_IPSR_DATA(IP3_8_6, TPU_TO2),
-       PINMUX_IPSR_DATA(IP3_11_9, RD_WR_N),
+       PINMUX_IPSR_GPSR(IP3_8_6, PWM2),
+       PINMUX_IPSR_GPSR(IP3_8_6, TPU_TO2),
+       PINMUX_IPSR_GPSR(IP3_11_9, RD_WR_N),
        PINMUX_IPSR_MSEL(IP3_11_9, HRX2_B, SEL_HSCIF2_1),
        PINMUX_IPSR_MSEL(IP3_11_9, FMIN_B, SEL_FM_1),
        PINMUX_IPSR_MSEL(IP3_11_9, SCIFB0_RXD_B, SEL_SCIFB_1),
        PINMUX_IPSR_MSEL(IP3_11_9, DREQ1_D, SEL_LBS_1),
-       PINMUX_IPSR_DATA(IP3_13_12, WE0_N),
+       PINMUX_IPSR_GPSR(IP3_13_12, WE0_N),
        PINMUX_IPSR_MSEL(IP3_13_12, HCTS2_N_B, SEL_HSCIF2_1),
        PINMUX_IPSR_MSEL(IP3_13_12, SCIFB0_TXD_B, SEL_SCIFB_1),
-       PINMUX_IPSR_DATA(IP3_15_14, WE1_N),
+       PINMUX_IPSR_GPSR(IP3_15_14, WE1_N),
        PINMUX_IPSR_MSEL(IP3_15_14, ATARD0_N_B, SEL_LBS_1),
        PINMUX_IPSR_MSEL(IP3_15_14, HTX2_B, SEL_HSCIF2_1),
        PINMUX_IPSR_MSEL(IP3_15_14, SCIFB0_RTS_N_B, SEL_SCIFB_1),
-       PINMUX_IPSR_DATA(IP3_17_16, EX_WAIT0),
+       PINMUX_IPSR_GPSR(IP3_17_16, EX_WAIT0),
        PINMUX_IPSR_MSEL(IP3_17_16, HRTS2_N_B, SEL_HSCIF2_1),
        PINMUX_IPSR_MSEL(IP3_17_16, SCIFB0_CTS_N_B, SEL_SCIFB_1),
-       PINMUX_IPSR_DATA(IP3_19_18, DREQ0),
-       PINMUX_IPSR_DATA(IP3_19_18, PWM3),
-       PINMUX_IPSR_DATA(IP3_19_18, TPU_TO3),
-       PINMUX_IPSR_DATA(IP3_21_20, DACK0),
-       PINMUX_IPSR_DATA(IP3_21_20, DRACK0),
+       PINMUX_IPSR_GPSR(IP3_19_18, DREQ0),
+       PINMUX_IPSR_GPSR(IP3_19_18, PWM3),
+       PINMUX_IPSR_GPSR(IP3_19_18, TPU_TO3),
+       PINMUX_IPSR_GPSR(IP3_21_20, DACK0),
+       PINMUX_IPSR_GPSR(IP3_21_20, DRACK0),
        PINMUX_IPSR_MSEL(IP3_21_20, REMOCON, SEL_RCN_0),
        PINMUX_IPSR_MSEL(IP3_24_22, SPEEDIN, SEL_RSP_0),
        PINMUX_IPSR_MSEL(IP3_24_22, HSCK0_C, SEL_HSCIF0_2),
@@ -995,61 +995,61 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP4_9_8, SDA1_B, SEL_IIC1_1),
        PINMUX_IPSR_MSEL(IP4_9_8, SDA8_B, SEL_IIC8_1),
        PINMUX_IPSR_MSEL(IP4_9_8, MSIOF2_RXD_C, SEL_SOF2_2),
-       PINMUX_IPSR_DATA(IP4_12_10, SSI_SCK2),
+       PINMUX_IPSR_GPSR(IP4_12_10, SSI_SCK2),
        PINMUX_IPSR_MSEL(IP4_12_10, SCL2, SEL_IIC2_0),
        PINMUX_IPSR_MSEL(IP4_12_10, GPS_CLK_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP4_12_10, GLO_Q0_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP4_15_13, SSI_WS2),
+       PINMUX_IPSR_GPSR(IP4_15_13, SSI_WS2),
        PINMUX_IPSR_MSEL(IP4_15_13, SDA2, SEL_IIC2_0),
        PINMUX_IPSR_MSEL(IP4_15_13, GPS_SIGN_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP4_15_13, RX2_E, SEL_SCIF2_4),
        PINMUX_IPSR_MSEL(IP4_15_13, GLO_Q1_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP4_18_16, SSI_SDATA2),
+       PINMUX_IPSR_GPSR(IP4_18_16, SSI_SDATA2),
        PINMUX_IPSR_MSEL(IP4_18_16, GPS_MAG_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP4_18_16, TX2_E, SEL_SCIF2_4),
-       PINMUX_IPSR_DATA(IP4_19, SSI_SCK34),
-       PINMUX_IPSR_DATA(IP4_20, SSI_WS34),
-       PINMUX_IPSR_DATA(IP4_21, SSI_SDATA3),
-       PINMUX_IPSR_DATA(IP4_23_22, SSI_SCK4),
+       PINMUX_IPSR_GPSR(IP4_19, SSI_SCK34),
+       PINMUX_IPSR_GPSR(IP4_20, SSI_WS34),
+       PINMUX_IPSR_GPSR(IP4_21, SSI_SDATA3),
+       PINMUX_IPSR_GPSR(IP4_23_22, SSI_SCK4),
        PINMUX_IPSR_MSEL(IP4_23_22, GLO_SS_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP4_25_24, SSI_WS4),
+       PINMUX_IPSR_GPSR(IP4_25_24, SSI_WS4),
        PINMUX_IPSR_MSEL(IP4_25_24, GLO_RFON_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP4_27_26, SSI_SDATA4),
+       PINMUX_IPSR_GPSR(IP4_27_26, SSI_SDATA4),
        PINMUX_IPSR_MSEL(IP4_27_26, MSIOF2_SCK_D, SEL_SOF2_3),
-       PINMUX_IPSR_DATA(IP4_30_28, SSI_SCK5),
+       PINMUX_IPSR_GPSR(IP4_30_28, SSI_SCK5),
        PINMUX_IPSR_MSEL(IP4_30_28, MSIOF1_SCK_C, SEL_SOF1_2),
        PINMUX_IPSR_MSEL(IP4_30_28, TS_SDATA0, SEL_TSIF0_0),
        PINMUX_IPSR_MSEL(IP4_30_28, GLO_I0, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP4_30_28, MSIOF2_SYNC_D, SEL_SOF2_3),
-       PINMUX_IPSR_DATA(IP4_30_28, VI1_R2_B),
+       PINMUX_IPSR_GPSR(IP4_30_28, VI1_R2_B),
 
        /* IPSR5 */
-       PINMUX_IPSR_DATA(IP5_2_0, SSI_WS5),
+       PINMUX_IPSR_GPSR(IP5_2_0, SSI_WS5),
        PINMUX_IPSR_MSEL(IP5_2_0, MSIOF1_SYNC_C, SEL_SOF1_2),
        PINMUX_IPSR_MSEL(IP5_2_0, TS_SCK0, SEL_TSIF0_0),
        PINMUX_IPSR_MSEL(IP5_2_0, GLO_I1, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP5_2_0, MSIOF2_TXD_D, SEL_SOF2_3),
-       PINMUX_IPSR_DATA(IP5_2_0, VI1_R3_B),
-       PINMUX_IPSR_DATA(IP5_5_3, SSI_SDATA5),
+       PINMUX_IPSR_GPSR(IP5_2_0, VI1_R3_B),
+       PINMUX_IPSR_GPSR(IP5_5_3, SSI_SDATA5),
        PINMUX_IPSR_MSEL(IP5_5_3, MSIOF1_TXD_C, SEL_SOF1_2),
        PINMUX_IPSR_MSEL(IP5_5_3, TS_SDEN0, SEL_TSIF0_0),
        PINMUX_IPSR_MSEL(IP5_5_3, GLO_Q0, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP5_5_3, MSIOF2_SS1_D, SEL_SOF2_3),
-       PINMUX_IPSR_DATA(IP5_5_3, VI1_R4_B),
-       PINMUX_IPSR_DATA(IP5_8_6, SSI_SCK6),
+       PINMUX_IPSR_GPSR(IP5_5_3, VI1_R4_B),
+       PINMUX_IPSR_GPSR(IP5_8_6, SSI_SCK6),
        PINMUX_IPSR_MSEL(IP5_8_6, MSIOF1_RXD_C, SEL_SOF1_2),
        PINMUX_IPSR_MSEL(IP5_8_6, TS_SPSYNC0, SEL_TSIF0_0),
        PINMUX_IPSR_MSEL(IP5_8_6, GLO_Q1, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP5_8_6, MSIOF2_RXD_D, SEL_SOF2_3),
-       PINMUX_IPSR_DATA(IP5_8_6, VI1_R5_B),
-       PINMUX_IPSR_DATA(IP5_11_9, SSI_WS6),
+       PINMUX_IPSR_GPSR(IP5_8_6, VI1_R5_B),
+       PINMUX_IPSR_GPSR(IP5_11_9, SSI_WS6),
        PINMUX_IPSR_MSEL(IP5_11_9, GLO_SCLK, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP5_11_9, MSIOF2_SS2_D, SEL_SOF2_3),
-       PINMUX_IPSR_DATA(IP5_11_9, VI1_R6_B),
-       PINMUX_IPSR_DATA(IP5_14_12, SSI_SDATA6),
+       PINMUX_IPSR_GPSR(IP5_11_9, VI1_R6_B),
+       PINMUX_IPSR_GPSR(IP5_14_12, SSI_SDATA6),
        PINMUX_IPSR_MSEL(IP5_14_12, STP_IVCXO27_0_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP5_14_12, GLO_SDATA, SEL_GPS_0),
-       PINMUX_IPSR_DATA(IP5_14_12, VI1_R7_B),
+       PINMUX_IPSR_GPSR(IP5_14_12, VI1_R7_B),
        PINMUX_IPSR_MSEL(IP5_16_15, SSI_SCK78, SEL_SSI7_0),
        PINMUX_IPSR_MSEL(IP5_16_15, STP_ISCLK_0_B, SEL_SSP_1),
        PINMUX_IPSR_MSEL(IP5_16_15, GLO_SS, SEL_GPS_0),
@@ -1080,307 +1080,307 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP6_2_0, MSIOF1_SCK_B, SEL_SOF1_1),
        PINMUX_IPSR_MSEL(IP6_2_0, SCIF_CLK, SEL_SCIF_0),
        PINMUX_IPSR_MSEL(IP6_2_0, BPFCLK_E, SEL_FM_4),
-       PINMUX_IPSR_DATA(IP6_5_3, AUDIO_CLKC),
+       PINMUX_IPSR_GPSR(IP6_5_3, AUDIO_CLKC),
        PINMUX_IPSR_MSEL(IP6_5_3, SCIFB0_SCK_C, SEL_SCIFB_2),
        PINMUX_IPSR_MSEL(IP6_5_3, MSIOF1_SYNC_B, SEL_SOF1_1),
        PINMUX_IPSR_MSEL(IP6_5_3, RX2, SEL_SCIF2_0),
        PINMUX_IPSR_MSEL(IP6_5_3, SCIFA2_RXD, SEL_SCIFA2_0),
        PINMUX_IPSR_MSEL(IP6_5_3, FMIN_E, SEL_FM_4),
-       PINMUX_IPSR_DATA(IP6_7_6, AUDIO_CLKOUT),
+       PINMUX_IPSR_GPSR(IP6_7_6, AUDIO_CLKOUT),
        PINMUX_IPSR_MSEL(IP6_7_6, MSIOF1_SS1_B, SEL_SOF1_1),
        PINMUX_IPSR_MSEL(IP6_5_3, TX2, SEL_SCIF2_0),
        PINMUX_IPSR_MSEL(IP6_7_6, SCIFA2_TXD, SEL_SCIFA2_0),
-       PINMUX_IPSR_DATA(IP6_9_8, IRQ0),
+       PINMUX_IPSR_GPSR(IP6_9_8, IRQ0),
        PINMUX_IPSR_MSEL(IP6_9_8, SCIFB1_RXD_D, SEL_SCIFB1_3),
-       PINMUX_IPSR_DATA(IP6_9_8, INTC_IRQ0_N),
-       PINMUX_IPSR_DATA(IP6_11_10, IRQ1),
+       PINMUX_IPSR_GPSR(IP6_9_8, INTC_IRQ0_N),
+       PINMUX_IPSR_GPSR(IP6_11_10, IRQ1),
        PINMUX_IPSR_MSEL(IP6_11_10, SCIFB1_SCK_C, SEL_SCIFB1_2),
-       PINMUX_IPSR_DATA(IP6_11_10, INTC_IRQ1_N),
-       PINMUX_IPSR_DATA(IP6_13_12, IRQ2),
+       PINMUX_IPSR_GPSR(IP6_11_10, INTC_IRQ1_N),
+       PINMUX_IPSR_GPSR(IP6_13_12, IRQ2),
        PINMUX_IPSR_MSEL(IP6_13_12, SCIFB1_TXD_D, SEL_SCIFB1_3),
-       PINMUX_IPSR_DATA(IP6_13_12, INTC_IRQ2_N),
-       PINMUX_IPSR_DATA(IP6_15_14, IRQ3),
+       PINMUX_IPSR_GPSR(IP6_13_12, INTC_IRQ2_N),
+       PINMUX_IPSR_GPSR(IP6_15_14, IRQ3),
        PINMUX_IPSR_MSEL(IP6_15_14, SCL4_C, SEL_IIC4_2),
        PINMUX_IPSR_MSEL(IP6_15_14, MSIOF2_TXD_E, SEL_SOF2_4),
-       PINMUX_IPSR_DATA(IP6_15_14, INTC_IRQ4_N),
-       PINMUX_IPSR_DATA(IP6_18_16, IRQ4),
+       PINMUX_IPSR_GPSR(IP6_15_14, INTC_IRQ4_N),
+       PINMUX_IPSR_GPSR(IP6_18_16, IRQ4),
        PINMUX_IPSR_MSEL(IP6_18_16, HRX1_C, SEL_HSCIF1_2),
        PINMUX_IPSR_MSEL(IP6_18_16, SDA4_C, SEL_IIC4_2),
        PINMUX_IPSR_MSEL(IP6_18_16, MSIOF2_RXD_E, SEL_SOF2_4),
-       PINMUX_IPSR_DATA(IP6_18_16, INTC_IRQ4_N),
-       PINMUX_IPSR_DATA(IP6_20_19, IRQ5),
+       PINMUX_IPSR_GPSR(IP6_18_16, INTC_IRQ4_N),
+       PINMUX_IPSR_GPSR(IP6_20_19, IRQ5),
        PINMUX_IPSR_MSEL(IP6_20_19, HTX1_C, SEL_HSCIF1_2),
        PINMUX_IPSR_MSEL(IP6_20_19, SCL1_E, SEL_IIC1_4),
        PINMUX_IPSR_MSEL(IP6_20_19, MSIOF2_SCK_E, SEL_SOF2_4),
-       PINMUX_IPSR_DATA(IP6_23_21, IRQ6),
+       PINMUX_IPSR_GPSR(IP6_23_21, IRQ6),
        PINMUX_IPSR_MSEL(IP6_23_21, HSCK1_C, SEL_HSCIF1_2),
        PINMUX_IPSR_MSEL(IP6_23_21, MSIOF1_SS2_B, SEL_SOF1_1),
        PINMUX_IPSR_MSEL(IP6_23_21, SDA1_E, SEL_IIC1_4),
        PINMUX_IPSR_MSEL(IP6_23_21, MSIOF2_SYNC_E, SEL_SOF2_4),
-       PINMUX_IPSR_DATA(IP6_26_24, IRQ7),
+       PINMUX_IPSR_GPSR(IP6_26_24, IRQ7),
        PINMUX_IPSR_MSEL(IP6_26_24, HCTS1_N_C, SEL_HSCIF1_2),
        PINMUX_IPSR_MSEL(IP6_26_24, MSIOF1_TXD_B, SEL_SOF1_1),
        PINMUX_IPSR_MSEL(IP6_26_24, GPS_CLK_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP6_26_24, GPS_CLK_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP6_29_27, IRQ8),
+       PINMUX_IPSR_GPSR(IP6_29_27, IRQ8),
        PINMUX_IPSR_MSEL(IP6_29_27, HRTS1_N_C, SEL_HSCIF1_2),
        PINMUX_IPSR_MSEL(IP6_29_27, MSIOF1_RXD_B, SEL_SOF1_1),
        PINMUX_IPSR_MSEL(IP6_29_27, GPS_SIGN_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP6_29_27, GPS_SIGN_D, SEL_GPS_3),
 
        /* IPSR7 */
-       PINMUX_IPSR_DATA(IP7_2_0, IRQ9),
+       PINMUX_IPSR_GPSR(IP7_2_0, IRQ9),
        PINMUX_IPSR_MSEL(IP7_2_0, DU1_DOTCLKIN_B, SEL_DIS_1),
        PINMUX_IPSR_MSEL(IP7_2_0, CAN_CLK_D, SEL_CANCLK_3),
        PINMUX_IPSR_MSEL(IP7_2_0, GPS_MAG_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP7_2_0, SCIF_CLK_B, SEL_SCIF_1),
        PINMUX_IPSR_MSEL(IP7_2_0, GPS_MAG_D, SEL_GPS_3),
-       PINMUX_IPSR_DATA(IP7_5_3, DU1_DR0),
-       PINMUX_IPSR_DATA(IP7_5_3, LCDOUT0),
+       PINMUX_IPSR_GPSR(IP7_5_3, DU1_DR0),
+       PINMUX_IPSR_GPSR(IP7_5_3, LCDOUT0),
        PINMUX_IPSR_MSEL(IP7_5_3, VI1_DATA0_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP7_5_3, TX0_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP7_5_3, SCIFA0_TXD_B, SEL_SCFA_1),
        PINMUX_IPSR_MSEL(IP7_5_3, MSIOF2_SCK_B, SEL_SOF2_1),
-       PINMUX_IPSR_DATA(IP7_8_6, DU1_DR1),
-       PINMUX_IPSR_DATA(IP7_8_6, LCDOUT1),
+       PINMUX_IPSR_GPSR(IP7_8_6, DU1_DR1),
+       PINMUX_IPSR_GPSR(IP7_8_6, LCDOUT1),
        PINMUX_IPSR_MSEL(IP7_8_6, VI1_DATA1_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP7_8_6, RX0_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP7_8_6, SCIFA0_RXD_B, SEL_SCFA_1),
        PINMUX_IPSR_MSEL(IP7_8_6, MSIOF2_SYNC_B, SEL_SOF2_1),
-       PINMUX_IPSR_DATA(IP7_10_9, DU1_DR2),
-       PINMUX_IPSR_DATA(IP7_10_9, LCDOUT2),
+       PINMUX_IPSR_GPSR(IP7_10_9, DU1_DR2),
+       PINMUX_IPSR_GPSR(IP7_10_9, LCDOUT2),
        PINMUX_IPSR_MSEL(IP7_10_9, SSI_SCK0129_B, SEL_SSI0_1),
-       PINMUX_IPSR_DATA(IP7_12_11, DU1_DR3),
-       PINMUX_IPSR_DATA(IP7_12_11, LCDOUT3),
+       PINMUX_IPSR_GPSR(IP7_12_11, DU1_DR3),
+       PINMUX_IPSR_GPSR(IP7_12_11, LCDOUT3),
        PINMUX_IPSR_MSEL(IP7_12_11, SSI_WS0129_B, SEL_SSI0_1),
-       PINMUX_IPSR_DATA(IP7_14_13, DU1_DR4),
-       PINMUX_IPSR_DATA(IP7_14_13, LCDOUT4),
+       PINMUX_IPSR_GPSR(IP7_14_13, DU1_DR4),
+       PINMUX_IPSR_GPSR(IP7_14_13, LCDOUT4),
        PINMUX_IPSR_MSEL(IP7_14_13, SSI_SDATA0_B, SEL_SSI0_1),
-       PINMUX_IPSR_DATA(IP7_16_15, DU1_DR5),
-       PINMUX_IPSR_DATA(IP7_16_15, LCDOUT5),
+       PINMUX_IPSR_GPSR(IP7_16_15, DU1_DR5),
+       PINMUX_IPSR_GPSR(IP7_16_15, LCDOUT5),
        PINMUX_IPSR_MSEL(IP7_16_15, SSI_SCK1_B, SEL_SSI1_1),
-       PINMUX_IPSR_DATA(IP7_18_17, DU1_DR6),
-       PINMUX_IPSR_DATA(IP7_18_17, LCDOUT6),
+       PINMUX_IPSR_GPSR(IP7_18_17, DU1_DR6),
+       PINMUX_IPSR_GPSR(IP7_18_17, LCDOUT6),
        PINMUX_IPSR_MSEL(IP7_18_17, SSI_WS1_B, SEL_SSI1_1),
-       PINMUX_IPSR_DATA(IP7_20_19, DU1_DR7),
-       PINMUX_IPSR_DATA(IP7_20_19, LCDOUT7),
+       PINMUX_IPSR_GPSR(IP7_20_19, DU1_DR7),
+       PINMUX_IPSR_GPSR(IP7_20_19, LCDOUT7),
        PINMUX_IPSR_MSEL(IP7_20_19, SSI_SDATA1_B, SEL_SSI1_1),
-       PINMUX_IPSR_DATA(IP7_23_21, DU1_DG0),
-       PINMUX_IPSR_DATA(IP7_23_21, LCDOUT8),
+       PINMUX_IPSR_GPSR(IP7_23_21, DU1_DG0),
+       PINMUX_IPSR_GPSR(IP7_23_21, LCDOUT8),
        PINMUX_IPSR_MSEL(IP7_23_21, VI1_DATA2_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP7_23_21, TX1_B, SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP7_23_21, SCIFA1_TXD_B, SEL_SCIFA1_1),
        PINMUX_IPSR_MSEL(IP7_23_21, MSIOF2_SS1_B, SEL_SOF2_1),
-       PINMUX_IPSR_DATA(IP7_26_24, DU1_DG1),
-       PINMUX_IPSR_DATA(IP7_26_24, LCDOUT9),
+       PINMUX_IPSR_GPSR(IP7_26_24, DU1_DG1),
+       PINMUX_IPSR_GPSR(IP7_26_24, LCDOUT9),
        PINMUX_IPSR_MSEL(IP7_26_24, VI1_DATA3_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP7_26_24, RX1_B, SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP7_26_24, SCIFA1_RXD_B, SEL_SCIFA1_1),
        PINMUX_IPSR_MSEL(IP7_26_24, MSIOF2_SS2_B, SEL_SOF2_1),
-       PINMUX_IPSR_DATA(IP7_29_27, DU1_DG2),
-       PINMUX_IPSR_DATA(IP7_29_27, LCDOUT10),
+       PINMUX_IPSR_GPSR(IP7_29_27, DU1_DG2),
+       PINMUX_IPSR_GPSR(IP7_29_27, LCDOUT10),
        PINMUX_IPSR_MSEL(IP7_29_27, VI1_DATA4_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP7_29_27, SCIF1_SCK_B),
+       PINMUX_IPSR_GPSR(IP7_29_27, SCIF1_SCK_B),
        PINMUX_IPSR_MSEL(IP7_29_27, SCIFA1_SCK, SEL_SCIFA1_0),
        PINMUX_IPSR_MSEL(IP7_29_27, SSI_SCK78_B, SEL_SSI7_1),
 
        /* IPSR8 */
-       PINMUX_IPSR_DATA(IP8_2_0, DU1_DG3),
-       PINMUX_IPSR_DATA(IP8_2_0, LCDOUT11),
+       PINMUX_IPSR_GPSR(IP8_2_0, DU1_DG3),
+       PINMUX_IPSR_GPSR(IP8_2_0, LCDOUT11),
        PINMUX_IPSR_MSEL(IP8_2_0, VI1_DATA5_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP8_2_0, SSI_WS78_B, SEL_SSI7_1),
-       PINMUX_IPSR_DATA(IP8_5_3, DU1_DG4),
-       PINMUX_IPSR_DATA(IP8_5_3, LCDOUT12),
+       PINMUX_IPSR_GPSR(IP8_5_3, DU1_DG4),
+       PINMUX_IPSR_GPSR(IP8_5_3, LCDOUT12),
        PINMUX_IPSR_MSEL(IP8_5_3, VI1_DATA6_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP8_5_3, HRX0_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP8_5_3, SCIFB2_RXD_B, SEL_SCIFB2_1),
        PINMUX_IPSR_MSEL(IP8_5_3, SSI_SDATA7_B, SEL_SSI7_1),
-       PINMUX_IPSR_DATA(IP8_8_6, DU1_DG5),
-       PINMUX_IPSR_DATA(IP8_8_6, LCDOUT13),
+       PINMUX_IPSR_GPSR(IP8_8_6, DU1_DG5),
+       PINMUX_IPSR_GPSR(IP8_8_6, LCDOUT13),
        PINMUX_IPSR_MSEL(IP8_8_6, VI1_DATA7_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP8_8_6, HCTS0_N_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP8_8_6, SCIFB2_TXD_B, SEL_SCIFB2_1),
        PINMUX_IPSR_MSEL(IP8_8_6, SSI_SDATA8_B, SEL_SSI8_1),
-       PINMUX_IPSR_DATA(IP8_11_9, DU1_DG6),
-       PINMUX_IPSR_DATA(IP8_11_9, LCDOUT14),
+       PINMUX_IPSR_GPSR(IP8_11_9, DU1_DG6),
+       PINMUX_IPSR_GPSR(IP8_11_9, LCDOUT14),
        PINMUX_IPSR_MSEL(IP8_11_9, HRTS0_N_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP8_11_9, SCIFB2_CTS_N_B, SEL_SCIFB2_1),
        PINMUX_IPSR_MSEL(IP8_11_9, SSI_SCK9_B, SEL_SSI9_1),
-       PINMUX_IPSR_DATA(IP8_14_12, DU1_DG7),
-       PINMUX_IPSR_DATA(IP8_14_12, LCDOUT15),
+       PINMUX_IPSR_GPSR(IP8_14_12, DU1_DG7),
+       PINMUX_IPSR_GPSR(IP8_14_12, LCDOUT15),
        PINMUX_IPSR_MSEL(IP8_14_12, HTX0_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP8_14_12, SCIFB2_RTS_N_B, SEL_SCIFB2_1),
        PINMUX_IPSR_MSEL(IP8_14_12, SSI_WS9_B, SEL_SSI9_1),
-       PINMUX_IPSR_DATA(IP8_17_15, DU1_DB0),
-       PINMUX_IPSR_DATA(IP8_17_15, LCDOUT16),
+       PINMUX_IPSR_GPSR(IP8_17_15, DU1_DB0),
+       PINMUX_IPSR_GPSR(IP8_17_15, LCDOUT16),
        PINMUX_IPSR_MSEL(IP8_17_15, VI1_CLK_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP8_17_15, TX2_B, SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP8_17_15, SCIFA2_TXD_B, SEL_SCIFA2_1),
        PINMUX_IPSR_MSEL(IP8_17_15, MSIOF2_TXD_B, SEL_SOF2_1),
-       PINMUX_IPSR_DATA(IP8_20_18, DU1_DB1),
-       PINMUX_IPSR_DATA(IP8_20_18, LCDOUT17),
+       PINMUX_IPSR_GPSR(IP8_20_18, DU1_DB1),
+       PINMUX_IPSR_GPSR(IP8_20_18, LCDOUT17),
        PINMUX_IPSR_MSEL(IP8_20_18, VI1_HSYNC_N_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP8_20_18, RX2_B, SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP8_20_18, SCIFA2_RXD_B, SEL_SCIFA2_1),
        PINMUX_IPSR_MSEL(IP8_20_18, MSIOF2_RXD_B, SEL_SOF2_1),
-       PINMUX_IPSR_DATA(IP8_23_21, DU1_DB2),
-       PINMUX_IPSR_DATA(IP8_23_21, LCDOUT18),
+       PINMUX_IPSR_GPSR(IP8_23_21, DU1_DB2),
+       PINMUX_IPSR_GPSR(IP8_23_21, LCDOUT18),
        PINMUX_IPSR_MSEL(IP8_23_21, VI1_VSYNC_N_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP8_23_21, SCIF2_SCK_B),
+       PINMUX_IPSR_GPSR(IP8_23_21, SCIF2_SCK_B),
        PINMUX_IPSR_MSEL(IP8_23_21, SCIFA2_SCK, SEL_SCIFA2_1),
        PINMUX_IPSR_MSEL(IP8_23_21, SSI_SDATA9_B, SEL_SSI9_1),
-       PINMUX_IPSR_DATA(IP8_25_24, DU1_DB3),
-       PINMUX_IPSR_DATA(IP8_25_24, LCDOUT19),
+       PINMUX_IPSR_GPSR(IP8_25_24, DU1_DB3),
+       PINMUX_IPSR_GPSR(IP8_25_24, LCDOUT19),
        PINMUX_IPSR_MSEL(IP8_25_24, VI1_CLKENB_B, SEL_VI1_1),
-       PINMUX_IPSR_DATA(IP8_27_26, DU1_DB4),
-       PINMUX_IPSR_DATA(IP8_27_26, LCDOUT20),
+       PINMUX_IPSR_GPSR(IP8_27_26, DU1_DB4),
+       PINMUX_IPSR_GPSR(IP8_27_26, LCDOUT20),
        PINMUX_IPSR_MSEL(IP8_27_26, VI1_FIELD_B, SEL_VI1_1),
        PINMUX_IPSR_MSEL(IP8_27_26, CAN1_RX, SEL_CAN1_0),
-       PINMUX_IPSR_DATA(IP8_30_28, DU1_DB5),
-       PINMUX_IPSR_DATA(IP8_30_28, LCDOUT21),
+       PINMUX_IPSR_GPSR(IP8_30_28, DU1_DB5),
+       PINMUX_IPSR_GPSR(IP8_30_28, LCDOUT21),
        PINMUX_IPSR_MSEL(IP8_30_28, TX3, SEL_SCIF3_0),
        PINMUX_IPSR_MSEL(IP8_30_28, SCIFA3_TXD, SEL_SCIFA3_0),
        PINMUX_IPSR_MSEL(IP8_30_28, CAN1_TX, SEL_CAN1_0),
 
        /* IPSR9 */
-       PINMUX_IPSR_DATA(IP9_2_0, DU1_DB6),
-       PINMUX_IPSR_DATA(IP9_2_0, LCDOUT22),
+       PINMUX_IPSR_GPSR(IP9_2_0, DU1_DB6),
+       PINMUX_IPSR_GPSR(IP9_2_0, LCDOUT22),
        PINMUX_IPSR_MSEL(IP9_2_0, SCL3_C, SEL_IIC3_2),
        PINMUX_IPSR_MSEL(IP9_2_0, RX3, SEL_SCIF3_0),
        PINMUX_IPSR_MSEL(IP9_2_0, SCIFA3_RXD, SEL_SCIFA3_0),
-       PINMUX_IPSR_DATA(IP9_5_3, DU1_DB7),
-       PINMUX_IPSR_DATA(IP9_5_3, LCDOUT23),
+       PINMUX_IPSR_GPSR(IP9_5_3, DU1_DB7),
+       PINMUX_IPSR_GPSR(IP9_5_3, LCDOUT23),
        PINMUX_IPSR_MSEL(IP9_5_3, SDA3_C, SEL_IIC3_2),
        PINMUX_IPSR_MSEL(IP9_5_3, SCIF3_SCK, SEL_SCIF3_0),
        PINMUX_IPSR_MSEL(IP9_5_3, SCIFA3_SCK, SEL_SCIFA3_0),
        PINMUX_IPSR_MSEL(IP9_6, DU1_DOTCLKIN, SEL_DIS_0),
-       PINMUX_IPSR_DATA(IP9_6, QSTVA_QVS),
-       PINMUX_IPSR_DATA(IP9_7, DU1_DOTCLKOUT0),
-       PINMUX_IPSR_DATA(IP9_7, QCLK),
-       PINMUX_IPSR_DATA(IP9_10_8, DU1_DOTCLKOUT1),
-       PINMUX_IPSR_DATA(IP9_10_8, QSTVB_QVE),
+       PINMUX_IPSR_GPSR(IP9_6, QSTVA_QVS),
+       PINMUX_IPSR_GPSR(IP9_7, DU1_DOTCLKOUT0),
+       PINMUX_IPSR_GPSR(IP9_7, QCLK),
+       PINMUX_IPSR_GPSR(IP9_10_8, DU1_DOTCLKOUT1),
+       PINMUX_IPSR_GPSR(IP9_10_8, QSTVB_QVE),
        PINMUX_IPSR_MSEL(IP9_10_8, CAN0_TX, SEL_CAN0_0),
        PINMUX_IPSR_MSEL(IP9_10_8, TX3_B, SEL_SCIF3_1),
        PINMUX_IPSR_MSEL(IP9_10_8, SCL2_B, SEL_IIC2_1),
-       PINMUX_IPSR_DATA(IP9_10_8, PWM4),
-       PINMUX_IPSR_DATA(IP9_11, DU1_EXHSYNC_DU1_HSYNC),
-       PINMUX_IPSR_DATA(IP9_11, QSTH_QHS),
-       PINMUX_IPSR_DATA(IP9_12, DU1_EXVSYNC_DU1_VSYNC),
-       PINMUX_IPSR_DATA(IP9_12, QSTB_QHE),
-       PINMUX_IPSR_DATA(IP9_15_13, DU1_EXODDF_DU1_ODDF_DISP_CDE),
-       PINMUX_IPSR_DATA(IP9_15_13, QCPV_QDE),
+       PINMUX_IPSR_GPSR(IP9_10_8, PWM4),
+       PINMUX_IPSR_GPSR(IP9_11, DU1_EXHSYNC_DU1_HSYNC),
+       PINMUX_IPSR_GPSR(IP9_11, QSTH_QHS),
+       PINMUX_IPSR_GPSR(IP9_12, DU1_EXVSYNC_DU1_VSYNC),
+       PINMUX_IPSR_GPSR(IP9_12, QSTB_QHE),
+       PINMUX_IPSR_GPSR(IP9_15_13, DU1_EXODDF_DU1_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP9_15_13, QCPV_QDE),
        PINMUX_IPSR_MSEL(IP9_15_13, CAN0_RX, SEL_CAN0_0),
        PINMUX_IPSR_MSEL(IP9_15_13, RX3_B, SEL_SCIF3_1),
        PINMUX_IPSR_MSEL(IP9_15_13, SDA2_B, SEL_IIC2_1),
-       PINMUX_IPSR_DATA(IP9_16, DU1_DISP),
-       PINMUX_IPSR_DATA(IP9_16, QPOLA),
-       PINMUX_IPSR_DATA(IP9_18_17, DU1_CDE),
-       PINMUX_IPSR_DATA(IP9_18_17, QPOLB),
-       PINMUX_IPSR_DATA(IP9_18_17, PWM4_B),
-       PINMUX_IPSR_DATA(IP9_20_19, VI0_CLKENB),
+       PINMUX_IPSR_GPSR(IP9_16, DU1_DISP),
+       PINMUX_IPSR_GPSR(IP9_16, QPOLA),
+       PINMUX_IPSR_GPSR(IP9_18_17, DU1_CDE),
+       PINMUX_IPSR_GPSR(IP9_18_17, QPOLB),
+       PINMUX_IPSR_GPSR(IP9_18_17, PWM4_B),
+       PINMUX_IPSR_GPSR(IP9_20_19, VI0_CLKENB),
        PINMUX_IPSR_MSEL(IP9_20_19, TX4, SEL_SCIF4_0),
        PINMUX_IPSR_MSEL(IP9_20_19, SCIFA4_TXD, SEL_SCIFA4_0),
        PINMUX_IPSR_MSEL(IP9_20_19, TS_SDATA0_D, SEL_TSIF0_3),
-       PINMUX_IPSR_DATA(IP9_22_21, VI0_FIELD),
+       PINMUX_IPSR_GPSR(IP9_22_21, VI0_FIELD),
        PINMUX_IPSR_MSEL(IP9_22_21, RX4, SEL_SCIF4_0),
        PINMUX_IPSR_MSEL(IP9_22_21, SCIFA4_RXD, SEL_SCIFA4_0),
        PINMUX_IPSR_MSEL(IP9_22_21, TS_SCK0_D, SEL_TSIF0_3),
-       PINMUX_IPSR_DATA(IP9_24_23, VI0_HSYNC_N),
+       PINMUX_IPSR_GPSR(IP9_24_23, VI0_HSYNC_N),
        PINMUX_IPSR_MSEL(IP9_24_23, TX5, SEL_SCIF5_0),
        PINMUX_IPSR_MSEL(IP9_24_23, SCIFA5_TXD, SEL_SCIFA5_0),
        PINMUX_IPSR_MSEL(IP9_24_23, TS_SDEN0_D, SEL_TSIF0_3),
-       PINMUX_IPSR_DATA(IP9_26_25, VI0_VSYNC_N),
+       PINMUX_IPSR_GPSR(IP9_26_25, VI0_VSYNC_N),
        PINMUX_IPSR_MSEL(IP9_26_25, RX5, SEL_SCIF5_0),
        PINMUX_IPSR_MSEL(IP9_26_25, SCIFA5_RXD, SEL_SCIFA5_0),
        PINMUX_IPSR_MSEL(IP9_26_25, TS_SPSYNC0_D, SEL_TSIF0_3),
-       PINMUX_IPSR_DATA(IP9_28_27, VI0_DATA3_VI0_B3),
+       PINMUX_IPSR_GPSR(IP9_28_27, VI0_DATA3_VI0_B3),
        PINMUX_IPSR_MSEL(IP9_28_27, SCIF3_SCK_B, SEL_SCIF3_1),
        PINMUX_IPSR_MSEL(IP9_28_27, SCIFA3_SCK_B, SEL_SCIFA3_1),
-       PINMUX_IPSR_DATA(IP9_31_29, VI0_G0),
+       PINMUX_IPSR_GPSR(IP9_31_29, VI0_G0),
        PINMUX_IPSR_MSEL(IP9_31_29, SCL8, SEL_IIC8_0),
        PINMUX_IPSR_MSEL(IP9_31_29, STP_IVCXO27_0_C, SEL_SSP_2),
        PINMUX_IPSR_MSEL(IP9_31_29, SCL4, SEL_IIC4_0),
        PINMUX_IPSR_MSEL(IP9_31_29, HCTS2_N, SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP9_31_29, SCIFB2_CTS_N, SEL_SCIFB2_0),
-       PINMUX_IPSR_DATA(IP9_31_29, ATAWR1_N),
+       PINMUX_IPSR_GPSR(IP9_31_29, ATAWR1_N),
 
        /* IPSR10 */
-       PINMUX_IPSR_DATA(IP10_2_0, VI0_G1),
+       PINMUX_IPSR_GPSR(IP10_2_0, VI0_G1),
        PINMUX_IPSR_MSEL(IP10_2_0, SDA8, SEL_IIC8_0),
        PINMUX_IPSR_MSEL(IP10_2_0, STP_ISCLK_0_C, SEL_SSP_2),
        PINMUX_IPSR_MSEL(IP10_2_0, SDA4, SEL_IIC4_0),
        PINMUX_IPSR_MSEL(IP10_2_0, HRTS2_N, SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP10_2_0, SCIFB2_RTS_N, SEL_SCIFB2_0),
-       PINMUX_IPSR_DATA(IP10_2_0, ATADIR1_N),
-       PINMUX_IPSR_DATA(IP10_5_3, VI0_G2),
-       PINMUX_IPSR_DATA(IP10_5_3, VI2_HSYNC_N),
+       PINMUX_IPSR_GPSR(IP10_2_0, ATADIR1_N),
+       PINMUX_IPSR_GPSR(IP10_5_3, VI0_G2),
+       PINMUX_IPSR_GPSR(IP10_5_3, VI2_HSYNC_N),
        PINMUX_IPSR_MSEL(IP10_5_3, STP_ISD_0_C, SEL_SSP_2),
        PINMUX_IPSR_MSEL(IP10_5_3, SCL3_B, SEL_IIC3_1),
        PINMUX_IPSR_MSEL(IP10_5_3, HSCK2, SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP10_5_3, SCIFB2_SCK, SEL_SCIFB2_0),
-       PINMUX_IPSR_DATA(IP10_5_3, ATARD1_N),
-       PINMUX_IPSR_DATA(IP10_8_6, VI0_G3),
-       PINMUX_IPSR_DATA(IP10_8_6, VI2_VSYNC_N),
+       PINMUX_IPSR_GPSR(IP10_5_3, ATARD1_N),
+       PINMUX_IPSR_GPSR(IP10_8_6, VI0_G3),
+       PINMUX_IPSR_GPSR(IP10_8_6, VI2_VSYNC_N),
        PINMUX_IPSR_MSEL(IP10_8_6, STP_ISEN_0_C, SEL_SSP_2),
        PINMUX_IPSR_MSEL(IP10_8_6, SDA3_B, SEL_IIC3_1),
        PINMUX_IPSR_MSEL(IP10_8_6, HRX2, SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP10_8_6, SCIFB2_RXD, SEL_SCIFB2_0),
-       PINMUX_IPSR_DATA(IP10_8_6, ATACS01_N),
-       PINMUX_IPSR_DATA(IP10_11_9, VI0_G4),
-       PINMUX_IPSR_DATA(IP10_11_9, VI2_CLKENB),
+       PINMUX_IPSR_GPSR(IP10_8_6, ATACS01_N),
+       PINMUX_IPSR_GPSR(IP10_11_9, VI0_G4),
+       PINMUX_IPSR_GPSR(IP10_11_9, VI2_CLKENB),
        PINMUX_IPSR_MSEL(IP10_11_9, STP_ISSYNC_0_C, SEL_SSP_2),
        PINMUX_IPSR_MSEL(IP10_11_9, HTX2, SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP10_11_9, SCIFB2_TXD, SEL_SCIFB2_0),
        PINMUX_IPSR_MSEL(IP10_11_9, SCIFB0_SCK_D, SEL_SCIFB_3),
-       PINMUX_IPSR_DATA(IP10_14_12, VI0_G5),
-       PINMUX_IPSR_DATA(IP10_14_12, VI2_FIELD),
+       PINMUX_IPSR_GPSR(IP10_14_12, VI0_G5),
+       PINMUX_IPSR_GPSR(IP10_14_12, VI2_FIELD),
        PINMUX_IPSR_MSEL(IP10_14_12, STP_OPWM_0_C, SEL_SSP_2),
        PINMUX_IPSR_MSEL(IP10_14_12, FMCLK_D, SEL_FM_3),
        PINMUX_IPSR_MSEL(IP10_14_12, CAN0_TX_E, SEL_CAN0_4),
        PINMUX_IPSR_MSEL(IP10_14_12, HTX1_D, SEL_HSCIF1_3),
        PINMUX_IPSR_MSEL(IP10_14_12, SCIFB0_TXD_D, SEL_SCIFB_3),
-       PINMUX_IPSR_DATA(IP10_16_15, VI0_G6),
-       PINMUX_IPSR_DATA(IP10_16_15, VI2_CLK),
+       PINMUX_IPSR_GPSR(IP10_16_15, VI0_G6),
+       PINMUX_IPSR_GPSR(IP10_16_15, VI2_CLK),
        PINMUX_IPSR_MSEL(IP10_16_15, BPFCLK_D, SEL_FM_3),
-       PINMUX_IPSR_DATA(IP10_18_17, VI0_G7),
-       PINMUX_IPSR_DATA(IP10_18_17, VI2_DATA0),
+       PINMUX_IPSR_GPSR(IP10_18_17, VI0_G7),
+       PINMUX_IPSR_GPSR(IP10_18_17, VI2_DATA0),
        PINMUX_IPSR_MSEL(IP10_18_17, FMIN_D, SEL_FM_3),
-       PINMUX_IPSR_DATA(IP10_21_19, VI0_R0),
-       PINMUX_IPSR_DATA(IP10_21_19, VI2_DATA1),
+       PINMUX_IPSR_GPSR(IP10_21_19, VI0_R0),
+       PINMUX_IPSR_GPSR(IP10_21_19, VI2_DATA1),
        PINMUX_IPSR_MSEL(IP10_21_19, GLO_I0_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_21_19, TS_SDATA0_C, SEL_TSIF0_2),
-       PINMUX_IPSR_DATA(IP10_21_19, ATACS11_N),
-       PINMUX_IPSR_DATA(IP10_24_22, VI0_R1),
-       PINMUX_IPSR_DATA(IP10_24_22, VI2_DATA2),
+       PINMUX_IPSR_GPSR(IP10_21_19, ATACS11_N),
+       PINMUX_IPSR_GPSR(IP10_24_22, VI0_R1),
+       PINMUX_IPSR_GPSR(IP10_24_22, VI2_DATA2),
        PINMUX_IPSR_MSEL(IP10_24_22, GLO_I1_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_24_22, TS_SCK0_C, SEL_TSIF0_2),
-       PINMUX_IPSR_DATA(IP10_24_22, ATAG1_N),
-       PINMUX_IPSR_DATA(IP10_26_25, VI0_R2),
-       PINMUX_IPSR_DATA(IP10_26_25, VI2_DATA3),
+       PINMUX_IPSR_GPSR(IP10_24_22, ATAG1_N),
+       PINMUX_IPSR_GPSR(IP10_26_25, VI0_R2),
+       PINMUX_IPSR_GPSR(IP10_26_25, VI2_DATA3),
        PINMUX_IPSR_MSEL(IP10_26_25, GLO_Q0_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_26_25, TS_SDEN0_C, SEL_TSIF0_2),
-       PINMUX_IPSR_DATA(IP10_28_27, VI0_R3),
-       PINMUX_IPSR_DATA(IP10_28_27, VI2_DATA4),
+       PINMUX_IPSR_GPSR(IP10_28_27, VI0_R3),
+       PINMUX_IPSR_GPSR(IP10_28_27, VI2_DATA4),
        PINMUX_IPSR_MSEL(IP10_28_27, GLO_Q1_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_28_27, TS_SPSYNC0_C, SEL_TSIF0_2),
-       PINMUX_IPSR_DATA(IP10_31_29, VI0_R4),
-       PINMUX_IPSR_DATA(IP10_31_29, VI2_DATA5),
+       PINMUX_IPSR_GPSR(IP10_31_29, VI0_R4),
+       PINMUX_IPSR_GPSR(IP10_31_29, VI2_DATA5),
        PINMUX_IPSR_MSEL(IP10_31_29, GLO_SCLK_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP10_31_29, TX0_C, SEL_SCIF0_2),
        PINMUX_IPSR_MSEL(IP10_31_29, SCL1_D, SEL_IIC1_3),
 
        /* IPSR11 */
-       PINMUX_IPSR_DATA(IP11_2_0, VI0_R5),
-       PINMUX_IPSR_DATA(IP11_2_0, VI2_DATA6),
+       PINMUX_IPSR_GPSR(IP11_2_0, VI0_R5),
+       PINMUX_IPSR_GPSR(IP11_2_0, VI2_DATA6),
        PINMUX_IPSR_MSEL(IP11_2_0, GLO_SDATA_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP11_2_0, RX0_C, SEL_SCIF0_2),
        PINMUX_IPSR_MSEL(IP11_2_0, SDA1_D, SEL_IIC1_3),
-       PINMUX_IPSR_DATA(IP11_5_3, VI0_R6),
-       PINMUX_IPSR_DATA(IP11_5_3, VI2_DATA7),
+       PINMUX_IPSR_GPSR(IP11_5_3, VI0_R6),
+       PINMUX_IPSR_GPSR(IP11_5_3, VI2_DATA7),
        PINMUX_IPSR_MSEL(IP11_5_3, GLO_SS_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP11_5_3, TX1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP11_5_3, SCL4_B, SEL_IIC4_1),
-       PINMUX_IPSR_DATA(IP11_8_6, VI0_R7),
+       PINMUX_IPSR_GPSR(IP11_8_6, VI0_R7),
        PINMUX_IPSR_MSEL(IP11_8_6, GLO_RFON_B, SEL_GPS_1),
        PINMUX_IPSR_MSEL(IP11_8_6, RX1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP11_8_6, CAN0_RX_E, SEL_CAN0_4),
@@ -1388,180 +1388,180 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP11_8_6, HRX1_D, SEL_HSCIF1_3),
        PINMUX_IPSR_MSEL(IP11_8_6, SCIFB0_RXD_D, SEL_SCIFB_3),
        PINMUX_IPSR_MSEL(IP11_11_9, VI1_HSYNC_N, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_11_9, AVB_RXD0),
+       PINMUX_IPSR_GPSR(IP11_11_9, AVB_RXD0),
        PINMUX_IPSR_MSEL(IP11_11_9, TS_SDATA0_B, SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP11_11_9, TX4_B, SEL_SCIF4_1),
        PINMUX_IPSR_MSEL(IP11_11_9, SCIFA4_TXD_B, SEL_SCIFA4_1),
        PINMUX_IPSR_MSEL(IP11_14_12, VI1_VSYNC_N, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_14_12, AVB_RXD1),
+       PINMUX_IPSR_GPSR(IP11_14_12, AVB_RXD1),
        PINMUX_IPSR_MSEL(IP11_14_12, TS_SCK0_B, SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP11_14_12, RX4_B, SEL_SCIF4_1),
        PINMUX_IPSR_MSEL(IP11_14_12, SCIFA4_RXD_B, SEL_SCIFA4_1),
        PINMUX_IPSR_MSEL(IP11_16_15, VI1_CLKENB, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_16_15, AVB_RXD2),
+       PINMUX_IPSR_GPSR(IP11_16_15, AVB_RXD2),
        PINMUX_IPSR_MSEL(IP11_16_15, TS_SDEN0_B, SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP11_18_17, VI1_FIELD, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_18_17, AVB_RXD3),
+       PINMUX_IPSR_GPSR(IP11_18_17, AVB_RXD3),
        PINMUX_IPSR_MSEL(IP11_18_17, TS_SPSYNC0_B, SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP11_19, VI1_CLK, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_19, AVB_RXD4),
+       PINMUX_IPSR_GPSR(IP11_19, AVB_RXD4),
        PINMUX_IPSR_MSEL(IP11_20, VI1_DATA0, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_20, AVB_RXD5),
+       PINMUX_IPSR_GPSR(IP11_20, AVB_RXD5),
        PINMUX_IPSR_MSEL(IP11_21, VI1_DATA1, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_21, AVB_RXD6),
+       PINMUX_IPSR_GPSR(IP11_21, AVB_RXD6),
        PINMUX_IPSR_MSEL(IP11_22, VI1_DATA2, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_22, AVB_RXD7),
+       PINMUX_IPSR_GPSR(IP11_22, AVB_RXD7),
        PINMUX_IPSR_MSEL(IP11_23, VI1_DATA3, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_23, AVB_RX_ER),
+       PINMUX_IPSR_GPSR(IP11_23, AVB_RX_ER),
        PINMUX_IPSR_MSEL(IP11_24, VI1_DATA4, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_24, AVB_MDIO),
+       PINMUX_IPSR_GPSR(IP11_24, AVB_MDIO),
        PINMUX_IPSR_MSEL(IP11_25, VI1_DATA5, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_25, AVB_RX_DV),
+       PINMUX_IPSR_GPSR(IP11_25, AVB_RX_DV),
        PINMUX_IPSR_MSEL(IP11_26, VI1_DATA6, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_26, AVB_MAGIC),
+       PINMUX_IPSR_GPSR(IP11_26, AVB_MAGIC),
        PINMUX_IPSR_MSEL(IP11_27, VI1_DATA7, SEL_VI1_0),
-       PINMUX_IPSR_DATA(IP11_27, AVB_MDC),
-       PINMUX_IPSR_DATA(IP11_29_28, ETH_MDIO),
-       PINMUX_IPSR_DATA(IP11_29_28, AVB_RX_CLK),
+       PINMUX_IPSR_GPSR(IP11_27, AVB_MDC),
+       PINMUX_IPSR_GPSR(IP11_29_28, ETH_MDIO),
+       PINMUX_IPSR_GPSR(IP11_29_28, AVB_RX_CLK),
        PINMUX_IPSR_MSEL(IP11_29_28, SCL2_C, SEL_IIC2_2),
-       PINMUX_IPSR_DATA(IP11_31_30, ETH_CRS_DV),
-       PINMUX_IPSR_DATA(IP11_31_30, AVB_LINK),
+       PINMUX_IPSR_GPSR(IP11_31_30, ETH_CRS_DV),
+       PINMUX_IPSR_GPSR(IP11_31_30, AVB_LINK),
        PINMUX_IPSR_MSEL(IP11_31_30, SDA2_C, SEL_IIC2_2),
 
        /* IPSR12 */
-       PINMUX_IPSR_DATA(IP12_1_0, ETH_RX_ER),
-       PINMUX_IPSR_DATA(IP12_1_0, AVB_CRS),
+       PINMUX_IPSR_GPSR(IP12_1_0, ETH_RX_ER),
+       PINMUX_IPSR_GPSR(IP12_1_0, AVB_CRS),
        PINMUX_IPSR_MSEL(IP12_1_0, SCL3, SEL_IIC3_0),
        PINMUX_IPSR_MSEL(IP12_1_0, SCL7, SEL_IIC7_0),
-       PINMUX_IPSR_DATA(IP12_3_2, ETH_RXD0),
-       PINMUX_IPSR_DATA(IP12_3_2, AVB_PHY_INT),
+       PINMUX_IPSR_GPSR(IP12_3_2, ETH_RXD0),
+       PINMUX_IPSR_GPSR(IP12_3_2, AVB_PHY_INT),
        PINMUX_IPSR_MSEL(IP12_3_2, SDA3, SEL_IIC3_0),
        PINMUX_IPSR_MSEL(IP12_3_2, SDA7, SEL_IIC7_0),
-       PINMUX_IPSR_DATA(IP12_6_4, ETH_RXD1),
-       PINMUX_IPSR_DATA(IP12_6_4, AVB_GTXREFCLK),
+       PINMUX_IPSR_GPSR(IP12_6_4, ETH_RXD1),
+       PINMUX_IPSR_GPSR(IP12_6_4, AVB_GTXREFCLK),
        PINMUX_IPSR_MSEL(IP12_6_4, CAN0_TX_C, SEL_CAN0_2),
        PINMUX_IPSR_MSEL(IP12_6_4, SCL2_D, SEL_IIC2_3),
        PINMUX_IPSR_MSEL(IP12_6_4, MSIOF1_RXD_E, SEL_SOF1_4),
-       PINMUX_IPSR_DATA(IP12_9_7, ETH_LINK),
-       PINMUX_IPSR_DATA(IP12_9_7, AVB_TXD0),
+       PINMUX_IPSR_GPSR(IP12_9_7, ETH_LINK),
+       PINMUX_IPSR_GPSR(IP12_9_7, AVB_TXD0),
        PINMUX_IPSR_MSEL(IP12_9_7, CAN0_RX_C, SEL_CAN0_2),
        PINMUX_IPSR_MSEL(IP12_9_7, SDA2_D, SEL_IIC2_3),
        PINMUX_IPSR_MSEL(IP12_9_7, MSIOF1_SCK_E, SEL_SOF1_4),
-       PINMUX_IPSR_DATA(IP12_12_10, ETH_REFCLK),
-       PINMUX_IPSR_DATA(IP12_12_10, AVB_TXD1),
+       PINMUX_IPSR_GPSR(IP12_12_10, ETH_REFCLK),
+       PINMUX_IPSR_GPSR(IP12_12_10, AVB_TXD1),
        PINMUX_IPSR_MSEL(IP12_12_10, SCIFA3_RXD_B, SEL_SCIFA3_1),
        PINMUX_IPSR_MSEL(IP12_12_10, CAN1_RX_C, SEL_CAN1_2),
        PINMUX_IPSR_MSEL(IP12_12_10, MSIOF1_SYNC_E, SEL_SOF1_4),
-       PINMUX_IPSR_DATA(IP12_15_13, ETH_TXD1),
-       PINMUX_IPSR_DATA(IP12_15_13, AVB_TXD2),
+       PINMUX_IPSR_GPSR(IP12_15_13, ETH_TXD1),
+       PINMUX_IPSR_GPSR(IP12_15_13, AVB_TXD2),
        PINMUX_IPSR_MSEL(IP12_15_13, SCIFA3_TXD_B, SEL_SCIFA3_1),
        PINMUX_IPSR_MSEL(IP12_15_13, CAN1_TX_C, SEL_CAN1_2),
        PINMUX_IPSR_MSEL(IP12_15_13, MSIOF1_TXD_E, SEL_SOF1_4),
-       PINMUX_IPSR_DATA(IP12_17_16, ETH_TX_EN),
-       PINMUX_IPSR_DATA(IP12_17_16, AVB_TXD3),
+       PINMUX_IPSR_GPSR(IP12_17_16, ETH_TX_EN),
+       PINMUX_IPSR_GPSR(IP12_17_16, AVB_TXD3),
        PINMUX_IPSR_MSEL(IP12_17_16, TCLK1_B, SEL_TMU1_0),
        PINMUX_IPSR_MSEL(IP12_17_16, CAN_CLK_B, SEL_CANCLK_1),
-       PINMUX_IPSR_DATA(IP12_19_18, ETH_MAGIC),
-       PINMUX_IPSR_DATA(IP12_19_18, AVB_TXD4),
+       PINMUX_IPSR_GPSR(IP12_19_18, ETH_MAGIC),
+       PINMUX_IPSR_GPSR(IP12_19_18, AVB_TXD4),
        PINMUX_IPSR_MSEL(IP12_19_18, IETX_C, SEL_IEB_2),
-       PINMUX_IPSR_DATA(IP12_21_20, ETH_TXD0),
-       PINMUX_IPSR_DATA(IP12_21_20, AVB_TXD5),
+       PINMUX_IPSR_GPSR(IP12_21_20, ETH_TXD0),
+       PINMUX_IPSR_GPSR(IP12_21_20, AVB_TXD5),
        PINMUX_IPSR_MSEL(IP12_21_20, IECLK_C, SEL_IEB_2),
-       PINMUX_IPSR_DATA(IP12_23_22, ETH_MDC),
-       PINMUX_IPSR_DATA(IP12_23_22, AVB_TXD6),
+       PINMUX_IPSR_GPSR(IP12_23_22, ETH_MDC),
+       PINMUX_IPSR_GPSR(IP12_23_22, AVB_TXD6),
        PINMUX_IPSR_MSEL(IP12_23_22, IERX_C, SEL_IEB_2),
        PINMUX_IPSR_MSEL(IP12_26_24, STP_IVCXO27_0, SEL_SSP_0),
-       PINMUX_IPSR_DATA(IP12_26_24, AVB_TXD7),
+       PINMUX_IPSR_GPSR(IP12_26_24, AVB_TXD7),
        PINMUX_IPSR_MSEL(IP12_26_24, SCIFB2_TXD_D, SEL_SCIFB2_3),
        PINMUX_IPSR_MSEL(IP12_26_24, ADIDATA_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP12_26_24, MSIOF0_SYNC_C, SEL_SOF0_2),
        PINMUX_IPSR_MSEL(IP12_29_27, STP_ISCLK_0, SEL_SSP_0),
-       PINMUX_IPSR_DATA(IP12_29_27, AVB_TX_EN),
+       PINMUX_IPSR_GPSR(IP12_29_27, AVB_TX_EN),
        PINMUX_IPSR_MSEL(IP12_29_27, SCIFB2_RXD_D, SEL_SCIFB2_3),
        PINMUX_IPSR_MSEL(IP12_29_27, ADICS_SAMP_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP12_29_27, MSIOF0_SCK_C, SEL_SOF0_2),
 
        /* IPSR13 */
        PINMUX_IPSR_MSEL(IP13_2_0, STP_ISD_0, SEL_SSP_0),
-       PINMUX_IPSR_DATA(IP13_2_0, AVB_TX_ER),
+       PINMUX_IPSR_GPSR(IP13_2_0, AVB_TX_ER),
        PINMUX_IPSR_MSEL(IP13_2_0, SCIFB2_SCK_C, SEL_SCIFB2_2),
        PINMUX_IPSR_MSEL(IP13_2_0, ADICLK_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP13_2_0, MSIOF0_SS1_C, SEL_SOF0_2),
        PINMUX_IPSR_MSEL(IP13_4_3, STP_ISEN_0, SEL_SSP_0),
-       PINMUX_IPSR_DATA(IP13_4_3, AVB_TX_CLK),
+       PINMUX_IPSR_GPSR(IP13_4_3, AVB_TX_CLK),
        PINMUX_IPSR_MSEL(IP13_4_3, ADICHS0_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP13_4_3, MSIOF0_SS2_C, SEL_SOF0_2),
        PINMUX_IPSR_MSEL(IP13_6_5, STP_ISSYNC_0, SEL_SSP_0),
-       PINMUX_IPSR_DATA(IP13_6_5, AVB_COL),
+       PINMUX_IPSR_GPSR(IP13_6_5, AVB_COL),
        PINMUX_IPSR_MSEL(IP13_6_5, ADICHS1_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP13_6_5, MSIOF0_RXD_C, SEL_SOF0_2),
        PINMUX_IPSR_MSEL(IP13_9_7, STP_OPWM_0, SEL_SSP_0),
-       PINMUX_IPSR_DATA(IP13_9_7, AVB_GTX_CLK),
-       PINMUX_IPSR_DATA(IP13_9_7, PWM0_B),
+       PINMUX_IPSR_GPSR(IP13_9_7, AVB_GTX_CLK),
+       PINMUX_IPSR_GPSR(IP13_9_7, PWM0_B),
        PINMUX_IPSR_MSEL(IP13_9_7, ADICHS2_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP13_9_7, MSIOF0_TXD_C, SEL_SOF0_2),
-       PINMUX_IPSR_DATA(IP13_10, SD0_CLK),
+       PINMUX_IPSR_GPSR(IP13_10, SD0_CLK),
        PINMUX_IPSR_MSEL(IP13_10, SPCLK_B, SEL_QSP_1),
-       PINMUX_IPSR_DATA(IP13_11, SD0_CMD),
+       PINMUX_IPSR_GPSR(IP13_11, SD0_CMD),
        PINMUX_IPSR_MSEL(IP13_11, MOSI_IO0_B, SEL_QSP_1),
-       PINMUX_IPSR_DATA(IP13_12, SD0_DATA0),
+       PINMUX_IPSR_GPSR(IP13_12, SD0_DATA0),
        PINMUX_IPSR_MSEL(IP13_12, MISO_IO1_B, SEL_QSP_1),
-       PINMUX_IPSR_DATA(IP13_13, SD0_DATA1),
+       PINMUX_IPSR_GPSR(IP13_13, SD0_DATA1),
        PINMUX_IPSR_MSEL(IP13_13, IO2_B, SEL_QSP_1),
-       PINMUX_IPSR_DATA(IP13_14, SD0_DATA2),
+       PINMUX_IPSR_GPSR(IP13_14, SD0_DATA2),
        PINMUX_IPSR_MSEL(IP13_14, IO3_B, SEL_QSP_1),
-       PINMUX_IPSR_DATA(IP13_15, SD0_DATA3),
+       PINMUX_IPSR_GPSR(IP13_15, SD0_DATA3),
        PINMUX_IPSR_MSEL(IP13_15, SSL_B, SEL_QSP_1),
-       PINMUX_IPSR_DATA(IP13_18_16, SD0_CD),
+       PINMUX_IPSR_GPSR(IP13_18_16, SD0_CD),
        PINMUX_IPSR_MSEL(IP13_18_16, MMC_D6_B, SEL_MMC_1),
        PINMUX_IPSR_MSEL(IP13_18_16, SIM0_RST_B, SEL_SIM_1),
        PINMUX_IPSR_MSEL(IP13_18_16, CAN0_RX_F, SEL_CAN0_5),
        PINMUX_IPSR_MSEL(IP13_18_16, SCIFA5_TXD_B, SEL_SCIFA5_1),
        PINMUX_IPSR_MSEL(IP13_18_16, TX3_C, SEL_SCIF3_2),
-       PINMUX_IPSR_DATA(IP13_21_19, SD0_WP),
+       PINMUX_IPSR_GPSR(IP13_21_19, SD0_WP),
        PINMUX_IPSR_MSEL(IP13_21_19, MMC_D7_B, SEL_MMC_1),
        PINMUX_IPSR_MSEL(IP13_21_19, SIM0_D_B, SEL_SIM_1),
        PINMUX_IPSR_MSEL(IP13_21_19, CAN0_TX_F, SEL_CAN0_5),
        PINMUX_IPSR_MSEL(IP13_21_19, SCIFA5_RXD_B, SEL_SCIFA5_1),
        PINMUX_IPSR_MSEL(IP13_21_19, RX3_C, SEL_SCIF3_2),
-       PINMUX_IPSR_DATA(IP13_22, SD1_CMD),
+       PINMUX_IPSR_GPSR(IP13_22, SD1_CMD),
        PINMUX_IPSR_MSEL(IP13_22, REMOCON_B, SEL_RCN_1),
-       PINMUX_IPSR_DATA(IP13_24_23, SD1_DATA0),
+       PINMUX_IPSR_GPSR(IP13_24_23, SD1_DATA0),
        PINMUX_IPSR_MSEL(IP13_24_23, SPEEDIN_B, SEL_RSP_1),
-       PINMUX_IPSR_DATA(IP13_25, SD1_DATA1),
+       PINMUX_IPSR_GPSR(IP13_25, SD1_DATA1),
        PINMUX_IPSR_MSEL(IP13_25, IETX_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP13_26, SD1_DATA2),
+       PINMUX_IPSR_GPSR(IP13_26, SD1_DATA2),
        PINMUX_IPSR_MSEL(IP13_26, IECLK_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP13_27, SD1_DATA3),
+       PINMUX_IPSR_GPSR(IP13_27, SD1_DATA3),
        PINMUX_IPSR_MSEL(IP13_27, IERX_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP13_30_28, SD1_CD),
-       PINMUX_IPSR_DATA(IP13_30_28, PWM0),
-       PINMUX_IPSR_DATA(IP13_30_28, TPU_TO0),
+       PINMUX_IPSR_GPSR(IP13_30_28, SD1_CD),
+       PINMUX_IPSR_GPSR(IP13_30_28, PWM0),
+       PINMUX_IPSR_GPSR(IP13_30_28, TPU_TO0),
        PINMUX_IPSR_MSEL(IP13_30_28, SCL1_C, SEL_IIC1_2),
 
        /* IPSR14 */
-       PINMUX_IPSR_DATA(IP14_1_0, SD1_WP),
-       PINMUX_IPSR_DATA(IP14_1_0, PWM1_B),
+       PINMUX_IPSR_GPSR(IP14_1_0, SD1_WP),
+       PINMUX_IPSR_GPSR(IP14_1_0, PWM1_B),
        PINMUX_IPSR_MSEL(IP14_1_0, SDA1_C, SEL_IIC1_2),
-       PINMUX_IPSR_DATA(IP14_2, SD2_CLK),
-       PINMUX_IPSR_DATA(IP14_2, MMC_CLK),
-       PINMUX_IPSR_DATA(IP14_3, SD2_CMD),
-       PINMUX_IPSR_DATA(IP14_3, MMC_CMD),
-       PINMUX_IPSR_DATA(IP14_4, SD2_DATA0),
-       PINMUX_IPSR_DATA(IP14_4, MMC_D0),
-       PINMUX_IPSR_DATA(IP14_5, SD2_DATA1),
-       PINMUX_IPSR_DATA(IP14_5, MMC_D1),
-       PINMUX_IPSR_DATA(IP14_6, SD2_DATA2),
-       PINMUX_IPSR_DATA(IP14_6, MMC_D2),
-       PINMUX_IPSR_DATA(IP14_7, SD2_DATA3),
-       PINMUX_IPSR_DATA(IP14_7, MMC_D3),
-       PINMUX_IPSR_DATA(IP14_10_8, SD2_CD),
-       PINMUX_IPSR_DATA(IP14_10_8, MMC_D4),
+       PINMUX_IPSR_GPSR(IP14_2, SD2_CLK),
+       PINMUX_IPSR_GPSR(IP14_2, MMC_CLK),
+       PINMUX_IPSR_GPSR(IP14_3, SD2_CMD),
+       PINMUX_IPSR_GPSR(IP14_3, MMC_CMD),
+       PINMUX_IPSR_GPSR(IP14_4, SD2_DATA0),
+       PINMUX_IPSR_GPSR(IP14_4, MMC_D0),
+       PINMUX_IPSR_GPSR(IP14_5, SD2_DATA1),
+       PINMUX_IPSR_GPSR(IP14_5, MMC_D1),
+       PINMUX_IPSR_GPSR(IP14_6, SD2_DATA2),
+       PINMUX_IPSR_GPSR(IP14_6, MMC_D2),
+       PINMUX_IPSR_GPSR(IP14_7, SD2_DATA3),
+       PINMUX_IPSR_GPSR(IP14_7, MMC_D3),
+       PINMUX_IPSR_GPSR(IP14_10_8, SD2_CD),
+       PINMUX_IPSR_GPSR(IP14_10_8, MMC_D4),
        PINMUX_IPSR_MSEL(IP14_10_8, SCL8_C, SEL_IIC8_2),
        PINMUX_IPSR_MSEL(IP14_10_8, TX5_B, SEL_SCIF5_1),
        PINMUX_IPSR_MSEL(IP14_10_8, SCIFA5_TXD_C, SEL_SCIFA5_2),
-       PINMUX_IPSR_DATA(IP14_13_11, SD2_WP),
-       PINMUX_IPSR_DATA(IP14_13_11, MMC_D5),
+       PINMUX_IPSR_GPSR(IP14_13_11, SD2_WP),
+       PINMUX_IPSR_GPSR(IP14_13_11, MMC_D5),
        PINMUX_IPSR_MSEL(IP14_13_11, SDA8_C, SEL_IIC8_2),
        PINMUX_IPSR_MSEL(IP14_13_11, RX5_B, SEL_SCIF5_1),
        PINMUX_IPSR_MSEL(IP14_13_11, SCIFA5_RXD_C, SEL_SCIFA5_2),
@@ -1569,40 +1569,40 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP14_16_14, RX2_C, SEL_SCIF2_2),
        PINMUX_IPSR_MSEL(IP14_16_14, ADIDATA, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP14_16_14, VI1_CLK_C, SEL_VI1_2),
-       PINMUX_IPSR_DATA(IP14_16_14, VI1_G0_B),
+       PINMUX_IPSR_GPSR(IP14_16_14, VI1_G0_B),
        PINMUX_IPSR_MSEL(IP14_19_17, MSIOF0_SYNC, SEL_SOF0_0),
        PINMUX_IPSR_MSEL(IP14_19_17, TX2_C, SEL_SCIF2_2),
        PINMUX_IPSR_MSEL(IP14_19_17, ADICS_SAMP, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP14_19_17, VI1_CLKENB_C, SEL_VI1_2),
-       PINMUX_IPSR_DATA(IP14_19_17, VI1_G1_B),
+       PINMUX_IPSR_GPSR(IP14_19_17, VI1_G1_B),
        PINMUX_IPSR_MSEL(IP14_22_20, MSIOF0_TXD, SEL_SOF0_0),
        PINMUX_IPSR_MSEL(IP14_22_20, ADICLK, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP14_22_20, VI1_FIELD_C, SEL_VI1_2),
-       PINMUX_IPSR_DATA(IP14_22_20, VI1_G2_B),
+       PINMUX_IPSR_GPSR(IP14_22_20, VI1_G2_B),
        PINMUX_IPSR_MSEL(IP14_25_23, MSIOF0_RXD, SEL_SOF0_0),
        PINMUX_IPSR_MSEL(IP14_25_23, ADICHS0, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP14_25_23, VI1_DATA0_C, SEL_VI1_2),
-       PINMUX_IPSR_DATA(IP14_25_23, VI1_G3_B),
+       PINMUX_IPSR_GPSR(IP14_25_23, VI1_G3_B),
        PINMUX_IPSR_MSEL(IP14_28_26, MSIOF0_SS1, SEL_SOF0_0),
        PINMUX_IPSR_MSEL(IP14_28_26, MMC_D6, SEL_MMC_0),
        PINMUX_IPSR_MSEL(IP14_28_26, ADICHS1, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP14_28_26, TX0_E, SEL_SCIF0_4),
        PINMUX_IPSR_MSEL(IP14_28_26, VI1_HSYNC_N_C, SEL_VI1_2),
        PINMUX_IPSR_MSEL(IP14_28_26, SCL7_C, SEL_IIC7_2),
-       PINMUX_IPSR_DATA(IP14_28_26, VI1_G4_B),
+       PINMUX_IPSR_GPSR(IP14_28_26, VI1_G4_B),
        PINMUX_IPSR_MSEL(IP14_31_29, MSIOF0_SS2, SEL_SOF0_0),
        PINMUX_IPSR_MSEL(IP14_31_29, MMC_D7, SEL_MMC_0),
        PINMUX_IPSR_MSEL(IP14_31_29, ADICHS2, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP14_31_29, RX0_E, SEL_SCIF0_4),
        PINMUX_IPSR_MSEL(IP14_31_29, VI1_VSYNC_N_C, SEL_VI1_2),
        PINMUX_IPSR_MSEL(IP14_31_29, SDA7_C, SEL_IIC7_2),
-       PINMUX_IPSR_DATA(IP14_31_29, VI1_G5_B),
+       PINMUX_IPSR_GPSR(IP14_31_29, VI1_G5_B),
 
        /* IPSR15 */
        PINMUX_IPSR_MSEL(IP15_1_0, SIM0_RST, SEL_SIM_0),
        PINMUX_IPSR_MSEL(IP15_1_0, IETX, SEL_IEB_0),
        PINMUX_IPSR_MSEL(IP15_1_0, CAN1_TX_D, SEL_CAN1_3),
-       PINMUX_IPSR_DATA(IP15_3_2, SIM0_CLK),
+       PINMUX_IPSR_GPSR(IP15_3_2, SIM0_CLK),
        PINMUX_IPSR_MSEL(IP15_3_2, IECLK, SEL_IEB_0),
        PINMUX_IPSR_MSEL(IP15_3_2, CAN_CLK_C, SEL_CANCLK_2),
        PINMUX_IPSR_MSEL(IP15_5_4, SIM0_D, SEL_SIM_0),
@@ -1611,19 +1611,19 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP15_8_6, GPS_CLK, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP15_8_6, DU1_DOTCLKIN_C, SEL_DIS_2),
        PINMUX_IPSR_MSEL(IP15_8_6, AUDIO_CLKB_B, SEL_ADG_1),
-       PINMUX_IPSR_DATA(IP15_8_6, PWM5_B),
+       PINMUX_IPSR_GPSR(IP15_8_6, PWM5_B),
        PINMUX_IPSR_MSEL(IP15_8_6, SCIFA3_TXD_C, SEL_SCIFA3_2),
        PINMUX_IPSR_MSEL(IP15_11_9, GPS_SIGN, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP15_11_9, TX4_C, SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP15_11_9, SCIFA4_TXD_C, SEL_SCIFA4_2),
-       PINMUX_IPSR_DATA(IP15_11_9, PWM5),
-       PINMUX_IPSR_DATA(IP15_11_9, VI1_G6_B),
+       PINMUX_IPSR_GPSR(IP15_11_9, PWM5),
+       PINMUX_IPSR_GPSR(IP15_11_9, VI1_G6_B),
        PINMUX_IPSR_MSEL(IP15_11_9, SCIFA3_RXD_C, SEL_SCIFA3_2),
        PINMUX_IPSR_MSEL(IP15_14_12, GPS_MAG, SEL_GPS_0),
        PINMUX_IPSR_MSEL(IP15_14_12, RX4_C, SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP15_14_12, SCIFA4_RXD_C, SEL_SCIFA4_2),
-       PINMUX_IPSR_DATA(IP15_14_12, PWM6),
-       PINMUX_IPSR_DATA(IP15_14_12, VI1_G7_B),
+       PINMUX_IPSR_GPSR(IP15_14_12, PWM6),
+       PINMUX_IPSR_GPSR(IP15_14_12, VI1_G7_B),
        PINMUX_IPSR_MSEL(IP15_14_12, SCIFA3_SCK_C, SEL_SCIFA3_2),
        PINMUX_IPSR_MSEL(IP15_17_15, HCTS0_N, SEL_HSCIF0_0),
        PINMUX_IPSR_MSEL(IP15_17_15, SCIFB0_CTS_N, SEL_SCIFB_0),
@@ -1638,7 +1638,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP15_23_21, SCIFB0_SCK, SEL_SCIFB_0),
        PINMUX_IPSR_MSEL(IP15_23_21, GLO_Q0_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP15_23_21, CAN_CLK, SEL_CANCLK_0),
-       PINMUX_IPSR_DATA(IP15_23_21, TCLK2),
+       PINMUX_IPSR_GPSR(IP15_23_21, TCLK2),
        PINMUX_IPSR_MSEL(IP15_23_21, VI1_DATA3_C, SEL_VI1_2),
        PINMUX_IPSR_MSEL(IP15_26_24, HRX0, SEL_HSCIF0_0),
        PINMUX_IPSR_MSEL(IP15_26_24, SCIFB0_RXD, SEL_SCIFB_0),
@@ -1654,25 +1654,25 @@ static const u16 pinmux_data[] = {
        /* IPSR16 */
        PINMUX_IPSR_MSEL(IP16_2_0, HRX1, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP16_2_0, SCIFB1_RXD, SEL_SCIFB1_0),
-       PINMUX_IPSR_DATA(IP16_2_0, VI1_R0_B),
+       PINMUX_IPSR_GPSR(IP16_2_0, VI1_R0_B),
        PINMUX_IPSR_MSEL(IP16_2_0, GLO_SDATA_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP16_2_0, VI1_DATA6_C, SEL_VI1_2),
        PINMUX_IPSR_MSEL(IP16_5_3, HTX1, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP16_5_3, SCIFB1_TXD, SEL_SCIFB1_0),
-       PINMUX_IPSR_DATA(IP16_5_3, VI1_R1_B),
+       PINMUX_IPSR_GPSR(IP16_5_3, VI1_R1_B),
        PINMUX_IPSR_MSEL(IP16_5_3, GLO_SS_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP16_5_3, VI1_DATA7_C, SEL_VI1_2),
        PINMUX_IPSR_MSEL(IP16_7_6, HSCK1, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP16_7_6, SCIFB1_SCK, SEL_SCIFB1_0),
-       PINMUX_IPSR_DATA(IP16_7_6, MLB_CLK),
+       PINMUX_IPSR_GPSR(IP16_7_6, MLB_CLK),
        PINMUX_IPSR_MSEL(IP16_7_6, GLO_RFON_C, SEL_GPS_2),
        PINMUX_IPSR_MSEL(IP16_9_8, HCTS1_N, SEL_HSCIF1_0),
-       PINMUX_IPSR_DATA(IP16_9_8, SCIFB1_CTS_N),
-       PINMUX_IPSR_DATA(IP16_9_8, MLB_SIG),
+       PINMUX_IPSR_GPSR(IP16_9_8, SCIFB1_CTS_N),
+       PINMUX_IPSR_GPSR(IP16_9_8, MLB_SIG),
        PINMUX_IPSR_MSEL(IP16_9_8, CAN1_TX_B, SEL_CAN1_1),
        PINMUX_IPSR_MSEL(IP16_11_10, HRTS1_N, SEL_HSCIF1_0),
-       PINMUX_IPSR_DATA(IP16_11_10, SCIFB1_RTS_N),
-       PINMUX_IPSR_DATA(IP16_11_10, MLB_DAT),
+       PINMUX_IPSR_GPSR(IP16_11_10, SCIFB1_RTS_N),
+       PINMUX_IPSR_GPSR(IP16_11_10, MLB_DAT),
        PINMUX_IPSR_MSEL(IP16_11_10, CAN1_RX_B, SEL_CAN1_1),
 };
 
index 3718c7846bfd5cd3cfce84076449b388432e8081..38912cff597bc2e57c168428d8e0fe8b353b2d8c 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * r8a7794 processor support - PFC hardware block.
  *
- * Copyright (C) 2014 Renesas Electronics Corporation
+ * Copyright (C) 2014-2015 Renesas Electronics Corporation
  * Copyright (C) 2015 Renesas Solutions Corp.
- * Copyright (C) 2015 Cogent  Embedded, Inc., <source@cogentembedded.com>
+ * Copyright (C) 2015-2016 Cogent Embedded, Inc., <source@cogentembedded.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
@@ -623,848 +623,848 @@ static const u16 pinmux_data[] = {
        PINMUX_SINGLE(SD1_DATA3),
 
        /* IPSR0 */
-       PINMUX_IPSR_DATA(IP0_0, SD1_CD),
+       PINMUX_IPSR_GPSR(IP0_0, SD1_CD),
        PINMUX_IPSR_MSEL(IP0_0, CAN0_RX, SEL_CAN0_0),
-       PINMUX_IPSR_DATA(IP0_9_8, SD1_WP),
-       PINMUX_IPSR_DATA(IP0_9_8, IRQ7),
+       PINMUX_IPSR_GPSR(IP0_9_8, SD1_WP),
+       PINMUX_IPSR_GPSR(IP0_9_8, IRQ7),
        PINMUX_IPSR_MSEL(IP0_9_8, CAN0_TX, SEL_CAN0_0),
-       PINMUX_IPSR_DATA(IP0_10, MMC_CLK),
-       PINMUX_IPSR_DATA(IP0_10, SD2_CLK),
-       PINMUX_IPSR_DATA(IP0_11, MMC_CMD),
-       PINMUX_IPSR_DATA(IP0_11, SD2_CMD),
-       PINMUX_IPSR_DATA(IP0_12, MMC_D0),
-       PINMUX_IPSR_DATA(IP0_12, SD2_DATA0),
-       PINMUX_IPSR_DATA(IP0_13, MMC_D1),
-       PINMUX_IPSR_DATA(IP0_13, SD2_DATA1),
-       PINMUX_IPSR_DATA(IP0_14, MMC_D2),
-       PINMUX_IPSR_DATA(IP0_14, SD2_DATA2),
-       PINMUX_IPSR_DATA(IP0_15, MMC_D3),
-       PINMUX_IPSR_DATA(IP0_15, SD2_DATA3),
-       PINMUX_IPSR_DATA(IP0_16, MMC_D4),
-       PINMUX_IPSR_DATA(IP0_16, SD2_CD),
-       PINMUX_IPSR_DATA(IP0_17, MMC_D5),
-       PINMUX_IPSR_DATA(IP0_17, SD2_WP),
-       PINMUX_IPSR_DATA(IP0_19_18, MMC_D6),
+       PINMUX_IPSR_GPSR(IP0_10, MMC_CLK),
+       PINMUX_IPSR_GPSR(IP0_10, SD2_CLK),
+       PINMUX_IPSR_GPSR(IP0_11, MMC_CMD),
+       PINMUX_IPSR_GPSR(IP0_11, SD2_CMD),
+       PINMUX_IPSR_GPSR(IP0_12, MMC_D0),
+       PINMUX_IPSR_GPSR(IP0_12, SD2_DATA0),
+       PINMUX_IPSR_GPSR(IP0_13, MMC_D1),
+       PINMUX_IPSR_GPSR(IP0_13, SD2_DATA1),
+       PINMUX_IPSR_GPSR(IP0_14, MMC_D2),
+       PINMUX_IPSR_GPSR(IP0_14, SD2_DATA2),
+       PINMUX_IPSR_GPSR(IP0_15, MMC_D3),
+       PINMUX_IPSR_GPSR(IP0_15, SD2_DATA3),
+       PINMUX_IPSR_GPSR(IP0_16, MMC_D4),
+       PINMUX_IPSR_GPSR(IP0_16, SD2_CD),
+       PINMUX_IPSR_GPSR(IP0_17, MMC_D5),
+       PINMUX_IPSR_GPSR(IP0_17, SD2_WP),
+       PINMUX_IPSR_GPSR(IP0_19_18, MMC_D6),
        PINMUX_IPSR_MSEL(IP0_19_18, SCIF0_RXD, SEL_SCIF0_0),
        PINMUX_IPSR_MSEL(IP0_19_18, I2C2_SCL_B, SEL_I2C02_1),
        PINMUX_IPSR_MSEL(IP0_19_18, CAN1_RX, SEL_CAN1_0),
-       PINMUX_IPSR_DATA(IP0_21_20, MMC_D7),
+       PINMUX_IPSR_GPSR(IP0_21_20, MMC_D7),
        PINMUX_IPSR_MSEL(IP0_21_20, SCIF0_TXD, SEL_SCIF0_0),
        PINMUX_IPSR_MSEL(IP0_21_20, I2C2_SDA_B, SEL_I2C02_1),
        PINMUX_IPSR_MSEL(IP0_21_20, CAN1_TX, SEL_CAN1_0),
-       PINMUX_IPSR_DATA(IP0_23_22, D0),
+       PINMUX_IPSR_GPSR(IP0_23_22, D0),
        PINMUX_IPSR_MSEL(IP0_23_22, SCIFA3_SCK_B, SEL_SCIFA3_1),
-       PINMUX_IPSR_DATA(IP0_23_22, IRQ4),
-       PINMUX_IPSR_DATA(IP0_24, D1),
+       PINMUX_IPSR_GPSR(IP0_23_22, IRQ4),
+       PINMUX_IPSR_GPSR(IP0_24, D1),
        PINMUX_IPSR_MSEL(IP0_24, SCIFA3_RXD_B, SEL_SCIFA3_1),
-       PINMUX_IPSR_DATA(IP0_25, D2),
+       PINMUX_IPSR_GPSR(IP0_25, D2),
        PINMUX_IPSR_MSEL(IP0_25, SCIFA3_TXD_B, SEL_SCIFA3_1),
-       PINMUX_IPSR_DATA(IP0_27_26, D3),
+       PINMUX_IPSR_GPSR(IP0_27_26, D3),
        PINMUX_IPSR_MSEL(IP0_27_26, I2C3_SCL_B, SEL_I2C03_1),
        PINMUX_IPSR_MSEL(IP0_27_26, SCIF5_RXD_B, SEL_SCIF5_1),
-       PINMUX_IPSR_DATA(IP0_29_28, D4),
+       PINMUX_IPSR_GPSR(IP0_29_28, D4),
        PINMUX_IPSR_MSEL(IP0_29_28, I2C3_SDA_B, SEL_I2C03_1),
        PINMUX_IPSR_MSEL(IP0_29_28, SCIF5_TXD_B, SEL_SCIF5_1),
-       PINMUX_IPSR_DATA(IP0_31_30, D5),
+       PINMUX_IPSR_GPSR(IP0_31_30, D5),
        PINMUX_IPSR_MSEL(IP0_31_30, SCIF4_RXD_B, SEL_SCIF4_1),
        PINMUX_IPSR_MSEL(IP0_31_30, I2C0_SCL_D, SEL_I2C00_3),
 
        /* IPSR1 */
-       PINMUX_IPSR_DATA(IP1_1_0, D6),
+       PINMUX_IPSR_GPSR(IP1_1_0, D6),
        PINMUX_IPSR_MSEL(IP1_1_0, SCIF4_TXD_B, SEL_SCIF4_1),
        PINMUX_IPSR_MSEL(IP1_1_0, I2C0_SDA_D, SEL_I2C00_3),
-       PINMUX_IPSR_DATA(IP1_3_2, D7),
-       PINMUX_IPSR_DATA(IP1_3_2, IRQ3),
+       PINMUX_IPSR_GPSR(IP1_3_2, D7),
+       PINMUX_IPSR_GPSR(IP1_3_2, IRQ3),
        PINMUX_IPSR_MSEL(IP1_3_2, TCLK1, SEL_TMU_0),
-       PINMUX_IPSR_DATA(IP1_3_2, PWM6_B),
-       PINMUX_IPSR_DATA(IP1_5_4, D8),
-       PINMUX_IPSR_DATA(IP1_5_4, HSCIF2_HRX),
+       PINMUX_IPSR_GPSR(IP1_3_2, PWM6_B),
+       PINMUX_IPSR_GPSR(IP1_5_4, D8),
+       PINMUX_IPSR_GPSR(IP1_5_4, HSCIF2_HRX),
        PINMUX_IPSR_MSEL(IP1_5_4, I2C1_SCL_B, SEL_I2C01_1),
-       PINMUX_IPSR_DATA(IP1_7_6, D9),
-       PINMUX_IPSR_DATA(IP1_7_6, HSCIF2_HTX),
+       PINMUX_IPSR_GPSR(IP1_7_6, D9),
+       PINMUX_IPSR_GPSR(IP1_7_6, HSCIF2_HTX),
        PINMUX_IPSR_MSEL(IP1_7_6, I2C1_SDA_B, SEL_I2C01_1),
-       PINMUX_IPSR_DATA(IP1_10_8, D10),
-       PINMUX_IPSR_DATA(IP1_10_8, HSCIF2_HSCK),
+       PINMUX_IPSR_GPSR(IP1_10_8, D10),
+       PINMUX_IPSR_GPSR(IP1_10_8, HSCIF2_HSCK),
        PINMUX_IPSR_MSEL(IP1_10_8, SCIF1_SCK_C, SEL_SCIF1_2),
-       PINMUX_IPSR_DATA(IP1_10_8, IRQ6),
-       PINMUX_IPSR_DATA(IP1_10_8, PWM5_C),
-       PINMUX_IPSR_DATA(IP1_12_11, D11),
-       PINMUX_IPSR_DATA(IP1_12_11, HSCIF2_HCTS_N),
+       PINMUX_IPSR_GPSR(IP1_10_8, IRQ6),
+       PINMUX_IPSR_GPSR(IP1_10_8, PWM5_C),
+       PINMUX_IPSR_GPSR(IP1_12_11, D11),
+       PINMUX_IPSR_GPSR(IP1_12_11, HSCIF2_HCTS_N),
        PINMUX_IPSR_MSEL(IP1_12_11, SCIF1_RXD_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP1_12_11, I2C1_SCL_D, SEL_I2C01_3),
-       PINMUX_IPSR_DATA(IP1_14_13, D12),
-       PINMUX_IPSR_DATA(IP1_14_13, HSCIF2_HRTS_N),
+       PINMUX_IPSR_GPSR(IP1_14_13, D12),
+       PINMUX_IPSR_GPSR(IP1_14_13, HSCIF2_HRTS_N),
        PINMUX_IPSR_MSEL(IP1_14_13, SCIF1_TXD_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP1_14_13, I2C1_SDA_D, SEL_I2C01_3),
-       PINMUX_IPSR_DATA(IP1_17_15, D13),
+       PINMUX_IPSR_GPSR(IP1_17_15, D13),
        PINMUX_IPSR_MSEL(IP1_17_15, SCIFA1_SCK, SEL_SCIFA1_0),
-       PINMUX_IPSR_DATA(IP1_17_15, TANS1),
-       PINMUX_IPSR_DATA(IP1_17_15, PWM2_C),
+       PINMUX_IPSR_GPSR(IP1_17_15, TANS1),
+       PINMUX_IPSR_GPSR(IP1_17_15, PWM2_C),
        PINMUX_IPSR_MSEL(IP1_17_15, TCLK2_B, SEL_TMU_1),
-       PINMUX_IPSR_DATA(IP1_19_18, D14),
+       PINMUX_IPSR_GPSR(IP1_19_18, D14),
        PINMUX_IPSR_MSEL(IP1_19_18, SCIFA1_RXD, SEL_SCIFA1_0),
        PINMUX_IPSR_MSEL(IP1_19_18, IIC0_SCL_B, SEL_IIC00_1),
-       PINMUX_IPSR_DATA(IP1_21_20, D15),
+       PINMUX_IPSR_GPSR(IP1_21_20, D15),
        PINMUX_IPSR_MSEL(IP1_21_20, SCIFA1_TXD, SEL_SCIFA1_0),
        PINMUX_IPSR_MSEL(IP1_21_20, IIC0_SDA_B, SEL_IIC00_1),
-       PINMUX_IPSR_DATA(IP1_23_22, A0),
-       PINMUX_IPSR_DATA(IP1_23_22, SCIFB1_SCK),
-       PINMUX_IPSR_DATA(IP1_23_22, PWM3_B),
-       PINMUX_IPSR_DATA(IP1_24, A1),
-       PINMUX_IPSR_DATA(IP1_24, SCIFB1_TXD),
-       PINMUX_IPSR_DATA(IP1_26, A3),
-       PINMUX_IPSR_DATA(IP1_26, SCIFB0_SCK),
-       PINMUX_IPSR_DATA(IP1_27, A4),
-       PINMUX_IPSR_DATA(IP1_27, SCIFB0_TXD),
-       PINMUX_IPSR_DATA(IP1_29_28, A5),
-       PINMUX_IPSR_DATA(IP1_29_28, SCIFB0_RXD),
-       PINMUX_IPSR_DATA(IP1_29_28, PWM4_B),
-       PINMUX_IPSR_DATA(IP1_29_28, TPUTO3_C),
-       PINMUX_IPSR_DATA(IP1_31_30, A6),
-       PINMUX_IPSR_DATA(IP1_31_30, SCIFB0_CTS_N),
+       PINMUX_IPSR_GPSR(IP1_23_22, A0),
+       PINMUX_IPSR_GPSR(IP1_23_22, SCIFB1_SCK),
+       PINMUX_IPSR_GPSR(IP1_23_22, PWM3_B),
+       PINMUX_IPSR_GPSR(IP1_24, A1),
+       PINMUX_IPSR_GPSR(IP1_24, SCIFB1_TXD),
+       PINMUX_IPSR_GPSR(IP1_26, A3),
+       PINMUX_IPSR_GPSR(IP1_26, SCIFB0_SCK),
+       PINMUX_IPSR_GPSR(IP1_27, A4),
+       PINMUX_IPSR_GPSR(IP1_27, SCIFB0_TXD),
+       PINMUX_IPSR_GPSR(IP1_29_28, A5),
+       PINMUX_IPSR_GPSR(IP1_29_28, SCIFB0_RXD),
+       PINMUX_IPSR_GPSR(IP1_29_28, PWM4_B),
+       PINMUX_IPSR_GPSR(IP1_29_28, TPUTO3_C),
+       PINMUX_IPSR_GPSR(IP1_31_30, A6),
+       PINMUX_IPSR_GPSR(IP1_31_30, SCIFB0_CTS_N),
        PINMUX_IPSR_MSEL(IP1_31_30, SCIFA4_RXD_B, SEL_SCIFA4_1),
-       PINMUX_IPSR_DATA(IP1_31_30, TPUTO2_C),
+       PINMUX_IPSR_GPSR(IP1_31_30, TPUTO2_C),
 
        /* IPSR2 */
-       PINMUX_IPSR_DATA(IP2_1_0, A7),
-       PINMUX_IPSR_DATA(IP2_1_0, SCIFB0_RTS_N),
+       PINMUX_IPSR_GPSR(IP2_1_0, A7),
+       PINMUX_IPSR_GPSR(IP2_1_0, SCIFB0_RTS_N),
        PINMUX_IPSR_MSEL(IP2_1_0, SCIFA4_TXD_B, SEL_SCIFA4_1),
-       PINMUX_IPSR_DATA(IP2_3_2, A8),
+       PINMUX_IPSR_GPSR(IP2_3_2, A8),
        PINMUX_IPSR_MSEL(IP2_3_2, MSIOF1_RXD, SEL_MSI1_0),
        PINMUX_IPSR_MSEL(IP2_3_2, SCIFA0_RXD_B, SEL_SCIFA0_1),
-       PINMUX_IPSR_DATA(IP2_5_4, A9),
+       PINMUX_IPSR_GPSR(IP2_5_4, A9),
        PINMUX_IPSR_MSEL(IP2_5_4, MSIOF1_TXD, SEL_MSI1_0),
        PINMUX_IPSR_MSEL(IP2_5_4, SCIFA0_TXD_B, SEL_SCIFA0_1),
-       PINMUX_IPSR_DATA(IP2_7_6, A10),
+       PINMUX_IPSR_GPSR(IP2_7_6, A10),
        PINMUX_IPSR_MSEL(IP2_7_6, MSIOF1_SCK, SEL_MSI1_0),
        PINMUX_IPSR_MSEL(IP2_7_6, IIC1_SCL_B, SEL_IIC01_1),
-       PINMUX_IPSR_DATA(IP2_9_8, A11),
+       PINMUX_IPSR_GPSR(IP2_9_8, A11),
        PINMUX_IPSR_MSEL(IP2_9_8, MSIOF1_SYNC, SEL_MSI1_0),
        PINMUX_IPSR_MSEL(IP2_9_8, IIC1_SDA_B, SEL_IIC01_1),
-       PINMUX_IPSR_DATA(IP2_11_10, A12),
+       PINMUX_IPSR_GPSR(IP2_11_10, A12),
        PINMUX_IPSR_MSEL(IP2_11_10, MSIOF1_SS1, SEL_MSI1_0),
        PINMUX_IPSR_MSEL(IP2_11_10, SCIFA5_RXD_B, SEL_SCIFA5_1),
-       PINMUX_IPSR_DATA(IP2_13_12, A13),
+       PINMUX_IPSR_GPSR(IP2_13_12, A13),
        PINMUX_IPSR_MSEL(IP2_13_12, MSIOF1_SS2, SEL_MSI1_0),
        PINMUX_IPSR_MSEL(IP2_13_12, SCIFA5_TXD_B, SEL_SCIFA5_1),
-       PINMUX_IPSR_DATA(IP2_15_14, A14),
+       PINMUX_IPSR_GPSR(IP2_15_14, A14),
        PINMUX_IPSR_MSEL(IP2_15_14, MSIOF2_RXD, SEL_MSI2_0),
        PINMUX_IPSR_MSEL(IP2_15_14, HSCIF0_HRX_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP2_15_14, DREQ1_N, SEL_LBS_0),
-       PINMUX_IPSR_DATA(IP2_17_16, A15),
+       PINMUX_IPSR_GPSR(IP2_17_16, A15),
        PINMUX_IPSR_MSEL(IP2_17_16, MSIOF2_TXD, SEL_MSI2_0),
        PINMUX_IPSR_MSEL(IP2_17_16, HSCIF0_HTX_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP2_17_16, DACK1, SEL_LBS_0),
-       PINMUX_IPSR_DATA(IP2_20_18, A16),
+       PINMUX_IPSR_GPSR(IP2_20_18, A16),
        PINMUX_IPSR_MSEL(IP2_20_18, MSIOF2_SCK, SEL_MSI2_0),
        PINMUX_IPSR_MSEL(IP2_20_18, HSCIF0_HSCK_B, SEL_HSCIF0_1),
        PINMUX_IPSR_MSEL(IP2_20_18, SPEEDIN, SEL_RSP_0),
        PINMUX_IPSR_MSEL(IP2_20_18, VSP, SEL_SPDM_0),
        PINMUX_IPSR_MSEL(IP2_20_18, CAN_CLK_C, SEL_CAN_2),
-       PINMUX_IPSR_DATA(IP2_20_18, TPUTO2_B),
-       PINMUX_IPSR_DATA(IP2_23_21, A17),
+       PINMUX_IPSR_GPSR(IP2_20_18, TPUTO2_B),
+       PINMUX_IPSR_GPSR(IP2_23_21, A17),
        PINMUX_IPSR_MSEL(IP2_23_21, MSIOF2_SYNC, SEL_MSI2_0),
        PINMUX_IPSR_MSEL(IP2_23_21, SCIF4_RXD_E, SEL_SCIF4_4),
        PINMUX_IPSR_MSEL(IP2_23_21, CAN1_RX_B, SEL_CAN1_1),
        PINMUX_IPSR_MSEL(IP2_23_21, AVB_AVTP_CAPTURE_B, SEL_AVB_1),
-       PINMUX_IPSR_DATA(IP2_26_24, A18),
+       PINMUX_IPSR_GPSR(IP2_26_24, A18),
        PINMUX_IPSR_MSEL(IP2_26_24, MSIOF2_SS1, SEL_MSI2_0),
        PINMUX_IPSR_MSEL(IP2_26_24, SCIF4_TXD_E, SEL_SCIF4_4),
        PINMUX_IPSR_MSEL(IP2_26_24, CAN1_TX_B, SEL_CAN1_1),
        PINMUX_IPSR_MSEL(IP2_26_24, AVB_AVTP_MATCH_B, SEL_AVB_1),
-       PINMUX_IPSR_DATA(IP2_29_27, A19),
+       PINMUX_IPSR_GPSR(IP2_29_27, A19),
        PINMUX_IPSR_MSEL(IP2_29_27, MSIOF2_SS2, SEL_MSI2_0),
-       PINMUX_IPSR_DATA(IP2_29_27, PWM4),
-       PINMUX_IPSR_DATA(IP2_29_27, TPUTO2),
-       PINMUX_IPSR_DATA(IP2_29_27, MOUT0),
-       PINMUX_IPSR_DATA(IP2_31_30, A20),
-       PINMUX_IPSR_DATA(IP2_31_30, SPCLK),
-       PINMUX_IPSR_DATA(IP2_29_27, MOUT1),
+       PINMUX_IPSR_GPSR(IP2_29_27, PWM4),
+       PINMUX_IPSR_GPSR(IP2_29_27, TPUTO2),
+       PINMUX_IPSR_GPSR(IP2_29_27, MOUT0),
+       PINMUX_IPSR_GPSR(IP2_31_30, A20),
+       PINMUX_IPSR_GPSR(IP2_31_30, SPCLK),
+       PINMUX_IPSR_GPSR(IP2_29_27, MOUT1),
 
        /* IPSR3 */
-       PINMUX_IPSR_DATA(IP3_1_0, A21),
-       PINMUX_IPSR_DATA(IP3_1_0, MOSI_IO0),
-       PINMUX_IPSR_DATA(IP3_1_0, MOUT2),
-       PINMUX_IPSR_DATA(IP3_3_2, A22),
-       PINMUX_IPSR_DATA(IP3_3_2, MISO_IO1),
-       PINMUX_IPSR_DATA(IP3_3_2, MOUT5),
-       PINMUX_IPSR_DATA(IP3_3_2, ATADIR1_N),
-       PINMUX_IPSR_DATA(IP3_5_4, A23),
-       PINMUX_IPSR_DATA(IP3_5_4, IO2),
-       PINMUX_IPSR_DATA(IP3_5_4, MOUT6),
-       PINMUX_IPSR_DATA(IP3_5_4, ATAWR1_N),
-       PINMUX_IPSR_DATA(IP3_7_6, A24),
-       PINMUX_IPSR_DATA(IP3_7_6, IO3),
-       PINMUX_IPSR_DATA(IP3_7_6, EX_WAIT2),
-       PINMUX_IPSR_DATA(IP3_9_8, A25),
-       PINMUX_IPSR_DATA(IP3_9_8, SSL),
-       PINMUX_IPSR_DATA(IP3_9_8, ATARD1_N),
-       PINMUX_IPSR_DATA(IP3_10, CS0_N),
-       PINMUX_IPSR_DATA(IP3_10, VI1_DATA8),
-       PINMUX_IPSR_DATA(IP3_11, CS1_N_A26),
-       PINMUX_IPSR_DATA(IP3_11, VI1_DATA9),
-       PINMUX_IPSR_DATA(IP3_12, EX_CS0_N),
-       PINMUX_IPSR_DATA(IP3_12, VI1_DATA10),
-       PINMUX_IPSR_DATA(IP3_14_13, EX_CS1_N),
-       PINMUX_IPSR_DATA(IP3_14_13, TPUTO3_B),
-       PINMUX_IPSR_DATA(IP3_14_13, SCIFB2_RXD),
-       PINMUX_IPSR_DATA(IP3_14_13, VI1_DATA11),
-       PINMUX_IPSR_DATA(IP3_17_15, EX_CS2_N),
-       PINMUX_IPSR_DATA(IP3_17_15, PWM0),
+       PINMUX_IPSR_GPSR(IP3_1_0, A21),
+       PINMUX_IPSR_GPSR(IP3_1_0, MOSI_IO0),
+       PINMUX_IPSR_GPSR(IP3_1_0, MOUT2),
+       PINMUX_IPSR_GPSR(IP3_3_2, A22),
+       PINMUX_IPSR_GPSR(IP3_3_2, MISO_IO1),
+       PINMUX_IPSR_GPSR(IP3_3_2, MOUT5),
+       PINMUX_IPSR_GPSR(IP3_3_2, ATADIR1_N),
+       PINMUX_IPSR_GPSR(IP3_5_4, A23),
+       PINMUX_IPSR_GPSR(IP3_5_4, IO2),
+       PINMUX_IPSR_GPSR(IP3_5_4, MOUT6),
+       PINMUX_IPSR_GPSR(IP3_5_4, ATAWR1_N),
+       PINMUX_IPSR_GPSR(IP3_7_6, A24),
+       PINMUX_IPSR_GPSR(IP3_7_6, IO3),
+       PINMUX_IPSR_GPSR(IP3_7_6, EX_WAIT2),
+       PINMUX_IPSR_GPSR(IP3_9_8, A25),
+       PINMUX_IPSR_GPSR(IP3_9_8, SSL),
+       PINMUX_IPSR_GPSR(IP3_9_8, ATARD1_N),
+       PINMUX_IPSR_GPSR(IP3_10, CS0_N),
+       PINMUX_IPSR_GPSR(IP3_10, VI1_DATA8),
+       PINMUX_IPSR_GPSR(IP3_11, CS1_N_A26),
+       PINMUX_IPSR_GPSR(IP3_11, VI1_DATA9),
+       PINMUX_IPSR_GPSR(IP3_12, EX_CS0_N),
+       PINMUX_IPSR_GPSR(IP3_12, VI1_DATA10),
+       PINMUX_IPSR_GPSR(IP3_14_13, EX_CS1_N),
+       PINMUX_IPSR_GPSR(IP3_14_13, TPUTO3_B),
+       PINMUX_IPSR_GPSR(IP3_14_13, SCIFB2_RXD),
+       PINMUX_IPSR_GPSR(IP3_14_13, VI1_DATA11),
+       PINMUX_IPSR_GPSR(IP3_17_15, EX_CS2_N),
+       PINMUX_IPSR_GPSR(IP3_17_15, PWM0),
        PINMUX_IPSR_MSEL(IP3_17_15, SCIF4_RXD_C, SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP3_17_15, TS_SDATA_B, SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP3_17_15, RIF0_SYNC, SEL_DR0_0),
-       PINMUX_IPSR_DATA(IP3_17_15, TPUTO3),
-       PINMUX_IPSR_DATA(IP3_17_15, SCIFB2_TXD),
+       PINMUX_IPSR_GPSR(IP3_17_15, TPUTO3),
+       PINMUX_IPSR_GPSR(IP3_17_15, SCIFB2_TXD),
        PINMUX_IPSR_MSEL(IP3_17_15, SDATA_B, SEL_FSN_1),
-       PINMUX_IPSR_DATA(IP3_20_18, EX_CS3_N),
+       PINMUX_IPSR_GPSR(IP3_20_18, EX_CS3_N),
        PINMUX_IPSR_MSEL(IP3_20_18, SCIFA2_SCK, SEL_SCIFA2_0),
        PINMUX_IPSR_MSEL(IP3_20_18, SCIF4_TXD_C, SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP3_20_18, TS_SCK_B, SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP3_20_18, RIF0_CLK, SEL_DR0_0),
        PINMUX_IPSR_MSEL(IP3_20_18, BPFCLK, SEL_DARC_0),
-       PINMUX_IPSR_DATA(IP3_20_18, SCIFB2_SCK),
+       PINMUX_IPSR_GPSR(IP3_20_18, SCIFB2_SCK),
        PINMUX_IPSR_MSEL(IP3_20_18, MDATA_B, SEL_FSN_1),
-       PINMUX_IPSR_DATA(IP3_23_21, EX_CS4_N),
+       PINMUX_IPSR_GPSR(IP3_23_21, EX_CS4_N),
        PINMUX_IPSR_MSEL(IP3_23_21, SCIFA2_RXD, SEL_SCIFA2_0),
        PINMUX_IPSR_MSEL(IP3_23_21, I2C2_SCL_E, SEL_I2C02_4),
        PINMUX_IPSR_MSEL(IP3_23_21, TS_SDEN_B, SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP3_23_21, RIF0_D0, SEL_DR0_0),
        PINMUX_IPSR_MSEL(IP3_23_21, FMCLK, SEL_DARC_0),
-       PINMUX_IPSR_DATA(IP3_23_21, SCIFB2_CTS_N),
+       PINMUX_IPSR_GPSR(IP3_23_21, SCIFB2_CTS_N),
        PINMUX_IPSR_MSEL(IP3_23_21, SCKZ_B, SEL_FSN_1),
-       PINMUX_IPSR_DATA(IP3_26_24, EX_CS5_N),
+       PINMUX_IPSR_GPSR(IP3_26_24, EX_CS5_N),
        PINMUX_IPSR_MSEL(IP3_26_24, SCIFA2_TXD, SEL_SCIFA2_0),
        PINMUX_IPSR_MSEL(IP3_26_24, I2C2_SDA_E, SEL_I2C02_4),
        PINMUX_IPSR_MSEL(IP3_26_24, TS_SPSYNC_B, SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP3_26_24, RIF0_D1, SEL_DR1_0),
        PINMUX_IPSR_MSEL(IP3_26_24, FMIN, SEL_DARC_0),
-       PINMUX_IPSR_DATA(IP3_26_24, SCIFB2_RTS_N),
+       PINMUX_IPSR_GPSR(IP3_26_24, SCIFB2_RTS_N),
        PINMUX_IPSR_MSEL(IP3_26_24, STM_N_B, SEL_FSN_1),
-       PINMUX_IPSR_DATA(IP3_29_27, BS_N),
-       PINMUX_IPSR_DATA(IP3_29_27, DRACK0),
-       PINMUX_IPSR_DATA(IP3_29_27, PWM1_C),
-       PINMUX_IPSR_DATA(IP3_29_27, TPUTO0_C),
-       PINMUX_IPSR_DATA(IP3_29_27, ATACS01_N),
+       PINMUX_IPSR_GPSR(IP3_29_27, BS_N),
+       PINMUX_IPSR_GPSR(IP3_29_27, DRACK0),
+       PINMUX_IPSR_GPSR(IP3_29_27, PWM1_C),
+       PINMUX_IPSR_GPSR(IP3_29_27, TPUTO0_C),
+       PINMUX_IPSR_GPSR(IP3_29_27, ATACS01_N),
        PINMUX_IPSR_MSEL(IP3_29_27, MTS_N_B, SEL_FSN_1),
-       PINMUX_IPSR_DATA(IP3_30, RD_N),
-       PINMUX_IPSR_DATA(IP3_30, ATACS11_N),
-       PINMUX_IPSR_DATA(IP3_31, RD_WR_N),
-       PINMUX_IPSR_DATA(IP3_31, ATAG1_N),
+       PINMUX_IPSR_GPSR(IP3_30, RD_N),
+       PINMUX_IPSR_GPSR(IP3_30, ATACS11_N),
+       PINMUX_IPSR_GPSR(IP3_31, RD_WR_N),
+       PINMUX_IPSR_GPSR(IP3_31, ATAG1_N),
 
        /* IPSR4 */
-       PINMUX_IPSR_DATA(IP4_1_0, EX_WAIT0),
+       PINMUX_IPSR_GPSR(IP4_1_0, EX_WAIT0),
        PINMUX_IPSR_MSEL(IP4_1_0, CAN_CLK_B, SEL_CAN_1),
        PINMUX_IPSR_MSEL(IP4_1_0, SCIF_CLK, SEL_SCIF0_0),
-       PINMUX_IPSR_DATA(IP4_1_0, PWMFSW0),
-       PINMUX_IPSR_DATA(IP4_4_2, DU0_DR0),
-       PINMUX_IPSR_DATA(IP4_4_2, LCDOUT16),
+       PINMUX_IPSR_GPSR(IP4_1_0, PWMFSW0),
+       PINMUX_IPSR_GPSR(IP4_4_2, DU0_DR0),
+       PINMUX_IPSR_GPSR(IP4_4_2, LCDOUT16),
        PINMUX_IPSR_MSEL(IP4_4_2, SCIF5_RXD_C, SEL_SCIF5_2),
        PINMUX_IPSR_MSEL(IP4_4_2, I2C2_SCL_D, SEL_I2C02_3),
-       PINMUX_IPSR_DATA(IP4_4_2, CC50_STATE0),
-       PINMUX_IPSR_DATA(IP4_7_5, DU0_DR1),
-       PINMUX_IPSR_DATA(IP4_7_5, LCDOUT17),
+       PINMUX_IPSR_GPSR(IP4_4_2, CC50_STATE0),
+       PINMUX_IPSR_GPSR(IP4_7_5, DU0_DR1),
+       PINMUX_IPSR_GPSR(IP4_7_5, LCDOUT17),
        PINMUX_IPSR_MSEL(IP4_7_5, SCIF5_TXD_C, SEL_SCIF5_2),
        PINMUX_IPSR_MSEL(IP4_7_5, I2C2_SDA_D, SEL_I2C02_3),
-       PINMUX_IPSR_DATA(IP4_9_8, CC50_STATE1),
-       PINMUX_IPSR_DATA(IP4_9_8, DU0_DR2),
-       PINMUX_IPSR_DATA(IP4_9_8, LCDOUT18),
-       PINMUX_IPSR_DATA(IP4_9_8, CC50_STATE2),
-       PINMUX_IPSR_DATA(IP4_11_10, DU0_DR3),
-       PINMUX_IPSR_DATA(IP4_11_10, LCDOUT19),
-       PINMUX_IPSR_DATA(IP4_11_10, CC50_STATE3),
-       PINMUX_IPSR_DATA(IP4_13_12, DU0_DR4),
-       PINMUX_IPSR_DATA(IP4_13_12, LCDOUT20),
-       PINMUX_IPSR_DATA(IP4_13_12, CC50_STATE4),
-       PINMUX_IPSR_DATA(IP4_15_14, DU0_DR5),
-       PINMUX_IPSR_DATA(IP4_15_14, LCDOUT21),
-       PINMUX_IPSR_DATA(IP4_15_14, CC50_STATE5),
-       PINMUX_IPSR_DATA(IP4_17_16, DU0_DR6),
-       PINMUX_IPSR_DATA(IP4_17_16, LCDOUT22),
-       PINMUX_IPSR_DATA(IP4_17_16, CC50_STATE6),
-       PINMUX_IPSR_DATA(IP4_19_18, DU0_DR7),
-       PINMUX_IPSR_DATA(IP4_19_18, LCDOUT23),
-       PINMUX_IPSR_DATA(IP4_19_18, CC50_STATE7),
-       PINMUX_IPSR_DATA(IP4_22_20, DU0_DG0),
-       PINMUX_IPSR_DATA(IP4_22_20, LCDOUT8),
+       PINMUX_IPSR_GPSR(IP4_9_8, CC50_STATE1),
+       PINMUX_IPSR_GPSR(IP4_9_8, DU0_DR2),
+       PINMUX_IPSR_GPSR(IP4_9_8, LCDOUT18),
+       PINMUX_IPSR_GPSR(IP4_9_8, CC50_STATE2),
+       PINMUX_IPSR_GPSR(IP4_11_10, DU0_DR3),
+       PINMUX_IPSR_GPSR(IP4_11_10, LCDOUT19),
+       PINMUX_IPSR_GPSR(IP4_11_10, CC50_STATE3),
+       PINMUX_IPSR_GPSR(IP4_13_12, DU0_DR4),
+       PINMUX_IPSR_GPSR(IP4_13_12, LCDOUT20),
+       PINMUX_IPSR_GPSR(IP4_13_12, CC50_STATE4),
+       PINMUX_IPSR_GPSR(IP4_15_14, DU0_DR5),
+       PINMUX_IPSR_GPSR(IP4_15_14, LCDOUT21),
+       PINMUX_IPSR_GPSR(IP4_15_14, CC50_STATE5),
+       PINMUX_IPSR_GPSR(IP4_17_16, DU0_DR6),
+       PINMUX_IPSR_GPSR(IP4_17_16, LCDOUT22),
+       PINMUX_IPSR_GPSR(IP4_17_16, CC50_STATE6),
+       PINMUX_IPSR_GPSR(IP4_19_18, DU0_DR7),
+       PINMUX_IPSR_GPSR(IP4_19_18, LCDOUT23),
+       PINMUX_IPSR_GPSR(IP4_19_18, CC50_STATE7),
+       PINMUX_IPSR_GPSR(IP4_22_20, DU0_DG0),
+       PINMUX_IPSR_GPSR(IP4_22_20, LCDOUT8),
        PINMUX_IPSR_MSEL(IP4_22_20, SCIFA0_RXD_C, SEL_SCIFA0_2),
        PINMUX_IPSR_MSEL(IP4_22_20, I2C3_SCL_D, SEL_I2C03_3),
-       PINMUX_IPSR_DATA(IP4_22_20, CC50_STATE8),
-       PINMUX_IPSR_DATA(IP4_25_23, DU0_DG1),
-       PINMUX_IPSR_DATA(IP4_25_23, LCDOUT9),
+       PINMUX_IPSR_GPSR(IP4_22_20, CC50_STATE8),
+       PINMUX_IPSR_GPSR(IP4_25_23, DU0_DG1),
+       PINMUX_IPSR_GPSR(IP4_25_23, LCDOUT9),
        PINMUX_IPSR_MSEL(IP4_25_23, SCIFA0_TXD_C, SEL_SCIFA0_2),
        PINMUX_IPSR_MSEL(IP4_25_23, I2C3_SDA_D, SEL_I2C03_3),
-       PINMUX_IPSR_DATA(IP4_25_23, CC50_STATE9),
-       PINMUX_IPSR_DATA(IP4_27_26, DU0_DG2),
-       PINMUX_IPSR_DATA(IP4_27_26, LCDOUT10),
-       PINMUX_IPSR_DATA(IP4_27_26, CC50_STATE10),
-       PINMUX_IPSR_DATA(IP4_29_28, DU0_DG3),
-       PINMUX_IPSR_DATA(IP4_29_28, LCDOUT11),
-       PINMUX_IPSR_DATA(IP4_29_28, CC50_STATE11),
-       PINMUX_IPSR_DATA(IP4_31_30, DU0_DG4),
-       PINMUX_IPSR_DATA(IP4_31_30, LCDOUT12),
-       PINMUX_IPSR_DATA(IP4_31_30, CC50_STATE12),
+       PINMUX_IPSR_GPSR(IP4_25_23, CC50_STATE9),
+       PINMUX_IPSR_GPSR(IP4_27_26, DU0_DG2),
+       PINMUX_IPSR_GPSR(IP4_27_26, LCDOUT10),
+       PINMUX_IPSR_GPSR(IP4_27_26, CC50_STATE10),
+       PINMUX_IPSR_GPSR(IP4_29_28, DU0_DG3),
+       PINMUX_IPSR_GPSR(IP4_29_28, LCDOUT11),
+       PINMUX_IPSR_GPSR(IP4_29_28, CC50_STATE11),
+       PINMUX_IPSR_GPSR(IP4_31_30, DU0_DG4),
+       PINMUX_IPSR_GPSR(IP4_31_30, LCDOUT12),
+       PINMUX_IPSR_GPSR(IP4_31_30, CC50_STATE12),
 
        /* IPSR5 */
-       PINMUX_IPSR_DATA(IP5_1_0, DU0_DG5),
-       PINMUX_IPSR_DATA(IP5_1_0, LCDOUT13),
-       PINMUX_IPSR_DATA(IP5_1_0, CC50_STATE13),
-       PINMUX_IPSR_DATA(IP5_3_2, DU0_DG6),
-       PINMUX_IPSR_DATA(IP5_3_2, LCDOUT14),
-       PINMUX_IPSR_DATA(IP5_3_2, CC50_STATE14),
-       PINMUX_IPSR_DATA(IP5_5_4, DU0_DG7),
-       PINMUX_IPSR_DATA(IP5_5_4, LCDOUT15),
-       PINMUX_IPSR_DATA(IP5_5_4, CC50_STATE15),
-       PINMUX_IPSR_DATA(IP5_8_6, DU0_DB0),
-       PINMUX_IPSR_DATA(IP5_8_6, LCDOUT0),
+       PINMUX_IPSR_GPSR(IP5_1_0, DU0_DG5),
+       PINMUX_IPSR_GPSR(IP5_1_0, LCDOUT13),
+       PINMUX_IPSR_GPSR(IP5_1_0, CC50_STATE13),
+       PINMUX_IPSR_GPSR(IP5_3_2, DU0_DG6),
+       PINMUX_IPSR_GPSR(IP5_3_2, LCDOUT14),
+       PINMUX_IPSR_GPSR(IP5_3_2, CC50_STATE14),
+       PINMUX_IPSR_GPSR(IP5_5_4, DU0_DG7),
+       PINMUX_IPSR_GPSR(IP5_5_4, LCDOUT15),
+       PINMUX_IPSR_GPSR(IP5_5_4, CC50_STATE15),
+       PINMUX_IPSR_GPSR(IP5_8_6, DU0_DB0),
+       PINMUX_IPSR_GPSR(IP5_8_6, LCDOUT0),
        PINMUX_IPSR_MSEL(IP5_8_6, SCIFA4_RXD_C, SEL_SCIFA4_2),
        PINMUX_IPSR_MSEL(IP5_8_6, I2C4_SCL_D, SEL_I2C04_3),
        PINMUX_IPSR_MSEL(IP7_8_6, CAN0_RX_C, SEL_CAN0_2),
-       PINMUX_IPSR_DATA(IP5_8_6, CC50_STATE16),
-       PINMUX_IPSR_DATA(IP5_11_9, DU0_DB1),
-       PINMUX_IPSR_DATA(IP5_11_9, LCDOUT1),
+       PINMUX_IPSR_GPSR(IP5_8_6, CC50_STATE16),
+       PINMUX_IPSR_GPSR(IP5_11_9, DU0_DB1),
+       PINMUX_IPSR_GPSR(IP5_11_9, LCDOUT1),
        PINMUX_IPSR_MSEL(IP5_11_9, SCIFA4_TXD_C, SEL_SCIFA4_2),
        PINMUX_IPSR_MSEL(IP5_11_9, I2C4_SDA_D, SEL_I2C04_3),
        PINMUX_IPSR_MSEL(IP5_11_9, CAN0_TX_C, SEL_CAN0_2),
-       PINMUX_IPSR_DATA(IP5_11_9, CC50_STATE17),
-       PINMUX_IPSR_DATA(IP5_13_12, DU0_DB2),
-       PINMUX_IPSR_DATA(IP5_13_12, LCDOUT2),
-       PINMUX_IPSR_DATA(IP5_13_12, CC50_STATE18),
-       PINMUX_IPSR_DATA(IP5_15_14, DU0_DB3),
-       PINMUX_IPSR_DATA(IP5_15_14, LCDOUT3),
-       PINMUX_IPSR_DATA(IP5_15_14, CC50_STATE19),
-       PINMUX_IPSR_DATA(IP5_17_16, DU0_DB4),
-       PINMUX_IPSR_DATA(IP5_17_16, LCDOUT4),
-       PINMUX_IPSR_DATA(IP5_17_16, CC50_STATE20),
-       PINMUX_IPSR_DATA(IP5_19_18, DU0_DB5),
-       PINMUX_IPSR_DATA(IP5_19_18, LCDOUT5),
-       PINMUX_IPSR_DATA(IP5_19_18, CC50_STATE21),
-       PINMUX_IPSR_DATA(IP5_21_20, DU0_DB6),
-       PINMUX_IPSR_DATA(IP5_21_20, LCDOUT6),
-       PINMUX_IPSR_DATA(IP5_21_20, CC50_STATE22),
-       PINMUX_IPSR_DATA(IP5_23_22, DU0_DB7),
-       PINMUX_IPSR_DATA(IP5_23_22, LCDOUT7),
-       PINMUX_IPSR_DATA(IP5_23_22, CC50_STATE23),
-       PINMUX_IPSR_DATA(IP5_25_24, DU0_DOTCLKIN),
-       PINMUX_IPSR_DATA(IP5_25_24, QSTVA_QVS),
-       PINMUX_IPSR_DATA(IP5_25_24, CC50_STATE24),
-       PINMUX_IPSR_DATA(IP5_27_26, DU0_DOTCLKOUT0),
-       PINMUX_IPSR_DATA(IP5_27_26, QCLK),
-       PINMUX_IPSR_DATA(IP5_27_26, CC50_STATE25),
-       PINMUX_IPSR_DATA(IP5_29_28, DU0_DOTCLKOUT1),
-       PINMUX_IPSR_DATA(IP5_29_28, QSTVB_QVE),
-       PINMUX_IPSR_DATA(IP5_29_28, CC50_STATE26),
-       PINMUX_IPSR_DATA(IP5_31_30, DU0_EXHSYNC_DU0_HSYNC),
-       PINMUX_IPSR_DATA(IP5_31_30, QSTH_QHS),
-       PINMUX_IPSR_DATA(IP5_31_30, CC50_STATE27),
+       PINMUX_IPSR_GPSR(IP5_11_9, CC50_STATE17),
+       PINMUX_IPSR_GPSR(IP5_13_12, DU0_DB2),
+       PINMUX_IPSR_GPSR(IP5_13_12, LCDOUT2),
+       PINMUX_IPSR_GPSR(IP5_13_12, CC50_STATE18),
+       PINMUX_IPSR_GPSR(IP5_15_14, DU0_DB3),
+       PINMUX_IPSR_GPSR(IP5_15_14, LCDOUT3),
+       PINMUX_IPSR_GPSR(IP5_15_14, CC50_STATE19),
+       PINMUX_IPSR_GPSR(IP5_17_16, DU0_DB4),
+       PINMUX_IPSR_GPSR(IP5_17_16, LCDOUT4),
+       PINMUX_IPSR_GPSR(IP5_17_16, CC50_STATE20),
+       PINMUX_IPSR_GPSR(IP5_19_18, DU0_DB5),
+       PINMUX_IPSR_GPSR(IP5_19_18, LCDOUT5),
+       PINMUX_IPSR_GPSR(IP5_19_18, CC50_STATE21),
+       PINMUX_IPSR_GPSR(IP5_21_20, DU0_DB6),
+       PINMUX_IPSR_GPSR(IP5_21_20, LCDOUT6),
+       PINMUX_IPSR_GPSR(IP5_21_20, CC50_STATE22),
+       PINMUX_IPSR_GPSR(IP5_23_22, DU0_DB7),
+       PINMUX_IPSR_GPSR(IP5_23_22, LCDOUT7),
+       PINMUX_IPSR_GPSR(IP5_23_22, CC50_STATE23),
+       PINMUX_IPSR_GPSR(IP5_25_24, DU0_DOTCLKIN),
+       PINMUX_IPSR_GPSR(IP5_25_24, QSTVA_QVS),
+       PINMUX_IPSR_GPSR(IP5_25_24, CC50_STATE24),
+       PINMUX_IPSR_GPSR(IP5_27_26, DU0_DOTCLKOUT0),
+       PINMUX_IPSR_GPSR(IP5_27_26, QCLK),
+       PINMUX_IPSR_GPSR(IP5_27_26, CC50_STATE25),
+       PINMUX_IPSR_GPSR(IP5_29_28, DU0_DOTCLKOUT1),
+       PINMUX_IPSR_GPSR(IP5_29_28, QSTVB_QVE),
+       PINMUX_IPSR_GPSR(IP5_29_28, CC50_STATE26),
+       PINMUX_IPSR_GPSR(IP5_31_30, DU0_EXHSYNC_DU0_HSYNC),
+       PINMUX_IPSR_GPSR(IP5_31_30, QSTH_QHS),
+       PINMUX_IPSR_GPSR(IP5_31_30, CC50_STATE27),
 
        /* IPSR6 */
-       PINMUX_IPSR_DATA(IP6_1_0, DU0_EXVSYNC_DU0_VSYNC),
-       PINMUX_IPSR_DATA(IP6_1_0, QSTB_QHE),
-       PINMUX_IPSR_DATA(IP6_1_0, CC50_STATE28),
-       PINMUX_IPSR_DATA(IP6_3_2, DU0_EXODDF_DU0_ODDF_DISP_CDE),
-       PINMUX_IPSR_DATA(IP6_3_2, QCPV_QDE),
-       PINMUX_IPSR_DATA(IP6_3_2, CC50_STATE29),
-       PINMUX_IPSR_DATA(IP6_5_4, DU0_DISP),
-       PINMUX_IPSR_DATA(IP6_5_4, QPOLA),
-       PINMUX_IPSR_DATA(IP6_5_4, CC50_STATE30),
-       PINMUX_IPSR_DATA(IP6_7_6, DU0_CDE),
-       PINMUX_IPSR_DATA(IP6_7_6, QPOLB),
-       PINMUX_IPSR_DATA(IP6_7_6, CC50_STATE31),
-       PINMUX_IPSR_DATA(IP6_8, VI0_CLK),
-       PINMUX_IPSR_DATA(IP6_8, AVB_RX_CLK),
-       PINMUX_IPSR_DATA(IP6_9, VI0_DATA0_VI0_B0),
-       PINMUX_IPSR_DATA(IP6_9, AVB_RX_DV),
-       PINMUX_IPSR_DATA(IP6_10, VI0_DATA1_VI0_B1),
-       PINMUX_IPSR_DATA(IP6_10, AVB_RXD0),
-       PINMUX_IPSR_DATA(IP6_11, VI0_DATA2_VI0_B2),
-       PINMUX_IPSR_DATA(IP6_11, AVB_RXD1),
-       PINMUX_IPSR_DATA(IP6_12, VI0_DATA3_VI0_B3),
-       PINMUX_IPSR_DATA(IP6_12, AVB_RXD2),
-       PINMUX_IPSR_DATA(IP6_13, VI0_DATA4_VI0_B4),
-       PINMUX_IPSR_DATA(IP6_13, AVB_RXD3),
-       PINMUX_IPSR_DATA(IP6_14, VI0_DATA5_VI0_B5),
-       PINMUX_IPSR_DATA(IP6_14, AVB_RXD4),
-       PINMUX_IPSR_DATA(IP6_15, VI0_DATA6_VI0_B6),
-       PINMUX_IPSR_DATA(IP6_15, AVB_RXD5),
-       PINMUX_IPSR_DATA(IP6_16, VI0_DATA7_VI0_B7),
-       PINMUX_IPSR_DATA(IP6_16, AVB_RXD6),
-       PINMUX_IPSR_DATA(IP6_19_17, VI0_CLKENB),
+       PINMUX_IPSR_GPSR(IP6_1_0, DU0_EXVSYNC_DU0_VSYNC),
+       PINMUX_IPSR_GPSR(IP6_1_0, QSTB_QHE),
+       PINMUX_IPSR_GPSR(IP6_1_0, CC50_STATE28),
+       PINMUX_IPSR_GPSR(IP6_3_2, DU0_EXODDF_DU0_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP6_3_2, QCPV_QDE),
+       PINMUX_IPSR_GPSR(IP6_3_2, CC50_STATE29),
+       PINMUX_IPSR_GPSR(IP6_5_4, DU0_DISP),
+       PINMUX_IPSR_GPSR(IP6_5_4, QPOLA),
+       PINMUX_IPSR_GPSR(IP6_5_4, CC50_STATE30),
+       PINMUX_IPSR_GPSR(IP6_7_6, DU0_CDE),
+       PINMUX_IPSR_GPSR(IP6_7_6, QPOLB),
+       PINMUX_IPSR_GPSR(IP6_7_6, CC50_STATE31),
+       PINMUX_IPSR_GPSR(IP6_8, VI0_CLK),
+       PINMUX_IPSR_GPSR(IP6_8, AVB_RX_CLK),
+       PINMUX_IPSR_GPSR(IP6_9, VI0_DATA0_VI0_B0),
+       PINMUX_IPSR_GPSR(IP6_9, AVB_RX_DV),
+       PINMUX_IPSR_GPSR(IP6_10, VI0_DATA1_VI0_B1),
+       PINMUX_IPSR_GPSR(IP6_10, AVB_RXD0),
+       PINMUX_IPSR_GPSR(IP6_11, VI0_DATA2_VI0_B2),
+       PINMUX_IPSR_GPSR(IP6_11, AVB_RXD1),
+       PINMUX_IPSR_GPSR(IP6_12, VI0_DATA3_VI0_B3),
+       PINMUX_IPSR_GPSR(IP6_12, AVB_RXD2),
+       PINMUX_IPSR_GPSR(IP6_13, VI0_DATA4_VI0_B4),
+       PINMUX_IPSR_GPSR(IP6_13, AVB_RXD3),
+       PINMUX_IPSR_GPSR(IP6_14, VI0_DATA5_VI0_B5),
+       PINMUX_IPSR_GPSR(IP6_14, AVB_RXD4),
+       PINMUX_IPSR_GPSR(IP6_15, VI0_DATA6_VI0_B6),
+       PINMUX_IPSR_GPSR(IP6_15, AVB_RXD5),
+       PINMUX_IPSR_GPSR(IP6_16, VI0_DATA7_VI0_B7),
+       PINMUX_IPSR_GPSR(IP6_16, AVB_RXD6),
+       PINMUX_IPSR_GPSR(IP6_19_17, VI0_CLKENB),
        PINMUX_IPSR_MSEL(IP6_19_17, I2C3_SCL, SEL_I2C03_0),
        PINMUX_IPSR_MSEL(IP6_19_17, SCIFA5_RXD_C, SEL_SCIFA5_2),
        PINMUX_IPSR_MSEL(IP6_19_17, IETX_C, SEL_IEB_2),
-       PINMUX_IPSR_DATA(IP6_19_17, AVB_RXD7),
-       PINMUX_IPSR_DATA(IP6_22_20, VI0_FIELD),
+       PINMUX_IPSR_GPSR(IP6_19_17, AVB_RXD7),
+       PINMUX_IPSR_GPSR(IP6_22_20, VI0_FIELD),
        PINMUX_IPSR_MSEL(IP6_22_20, I2C3_SDA, SEL_I2C03_0),
        PINMUX_IPSR_MSEL(IP6_22_20, SCIFA5_TXD_C, SEL_SCIFA5_2),
        PINMUX_IPSR_MSEL(IP6_22_20, IECLK_C, SEL_IEB_2),
-       PINMUX_IPSR_DATA(IP6_22_20, AVB_RX_ER),
-       PINMUX_IPSR_DATA(IP6_25_23, VI0_HSYNC_N),
+       PINMUX_IPSR_GPSR(IP6_22_20, AVB_RX_ER),
+       PINMUX_IPSR_GPSR(IP6_25_23, VI0_HSYNC_N),
        PINMUX_IPSR_MSEL(IP6_25_23, SCIF0_RXD_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP6_25_23, I2C0_SCL_C, SEL_I2C00_2),
        PINMUX_IPSR_MSEL(IP6_25_23, IERX_C, SEL_IEB_2),
-       PINMUX_IPSR_DATA(IP6_25_23, AVB_COL),
-       PINMUX_IPSR_DATA(IP6_28_26, VI0_VSYNC_N),
+       PINMUX_IPSR_GPSR(IP6_25_23, AVB_COL),
+       PINMUX_IPSR_GPSR(IP6_28_26, VI0_VSYNC_N),
        PINMUX_IPSR_MSEL(IP6_28_26, SCIF0_TXD_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP6_28_26, I2C0_SDA_C, SEL_I2C00_2),
        PINMUX_IPSR_MSEL(IP6_28_26, AUDIO_CLKOUT_B, SEL_ADG_1),
-       PINMUX_IPSR_DATA(IP6_28_26, AVB_TX_EN),
+       PINMUX_IPSR_GPSR(IP6_28_26, AVB_TX_EN),
        PINMUX_IPSR_MSEL(IP6_31_29, ETH_MDIO, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP6_31_29, VI0_G0),
+       PINMUX_IPSR_GPSR(IP6_31_29, VI0_G0),
        PINMUX_IPSR_MSEL(IP6_31_29, MSIOF2_RXD_B, SEL_MSI2_1),
        PINMUX_IPSR_MSEL(IP6_31_29, IIC0_SCL_D, SEL_IIC00_3),
-       PINMUX_IPSR_DATA(IP6_31_29, AVB_TX_CLK),
+       PINMUX_IPSR_GPSR(IP6_31_29, AVB_TX_CLK),
        PINMUX_IPSR_MSEL(IP6_31_29, ADIDATA, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP6_31_29, AD_DI, SEL_ADI_0),
 
        /* IPSR7 */
        PINMUX_IPSR_MSEL(IP7_2_0, ETH_CRS_DV, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_2_0, VI0_G1),
+       PINMUX_IPSR_GPSR(IP7_2_0, VI0_G1),
        PINMUX_IPSR_MSEL(IP7_2_0, MSIOF2_TXD_B, SEL_MSI2_1),
        PINMUX_IPSR_MSEL(IP7_2_0, IIC0_SDA_D, SEL_IIC00_3),
-       PINMUX_IPSR_DATA(IP7_2_0, AVB_TXD0),
+       PINMUX_IPSR_GPSR(IP7_2_0, AVB_TXD0),
        PINMUX_IPSR_MSEL(IP7_2_0, ADICS_SAMP, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP7_2_0, AD_DO, SEL_ADI_0),
        PINMUX_IPSR_MSEL(IP7_5_3, ETH_RX_ER, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_5_3, VI0_G2),
+       PINMUX_IPSR_GPSR(IP7_5_3, VI0_G2),
        PINMUX_IPSR_MSEL(IP7_5_3, MSIOF2_SCK_B, SEL_MSI2_1),
        PINMUX_IPSR_MSEL(IP7_5_3, CAN0_RX_B, SEL_CAN0_1),
-       PINMUX_IPSR_DATA(IP7_5_3, AVB_TXD1),
+       PINMUX_IPSR_GPSR(IP7_5_3, AVB_TXD1),
        PINMUX_IPSR_MSEL(IP7_5_3, ADICLK, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP7_5_3, AD_CLK, SEL_ADI_0),
        PINMUX_IPSR_MSEL(IP7_8_6, ETH_RXD0, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_8_6, VI0_G3),
+       PINMUX_IPSR_GPSR(IP7_8_6, VI0_G3),
        PINMUX_IPSR_MSEL(IP7_8_6, MSIOF2_SYNC_B, SEL_MSI2_1),
        PINMUX_IPSR_MSEL(IP7_8_6, CAN0_TX_B, SEL_CAN0_1),
-       PINMUX_IPSR_DATA(IP7_8_6, AVB_TXD2),
+       PINMUX_IPSR_GPSR(IP7_8_6, AVB_TXD2),
        PINMUX_IPSR_MSEL(IP7_8_6, ADICHS0, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP7_8_6, AD_NCS_N, SEL_ADI_0),
        PINMUX_IPSR_MSEL(IP7_11_9, ETH_RXD1, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_11_9, VI0_G4),
+       PINMUX_IPSR_GPSR(IP7_11_9, VI0_G4),
        PINMUX_IPSR_MSEL(IP7_11_9, MSIOF2_SS1_B, SEL_MSI2_1),
        PINMUX_IPSR_MSEL(IP7_11_9, SCIF4_RXD_D, SEL_SCIF4_3),
-       PINMUX_IPSR_DATA(IP7_11_9, AVB_TXD3),
+       PINMUX_IPSR_GPSR(IP7_11_9, AVB_TXD3),
        PINMUX_IPSR_MSEL(IP7_11_9, ADICHS1, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP7_14_12, ETH_LINK, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_14_12, VI0_G5),
+       PINMUX_IPSR_GPSR(IP7_14_12, VI0_G5),
        PINMUX_IPSR_MSEL(IP7_14_12, MSIOF2_SS2_B, SEL_MSI2_1),
        PINMUX_IPSR_MSEL(IP7_14_12, SCIF4_TXD_D, SEL_SCIF4_3),
-       PINMUX_IPSR_DATA(IP7_14_12, AVB_TXD4),
+       PINMUX_IPSR_GPSR(IP7_14_12, AVB_TXD4),
        PINMUX_IPSR_MSEL(IP7_14_12, ADICHS2, SEL_RAD_0),
        PINMUX_IPSR_MSEL(IP7_17_15, ETH_REFCLK, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_17_15, VI0_G6),
+       PINMUX_IPSR_GPSR(IP7_17_15, VI0_G6),
        PINMUX_IPSR_MSEL(IP7_17_15, SCIF2_SCK_C, SEL_SCIF2_2),
-       PINMUX_IPSR_DATA(IP7_17_15, AVB_TXD5),
+       PINMUX_IPSR_GPSR(IP7_17_15, AVB_TXD5),
        PINMUX_IPSR_MSEL(IP7_17_15, SSI_SCK5_B, SEL_SSI5_1),
        PINMUX_IPSR_MSEL(IP7_20_18, ETH_TXD1, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_20_18, VI0_G7),
+       PINMUX_IPSR_GPSR(IP7_20_18, VI0_G7),
        PINMUX_IPSR_MSEL(IP7_20_18, SCIF2_RXD_C, SEL_SCIF2_2),
        PINMUX_IPSR_MSEL(IP7_20_18, IIC1_SCL_D, SEL_IIC01_3),
-       PINMUX_IPSR_DATA(IP7_20_18, AVB_TXD6),
+       PINMUX_IPSR_GPSR(IP7_20_18, AVB_TXD6),
        PINMUX_IPSR_MSEL(IP7_20_18, SSI_WS5_B, SEL_SSI5_1),
        PINMUX_IPSR_MSEL(IP7_23_21, ETH_TX_EN, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_23_21, VI0_R0),
+       PINMUX_IPSR_GPSR(IP7_23_21, VI0_R0),
        PINMUX_IPSR_MSEL(IP7_23_21, SCIF2_TXD_C, SEL_SCIF2_2),
        PINMUX_IPSR_MSEL(IP7_23_21, IIC1_SDA_D, SEL_IIC01_3),
-       PINMUX_IPSR_DATA(IP7_23_21, AVB_TXD7),
+       PINMUX_IPSR_GPSR(IP7_23_21, AVB_TXD7),
        PINMUX_IPSR_MSEL(IP7_23_21, SSI_SDATA5_B, SEL_SSI5_1),
        PINMUX_IPSR_MSEL(IP7_26_24, ETH_MAGIC, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_26_24, VI0_R1),
+       PINMUX_IPSR_GPSR(IP7_26_24, VI0_R1),
        PINMUX_IPSR_MSEL(IP7_26_24, SCIF3_SCK_B, SEL_SCIF3_1),
-       PINMUX_IPSR_DATA(IP7_26_24, AVB_TX_ER),
+       PINMUX_IPSR_GPSR(IP7_26_24, AVB_TX_ER),
        PINMUX_IPSR_MSEL(IP7_26_24, SSI_SCK6_B, SEL_SSI6_1),
        PINMUX_IPSR_MSEL(IP7_29_27, ETH_TXD0, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP7_29_27, VI0_R2),
+       PINMUX_IPSR_GPSR(IP7_29_27, VI0_R2),
        PINMUX_IPSR_MSEL(IP7_29_27, SCIF3_RXD_B, SEL_SCIF3_1),
        PINMUX_IPSR_MSEL(IP7_29_27, I2C4_SCL_E, SEL_I2C04_4),
-       PINMUX_IPSR_DATA(IP7_29_27, AVB_GTX_CLK),
+       PINMUX_IPSR_GPSR(IP7_29_27, AVB_GTX_CLK),
        PINMUX_IPSR_MSEL(IP7_29_27, SSI_WS6_B, SEL_SSI6_1),
-       PINMUX_IPSR_DATA(IP7_31, DREQ0_N),
-       PINMUX_IPSR_DATA(IP7_31, SCIFB1_RXD),
+       PINMUX_IPSR_GPSR(IP7_31, DREQ0_N),
+       PINMUX_IPSR_GPSR(IP7_31, SCIFB1_RXD),
 
        /* IPSR8 */
        PINMUX_IPSR_MSEL(IP8_2_0, ETH_MDC, SEL_ETH_0),
-       PINMUX_IPSR_DATA(IP8_2_0, VI0_R3),
+       PINMUX_IPSR_GPSR(IP8_2_0, VI0_R3),
        PINMUX_IPSR_MSEL(IP8_2_0, SCIF3_TXD_B, SEL_SCIF3_1),
        PINMUX_IPSR_MSEL(IP8_2_0, I2C4_SDA_E, SEL_I2C04_4),
-       PINMUX_IPSR_DATA(IP8_2_0, AVB_MDC),
+       PINMUX_IPSR_GPSR(IP8_2_0, AVB_MDC),
        PINMUX_IPSR_MSEL(IP8_2_0, SSI_SDATA6_B, SEL_SSI6_1),
        PINMUX_IPSR_MSEL(IP8_5_3, HSCIF0_HRX, SEL_HSCIF0_0),
-       PINMUX_IPSR_DATA(IP8_5_3, VI0_R4),
+       PINMUX_IPSR_GPSR(IP8_5_3, VI0_R4),
        PINMUX_IPSR_MSEL(IP8_5_3, I2C1_SCL_C, SEL_I2C01_2),
        PINMUX_IPSR_MSEL(IP8_5_3, AUDIO_CLKA_B, SEL_ADG_1),
-       PINMUX_IPSR_DATA(IP8_5_3, AVB_MDIO),
+       PINMUX_IPSR_GPSR(IP8_5_3, AVB_MDIO),
        PINMUX_IPSR_MSEL(IP8_5_3, SSI_SCK78_B, SEL_SSI7_1),
        PINMUX_IPSR_MSEL(IP8_8_6, HSCIF0_HTX, SEL_HSCIF0_0),
-       PINMUX_IPSR_DATA(IP8_8_6, VI0_R5),
+       PINMUX_IPSR_GPSR(IP8_8_6, VI0_R5),
        PINMUX_IPSR_MSEL(IP8_8_6, I2C1_SDA_C, SEL_I2C01_2),
        PINMUX_IPSR_MSEL(IP8_8_6, AUDIO_CLKB_B, SEL_ADG_1),
-       PINMUX_IPSR_DATA(IP8_5_3, AVB_LINK),
+       PINMUX_IPSR_GPSR(IP8_5_3, AVB_LINK),
        PINMUX_IPSR_MSEL(IP8_8_6, SSI_WS78_B, SEL_SSI7_1),
-       PINMUX_IPSR_DATA(IP8_11_9, HSCIF0_HCTS_N),
-       PINMUX_IPSR_DATA(IP8_11_9, VI0_R6),
+       PINMUX_IPSR_GPSR(IP8_11_9, HSCIF0_HCTS_N),
+       PINMUX_IPSR_GPSR(IP8_11_9, VI0_R6),
        PINMUX_IPSR_MSEL(IP8_11_9, SCIF0_RXD_D, SEL_SCIF0_3),
        PINMUX_IPSR_MSEL(IP8_11_9, I2C0_SCL_E, SEL_I2C00_4),
-       PINMUX_IPSR_DATA(IP8_11_9, AVB_MAGIC),
+       PINMUX_IPSR_GPSR(IP8_11_9, AVB_MAGIC),
        PINMUX_IPSR_MSEL(IP8_11_9, SSI_SDATA7_B, SEL_SSI7_1),
-       PINMUX_IPSR_DATA(IP8_14_12, HSCIF0_HRTS_N),
-       PINMUX_IPSR_DATA(IP8_14_12, VI0_R7),
+       PINMUX_IPSR_GPSR(IP8_14_12, HSCIF0_HRTS_N),
+       PINMUX_IPSR_GPSR(IP8_14_12, VI0_R7),
        PINMUX_IPSR_MSEL(IP8_14_12, SCIF0_TXD_D, SEL_SCIF0_3),
        PINMUX_IPSR_MSEL(IP8_14_12, I2C0_SDA_E, SEL_I2C00_4),
-       PINMUX_IPSR_DATA(IP8_14_12, AVB_PHY_INT),
+       PINMUX_IPSR_GPSR(IP8_14_12, AVB_PHY_INT),
        PINMUX_IPSR_MSEL(IP8_14_12, SSI_SDATA8_B, SEL_SSI8_1),
        PINMUX_IPSR_MSEL(IP8_16_15, HSCIF0_HSCK, SEL_HSCIF0_0),
        PINMUX_IPSR_MSEL(IP8_16_15, SCIF_CLK_B, SEL_SCIF0_1),
-       PINMUX_IPSR_DATA(IP8_16_15, AVB_CRS),
+       PINMUX_IPSR_GPSR(IP8_16_15, AVB_CRS),
        PINMUX_IPSR_MSEL(IP8_16_15, AUDIO_CLKC_B, SEL_ADG_1),
        PINMUX_IPSR_MSEL(IP8_19_17, I2C0_SCL, SEL_I2C00_0),
        PINMUX_IPSR_MSEL(IP8_19_17, SCIF0_RXD_C, SEL_SCIF0_2),
-       PINMUX_IPSR_DATA(IP8_19_17, PWM5),
+       PINMUX_IPSR_GPSR(IP8_19_17, PWM5),
        PINMUX_IPSR_MSEL(IP8_19_17, TCLK1_B, SEL_TMU_1),
-       PINMUX_IPSR_DATA(IP8_19_17, AVB_GTXREFCLK),
+       PINMUX_IPSR_GPSR(IP8_19_17, AVB_GTXREFCLK),
        PINMUX_IPSR_MSEL(IP8_19_17, CAN1_RX_D, SEL_CAN1_3),
-       PINMUX_IPSR_DATA(IP8_19_17, TPUTO0_B),
+       PINMUX_IPSR_GPSR(IP8_19_17, TPUTO0_B),
        PINMUX_IPSR_MSEL(IP8_22_20, I2C0_SDA, SEL_I2C00_0),
        PINMUX_IPSR_MSEL(IP8_22_20, SCIF0_TXD_C, SEL_SCIF0_2),
-       PINMUX_IPSR_DATA(IP8_22_20, TPUTO0),
+       PINMUX_IPSR_GPSR(IP8_22_20, TPUTO0),
        PINMUX_IPSR_MSEL(IP8_22_20, CAN_CLK, SEL_CAN_0),
-       PINMUX_IPSR_DATA(IP8_22_20, DVC_MUTE),
+       PINMUX_IPSR_GPSR(IP8_22_20, DVC_MUTE),
        PINMUX_IPSR_MSEL(IP8_22_20, CAN1_TX_D, SEL_CAN1_3),
        PINMUX_IPSR_MSEL(IP8_25_23, I2C1_SCL, SEL_I2C01_0),
        PINMUX_IPSR_MSEL(IP8_25_23, SCIF4_RXD, SEL_SCIF4_0),
-       PINMUX_IPSR_DATA(IP8_25_23, PWM5_B),
-       PINMUX_IPSR_DATA(IP8_25_23, DU1_DR0),
+       PINMUX_IPSR_GPSR(IP8_25_23, PWM5_B),
+       PINMUX_IPSR_GPSR(IP8_25_23, DU1_DR0),
        PINMUX_IPSR_MSEL(IP8_25_23, RIF1_SYNC_B, SEL_DR2_1),
        PINMUX_IPSR_MSEL(IP8_25_23, TS_SDATA_D, SEL_TSIF0_3),
-       PINMUX_IPSR_DATA(IP8_25_23, TPUTO1_B),
+       PINMUX_IPSR_GPSR(IP8_25_23, TPUTO1_B),
        PINMUX_IPSR_MSEL(IP8_28_26, I2C1_SDA, SEL_I2C01_0),
        PINMUX_IPSR_MSEL(IP8_28_26, SCIF4_TXD, SEL_SCIF4_0),
-       PINMUX_IPSR_DATA(IP8_28_26, IRQ5),
-       PINMUX_IPSR_DATA(IP8_28_26, DU1_DR1),
+       PINMUX_IPSR_GPSR(IP8_28_26, IRQ5),
+       PINMUX_IPSR_GPSR(IP8_28_26, DU1_DR1),
        PINMUX_IPSR_MSEL(IP8_28_26, RIF1_CLK_B, SEL_DR2_1),
        PINMUX_IPSR_MSEL(IP8_28_26, TS_SCK_D, SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP8_28_26, BPFCLK_C, SEL_DARC_2),
-       PINMUX_IPSR_DATA(IP8_31_29, MSIOF0_RXD),
+       PINMUX_IPSR_GPSR(IP8_31_29, MSIOF0_RXD),
        PINMUX_IPSR_MSEL(IP8_31_29, SCIF5_RXD, SEL_SCIF5_0),
        PINMUX_IPSR_MSEL(IP8_31_29, I2C2_SCL_C, SEL_I2C02_2),
-       PINMUX_IPSR_DATA(IP8_31_29, DU1_DR2),
+       PINMUX_IPSR_GPSR(IP8_31_29, DU1_DR2),
        PINMUX_IPSR_MSEL(IP8_31_29, RIF1_D0_B, SEL_DR2_1),
        PINMUX_IPSR_MSEL(IP8_31_29, TS_SDEN_D, SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP8_31_29, FMCLK_C, SEL_DARC_2),
        PINMUX_IPSR_MSEL(IP8_31_29, RDS_CLK, SEL_RDS_0),
 
        /* IPSR9 */
-       PINMUX_IPSR_DATA(IP9_2_0, MSIOF0_TXD),
+       PINMUX_IPSR_GPSR(IP9_2_0, MSIOF0_TXD),
        PINMUX_IPSR_MSEL(IP9_2_0, SCIF5_TXD, SEL_SCIF5_0),
        PINMUX_IPSR_MSEL(IP9_2_0, I2C2_SDA_C, SEL_I2C02_2),
-       PINMUX_IPSR_DATA(IP9_2_0, DU1_DR3),
+       PINMUX_IPSR_GPSR(IP9_2_0, DU1_DR3),
        PINMUX_IPSR_MSEL(IP9_2_0, RIF1_D1_B, SEL_DR3_1),
        PINMUX_IPSR_MSEL(IP9_2_0, TS_SPSYNC_D, SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP9_2_0, FMIN_C, SEL_DARC_2),
        PINMUX_IPSR_MSEL(IP9_2_0, RDS_DATA, SEL_RDS_0),
-       PINMUX_IPSR_DATA(IP9_5_3, MSIOF0_SCK),
-       PINMUX_IPSR_DATA(IP9_5_3, IRQ0),
+       PINMUX_IPSR_GPSR(IP9_5_3, MSIOF0_SCK),
+       PINMUX_IPSR_GPSR(IP9_5_3, IRQ0),
        PINMUX_IPSR_MSEL(IP9_5_3, TS_SDATA, SEL_TSIF0_0),
-       PINMUX_IPSR_DATA(IP9_5_3, DU1_DR4),
+       PINMUX_IPSR_GPSR(IP9_5_3, DU1_DR4),
        PINMUX_IPSR_MSEL(IP9_5_3, RIF1_SYNC, SEL_DR2_0),
-       PINMUX_IPSR_DATA(IP9_5_3, TPUTO1_C),
-       PINMUX_IPSR_DATA(IP9_8_6, MSIOF0_SYNC),
-       PINMUX_IPSR_DATA(IP9_8_6, PWM1),
+       PINMUX_IPSR_GPSR(IP9_5_3, TPUTO1_C),
+       PINMUX_IPSR_GPSR(IP9_8_6, MSIOF0_SYNC),
+       PINMUX_IPSR_GPSR(IP9_8_6, PWM1),
        PINMUX_IPSR_MSEL(IP9_8_6, TS_SCK, SEL_TSIF0_0),
-       PINMUX_IPSR_DATA(IP9_8_6, DU1_DR5),
+       PINMUX_IPSR_GPSR(IP9_8_6, DU1_DR5),
        PINMUX_IPSR_MSEL(IP9_8_6, RIF1_CLK, SEL_DR2_0),
        PINMUX_IPSR_MSEL(IP9_8_6, BPFCLK_B, SEL_DARC_1),
-       PINMUX_IPSR_DATA(IP9_11_9, MSIOF0_SS1),
+       PINMUX_IPSR_GPSR(IP9_11_9, MSIOF0_SS1),
        PINMUX_IPSR_MSEL(IP9_11_9, SCIFA0_RXD, SEL_SCIFA0_0),
        PINMUX_IPSR_MSEL(IP9_11_9, TS_SDEN, SEL_TSIF0_0),
-       PINMUX_IPSR_DATA(IP9_11_9, DU1_DR6),
+       PINMUX_IPSR_GPSR(IP9_11_9, DU1_DR6),
        PINMUX_IPSR_MSEL(IP9_11_9, RIF1_D0, SEL_DR2_0),
        PINMUX_IPSR_MSEL(IP9_11_9, FMCLK_B, SEL_DARC_1),
        PINMUX_IPSR_MSEL(IP9_11_9, RDS_CLK_B, SEL_RDS_1),
-       PINMUX_IPSR_DATA(IP9_14_12, MSIOF0_SS2),
+       PINMUX_IPSR_GPSR(IP9_14_12, MSIOF0_SS2),
        PINMUX_IPSR_MSEL(IP9_14_12, SCIFA0_TXD, SEL_SCIFA0_0),
        PINMUX_IPSR_MSEL(IP9_14_12, TS_SPSYNC, SEL_TSIF0_0),
-       PINMUX_IPSR_DATA(IP9_14_12, DU1_DR7),
+       PINMUX_IPSR_GPSR(IP9_14_12, DU1_DR7),
        PINMUX_IPSR_MSEL(IP9_14_12, RIF1_D1, SEL_DR3_0),
        PINMUX_IPSR_MSEL(IP9_14_12, FMIN_B, SEL_DARC_1),
        PINMUX_IPSR_MSEL(IP9_14_12, RDS_DATA_B, SEL_RDS_1),
        PINMUX_IPSR_MSEL(IP9_16_15, HSCIF1_HRX, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP9_16_15, I2C4_SCL, SEL_I2C04_0),
-       PINMUX_IPSR_DATA(IP9_16_15, PWM6),
-       PINMUX_IPSR_DATA(IP9_16_15, DU1_DG0),
+       PINMUX_IPSR_GPSR(IP9_16_15, PWM6),
+       PINMUX_IPSR_GPSR(IP9_16_15, DU1_DG0),
        PINMUX_IPSR_MSEL(IP9_18_17, HSCIF1_HTX, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP9_18_17, I2C4_SDA, SEL_I2C04_0),
-       PINMUX_IPSR_DATA(IP9_18_17, TPUTO1),
-       PINMUX_IPSR_DATA(IP9_18_17, DU1_DG1),
-       PINMUX_IPSR_DATA(IP9_21_19, HSCIF1_HSCK),
-       PINMUX_IPSR_DATA(IP9_21_19, PWM2),
+       PINMUX_IPSR_GPSR(IP9_18_17, TPUTO1),
+       PINMUX_IPSR_GPSR(IP9_18_17, DU1_DG1),
+       PINMUX_IPSR_GPSR(IP9_21_19, HSCIF1_HSCK),
+       PINMUX_IPSR_GPSR(IP9_21_19, PWM2),
        PINMUX_IPSR_MSEL(IP9_21_19, IETX, SEL_IEB_0),
-       PINMUX_IPSR_DATA(IP9_21_19, DU1_DG2),
+       PINMUX_IPSR_GPSR(IP9_21_19, DU1_DG2),
        PINMUX_IPSR_MSEL(IP9_21_19, REMOCON_B, SEL_RCN_1),
        PINMUX_IPSR_MSEL(IP9_21_19, SPEEDIN_B, SEL_RSP_1),
        PINMUX_IPSR_MSEL(IP9_21_19, VSP_B, SEL_SPDM_1),
        PINMUX_IPSR_MSEL(IP9_24_22, HSCIF1_HCTS_N, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP9_24_22, SCIFA4_RXD, SEL_SCIFA4_0),
        PINMUX_IPSR_MSEL(IP9_24_22, IECLK, SEL_IEB_0),
-       PINMUX_IPSR_DATA(IP9_24_22, DU1_DG3),
+       PINMUX_IPSR_GPSR(IP9_24_22, DU1_DG3),
        PINMUX_IPSR_MSEL(IP9_24_22, SSI_SCK1_B, SEL_SSI1_1),
-       PINMUX_IPSR_DATA(IP9_24_22, CAN_DEBUG_HW_TRIGGER),
-       PINMUX_IPSR_DATA(IP9_24_22, CC50_STATE32),
+       PINMUX_IPSR_GPSR(IP9_24_22, CAN_DEBUG_HW_TRIGGER),
+       PINMUX_IPSR_GPSR(IP9_24_22, CC50_STATE32),
        PINMUX_IPSR_MSEL(IP9_27_25, HSCIF1_HRTS_N, SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP9_27_25, SCIFA4_TXD, SEL_SCIFA4_0),
        PINMUX_IPSR_MSEL(IP9_27_25, IERX, SEL_IEB_0),
-       PINMUX_IPSR_DATA(IP9_27_25, DU1_DG4),
+       PINMUX_IPSR_GPSR(IP9_27_25, DU1_DG4),
        PINMUX_IPSR_MSEL(IP9_27_25, SSI_WS1_B, SEL_SSI1_1),
-       PINMUX_IPSR_DATA(IP9_27_25, CAN_STEP0),
-       PINMUX_IPSR_DATA(IP9_27_25, CC50_STATE33),
+       PINMUX_IPSR_GPSR(IP9_27_25, CAN_STEP0),
+       PINMUX_IPSR_GPSR(IP9_27_25, CC50_STATE33),
        PINMUX_IPSR_MSEL(IP9_30_28, SCIF1_SCK, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP9_30_28, PWM3),
+       PINMUX_IPSR_GPSR(IP9_30_28, PWM3),
        PINMUX_IPSR_MSEL(IP9_30_28, TCLK2, SEL_TMU_0),
-       PINMUX_IPSR_DATA(IP9_30_28, DU1_DG5),
+       PINMUX_IPSR_GPSR(IP9_30_28, DU1_DG5),
        PINMUX_IPSR_MSEL(IP9_30_28, SSI_SDATA1_B, SEL_SSI1_1),
-       PINMUX_IPSR_DATA(IP9_30_28, CAN_TXCLK),
-       PINMUX_IPSR_DATA(IP9_30_28, CC50_STATE34),
+       PINMUX_IPSR_GPSR(IP9_30_28, CAN_TXCLK),
+       PINMUX_IPSR_GPSR(IP9_30_28, CC50_STATE34),
 
        /* IPSR10 */
        PINMUX_IPSR_MSEL(IP10_2_0, SCIF1_RXD, SEL_SCIF1_0),
        PINMUX_IPSR_MSEL(IP10_2_0, IIC0_SCL, SEL_IIC00_0),
-       PINMUX_IPSR_DATA(IP10_2_0, DU1_DG6),
+       PINMUX_IPSR_GPSR(IP10_2_0, DU1_DG6),
        PINMUX_IPSR_MSEL(IP10_2_0, SSI_SCK2_B, SEL_SSI2_1),
-       PINMUX_IPSR_DATA(IP10_2_0, CAN_DEBUGOUT0),
-       PINMUX_IPSR_DATA(IP10_2_0, CC50_STATE35),
+       PINMUX_IPSR_GPSR(IP10_2_0, CAN_DEBUGOUT0),
+       PINMUX_IPSR_GPSR(IP10_2_0, CC50_STATE35),
        PINMUX_IPSR_MSEL(IP10_5_3, SCIF1_TXD, SEL_SCIF1_0),
        PINMUX_IPSR_MSEL(IP10_5_3, IIC0_SDA, SEL_IIC00_0),
-       PINMUX_IPSR_DATA(IP10_5_3, DU1_DG7),
+       PINMUX_IPSR_GPSR(IP10_5_3, DU1_DG7),
        PINMUX_IPSR_MSEL(IP10_5_3, SSI_WS2_B, SEL_SSI2_1),
-       PINMUX_IPSR_DATA(IP10_5_3, CAN_DEBUGOUT1),
-       PINMUX_IPSR_DATA(IP10_5_3, CC50_STATE36),
+       PINMUX_IPSR_GPSR(IP10_5_3, CAN_DEBUGOUT1),
+       PINMUX_IPSR_GPSR(IP10_5_3, CC50_STATE36),
        PINMUX_IPSR_MSEL(IP10_8_6, SCIF2_RXD, SEL_SCIF2_0),
        PINMUX_IPSR_MSEL(IP10_8_6, IIC1_SCL, SEL_IIC01_0),
-       PINMUX_IPSR_DATA(IP10_8_6, DU1_DB0),
+       PINMUX_IPSR_GPSR(IP10_8_6, DU1_DB0),
        PINMUX_IPSR_MSEL(IP10_8_6, SSI_SDATA2_B, SEL_SSI2_1),
-       PINMUX_IPSR_DATA(IP10_8_6, USB0_EXTLP),
-       PINMUX_IPSR_DATA(IP10_8_6, CAN_DEBUGOUT2),
-       PINMUX_IPSR_DATA(IP10_8_6, CC50_STATE37),
+       PINMUX_IPSR_GPSR(IP10_8_6, USB0_EXTLP),
+       PINMUX_IPSR_GPSR(IP10_8_6, CAN_DEBUGOUT2),
+       PINMUX_IPSR_GPSR(IP10_8_6, CC50_STATE37),
        PINMUX_IPSR_MSEL(IP10_11_9, SCIF2_TXD, SEL_SCIF2_0),
        PINMUX_IPSR_MSEL(IP10_11_9, IIC1_SDA, SEL_IIC01_0),
-       PINMUX_IPSR_DATA(IP10_11_9, DU1_DB1),
+       PINMUX_IPSR_GPSR(IP10_11_9, DU1_DB1),
        PINMUX_IPSR_MSEL(IP10_11_9, SSI_SCK9_B, SEL_SSI9_1),
-       PINMUX_IPSR_DATA(IP10_11_9, USB0_OVC1),
-       PINMUX_IPSR_DATA(IP10_11_9, CAN_DEBUGOUT3),
-       PINMUX_IPSR_DATA(IP10_11_9, CC50_STATE38),
+       PINMUX_IPSR_GPSR(IP10_11_9, USB0_OVC1),
+       PINMUX_IPSR_GPSR(IP10_11_9, CAN_DEBUGOUT3),
+       PINMUX_IPSR_GPSR(IP10_11_9, CC50_STATE38),
        PINMUX_IPSR_MSEL(IP10_14_12, SCIF2_SCK, SEL_SCIF2_0),
-       PINMUX_IPSR_DATA(IP10_14_12, IRQ1),
-       PINMUX_IPSR_DATA(IP10_14_12, DU1_DB2),
+       PINMUX_IPSR_GPSR(IP10_14_12, IRQ1),
+       PINMUX_IPSR_GPSR(IP10_14_12, DU1_DB2),
        PINMUX_IPSR_MSEL(IP10_14_12, SSI_WS9_B, SEL_SSI9_1),
-       PINMUX_IPSR_DATA(IP10_14_12, USB0_IDIN),
-       PINMUX_IPSR_DATA(IP10_14_12, CAN_DEBUGOUT4),
-       PINMUX_IPSR_DATA(IP10_14_12, CC50_STATE39),
+       PINMUX_IPSR_GPSR(IP10_14_12, USB0_IDIN),
+       PINMUX_IPSR_GPSR(IP10_14_12, CAN_DEBUGOUT4),
+       PINMUX_IPSR_GPSR(IP10_14_12, CC50_STATE39),
        PINMUX_IPSR_MSEL(IP10_17_15, SCIF3_SCK, SEL_SCIF3_0),
-       PINMUX_IPSR_DATA(IP10_17_15, IRQ2),
+       PINMUX_IPSR_GPSR(IP10_17_15, IRQ2),
        PINMUX_IPSR_MSEL(IP10_17_15, BPFCLK_D, SEL_DARC_3),
-       PINMUX_IPSR_DATA(IP10_17_15, DU1_DB3),
+       PINMUX_IPSR_GPSR(IP10_17_15, DU1_DB3),
        PINMUX_IPSR_MSEL(IP10_17_15, SSI_SDATA9_B, SEL_SSI9_1),
-       PINMUX_IPSR_DATA(IP10_17_15, TANS2),
-       PINMUX_IPSR_DATA(IP10_17_15, CAN_DEBUGOUT5),
-       PINMUX_IPSR_DATA(IP10_17_15, CC50_OSCOUT),
+       PINMUX_IPSR_GPSR(IP10_17_15, TANS2),
+       PINMUX_IPSR_GPSR(IP10_17_15, CAN_DEBUGOUT5),
+       PINMUX_IPSR_GPSR(IP10_17_15, CC50_OSCOUT),
        PINMUX_IPSR_MSEL(IP10_20_18, SCIF3_RXD, SEL_SCIF3_0),
        PINMUX_IPSR_MSEL(IP10_20_18, I2C1_SCL_E, SEL_I2C01_4),
        PINMUX_IPSR_MSEL(IP10_20_18, FMCLK_D, SEL_DARC_3),
-       PINMUX_IPSR_DATA(IP10_20_18, DU1_DB4),
+       PINMUX_IPSR_GPSR(IP10_20_18, DU1_DB4),
        PINMUX_IPSR_MSEL(IP10_20_18, AUDIO_CLKA_C, SEL_ADG_2),
        PINMUX_IPSR_MSEL(IP10_20_18, SSI_SCK4_B, SEL_SSI4_1),
-       PINMUX_IPSR_DATA(IP10_20_18, CAN_DEBUGOUT6),
+       PINMUX_IPSR_GPSR(IP10_20_18, CAN_DEBUGOUT6),
        PINMUX_IPSR_MSEL(IP10_20_18, RDS_CLK_C, SEL_RDS_2),
        PINMUX_IPSR_MSEL(IP10_23_21, SCIF3_TXD, SEL_SCIF3_0),
        PINMUX_IPSR_MSEL(IP10_23_21, I2C1_SDA_E, SEL_I2C01_4),
        PINMUX_IPSR_MSEL(IP10_23_21, FMIN_D, SEL_DARC_3),
-       PINMUX_IPSR_DATA(IP10_23_21, DU1_DB5),
+       PINMUX_IPSR_GPSR(IP10_23_21, DU1_DB5),
        PINMUX_IPSR_MSEL(IP10_23_21, AUDIO_CLKB_C, SEL_ADG_2),
        PINMUX_IPSR_MSEL(IP10_23_21, SSI_WS4_B, SEL_SSI4_1),
-       PINMUX_IPSR_DATA(IP10_23_21, CAN_DEBUGOUT7),
+       PINMUX_IPSR_GPSR(IP10_23_21, CAN_DEBUGOUT7),
        PINMUX_IPSR_MSEL(IP10_23_21, RDS_DATA_C, SEL_RDS_2),
        PINMUX_IPSR_MSEL(IP10_26_24, I2C2_SCL, SEL_I2C02_0),
        PINMUX_IPSR_MSEL(IP10_26_24, SCIFA5_RXD, SEL_SCIFA5_0),
-       PINMUX_IPSR_DATA(IP10_26_24, DU1_DB6),
+       PINMUX_IPSR_GPSR(IP10_26_24, DU1_DB6),
        PINMUX_IPSR_MSEL(IP10_26_24, AUDIO_CLKC_C, SEL_ADG_2),
        PINMUX_IPSR_MSEL(IP10_26_24, SSI_SDATA4_B, SEL_SSI4_1),
-       PINMUX_IPSR_DATA(IP10_26_24, CAN_DEBUGOUT8),
+       PINMUX_IPSR_GPSR(IP10_26_24, CAN_DEBUGOUT8),
        PINMUX_IPSR_MSEL(IP10_29_27, I2C2_SDA, SEL_I2C02_0),
        PINMUX_IPSR_MSEL(IP10_29_27, SCIFA5_TXD, SEL_SCIFA5_0),
-       PINMUX_IPSR_DATA(IP10_29_27, DU1_DB7),
+       PINMUX_IPSR_GPSR(IP10_29_27, DU1_DB7),
        PINMUX_IPSR_MSEL(IP10_29_27, AUDIO_CLKOUT_C, SEL_ADG_2),
-       PINMUX_IPSR_DATA(IP10_29_27, CAN_DEBUGOUT9),
+       PINMUX_IPSR_GPSR(IP10_29_27, CAN_DEBUGOUT9),
        PINMUX_IPSR_MSEL(IP10_31_30, SSI_SCK5, SEL_SSI5_0),
        PINMUX_IPSR_MSEL(IP10_31_30, SCIFA3_SCK, SEL_SCIFA3_0),
-       PINMUX_IPSR_DATA(IP10_31_30, DU1_DOTCLKIN),
-       PINMUX_IPSR_DATA(IP10_31_30, CAN_DEBUGOUT10),
+       PINMUX_IPSR_GPSR(IP10_31_30, DU1_DOTCLKIN),
+       PINMUX_IPSR_GPSR(IP10_31_30, CAN_DEBUGOUT10),
 
        /* IPSR11 */
        PINMUX_IPSR_MSEL(IP11_2_0, SSI_WS5, SEL_SSI5_0),
        PINMUX_IPSR_MSEL(IP11_2_0, SCIFA3_RXD, SEL_SCIFA3_0),
        PINMUX_IPSR_MSEL(IP11_2_0, I2C3_SCL_C, SEL_I2C03_2),
-       PINMUX_IPSR_DATA(IP11_2_0, DU1_DOTCLKOUT0),
-       PINMUX_IPSR_DATA(IP11_2_0, CAN_DEBUGOUT11),
+       PINMUX_IPSR_GPSR(IP11_2_0, DU1_DOTCLKOUT0),
+       PINMUX_IPSR_GPSR(IP11_2_0, CAN_DEBUGOUT11),
        PINMUX_IPSR_MSEL(IP11_5_3, SSI_SDATA5, SEL_SSI5_0),
        PINMUX_IPSR_MSEL(IP11_5_3, SCIFA3_TXD, SEL_SCIFA3_0),
        PINMUX_IPSR_MSEL(IP11_5_3, I2C3_SDA_C, SEL_I2C03_2),
-       PINMUX_IPSR_DATA(IP11_5_3, DU1_DOTCLKOUT1),
-       PINMUX_IPSR_DATA(IP11_5_3, CAN_DEBUGOUT12),
+       PINMUX_IPSR_GPSR(IP11_5_3, DU1_DOTCLKOUT1),
+       PINMUX_IPSR_GPSR(IP11_5_3, CAN_DEBUGOUT12),
        PINMUX_IPSR_MSEL(IP11_7_6, SSI_SCK6, SEL_SSI6_0),
        PINMUX_IPSR_MSEL(IP11_7_6, SCIFA1_SCK_B, SEL_SCIFA1_1),
-       PINMUX_IPSR_DATA(IP11_7_6, DU1_EXHSYNC_DU1_HSYNC),
-       PINMUX_IPSR_DATA(IP11_7_6, CAN_DEBUGOUT13),
+       PINMUX_IPSR_GPSR(IP11_7_6, DU1_EXHSYNC_DU1_HSYNC),
+       PINMUX_IPSR_GPSR(IP11_7_6, CAN_DEBUGOUT13),
        PINMUX_IPSR_MSEL(IP11_10_8, SSI_WS6, SEL_SSI6_0),
        PINMUX_IPSR_MSEL(IP11_10_8, SCIFA1_RXD_B, SEL_SCIFA1_1),
        PINMUX_IPSR_MSEL(IP11_10_8, I2C4_SCL_C, SEL_I2C04_2),
-       PINMUX_IPSR_DATA(IP11_10_8, DU1_EXVSYNC_DU1_VSYNC),
-       PINMUX_IPSR_DATA(IP11_10_8, CAN_DEBUGOUT14),
+       PINMUX_IPSR_GPSR(IP11_10_8, DU1_EXVSYNC_DU1_VSYNC),
+       PINMUX_IPSR_GPSR(IP11_10_8, CAN_DEBUGOUT14),
        PINMUX_IPSR_MSEL(IP11_13_11, SSI_SDATA6, SEL_SSI6_0),
        PINMUX_IPSR_MSEL(IP11_13_11, SCIFA1_TXD_B, SEL_SCIFA1_1),
        PINMUX_IPSR_MSEL(IP11_13_11, I2C4_SDA_C, SEL_I2C04_2),
-       PINMUX_IPSR_DATA(IP11_13_11, DU1_EXODDF_DU1_ODDF_DISP_CDE),
-       PINMUX_IPSR_DATA(IP11_13_11, CAN_DEBUGOUT15),
+       PINMUX_IPSR_GPSR(IP11_13_11, DU1_EXODDF_DU1_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP11_13_11, CAN_DEBUGOUT15),
        PINMUX_IPSR_MSEL(IP11_15_14, SSI_SCK78, SEL_SSI7_0),
        PINMUX_IPSR_MSEL(IP11_15_14, SCIFA2_SCK_B, SEL_SCIFA2_1),
        PINMUX_IPSR_MSEL(IP11_15_14, IIC0_SDA_C, SEL_IIC00_2),
-       PINMUX_IPSR_DATA(IP11_15_14, DU1_DISP),
+       PINMUX_IPSR_GPSR(IP11_15_14, DU1_DISP),
        PINMUX_IPSR_MSEL(IP11_17_16, SSI_WS78, SEL_SSI7_0),
        PINMUX_IPSR_MSEL(IP11_17_16, SCIFA2_RXD_B, SEL_SCIFA2_1),
        PINMUX_IPSR_MSEL(IP11_17_16, IIC0_SCL_C, SEL_IIC00_2),
-       PINMUX_IPSR_DATA(IP11_17_16, DU1_CDE),
+       PINMUX_IPSR_GPSR(IP11_17_16, DU1_CDE),
        PINMUX_IPSR_MSEL(IP11_20_18, SSI_SDATA7, SEL_SSI7_0),
        PINMUX_IPSR_MSEL(IP11_20_18, SCIFA2_TXD_B, SEL_SCIFA2_1),
-       PINMUX_IPSR_DATA(IP11_20_18, IRQ8),
+       PINMUX_IPSR_GPSR(IP11_20_18, IRQ8),
        PINMUX_IPSR_MSEL(IP11_20_18, AUDIO_CLKA_D, SEL_ADG_3),
        PINMUX_IPSR_MSEL(IP11_20_18, CAN_CLK_D, SEL_CAN_3),
-       PINMUX_IPSR_DATA(IP11_20_18, PCMOE_N),
-       PINMUX_IPSR_DATA(IP11_23_21, SSI_SCK0129),
+       PINMUX_IPSR_GPSR(IP11_20_18, PCMOE_N),
+       PINMUX_IPSR_GPSR(IP11_23_21, SSI_SCK0129),
        PINMUX_IPSR_MSEL(IP11_23_21, MSIOF1_RXD_B, SEL_MSI1_1),
        PINMUX_IPSR_MSEL(IP11_23_21, SCIF5_RXD_D, SEL_SCIF5_3),
        PINMUX_IPSR_MSEL(IP11_23_21, ADIDATA_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP11_23_21, AD_DI_B, SEL_ADI_1),
-       PINMUX_IPSR_DATA(IP11_23_21, PCMWE_N),
-       PINMUX_IPSR_DATA(IP11_26_24, SSI_WS0129),
+       PINMUX_IPSR_GPSR(IP11_23_21, PCMWE_N),
+       PINMUX_IPSR_GPSR(IP11_26_24, SSI_WS0129),
        PINMUX_IPSR_MSEL(IP11_26_24, MSIOF1_TXD_B, SEL_MSI1_1),
        PINMUX_IPSR_MSEL(IP11_26_24, SCIF5_TXD_D, SEL_SCIF5_3),
        PINMUX_IPSR_MSEL(IP11_26_24, ADICS_SAMP_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP11_26_24, AD_DO_B, SEL_ADI_1),
-       PINMUX_IPSR_DATA(IP11_29_27, SSI_SDATA0),
+       PINMUX_IPSR_GPSR(IP11_29_27, SSI_SDATA0),
        PINMUX_IPSR_MSEL(IP11_29_27, MSIOF1_SCK_B, SEL_MSI1_1),
-       PINMUX_IPSR_DATA(IP11_29_27, PWM0_B),
+       PINMUX_IPSR_GPSR(IP11_29_27, PWM0_B),
        PINMUX_IPSR_MSEL(IP11_29_27, ADICLK_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP11_29_27, AD_CLK_B, SEL_ADI_1),
 
        /* IPSR12 */
-       PINMUX_IPSR_DATA(IP12_2_0, SSI_SCK34),
+       PINMUX_IPSR_GPSR(IP12_2_0, SSI_SCK34),
        PINMUX_IPSR_MSEL(IP12_2_0, MSIOF1_SYNC_B, SEL_MSI1_1),
        PINMUX_IPSR_MSEL(IP12_2_0, SCIFA1_SCK_C, SEL_SCIFA1_2),
        PINMUX_IPSR_MSEL(IP12_2_0, ADICHS0_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP12_2_0, AD_NCS_N_B, SEL_ADI_1),
        PINMUX_IPSR_MSEL(IP12_2_0, DREQ1_N_B, SEL_LBS_1),
-       PINMUX_IPSR_DATA(IP12_5_3, SSI_WS34),
+       PINMUX_IPSR_GPSR(IP12_5_3, SSI_WS34),
        PINMUX_IPSR_MSEL(IP12_5_3, MSIOF1_SS1_B, SEL_MSI1_1),
        PINMUX_IPSR_MSEL(IP12_5_3, SCIFA1_RXD_C, SEL_SCIFA1_2),
        PINMUX_IPSR_MSEL(IP12_5_3, ADICHS1_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP12_5_3, CAN1_RX_C, SEL_CAN1_2),
        PINMUX_IPSR_MSEL(IP12_5_3, DACK1_B, SEL_LBS_1),
-       PINMUX_IPSR_DATA(IP12_8_6, SSI_SDATA3),
+       PINMUX_IPSR_GPSR(IP12_8_6, SSI_SDATA3),
        PINMUX_IPSR_MSEL(IP12_8_6, MSIOF1_SS2_B, SEL_MSI1_1),
        PINMUX_IPSR_MSEL(IP12_8_6, SCIFA1_TXD_C, SEL_SCIFA1_2),
        PINMUX_IPSR_MSEL(IP12_8_6, ADICHS2_B, SEL_RAD_1),
        PINMUX_IPSR_MSEL(IP12_8_6, CAN1_TX_C, SEL_CAN1_2),
-       PINMUX_IPSR_DATA(IP12_8_6, DREQ2_N),
+       PINMUX_IPSR_GPSR(IP12_8_6, DREQ2_N),
        PINMUX_IPSR_MSEL(IP12_10_9, SSI_SCK4, SEL_SSI4_0),
-       PINMUX_IPSR_DATA(IP12_10_9, MLB_CLK),
+       PINMUX_IPSR_GPSR(IP12_10_9, MLB_CLK),
        PINMUX_IPSR_MSEL(IP12_10_9, IETX_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP12_10_9, IRD_TX),
+       PINMUX_IPSR_GPSR(IP12_10_9, IRD_TX),
        PINMUX_IPSR_MSEL(IP12_12_11, SSI_WS4, SEL_SSI4_0),
-       PINMUX_IPSR_DATA(IP12_12_11, MLB_SIG),
+       PINMUX_IPSR_GPSR(IP12_12_11, MLB_SIG),
        PINMUX_IPSR_MSEL(IP12_12_11, IECLK_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP12_12_11, IRD_RX),
+       PINMUX_IPSR_GPSR(IP12_12_11, IRD_RX),
        PINMUX_IPSR_MSEL(IP12_14_13, SSI_SDATA4, SEL_SSI4_0),
-       PINMUX_IPSR_DATA(IP12_14_13, MLB_DAT),
+       PINMUX_IPSR_GPSR(IP12_14_13, MLB_DAT),
        PINMUX_IPSR_MSEL(IP12_14_13, IERX_B, SEL_IEB_1),
-       PINMUX_IPSR_DATA(IP12_14_13, IRD_SCK),
+       PINMUX_IPSR_GPSR(IP12_14_13, IRD_SCK),
        PINMUX_IPSR_MSEL(IP12_17_15, SSI_SDATA8, SEL_SSI8_0),
        PINMUX_IPSR_MSEL(IP12_17_15, SCIF1_SCK_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP12_17_15, PWM1_B),
-       PINMUX_IPSR_DATA(IP12_17_15, IRQ9),
+       PINMUX_IPSR_GPSR(IP12_17_15, PWM1_B),
+       PINMUX_IPSR_GPSR(IP12_17_15, IRQ9),
        PINMUX_IPSR_MSEL(IP12_17_15, REMOCON, SEL_RCN_0),
-       PINMUX_IPSR_DATA(IP12_17_15, DACK2),
+       PINMUX_IPSR_GPSR(IP12_17_15, DACK2),
        PINMUX_IPSR_MSEL(IP12_17_15, ETH_MDIO_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP12_20_18, SSI_SCK1, SEL_SSI1_0),
        PINMUX_IPSR_MSEL(IP12_20_18, SCIF1_RXD_B, SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP12_20_18, IIC1_SCL_C, SEL_IIC01_2),
-       PINMUX_IPSR_DATA(IP12_20_18, VI1_CLK),
+       PINMUX_IPSR_GPSR(IP12_20_18, VI1_CLK),
        PINMUX_IPSR_MSEL(IP12_20_18, CAN0_RX_D, SEL_CAN0_3),
        PINMUX_IPSR_MSEL(IP12_20_18, AVB_AVTP_CAPTURE, SEL_AVB_0),
        PINMUX_IPSR_MSEL(IP12_20_18, ETH_CRS_DV_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP12_23_21, SSI_WS1, SEL_SSI1_0),
        PINMUX_IPSR_MSEL(IP12_23_21, SCIF1_TXD_B, SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP12_23_21, IIC1_SDA_C, SEL_IIC01_2),
-       PINMUX_IPSR_DATA(IP12_23_21, VI1_DATA0),
+       PINMUX_IPSR_GPSR(IP12_23_21, VI1_DATA0),
        PINMUX_IPSR_MSEL(IP12_23_21, CAN0_TX_D, SEL_CAN0_3),
        PINMUX_IPSR_MSEL(IP12_23_21, AVB_AVTP_MATCH, SEL_AVB_0),
        PINMUX_IPSR_MSEL(IP12_23_21, ETH_RX_ER_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP12_26_24, SSI_SDATA1, SEL_SSI1_0),
        PINMUX_IPSR_MSEL(IP12_26_24, HSCIF1_HRX_B, SEL_HSCIF1_1),
-       PINMUX_IPSR_DATA(IP12_26_24, VI1_DATA1),
+       PINMUX_IPSR_GPSR(IP12_26_24, VI1_DATA1),
        PINMUX_IPSR_MSEL(IP12_26_24, SDATA, SEL_FSN_0),
-       PINMUX_IPSR_DATA(IP12_26_24, ATAG0_N),
+       PINMUX_IPSR_GPSR(IP12_26_24, ATAG0_N),
        PINMUX_IPSR_MSEL(IP12_26_24, ETH_RXD0_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP12_29_27, SSI_SCK2, SEL_SSI2_0),
        PINMUX_IPSR_MSEL(IP12_29_27, HSCIF1_HTX_B, SEL_HSCIF1_1),
-       PINMUX_IPSR_DATA(IP12_29_27, VI1_DATA2),
+       PINMUX_IPSR_GPSR(IP12_29_27, VI1_DATA2),
        PINMUX_IPSR_MSEL(IP12_29_27, MDATA, SEL_FSN_0),
-       PINMUX_IPSR_DATA(IP12_29_27, ATAWR0_N),
+       PINMUX_IPSR_GPSR(IP12_29_27, ATAWR0_N),
        PINMUX_IPSR_MSEL(IP12_29_27, ETH_RXD1_B, SEL_ETH_1),
 
        /* IPSR13 */
        PINMUX_IPSR_MSEL(IP13_2_0, SSI_WS2, SEL_SSI2_0),
        PINMUX_IPSR_MSEL(IP13_2_0, HSCIF1_HCTS_N_B, SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP13_2_0, SCIFA0_RXD_D, SEL_SCIFA0_3),
-       PINMUX_IPSR_DATA(IP13_2_0, VI1_DATA3),
+       PINMUX_IPSR_GPSR(IP13_2_0, VI1_DATA3),
        PINMUX_IPSR_MSEL(IP13_2_0, SCKZ, SEL_FSN_0),
-       PINMUX_IPSR_DATA(IP13_2_0, ATACS00_N),
+       PINMUX_IPSR_GPSR(IP13_2_0, ATACS00_N),
        PINMUX_IPSR_MSEL(IP13_2_0, ETH_LINK_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP13_5_3, SSI_SDATA2, SEL_SSI2_0),
        PINMUX_IPSR_MSEL(IP13_5_3, HSCIF1_HRTS_N_B, SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP13_5_3, SCIFA0_TXD_D, SEL_SCIFA0_3),
-       PINMUX_IPSR_DATA(IP13_5_3, VI1_DATA4),
+       PINMUX_IPSR_GPSR(IP13_5_3, VI1_DATA4),
        PINMUX_IPSR_MSEL(IP13_5_3, STM_N, SEL_FSN_0),
-       PINMUX_IPSR_DATA(IP13_5_3, ATACS10_N),
+       PINMUX_IPSR_GPSR(IP13_5_3, ATACS10_N),
        PINMUX_IPSR_MSEL(IP13_5_3, ETH_REFCLK_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP13_8_6, SSI_SCK9, SEL_SSI9_0),
        PINMUX_IPSR_MSEL(IP13_8_6, SCIF2_SCK_B, SEL_SCIF2_1),
-       PINMUX_IPSR_DATA(IP13_8_6, PWM2_B),
-       PINMUX_IPSR_DATA(IP13_8_6, VI1_DATA5),
+       PINMUX_IPSR_GPSR(IP13_8_6, PWM2_B),
+       PINMUX_IPSR_GPSR(IP13_8_6, VI1_DATA5),
        PINMUX_IPSR_MSEL(IP13_8_6, MTS_N, SEL_FSN_0),
-       PINMUX_IPSR_DATA(IP13_8_6, EX_WAIT1),
+       PINMUX_IPSR_GPSR(IP13_8_6, EX_WAIT1),
        PINMUX_IPSR_MSEL(IP13_8_6, ETH_TXD1_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP13_11_9, SSI_WS9, SEL_SSI9_0),
        PINMUX_IPSR_MSEL(IP13_11_9, SCIF2_RXD_B, SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP13_11_9, I2C3_SCL_E, SEL_I2C03_4),
-       PINMUX_IPSR_DATA(IP13_11_9, VI1_DATA6),
-       PINMUX_IPSR_DATA(IP13_11_9, ATARD0_N),
+       PINMUX_IPSR_GPSR(IP13_11_9, VI1_DATA6),
+       PINMUX_IPSR_GPSR(IP13_11_9, ATARD0_N),
        PINMUX_IPSR_MSEL(IP13_11_9, ETH_TX_EN_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP13_14_12, SSI_SDATA9, SEL_SSI9_0),
        PINMUX_IPSR_MSEL(IP13_14_12, SCIF2_TXD_B, SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP13_14_12, I2C3_SDA_E, SEL_I2C03_4),
-       PINMUX_IPSR_DATA(IP13_14_12, VI1_DATA7),
-       PINMUX_IPSR_DATA(IP13_14_12, ATADIR0_N),
+       PINMUX_IPSR_GPSR(IP13_14_12, VI1_DATA7),
+       PINMUX_IPSR_GPSR(IP13_14_12, ATADIR0_N),
        PINMUX_IPSR_MSEL(IP13_14_12, ETH_MAGIC_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP13_17_15, AUDIO_CLKA, SEL_ADG_0),
        PINMUX_IPSR_MSEL(IP13_17_15, I2C0_SCL_B, SEL_I2C00_1),
        PINMUX_IPSR_MSEL(IP13_17_15, SCIFA4_RXD_D, SEL_SCIFA4_3),
-       PINMUX_IPSR_DATA(IP13_17_15, VI1_CLKENB),
+       PINMUX_IPSR_GPSR(IP13_17_15, VI1_CLKENB),
        PINMUX_IPSR_MSEL(IP13_17_15, TS_SDATA_C, SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP13_17_15, RIF0_SYNC_B, SEL_DR0_1),
        PINMUX_IPSR_MSEL(IP13_17_15, ETH_TXD0_B, SEL_ETH_1),
        PINMUX_IPSR_MSEL(IP13_20_18, AUDIO_CLKB, SEL_ADG_0),
        PINMUX_IPSR_MSEL(IP13_20_18, I2C0_SDA_B, SEL_I2C00_1),
        PINMUX_IPSR_MSEL(IP13_20_18, SCIFA4_TXD_D, SEL_SCIFA4_3),
-       PINMUX_IPSR_DATA(IP13_20_18, VI1_FIELD),
+       PINMUX_IPSR_GPSR(IP13_20_18, VI1_FIELD),
        PINMUX_IPSR_MSEL(IP13_20_18, TS_SCK_C, SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP13_20_18, RIF0_CLK_B, SEL_DR0_1),
        PINMUX_IPSR_MSEL(IP13_20_18, BPFCLK_E, SEL_DARC_4),
@@ -1472,7 +1472,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP13_23_21, AUDIO_CLKC, SEL_ADG_0),
        PINMUX_IPSR_MSEL(IP13_23_21, I2C4_SCL_B, SEL_I2C04_1),
        PINMUX_IPSR_MSEL(IP13_23_21, SCIFA5_RXD_D, SEL_SCIFA5_3),
-       PINMUX_IPSR_DATA(IP13_23_21, VI1_HSYNC_N),
+       PINMUX_IPSR_GPSR(IP13_23_21, VI1_HSYNC_N),
        PINMUX_IPSR_MSEL(IP13_23_21, TS_SDEN_C, SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP13_23_21, RIF0_D0_B, SEL_DR0_1),
        PINMUX_IPSR_MSEL(IP13_23_21, FMCLK_E, SEL_DARC_4),
@@ -1480,7 +1480,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP13_26_24, AUDIO_CLKOUT, SEL_ADG_0),
        PINMUX_IPSR_MSEL(IP13_26_24, I2C4_SDA_B, SEL_I2C04_1),
        PINMUX_IPSR_MSEL(IP13_26_24, SCIFA5_TXD_D, SEL_SCIFA5_3),
-       PINMUX_IPSR_DATA(IP13_26_24, VI1_VSYNC_N),
+       PINMUX_IPSR_GPSR(IP13_26_24, VI1_VSYNC_N),
        PINMUX_IPSR_MSEL(IP13_26_24, TS_SPSYNC_C, SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP13_26_24, RIF0_D1_B, SEL_DR1_1),
        PINMUX_IPSR_MSEL(IP13_26_24, FMIN_E, SEL_DARC_4),
@@ -1491,6 +1491,197 @@ static const struct sh_pfc_pin pinmux_pins[] = {
        PINMUX_GPIO_GP_ALL(),
 };
 
+/* - Audio Clock ------------------------------------------------------------ */
+static const unsigned int audio_clka_pins[] = {
+       /* CLKA */
+       RCAR_GP_PIN(5, 20),
+};
+static const unsigned int audio_clka_mux[] = {
+       AUDIO_CLKA_MARK,
+};
+static const unsigned int audio_clka_b_pins[] = {
+       /* CLKA */
+       RCAR_GP_PIN(3, 25),
+};
+static const unsigned int audio_clka_b_mux[] = {
+       AUDIO_CLKA_B_MARK,
+};
+static const unsigned int audio_clka_c_pins[] = {
+       /* CLKA */
+       RCAR_GP_PIN(4, 20),
+};
+static const unsigned int audio_clka_c_mux[] = {
+       AUDIO_CLKA_C_MARK,
+};
+static const unsigned int audio_clka_d_pins[] = {
+       /* CLKA */
+       RCAR_GP_PIN(5, 0),
+};
+static const unsigned int audio_clka_d_mux[] = {
+       AUDIO_CLKA_D_MARK,
+};
+static const unsigned int audio_clkb_pins[] = {
+       /* CLKB */
+       RCAR_GP_PIN(5, 21),
+};
+static const unsigned int audio_clkb_mux[] = {
+       AUDIO_CLKB_MARK,
+};
+static const unsigned int audio_clkb_b_pins[] = {
+       /* CLKB */
+       RCAR_GP_PIN(3, 26),
+};
+static const unsigned int audio_clkb_b_mux[] = {
+       AUDIO_CLKB_B_MARK,
+};
+static const unsigned int audio_clkb_c_pins[] = {
+       /* CLKB */
+       RCAR_GP_PIN(4, 21),
+};
+static const unsigned int audio_clkb_c_mux[] = {
+       AUDIO_CLKB_C_MARK,
+};
+static const unsigned int audio_clkc_pins[] = {
+       /* CLKC */
+       RCAR_GP_PIN(5, 22),
+};
+static const unsigned int audio_clkc_mux[] = {
+       AUDIO_CLKC_MARK,
+};
+static const unsigned int audio_clkc_b_pins[] = {
+       /* CLKC */
+       RCAR_GP_PIN(3, 29),
+};
+static const unsigned int audio_clkc_b_mux[] = {
+       AUDIO_CLKC_B_MARK,
+};
+static const unsigned int audio_clkc_c_pins[] = {
+       /* CLKC */
+       RCAR_GP_PIN(4, 22),
+};
+static const unsigned int audio_clkc_c_mux[] = {
+       AUDIO_CLKC_C_MARK,
+};
+static const unsigned int audio_clkout_pins[] = {
+       /* CLKOUT */
+       RCAR_GP_PIN(5, 23),
+};
+static const unsigned int audio_clkout_mux[] = {
+       AUDIO_CLKOUT_MARK,
+};
+static const unsigned int audio_clkout_b_pins[] = {
+       /* CLKOUT */
+       RCAR_GP_PIN(3, 12),
+};
+static const unsigned int audio_clkout_b_mux[] = {
+       AUDIO_CLKOUT_B_MARK,
+};
+static const unsigned int audio_clkout_c_pins[] = {
+       /* CLKOUT */
+       RCAR_GP_PIN(4, 23),
+};
+static const unsigned int audio_clkout_c_mux[] = {
+       AUDIO_CLKOUT_C_MARK,
+};
+/* - AVB -------------------------------------------------------------------- */
+static const unsigned int avb_link_pins[] = {
+       RCAR_GP_PIN(3, 26),
+};
+static const unsigned int avb_link_mux[] = {
+       AVB_LINK_MARK,
+};
+static const unsigned int avb_magic_pins[] = {
+       RCAR_GP_PIN(3, 27),
+};
+static const unsigned int avb_magic_mux[] = {
+       AVB_MAGIC_MARK,
+};
+static const unsigned int avb_phy_int_pins[] = {
+       RCAR_GP_PIN(3, 28),
+};
+static const unsigned int avb_phy_int_mux[] = {
+       AVB_PHY_INT_MARK,
+};
+static const unsigned int avb_mdio_pins[] = {
+       RCAR_GP_PIN(3, 24), RCAR_GP_PIN(3, 25),
+};
+static const unsigned int avb_mdio_mux[] = {
+       AVB_MDC_MARK, AVB_MDIO_MARK,
+};
+static const unsigned int avb_mii_pins[] = {
+       RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 16),
+       RCAR_GP_PIN(3, 17),
+
+       RCAR_GP_PIN(3, 2), RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 4),
+       RCAR_GP_PIN(3, 5),
+
+       RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 0), RCAR_GP_PIN(3, 1),
+       RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 22),
+       RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 11),
+};
+static const unsigned int avb_mii_mux[] = {
+       AVB_TXD0_MARK, AVB_TXD1_MARK, AVB_TXD2_MARK,
+       AVB_TXD3_MARK,
+
+       AVB_RXD0_MARK, AVB_RXD1_MARK, AVB_RXD2_MARK,
+       AVB_RXD3_MARK,
+
+       AVB_RX_ER_MARK, AVB_RX_CLK_MARK, AVB_RX_DV_MARK,
+       AVB_CRS_MARK, AVB_TX_EN_MARK, AVB_TX_ER_MARK,
+       AVB_TX_CLK_MARK, AVB_COL_MARK,
+};
+static const unsigned int avb_gmii_pins[] = {
+       RCAR_GP_PIN(3, 14), RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 16),
+       RCAR_GP_PIN(3, 17), RCAR_GP_PIN(3, 18), RCAR_GP_PIN(3, 19),
+       RCAR_GP_PIN(3, 20), RCAR_GP_PIN(3, 21),
+
+       RCAR_GP_PIN(3, 2), RCAR_GP_PIN(3, 3), RCAR_GP_PIN(3, 4),
+       RCAR_GP_PIN(3, 5), RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+       RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
+
+       RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 0), RCAR_GP_PIN(3, 1),
+       RCAR_GP_PIN(3, 29), RCAR_GP_PIN(3, 23), RCAR_GP_PIN(3, 30),
+       RCAR_GP_PIN(3, 12), RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 13),
+       RCAR_GP_PIN(3, 11),
+};
+static const unsigned int avb_gmii_mux[] = {
+       AVB_TXD0_MARK, AVB_TXD1_MARK, AVB_TXD2_MARK,
+       AVB_TXD3_MARK, AVB_TXD4_MARK, AVB_TXD5_MARK,
+       AVB_TXD6_MARK, AVB_TXD7_MARK,
+
+       AVB_RXD0_MARK, AVB_RXD1_MARK, AVB_RXD2_MARK,
+       AVB_RXD3_MARK, AVB_RXD4_MARK, AVB_RXD5_MARK,
+       AVB_RXD6_MARK, AVB_RXD7_MARK,
+
+       AVB_RX_ER_MARK, AVB_RX_CLK_MARK, AVB_RX_DV_MARK,
+       AVB_CRS_MARK, AVB_GTX_CLK_MARK, AVB_GTXREFCLK_MARK,
+       AVB_TX_EN_MARK, AVB_TX_ER_MARK, AVB_TX_CLK_MARK,
+       AVB_COL_MARK,
+};
+static const unsigned int avb_avtp_capture_pins[] = {
+       RCAR_GP_PIN(5, 11),
+};
+static const unsigned int avb_avtp_capture_mux[] = {
+       AVB_AVTP_CAPTURE_MARK,
+};
+static const unsigned int avb_avtp_match_pins[] = {
+       RCAR_GP_PIN(5, 12),
+};
+static const unsigned int avb_avtp_match_mux[] = {
+       AVB_AVTP_MATCH_MARK,
+};
+static const unsigned int avb_avtp_capture_b_pins[] = {
+       RCAR_GP_PIN(1, 1),
+};
+static const unsigned int avb_avtp_capture_b_mux[] = {
+       AVB_AVTP_CAPTURE_B_MARK,
+};
+static const unsigned int avb_avtp_match_b_pins[] = {
+       RCAR_GP_PIN(1, 2),
+};
+static const unsigned int avb_avtp_match_b_mux[] = {
+       AVB_AVTP_MATCH_B_MARK,
+};
 /* - ETH -------------------------------------------------------------------- */
 static const unsigned int eth_link_pins[] = {
        /* LINK */
@@ -2751,6 +2942,245 @@ static const unsigned int sdhi2_wp_pins[] = {
 static const unsigned int sdhi2_wp_mux[] = {
        SD2_WP_MARK,
 };
+/* - SSI -------------------------------------------------------------------- */
+static const unsigned int ssi0_data_pins[] = {
+       /* SDATA0 */
+       RCAR_GP_PIN(5, 3),
+};
+static const unsigned int ssi0_data_mux[] = {
+       SSI_SDATA0_MARK,
+};
+static const unsigned int ssi0129_ctrl_pins[] = {
+       /* SCK0129, WS0129 */
+       RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2),
+};
+static const unsigned int ssi0129_ctrl_mux[] = {
+       SSI_SCK0129_MARK, SSI_WS0129_MARK,
+};
+static const unsigned int ssi1_data_pins[] = {
+       /* SDATA1 */
+       RCAR_GP_PIN(5, 13),
+};
+static const unsigned int ssi1_data_mux[] = {
+       SSI_SDATA1_MARK,
+};
+static const unsigned int ssi1_ctrl_pins[] = {
+       /* SCK1, WS1 */
+       RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 12),
+};
+static const unsigned int ssi1_ctrl_mux[] = {
+       SSI_SCK1_MARK, SSI_WS1_MARK,
+};
+static const unsigned int ssi1_data_b_pins[] = {
+       /* SDATA1 */
+       RCAR_GP_PIN(4, 13),
+};
+static const unsigned int ssi1_data_b_mux[] = {
+       SSI_SDATA1_B_MARK,
+};
+static const unsigned int ssi1_ctrl_b_pins[] = {
+       /* SCK1, WS1 */
+       RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 12),
+};
+static const unsigned int ssi1_ctrl_b_mux[] = {
+       SSI_SCK1_B_MARK, SSI_WS1_B_MARK,
+};
+static const unsigned int ssi2_data_pins[] = {
+       /* SDATA2 */
+       RCAR_GP_PIN(5, 16),
+};
+static const unsigned int ssi2_data_mux[] = {
+       SSI_SDATA2_MARK,
+};
+static const unsigned int ssi2_ctrl_pins[] = {
+       /* SCK2, WS2 */
+       RCAR_GP_PIN(5, 14), RCAR_GP_PIN(5, 15),
+};
+static const unsigned int ssi2_ctrl_mux[] = {
+       SSI_SCK2_MARK, SSI_WS2_MARK,
+};
+static const unsigned int ssi2_data_b_pins[] = {
+       /* SDATA2 */
+       RCAR_GP_PIN(4, 16),
+};
+static const unsigned int ssi2_data_b_mux[] = {
+       SSI_SDATA2_B_MARK,
+};
+static const unsigned int ssi2_ctrl_b_pins[] = {
+       /* SCK2, WS2 */
+       RCAR_GP_PIN(4, 14), RCAR_GP_PIN(4, 15),
+};
+static const unsigned int ssi2_ctrl_b_mux[] = {
+       SSI_SCK2_B_MARK, SSI_WS2_B_MARK,
+};
+static const unsigned int ssi3_data_pins[] = {
+       /* SDATA3 */
+       RCAR_GP_PIN(5, 6),
+};
+static const unsigned int ssi3_data_mux[] = {
+       SSI_SDATA3_MARK
+};
+static const unsigned int ssi34_ctrl_pins[] = {
+       /* SCK34, WS34 */
+       RCAR_GP_PIN(5, 4), RCAR_GP_PIN(5, 5),
+};
+static const unsigned int ssi34_ctrl_mux[] = {
+       SSI_SCK34_MARK, SSI_WS34_MARK,
+};
+static const unsigned int ssi4_data_pins[] = {
+       /* SDATA4 */
+       RCAR_GP_PIN(5, 9),
+};
+static const unsigned int ssi4_data_mux[] = {
+       SSI_SDATA4_MARK,
+};
+static const unsigned int ssi4_ctrl_pins[] = {
+       /* SCK4, WS4 */
+       RCAR_GP_PIN(5, 7), RCAR_GP_PIN(5, 8),
+};
+static const unsigned int ssi4_ctrl_mux[] = {
+       SSI_SCK4_MARK, SSI_WS4_MARK,
+};
+static const unsigned int ssi4_data_b_pins[] = {
+       /* SDATA4 */
+       RCAR_GP_PIN(4, 22),
+};
+static const unsigned int ssi4_data_b_mux[] = {
+       SSI_SDATA4_B_MARK,
+};
+static const unsigned int ssi4_ctrl_b_pins[] = {
+       /* SCK4, WS4 */
+       RCAR_GP_PIN(4, 20), RCAR_GP_PIN(4, 21),
+};
+static const unsigned int ssi4_ctrl_b_mux[] = {
+       SSI_SCK4_B_MARK, SSI_WS4_B_MARK,
+};
+static const unsigned int ssi5_data_pins[] = {
+       /* SDATA5 */
+       RCAR_GP_PIN(4, 26),
+};
+static const unsigned int ssi5_data_mux[] = {
+       SSI_SDATA5_MARK,
+};
+static const unsigned int ssi5_ctrl_pins[] = {
+       /* SCK5, WS5 */
+       RCAR_GP_PIN(4, 24), RCAR_GP_PIN(4, 25),
+};
+static const unsigned int ssi5_ctrl_mux[] = {
+       SSI_SCK5_MARK, SSI_WS5_MARK,
+};
+static const unsigned int ssi5_data_b_pins[] = {
+       /* SDATA5 */
+       RCAR_GP_PIN(3, 21),
+};
+static const unsigned int ssi5_data_b_mux[] = {
+       SSI_SDATA5_B_MARK,
+};
+static const unsigned int ssi5_ctrl_b_pins[] = {
+       /* SCK5, WS5 */
+       RCAR_GP_PIN(3, 19), RCAR_GP_PIN(3, 20),
+};
+static const unsigned int ssi5_ctrl_b_mux[] = {
+       SSI_SCK5_B_MARK, SSI_WS5_B_MARK,
+};
+static const unsigned int ssi6_data_pins[] = {
+       /* SDATA6 */
+       RCAR_GP_PIN(4, 29),
+};
+static const unsigned int ssi6_data_mux[] = {
+       SSI_SDATA6_MARK,
+};
+static const unsigned int ssi6_ctrl_pins[] = {
+       /* SCK6, WS6 */
+       RCAR_GP_PIN(4, 27), RCAR_GP_PIN(4, 28),
+};
+static const unsigned int ssi6_ctrl_mux[] = {
+       SSI_SCK6_MARK, SSI_WS6_MARK,
+};
+static const unsigned int ssi6_data_b_pins[] = {
+       /* SDATA6 */
+       RCAR_GP_PIN(3, 24),
+};
+static const unsigned int ssi6_data_b_mux[] = {
+       SSI_SDATA6_B_MARK,
+};
+static const unsigned int ssi6_ctrl_b_pins[] = {
+       /* SCK6, WS6 */
+       RCAR_GP_PIN(3, 22), RCAR_GP_PIN(3, 23),
+};
+static const unsigned int ssi6_ctrl_b_mux[] = {
+       SSI_SCK6_B_MARK, SSI_WS6_B_MARK,
+};
+static const unsigned int ssi7_data_pins[] = {
+       /* SDATA7 */
+       RCAR_GP_PIN(5, 0),
+};
+static const unsigned int ssi7_data_mux[] = {
+       SSI_SDATA7_MARK,
+};
+static const unsigned int ssi78_ctrl_pins[] = {
+       /* SCK78, WS78 */
+       RCAR_GP_PIN(4, 30), RCAR_GP_PIN(4, 31),
+};
+static const unsigned int ssi78_ctrl_mux[] = {
+       SSI_SCK78_MARK, SSI_WS78_MARK,
+};
+static const unsigned int ssi7_data_b_pins[] = {
+       /* SDATA7 */
+       RCAR_GP_PIN(3, 27),
+};
+static const unsigned int ssi7_data_b_mux[] = {
+       SSI_SDATA7_B_MARK,
+};
+static const unsigned int ssi78_ctrl_b_pins[] = {
+       /* SCK78, WS78 */
+       RCAR_GP_PIN(3, 25), RCAR_GP_PIN(3, 26),
+};
+static const unsigned int ssi78_ctrl_b_mux[] = {
+       SSI_SCK78_B_MARK, SSI_WS78_B_MARK,
+};
+static const unsigned int ssi8_data_pins[] = {
+       /* SDATA8 */
+       RCAR_GP_PIN(5, 10),
+};
+static const unsigned int ssi8_data_mux[] = {
+       SSI_SDATA8_MARK,
+};
+static const unsigned int ssi8_data_b_pins[] = {
+       /* SDATA8 */
+       RCAR_GP_PIN(3, 28),
+};
+static const unsigned int ssi8_data_b_mux[] = {
+       SSI_SDATA8_B_MARK,
+};
+static const unsigned int ssi9_data_pins[] = {
+       /* SDATA9 */
+       RCAR_GP_PIN(5, 19),
+};
+static const unsigned int ssi9_data_mux[] = {
+       SSI_SDATA9_MARK,
+};
+static const unsigned int ssi9_ctrl_pins[] = {
+       /* SCK9, WS9 */
+       RCAR_GP_PIN(5, 17), RCAR_GP_PIN(5, 18),
+};
+static const unsigned int ssi9_ctrl_mux[] = {
+       SSI_SCK9_MARK, SSI_WS9_MARK,
+};
+static const unsigned int ssi9_data_b_pins[] = {
+       /* SDATA9 */
+       RCAR_GP_PIN(4, 19),
+};
+static const unsigned int ssi9_data_b_mux[] = {
+       SSI_SDATA9_B_MARK,
+};
+static const unsigned int ssi9_ctrl_b_pins[] = {
+       /* SCK9, WS9 */
+       RCAR_GP_PIN(4, 17), RCAR_GP_PIN(4, 18),
+};
+static const unsigned int ssi9_ctrl_b_mux[] = {
+       SSI_SCK9_B_MARK, SSI_WS9_B_MARK,
+};
 /* - USB0 ------------------------------------------------------------------- */
 static const unsigned int usb0_pins[] = {
        RCAR_GP_PIN(5, 24), /* PWEN */
@@ -2911,6 +3341,29 @@ static const unsigned int vin1_clk_mux[] = {
 };
 
 static const struct sh_pfc_pin_group pinmux_groups[] = {
+       SH_PFC_PIN_GROUP(audio_clka),
+       SH_PFC_PIN_GROUP(audio_clka_b),
+       SH_PFC_PIN_GROUP(audio_clka_c),
+       SH_PFC_PIN_GROUP(audio_clka_d),
+       SH_PFC_PIN_GROUP(audio_clkb),
+       SH_PFC_PIN_GROUP(audio_clkb_b),
+       SH_PFC_PIN_GROUP(audio_clkb_c),
+       SH_PFC_PIN_GROUP(audio_clkc),
+       SH_PFC_PIN_GROUP(audio_clkc_b),
+       SH_PFC_PIN_GROUP(audio_clkc_c),
+       SH_PFC_PIN_GROUP(audio_clkout),
+       SH_PFC_PIN_GROUP(audio_clkout_b),
+       SH_PFC_PIN_GROUP(audio_clkout_c),
+       SH_PFC_PIN_GROUP(avb_link),
+       SH_PFC_PIN_GROUP(avb_magic),
+       SH_PFC_PIN_GROUP(avb_phy_int),
+       SH_PFC_PIN_GROUP(avb_mdio),
+       SH_PFC_PIN_GROUP(avb_mii),
+       SH_PFC_PIN_GROUP(avb_gmii),
+       SH_PFC_PIN_GROUP(avb_avtp_capture),
+       SH_PFC_PIN_GROUP(avb_avtp_match),
+       SH_PFC_PIN_GROUP(avb_avtp_capture_b),
+       SH_PFC_PIN_GROUP(avb_avtp_match_b),
        SH_PFC_PIN_GROUP(eth_link),
        SH_PFC_PIN_GROUP(eth_magic),
        SH_PFC_PIN_GROUP(eth_mdio),
@@ -3084,6 +3537,40 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(sdhi2_ctrl),
        SH_PFC_PIN_GROUP(sdhi2_cd),
        SH_PFC_PIN_GROUP(sdhi2_wp),
+       SH_PFC_PIN_GROUP(ssi0_data),
+       SH_PFC_PIN_GROUP(ssi0129_ctrl),
+       SH_PFC_PIN_GROUP(ssi1_data),
+       SH_PFC_PIN_GROUP(ssi1_ctrl),
+       SH_PFC_PIN_GROUP(ssi1_data_b),
+       SH_PFC_PIN_GROUP(ssi1_ctrl_b),
+       SH_PFC_PIN_GROUP(ssi2_data),
+       SH_PFC_PIN_GROUP(ssi2_ctrl),
+       SH_PFC_PIN_GROUP(ssi2_data_b),
+       SH_PFC_PIN_GROUP(ssi2_ctrl_b),
+       SH_PFC_PIN_GROUP(ssi3_data),
+       SH_PFC_PIN_GROUP(ssi34_ctrl),
+       SH_PFC_PIN_GROUP(ssi4_data),
+       SH_PFC_PIN_GROUP(ssi4_ctrl),
+       SH_PFC_PIN_GROUP(ssi4_data_b),
+       SH_PFC_PIN_GROUP(ssi4_ctrl_b),
+       SH_PFC_PIN_GROUP(ssi5_data),
+       SH_PFC_PIN_GROUP(ssi5_ctrl),
+       SH_PFC_PIN_GROUP(ssi5_data_b),
+       SH_PFC_PIN_GROUP(ssi5_ctrl_b),
+       SH_PFC_PIN_GROUP(ssi6_data),
+       SH_PFC_PIN_GROUP(ssi6_ctrl),
+       SH_PFC_PIN_GROUP(ssi6_data_b),
+       SH_PFC_PIN_GROUP(ssi6_ctrl_b),
+       SH_PFC_PIN_GROUP(ssi7_data),
+       SH_PFC_PIN_GROUP(ssi78_ctrl),
+       SH_PFC_PIN_GROUP(ssi7_data_b),
+       SH_PFC_PIN_GROUP(ssi78_ctrl_b),
+       SH_PFC_PIN_GROUP(ssi8_data),
+       SH_PFC_PIN_GROUP(ssi8_data_b),
+       SH_PFC_PIN_GROUP(ssi9_data),
+       SH_PFC_PIN_GROUP(ssi9_ctrl),
+       SH_PFC_PIN_GROUP(ssi9_data_b),
+       SH_PFC_PIN_GROUP(ssi9_ctrl_b),
        SH_PFC_PIN_GROUP(usb0),
        SH_PFC_PIN_GROUP(usb1),
        VIN_DATA_PIN_GROUP(vin0_data, 24),
@@ -3106,6 +3593,35 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(vin1_clk),
 };
 
+static const char * const audio_clk_groups[] = {
+       "audio_clka",
+       "audio_clka_b",
+       "audio_clka_c",
+       "audio_clka_d",
+       "audio_clkb",
+       "audio_clkb_b",
+       "audio_clkb_c",
+       "audio_clkc",
+       "audio_clkc_b",
+       "audio_clkc_c",
+       "audio_clkout",
+       "audio_clkout_b",
+       "audio_clkout_c",
+};
+
+static const char * const avb_groups[] = {
+       "avb_link",
+       "avb_magic",
+       "avb_phy_int",
+       "avb_mdio",
+       "avb_mii",
+       "avb_gmii",
+       "avb_avtp_capture",
+       "avb_avtp_match",
+       "avb_avtp_capture_b",
+       "avb_avtp_match_b",
+};
+
 static const char * const eth_groups[] = {
        "eth_link",
        "eth_magic",
@@ -3381,6 +3897,43 @@ static const char * const sdhi2_groups[] = {
        "sdhi2_wp",
 };
 
+static const char * const ssi_groups[] = {
+       "ssi0_data",
+       "ssi0129_ctrl",
+       "ssi1_data",
+       "ssi1_ctrl",
+       "ssi1_data_b",
+       "ssi1_ctrl_b",
+       "ssi2_data",
+       "ssi2_ctrl",
+       "ssi2_data_b",
+       "ssi2_ctrl_b",
+       "ssi3_data",
+       "ssi34_ctrl",
+       "ssi4_data",
+       "ssi4_ctrl",
+       "ssi4_data_b",
+       "ssi4_ctrl_b",
+       "ssi5_data",
+       "ssi5_ctrl",
+       "ssi5_data_b",
+       "ssi5_ctrl_b",
+       "ssi6_data",
+       "ssi6_ctrl",
+       "ssi6_data_b",
+       "ssi6_ctrl_b",
+       "ssi7_data",
+       "ssi78_ctrl",
+       "ssi7_data_b",
+       "ssi78_ctrl_b",
+       "ssi8_data",
+       "ssi8_data_b",
+       "ssi9_data",
+       "ssi9_ctrl",
+       "ssi9_data_b",
+       "ssi9_ctrl_b",
+};
+
 static const char * const usb0_groups[] = {
        "usb0",
 };
@@ -3414,6 +3967,8 @@ static const char * const vin1_groups[] = {
 };
 
 static const struct sh_pfc_function pinmux_functions[] = {
+       SH_PFC_FUNCTION(audio_clk),
+       SH_PFC_FUNCTION(avb),
        SH_PFC_FUNCTION(eth),
        SH_PFC_FUNCTION(hscif0),
        SH_PFC_FUNCTION(hscif1),
@@ -3448,6 +4003,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
        SH_PFC_FUNCTION(sdhi0),
        SH_PFC_FUNCTION(sdhi1),
        SH_PFC_FUNCTION(sdhi2),
+       SH_PFC_FUNCTION(ssi),
        SH_PFC_FUNCTION(usb0),
        SH_PFC_FUNCTION(usb1),
        SH_PFC_FUNCTION(vin0),
@@ -3974,6 +4530,7 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
                FN_DU0_DISP, FN_QPOLA, FN_CC50_STATE30, 0,
                /* IP6_3_2 [2] */
                FN_DU0_EXODDF_DU0_ODDF_DISP_CDE, FN_QCPV_QDE, FN_CC50_STATE29,
+               0,
                /* IP6_1_0 [2] */
                FN_DU0_EXVSYNC_DU0_VSYNC, FN_QSTB_QHE, FN_CC50_STATE28, 0, }
        },
index ce4f5cdb05798fe324a50d79e194f218464bd150..5979dabc02facbbb1fad092b75b0f225252aefe8 100644 (file)
 #define GPSR6_4                F_(SSI_SDATA2_A,        IP14_7_4)
 #define GPSR6_3                F_(SSI_SDATA1_A,        IP14_3_0)
 #define GPSR6_2                F_(SSI_SDATA0,          IP13_31_28)
-#define GPSR6_1                F_(SSI_WS0129,          IP13_27_24)
-#define GPSR6_0                F_(SSI_SCK0129,         IP13_23_20)
+#define GPSR6_1                F_(SSI_WS01239,         IP13_27_24)
+#define GPSR6_0                F_(SSI_SCK01239,        IP13_23_20)
 
 /* GPSR7 */
 #define GPSR7_3                FM(HDMI1_CEC)
 #define IP13_11_8      FM(MLB_CLK)             F_(0, 0)        FM(MSIOF1_SCK_F)        F_(0, 0)                        FM(SCL1_B)      F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
 #define IP13_15_12     FM(MLB_SIG)             FM(RX1_B)       FM(MSIOF1_SYNC_F)       F_(0, 0)                        FM(SDA1_B)      F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
 #define IP13_19_16     FM(MLB_DAT)             FM(TX1_B)       FM(MSIOF1_RXD_F)        F_(0, 0)                        F_(0, 0)        F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP13_23_20     FM(SSI_SCK0129)         F_(0, 0)        FM(MSIOF1_TXD_F)        F_(0, 0)                        F_(0, 0)        F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
-#define IP13_27_24     FM(SSI_WS0129)          F_(0, 0)        FM(MSIOF1_SS1_F)        F_(0, 0)                        F_(0, 0)        F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_23_20     FM(SSI_SCK01239)        F_(0, 0)        FM(MSIOF1_TXD_F)        F_(0, 0)                        F_(0, 0)        F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
+#define IP13_27_24     FM(SSI_WS01239)         F_(0, 0)        FM(MSIOF1_SS1_F)        F_(0, 0)                        F_(0, 0)        F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
 #define IP13_31_28     FM(SSI_SDATA0)          F_(0, 0)        FM(MSIOF1_SS2_F)        F_(0, 0)                        F_(0, 0)        F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
 #define IP14_3_0       FM(SSI_SDATA1_A)        F_(0, 0)        F_(0, 0)                F_(0, 0)                        F_(0, 0)        F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
 #define IP14_7_4       FM(SSI_SDATA2_A)        F_(0, 0)        F_(0, 0)                F_(0, 0)                        FM(SSI_SCK1_B)  F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)                F_(0, 0)        F_(0, 0)        F_(0, 0)        F_(0, 0) F_(0, 0) F_(0, 0) F_(0, 0)
@@ -478,7 +478,6 @@ FM(IP16_31_28)      IP16_31_28
 #define MOD_SEL2_31            FM(I2C_SEL_5_0)         FM(I2C_SEL_5_1)
 #define MOD_SEL2_30            FM(I2C_SEL_3_0)         FM(I2C_SEL_3_1)
 #define MOD_SEL2_29            FM(I2C_SEL_0_0)         FM(I2C_SEL_0_1)
-#define MOD_SEL2_2_1           FM(SEL_VSP_0)           FM(SEL_VSP_1)           FM(SEL_VSP_2)           FM(SEL_VSP_3)
 #define MOD_SEL2_0             FM(SEL_VIN4_0)          FM(SEL_VIN4_1)
 
 #define PINMUX_MOD_SELS\
@@ -512,7 +511,7 @@ MOD_SEL0_7_6 \
 MOD_SEL0_5_4           MOD_SEL1_5 \
                        MOD_SEL1_4 \
 MOD_SEL0_3             MOD_SEL1_3 \
-MOD_SEL0_2_1           MOD_SEL1_2              MOD_SEL2_2_1 \
+MOD_SEL0_2_1           MOD_SEL1_2 \
                        MOD_SEL1_1 \
                        MOD_SEL1_0              MOD_SEL2_0
 
@@ -569,18 +568,18 @@ static const u16 pinmux_data[] = {
        PINMUX_SINGLE(SSI_WS5),
 
        /* IPSR0 */
-       PINMUX_IPSR_DATA(IP0_3_0,       AVB_MDC),
+       PINMUX_IPSR_GPSR(IP0_3_0,       AVB_MDC),
        PINMUX_IPSR_MSEL(IP0_3_0,       MSIOF2_SS2_C,           SEL_MSIOF2_2),
 
-       PINMUX_IPSR_DATA(IP0_7_4,       AVB_MAGIC),
+       PINMUX_IPSR_GPSR(IP0_7_4,       AVB_MAGIC),
        PINMUX_IPSR_MSEL(IP0_7_4,       MSIOF2_SS1_C,           SEL_MSIOF2_2),
        PINMUX_IPSR_MSEL(IP0_7_4,       SCK4_A,                 SEL_SCIF4_0),
 
-       PINMUX_IPSR_DATA(IP0_11_8,      AVB_PHY_INT),
+       PINMUX_IPSR_GPSR(IP0_11_8,      AVB_PHY_INT),
        PINMUX_IPSR_MSEL(IP0_11_8,      MSIOF2_SYNC_C,          SEL_MSIOF2_2),
        PINMUX_IPSR_MSEL(IP0_11_8,      RX4_A,                  SEL_SCIF4_0),
 
-       PINMUX_IPSR_DATA(IP0_15_12,     AVB_LINK),
+       PINMUX_IPSR_GPSR(IP0_15_12,     AVB_LINK),
        PINMUX_IPSR_MSEL(IP0_15_12,     MSIOF2_SCK_C,           SEL_MSIOF2_2),
        PINMUX_IPSR_MSEL(IP0_15_12,     TX4_A,                  SEL_SCIF4_0),
 
@@ -592,126 +591,126 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP0_23_20,     MSIOF2_TXD_C,           SEL_MSIOF2_2),
        PINMUX_IPSR_MSEL(IP0_23_20,     RTS4_N_TANS_A,          SEL_SCIF4_0),
 
-       PINMUX_IPSR_DATA(IP0_27_24,     IRQ0),
-       PINMUX_IPSR_DATA(IP0_27_24,     QPOLB),
-       PINMUX_IPSR_DATA(IP0_27_24,     DU_CDE),
+       PINMUX_IPSR_GPSR(IP0_27_24,     IRQ0),
+       PINMUX_IPSR_GPSR(IP0_27_24,     QPOLB),
+       PINMUX_IPSR_GPSR(IP0_27_24,     DU_CDE),
        PINMUX_IPSR_MSEL(IP0_27_24,     VI4_DATA0_B,            SEL_VIN4_1),
        PINMUX_IPSR_MSEL(IP0_27_24,     CAN0_TX_B,              SEL_RCAN0_1),
        PINMUX_IPSR_MSEL(IP0_27_24,     CANFD0_TX_B,            SEL_CANFD0_1),
 
-       PINMUX_IPSR_DATA(IP0_31_28,     IRQ1),
-       PINMUX_IPSR_DATA(IP0_31_28,     QPOLA),
-       PINMUX_IPSR_DATA(IP0_31_28,     DU_DISP),
+       PINMUX_IPSR_GPSR(IP0_31_28,     IRQ1),
+       PINMUX_IPSR_GPSR(IP0_31_28,     QPOLA),
+       PINMUX_IPSR_GPSR(IP0_31_28,     DU_DISP),
        PINMUX_IPSR_MSEL(IP0_31_28,     VI4_DATA1_B,            SEL_VIN4_1),
        PINMUX_IPSR_MSEL(IP0_31_28,     CAN0_RX_B,              SEL_RCAN0_1),
        PINMUX_IPSR_MSEL(IP0_31_28,     CANFD0_RX_B,            SEL_CANFD0_1),
 
        /* IPSR1 */
-       PINMUX_IPSR_DATA(IP1_3_0,       IRQ2),
-       PINMUX_IPSR_DATA(IP1_3_0,       QCPV_QDE),
-       PINMUX_IPSR_DATA(IP1_3_0,       DU_EXODDF_DU_ODDF_DISP_CDE),
+       PINMUX_IPSR_GPSR(IP1_3_0,       IRQ2),
+       PINMUX_IPSR_GPSR(IP1_3_0,       QCPV_QDE),
+       PINMUX_IPSR_GPSR(IP1_3_0,       DU_EXODDF_DU_ODDF_DISP_CDE),
        PINMUX_IPSR_MSEL(IP1_3_0,       VI4_DATA2_B,            SEL_VIN4_1),
        PINMUX_IPSR_MSEL(IP1_3_0,       PWM3_B,                 SEL_PWM3_1),
 
-       PINMUX_IPSR_DATA(IP1_7_4,       IRQ3),
-       PINMUX_IPSR_DATA(IP1_7_4,       QSTVB_QVE),
-       PINMUX_IPSR_DATA(IP1_7_4,       A25),
-       PINMUX_IPSR_DATA(IP1_7_4,       DU_DOTCLKOUT1),
+       PINMUX_IPSR_GPSR(IP1_7_4,       IRQ3),
+       PINMUX_IPSR_GPSR(IP1_7_4,       QSTVB_QVE),
+       PINMUX_IPSR_GPSR(IP1_7_4,       A25),
+       PINMUX_IPSR_GPSR(IP1_7_4,       DU_DOTCLKOUT1),
        PINMUX_IPSR_MSEL(IP1_7_4,       VI4_DATA3_B,            SEL_VIN4_1),
        PINMUX_IPSR_MSEL(IP1_7_4,       PWM4_B,                 SEL_PWM4_1),
 
-       PINMUX_IPSR_DATA(IP1_11_8,      IRQ4),
-       PINMUX_IPSR_DATA(IP1_11_8,      QSTH_QHS),
-       PINMUX_IPSR_DATA(IP1_11_8,      A24),
-       PINMUX_IPSR_DATA(IP1_11_8,      DU_EXHSYNC_DU_HSYNC),
+       PINMUX_IPSR_GPSR(IP1_11_8,      IRQ4),
+       PINMUX_IPSR_GPSR(IP1_11_8,      QSTH_QHS),
+       PINMUX_IPSR_GPSR(IP1_11_8,      A24),
+       PINMUX_IPSR_GPSR(IP1_11_8,      DU_EXHSYNC_DU_HSYNC),
        PINMUX_IPSR_MSEL(IP1_11_8,      VI4_DATA4_B,            SEL_VIN4_1),
        PINMUX_IPSR_MSEL(IP1_11_8,      PWM5_B,                 SEL_PWM5_1),
 
-       PINMUX_IPSR_DATA(IP1_15_12,     IRQ5),
-       PINMUX_IPSR_DATA(IP1_15_12,     QSTB_QHE),
-       PINMUX_IPSR_DATA(IP1_15_12,     A23),
-       PINMUX_IPSR_DATA(IP1_15_12,     DU_EXVSYNC_DU_VSYNC),
+       PINMUX_IPSR_GPSR(IP1_15_12,     IRQ5),
+       PINMUX_IPSR_GPSR(IP1_15_12,     QSTB_QHE),
+       PINMUX_IPSR_GPSR(IP1_15_12,     A23),
+       PINMUX_IPSR_GPSR(IP1_15_12,     DU_EXVSYNC_DU_VSYNC),
        PINMUX_IPSR_MSEL(IP1_15_12,     VI4_DATA5_B,            SEL_VIN4_1),
        PINMUX_IPSR_MSEL(IP1_15_12,     PWM6_B,                 SEL_PWM6_1),
 
-       PINMUX_IPSR_DATA(IP1_19_16,     PWM0),
-       PINMUX_IPSR_DATA(IP1_19_16,     AVB_AVTP_PPS),
-       PINMUX_IPSR_DATA(IP1_19_16,     A22),
+       PINMUX_IPSR_GPSR(IP1_19_16,     PWM0),
+       PINMUX_IPSR_GPSR(IP1_19_16,     AVB_AVTP_PPS),
+       PINMUX_IPSR_GPSR(IP1_19_16,     A22),
        PINMUX_IPSR_MSEL(IP1_19_16,     VI4_DATA6_B,            SEL_VIN4_1),
        PINMUX_IPSR_MSEL(IP1_19_16,     IECLK_B,                SEL_IEBUS_1),
 
        PINMUX_IPSR_MSEL(IP1_23_20,     PWM1_A,                 SEL_PWM1_0),
-       PINMUX_IPSR_DATA(IP1_23_20,     A21),
+       PINMUX_IPSR_GPSR(IP1_23_20,     A21),
        PINMUX_IPSR_MSEL(IP1_23_20,     HRX3_D,                 SEL_HSCIF3_3),
        PINMUX_IPSR_MSEL(IP1_23_20,     VI4_DATA7_B,            SEL_VIN4_1),
        PINMUX_IPSR_MSEL(IP1_23_20,     IERX_B,                 SEL_IEBUS_1),
 
        PINMUX_IPSR_MSEL(IP1_27_24,     PWM2_A,                 SEL_PWM2_0),
-       PINMUX_IPSR_DATA(IP1_27_24,     A20),
+       PINMUX_IPSR_GPSR(IP1_27_24,     A20),
        PINMUX_IPSR_MSEL(IP1_27_24,     HTX3_D,                 SEL_HSCIF3_3),
        PINMUX_IPSR_MSEL(IP1_27_24,     IETX_B,                 SEL_IEBUS_1),
 
-       PINMUX_IPSR_DATA(IP1_31_28,     A0),
-       PINMUX_IPSR_DATA(IP1_31_28,     LCDOUT16),
+       PINMUX_IPSR_GPSR(IP1_31_28,     A0),
+       PINMUX_IPSR_GPSR(IP1_31_28,     LCDOUT16),
        PINMUX_IPSR_MSEL(IP1_31_28,     MSIOF3_SYNC_B,          SEL_MSIOF3_1),
-       PINMUX_IPSR_DATA(IP1_31_28,     VI4_DATA8),
-       PINMUX_IPSR_DATA(IP1_31_28,     DU_DB0),
+       PINMUX_IPSR_GPSR(IP1_31_28,     VI4_DATA8),
+       PINMUX_IPSR_GPSR(IP1_31_28,     DU_DB0),
        PINMUX_IPSR_MSEL(IP1_31_28,     PWM3_A,                 SEL_PWM3_0),
 
        /* IPSR2 */
-       PINMUX_IPSR_DATA(IP2_3_0,       A1),
-       PINMUX_IPSR_DATA(IP2_3_0,       LCDOUT17),
+       PINMUX_IPSR_GPSR(IP2_3_0,       A1),
+       PINMUX_IPSR_GPSR(IP2_3_0,       LCDOUT17),
        PINMUX_IPSR_MSEL(IP2_3_0,       MSIOF3_TXD_B,           SEL_MSIOF3_1),
-       PINMUX_IPSR_DATA(IP2_3_0,       VI4_DATA9),
-       PINMUX_IPSR_DATA(IP2_3_0,       DU_DB1),
+       PINMUX_IPSR_GPSR(IP2_3_0,       VI4_DATA9),
+       PINMUX_IPSR_GPSR(IP2_3_0,       DU_DB1),
        PINMUX_IPSR_MSEL(IP2_3_0,       PWM4_A,                 SEL_PWM4_0),
 
-       PINMUX_IPSR_DATA(IP2_7_4,       A2),
-       PINMUX_IPSR_DATA(IP2_7_4,       LCDOUT18),
+       PINMUX_IPSR_GPSR(IP2_7_4,       A2),
+       PINMUX_IPSR_GPSR(IP2_7_4,       LCDOUT18),
        PINMUX_IPSR_MSEL(IP2_7_4,       MSIOF3_SCK_B,           SEL_MSIOF3_1),
-       PINMUX_IPSR_DATA(IP2_7_4,       VI4_DATA10),
-       PINMUX_IPSR_DATA(IP2_7_4,       DU_DB2),
+       PINMUX_IPSR_GPSR(IP2_7_4,       VI4_DATA10),
+       PINMUX_IPSR_GPSR(IP2_7_4,       DU_DB2),
        PINMUX_IPSR_MSEL(IP2_7_4,       PWM5_A,                 SEL_PWM5_0),
 
-       PINMUX_IPSR_DATA(IP2_11_8,      A3),
-       PINMUX_IPSR_DATA(IP2_11_8,      LCDOUT19),
+       PINMUX_IPSR_GPSR(IP2_11_8,      A3),
+       PINMUX_IPSR_GPSR(IP2_11_8,      LCDOUT19),
        PINMUX_IPSR_MSEL(IP2_11_8,      MSIOF3_RXD_B,           SEL_MSIOF3_1),
-       PINMUX_IPSR_DATA(IP2_11_8,      VI4_DATA11),
-       PINMUX_IPSR_DATA(IP2_11_8,      DU_DB3),
+       PINMUX_IPSR_GPSR(IP2_11_8,      VI4_DATA11),
+       PINMUX_IPSR_GPSR(IP2_11_8,      DU_DB3),
        PINMUX_IPSR_MSEL(IP2_11_8,      PWM6_A,                 SEL_PWM6_0),
 
-       PINMUX_IPSR_DATA(IP2_15_12,     A4),
-       PINMUX_IPSR_DATA(IP2_15_12,     LCDOUT20),
+       PINMUX_IPSR_GPSR(IP2_15_12,     A4),
+       PINMUX_IPSR_GPSR(IP2_15_12,     LCDOUT20),
        PINMUX_IPSR_MSEL(IP2_15_12,     MSIOF3_SS1_B,           SEL_MSIOF3_1),
-       PINMUX_IPSR_DATA(IP2_15_12,     VI4_DATA12),
-       PINMUX_IPSR_DATA(IP2_15_12,     VI5_DATA12),
-       PINMUX_IPSR_DATA(IP2_15_12,     DU_DB4),
+       PINMUX_IPSR_GPSR(IP2_15_12,     VI4_DATA12),
+       PINMUX_IPSR_GPSR(IP2_15_12,     VI5_DATA12),
+       PINMUX_IPSR_GPSR(IP2_15_12,     DU_DB4),
 
-       PINMUX_IPSR_DATA(IP2_19_16,     A5),
-       PINMUX_IPSR_DATA(IP2_19_16,     LCDOUT21),
+       PINMUX_IPSR_GPSR(IP2_19_16,     A5),
+       PINMUX_IPSR_GPSR(IP2_19_16,     LCDOUT21),
        PINMUX_IPSR_MSEL(IP2_19_16,     MSIOF3_SS2_B,           SEL_MSIOF3_1),
        PINMUX_IPSR_MSEL(IP2_19_16,     SCK4_B,                 SEL_SCIF4_1),
-       PINMUX_IPSR_DATA(IP2_19_16,     VI4_DATA13),
-       PINMUX_IPSR_DATA(IP2_19_16,     VI5_DATA13),
-       PINMUX_IPSR_DATA(IP2_19_16,     DU_DB5),
+       PINMUX_IPSR_GPSR(IP2_19_16,     VI4_DATA13),
+       PINMUX_IPSR_GPSR(IP2_19_16,     VI5_DATA13),
+       PINMUX_IPSR_GPSR(IP2_19_16,     DU_DB5),
 
-       PINMUX_IPSR_DATA(IP2_23_20,     A6),
-       PINMUX_IPSR_DATA(IP2_23_20,     LCDOUT22),
+       PINMUX_IPSR_GPSR(IP2_23_20,     A6),
+       PINMUX_IPSR_GPSR(IP2_23_20,     LCDOUT22),
        PINMUX_IPSR_MSEL(IP2_23_20,     MSIOF2_SS1_A,           SEL_MSIOF2_0),
        PINMUX_IPSR_MSEL(IP2_23_20,     RX4_B,                  SEL_SCIF4_1),
-       PINMUX_IPSR_DATA(IP2_23_20,     VI4_DATA14),
-       PINMUX_IPSR_DATA(IP2_23_20,     VI5_DATA14),
-       PINMUX_IPSR_DATA(IP2_23_20,     DU_DB6),
+       PINMUX_IPSR_GPSR(IP2_23_20,     VI4_DATA14),
+       PINMUX_IPSR_GPSR(IP2_23_20,     VI5_DATA14),
+       PINMUX_IPSR_GPSR(IP2_23_20,     DU_DB6),
 
-       PINMUX_IPSR_DATA(IP2_27_24,     A7),
-       PINMUX_IPSR_DATA(IP2_27_24,     LCDOUT23),
+       PINMUX_IPSR_GPSR(IP2_27_24,     A7),
+       PINMUX_IPSR_GPSR(IP2_27_24,     LCDOUT23),
        PINMUX_IPSR_MSEL(IP2_27_24,     MSIOF2_SS2_A,           SEL_MSIOF2_0),
        PINMUX_IPSR_MSEL(IP2_27_24,     TX4_B,                  SEL_SCIF4_1),
-       PINMUX_IPSR_DATA(IP2_27_24,     VI4_DATA15),
-       PINMUX_IPSR_DATA(IP2_27_24,     VI5_DATA15),
-       PINMUX_IPSR_DATA(IP2_27_24,     DU_DB7),
+       PINMUX_IPSR_GPSR(IP2_27_24,     VI4_DATA15),
+       PINMUX_IPSR_GPSR(IP2_27_24,     VI5_DATA15),
+       PINMUX_IPSR_GPSR(IP2_27_24,     DU_DB7),
 
-       PINMUX_IPSR_DATA(IP2_31_28,     A8),
+       PINMUX_IPSR_GPSR(IP2_31_28,     A8),
        PINMUX_IPSR_MSEL(IP2_31_28,     RX3_B,                  SEL_SCIF3_1),
        PINMUX_IPSR_MSEL(IP2_31_28,     MSIOF2_SYNC_A,          SEL_MSIOF2_0),
        PINMUX_IPSR_MSEL(IP2_31_28,     HRX4_B,                 SEL_HSCIF4_1),
@@ -720,99 +719,99 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP2_31_28,     PWM1_B,                 SEL_PWM1_1),
 
        /* IPSR3 */
-       PINMUX_IPSR_DATA(IP3_3_0,       A9),
+       PINMUX_IPSR_GPSR(IP3_3_0,       A9),
        PINMUX_IPSR_MSEL(IP3_3_0,       MSIOF2_SCK_A,           SEL_MSIOF2_0),
        PINMUX_IPSR_MSEL(IP3_3_0,       CTS4_N_B,               SEL_SCIF4_1),
-       PINMUX_IPSR_DATA(IP3_3_0,       VI5_VSYNC_N),
+       PINMUX_IPSR_GPSR(IP3_3_0,       VI5_VSYNC_N),
 
-       PINMUX_IPSR_DATA(IP3_7_4,       A10),
+       PINMUX_IPSR_GPSR(IP3_7_4,       A10),
        PINMUX_IPSR_MSEL(IP3_7_4,       MSIOF2_RXD_A,           SEL_MSIOF2_0),
        PINMUX_IPSR_MSEL(IP3_7_4,       RTS4_N_TANS_B,          SEL_SCIF4_1),
-       PINMUX_IPSR_DATA(IP3_7_4,       VI5_HSYNC_N),
+       PINMUX_IPSR_GPSR(IP3_7_4,       VI5_HSYNC_N),
 
-       PINMUX_IPSR_DATA(IP3_11_8,      A11),
+       PINMUX_IPSR_GPSR(IP3_11_8,      A11),
        PINMUX_IPSR_MSEL(IP3_11_8,      TX3_B,                  SEL_SCIF3_1),
        PINMUX_IPSR_MSEL(IP3_11_8,      MSIOF2_TXD_A,           SEL_MSIOF2_0),
        PINMUX_IPSR_MSEL(IP3_11_8,      HTX4_B,                 SEL_HSCIF4_1),
-       PINMUX_IPSR_DATA(IP3_11_8,      HSCK4),
-       PINMUX_IPSR_DATA(IP3_11_8,      VI5_FIELD),
+       PINMUX_IPSR_GPSR(IP3_11_8,      HSCK4),
+       PINMUX_IPSR_GPSR(IP3_11_8,      VI5_FIELD),
        PINMUX_IPSR_MSEL(IP3_11_8,      SCL6_A,                 SEL_I2C6_0),
        PINMUX_IPSR_MSEL(IP3_11_8,      AVB_AVTP_CAPTURE_B,     SEL_ETHERAVB_1),
        PINMUX_IPSR_MSEL(IP3_11_8,      PWM2_B,                 SEL_PWM2_1),
 
-       PINMUX_IPSR_DATA(IP3_15_12,     A12),
-       PINMUX_IPSR_DATA(IP3_15_12,     LCDOUT12),
+       PINMUX_IPSR_GPSR(IP3_15_12,     A12),
+       PINMUX_IPSR_GPSR(IP3_15_12,     LCDOUT12),
        PINMUX_IPSR_MSEL(IP3_15_12,     MSIOF3_SCK_C,           SEL_MSIOF3_2),
        PINMUX_IPSR_MSEL(IP3_15_12,     HRX4_A,                 SEL_HSCIF4_0),
-       PINMUX_IPSR_DATA(IP3_15_12,     VI5_DATA8),
-       PINMUX_IPSR_DATA(IP3_15_12,     DU_DG4),
+       PINMUX_IPSR_GPSR(IP3_15_12,     VI5_DATA8),
+       PINMUX_IPSR_GPSR(IP3_15_12,     DU_DG4),
 
-       PINMUX_IPSR_DATA(IP3_19_16,     A13),
-       PINMUX_IPSR_DATA(IP3_19_16,     LCDOUT13),
+       PINMUX_IPSR_GPSR(IP3_19_16,     A13),
+       PINMUX_IPSR_GPSR(IP3_19_16,     LCDOUT13),
        PINMUX_IPSR_MSEL(IP3_19_16,     MSIOF3_SYNC_C,          SEL_MSIOF3_2),
        PINMUX_IPSR_MSEL(IP3_19_16,     HTX4_A,                 SEL_HSCIF4_0),
-       PINMUX_IPSR_DATA(IP3_19_16,     VI5_DATA9),
-       PINMUX_IPSR_DATA(IP3_19_16,     DU_DG5),
+       PINMUX_IPSR_GPSR(IP3_19_16,     VI5_DATA9),
+       PINMUX_IPSR_GPSR(IP3_19_16,     DU_DG5),
 
-       PINMUX_IPSR_DATA(IP3_23_20,     A14),
-       PINMUX_IPSR_DATA(IP3_23_20,     LCDOUT14),
+       PINMUX_IPSR_GPSR(IP3_23_20,     A14),
+       PINMUX_IPSR_GPSR(IP3_23_20,     LCDOUT14),
        PINMUX_IPSR_MSEL(IP3_23_20,     MSIOF3_RXD_C,           SEL_MSIOF3_2),
-       PINMUX_IPSR_DATA(IP3_23_20,     HCTS4_N),
-       PINMUX_IPSR_DATA(IP3_23_20,     VI5_DATA10),
-       PINMUX_IPSR_DATA(IP3_23_20,     DU_DG6),
+       PINMUX_IPSR_GPSR(IP3_23_20,     HCTS4_N),
+       PINMUX_IPSR_GPSR(IP3_23_20,     VI5_DATA10),
+       PINMUX_IPSR_GPSR(IP3_23_20,     DU_DG6),
 
-       PINMUX_IPSR_DATA(IP3_27_24,     A15),
-       PINMUX_IPSR_DATA(IP3_27_24,     LCDOUT15),
+       PINMUX_IPSR_GPSR(IP3_27_24,     A15),
+       PINMUX_IPSR_GPSR(IP3_27_24,     LCDOUT15),
        PINMUX_IPSR_MSEL(IP3_27_24,     MSIOF3_TXD_C,           SEL_MSIOF3_2),
-       PINMUX_IPSR_DATA(IP3_27_24,     HRTS4_N),
-       PINMUX_IPSR_DATA(IP3_27_24,     VI5_DATA11),
-       PINMUX_IPSR_DATA(IP3_27_24,     DU_DG7),
+       PINMUX_IPSR_GPSR(IP3_27_24,     HRTS4_N),
+       PINMUX_IPSR_GPSR(IP3_27_24,     VI5_DATA11),
+       PINMUX_IPSR_GPSR(IP3_27_24,     DU_DG7),
 
-       PINMUX_IPSR_DATA(IP3_31_28,     A16),
-       PINMUX_IPSR_DATA(IP3_31_28,     LCDOUT8),
-       PINMUX_IPSR_DATA(IP3_31_28,     VI4_FIELD),
-       PINMUX_IPSR_DATA(IP3_31_28,     DU_DG0),
+       PINMUX_IPSR_GPSR(IP3_31_28,     A16),
+       PINMUX_IPSR_GPSR(IP3_31_28,     LCDOUT8),
+       PINMUX_IPSR_GPSR(IP3_31_28,     VI4_FIELD),
+       PINMUX_IPSR_GPSR(IP3_31_28,     DU_DG0),
 
        /* IPSR4 */
-       PINMUX_IPSR_DATA(IP4_3_0,       A17),
-       PINMUX_IPSR_DATA(IP4_3_0,       LCDOUT9),
-       PINMUX_IPSR_DATA(IP4_3_0,       VI4_VSYNC_N),
-       PINMUX_IPSR_DATA(IP4_3_0,       DU_DG1),
-
-       PINMUX_IPSR_DATA(IP4_7_4,       A18),
-       PINMUX_IPSR_DATA(IP4_7_4,       LCDOUT10),
-       PINMUX_IPSR_DATA(IP4_7_4,       VI4_HSYNC_N),
-       PINMUX_IPSR_DATA(IP4_7_4,       DU_DG2),
-
-       PINMUX_IPSR_DATA(IP4_11_8,      A19),
-       PINMUX_IPSR_DATA(IP4_11_8,      LCDOUT11),
-       PINMUX_IPSR_DATA(IP4_11_8,      VI4_CLKENB),
-       PINMUX_IPSR_DATA(IP4_11_8,      DU_DG3),
-
-       PINMUX_IPSR_DATA(IP4_15_12,     CS0_N),
-       PINMUX_IPSR_DATA(IP4_15_12,     VI5_CLKENB),
-
-       PINMUX_IPSR_DATA(IP4_19_16,     CS1_N_A26),
-       PINMUX_IPSR_DATA(IP4_19_16,     VI5_CLK),
+       PINMUX_IPSR_GPSR(IP4_3_0,       A17),
+       PINMUX_IPSR_GPSR(IP4_3_0,       LCDOUT9),
+       PINMUX_IPSR_GPSR(IP4_3_0,       VI4_VSYNC_N),
+       PINMUX_IPSR_GPSR(IP4_3_0,       DU_DG1),
+
+       PINMUX_IPSR_GPSR(IP4_7_4,       A18),
+       PINMUX_IPSR_GPSR(IP4_7_4,       LCDOUT10),
+       PINMUX_IPSR_GPSR(IP4_7_4,       VI4_HSYNC_N),
+       PINMUX_IPSR_GPSR(IP4_7_4,       DU_DG2),
+
+       PINMUX_IPSR_GPSR(IP4_11_8,      A19),
+       PINMUX_IPSR_GPSR(IP4_11_8,      LCDOUT11),
+       PINMUX_IPSR_GPSR(IP4_11_8,      VI4_CLKENB),
+       PINMUX_IPSR_GPSR(IP4_11_8,      DU_DG3),
+
+       PINMUX_IPSR_GPSR(IP4_15_12,     CS0_N),
+       PINMUX_IPSR_GPSR(IP4_15_12,     VI5_CLKENB),
+
+       PINMUX_IPSR_GPSR(IP4_19_16,     CS1_N_A26),
+       PINMUX_IPSR_GPSR(IP4_19_16,     VI5_CLK),
        PINMUX_IPSR_MSEL(IP4_19_16,     EX_WAIT0_B,             SEL_LBSC_1),
 
-       PINMUX_IPSR_DATA(IP4_23_20,     BS_N),
-       PINMUX_IPSR_DATA(IP4_23_20,     QSTVA_QVS),
+       PINMUX_IPSR_GPSR(IP4_23_20,     BS_N),
+       PINMUX_IPSR_GPSR(IP4_23_20,     QSTVA_QVS),
        PINMUX_IPSR_MSEL(IP4_23_20,     MSIOF3_SCK_D,           SEL_MSIOF3_3),
-       PINMUX_IPSR_DATA(IP4_23_20,     SCK3),
-       PINMUX_IPSR_DATA(IP4_23_20,     HSCK3),
-       PINMUX_IPSR_DATA(IP4_23_20,     CAN1_TX),
-       PINMUX_IPSR_DATA(IP4_23_20,     CANFD1_TX),
+       PINMUX_IPSR_GPSR(IP4_23_20,     SCK3),
+       PINMUX_IPSR_GPSR(IP4_23_20,     HSCK3),
+       PINMUX_IPSR_GPSR(IP4_23_20,     CAN1_TX),
+       PINMUX_IPSR_GPSR(IP4_23_20,     CANFD1_TX),
        PINMUX_IPSR_MSEL(IP4_23_20,     IETX_A,                 SEL_IEBUS_0),
 
-       PINMUX_IPSR_DATA(IP4_27_24,     RD_N),
+       PINMUX_IPSR_GPSR(IP4_27_24,     RD_N),
        PINMUX_IPSR_MSEL(IP4_27_24,     MSIOF3_SYNC_D,          SEL_MSIOF3_3),
        PINMUX_IPSR_MSEL(IP4_27_24,     RX3_A,                  SEL_SCIF3_0),
        PINMUX_IPSR_MSEL(IP4_27_24,     HRX3_A,                 SEL_HSCIF3_0),
        PINMUX_IPSR_MSEL(IP4_27_24,     CAN0_TX_A,              SEL_RCAN0_0),
        PINMUX_IPSR_MSEL(IP4_27_24,     CANFD0_TX_A,            SEL_CANFD0_0),
 
-       PINMUX_IPSR_DATA(IP4_31_28,     RD_WR_N),
+       PINMUX_IPSR_GPSR(IP4_31_28,     RD_WR_N),
        PINMUX_IPSR_MSEL(IP4_31_28,     MSIOF3_RXD_D,           SEL_MSIOF3_3),
        PINMUX_IPSR_MSEL(IP4_31_28,     TX3_A,                  SEL_SCIF3_0),
        PINMUX_IPSR_MSEL(IP4_31_28,     HTX3_A,                 SEL_HSCIF3_0),
@@ -820,236 +819,236 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP4_31_28,     CANFD0_RX_A,            SEL_CANFD0_0),
 
        /* IPSR5 */
-       PINMUX_IPSR_DATA(IP5_3_0,       WE0_N),
+       PINMUX_IPSR_GPSR(IP5_3_0,       WE0_N),
        PINMUX_IPSR_MSEL(IP5_3_0,       MSIOF3_TXD_D,           SEL_MSIOF3_3),
-       PINMUX_IPSR_DATA(IP5_3_0,       CTS3_N),
-       PINMUX_IPSR_DATA(IP5_3_0,       HCTS3_N),
+       PINMUX_IPSR_GPSR(IP5_3_0,       CTS3_N),
+       PINMUX_IPSR_GPSR(IP5_3_0,       HCTS3_N),
        PINMUX_IPSR_MSEL(IP5_3_0,       SCL6_B,                 SEL_I2C6_1),
-       PINMUX_IPSR_DATA(IP5_3_0,       CAN_CLK),
+       PINMUX_IPSR_GPSR(IP5_3_0,       CAN_CLK),
        PINMUX_IPSR_MSEL(IP5_3_0,       IECLK_A,                SEL_IEBUS_0),
 
-       PINMUX_IPSR_DATA(IP5_7_4,       WE1_N),
+       PINMUX_IPSR_GPSR(IP5_7_4,       WE1_N),
        PINMUX_IPSR_MSEL(IP5_7_4,       MSIOF3_SS1_D,           SEL_MSIOF3_3),
-       PINMUX_IPSR_DATA(IP5_7_4,       RTS3_N_TANS),
-       PINMUX_IPSR_DATA(IP5_7_4,       HRTS3_N),
+       PINMUX_IPSR_GPSR(IP5_7_4,       RTS3_N_TANS),
+       PINMUX_IPSR_GPSR(IP5_7_4,       HRTS3_N),
        PINMUX_IPSR_MSEL(IP5_7_4,       SDA6_B,                 SEL_I2C6_1),
-       PINMUX_IPSR_DATA(IP5_7_4,       CAN1_RX),
-       PINMUX_IPSR_DATA(IP5_7_4,       CANFD1_RX),
+       PINMUX_IPSR_GPSR(IP5_7_4,       CAN1_RX),
+       PINMUX_IPSR_GPSR(IP5_7_4,       CANFD1_RX),
        PINMUX_IPSR_MSEL(IP5_7_4,       IERX_A,                 SEL_IEBUS_0),
 
        PINMUX_IPSR_MSEL(IP5_11_8,      EX_WAIT0_A,             SEL_LBSC_0),
-       PINMUX_IPSR_DATA(IP5_11_8,      QCLK),
-       PINMUX_IPSR_DATA(IP5_11_8,      VI4_CLK),
-       PINMUX_IPSR_DATA(IP5_11_8,      DU_DOTCLKOUT0),
+       PINMUX_IPSR_GPSR(IP5_11_8,      QCLK),
+       PINMUX_IPSR_GPSR(IP5_11_8,      VI4_CLK),
+       PINMUX_IPSR_GPSR(IP5_11_8,      DU_DOTCLKOUT0),
 
-       PINMUX_IPSR_DATA(IP5_15_12,     D0),
+       PINMUX_IPSR_GPSR(IP5_15_12,     D0),
        PINMUX_IPSR_MSEL(IP5_15_12,     MSIOF2_SS1_B,           SEL_MSIOF2_1),
        PINMUX_IPSR_MSEL(IP5_15_12,     MSIOF3_SCK_A,           SEL_MSIOF3_0),
-       PINMUX_IPSR_DATA(IP5_15_12,     VI4_DATA16),
-       PINMUX_IPSR_DATA(IP5_15_12,     VI5_DATA0),
+       PINMUX_IPSR_GPSR(IP5_15_12,     VI4_DATA16),
+       PINMUX_IPSR_GPSR(IP5_15_12,     VI5_DATA0),
 
-       PINMUX_IPSR_DATA(IP5_19_16,     D1),
+       PINMUX_IPSR_GPSR(IP5_19_16,     D1),
        PINMUX_IPSR_MSEL(IP5_19_16,     MSIOF2_SS2_B,           SEL_MSIOF2_1),
        PINMUX_IPSR_MSEL(IP5_19_16,     MSIOF3_SYNC_A,          SEL_MSIOF3_0),
-       PINMUX_IPSR_DATA(IP5_19_16,     VI4_DATA17),
-       PINMUX_IPSR_DATA(IP5_19_16,     VI5_DATA1),
+       PINMUX_IPSR_GPSR(IP5_19_16,     VI4_DATA17),
+       PINMUX_IPSR_GPSR(IP5_19_16,     VI5_DATA1),
 
-       PINMUX_IPSR_DATA(IP5_23_20,     D2),
+       PINMUX_IPSR_GPSR(IP5_23_20,     D2),
        PINMUX_IPSR_MSEL(IP5_23_20,     MSIOF3_RXD_A,           SEL_MSIOF3_0),
-       PINMUX_IPSR_DATA(IP5_23_20,     VI4_DATA18),
-       PINMUX_IPSR_DATA(IP5_23_20,     VI5_DATA2),
+       PINMUX_IPSR_GPSR(IP5_23_20,     VI4_DATA18),
+       PINMUX_IPSR_GPSR(IP5_23_20,     VI5_DATA2),
 
-       PINMUX_IPSR_DATA(IP5_27_24,     D3),
+       PINMUX_IPSR_GPSR(IP5_27_24,     D3),
        PINMUX_IPSR_MSEL(IP5_27_24,     MSIOF3_TXD_A,           SEL_MSIOF3_0),
-       PINMUX_IPSR_DATA(IP5_27_24,     VI4_DATA19),
-       PINMUX_IPSR_DATA(IP5_27_24,     VI5_DATA3),
+       PINMUX_IPSR_GPSR(IP5_27_24,     VI4_DATA19),
+       PINMUX_IPSR_GPSR(IP5_27_24,     VI5_DATA3),
 
-       PINMUX_IPSR_DATA(IP5_31_28,     D4),
+       PINMUX_IPSR_GPSR(IP5_31_28,     D4),
        PINMUX_IPSR_MSEL(IP5_31_28,     MSIOF2_SCK_B,           SEL_MSIOF2_1),
-       PINMUX_IPSR_DATA(IP5_31_28,     VI4_DATA20),
-       PINMUX_IPSR_DATA(IP5_31_28,     VI5_DATA4),
+       PINMUX_IPSR_GPSR(IP5_31_28,     VI4_DATA20),
+       PINMUX_IPSR_GPSR(IP5_31_28,     VI5_DATA4),
 
        /* IPSR6 */
-       PINMUX_IPSR_DATA(IP6_3_0,       D5),
+       PINMUX_IPSR_GPSR(IP6_3_0,       D5),
        PINMUX_IPSR_MSEL(IP6_3_0,       MSIOF2_SYNC_B,          SEL_MSIOF2_1),
-       PINMUX_IPSR_DATA(IP6_3_0,       VI4_DATA21),
-       PINMUX_IPSR_DATA(IP6_3_0,       VI5_DATA5),
+       PINMUX_IPSR_GPSR(IP6_3_0,       VI4_DATA21),
+       PINMUX_IPSR_GPSR(IP6_3_0,       VI5_DATA5),
 
-       PINMUX_IPSR_DATA(IP6_7_4,       D6),
+       PINMUX_IPSR_GPSR(IP6_7_4,       D6),
        PINMUX_IPSR_MSEL(IP6_7_4,       MSIOF2_RXD_B,           SEL_MSIOF2_1),
-       PINMUX_IPSR_DATA(IP6_7_4,       VI4_DATA22),
-       PINMUX_IPSR_DATA(IP6_7_4,       VI5_DATA6),
+       PINMUX_IPSR_GPSR(IP6_7_4,       VI4_DATA22),
+       PINMUX_IPSR_GPSR(IP6_7_4,       VI5_DATA6),
 
-       PINMUX_IPSR_DATA(IP6_11_8,      D7),
+       PINMUX_IPSR_GPSR(IP6_11_8,      D7),
        PINMUX_IPSR_MSEL(IP6_11_8,      MSIOF2_TXD_B,           SEL_MSIOF2_1),
-       PINMUX_IPSR_DATA(IP6_11_8,      VI4_DATA23),
-       PINMUX_IPSR_DATA(IP6_11_8,      VI5_DATA7),
+       PINMUX_IPSR_GPSR(IP6_11_8,      VI4_DATA23),
+       PINMUX_IPSR_GPSR(IP6_11_8,      VI5_DATA7),
 
-       PINMUX_IPSR_DATA(IP6_15_12,     D8),
-       PINMUX_IPSR_DATA(IP6_15_12,     LCDOUT0),
+       PINMUX_IPSR_GPSR(IP6_15_12,     D8),
+       PINMUX_IPSR_GPSR(IP6_15_12,     LCDOUT0),
        PINMUX_IPSR_MSEL(IP6_15_12,     MSIOF2_SCK_D,           SEL_MSIOF2_3),
        PINMUX_IPSR_MSEL(IP6_15_12,     SCK4_C,                 SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP6_15_12,     VI4_DATA0_A,            SEL_VIN4_0),
-       PINMUX_IPSR_DATA(IP6_15_12,     DU_DR0),
+       PINMUX_IPSR_GPSR(IP6_15_12,     DU_DR0),
 
-       PINMUX_IPSR_DATA(IP6_19_16,     D9),
-       PINMUX_IPSR_DATA(IP6_19_16,     LCDOUT1),
+       PINMUX_IPSR_GPSR(IP6_19_16,     D9),
+       PINMUX_IPSR_GPSR(IP6_19_16,     LCDOUT1),
        PINMUX_IPSR_MSEL(IP6_19_16,     MSIOF2_SYNC_D,          SEL_MSIOF2_3),
        PINMUX_IPSR_MSEL(IP6_19_16,     VI4_DATA1_A,            SEL_VIN4_0),
-       PINMUX_IPSR_DATA(IP6_19_16,     DU_DR1),
+       PINMUX_IPSR_GPSR(IP6_19_16,     DU_DR1),
 
-       PINMUX_IPSR_DATA(IP6_23_20,     D10),
-       PINMUX_IPSR_DATA(IP6_23_20,     LCDOUT2),
+       PINMUX_IPSR_GPSR(IP6_23_20,     D10),
+       PINMUX_IPSR_GPSR(IP6_23_20,     LCDOUT2),
        PINMUX_IPSR_MSEL(IP6_23_20,     MSIOF2_RXD_D,           SEL_MSIOF2_3),
        PINMUX_IPSR_MSEL(IP6_23_20,     HRX3_B,                 SEL_HSCIF3_1),
        PINMUX_IPSR_MSEL(IP6_23_20,     VI4_DATA2_A,            SEL_VIN4_0),
        PINMUX_IPSR_MSEL(IP6_23_20,     CTS4_N_C,               SEL_SCIF4_2),
-       PINMUX_IPSR_DATA(IP6_23_20,     DU_DR2),
+       PINMUX_IPSR_GPSR(IP6_23_20,     DU_DR2),
 
-       PINMUX_IPSR_DATA(IP6_27_24,     D11),
-       PINMUX_IPSR_DATA(IP6_27_24,     LCDOUT3),
+       PINMUX_IPSR_GPSR(IP6_27_24,     D11),
+       PINMUX_IPSR_GPSR(IP6_27_24,     LCDOUT3),
        PINMUX_IPSR_MSEL(IP6_27_24,     MSIOF2_TXD_D,           SEL_MSIOF2_3),
        PINMUX_IPSR_MSEL(IP6_27_24,     HTX3_B,                 SEL_HSCIF3_1),
        PINMUX_IPSR_MSEL(IP6_27_24,     VI4_DATA3_A,            SEL_VIN4_0),
        PINMUX_IPSR_MSEL(IP6_27_24,     RTS4_N_TANS_C,          SEL_SCIF4_2),
-       PINMUX_IPSR_DATA(IP6_27_24,     DU_DR3),
+       PINMUX_IPSR_GPSR(IP6_27_24,     DU_DR3),
 
-       PINMUX_IPSR_DATA(IP6_31_28,     D12),
-       PINMUX_IPSR_DATA(IP6_31_28,     LCDOUT4),
+       PINMUX_IPSR_GPSR(IP6_31_28,     D12),
+       PINMUX_IPSR_GPSR(IP6_31_28,     LCDOUT4),
        PINMUX_IPSR_MSEL(IP6_31_28,     MSIOF2_SS1_D,           SEL_MSIOF2_3),
        PINMUX_IPSR_MSEL(IP6_31_28,     RX4_C,                  SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP6_31_28,     VI4_DATA4_A,            SEL_VIN4_0),
-       PINMUX_IPSR_DATA(IP6_31_28,     DU_DR4),
+       PINMUX_IPSR_GPSR(IP6_31_28,     DU_DR4),
 
        /* IPSR7 */
-       PINMUX_IPSR_DATA(IP7_3_0,       D13),
-       PINMUX_IPSR_DATA(IP7_3_0,       LCDOUT5),
+       PINMUX_IPSR_GPSR(IP7_3_0,       D13),
+       PINMUX_IPSR_GPSR(IP7_3_0,       LCDOUT5),
        PINMUX_IPSR_MSEL(IP7_3_0,       MSIOF2_SS2_D,           SEL_MSIOF2_3),
        PINMUX_IPSR_MSEL(IP7_3_0,       TX4_C,                  SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP7_3_0,       VI4_DATA5_A,            SEL_VIN4_0),
-       PINMUX_IPSR_DATA(IP7_3_0,       DU_DR5),
+       PINMUX_IPSR_GPSR(IP7_3_0,       DU_DR5),
 
-       PINMUX_IPSR_DATA(IP7_7_4,       D14),
-       PINMUX_IPSR_DATA(IP7_7_4,       LCDOUT6),
+       PINMUX_IPSR_GPSR(IP7_7_4,       D14),
+       PINMUX_IPSR_GPSR(IP7_7_4,       LCDOUT6),
        PINMUX_IPSR_MSEL(IP7_7_4,       MSIOF3_SS1_A,           SEL_MSIOF3_0),
        PINMUX_IPSR_MSEL(IP7_7_4,       HRX3_C,                 SEL_HSCIF3_2),
        PINMUX_IPSR_MSEL(IP7_7_4,       VI4_DATA6_A,            SEL_VIN4_0),
-       PINMUX_IPSR_DATA(IP7_7_4,       DU_DR6),
+       PINMUX_IPSR_GPSR(IP7_7_4,       DU_DR6),
        PINMUX_IPSR_MSEL(IP7_7_4,       SCL6_C,                 SEL_I2C6_2),
 
-       PINMUX_IPSR_DATA(IP7_11_8,      D15),
-       PINMUX_IPSR_DATA(IP7_11_8,      LCDOUT7),
+       PINMUX_IPSR_GPSR(IP7_11_8,      D15),
+       PINMUX_IPSR_GPSR(IP7_11_8,      LCDOUT7),
        PINMUX_IPSR_MSEL(IP7_11_8,      MSIOF3_SS2_A,           SEL_MSIOF3_0),
        PINMUX_IPSR_MSEL(IP7_11_8,      HTX3_C,                 SEL_HSCIF3_2),
        PINMUX_IPSR_MSEL(IP7_11_8,      VI4_DATA7_A,            SEL_VIN4_0),
-       PINMUX_IPSR_DATA(IP7_11_8,      DU_DR7),
+       PINMUX_IPSR_GPSR(IP7_11_8,      DU_DR7),
        PINMUX_IPSR_MSEL(IP7_11_8,      SDA6_C,                 SEL_I2C6_2),
 
-       PINMUX_IPSR_DATA(IP7_15_12,     FSCLKST),
+       PINMUX_IPSR_GPSR(IP7_15_12,     FSCLKST),
 
-       PINMUX_IPSR_DATA(IP7_19_16,     SD0_CLK),
+       PINMUX_IPSR_GPSR(IP7_19_16,     SD0_CLK),
        PINMUX_IPSR_MSEL(IP7_19_16,     MSIOF1_SCK_E,           SEL_MSIOF1_4),
        PINMUX_IPSR_MSEL(IP7_19_16,     STP_OPWM_0_B,           SEL_SSP1_0_1),
 
-       PINMUX_IPSR_DATA(IP7_23_20,     SD0_CMD),
+       PINMUX_IPSR_GPSR(IP7_23_20,     SD0_CMD),
        PINMUX_IPSR_MSEL(IP7_23_20,     MSIOF1_SYNC_E,          SEL_MSIOF1_4),
        PINMUX_IPSR_MSEL(IP7_23_20,     STP_IVCXO27_0_B,        SEL_SSP1_0_1),
 
-       PINMUX_IPSR_DATA(IP7_27_24,     SD0_DAT0),
+       PINMUX_IPSR_GPSR(IP7_27_24,     SD0_DAT0),
        PINMUX_IPSR_MSEL(IP7_27_24,     MSIOF1_RXD_E,           SEL_MSIOF1_4),
        PINMUX_IPSR_MSEL(IP7_27_24,     TS_SCK0_B,              SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP7_27_24,     STP_ISCLK_0_B,          SEL_SSP1_0_1),
 
-       PINMUX_IPSR_DATA(IP7_31_28,     SD0_DAT1),
+       PINMUX_IPSR_GPSR(IP7_31_28,     SD0_DAT1),
        PINMUX_IPSR_MSEL(IP7_31_28,     MSIOF1_TXD_E,           SEL_MSIOF1_4),
        PINMUX_IPSR_MSEL(IP7_31_28,     TS_SPSYNC0_B,           SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP7_31_28,     STP_ISSYNC_0_B,         SEL_SSP1_0_1),
 
        /* IPSR8 */
-       PINMUX_IPSR_DATA(IP8_3_0,       SD0_DAT2),
+       PINMUX_IPSR_GPSR(IP8_3_0,       SD0_DAT2),
        PINMUX_IPSR_MSEL(IP8_3_0,       MSIOF1_SS1_E,           SEL_MSIOF1_4),
        PINMUX_IPSR_MSEL(IP8_3_0,       TS_SDAT0_B,             SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP8_3_0,       STP_ISD_0_B,            SEL_SSP1_0_1),
 
-       PINMUX_IPSR_DATA(IP8_7_4,       SD0_DAT3),
+       PINMUX_IPSR_GPSR(IP8_7_4,       SD0_DAT3),
        PINMUX_IPSR_MSEL(IP8_7_4,       MSIOF1_SS2_E,           SEL_MSIOF1_4),
        PINMUX_IPSR_MSEL(IP8_7_4,       TS_SDEN0_B,             SEL_TSIF0_1),
        PINMUX_IPSR_MSEL(IP8_7_4,       STP_ISEN_0_B,           SEL_SSP1_0_1),
 
-       PINMUX_IPSR_DATA(IP8_11_8,      SD1_CLK),
+       PINMUX_IPSR_GPSR(IP8_11_8,      SD1_CLK),
        PINMUX_IPSR_MSEL(IP8_11_8,      MSIOF1_SCK_G,           SEL_MSIOF1_6),
        PINMUX_IPSR_MSEL(IP8_11_8,      SIM0_CLK_A,             SEL_SIMCARD_0),
 
-       PINMUX_IPSR_DATA(IP8_15_12,     SD1_CMD),
+       PINMUX_IPSR_GPSR(IP8_15_12,     SD1_CMD),
        PINMUX_IPSR_MSEL(IP8_15_12,     MSIOF1_SYNC_G,          SEL_MSIOF1_6),
        PINMUX_IPSR_MSEL(IP8_15_12,     SIM0_D_A,               SEL_SIMCARD_0),
        PINMUX_IPSR_MSEL(IP8_15_12,     STP_IVCXO27_1_B,        SEL_SSP1_1_1),
 
-       PINMUX_IPSR_DATA(IP8_19_16,     SD1_DAT0),
-       PINMUX_IPSR_DATA(IP8_19_16,     SD2_DAT4),
+       PINMUX_IPSR_GPSR(IP8_19_16,     SD1_DAT0),
+       PINMUX_IPSR_GPSR(IP8_19_16,     SD2_DAT4),
        PINMUX_IPSR_MSEL(IP8_19_16,     MSIOF1_RXD_G,           SEL_MSIOF1_6),
        PINMUX_IPSR_MSEL(IP8_19_16,     TS_SCK1_B,              SEL_TSIF1_1),
        PINMUX_IPSR_MSEL(IP8_19_16,     STP_ISCLK_1_B,          SEL_SSP1_1_1),
 
-       PINMUX_IPSR_DATA(IP8_23_20,     SD1_DAT1),
-       PINMUX_IPSR_DATA(IP8_23_20,     SD2_DAT5),
+       PINMUX_IPSR_GPSR(IP8_23_20,     SD1_DAT1),
+       PINMUX_IPSR_GPSR(IP8_23_20,     SD2_DAT5),
        PINMUX_IPSR_MSEL(IP8_23_20,     MSIOF1_TXD_G,           SEL_MSIOF1_6),
        PINMUX_IPSR_MSEL(IP8_23_20,     TS_SPSYNC1_B,           SEL_TSIF1_1),
        PINMUX_IPSR_MSEL(IP8_23_20,     STP_ISSYNC_1_B,         SEL_SSP1_1_1),
 
-       PINMUX_IPSR_DATA(IP8_27_24,     SD1_DAT2),
-       PINMUX_IPSR_DATA(IP8_27_24,     SD2_DAT6),
+       PINMUX_IPSR_GPSR(IP8_27_24,     SD1_DAT2),
+       PINMUX_IPSR_GPSR(IP8_27_24,     SD2_DAT6),
        PINMUX_IPSR_MSEL(IP8_27_24,     MSIOF1_SS1_G,           SEL_MSIOF1_6),
        PINMUX_IPSR_MSEL(IP8_27_24,     TS_SDAT1_B,             SEL_TSIF1_1),
        PINMUX_IPSR_MSEL(IP8_27_24,     STP_ISD_1_B,            SEL_SSP1_1_1),
 
-       PINMUX_IPSR_DATA(IP8_31_28,     SD1_DAT3),
-       PINMUX_IPSR_DATA(IP8_31_28,     SD2_DAT7),
+       PINMUX_IPSR_GPSR(IP8_31_28,     SD1_DAT3),
+       PINMUX_IPSR_GPSR(IP8_31_28,     SD2_DAT7),
        PINMUX_IPSR_MSEL(IP8_31_28,     MSIOF1_SS2_G,           SEL_MSIOF1_6),
        PINMUX_IPSR_MSEL(IP8_31_28,     TS_SDEN1_B,             SEL_TSIF1_1),
        PINMUX_IPSR_MSEL(IP8_31_28,     STP_ISEN_1_B,           SEL_SSP1_1_1),
 
        /* IPSR9 */
-       PINMUX_IPSR_DATA(IP9_3_0,       SD2_CLK),
+       PINMUX_IPSR_GPSR(IP9_3_0,       SD2_CLK),
 
-       PINMUX_IPSR_DATA(IP9_7_4,       SD2_DAT0),
+       PINMUX_IPSR_GPSR(IP9_7_4,       SD2_DAT0),
 
-       PINMUX_IPSR_DATA(IP9_11_8,      SD2_DAT1),
+       PINMUX_IPSR_GPSR(IP9_11_8,      SD2_DAT1),
 
-       PINMUX_IPSR_DATA(IP9_15_12,     SD2_DAT2),
+       PINMUX_IPSR_GPSR(IP9_15_12,     SD2_DAT2),
 
-       PINMUX_IPSR_DATA(IP9_19_16,     SD2_DAT3),
+       PINMUX_IPSR_GPSR(IP9_19_16,     SD2_DAT3),
 
-       PINMUX_IPSR_DATA(IP9_23_20,     SD2_DS),
+       PINMUX_IPSR_GPSR(IP9_23_20,     SD2_DS),
        PINMUX_IPSR_MSEL(IP9_23_20,     SATA_DEVSLP_B,          SEL_SATA_1),
 
-       PINMUX_IPSR_DATA(IP9_27_24,     SD3_DAT4),
+       PINMUX_IPSR_GPSR(IP9_27_24,     SD3_DAT4),
        PINMUX_IPSR_MSEL(IP9_27_24,     SD2_CD_A,               SEL_SDHI2_0),
 
-       PINMUX_IPSR_DATA(IP9_31_28,     SD3_DAT5),
+       PINMUX_IPSR_GPSR(IP9_31_28,     SD3_DAT5),
        PINMUX_IPSR_MSEL(IP9_31_28,     SD2_WP_A,               SEL_SDHI2_0),
 
        /* IPSR10 */
-       PINMUX_IPSR_DATA(IP10_3_0,      SD3_DAT6),
-       PINMUX_IPSR_DATA(IP10_3_0,      SD3_CD),
+       PINMUX_IPSR_GPSR(IP10_3_0,      SD3_DAT6),
+       PINMUX_IPSR_GPSR(IP10_3_0,      SD3_CD),
 
-       PINMUX_IPSR_DATA(IP10_7_4,      SD3_DAT7),
-       PINMUX_IPSR_DATA(IP10_7_4,      SD3_WP),
+       PINMUX_IPSR_GPSR(IP10_7_4,      SD3_DAT7),
+       PINMUX_IPSR_GPSR(IP10_7_4,      SD3_WP),
 
-       PINMUX_IPSR_DATA(IP10_11_8,     SD0_CD),
+       PINMUX_IPSR_GPSR(IP10_11_8,     SD0_CD),
        PINMUX_IPSR_MSEL(IP10_11_8,     SCL2_B,                 SEL_I2C2_1),
        PINMUX_IPSR_MSEL(IP10_11_8,     SIM0_RST_A,             SEL_SIMCARD_0),
 
-       PINMUX_IPSR_DATA(IP10_15_12,    SD0_WP),
+       PINMUX_IPSR_GPSR(IP10_15_12,    SD0_WP),
        PINMUX_IPSR_MSEL(IP10_15_12,    SDA2_B,                 SEL_I2C2_1),
 
-       PINMUX_IPSR_DATA(IP10_19_16,    SD1_CD),
+       PINMUX_IPSR_GPSR(IP10_19_16,    SD1_CD),
        PINMUX_IPSR_MSEL(IP10_19_16,    SIM0_CLK_B,             SEL_SIMCARD_1),
 
-       PINMUX_IPSR_DATA(IP10_23_20,    SD1_WP),
+       PINMUX_IPSR_GPSR(IP10_23_20,    SD1_WP),
        PINMUX_IPSR_MSEL(IP10_23_20,    SIM0_D_B,               SEL_SIMCARD_1),
 
-       PINMUX_IPSR_DATA(IP10_27_24,    SCK0),
+       PINMUX_IPSR_GPSR(IP10_27_24,    SCK0),
        PINMUX_IPSR_MSEL(IP10_27_24,    HSCK1_B,                SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP10_27_24,    MSIOF1_SS2_B,           SEL_MSIOF1_1),
        PINMUX_IPSR_MSEL(IP10_27_24,    AUDIO_CLKC_B,           SEL_ADG_1),
@@ -1057,38 +1056,38 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP10_27_24,    SIM0_RST_B,             SEL_SIMCARD_1),
        PINMUX_IPSR_MSEL(IP10_27_24,    STP_OPWM_0_C,           SEL_SSP1_0_2),
        PINMUX_IPSR_MSEL(IP10_27_24,    RIF0_CLK_B,             SEL_DRIF0_1),
-       PINMUX_IPSR_DATA(IP10_27_24,    ADICHS2),
+       PINMUX_IPSR_GPSR(IP10_27_24,    ADICHS2),
 
-       PINMUX_IPSR_DATA(IP10_31_28,    RX0),
+       PINMUX_IPSR_GPSR(IP10_31_28,    RX0),
        PINMUX_IPSR_MSEL(IP10_31_28,    HRX1_B,                 SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP10_31_28,    TS_SCK0_C,              SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP10_31_28,    STP_ISCLK_0_C,          SEL_SSP1_0_2),
        PINMUX_IPSR_MSEL(IP10_31_28,    RIF0_D0_B,              SEL_DRIF0_1),
 
        /* IPSR11 */
-       PINMUX_IPSR_DATA(IP11_3_0,      TX0),
+       PINMUX_IPSR_GPSR(IP11_3_0,      TX0),
        PINMUX_IPSR_MSEL(IP11_3_0,      HTX1_B,                 SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP11_3_0,      TS_SPSYNC0_C,           SEL_TSIF0_2),
        PINMUX_IPSR_MSEL(IP11_3_0,      STP_ISSYNC_0_C,         SEL_SSP1_0_2),
        PINMUX_IPSR_MSEL(IP11_3_0,      RIF0_D1_B,              SEL_DRIF0_1),
 
-       PINMUX_IPSR_DATA(IP11_7_4,      CTS0_N),
+       PINMUX_IPSR_GPSR(IP11_7_4,      CTS0_N),
        PINMUX_IPSR_MSEL(IP11_7_4,      HCTS1_N_B,              SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP11_7_4,      MSIOF1_SYNC_B,          SEL_MSIOF1_1),
        PINMUX_IPSR_MSEL(IP11_7_4,      TS_SPSYNC1_C,           SEL_TSIF1_2),
        PINMUX_IPSR_MSEL(IP11_7_4,      STP_ISSYNC_1_C,         SEL_SSP1_1_2),
        PINMUX_IPSR_MSEL(IP11_7_4,      RIF1_SYNC_B,            SEL_DRIF1_1),
        PINMUX_IPSR_MSEL(IP11_7_4,      AUDIO_CLKOUT_C,         SEL_ADG_2),
-       PINMUX_IPSR_DATA(IP11_7_4,      ADICS_SAMP),
+       PINMUX_IPSR_GPSR(IP11_7_4,      ADICS_SAMP),
 
-       PINMUX_IPSR_DATA(IP11_11_8,     RTS0_N_TANS),
+       PINMUX_IPSR_GPSR(IP11_11_8,     RTS0_N_TANS),
        PINMUX_IPSR_MSEL(IP11_11_8,     HRTS1_N_B,              SEL_HSCIF1_1),
        PINMUX_IPSR_MSEL(IP11_11_8,     MSIOF1_SS1_B,           SEL_MSIOF1_1),
        PINMUX_IPSR_MSEL(IP11_11_8,     AUDIO_CLKA_B,           SEL_ADG_1),
        PINMUX_IPSR_MSEL(IP11_11_8,     SCL2_A,                 SEL_I2C2_0),
        PINMUX_IPSR_MSEL(IP11_11_8,     STP_IVCXO27_1_C,        SEL_SSP1_1_2),
        PINMUX_IPSR_MSEL(IP11_11_8,     RIF0_SYNC_B,            SEL_DRIF0_1),
-       PINMUX_IPSR_DATA(IP11_11_8,     ADICHS1),
+       PINMUX_IPSR_GPSR(IP11_11_8,     ADICHS1),
 
        PINMUX_IPSR_MSEL(IP11_15_12,    RX1_A,                  SEL_SCIF1_0),
        PINMUX_IPSR_MSEL(IP11_15_12,    HRX1_A,                 SEL_HSCIF1_0),
@@ -1102,29 +1101,29 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP11_19_16,    STP_ISEN_0_C,           SEL_SSP1_0_2),
        PINMUX_IPSR_MSEL(IP11_19_16,    RIF1_D0_C,              SEL_DRIF1_2),
 
-       PINMUX_IPSR_DATA(IP11_23_20,    CTS1_N),
+       PINMUX_IPSR_GPSR(IP11_23_20,    CTS1_N),
        PINMUX_IPSR_MSEL(IP11_23_20,    HCTS1_N_A,              SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP11_23_20,    MSIOF1_RXD_B,           SEL_MSIOF1_1),
        PINMUX_IPSR_MSEL(IP11_23_20,    TS_SDEN1_C,             SEL_TSIF1_2),
        PINMUX_IPSR_MSEL(IP11_23_20,    STP_ISEN_1_C,           SEL_SSP1_1_2),
        PINMUX_IPSR_MSEL(IP11_23_20,    RIF1_D0_B,              SEL_DRIF1_1),
-       PINMUX_IPSR_DATA(IP11_23_20,    ADIDATA),
+       PINMUX_IPSR_GPSR(IP11_23_20,    ADIDATA),
 
-       PINMUX_IPSR_DATA(IP11_27_24,    RTS1_N_TANS),
+       PINMUX_IPSR_GPSR(IP11_27_24,    RTS1_N_TANS),
        PINMUX_IPSR_MSEL(IP11_27_24,    HRTS1_N_A,              SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP11_27_24,    MSIOF1_TXD_B,           SEL_MSIOF1_1),
        PINMUX_IPSR_MSEL(IP11_27_24,    TS_SDAT1_C,             SEL_TSIF1_2),
        PINMUX_IPSR_MSEL(IP11_27_24,    STP_ISD_1_C,            SEL_SSP1_1_2),
        PINMUX_IPSR_MSEL(IP11_27_24,    RIF1_D1_B,              SEL_DRIF1_1),
-       PINMUX_IPSR_DATA(IP11_27_24,    ADICHS0),
+       PINMUX_IPSR_GPSR(IP11_27_24,    ADICHS0),
 
-       PINMUX_IPSR_DATA(IP11_31_28,    SCK2),
+       PINMUX_IPSR_GPSR(IP11_31_28,    SCK2),
        PINMUX_IPSR_MSEL(IP11_31_28,    SCIF_CLK_B,             SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP11_31_28,    MSIOF1_SCK_B,           SEL_MSIOF1_1),
        PINMUX_IPSR_MSEL(IP11_31_28,    TS_SCK1_C,              SEL_TSIF1_2),
        PINMUX_IPSR_MSEL(IP11_31_28,    STP_ISCLK_1_C,          SEL_SSP1_1_2),
        PINMUX_IPSR_MSEL(IP11_31_28,    RIF1_CLK_B,             SEL_DRIF1_1),
-       PINMUX_IPSR_DATA(IP11_31_28,    ADICLK),
+       PINMUX_IPSR_GPSR(IP11_31_28,    ADICLK),
 
        /* IPSR12 */
        PINMUX_IPSR_MSEL(IP12_3_0,      TX2_A,                  SEL_SCIF2_0),
@@ -1141,7 +1140,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP12_7_4,      RIF1_SYNC_C,            SEL_DRIF1_2),
        PINMUX_IPSR_MSEL(IP12_7_4,      FSO_CFE_1_B,            SEL_FSO_1),
 
-       PINMUX_IPSR_DATA(IP12_11_8,     HSCK0),
+       PINMUX_IPSR_GPSR(IP12_11_8,     HSCK0),
        PINMUX_IPSR_MSEL(IP12_11_8,     MSIOF1_SCK_D,           SEL_MSIOF1_3),
        PINMUX_IPSR_MSEL(IP12_11_8,     AUDIO_CLKB_A,           SEL_ADG_0),
        PINMUX_IPSR_MSEL(IP12_11_8,     SSI_SDATA1_B,           SEL_SSI_1),
@@ -1149,21 +1148,21 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP12_11_8,     STP_ISCLK_0_D,          SEL_SSP1_0_3),
        PINMUX_IPSR_MSEL(IP12_11_8,     RIF0_CLK_C,             SEL_DRIF0_2),
 
-       PINMUX_IPSR_DATA(IP12_15_12,    HRX0),
+       PINMUX_IPSR_GPSR(IP12_15_12,    HRX0),
        PINMUX_IPSR_MSEL(IP12_15_12,    MSIOF1_RXD_D,           SEL_MSIOF1_3),
        PINMUX_IPSR_MSEL(IP12_15_12,    SSI_SDATA2_B,           SEL_SSI_1),
        PINMUX_IPSR_MSEL(IP12_15_12,    TS_SDEN0_D,             SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP12_15_12,    STP_ISEN_0_D,           SEL_SSP1_0_3),
        PINMUX_IPSR_MSEL(IP12_15_12,    RIF0_D0_C,              SEL_DRIF0_2),
 
-       PINMUX_IPSR_DATA(IP12_19_16,    HTX0),
+       PINMUX_IPSR_GPSR(IP12_19_16,    HTX0),
        PINMUX_IPSR_MSEL(IP12_19_16,    MSIOF1_TXD_D,           SEL_MSIOF1_3),
        PINMUX_IPSR_MSEL(IP12_19_16,    SSI_SDATA9_B,           SEL_SSI_1),
        PINMUX_IPSR_MSEL(IP12_19_16,    TS_SDAT0_D,             SEL_TSIF0_3),
        PINMUX_IPSR_MSEL(IP12_19_16,    STP_ISD_0_D,            SEL_SSP1_0_3),
        PINMUX_IPSR_MSEL(IP12_19_16,    RIF0_D1_C,              SEL_DRIF0_2),
 
-       PINMUX_IPSR_DATA(IP12_23_20,    HCTS0_N),
+       PINMUX_IPSR_GPSR(IP12_23_20,    HCTS0_N),
        PINMUX_IPSR_MSEL(IP12_23_20,    RX2_B,                  SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP12_23_20,    MSIOF1_SYNC_D,          SEL_MSIOF1_3),
        PINMUX_IPSR_MSEL(IP12_23_20,    SSI_SCK9_A,             SEL_SSI_0),
@@ -1172,7 +1171,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP12_23_20,    RIF0_SYNC_C,            SEL_DRIF0_2),
        PINMUX_IPSR_MSEL(IP12_23_20,    AUDIO_CLKOUT1_A,        SEL_ADG_0),
 
-       PINMUX_IPSR_DATA(IP12_27_24,    HRTS0_N),
+       PINMUX_IPSR_GPSR(IP12_27_24,    HRTS0_N),
        PINMUX_IPSR_MSEL(IP12_27_24,    TX2_B,                  SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP12_27_24,    MSIOF1_SS1_D,           SEL_MSIOF1_3),
        PINMUX_IPSR_MSEL(IP12_27_24,    SSI_WS9_A,              SEL_SSI_0),
@@ -1180,20 +1179,20 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP12_27_24,    BPFCLK_A,               SEL_FM_0),
        PINMUX_IPSR_MSEL(IP12_27_24,    AUDIO_CLKOUT2_A,        SEL_ADG_0),
 
-       PINMUX_IPSR_DATA(IP12_31_28,    MSIOF0_SYNC),
+       PINMUX_IPSR_GPSR(IP12_31_28,    MSIOF0_SYNC),
        PINMUX_IPSR_MSEL(IP12_31_28,    AUDIO_CLKOUT_A,         SEL_ADG_0),
 
        /* IPSR13 */
-       PINMUX_IPSR_DATA(IP13_3_0,      MSIOF0_SS1),
-       PINMUX_IPSR_DATA(IP13_3_0,      RX5),
+       PINMUX_IPSR_GPSR(IP13_3_0,      MSIOF0_SS1),
+       PINMUX_IPSR_GPSR(IP13_3_0,      RX5),
        PINMUX_IPSR_MSEL(IP13_3_0,      AUDIO_CLKA_C,           SEL_ADG_2),
        PINMUX_IPSR_MSEL(IP13_3_0,      SSI_SCK2_A,             SEL_SSI_0),
        PINMUX_IPSR_MSEL(IP13_3_0,      STP_IVCXO27_0_C,        SEL_SSP1_0_2),
        PINMUX_IPSR_MSEL(IP13_3_0,      AUDIO_CLKOUT3_A,        SEL_ADG_0),
        PINMUX_IPSR_MSEL(IP13_3_0,      TCLK1_B,                SEL_TIMER_TMU_1),
 
-       PINMUX_IPSR_DATA(IP13_7_4,      MSIOF0_SS2),
-       PINMUX_IPSR_DATA(IP13_7_4,      TX5),
+       PINMUX_IPSR_GPSR(IP13_7_4,      MSIOF0_SS2),
+       PINMUX_IPSR_GPSR(IP13_7_4,      TX5),
        PINMUX_IPSR_MSEL(IP13_7_4,      MSIOF1_SS2_D,           SEL_MSIOF1_3),
        PINMUX_IPSR_MSEL(IP13_7_4,      AUDIO_CLKC_A,           SEL_ADG_0),
        PINMUX_IPSR_MSEL(IP13_7_4,      SSI_WS2_A,              SEL_SSI_0),
@@ -1201,26 +1200,26 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP13_7_4,      AUDIO_CLKOUT_D,         SEL_ADG_3),
        PINMUX_IPSR_MSEL(IP13_7_4,      SPEEDIN_B,              SEL_SPEED_PULSE_1),
 
-       PINMUX_IPSR_DATA(IP13_11_8,     MLB_CLK),
+       PINMUX_IPSR_GPSR(IP13_11_8,     MLB_CLK),
        PINMUX_IPSR_MSEL(IP13_11_8,     MSIOF1_SCK_F,           SEL_MSIOF1_5),
        PINMUX_IPSR_MSEL(IP13_11_8,     SCL1_B,                 SEL_I2C1_1),
 
-       PINMUX_IPSR_DATA(IP13_15_12,    MLB_SIG),
+       PINMUX_IPSR_GPSR(IP13_15_12,    MLB_SIG),
        PINMUX_IPSR_MSEL(IP13_15_12,    RX1_B,                  SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP13_15_12,    MSIOF1_SYNC_F,          SEL_MSIOF1_5),
        PINMUX_IPSR_MSEL(IP13_15_12,    SDA1_B,                 SEL_I2C1_1),
 
-       PINMUX_IPSR_DATA(IP13_19_16,    MLB_DAT),
+       PINMUX_IPSR_GPSR(IP13_19_16,    MLB_DAT),
        PINMUX_IPSR_MSEL(IP13_19_16,    TX1_B,                  SEL_SCIF1_1),
        PINMUX_IPSR_MSEL(IP13_19_16,    MSIOF1_RXD_F,           SEL_MSIOF1_5),
 
-       PINMUX_IPSR_DATA(IP13_23_20,    SSI_SCK0129),
+       PINMUX_IPSR_GPSR(IP13_23_20,    SSI_SCK01239),
        PINMUX_IPSR_MSEL(IP13_23_20,    MSIOF1_TXD_F,           SEL_MSIOF1_5),
 
-       PINMUX_IPSR_DATA(IP13_27_24,    SSI_WS0129),
+       PINMUX_IPSR_GPSR(IP13_27_24,    SSI_WS01239),
        PINMUX_IPSR_MSEL(IP13_27_24,    MSIOF1_SS1_F,           SEL_MSIOF1_5),
 
-       PINMUX_IPSR_DATA(IP13_31_28,    SSI_SDATA0),
+       PINMUX_IPSR_GPSR(IP13_31_28,    SSI_SDATA0),
        PINMUX_IPSR_MSEL(IP13_31_28,    MSIOF1_SS2_F,           SEL_MSIOF1_5),
 
        /* IPSR14 */
@@ -1229,16 +1228,16 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP14_7_4,      SSI_SDATA2_A,           SEL_SSI_0),
        PINMUX_IPSR_MSEL(IP14_7_4,      SSI_SCK1_B,             SEL_SSI_1),
 
-       PINMUX_IPSR_DATA(IP14_11_8,     SSI_SCK34),
+       PINMUX_IPSR_GPSR(IP14_11_8,     SSI_SCK34),
        PINMUX_IPSR_MSEL(IP14_11_8,     MSIOF1_SS1_A,           SEL_MSIOF1_0),
        PINMUX_IPSR_MSEL(IP14_11_8,     STP_OPWM_0_A,           SEL_SSP1_0_0),
 
-       PINMUX_IPSR_DATA(IP14_15_12,    SSI_WS34),
+       PINMUX_IPSR_GPSR(IP14_15_12,    SSI_WS34),
        PINMUX_IPSR_MSEL(IP14_15_12,    HCTS2_N_A,              SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP14_15_12,    MSIOF1_SS2_A,           SEL_MSIOF1_0),
        PINMUX_IPSR_MSEL(IP14_15_12,    STP_IVCXO27_0_A,        SEL_SSP1_0_0),
 
-       PINMUX_IPSR_DATA(IP14_19_16,    SSI_SDATA3),
+       PINMUX_IPSR_GPSR(IP14_19_16,    SSI_SDATA3),
        PINMUX_IPSR_MSEL(IP14_19_16,    HRTS2_N_A,              SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP14_19_16,    MSIOF1_TXD_A,           SEL_MSIOF1_0),
        PINMUX_IPSR_MSEL(IP14_19_16,    TS_SCK0_A,              SEL_TSIF0_0),
@@ -1246,7 +1245,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP14_19_16,    RIF0_D1_A,              SEL_DRIF0_0),
        PINMUX_IPSR_MSEL(IP14_19_16,    RIF2_D0_A,              SEL_DRIF2_0),
 
-       PINMUX_IPSR_DATA(IP14_23_20,    SSI_SCK4),
+       PINMUX_IPSR_GPSR(IP14_23_20,    SSI_SCK4),
        PINMUX_IPSR_MSEL(IP14_23_20,    HRX2_A,                 SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP14_23_20,    MSIOF1_SCK_A,           SEL_MSIOF1_0),
        PINMUX_IPSR_MSEL(IP14_23_20,    TS_SDAT0_A,             SEL_TSIF0_0),
@@ -1254,7 +1253,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP14_23_20,    RIF0_CLK_A,             SEL_DRIF0_0),
        PINMUX_IPSR_MSEL(IP14_23_20,    RIF2_CLK_A,             SEL_DRIF2_0),
 
-       PINMUX_IPSR_DATA(IP14_27_24,    SSI_WS4),
+       PINMUX_IPSR_GPSR(IP14_27_24,    SSI_WS4),
        PINMUX_IPSR_MSEL(IP14_27_24,    HTX2_A,                 SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP14_27_24,    MSIOF1_SYNC_A,          SEL_MSIOF1_0),
        PINMUX_IPSR_MSEL(IP14_27_24,    TS_SDEN0_A,             SEL_TSIF0_0),
@@ -1262,7 +1261,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP14_27_24,    RIF0_SYNC_A,            SEL_DRIF0_0),
        PINMUX_IPSR_MSEL(IP14_27_24,    RIF2_SYNC_A,            SEL_DRIF2_0),
 
-       PINMUX_IPSR_DATA(IP14_31_28,    SSI_SDATA4),
+       PINMUX_IPSR_GPSR(IP14_31_28,    SSI_SDATA4),
        PINMUX_IPSR_MSEL(IP14_31_28,    HSCK2_A,                SEL_HSCIF2_0),
        PINMUX_IPSR_MSEL(IP14_31_28,    MSIOF1_RXD_A,           SEL_MSIOF1_0),
        PINMUX_IPSR_MSEL(IP14_31_28,    TS_SPSYNC0_A,           SEL_TSIF0_0),
@@ -1271,19 +1270,19 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP14_31_28,    RIF2_D1_A,              SEL_DRIF2_0),
 
        /* IPSR15 */
-       PINMUX_IPSR_DATA(IP15_3_0,      SSI_SCK6),
-       PINMUX_IPSR_DATA(IP15_3_0,      USB2_PWEN),
+       PINMUX_IPSR_GPSR(IP15_3_0,      SSI_SCK6),
+       PINMUX_IPSR_GPSR(IP15_3_0,      USB2_PWEN),
        PINMUX_IPSR_MSEL(IP15_3_0,      SIM0_RST_D,             SEL_SIMCARD_3),
 
-       PINMUX_IPSR_DATA(IP15_7_4,      SSI_WS6),
-       PINMUX_IPSR_DATA(IP15_7_4,      USB2_OVC),
+       PINMUX_IPSR_GPSR(IP15_7_4,      SSI_WS6),
+       PINMUX_IPSR_GPSR(IP15_7_4,      USB2_OVC),
        PINMUX_IPSR_MSEL(IP15_7_4,      SIM0_D_D,               SEL_SIMCARD_3),
 
-       PINMUX_IPSR_DATA(IP15_11_8,     SSI_SDATA6),
+       PINMUX_IPSR_GPSR(IP15_11_8,     SSI_SDATA6),
        PINMUX_IPSR_MSEL(IP15_11_8,     SIM0_CLK_D,             SEL_SIMCARD_3),
        PINMUX_IPSR_MSEL(IP15_11_8,     SATA_DEVSLP_A,          SEL_SATA_0),
 
-       PINMUX_IPSR_DATA(IP15_15_12,    SSI_SCK78),
+       PINMUX_IPSR_GPSR(IP15_15_12,    SSI_SCK78),
        PINMUX_IPSR_MSEL(IP15_15_12,    HRX2_B,                 SEL_HSCIF2_1),
        PINMUX_IPSR_MSEL(IP15_15_12,    MSIOF1_SCK_C,           SEL_MSIOF1_2),
        PINMUX_IPSR_MSEL(IP15_15_12,    TS_SCK1_A,              SEL_TSIF1_0),
@@ -1291,7 +1290,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP15_15_12,    RIF1_CLK_A,             SEL_DRIF1_0),
        PINMUX_IPSR_MSEL(IP15_15_12,    RIF3_CLK_A,             SEL_DRIF3_0),
 
-       PINMUX_IPSR_DATA(IP15_19_16,    SSI_WS78),
+       PINMUX_IPSR_GPSR(IP15_19_16,    SSI_WS78),
        PINMUX_IPSR_MSEL(IP15_19_16,    HTX2_B,                 SEL_HSCIF2_1),
        PINMUX_IPSR_MSEL(IP15_19_16,    MSIOF1_SYNC_C,          SEL_MSIOF1_2),
        PINMUX_IPSR_MSEL(IP15_19_16,    TS_SDAT1_A,             SEL_TSIF1_0),
@@ -1299,7 +1298,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP15_19_16,    RIF1_SYNC_A,            SEL_DRIF1_0),
        PINMUX_IPSR_MSEL(IP15_19_16,    RIF3_SYNC_A,            SEL_DRIF3_0),
 
-       PINMUX_IPSR_DATA(IP15_23_20,    SSI_SDATA7),
+       PINMUX_IPSR_GPSR(IP15_23_20,    SSI_SDATA7),
        PINMUX_IPSR_MSEL(IP15_23_20,    HCTS2_N_B,              SEL_HSCIF2_1),
        PINMUX_IPSR_MSEL(IP15_23_20,    MSIOF1_RXD_C,           SEL_MSIOF1_2),
        PINMUX_IPSR_MSEL(IP15_23_20,    TS_SDEN1_A,             SEL_TSIF1_0),
@@ -1308,7 +1307,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP15_23_20,    RIF3_D0_A,              SEL_DRIF3_0),
        PINMUX_IPSR_MSEL(IP15_23_20,    TCLK2_A,                SEL_TIMER_TMU_0),
 
-       PINMUX_IPSR_DATA(IP15_27_24,    SSI_SDATA8),
+       PINMUX_IPSR_GPSR(IP15_27_24,    SSI_SDATA8),
        PINMUX_IPSR_MSEL(IP15_27_24,    HRTS2_N_B,              SEL_HSCIF2_1),
        PINMUX_IPSR_MSEL(IP15_27_24,    MSIOF1_TXD_C,           SEL_MSIOF1_2),
        PINMUX_IPSR_MSEL(IP15_27_24,    TS_SPSYNC1_A,           SEL_TSIF1_0),
@@ -1321,13 +1320,13 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP15_31_28,    MSIOF1_SS1_C,           SEL_MSIOF1_2),
        PINMUX_IPSR_MSEL(IP15_31_28,    HSCK1_A,                SEL_HSCIF1_0),
        PINMUX_IPSR_MSEL(IP15_31_28,    SSI_WS1_B,              SEL_SSI_1),
-       PINMUX_IPSR_DATA(IP15_31_28,    SCK1),
+       PINMUX_IPSR_GPSR(IP15_31_28,    SCK1),
        PINMUX_IPSR_MSEL(IP15_31_28,    STP_IVCXO27_1_A,        SEL_SSP1_1_0),
-       PINMUX_IPSR_DATA(IP15_31_28,    SCK5),
+       PINMUX_IPSR_GPSR(IP15_31_28,    SCK5),
 
        /* IPSR16 */
        PINMUX_IPSR_MSEL(IP16_3_0,      AUDIO_CLKA_A,           SEL_ADG_0),
-       PINMUX_IPSR_DATA(IP16_3_0,      CC5_OSCOUT),
+       PINMUX_IPSR_GPSR(IP16_3_0,      CC5_OSCOUT),
 
        PINMUX_IPSR_MSEL(IP16_7_4,      AUDIO_CLKB_B,           SEL_ADG_1),
        PINMUX_IPSR_MSEL(IP16_7_4,      SCIF_CLK_A,             SEL_SCIF1_0),
@@ -1335,20 +1334,20 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP16_7_4,      REMOCON_A,              SEL_REMOCON_0),
        PINMUX_IPSR_MSEL(IP16_7_4,      TCLK1_A,                SEL_TIMER_TMU_0),
 
-       PINMUX_IPSR_DATA(IP16_11_8,     USB0_PWEN),
+       PINMUX_IPSR_GPSR(IP16_11_8,     USB0_PWEN),
        PINMUX_IPSR_MSEL(IP16_11_8,     SIM0_RST_C,             SEL_SIMCARD_2),
        PINMUX_IPSR_MSEL(IP16_11_8,     TS_SCK1_D,              SEL_TSIF1_3),
        PINMUX_IPSR_MSEL(IP16_11_8,     STP_ISCLK_1_D,          SEL_SSP1_1_3),
        PINMUX_IPSR_MSEL(IP16_11_8,     BPFCLK_B,               SEL_FM_1),
        PINMUX_IPSR_MSEL(IP16_11_8,     RIF3_CLK_B,             SEL_DRIF3_1),
 
-       PINMUX_IPSR_DATA(IP16_15_12,    USB0_OVC),
+       PINMUX_IPSR_GPSR(IP16_15_12,    USB0_OVC),
        PINMUX_IPSR_MSEL(IP16_11_8,     SIM0_D_C,               SEL_SIMCARD_2),
        PINMUX_IPSR_MSEL(IP16_11_8,     TS_SDAT1_D,             SEL_TSIF1_3),
        PINMUX_IPSR_MSEL(IP16_11_8,     STP_ISD_1_D,            SEL_SSP1_1_3),
        PINMUX_IPSR_MSEL(IP16_11_8,     RIF3_SYNC_B,            SEL_DRIF3_1),
 
-       PINMUX_IPSR_DATA(IP16_19_16,    USB1_PWEN),
+       PINMUX_IPSR_GPSR(IP16_19_16,    USB1_PWEN),
        PINMUX_IPSR_MSEL(IP16_19_16,    SIM0_CLK_C,             SEL_SIMCARD_2),
        PINMUX_IPSR_MSEL(IP16_19_16,    SSI_SCK1_A,             SEL_SSI_0),
        PINMUX_IPSR_MSEL(IP16_19_16,    TS_SCK0_E,              SEL_TSIF0_4),
@@ -1357,7 +1356,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP16_19_16,    RIF2_CLK_B,             SEL_DRIF2_1),
        PINMUX_IPSR_MSEL(IP16_19_16,    SPEEDIN_A,              SEL_SPEED_PULSE_0),
 
-       PINMUX_IPSR_DATA(IP16_23_20,    USB1_OVC),
+       PINMUX_IPSR_GPSR(IP16_23_20,    USB1_OVC),
        PINMUX_IPSR_MSEL(IP16_23_20,    MSIOF1_SS2_C,           SEL_MSIOF1_2),
        PINMUX_IPSR_MSEL(IP16_23_20,    SSI_WS1_A,              SEL_SSI_0),
        PINMUX_IPSR_MSEL(IP16_23_20,    TS_SDAT0_E,             SEL_TSIF0_4),
@@ -1366,7 +1365,7 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP16_23_20,    RIF2_SYNC_B,            SEL_DRIF2_1),
        PINMUX_IPSR_MSEL(IP16_23_20,    REMOCON_B,              SEL_REMOCON_1),
 
-       PINMUX_IPSR_DATA(IP16_27_24,    USB30_PWEN),
+       PINMUX_IPSR_GPSR(IP16_27_24,    USB30_PWEN),
        PINMUX_IPSR_MSEL(IP16_27_24,    AUDIO_CLKOUT_B,         SEL_ADG_1),
        PINMUX_IPSR_MSEL(IP16_27_24,    SSI_SCK2_B,             SEL_SSI_1),
        PINMUX_IPSR_MSEL(IP16_27_24,    TS_SDEN1_D,             SEL_TSIF1_3),
@@ -1374,9 +1373,9 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP16_27_24,    STP_OPWM_0_E,           SEL_SSP1_0_4),
        PINMUX_IPSR_MSEL(IP16_27_24,    RIF3_D0_B,              SEL_DRIF3_1),
        PINMUX_IPSR_MSEL(IP16_27_24,    TCLK2_B,                SEL_TIMER_TMU_1),
-       PINMUX_IPSR_DATA(IP16_27_24,    TPU0TO0),
+       PINMUX_IPSR_GPSR(IP16_27_24,    TPU0TO0),
 
-       PINMUX_IPSR_DATA(IP16_31_28,    USB30_OVC),
+       PINMUX_IPSR_GPSR(IP16_31_28,    USB30_OVC),
        PINMUX_IPSR_MSEL(IP16_31_28,    AUDIO_CLKOUT1_B,        SEL_ADG_1),
        PINMUX_IPSR_MSEL(IP16_31_28,    SSI_WS2_B,              SEL_SSI_1),
        PINMUX_IPSR_MSEL(IP16_31_28,    TS_SPSYNC1_D,           SEL_TSIF1_3),
@@ -1384,24 +1383,24 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP16_31_28,    STP_IVCXO27_0_E,        SEL_SSP1_0_4),
        PINMUX_IPSR_MSEL(IP16_31_28,    RIF3_D1_B,              SEL_DRIF3_1),
        PINMUX_IPSR_MSEL(IP16_31_28,    FSO_TOE_B,              SEL_FSO_1),
-       PINMUX_IPSR_DATA(IP16_31_28,    TPU0TO1),
+       PINMUX_IPSR_GPSR(IP16_31_28,    TPU0TO1),
 
        /* IPSR17 */
-       PINMUX_IPSR_DATA(IP17_3_0,      USB31_PWEN),
+       PINMUX_IPSR_GPSR(IP17_3_0,      USB31_PWEN),
        PINMUX_IPSR_MSEL(IP17_3_0,      AUDIO_CLKOUT2_B,        SEL_ADG_1),
        PINMUX_IPSR_MSEL(IP17_3_0,      SSI_SCK9_B,             SEL_SSI_1),
        PINMUX_IPSR_MSEL(IP17_3_0,      TS_SDEN0_E,             SEL_TSIF0_4),
        PINMUX_IPSR_MSEL(IP17_3_0,      STP_ISEN_0_E,           SEL_SSP1_0_4),
        PINMUX_IPSR_MSEL(IP17_3_0,      RIF2_D0_B,              SEL_DRIF2_1),
-       PINMUX_IPSR_DATA(IP17_3_0,      TPU0TO2),
+       PINMUX_IPSR_GPSR(IP17_3_0,      TPU0TO2),
 
-       PINMUX_IPSR_DATA(IP17_7_4,      USB31_OVC),
+       PINMUX_IPSR_GPSR(IP17_7_4,      USB31_OVC),
        PINMUX_IPSR_MSEL(IP17_7_4,      AUDIO_CLKOUT3_B,        SEL_ADG_1),
        PINMUX_IPSR_MSEL(IP17_7_4,      SSI_WS9_B,              SEL_SSI_1),
        PINMUX_IPSR_MSEL(IP17_7_4,      TS_SPSYNC0_E,           SEL_TSIF0_4),
        PINMUX_IPSR_MSEL(IP17_7_4,      STP_ISSYNC_0_E,         SEL_SSP1_0_4),
        PINMUX_IPSR_MSEL(IP17_7_4,      RIF2_D1_B,              SEL_DRIF2_1),
-       PINMUX_IPSR_DATA(IP17_7_4,      TPU0TO3),
+       PINMUX_IPSR_GPSR(IP17_7_4,      TPU0TO3),
 
        /* I2C */
        PINMUX_IPSR_NOGP(0,             I2C_SEL_0_1),
@@ -1600,6 +1599,61 @@ static const unsigned int avb_avtp_capture_b_mux[] = {
        AVB_AVTP_CAPTURE_B_MARK,
 };
 
+/* - CAN ------------------------------------------------------------------ */
+static const unsigned int can0_data_a_pins[] = {
+       /* TX, RX */
+       RCAR_GP_PIN(1, 23),     RCAR_GP_PIN(1, 24),
+};
+static const unsigned int can0_data_a_mux[] = {
+       CAN0_TX_A_MARK,         CAN0_RX_A_MARK,
+};
+static const unsigned int can0_data_b_pins[] = {
+       /* TX, RX */
+       RCAR_GP_PIN(2, 0),      RCAR_GP_PIN(2, 1),
+};
+static const unsigned int can0_data_b_mux[] = {
+       CAN0_TX_B_MARK,         CAN0_RX_B_MARK,
+};
+static const unsigned int can1_data_pins[] = {
+       /* TX, RX */
+       RCAR_GP_PIN(1, 22),     RCAR_GP_PIN(1, 26),
+};
+static const unsigned int can1_data_mux[] = {
+       CAN1_TX_MARK,           CAN1_RX_MARK,
+};
+
+/* - CAN Clock -------------------------------------------------------------- */
+static const unsigned int can_clk_pins[] = {
+       /* CLK */
+       RCAR_GP_PIN(1, 25),
+};
+static const unsigned int can_clk_mux[] = {
+       CAN_CLK_MARK,
+};
+
+/* - CAN FD --------------------------------------------------------------- */
+static const unsigned int canfd0_data_a_pins[] = {
+       /* TX, RX */
+       RCAR_GP_PIN(1, 23),     RCAR_GP_PIN(1, 24),
+};
+static const unsigned int canfd0_data_a_mux[] = {
+       CANFD0_TX_A_MARK,       CANFD0_RX_A_MARK,
+};
+static const unsigned int canfd0_data_b_pins[] = {
+       /* TX, RX */
+       RCAR_GP_PIN(2, 0),      RCAR_GP_PIN(2, 1),
+};
+static const unsigned int canfd0_data_b_mux[] = {
+       CANFD0_TX_B_MARK,       CANFD0_RX_B_MARK,
+};
+static const unsigned int canfd1_data_pins[] = {
+       /* TX, RX */
+       RCAR_GP_PIN(1, 22),     RCAR_GP_PIN(1, 26),
+};
+static const unsigned int canfd1_data_mux[] = {
+       CANFD1_TX_MARK,         CANFD1_RX_MARK,
+};
+
 /* - HSCIF0 ----------------------------------------------------------------- */
 static const unsigned int hscif0_data_pins[] = {
        /* RX, TX */
@@ -1836,6 +1890,50 @@ static const unsigned int i2c6_c_mux[] = {
        SDA6_C_MARK, SCL6_C_MARK,
 };
 
+/* - INTC-EX ---------------------------------------------------------------- */
+static const unsigned int intc_ex_irq0_pins[] = {
+       /* IRQ0 */
+       RCAR_GP_PIN(2, 0),
+};
+static const unsigned int intc_ex_irq0_mux[] = {
+       IRQ0_MARK,
+};
+static const unsigned int intc_ex_irq1_pins[] = {
+       /* IRQ1 */
+       RCAR_GP_PIN(2, 1),
+};
+static const unsigned int intc_ex_irq1_mux[] = {
+       IRQ1_MARK,
+};
+static const unsigned int intc_ex_irq2_pins[] = {
+       /* IRQ2 */
+       RCAR_GP_PIN(2, 2),
+};
+static const unsigned int intc_ex_irq2_mux[] = {
+       IRQ2_MARK,
+};
+static const unsigned int intc_ex_irq3_pins[] = {
+       /* IRQ3 */
+       RCAR_GP_PIN(2, 3),
+};
+static const unsigned int intc_ex_irq3_mux[] = {
+       IRQ3_MARK,
+};
+static const unsigned int intc_ex_irq4_pins[] = {
+       /* IRQ4 */
+       RCAR_GP_PIN(2, 4),
+};
+static const unsigned int intc_ex_irq4_mux[] = {
+       IRQ4_MARK,
+};
+static const unsigned int intc_ex_irq5_pins[] = {
+       /* IRQ5 */
+       RCAR_GP_PIN(2, 5),
+};
+static const unsigned int intc_ex_irq5_mux[] = {
+       IRQ5_MARK,
+};
+
 /* - MSIOF0 ----------------------------------------------------------------- */
 static const unsigned int msiof0_clk_pins[] = {
        /* SCK */
@@ -2492,6 +2590,105 @@ static const unsigned int msiof3_rxd_d_mux[] = {
        MSIOF3_RXD_D_MARK,
 };
 
+/* - PWM0 --------------------------------------------------------------------*/
+static const unsigned int pwm0_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(2, 6),
+};
+static const unsigned int pwm0_mux[] = {
+       PWM0_MARK,
+};
+/* - PWM1 --------------------------------------------------------------------*/
+static const unsigned int pwm1_a_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(2, 7),
+};
+static const unsigned int pwm1_a_mux[] = {
+       PWM1_A_MARK,
+};
+static const unsigned int pwm1_b_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(1, 8),
+};
+static const unsigned int pwm1_b_mux[] = {
+       PWM1_B_MARK,
+};
+/* - PWM2 --------------------------------------------------------------------*/
+static const unsigned int pwm2_a_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(2, 8),
+};
+static const unsigned int pwm2_a_mux[] = {
+       PWM2_A_MARK,
+};
+static const unsigned int pwm2_b_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(1, 11),
+};
+static const unsigned int pwm2_b_mux[] = {
+       PWM2_B_MARK,
+};
+/* - PWM3 --------------------------------------------------------------------*/
+static const unsigned int pwm3_a_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(1, 0),
+};
+static const unsigned int pwm3_a_mux[] = {
+       PWM3_A_MARK,
+};
+static const unsigned int pwm3_b_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(2, 2),
+};
+static const unsigned int pwm3_b_mux[] = {
+       PWM3_B_MARK,
+};
+/* - PWM4 --------------------------------------------------------------------*/
+static const unsigned int pwm4_a_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(1, 1),
+};
+static const unsigned int pwm4_a_mux[] = {
+       PWM4_A_MARK,
+};
+static const unsigned int pwm4_b_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(2, 3),
+};
+static const unsigned int pwm4_b_mux[] = {
+       PWM4_B_MARK,
+};
+/* - PWM5 --------------------------------------------------------------------*/
+static const unsigned int pwm5_a_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(1, 2),
+};
+static const unsigned int pwm5_a_mux[] = {
+       PWM5_A_MARK,
+};
+static const unsigned int pwm5_b_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(2, 4),
+};
+static const unsigned int pwm5_b_mux[] = {
+       PWM5_B_MARK,
+};
+/* - PWM6 --------------------------------------------------------------------*/
+static const unsigned int pwm6_a_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(1, 3),
+};
+static const unsigned int pwm6_a_mux[] = {
+       PWM6_A_MARK,
+};
+static const unsigned int pwm6_b_pins[] = {
+       /* PWM */
+       RCAR_GP_PIN(2, 5),
+};
+static const unsigned int pwm6_b_mux[] = {
+       PWM6_B_MARK,
+};
+
 /* - SATA --------------------------------------------------------------------*/
 static const unsigned int sata0_devslp_a_pins[] = {
        /* DEVSLP */
@@ -2926,7 +3123,7 @@ static const unsigned int ssi01239_ctrl_pins[] = {
        RCAR_GP_PIN(6, 0), RCAR_GP_PIN(6, 1),
 };
 static const unsigned int ssi01239_ctrl_mux[] = {
-       SSI_SCK0129_MARK, SSI_WS0129_MARK,
+       SSI_SCK01239_MARK, SSI_WS01239_MARK,
 };
 static const unsigned int ssi1_data_a_pins[] = {
        /* SDATA */
@@ -3090,6 +3287,31 @@ static const unsigned int ssi9_ctrl_b_mux[] = {
        SSI_SCK9_B_MARK, SSI_WS9_B_MARK,
 };
 
+/* - USB0 ------------------------------------------------------------------- */
+static const unsigned int usb0_pins[] = {
+       /* PWEN, OVC */
+       RCAR_GP_PIN(6, 24), RCAR_GP_PIN(6, 25),
+};
+static const unsigned int usb0_mux[] = {
+       USB0_PWEN_MARK, USB0_OVC_MARK,
+};
+/* - USB1 ------------------------------------------------------------------- */
+static const unsigned int usb1_pins[] = {
+       /* PWEN, OVC */
+       RCAR_GP_PIN(6, 26), RCAR_GP_PIN(6, 27),
+};
+static const unsigned int usb1_mux[] = {
+       USB1_PWEN_MARK, USB1_OVC_MARK,
+};
+/* - USB2 ------------------------------------------------------------------- */
+static const unsigned int usb2_pins[] = {
+       /* PWEN, OVC */
+       RCAR_GP_PIN(6, 14), RCAR_GP_PIN(6, 15),
+};
+static const unsigned int usb2_mux[] = {
+       USB2_PWEN_MARK, USB2_OVC_MARK,
+};
+
 static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(audio_clk_a_a),
        SH_PFC_PIN_GROUP(audio_clk_a_b),
@@ -3117,6 +3339,13 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(avb_avtp_capture_a),
        SH_PFC_PIN_GROUP(avb_avtp_match_b),
        SH_PFC_PIN_GROUP(avb_avtp_capture_b),
+       SH_PFC_PIN_GROUP(can0_data_a),
+       SH_PFC_PIN_GROUP(can0_data_b),
+       SH_PFC_PIN_GROUP(can1_data),
+       SH_PFC_PIN_GROUP(can_clk),
+       SH_PFC_PIN_GROUP(canfd0_data_a),
+       SH_PFC_PIN_GROUP(canfd0_data_b),
+       SH_PFC_PIN_GROUP(canfd1_data),
        SH_PFC_PIN_GROUP(hscif0_data),
        SH_PFC_PIN_GROUP(hscif0_clk),
        SH_PFC_PIN_GROUP(hscif0_ctrl),
@@ -3149,6 +3378,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(i2c6_a),
        SH_PFC_PIN_GROUP(i2c6_b),
        SH_PFC_PIN_GROUP(i2c6_c),
+       SH_PFC_PIN_GROUP(intc_ex_irq0),
+       SH_PFC_PIN_GROUP(intc_ex_irq1),
+       SH_PFC_PIN_GROUP(intc_ex_irq2),
+       SH_PFC_PIN_GROUP(intc_ex_irq3),
+       SH_PFC_PIN_GROUP(intc_ex_irq4),
+       SH_PFC_PIN_GROUP(intc_ex_irq5),
        SH_PFC_PIN_GROUP(msiof0_clk),
        SH_PFC_PIN_GROUP(msiof0_sync),
        SH_PFC_PIN_GROUP(msiof0_ss1),
@@ -3242,6 +3477,19 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(msiof3_ss1_d),
        SH_PFC_PIN_GROUP(msiof3_txd_d),
        SH_PFC_PIN_GROUP(msiof3_rxd_d),
+       SH_PFC_PIN_GROUP(pwm0),
+       SH_PFC_PIN_GROUP(pwm1_a),
+       SH_PFC_PIN_GROUP(pwm1_b),
+       SH_PFC_PIN_GROUP(pwm2_a),
+       SH_PFC_PIN_GROUP(pwm2_b),
+       SH_PFC_PIN_GROUP(pwm3_a),
+       SH_PFC_PIN_GROUP(pwm3_b),
+       SH_PFC_PIN_GROUP(pwm4_a),
+       SH_PFC_PIN_GROUP(pwm4_b),
+       SH_PFC_PIN_GROUP(pwm5_a),
+       SH_PFC_PIN_GROUP(pwm5_b),
+       SH_PFC_PIN_GROUP(pwm6_a),
+       SH_PFC_PIN_GROUP(pwm6_b),
        SH_PFC_PIN_GROUP(sata0_devslp_a),
        SH_PFC_PIN_GROUP(sata0_devslp_b),
        SH_PFC_PIN_GROUP(scif0_data),
@@ -3322,6 +3570,9 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
        SH_PFC_PIN_GROUP(ssi9_data_b),
        SH_PFC_PIN_GROUP(ssi9_ctrl_a),
        SH_PFC_PIN_GROUP(ssi9_ctrl_b),
+       SH_PFC_PIN_GROUP(usb0),
+       SH_PFC_PIN_GROUP(usb1),
+       SH_PFC_PIN_GROUP(usb2),
 };
 
 static const char * const audio_clk_groups[] = {
@@ -3356,6 +3607,28 @@ static const char * const avb_groups[] = {
        "avb_avtp_capture_b",
 };
 
+static const char * const can0_groups[] = {
+       "can0_data_a",
+       "can0_data_b",
+};
+
+static const char * const can1_groups[] = {
+       "can1_data",
+};
+
+static const char * const can_clk_groups[] = {
+       "can_clk",
+};
+
+static const char * const canfd0_groups[] = {
+       "canfd0_data_a",
+       "canfd0_data_b",
+};
+
+static const char * const canfd1_groups[] = {
+       "canfd1_data",
+};
+
 static const char * const hscif0_groups[] = {
        "hscif0_data",
        "hscif0_clk",
@@ -3412,6 +3685,15 @@ static const char * const i2c6_groups[] = {
        "i2c6_c",
 };
 
+static const char * const intc_ex_groups[] = {
+       "intc_ex_irq0",
+       "intc_ex_irq1",
+       "intc_ex_irq2",
+       "intc_ex_irq3",
+       "intc_ex_irq4",
+       "intc_ex_irq5",
+};
+
 static const char * const msiof0_groups[] = {
        "msiof0_clk",
        "msiof0_sync",
@@ -3517,6 +3799,40 @@ static const char * const msiof3_groups[] = {
        "msiof3_rxd_d",
 };
 
+static const char * const pwm0_groups[] = {
+       "pwm0",
+};
+
+static const char * const pwm1_groups[] = {
+       "pwm1_a",
+       "pwm1_b",
+};
+
+static const char * const pwm2_groups[] = {
+       "pwm2_a",
+       "pwm2_b",
+};
+
+static const char * const pwm3_groups[] = {
+       "pwm3_a",
+       "pwm3_b",
+};
+
+static const char * const pwm4_groups[] = {
+       "pwm4_a",
+       "pwm4_b",
+};
+
+static const char * const pwm5_groups[] = {
+       "pwm5_a",
+       "pwm5_b",
+};
+
+static const char * const pwm6_groups[] = {
+       "pwm6_a",
+       "pwm6_b",
+};
+
 static const char * const sata0_groups[] = {
        "sata0_devslp_a",
        "sata0_devslp_b",
@@ -3636,9 +3952,26 @@ static const char * const ssi_groups[] = {
        "ssi9_ctrl_b",
 };
 
+static const char * const usb0_groups[] = {
+       "usb0",
+};
+
+static const char * const usb1_groups[] = {
+       "usb1",
+};
+
+static const char * const usb2_groups[] = {
+       "usb2",
+};
+
 static const struct sh_pfc_function pinmux_functions[] = {
        SH_PFC_FUNCTION(audio_clk),
        SH_PFC_FUNCTION(avb),
+       SH_PFC_FUNCTION(can0),
+       SH_PFC_FUNCTION(can1),
+       SH_PFC_FUNCTION(can_clk),
+       SH_PFC_FUNCTION(canfd0),
+       SH_PFC_FUNCTION(canfd1),
        SH_PFC_FUNCTION(hscif0),
        SH_PFC_FUNCTION(hscif1),
        SH_PFC_FUNCTION(hscif2),
@@ -3647,10 +3980,18 @@ static const struct sh_pfc_function pinmux_functions[] = {
        SH_PFC_FUNCTION(i2c1),
        SH_PFC_FUNCTION(i2c2),
        SH_PFC_FUNCTION(i2c6),
+       SH_PFC_FUNCTION(intc_ex),
        SH_PFC_FUNCTION(msiof0),
        SH_PFC_FUNCTION(msiof1),
        SH_PFC_FUNCTION(msiof2),
        SH_PFC_FUNCTION(msiof3),
+       SH_PFC_FUNCTION(pwm0),
+       SH_PFC_FUNCTION(pwm1),
+       SH_PFC_FUNCTION(pwm2),
+       SH_PFC_FUNCTION(pwm3),
+       SH_PFC_FUNCTION(pwm4),
+       SH_PFC_FUNCTION(pwm5),
+       SH_PFC_FUNCTION(pwm6),
        SH_PFC_FUNCTION(sata0),
        SH_PFC_FUNCTION(scif0),
        SH_PFC_FUNCTION(scif1),
@@ -3664,6 +4005,9 @@ static const struct sh_pfc_function pinmux_functions[] = {
        SH_PFC_FUNCTION(sdhi2),
        SH_PFC_FUNCTION(sdhi3),
        SH_PFC_FUNCTION(ssi),
+       SH_PFC_FUNCTION(usb0),
+       SH_PFC_FUNCTION(usb1),
+       SH_PFC_FUNCTION(usb2),
 };
 
 static const struct pinmux_cfg_reg pinmux_config_regs[] = {
@@ -4213,7 +4557,8 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
                0, 0, 0, 0, 0, 0, 0, 0,
                /* RESERVED 3 */
                0, 0,
-               MOD_SEL2_2_1
+               /* RESERVED 2, 1 */
+               0, 0, 0, 0,
                MOD_SEL2_0 }
        },
        { },
index b0b328b3130b13247672cf5bbca3d6be10f8b504..6502e676d368617927c9cf55be7fea2ea31697e8 100644 (file)
@@ -591,547 +591,547 @@ static const u16 pinmux_data[] = {
        PINMUX_SINGLE(IRQ3_B),
 
        /* IPSR0 */
-       PINMUX_IPSR_DATA(IP0_1_0, A0),
-       PINMUX_IPSR_DATA(IP0_1_0, ST0_CLKIN),
+       PINMUX_IPSR_GPSR(IP0_1_0, A0),
+       PINMUX_IPSR_GPSR(IP0_1_0, ST0_CLKIN),
        PINMUX_IPSR_MSEL(IP0_1_0, LCD_DATA0_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_1_0, TCLKA_C, SEL_MTU2_CLK_1),
 
-       PINMUX_IPSR_DATA(IP0_3_2, A1),
-       PINMUX_IPSR_DATA(IP0_3_2, ST0_REQ),
+       PINMUX_IPSR_GPSR(IP0_3_2, A1),
+       PINMUX_IPSR_GPSR(IP0_3_2, ST0_REQ),
        PINMUX_IPSR_MSEL(IP0_3_2, LCD_DATA1_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_3_2, TCLKB_C, SEL_MTU2_CLK_1),
 
-       PINMUX_IPSR_DATA(IP0_5_4, A2),
-       PINMUX_IPSR_DATA(IP0_5_4, ST0_SYC),
+       PINMUX_IPSR_GPSR(IP0_5_4, A2),
+       PINMUX_IPSR_GPSR(IP0_5_4, ST0_SYC),
        PINMUX_IPSR_MSEL(IP0_5_4, LCD_DATA2_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_5_4, TCLKC_C, SEL_MTU2_CLK_1),
 
-       PINMUX_IPSR_DATA(IP0_7_6, A3),
-       PINMUX_IPSR_DATA(IP0_7_6, ST0_VLD),
+       PINMUX_IPSR_GPSR(IP0_7_6, A3),
+       PINMUX_IPSR_GPSR(IP0_7_6, ST0_VLD),
        PINMUX_IPSR_MSEL(IP0_7_6, LCD_DATA3_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_7_6, TCLKD_C, SEL_MTU2_CLK_1),
 
-       PINMUX_IPSR_DATA(IP0_9_8, A4),
-       PINMUX_IPSR_DATA(IP0_9_8, ST0_D0),
+       PINMUX_IPSR_GPSR(IP0_9_8, A4),
+       PINMUX_IPSR_GPSR(IP0_9_8, ST0_D0),
        PINMUX_IPSR_MSEL(IP0_9_8, LCD_DATA4_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_9_8, TIOC0A_C, SEL_MTU2_CH0_1),
 
-       PINMUX_IPSR_DATA(IP0_11_10, A5),
-       PINMUX_IPSR_DATA(IP0_11_10, ST0_D1),
+       PINMUX_IPSR_GPSR(IP0_11_10, A5),
+       PINMUX_IPSR_GPSR(IP0_11_10, ST0_D1),
        PINMUX_IPSR_MSEL(IP0_11_10, LCD_DATA5_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_11_10, TIOC0B_C, SEL_MTU2_CH0_1),
 
-       PINMUX_IPSR_DATA(IP0_13_12, A6),
-       PINMUX_IPSR_DATA(IP0_13_12, ST0_D2),
+       PINMUX_IPSR_GPSR(IP0_13_12, A6),
+       PINMUX_IPSR_GPSR(IP0_13_12, ST0_D2),
        PINMUX_IPSR_MSEL(IP0_13_12, LCD_DATA6_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_13_12, TIOC0C_C, SEL_MTU2_CH0_1),
 
-       PINMUX_IPSR_DATA(IP0_15_14, A7),
-       PINMUX_IPSR_DATA(IP0_15_14, ST0_D3),
+       PINMUX_IPSR_GPSR(IP0_15_14, A7),
+       PINMUX_IPSR_GPSR(IP0_15_14, ST0_D3),
        PINMUX_IPSR_MSEL(IP0_15_14, LCD_DATA7_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_15_14, TIOC0D_C, SEL_MTU2_CH0_1),
 
-       PINMUX_IPSR_DATA(IP0_17_16, A8),
-       PINMUX_IPSR_DATA(IP0_17_16, ST0_D4),
+       PINMUX_IPSR_GPSR(IP0_17_16, A8),
+       PINMUX_IPSR_GPSR(IP0_17_16, ST0_D4),
        PINMUX_IPSR_MSEL(IP0_17_16, LCD_DATA8_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_17_16, TIOC1A_C, SEL_MTU2_CH1_2),
 
-       PINMUX_IPSR_DATA(IP0_19_18, A9),
-       PINMUX_IPSR_DATA(IP0_19_18, ST0_D5),
+       PINMUX_IPSR_GPSR(IP0_19_18, A9),
+       PINMUX_IPSR_GPSR(IP0_19_18, ST0_D5),
        PINMUX_IPSR_MSEL(IP0_19_18, LCD_DATA9_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_19_18, TIOC1B_C, SEL_MTU2_CH1_2),
 
-       PINMUX_IPSR_DATA(IP0_21_20, A10),
-       PINMUX_IPSR_DATA(IP0_21_20, ST0_D6),
+       PINMUX_IPSR_GPSR(IP0_21_20, A10),
+       PINMUX_IPSR_GPSR(IP0_21_20, ST0_D6),
        PINMUX_IPSR_MSEL(IP0_21_20, LCD_DATA10_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_21_20, TIOC2A_C, SEL_MTU2_CH2_2),
 
-       PINMUX_IPSR_DATA(IP0_23_22, A11),
-       PINMUX_IPSR_DATA(IP0_23_22, ST0_D7),
+       PINMUX_IPSR_GPSR(IP0_23_22, A11),
+       PINMUX_IPSR_GPSR(IP0_23_22, ST0_D7),
        PINMUX_IPSR_MSEL(IP0_23_22, LCD_DATA11_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_23_22, TIOC2B_C, SEL_MTU2_CH2_2),
 
-       PINMUX_IPSR_DATA(IP0_25_24, A12),
+       PINMUX_IPSR_GPSR(IP0_25_24, A12),
        PINMUX_IPSR_MSEL(IP0_25_24, LCD_DATA12_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_25_24, TIOC3A_C, SEL_MTU2_CH3_1),
 
-       PINMUX_IPSR_DATA(IP0_27_26, A13),
+       PINMUX_IPSR_GPSR(IP0_27_26, A13),
        PINMUX_IPSR_MSEL(IP0_27_26, LCD_DATA13_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_27_26, TIOC3B_C, SEL_MTU2_CH3_1),
 
-       PINMUX_IPSR_DATA(IP0_29_28, A14),
+       PINMUX_IPSR_GPSR(IP0_29_28, A14),
        PINMUX_IPSR_MSEL(IP0_29_28, LCD_DATA14_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_29_28, TIOC3C_C, SEL_MTU2_CH3_1),
 
-       PINMUX_IPSR_DATA(IP0_31_30, A15),
-       PINMUX_IPSR_DATA(IP0_31_30, ST0_VCO_CLKIN),
+       PINMUX_IPSR_GPSR(IP0_31_30, A15),
+       PINMUX_IPSR_GPSR(IP0_31_30, ST0_VCO_CLKIN),
        PINMUX_IPSR_MSEL(IP0_31_30, LCD_DATA15_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP0_31_30, TIOC3D_C, SEL_MTU2_CH3_1),
 
 
        /* IPSR1 */
-       PINMUX_IPSR_DATA(IP1_1_0, A16),
-       PINMUX_IPSR_DATA(IP1_1_0, ST0_PWM),
+       PINMUX_IPSR_GPSR(IP1_1_0, A16),
+       PINMUX_IPSR_GPSR(IP1_1_0, ST0_PWM),
        PINMUX_IPSR_MSEL(IP1_1_0, LCD_DON_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP1_1_0, TIOC4A_C, SEL_MTU2_CH4_1),
 
-       PINMUX_IPSR_DATA(IP1_3_2, A17),
-       PINMUX_IPSR_DATA(IP1_3_2, ST1_VCO_CLKIN),
+       PINMUX_IPSR_GPSR(IP1_3_2, A17),
+       PINMUX_IPSR_GPSR(IP1_3_2, ST1_VCO_CLKIN),
        PINMUX_IPSR_MSEL(IP1_3_2, LCD_CL1_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP1_3_2, TIOC4B_C, SEL_MTU2_CH4_1),
 
-       PINMUX_IPSR_DATA(IP1_5_4, A18),
-       PINMUX_IPSR_DATA(IP1_5_4, ST1_PWM),
+       PINMUX_IPSR_GPSR(IP1_5_4, A18),
+       PINMUX_IPSR_GPSR(IP1_5_4, ST1_PWM),
        PINMUX_IPSR_MSEL(IP1_5_4, LCD_CL2_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP1_5_4, TIOC4C_C, SEL_MTU2_CH4_1),
 
-       PINMUX_IPSR_DATA(IP1_7_6, A19),
-       PINMUX_IPSR_DATA(IP1_7_6, ST1_CLKIN),
+       PINMUX_IPSR_GPSR(IP1_7_6, A19),
+       PINMUX_IPSR_GPSR(IP1_7_6, ST1_CLKIN),
        PINMUX_IPSR_MSEL(IP1_7_6, LCD_CLK_A, SEL_LCDC_0),
        PINMUX_IPSR_MSEL(IP1_7_6, TIOC4D_C, SEL_MTU2_CH4_1),
 
-       PINMUX_IPSR_DATA(IP1_9_8, A20),
-       PINMUX_IPSR_DATA(IP1_9_8, ST1_REQ),
+       PINMUX_IPSR_GPSR(IP1_9_8, A20),
+       PINMUX_IPSR_GPSR(IP1_9_8, ST1_REQ),
        PINMUX_IPSR_MSEL(IP1_9_8, LCD_FLM_A, SEL_LCDC_0),
 
-       PINMUX_IPSR_DATA(IP1_11_10, A21),
-       PINMUX_IPSR_DATA(IP1_11_10, ST1_SYC),
+       PINMUX_IPSR_GPSR(IP1_11_10, A21),
+       PINMUX_IPSR_GPSR(IP1_11_10, ST1_SYC),
        PINMUX_IPSR_MSEL(IP1_11_10, LCD_VCPWC_A, SEL_LCDC_0),
 
-       PINMUX_IPSR_DATA(IP1_13_12, A22),
-       PINMUX_IPSR_DATA(IP1_13_12, ST1_VLD),
+       PINMUX_IPSR_GPSR(IP1_13_12, A22),
+       PINMUX_IPSR_GPSR(IP1_13_12, ST1_VLD),
        PINMUX_IPSR_MSEL(IP1_13_12, LCD_VEPWC_A, SEL_LCDC_0),
 
-       PINMUX_IPSR_DATA(IP1_15_14, A23),
-       PINMUX_IPSR_DATA(IP1_15_14, ST1_D0),
+       PINMUX_IPSR_GPSR(IP1_15_14, A23),
+       PINMUX_IPSR_GPSR(IP1_15_14, ST1_D0),
        PINMUX_IPSR_MSEL(IP1_15_14, LCD_M_DISP_A, SEL_LCDC_0),
 
-       PINMUX_IPSR_DATA(IP1_17_16, A24),
+       PINMUX_IPSR_GPSR(IP1_17_16, A24),
        PINMUX_IPSR_MSEL(IP1_17_16, RX2_D, SEL_SCIF2_3),
-       PINMUX_IPSR_DATA(IP1_17_16, ST1_D1),
+       PINMUX_IPSR_GPSR(IP1_17_16, ST1_D1),
 
-       PINMUX_IPSR_DATA(IP1_19_18, A25),
+       PINMUX_IPSR_GPSR(IP1_19_18, A25),
        PINMUX_IPSR_MSEL(IP1_17_16, RX2_D, SEL_SCIF2_3),
-       PINMUX_IPSR_DATA(IP1_17_16, ST1_D2),
+       PINMUX_IPSR_GPSR(IP1_17_16, ST1_D2),
 
-       PINMUX_IPSR_DATA(IP1_22_20, D0),
+       PINMUX_IPSR_GPSR(IP1_22_20, D0),
        PINMUX_IPSR_MSEL(IP1_22_20, SD0_DAT0_A, SEL_SDHI0_0),
        PINMUX_IPSR_MSEL(IP1_22_20, MMC_D0_A, SEL_MMC_0),
-       PINMUX_IPSR_DATA(IP1_22_20, ST1_D3),
+       PINMUX_IPSR_GPSR(IP1_22_20, ST1_D3),
        PINMUX_IPSR_MSEL(IP1_22_20, FD0_A, SEL_FLCTL_0),
 
-       PINMUX_IPSR_DATA(IP1_25_23, D1),
+       PINMUX_IPSR_GPSR(IP1_25_23, D1),
        PINMUX_IPSR_MSEL(IP1_25_23, SD0_DAT0_A, SEL_SDHI0_0),
        PINMUX_IPSR_MSEL(IP1_25_23, MMC_D1_A, SEL_MMC_0),
-       PINMUX_IPSR_DATA(IP1_25_23, ST1_D4),
+       PINMUX_IPSR_GPSR(IP1_25_23, ST1_D4),
        PINMUX_IPSR_MSEL(IP1_25_23, FD1_A, SEL_FLCTL_0),
 
-       PINMUX_IPSR_DATA(IP1_28_26, D2),
+       PINMUX_IPSR_GPSR(IP1_28_26, D2),
        PINMUX_IPSR_MSEL(IP1_28_26, SD0_DAT0_A, SEL_SDHI0_0),
        PINMUX_IPSR_MSEL(IP1_28_26, MMC_D2_A, SEL_MMC_0),
-       PINMUX_IPSR_DATA(IP1_28_26, ST1_D5),
+       PINMUX_IPSR_GPSR(IP1_28_26, ST1_D5),
        PINMUX_IPSR_MSEL(IP1_28_26, FD2_A, SEL_FLCTL_0),
 
-       PINMUX_IPSR_DATA(IP1_31_29, D3),
+       PINMUX_IPSR_GPSR(IP1_31_29, D3),
        PINMUX_IPSR_MSEL(IP1_31_29, SD0_DAT0_A, SEL_SDHI0_0),
        PINMUX_IPSR_MSEL(IP1_31_29, MMC_D3_A, SEL_MMC_0),
-       PINMUX_IPSR_DATA(IP1_31_29, ST1_D6),
+       PINMUX_IPSR_GPSR(IP1_31_29, ST1_D6),
        PINMUX_IPSR_MSEL(IP1_31_29, FD3_A, SEL_FLCTL_0),
 
        /* IPSR2 */
-       PINMUX_IPSR_DATA(IP2_2_0, D4),
+       PINMUX_IPSR_GPSR(IP2_2_0, D4),
        PINMUX_IPSR_MSEL(IP2_2_0, SD0_CD_A, SEL_SDHI0_0),
        PINMUX_IPSR_MSEL(IP2_2_0, MMC_D4_A, SEL_MMC_0),
-       PINMUX_IPSR_DATA(IP2_2_0, ST1_D7),
+       PINMUX_IPSR_GPSR(IP2_2_0, ST1_D7),
        PINMUX_IPSR_MSEL(IP2_2_0, FD4_A, SEL_FLCTL_0),
 
-       PINMUX_IPSR_DATA(IP2_4_3, D5),
+       PINMUX_IPSR_GPSR(IP2_4_3, D5),
        PINMUX_IPSR_MSEL(IP2_4_3, SD0_WP_A, SEL_SDHI0_0),
        PINMUX_IPSR_MSEL(IP2_4_3, MMC_D5_A, SEL_MMC_0),
        PINMUX_IPSR_MSEL(IP2_4_3, FD5_A, SEL_FLCTL_0),
 
-       PINMUX_IPSR_DATA(IP2_7_5, D6),
+       PINMUX_IPSR_GPSR(IP2_7_5, D6),
        PINMUX_IPSR_MSEL(IP2_7_5, RSPI_RSPCK_A, SEL_RSPI_0),
        PINMUX_IPSR_MSEL(IP2_7_5, MMC_D6_A, SEL_MMC_0),
        PINMUX_IPSR_MSEL(IP2_7_5, QSPCLK_A, SEL_RQSPI_0),
        PINMUX_IPSR_MSEL(IP2_7_5, FD6_A, SEL_FLCTL_0),
 
-       PINMUX_IPSR_DATA(IP2_10_8, D7),
+       PINMUX_IPSR_GPSR(IP2_10_8, D7),
        PINMUX_IPSR_MSEL(IP2_10_8, RSPI_SSL_A, SEL_RSPI_0),
        PINMUX_IPSR_MSEL(IP2_10_8, MMC_D7_A, SEL_MMC_0),
        PINMUX_IPSR_MSEL(IP2_10_8, QSSL_A, SEL_RQSPI_0),
        PINMUX_IPSR_MSEL(IP2_10_8, FD7_A, SEL_FLCTL_0),
 
-       PINMUX_IPSR_DATA(IP2_13_11, D8),
+       PINMUX_IPSR_GPSR(IP2_13_11, D8),
        PINMUX_IPSR_MSEL(IP2_13_11, SD0_CLK_A, SEL_SDHI0_0),
        PINMUX_IPSR_MSEL(IP2_13_11, MMC_CLK_A, SEL_MMC_0),
        PINMUX_IPSR_MSEL(IP2_13_11, QIO2_A, SEL_RQSPI_0),
        PINMUX_IPSR_MSEL(IP2_13_11, FCE_A, SEL_FLCTL_0),
        PINMUX_IPSR_MSEL(IP2_13_11, ET0_GTX_CLK_B, SEL_ET0_1),
 
-       PINMUX_IPSR_DATA(IP2_16_14, D9),
+       PINMUX_IPSR_GPSR(IP2_16_14, D9),
        PINMUX_IPSR_MSEL(IP2_16_14, SD0_CMD_A, SEL_SDHI0_0),
        PINMUX_IPSR_MSEL(IP2_16_14, MMC_CMD_A, SEL_MMC_0),
        PINMUX_IPSR_MSEL(IP2_16_14, QIO3_A, SEL_RQSPI_0),
        PINMUX_IPSR_MSEL(IP2_16_14, FCLE_A, SEL_FLCTL_0),
        PINMUX_IPSR_MSEL(IP2_16_14, ET0_ETXD1_B, SEL_ET0_1),
 
-       PINMUX_IPSR_DATA(IP2_19_17, D10),
+       PINMUX_IPSR_GPSR(IP2_19_17, D10),
        PINMUX_IPSR_MSEL(IP2_19_17, RSPI_MOSI_A, SEL_RSPI_0),
        PINMUX_IPSR_MSEL(IP2_19_17, QMO_QIO0_A, SEL_RQSPI_0),
        PINMUX_IPSR_MSEL(IP2_19_17, FALE_A, SEL_FLCTL_0),
        PINMUX_IPSR_MSEL(IP2_19_17, ET0_ETXD2_B, SEL_ET0_1),
 
-       PINMUX_IPSR_DATA(IP2_22_20, D11),
+       PINMUX_IPSR_GPSR(IP2_22_20, D11),
        PINMUX_IPSR_MSEL(IP2_22_20, RSPI_MISO_A, SEL_RSPI_0),
        PINMUX_IPSR_MSEL(IP2_22_20, QMI_QIO1_A, SEL_RQSPI_0),
        PINMUX_IPSR_MSEL(IP2_22_20, FRE_A, SEL_FLCTL_0),
 
-       PINMUX_IPSR_DATA(IP2_24_23, D12),
+       PINMUX_IPSR_GPSR(IP2_24_23, D12),
        PINMUX_IPSR_MSEL(IP2_24_23, FWE_A, SEL_FLCTL_0),
        PINMUX_IPSR_MSEL(IP2_24_23, ET0_ETXD5_B, SEL_ET0_1),
 
-       PINMUX_IPSR_DATA(IP2_27_25, D13),
+       PINMUX_IPSR_GPSR(IP2_27_25, D13),
        PINMUX_IPSR_MSEL(IP2_27_25, RX2_B, SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP2_27_25, FRB_A, SEL_FLCTL_0),
        PINMUX_IPSR_MSEL(IP2_27_25, ET0_ETXD6_B, SEL_ET0_1),
 
-       PINMUX_IPSR_DATA(IP2_30_28, D14),
+       PINMUX_IPSR_GPSR(IP2_30_28, D14),
        PINMUX_IPSR_MSEL(IP2_30_28, TX2_B, SEL_SCIF2_1),
        PINMUX_IPSR_MSEL(IP2_30_28, FSE_A, SEL_FLCTL_0),
        PINMUX_IPSR_MSEL(IP2_30_28, ET0_TX_CLK_B, SEL_ET0_1),
 
        /* IPSR3 */
-       PINMUX_IPSR_DATA(IP3_1_0, D15),
+       PINMUX_IPSR_GPSR(IP3_1_0, D15),
        PINMUX_IPSR_MSEL(IP3_1_0, SCK2_B, SEL_SCIF2_1),
 
-       PINMUX_IPSR_DATA(IP3_2, CS1_A26),
+       PINMUX_IPSR_GPSR(IP3_2, CS1_A26),
        PINMUX_IPSR_MSEL(IP3_2, QIO3_B, SEL_RQSPI_1),
 
-       PINMUX_IPSR_DATA(IP3_5_3, EX_CS1),
+       PINMUX_IPSR_GPSR(IP3_5_3, EX_CS1),
        PINMUX_IPSR_MSEL(IP3_5_3, RX3_B, SEL_SCIF2_1),
-       PINMUX_IPSR_DATA(IP3_5_3, ATACS0),
+       PINMUX_IPSR_GPSR(IP3_5_3, ATACS0),
        PINMUX_IPSR_MSEL(IP3_5_3, QIO2_B, SEL_RQSPI_1),
-       PINMUX_IPSR_DATA(IP3_5_3, ET0_ETXD0),
+       PINMUX_IPSR_GPSR(IP3_5_3, ET0_ETXD0),
 
-       PINMUX_IPSR_DATA(IP3_8_6, EX_CS2),
+       PINMUX_IPSR_GPSR(IP3_8_6, EX_CS2),
        PINMUX_IPSR_MSEL(IP3_8_6, TX3_B, SEL_SCIF3_1),
-       PINMUX_IPSR_DATA(IP3_8_6, ATACS1),
+       PINMUX_IPSR_GPSR(IP3_8_6, ATACS1),
        PINMUX_IPSR_MSEL(IP3_8_6, QSPCLK_B, SEL_RQSPI_1),
        PINMUX_IPSR_MSEL(IP3_8_6, ET0_GTX_CLK_A, SEL_ET0_0),
 
-       PINMUX_IPSR_DATA(IP3_11_9, EX_CS3),
+       PINMUX_IPSR_GPSR(IP3_11_9, EX_CS3),
        PINMUX_IPSR_MSEL(IP3_11_9, SD1_CD_A, SEL_SDHI1_0),
-       PINMUX_IPSR_DATA(IP3_11_9, ATARD),
+       PINMUX_IPSR_GPSR(IP3_11_9, ATARD),
        PINMUX_IPSR_MSEL(IP3_11_9, QMO_QIO0_B, SEL_RQSPI_1),
        PINMUX_IPSR_MSEL(IP3_11_9, ET0_ETXD1_A, SEL_ET0_0),
 
-       PINMUX_IPSR_DATA(IP3_14_12, EX_CS4),
+       PINMUX_IPSR_GPSR(IP3_14_12, EX_CS4),
        PINMUX_IPSR_MSEL(IP3_14_12, SD1_WP_A, SEL_SDHI1_0),
-       PINMUX_IPSR_DATA(IP3_14_12, ATAWR),
+       PINMUX_IPSR_GPSR(IP3_14_12, ATAWR),
        PINMUX_IPSR_MSEL(IP3_14_12, QMI_QIO1_B, SEL_RQSPI_1),
        PINMUX_IPSR_MSEL(IP3_14_12, ET0_ETXD2_A, SEL_ET0_0),
 
-       PINMUX_IPSR_DATA(IP3_17_15, EX_CS5),
+       PINMUX_IPSR_GPSR(IP3_17_15, EX_CS5),
        PINMUX_IPSR_MSEL(IP3_17_15, SD1_CMD_A, SEL_SDHI1_0),
-       PINMUX_IPSR_DATA(IP3_17_15, ATADIR),
+       PINMUX_IPSR_GPSR(IP3_17_15, ATADIR),
        PINMUX_IPSR_MSEL(IP3_17_15, QSSL_B, SEL_RQSPI_1),
        PINMUX_IPSR_MSEL(IP3_17_15, ET0_ETXD3_A, SEL_ET0_0),
 
-       PINMUX_IPSR_DATA(IP3_19_18, RD_WR),
-       PINMUX_IPSR_DATA(IP3_19_18, TCLK0),
+       PINMUX_IPSR_GPSR(IP3_19_18, RD_WR),
+       PINMUX_IPSR_GPSR(IP3_19_18, TCLK0),
        PINMUX_IPSR_MSEL(IP3_19_18, CAN_CLK_B, SEL_RCAN_CLK_1),
-       PINMUX_IPSR_DATA(IP3_19_18, ET0_ETXD4),
+       PINMUX_IPSR_GPSR(IP3_19_18, ET0_ETXD4),
 
-       PINMUX_IPSR_DATA(IP3_20, EX_WAIT0),
+       PINMUX_IPSR_GPSR(IP3_20, EX_WAIT0),
        PINMUX_IPSR_MSEL(IP3_20, TCLK1_B, SEL_TMU_1),
 
-       PINMUX_IPSR_DATA(IP3_23_21, EX_WAIT1),
+       PINMUX_IPSR_GPSR(IP3_23_21, EX_WAIT1),
        PINMUX_IPSR_MSEL(IP3_23_21, SD1_DAT0_A, SEL_SDHI1_0),
-       PINMUX_IPSR_DATA(IP3_23_21, DREQ2),
+       PINMUX_IPSR_GPSR(IP3_23_21, DREQ2),
        PINMUX_IPSR_MSEL(IP3_23_21, CAN1_TX_C, SEL_RCAN1_2),
        PINMUX_IPSR_MSEL(IP3_23_21, ET0_LINK_C, SEL_ET0_CTL_2),
        PINMUX_IPSR_MSEL(IP3_23_21, ET0_ETXD5_A, SEL_ET0_0),
 
-       PINMUX_IPSR_DATA(IP3_26_24, EX_WAIT2),
+       PINMUX_IPSR_GPSR(IP3_26_24, EX_WAIT2),
        PINMUX_IPSR_MSEL(IP3_26_24, SD1_DAT1_A, SEL_SDHI1_0),
-       PINMUX_IPSR_DATA(IP3_26_24, DACK2),
+       PINMUX_IPSR_GPSR(IP3_26_24, DACK2),
        PINMUX_IPSR_MSEL(IP3_26_24, CAN1_RX_C, SEL_RCAN1_2),
        PINMUX_IPSR_MSEL(IP3_26_24, ET0_MAGIC_C, SEL_ET0_CTL_2),
        PINMUX_IPSR_MSEL(IP3_26_24, ET0_ETXD6_A, SEL_ET0_0),
 
-       PINMUX_IPSR_DATA(IP3_29_27, DRACK0),
+       PINMUX_IPSR_GPSR(IP3_29_27, DRACK0),
        PINMUX_IPSR_MSEL(IP3_29_27, SD1_DAT2_A, SEL_SDHI1_0),
-       PINMUX_IPSR_DATA(IP3_29_27, ATAG),
+       PINMUX_IPSR_GPSR(IP3_29_27, ATAG),
        PINMUX_IPSR_MSEL(IP3_29_27, TCLK1_A, SEL_TMU_0),
-       PINMUX_IPSR_DATA(IP3_29_27, ET0_ETXD7),
+       PINMUX_IPSR_GPSR(IP3_29_27, ET0_ETXD7),
 
        /* IPSR4 */
        PINMUX_IPSR_MSEL(IP4_2_0, HCTS0_A, SEL_HSCIF_0),
        PINMUX_IPSR_MSEL(IP4_2_0, CTS1_A, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP4_2_0, VI0_FIELD),
+       PINMUX_IPSR_GPSR(IP4_2_0, VI0_FIELD),
        PINMUX_IPSR_MSEL(IP4_2_0, RMII0_RXD1_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP4_2_0, ET0_ERXD7),
+       PINMUX_IPSR_GPSR(IP4_2_0, ET0_ERXD7),
 
        PINMUX_IPSR_MSEL(IP4_5_3, HRTS0_A, SEL_HSCIF_0),
        PINMUX_IPSR_MSEL(IP4_5_3, RTS1_A, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP4_5_3, VI0_HSYNC),
+       PINMUX_IPSR_GPSR(IP4_5_3, VI0_HSYNC),
        PINMUX_IPSR_MSEL(IP4_5_3, RMII0_TXD_EN_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP4_5_3, ET0_RX_DV),
+       PINMUX_IPSR_GPSR(IP4_5_3, ET0_RX_DV),
 
        PINMUX_IPSR_MSEL(IP4_8_6, HSCK0_A, SEL_HSCIF_0),
        PINMUX_IPSR_MSEL(IP4_8_6, SCK1_A, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP4_8_6, VI0_VSYNC),
+       PINMUX_IPSR_GPSR(IP4_8_6, VI0_VSYNC),
        PINMUX_IPSR_MSEL(IP4_8_6, RMII0_RX_ER_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP4_8_6, ET0_RX_ER),
+       PINMUX_IPSR_GPSR(IP4_8_6, ET0_RX_ER),
 
        PINMUX_IPSR_MSEL(IP4_11_9, HRX0_A, SEL_HSCIF_0),
        PINMUX_IPSR_MSEL(IP4_11_9, RX1_A, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP4_11_9, VI0_DATA0_VI0_B0),
+       PINMUX_IPSR_GPSR(IP4_11_9, VI0_DATA0_VI0_B0),
        PINMUX_IPSR_MSEL(IP4_11_9, RMII0_CRS_DV_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP4_11_9, ET0_CRS),
+       PINMUX_IPSR_GPSR(IP4_11_9, ET0_CRS),
 
        PINMUX_IPSR_MSEL(IP4_14_12, HTX0_A, SEL_HSCIF_0),
        PINMUX_IPSR_MSEL(IP4_14_12, TX1_A, SEL_SCIF1_0),
-       PINMUX_IPSR_DATA(IP4_14_12, VI0_DATA1_VI0_B1),
+       PINMUX_IPSR_GPSR(IP4_14_12, VI0_DATA1_VI0_B1),
        PINMUX_IPSR_MSEL(IP4_14_12, RMII0_MDC_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP4_14_12, ET0_COL),
+       PINMUX_IPSR_GPSR(IP4_14_12, ET0_COL),
 
        PINMUX_IPSR_MSEL(IP4_17_15, CTS0_B, SEL_SCIF0_1),
-       PINMUX_IPSR_DATA(IP4_17_15, VI0_DATA2_VI0_B2),
+       PINMUX_IPSR_GPSR(IP4_17_15, VI0_DATA2_VI0_B2),
        PINMUX_IPSR_MSEL(IP4_17_15, RMII0_MDIO_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP4_17_15, ET0_MDC),
+       PINMUX_IPSR_GPSR(IP4_17_15, ET0_MDC),
 
        PINMUX_IPSR_MSEL(IP4_19_18, RTS0_B, SEL_SCIF0_1),
-       PINMUX_IPSR_DATA(IP4_19_18, VI0_DATA3_VI0_B3),
+       PINMUX_IPSR_GPSR(IP4_19_18, VI0_DATA3_VI0_B3),
        PINMUX_IPSR_MSEL(IP4_19_18, ET0_MDIO_A, SEL_ET0_0),
 
        PINMUX_IPSR_MSEL(IP4_21_20, SCK1_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP4_21_20, VI0_DATA4_VI0_B4),
+       PINMUX_IPSR_GPSR(IP4_21_20, VI0_DATA4_VI0_B4),
        PINMUX_IPSR_MSEL(IP4_21_20, ET0_LINK_A, SEL_ET0_CTL_0),
 
        PINMUX_IPSR_MSEL(IP4_23_22, RX1_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP4_23_22, VI0_DATA5_VI0_B5),
+       PINMUX_IPSR_GPSR(IP4_23_22, VI0_DATA5_VI0_B5),
        PINMUX_IPSR_MSEL(IP4_23_22, ET0_MAGIC_A, SEL_ET0_CTL_0),
 
        PINMUX_IPSR_MSEL(IP4_25_24, TX1_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP4_25_24, VI0_DATA6_VI0_G0),
+       PINMUX_IPSR_GPSR(IP4_25_24, VI0_DATA6_VI0_G0),
        PINMUX_IPSR_MSEL(IP4_25_24, ET0_PHY_INT_A, SEL_ET0_CTL_0),
 
        PINMUX_IPSR_MSEL(IP4_27_26, CTS1_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP4_27_26, VI0_DATA7_VI0_G1),
+       PINMUX_IPSR_GPSR(IP4_27_26, VI0_DATA7_VI0_G1),
 
        PINMUX_IPSR_MSEL(IP4_29_28, RTS1_B, SEL_SCIF1_1),
-       PINMUX_IPSR_DATA(IP4_29_28, VI0_G2),
+       PINMUX_IPSR_GPSR(IP4_29_28, VI0_G2),
 
        PINMUX_IPSR_MSEL(IP4_31_30, SCK2_A, SEL_SCIF2_0),
-       PINMUX_IPSR_DATA(IP4_31_30, VI0_G3),
+       PINMUX_IPSR_GPSR(IP4_31_30, VI0_G3),
 
        /* IPSR5 */
        PINMUX_IPSR_MSEL(IP5_2_0, SD2_CLK_A, SEL_SDHI2_0),
        PINMUX_IPSR_MSEL(IP5_2_0, RX2_A, SEL_SCIF2_0),
-       PINMUX_IPSR_DATA(IP5_2_0, VI0_G4),
+       PINMUX_IPSR_GPSR(IP5_2_0, VI0_G4),
        PINMUX_IPSR_MSEL(IP5_2_0, ET0_RX_CLK_B, SEL_ET0_1),
 
        PINMUX_IPSR_MSEL(IP5_5_3, SD2_CMD_A, SEL_SDHI2_0),
        PINMUX_IPSR_MSEL(IP5_5_3, TX2_A, SEL_SCIF2_0),
-       PINMUX_IPSR_DATA(IP5_5_3, VI0_G5),
+       PINMUX_IPSR_GPSR(IP5_5_3, VI0_G5),
        PINMUX_IPSR_MSEL(IP5_5_3, ET0_ERXD2_B, SEL_ET0_1),
 
        PINMUX_IPSR_MSEL(IP5_8_6, SD2_DAT0_A, SEL_SDHI2_0),
        PINMUX_IPSR_MSEL(IP5_8_6, RX3_A, SEL_SCIF3_0),
-       PINMUX_IPSR_DATA(IP4_8_6, VI0_R0),
+       PINMUX_IPSR_GPSR(IP4_8_6, VI0_R0),
        PINMUX_IPSR_MSEL(IP4_8_6, ET0_ERXD2_B, SEL_ET0_1),
 
        PINMUX_IPSR_MSEL(IP5_11_9, SD2_DAT1_A, SEL_SDHI2_0),
        PINMUX_IPSR_MSEL(IP5_11_9, TX3_A, SEL_SCIF3_0),
-       PINMUX_IPSR_DATA(IP5_11_9, VI0_R1),
+       PINMUX_IPSR_GPSR(IP5_11_9, VI0_R1),
        PINMUX_IPSR_MSEL(IP5_11_9, ET0_MDIO_B, SEL_ET0_1),
 
        PINMUX_IPSR_MSEL(IP5_14_12, SD2_DAT2_A, SEL_SDHI2_0),
        PINMUX_IPSR_MSEL(IP5_14_12, RX4_A, SEL_SCIF4_0),
-       PINMUX_IPSR_DATA(IP5_14_12, VI0_R2),
+       PINMUX_IPSR_GPSR(IP5_14_12, VI0_R2),
        PINMUX_IPSR_MSEL(IP5_14_12, ET0_LINK_B, SEL_ET0_CTL_1),
 
        PINMUX_IPSR_MSEL(IP5_17_15, SD2_DAT3_A, SEL_SDHI2_0),
        PINMUX_IPSR_MSEL(IP5_17_15, TX4_A, SEL_SCIF4_0),
-       PINMUX_IPSR_DATA(IP5_17_15, VI0_R3),
+       PINMUX_IPSR_GPSR(IP5_17_15, VI0_R3),
        PINMUX_IPSR_MSEL(IP5_17_15, ET0_MAGIC_B, SEL_ET0_CTL_1),
 
        PINMUX_IPSR_MSEL(IP5_20_18, SD2_CD_A, SEL_SDHI2_0),
        PINMUX_IPSR_MSEL(IP5_20_18, RX5_A, SEL_SCIF5_0),
-       PINMUX_IPSR_DATA(IP5_20_18, VI0_R4),
+       PINMUX_IPSR_GPSR(IP5_20_18, VI0_R4),
        PINMUX_IPSR_MSEL(IP5_20_18, ET0_PHY_INT_B, SEL_ET0_CTL_1),
 
        PINMUX_IPSR_MSEL(IP5_22_21, SD2_WP_A, SEL_SDHI2_0),
        PINMUX_IPSR_MSEL(IP5_22_21, TX5_A, SEL_SCIF5_0),
-       PINMUX_IPSR_DATA(IP5_22_21, VI0_R5),
+       PINMUX_IPSR_GPSR(IP5_22_21, VI0_R5),
 
-       PINMUX_IPSR_DATA(IP5_24_23, REF125CK),
-       PINMUX_IPSR_DATA(IP5_24_23, ADTRG),
+       PINMUX_IPSR_GPSR(IP5_24_23, REF125CK),
+       PINMUX_IPSR_GPSR(IP5_24_23, ADTRG),
        PINMUX_IPSR_MSEL(IP5_24_23, RX5_C, SEL_SCIF5_2),
-       PINMUX_IPSR_DATA(IP5_26_25, REF50CK),
+       PINMUX_IPSR_GPSR(IP5_26_25, REF50CK),
        PINMUX_IPSR_MSEL(IP5_26_25, CTS1_E, SEL_SCIF1_3),
        PINMUX_IPSR_MSEL(IP5_26_25, HCTS0_D, SEL_HSCIF_3),
 
        /* IPSR6 */
-       PINMUX_IPSR_DATA(IP6_2_0, DU0_DR0),
+       PINMUX_IPSR_GPSR(IP6_2_0, DU0_DR0),
        PINMUX_IPSR_MSEL(IP6_2_0, SCIF_CLK_B, SEL_SCIF_CLK_1),
        PINMUX_IPSR_MSEL(IP6_2_0, HRX0_D, SEL_HSCIF_3),
        PINMUX_IPSR_MSEL(IP6_2_0, IETX_A, SEL_IEBUS_0),
        PINMUX_IPSR_MSEL(IP6_2_0, TCLKA_A, SEL_MTU2_CLK_0),
-       PINMUX_IPSR_DATA(IP6_2_0, HIFD00),
+       PINMUX_IPSR_GPSR(IP6_2_0, HIFD00),
 
-       PINMUX_IPSR_DATA(IP6_5_3, DU0_DR1),
+       PINMUX_IPSR_GPSR(IP6_5_3, DU0_DR1),
        PINMUX_IPSR_MSEL(IP6_5_3, SCK0_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP6_5_3, HTX0_D, SEL_HSCIF_3),
        PINMUX_IPSR_MSEL(IP6_5_3, IERX_A, SEL_IEBUS_0),
        PINMUX_IPSR_MSEL(IP6_5_3, TCLKB_A, SEL_MTU2_CLK_0),
-       PINMUX_IPSR_DATA(IP6_5_3, HIFD01),
+       PINMUX_IPSR_GPSR(IP6_5_3, HIFD01),
 
-       PINMUX_IPSR_DATA(IP6_7_6, DU0_DR2),
+       PINMUX_IPSR_GPSR(IP6_7_6, DU0_DR2),
        PINMUX_IPSR_MSEL(IP6_7_6, RX0_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP6_7_6, TCLKC_A, SEL_MTU2_CLK_0),
-       PINMUX_IPSR_DATA(IP6_7_6, HIFD02),
+       PINMUX_IPSR_GPSR(IP6_7_6, HIFD02),
 
-       PINMUX_IPSR_DATA(IP6_9_8, DU0_DR3),
+       PINMUX_IPSR_GPSR(IP6_9_8, DU0_DR3),
        PINMUX_IPSR_MSEL(IP6_9_8, TX0_B, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP6_9_8, TCLKD_A, SEL_MTU2_CLK_0),
-       PINMUX_IPSR_DATA(IP6_9_8, HIFD03),
+       PINMUX_IPSR_GPSR(IP6_9_8, HIFD03),
 
-       PINMUX_IPSR_DATA(IP6_11_10, DU0_DR4),
+       PINMUX_IPSR_GPSR(IP6_11_10, DU0_DR4),
        PINMUX_IPSR_MSEL(IP6_11_10, CTS0_C, SEL_SCIF0_2),
        PINMUX_IPSR_MSEL(IP6_11_10, TIOC0A_A, SEL_MTU2_CH0_0),
-       PINMUX_IPSR_DATA(IP6_11_10, HIFD04),
+       PINMUX_IPSR_GPSR(IP6_11_10, HIFD04),
 
-       PINMUX_IPSR_DATA(IP6_13_12, DU0_DR5),
+       PINMUX_IPSR_GPSR(IP6_13_12, DU0_DR5),
        PINMUX_IPSR_MSEL(IP6_13_12, RTS0_C, SEL_SCIF0_1),
        PINMUX_IPSR_MSEL(IP6_13_12, TIOC0B_A, SEL_MTU2_CH0_0),
-       PINMUX_IPSR_DATA(IP6_13_12, HIFD05),
+       PINMUX_IPSR_GPSR(IP6_13_12, HIFD05),
 
-       PINMUX_IPSR_DATA(IP6_15_14, DU0_DR6),
+       PINMUX_IPSR_GPSR(IP6_15_14, DU0_DR6),
        PINMUX_IPSR_MSEL(IP6_15_14, SCK1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP6_15_14, TIOC0C_A, SEL_MTU2_CH0_0),
-       PINMUX_IPSR_DATA(IP6_15_14, HIFD06),
+       PINMUX_IPSR_GPSR(IP6_15_14, HIFD06),
 
-       PINMUX_IPSR_DATA(IP6_17_16, DU0_DR7),
+       PINMUX_IPSR_GPSR(IP6_17_16, DU0_DR7),
        PINMUX_IPSR_MSEL(IP6_17_16, RX1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP6_17_16, TIOC0D_A, SEL_MTU2_CH0_0),
-       PINMUX_IPSR_DATA(IP6_17_16, HIFD07),
+       PINMUX_IPSR_GPSR(IP6_17_16, HIFD07),
 
-       PINMUX_IPSR_DATA(IP6_20_18, DU0_DG0),
+       PINMUX_IPSR_GPSR(IP6_20_18, DU0_DG0),
        PINMUX_IPSR_MSEL(IP6_20_18, TX1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP6_20_18, HSCK0_D, SEL_HSCIF_3),
        PINMUX_IPSR_MSEL(IP6_20_18, IECLK_A, SEL_IEBUS_0),
        PINMUX_IPSR_MSEL(IP6_20_18, TIOC1A_A, SEL_MTU2_CH1_0),
-       PINMUX_IPSR_DATA(IP6_20_18, HIFD08),
+       PINMUX_IPSR_GPSR(IP6_20_18, HIFD08),
 
-       PINMUX_IPSR_DATA(IP6_23_21, DU0_DG1),
+       PINMUX_IPSR_GPSR(IP6_23_21, DU0_DG1),
        PINMUX_IPSR_MSEL(IP6_23_21, CTS1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP6_23_21, HRTS0_D, SEL_HSCIF_3),
        PINMUX_IPSR_MSEL(IP6_23_21, TIOC1B_A, SEL_MTU2_CH1_0),
-       PINMUX_IPSR_DATA(IP6_23_21, HIFD09),
+       PINMUX_IPSR_GPSR(IP6_23_21, HIFD09),
 
        /* IPSR7 */
-       PINMUX_IPSR_DATA(IP7_2_0, DU0_DG2),
+       PINMUX_IPSR_GPSR(IP7_2_0, DU0_DG2),
        PINMUX_IPSR_MSEL(IP7_2_0, RTS1_C, SEL_SCIF1_2),
        PINMUX_IPSR_MSEL(IP7_2_0, RMII0_MDC_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_2_0, TIOC2A_A, SEL_MTU2_CH2_0),
-       PINMUX_IPSR_DATA(IP7_2_0, HIFD10),
+       PINMUX_IPSR_GPSR(IP7_2_0, HIFD10),
 
-       PINMUX_IPSR_DATA(IP7_5_3, DU0_DG3),
+       PINMUX_IPSR_GPSR(IP7_5_3, DU0_DG3),
        PINMUX_IPSR_MSEL(IP7_5_3, SCK2_C, SEL_SCIF2_2),
        PINMUX_IPSR_MSEL(IP7_5_3, RMII0_MDIO_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_5_3, TIOC2B_A, SEL_MTU2_CH2_0),
-       PINMUX_IPSR_DATA(IP7_5_3, HIFD11),
+       PINMUX_IPSR_GPSR(IP7_5_3, HIFD11),
 
-       PINMUX_IPSR_DATA(IP7_8_6, DU0_DG4),
+       PINMUX_IPSR_GPSR(IP7_8_6, DU0_DG4),
        PINMUX_IPSR_MSEL(IP7_8_6, RX2_C, SEL_SCIF2_2),
        PINMUX_IPSR_MSEL(IP7_8_6, RMII0_CRS_DV_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_8_6, TIOC3A_A, SEL_MTU2_CH3_0),
-       PINMUX_IPSR_DATA(IP7_8_6, HIFD12),
+       PINMUX_IPSR_GPSR(IP7_8_6, HIFD12),
 
-       PINMUX_IPSR_DATA(IP7_11_9, DU0_DG5),
+       PINMUX_IPSR_GPSR(IP7_11_9, DU0_DG5),
        PINMUX_IPSR_MSEL(IP7_11_9, TX2_C, SEL_SCIF2_2),
        PINMUX_IPSR_MSEL(IP7_11_9, RMII0_RX_ER_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_11_9, TIOC3B_A, SEL_MTU2_CH3_0),
-       PINMUX_IPSR_DATA(IP7_11_9, HIFD13),
+       PINMUX_IPSR_GPSR(IP7_11_9, HIFD13),
 
-       PINMUX_IPSR_DATA(IP7_14_12, DU0_DG6),
+       PINMUX_IPSR_GPSR(IP7_14_12, DU0_DG6),
        PINMUX_IPSR_MSEL(IP7_14_12, RX3_C, SEL_SCIF3_2),
        PINMUX_IPSR_MSEL(IP7_14_12, RMII0_RXD0_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_14_12, TIOC3C_A, SEL_MTU2_CH3_0),
-       PINMUX_IPSR_DATA(IP7_14_12, HIFD14),
+       PINMUX_IPSR_GPSR(IP7_14_12, HIFD14),
 
-       PINMUX_IPSR_DATA(IP7_17_15, DU0_DG7),
+       PINMUX_IPSR_GPSR(IP7_17_15, DU0_DG7),
        PINMUX_IPSR_MSEL(IP7_17_15, TX3_C, SEL_SCIF3_2),
        PINMUX_IPSR_MSEL(IP7_17_15, RMII0_RXD1_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_17_15, TIOC3D_A, SEL_MTU2_CH3_0),
-       PINMUX_IPSR_DATA(IP7_17_15, HIFD15),
+       PINMUX_IPSR_GPSR(IP7_17_15, HIFD15),
 
-       PINMUX_IPSR_DATA(IP7_20_18, DU0_DB0),
+       PINMUX_IPSR_GPSR(IP7_20_18, DU0_DB0),
        PINMUX_IPSR_MSEL(IP7_20_18, RX4_C, SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP7_20_18, RMII0_TXD_EN_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_20_18, TIOC4A_A, SEL_MTU2_CH4_0),
-       PINMUX_IPSR_DATA(IP7_20_18, HIFCS),
+       PINMUX_IPSR_GPSR(IP7_20_18, HIFCS),
 
-       PINMUX_IPSR_DATA(IP7_23_21, DU0_DB1),
+       PINMUX_IPSR_GPSR(IP7_23_21, DU0_DB1),
        PINMUX_IPSR_MSEL(IP7_23_21, TX4_C, SEL_SCIF4_2),
        PINMUX_IPSR_MSEL(IP7_23_21, RMII0_TXD0_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_23_21, TIOC4B_A, SEL_MTU2_CH4_0),
-       PINMUX_IPSR_DATA(IP7_23_21, HIFWR),
+       PINMUX_IPSR_GPSR(IP7_23_21, HIFWR),
 
-       PINMUX_IPSR_DATA(IP7_26_24, DU0_DB2),
+       PINMUX_IPSR_GPSR(IP7_26_24, DU0_DB2),
        PINMUX_IPSR_MSEL(IP7_26_24, RX5_B, SEL_SCIF5_1),
        PINMUX_IPSR_MSEL(IP7_26_24, RMII0_TXD1_B, SEL_RMII_1),
        PINMUX_IPSR_MSEL(IP7_26_24, TIOC4C_A, SEL_MTU2_CH4_0),
 
-       PINMUX_IPSR_DATA(IP7_28_27, DU0_DB3),
+       PINMUX_IPSR_GPSR(IP7_28_27, DU0_DB3),
        PINMUX_IPSR_MSEL(IP7_28_27, TX5_B, SEL_SCIF5_1),
        PINMUX_IPSR_MSEL(IP7_28_27, TIOC4D_A, SEL_MTU2_CH4_0),
-       PINMUX_IPSR_DATA(IP7_28_27, HIFRD),
+       PINMUX_IPSR_GPSR(IP7_28_27, HIFRD),
 
-       PINMUX_IPSR_DATA(IP7_30_29, DU0_DB4),
-       PINMUX_IPSR_DATA(IP7_30_29, HIFINT),
+       PINMUX_IPSR_GPSR(IP7_30_29, DU0_DB4),
+       PINMUX_IPSR_GPSR(IP7_30_29, HIFINT),
 
        /* IPSR8 */
-       PINMUX_IPSR_DATA(IP8_1_0, DU0_DB5),
-       PINMUX_IPSR_DATA(IP8_1_0, HIFDREQ),
+       PINMUX_IPSR_GPSR(IP8_1_0, DU0_DB5),
+       PINMUX_IPSR_GPSR(IP8_1_0, HIFDREQ),
 
-       PINMUX_IPSR_DATA(IP8_3_2, DU0_DB6),
-       PINMUX_IPSR_DATA(IP8_3_2, HIFRDY),
+       PINMUX_IPSR_GPSR(IP8_3_2, DU0_DB6),
+       PINMUX_IPSR_GPSR(IP8_3_2, HIFRDY),
 
-       PINMUX_IPSR_DATA(IP8_5_4, DU0_DB7),
+       PINMUX_IPSR_GPSR(IP8_5_4, DU0_DB7),
        PINMUX_IPSR_MSEL(IP8_5_4, SSI_SCK0_B, SEL_SSI0_1),
        PINMUX_IPSR_MSEL(IP8_5_4, HIFEBL_B, SEL_HIF_1),
 
-       PINMUX_IPSR_DATA(IP8_7_6, DU0_DOTCLKIN),
+       PINMUX_IPSR_GPSR(IP8_7_6, DU0_DOTCLKIN),
        PINMUX_IPSR_MSEL(IP8_7_6, HSPI_CS0_C, SEL_HSPI_2),
        PINMUX_IPSR_MSEL(IP8_7_6, SSI_WS0_B, SEL_SSI0_1),
 
-       PINMUX_IPSR_DATA(IP8_9_8, DU0_DOTCLKOUT),
+       PINMUX_IPSR_GPSR(IP8_9_8, DU0_DOTCLKOUT),
        PINMUX_IPSR_MSEL(IP8_9_8, HSPI_CLK0_C, SEL_HSPI_2),
        PINMUX_IPSR_MSEL(IP8_9_8, SSI_SDATA0_B, SEL_SSI0_1),
 
-       PINMUX_IPSR_DATA(IP8_11_10, DU0_EXHSYNC_DU0_HSYNC),
+       PINMUX_IPSR_GPSR(IP8_11_10, DU0_EXHSYNC_DU0_HSYNC),
        PINMUX_IPSR_MSEL(IP8_11_10, HSPI_TX0_C, SEL_HSPI_2),
        PINMUX_IPSR_MSEL(IP8_11_10, SSI_SCK1_B, SEL_SSI1_1),
 
-       PINMUX_IPSR_DATA(IP8_13_12, DU0_EXVSYNC_DU0_VSYNC),
+       PINMUX_IPSR_GPSR(IP8_13_12, DU0_EXVSYNC_DU0_VSYNC),
        PINMUX_IPSR_MSEL(IP8_13_12, HSPI_RX0_C, SEL_HSPI_2),
        PINMUX_IPSR_MSEL(IP8_13_12, SSI_WS1_B, SEL_SSI1_1),
 
-       PINMUX_IPSR_DATA(IP8_15_14, DU0_EXODDF_DU0_ODDF),
+       PINMUX_IPSR_GPSR(IP8_15_14, DU0_EXODDF_DU0_ODDF),
        PINMUX_IPSR_MSEL(IP8_15_14, CAN0_RX_B, SEL_RCAN0_1),
        PINMUX_IPSR_MSEL(IP8_15_14, HSCK0_B, SEL_HSCIF_1),
        PINMUX_IPSR_MSEL(IP8_15_14, SSI_SDATA1_B, SEL_SSI1_1),
 
-       PINMUX_IPSR_DATA(IP8_17_16, DU0_DISP),
+       PINMUX_IPSR_GPSR(IP8_17_16, DU0_DISP),
        PINMUX_IPSR_MSEL(IP8_17_16, CAN0_TX_B, SEL_RCAN0_1),
        PINMUX_IPSR_MSEL(IP8_17_16, HRX0_B, SEL_HSCIF_1),
        PINMUX_IPSR_MSEL(IP8_17_16, AUDIO_CLKA_B, SEL_AUDIO_CLKA_1),
 
-       PINMUX_IPSR_DATA(IP8_19_18, DU0_CDE),
+       PINMUX_IPSR_GPSR(IP8_19_18, DU0_CDE),
        PINMUX_IPSR_MSEL(IP8_19_18, HTX0_B, SEL_HSCIF_1),
        PINMUX_IPSR_MSEL(IP8_19_18, AUDIO_CLKB_B, SEL_AUDIO_CLKB_1),
        PINMUX_IPSR_MSEL(IP8_19_18, LCD_VCPWC_B, SEL_LCDC_1),
@@ -1139,12 +1139,12 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP8_22_20, IRQ0_A, SEL_INTC_0),
        PINMUX_IPSR_MSEL(IP8_22_20, HSPI_TX_B, SEL_HSPI_1),
        PINMUX_IPSR_MSEL(IP8_22_20, RX3_E, SEL_SCIF3_4),
-       PINMUX_IPSR_DATA(IP8_22_20, ET0_ERXD0),
+       PINMUX_IPSR_GPSR(IP8_22_20, ET0_ERXD0),
 
        PINMUX_IPSR_MSEL(IP8_25_23, IRQ1_A, SEL_INTC_0),
        PINMUX_IPSR_MSEL(IP8_25_23, HSPI_RX_B, SEL_HSPI_1),
        PINMUX_IPSR_MSEL(IP8_25_23, TX3_E, SEL_SCIF3_4),
-       PINMUX_IPSR_DATA(IP8_25_23, ET0_ERXD1),
+       PINMUX_IPSR_GPSR(IP8_25_23, ET0_ERXD1),
 
        PINMUX_IPSR_MSEL(IP8_27_26, IRQ2_A, SEL_INTC_0),
        PINMUX_IPSR_MSEL(IP8_27_26, CTS0_A, SEL_SCIF0_0),
@@ -1220,26 +1220,26 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP9_29_28, LCD_DATA14_B, SEL_LCDC_1),
 
        /* IPSE10 */
-       PINMUX_IPSR_DATA(IP10_2_0, SSI_SCK23),
+       PINMUX_IPSR_GPSR(IP10_2_0, SSI_SCK23),
        PINMUX_IPSR_MSEL(IP10_2_0, VI1_4_B, SEL_VIN1_1),
        PINMUX_IPSR_MSEL(IP10_2_0, RX1_D, SEL_SCIF1_3),
        PINMUX_IPSR_MSEL(IP10_2_0, FCLE_B, SEL_FLCTL_1),
        PINMUX_IPSR_MSEL(IP10_2_0, LCD_DATA15_B, SEL_LCDC_1),
 
-       PINMUX_IPSR_DATA(IP10_5_3, SSI_WS23),
+       PINMUX_IPSR_GPSR(IP10_5_3, SSI_WS23),
        PINMUX_IPSR_MSEL(IP10_5_3, VI1_5_B, SEL_VIN1_1),
        PINMUX_IPSR_MSEL(IP10_5_3, TX1_D, SEL_SCIF1_3),
        PINMUX_IPSR_MSEL(IP10_5_3, HSCK0_C, SEL_HSCIF_2),
        PINMUX_IPSR_MSEL(IP10_5_3, FALE_B, SEL_FLCTL_1),
        PINMUX_IPSR_MSEL(IP10_5_3, LCD_DON_B, SEL_LCDC_1),
 
-       PINMUX_IPSR_DATA(IP10_8_6, SSI_SDATA2),
+       PINMUX_IPSR_GPSR(IP10_8_6, SSI_SDATA2),
        PINMUX_IPSR_MSEL(IP10_8_6, VI1_6_B, SEL_VIN1_1),
        PINMUX_IPSR_MSEL(IP10_8_6, HRX0_C, SEL_HSCIF_2),
        PINMUX_IPSR_MSEL(IP10_8_6, FRE_B, SEL_FLCTL_1),
        PINMUX_IPSR_MSEL(IP10_8_6, LCD_CL1_B, SEL_LCDC_1),
 
-       PINMUX_IPSR_DATA(IP10_11_9, SSI_SDATA3),
+       PINMUX_IPSR_GPSR(IP10_11_9, SSI_SDATA3),
        PINMUX_IPSR_MSEL(IP10_11_9, VI1_7_B, SEL_VIN1_1),
        PINMUX_IPSR_MSEL(IP10_11_9, HTX0_C, SEL_HSCIF_2),
        PINMUX_IPSR_MSEL(IP10_11_9, FWE_B, SEL_FLCTL_1),
@@ -1254,13 +1254,13 @@ static const u16 pinmux_data[] = {
        PINMUX_IPSR_MSEL(IP10_15, AUDIO_CLKB_A, SEL_AUDIO_CLKB_0),
        PINMUX_IPSR_MSEL(IP10_15, LCD_CLK_B, SEL_LCDC_1),
 
-       PINMUX_IPSR_DATA(IP10_18_16, AUDIO_CLKC),
+       PINMUX_IPSR_GPSR(IP10_18_16, AUDIO_CLKC),
        PINMUX_IPSR_MSEL(IP10_18_16, SCK1_E, SEL_SCIF1_4),
        PINMUX_IPSR_MSEL(IP10_18_16, HCTS0_C, SEL_HSCIF_2),
        PINMUX_IPSR_MSEL(IP10_18_16, FRB_B, SEL_FLCTL_1),
        PINMUX_IPSR_MSEL(IP10_18_16, LCD_VEPWC_B, SEL_LCDC_1),
 
-       PINMUX_IPSR_DATA(IP10_21_19, AUDIO_CLKOUT),
+       PINMUX_IPSR_GPSR(IP10_21_19, AUDIO_CLKOUT),
        PINMUX_IPSR_MSEL(IP10_21_19, TX1_E, SEL_SCIF1_4),
        PINMUX_IPSR_MSEL(IP10_21_19, HRTS0_C, SEL_HSCIF_2),
        PINMUX_IPSR_MSEL(IP10_21_19, FSE_B, SEL_FLCTL_1),
@@ -1271,85 +1271,85 @@ static const u16 pinmux_data[] = {
 
        PINMUX_IPSR_MSEL(IP10_24_23, CAN0_TX_A, SEL_RCAN0_0),
        PINMUX_IPSR_MSEL(IP10_24_23, TX4_D, SEL_SCIF4_3),
-       PINMUX_IPSR_DATA(IP10_24_23, MLB_CLK),
+       PINMUX_IPSR_GPSR(IP10_24_23, MLB_CLK),
 
        PINMUX_IPSR_MSEL(IP10_25, CAN1_RX_A, SEL_RCAN1_0),
        PINMUX_IPSR_MSEL(IP10_25, IRQ1_B, SEL_INTC_1),
 
        PINMUX_IPSR_MSEL(IP10_27_26, CAN0_RX_A, SEL_RCAN0_0),
        PINMUX_IPSR_MSEL(IP10_27_26, IRQ0_B, SEL_INTC_1),
-       PINMUX_IPSR_DATA(IP10_27_26, MLB_SIG),
+       PINMUX_IPSR_GPSR(IP10_27_26, MLB_SIG),
 
        PINMUX_IPSR_MSEL(IP10_29_28, CAN1_TX_A, SEL_RCAN1_0),
        PINMUX_IPSR_MSEL(IP10_29_28, TX5_C, SEL_SCIF1_2),
-       PINMUX_IPSR_DATA(IP10_29_28, MLB_DAT),
+       PINMUX_IPSR_GPSR(IP10_29_28, MLB_DAT),
 
        /* IPSR11 */
-       PINMUX_IPSR_DATA(IP11_0, SCL1),
+       PINMUX_IPSR_GPSR(IP11_0, SCL1),
        PINMUX_IPSR_MSEL(IP11_0, SCIF_CLK_C, SEL_SCIF_CLK_2),
 
-       PINMUX_IPSR_DATA(IP11_1, SDA1),
+       PINMUX_IPSR_GPSR(IP11_1, SDA1),
        PINMUX_IPSR_MSEL(IP11_0, RX1_E, SEL_SCIF1_4),
 
-       PINMUX_IPSR_DATA(IP11_2, SDA0),
+       PINMUX_IPSR_GPSR(IP11_2, SDA0),
        PINMUX_IPSR_MSEL(IP11_2, HIFEBL_A, SEL_HIF_0),
 
-       PINMUX_IPSR_DATA(IP11_3, SDSELF),
+       PINMUX_IPSR_GPSR(IP11_3, SDSELF),
        PINMUX_IPSR_MSEL(IP11_3, RTS1_E, SEL_SCIF1_3),
 
        PINMUX_IPSR_MSEL(IP11_6_4, SCIF_CLK_A, SEL_SCIF_CLK_0),
        PINMUX_IPSR_MSEL(IP11_6_4, HSPI_CLK_A, SEL_HSPI_0),
-       PINMUX_IPSR_DATA(IP11_6_4, VI0_CLK),
+       PINMUX_IPSR_GPSR(IP11_6_4, VI0_CLK),
        PINMUX_IPSR_MSEL(IP11_6_4, RMII0_TXD0_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP11_6_4, ET0_ERXD4),
+       PINMUX_IPSR_GPSR(IP11_6_4, ET0_ERXD4),
 
        PINMUX_IPSR_MSEL(IP11_9_7, SCK0_A, SEL_SCIF0_0),
        PINMUX_IPSR_MSEL(IP11_9_7, HSPI_CS_A, SEL_HSPI_0),
-       PINMUX_IPSR_DATA(IP11_9_7, VI0_CLKENB),
+       PINMUX_IPSR_GPSR(IP11_9_7, VI0_CLKENB),
        PINMUX_IPSR_MSEL(IP11_9_7, RMII0_TXD1_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP11_9_7, ET0_ERXD5),
+       PINMUX_IPSR_GPSR(IP11_9_7, ET0_ERXD5),
 
        PINMUX_IPSR_MSEL(IP11_11_10, RX0_A, SEL_SCIF0_0),
        PINMUX_IPSR_MSEL(IP11_11_10, HSPI_RX_A, SEL_HSPI_0),
        PINMUX_IPSR_MSEL(IP11_11_10, RMII0_RXD0_A, SEL_RMII_0),
-       PINMUX_IPSR_DATA(IP11_11_10, ET0_ERXD6),
+       PINMUX_IPSR_GPSR(IP11_11_10, ET0_ERXD6),
 
        PINMUX_IPSR_MSEL(IP11_12, TX0_A, SEL_SCIF0_0),
        PINMUX_IPSR_MSEL(IP11_12, HSPI_TX_A, SEL_HSPI_0),
 
-       PINMUX_IPSR_DATA(IP11_15_13, PENC1),
+       PINMUX_IPSR_GPSR(IP11_15_13, PENC1),
        PINMUX_IPSR_MSEL(IP11_15_13, TX3_D, SEL_SCIF3_3),
        PINMUX_IPSR_MSEL(IP11_15_13, CAN1_TX_B,  SEL_RCAN1_1),
        PINMUX_IPSR_MSEL(IP11_15_13, TX5_D, SEL_SCIF5_3),
        PINMUX_IPSR_MSEL(IP11_15_13, IETX_B, SEL_IEBUS_1),
 
-       PINMUX_IPSR_DATA(IP11_18_16, USB_OVC1),
+       PINMUX_IPSR_GPSR(IP11_18_16, USB_OVC1),
        PINMUX_IPSR_MSEL(IP11_18_16, RX3_D, SEL_SCIF3_3),
        PINMUX_IPSR_MSEL(IP11_18_16, CAN1_RX_B, SEL_RCAN1_1),
        PINMUX_IPSR_MSEL(IP11_18_16, RX5_D, SEL_SCIF5_3),
        PINMUX_IPSR_MSEL(IP11_18_16, IERX_B, SEL_IEBUS_1),
 
-       PINMUX_IPSR_DATA(IP11_20_19, DREQ0),
+       PINMUX_IPSR_GPSR(IP11_20_19, DREQ0),
        PINMUX_IPSR_MSEL(IP11_20_19, SD1_CLK_A, SEL_SDHI1_0),
-       PINMUX_IPSR_DATA(IP11_20_19, ET0_TX_EN),
+       PINMUX_IPSR_GPSR(IP11_20_19, ET0_TX_EN),
 
-       PINMUX_IPSR_DATA(IP11_22_21, DACK0),
+       PINMUX_IPSR_GPSR(IP11_22_21, DACK0),
        PINMUX_IPSR_MSEL(IP11_22_21, SD1_DAT3_A, SEL_SDHI1_0),
-       PINMUX_IPSR_DATA(IP11_22_21, ET0_TX_ER),
+       PINMUX_IPSR_GPSR(IP11_22_21, ET0_TX_ER),
 
-       PINMUX_IPSR_DATA(IP11_25_23, DREQ1),
+       PINMUX_IPSR_GPSR(IP11_25_23, DREQ1),
        PINMUX_IPSR_MSEL(IP11_25_23, HSPI_CLK_B, SEL_HSPI_1),
        PINMUX_IPSR_MSEL(IP11_25_23, RX4_B, SEL_SCIF4_1),
        PINMUX_IPSR_MSEL(IP11_25_23, ET0_PHY_INT_C, SEL_ET0_CTL_0),
        PINMUX_IPSR_MSEL(IP11_25_23, ET0_TX_CLK_A, SEL_ET0_0),
 
-       PINMUX_IPSR_DATA(IP11_27_26, DACK1),
+       PINMUX_IPSR_GPSR(IP11_27_26, DACK1),
        PINMUX_IPSR_MSEL(IP11_27_26, HSPI_CS_B, SEL_HSPI_1),
        PINMUX_IPSR_MSEL(IP11_27_26, TX4_B, SEL_SCIF3_1),
        PINMUX_IPSR_MSEL(IP11_27_26, ET0_RX_CLK_A, SEL_ET0_0),
 
-       PINMUX_IPSR_DATA(IP11_28, PRESETOUT),
-       PINMUX_IPSR_DATA(IP11_28, ST_CLKOUT),
+       PINMUX_IPSR_GPSR(IP11_28, PRESETOUT),
+       PINMUX_IPSR_GPSR(IP11_28, ST_CLKOUT),
 };
 
 static const struct sh_pfc_pin pinmux_pins[] = {
index 2123ab49d6a50151c51da3f90b65e5938c5c86f9..a490834e208931cfda56f2980507489caa229d02 100644 (file)
@@ -100,10 +100,31 @@ struct pinmux_cfg_reg {
        const u8 *var_field_width;
 };
 
+/*
+ * Describe a config register consisting of several fields of the same width
+ *   - name: Register name (unused, for documentation purposes only)
+ *   - r: Physical register address
+ *   - r_width: Width of the register (in bits)
+ *   - f_width: Width of the fixed-width register fields (in bits)
+ * This macro must be followed by initialization data: For each register field
+ * (from left to right, i.e. MSB to LSB), 2^f_width enum IDs must be specified,
+ * one for each possible combination of the register field bit values.
+ */
 #define PINMUX_CFG_REG(name, r, r_width, f_width) \
        .reg = r, .reg_width = r_width, .field_width = f_width,         \
        .enum_ids = (const u16 [(r_width / f_width) * (1 << f_width)])
 
+/*
+ * Describe a config register consisting of several fields of different widths
+ *   - name: Register name (unused, for documentation purposes only)
+ *   - r: Physical register address
+ *   - r_width: Width of the register (in bits)
+ *   - var_fw0, var_fwn...: List of widths of the register fields (in bits),
+ *                          From left to right (i.e. MSB to LSB)
+ * This macro must be followed by initialization data: For each register field
+ * (from left to right, i.e. MSB to LSB), 2^var_fwi enum IDs must be specified,
+ * one for each possible combination of the register field bit values.
+ */
 #define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
        .reg = r, .reg_width = r_width, \
        .var_field_width = (const u8 [r_width]) \
@@ -116,6 +137,14 @@ struct pinmux_data_reg {
        const u16 *enum_ids;
 };
 
+/*
+ * Describe a data register
+ *   - name: Register name (unused, for documentation purposes only)
+ *   - r: Physical register address
+ *   - r_width: Width of the register (in bits)
+ * This macro must be followed by initialization data: For each register bit
+ * (from left to right, i.e. MSB to LSB), one enum ID must be specified.
+ */
 #define PINMUX_DATA_REG(name, r, r_width) \
        .reg = r, .reg_width = r_width, \
        .enum_ids = (const u16 [r_width]) \
@@ -124,6 +153,10 @@ struct pinmux_irq {
        const short *gpios;
 };
 
+/*
+ * Describe the mapping from GPIOs to a single IRQ
+ *   - ids...: List of GPIOs that are mapped to the same IRQ
+ */
 #define PINMUX_IRQ(ids...)                        \
        { .gpios = (const short []) { ids, -1 } }
 
@@ -185,18 +218,65 @@ struct sh_pfc_soc_info {
  * sh_pfc_soc_info pinmux_data array macros
  */
 
+/*
+ * Describe generic pinmux data
+ *   - data_or_mark: *_DATA or *_MARK enum ID
+ *   - ids...: List of enum IDs to associate with data_or_mark
+ */
 #define PINMUX_DATA(data_or_mark, ids...)      data_or_mark, ids, 0
 
-#define PINMUX_IPSR_NOGP(ispr, fn)                                     \
+/*
+ * Describe a pinmux configuration without GPIO function that needs
+ * configuration in a Peripheral Function Select Register (IPSR)
+ *   - ipsr: IPSR field (unused, for documentation purposes only)
+ *   - fn: Function name, referring to a field in the IPSR
+ */
+#define PINMUX_IPSR_NOGP(ipsr, fn)                                     \
        PINMUX_DATA(fn##_MARK, FN_##fn)
-#define PINMUX_IPSR_DATA(ipsr, fn)                                     \
+
+/*
+ * Describe a pinmux configuration with GPIO function that needs configuration
+ * in both a Peripheral Function Select Register (IPSR) and in a
+ * GPIO/Peripheral Function Select Register (GPSR)
+ *   - ipsr: IPSR field
+ *   - fn: Function name, also referring to the IPSR field
+ */
+#define PINMUX_IPSR_GPSR(ipsr, fn)                                     \
        PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ipsr)
-#define PINMUX_IPSR_NOGM(ispr, fn, ms)                                 \
-       PINMUX_DATA(fn##_MARK, FN_##fn, FN_##ms)
-#define PINMUX_IPSR_NOFN(ipsr, fn, ms)                                 \
-       PINMUX_DATA(fn##_MARK, FN_##ipsr, FN_##ms)
-#define PINMUX_IPSR_MSEL(ipsr, fn, ms)                                 \
-       PINMUX_DATA(fn##_MARK, FN_##ms, FN_##ipsr, FN_##fn)
+
+/*
+ * Describe a pinmux configuration without GPIO function that needs
+ * configuration in a Peripheral Function Select Register (IPSR), and where the
+ * pinmux function has a representation in a Module Select Register (MOD_SEL).
+ *   - ipsr: IPSR field (unused, for documentation purposes only)
+ *   - fn: Function name, also referring to the IPSR field
+ *   - msel: Module selector
+ */
+#define PINMUX_IPSR_NOGM(ipsr, fn, msel)                               \
+       PINMUX_DATA(fn##_MARK, FN_##fn, FN_##msel)
+
+/*
+ * Describe a pinmux configuration with GPIO function where the pinmux function
+ * has no representation in a Peripheral Function Select Register (IPSR), but
+ * instead solely depends on a group selection.
+ *   - gpsr: GPSR field
+ *   - fn: Function name, also referring to the GPSR field
+ *   - gsel: Group selector
+ */
+#define PINMUX_IPSR_NOFN(gpsr, fn, gsel)                               \
+       PINMUX_DATA(fn##_MARK, FN_##gpsr, FN_##gsel)
+
+/*
+ * Describe a pinmux configuration with GPIO function that needs configuration
+ * in both a Peripheral Function Select Register (IPSR) and a GPIO/Peripheral
+ * Function Select Register (GPSR), and where the pinmux function has a
+ * representation in a Module Select Register (MOD_SEL).
+ *   - ipsr: IPSR field
+ *   - fn: Function name, also referring to the IPSR field
+ *   - msel: Module selector
+ */
+#define PINMUX_IPSR_MSEL(ipsr, fn, msel)                               \
+       PINMUX_DATA(fn##_MARK, FN_##msel, FN_##ipsr, FN_##fn)
 
 /*
  * Describe a pinmux configuration for a single-function pin with GPIO
@@ -381,7 +461,7 @@ struct sh_pfc_soc_info {
        PINMUX_GPIO_FN(GPIO_FN_##str, PINMUX_FN_BASE, str##_MARK)
 
 /*
- * PORTnCR macro
+ * PORTnCR helper macro for SH-Mobile/R-Mobile
  */
 #define PORTCR(nr, reg)                                                        \
        {                                                               \
diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig
new file mode 100644 (file)
index 0000000..0f28841
--- /dev/null
@@ -0,0 +1,16 @@
+if ARCH_STM32 || COMPILE_TEST
+
+config PINCTRL_STM32
+       bool
+       depends on OF
+       select PINMUX
+       select GENERIC_PINCONF
+       select GPIOLIB
+
+config PINCTRL_STM32F429
+       bool "STMicroelectronics STM32F429 pin control" if COMPILE_TEST && !MACH_STM32F429
+       depends on OF
+       default MACH_STM32F429
+       select PINCTRL_STM32
+
+endif
diff --git a/drivers/pinctrl/stm32/Makefile b/drivers/pinctrl/stm32/Makefile
new file mode 100644 (file)
index 0000000..fc17d42
--- /dev/null
@@ -0,0 +1,5 @@
+# Core
+obj-$(CONFIG_PINCTRL_STM32) += pinctrl-stm32.o
+
+# SoC Drivers
+obj-$(CONFIG_PINCTRL_STM32F429)        += pinctrl-stm32f429.o
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c
new file mode 100644 (file)
index 0000000..8deb566
--- /dev/null
@@ -0,0 +1,829 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ *
+ * Heavily based on Mediatek's pinctrl driver
+ */
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinctrl-utils.h"
+#include "pinctrl-stm32.h"
+
+#define STM32_GPIO_MODER       0x00
+#define STM32_GPIO_TYPER       0x04
+#define STM32_GPIO_SPEEDR      0x08
+#define STM32_GPIO_PUPDR       0x0c
+#define STM32_GPIO_IDR         0x10
+#define STM32_GPIO_ODR         0x14
+#define STM32_GPIO_BSRR                0x18
+#define STM32_GPIO_LCKR                0x1c
+#define STM32_GPIO_AFRL                0x20
+#define STM32_GPIO_AFRH                0x24
+
+#define STM32_GPIO_PINS_PER_BANK 16
+
+#define gpio_range_to_bank(chip) \
+               container_of(chip, struct stm32_gpio_bank, range)
+
+static const char * const stm32_gpio_functions[] = {
+       "gpio", "af0", "af1",
+       "af2", "af3", "af4",
+       "af5", "af6", "af7",
+       "af8", "af9", "af10",
+       "af11", "af12", "af13",
+       "af14", "af15", "analog",
+};
+
+struct stm32_pinctrl_group {
+       const char *name;
+       unsigned long config;
+       unsigned pin;
+};
+
+struct stm32_gpio_bank {
+       void __iomem *base;
+       struct clk *clk;
+       spinlock_t lock;
+       struct gpio_chip gpio_chip;
+       struct pinctrl_gpio_range range;
+};
+
+struct stm32_pinctrl {
+       struct device *dev;
+       struct pinctrl_dev *pctl_dev;
+       struct pinctrl_desc pctl_desc;
+       struct stm32_pinctrl_group *groups;
+       unsigned ngroups;
+       const char **grp_names;
+       struct stm32_gpio_bank *banks;
+       unsigned nbanks;
+       const struct stm32_pinctrl_match_data *match_data;
+};
+
+static inline int stm32_gpio_pin(int gpio)
+{
+       return gpio % STM32_GPIO_PINS_PER_BANK;
+}
+
+static inline u32 stm32_gpio_get_mode(u32 function)
+{
+       switch (function) {
+       case STM32_PIN_GPIO:
+               return 0;
+       case STM32_PIN_AF(0) ... STM32_PIN_AF(15):
+               return 2;
+       case STM32_PIN_ANALOG:
+               return 3;
+       }
+
+       return 0;
+}
+
+static inline u32 stm32_gpio_get_alt(u32 function)
+{
+       switch (function) {
+       case STM32_PIN_GPIO:
+               return 0;
+       case STM32_PIN_AF(0) ... STM32_PIN_AF(15):
+               return function - 1;
+       case STM32_PIN_ANALOG:
+               return 0;
+       }
+
+       return 0;
+}
+
+/* GPIO functions */
+
+static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank,
+       unsigned offset, int value)
+{
+       if (!value)
+               offset += STM32_GPIO_PINS_PER_BANK;
+
+       clk_enable(bank->clk);
+
+       writel_relaxed(BIT(offset), bank->base + STM32_GPIO_BSRR);
+
+       clk_disable(bank->clk);
+}
+
+static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       pinctrl_free_gpio(chip->base + offset);
+}
+
+static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
+       int ret;
+
+       clk_enable(bank->clk);
+
+       ret = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset));
+
+       clk_disable(bank->clk);
+
+       return ret;
+}
+
+static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
+
+       __stm32_gpio_set(bank, offset, value);
+}
+
+static int stm32_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int stm32_gpio_direction_output(struct gpio_chip *chip,
+       unsigned offset, int value)
+{
+       struct stm32_gpio_bank *bank = gpiochip_get_data(chip);
+
+       __stm32_gpio_set(bank, offset, value);
+       pinctrl_gpio_direction_output(chip->base + offset);
+
+       return 0;
+}
+
+static struct gpio_chip stm32_gpio_template = {
+       .request                = stm32_gpio_request,
+       .free                   = stm32_gpio_free,
+       .get                    = stm32_gpio_get,
+       .set                    = stm32_gpio_set,
+       .direction_input        = stm32_gpio_direction_input,
+       .direction_output       = stm32_gpio_direction_output,
+};
+
+/* Pinctrl functions */
+
+static struct stm32_pinctrl_group *
+stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin)
+{
+       int i;
+
+       for (i = 0; i < pctl->ngroups; i++) {
+               struct stm32_pinctrl_group *grp = pctl->groups + i;
+
+               if (grp->pin == pin)
+                       return grp;
+       }
+
+       return NULL;
+}
+
+static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl,
+               u32 pin_num, u32 fnum)
+{
+       int i;
+
+       for (i = 0; i < pctl->match_data->npins; i++) {
+               const struct stm32_desc_pin *pin = pctl->match_data->pins + i;
+               const struct stm32_desc_function *func = pin->functions;
+
+               if (pin->pin.number != pin_num)
+                       continue;
+
+               while (func && func->name) {
+                       if (func->num == fnum)
+                               return true;
+                       func++;
+               }
+
+               break;
+       }
+
+       return false;
+}
+
+static int stm32_pctrl_dt_node_to_map_func(struct stm32_pinctrl *pctl,
+               u32 pin, u32 fnum, struct stm32_pinctrl_group *grp,
+               struct pinctrl_map **map, unsigned *reserved_maps,
+               unsigned *num_maps)
+{
+       if (*num_maps == *reserved_maps)
+               return -ENOSPC;
+
+       (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+       (*map)[*num_maps].data.mux.group = grp->name;
+
+       if (!stm32_pctrl_is_function_valid(pctl, pin, fnum)) {
+               dev_err(pctl->dev, "invalid function %d on pin %d .\n",
+                               fnum, pin);
+               return -EINVAL;
+       }
+
+       (*map)[*num_maps].data.mux.function = stm32_gpio_functions[fnum];
+       (*num_maps)++;
+
+       return 0;
+}
+
+static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+                                     struct device_node *node,
+                                     struct pinctrl_map **map,
+                                     unsigned *reserved_maps,
+                                     unsigned *num_maps)
+{
+       struct stm32_pinctrl *pctl;
+       struct stm32_pinctrl_group *grp;
+       struct property *pins;
+       u32 pinfunc, pin, func;
+       unsigned long *configs;
+       unsigned int num_configs;
+       bool has_config = 0;
+       unsigned reserve = 0;
+       int num_pins, num_funcs, maps_per_pin, i, err;
+
+       pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       pins = of_find_property(node, "pinmux", NULL);
+       if (!pins) {
+               dev_err(pctl->dev, "missing pins property in node %s .\n",
+                               node->name);
+               return -EINVAL;
+       }
+
+       err = pinconf_generic_parse_dt_config(node, pctldev, &configs,
+               &num_configs);
+       if (err)
+               return err;
+
+       if (num_configs)
+               has_config = 1;
+
+       num_pins = pins->length / sizeof(u32);
+       num_funcs = num_pins;
+       maps_per_pin = 0;
+       if (num_funcs)
+               maps_per_pin++;
+       if (has_config && num_pins >= 1)
+               maps_per_pin++;
+
+       if (!num_pins || !maps_per_pin)
+               return -EINVAL;
+
+       reserve = num_pins * maps_per_pin;
+
+       err = pinctrl_utils_reserve_map(pctldev, map,
+                       reserved_maps, num_maps, reserve);
+       if (err)
+               return err;
+
+       for (i = 0; i < num_pins; i++) {
+               err = of_property_read_u32_index(node, "pinmux",
+                               i, &pinfunc);
+               if (err)
+                       return err;
+
+               pin = STM32_GET_PIN_NO(pinfunc);
+               func = STM32_GET_PIN_FUNC(pinfunc);
+
+               if (pin >= pctl->match_data->npins) {
+                       dev_err(pctl->dev, "invalid pin number.\n");
+                       return -EINVAL;
+               }
+
+               if (!stm32_pctrl_is_function_valid(pctl, pin, func)) {
+                       dev_err(pctl->dev, "invalid function.\n");
+                       return -EINVAL;
+               }
+
+               grp = stm32_pctrl_find_group_by_pin(pctl, pin);
+               if (!grp) {
+                       dev_err(pctl->dev, "unable to match pin %d to group\n",
+                                       pin);
+                       return -EINVAL;
+               }
+
+               err = stm32_pctrl_dt_node_to_map_func(pctl, pin, func, grp, map,
+                               reserved_maps, num_maps);
+               if (err)
+                       return err;
+
+               if (has_config) {
+                       err = pinctrl_utils_add_map_configs(pctldev, map,
+                                       reserved_maps, num_maps, grp->name,
+                                       configs, num_configs,
+                                       PIN_MAP_TYPE_CONFIGS_GROUP);
+                       if (err)
+                               return err;
+               }
+       }
+
+       return 0;
+}
+
+static int stm32_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                struct device_node *np_config,
+                                struct pinctrl_map **map, unsigned *num_maps)
+{
+       struct device_node *np;
+       unsigned reserved_maps;
+       int ret;
+
+       *map = NULL;
+       *num_maps = 0;
+       reserved_maps = 0;
+
+       for_each_child_of_node(np_config, np) {
+               ret = stm32_pctrl_dt_subnode_to_map(pctldev, np, map,
+                               &reserved_maps, num_maps);
+               if (ret < 0) {
+                       pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int stm32_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->ngroups;
+}
+
+static const char *stm32_pctrl_get_group_name(struct pinctrl_dev *pctldev,
+                                             unsigned group)
+{
+       struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       return pctl->groups[group].name;
+}
+
+static int stm32_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
+                                     unsigned group,
+                                     const unsigned **pins,
+                                     unsigned *num_pins)
+{
+       struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = (unsigned *)&pctl->groups[group].pin;
+       *num_pins = 1;
+
+       return 0;
+}
+
+static const struct pinctrl_ops stm32_pctrl_ops = {
+       .dt_node_to_map         = stm32_pctrl_dt_node_to_map,
+       .dt_free_map            = pinctrl_utils_dt_free_map,
+       .get_groups_count       = stm32_pctrl_get_groups_count,
+       .get_group_name         = stm32_pctrl_get_group_name,
+       .get_group_pins         = stm32_pctrl_get_group_pins,
+};
+
+
+/* Pinmux functions */
+
+static int stm32_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
+{
+       return ARRAY_SIZE(stm32_gpio_functions);
+}
+
+static const char *stm32_pmx_get_func_name(struct pinctrl_dev *pctldev,
+                                          unsigned selector)
+{
+       return stm32_gpio_functions[selector];
+}
+
+static int stm32_pmx_get_func_groups(struct pinctrl_dev *pctldev,
+                                    unsigned function,
+                                    const char * const **groups,
+                                    unsigned * const num_groups)
+{
+       struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = pctl->grp_names;
+       *num_groups = pctl->ngroups;
+
+       return 0;
+}
+
+static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank,
+               int pin, u32 mode, u32 alt)
+{
+       u32 val;
+       int alt_shift = (pin % 8) * 4;
+       int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4;
+       unsigned long flags;
+
+       clk_enable(bank->clk);
+       spin_lock_irqsave(&bank->lock, flags);
+
+       val = readl_relaxed(bank->base + alt_offset);
+       val &= ~GENMASK(alt_shift + 3, alt_shift);
+       val |= (alt << alt_shift);
+       writel_relaxed(val, bank->base + alt_offset);
+
+       val = readl_relaxed(bank->base + STM32_GPIO_MODER);
+       val &= ~GENMASK(pin * 2 + 1, pin * 2);
+       val |= mode << (pin * 2);
+       writel_relaxed(val, bank->base + STM32_GPIO_MODER);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+       clk_disable(bank->clk);
+}
+
+static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev,
+                           unsigned function,
+                           unsigned group)
+{
+       bool ret;
+       struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct stm32_pinctrl_group *g = pctl->groups + group;
+       struct pinctrl_gpio_range *range;
+       struct stm32_gpio_bank *bank;
+       u32 mode, alt;
+       int pin;
+
+       ret = stm32_pctrl_is_function_valid(pctl, g->pin, function);
+       if (!ret) {
+               dev_err(pctl->dev, "invalid function %d on group %d .\n",
+                               function, group);
+               return -EINVAL;
+       }
+
+       range = pinctrl_find_gpio_range_from_pin(pctldev, g->pin);
+       bank = gpio_range_to_bank(range);
+       pin = stm32_gpio_pin(g->pin);
+
+       mode = stm32_gpio_get_mode(function);
+       alt = stm32_gpio_get_alt(function);
+
+       stm32_pmx_set_mode(bank, pin, mode, alt);
+
+       return 0;
+}
+
+static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+                       struct pinctrl_gpio_range *range, unsigned gpio,
+                       bool input)
+{
+       struct stm32_gpio_bank *bank = gpio_range_to_bank(range);
+       int pin = stm32_gpio_pin(gpio);
+
+       stm32_pmx_set_mode(bank, pin, !input, 0);
+
+       return 0;
+}
+
+static const struct pinmux_ops stm32_pmx_ops = {
+       .get_functions_count    = stm32_pmx_get_funcs_cnt,
+       .get_function_name      = stm32_pmx_get_func_name,
+       .get_function_groups    = stm32_pmx_get_func_groups,
+       .set_mux                = stm32_pmx_set_mux,
+       .gpio_set_direction     = stm32_pmx_gpio_set_direction,
+};
+
+/* Pinconf functions */
+
+static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank,
+       unsigned offset, u32 drive)
+{
+       unsigned long flags;
+       u32 val;
+
+       clk_enable(bank->clk);
+       spin_lock_irqsave(&bank->lock, flags);
+
+       val = readl_relaxed(bank->base + STM32_GPIO_TYPER);
+       val &= ~BIT(offset);
+       val |= drive << offset;
+       writel_relaxed(val, bank->base + STM32_GPIO_TYPER);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+       clk_disable(bank->clk);
+}
+
+static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank,
+       unsigned offset, u32 speed)
+{
+       unsigned long flags;
+       u32 val;
+
+       clk_enable(bank->clk);
+       spin_lock_irqsave(&bank->lock, flags);
+
+       val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR);
+       val &= ~GENMASK(offset * 2 + 1, offset * 2);
+       val |= speed << (offset * 2);
+       writel_relaxed(val, bank->base + STM32_GPIO_SPEEDR);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+       clk_disable(bank->clk);
+}
+
+static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank,
+       unsigned offset, u32 bias)
+{
+       unsigned long flags;
+       u32 val;
+
+       clk_enable(bank->clk);
+       spin_lock_irqsave(&bank->lock, flags);
+
+       val = readl_relaxed(bank->base + STM32_GPIO_PUPDR);
+       val &= ~GENMASK(offset * 2 + 1, offset * 2);
+       val |= bias << (offset * 2);
+       writel_relaxed(val, bank->base + STM32_GPIO_PUPDR);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+       clk_disable(bank->clk);
+}
+
+static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev,
+               unsigned int pin, enum pin_config_param param,
+               enum pin_config_param arg)
+{
+       struct pinctrl_gpio_range *range;
+       struct stm32_gpio_bank *bank;
+       int offset, ret = 0;
+
+       range = pinctrl_find_gpio_range_from_pin(pctldev, pin);
+       bank = gpio_range_to_bank(range);
+       offset = stm32_gpio_pin(pin);
+
+       switch (param) {
+       case PIN_CONFIG_DRIVE_PUSH_PULL:
+               stm32_pconf_set_driving(bank, offset, 0);
+               break;
+       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+               stm32_pconf_set_driving(bank, offset, 1);
+               break;
+       case PIN_CONFIG_SLEW_RATE:
+               stm32_pconf_set_speed(bank, offset, arg);
+               break;
+       case PIN_CONFIG_BIAS_DISABLE:
+               stm32_pconf_set_bias(bank, offset, 0);
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+               stm32_pconf_set_bias(bank, offset, 1);
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               stm32_pconf_set_bias(bank, offset, 2);
+               break;
+       case PIN_CONFIG_OUTPUT:
+               __stm32_gpio_set(bank, offset, arg);
+               ret = stm32_pmx_gpio_set_direction(pctldev, NULL, pin, false);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int stm32_pconf_group_get(struct pinctrl_dev *pctldev,
+                                unsigned group,
+                                unsigned long *config)
+{
+       struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+       *config = pctl->groups[group].config;
+
+       return 0;
+}
+
+static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
+                                unsigned long *configs, unsigned num_configs)
+{
+       struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+       struct stm32_pinctrl_group *g = &pctl->groups[group];
+       int i, ret;
+
+       for (i = 0; i < num_configs; i++) {
+               ret = stm32_pconf_parse_conf(pctldev, g->pin,
+                       pinconf_to_config_param(configs[i]),
+                       pinconf_to_config_argument(configs[i]));
+               if (ret < 0)
+                       return ret;
+
+               g->config = configs[i];
+       }
+
+       return 0;
+}
+
+static const struct pinconf_ops stm32_pconf_ops = {
+       .pin_config_group_get   = stm32_pconf_group_get,
+       .pin_config_group_set   = stm32_pconf_group_set,
+};
+
+static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl,
+       struct device_node *np)
+{
+       int bank_nr = pctl->nbanks;
+       struct stm32_gpio_bank *bank = &pctl->banks[bank_nr];
+       struct pinctrl_gpio_range *range = &bank->range;
+       struct device *dev = pctl->dev;
+       struct resource res;
+       struct reset_control *rstc;
+       int err, npins;
+
+       rstc = of_reset_control_get(np, NULL);
+       if (!IS_ERR(rstc))
+               reset_control_deassert(rstc);
+
+       if (of_address_to_resource(np, 0, &res))
+               return -ENODEV;
+
+       bank->base = devm_ioremap_resource(dev, &res);
+       if (IS_ERR(bank->base))
+               return PTR_ERR(bank->base);
+
+       bank->clk = of_clk_get_by_name(np, NULL);
+       if (IS_ERR(bank->clk)) {
+               dev_err(dev, "failed to get clk (%ld)\n", PTR_ERR(bank->clk));
+               return PTR_ERR(bank->clk);
+       }
+
+       err = clk_prepare(bank->clk);
+       if (err) {
+               dev_err(dev, "failed to prepare clk (%d)\n", err);
+               return err;
+       }
+
+       npins = pctl->match_data->npins;
+       npins -= bank_nr * STM32_GPIO_PINS_PER_BANK;
+       if (npins < 0)
+               return -EINVAL;
+       else if (npins > STM32_GPIO_PINS_PER_BANK)
+               npins = STM32_GPIO_PINS_PER_BANK;
+
+       bank->gpio_chip = stm32_gpio_template;
+       bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK;
+       bank->gpio_chip.ngpio = npins;
+       bank->gpio_chip.of_node = np;
+       bank->gpio_chip.parent = dev;
+       spin_lock_init(&bank->lock);
+
+       of_property_read_string(np, "st,bank-name", &range->name);
+       bank->gpio_chip.label = range->name;
+
+       range->id = bank_nr;
+       range->pin_base = range->base = range->id * STM32_GPIO_PINS_PER_BANK;
+       range->npins = bank->gpio_chip.ngpio;
+       range->gc = &bank->gpio_chip;
+       err = gpiochip_add_data(&bank->gpio_chip, bank);
+       if (err) {
+               dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr);
+               return err;
+       }
+
+       dev_info(dev, "%s bank added\n", range->name);
+       return 0;
+}
+
+static int stm32_pctrl_build_state(struct platform_device *pdev)
+{
+       struct stm32_pinctrl *pctl = platform_get_drvdata(pdev);
+       int i;
+
+       pctl->ngroups = pctl->match_data->npins;
+
+       /* Allocate groups */
+       pctl->groups = devm_kcalloc(&pdev->dev, pctl->ngroups,
+                                   sizeof(*pctl->groups), GFP_KERNEL);
+       if (!pctl->groups)
+               return -ENOMEM;
+
+       /* We assume that one pin is one group, use pin name as group name. */
+       pctl->grp_names = devm_kcalloc(&pdev->dev, pctl->ngroups,
+                                      sizeof(*pctl->grp_names), GFP_KERNEL);
+       if (!pctl->grp_names)
+               return -ENOMEM;
+
+       for (i = 0; i < pctl->match_data->npins; i++) {
+               const struct stm32_desc_pin *pin = pctl->match_data->pins + i;
+               struct stm32_pinctrl_group *group = pctl->groups + i;
+
+               group->name = pin->pin.name;
+               group->pin = pin->pin.number;
+
+               pctl->grp_names[i] = pin->pin.name;
+       }
+
+       return 0;
+}
+
+int stm32_pctl_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct device_node *child;
+       const struct of_device_id *match;
+       struct device *dev = &pdev->dev;
+       struct stm32_pinctrl *pctl;
+       struct pinctrl_pin_desc *pins;
+       int i, ret, banks = 0;
+
+       if (!np)
+               return -EINVAL;
+
+       match = of_match_device(dev->driver->of_match_table, dev);
+       if (!match || !match->data)
+               return -EINVAL;
+
+       if (!of_find_property(np, "pins-are-numbered", NULL)) {
+               dev_err(dev, "only support pins-are-numbered format\n");
+               return -EINVAL;
+       }
+
+       pctl = devm_kzalloc(dev, sizeof(*pctl), GFP_KERNEL);
+       if (!pctl)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, pctl);
+
+       pctl->dev = dev;
+       pctl->match_data = match->data;
+       ret = stm32_pctrl_build_state(pdev);
+       if (ret) {
+               dev_err(dev, "build state failed: %d\n", ret);
+               return -EINVAL;
+       }
+
+       for_each_child_of_node(np, child)
+               if (of_property_read_bool(child, "gpio-controller"))
+                       banks++;
+
+       if (!banks) {
+               dev_err(dev, "at least one GPIO bank is required\n");
+               return -EINVAL;
+       }
+
+       pctl->banks = devm_kcalloc(dev, banks, sizeof(*pctl->banks),
+                       GFP_KERNEL);
+       if (!pctl->banks)
+               return -ENOMEM;
+
+       for_each_child_of_node(np, child) {
+               if (of_property_read_bool(child, "gpio-controller")) {
+                       ret = stm32_gpiolib_register_bank(pctl, child);
+                       if (ret)
+                               return ret;
+
+                       pctl->nbanks++;
+               }
+       }
+
+       pins = devm_kcalloc(&pdev->dev, pctl->match_data->npins, sizeof(*pins),
+                           GFP_KERNEL);
+       if (!pins)
+               return -ENOMEM;
+
+       for (i = 0; i < pctl->match_data->npins; i++)
+               pins[i] = pctl->match_data->pins[i].pin;
+
+       pctl->pctl_desc.name = dev_name(&pdev->dev);
+       pctl->pctl_desc.owner = THIS_MODULE;
+       pctl->pctl_desc.pins = pins;
+       pctl->pctl_desc.npins = pctl->match_data->npins;
+       pctl->pctl_desc.confops = &stm32_pconf_ops;
+       pctl->pctl_desc.pctlops = &stm32_pctrl_ops;
+       pctl->pctl_desc.pmxops = &stm32_pmx_ops;
+       pctl->dev = &pdev->dev;
+
+       pctl->pctl_dev = pinctrl_register(&pctl->pctl_desc, &pdev->dev, pctl);
+       if (!pctl->pctl_dev) {
+               dev_err(&pdev->dev, "Failed pinctrl registration\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < pctl->nbanks; i++)
+               pinctrl_add_gpio_range(pctl->pctl_dev, &pctl->banks[i].range);
+
+       dev_info(dev, "Pinctrl STM32 initialized\n");
+
+       return 0;
+}
+
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h
new file mode 100644 (file)
index 0000000..35ebc94
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+#ifndef __PINCTRL_STM32_H
+#define __PINCTRL_STM32_H
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
+#define STM32_PIN_NO(x) ((x) << 8)
+#define STM32_GET_PIN_NO(x) ((x) >> 8)
+#define STM32_GET_PIN_FUNC(x) ((x) & 0xff)
+
+#define STM32_PIN_GPIO         0
+#define STM32_PIN_AF(x)                ((x) + 1)
+#define STM32_PIN_ANALOG       (STM32_PIN_AF(15) + 1)
+
+struct stm32_desc_function {
+       const char *name;
+       const unsigned char num;
+};
+
+struct stm32_desc_pin {
+       struct pinctrl_pin_desc pin;
+       const struct stm32_desc_function *functions;
+};
+
+#define STM32_PIN(_pin, ...)                                   \
+       {                                                       \
+               .pin = _pin,                                    \
+               .functions = (struct stm32_desc_function[]){    \
+                       __VA_ARGS__, { } },                     \
+       }
+
+#define STM32_FUNCTION(_num, _name)            \
+       {                                                       \
+               .num = _num,                                    \
+               .name = _name,                                  \
+       }
+
+struct stm32_pinctrl_match_data {
+       const struct stm32_desc_pin *pins;
+       const unsigned int npins;
+};
+
+int stm32_pctl_probe(struct platform_device *pdev);
+
+#endif /* __PINCTRL_STM32_H */
+
diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f429.c b/drivers/pinctrl/stm32/pinctrl-stm32f429.c
new file mode 100644 (file)
index 0000000..e9b15dc
--- /dev/null
@@ -0,0 +1,1591 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-stm32.h"
+
+static const struct stm32_desc_pin stm32f429_pins[] = {
+       STM32_PIN(
+               PINCTRL_PIN(0, "PA0"),
+               STM32_FUNCTION(0, "GPIOA0"),
+               STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+               STM32_FUNCTION(3, "TIM5_CH1"),
+               STM32_FUNCTION(4, "TIM8_ETR"),
+               STM32_FUNCTION(8, "USART2_CTS"),
+               STM32_FUNCTION(9, "UART4_TX"),
+               STM32_FUNCTION(12, "ETH_MII_CRS"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(1, "PA1"),
+               STM32_FUNCTION(0, "GPIOA1"),
+               STM32_FUNCTION(2, "TIM2_CH2"),
+               STM32_FUNCTION(3, "TIM5_CH2"),
+               STM32_FUNCTION(8, "USART2_RTS"),
+               STM32_FUNCTION(9, "UART4_RX"),
+               STM32_FUNCTION(12, "ETH_MII_RX_CLK ETH_RMII_REF_CLK"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(2, "PA2"),
+               STM32_FUNCTION(0, "GPIOA2"),
+               STM32_FUNCTION(2, "TIM2_CH3"),
+               STM32_FUNCTION(3, "TIM5_CH3"),
+               STM32_FUNCTION(4, "TIM9_CH1"),
+               STM32_FUNCTION(8, "USART2_TX"),
+               STM32_FUNCTION(12, "ETH_MDIO"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(3, "PA3"),
+               STM32_FUNCTION(0, "GPIOA3"),
+               STM32_FUNCTION(2, "TIM2_CH4"),
+               STM32_FUNCTION(3, "TIM5_CH4"),
+               STM32_FUNCTION(4, "TIM9_CH2"),
+               STM32_FUNCTION(8, "USART2_RX"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_D0"),
+               STM32_FUNCTION(12, "ETH_MII_COL"),
+               STM32_FUNCTION(15, "LCD_B5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(4, "PA4"),
+               STM32_FUNCTION(0, "GPIOA4"),
+               STM32_FUNCTION(6, "SPI1_NSS"),
+               STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"),
+               STM32_FUNCTION(8, "USART2_CK"),
+               STM32_FUNCTION(13, "OTG_HS_SOF"),
+               STM32_FUNCTION(14, "DCMI_HSYNC"),
+               STM32_FUNCTION(15, "LCD_VSYNC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(5, "PA5"),
+               STM32_FUNCTION(0, "GPIOA5"),
+               STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+               STM32_FUNCTION(4, "TIM8_CH1N"),
+               STM32_FUNCTION(6, "SPI1_SCK"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_CK"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(6, "PA6"),
+               STM32_FUNCTION(0, "GPIOA6"),
+               STM32_FUNCTION(2, "TIM1_BKIN"),
+               STM32_FUNCTION(3, "TIM3_CH1"),
+               STM32_FUNCTION(4, "TIM8_BKIN"),
+               STM32_FUNCTION(6, "SPI1_MISO"),
+               STM32_FUNCTION(10, "TIM13_CH1"),
+               STM32_FUNCTION(14, "DCMI_PIXCLK"),
+               STM32_FUNCTION(15, "LCD_G2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(7, "PA7"),
+               STM32_FUNCTION(0, "GPIOA7"),
+               STM32_FUNCTION(2, "TIM1_CH1N"),
+               STM32_FUNCTION(3, "TIM3_CH2"),
+               STM32_FUNCTION(4, "TIM8_CH1N"),
+               STM32_FUNCTION(6, "SPI1_MOSI"),
+               STM32_FUNCTION(10, "TIM14_CH1"),
+               STM32_FUNCTION(12, "ETH_MII_RX_DV ETH_RMII_CRS_DV"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(8, "PA8"),
+               STM32_FUNCTION(0, "GPIOA8"),
+               STM32_FUNCTION(1, "MCO1"),
+               STM32_FUNCTION(2, "TIM1_CH1"),
+               STM32_FUNCTION(5, "I2C3_SCL"),
+               STM32_FUNCTION(8, "USART1_CK"),
+               STM32_FUNCTION(11, "OTG_FS_SOF"),
+               STM32_FUNCTION(15, "LCD_R6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(9, "PA9"),
+               STM32_FUNCTION(0, "GPIOA9"),
+               STM32_FUNCTION(2, "TIM1_CH2"),
+               STM32_FUNCTION(5, "I2C3_SMBA"),
+               STM32_FUNCTION(8, "USART1_TX"),
+               STM32_FUNCTION(14, "DCMI_D0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(10, "PA10"),
+               STM32_FUNCTION(0, "GPIOA10"),
+               STM32_FUNCTION(2, "TIM1_CH3"),
+               STM32_FUNCTION(8, "USART1_RX"),
+               STM32_FUNCTION(11, "OTG_FS_ID"),
+               STM32_FUNCTION(14, "DCMI_D1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(11, "PA11"),
+               STM32_FUNCTION(0, "GPIOA11"),
+               STM32_FUNCTION(2, "TIM1_CH4"),
+               STM32_FUNCTION(8, "USART1_CTS"),
+               STM32_FUNCTION(10, "CAN1_RX"),
+               STM32_FUNCTION(11, "OTG_FS_DM"),
+               STM32_FUNCTION(15, "LCD_R4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(12, "PA12"),
+               STM32_FUNCTION(0, "GPIOA12"),
+               STM32_FUNCTION(2, "TIM1_ETR"),
+               STM32_FUNCTION(8, "USART1_RTS"),
+               STM32_FUNCTION(10, "CAN1_TX"),
+               STM32_FUNCTION(11, "OTG_FS_DP"),
+               STM32_FUNCTION(15, "LCD_R5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(13, "PA13"),
+               STM32_FUNCTION(0, "GPIOA13"),
+               STM32_FUNCTION(1, "JTMS SWDIO"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(14, "PA14"),
+               STM32_FUNCTION(0, "GPIOA14"),
+               STM32_FUNCTION(1, "JTCK SWCLK"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(15, "PA15"),
+               STM32_FUNCTION(0, "GPIOA15"),
+               STM32_FUNCTION(1, "JTDI"),
+               STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"),
+               STM32_FUNCTION(6, "SPI1_NSS"),
+               STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(16, "PB0"),
+               STM32_FUNCTION(0, "GPIOB0"),
+               STM32_FUNCTION(2, "TIM1_CH2N"),
+               STM32_FUNCTION(3, "TIM3_CH3"),
+               STM32_FUNCTION(4, "TIM8_CH2N"),
+               STM32_FUNCTION(10, "LCD_R3"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_D1"),
+               STM32_FUNCTION(12, "ETH_MII_RXD2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(17, "PB1"),
+               STM32_FUNCTION(0, "GPIOB1"),
+               STM32_FUNCTION(2, "TIM1_CH3N"),
+               STM32_FUNCTION(3, "TIM3_CH4"),
+               STM32_FUNCTION(4, "TIM8_CH3N"),
+               STM32_FUNCTION(10, "LCD_R6"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_D2"),
+               STM32_FUNCTION(12, "ETH_MII_RXD3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(18, "PB2"),
+               STM32_FUNCTION(0, "GPIOB2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(19, "PB3"),
+               STM32_FUNCTION(0, "GPIOB3"),
+               STM32_FUNCTION(1, "JTDO TRACESWO"),
+               STM32_FUNCTION(2, "TIM2_CH2"),
+               STM32_FUNCTION(6, "SPI1_SCK"),
+               STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(20, "PB4"),
+               STM32_FUNCTION(0, "GPIOB4"),
+               STM32_FUNCTION(1, "NJTRST"),
+               STM32_FUNCTION(3, "TIM3_CH1"),
+               STM32_FUNCTION(6, "SPI1_MISO"),
+               STM32_FUNCTION(7, "SPI3_MISO"),
+               STM32_FUNCTION(8, "I2S3EXT_SD"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(21, "PB5"),
+               STM32_FUNCTION(0, "GPIOB5"),
+               STM32_FUNCTION(3, "TIM3_CH2"),
+               STM32_FUNCTION(5, "I2C1_SMBA"),
+               STM32_FUNCTION(6, "SPI1_MOSI"),
+               STM32_FUNCTION(7, "SPI3_MOSI I2S3_SD"),
+               STM32_FUNCTION(10, "CAN2_RX"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_D7"),
+               STM32_FUNCTION(12, "ETH_PPS_OUT"),
+               STM32_FUNCTION(13, "FMC_SDCKE1"),
+               STM32_FUNCTION(14, "DCMI_D10"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(22, "PB6"),
+               STM32_FUNCTION(0, "GPIOB6"),
+               STM32_FUNCTION(3, "TIM4_CH1"),
+               STM32_FUNCTION(5, "I2C1_SCL"),
+               STM32_FUNCTION(8, "USART1_TX"),
+               STM32_FUNCTION(10, "CAN2_TX"),
+               STM32_FUNCTION(13, "FMC_SDNE1"),
+               STM32_FUNCTION(14, "DCMI_D5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(23, "PB7"),
+               STM32_FUNCTION(0, "GPIOB7"),
+               STM32_FUNCTION(3, "TIM4_CH2"),
+               STM32_FUNCTION(5, "I2C1_SDA"),
+               STM32_FUNCTION(8, "USART1_RX"),
+               STM32_FUNCTION(13, "FMC_NL"),
+               STM32_FUNCTION(14, "DCMI_VSYNC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(24, "PB8"),
+               STM32_FUNCTION(0, "GPIOB8"),
+               STM32_FUNCTION(3, "TIM4_CH3"),
+               STM32_FUNCTION(4, "TIM10_CH1"),
+               STM32_FUNCTION(5, "I2C1_SCL"),
+               STM32_FUNCTION(10, "CAN1_RX"),
+               STM32_FUNCTION(12, "ETH_MII_TXD3"),
+               STM32_FUNCTION(13, "SDIO_D4"),
+               STM32_FUNCTION(14, "DCMI_D6"),
+               STM32_FUNCTION(15, "LCD_B6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(25, "PB9"),
+               STM32_FUNCTION(0, "GPIOB9"),
+               STM32_FUNCTION(3, "TIM4_CH4"),
+               STM32_FUNCTION(4, "TIM11_CH1"),
+               STM32_FUNCTION(5, "I2C1_SDA"),
+               STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+               STM32_FUNCTION(10, "CAN1_TX"),
+               STM32_FUNCTION(13, "SDIO_D5"),
+               STM32_FUNCTION(14, "DCMI_D7"),
+               STM32_FUNCTION(15, "LCD_B7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(26, "PB10"),
+               STM32_FUNCTION(0, "GPIOB10"),
+               STM32_FUNCTION(2, "TIM2_CH3"),
+               STM32_FUNCTION(5, "I2C2_SCL"),
+               STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+               STM32_FUNCTION(8, "USART3_TX"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_D3"),
+               STM32_FUNCTION(12, "ETH_MII_RX_ER"),
+               STM32_FUNCTION(15, "LCD_G4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(27, "PB11"),
+               STM32_FUNCTION(0, "GPIOB11"),
+               STM32_FUNCTION(2, "TIM2_CH4"),
+               STM32_FUNCTION(5, "I2C2_SDA"),
+               STM32_FUNCTION(8, "USART3_RX"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_D4"),
+               STM32_FUNCTION(12, "ETH_MII_TX_EN ETH_RMII_TX_EN"),
+               STM32_FUNCTION(15, "LCD_G5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(28, "PB12"),
+               STM32_FUNCTION(0, "GPIOB12"),
+               STM32_FUNCTION(2, "TIM1_BKIN"),
+               STM32_FUNCTION(5, "I2C2_SMBA"),
+               STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+               STM32_FUNCTION(8, "USART3_CK"),
+               STM32_FUNCTION(10, "CAN2_RX"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_D5"),
+               STM32_FUNCTION(12, "ETH_MII_TXD0 ETH_RMII_TXD0"),
+               STM32_FUNCTION(13, "OTG_HS_ID"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(29, "PB13"),
+               STM32_FUNCTION(0, "GPIOB13"),
+               STM32_FUNCTION(2, "TIM1_CH1N"),
+               STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+               STM32_FUNCTION(8, "USART3_CTS"),
+               STM32_FUNCTION(10, "CAN2_TX"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_D6"),
+               STM32_FUNCTION(12, "ETH_MII_TXD1 ETH_RMII_TXD1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(30, "PB14"),
+               STM32_FUNCTION(0, "GPIOB14"),
+               STM32_FUNCTION(2, "TIM1_CH2N"),
+               STM32_FUNCTION(4, "TIM8_CH2N"),
+               STM32_FUNCTION(6, "SPI2_MISO"),
+               STM32_FUNCTION(7, "I2S2EXT_SD"),
+               STM32_FUNCTION(8, "USART3_RTS"),
+               STM32_FUNCTION(10, "TIM12_CH1"),
+               STM32_FUNCTION(13, "OTG_HS_DM"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(31, "PB15"),
+               STM32_FUNCTION(0, "GPIOB15"),
+               STM32_FUNCTION(1, "RTC_REFIN"),
+               STM32_FUNCTION(2, "TIM1_CH3N"),
+               STM32_FUNCTION(4, "TIM8_CH3N"),
+               STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"),
+               STM32_FUNCTION(10, "TIM12_CH2"),
+               STM32_FUNCTION(13, "OTG_HS_DP"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(32, "PC0"),
+               STM32_FUNCTION(0, "GPIOC0"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_STP"),
+               STM32_FUNCTION(13, "FMC_SDNWE"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(33, "PC1"),
+               STM32_FUNCTION(0, "GPIOC1"),
+               STM32_FUNCTION(12, "ETH_MDC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(34, "PC2"),
+               STM32_FUNCTION(0, "GPIOC2"),
+               STM32_FUNCTION(6, "SPI2_MISO"),
+               STM32_FUNCTION(7, "I2S2EXT_SD"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_DIR"),
+               STM32_FUNCTION(12, "ETH_MII_TXD2"),
+               STM32_FUNCTION(13, "FMC_SDNE0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(35, "PC3"),
+               STM32_FUNCTION(0, "GPIOC3"),
+               STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_NXT"),
+               STM32_FUNCTION(12, "ETH_MII_TX_CLK"),
+               STM32_FUNCTION(13, "FMC_SDCKE0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(36, "PC4"),
+               STM32_FUNCTION(0, "GPIOC4"),
+               STM32_FUNCTION(12, "ETH_MII_RXD0 ETH_RMII_RXD0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(37, "PC5"),
+               STM32_FUNCTION(0, "GPIOC5"),
+               STM32_FUNCTION(12, "ETH_MII_RXD1 ETH_RMII_RXD1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(38, "PC6"),
+               STM32_FUNCTION(0, "GPIOC6"),
+               STM32_FUNCTION(3, "TIM3_CH1"),
+               STM32_FUNCTION(4, "TIM8_CH1"),
+               STM32_FUNCTION(6, "I2S2_MCK"),
+               STM32_FUNCTION(9, "USART6_TX"),
+               STM32_FUNCTION(13, "SDIO_D6"),
+               STM32_FUNCTION(14, "DCMI_D0"),
+               STM32_FUNCTION(15, "LCD_HSYNC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(39, "PC7"),
+               STM32_FUNCTION(0, "GPIOC7"),
+               STM32_FUNCTION(3, "TIM3_CH2"),
+               STM32_FUNCTION(4, "TIM8_CH2"),
+               STM32_FUNCTION(7, "I2S3_MCK"),
+               STM32_FUNCTION(9, "USART6_RX"),
+               STM32_FUNCTION(13, "SDIO_D7"),
+               STM32_FUNCTION(14, "DCMI_D1"),
+               STM32_FUNCTION(15, "LCD_G6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(40, "PC8"),
+               STM32_FUNCTION(0, "GPIOC8"),
+               STM32_FUNCTION(3, "TIM3_CH3"),
+               STM32_FUNCTION(4, "TIM8_CH3"),
+               STM32_FUNCTION(9, "USART6_CK"),
+               STM32_FUNCTION(13, "SDIO_D0"),
+               STM32_FUNCTION(14, "DCMI_D2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(41, "PC9"),
+               STM32_FUNCTION(0, "GPIOC9"),
+               STM32_FUNCTION(1, "MCO2"),
+               STM32_FUNCTION(3, "TIM3_CH4"),
+               STM32_FUNCTION(4, "TIM8_CH4"),
+               STM32_FUNCTION(5, "I2C3_SDA"),
+               STM32_FUNCTION(6, "I2S_CKIN"),
+               STM32_FUNCTION(13, "SDIO_D1"),
+               STM32_FUNCTION(14, "DCMI_D3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(42, "PC10"),
+               STM32_FUNCTION(0, "GPIOC10"),
+               STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"),
+               STM32_FUNCTION(8, "USART3_TX"),
+               STM32_FUNCTION(9, "UART4_TX"),
+               STM32_FUNCTION(13, "SDIO_D2"),
+               STM32_FUNCTION(14, "DCMI_D8"),
+               STM32_FUNCTION(15, "LCD_R2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(43, "PC11"),
+               STM32_FUNCTION(0, "GPIOC11"),
+               STM32_FUNCTION(6, "I2S3EXT_SD"),
+               STM32_FUNCTION(7, "SPI3_MISO"),
+               STM32_FUNCTION(8, "USART3_RX"),
+               STM32_FUNCTION(9, "UART4_RX"),
+               STM32_FUNCTION(13, "SDIO_D3"),
+               STM32_FUNCTION(14, "DCMI_D4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(44, "PC12"),
+               STM32_FUNCTION(0, "GPIOC12"),
+               STM32_FUNCTION(7, "SPI3_MOSI I2S3_SD"),
+               STM32_FUNCTION(8, "USART3_CK"),
+               STM32_FUNCTION(9, "UART5_TX"),
+               STM32_FUNCTION(13, "SDIO_CK"),
+               STM32_FUNCTION(14, "DCMI_D9"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(45, "PC13"),
+               STM32_FUNCTION(0, "GPIOC13"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(46, "PC14"),
+               STM32_FUNCTION(0, "GPIOC14"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(47, "PC15"),
+               STM32_FUNCTION(0, "GPIOC15"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(48, "PD0"),
+               STM32_FUNCTION(0, "GPIOD0"),
+               STM32_FUNCTION(10, "CAN1_RX"),
+               STM32_FUNCTION(13, "FMC_D2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(49, "PD1"),
+               STM32_FUNCTION(0, "GPIOD1"),
+               STM32_FUNCTION(10, "CAN1_TX"),
+               STM32_FUNCTION(13, "FMC_D3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(50, "PD2"),
+               STM32_FUNCTION(0, "GPIOD2"),
+               STM32_FUNCTION(3, "TIM3_ETR"),
+               STM32_FUNCTION(9, "UART5_RX"),
+               STM32_FUNCTION(13, "SDIO_CMD"),
+               STM32_FUNCTION(14, "DCMI_D11"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(51, "PD3"),
+               STM32_FUNCTION(0, "GPIOD3"),
+               STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+               STM32_FUNCTION(8, "USART2_CTS"),
+               STM32_FUNCTION(13, "FMC_CLK"),
+               STM32_FUNCTION(14, "DCMI_D5"),
+               STM32_FUNCTION(15, "LCD_G7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(52, "PD4"),
+               STM32_FUNCTION(0, "GPIOD4"),
+               STM32_FUNCTION(8, "USART2_RTS"),
+               STM32_FUNCTION(13, "FMC_NOE"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(53, "PD5"),
+               STM32_FUNCTION(0, "GPIOD5"),
+               STM32_FUNCTION(8, "USART2_TX"),
+               STM32_FUNCTION(13, "FMC_NWE"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(54, "PD6"),
+               STM32_FUNCTION(0, "GPIOD6"),
+               STM32_FUNCTION(6, "SPI3_MOSI I2S3_SD"),
+               STM32_FUNCTION(7, "SAI1_SD_A"),
+               STM32_FUNCTION(8, "USART2_RX"),
+               STM32_FUNCTION(13, "FMC_NWAIT"),
+               STM32_FUNCTION(14, "DCMI_D10"),
+               STM32_FUNCTION(15, "LCD_B2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(55, "PD7"),
+               STM32_FUNCTION(0, "GPIOD7"),
+               STM32_FUNCTION(8, "USART2_CK"),
+               STM32_FUNCTION(13, "FMC_NE1 FMC_NCE2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(56, "PD8"),
+               STM32_FUNCTION(0, "GPIOD8"),
+               STM32_FUNCTION(8, "USART3_TX"),
+               STM32_FUNCTION(13, "FMC_D13"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(57, "PD9"),
+               STM32_FUNCTION(0, "GPIOD9"),
+               STM32_FUNCTION(8, "USART3_RX"),
+               STM32_FUNCTION(13, "FMC_D14"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(58, "PD10"),
+               STM32_FUNCTION(0, "GPIOD10"),
+               STM32_FUNCTION(8, "USART3_CK"),
+               STM32_FUNCTION(13, "FMC_D15"),
+               STM32_FUNCTION(15, "LCD_B3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(59, "PD11"),
+               STM32_FUNCTION(0, "GPIOD11"),
+               STM32_FUNCTION(8, "USART3_CTS"),
+               STM32_FUNCTION(13, "FMC_A16"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(60, "PD12"),
+               STM32_FUNCTION(0, "GPIOD12"),
+               STM32_FUNCTION(3, "TIM4_CH1"),
+               STM32_FUNCTION(8, "USART3_RTS"),
+               STM32_FUNCTION(13, "FMC_A17"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(61, "PD13"),
+               STM32_FUNCTION(0, "GPIOD13"),
+               STM32_FUNCTION(3, "TIM4_CH2"),
+               STM32_FUNCTION(13, "FMC_A18"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(62, "PD14"),
+               STM32_FUNCTION(0, "GPIOD14"),
+               STM32_FUNCTION(3, "TIM4_CH3"),
+               STM32_FUNCTION(13, "FMC_D0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(63, "PD15"),
+               STM32_FUNCTION(0, "GPIOD15"),
+               STM32_FUNCTION(3, "TIM4_CH4"),
+               STM32_FUNCTION(13, "FMC_D1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(64, "PE0"),
+               STM32_FUNCTION(0, "GPIOE0"),
+               STM32_FUNCTION(3, "TIM4_ETR"),
+               STM32_FUNCTION(9, "UART8_RX"),
+               STM32_FUNCTION(13, "FMC_NBL0"),
+               STM32_FUNCTION(14, "DCMI_D2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(65, "PE1"),
+               STM32_FUNCTION(0, "GPIOE1"),
+               STM32_FUNCTION(9, "UART8_TX"),
+               STM32_FUNCTION(13, "FMC_NBL1"),
+               STM32_FUNCTION(14, "DCMI_D3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(66, "PE2"),
+               STM32_FUNCTION(0, "GPIOE2"),
+               STM32_FUNCTION(1, "TRACECLK"),
+               STM32_FUNCTION(6, "SPI4_SCK"),
+               STM32_FUNCTION(7, "SAI1_MCLK_A"),
+               STM32_FUNCTION(12, "ETH_MII_TXD3"),
+               STM32_FUNCTION(13, "FMC_A23"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(67, "PE3"),
+               STM32_FUNCTION(0, "GPIOE3"),
+               STM32_FUNCTION(1, "TRACED0"),
+               STM32_FUNCTION(7, "SAI1_SD_B"),
+               STM32_FUNCTION(13, "FMC_A19"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(68, "PE4"),
+               STM32_FUNCTION(0, "GPIOE4"),
+               STM32_FUNCTION(1, "TRACED1"),
+               STM32_FUNCTION(6, "SPI4_NSS"),
+               STM32_FUNCTION(7, "SAI1_FS_A"),
+               STM32_FUNCTION(13, "FMC_A20"),
+               STM32_FUNCTION(14, "DCMI_D4"),
+               STM32_FUNCTION(15, "LCD_B0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(69, "PE5"),
+               STM32_FUNCTION(0, "GPIOE5"),
+               STM32_FUNCTION(1, "TRACED2"),
+               STM32_FUNCTION(4, "TIM9_CH1"),
+               STM32_FUNCTION(6, "SPI4_MISO"),
+               STM32_FUNCTION(7, "SAI1_SCK_A"),
+               STM32_FUNCTION(13, "FMC_A21"),
+               STM32_FUNCTION(14, "DCMI_D6"),
+               STM32_FUNCTION(15, "LCD_G0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(70, "PE6"),
+               STM32_FUNCTION(0, "GPIOE6"),
+               STM32_FUNCTION(1, "TRACED3"),
+               STM32_FUNCTION(4, "TIM9_CH2"),
+               STM32_FUNCTION(6, "SPI4_MOSI"),
+               STM32_FUNCTION(7, "SAI1_SD_A"),
+               STM32_FUNCTION(13, "FMC_A22"),
+               STM32_FUNCTION(14, "DCMI_D7"),
+               STM32_FUNCTION(15, "LCD_G1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(71, "PE7"),
+               STM32_FUNCTION(0, "GPIOE7"),
+               STM32_FUNCTION(2, "TIM1_ETR"),
+               STM32_FUNCTION(9, "UART7_RX"),
+               STM32_FUNCTION(13, "FMC_D4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(72, "PE8"),
+               STM32_FUNCTION(0, "GPIOE8"),
+               STM32_FUNCTION(2, "TIM1_CH1N"),
+               STM32_FUNCTION(9, "UART7_TX"),
+               STM32_FUNCTION(13, "FMC_D5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(73, "PE9"),
+               STM32_FUNCTION(0, "GPIOE9"),
+               STM32_FUNCTION(2, "TIM1_CH1"),
+               STM32_FUNCTION(13, "FMC_D6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(74, "PE10"),
+               STM32_FUNCTION(0, "GPIOE10"),
+               STM32_FUNCTION(2, "TIM1_CH2N"),
+               STM32_FUNCTION(13, "FMC_D7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(75, "PE11"),
+               STM32_FUNCTION(0, "GPIOE11"),
+               STM32_FUNCTION(2, "TIM1_CH2"),
+               STM32_FUNCTION(6, "SPI4_NSS"),
+               STM32_FUNCTION(13, "FMC_D8"),
+               STM32_FUNCTION(15, "LCD_G3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(76, "PE12"),
+               STM32_FUNCTION(0, "GPIOE12"),
+               STM32_FUNCTION(2, "TIM1_CH3N"),
+               STM32_FUNCTION(6, "SPI4_SCK"),
+               STM32_FUNCTION(13, "FMC_D9"),
+               STM32_FUNCTION(15, "LCD_B4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(77, "PE13"),
+               STM32_FUNCTION(0, "GPIOE13"),
+               STM32_FUNCTION(2, "TIM1_CH3"),
+               STM32_FUNCTION(6, "SPI4_MISO"),
+               STM32_FUNCTION(13, "FMC_D10"),
+               STM32_FUNCTION(15, "LCD_DE"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(78, "PE14"),
+               STM32_FUNCTION(0, "GPIOE14"),
+               STM32_FUNCTION(2, "TIM1_CH4"),
+               STM32_FUNCTION(6, "SPI4_MOSI"),
+               STM32_FUNCTION(13, "FMC_D11"),
+               STM32_FUNCTION(15, "LCD_CLK"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(79, "PE15"),
+               STM32_FUNCTION(0, "GPIOE15"),
+               STM32_FUNCTION(2, "TIM1_BKIN"),
+               STM32_FUNCTION(13, "FMC_D12"),
+               STM32_FUNCTION(15, "LCD_R7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(80, "PF0"),
+               STM32_FUNCTION(0, "GPIOF0"),
+               STM32_FUNCTION(5, "I2C2_SDA"),
+               STM32_FUNCTION(13, "FMC_A0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(81, "PF1"),
+               STM32_FUNCTION(0, "GPIOF1"),
+               STM32_FUNCTION(5, "I2C2_SCL"),
+               STM32_FUNCTION(13, "FMC_A1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(82, "PF2"),
+               STM32_FUNCTION(0, "GPIOF2"),
+               STM32_FUNCTION(5, "I2C2_SMBA"),
+               STM32_FUNCTION(13, "FMC_A2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(83, "PF3"),
+               STM32_FUNCTION(0, "GPIOF3"),
+               STM32_FUNCTION(13, "FMC_A3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(84, "PF4"),
+               STM32_FUNCTION(0, "GPIOF4"),
+               STM32_FUNCTION(13, "FMC_A4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(85, "PF5"),
+               STM32_FUNCTION(0, "GPIOF5"),
+               STM32_FUNCTION(13, "FMC_A5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(86, "PF6"),
+               STM32_FUNCTION(0, "GPIOF6"),
+               STM32_FUNCTION(4, "TIM10_CH1"),
+               STM32_FUNCTION(6, "SPI5_NSS"),
+               STM32_FUNCTION(7, "SAI1_SD_B"),
+               STM32_FUNCTION(9, "UART7_RX"),
+               STM32_FUNCTION(13, "FMC_NIORD"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(87, "PF7"),
+               STM32_FUNCTION(0, "GPIOF7"),
+               STM32_FUNCTION(4, "TIM11_CH1"),
+               STM32_FUNCTION(6, "SPI5_SCK"),
+               STM32_FUNCTION(7, "SAI1_MCLK_B"),
+               STM32_FUNCTION(9, "UART7_TX"),
+               STM32_FUNCTION(13, "FMC_NREG"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(88, "PF8"),
+               STM32_FUNCTION(0, "GPIOF8"),
+               STM32_FUNCTION(6, "SPI5_MISO"),
+               STM32_FUNCTION(7, "SAI1_SCK_B"),
+               STM32_FUNCTION(10, "TIM13_CH1"),
+               STM32_FUNCTION(13, "FMC_NIOWR"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(89, "PF9"),
+               STM32_FUNCTION(0, "GPIOF9"),
+               STM32_FUNCTION(6, "SPI5_MOSI"),
+               STM32_FUNCTION(7, "SAI1_FS_B"),
+               STM32_FUNCTION(10, "TIM14_CH1"),
+               STM32_FUNCTION(13, "FMC_CD"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(90, "PF10"),
+               STM32_FUNCTION(0, "GPIOF10"),
+               STM32_FUNCTION(13, "FMC_INTR"),
+               STM32_FUNCTION(14, "DCMI_D11"),
+               STM32_FUNCTION(15, "LCD_DE"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(91, "PF11"),
+               STM32_FUNCTION(0, "GPIOF11"),
+               STM32_FUNCTION(6, "SPI5_MOSI"),
+               STM32_FUNCTION(13, "FMC_SDNRAS"),
+               STM32_FUNCTION(14, "DCMI_D12"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(92, "PF12"),
+               STM32_FUNCTION(0, "GPIOF12"),
+               STM32_FUNCTION(13, "FMC_A6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(93, "PF13"),
+               STM32_FUNCTION(0, "GPIOF13"),
+               STM32_FUNCTION(13, "FMC_A7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(94, "PF14"),
+               STM32_FUNCTION(0, "GPIOF14"),
+               STM32_FUNCTION(13, "FMC_A8"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(95, "PF15"),
+               STM32_FUNCTION(0, "GPIOF15"),
+               STM32_FUNCTION(13, "FMC_A9"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(96, "PG0"),
+               STM32_FUNCTION(0, "GPIOG0"),
+               STM32_FUNCTION(13, "FMC_A10"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(97, "PG1"),
+               STM32_FUNCTION(0, "GPIOG1"),
+               STM32_FUNCTION(13, "FMC_A11"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(98, "PG2"),
+               STM32_FUNCTION(0, "GPIOG2"),
+               STM32_FUNCTION(13, "FMC_A12"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(99, "PG3"),
+               STM32_FUNCTION(0, "GPIOG3"),
+               STM32_FUNCTION(13, "FMC_A13"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(100, "PG4"),
+               STM32_FUNCTION(0, "GPIOG4"),
+               STM32_FUNCTION(13, "FMC_A14 FMC_BA0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(101, "PG5"),
+               STM32_FUNCTION(0, "GPIOG5"),
+               STM32_FUNCTION(13, "FMC_A15 FMC_BA1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(102, "PG6"),
+               STM32_FUNCTION(0, "GPIOG6"),
+               STM32_FUNCTION(13, "FMC_INT2"),
+               STM32_FUNCTION(14, "DCMI_D12"),
+               STM32_FUNCTION(15, "LCD_R7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(103, "PG7"),
+               STM32_FUNCTION(0, "GPIOG7"),
+               STM32_FUNCTION(9, "USART6_CK"),
+               STM32_FUNCTION(13, "FMC_INT3"),
+               STM32_FUNCTION(14, "DCMI_D13"),
+               STM32_FUNCTION(15, "LCD_CLK"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(104, "PG8"),
+               STM32_FUNCTION(0, "GPIOG8"),
+               STM32_FUNCTION(6, "SPI6_NSS"),
+               STM32_FUNCTION(9, "USART6_RTS"),
+               STM32_FUNCTION(12, "ETH_PPS_OUT"),
+               STM32_FUNCTION(13, "FMC_SDCLK"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(105, "PG9"),
+               STM32_FUNCTION(0, "GPIOG9"),
+               STM32_FUNCTION(9, "USART6_RX"),
+               STM32_FUNCTION(13, "FMC_NE2 FMC_NCE3"),
+               STM32_FUNCTION(14, "DCMI_VSYNC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(106, "PG10"),
+               STM32_FUNCTION(0, "GPIOG10"),
+               STM32_FUNCTION(10, "LCD_G3"),
+               STM32_FUNCTION(13, "FMC_NCE4_1 FMC_NE3"),
+               STM32_FUNCTION(14, "DCMI_D2"),
+               STM32_FUNCTION(15, "LCD_B2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(107, "PG11"),
+               STM32_FUNCTION(0, "GPIOG11"),
+               STM32_FUNCTION(12, "ETH_MII_TX_EN ETH_RMII_TX_EN"),
+               STM32_FUNCTION(13, "FMC_NCE4_2"),
+               STM32_FUNCTION(14, "DCMI_D3"),
+               STM32_FUNCTION(15, "LCD_B3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(108, "PG12"),
+               STM32_FUNCTION(0, "GPIOG12"),
+               STM32_FUNCTION(6, "SPI6_MISO"),
+               STM32_FUNCTION(9, "USART6_RTS"),
+               STM32_FUNCTION(10, "LCD_B4"),
+               STM32_FUNCTION(13, "FMC_NE4"),
+               STM32_FUNCTION(15, "LCD_B1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(109, "PG13"),
+               STM32_FUNCTION(0, "GPIOG13"),
+               STM32_FUNCTION(6, "SPI6_SCK"),
+               STM32_FUNCTION(9, "USART6_CTS"),
+               STM32_FUNCTION(12, "ETH_MII_TXD0 ETH_RMII_TXD0"),
+               STM32_FUNCTION(13, "FMC_A24"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(110, "PG14"),
+               STM32_FUNCTION(0, "GPIOG14"),
+               STM32_FUNCTION(6, "SPI6_MOSI"),
+               STM32_FUNCTION(9, "USART6_TX"),
+               STM32_FUNCTION(12, "ETH_MII_TXD1 ETH_RMII_TXD1"),
+               STM32_FUNCTION(13, "FMC_A25"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(111, "PG15"),
+               STM32_FUNCTION(0, "GPIOG15"),
+               STM32_FUNCTION(9, "USART6_CTS"),
+               STM32_FUNCTION(13, "FMC_SDNCAS"),
+               STM32_FUNCTION(14, "DCMI_D13"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(112, "PH0"),
+               STM32_FUNCTION(0, "GPIOH0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(113, "PH1"),
+               STM32_FUNCTION(0, "GPIOH1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(114, "PH2"),
+               STM32_FUNCTION(0, "GPIOH2"),
+               STM32_FUNCTION(12, "ETH_MII_CRS"),
+               STM32_FUNCTION(13, "FMC_SDCKE0"),
+               STM32_FUNCTION(15, "LCD_R0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(115, "PH3"),
+               STM32_FUNCTION(0, "GPIOH3"),
+               STM32_FUNCTION(12, "ETH_MII_COL"),
+               STM32_FUNCTION(13, "FMC_SDNE0"),
+               STM32_FUNCTION(15, "LCD_R1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(116, "PH4"),
+               STM32_FUNCTION(0, "GPIOH4"),
+               STM32_FUNCTION(5, "I2C2_SCL"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_NXT"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(117, "PH5"),
+               STM32_FUNCTION(0, "GPIOH5"),
+               STM32_FUNCTION(5, "I2C2_SDA"),
+               STM32_FUNCTION(6, "SPI5_NSS"),
+               STM32_FUNCTION(13, "FMC_SDNWE"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(118, "PH6"),
+               STM32_FUNCTION(0, "GPIOH6"),
+               STM32_FUNCTION(5, "I2C2_SMBA"),
+               STM32_FUNCTION(6, "SPI5_SCK"),
+               STM32_FUNCTION(10, "TIM12_CH1"),
+               STM32_FUNCTION(12, "ETH_MII_RXD2"),
+               STM32_FUNCTION(13, "FMC_SDNE1"),
+               STM32_FUNCTION(14, "DCMI_D8"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(119, "PH7"),
+               STM32_FUNCTION(0, "GPIOH7"),
+               STM32_FUNCTION(5, "I2C3_SCL"),
+               STM32_FUNCTION(6, "SPI5_MISO"),
+               STM32_FUNCTION(12, "ETH_MII_RXD3"),
+               STM32_FUNCTION(13, "FMC_SDCKE1"),
+               STM32_FUNCTION(14, "DCMI_D9"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(120, "PH8"),
+               STM32_FUNCTION(0, "GPIOH8"),
+               STM32_FUNCTION(5, "I2C3_SDA"),
+               STM32_FUNCTION(13, "FMC_D16"),
+               STM32_FUNCTION(14, "DCMI_HSYNC"),
+               STM32_FUNCTION(15, "LCD_R2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(121, "PH9"),
+               STM32_FUNCTION(0, "GPIOH9"),
+               STM32_FUNCTION(5, "I2C3_SMBA"),
+               STM32_FUNCTION(10, "TIM12_CH2"),
+               STM32_FUNCTION(13, "FMC_D17"),
+               STM32_FUNCTION(14, "DCMI_D0"),
+               STM32_FUNCTION(15, "LCD_R3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(122, "PH10"),
+               STM32_FUNCTION(0, "GPIOH10"),
+               STM32_FUNCTION(3, "TIM5_CH1"),
+               STM32_FUNCTION(13, "FMC_D18"),
+               STM32_FUNCTION(14, "DCMI_D1"),
+               STM32_FUNCTION(15, "LCD_R4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(123, "PH11"),
+               STM32_FUNCTION(0, "GPIOH11"),
+               STM32_FUNCTION(3, "TIM5_CH2"),
+               STM32_FUNCTION(13, "FMC_D19"),
+               STM32_FUNCTION(14, "DCMI_D2"),
+               STM32_FUNCTION(15, "LCD_R5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(124, "PH12"),
+               STM32_FUNCTION(0, "GPIOH12"),
+               STM32_FUNCTION(3, "TIM5_CH3"),
+               STM32_FUNCTION(13, "FMC_D20"),
+               STM32_FUNCTION(14, "DCMI_D3"),
+               STM32_FUNCTION(15, "LCD_R6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(125, "PH13"),
+               STM32_FUNCTION(0, "GPIOH13"),
+               STM32_FUNCTION(4, "TIM8_CH1N"),
+               STM32_FUNCTION(10, "CAN1_TX"),
+               STM32_FUNCTION(13, "FMC_D21"),
+               STM32_FUNCTION(15, "LCD_G2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(126, "PH14"),
+               STM32_FUNCTION(0, "GPIOH14"),
+               STM32_FUNCTION(4, "TIM8_CH2N"),
+               STM32_FUNCTION(13, "FMC_D22"),
+               STM32_FUNCTION(14, "DCMI_D4"),
+               STM32_FUNCTION(15, "LCD_G3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(127, "PH15"),
+               STM32_FUNCTION(0, "GPIOH15"),
+               STM32_FUNCTION(4, "TIM8_CH3N"),
+               STM32_FUNCTION(13, "FMC_D23"),
+               STM32_FUNCTION(14, "DCMI_D11"),
+               STM32_FUNCTION(15, "LCD_G4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(128, "PI0"),
+               STM32_FUNCTION(0, "GPIOI0"),
+               STM32_FUNCTION(3, "TIM5_CH4"),
+               STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"),
+               STM32_FUNCTION(13, "FMC_D24"),
+               STM32_FUNCTION(14, "DCMI_D13"),
+               STM32_FUNCTION(15, "LCD_G5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(129, "PI1"),
+               STM32_FUNCTION(0, "GPIOI1"),
+               STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"),
+               STM32_FUNCTION(13, "FMC_D25"),
+               STM32_FUNCTION(14, "DCMI_D8"),
+               STM32_FUNCTION(15, "LCD_G6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(130, "PI2"),
+               STM32_FUNCTION(0, "GPIOI2"),
+               STM32_FUNCTION(4, "TIM8_CH4"),
+               STM32_FUNCTION(6, "SPI2_MISO"),
+               STM32_FUNCTION(7, "I2S2EXT_SD"),
+               STM32_FUNCTION(13, "FMC_D26"),
+               STM32_FUNCTION(14, "DCMI_D9"),
+               STM32_FUNCTION(15, "LCD_G7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(131, "PI3"),
+               STM32_FUNCTION(0, "GPIOI3"),
+               STM32_FUNCTION(4, "TIM8_ETR"),
+               STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"),
+               STM32_FUNCTION(13, "FMC_D27"),
+               STM32_FUNCTION(14, "DCMI_D10"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(132, "PI4"),
+               STM32_FUNCTION(0, "GPIOI4"),
+               STM32_FUNCTION(4, "TIM8_BKIN"),
+               STM32_FUNCTION(13, "FMC_NBL2"),
+               STM32_FUNCTION(14, "DCMI_D5"),
+               STM32_FUNCTION(15, "LCD_B4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(133, "PI5"),
+               STM32_FUNCTION(0, "GPIOI5"),
+               STM32_FUNCTION(4, "TIM8_CH1"),
+               STM32_FUNCTION(13, "FMC_NBL3"),
+               STM32_FUNCTION(14, "DCMI_VSYNC"),
+               STM32_FUNCTION(15, "LCD_B5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(134, "PI6"),
+               STM32_FUNCTION(0, "GPIOI6"),
+               STM32_FUNCTION(4, "TIM8_CH2"),
+               STM32_FUNCTION(13, "FMC_D28"),
+               STM32_FUNCTION(14, "DCMI_D6"),
+               STM32_FUNCTION(15, "LCD_B6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(135, "PI7"),
+               STM32_FUNCTION(0, "GPIOI7"),
+               STM32_FUNCTION(4, "TIM8_CH3"),
+               STM32_FUNCTION(13, "FMC_D29"),
+               STM32_FUNCTION(14, "DCMI_D7"),
+               STM32_FUNCTION(15, "LCD_B7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(136, "PI8"),
+               STM32_FUNCTION(0, "GPIOI8"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(137, "PI9"),
+               STM32_FUNCTION(0, "GPIOI9"),
+               STM32_FUNCTION(10, "CAN1_RX"),
+               STM32_FUNCTION(13, "FMC_D30"),
+               STM32_FUNCTION(15, "LCD_VSYNC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(138, "PI10"),
+               STM32_FUNCTION(0, "GPIOI10"),
+               STM32_FUNCTION(12, "ETH_MII_RX_ER"),
+               STM32_FUNCTION(13, "FMC_D31"),
+               STM32_FUNCTION(15, "LCD_HSYNC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(139, "PI11"),
+               STM32_FUNCTION(0, "GPIOI11"),
+               STM32_FUNCTION(11, "OTG_HS_ULPI_DIR"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(140, "PI12"),
+               STM32_FUNCTION(0, "GPIOI12"),
+               STM32_FUNCTION(15, "LCD_HSYNC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(141, "PI13"),
+               STM32_FUNCTION(0, "GPIOI13"),
+               STM32_FUNCTION(15, "LCD_VSYNC"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(142, "PI14"),
+               STM32_FUNCTION(0, "GPIOI14"),
+               STM32_FUNCTION(15, "LCD_CLK"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(143, "PI15"),
+               STM32_FUNCTION(0, "GPIOI15"),
+               STM32_FUNCTION(15, "LCD_R0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(144, "PJ0"),
+               STM32_FUNCTION(0, "GPIOJ0"),
+               STM32_FUNCTION(15, "LCD_R1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(145, "PJ1"),
+               STM32_FUNCTION(0, "GPIOJ1"),
+               STM32_FUNCTION(15, "LCD_R2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(146, "PJ2"),
+               STM32_FUNCTION(0, "GPIOJ2"),
+               STM32_FUNCTION(15, "LCD_R3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(147, "PJ3"),
+               STM32_FUNCTION(0, "GPIOJ3"),
+               STM32_FUNCTION(15, "LCD_R4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(148, "PJ4"),
+               STM32_FUNCTION(0, "GPIOJ4"),
+               STM32_FUNCTION(15, "LCD_R5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(149, "PJ5"),
+               STM32_FUNCTION(0, "GPIOJ5"),
+               STM32_FUNCTION(15, "LCD_R6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(150, "PJ6"),
+               STM32_FUNCTION(0, "GPIOJ6"),
+               STM32_FUNCTION(15, "LCD_R7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(151, "PJ7"),
+               STM32_FUNCTION(0, "GPIOJ7"),
+               STM32_FUNCTION(15, "LCD_G0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(152, "PJ8"),
+               STM32_FUNCTION(0, "GPIOJ8"),
+               STM32_FUNCTION(15, "LCD_G1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(153, "PJ9"),
+               STM32_FUNCTION(0, "GPIOJ9"),
+               STM32_FUNCTION(15, "LCD_G2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(154, "PJ10"),
+               STM32_FUNCTION(0, "GPIOJ10"),
+               STM32_FUNCTION(15, "LCD_G3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(155, "PJ11"),
+               STM32_FUNCTION(0, "GPIOJ11"),
+               STM32_FUNCTION(15, "LCD_G4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(156, "PJ12"),
+               STM32_FUNCTION(0, "GPIOJ12"),
+               STM32_FUNCTION(15, "LCD_B0"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(157, "PJ13"),
+               STM32_FUNCTION(0, "GPIOJ13"),
+               STM32_FUNCTION(15, "LCD_B1"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(158, "PJ14"),
+               STM32_FUNCTION(0, "GPIOJ14"),
+               STM32_FUNCTION(15, "LCD_B2"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(159, "PJ15"),
+               STM32_FUNCTION(0, "GPIOJ15"),
+               STM32_FUNCTION(15, "LCD_B3"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(160, "PK0"),
+               STM32_FUNCTION(0, "GPIOK0"),
+               STM32_FUNCTION(15, "LCD_G5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(161, "PK1"),
+               STM32_FUNCTION(0, "GPIOK1"),
+               STM32_FUNCTION(15, "LCD_G6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(162, "PK2"),
+               STM32_FUNCTION(0, "GPIOK2"),
+               STM32_FUNCTION(15, "LCD_G7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(163, "PK3"),
+               STM32_FUNCTION(0, "GPIOK3"),
+               STM32_FUNCTION(15, "LCD_B4"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(164, "PK4"),
+               STM32_FUNCTION(0, "GPIOK4"),
+               STM32_FUNCTION(15, "LCD_B5"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(165, "PK5"),
+               STM32_FUNCTION(0, "GPIOK5"),
+               STM32_FUNCTION(15, "LCD_B6"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(166, "PK6"),
+               STM32_FUNCTION(0, "GPIOK6"),
+               STM32_FUNCTION(15, "LCD_B7"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+       STM32_PIN(
+               PINCTRL_PIN(167, "PK7"),
+               STM32_FUNCTION(0, "GPIOK7"),
+               STM32_FUNCTION(15, "LCD_DE"),
+               STM32_FUNCTION(16, "EVENTOUT"),
+               STM32_FUNCTION(17, "ANALOG")
+       ),
+};
+
+static struct stm32_pinctrl_match_data stm32f429_match_data = {
+       .pins = stm32f429_pins,
+       .npins = ARRAY_SIZE(stm32f429_pins),
+};
+
+static const struct of_device_id stm32f429_pctrl_match[] = {
+       {
+               .compatible = "st,stm32f429-pinctrl",
+               .data = &stm32f429_match_data,
+       },
+       { }
+};
+
+static struct platform_driver stm32f429_pinctrl_driver = {
+       .probe = stm32_pctl_probe,
+       .driver = {
+               .name = "stm32f429-pinctrl",
+               .of_match_table = stm32f429_pctrl_match,
+       },
+};
+
+static int __init stm32f429_pinctrl_init(void)
+{
+       return platform_driver_register(&stm32f429_pinctrl_driver);
+}
+device_initcall(stm32f429_pinctrl_init);
index f8dbc8bec0e1e5363520abc12263182fe68b6c00..aaf075b972f5a14cac90416519594d3112871d72 100644 (file)
@@ -1,67 +1,75 @@
 if ARCH_SUNXI
 
-config PINCTRL_SUNXI_COMMON
+config PINCTRL_SUNXI
        bool
        select PINMUX
        select GENERIC_PINCONF
 
 config PINCTRL_SUN4I_A10
        def_bool MACH_SUN4I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN5I_A10S
        def_bool MACH_SUN5I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN5I_A13
        def_bool MACH_SUN5I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN6I_A31
        def_bool MACH_SUN6I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN6I_A31S
        def_bool MACH_SUN6I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN6I_A31_R
        def_bool MACH_SUN6I
        depends on RESET_CONTROLLER
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN7I_A20
        def_bool MACH_SUN7I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN8I_A23
        def_bool MACH_SUN8I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN8I_A33
        def_bool MACH_SUN8I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN8I_A83T
        def_bool MACH_SUN8I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN8I_A23_R
        def_bool MACH_SUN8I
        depends on RESET_CONTROLLER
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN8I_H3
+       def_bool MACH_SUN8I
+       select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_H3_R
        def_bool MACH_SUN8I
        select PINCTRL_SUNXI_COMMON
 
 config PINCTRL_SUN9I_A80
        def_bool MACH_SUN9I
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
 
 config PINCTRL_SUN9I_A80_R
        def_bool MACH_SUN9I
        depends on RESET_CONTROLLER
-       select PINCTRL_SUNXI_COMMON
+       select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_A64
+       bool
+       select PINCTRL_SUNXI
 
 endif
index ef82f22bb9ef594ef19e783f2cece3a9962a6de0..2d8b64e222e0a693ab3f9af6ebf8c96b5e1208cf 100644 (file)
@@ -1,5 +1,5 @@
 # Core
-obj-$(CONFIG_PINCTRL_SUNXI_COMMON)     += pinctrl-sunxi.o
+obj-y                                  += pinctrl-sunxi.o
 
 # SoC Drivers
 obj-$(CONFIG_PINCTRL_SUN4I_A10)                += pinctrl-sun4i-a10.o
@@ -12,7 +12,9 @@ obj-$(CONFIG_PINCTRL_SUN7I_A20)               += pinctrl-sun7i-a20.o
 obj-$(CONFIG_PINCTRL_SUN8I_A23)                += pinctrl-sun8i-a23.o
 obj-$(CONFIG_PINCTRL_SUN8I_A23_R)      += pinctrl-sun8i-a23-r.o
 obj-$(CONFIG_PINCTRL_SUN8I_A33)                += pinctrl-sun8i-a33.o
+obj-$(CONFIG_PINCTRL_SUN50I_A64)       += pinctrl-sun50i-a64.o
 obj-$(CONFIG_PINCTRL_SUN8I_A83T)       += pinctrl-sun8i-a83t.o
 obj-$(CONFIG_PINCTRL_SUN8I_H3)         += pinctrl-sun8i-h3.o
+obj-$(CONFIG_PINCTRL_SUN8I_H3_R)       += pinctrl-sun8i-h3-r.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)                += pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)      += pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a64.c
new file mode 100644 (file)
index 0000000..4f2a726
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+ * Allwinner A64 SoCs pinctrl driver.
+ *
+ * Copyright (C) 2016 - ARM Ltd.
+ * Author: Andre Przywara <andre.przywara@arm.com>
+ *
+ * Based on pinctrl-sun7i-a20.c, which is:
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin a64_pins[] = {
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart2"),         /* TX */
+                 SUNXI_FUNCTION(0x4, "jtag"),          /* MS0 */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),  /* EINT0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart2"),         /* RX */
+                 SUNXI_FUNCTION(0x4, "jtag"),          /* CK0 */
+                 SUNXI_FUNCTION(0x5, "sim"),           /* VCCEN */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),          /* EINT1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart2"),         /* RTS */
+                 SUNXI_FUNCTION(0x4, "jtag"),          /* DO0 */
+                 SUNXI_FUNCTION(0x5, "sim"),           /* VPPEN */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),          /* EINT2 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart2"),         /* CTS */
+                 SUNXI_FUNCTION(0x3, "i2s0"),          /* MCLK */
+                 SUNXI_FUNCTION(0x4, "jtag"),          /* DI0 */
+                 SUNXI_FUNCTION(0x5, "sim"),           /* VPPPP */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),          /* EINT3 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "aif2"),          /* SYNC */
+                 SUNXI_FUNCTION(0x3, "i2s0"),          /* SYNC */
+                 SUNXI_FUNCTION(0x5, "sim"),           /* CLK */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),          /* EINT4 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "aif2"),          /* BCLK */
+                 SUNXI_FUNCTION(0x3, "i2s0"),          /* BCLK */
+                 SUNXI_FUNCTION(0x5, "sim"),           /* DATA */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),          /* EINT5 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "aif2"),          /* DOUT */
+                 SUNXI_FUNCTION(0x3, "i2s0"),          /* DOUT */
+                 SUNXI_FUNCTION(0x5, "sim"),           /* RST */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),          /* EINT6 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "aif2"),          /* DIN */
+                 SUNXI_FUNCTION(0x3, "i2s0"),          /* DIN */
+                 SUNXI_FUNCTION(0x5, "sim"),           /* DET */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),          /* EINT7 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 8),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x4, "uart0"),         /* TX */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),          /* EINT8 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 9),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x4, "uart0"),         /* RX */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)),          /* EINT9 */
+       /* Hole */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NWE */
+                 SUNXI_FUNCTION(0x4, "spi0")),         /* MOSI */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NALE */
+                 SUNXI_FUNCTION(0x3, "mmc2"),          /* DS */
+                 SUNXI_FUNCTION(0x4, "spi0")),         /* MISO */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NCLE */
+                 SUNXI_FUNCTION(0x4, "spi0")),         /* SCK */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NCE1 */
+                 SUNXI_FUNCTION(0x4, "spi0")),         /* CS */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0")),        /* NCE0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NRE# */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* CLK */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NRB0 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* CMD */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0")),        /* NRB1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQ0 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* D0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQ1 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* D1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQ2 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* D2 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQ3 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* D3 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQ4 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* D4 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQ5 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* D5 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQ6 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* D6 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQ7 */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* D7 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "nand0"),         /* NDQS */
+                 SUNXI_FUNCTION(0x3, "mmc2")),         /* RST */
+       /* Hole */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D2 */
+                 SUNXI_FUNCTION(0x3, "uart3"),         /* TX */
+                 SUNXI_FUNCTION(0x4, "spi1"),          /* CS */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* CLK */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D3 */
+                 SUNXI_FUNCTION(0x3, "uart3"),         /* RX */
+                 SUNXI_FUNCTION(0x4, "spi1"),          /* CLK */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* DE */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D4 */
+                 SUNXI_FUNCTION(0x3, "uart4"),         /* TX */
+                 SUNXI_FUNCTION(0x4, "spi1"),          /* MOSI */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* HSYNC */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D5 */
+                 SUNXI_FUNCTION(0x3, "uart4"),         /* RX */
+                 SUNXI_FUNCTION(0x4, "spi1"),          /* MISO */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* VSYNC */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D6 */
+                 SUNXI_FUNCTION(0x3, "uart4"),         /* RTS */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* D0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D7 */
+                 SUNXI_FUNCTION(0x3, "uart4"),         /* CTS */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* D1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D10 */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* D2 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D11 */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* D3 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D12 */
+                 SUNXI_FUNCTION(0x4, "emac"),          /* ERXD3 */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* D4 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D13 */
+                 SUNXI_FUNCTION(0x4, "emac"),          /* ERXD2 */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* D5 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D14 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ERXD1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D15 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ERXD0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D18 */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VP0 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ERXCK */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D19 */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VN0 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ERXCTL */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D20 */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VP1 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ENULL */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D21 */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VN1 */
+                 SUNXI_FUNCTION(0x4, "emac"),          /* ETXD3 */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* D6 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D22 */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VP2 */
+                 SUNXI_FUNCTION(0x4, "emac"),          /* ETXD2 */
+                 SUNXI_FUNCTION(0x5, "ccir")),         /* D7 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* D23 */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VN2 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ETXD1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* CLK */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VPC */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ETXD0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* DE */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VNC */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ETXCK */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* HSYNC */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VP3 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ETXCTL */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "lcd0"),          /* VSYNC */
+                 SUNXI_FUNCTION(0x3, "lvds0"),         /* VN3 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* ECLKIN */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "pwm"),           /* PWM0 */
+                 SUNXI_FUNCTION(0x4, "emac")),         /* EMDC */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 23),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x4, "emac")),         /* EMDIO */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 24),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out")),
+       /* Hole */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* PCK */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* CLK */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* CK */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* ERR */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* HSYNC */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* SYNC */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* VSYNC */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* DVLD */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* D0 */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* D0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* D1 */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* D1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* D2 */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* D2 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* D3 */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* D3 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* D4 */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* D4 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* D5 */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* D5 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* D6 */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* D6 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0"),          /* D7 */
+                 SUNXI_FUNCTION(0x4, "ts0")),          /* D7 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0")),         /* SCK */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "csi0")),         /* SDA */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "pll"),           /* LOCK_DBG */
+                 SUNXI_FUNCTION(0x3, "i2c2")),         /* SCK */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x3, "i2c2")),         /* SDA */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out")),
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out")),
+       /* Hole */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc0"),          /* D1 */
+                 SUNXI_FUNCTION(0x3, "jtag")),         /* MSI */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc0"),          /* D0 */
+                 SUNXI_FUNCTION(0x3, "jtag")),         /* DI1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc0"),          /* CLK */
+                 SUNXI_FUNCTION(0x3, "uart0")),        /* TX */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc0"),          /* CMD */
+                 SUNXI_FUNCTION(0x3, "jtag")),         /* DO1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc0"),          /* D3 */
+                 SUNXI_FUNCTION(0x4, "uart0")),        /* RX */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc0"),          /* D2 */
+                 SUNXI_FUNCTION(0x3, "jtag")),         /* CK1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out")),
+       /* Hole */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc1"),          /* CLK */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)),  /* EINT0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc1"),          /* CMD */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)),  /* EINT1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc1"),          /* D0 */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)),  /* EINT2 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc1"),          /* D1 */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)),  /* EINT3 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc1"),          /* D2 */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)),  /* EINT4 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mmc1"),          /* D3 */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)),  /* EINT5 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart1"),         /* TX */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)),  /* EINT6 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart1"),         /* RX */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)),  /* EINT7 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart1"),         /* RTS */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)),  /* EINT8 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart1"),         /* CTS */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 9)),  /* EINT9 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "aif3"),          /* SYNC */
+                 SUNXI_FUNCTION(0x3, "i2s1"),          /* SYNC */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 10)), /* EINT10 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "aif3"),          /* BCLK */
+                 SUNXI_FUNCTION(0x3, "i2s1"),          /* BCLK */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 11)), /* EINT11 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "aif3"),          /* DOUT */
+                 SUNXI_FUNCTION(0x3, "i2s1"),          /* DOUT */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 12)), /* EINT12 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "aif3"),          /* DIN */
+                 SUNXI_FUNCTION(0x3, "i2s1"),          /* DIN */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 13)), /* EINT13 */
+       /* Hole */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "i2c0"),          /* SCK */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 0)),  /* EINT0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "i2c0"),          /* SDA */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 1)),  /* EINT1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "i2c1"),          /* SCK */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 2)),  /* EINT2 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "i2c1"),          /* SDA */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 3)),  /* EINT3 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart3"),         /* TX */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 4)),  /* EINT4 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart3"),         /* RX */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 5)),  /* EINT5 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart3"),         /* RTS */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 6)),  /* EINT6 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "uart3"),         /* CTS */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 7)),  /* EINT7 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "spdif"),         /* OUT */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 8)),  /* EINT8 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 9)),  /* EINT9 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mic"),           /* CLK */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 10)), /* EINT10 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "mic"),           /* DATA */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 2, 11)), /* EINT11 */
+};
+
+static const struct sunxi_pinctrl_desc a64_pinctrl_data = {
+       .pins = a64_pins,
+       .npins = ARRAY_SIZE(a64_pins),
+       .irq_banks = 3,
+};
+
+static int a64_pinctrl_probe(struct platform_device *pdev)
+{
+       return sunxi_pinctrl_init(pdev,
+                                 &a64_pinctrl_data);
+}
+
+static const struct of_device_id a64_pinctrl_match[] = {
+       { .compatible = "allwinner,sun50i-a64-pinctrl", },
+       {}
+};
+
+static struct platform_driver a64_pinctrl_driver = {
+       .probe  = a64_pinctrl_probe,
+       .driver = {
+               .name           = "sun50i-a64-pinctrl",
+               .of_match_table = a64_pinctrl_match,
+       },
+};
+builtin_platform_driver(a64_pinctrl_driver);
index cf1ce0c02600e6e051f9726f693e3a848eaa379d..435ad30f45dbf7a46ac8ff299efe66f60b4e405e 100644 (file)
@@ -343,26 +343,22 @@ static const struct sunxi_desc_pin sun7i_a20_pins[] = {
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "nand0"),         /* NCE4 */
-                 SUNXI_FUNCTION(0x3, "spi2"),          /* CS0 */
-                 SUNXI_FUNCTION_IRQ(0x6, 12)),         /* EINT12 */
+                 SUNXI_FUNCTION(0x3, "spi2")),         /* CS0 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 20),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "nand0"),         /* NCE5 */
-                 SUNXI_FUNCTION(0x3, "spi2"),          /* CLK */
-                 SUNXI_FUNCTION_IRQ(0x6, 13)),         /* EINT13 */
+                 SUNXI_FUNCTION(0x3, "spi2")),         /* CLK */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 21),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "nand0"),         /* NCE6 */
-                 SUNXI_FUNCTION(0x3, "spi2"),          /* MOSI */
-                 SUNXI_FUNCTION_IRQ(0x6, 14)),         /* EINT14 */
+                 SUNXI_FUNCTION(0x3, "spi2")),         /* MOSI */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 22),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "nand0"),         /* NCE7 */
-                 SUNXI_FUNCTION(0x3, "spi2"),          /* MISO */
-                 SUNXI_FUNCTION_IRQ(0x6, 15)),         /* EINT15 */
+                 SUNXI_FUNCTION(0x3, "spi2")),         /* MISO */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 23),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
@@ -960,65 +956,65 @@ static const struct sunxi_desc_pin sun7i_a20_pins[] = {
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi0"),          /* CS0 */
                  SUNXI_FUNCTION(0x3, "uart5"),         /* TX */
-                 SUNXI_FUNCTION_IRQ(0x5, 22)),         /* EINT22 */
+                 SUNXI_FUNCTION_IRQ(0x6, 22)),         /* EINT22 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 11),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi0"),          /* CLK */
                  SUNXI_FUNCTION(0x3, "uart5"),         /* RX */
-                 SUNXI_FUNCTION_IRQ(0x5, 23)),         /* EINT23 */
+                 SUNXI_FUNCTION_IRQ(0x6, 23)),         /* EINT23 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 12),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi0"),          /* MOSI */
                  SUNXI_FUNCTION(0x3, "uart6"),         /* TX */
                  SUNXI_FUNCTION(0x4, "clk_out_a"),     /* CLK_OUT_A */
-                 SUNXI_FUNCTION_IRQ(0x5, 24)),         /* EINT24 */
+                 SUNXI_FUNCTION_IRQ(0x6, 24)),         /* EINT24 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 13),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi0"),          /* MISO */
                  SUNXI_FUNCTION(0x3, "uart6"),         /* RX */
                  SUNXI_FUNCTION(0x4, "clk_out_b"),     /* CLK_OUT_B */
-                 SUNXI_FUNCTION_IRQ(0x5, 25)),         /* EINT25 */
+                 SUNXI_FUNCTION_IRQ(0x6, 25)),         /* EINT25 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 14),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi0"),          /* CS1 */
                  SUNXI_FUNCTION(0x3, "ps2"),           /* SCK1 */
                  SUNXI_FUNCTION(0x4, "timer4"),        /* TCLKIN0 */
-                 SUNXI_FUNCTION_IRQ(0x5, 26)),         /* EINT26 */
+                 SUNXI_FUNCTION_IRQ(0x6, 26)),         /* EINT26 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 15),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi1"),          /* CS1 */
                  SUNXI_FUNCTION(0x3, "ps2"),           /* SDA1 */
                  SUNXI_FUNCTION(0x4, "timer5"),        /* TCLKIN1 */
-                 SUNXI_FUNCTION_IRQ(0x5, 27)),         /* EINT27 */
+                 SUNXI_FUNCTION_IRQ(0x6, 27)),         /* EINT27 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 16),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi1"),          /* CS0 */
                  SUNXI_FUNCTION(0x3, "uart2"),         /* RTS */
-                 SUNXI_FUNCTION_IRQ(0x5, 28)),         /* EINT28 */
+                 SUNXI_FUNCTION_IRQ(0x6, 28)),         /* EINT28 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 17),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi1"),          /* CLK */
                  SUNXI_FUNCTION(0x3, "uart2"),         /* CTS */
-                 SUNXI_FUNCTION_IRQ(0x5, 29)),         /* EINT29 */
+                 SUNXI_FUNCTION_IRQ(0x6, 29)),         /* EINT29 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 18),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi1"),          /* MOSI */
                  SUNXI_FUNCTION(0x3, "uart2"),         /* TX */
-                 SUNXI_FUNCTION_IRQ(0x5, 30)),         /* EINT30 */
+                 SUNXI_FUNCTION_IRQ(0x6, 30)),         /* EINT30 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 19),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi1"),          /* MISO */
                  SUNXI_FUNCTION(0x3, "uart2"),         /* RX */
-                 SUNXI_FUNCTION_IRQ(0x5, 31)),         /* EINT31 */
+                 SUNXI_FUNCTION_IRQ(0x6, 31)),         /* EINT31 */
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 20),
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c
new file mode 100644 (file)
index 0000000..686ec21
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Allwinner H3 SoCs pinctrl driver.
+ *
+ * Copyright (C) 2016 Krzysztof Adamski <k@japko.eu>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_h3_r_pins[] = {
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_twi"),         /* SCK */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)),  /* PL_EINT0 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_twi"),         /* SDA */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)),  /* PL_EINT1 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_uart"),        /* TX */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)),  /* PL_EINT2 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_uart"),        /* RX */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)),  /* PL_EINT3 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 4),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_jtag"),        /* MS */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)),  /* PL_EINT4 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_jtag"),        /* CK */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)),  /* PL_EINT5 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_jtag"),        /* DO */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)),  /* PL_EINT6 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_jtag"),        /* DI */
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)),  /* PL_EINT7 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)),  /* PL_EINT8 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 9),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)),  /* PL_EINT9 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 10),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_pwm"),
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PL_EINT10 */
+       SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 11),
+                 SUNXI_FUNCTION(0x0, "gpio_in"),
+                 SUNXI_FUNCTION(0x1, "gpio_out"),
+                 SUNXI_FUNCTION(0x2, "s_cir_rx"),
+                 SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PL_EINT11 */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_h3_r_pinctrl_data = {
+       .pins = sun8i_h3_r_pins,
+       .npins = ARRAY_SIZE(sun8i_h3_r_pins),
+       .irq_banks = 1,
+       .pin_base = PL_BASE,
+       .irq_read_needs_mux = true
+};
+
+static int sun8i_h3_r_pinctrl_probe(struct platform_device *pdev)
+{
+       return sunxi_pinctrl_init(pdev,
+                                 &sun8i_h3_r_pinctrl_data);
+}
+
+static const struct of_device_id sun8i_h3_r_pinctrl_match[] = {
+       { .compatible = "allwinner,sun8i-h3-r-pinctrl", },
+       {}
+};
+
+static struct platform_driver sun8i_h3_r_pinctrl_driver = {
+       .probe  = sun8i_h3_r_pinctrl_probe,
+       .driver = {
+               .name           = "sun8i-h3-r-pinctrl",
+               .of_match_table = sun8i_h3_r_pinctrl_match,
+       },
+};
+builtin_platform_driver(sun8i_h3_r_pinctrl_driver);
index 42547ffa20a8d3080609a488cf05f3bc5f12bcbf..92a873f736975c2d96cefc8bb135b40b79f22d37 100644 (file)
@@ -9,7 +9,7 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -164,7 +164,6 @@ static const struct of_device_id sun9i_a80_r_pinctrl_match[] = {
        { .compatible = "allwinner,sun9i-a80-r-pinctrl", },
        {}
 };
-MODULE_DEVICE_TABLE(of, sun9i_a80_r_pinctrl_match);
 
 static struct platform_driver sun9i_a80_r_pinctrl_driver = {
        .probe  = sun9i_a80_r_pinctrl_probe,
@@ -174,8 +173,4 @@ static struct platform_driver sun9i_a80_r_pinctrl_driver = {
                .of_match_table = sun9i_a80_r_pinctrl_match,
        },
 };
-module_platform_driver(sun9i_a80_r_pinctrl_driver);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
-MODULE_DESCRIPTION("Allwinner A80 R_PIO pinctrl driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(sun9i_a80_r_pinctrl_driver);
index 7a2465f5e71e67c7e06f78dac19f850e2c01ba1f..3a2f5619f87c8d524ba6f1d74db6f290681e5c82 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/gpio/driver.h>
 #include <linux/irqdomain.h>
 #include <linux/irqchip/chained_irq.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
@@ -459,15 +459,16 @@ static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
        u8 index = sunxi_data_offset(offset);
        u32 set_mux = pctl->desc->irq_read_needs_mux &&
                        test_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags);
+       u32 pin = offset + chip->base;
        u32 val;
 
        if (set_mux)
-               sunxi_pmx_set(pctl->pctl_dev, offset, SUN4I_FUNC_INPUT);
+               sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT);
 
        val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
 
        if (set_mux)
-               sunxi_pmx_set(pctl->pctl_dev, offset, SUN4I_FUNC_IRQ);
+               sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_IRQ);
 
        return !!val;
 }
diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig
new file mode 100644 (file)
index 0000000..24e20cc
--- /dev/null
@@ -0,0 +1,30 @@
+config PINCTRL_TEGRA
+       bool
+       select PINMUX
+       select PINCONF
+
+config PINCTRL_TEGRA20
+       bool
+       select PINCTRL_TEGRA
+
+config PINCTRL_TEGRA30
+       bool
+       select PINCTRL_TEGRA
+
+config PINCTRL_TEGRA114
+       bool
+       select PINCTRL_TEGRA
+
+config PINCTRL_TEGRA124
+       bool
+       select PINCTRL_TEGRA
+
+config PINCTRL_TEGRA210
+       bool
+       select PINCTRL_TEGRA
+
+config PINCTRL_TEGRA_XUSB
+       def_bool y if ARCH_TEGRA
+       select GENERIC_PHY
+       select PINCONF
+       select PINMUX
diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile
new file mode 100644 (file)
index 0000000..a927379
--- /dev/null
@@ -0,0 +1,7 @@
+obj-y                                  += pinctrl-tegra.o
+obj-$(CONFIG_PINCTRL_TEGRA20)          += pinctrl-tegra20.o
+obj-$(CONFIG_PINCTRL_TEGRA30)          += pinctrl-tegra30.o
+obj-$(CONFIG_PINCTRL_TEGRA114)         += pinctrl-tegra114.o
+obj-$(CONFIG_PINCTRL_TEGRA124)         += pinctrl-tegra124.o
+obj-$(CONFIG_PINCTRL_TEGRA210)         += pinctrl-tegra210.o
+obj-$(CONFIG_PINCTRL_TEGRA_XUSB)       += pinctrl-tegra-xusb.o
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c
new file mode 100644 (file)
index 0000000..2f06029
--- /dev/null
@@ -0,0 +1,985 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+
+#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
+#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
+
+struct tegra_xusb_padctl_function {
+       const char *name;
+       const char * const *groups;
+       unsigned int num_groups;
+};
+
+struct tegra_xusb_padctl_soc {
+       const struct pinctrl_pin_desc *pins;
+       unsigned int num_pins;
+
+       const struct tegra_xusb_padctl_function *functions;
+       unsigned int num_functions;
+
+       const struct tegra_xusb_padctl_lane *lanes;
+       unsigned int num_lanes;
+};
+
+struct tegra_xusb_padctl_lane {
+       const char *name;
+
+       unsigned int offset;
+       unsigned int shift;
+       unsigned int mask;
+       unsigned int iddq;
+
+       const unsigned int *funcs;
+       unsigned int num_funcs;
+};
+
+struct tegra_xusb_padctl {
+       struct device *dev;
+       void __iomem *regs;
+       struct mutex lock;
+       struct reset_control *rst;
+
+       const struct tegra_xusb_padctl_soc *soc;
+       struct pinctrl_dev *pinctrl;
+       struct pinctrl_desc desc;
+
+       struct phy_provider *provider;
+       struct phy *phys[2];
+
+       unsigned int enable;
+};
+
+static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
+                                unsigned long offset)
+{
+       writel(value, padctl->regs + offset);
+}
+
+static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
+                              unsigned long offset)
+{
+       return readl(padctl->regs + offset);
+}
+
+static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+       return padctl->soc->num_pins;
+}
+
+static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
+                                                   unsigned int group)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+       return padctl->soc->pins[group].name;
+}
+
+static int tegra_xusb_padctl_get_group_pins(struct pinctrl_dev *pinctrl,
+                                           unsigned group,
+                                           const unsigned **pins,
+                                           unsigned *num_pins)
+{
+       /*
+        * For the tegra-xusb pad controller groups are synonomous
+        * with lanes/pins and there is always one lane/pin per group.
+        */
+       *pins = &pinctrl->desc->pins[group].number;
+       *num_pins = 1;
+
+       return 0;
+}
+
+enum tegra_xusb_padctl_param {
+       TEGRA_XUSB_PADCTL_IDDQ,
+};
+
+static const struct tegra_xusb_padctl_property {
+       const char *name;
+       enum tegra_xusb_padctl_param param;
+} properties[] = {
+       { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
+};
+
+#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
+#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16)
+#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff)
+
+static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl,
+                                          struct device_node *np,
+                                          struct pinctrl_map **maps,
+                                          unsigned int *reserved_maps,
+                                          unsigned int *num_maps)
+{
+       unsigned int i, reserve = 0, num_configs = 0;
+       unsigned long config, *configs = NULL;
+       const char *function, *group;
+       struct property *prop;
+       int err = 0;
+       u32 value;
+
+       err = of_property_read_string(np, "nvidia,function", &function);
+       if (err < 0) {
+               if (err != -EINVAL)
+                       return err;
+
+               function = NULL;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(properties); i++) {
+               err = of_property_read_u32(np, properties[i].name, &value);
+               if (err < 0) {
+                       if (err == -EINVAL)
+                               continue;
+
+                       goto out;
+               }
+
+               config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value);
+
+               err = pinctrl_utils_add_config(padctl->pinctrl, &configs,
+                                              &num_configs, config);
+               if (err < 0)
+                       goto out;
+       }
+
+       if (function)
+               reserve++;
+
+       if (num_configs)
+               reserve++;
+
+       err = of_property_count_strings(np, "nvidia,lanes");
+       if (err < 0)
+               goto out;
+
+       reserve *= err;
+
+       err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps,
+                                       num_maps, reserve);
+       if (err < 0)
+               goto out;
+
+       of_property_for_each_string(np, "nvidia,lanes", prop, group) {
+               if (function) {
+                       err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps,
+                                       reserved_maps, num_maps, group,
+                                       function);
+                       if (err < 0)
+                               goto out;
+               }
+
+               if (num_configs) {
+                       err = pinctrl_utils_add_map_configs(padctl->pinctrl,
+                                       maps, reserved_maps, num_maps, group,
+                                       configs, num_configs,
+                                       PIN_MAP_TYPE_CONFIGS_GROUP);
+                       if (err < 0)
+                               goto out;
+               }
+       }
+
+       err = 0;
+
+out:
+       kfree(configs);
+       return err;
+}
+
+static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
+                                           struct device_node *parent,
+                                           struct pinctrl_map **maps,
+                                           unsigned int *num_maps)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+       unsigned int reserved_maps = 0;
+       struct device_node *np;
+       int err;
+
+       *num_maps = 0;
+       *maps = NULL;
+
+       for_each_child_of_node(parent, np) {
+               err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
+                                                     &reserved_maps,
+                                                     num_maps);
+               if (err < 0) {
+                       of_node_put(np);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = {
+       .get_groups_count = tegra_xusb_padctl_get_groups_count,
+       .get_group_name = tegra_xusb_padctl_get_group_name,
+       .get_group_pins = tegra_xusb_padctl_get_group_pins,
+       .dt_node_to_map = tegra_xusb_padctl_dt_node_to_map,
+       .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+       return padctl->soc->num_functions;
+}
+
+static const char *
+tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl,
+                                   unsigned int function)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+       return padctl->soc->functions[function].name;
+}
+
+static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl,
+                                                unsigned int function,
+                                                const char * const **groups,
+                                                unsigned * const num_groups)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+
+       *num_groups = padctl->soc->functions[function].num_groups;
+       *groups = padctl->soc->functions[function].groups;
+
+       return 0;
+}
+
+static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl,
+                                       unsigned int function,
+                                       unsigned int group)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+       const struct tegra_xusb_padctl_lane *lane;
+       unsigned int i;
+       u32 value;
+
+       lane = &padctl->soc->lanes[group];
+
+       for (i = 0; i < lane->num_funcs; i++)
+               if (lane->funcs[i] == function)
+                       break;
+
+       if (i >= lane->num_funcs)
+               return -EINVAL;
+
+       value = padctl_readl(padctl, lane->offset);
+       value &= ~(lane->mask << lane->shift);
+       value |= i << lane->shift;
+       padctl_writel(padctl, value, lane->offset);
+
+       return 0;
+}
+
+static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = {
+       .get_functions_count = tegra_xusb_padctl_get_functions_count,
+       .get_function_name = tegra_xusb_padctl_get_function_name,
+       .get_function_groups = tegra_xusb_padctl_get_function_groups,
+       .set_mux = tegra_xusb_padctl_pinmux_set,
+};
+
+static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
+                                              unsigned int group,
+                                              unsigned long *config)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+       const struct tegra_xusb_padctl_lane *lane;
+       enum tegra_xusb_padctl_param param;
+       u32 value;
+
+       param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
+       lane = &padctl->soc->lanes[group];
+
+       switch (param) {
+       case TEGRA_XUSB_PADCTL_IDDQ:
+               /* lanes with iddq == 0 don't support this parameter */
+               if (lane->iddq == 0)
+                       return -EINVAL;
+
+               value = padctl_readl(padctl, lane->offset);
+
+               if (value & BIT(lane->iddq))
+                       value = 0;
+               else
+                       value = 1;
+
+               *config = TEGRA_XUSB_PADCTL_PACK(param, value);
+               break;
+
+       default:
+               dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
+                       param);
+               return -ENOTSUPP;
+       }
+
+       return 0;
+}
+
+static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
+                                              unsigned int group,
+                                              unsigned long *configs,
+                                              unsigned int num_configs)
+{
+       struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
+       const struct tegra_xusb_padctl_lane *lane;
+       enum tegra_xusb_padctl_param param;
+       unsigned long value;
+       unsigned int i;
+       u32 regval;
+
+       lane = &padctl->soc->lanes[group];
+
+       for (i = 0; i < num_configs; i++) {
+               param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]);
+               value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]);
+
+               switch (param) {
+               case TEGRA_XUSB_PADCTL_IDDQ:
+                       /* lanes with iddq == 0 don't support this parameter */
+                       if (lane->iddq == 0)
+                               return -EINVAL;
+
+                       regval = padctl_readl(padctl, lane->offset);
+
+                       if (value)
+                               regval &= ~BIT(lane->iddq);
+                       else
+                               regval |= BIT(lane->iddq);
+
+                       padctl_writel(padctl, regval, lane->offset);
+                       break;
+
+               default:
+                       dev_err(padctl->dev,
+                               "invalid configuration parameter: %04x\n",
+                               param);
+                       return -ENOTSUPP;
+               }
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static const char *strip_prefix(const char *s)
+{
+       const char *comma = strchr(s, ',');
+       if (!comma)
+               return s;
+
+       return comma + 1;
+}
+
+static void
+tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl,
+                                        struct seq_file *s,
+                                        unsigned int group)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(properties); i++) {
+               unsigned long config, value;
+               int err;
+
+               config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0);
+
+               err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group,
+                                                         &config);
+               if (err < 0)
+                       continue;
+
+               value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
+
+               seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name),
+                          value);
+       }
+}
+
+static void
+tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl,
+                                         struct seq_file *s,
+                                         unsigned long config)
+{
+       enum tegra_xusb_padctl_param param;
+       const char *name = "unknown";
+       unsigned long value;
+       unsigned int i;
+
+       param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config);
+       value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
+
+       for (i = 0; i < ARRAY_SIZE(properties); i++) {
+               if (properties[i].param == param) {
+                       name = properties[i].name;
+                       break;
+               }
+       }
+
+       seq_printf(s, "%s=%lu", strip_prefix(name), value);
+}
+#endif
+
+static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
+       .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get,
+       .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set,
+#ifdef CONFIG_DEBUG_FS
+       .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show,
+       .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show,
+#endif
+};
+
+static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
+{
+       u32 value;
+
+       mutex_lock(&padctl->lock);
+
+       if (padctl->enable++ > 0)
+               goto out;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       usleep_range(100, 200);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       usleep_range(100, 200);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+out:
+       mutex_unlock(&padctl->lock);
+       return 0;
+}
+
+static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
+{
+       u32 value;
+
+       mutex_lock(&padctl->lock);
+
+       if (WARN_ON(padctl->enable == 0))
+               goto out;
+
+       if (--padctl->enable > 0)
+               goto out;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       usleep_range(100, 200);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+       usleep_range(100, 200);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+       value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+       padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+out:
+       mutex_unlock(&padctl->lock);
+       return 0;
+}
+
+static int tegra_xusb_phy_init(struct phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+
+       return tegra_xusb_padctl_enable(padctl);
+}
+
+static int tegra_xusb_phy_exit(struct phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+
+       return tegra_xusb_padctl_disable(padctl);
+}
+
+static int pcie_phy_power_on(struct phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+       unsigned long timeout;
+       int err = -ETIMEDOUT;
+       u32 value;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+       value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
+                XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
+                XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+       value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+       timeout = jiffies + msecs_to_jiffies(50);
+
+       while (time_before(jiffies, timeout)) {
+               value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+               if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
+                       err = 0;
+                       break;
+               }
+
+               usleep_range(100, 200);
+       }
+
+       return err;
+}
+
+static int pcie_phy_power_off(struct phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+       u32 value;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+
+       return 0;
+}
+
+static const struct phy_ops pcie_phy_ops = {
+       .init = tegra_xusb_phy_init,
+       .exit = tegra_xusb_phy_exit,
+       .power_on = pcie_phy_power_on,
+       .power_off = pcie_phy_power_off,
+       .owner = THIS_MODULE,
+};
+
+static int sata_phy_power_on(struct phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+       unsigned long timeout;
+       int err = -ETIMEDOUT;
+       u32 value;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+       value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       timeout = jiffies + msecs_to_jiffies(50);
+
+       while (time_before(jiffies, timeout)) {
+               value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+               if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
+                       err = 0;
+                       break;
+               }
+
+               usleep_range(100, 200);
+       }
+
+       return err;
+}
+
+static int sata_phy_power_off(struct phy *phy)
+{
+       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+       u32 value;
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+       value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+       value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+       value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+       value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+       padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+
+       return 0;
+}
+
+static const struct phy_ops sata_phy_ops = {
+       .init = tegra_xusb_phy_init,
+       .exit = tegra_xusb_phy_exit,
+       .power_on = sata_phy_power_on,
+       .power_off = sata_phy_power_off,
+       .owner = THIS_MODULE,
+};
+
+static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
+                                          struct of_phandle_args *args)
+{
+       struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
+       unsigned int index = args->args[0];
+
+       if (args->args_count <= 0)
+               return ERR_PTR(-EINVAL);
+
+       if (index >= ARRAY_SIZE(padctl->phys))
+               return ERR_PTR(-EINVAL);
+
+       return padctl->phys[index];
+}
+
+#define PIN_OTG_0   0
+#define PIN_OTG_1   1
+#define PIN_OTG_2   2
+#define PIN_ULPI_0  3
+#define PIN_HSIC_0  4
+#define PIN_HSIC_1  5
+#define PIN_PCIE_0  6
+#define PIN_PCIE_1  7
+#define PIN_PCIE_2  8
+#define PIN_PCIE_3  9
+#define PIN_PCIE_4 10
+#define PIN_SATA_0 11
+
+static const struct pinctrl_pin_desc tegra124_pins[] = {
+       PINCTRL_PIN(PIN_OTG_0,  "otg-0"),
+       PINCTRL_PIN(PIN_OTG_1,  "otg-1"),
+       PINCTRL_PIN(PIN_OTG_2,  "otg-2"),
+       PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
+       PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
+       PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
+       PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
+       PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
+       PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
+       PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
+       PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
+       PINCTRL_PIN(PIN_SATA_0, "sata-0"),
+};
+
+static const char * const tegra124_snps_groups[] = {
+       "otg-0",
+       "otg-1",
+       "otg-2",
+       "ulpi-0",
+       "hsic-0",
+       "hsic-1",
+};
+
+static const char * const tegra124_xusb_groups[] = {
+       "otg-0",
+       "otg-1",
+       "otg-2",
+       "ulpi-0",
+       "hsic-0",
+       "hsic-1",
+};
+
+static const char * const tegra124_uart_groups[] = {
+       "otg-0",
+       "otg-1",
+       "otg-2",
+};
+
+static const char * const tegra124_pcie_groups[] = {
+       "pcie-0",
+       "pcie-1",
+       "pcie-2",
+       "pcie-3",
+       "pcie-4",
+};
+
+static const char * const tegra124_usb3_groups[] = {
+       "pcie-0",
+       "pcie-1",
+       "sata-0",
+};
+
+static const char * const tegra124_sata_groups[] = {
+       "sata-0",
+};
+
+static const char * const tegra124_rsvd_groups[] = {
+       "otg-0",
+       "otg-1",
+       "otg-2",
+       "pcie-0",
+       "pcie-1",
+       "pcie-2",
+       "pcie-3",
+       "pcie-4",
+       "sata-0",
+};
+
+#define TEGRA124_FUNCTION(_name)                                       \
+       {                                                               \
+               .name = #_name,                                         \
+               .num_groups = ARRAY_SIZE(tegra124_##_name##_groups),    \
+               .groups = tegra124_##_name##_groups,                    \
+       }
+
+static struct tegra_xusb_padctl_function tegra124_functions[] = {
+       TEGRA124_FUNCTION(snps),
+       TEGRA124_FUNCTION(xusb),
+       TEGRA124_FUNCTION(uart),
+       TEGRA124_FUNCTION(pcie),
+       TEGRA124_FUNCTION(usb3),
+       TEGRA124_FUNCTION(sata),
+       TEGRA124_FUNCTION(rsvd),
+};
+
+enum tegra124_function {
+       TEGRA124_FUNC_SNPS,
+       TEGRA124_FUNC_XUSB,
+       TEGRA124_FUNC_UART,
+       TEGRA124_FUNC_PCIE,
+       TEGRA124_FUNC_USB3,
+       TEGRA124_FUNC_SATA,
+       TEGRA124_FUNC_RSVD,
+};
+
+static const unsigned int tegra124_otg_functions[] = {
+       TEGRA124_FUNC_SNPS,
+       TEGRA124_FUNC_XUSB,
+       TEGRA124_FUNC_UART,
+       TEGRA124_FUNC_RSVD,
+};
+
+static const unsigned int tegra124_usb_functions[] = {
+       TEGRA124_FUNC_SNPS,
+       TEGRA124_FUNC_XUSB,
+};
+
+static const unsigned int tegra124_pci_functions[] = {
+       TEGRA124_FUNC_PCIE,
+       TEGRA124_FUNC_USB3,
+       TEGRA124_FUNC_SATA,
+       TEGRA124_FUNC_RSVD,
+};
+
+#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)    \
+       {                                                               \
+               .name = _name,                                          \
+               .offset = _offset,                                      \
+               .shift = _shift,                                        \
+               .mask = _mask,                                          \
+               .iddq = _iddq,                                          \
+               .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \
+               .funcs = tegra124_##_funcs##_functions,                 \
+       }
+
+static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
+       TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
+       TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
+       TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
+       TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
+       TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
+       TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
+       TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
+       TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
+       TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
+       TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
+       TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
+       TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
+};
+
+static const struct tegra_xusb_padctl_soc tegra124_soc = {
+       .num_pins = ARRAY_SIZE(tegra124_pins),
+       .pins = tegra124_pins,
+       .num_functions = ARRAY_SIZE(tegra124_functions),
+       .functions = tegra124_functions,
+       .num_lanes = ARRAY_SIZE(tegra124_lanes),
+       .lanes = tegra124_lanes,
+};
+
+static const struct of_device_id tegra_xusb_padctl_of_match[] = {
+       { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc },
+       { }
+};
+MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
+
+static int tegra_xusb_padctl_probe(struct platform_device *pdev)
+{
+       struct tegra_xusb_padctl *padctl;
+       const struct of_device_id *match;
+       struct resource *res;
+       struct phy *phy;
+       int err;
+
+       padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
+       if (!padctl)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, padctl);
+       mutex_init(&padctl->lock);
+       padctl->dev = &pdev->dev;
+
+       match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node);
+       padctl->soc = match->data;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       padctl->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(padctl->regs))
+               return PTR_ERR(padctl->regs);
+
+       padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
+       if (IS_ERR(padctl->rst))
+               return PTR_ERR(padctl->rst);
+
+       err = reset_control_deassert(padctl->rst);
+       if (err < 0)
+               return err;
+
+       memset(&padctl->desc, 0, sizeof(padctl->desc));
+       padctl->desc.name = dev_name(padctl->dev);
+       padctl->desc.pins = tegra124_pins;
+       padctl->desc.npins = ARRAY_SIZE(tegra124_pins);
+       padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
+       padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops;
+       padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops;
+       padctl->desc.owner = THIS_MODULE;
+
+       padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl);
+       if (IS_ERR(padctl->pinctrl)) {
+               dev_err(&pdev->dev, "failed to register pincontrol\n");
+               err = PTR_ERR(padctl->pinctrl);
+               goto reset;
+       }
+
+       phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops);
+       if (IS_ERR(phy)) {
+               err = PTR_ERR(phy);
+               goto unregister;
+       }
+
+       padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
+       phy_set_drvdata(phy, padctl);
+
+       phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops);
+       if (IS_ERR(phy)) {
+               err = PTR_ERR(phy);
+               goto unregister;
+       }
+
+       padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
+       phy_set_drvdata(phy, padctl);
+
+       padctl->provider = devm_of_phy_provider_register(&pdev->dev,
+                                                        tegra_xusb_padctl_xlate);
+       if (IS_ERR(padctl->provider)) {
+               err = PTR_ERR(padctl->provider);
+               dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
+               goto unregister;
+       }
+
+       return 0;
+
+unregister:
+       pinctrl_unregister(padctl->pinctrl);
+reset:
+       reset_control_assert(padctl->rst);
+       return err;
+}
+
+static int tegra_xusb_padctl_remove(struct platform_device *pdev)
+{
+       struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
+       int err;
+
+       pinctrl_unregister(padctl->pinctrl);
+
+       err = reset_control_assert(padctl->rst);
+       if (err < 0)
+               dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
+
+       return err;
+}
+
+static struct platform_driver tegra_xusb_padctl_driver = {
+       .driver = {
+               .name = "tegra-xusb-padctl",
+               .of_match_table = tegra_xusb_padctl_of_match,
+       },
+       .probe = tegra_xusb_padctl_probe,
+       .remove = tegra_xusb_padctl_remove,
+};
+module_platform_driver(tegra_xusb_padctl_driver);
+
+MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
new file mode 100644 (file)
index 0000000..4938882
--- /dev/null
@@ -0,0 +1,747 @@
+/*
+ * Driver for the NVIDIA Tegra pinmux
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Derived from code:
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2009-2011 ST-Ericsson AB
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/slab.h>
+
+#include "../core.h"
+#include "../pinctrl-utils.h"
+#include "pinctrl-tegra.h"
+
+struct tegra_pmx {
+       struct device *dev;
+       struct pinctrl_dev *pctl;
+
+       const struct tegra_pinctrl_soc_data *soc;
+       const char **group_pins;
+
+       int nbanks;
+       void __iomem **regs;
+};
+
+static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg)
+{
+       return readl(pmx->regs[bank] + reg);
+}
+
+static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
+{
+       writel(val, pmx->regs[bank] + reg);
+}
+
+static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       return pmx->soc->ngroups;
+}
+
+static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+                                               unsigned group)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       return pmx->soc->groups[group].name;
+}
+
+static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+                                       unsigned group,
+                                       const unsigned **pins,
+                                       unsigned *num_pins)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = pmx->soc->groups[group].pins;
+       *num_pins = pmx->soc->groups[group].npins;
+
+       return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+                                      struct seq_file *s,
+                                      unsigned offset)
+{
+       seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+#endif
+
+static const struct cfg_param {
+       const char *property;
+       enum tegra_pinconf_param param;
+} cfg_params[] = {
+       {"nvidia,pull",                 TEGRA_PINCONF_PARAM_PULL},
+       {"nvidia,tristate",             TEGRA_PINCONF_PARAM_TRISTATE},
+       {"nvidia,enable-input",         TEGRA_PINCONF_PARAM_ENABLE_INPUT},
+       {"nvidia,open-drain",           TEGRA_PINCONF_PARAM_OPEN_DRAIN},
+       {"nvidia,lock",                 TEGRA_PINCONF_PARAM_LOCK},
+       {"nvidia,io-reset",             TEGRA_PINCONF_PARAM_IORESET},
+       {"nvidia,rcv-sel",              TEGRA_PINCONF_PARAM_RCV_SEL},
+       {"nvidia,io-hv",                TEGRA_PINCONF_PARAM_RCV_SEL},
+       {"nvidia,high-speed-mode",      TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE},
+       {"nvidia,schmitt",              TEGRA_PINCONF_PARAM_SCHMITT},
+       {"nvidia,low-power-mode",       TEGRA_PINCONF_PARAM_LOW_POWER_MODE},
+       {"nvidia,pull-down-strength",   TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH},
+       {"nvidia,pull-up-strength",     TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH},
+       {"nvidia,slew-rate-falling",    TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING},
+       {"nvidia,slew-rate-rising",     TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
+       {"nvidia,drive-type",           TEGRA_PINCONF_PARAM_DRIVE_TYPE},
+};
+
+static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+                                          struct device_node *np,
+                                          struct pinctrl_map **map,
+                                          unsigned *reserved_maps,
+                                          unsigned *num_maps)
+{
+       struct device *dev = pctldev->dev;
+       int ret, i;
+       const char *function;
+       u32 val;
+       unsigned long config;
+       unsigned long *configs = NULL;
+       unsigned num_configs = 0;
+       unsigned reserve;
+       struct property *prop;
+       const char *group;
+
+       ret = of_property_read_string(np, "nvidia,function", &function);
+       if (ret < 0) {
+               /* EINVAL=missing, which is fine since it's optional */
+               if (ret != -EINVAL)
+                       dev_err(dev,
+                               "could not parse property nvidia,function\n");
+               function = NULL;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+               ret = of_property_read_u32(np, cfg_params[i].property, &val);
+               if (!ret) {
+                       config = TEGRA_PINCONF_PACK(cfg_params[i].param, val);
+                       ret = pinctrl_utils_add_config(pctldev, &configs,
+                                       &num_configs, config);
+                       if (ret < 0)
+                               goto exit;
+               /* EINVAL=missing, which is fine since it's optional */
+               } else if (ret != -EINVAL) {
+                       dev_err(dev, "could not parse property %s\n",
+                               cfg_params[i].property);
+               }
+       }
+
+       reserve = 0;
+       if (function != NULL)
+               reserve++;
+       if (num_configs)
+               reserve++;
+       ret = of_property_count_strings(np, "nvidia,pins");
+       if (ret < 0) {
+               dev_err(dev, "could not parse property nvidia,pins\n");
+               goto exit;
+       }
+       reserve *= ret;
+
+       ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
+                                       num_maps, reserve);
+       if (ret < 0)
+               goto exit;
+
+       of_property_for_each_string(np, "nvidia,pins", prop, group) {
+               if (function) {
+                       ret = pinctrl_utils_add_map_mux(pctldev, map,
+                                       reserved_maps, num_maps, group,
+                                       function);
+                       if (ret < 0)
+                               goto exit;
+               }
+
+               if (num_configs) {
+                       ret = pinctrl_utils_add_map_configs(pctldev, map,
+                                       reserved_maps, num_maps, group,
+                                       configs, num_configs,
+                                       PIN_MAP_TYPE_CONFIGS_GROUP);
+                       if (ret < 0)
+                               goto exit;
+               }
+       }
+
+       ret = 0;
+
+exit:
+       kfree(configs);
+       return ret;
+}
+
+static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                       struct device_node *np_config,
+                                       struct pinctrl_map **map,
+                                       unsigned *num_maps)
+{
+       unsigned reserved_maps;
+       struct device_node *np;
+       int ret;
+
+       reserved_maps = 0;
+       *map = NULL;
+       *num_maps = 0;
+
+       for_each_child_of_node(np_config, np) {
+               ret = tegra_pinctrl_dt_subnode_to_map(pctldev, np, map,
+                                                     &reserved_maps, num_maps);
+               if (ret < 0) {
+                       pinctrl_utils_dt_free_map(pctldev, *map,
+                               *num_maps);
+                       of_node_put(np);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct pinctrl_ops tegra_pinctrl_ops = {
+       .get_groups_count = tegra_pinctrl_get_groups_count,
+       .get_group_name = tegra_pinctrl_get_group_name,
+       .get_group_pins = tegra_pinctrl_get_group_pins,
+#ifdef CONFIG_DEBUG_FS
+       .pin_dbg_show = tegra_pinctrl_pin_dbg_show,
+#endif
+       .dt_node_to_map = tegra_pinctrl_dt_node_to_map,
+       .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       return pmx->soc->nfunctions;
+}
+
+static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+                                              unsigned function)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       return pmx->soc->functions[function].name;
+}
+
+static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
+                                        unsigned function,
+                                        const char * const **groups,
+                                        unsigned * const num_groups)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = pmx->soc->functions[function].groups;
+       *num_groups = pmx->soc->functions[function].ngroups;
+
+       return 0;
+}
+
+static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev,
+                                unsigned function,
+                                unsigned group)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+       const struct tegra_pingroup *g;
+       int i;
+       u32 val;
+
+       g = &pmx->soc->groups[group];
+
+       if (WARN_ON(g->mux_reg < 0))
+               return -EINVAL;
+
+       for (i = 0; i < ARRAY_SIZE(g->funcs); i++) {
+               if (g->funcs[i] == function)
+                       break;
+       }
+       if (WARN_ON(i == ARRAY_SIZE(g->funcs)))
+               return -EINVAL;
+
+       val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
+       val &= ~(0x3 << g->mux_bit);
+       val |= i << g->mux_bit;
+       pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
+
+       return 0;
+}
+
+static const struct pinmux_ops tegra_pinmux_ops = {
+       .get_functions_count = tegra_pinctrl_get_funcs_count,
+       .get_function_name = tegra_pinctrl_get_func_name,
+       .get_function_groups = tegra_pinctrl_get_func_groups,
+       .set_mux = tegra_pinctrl_set_mux,
+};
+
+static int tegra_pinconf_reg(struct tegra_pmx *pmx,
+                            const struct tegra_pingroup *g,
+                            enum tegra_pinconf_param param,
+                            bool report_err,
+                            s8 *bank, s16 *reg, s8 *bit, s8 *width)
+{
+       switch (param) {
+       case TEGRA_PINCONF_PARAM_PULL:
+               *bank = g->pupd_bank;
+               *reg = g->pupd_reg;
+               *bit = g->pupd_bit;
+               *width = 2;
+               break;
+       case TEGRA_PINCONF_PARAM_TRISTATE:
+               *bank = g->tri_bank;
+               *reg = g->tri_reg;
+               *bit = g->tri_bit;
+               *width = 1;
+               break;
+       case TEGRA_PINCONF_PARAM_ENABLE_INPUT:
+               *bank = g->mux_bank;
+               *reg = g->mux_reg;
+               *bit = g->einput_bit;
+               *width = 1;
+               break;
+       case TEGRA_PINCONF_PARAM_OPEN_DRAIN:
+               *bank = g->mux_bank;
+               *reg = g->mux_reg;
+               *bit = g->odrain_bit;
+               *width = 1;
+               break;
+       case TEGRA_PINCONF_PARAM_LOCK:
+               *bank = g->mux_bank;
+               *reg = g->mux_reg;
+               *bit = g->lock_bit;
+               *width = 1;
+               break;
+       case TEGRA_PINCONF_PARAM_IORESET:
+               *bank = g->mux_bank;
+               *reg = g->mux_reg;
+               *bit = g->ioreset_bit;
+               *width = 1;
+               break;
+       case TEGRA_PINCONF_PARAM_RCV_SEL:
+               *bank = g->mux_bank;
+               *reg = g->mux_reg;
+               *bit = g->rcv_sel_bit;
+               *width = 1;
+               break;
+       case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE:
+               if (pmx->soc->hsm_in_mux) {
+                       *bank = g->mux_bank;
+                       *reg = g->mux_reg;
+               } else {
+                       *bank = g->drv_bank;
+                       *reg = g->drv_reg;
+               }
+               *bit = g->hsm_bit;
+               *width = 1;
+               break;
+       case TEGRA_PINCONF_PARAM_SCHMITT:
+               if (pmx->soc->schmitt_in_mux) {
+                       *bank = g->mux_bank;
+                       *reg = g->mux_reg;
+               } else {
+                       *bank = g->drv_bank;
+                       *reg = g->drv_reg;
+               }
+               *bit = g->schmitt_bit;
+               *width = 1;
+               break;
+       case TEGRA_PINCONF_PARAM_LOW_POWER_MODE:
+               *bank = g->drv_bank;
+               *reg = g->drv_reg;
+               *bit = g->lpmd_bit;
+               *width = 2;
+               break;
+       case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
+               *bank = g->drv_bank;
+               *reg = g->drv_reg;
+               *bit = g->drvdn_bit;
+               *width = g->drvdn_width;
+               break;
+       case TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH:
+               *bank = g->drv_bank;
+               *reg = g->drv_reg;
+               *bit = g->drvup_bit;
+               *width = g->drvup_width;
+               break;
+       case TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING:
+               *bank = g->drv_bank;
+               *reg = g->drv_reg;
+               *bit = g->slwf_bit;
+               *width = g->slwf_width;
+               break;
+       case TEGRA_PINCONF_PARAM_SLEW_RATE_RISING:
+               *bank = g->drv_bank;
+               *reg = g->drv_reg;
+               *bit = g->slwr_bit;
+               *width = g->slwr_width;
+               break;
+       case TEGRA_PINCONF_PARAM_DRIVE_TYPE:
+               if (pmx->soc->drvtype_in_mux) {
+                       *bank = g->mux_bank;
+                       *reg = g->mux_reg;
+               } else {
+                       *bank = g->drv_bank;
+                       *reg = g->drv_reg;
+               }
+               *bit = g->drvtype_bit;
+               *width = 2;
+               break;
+       default:
+               dev_err(pmx->dev, "Invalid config param %04x\n", param);
+               return -ENOTSUPP;
+       }
+
+       if (*reg < 0 || *bit > 31) {
+               if (report_err) {
+                       const char *prop = "unknown";
+                       int i;
+
+                       for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+                               if (cfg_params[i].param == param) {
+                                       prop = cfg_params[i].property;
+                                       break;
+                               }
+                       }
+
+                       dev_err(pmx->dev,
+                               "Config param %04x (%s) not supported on group %s\n",
+                               param, prop, g->name);
+               }
+               return -ENOTSUPP;
+       }
+
+       return 0;
+}
+
+static int tegra_pinconf_get(struct pinctrl_dev *pctldev,
+                            unsigned pin, unsigned long *config)
+{
+       dev_err(pctldev->dev, "pin_config_get op not supported\n");
+       return -ENOTSUPP;
+}
+
+static int tegra_pinconf_set(struct pinctrl_dev *pctldev,
+                            unsigned pin, unsigned long *configs,
+                            unsigned num_configs)
+{
+       dev_err(pctldev->dev, "pin_config_set op not supported\n");
+       return -ENOTSUPP;
+}
+
+static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
+                                  unsigned group, unsigned long *config)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+       enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(*config);
+       u16 arg;
+       const struct tegra_pingroup *g;
+       int ret;
+       s8 bank, bit, width;
+       s16 reg;
+       u32 val, mask;
+
+       g = &pmx->soc->groups[group];
+
+       ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
+                               &width);
+       if (ret < 0)
+               return ret;
+
+       val = pmx_readl(pmx, bank, reg);
+       mask = (1 << width) - 1;
+       arg = (val >> bit) & mask;
+
+       *config = TEGRA_PINCONF_PACK(param, arg);
+
+       return 0;
+}
+
+static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
+                                  unsigned group, unsigned long *configs,
+                                  unsigned num_configs)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+       enum tegra_pinconf_param param;
+       u16 arg;
+       const struct tegra_pingroup *g;
+       int ret, i;
+       s8 bank, bit, width;
+       s16 reg;
+       u32 val, mask;
+
+       g = &pmx->soc->groups[group];
+
+       for (i = 0; i < num_configs; i++) {
+               param = TEGRA_PINCONF_UNPACK_PARAM(configs[i]);
+               arg = TEGRA_PINCONF_UNPACK_ARG(configs[i]);
+
+               ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
+                                       &width);
+               if (ret < 0)
+                       return ret;
+
+               val = pmx_readl(pmx, bank, reg);
+
+               /* LOCK can't be cleared */
+               if (param == TEGRA_PINCONF_PARAM_LOCK) {
+                       if ((val & BIT(bit)) && !arg) {
+                               dev_err(pctldev->dev, "LOCK bit cannot be cleared\n");
+                               return -EINVAL;
+                       }
+               }
+
+               /* Special-case Boolean values; allow any non-zero as true */
+               if (width == 1)
+                       arg = !!arg;
+
+               /* Range-check user-supplied value */
+               mask = (1 << width) - 1;
+               if (arg & ~mask) {
+                       dev_err(pctldev->dev,
+                               "config %lx: %x too big for %d bit register\n",
+                               configs[i], arg, width);
+                       return -EINVAL;
+               }
+
+               /* Update register */
+               val &= ~(mask << bit);
+               val |= arg << bit;
+               pmx_writel(pmx, val, bank, reg);
+       } /* for each config */
+
+       return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+                                  struct seq_file *s, unsigned offset)
+{
+}
+
+static const char *strip_prefix(const char *s)
+{
+       const char *comma = strchr(s, ',');
+       if (!comma)
+               return s;
+
+       return comma + 1;
+}
+
+static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+                                        struct seq_file *s, unsigned group)
+{
+       struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+       const struct tegra_pingroup *g;
+       int i, ret;
+       s8 bank, bit, width;
+       s16 reg;
+       u32 val;
+
+       g = &pmx->soc->groups[group];
+
+       for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+               ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false,
+                                       &bank, &reg, &bit, &width);
+               if (ret < 0)
+                       continue;
+
+               val = pmx_readl(pmx, bank, reg);
+               val >>= bit;
+               val &= (1 << width) - 1;
+
+               seq_printf(s, "\n\t%s=%u",
+                          strip_prefix(cfg_params[i].property), val);
+       }
+}
+
+static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
+                                         struct seq_file *s,
+                                         unsigned long config)
+{
+       enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config);
+       u16 arg = TEGRA_PINCONF_UNPACK_ARG(config);
+       const char *pname = "unknown";
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
+               if (cfg_params[i].param == param) {
+                       pname = cfg_params[i].property;
+                       break;
+               }
+       }
+
+       seq_printf(s, "%s=%d", strip_prefix(pname), arg);
+}
+#endif
+
+static const struct pinconf_ops tegra_pinconf_ops = {
+       .pin_config_get = tegra_pinconf_get,
+       .pin_config_set = tegra_pinconf_set,
+       .pin_config_group_get = tegra_pinconf_group_get,
+       .pin_config_group_set = tegra_pinconf_group_set,
+#ifdef CONFIG_DEBUG_FS
+       .pin_config_dbg_show = tegra_pinconf_dbg_show,
+       .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show,
+       .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show,
+#endif
+};
+
+static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = {
+       .name = "Tegra GPIOs",
+       .id = 0,
+       .base = 0,
+};
+
+static struct pinctrl_desc tegra_pinctrl_desc = {
+       .pctlops = &tegra_pinctrl_ops,
+       .pmxops = &tegra_pinmux_ops,
+       .confops = &tegra_pinconf_ops,
+       .owner = THIS_MODULE,
+};
+
+static bool gpio_node_has_range(void)
+{
+       struct device_node *np;
+       bool has_prop = false;
+
+       np = of_find_compatible_node(NULL, NULL, "nvidia,tegra30-gpio");
+       if (!np)
+               return has_prop;
+
+       has_prop = of_find_property(np, "gpio-ranges", NULL);
+
+       of_node_put(np);
+
+       return has_prop;
+}
+
+int tegra_pinctrl_probe(struct platform_device *pdev,
+                       const struct tegra_pinctrl_soc_data *soc_data)
+{
+       struct tegra_pmx *pmx;
+       struct resource *res;
+       int i;
+       const char **group_pins;
+       int fn, gn, gfn;
+
+       pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
+       if (!pmx) {
+               dev_err(&pdev->dev, "Can't alloc tegra_pmx\n");
+               return -ENOMEM;
+       }
+       pmx->dev = &pdev->dev;
+       pmx->soc = soc_data;
+
+       /*
+        * Each mux group will appear in 4 functions' list of groups.
+        * This over-allocates slightly, since not all groups are mux groups.
+        */
+       pmx->group_pins = devm_kzalloc(&pdev->dev,
+               soc_data->ngroups * 4 * sizeof(*pmx->group_pins),
+               GFP_KERNEL);
+       if (!pmx->group_pins)
+               return -ENOMEM;
+
+       group_pins = pmx->group_pins;
+       for (fn = 0; fn < soc_data->nfunctions; fn++) {
+               struct tegra_function *func = &soc_data->functions[fn];
+
+               func->groups = group_pins;
+
+               for (gn = 0; gn < soc_data->ngroups; gn++) {
+                       const struct tegra_pingroup *g = &soc_data->groups[gn];
+
+                       if (g->mux_reg == -1)
+                               continue;
+
+                       for (gfn = 0; gfn < 4; gfn++)
+                               if (g->funcs[gfn] == fn)
+                                       break;
+                       if (gfn == 4)
+                               continue;
+
+                       BUG_ON(group_pins - pmx->group_pins >=
+                               soc_data->ngroups * 4);
+                       *group_pins++ = g->name;
+                       func->ngroups++;
+               }
+       }
+
+       tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios;
+       tegra_pinctrl_desc.name = dev_name(&pdev->dev);
+       tegra_pinctrl_desc.pins = pmx->soc->pins;
+       tegra_pinctrl_desc.npins = pmx->soc->npins;
+
+       for (i = 0; ; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               if (!res)
+                       break;
+       }
+       pmx->nbanks = i;
+
+       pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs),
+                                GFP_KERNEL);
+       if (!pmx->regs) {
+               dev_err(&pdev->dev, "Can't alloc regs pointer\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < pmx->nbanks; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(pmx->regs[i]))
+                       return PTR_ERR(pmx->regs[i]);
+       }
+
+       pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx);
+       if (IS_ERR(pmx->pctl)) {
+               dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
+               return PTR_ERR(pmx->pctl);
+       }
+
+       if (!gpio_node_has_range())
+               pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range);
+
+       platform_set_drvdata(pdev, pmx);
+
+       dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n");
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
+
+int tegra_pinctrl_remove(struct platform_device *pdev)
+{
+       struct tegra_pmx *pmx = platform_get_drvdata(pdev);
+
+       pinctrl_unregister(pmx->pctl);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_pinctrl_remove);
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.h b/drivers/pinctrl/tegra/pinctrl-tegra.h
new file mode 100644 (file)
index 0000000..1615db7
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Driver for the NVIDIA Tegra pinmux
+ *
+ * Copyright (c) 2011, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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 __PINMUX_TEGRA_H__
+#define __PINMUX_TEGRA_H__
+
+enum tegra_pinconf_param {
+       /* argument: tegra_pinconf_pull */
+       TEGRA_PINCONF_PARAM_PULL,
+       /* argument: tegra_pinconf_tristate */
+       TEGRA_PINCONF_PARAM_TRISTATE,
+       /* argument: Boolean */
+       TEGRA_PINCONF_PARAM_ENABLE_INPUT,
+       /* argument: Boolean */
+       TEGRA_PINCONF_PARAM_OPEN_DRAIN,
+       /* argument: Boolean */
+       TEGRA_PINCONF_PARAM_LOCK,
+       /* argument: Boolean */
+       TEGRA_PINCONF_PARAM_IORESET,
+       /* argument: Boolean */
+       TEGRA_PINCONF_PARAM_RCV_SEL,
+       /* argument: Boolean */
+       TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE,
+       /* argument: Boolean */
+       TEGRA_PINCONF_PARAM_SCHMITT,
+       /* argument: Boolean */
+       TEGRA_PINCONF_PARAM_LOW_POWER_MODE,
+       /* argument: Integer, range is HW-dependant */
+       TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH,
+       /* argument: Integer, range is HW-dependant */
+       TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH,
+       /* argument: Integer, range is HW-dependant */
+       TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING,
+       /* argument: Integer, range is HW-dependant */
+       TEGRA_PINCONF_PARAM_SLEW_RATE_RISING,
+       /* argument: Integer, range is HW-dependant */
+       TEGRA_PINCONF_PARAM_DRIVE_TYPE,
+};
+
+enum tegra_pinconf_pull {
+       TEGRA_PINCONFIG_PULL_NONE,
+       TEGRA_PINCONFIG_PULL_DOWN,
+       TEGRA_PINCONFIG_PULL_UP,
+};
+
+enum tegra_pinconf_tristate {
+       TEGRA_PINCONFIG_DRIVEN,
+       TEGRA_PINCONFIG_TRISTATE,
+};
+
+#define TEGRA_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_))
+#define TEGRA_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
+#define TEGRA_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
+
+/**
+ * struct tegra_function - Tegra pinctrl mux function
+ * @name: The name of the function, exported to pinctrl core.
+ * @groups: An array of pin groups that may select this function.
+ * @ngroups: The number of entries in @groups.
+ */
+struct tegra_function {
+       const char *name;
+       const char **groups;
+       unsigned ngroups;
+};
+
+/**
+ * struct tegra_pingroup - Tegra pin group
+ * @name               The name of the pin group.
+ * @pins               An array of pin IDs included in this pin group.
+ * @npins              The number of entries in @pins.
+ * @funcs              The mux functions which can be muxed onto this group.
+ * @mux_reg:           Mux register offset.
+ *                     This register contains the mux, einput, odrain, lock,
+ *                     ioreset, rcv_sel parameters.
+ * @mux_bank:          Mux register bank.
+ * @mux_bit:           Mux register bit.
+ * @pupd_reg:          Pull-up/down register offset.
+ * @pupd_bank:         Pull-up/down register bank.
+ * @pupd_bit:          Pull-up/down register bit.
+ * @tri_reg:           Tri-state register offset.
+ * @tri_bank:          Tri-state register bank.
+ * @tri_bit:           Tri-state register bit.
+ * @einput_bit:                Enable-input register bit.
+ * @odrain_bit:                Open-drain register bit.
+ * @lock_bit:          Lock register bit.
+ * @ioreset_bit:       IO reset register bit.
+ * @rcv_sel_bit:       Receiver select bit.
+ * @drv_reg:           Drive fields register offset.
+ *                     This register contains hsm, schmitt, lpmd, drvdn,
+ *                     drvup, slwr, slwf, and drvtype parameters.
+ * @drv_bank:          Drive fields register bank.
+ * @hsm_bit:           High Speed Mode register bit.
+ * @schmitt_bit:       Scmitt register bit.
+ * @lpmd_bit:          Low Power Mode register bit.
+ * @drvdn_bit:         Drive Down register bit.
+ * @drvdn_width:       Drive Down field width.
+ * @drvup_bit:         Drive Up register bit.
+ * @drvup_width:       Drive Up field width.
+ * @slwr_bit:          Slew Rising register bit.
+ * @slwr_width:                Slew Rising field width.
+ * @slwf_bit:          Slew Falling register bit.
+ * @slwf_width:                Slew Falling field width.
+ * @drvtype_bit:       Drive type register bit.
+ *
+ * -1 in a *_reg field means that feature is unsupported for this group.
+ * *_bank and *_reg values are irrelevant when *_reg is -1.
+ * When *_reg is valid, *_bit may be -1 to indicate an unsupported feature.
+ *
+ * A representation of a group of pins (possibly just one pin) in the Tegra
+ * pin controller. Each group allows some parameter or parameters to be
+ * configured. The most common is mux function selection. Many others exist
+ * such as pull-up/down, tri-state, etc. Tegra's pin controller is complex;
+ * certain groups may only support configuring certain parameters, hence
+ * each parameter is optional.
+ */
+struct tegra_pingroup {
+       const char *name;
+       const unsigned *pins;
+       u8 npins;
+       u8 funcs[4];
+       s16 mux_reg;
+       s16 pupd_reg;
+       s16 tri_reg;
+       s16 drv_reg;
+       u32 mux_bank:2;
+       u32 pupd_bank:2;
+       u32 tri_bank:2;
+       u32 drv_bank:2;
+       s32 mux_bit:6;
+       s32 pupd_bit:6;
+       s32 tri_bit:6;
+       s32 einput_bit:6;
+       s32 odrain_bit:6;
+       s32 lock_bit:6;
+       s32 ioreset_bit:6;
+       s32 rcv_sel_bit:6;
+       s32 hsm_bit:6;
+       s32 schmitt_bit:6;
+       s32 lpmd_bit:6;
+       s32 drvdn_bit:6;
+       s32 drvup_bit:6;
+       s32 slwr_bit:6;
+       s32 slwf_bit:6;
+       s32 drvtype_bit:6;
+       s32 drvdn_width:6;
+       s32 drvup_width:6;
+       s32 slwr_width:6;
+       s32 slwf_width:6;
+};
+
+/**
+ * struct tegra_pinctrl_soc_data - Tegra pin controller driver configuration
+ * @ngpios:    The number of GPIO pins the pin controller HW affects.
+ * @pins:      An array describing all pins the pin controller affects.
+ *             All pins which are also GPIOs must be listed first within the
+ *             array, and be numbered identically to the GPIO controller's
+ *             numbering.
+ * @npins:     The numbmer of entries in @pins.
+ * @functions: An array describing all mux functions the SoC supports.
+ * @nfunctions:        The numbmer of entries in @functions.
+ * @groups:    An array describing all pin groups the pin SoC supports.
+ * @ngroups:   The numbmer of entries in @groups.
+ */
+struct tegra_pinctrl_soc_data {
+       unsigned ngpios;
+       const struct pinctrl_pin_desc *pins;
+       unsigned npins;
+       struct tegra_function *functions;
+       unsigned nfunctions;
+       const struct tegra_pingroup *groups;
+       unsigned ngroups;
+       bool hsm_in_mux;
+       bool schmitt_in_mux;
+       bool drvtype_in_mux;
+};
+
+int tegra_pinctrl_probe(struct platform_device *pdev,
+                       const struct tegra_pinctrl_soc_data *soc_data);
+int tegra_pinctrl_remove(struct platform_device *pdev);
+
+#endif
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra114.c b/drivers/pinctrl/tegra/pinctrl-tegra114.c
new file mode 100644 (file)
index 0000000..05e49d5
--- /dev/null
@@ -0,0 +1,1872 @@
+/*
+ * Pinctrl data for the NVIDIA Tegra114 pinmux
+ *
+ * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/*
+ * Most pins affected by the pinmux can also be GPIOs. Define these first.
+ * These must match how the GPIO driver names/numbers its pins.
+ */
+#define _GPIO(offset)                          (offset)
+
+#define TEGRA_PIN_CLK_32K_OUT_PA0              _GPIO(0)
+#define TEGRA_PIN_UART3_CTS_N_PA1              _GPIO(1)
+#define TEGRA_PIN_DAP2_FS_PA2                  _GPIO(2)
+#define TEGRA_PIN_DAP2_SCLK_PA3                        _GPIO(3)
+#define TEGRA_PIN_DAP2_DIN_PA4                 _GPIO(4)
+#define TEGRA_PIN_DAP2_DOUT_PA5                        _GPIO(5)
+#define TEGRA_PIN_SDMMC3_CLK_PA6               _GPIO(6)
+#define TEGRA_PIN_SDMMC3_CMD_PA7               _GPIO(7)
+#define TEGRA_PIN_GMI_A17_PB0                  _GPIO(8)
+#define TEGRA_PIN_GMI_A18_PB1                  _GPIO(9)
+#define TEGRA_PIN_SDMMC3_DAT3_PB4              _GPIO(12)
+#define TEGRA_PIN_SDMMC3_DAT2_PB5              _GPIO(13)
+#define TEGRA_PIN_SDMMC3_DAT1_PB6              _GPIO(14)
+#define TEGRA_PIN_SDMMC3_DAT0_PB7              _GPIO(15)
+#define TEGRA_PIN_UART3_RTS_N_PC0              _GPIO(16)
+#define TEGRA_PIN_UART2_TXD_PC2                        _GPIO(18)
+#define TEGRA_PIN_UART2_RXD_PC3                        _GPIO(19)
+#define TEGRA_PIN_GEN1_I2C_SCL_PC4             _GPIO(20)
+#define TEGRA_PIN_GEN1_I2C_SDA_PC5             _GPIO(21)
+#define TEGRA_PIN_GMI_WP_N_PC7                 _GPIO(23)
+#define TEGRA_PIN_GMI_AD0_PG0                  _GPIO(48)
+#define TEGRA_PIN_GMI_AD1_PG1                  _GPIO(49)
+#define TEGRA_PIN_GMI_AD2_PG2                  _GPIO(50)
+#define TEGRA_PIN_GMI_AD3_PG3                  _GPIO(51)
+#define TEGRA_PIN_GMI_AD4_PG4                  _GPIO(52)
+#define TEGRA_PIN_GMI_AD5_PG5                  _GPIO(53)
+#define TEGRA_PIN_GMI_AD6_PG6                  _GPIO(54)
+#define TEGRA_PIN_GMI_AD7_PG7                  _GPIO(55)
+#define TEGRA_PIN_GMI_AD8_PH0                  _GPIO(56)
+#define TEGRA_PIN_GMI_AD9_PH1                  _GPIO(57)
+#define TEGRA_PIN_GMI_AD10_PH2                 _GPIO(58)
+#define TEGRA_PIN_GMI_AD11_PH3                 _GPIO(59)
+#define TEGRA_PIN_GMI_AD12_PH4                 _GPIO(60)
+#define TEGRA_PIN_GMI_AD13_PH5                 _GPIO(61)
+#define TEGRA_PIN_GMI_AD14_PH6                 _GPIO(62)
+#define TEGRA_PIN_GMI_AD15_PH7                 _GPIO(63)
+#define TEGRA_PIN_GMI_WR_N_PI0                 _GPIO(64)
+#define TEGRA_PIN_GMI_OE_N_PI1                 _GPIO(65)
+#define TEGRA_PIN_GMI_CS6_N_PI3                        _GPIO(67)
+#define TEGRA_PIN_GMI_RST_N_PI4                        _GPIO(68)
+#define TEGRA_PIN_GMI_IORDY_PI5                        _GPIO(69)
+#define TEGRA_PIN_GMI_CS7_N_PI6                        _GPIO(70)
+#define TEGRA_PIN_GMI_WAIT_PI7                 _GPIO(71)
+#define TEGRA_PIN_GMI_CS0_N_PJ0                        _GPIO(72)
+#define TEGRA_PIN_GMI_CS1_N_PJ2                        _GPIO(74)
+#define TEGRA_PIN_GMI_DQS_P_PJ3                        _GPIO(75)
+#define TEGRA_PIN_UART2_CTS_N_PJ5              _GPIO(77)
+#define TEGRA_PIN_UART2_RTS_N_PJ6              _GPIO(78)
+#define TEGRA_PIN_GMI_A16_PJ7                  _GPIO(79)
+#define TEGRA_PIN_GMI_ADV_N_PK0                        _GPIO(80)
+#define TEGRA_PIN_GMI_CLK_PK1                  _GPIO(81)
+#define TEGRA_PIN_GMI_CS4_N_PK2                        _GPIO(82)
+#define TEGRA_PIN_GMI_CS2_N_PK3                        _GPIO(83)
+#define TEGRA_PIN_GMI_CS3_N_PK4                        _GPIO(84)
+#define TEGRA_PIN_SPDIF_OUT_PK5                        _GPIO(85)
+#define TEGRA_PIN_SPDIF_IN_PK6                 _GPIO(86)
+#define TEGRA_PIN_GMI_A19_PK7                  _GPIO(87)
+#define TEGRA_PIN_DAP1_FS_PN0                  _GPIO(104)
+#define TEGRA_PIN_DAP1_DIN_PN1                 _GPIO(105)
+#define TEGRA_PIN_DAP1_DOUT_PN2                        _GPIO(106)
+#define TEGRA_PIN_DAP1_SCLK_PN3                        _GPIO(107)
+#define TEGRA_PIN_USB_VBUS_EN0_PN4             _GPIO(108)
+#define TEGRA_PIN_USB_VBUS_EN1_PN5             _GPIO(109)
+#define TEGRA_PIN_HDMI_INT_PN7                 _GPIO(111)
+#define TEGRA_PIN_ULPI_DATA7_PO0               _GPIO(112)
+#define TEGRA_PIN_ULPI_DATA0_PO1               _GPIO(113)
+#define TEGRA_PIN_ULPI_DATA1_PO2               _GPIO(114)
+#define TEGRA_PIN_ULPI_DATA2_PO3               _GPIO(115)
+#define TEGRA_PIN_ULPI_DATA3_PO4               _GPIO(116)
+#define TEGRA_PIN_ULPI_DATA4_PO5               _GPIO(117)
+#define TEGRA_PIN_ULPI_DATA5_PO6               _GPIO(118)
+#define TEGRA_PIN_ULPI_DATA6_PO7               _GPIO(119)
+#define TEGRA_PIN_DAP3_FS_PP0                  _GPIO(120)
+#define TEGRA_PIN_DAP3_DIN_PP1                 _GPIO(121)
+#define TEGRA_PIN_DAP3_DOUT_PP2                        _GPIO(122)
+#define TEGRA_PIN_DAP3_SCLK_PP3                        _GPIO(123)
+#define TEGRA_PIN_DAP4_FS_PP4                  _GPIO(124)
+#define TEGRA_PIN_DAP4_DIN_PP5                 _GPIO(125)
+#define TEGRA_PIN_DAP4_DOUT_PP6                        _GPIO(126)
+#define TEGRA_PIN_DAP4_SCLK_PP7                        _GPIO(127)
+#define TEGRA_PIN_KB_COL0_PQ0                  _GPIO(128)
+#define TEGRA_PIN_KB_COL1_PQ1                  _GPIO(129)
+#define TEGRA_PIN_KB_COL2_PQ2                  _GPIO(130)
+#define TEGRA_PIN_KB_COL3_PQ3                  _GPIO(131)
+#define TEGRA_PIN_KB_COL4_PQ4                  _GPIO(132)
+#define TEGRA_PIN_KB_COL5_PQ5                  _GPIO(133)
+#define TEGRA_PIN_KB_COL6_PQ6                  _GPIO(134)
+#define TEGRA_PIN_KB_COL7_PQ7                  _GPIO(135)
+#define TEGRA_PIN_KB_ROW0_PR0                  _GPIO(136)
+#define TEGRA_PIN_KB_ROW1_PR1                  _GPIO(137)
+#define TEGRA_PIN_KB_ROW2_PR2                  _GPIO(138)
+#define TEGRA_PIN_KB_ROW3_PR3                  _GPIO(139)
+#define TEGRA_PIN_KB_ROW4_PR4                  _GPIO(140)
+#define TEGRA_PIN_KB_ROW5_PR5                  _GPIO(141)
+#define TEGRA_PIN_KB_ROW6_PR6                  _GPIO(142)
+#define TEGRA_PIN_KB_ROW7_PR7                  _GPIO(143)
+#define TEGRA_PIN_KB_ROW8_PS0                  _GPIO(144)
+#define TEGRA_PIN_KB_ROW9_PS1                  _GPIO(145)
+#define TEGRA_PIN_KB_ROW10_PS2                 _GPIO(146)
+#define TEGRA_PIN_GEN2_I2C_SCL_PT5             _GPIO(157)
+#define TEGRA_PIN_GEN2_I2C_SDA_PT6             _GPIO(158)
+#define TEGRA_PIN_SDMMC4_CMD_PT7               _GPIO(159)
+#define TEGRA_PIN_PU0                          _GPIO(160)
+#define TEGRA_PIN_PU1                          _GPIO(161)
+#define TEGRA_PIN_PU2                          _GPIO(162)
+#define TEGRA_PIN_PU3                          _GPIO(163)
+#define TEGRA_PIN_PU4                          _GPIO(164)
+#define TEGRA_PIN_PU5                          _GPIO(165)
+#define TEGRA_PIN_PU6                          _GPIO(166)
+#define TEGRA_PIN_PV0                          _GPIO(168)
+#define TEGRA_PIN_PV1                          _GPIO(169)
+#define TEGRA_PIN_SDMMC3_CD_N_PV2              _GPIO(170)
+#define TEGRA_PIN_SDMMC1_WP_N_PV3              _GPIO(171)
+#define TEGRA_PIN_DDC_SCL_PV4                  _GPIO(172)
+#define TEGRA_PIN_DDC_SDA_PV5                  _GPIO(173)
+#define TEGRA_PIN_GPIO_W2_AUD_PW2              _GPIO(178)
+#define TEGRA_PIN_GPIO_W3_AUD_PW3              _GPIO(179)
+#define TEGRA_PIN_CLK1_OUT_PW4                 _GPIO(180)
+#define TEGRA_PIN_CLK2_OUT_PW5                 _GPIO(181)
+#define TEGRA_PIN_UART3_TXD_PW6                        _GPIO(182)
+#define TEGRA_PIN_UART3_RXD_PW7                        _GPIO(183)
+#define TEGRA_PIN_DVFS_PWM_PX0                 _GPIO(184)
+#define TEGRA_PIN_GPIO_X1_AUD_PX1              _GPIO(185)
+#define TEGRA_PIN_DVFS_CLK_PX2                 _GPIO(186)
+#define TEGRA_PIN_GPIO_X3_AUD_PX3              _GPIO(187)
+#define TEGRA_PIN_GPIO_X4_AUD_PX4              _GPIO(188)
+#define TEGRA_PIN_GPIO_X5_AUD_PX5              _GPIO(189)
+#define TEGRA_PIN_GPIO_X6_AUD_PX6              _GPIO(190)
+#define TEGRA_PIN_GPIO_X7_AUD_PX7              _GPIO(191)
+#define TEGRA_PIN_ULPI_CLK_PY0                 _GPIO(192)
+#define TEGRA_PIN_ULPI_DIR_PY1                 _GPIO(193)
+#define TEGRA_PIN_ULPI_NXT_PY2                 _GPIO(194)
+#define TEGRA_PIN_ULPI_STP_PY3                 _GPIO(195)
+#define TEGRA_PIN_SDMMC1_DAT3_PY4              _GPIO(196)
+#define TEGRA_PIN_SDMMC1_DAT2_PY5              _GPIO(197)
+#define TEGRA_PIN_SDMMC1_DAT1_PY6              _GPIO(198)
+#define TEGRA_PIN_SDMMC1_DAT0_PY7              _GPIO(199)
+#define TEGRA_PIN_SDMMC1_CLK_PZ0               _GPIO(200)
+#define TEGRA_PIN_SDMMC1_CMD_PZ1               _GPIO(201)
+#define TEGRA_PIN_SYS_CLK_REQ_PZ5              _GPIO(205)
+#define TEGRA_PIN_PWR_I2C_SCL_PZ6              _GPIO(206)
+#define TEGRA_PIN_PWR_I2C_SDA_PZ7              _GPIO(207)
+#define TEGRA_PIN_SDMMC4_DAT0_PAA0             _GPIO(208)
+#define TEGRA_PIN_SDMMC4_DAT1_PAA1             _GPIO(209)
+#define TEGRA_PIN_SDMMC4_DAT2_PAA2             _GPIO(210)
+#define TEGRA_PIN_SDMMC4_DAT3_PAA3             _GPIO(211)
+#define TEGRA_PIN_SDMMC4_DAT4_PAA4             _GPIO(212)
+#define TEGRA_PIN_SDMMC4_DAT5_PAA5             _GPIO(213)
+#define TEGRA_PIN_SDMMC4_DAT6_PAA6             _GPIO(214)
+#define TEGRA_PIN_SDMMC4_DAT7_PAA7             _GPIO(215)
+#define TEGRA_PIN_PBB0                         _GPIO(216)
+#define TEGRA_PIN_CAM_I2C_SCL_PBB1             _GPIO(217)
+#define TEGRA_PIN_CAM_I2C_SDA_PBB2             _GPIO(218)
+#define TEGRA_PIN_PBB3                         _GPIO(219)
+#define TEGRA_PIN_PBB4                         _GPIO(220)
+#define TEGRA_PIN_PBB5                         _GPIO(221)
+#define TEGRA_PIN_PBB6                         _GPIO(222)
+#define TEGRA_PIN_PBB7                         _GPIO(223)
+#define TEGRA_PIN_CAM_MCLK_PCC0                        _GPIO(224)
+#define TEGRA_PIN_PCC1                         _GPIO(225)
+#define TEGRA_PIN_PCC2                         _GPIO(226)
+#define TEGRA_PIN_SDMMC4_CLK_PCC4              _GPIO(228)
+#define TEGRA_PIN_CLK2_REQ_PCC5                        _GPIO(229)
+#define TEGRA_PIN_CLK3_OUT_PEE0                        _GPIO(240)
+#define TEGRA_PIN_CLK3_REQ_PEE1                        _GPIO(241)
+#define TEGRA_PIN_CLK1_REQ_PEE2                        _GPIO(242)
+#define TEGRA_PIN_HDMI_CEC_PEE3                        _GPIO(243)
+#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4       _GPIO(244)
+#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5                _GPIO(245)
+
+/* All non-GPIO pins follow */
+#define NUM_GPIOS                              (TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 + 1)
+#define _PIN(offset)                           (NUM_GPIOS + (offset))
+
+/* Non-GPIO pins */
+#define TEGRA_PIN_CORE_PWR_REQ                 _PIN(0)
+#define TEGRA_PIN_CPU_PWR_REQ                  _PIN(1)
+#define TEGRA_PIN_PWR_INT_N                    _PIN(2)
+#define TEGRA_PIN_RESET_OUT_N                  _PIN(3)
+#define TEGRA_PIN_OWR                          _PIN(4)
+#define TEGRA_PIN_JTAG_RTCK                    _PIN(5)
+#define TEGRA_PIN_CLK_32K_IN                   _PIN(6)
+#define TEGRA_PIN_GMI_CLK_LB                   _PIN(7)
+
+static const struct pinctrl_pin_desc tegra114_pins[] = {
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_DQS_P_PJ3, "GMI_DQS_P PJ3"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"),
+       PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"),
+       PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"),
+       PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"),
+       PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"),
+       PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"),
+       PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"),
+       PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"),
+       PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"),
+       PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"),
+       PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"),
+       PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"),
+       PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"),
+       PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"),
+       PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"),
+       PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"),
+       PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"),
+       PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"),
+       PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"),
+       PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"),
+       PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"),
+       PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"),
+       PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"),
+       PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"),
+       PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"),
+       PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"),
+       PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"),
+       PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"),
+       PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"),
+       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
+       PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"),
+       PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"),
+};
+
+static const unsigned clk_32k_out_pa0_pins[] = {
+       TEGRA_PIN_CLK_32K_OUT_PA0,
+};
+
+static const unsigned uart3_cts_n_pa1_pins[] = {
+       TEGRA_PIN_UART3_CTS_N_PA1,
+};
+
+static const unsigned dap2_fs_pa2_pins[] = {
+       TEGRA_PIN_DAP2_FS_PA2,
+};
+
+static const unsigned dap2_sclk_pa3_pins[] = {
+       TEGRA_PIN_DAP2_SCLK_PA3,
+};
+
+static const unsigned dap2_din_pa4_pins[] = {
+       TEGRA_PIN_DAP2_DIN_PA4,
+};
+
+static const unsigned dap2_dout_pa5_pins[] = {
+       TEGRA_PIN_DAP2_DOUT_PA5,
+};
+
+static const unsigned sdmmc3_clk_pa6_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PA6,
+};
+
+static const unsigned sdmmc3_cmd_pa7_pins[] = {
+       TEGRA_PIN_SDMMC3_CMD_PA7,
+};
+
+static const unsigned gmi_a17_pb0_pins[] = {
+       TEGRA_PIN_GMI_A17_PB0,
+};
+
+static const unsigned gmi_a18_pb1_pins[] = {
+       TEGRA_PIN_GMI_A18_PB1,
+};
+
+static const unsigned sdmmc3_dat3_pb4_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT3_PB4,
+};
+
+static const unsigned sdmmc3_dat2_pb5_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT2_PB5,
+};
+
+static const unsigned sdmmc3_dat1_pb6_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT1_PB6,
+};
+
+static const unsigned sdmmc3_dat0_pb7_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT0_PB7,
+};
+
+static const unsigned uart3_rts_n_pc0_pins[] = {
+       TEGRA_PIN_UART3_RTS_N_PC0,
+};
+
+static const unsigned uart2_txd_pc2_pins[] = {
+       TEGRA_PIN_UART2_TXD_PC2,
+};
+
+static const unsigned uart2_rxd_pc3_pins[] = {
+       TEGRA_PIN_UART2_RXD_PC3,
+};
+
+static const unsigned gen1_i2c_scl_pc4_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PC4,
+};
+
+static const unsigned gen1_i2c_sda_pc5_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SDA_PC5,
+};
+
+static const unsigned gmi_wp_n_pc7_pins[] = {
+       TEGRA_PIN_GMI_WP_N_PC7,
+};
+
+static const unsigned gmi_ad0_pg0_pins[] = {
+       TEGRA_PIN_GMI_AD0_PG0,
+};
+
+static const unsigned gmi_ad1_pg1_pins[] = {
+       TEGRA_PIN_GMI_AD1_PG1,
+};
+
+static const unsigned gmi_ad2_pg2_pins[] = {
+       TEGRA_PIN_GMI_AD2_PG2,
+};
+
+static const unsigned gmi_ad3_pg3_pins[] = {
+       TEGRA_PIN_GMI_AD3_PG3,
+};
+
+static const unsigned gmi_ad4_pg4_pins[] = {
+       TEGRA_PIN_GMI_AD4_PG4,
+};
+
+static const unsigned gmi_ad5_pg5_pins[] = {
+       TEGRA_PIN_GMI_AD5_PG5,
+};
+
+static const unsigned gmi_ad6_pg6_pins[] = {
+       TEGRA_PIN_GMI_AD6_PG6,
+};
+
+static const unsigned gmi_ad7_pg7_pins[] = {
+       TEGRA_PIN_GMI_AD7_PG7,
+};
+
+static const unsigned gmi_ad8_ph0_pins[] = {
+       TEGRA_PIN_GMI_AD8_PH0,
+};
+
+static const unsigned gmi_ad9_ph1_pins[] = {
+       TEGRA_PIN_GMI_AD9_PH1,
+};
+
+static const unsigned gmi_ad10_ph2_pins[] = {
+       TEGRA_PIN_GMI_AD10_PH2,
+};
+
+static const unsigned gmi_ad11_ph3_pins[] = {
+       TEGRA_PIN_GMI_AD11_PH3,
+};
+
+static const unsigned gmi_ad12_ph4_pins[] = {
+       TEGRA_PIN_GMI_AD12_PH4,
+};
+
+static const unsigned gmi_ad13_ph5_pins[] = {
+       TEGRA_PIN_GMI_AD13_PH5,
+};
+
+static const unsigned gmi_ad14_ph6_pins[] = {
+       TEGRA_PIN_GMI_AD14_PH6,
+};
+
+static const unsigned gmi_ad15_ph7_pins[] = {
+       TEGRA_PIN_GMI_AD15_PH7,
+};
+
+static const unsigned gmi_wr_n_pi0_pins[] = {
+       TEGRA_PIN_GMI_WR_N_PI0,
+};
+
+static const unsigned gmi_oe_n_pi1_pins[] = {
+       TEGRA_PIN_GMI_OE_N_PI1,
+};
+
+static const unsigned gmi_cs6_n_pi3_pins[] = {
+       TEGRA_PIN_GMI_CS6_N_PI3,
+};
+
+static const unsigned gmi_rst_n_pi4_pins[] = {
+       TEGRA_PIN_GMI_RST_N_PI4,
+};
+
+static const unsigned gmi_iordy_pi5_pins[] = {
+       TEGRA_PIN_GMI_IORDY_PI5,
+};
+
+static const unsigned gmi_cs7_n_pi6_pins[] = {
+       TEGRA_PIN_GMI_CS7_N_PI6,
+};
+
+static const unsigned gmi_wait_pi7_pins[] = {
+       TEGRA_PIN_GMI_WAIT_PI7,
+};
+
+static const unsigned gmi_cs0_n_pj0_pins[] = {
+       TEGRA_PIN_GMI_CS0_N_PJ0,
+};
+
+static const unsigned gmi_cs1_n_pj2_pins[] = {
+       TEGRA_PIN_GMI_CS1_N_PJ2,
+};
+
+static const unsigned gmi_dqs_p_pj3_pins[] = {
+       TEGRA_PIN_GMI_DQS_P_PJ3,
+};
+
+static const unsigned uart2_cts_n_pj5_pins[] = {
+       TEGRA_PIN_UART2_CTS_N_PJ5,
+};
+
+static const unsigned uart2_rts_n_pj6_pins[] = {
+       TEGRA_PIN_UART2_RTS_N_PJ6,
+};
+
+static const unsigned gmi_a16_pj7_pins[] = {
+       TEGRA_PIN_GMI_A16_PJ7,
+};
+
+static const unsigned gmi_adv_n_pk0_pins[] = {
+       TEGRA_PIN_GMI_ADV_N_PK0,
+};
+
+static const unsigned gmi_clk_pk1_pins[] = {
+       TEGRA_PIN_GMI_CLK_PK1,
+};
+
+static const unsigned gmi_cs4_n_pk2_pins[] = {
+       TEGRA_PIN_GMI_CS4_N_PK2,
+};
+
+static const unsigned gmi_cs2_n_pk3_pins[] = {
+       TEGRA_PIN_GMI_CS2_N_PK3,
+};
+
+static const unsigned gmi_cs3_n_pk4_pins[] = {
+       TEGRA_PIN_GMI_CS3_N_PK4,
+};
+
+static const unsigned spdif_out_pk5_pins[] = {
+       TEGRA_PIN_SPDIF_OUT_PK5,
+};
+
+static const unsigned spdif_in_pk6_pins[] = {
+       TEGRA_PIN_SPDIF_IN_PK6,
+};
+
+static const unsigned gmi_a19_pk7_pins[] = {
+       TEGRA_PIN_GMI_A19_PK7,
+};
+
+static const unsigned dap1_fs_pn0_pins[] = {
+       TEGRA_PIN_DAP1_FS_PN0,
+};
+
+static const unsigned dap1_din_pn1_pins[] = {
+       TEGRA_PIN_DAP1_DIN_PN1,
+};
+
+static const unsigned dap1_dout_pn2_pins[] = {
+       TEGRA_PIN_DAP1_DOUT_PN2,
+};
+
+static const unsigned dap1_sclk_pn3_pins[] = {
+       TEGRA_PIN_DAP1_SCLK_PN3,
+};
+
+static const unsigned usb_vbus_en0_pn4_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN0_PN4,
+};
+
+static const unsigned usb_vbus_en1_pn5_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN1_PN5,
+};
+
+static const unsigned hdmi_int_pn7_pins[] = {
+       TEGRA_PIN_HDMI_INT_PN7,
+};
+
+static const unsigned ulpi_data7_po0_pins[] = {
+       TEGRA_PIN_ULPI_DATA7_PO0,
+};
+
+static const unsigned ulpi_data0_po1_pins[] = {
+       TEGRA_PIN_ULPI_DATA0_PO1,
+};
+
+static const unsigned ulpi_data1_po2_pins[] = {
+       TEGRA_PIN_ULPI_DATA1_PO2,
+};
+
+static const unsigned ulpi_data2_po3_pins[] = {
+       TEGRA_PIN_ULPI_DATA2_PO3,
+};
+
+static const unsigned ulpi_data3_po4_pins[] = {
+       TEGRA_PIN_ULPI_DATA3_PO4,
+};
+
+static const unsigned ulpi_data4_po5_pins[] = {
+       TEGRA_PIN_ULPI_DATA4_PO5,
+};
+
+static const unsigned ulpi_data5_po6_pins[] = {
+       TEGRA_PIN_ULPI_DATA5_PO6,
+};
+
+static const unsigned ulpi_data6_po7_pins[] = {
+       TEGRA_PIN_ULPI_DATA6_PO7,
+};
+
+static const unsigned dap3_fs_pp0_pins[] = {
+       TEGRA_PIN_DAP3_FS_PP0,
+};
+
+static const unsigned dap3_din_pp1_pins[] = {
+       TEGRA_PIN_DAP3_DIN_PP1,
+};
+
+static const unsigned dap3_dout_pp2_pins[] = {
+       TEGRA_PIN_DAP3_DOUT_PP2,
+};
+
+static const unsigned dap3_sclk_pp3_pins[] = {
+       TEGRA_PIN_DAP3_SCLK_PP3,
+};
+
+static const unsigned dap4_fs_pp4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PP4,
+};
+
+static const unsigned dap4_din_pp5_pins[] = {
+       TEGRA_PIN_DAP4_DIN_PP5,
+};
+
+static const unsigned dap4_dout_pp6_pins[] = {
+       TEGRA_PIN_DAP4_DOUT_PP6,
+};
+
+static const unsigned dap4_sclk_pp7_pins[] = {
+       TEGRA_PIN_DAP4_SCLK_PP7,
+};
+
+static const unsigned kb_col0_pq0_pins[] = {
+       TEGRA_PIN_KB_COL0_PQ0,
+};
+
+static const unsigned kb_col1_pq1_pins[] = {
+       TEGRA_PIN_KB_COL1_PQ1,
+};
+
+static const unsigned kb_col2_pq2_pins[] = {
+       TEGRA_PIN_KB_COL2_PQ2,
+};
+
+static const unsigned kb_col3_pq3_pins[] = {
+       TEGRA_PIN_KB_COL3_PQ3,
+};
+
+static const unsigned kb_col4_pq4_pins[] = {
+       TEGRA_PIN_KB_COL4_PQ4,
+};
+
+static const unsigned kb_col5_pq5_pins[] = {
+       TEGRA_PIN_KB_COL5_PQ5,
+};
+
+static const unsigned kb_col6_pq6_pins[] = {
+       TEGRA_PIN_KB_COL6_PQ6,
+};
+
+static const unsigned kb_col7_pq7_pins[] = {
+       TEGRA_PIN_KB_COL7_PQ7,
+};
+
+static const unsigned kb_row0_pr0_pins[] = {
+       TEGRA_PIN_KB_ROW0_PR0,
+};
+
+static const unsigned kb_row1_pr1_pins[] = {
+       TEGRA_PIN_KB_ROW1_PR1,
+};
+
+static const unsigned kb_row2_pr2_pins[] = {
+       TEGRA_PIN_KB_ROW2_PR2,
+};
+
+static const unsigned kb_row3_pr3_pins[] = {
+       TEGRA_PIN_KB_ROW3_PR3,
+};
+
+static const unsigned kb_row4_pr4_pins[] = {
+       TEGRA_PIN_KB_ROW4_PR4,
+};
+
+static const unsigned kb_row5_pr5_pins[] = {
+       TEGRA_PIN_KB_ROW5_PR5,
+};
+
+static const unsigned kb_row6_pr6_pins[] = {
+       TEGRA_PIN_KB_ROW6_PR6,
+};
+
+static const unsigned kb_row7_pr7_pins[] = {
+       TEGRA_PIN_KB_ROW7_PR7,
+};
+
+static const unsigned kb_row8_ps0_pins[] = {
+       TEGRA_PIN_KB_ROW8_PS0,
+};
+
+static const unsigned kb_row9_ps1_pins[] = {
+       TEGRA_PIN_KB_ROW9_PS1,
+};
+
+static const unsigned kb_row10_ps2_pins[] = {
+       TEGRA_PIN_KB_ROW10_PS2,
+};
+
+static const unsigned gen2_i2c_scl_pt5_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PT5,
+};
+
+static const unsigned gen2_i2c_sda_pt6_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SDA_PT6,
+};
+
+static const unsigned sdmmc4_cmd_pt7_pins[] = {
+       TEGRA_PIN_SDMMC4_CMD_PT7,
+};
+
+static const unsigned pu0_pins[] = {
+       TEGRA_PIN_PU0,
+};
+
+static const unsigned pu1_pins[] = {
+       TEGRA_PIN_PU1,
+};
+
+static const unsigned pu2_pins[] = {
+       TEGRA_PIN_PU2,
+};
+
+static const unsigned pu3_pins[] = {
+       TEGRA_PIN_PU3,
+};
+
+static const unsigned pu4_pins[] = {
+       TEGRA_PIN_PU4,
+};
+
+static const unsigned pu5_pins[] = {
+       TEGRA_PIN_PU5,
+};
+
+static const unsigned pu6_pins[] = {
+       TEGRA_PIN_PU6,
+};
+
+static const unsigned pv0_pins[] = {
+       TEGRA_PIN_PV0,
+};
+
+static const unsigned pv1_pins[] = {
+       TEGRA_PIN_PV1,
+};
+
+static const unsigned sdmmc3_cd_n_pv2_pins[] = {
+       TEGRA_PIN_SDMMC3_CD_N_PV2,
+};
+
+static const unsigned sdmmc1_wp_n_pv3_pins[] = {
+       TEGRA_PIN_SDMMC1_WP_N_PV3,
+};
+
+static const unsigned ddc_scl_pv4_pins[] = {
+       TEGRA_PIN_DDC_SCL_PV4,
+};
+
+static const unsigned ddc_sda_pv5_pins[] = {
+       TEGRA_PIN_DDC_SDA_PV5,
+};
+
+static const unsigned gpio_w2_aud_pw2_pins[] = {
+       TEGRA_PIN_GPIO_W2_AUD_PW2,
+};
+
+static const unsigned gpio_w3_aud_pw3_pins[] = {
+       TEGRA_PIN_GPIO_W3_AUD_PW3,
+};
+
+static const unsigned clk1_out_pw4_pins[] = {
+       TEGRA_PIN_CLK1_OUT_PW4,
+};
+
+static const unsigned clk2_out_pw5_pins[] = {
+       TEGRA_PIN_CLK2_OUT_PW5,
+};
+
+static const unsigned uart3_txd_pw6_pins[] = {
+       TEGRA_PIN_UART3_TXD_PW6,
+};
+
+static const unsigned uart3_rxd_pw7_pins[] = {
+       TEGRA_PIN_UART3_RXD_PW7,
+};
+
+static const unsigned dvfs_pwm_px0_pins[] = {
+       TEGRA_PIN_DVFS_PWM_PX0,
+};
+
+static const unsigned gpio_x1_aud_px1_pins[] = {
+       TEGRA_PIN_GPIO_X1_AUD_PX1,
+};
+
+static const unsigned dvfs_clk_px2_pins[] = {
+       TEGRA_PIN_DVFS_CLK_PX2,
+};
+
+static const unsigned gpio_x3_aud_px3_pins[] = {
+       TEGRA_PIN_GPIO_X3_AUD_PX3,
+};
+
+static const unsigned gpio_x4_aud_px4_pins[] = {
+       TEGRA_PIN_GPIO_X4_AUD_PX4,
+};
+
+static const unsigned gpio_x5_aud_px5_pins[] = {
+       TEGRA_PIN_GPIO_X5_AUD_PX5,
+};
+
+static const unsigned gpio_x6_aud_px6_pins[] = {
+       TEGRA_PIN_GPIO_X6_AUD_PX6,
+};
+
+static const unsigned gpio_x7_aud_px7_pins[] = {
+       TEGRA_PIN_GPIO_X7_AUD_PX7,
+};
+
+static const unsigned ulpi_clk_py0_pins[] = {
+       TEGRA_PIN_ULPI_CLK_PY0,
+};
+
+static const unsigned ulpi_dir_py1_pins[] = {
+       TEGRA_PIN_ULPI_DIR_PY1,
+};
+
+static const unsigned ulpi_nxt_py2_pins[] = {
+       TEGRA_PIN_ULPI_NXT_PY2,
+};
+
+static const unsigned ulpi_stp_py3_pins[] = {
+       TEGRA_PIN_ULPI_STP_PY3,
+};
+
+static const unsigned sdmmc1_dat3_py4_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT3_PY4,
+};
+
+static const unsigned sdmmc1_dat2_py5_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT2_PY5,
+};
+
+static const unsigned sdmmc1_dat1_py6_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT1_PY6,
+};
+
+static const unsigned sdmmc1_dat0_py7_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT0_PY7,
+};
+
+static const unsigned sdmmc1_clk_pz0_pins[] = {
+       TEGRA_PIN_SDMMC1_CLK_PZ0,
+};
+
+static const unsigned sdmmc1_cmd_pz1_pins[] = {
+       TEGRA_PIN_SDMMC1_CMD_PZ1,
+};
+
+static const unsigned sys_clk_req_pz5_pins[] = {
+       TEGRA_PIN_SYS_CLK_REQ_PZ5,
+};
+
+static const unsigned pwr_i2c_scl_pz6_pins[] = {
+       TEGRA_PIN_PWR_I2C_SCL_PZ6,
+};
+
+static const unsigned pwr_i2c_sda_pz7_pins[] = {
+       TEGRA_PIN_PWR_I2C_SDA_PZ7,
+};
+
+static const unsigned sdmmc4_dat0_paa0_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT0_PAA0,
+};
+
+static const unsigned sdmmc4_dat1_paa1_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT1_PAA1,
+};
+
+static const unsigned sdmmc4_dat2_paa2_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT2_PAA2,
+};
+
+static const unsigned sdmmc4_dat3_paa3_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT3_PAA3,
+};
+
+static const unsigned sdmmc4_dat4_paa4_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT4_PAA4,
+};
+
+static const unsigned sdmmc4_dat5_paa5_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT5_PAA5,
+};
+
+static const unsigned sdmmc4_dat6_paa6_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT6_PAA6,
+};
+
+static const unsigned sdmmc4_dat7_paa7_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT7_PAA7,
+};
+
+static const unsigned pbb0_pins[] = {
+       TEGRA_PIN_PBB0,
+};
+
+static const unsigned cam_i2c_scl_pbb1_pins[] = {
+       TEGRA_PIN_CAM_I2C_SCL_PBB1,
+};
+
+static const unsigned cam_i2c_sda_pbb2_pins[] = {
+       TEGRA_PIN_CAM_I2C_SDA_PBB2,
+};
+
+static const unsigned pbb3_pins[] = {
+       TEGRA_PIN_PBB3,
+};
+
+static const unsigned pbb4_pins[] = {
+       TEGRA_PIN_PBB4,
+};
+
+static const unsigned pbb5_pins[] = {
+       TEGRA_PIN_PBB5,
+};
+
+static const unsigned pbb6_pins[] = {
+       TEGRA_PIN_PBB6,
+};
+
+static const unsigned pbb7_pins[] = {
+       TEGRA_PIN_PBB7,
+};
+
+static const unsigned cam_mclk_pcc0_pins[] = {
+       TEGRA_PIN_CAM_MCLK_PCC0,
+};
+
+static const unsigned pcc1_pins[] = {
+       TEGRA_PIN_PCC1,
+};
+
+static const unsigned pcc2_pins[] = {
+       TEGRA_PIN_PCC2,
+};
+
+static const unsigned sdmmc4_clk_pcc4_pins[] = {
+       TEGRA_PIN_SDMMC4_CLK_PCC4,
+};
+
+static const unsigned clk2_req_pcc5_pins[] = {
+       TEGRA_PIN_CLK2_REQ_PCC5,
+};
+
+static const unsigned clk3_out_pee0_pins[] = {
+       TEGRA_PIN_CLK3_OUT_PEE0,
+};
+
+static const unsigned clk3_req_pee1_pins[] = {
+       TEGRA_PIN_CLK3_REQ_PEE1,
+};
+
+static const unsigned clk1_req_pee2_pins[] = {
+       TEGRA_PIN_CLK1_REQ_PEE2,
+};
+
+static const unsigned hdmi_cec_pee3_pins[] = {
+       TEGRA_PIN_HDMI_CEC_PEE3,
+};
+
+static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4,
+};
+
+static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5,
+};
+
+static const unsigned core_pwr_req_pins[] = {
+       TEGRA_PIN_CORE_PWR_REQ,
+};
+
+static const unsigned cpu_pwr_req_pins[] = {
+       TEGRA_PIN_CPU_PWR_REQ,
+};
+
+static const unsigned pwr_int_n_pins[] = {
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned reset_out_n_pins[] = {
+       TEGRA_PIN_RESET_OUT_N,
+};
+
+static const unsigned owr_pins[] = {
+       TEGRA_PIN_OWR,
+};
+
+static const unsigned jtag_rtck_pins[] = {
+       TEGRA_PIN_JTAG_RTCK,
+};
+
+static const unsigned clk_32k_in_pins[] = {
+       TEGRA_PIN_CLK_32K_IN,
+};
+
+static const unsigned gmi_clk_lb_pins[] = {
+       TEGRA_PIN_GMI_CLK_LB,
+};
+
+static const unsigned drive_ao1_pins[] = {
+       TEGRA_PIN_KB_ROW0_PR0,
+       TEGRA_PIN_KB_ROW1_PR1,
+       TEGRA_PIN_KB_ROW2_PR2,
+       TEGRA_PIN_KB_ROW3_PR3,
+       TEGRA_PIN_KB_ROW4_PR4,
+       TEGRA_PIN_KB_ROW5_PR5,
+       TEGRA_PIN_KB_ROW6_PR6,
+       TEGRA_PIN_KB_ROW7_PR7,
+       TEGRA_PIN_PWR_I2C_SCL_PZ6,
+       TEGRA_PIN_PWR_I2C_SDA_PZ7,
+};
+
+static const unsigned drive_ao2_pins[] = {
+       TEGRA_PIN_CLK_32K_OUT_PA0,
+       TEGRA_PIN_KB_COL0_PQ0,
+       TEGRA_PIN_KB_COL1_PQ1,
+       TEGRA_PIN_KB_COL2_PQ2,
+       TEGRA_PIN_KB_COL3_PQ3,
+       TEGRA_PIN_KB_COL4_PQ4,
+       TEGRA_PIN_KB_COL5_PQ5,
+       TEGRA_PIN_KB_COL6_PQ6,
+       TEGRA_PIN_KB_COL7_PQ7,
+       TEGRA_PIN_KB_ROW8_PS0,
+       TEGRA_PIN_KB_ROW9_PS1,
+       TEGRA_PIN_KB_ROW10_PS2,
+       TEGRA_PIN_SYS_CLK_REQ_PZ5,
+       TEGRA_PIN_CORE_PWR_REQ,
+       TEGRA_PIN_CPU_PWR_REQ,
+       TEGRA_PIN_RESET_OUT_N,
+};
+
+static const unsigned drive_at1_pins[] = {
+       TEGRA_PIN_GMI_AD8_PH0,
+       TEGRA_PIN_GMI_AD9_PH1,
+       TEGRA_PIN_GMI_AD10_PH2,
+       TEGRA_PIN_GMI_AD11_PH3,
+       TEGRA_PIN_GMI_AD12_PH4,
+       TEGRA_PIN_GMI_AD13_PH5,
+       TEGRA_PIN_GMI_AD14_PH6,
+       TEGRA_PIN_GMI_AD15_PH7,
+       TEGRA_PIN_GMI_IORDY_PI5,
+       TEGRA_PIN_GMI_CS7_N_PI6,
+};
+
+static const unsigned drive_at2_pins[] = {
+       TEGRA_PIN_GMI_AD0_PG0,
+       TEGRA_PIN_GMI_AD1_PG1,
+       TEGRA_PIN_GMI_AD2_PG2,
+       TEGRA_PIN_GMI_AD3_PG3,
+       TEGRA_PIN_GMI_AD4_PG4,
+       TEGRA_PIN_GMI_AD5_PG5,
+       TEGRA_PIN_GMI_AD6_PG6,
+       TEGRA_PIN_GMI_AD7_PG7,
+       TEGRA_PIN_GMI_WR_N_PI0,
+       TEGRA_PIN_GMI_OE_N_PI1,
+       TEGRA_PIN_GMI_CS6_N_PI3,
+       TEGRA_PIN_GMI_RST_N_PI4,
+       TEGRA_PIN_GMI_WAIT_PI7,
+       TEGRA_PIN_GMI_DQS_P_PJ3,
+       TEGRA_PIN_GMI_ADV_N_PK0,
+       TEGRA_PIN_GMI_CLK_PK1,
+       TEGRA_PIN_GMI_CS4_N_PK2,
+       TEGRA_PIN_GMI_CS2_N_PK3,
+       TEGRA_PIN_GMI_CS3_N_PK4,
+};
+
+static const unsigned drive_at3_pins[] = {
+       TEGRA_PIN_GMI_WP_N_PC7,
+       TEGRA_PIN_GMI_CS0_N_PJ0,
+};
+
+static const unsigned drive_at4_pins[] = {
+       TEGRA_PIN_GMI_A17_PB0,
+       TEGRA_PIN_GMI_A18_PB1,
+       TEGRA_PIN_GMI_CS1_N_PJ2,
+       TEGRA_PIN_GMI_A16_PJ7,
+       TEGRA_PIN_GMI_A19_PK7,
+};
+
+static const unsigned drive_at5_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PT5,
+       TEGRA_PIN_GEN2_I2C_SDA_PT6,
+};
+
+static const unsigned drive_cdev1_pins[] = {
+       TEGRA_PIN_CLK1_OUT_PW4,
+       TEGRA_PIN_CLK1_REQ_PEE2,
+};
+
+static const unsigned drive_cdev2_pins[] = {
+       TEGRA_PIN_CLK2_OUT_PW5,
+       TEGRA_PIN_CLK2_REQ_PCC5,
+       TEGRA_PIN_SDMMC1_WP_N_PV3,
+};
+
+static const unsigned drive_dap1_pins[] = {
+       TEGRA_PIN_DAP1_FS_PN0,
+       TEGRA_PIN_DAP1_DIN_PN1,
+       TEGRA_PIN_DAP1_DOUT_PN2,
+       TEGRA_PIN_DAP1_SCLK_PN3,
+};
+
+static const unsigned drive_dap2_pins[] = {
+       TEGRA_PIN_DAP2_FS_PA2,
+       TEGRA_PIN_DAP2_SCLK_PA3,
+       TEGRA_PIN_DAP2_DIN_PA4,
+       TEGRA_PIN_DAP2_DOUT_PA5,
+};
+
+static const unsigned drive_dap3_pins[] = {
+       TEGRA_PIN_DAP3_FS_PP0,
+       TEGRA_PIN_DAP3_DIN_PP1,
+       TEGRA_PIN_DAP3_DOUT_PP2,
+       TEGRA_PIN_DAP3_SCLK_PP3,
+};
+
+static const unsigned drive_dap4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PP4,
+       TEGRA_PIN_DAP4_DIN_PP5,
+       TEGRA_PIN_DAP4_DOUT_PP6,
+       TEGRA_PIN_DAP4_SCLK_PP7,
+};
+
+static const unsigned drive_dbg_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PC4,
+       TEGRA_PIN_GEN1_I2C_SDA_PC5,
+       TEGRA_PIN_PU0,
+       TEGRA_PIN_PU1,
+       TEGRA_PIN_PU2,
+       TEGRA_PIN_PU3,
+       TEGRA_PIN_PU4,
+       TEGRA_PIN_PU5,
+       TEGRA_PIN_PU6,
+};
+
+static const unsigned drive_sdio3_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PA6,
+       TEGRA_PIN_SDMMC3_CMD_PA7,
+       TEGRA_PIN_SDMMC3_DAT3_PB4,
+       TEGRA_PIN_SDMMC3_DAT2_PB5,
+       TEGRA_PIN_SDMMC3_DAT1_PB6,
+       TEGRA_PIN_SDMMC3_DAT0_PB7,
+       TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4,
+       TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5,
+};
+
+static const unsigned drive_spi_pins[] = {
+       TEGRA_PIN_DVFS_PWM_PX0,
+       TEGRA_PIN_GPIO_X1_AUD_PX1,
+       TEGRA_PIN_DVFS_CLK_PX2,
+       TEGRA_PIN_GPIO_X3_AUD_PX3,
+       TEGRA_PIN_GPIO_X4_AUD_PX4,
+       TEGRA_PIN_GPIO_X5_AUD_PX5,
+       TEGRA_PIN_GPIO_X6_AUD_PX6,
+       TEGRA_PIN_GPIO_X7_AUD_PX7,
+       TEGRA_PIN_GPIO_W2_AUD_PW2,
+       TEGRA_PIN_GPIO_W3_AUD_PW3,
+};
+
+static const unsigned drive_uaa_pins[] = {
+       TEGRA_PIN_ULPI_DATA0_PO1,
+       TEGRA_PIN_ULPI_DATA1_PO2,
+       TEGRA_PIN_ULPI_DATA2_PO3,
+       TEGRA_PIN_ULPI_DATA3_PO4,
+};
+
+static const unsigned drive_uab_pins[] = {
+       TEGRA_PIN_ULPI_DATA7_PO0,
+       TEGRA_PIN_ULPI_DATA4_PO5,
+       TEGRA_PIN_ULPI_DATA5_PO6,
+       TEGRA_PIN_ULPI_DATA6_PO7,
+       TEGRA_PIN_PV0,
+       TEGRA_PIN_PV1,
+};
+
+static const unsigned drive_uart2_pins[] = {
+       TEGRA_PIN_UART2_TXD_PC2,
+       TEGRA_PIN_UART2_RXD_PC3,
+       TEGRA_PIN_UART2_CTS_N_PJ5,
+       TEGRA_PIN_UART2_RTS_N_PJ6,
+};
+
+static const unsigned drive_uart3_pins[] = {
+       TEGRA_PIN_UART3_CTS_N_PA1,
+       TEGRA_PIN_UART3_RTS_N_PC0,
+       TEGRA_PIN_UART3_TXD_PW6,
+       TEGRA_PIN_UART3_RXD_PW7,
+};
+
+static const unsigned drive_sdio1_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT3_PY4,
+       TEGRA_PIN_SDMMC1_DAT2_PY5,
+       TEGRA_PIN_SDMMC1_DAT1_PY6,
+       TEGRA_PIN_SDMMC1_DAT0_PY7,
+       TEGRA_PIN_SDMMC1_CLK_PZ0,
+       TEGRA_PIN_SDMMC1_CMD_PZ1,
+};
+
+static const unsigned drive_ddc_pins[] = {
+       TEGRA_PIN_DDC_SCL_PV4,
+       TEGRA_PIN_DDC_SDA_PV5,
+};
+
+static const unsigned drive_gma_pins[] = {
+       TEGRA_PIN_SDMMC4_CLK_PCC4,
+       TEGRA_PIN_SDMMC4_CMD_PT7,
+       TEGRA_PIN_SDMMC4_DAT0_PAA0,
+       TEGRA_PIN_SDMMC4_DAT1_PAA1,
+       TEGRA_PIN_SDMMC4_DAT2_PAA2,
+       TEGRA_PIN_SDMMC4_DAT3_PAA3,
+       TEGRA_PIN_SDMMC4_DAT4_PAA4,
+       TEGRA_PIN_SDMMC4_DAT5_PAA5,
+       TEGRA_PIN_SDMMC4_DAT6_PAA6,
+       TEGRA_PIN_SDMMC4_DAT7_PAA7,
+};
+
+static const unsigned drive_gme_pins[] = {
+       TEGRA_PIN_PBB0,
+       TEGRA_PIN_CAM_I2C_SCL_PBB1,
+       TEGRA_PIN_CAM_I2C_SDA_PBB2,
+       TEGRA_PIN_PBB3,
+       TEGRA_PIN_PCC2,
+};
+
+static const unsigned drive_gmf_pins[] = {
+       TEGRA_PIN_PBB4,
+       TEGRA_PIN_PBB5,
+       TEGRA_PIN_PBB6,
+       TEGRA_PIN_PBB7,
+};
+
+static const unsigned drive_gmg_pins[] = {
+       TEGRA_PIN_CAM_MCLK_PCC0,
+};
+
+static const unsigned drive_gmh_pins[] = {
+       TEGRA_PIN_PCC1,
+};
+
+static const unsigned drive_owr_pins[] = {
+       TEGRA_PIN_SDMMC3_CD_N_PV2,
+};
+
+static const unsigned drive_uda_pins[] = {
+       TEGRA_PIN_ULPI_CLK_PY0,
+       TEGRA_PIN_ULPI_DIR_PY1,
+       TEGRA_PIN_ULPI_NXT_PY2,
+       TEGRA_PIN_ULPI_STP_PY3,
+};
+
+static const unsigned drive_dev3_pins[] = {
+};
+
+static const unsigned drive_cec_pins[] = {
+};
+
+static const unsigned drive_at6_pins[] = {
+};
+
+static const unsigned drive_dap5_pins[] = {
+};
+
+static const unsigned drive_usb_vbus_en_pins[] = {
+};
+
+static const unsigned drive_ao3_pins[] = {
+};
+
+static const unsigned drive_hv0_pins[] = {
+};
+
+static const unsigned drive_sdio4_pins[] = {
+};
+
+static const unsigned drive_ao0_pins[] = {
+};
+
+enum tegra_mux {
+       TEGRA_MUX_BLINK,
+       TEGRA_MUX_CEC,
+       TEGRA_MUX_CLDVFS,
+       TEGRA_MUX_CLK,
+       TEGRA_MUX_CLK12,
+       TEGRA_MUX_CPU,
+       TEGRA_MUX_DAP,
+       TEGRA_MUX_DAP1,
+       TEGRA_MUX_DAP2,
+       TEGRA_MUX_DEV3,
+       TEGRA_MUX_DISPLAYA,
+       TEGRA_MUX_DISPLAYA_ALT,
+       TEGRA_MUX_DISPLAYB,
+       TEGRA_MUX_DTV,
+       TEGRA_MUX_EMC_DLL,
+       TEGRA_MUX_EXTPERIPH1,
+       TEGRA_MUX_EXTPERIPH2,
+       TEGRA_MUX_EXTPERIPH3,
+       TEGRA_MUX_GMI,
+       TEGRA_MUX_GMI_ALT,
+       TEGRA_MUX_HDA,
+       TEGRA_MUX_HSI,
+       TEGRA_MUX_I2C1,
+       TEGRA_MUX_I2C2,
+       TEGRA_MUX_I2C3,
+       TEGRA_MUX_I2C4,
+       TEGRA_MUX_I2CPWR,
+       TEGRA_MUX_I2S0,
+       TEGRA_MUX_I2S1,
+       TEGRA_MUX_I2S2,
+       TEGRA_MUX_I2S3,
+       TEGRA_MUX_I2S4,
+       TEGRA_MUX_IRDA,
+       TEGRA_MUX_KBC,
+       TEGRA_MUX_NAND,
+       TEGRA_MUX_NAND_ALT,
+       TEGRA_MUX_OWR,
+       TEGRA_MUX_PMI,
+       TEGRA_MUX_PWM0,
+       TEGRA_MUX_PWM1,
+       TEGRA_MUX_PWM2,
+       TEGRA_MUX_PWM3,
+       TEGRA_MUX_PWRON,
+       TEGRA_MUX_RESET_OUT_N,
+       TEGRA_MUX_RSVD1,
+       TEGRA_MUX_RSVD2,
+       TEGRA_MUX_RSVD3,
+       TEGRA_MUX_RSVD4,
+       TEGRA_MUX_RTCK,
+       TEGRA_MUX_SDMMC1,
+       TEGRA_MUX_SDMMC2,
+       TEGRA_MUX_SDMMC3,
+       TEGRA_MUX_SDMMC4,
+       TEGRA_MUX_SOC,
+       TEGRA_MUX_SPDIF,
+       TEGRA_MUX_SPI1,
+       TEGRA_MUX_SPI2,
+       TEGRA_MUX_SPI3,
+       TEGRA_MUX_SPI4,
+       TEGRA_MUX_SPI5,
+       TEGRA_MUX_SPI6,
+       TEGRA_MUX_SYSCLK,
+       TEGRA_MUX_TRACE,
+       TEGRA_MUX_UARTA,
+       TEGRA_MUX_UARTB,
+       TEGRA_MUX_UARTC,
+       TEGRA_MUX_UARTD,
+       TEGRA_MUX_ULPI,
+       TEGRA_MUX_USB,
+       TEGRA_MUX_VGP1,
+       TEGRA_MUX_VGP2,
+       TEGRA_MUX_VGP3,
+       TEGRA_MUX_VGP4,
+       TEGRA_MUX_VGP5,
+       TEGRA_MUX_VGP6,
+       TEGRA_MUX_VI,
+       TEGRA_MUX_VI_ALT1,
+       TEGRA_MUX_VI_ALT3,
+};
+
+#define FUNCTION(fname)                                        \
+       {                                               \
+               .name = #fname,                         \
+       }
+
+static struct tegra_function tegra114_functions[] = {
+       FUNCTION(blink),
+       FUNCTION(cec),
+       FUNCTION(cldvfs),
+       FUNCTION(clk),
+       FUNCTION(clk12),
+       FUNCTION(cpu),
+       FUNCTION(dap),
+       FUNCTION(dap1),
+       FUNCTION(dap2),
+       FUNCTION(dev3),
+       FUNCTION(displaya),
+       FUNCTION(displaya_alt),
+       FUNCTION(displayb),
+       FUNCTION(dtv),
+       FUNCTION(emc_dll),
+       FUNCTION(extperiph1),
+       FUNCTION(extperiph2),
+       FUNCTION(extperiph3),
+       FUNCTION(gmi),
+       FUNCTION(gmi_alt),
+       FUNCTION(hda),
+       FUNCTION(hsi),
+       FUNCTION(i2c1),
+       FUNCTION(i2c2),
+       FUNCTION(i2c3),
+       FUNCTION(i2c4),
+       FUNCTION(i2cpwr),
+       FUNCTION(i2s0),
+       FUNCTION(i2s1),
+       FUNCTION(i2s2),
+       FUNCTION(i2s3),
+       FUNCTION(i2s4),
+       FUNCTION(irda),
+       FUNCTION(kbc),
+       FUNCTION(nand),
+       FUNCTION(nand_alt),
+       FUNCTION(owr),
+       FUNCTION(pmi),
+       FUNCTION(pwm0),
+       FUNCTION(pwm1),
+       FUNCTION(pwm2),
+       FUNCTION(pwm3),
+       FUNCTION(pwron),
+       FUNCTION(reset_out_n),
+       FUNCTION(rsvd1),
+       FUNCTION(rsvd2),
+       FUNCTION(rsvd3),
+       FUNCTION(rsvd4),
+       FUNCTION(rtck),
+       FUNCTION(sdmmc1),
+       FUNCTION(sdmmc2),
+       FUNCTION(sdmmc3),
+       FUNCTION(sdmmc4),
+       FUNCTION(soc),
+       FUNCTION(spdif),
+       FUNCTION(spi1),
+       FUNCTION(spi2),
+       FUNCTION(spi3),
+       FUNCTION(spi4),
+       FUNCTION(spi5),
+       FUNCTION(spi6),
+       FUNCTION(sysclk),
+       FUNCTION(trace),
+       FUNCTION(uarta),
+       FUNCTION(uartb),
+       FUNCTION(uartc),
+       FUNCTION(uartd),
+       FUNCTION(ulpi),
+       FUNCTION(usb),
+       FUNCTION(vgp1),
+       FUNCTION(vgp2),
+       FUNCTION(vgp3),
+       FUNCTION(vgp4),
+       FUNCTION(vgp5),
+       FUNCTION(vgp6),
+       FUNCTION(vi),
+       FUNCTION(vi_alt1),
+       FUNCTION(vi_alt3),
+};
+
+#define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
+#define PINGROUP_REG_A                 0x3000  /* bank 1 */
+
+#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
+#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
+
+#define PINGROUP_BIT_Y(b)              (b)
+#define PINGROUP_BIT_N(b)              (-1)
+
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel)         \
+       {                                                               \
+               .name = #pg_name,                                       \
+               .pins = pg_name##_pins,                                 \
+               .npins = ARRAY_SIZE(pg_name##_pins),                    \
+               .funcs = {                                              \
+                       TEGRA_MUX_##f0,                                 \
+                       TEGRA_MUX_##f1,                                 \
+                       TEGRA_MUX_##f2,                                 \
+                       TEGRA_MUX_##f3,                                 \
+               },                                                      \
+               .mux_reg = PINGROUP_REG(r),                             \
+               .mux_bank = 1,                                          \
+               .mux_bit = 0,                                           \
+               .pupd_reg = PINGROUP_REG(r),                            \
+               .pupd_bank = 1,                                         \
+               .pupd_bit = 2,                                          \
+               .tri_reg = PINGROUP_REG(r),                             \
+               .tri_bank = 1,                                          \
+               .tri_bit = 4,                                           \
+               .einput_bit = 5,                                        \
+               .odrain_bit = PINGROUP_BIT_##od(6),                     \
+               .lock_bit = 7,                                          \
+               .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
+               .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9),               \
+               .drv_reg = -1,                                          \
+       }
+
+#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
+                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
+                    slwf_b, slwf_w, drvtype)                           \
+       {                                                               \
+               .name = "drive_" #pg_name,                              \
+               .pins = drive_##pg_name##_pins,                         \
+               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
+               .mux_reg = -1,                                          \
+               .pupd_reg = -1,                                         \
+               .tri_reg = -1,                                          \
+               .einput_bit = -1,                                       \
+               .odrain_bit = -1,                                       \
+               .lock_bit = -1,                                         \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = DRV_PINGROUP_REG(r),                         \
+               .drv_bank = 0,                                          \
+               .hsm_bit = hsm_b,                                       \
+               .schmitt_bit = schmitt_b,                               \
+               .lpmd_bit = lpmd_b,                                     \
+               .drvdn_bit = drvdn_b,                                   \
+               .drvdn_width = drvdn_w,                                 \
+               .drvup_bit = drvup_b,                                   \
+               .drvup_width = drvup_w,                                 \
+               .slwr_bit = slwr_b,                                     \
+               .slwr_width = slwr_w,                                   \
+               .slwf_bit = slwf_b,                                     \
+               .slwf_width = slwf_w,                                   \
+               .drvtype_bit = PINGROUP_BIT_##drvtype(6),               \
+       }
+
+static const struct tegra_pingroup tegra114_groups[] = {
+       /*       pg_name,                f0,         f1,         f2,           f3,          r,      od, ior, rcv_sel */
+       PINGROUP(ulpi_data0_po1,         SPI3,       HSI,        UARTA,        ULPI,        0x3000, N,   N,  N),
+       PINGROUP(ulpi_data1_po2,         SPI3,       HSI,        UARTA,        ULPI,        0x3004, N,   N,  N),
+       PINGROUP(ulpi_data2_po3,         SPI3,       HSI,        UARTA,        ULPI,        0x3008, N,   N,  N),
+       PINGROUP(ulpi_data3_po4,         SPI3,       HSI,        UARTA,        ULPI,        0x300c, N,   N,  N),
+       PINGROUP(ulpi_data4_po5,         SPI2,       HSI,        UARTA,        ULPI,        0x3010, N,   N,  N),
+       PINGROUP(ulpi_data5_po6,         SPI2,       HSI,        UARTA,        ULPI,        0x3014, N,   N,  N),
+       PINGROUP(ulpi_data6_po7,         SPI2,       HSI,        UARTA,        ULPI,        0x3018, N,   N,  N),
+       PINGROUP(ulpi_data7_po0,         SPI2,       HSI,        UARTA,        ULPI,        0x301c, N,   N,  N),
+       PINGROUP(ulpi_clk_py0,           SPI1,       SPI5,       UARTD,        ULPI,        0x3020, N,   N,  N),
+       PINGROUP(ulpi_dir_py1,           SPI1,       SPI5,       UARTD,        ULPI,        0x3024, N,   N,  N),
+       PINGROUP(ulpi_nxt_py2,           SPI1,       SPI5,       UARTD,        ULPI,        0x3028, N,   N,  N),
+       PINGROUP(ulpi_stp_py3,           SPI1,       SPI5,       UARTD,        ULPI,        0x302c, N,   N,  N),
+       PINGROUP(dap3_fs_pp0,            I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3030, N,   N,  N),
+       PINGROUP(dap3_din_pp1,           I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3034, N,   N,  N),
+       PINGROUP(dap3_dout_pp2,          I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3038, N,   N,  N),
+       PINGROUP(dap3_sclk_pp3,          I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x303c, N,   N,  N),
+       PINGROUP(pv0,                    USB,        RSVD2,      RSVD3,        RSVD4,       0x3040, N,   N,  N),
+       PINGROUP(pv1,                    RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3044, N,   N,  N),
+       PINGROUP(sdmmc1_clk_pz0,         SDMMC1,     CLK12,      RSVD3,        RSVD4,       0x3048, N,   N,  N),
+       PINGROUP(sdmmc1_cmd_pz1,         SDMMC1,     SPDIF,      SPI4,         UARTA,       0x304c, N,   N,  N),
+       PINGROUP(sdmmc1_dat3_py4,        SDMMC1,     SPDIF,      SPI4,         UARTA,       0x3050, N,   N,  N),
+       PINGROUP(sdmmc1_dat2_py5,        SDMMC1,     PWM0,       SPI4,         UARTA,       0x3054, N,   N,  N),
+       PINGROUP(sdmmc1_dat1_py6,        SDMMC1,     PWM1,       SPI4,         UARTA,       0x3058, N,   N,  N),
+       PINGROUP(sdmmc1_dat0_py7,        SDMMC1,     RSVD2,      SPI4,         UARTA,       0x305c, N,   N,  N),
+       PINGROUP(clk2_out_pw5,           EXTPERIPH2, RSVD2,      RSVD3,        RSVD4,       0x3068, N,   N,  N),
+       PINGROUP(clk2_req_pcc5,          DAP,        RSVD2,      RSVD3,        RSVD4,       0x306c, N,   N,  N),
+       PINGROUP(hdmi_int_pn7,           RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3110, N,   N,  Y),
+       PINGROUP(ddc_scl_pv4,            I2C4,       RSVD2,      RSVD3,        RSVD4,       0x3114, N,   N,  Y),
+       PINGROUP(ddc_sda_pv5,            I2C4,       RSVD2,      RSVD3,        RSVD4,       0x3118, N,   N,  Y),
+       PINGROUP(uart2_rxd_pc3,          IRDA,       SPDIF,      UARTA,        SPI4,        0x3164, N,   N,  N),
+       PINGROUP(uart2_txd_pc2,          IRDA,       SPDIF,      UARTA,        SPI4,        0x3168, N,   N,  N),
+       PINGROUP(uart2_rts_n_pj6,        UARTA,      UARTB,      RSVD3,        SPI4,        0x316c, N,   N,  N),
+       PINGROUP(uart2_cts_n_pj5,        UARTA,      UARTB,      RSVD3,        SPI4,        0x3170, N,   N,  N),
+       PINGROUP(uart3_txd_pw6,          UARTC,      RSVD2,      RSVD3,        SPI4,        0x3174, N,   N,  N),
+       PINGROUP(uart3_rxd_pw7,          UARTC,      RSVD2,      RSVD3,        SPI4,        0x3178, N,   N,  N),
+       PINGROUP(uart3_cts_n_pa1,        UARTC,      SDMMC1,     DTV,          SPI4,        0x317c, N,   N,  N),
+       PINGROUP(uart3_rts_n_pc0,        UARTC,      PWM0,       DTV,          DISPLAYA,    0x3180, N,   N,  N),
+       PINGROUP(pu0,                    OWR,        UARTA,      RSVD3,        RSVD4,       0x3184, N,   N,  N),
+       PINGROUP(pu1,                    RSVD1,      UARTA,      RSVD3,        RSVD4,       0x3188, N,   N,  N),
+       PINGROUP(pu2,                    RSVD1,      UARTA,      RSVD3,        RSVD4,       0x318c, N,   N,  N),
+       PINGROUP(pu3,                    PWM0,       UARTA,      DISPLAYA,     DISPLAYB,    0x3190, N,   N,  N),
+       PINGROUP(pu4,                    PWM1,       UARTA,      DISPLAYA,     DISPLAYB,    0x3194, N,   N,  N),
+       PINGROUP(pu5,                    PWM2,       UARTA,      DISPLAYA,     DISPLAYB,    0x3198, N,   N,  N),
+       PINGROUP(pu6,                    PWM3,       UARTA,      USB,          DISPLAYB,    0x319c, N,   N,  N),
+       PINGROUP(gen1_i2c_sda_pc5,       I2C1,       RSVD2,      RSVD3,        RSVD4,       0x31a0, Y,   N,  N),
+       PINGROUP(gen1_i2c_scl_pc4,       I2C1,       RSVD2,      RSVD3,        RSVD4,       0x31a4, Y,   N,  N),
+       PINGROUP(dap4_fs_pp4,            I2S3,       RSVD2,      DTV,          RSVD4,       0x31a8, N,   N,  N),
+       PINGROUP(dap4_din_pp5,           I2S3,       RSVD2,      RSVD3,        RSVD4,       0x31ac, N,   N,  N),
+       PINGROUP(dap4_dout_pp6,          I2S3,       RSVD2,      DTV,          RSVD4,       0x31b0, N,   N,  N),
+       PINGROUP(dap4_sclk_pp7,          I2S3,       RSVD2,      RSVD3,        RSVD4,       0x31b4, N,   N,  N),
+       PINGROUP(clk3_out_pee0,          EXTPERIPH3, RSVD2,      RSVD3,        RSVD4,       0x31b8, N,   N,  N),
+       PINGROUP(clk3_req_pee1,          DEV3,       RSVD2,      RSVD3,        RSVD4,       0x31bc, N,   N,  N),
+       PINGROUP(gmi_wp_n_pc7,           RSVD1,      NAND,       GMI,          GMI_ALT,     0x31c0, N,   N,  N),
+       PINGROUP(gmi_iordy_pi5,          SDMMC2,     RSVD2,      GMI,          TRACE,       0x31c4, N,   N,  N),
+       PINGROUP(gmi_wait_pi7,           SPI4,       NAND,       GMI,          DTV,         0x31c8, N,   N,  N),
+       PINGROUP(gmi_adv_n_pk0,          RSVD1,      NAND,       GMI,          TRACE,       0x31cc, N,   N,  N),
+       PINGROUP(gmi_clk_pk1,            SDMMC2,     NAND,       GMI,          TRACE,       0x31d0, N,   N,  N),
+       PINGROUP(gmi_cs0_n_pj0,          RSVD1,      NAND,       GMI,          USB,         0x31d4, N,   N,  N),
+       PINGROUP(gmi_cs1_n_pj2,          RSVD1,      NAND,       GMI,          SOC,         0x31d8, N,   N,  N),
+       PINGROUP(gmi_cs2_n_pk3,          SDMMC2,     NAND,       GMI,          TRACE,       0x31dc, N,   N,  N),
+       PINGROUP(gmi_cs3_n_pk4,          SDMMC2,     NAND,       GMI,          GMI_ALT,     0x31e0, N,   N,  N),
+       PINGROUP(gmi_cs4_n_pk2,          USB,        NAND,       GMI,          TRACE,       0x31e4, N,   N,  N),
+       PINGROUP(gmi_cs6_n_pi3,          NAND,       NAND_ALT,   GMI,          SPI4,        0x31e8, N,   N,  N),
+       PINGROUP(gmi_cs7_n_pi6,          NAND,       NAND_ALT,   GMI,          SDMMC2,      0x31ec, N,   N,  N),
+       PINGROUP(gmi_ad0_pg0,            RSVD1,      NAND,       GMI,          RSVD4,       0x31f0, N,   N,  N),
+       PINGROUP(gmi_ad1_pg1,            RSVD1,      NAND,       GMI,          RSVD4,       0x31f4, N,   N,  N),
+       PINGROUP(gmi_ad2_pg2,            RSVD1,      NAND,       GMI,          RSVD4,       0x31f8, N,   N,  N),
+       PINGROUP(gmi_ad3_pg3,            RSVD1,      NAND,       GMI,          RSVD4,       0x31fc, N,   N,  N),
+       PINGROUP(gmi_ad4_pg4,            RSVD1,      NAND,       GMI,          RSVD4,       0x3200, N,   N,  N),
+       PINGROUP(gmi_ad5_pg5,            RSVD1,      NAND,       GMI,          SPI4,        0x3204, N,   N,  N),
+       PINGROUP(gmi_ad6_pg6,            RSVD1,      NAND,       GMI,          SPI4,        0x3208, N,   N,  N),
+       PINGROUP(gmi_ad7_pg7,            RSVD1,      NAND,       GMI,          SPI4,        0x320c, N,   N,  N),
+       PINGROUP(gmi_ad8_ph0,            PWM0,       NAND,       GMI,          DTV,         0x3210, N,   N,  N),
+       PINGROUP(gmi_ad9_ph1,            PWM1,       NAND,       GMI,          CLDVFS,      0x3214, N,   N,  N),
+       PINGROUP(gmi_ad10_ph2,           PWM2,       NAND,       GMI,          CLDVFS,      0x3218, N,   N,  N),
+       PINGROUP(gmi_ad11_ph3,           PWM3,       NAND,       GMI,          USB,         0x321c, N,   N,  N),
+       PINGROUP(gmi_ad12_ph4,           SDMMC2,     NAND,       GMI,          RSVD4,       0x3220, N,   N,  N),
+       PINGROUP(gmi_ad13_ph5,           SDMMC2,     NAND,       GMI,          RSVD4,       0x3224, N,   N,  N),
+       PINGROUP(gmi_ad14_ph6,           SDMMC2,     NAND,       GMI,          DTV,         0x3228, N,   N,  N),
+       PINGROUP(gmi_ad15_ph7,           SDMMC2,     NAND,       GMI,          DTV,         0x322c, N,   N,  N),
+       PINGROUP(gmi_a16_pj7,            UARTD,      TRACE,      GMI,          GMI_ALT,     0x3230, N,   N,  N),
+       PINGROUP(gmi_a17_pb0,            UARTD,      RSVD2,      GMI,          TRACE,       0x3234, N,   N,  N),
+       PINGROUP(gmi_a18_pb1,            UARTD,      RSVD2,      GMI,          TRACE,       0x3238, N,   N,  N),
+       PINGROUP(gmi_a19_pk7,            UARTD,      SPI4,       GMI,          TRACE,       0x323c, N,   N,  N),
+       PINGROUP(gmi_wr_n_pi0,           RSVD1,      NAND,       GMI,          SPI4,        0x3240, N,   N,  N),
+       PINGROUP(gmi_oe_n_pi1,           RSVD1,      NAND,       GMI,          SOC,         0x3244, N,   N,  N),
+       PINGROUP(gmi_dqs_p_pj3,          SDMMC2,     NAND,       GMI,          TRACE,       0x3248, N,   N,  N),
+       PINGROUP(gmi_rst_n_pi4,          NAND,       NAND_ALT,   GMI,          RSVD4,       0x324c, N,   N,  N),
+       PINGROUP(gen2_i2c_scl_pt5,       I2C2,       RSVD2,      GMI,          RSVD4,       0x3250, Y,   N,  N),
+       PINGROUP(gen2_i2c_sda_pt6,       I2C2,       RSVD2,      GMI,          RSVD4,       0x3254, Y,   N,  N),
+       PINGROUP(sdmmc4_clk_pcc4,        SDMMC4,     RSVD2,      GMI,          RSVD4,       0x3258, N,   Y,  N),
+       PINGROUP(sdmmc4_cmd_pt7,         SDMMC4,     RSVD2,      GMI,          RSVD4,       0x325c, N,   Y,  N),
+       PINGROUP(sdmmc4_dat0_paa0,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3260, N,   Y,  N),
+       PINGROUP(sdmmc4_dat1_paa1,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3264, N,   Y,  N),
+       PINGROUP(sdmmc4_dat2_paa2,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3268, N,   Y,  N),
+       PINGROUP(sdmmc4_dat3_paa3,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x326c, N,   Y,  N),
+       PINGROUP(sdmmc4_dat4_paa4,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3270, N,   Y,  N),
+       PINGROUP(sdmmc4_dat5_paa5,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3274, N,   Y,  N),
+       PINGROUP(sdmmc4_dat6_paa6,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3278, N,   Y,  N),
+       PINGROUP(sdmmc4_dat7_paa7,       SDMMC4,     RSVD2,      GMI,          RSVD4,       0x327c, N,   Y,  N),
+       PINGROUP(cam_mclk_pcc0,          VI,         VI_ALT1,    VI_ALT3,      RSVD4,       0x3284, N,   N,  N),
+       PINGROUP(pcc1,                   I2S4,       RSVD2,      RSVD3,        RSVD4,       0x3288, N,   N,  N),
+       PINGROUP(pbb0,                   I2S4,       VI,         VI_ALT1,      VI_ALT3,     0x328c, N,   N,  N),
+       PINGROUP(cam_i2c_scl_pbb1,       VGP1,       I2C3,       RSVD3,        RSVD4,       0x3290, Y,   N,  N),
+       PINGROUP(cam_i2c_sda_pbb2,       VGP2,       I2C3,       RSVD3,        RSVD4,       0x3294, Y,   N,  N),
+       PINGROUP(pbb3,                   VGP3,       DISPLAYA,   DISPLAYB,     RSVD4,       0x3298, N,   N,  N),
+       PINGROUP(pbb4,                   VGP4,       DISPLAYA,   DISPLAYB,     RSVD4,       0x329c, N,   N,  N),
+       PINGROUP(pbb5,                   VGP5,       DISPLAYA,   DISPLAYB,     RSVD4,       0x32a0, N,   N,  N),
+       PINGROUP(pbb6,                   VGP6,       DISPLAYA,   DISPLAYB,     RSVD4,       0x32a4, N,   N,  N),
+       PINGROUP(pbb7,                   I2S4,       RSVD2,      RSVD3,        RSVD4,       0x32a8, N,   N,  N),
+       PINGROUP(pcc2,                   I2S4,       RSVD2,      RSVD3,        RSVD4,       0x32ac, N,   N,  N),
+       PINGROUP(jtag_rtck,              RTCK,       RSVD2,      RSVD3,        RSVD4,       0x32b0, N,   N,  N),
+       PINGROUP(pwr_i2c_scl_pz6,        I2CPWR,     RSVD2,      RSVD3,        RSVD4,       0x32b4, Y,   N,  N),
+       PINGROUP(pwr_i2c_sda_pz7,        I2CPWR,     RSVD2,      RSVD3,        RSVD4,       0x32b8, Y,   N,  N),
+       PINGROUP(kb_row0_pr0,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32bc, N,   N,  N),
+       PINGROUP(kb_row1_pr1,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32c0, N,   N,  N),
+       PINGROUP(kb_row2_pr2,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32c4, N,   N,  N),
+       PINGROUP(kb_row3_pr3,            KBC,        DISPLAYA,   RSVD3,        DISPLAYB,    0x32c8, N,   N,  N),
+       PINGROUP(kb_row4_pr4,            KBC,        DISPLAYA,   SPI2,         DISPLAYB,    0x32cc, N,   N,  N),
+       PINGROUP(kb_row5_pr5,            KBC,        DISPLAYA,   SPI2,         DISPLAYB,    0x32d0, N,   N,  N),
+       PINGROUP(kb_row6_pr6,            KBC,        DISPLAYA,   DISPLAYA_ALT, DISPLAYB,    0x32d4, N,   N,  N),
+       PINGROUP(kb_row7_pr7,            KBC,        RSVD2,      CLDVFS,       UARTA,       0x32d8, N,   N,  N),
+       PINGROUP(kb_row8_ps0,            KBC,        RSVD2,      CLDVFS,       UARTA,       0x32dc, N,   N,  N),
+       PINGROUP(kb_row9_ps1,            KBC,        RSVD2,      RSVD3,        UARTA,       0x32e0, N,   N,  N),
+       PINGROUP(kb_row10_ps2,           KBC,        RSVD2,      RSVD3,        UARTA,       0x32e4, N,   N,  N),
+       PINGROUP(kb_col0_pq0,            KBC,        USB,        SPI2,         EMC_DLL,     0x32fc, N,   N,  N),
+       PINGROUP(kb_col1_pq1,            KBC,        RSVD2,      SPI2,         EMC_DLL,     0x3300, N,   N,  N),
+       PINGROUP(kb_col2_pq2,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3304, N,   N,  N),
+       PINGROUP(kb_col3_pq3,            KBC,        DISPLAYA,   PWM2,         UARTA,       0x3308, N,   N,  N),
+       PINGROUP(kb_col4_pq4,            KBC,        OWR,        SDMMC3,       UARTA,       0x330c, N,   N,  N),
+       PINGROUP(kb_col5_pq5,            KBC,        RSVD2,      SDMMC1,       RSVD4,       0x3310, N,   N,  N),
+       PINGROUP(kb_col6_pq6,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3314, N,   N,  N),
+       PINGROUP(kb_col7_pq7,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3318, N,   N,  N),
+       PINGROUP(clk_32k_out_pa0,        BLINK,      SOC,        RSVD3,        RSVD4,       0x331c, N,   N,  N),
+       PINGROUP(sys_clk_req_pz5,        SYSCLK,     RSVD2,      RSVD3,        RSVD4,       0x3320, N,   N,  N),
+       PINGROUP(core_pwr_req,           PWRON,      RSVD2,      RSVD3,        RSVD4,       0x3324, N,   N,  N),
+       PINGROUP(cpu_pwr_req,            CPU,        RSVD2,      RSVD3,        RSVD4,       0x3328, N,   N,  N),
+       PINGROUP(pwr_int_n,              PMI,        RSVD2,      RSVD3,        RSVD4,       0x332c, N,   N,  N),
+       PINGROUP(clk_32k_in,             CLK,        RSVD2,      RSVD3,        RSVD4,       0x3330, N,   N,  N),
+       PINGROUP(owr,                    OWR,        RSVD2,      RSVD3,        RSVD4,       0x3334, N,   N,  Y),
+       PINGROUP(dap1_fs_pn0,            I2S0,       HDA,        GMI,          RSVD4,       0x3338, N,   N,  N),
+       PINGROUP(dap1_din_pn1,           I2S0,       HDA,        GMI,          RSVD4,       0x333c, N,   N,  N),
+       PINGROUP(dap1_dout_pn2,          I2S0,       HDA,        GMI,          RSVD4,       0x3340, N,   N,  N),
+       PINGROUP(dap1_sclk_pn3,          I2S0,       HDA,        GMI,          RSVD4,       0x3344, N,   N,  N),
+       PINGROUP(clk1_req_pee2,          DAP,        DAP1,       RSVD3,        RSVD4,       0x3348, N,   N,  N),
+       PINGROUP(clk1_out_pw4,           EXTPERIPH1, DAP2,       RSVD3,        RSVD4,       0x334c, N,   N,  N),
+       PINGROUP(spdif_in_pk6,           SPDIF,      USB,        RSVD3,        RSVD4,       0x3350, N,   N,  N),
+       PINGROUP(spdif_out_pk5,          SPDIF,      RSVD2,      RSVD3,        RSVD4,       0x3354, N,   N,  N),
+       PINGROUP(dap2_fs_pa2,            I2S1,       HDA,        RSVD3,        RSVD4,       0x3358, N,   N,  N),
+       PINGROUP(dap2_din_pa4,           I2S1,       HDA,        RSVD3,        RSVD4,       0x335c, N,   N,  N),
+       PINGROUP(dap2_dout_pa5,          I2S1,       HDA,        RSVD3,        RSVD4,       0x3360, N,   N,  N),
+       PINGROUP(dap2_sclk_pa3,          I2S1,       HDA,        RSVD3,        RSVD4,       0x3364, N,   N,  N),
+       PINGROUP(dvfs_pwm_px0,           SPI6,       CLDVFS,     RSVD3,        RSVD4,       0x3368, N,   N,  N),
+       PINGROUP(gpio_x1_aud_px1,        SPI6,       RSVD2,      RSVD3,        RSVD4,       0x336c, N,   N,  N),
+       PINGROUP(gpio_x3_aud_px3,        SPI6,       SPI1,       RSVD3,        RSVD4,       0x3370, N,   N,  N),
+       PINGROUP(dvfs_clk_px2,           SPI6,       CLDVFS,     RSVD3,        RSVD4,       0x3374, N,   N,  N),
+       PINGROUP(gpio_x4_aud_px4,        RSVD1,      SPI1,       SPI2,         DAP2,        0x3378, N,   N,  N),
+       PINGROUP(gpio_x5_aud_px5,        RSVD1,      SPI1,       SPI2,         RSVD4,       0x337c, N,   N,  N),
+       PINGROUP(gpio_x6_aud_px6,        SPI6,       SPI1,       SPI2,         RSVD4,       0x3380, N,   N,  N),
+       PINGROUP(gpio_x7_aud_px7,        RSVD1,      SPI1,       SPI2,         RSVD4,       0x3384, N,   N,  N),
+       PINGROUP(sdmmc3_clk_pa6,         SDMMC3,     RSVD2,      RSVD3,        SPI3,        0x3390, N,   N,  N),
+       PINGROUP(sdmmc3_cmd_pa7,         SDMMC3,     PWM3,       UARTA,        SPI3,        0x3394, N,   N,  N),
+       PINGROUP(sdmmc3_dat0_pb7,        SDMMC3,     RSVD2,      RSVD3,        SPI3,        0x3398, N,   N,  N),
+       PINGROUP(sdmmc3_dat1_pb6,        SDMMC3,     PWM2,       UARTA,        SPI3,        0x339c, N,   N,  N),
+       PINGROUP(sdmmc3_dat2_pb5,        SDMMC3,     PWM1,       DISPLAYA,     SPI3,        0x33a0, N,   N,  N),
+       PINGROUP(sdmmc3_dat3_pb4,        SDMMC3,     PWM0,       DISPLAYB,     SPI3,        0x33a4, N,   N,  N),
+       PINGROUP(hdmi_cec_pee3,          CEC,        SDMMC3,     RSVD3,        SOC,         0x33e0, Y,   N,  N),
+       PINGROUP(sdmmc1_wp_n_pv3,        SDMMC1,     CLK12,      SPI4,         UARTA,       0x33e4, N,   N,  N),
+       PINGROUP(sdmmc3_cd_n_pv2,        SDMMC3,     OWR,        RSVD3,        RSVD4,       0x33e8, N,   N,  N),
+       PINGROUP(gpio_w2_aud_pw2,        SPI6,       RSVD2,      SPI2,         I2C1,        0x33ec, N,   N,  N),
+       PINGROUP(gpio_w3_aud_pw3,        SPI6,       SPI1,       SPI2,         I2C1,        0x33f0, N,   N,  N),
+       PINGROUP(usb_vbus_en0_pn4,       USB,        RSVD2,      RSVD3,        RSVD4,       0x33f4, Y,   N,  N),
+       PINGROUP(usb_vbus_en1_pn5,       USB,        RSVD2,      RSVD3,        RSVD4,       0x33f8, Y,   N,  N),
+       PINGROUP(sdmmc3_clk_lb_in_pee5,  SDMMC3,     RSVD2,      RSVD3,        RSVD4,       0x33fc, N,   N,  N),
+       PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3,     RSVD2,      RSVD3,        RSVD4,       0x3400, N,   N,  N),
+       PINGROUP(gmi_clk_lb,             SDMMC2,     NAND,       GMI,          RSVD4,       0x3404, N,   N,  N),
+       PINGROUP(reset_out_n,            RSVD1,      RSVD2,      RSVD3,        RESET_OUT_N, 0x3408, N,   N,  N),
+
+       /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */
+       DRV_PINGROUP(ao1,         0x868,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(ao2,         0x86c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(at1,         0x870,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(at2,         0x874,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(at3,         0x878,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(at4,         0x87c,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(at5,         0x880,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(cdev1,       0x884,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(cdev2,       0x888,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dap1,        0x890,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dap2,        0x894,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dap3,        0x898,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dap4,        0x89c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dbg,         0x8a0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(sdio3,       0x8b0,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(spi,         0x8b4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uaa,         0x8b8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uab,         0x8bc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uart2,       0x8c0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uart3,       0x8c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(sdio1,       0x8ec,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(ddc,         0x8fc,  2,  3, -1,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gma,         0x900,  2,  3, -1,  14,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gme,         0x910,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gmf,         0x914,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gmg,         0x918,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gmh,         0x91c,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(owr,         0x920,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uda,         0x924,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dev3,        0x92c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(cec,         0x938,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(at6,         0x994,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(dap5,        0x998,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(usb_vbus_en, 0x99c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(ao3,         0x9a0,  2,  3,  4,  12,  5,  -1, -1,  28,  2,  -1, -1,  N),
+       DRV_PINGROUP(hv0,         0x9a4,  2,  3,  4,  12,  5,  -1, -1,  28,  2,  -1, -1,  N),
+       DRV_PINGROUP(sdio4,       0x9a8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(ao0,         0x9ac,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+};
+
+static const struct tegra_pinctrl_soc_data tegra114_pinctrl = {
+       .ngpios = NUM_GPIOS,
+       .pins = tegra114_pins,
+       .npins = ARRAY_SIZE(tegra114_pins),
+       .functions = tegra114_functions,
+       .nfunctions = ARRAY_SIZE(tegra114_functions),
+       .groups = tegra114_groups,
+       .ngroups = ARRAY_SIZE(tegra114_groups),
+       .hsm_in_mux = false,
+       .schmitt_in_mux = false,
+       .drvtype_in_mux = false,
+};
+
+static int tegra114_pinctrl_probe(struct platform_device *pdev)
+{
+       return tegra_pinctrl_probe(pdev, &tegra114_pinctrl);
+}
+
+static const struct of_device_id tegra114_pinctrl_of_match[] = {
+       { .compatible = "nvidia,tegra114-pinmux", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, tegra114_pinctrl_of_match);
+
+static struct platform_driver tegra114_pinctrl_driver = {
+       .driver = {
+               .name = "tegra114-pinctrl",
+               .of_match_table = tegra114_pinctrl_of_match,
+       },
+       .probe = tegra114_pinctrl_probe,
+       .remove = tegra_pinctrl_remove,
+};
+module_platform_driver(tegra114_pinctrl_driver);
+
+MODULE_AUTHOR("Pritesh Raithatha <praithatha@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra114 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c
new file mode 100644 (file)
index 0000000..7cd44c7
--- /dev/null
@@ -0,0 +1,2084 @@
+/*
+ * Pinctrl data for the NVIDIA Tegra124 pinmux
+ *
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/*
+ * Most pins affected by the pinmux can also be GPIOs. Define these first.
+ * These must match how the GPIO driver names/numbers its pins.
+ */
+#define _GPIO(offset)                          (offset)
+
+#define TEGRA_PIN_CLK_32K_OUT_PA0              _GPIO(0)
+#define TEGRA_PIN_UART3_CTS_N_PA1              _GPIO(1)
+#define TEGRA_PIN_DAP2_FS_PA2                  _GPIO(2)
+#define TEGRA_PIN_DAP2_SCLK_PA3                        _GPIO(3)
+#define TEGRA_PIN_DAP2_DIN_PA4                 _GPIO(4)
+#define TEGRA_PIN_DAP2_DOUT_PA5                        _GPIO(5)
+#define TEGRA_PIN_SDMMC3_CLK_PA6               _GPIO(6)
+#define TEGRA_PIN_SDMMC3_CMD_PA7               _GPIO(7)
+#define TEGRA_PIN_PB0                          _GPIO(8)
+#define TEGRA_PIN_PB1                          _GPIO(9)
+#define TEGRA_PIN_SDMMC3_DAT3_PB4              _GPIO(12)
+#define TEGRA_PIN_SDMMC3_DAT2_PB5              _GPIO(13)
+#define TEGRA_PIN_SDMMC3_DAT1_PB6              _GPIO(14)
+#define TEGRA_PIN_SDMMC3_DAT0_PB7              _GPIO(15)
+#define TEGRA_PIN_UART3_RTS_N_PC0              _GPIO(16)
+#define TEGRA_PIN_UART2_TXD_PC2                        _GPIO(18)
+#define TEGRA_PIN_UART2_RXD_PC3                        _GPIO(19)
+#define TEGRA_PIN_GEN1_I2C_SCL_PC4             _GPIO(20)
+#define TEGRA_PIN_GEN1_I2C_SDA_PC5             _GPIO(21)
+#define TEGRA_PIN_PC7                          _GPIO(23)
+#define TEGRA_PIN_PG0                          _GPIO(48)
+#define TEGRA_PIN_PG1                          _GPIO(49)
+#define TEGRA_PIN_PG2                          _GPIO(50)
+#define TEGRA_PIN_PG3                          _GPIO(51)
+#define TEGRA_PIN_PG4                          _GPIO(52)
+#define TEGRA_PIN_PG5                          _GPIO(53)
+#define TEGRA_PIN_PG6                          _GPIO(54)
+#define TEGRA_PIN_PG7                          _GPIO(55)
+#define TEGRA_PIN_PH0                          _GPIO(56)
+#define TEGRA_PIN_PH1                          _GPIO(57)
+#define TEGRA_PIN_PH2                          _GPIO(58)
+#define TEGRA_PIN_PH3                          _GPIO(59)
+#define TEGRA_PIN_PH4                          _GPIO(60)
+#define TEGRA_PIN_PH5                          _GPIO(61)
+#define TEGRA_PIN_PH6                          _GPIO(62)
+#define TEGRA_PIN_PH7                          _GPIO(63)
+#define TEGRA_PIN_PI0                          _GPIO(64)
+#define TEGRA_PIN_PI1                          _GPIO(65)
+#define TEGRA_PIN_PI2                          _GPIO(66)
+#define TEGRA_PIN_PI3                          _GPIO(67)
+#define TEGRA_PIN_PI4                          _GPIO(68)
+#define TEGRA_PIN_PI5                          _GPIO(69)
+#define TEGRA_PIN_PI6                          _GPIO(70)
+#define TEGRA_PIN_PI7                          _GPIO(71)
+#define TEGRA_PIN_PJ0                          _GPIO(72)
+#define TEGRA_PIN_PJ2                          _GPIO(74)
+#define TEGRA_PIN_UART2_CTS_N_PJ5              _GPIO(77)
+#define TEGRA_PIN_UART2_RTS_N_PJ6              _GPIO(78)
+#define TEGRA_PIN_PJ7                          _GPIO(79)
+#define TEGRA_PIN_PK0                          _GPIO(80)
+#define TEGRA_PIN_PK1                          _GPIO(81)
+#define TEGRA_PIN_PK2                          _GPIO(82)
+#define TEGRA_PIN_PK3                          _GPIO(83)
+#define TEGRA_PIN_PK4                          _GPIO(84)
+#define TEGRA_PIN_SPDIF_OUT_PK5                        _GPIO(85)
+#define TEGRA_PIN_SPDIF_IN_PK6                 _GPIO(86)
+#define TEGRA_PIN_PK7                          _GPIO(87)
+#define TEGRA_PIN_DAP1_FS_PN0                  _GPIO(104)
+#define TEGRA_PIN_DAP1_DIN_PN1                 _GPIO(105)
+#define TEGRA_PIN_DAP1_DOUT_PN2                        _GPIO(106)
+#define TEGRA_PIN_DAP1_SCLK_PN3                        _GPIO(107)
+#define TEGRA_PIN_USB_VBUS_EN0_PN4             _GPIO(108)
+#define TEGRA_PIN_USB_VBUS_EN1_PN5             _GPIO(109)
+#define TEGRA_PIN_HDMI_INT_PN7                 _GPIO(111)
+#define TEGRA_PIN_ULPI_DATA7_PO0               _GPIO(112)
+#define TEGRA_PIN_ULPI_DATA0_PO1               _GPIO(113)
+#define TEGRA_PIN_ULPI_DATA1_PO2               _GPIO(114)
+#define TEGRA_PIN_ULPI_DATA2_PO3               _GPIO(115)
+#define TEGRA_PIN_ULPI_DATA3_PO4               _GPIO(116)
+#define TEGRA_PIN_ULPI_DATA4_PO5               _GPIO(117)
+#define TEGRA_PIN_ULPI_DATA5_PO6               _GPIO(118)
+#define TEGRA_PIN_ULPI_DATA6_PO7               _GPIO(119)
+#define TEGRA_PIN_DAP3_FS_PP0                  _GPIO(120)
+#define TEGRA_PIN_DAP3_DIN_PP1                 _GPIO(121)
+#define TEGRA_PIN_DAP3_DOUT_PP2                        _GPIO(122)
+#define TEGRA_PIN_DAP3_SCLK_PP3                        _GPIO(123)
+#define TEGRA_PIN_DAP4_FS_PP4                  _GPIO(124)
+#define TEGRA_PIN_DAP4_DIN_PP5                 _GPIO(125)
+#define TEGRA_PIN_DAP4_DOUT_PP6                        _GPIO(126)
+#define TEGRA_PIN_DAP4_SCLK_PP7                        _GPIO(127)
+#define TEGRA_PIN_KB_COL0_PQ0                  _GPIO(128)
+#define TEGRA_PIN_KB_COL1_PQ1                  _GPIO(129)
+#define TEGRA_PIN_KB_COL2_PQ2                  _GPIO(130)
+#define TEGRA_PIN_KB_COL3_PQ3                  _GPIO(131)
+#define TEGRA_PIN_KB_COL4_PQ4                  _GPIO(132)
+#define TEGRA_PIN_KB_COL5_PQ5                  _GPIO(133)
+#define TEGRA_PIN_KB_COL6_PQ6                  _GPIO(134)
+#define TEGRA_PIN_KB_COL7_PQ7                  _GPIO(135)
+#define TEGRA_PIN_KB_ROW0_PR0                  _GPIO(136)
+#define TEGRA_PIN_KB_ROW1_PR1                  _GPIO(137)
+#define TEGRA_PIN_KB_ROW2_PR2                  _GPIO(138)
+#define TEGRA_PIN_KB_ROW3_PR3                  _GPIO(139)
+#define TEGRA_PIN_KB_ROW4_PR4                  _GPIO(140)
+#define TEGRA_PIN_KB_ROW5_PR5                  _GPIO(141)
+#define TEGRA_PIN_KB_ROW6_PR6                  _GPIO(142)
+#define TEGRA_PIN_KB_ROW7_PR7                  _GPIO(143)
+#define TEGRA_PIN_KB_ROW8_PS0                  _GPIO(144)
+#define TEGRA_PIN_KB_ROW9_PS1                  _GPIO(145)
+#define TEGRA_PIN_KB_ROW10_PS2                 _GPIO(146)
+#define TEGRA_PIN_KB_ROW11_PS3                 _GPIO(147)
+#define TEGRA_PIN_KB_ROW12_PS4                 _GPIO(148)
+#define TEGRA_PIN_KB_ROW13_PS5                 _GPIO(149)
+#define TEGRA_PIN_KB_ROW14_PS6                 _GPIO(150)
+#define TEGRA_PIN_KB_ROW15_PS7                 _GPIO(151)
+#define TEGRA_PIN_KB_ROW16_PT0                 _GPIO(152)
+#define TEGRA_PIN_KB_ROW17_PT1                 _GPIO(153)
+#define TEGRA_PIN_GEN2_I2C_SCL_PT5             _GPIO(157)
+#define TEGRA_PIN_GEN2_I2C_SDA_PT6             _GPIO(158)
+#define TEGRA_PIN_SDMMC4_CMD_PT7               _GPIO(159)
+#define TEGRA_PIN_PU0                          _GPIO(160)
+#define TEGRA_PIN_PU1                          _GPIO(161)
+#define TEGRA_PIN_PU2                          _GPIO(162)
+#define TEGRA_PIN_PU3                          _GPIO(163)
+#define TEGRA_PIN_PU4                          _GPIO(164)
+#define TEGRA_PIN_PU5                          _GPIO(165)
+#define TEGRA_PIN_PU6                          _GPIO(166)
+#define TEGRA_PIN_PV0                          _GPIO(168)
+#define TEGRA_PIN_PV1                          _GPIO(169)
+#define TEGRA_PIN_SDMMC3_CD_N_PV2              _GPIO(170)
+#define TEGRA_PIN_SDMMC1_WP_N_PV3              _GPIO(171)
+#define TEGRA_PIN_DDC_SCL_PV4                  _GPIO(172)
+#define TEGRA_PIN_DDC_SDA_PV5                  _GPIO(173)
+#define TEGRA_PIN_GPIO_W2_AUD_PW2              _GPIO(178)
+#define TEGRA_PIN_GPIO_W3_AUD_PW3              _GPIO(179)
+#define TEGRA_PIN_DAP_MCLK1_PW4                        _GPIO(180)
+#define TEGRA_PIN_CLK2_OUT_PW5                 _GPIO(181)
+#define TEGRA_PIN_UART3_TXD_PW6                        _GPIO(182)
+#define TEGRA_PIN_UART3_RXD_PW7                        _GPIO(183)
+#define TEGRA_PIN_DVFS_PWM_PX0                 _GPIO(184)
+#define TEGRA_PIN_GPIO_X1_AUD_PX1              _GPIO(185)
+#define TEGRA_PIN_DVFS_CLK_PX2                 _GPIO(186)
+#define TEGRA_PIN_GPIO_X3_AUD_PX3              _GPIO(187)
+#define TEGRA_PIN_GPIO_X4_AUD_PX4              _GPIO(188)
+#define TEGRA_PIN_GPIO_X5_AUD_PX5              _GPIO(189)
+#define TEGRA_PIN_GPIO_X6_AUD_PX6              _GPIO(190)
+#define TEGRA_PIN_GPIO_X7_AUD_PX7              _GPIO(191)
+#define TEGRA_PIN_ULPI_CLK_PY0                 _GPIO(192)
+#define TEGRA_PIN_ULPI_DIR_PY1                 _GPIO(193)
+#define TEGRA_PIN_ULPI_NXT_PY2                 _GPIO(194)
+#define TEGRA_PIN_ULPI_STP_PY3                 _GPIO(195)
+#define TEGRA_PIN_SDMMC1_DAT3_PY4              _GPIO(196)
+#define TEGRA_PIN_SDMMC1_DAT2_PY5              _GPIO(197)
+#define TEGRA_PIN_SDMMC1_DAT1_PY6              _GPIO(198)
+#define TEGRA_PIN_SDMMC1_DAT0_PY7              _GPIO(199)
+#define TEGRA_PIN_SDMMC1_CLK_PZ0               _GPIO(200)
+#define TEGRA_PIN_SDMMC1_CMD_PZ1               _GPIO(201)
+#define TEGRA_PIN_PWR_I2C_SCL_PZ6              _GPIO(206)
+#define TEGRA_PIN_PWR_I2C_SDA_PZ7              _GPIO(207)
+#define TEGRA_PIN_SDMMC4_DAT0_PAA0             _GPIO(208)
+#define TEGRA_PIN_SDMMC4_DAT1_PAA1             _GPIO(209)
+#define TEGRA_PIN_SDMMC4_DAT2_PAA2             _GPIO(210)
+#define TEGRA_PIN_SDMMC4_DAT3_PAA3             _GPIO(211)
+#define TEGRA_PIN_SDMMC4_DAT4_PAA4             _GPIO(212)
+#define TEGRA_PIN_SDMMC4_DAT5_PAA5             _GPIO(213)
+#define TEGRA_PIN_SDMMC4_DAT6_PAA6             _GPIO(214)
+#define TEGRA_PIN_SDMMC4_DAT7_PAA7             _GPIO(215)
+#define TEGRA_PIN_PBB0                         _GPIO(216)
+#define TEGRA_PIN_CAM_I2C_SCL_PBB1             _GPIO(217)
+#define TEGRA_PIN_CAM_I2C_SDA_PBB2             _GPIO(218)
+#define TEGRA_PIN_PBB3                         _GPIO(219)
+#define TEGRA_PIN_PBB4                         _GPIO(220)
+#define TEGRA_PIN_PBB5                         _GPIO(221)
+#define TEGRA_PIN_PBB6                         _GPIO(222)
+#define TEGRA_PIN_PBB7                         _GPIO(223)
+#define TEGRA_PIN_CAM_MCLK_PCC0                        _GPIO(224)
+#define TEGRA_PIN_PCC1                         _GPIO(225)
+#define TEGRA_PIN_PCC2                         _GPIO(226)
+#define TEGRA_PIN_SDMMC4_CLK_PCC4              _GPIO(228)
+#define TEGRA_PIN_CLK2_REQ_PCC5                        _GPIO(229)
+#define TEGRA_PIN_PEX_L0_RST_N_PDD1            _GPIO(233)
+#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2         _GPIO(234)
+#define TEGRA_PIN_PEX_WAKE_N_PDD3              _GPIO(235)
+#define TEGRA_PIN_PEX_L1_RST_N_PDD5            _GPIO(237)
+#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6         _GPIO(238)
+#define TEGRA_PIN_CLK3_OUT_PEE0                        _GPIO(240)
+#define TEGRA_PIN_CLK3_REQ_PEE1                        _GPIO(241)
+#define TEGRA_PIN_DAP_MCLK1_REQ_PEE2           _GPIO(242)
+#define TEGRA_PIN_HDMI_CEC_PEE3                        _GPIO(243)
+#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4       _GPIO(244)
+#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5                _GPIO(245)
+#define TEGRA_PIN_DP_HPD_PFF0                  _GPIO(248)
+#define TEGRA_PIN_USB_VBUS_EN2_PFF1            _GPIO(249)
+#define TEGRA_PIN_PFF2                         _GPIO(250)
+
+/* All non-GPIO pins follow */
+#define NUM_GPIOS                              (TEGRA_PIN_PFF2 + 1)
+#define _PIN(offset)                           (NUM_GPIOS + (offset))
+
+/* Non-GPIO pins */
+#define TEGRA_PIN_CORE_PWR_REQ                 _PIN(0)
+#define TEGRA_PIN_CPU_PWR_REQ                  _PIN(1)
+#define TEGRA_PIN_PWR_INT_N                    _PIN(2)
+#define TEGRA_PIN_GMI_CLK_LB                   _PIN(3)
+#define TEGRA_PIN_RESET_OUT_N                  _PIN(4)
+#define TEGRA_PIN_OWR                          _PIN(5)
+#define TEGRA_PIN_CLK_32K_IN                   _PIN(6)
+#define TEGRA_PIN_JTAG_RTCK                    _PIN(7)
+#define TEGRA_PIN_DSI_B_CLK_P                  _PIN(8)
+#define TEGRA_PIN_DSI_B_CLK_N                  _PIN(9)
+#define TEGRA_PIN_DSI_B_D0_P                   _PIN(10)
+#define TEGRA_PIN_DSI_B_D0_N                   _PIN(11)
+#define TEGRA_PIN_DSI_B_D1_P                   _PIN(12)
+#define TEGRA_PIN_DSI_B_D1_N                   _PIN(13)
+#define TEGRA_PIN_DSI_B_D2_P                   _PIN(14)
+#define TEGRA_PIN_DSI_B_D2_N                   _PIN(15)
+#define TEGRA_PIN_DSI_B_D3_P                   _PIN(16)
+#define TEGRA_PIN_DSI_B_D3_N                   _PIN(17)
+
+static const struct pinctrl_pin_desc tegra124_pins[] = {
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"),
+       PINCTRL_PIN(TEGRA_PIN_PB0, "PB0"),
+       PINCTRL_PIN(TEGRA_PIN_PB1, "PB1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"),
+       PINCTRL_PIN(TEGRA_PIN_PC7, "PC7"),
+       PINCTRL_PIN(TEGRA_PIN_PG0, "PG0"),
+       PINCTRL_PIN(TEGRA_PIN_PG1, "PG1"),
+       PINCTRL_PIN(TEGRA_PIN_PG2, "PG2"),
+       PINCTRL_PIN(TEGRA_PIN_PG3, "PG3"),
+       PINCTRL_PIN(TEGRA_PIN_PG4, "PG4"),
+       PINCTRL_PIN(TEGRA_PIN_PG5, "PG5"),
+       PINCTRL_PIN(TEGRA_PIN_PG6, "PG6"),
+       PINCTRL_PIN(TEGRA_PIN_PG7, "PG7"),
+       PINCTRL_PIN(TEGRA_PIN_PH0, "PH0"),
+       PINCTRL_PIN(TEGRA_PIN_PH1, "PH1"),
+       PINCTRL_PIN(TEGRA_PIN_PH2, "PH2"),
+       PINCTRL_PIN(TEGRA_PIN_PH3, "PH3"),
+       PINCTRL_PIN(TEGRA_PIN_PH4, "PH4"),
+       PINCTRL_PIN(TEGRA_PIN_PH5, "PH5"),
+       PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"),
+       PINCTRL_PIN(TEGRA_PIN_PH7, "PH7"),
+       PINCTRL_PIN(TEGRA_PIN_PI0, "PI0"),
+       PINCTRL_PIN(TEGRA_PIN_PI1, "PI1"),
+       PINCTRL_PIN(TEGRA_PIN_PI2, "PI2"),
+       PINCTRL_PIN(TEGRA_PIN_PI3, "PI3"),
+       PINCTRL_PIN(TEGRA_PIN_PI4, "PI4"),
+       PINCTRL_PIN(TEGRA_PIN_PI5, "PI5"),
+       PINCTRL_PIN(TEGRA_PIN_PI6, "PI6"),
+       PINCTRL_PIN(TEGRA_PIN_PI7, "PI7"),
+       PINCTRL_PIN(TEGRA_PIN_PJ0, "PJ0"),
+       PINCTRL_PIN(TEGRA_PIN_PJ2, "PJ2"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"),
+       PINCTRL_PIN(TEGRA_PIN_PJ7, "PJ7"),
+       PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"),
+       PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"),
+       PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"),
+       PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"),
+       PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"),
+       PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW16_PT0, "KB_ROW16 PT0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW17_PT1, "KB_ROW17 PT1"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"),
+       PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"),
+       PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"),
+       PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"),
+       PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"),
+       PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"),
+       PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"),
+       PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"),
+       PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"),
+       PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"),
+       PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"),
+       PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"),
+       PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"),
+       PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"),
+       PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"),
+       PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"),
+       PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"),
+       PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"),
+       PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"),
+       PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"),
+       PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"),
+       PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"),
+       PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"),
+       PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"),
+       PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"),
+       PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_REQ_PEE2, "DAP_MCLK1_REQ PEE2"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"),
+       PINCTRL_PIN(TEGRA_PIN_DP_HPD_PFF0, "DP_HPD PFF0"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN2_PFF1, "USB_VBUS_EN2 PFF1"),
+       PINCTRL_PIN(TEGRA_PIN_PFF2, "PFF2"),
+       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"),
+       PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"),
+       PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_P, "DSI_B_CLK_P"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_N, "DSI_B_CLK_N"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_P, "DSI_B_D0_P"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_N, "DSI_B_D0_N"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_P, "DSI_B_D1_P"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_N, "DSI_B_D1_N"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_P, "DSI_B_D2_P"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_N, "DSI_B_D2_N"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_P, "DSI_B_D3_P"),
+       PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_N, "DSI_B_D3_N"),
+};
+
+static const unsigned clk_32k_out_pa0_pins[] = {
+       TEGRA_PIN_CLK_32K_OUT_PA0,
+};
+
+static const unsigned uart3_cts_n_pa1_pins[] = {
+       TEGRA_PIN_UART3_CTS_N_PA1,
+};
+
+static const unsigned dap2_fs_pa2_pins[] = {
+       TEGRA_PIN_DAP2_FS_PA2,
+};
+
+static const unsigned dap2_sclk_pa3_pins[] = {
+       TEGRA_PIN_DAP2_SCLK_PA3,
+};
+
+static const unsigned dap2_din_pa4_pins[] = {
+       TEGRA_PIN_DAP2_DIN_PA4,
+};
+
+static const unsigned dap2_dout_pa5_pins[] = {
+       TEGRA_PIN_DAP2_DOUT_PA5,
+};
+
+static const unsigned sdmmc3_clk_pa6_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PA6,
+};
+
+static const unsigned sdmmc3_cmd_pa7_pins[] = {
+       TEGRA_PIN_SDMMC3_CMD_PA7,
+};
+
+static const unsigned pb0_pins[] = {
+       TEGRA_PIN_PB0,
+};
+
+static const unsigned pb1_pins[] = {
+       TEGRA_PIN_PB1,
+};
+
+static const unsigned sdmmc3_dat3_pb4_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT3_PB4,
+};
+
+static const unsigned sdmmc3_dat2_pb5_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT2_PB5,
+};
+
+static const unsigned sdmmc3_dat1_pb6_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT1_PB6,
+};
+
+static const unsigned sdmmc3_dat0_pb7_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT0_PB7,
+};
+
+static const unsigned uart3_rts_n_pc0_pins[] = {
+       TEGRA_PIN_UART3_RTS_N_PC0,
+};
+
+static const unsigned uart2_txd_pc2_pins[] = {
+       TEGRA_PIN_UART2_TXD_PC2,
+};
+
+static const unsigned uart2_rxd_pc3_pins[] = {
+       TEGRA_PIN_UART2_RXD_PC3,
+};
+
+static const unsigned gen1_i2c_scl_pc4_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PC4,
+};
+
+static const unsigned gen1_i2c_sda_pc5_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SDA_PC5,
+};
+
+static const unsigned pc7_pins[] = {
+       TEGRA_PIN_PC7,
+};
+
+static const unsigned pg0_pins[] = {
+       TEGRA_PIN_PG0,
+};
+
+static const unsigned pg1_pins[] = {
+       TEGRA_PIN_PG1,
+};
+
+static const unsigned pg2_pins[] = {
+       TEGRA_PIN_PG2,
+};
+
+static const unsigned pg3_pins[] = {
+       TEGRA_PIN_PG3,
+};
+
+static const unsigned pg4_pins[] = {
+       TEGRA_PIN_PG4,
+};
+
+static const unsigned pg5_pins[] = {
+       TEGRA_PIN_PG5,
+};
+
+static const unsigned pg6_pins[] = {
+       TEGRA_PIN_PG6,
+};
+
+static const unsigned pg7_pins[] = {
+       TEGRA_PIN_PG7,
+};
+
+static const unsigned ph0_pins[] = {
+       TEGRA_PIN_PH0,
+};
+
+static const unsigned ph1_pins[] = {
+       TEGRA_PIN_PH1,
+};
+
+static const unsigned ph2_pins[] = {
+       TEGRA_PIN_PH2,
+};
+
+static const unsigned ph3_pins[] = {
+       TEGRA_PIN_PH3,
+};
+
+static const unsigned ph4_pins[] = {
+       TEGRA_PIN_PH4,
+};
+
+static const unsigned ph5_pins[] = {
+       TEGRA_PIN_PH5,
+};
+
+static const unsigned ph6_pins[] = {
+       TEGRA_PIN_PH6,
+};
+
+static const unsigned ph7_pins[] = {
+       TEGRA_PIN_PH7,
+};
+
+static const unsigned pi0_pins[] = {
+       TEGRA_PIN_PI0,
+};
+
+static const unsigned pi1_pins[] = {
+       TEGRA_PIN_PI1,
+};
+
+static const unsigned pi2_pins[] = {
+       TEGRA_PIN_PI2,
+};
+
+static const unsigned pi3_pins[] = {
+       TEGRA_PIN_PI3,
+};
+
+static const unsigned pi4_pins[] = {
+       TEGRA_PIN_PI4,
+};
+
+static const unsigned pi5_pins[] = {
+       TEGRA_PIN_PI5,
+};
+
+static const unsigned pi6_pins[] = {
+       TEGRA_PIN_PI6,
+};
+
+static const unsigned pi7_pins[] = {
+       TEGRA_PIN_PI7,
+};
+
+static const unsigned pj0_pins[] = {
+       TEGRA_PIN_PJ0,
+};
+
+static const unsigned pj2_pins[] = {
+       TEGRA_PIN_PJ2,
+};
+
+static const unsigned uart2_cts_n_pj5_pins[] = {
+       TEGRA_PIN_UART2_CTS_N_PJ5,
+};
+
+static const unsigned uart2_rts_n_pj6_pins[] = {
+       TEGRA_PIN_UART2_RTS_N_PJ6,
+};
+
+static const unsigned pj7_pins[] = {
+       TEGRA_PIN_PJ7,
+};
+
+static const unsigned pk0_pins[] = {
+       TEGRA_PIN_PK0,
+};
+
+static const unsigned pk1_pins[] = {
+       TEGRA_PIN_PK1,
+};
+
+static const unsigned pk2_pins[] = {
+       TEGRA_PIN_PK2,
+};
+
+static const unsigned pk3_pins[] = {
+       TEGRA_PIN_PK3,
+};
+
+static const unsigned pk4_pins[] = {
+       TEGRA_PIN_PK4,
+};
+
+static const unsigned spdif_out_pk5_pins[] = {
+       TEGRA_PIN_SPDIF_OUT_PK5,
+};
+
+static const unsigned spdif_in_pk6_pins[] = {
+       TEGRA_PIN_SPDIF_IN_PK6,
+};
+
+static const unsigned pk7_pins[] = {
+       TEGRA_PIN_PK7,
+};
+
+static const unsigned dap1_fs_pn0_pins[] = {
+       TEGRA_PIN_DAP1_FS_PN0,
+};
+
+static const unsigned dap1_din_pn1_pins[] = {
+       TEGRA_PIN_DAP1_DIN_PN1,
+};
+
+static const unsigned dap1_dout_pn2_pins[] = {
+       TEGRA_PIN_DAP1_DOUT_PN2,
+};
+
+static const unsigned dap1_sclk_pn3_pins[] = {
+       TEGRA_PIN_DAP1_SCLK_PN3,
+};
+
+static const unsigned usb_vbus_en0_pn4_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN0_PN4,
+};
+
+static const unsigned usb_vbus_en1_pn5_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN1_PN5,
+};
+
+static const unsigned hdmi_int_pn7_pins[] = {
+       TEGRA_PIN_HDMI_INT_PN7,
+};
+
+static const unsigned ulpi_data7_po0_pins[] = {
+       TEGRA_PIN_ULPI_DATA7_PO0,
+};
+
+static const unsigned ulpi_data0_po1_pins[] = {
+       TEGRA_PIN_ULPI_DATA0_PO1,
+};
+
+static const unsigned ulpi_data1_po2_pins[] = {
+       TEGRA_PIN_ULPI_DATA1_PO2,
+};
+
+static const unsigned ulpi_data2_po3_pins[] = {
+       TEGRA_PIN_ULPI_DATA2_PO3,
+};
+
+static const unsigned ulpi_data3_po4_pins[] = {
+       TEGRA_PIN_ULPI_DATA3_PO4,
+};
+
+static const unsigned ulpi_data4_po5_pins[] = {
+       TEGRA_PIN_ULPI_DATA4_PO5,
+};
+
+static const unsigned ulpi_data5_po6_pins[] = {
+       TEGRA_PIN_ULPI_DATA5_PO6,
+};
+
+static const unsigned ulpi_data6_po7_pins[] = {
+       TEGRA_PIN_ULPI_DATA6_PO7,
+};
+
+static const unsigned dap3_fs_pp0_pins[] = {
+       TEGRA_PIN_DAP3_FS_PP0,
+};
+
+static const unsigned dap3_din_pp1_pins[] = {
+       TEGRA_PIN_DAP3_DIN_PP1,
+};
+
+static const unsigned dap3_dout_pp2_pins[] = {
+       TEGRA_PIN_DAP3_DOUT_PP2,
+};
+
+static const unsigned dap3_sclk_pp3_pins[] = {
+       TEGRA_PIN_DAP3_SCLK_PP3,
+};
+
+static const unsigned dap4_fs_pp4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PP4,
+};
+
+static const unsigned dap4_din_pp5_pins[] = {
+       TEGRA_PIN_DAP4_DIN_PP5,
+};
+
+static const unsigned dap4_dout_pp6_pins[] = {
+       TEGRA_PIN_DAP4_DOUT_PP6,
+};
+
+static const unsigned dap4_sclk_pp7_pins[] = {
+       TEGRA_PIN_DAP4_SCLK_PP7,
+};
+
+static const unsigned kb_col0_pq0_pins[] = {
+       TEGRA_PIN_KB_COL0_PQ0,
+};
+
+static const unsigned kb_col1_pq1_pins[] = {
+       TEGRA_PIN_KB_COL1_PQ1,
+};
+
+static const unsigned kb_col2_pq2_pins[] = {
+       TEGRA_PIN_KB_COL2_PQ2,
+};
+
+static const unsigned kb_col3_pq3_pins[] = {
+       TEGRA_PIN_KB_COL3_PQ3,
+};
+
+static const unsigned kb_col4_pq4_pins[] = {
+       TEGRA_PIN_KB_COL4_PQ4,
+};
+
+static const unsigned kb_col5_pq5_pins[] = {
+       TEGRA_PIN_KB_COL5_PQ5,
+};
+
+static const unsigned kb_col6_pq6_pins[] = {
+       TEGRA_PIN_KB_COL6_PQ6,
+};
+
+static const unsigned kb_col7_pq7_pins[] = {
+       TEGRA_PIN_KB_COL7_PQ7,
+};
+
+static const unsigned kb_row0_pr0_pins[] = {
+       TEGRA_PIN_KB_ROW0_PR0,
+};
+
+static const unsigned kb_row1_pr1_pins[] = {
+       TEGRA_PIN_KB_ROW1_PR1,
+};
+
+static const unsigned kb_row2_pr2_pins[] = {
+       TEGRA_PIN_KB_ROW2_PR2,
+};
+
+static const unsigned kb_row3_pr3_pins[] = {
+       TEGRA_PIN_KB_ROW3_PR3,
+};
+
+static const unsigned kb_row4_pr4_pins[] = {
+       TEGRA_PIN_KB_ROW4_PR4,
+};
+
+static const unsigned kb_row5_pr5_pins[] = {
+       TEGRA_PIN_KB_ROW5_PR5,
+};
+
+static const unsigned kb_row6_pr6_pins[] = {
+       TEGRA_PIN_KB_ROW6_PR6,
+};
+
+static const unsigned kb_row7_pr7_pins[] = {
+       TEGRA_PIN_KB_ROW7_PR7,
+};
+
+static const unsigned kb_row8_ps0_pins[] = {
+       TEGRA_PIN_KB_ROW8_PS0,
+};
+
+static const unsigned kb_row9_ps1_pins[] = {
+       TEGRA_PIN_KB_ROW9_PS1,
+};
+
+static const unsigned kb_row10_ps2_pins[] = {
+       TEGRA_PIN_KB_ROW10_PS2,
+};
+
+static const unsigned kb_row11_ps3_pins[] = {
+       TEGRA_PIN_KB_ROW11_PS3,
+};
+
+static const unsigned kb_row12_ps4_pins[] = {
+       TEGRA_PIN_KB_ROW12_PS4,
+};
+
+static const unsigned kb_row13_ps5_pins[] = {
+       TEGRA_PIN_KB_ROW13_PS5,
+};
+
+static const unsigned kb_row14_ps6_pins[] = {
+       TEGRA_PIN_KB_ROW14_PS6,
+};
+
+static const unsigned kb_row15_ps7_pins[] = {
+       TEGRA_PIN_KB_ROW15_PS7,
+};
+
+static const unsigned kb_row16_pt0_pins[] = {
+       TEGRA_PIN_KB_ROW16_PT0,
+};
+
+static const unsigned kb_row17_pt1_pins[] = {
+       TEGRA_PIN_KB_ROW17_PT1,
+};
+
+static const unsigned gen2_i2c_scl_pt5_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PT5,
+};
+
+static const unsigned gen2_i2c_sda_pt6_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SDA_PT6,
+};
+
+static const unsigned sdmmc4_cmd_pt7_pins[] = {
+       TEGRA_PIN_SDMMC4_CMD_PT7,
+};
+
+static const unsigned pu0_pins[] = {
+       TEGRA_PIN_PU0,
+};
+
+static const unsigned pu1_pins[] = {
+       TEGRA_PIN_PU1,
+};
+
+static const unsigned pu2_pins[] = {
+       TEGRA_PIN_PU2,
+};
+
+static const unsigned pu3_pins[] = {
+       TEGRA_PIN_PU3,
+};
+
+static const unsigned pu4_pins[] = {
+       TEGRA_PIN_PU4,
+};
+
+static const unsigned pu5_pins[] = {
+       TEGRA_PIN_PU5,
+};
+
+static const unsigned pu6_pins[] = {
+       TEGRA_PIN_PU6,
+};
+
+static const unsigned pv0_pins[] = {
+       TEGRA_PIN_PV0,
+};
+
+static const unsigned pv1_pins[] = {
+       TEGRA_PIN_PV1,
+};
+
+static const unsigned sdmmc3_cd_n_pv2_pins[] = {
+       TEGRA_PIN_SDMMC3_CD_N_PV2,
+};
+
+static const unsigned sdmmc1_wp_n_pv3_pins[] = {
+       TEGRA_PIN_SDMMC1_WP_N_PV3,
+};
+
+static const unsigned ddc_scl_pv4_pins[] = {
+       TEGRA_PIN_DDC_SCL_PV4,
+};
+
+static const unsigned ddc_sda_pv5_pins[] = {
+       TEGRA_PIN_DDC_SDA_PV5,
+};
+
+static const unsigned gpio_w2_aud_pw2_pins[] = {
+       TEGRA_PIN_GPIO_W2_AUD_PW2,
+};
+
+static const unsigned gpio_w3_aud_pw3_pins[] = {
+       TEGRA_PIN_GPIO_W3_AUD_PW3,
+};
+
+static const unsigned dap_mclk1_pw4_pins[] = {
+       TEGRA_PIN_DAP_MCLK1_PW4,
+};
+
+static const unsigned clk2_out_pw5_pins[] = {
+       TEGRA_PIN_CLK2_OUT_PW5,
+};
+
+static const unsigned uart3_txd_pw6_pins[] = {
+       TEGRA_PIN_UART3_TXD_PW6,
+};
+
+static const unsigned uart3_rxd_pw7_pins[] = {
+       TEGRA_PIN_UART3_RXD_PW7,
+};
+
+static const unsigned dvfs_pwm_px0_pins[] = {
+       TEGRA_PIN_DVFS_PWM_PX0,
+};
+
+static const unsigned gpio_x1_aud_px1_pins[] = {
+       TEGRA_PIN_GPIO_X1_AUD_PX1,
+};
+
+static const unsigned dvfs_clk_px2_pins[] = {
+       TEGRA_PIN_DVFS_CLK_PX2,
+};
+
+static const unsigned gpio_x3_aud_px3_pins[] = {
+       TEGRA_PIN_GPIO_X3_AUD_PX3,
+};
+
+static const unsigned gpio_x4_aud_px4_pins[] = {
+       TEGRA_PIN_GPIO_X4_AUD_PX4,
+};
+
+static const unsigned gpio_x5_aud_px5_pins[] = {
+       TEGRA_PIN_GPIO_X5_AUD_PX5,
+};
+
+static const unsigned gpio_x6_aud_px6_pins[] = {
+       TEGRA_PIN_GPIO_X6_AUD_PX6,
+};
+
+static const unsigned gpio_x7_aud_px7_pins[] = {
+       TEGRA_PIN_GPIO_X7_AUD_PX7,
+};
+
+static const unsigned ulpi_clk_py0_pins[] = {
+       TEGRA_PIN_ULPI_CLK_PY0,
+};
+
+static const unsigned ulpi_dir_py1_pins[] = {
+       TEGRA_PIN_ULPI_DIR_PY1,
+};
+
+static const unsigned ulpi_nxt_py2_pins[] = {
+       TEGRA_PIN_ULPI_NXT_PY2,
+};
+
+static const unsigned ulpi_stp_py3_pins[] = {
+       TEGRA_PIN_ULPI_STP_PY3,
+};
+
+static const unsigned sdmmc1_dat3_py4_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT3_PY4,
+};
+
+static const unsigned sdmmc1_dat2_py5_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT2_PY5,
+};
+
+static const unsigned sdmmc1_dat1_py6_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT1_PY6,
+};
+
+static const unsigned sdmmc1_dat0_py7_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT0_PY7,
+};
+
+static const unsigned sdmmc1_clk_pz0_pins[] = {
+       TEGRA_PIN_SDMMC1_CLK_PZ0,
+};
+
+static const unsigned sdmmc1_cmd_pz1_pins[] = {
+       TEGRA_PIN_SDMMC1_CMD_PZ1,
+};
+
+static const unsigned pwr_i2c_scl_pz6_pins[] = {
+       TEGRA_PIN_PWR_I2C_SCL_PZ6,
+};
+
+static const unsigned pwr_i2c_sda_pz7_pins[] = {
+       TEGRA_PIN_PWR_I2C_SDA_PZ7,
+};
+
+static const unsigned sdmmc4_dat0_paa0_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT0_PAA0,
+};
+
+static const unsigned sdmmc4_dat1_paa1_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT1_PAA1,
+};
+
+static const unsigned sdmmc4_dat2_paa2_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT2_PAA2,
+};
+
+static const unsigned sdmmc4_dat3_paa3_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT3_PAA3,
+};
+
+static const unsigned sdmmc4_dat4_paa4_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT4_PAA4,
+};
+
+static const unsigned sdmmc4_dat5_paa5_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT5_PAA5,
+};
+
+static const unsigned sdmmc4_dat6_paa6_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT6_PAA6,
+};
+
+static const unsigned sdmmc4_dat7_paa7_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT7_PAA7,
+};
+
+static const unsigned pbb0_pins[] = {
+       TEGRA_PIN_PBB0,
+};
+
+static const unsigned cam_i2c_scl_pbb1_pins[] = {
+       TEGRA_PIN_CAM_I2C_SCL_PBB1,
+};
+
+static const unsigned cam_i2c_sda_pbb2_pins[] = {
+       TEGRA_PIN_CAM_I2C_SDA_PBB2,
+};
+
+static const unsigned pbb3_pins[] = {
+       TEGRA_PIN_PBB3,
+};
+
+static const unsigned pbb4_pins[] = {
+       TEGRA_PIN_PBB4,
+};
+
+static const unsigned pbb5_pins[] = {
+       TEGRA_PIN_PBB5,
+};
+
+static const unsigned pbb6_pins[] = {
+       TEGRA_PIN_PBB6,
+};
+
+static const unsigned pbb7_pins[] = {
+       TEGRA_PIN_PBB7,
+};
+
+static const unsigned cam_mclk_pcc0_pins[] = {
+       TEGRA_PIN_CAM_MCLK_PCC0,
+};
+
+static const unsigned pcc1_pins[] = {
+       TEGRA_PIN_PCC1,
+};
+
+static const unsigned pcc2_pins[] = {
+       TEGRA_PIN_PCC2,
+};
+
+static const unsigned sdmmc4_clk_pcc4_pins[] = {
+       TEGRA_PIN_SDMMC4_CLK_PCC4,
+};
+
+static const unsigned clk2_req_pcc5_pins[] = {
+       TEGRA_PIN_CLK2_REQ_PCC5,
+};
+
+static const unsigned pex_l0_rst_n_pdd1_pins[] = {
+       TEGRA_PIN_PEX_L0_RST_N_PDD1,
+};
+
+static const unsigned pex_l0_clkreq_n_pdd2_pins[] = {
+       TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2,
+};
+
+static const unsigned pex_wake_n_pdd3_pins[] = {
+       TEGRA_PIN_PEX_WAKE_N_PDD3,
+};
+
+static const unsigned pex_l1_rst_n_pdd5_pins[] = {
+       TEGRA_PIN_PEX_L1_RST_N_PDD5,
+};
+
+static const unsigned pex_l1_clkreq_n_pdd6_pins[] = {
+       TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6,
+};
+
+static const unsigned clk3_out_pee0_pins[] = {
+       TEGRA_PIN_CLK3_OUT_PEE0,
+};
+
+static const unsigned clk3_req_pee1_pins[] = {
+       TEGRA_PIN_CLK3_REQ_PEE1,
+};
+
+static const unsigned dap_mclk1_req_pee2_pins[] = {
+       TEGRA_PIN_DAP_MCLK1_REQ_PEE2,
+};
+
+static const unsigned hdmi_cec_pee3_pins[] = {
+       TEGRA_PIN_HDMI_CEC_PEE3,
+};
+
+static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4,
+};
+
+static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5,
+};
+
+static const unsigned dp_hpd_pff0_pins[] = {
+       TEGRA_PIN_DP_HPD_PFF0,
+};
+
+static const unsigned usb_vbus_en2_pff1_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN2_PFF1,
+};
+
+static const unsigned pff2_pins[] = {
+       TEGRA_PIN_PFF2,
+};
+
+static const unsigned core_pwr_req_pins[] = {
+       TEGRA_PIN_CORE_PWR_REQ,
+};
+
+static const unsigned cpu_pwr_req_pins[] = {
+       TEGRA_PIN_CPU_PWR_REQ,
+};
+
+static const unsigned pwr_int_n_pins[] = {
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned gmi_clk_lb_pins[] = {
+       TEGRA_PIN_GMI_CLK_LB,
+};
+
+static const unsigned reset_out_n_pins[] = {
+       TEGRA_PIN_RESET_OUT_N,
+};
+
+static const unsigned owr_pins[] = {
+       TEGRA_PIN_OWR,
+};
+
+static const unsigned clk_32k_in_pins[] = {
+       TEGRA_PIN_CLK_32K_IN,
+};
+
+static const unsigned jtag_rtck_pins[] = {
+       TEGRA_PIN_JTAG_RTCK,
+};
+
+static const unsigned drive_ao1_pins[] = {
+       TEGRA_PIN_KB_ROW0_PR0,
+       TEGRA_PIN_KB_ROW1_PR1,
+       TEGRA_PIN_KB_ROW2_PR2,
+       TEGRA_PIN_KB_ROW3_PR3,
+       TEGRA_PIN_KB_ROW4_PR4,
+       TEGRA_PIN_KB_ROW5_PR5,
+       TEGRA_PIN_KB_ROW6_PR6,
+       TEGRA_PIN_KB_ROW7_PR7,
+       TEGRA_PIN_PWR_I2C_SCL_PZ6,
+       TEGRA_PIN_PWR_I2C_SDA_PZ7,
+};
+
+static const unsigned drive_ao2_pins[] = {
+       TEGRA_PIN_CLK_32K_OUT_PA0,
+       TEGRA_PIN_CLK_32K_IN,
+       TEGRA_PIN_KB_COL0_PQ0,
+       TEGRA_PIN_KB_COL1_PQ1,
+       TEGRA_PIN_KB_COL2_PQ2,
+       TEGRA_PIN_KB_COL3_PQ3,
+       TEGRA_PIN_KB_COL4_PQ4,
+       TEGRA_PIN_KB_COL5_PQ5,
+       TEGRA_PIN_KB_COL6_PQ6,
+       TEGRA_PIN_KB_COL7_PQ7,
+       TEGRA_PIN_KB_ROW8_PS0,
+       TEGRA_PIN_KB_ROW9_PS1,
+       TEGRA_PIN_KB_ROW10_PS2,
+       TEGRA_PIN_KB_ROW11_PS3,
+       TEGRA_PIN_KB_ROW12_PS4,
+       TEGRA_PIN_KB_ROW13_PS5,
+       TEGRA_PIN_KB_ROW14_PS6,
+       TEGRA_PIN_KB_ROW15_PS7,
+       TEGRA_PIN_KB_ROW16_PT0,
+       TEGRA_PIN_KB_ROW17_PT1,
+       TEGRA_PIN_SDMMC3_CD_N_PV2,
+       TEGRA_PIN_CORE_PWR_REQ,
+       TEGRA_PIN_CPU_PWR_REQ,
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned drive_at1_pins[] = {
+       TEGRA_PIN_PH0,
+       TEGRA_PIN_PH1,
+       TEGRA_PIN_PH2,
+       TEGRA_PIN_PH3,
+};
+
+static const unsigned drive_at2_pins[] = {
+       TEGRA_PIN_PG0,
+       TEGRA_PIN_PG1,
+       TEGRA_PIN_PG2,
+       TEGRA_PIN_PG3,
+       TEGRA_PIN_PG4,
+       TEGRA_PIN_PG5,
+       TEGRA_PIN_PG6,
+       TEGRA_PIN_PG7,
+       TEGRA_PIN_PI0,
+       TEGRA_PIN_PI1,
+       TEGRA_PIN_PI3,
+       TEGRA_PIN_PI4,
+       TEGRA_PIN_PI7,
+       TEGRA_PIN_PK0,
+       TEGRA_PIN_PK2,
+};
+
+static const unsigned drive_at3_pins[] = {
+       TEGRA_PIN_PC7,
+       TEGRA_PIN_PJ0,
+};
+
+static const unsigned drive_at4_pins[] = {
+       TEGRA_PIN_PB0,
+       TEGRA_PIN_PB1,
+       TEGRA_PIN_PJ0,
+       TEGRA_PIN_PJ7,
+       TEGRA_PIN_PK7,
+};
+
+static const unsigned drive_at5_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PT5,
+       TEGRA_PIN_GEN2_I2C_SDA_PT6,
+};
+
+static const unsigned drive_cdev1_pins[] = {
+       TEGRA_PIN_DAP_MCLK1_PW4,
+       TEGRA_PIN_DAP_MCLK1_REQ_PEE2,
+};
+
+static const unsigned drive_cdev2_pins[] = {
+       TEGRA_PIN_CLK2_OUT_PW5,
+       TEGRA_PIN_CLK2_REQ_PCC5,
+};
+
+static const unsigned drive_dap1_pins[] = {
+       TEGRA_PIN_DAP1_FS_PN0,
+       TEGRA_PIN_DAP1_DIN_PN1,
+       TEGRA_PIN_DAP1_DOUT_PN2,
+       TEGRA_PIN_DAP1_SCLK_PN3,
+};
+
+static const unsigned drive_dap2_pins[] = {
+       TEGRA_PIN_DAP2_FS_PA2,
+       TEGRA_PIN_DAP2_SCLK_PA3,
+       TEGRA_PIN_DAP2_DIN_PA4,
+       TEGRA_PIN_DAP2_DOUT_PA5,
+};
+
+static const unsigned drive_dap3_pins[] = {
+       TEGRA_PIN_DAP3_FS_PP0,
+       TEGRA_PIN_DAP3_DIN_PP1,
+       TEGRA_PIN_DAP3_DOUT_PP2,
+       TEGRA_PIN_DAP3_SCLK_PP3,
+};
+
+static const unsigned drive_dap4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PP4,
+       TEGRA_PIN_DAP4_DIN_PP5,
+       TEGRA_PIN_DAP4_DOUT_PP6,
+       TEGRA_PIN_DAP4_SCLK_PP7,
+};
+
+static const unsigned drive_dbg_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PC4,
+       TEGRA_PIN_GEN1_I2C_SDA_PC5,
+       TEGRA_PIN_PU0,
+       TEGRA_PIN_PU1,
+       TEGRA_PIN_PU2,
+       TEGRA_PIN_PU3,
+       TEGRA_PIN_PU4,
+       TEGRA_PIN_PU5,
+       TEGRA_PIN_PU6,
+};
+
+static const unsigned drive_sdio3_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PA6,
+       TEGRA_PIN_SDMMC3_CMD_PA7,
+       TEGRA_PIN_SDMMC3_DAT3_PB4,
+       TEGRA_PIN_SDMMC3_DAT2_PB5,
+       TEGRA_PIN_SDMMC3_DAT1_PB6,
+       TEGRA_PIN_SDMMC3_DAT0_PB7,
+       TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4,
+       TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5,
+};
+
+static const unsigned drive_spi_pins[] = {
+       TEGRA_PIN_DVFS_PWM_PX0,
+       TEGRA_PIN_GPIO_X1_AUD_PX1,
+       TEGRA_PIN_DVFS_CLK_PX2,
+       TEGRA_PIN_GPIO_X3_AUD_PX3,
+       TEGRA_PIN_GPIO_X4_AUD_PX4,
+       TEGRA_PIN_GPIO_X5_AUD_PX5,
+       TEGRA_PIN_GPIO_X6_AUD_PX6,
+       TEGRA_PIN_GPIO_X7_AUD_PX7,
+       TEGRA_PIN_GPIO_W2_AUD_PW2,
+       TEGRA_PIN_GPIO_W3_AUD_PW3,
+};
+
+static const unsigned drive_uaa_pins[] = {
+       TEGRA_PIN_ULPI_DATA0_PO1,
+       TEGRA_PIN_ULPI_DATA1_PO2,
+       TEGRA_PIN_ULPI_DATA2_PO3,
+       TEGRA_PIN_ULPI_DATA3_PO4,
+};
+
+static const unsigned drive_uab_pins[] = {
+       TEGRA_PIN_ULPI_DATA7_PO0,
+       TEGRA_PIN_ULPI_DATA4_PO5,
+       TEGRA_PIN_ULPI_DATA5_PO6,
+       TEGRA_PIN_ULPI_DATA6_PO7,
+       TEGRA_PIN_PV0,
+       TEGRA_PIN_PV1,
+};
+
+static const unsigned drive_uart2_pins[] = {
+       TEGRA_PIN_UART2_TXD_PC2,
+       TEGRA_PIN_UART2_RXD_PC3,
+       TEGRA_PIN_UART2_CTS_N_PJ5,
+       TEGRA_PIN_UART2_RTS_N_PJ6,
+};
+
+static const unsigned drive_uart3_pins[] = {
+       TEGRA_PIN_UART3_CTS_N_PA1,
+       TEGRA_PIN_UART3_RTS_N_PC0,
+       TEGRA_PIN_UART3_TXD_PW6,
+       TEGRA_PIN_UART3_RXD_PW7,
+};
+
+static const unsigned drive_sdio1_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT3_PY4,
+       TEGRA_PIN_SDMMC1_DAT2_PY5,
+       TEGRA_PIN_SDMMC1_DAT1_PY6,
+       TEGRA_PIN_SDMMC1_DAT0_PY7,
+       TEGRA_PIN_SDMMC1_CLK_PZ0,
+       TEGRA_PIN_SDMMC1_CMD_PZ1,
+};
+
+static const unsigned drive_ddc_pins[] = {
+       TEGRA_PIN_DDC_SCL_PV4,
+       TEGRA_PIN_DDC_SDA_PV5,
+};
+
+static const unsigned drive_gma_pins[] = {
+       TEGRA_PIN_SDMMC4_CLK_PCC4,
+       TEGRA_PIN_SDMMC4_CMD_PT7,
+       TEGRA_PIN_SDMMC4_DAT0_PAA0,
+       TEGRA_PIN_SDMMC4_DAT1_PAA1,
+       TEGRA_PIN_SDMMC4_DAT2_PAA2,
+       TEGRA_PIN_SDMMC4_DAT3_PAA3,
+       TEGRA_PIN_SDMMC4_DAT4_PAA4,
+       TEGRA_PIN_SDMMC4_DAT5_PAA5,
+       TEGRA_PIN_SDMMC4_DAT6_PAA6,
+       TEGRA_PIN_SDMMC4_DAT7_PAA7,
+};
+
+static const unsigned drive_gme_pins[] = {
+       TEGRA_PIN_PBB0,
+       TEGRA_PIN_CAM_I2C_SCL_PBB1,
+       TEGRA_PIN_CAM_I2C_SDA_PBB2,
+       TEGRA_PIN_PBB3,
+       TEGRA_PIN_PCC2,
+};
+
+static const unsigned drive_gmf_pins[] = {
+       TEGRA_PIN_PBB4,
+       TEGRA_PIN_PBB5,
+       TEGRA_PIN_PBB6,
+       TEGRA_PIN_PBB7,
+};
+
+static const unsigned drive_gmg_pins[] = {
+       TEGRA_PIN_CAM_MCLK_PCC0,
+};
+
+static const unsigned drive_gmh_pins[] = {
+       TEGRA_PIN_PCC1,
+};
+
+static const unsigned drive_owr_pins[] = {
+       TEGRA_PIN_SDMMC3_CD_N_PV2,
+       TEGRA_PIN_OWR,
+};
+
+static const unsigned drive_uda_pins[] = {
+       TEGRA_PIN_ULPI_CLK_PY0,
+       TEGRA_PIN_ULPI_DIR_PY1,
+       TEGRA_PIN_ULPI_NXT_PY2,
+       TEGRA_PIN_ULPI_STP_PY3,
+};
+
+static const unsigned drive_gpv_pins[] = {
+       TEGRA_PIN_PEX_L0_RST_N_PDD1,
+       TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2,
+       TEGRA_PIN_PEX_WAKE_N_PDD3,
+       TEGRA_PIN_PEX_L1_RST_N_PDD5,
+       TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6,
+       TEGRA_PIN_USB_VBUS_EN2_PFF1,
+       TEGRA_PIN_PFF2,
+};
+
+static const unsigned drive_dev3_pins[] = {
+       TEGRA_PIN_CLK3_OUT_PEE0,
+       TEGRA_PIN_CLK3_REQ_PEE1,
+};
+
+static const unsigned drive_cec_pins[] = {
+       TEGRA_PIN_HDMI_CEC_PEE3,
+};
+
+static const unsigned drive_at6_pins[] = {
+       TEGRA_PIN_PK1,
+       TEGRA_PIN_PK3,
+       TEGRA_PIN_PK4,
+       TEGRA_PIN_PI2,
+       TEGRA_PIN_PI5,
+       TEGRA_PIN_PI6,
+       TEGRA_PIN_PH4,
+       TEGRA_PIN_PH5,
+       TEGRA_PIN_PH6,
+       TEGRA_PIN_PH7,
+};
+
+static const unsigned drive_dap5_pins[] = {
+       TEGRA_PIN_SPDIF_IN_PK6,
+       TEGRA_PIN_SPDIF_OUT_PK5,
+       TEGRA_PIN_DP_HPD_PFF0,
+};
+
+static const unsigned drive_usb_vbus_en_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN0_PN4,
+       TEGRA_PIN_USB_VBUS_EN1_PN5,
+};
+
+static const unsigned drive_ao3_pins[] = {
+       TEGRA_PIN_RESET_OUT_N,
+};
+
+static const unsigned drive_ao0_pins[] = {
+       TEGRA_PIN_JTAG_RTCK,
+};
+
+static const unsigned drive_hv0_pins[] = {
+       TEGRA_PIN_HDMI_INT_PN7,
+};
+
+static const unsigned drive_sdio4_pins[] = {
+       TEGRA_PIN_SDMMC1_WP_N_PV3,
+};
+
+static const unsigned drive_ao4_pins[] = {
+       TEGRA_PIN_JTAG_RTCK,
+};
+
+static const unsigned mipi_pad_ctrl_dsi_b_pins[] = {
+       TEGRA_PIN_DSI_B_CLK_P,
+       TEGRA_PIN_DSI_B_CLK_N,
+       TEGRA_PIN_DSI_B_D0_P,
+       TEGRA_PIN_DSI_B_D0_N,
+       TEGRA_PIN_DSI_B_D1_P,
+       TEGRA_PIN_DSI_B_D1_N,
+       TEGRA_PIN_DSI_B_D2_P,
+       TEGRA_PIN_DSI_B_D2_N,
+       TEGRA_PIN_DSI_B_D3_P,
+       TEGRA_PIN_DSI_B_D3_N,
+};
+
+enum tegra_mux {
+       TEGRA_MUX_BLINK,
+       TEGRA_MUX_CCLA,
+       TEGRA_MUX_CEC,
+       TEGRA_MUX_CLDVFS,
+       TEGRA_MUX_CLK,
+       TEGRA_MUX_CLK12,
+       TEGRA_MUX_CPU,
+       TEGRA_MUX_CSI,
+       TEGRA_MUX_DAP,
+       TEGRA_MUX_DAP1,
+       TEGRA_MUX_DAP2,
+       TEGRA_MUX_DEV3,
+       TEGRA_MUX_DISPLAYA,
+       TEGRA_MUX_DISPLAYA_ALT,
+       TEGRA_MUX_DISPLAYB,
+       TEGRA_MUX_DP,
+       TEGRA_MUX_DSI_B,
+       TEGRA_MUX_DTV,
+       TEGRA_MUX_EXTPERIPH1,
+       TEGRA_MUX_EXTPERIPH2,
+       TEGRA_MUX_EXTPERIPH3,
+       TEGRA_MUX_GMI,
+       TEGRA_MUX_GMI_ALT,
+       TEGRA_MUX_HDA,
+       TEGRA_MUX_HSI,
+       TEGRA_MUX_I2C1,
+       TEGRA_MUX_I2C2,
+       TEGRA_MUX_I2C3,
+       TEGRA_MUX_I2C4,
+       TEGRA_MUX_I2CPWR,
+       TEGRA_MUX_I2S0,
+       TEGRA_MUX_I2S1,
+       TEGRA_MUX_I2S2,
+       TEGRA_MUX_I2S3,
+       TEGRA_MUX_I2S4,
+       TEGRA_MUX_IRDA,
+       TEGRA_MUX_KBC,
+       TEGRA_MUX_OWR,
+       TEGRA_MUX_PE,
+       TEGRA_MUX_PE0,
+       TEGRA_MUX_PE1,
+       TEGRA_MUX_PMI,
+       TEGRA_MUX_PWM0,
+       TEGRA_MUX_PWM1,
+       TEGRA_MUX_PWM2,
+       TEGRA_MUX_PWM3,
+       TEGRA_MUX_PWRON,
+       TEGRA_MUX_RESET_OUT_N,
+       TEGRA_MUX_RSVD1,
+       TEGRA_MUX_RSVD2,
+       TEGRA_MUX_RSVD3,
+       TEGRA_MUX_RSVD4,
+       TEGRA_MUX_RTCK,
+       TEGRA_MUX_SATA,
+       TEGRA_MUX_SDMMC1,
+       TEGRA_MUX_SDMMC2,
+       TEGRA_MUX_SDMMC3,
+       TEGRA_MUX_SDMMC4,
+       TEGRA_MUX_SOC,
+       TEGRA_MUX_SPDIF,
+       TEGRA_MUX_SPI1,
+       TEGRA_MUX_SPI2,
+       TEGRA_MUX_SPI3,
+       TEGRA_MUX_SPI4,
+       TEGRA_MUX_SPI5,
+       TEGRA_MUX_SPI6,
+       TEGRA_MUX_SYS,
+       TEGRA_MUX_TMDS,
+       TEGRA_MUX_TRACE,
+       TEGRA_MUX_UARTA,
+       TEGRA_MUX_UARTB,
+       TEGRA_MUX_UARTC,
+       TEGRA_MUX_UARTD,
+       TEGRA_MUX_ULPI,
+       TEGRA_MUX_USB,
+       TEGRA_MUX_VGP1,
+       TEGRA_MUX_VGP2,
+       TEGRA_MUX_VGP3,
+       TEGRA_MUX_VGP4,
+       TEGRA_MUX_VGP5,
+       TEGRA_MUX_VGP6,
+       TEGRA_MUX_VI,
+       TEGRA_MUX_VI_ALT1,
+       TEGRA_MUX_VI_ALT3,
+       TEGRA_MUX_VIMCLK2,
+       TEGRA_MUX_VIMCLK2_ALT,
+};
+
+#define FUNCTION(fname)                                        \
+       {                                               \
+               .name = #fname,                         \
+       }
+
+static struct tegra_function tegra124_functions[] = {
+       FUNCTION(blink),
+       FUNCTION(ccla),
+       FUNCTION(cec),
+       FUNCTION(cldvfs),
+       FUNCTION(clk),
+       FUNCTION(clk12),
+       FUNCTION(cpu),
+       FUNCTION(csi),
+       FUNCTION(dap),
+       FUNCTION(dap1),
+       FUNCTION(dap2),
+       FUNCTION(dev3),
+       FUNCTION(displaya),
+       FUNCTION(displaya_alt),
+       FUNCTION(displayb),
+       FUNCTION(dp),
+       FUNCTION(dsi_b),
+       FUNCTION(dtv),
+       FUNCTION(extperiph1),
+       FUNCTION(extperiph2),
+       FUNCTION(extperiph3),
+       FUNCTION(gmi),
+       FUNCTION(gmi_alt),
+       FUNCTION(hda),
+       FUNCTION(hsi),
+       FUNCTION(i2c1),
+       FUNCTION(i2c2),
+       FUNCTION(i2c3),
+       FUNCTION(i2c4),
+       FUNCTION(i2cpwr),
+       FUNCTION(i2s0),
+       FUNCTION(i2s1),
+       FUNCTION(i2s2),
+       FUNCTION(i2s3),
+       FUNCTION(i2s4),
+       FUNCTION(irda),
+       FUNCTION(kbc),
+       FUNCTION(owr),
+       FUNCTION(pe),
+       FUNCTION(pe0),
+       FUNCTION(pe1),
+       FUNCTION(pmi),
+       FUNCTION(pwm0),
+       FUNCTION(pwm1),
+       FUNCTION(pwm2),
+       FUNCTION(pwm3),
+       FUNCTION(pwron),
+       FUNCTION(reset_out_n),
+       FUNCTION(rsvd1),
+       FUNCTION(rsvd2),
+       FUNCTION(rsvd3),
+       FUNCTION(rsvd4),
+       FUNCTION(rtck),
+       FUNCTION(sata),
+       FUNCTION(sdmmc1),
+       FUNCTION(sdmmc2),
+       FUNCTION(sdmmc3),
+       FUNCTION(sdmmc4),
+       FUNCTION(soc),
+       FUNCTION(spdif),
+       FUNCTION(spi1),
+       FUNCTION(spi2),
+       FUNCTION(spi3),
+       FUNCTION(spi4),
+       FUNCTION(spi5),
+       FUNCTION(spi6),
+       FUNCTION(sys),
+       FUNCTION(tmds),
+       FUNCTION(trace),
+       FUNCTION(uarta),
+       FUNCTION(uartb),
+       FUNCTION(uartc),
+       FUNCTION(uartd),
+       FUNCTION(ulpi),
+       FUNCTION(usb),
+       FUNCTION(vgp1),
+       FUNCTION(vgp2),
+       FUNCTION(vgp3),
+       FUNCTION(vgp4),
+       FUNCTION(vgp5),
+       FUNCTION(vgp6),
+       FUNCTION(vi),
+       FUNCTION(vi_alt1),
+       FUNCTION(vi_alt3),
+       FUNCTION(vimclk2),
+       FUNCTION(vimclk2_alt),
+};
+
+#define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
+#define PINGROUP_REG_A                 0x3000  /* bank 1 */
+#define MIPI_PAD_CTRL_PINGROUP_REG_A   0x820   /* bank 2 */
+
+#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
+#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
+#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r)        ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A)
+
+#define PINGROUP_BIT_Y(b)              (b)
+#define PINGROUP_BIT_N(b)              (-1)
+
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel)         \
+       {                                                               \
+               .name = #pg_name,                                       \
+               .pins = pg_name##_pins,                                 \
+               .npins = ARRAY_SIZE(pg_name##_pins),                    \
+               .funcs = {                                              \
+                       TEGRA_MUX_##f0,                                 \
+                       TEGRA_MUX_##f1,                                 \
+                       TEGRA_MUX_##f2,                                 \
+                       TEGRA_MUX_##f3,                                 \
+               },                                                      \
+               .mux_reg = PINGROUP_REG(r),                             \
+               .mux_bank = 1,                                          \
+               .mux_bit = 0,                                           \
+               .pupd_reg = PINGROUP_REG(r),                            \
+               .pupd_bank = 1,                                         \
+               .pupd_bit = 2,                                          \
+               .tri_reg = PINGROUP_REG(r),                             \
+               .tri_bank = 1,                                          \
+               .tri_bit = 4,                                           \
+               .einput_bit = 5,                                        \
+               .odrain_bit = PINGROUP_BIT_##od(6),                     \
+               .lock_bit = 7,                                          \
+               .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
+               .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9),               \
+               .drv_reg = -1,                                          \
+       }
+
+#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
+                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
+                    slwf_b, slwf_w, drvtype)                           \
+       {                                                               \
+               .name = "drive_" #pg_name,                              \
+               .pins = drive_##pg_name##_pins,                         \
+               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
+               .mux_reg = -1,                                          \
+               .pupd_reg = -1,                                         \
+               .tri_reg = -1,                                          \
+               .einput_bit = -1,                                       \
+               .odrain_bit = -1,                                       \
+               .lock_bit = -1,                                         \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = DRV_PINGROUP_REG(r),                         \
+               .drv_bank = 0,                                          \
+               .hsm_bit = hsm_b,                                       \
+               .schmitt_bit = schmitt_b,                               \
+               .lpmd_bit = lpmd_b,                                     \
+               .drvdn_bit = drvdn_b,                                   \
+               .drvdn_width = drvdn_w,                                 \
+               .drvup_bit = drvup_b,                                   \
+               .drvup_width = drvup_w,                                 \
+               .slwr_bit = slwr_b,                                     \
+               .slwr_width = slwr_w,                                   \
+               .slwf_bit = slwf_b,                                     \
+               .slwf_width = slwf_w,                                   \
+               .drvtype_bit = PINGROUP_BIT_##drvtype(6),               \
+       }
+
+#define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1)                  \
+       {                                                               \
+               .name = "mipi_pad_ctrl_" #pg_name,                      \
+               .pins = mipi_pad_ctrl_##pg_name##_pins,                 \
+               .npins = ARRAY_SIZE(mipi_pad_ctrl_##pg_name##_pins),    \
+               .funcs = {                                              \
+                       TEGRA_MUX_ ## f0,                               \
+                       TEGRA_MUX_ ## f1,                               \
+                       TEGRA_MUX_RSVD3,                                \
+                       TEGRA_MUX_RSVD4,                                \
+               },                                                      \
+               .mux_reg = MIPI_PAD_CTRL_PINGROUP_REG_Y(r),             \
+               .mux_bank = 2,                                          \
+               .mux_bit = b,                                           \
+               .pupd_reg = -1,                                         \
+               .tri_reg = -1,                                          \
+               .einput_bit = -1,                                       \
+               .odrain_bit = -1,                                       \
+               .lock_bit = -1,                                         \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = -1,                                          \
+       }
+
+static const struct tegra_pingroup tegra124_groups[] = {
+       /*       pg_name,                f0,         f1,         f2,           f3,          r,      od, ior, rcv_sel */
+       PINGROUP(ulpi_data0_po1,         SPI3,       HSI,        UARTA,        ULPI,        0x3000, N,   N,  N),
+       PINGROUP(ulpi_data1_po2,         SPI3,       HSI,        UARTA,        ULPI,        0x3004, N,   N,  N),
+       PINGROUP(ulpi_data2_po3,         SPI3,       HSI,        UARTA,        ULPI,        0x3008, N,   N,  N),
+       PINGROUP(ulpi_data3_po4,         SPI3,       HSI,        UARTA,        ULPI,        0x300c, N,   N,  N),
+       PINGROUP(ulpi_data4_po5,         SPI2,       HSI,        UARTA,        ULPI,        0x3010, N,   N,  N),
+       PINGROUP(ulpi_data5_po6,         SPI2,       HSI,        UARTA,        ULPI,        0x3014, N,   N,  N),
+       PINGROUP(ulpi_data6_po7,         SPI2,       HSI,        UARTA,        ULPI,        0x3018, N,   N,  N),
+       PINGROUP(ulpi_data7_po0,         SPI2,       HSI,        UARTA,        ULPI,        0x301c, N,   N,  N),
+       PINGROUP(ulpi_clk_py0,           SPI1,       SPI5,       UARTD,        ULPI,        0x3020, N,   N,  N),
+       PINGROUP(ulpi_dir_py1,           SPI1,       SPI5,       UARTD,        ULPI,        0x3024, N,   N,  N),
+       PINGROUP(ulpi_nxt_py2,           SPI1,       SPI5,       UARTD,        ULPI,        0x3028, N,   N,  N),
+       PINGROUP(ulpi_stp_py3,           SPI1,       SPI5,       UARTD,        ULPI,        0x302c, N,   N,  N),
+       PINGROUP(dap3_fs_pp0,            I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3030, N,   N,  N),
+       PINGROUP(dap3_din_pp1,           I2S2,       SPI5,       DISPLAYA,     DISPLAYB,    0x3034, N,   N,  N),
+       PINGROUP(dap3_dout_pp2,          I2S2,       SPI5,       DISPLAYA,     RSVD4,       0x3038, N,   N,  N),
+       PINGROUP(dap3_sclk_pp3,          I2S2,       SPI5,       RSVD3,        DISPLAYB,    0x303c, N,   N,  N),
+       PINGROUP(pv0,                    RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3040, N,   N,  N),
+       PINGROUP(pv1,                    RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3044, N,   N,  N),
+       PINGROUP(sdmmc1_clk_pz0,         SDMMC1,     CLK12,      RSVD3,        RSVD4,       0x3048, N,   N,  N),
+       PINGROUP(sdmmc1_cmd_pz1,         SDMMC1,     SPDIF,      SPI4,         UARTA,       0x304c, N,   N,  N),
+       PINGROUP(sdmmc1_dat3_py4,        SDMMC1,     SPDIF,      SPI4,         UARTA,       0x3050, N,   N,  N),
+       PINGROUP(sdmmc1_dat2_py5,        SDMMC1,     PWM0,       SPI4,         UARTA,       0x3054, N,   N,  N),
+       PINGROUP(sdmmc1_dat1_py6,        SDMMC1,     PWM1,       SPI4,         UARTA,       0x3058, N,   N,  N),
+       PINGROUP(sdmmc1_dat0_py7,        SDMMC1,     RSVD2,      SPI4,         UARTA,       0x305c, N,   N,  N),
+       PINGROUP(clk2_out_pw5,           EXTPERIPH2, RSVD2,      RSVD3,        RSVD4,       0x3068, N,   N,  N),
+       PINGROUP(clk2_req_pcc5,          DAP,        RSVD2,      RSVD3,        RSVD4,       0x306c, N,   N,  N),
+       PINGROUP(hdmi_int_pn7,           RSVD1,      RSVD2,      RSVD3,        RSVD4,       0x3110, N,   N,  Y),
+       PINGROUP(ddc_scl_pv4,            I2C4,       RSVD2,      RSVD3,        RSVD4,       0x3114, N,   N,  Y),
+       PINGROUP(ddc_sda_pv5,            I2C4,       RSVD2,      RSVD3,        RSVD4,       0x3118, N,   N,  Y),
+       PINGROUP(uart2_rxd_pc3,          IRDA,       SPDIF,      UARTA,        SPI4,        0x3164, N,   N,  N),
+       PINGROUP(uart2_txd_pc2,          IRDA,       SPDIF,      UARTA,        SPI4,        0x3168, N,   N,  N),
+       PINGROUP(uart2_rts_n_pj6,        UARTA,      UARTB,      GMI,          SPI4,        0x316c, N,   N,  N),
+       PINGROUP(uart2_cts_n_pj5,        UARTA,      UARTB,      GMI,          SPI4,        0x3170, N,   N,  N),
+       PINGROUP(uart3_txd_pw6,          UARTC,      RSVD2,      GMI,          SPI4,        0x3174, N,   N,  N),
+       PINGROUP(uart3_rxd_pw7,          UARTC,      RSVD2,      GMI,          SPI4,        0x3178, N,   N,  N),
+       PINGROUP(uart3_cts_n_pa1,        UARTC,      SDMMC1,     DTV,          GMI,         0x317c, N,   N,  N),
+       PINGROUP(uart3_rts_n_pc0,        UARTC,      PWM0,       DTV,          GMI,         0x3180, N,   N,  N),
+       PINGROUP(pu0,                    OWR,        UARTA,      GMI,          RSVD4,       0x3184, N,   N,  N),
+       PINGROUP(pu1,                    RSVD1,      UARTA,      GMI,          RSVD4,       0x3188, N,   N,  N),
+       PINGROUP(pu2,                    RSVD1,      UARTA,      GMI,          RSVD4,       0x318c, N,   N,  N),
+       PINGROUP(pu3,                    PWM0,       UARTA,      GMI,          DISPLAYB,    0x3190, N,   N,  N),
+       PINGROUP(pu4,                    PWM1,       UARTA,      GMI,          DISPLAYB,    0x3194, N,   N,  N),
+       PINGROUP(pu5,                    PWM2,       UARTA,      GMI,          DISPLAYB,    0x3198, N,   N,  N),
+       PINGROUP(pu6,                    PWM3,       UARTA,      RSVD3,        GMI,         0x319c, N,   N,  N),
+       PINGROUP(gen1_i2c_sda_pc5,       I2C1,       RSVD2,      RSVD3,        RSVD4,       0x31a0, Y,   N,  N),
+       PINGROUP(gen1_i2c_scl_pc4,       I2C1,       RSVD2,      RSVD3,        RSVD4,       0x31a4, Y,   N,  N),
+       PINGROUP(dap4_fs_pp4,            I2S3,       GMI,        DTV,          RSVD4,       0x31a8, N,   N,  N),
+       PINGROUP(dap4_din_pp5,           I2S3,       GMI,        RSVD3,        RSVD4,       0x31ac, N,   N,  N),
+       PINGROUP(dap4_dout_pp6,          I2S3,       GMI,        DTV,          RSVD4,       0x31b0, N,   N,  N),
+       PINGROUP(dap4_sclk_pp7,          I2S3,       GMI,        RSVD3,        RSVD4,       0x31b4, N,   N,  N),
+       PINGROUP(clk3_out_pee0,          EXTPERIPH3, RSVD2,      RSVD3,        RSVD4,       0x31b8, N,   N,  N),
+       PINGROUP(clk3_req_pee1,          DEV3,       RSVD2,      RSVD3,        RSVD4,       0x31bc, N,   N,  N),
+       PINGROUP(pc7,                    RSVD1,      RSVD2,      GMI,          GMI_ALT,     0x31c0, N,   N,  N),
+       PINGROUP(pi5,                    SDMMC2,     RSVD2,      GMI,          RSVD4,       0x31c4, N,   N,  N),
+       PINGROUP(pi7,                    RSVD1,      TRACE,      GMI,          DTV,         0x31c8, N,   N,  N),
+       PINGROUP(pk0,                    RSVD1,      SDMMC3,     GMI,          SOC,         0x31cc, N,   N,  N),
+       PINGROUP(pk1,                    SDMMC2,     TRACE,      GMI,          RSVD4,       0x31d0, N,   N,  N),
+       PINGROUP(pj0,                    RSVD1,      RSVD2,      GMI,          USB,         0x31d4, N,   N,  N),
+       PINGROUP(pj2,                    RSVD1,      RSVD2,      GMI,          SOC,         0x31d8, N,   N,  N),
+       PINGROUP(pk3,                    SDMMC2,     TRACE,      GMI,          CCLA,        0x31dc, N,   N,  N),
+       PINGROUP(pk4,                    SDMMC2,     RSVD2,      GMI,          GMI_ALT,     0x31e0, N,   N,  N),
+       PINGROUP(pk2,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x31e4, N,   N,  N),
+       PINGROUP(pi3,                    RSVD1,      RSVD2,      GMI,          SPI4,        0x31e8, N,   N,  N),
+       PINGROUP(pi6,                    RSVD1,      RSVD2,      GMI,          SDMMC2,      0x31ec, N,   N,  N),
+       PINGROUP(pg0,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x31f0, N,   N,  N),
+       PINGROUP(pg1,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x31f4, N,   N,  N),
+       PINGROUP(pg2,                    RSVD1,      TRACE,      GMI,          RSVD4,       0x31f8, N,   N,  N),
+       PINGROUP(pg3,                    RSVD1,      TRACE,      GMI,          RSVD4,       0x31fc, N,   N,  N),
+       PINGROUP(pg4,                    RSVD1,      TMDS,       GMI,          SPI4,        0x3200, N,   N,  N),
+       PINGROUP(pg5,                    RSVD1,      RSVD2,      GMI,          SPI4,        0x3204, N,   N,  N),
+       PINGROUP(pg6,                    RSVD1,      RSVD2,      GMI,          SPI4,        0x3208, N,   N,  N),
+       PINGROUP(pg7,                    RSVD1,      RSVD2,      GMI,          SPI4,        0x320c, N,   N,  N),
+       PINGROUP(ph0,                    PWM0,       TRACE,      GMI,          DTV,         0x3210, N,   N,  N),
+       PINGROUP(ph1,                    PWM1,       TMDS,       GMI,          DISPLAYA,    0x3214, N,   N,  N),
+       PINGROUP(ph2,                    PWM2,       TMDS,       GMI,          CLDVFS,      0x3218, N,   N,  N),
+       PINGROUP(ph3,                    PWM3,       SPI4,       GMI,          CLDVFS,      0x321c, N,   N,  N),
+       PINGROUP(ph4,                    SDMMC2,     RSVD2,      GMI,          RSVD4,       0x3220, N,   N,  N),
+       PINGROUP(ph5,                    SDMMC2,     RSVD2,      GMI,          RSVD4,       0x3224, N,   N,  N),
+       PINGROUP(ph6,                    SDMMC2,     TRACE,      GMI,          DTV,         0x3228, N,   N,  N),
+       PINGROUP(ph7,                    SDMMC2,     TRACE,      GMI,          DTV,         0x322c, N,   N,  N),
+       PINGROUP(pj7,                    UARTD,      RSVD2,      GMI,          GMI_ALT,     0x3230, N,   N,  N),
+       PINGROUP(pb0,                    UARTD,      RSVD2,      GMI,          RSVD4,       0x3234, N,   N,  N),
+       PINGROUP(pb1,                    UARTD,      RSVD2,      GMI,          RSVD4,       0x3238, N,   N,  N),
+       PINGROUP(pk7,                    UARTD,      RSVD2,      GMI,          RSVD4,       0x323c, N,   N,  N),
+       PINGROUP(pi0,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x3240, N,   N,  N),
+       PINGROUP(pi1,                    RSVD1,      RSVD2,      GMI,          RSVD4,       0x3244, N,   N,  N),
+       PINGROUP(pi2,                    SDMMC2,     TRACE,      GMI,          RSVD4,       0x3248, N,   N,  N),
+       PINGROUP(pi4,                    SPI4,       TRACE,      GMI,          DISPLAYA,    0x324c, N,   N,  N),
+       PINGROUP(gen2_i2c_scl_pt5,       I2C2,       RSVD2,      GMI,          RSVD4,       0x3250, Y,   N,  N),
+       PINGROUP(gen2_i2c_sda_pt6,       I2C2,       RSVD2,      GMI,          RSVD4,       0x3254, Y,   N,  N),
+       PINGROUP(sdmmc4_clk_pcc4,        SDMMC4,     RSVD2,      GMI,          RSVD4,       0x3258, N,   Y,  N),
+       PINGROUP(sdmmc4_cmd_pt7,         SDMMC4,     RSVD2,      GMI,          RSVD4,       0x325c, N,   Y,  N),
+       PINGROUP(sdmmc4_dat0_paa0,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3260, N,   Y,  N),
+       PINGROUP(sdmmc4_dat1_paa1,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3264, N,   Y,  N),
+       PINGROUP(sdmmc4_dat2_paa2,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3268, N,   Y,  N),
+       PINGROUP(sdmmc4_dat3_paa3,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x326c, N,   Y,  N),
+       PINGROUP(sdmmc4_dat4_paa4,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3270, N,   Y,  N),
+       PINGROUP(sdmmc4_dat5_paa5,       SDMMC4,     SPI3,       RSVD3,        RSVD4,       0x3274, N,   Y,  N),
+       PINGROUP(sdmmc4_dat6_paa6,       SDMMC4,     SPI3,       GMI,          RSVD4,       0x3278, N,   Y,  N),
+       PINGROUP(sdmmc4_dat7_paa7,       SDMMC4,     RSVD2,      GMI,          RSVD4,       0x327c, N,   Y,  N),
+       PINGROUP(cam_mclk_pcc0,          VI,         VI_ALT1,    VI_ALT3,      SDMMC2,      0x3284, N,   N,  N),
+       PINGROUP(pcc1,                   I2S4,       RSVD2,      RSVD3,        SDMMC2,      0x3288, N,   N,  N),
+       PINGROUP(pbb0,                   VGP6,       VIMCLK2,    SDMMC2,       VIMCLK2_ALT, 0x328c, N,   N,  N),
+       PINGROUP(cam_i2c_scl_pbb1,       VGP1,       I2C3,       RSVD3,        SDMMC2,      0x3290, Y,   N,  N),
+       PINGROUP(cam_i2c_sda_pbb2,       VGP2,       I2C3,       RSVD3,        SDMMC2,      0x3294, Y,   N,  N),
+       PINGROUP(pbb3,                   VGP3,       DISPLAYA,   DISPLAYB,     SDMMC2,      0x3298, N,   N,  N),
+       PINGROUP(pbb4,                   VGP4,       DISPLAYA,   DISPLAYB,     SDMMC2,      0x329c, N,   N,  N),
+       PINGROUP(pbb5,                   VGP5,       DISPLAYA,   RSVD3,        SDMMC2,      0x32a0, N,   N,  N),
+       PINGROUP(pbb6,                   I2S4,       RSVD2,      DISPLAYB,     SDMMC2,      0x32a4, N,   N,  N),
+       PINGROUP(pbb7,                   I2S4,       RSVD2,      RSVD3,        SDMMC2,      0x32a8, N,   N,  N),
+       PINGROUP(pcc2,                   I2S4,       RSVD2,      SDMMC3,       SDMMC2,      0x32ac, N,   N,  N),
+       PINGROUP(jtag_rtck,              RTCK,       RSVD2,      RSVD3,        RSVD4,       0x32b0, N,   N,  N),
+       PINGROUP(pwr_i2c_scl_pz6,        I2CPWR,     RSVD2,      RSVD3,        RSVD4,       0x32b4, Y,   N,  N),
+       PINGROUP(pwr_i2c_sda_pz7,        I2CPWR,     RSVD2,      RSVD3,        RSVD4,       0x32b8, Y,   N,  N),
+       PINGROUP(kb_row0_pr0,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32bc, N,   N,  N),
+       PINGROUP(kb_row1_pr1,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32c0, N,   N,  N),
+       PINGROUP(kb_row2_pr2,            KBC,        RSVD2,      RSVD3,        RSVD4,       0x32c4, N,   N,  N),
+       PINGROUP(kb_row3_pr3,            KBC,        DISPLAYA,   SYS,          DISPLAYB,    0x32c8, N,   N,  N),
+       PINGROUP(kb_row4_pr4,            KBC,        DISPLAYA,   RSVD3,        DISPLAYB,    0x32cc, N,   N,  N),
+       PINGROUP(kb_row5_pr5,            KBC,        DISPLAYA,   RSVD3,        DISPLAYB,    0x32d0, N,   N,  N),
+       PINGROUP(kb_row6_pr6,            KBC,        DISPLAYA,   DISPLAYA_ALT, DISPLAYB,    0x32d4, N,   N,  N),
+       PINGROUP(kb_row7_pr7,            KBC,        RSVD2,      CLDVFS,       UARTA,       0x32d8, N,   N,  N),
+       PINGROUP(kb_row8_ps0,            KBC,        RSVD2,      CLDVFS,       UARTA,       0x32dc, N,   N,  N),
+       PINGROUP(kb_row9_ps1,            KBC,        RSVD2,      RSVD3,        UARTA,       0x32e0, N,   N,  N),
+       PINGROUP(kb_row10_ps2,           KBC,        RSVD2,      RSVD3,        UARTA,       0x32e4, N,   N,  N),
+       PINGROUP(kb_row11_ps3,           KBC,        RSVD2,      RSVD3,        IRDA,        0x32e8, N,   N,  N),
+       PINGROUP(kb_row12_ps4,           KBC,        RSVD2,      RSVD3,        IRDA,        0x32ec, N,   N,  N),
+       PINGROUP(kb_row13_ps5,           KBC,        RSVD2,      SPI2,         RSVD4,       0x32f0, N,   N,  N),
+       PINGROUP(kb_row14_ps6,           KBC,        RSVD2,      SPI2,         RSVD4,       0x32f4, N,   N,  N),
+       PINGROUP(kb_row15_ps7,           KBC,        SOC,        RSVD3,        RSVD4,       0x32f8, N,   N,  N),
+       PINGROUP(kb_col0_pq0,            KBC,        RSVD2,      SPI2,         RSVD4,       0x32fc, N,   N,  N),
+       PINGROUP(kb_col1_pq1,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3300, N,   N,  N),
+       PINGROUP(kb_col2_pq2,            KBC,        RSVD2,      SPI2,         RSVD4,       0x3304, N,   N,  N),
+       PINGROUP(kb_col3_pq3,            KBC,        DISPLAYA,   PWM2,         UARTA,       0x3308, N,   N,  N),
+       PINGROUP(kb_col4_pq4,            KBC,        OWR,        SDMMC3,       UARTA,       0x330c, N,   N,  N),
+       PINGROUP(kb_col5_pq5,            KBC,        RSVD2,      SDMMC3,       RSVD4,       0x3310, N,   N,  N),
+       PINGROUP(kb_col6_pq6,            KBC,        RSVD2,      SPI2,         UARTD,       0x3314, N,   N,  N),
+       PINGROUP(kb_col7_pq7,            KBC,        RSVD2,      SPI2,         UARTD,       0x3318, N,   N,  N),
+       PINGROUP(clk_32k_out_pa0,        BLINK,      SOC,        RSVD3,        RSVD4,       0x331c, N,   N,  N),
+       PINGROUP(core_pwr_req,           PWRON,      RSVD2,      RSVD3,        RSVD4,       0x3324, N,   N,  N),
+       PINGROUP(cpu_pwr_req,            CPU,        RSVD2,      RSVD3,        RSVD4,       0x3328, N,   N,  N),
+       PINGROUP(pwr_int_n,              PMI,        RSVD2,      RSVD3,        RSVD4,       0x332c, N,   N,  N),
+       PINGROUP(clk_32k_in,             CLK,        RSVD2,      RSVD3,        RSVD4,       0x3330, N,   N,  N),
+       PINGROUP(owr,                    OWR,        RSVD2,      RSVD3,        RSVD4,       0x3334, N,   N,  Y),
+       PINGROUP(dap1_fs_pn0,            I2S0,       HDA,        GMI,          RSVD4,       0x3338, N,   N,  N),
+       PINGROUP(dap1_din_pn1,           I2S0,       HDA,        GMI,          RSVD4,       0x333c, N,   N,  N),
+       PINGROUP(dap1_dout_pn2,          I2S0,       HDA,        GMI,          SATA,        0x3340, N,   N,  N),
+       PINGROUP(dap1_sclk_pn3,          I2S0,       HDA,        GMI,          RSVD4,       0x3344, N,   N,  N),
+       PINGROUP(dap_mclk1_req_pee2,     DAP,        DAP1,       SATA,         RSVD4,       0x3348, N,   N,  N),
+       PINGROUP(dap_mclk1_pw4,          EXTPERIPH1, DAP2,       RSVD3,        RSVD4,       0x334c, N,   N,  N),
+       PINGROUP(spdif_in_pk6,           SPDIF,      RSVD2,      RSVD3,        I2C3,        0x3350, N,   N,  N),
+       PINGROUP(spdif_out_pk5,          SPDIF,      RSVD2,      RSVD3,        I2C3,        0x3354, N,   N,  N),
+       PINGROUP(dap2_fs_pa2,            I2S1,       HDA,        GMI,          RSVD4,       0x3358, N,   N,  N),
+       PINGROUP(dap2_din_pa4,           I2S1,       HDA,        GMI,          RSVD4,       0x335c, N,   N,  N),
+       PINGROUP(dap2_dout_pa5,          I2S1,       HDA,        GMI,          RSVD4,       0x3360, N,   N,  N),
+       PINGROUP(dap2_sclk_pa3,          I2S1,       HDA,        GMI,          RSVD4,       0x3364, N,   N,  N),
+       PINGROUP(dvfs_pwm_px0,           SPI6,       CLDVFS,     GMI,          RSVD4,       0x3368, N,   N,  N),
+       PINGROUP(gpio_x1_aud_px1,        SPI6,       RSVD2,      GMI,          RSVD4,       0x336c, N,   N,  N),
+       PINGROUP(gpio_x3_aud_px3,        SPI6,       SPI1,       GMI,          RSVD4,       0x3370, N,   N,  N),
+       PINGROUP(dvfs_clk_px2,           SPI6,       CLDVFS,     GMI,          RSVD4,       0x3374, N,   N,  N),
+       PINGROUP(gpio_x4_aud_px4,        GMI,        SPI1,       SPI2,         DAP2,        0x3378, N,   N,  N),
+       PINGROUP(gpio_x5_aud_px5,        GMI,        SPI1,       SPI2,         RSVD4,       0x337c, N,   N,  N),
+       PINGROUP(gpio_x6_aud_px6,        SPI6,       SPI1,       SPI2,         GMI,         0x3380, N,   N,  N),
+       PINGROUP(gpio_x7_aud_px7,        RSVD1,      SPI1,       SPI2,         RSVD4,       0x3384, N,   N,  N),
+       PINGROUP(sdmmc3_clk_pa6,         SDMMC3,     RSVD2,      RSVD3,        SPI3,        0x3390, N,   N,  N),
+       PINGROUP(sdmmc3_cmd_pa7,         SDMMC3,     PWM3,       UARTA,        SPI3,        0x3394, N,   N,  N),
+       PINGROUP(sdmmc3_dat0_pb7,        SDMMC3,     RSVD2,      RSVD3,        SPI3,        0x3398, N,   N,  N),
+       PINGROUP(sdmmc3_dat1_pb6,        SDMMC3,     PWM2,       UARTA,        SPI3,        0x339c, N,   N,  N),
+       PINGROUP(sdmmc3_dat2_pb5,        SDMMC3,     PWM1,       DISPLAYA,     SPI3,        0x33a0, N,   N,  N),
+       PINGROUP(sdmmc3_dat3_pb4,        SDMMC3,     PWM0,       DISPLAYB,     SPI3,        0x33a4, N,   N,  N),
+       PINGROUP(pex_l0_rst_n_pdd1,      PE0,        RSVD2,      RSVD3,        RSVD4,       0x33bc, N,   N,  N),
+       PINGROUP(pex_l0_clkreq_n_pdd2,   PE0,        RSVD2,      RSVD3,        RSVD4,       0x33c0, N,   N,  N),
+       PINGROUP(pex_wake_n_pdd3,        PE,         RSVD2,      RSVD3,        RSVD4,       0x33c4, N,   N,  N),
+       PINGROUP(pex_l1_rst_n_pdd5,      PE1,        RSVD2,      RSVD3,        RSVD4,       0x33cc, N,   N,  N),
+       PINGROUP(pex_l1_clkreq_n_pdd6,   PE1,        RSVD2,      RSVD3,        RSVD4,       0x33d0, N,   N,  N),
+       PINGROUP(hdmi_cec_pee3,          CEC,        RSVD2,      RSVD3,        RSVD4,       0x33e0, Y,   N,  N),
+       PINGROUP(sdmmc1_wp_n_pv3,        SDMMC1,     CLK12,      SPI4,         UARTA,       0x33e4, N,   N,  N),
+       PINGROUP(sdmmc3_cd_n_pv2,        SDMMC3,     OWR,        RSVD3,        RSVD4,       0x33e8, N,   N,  N),
+       PINGROUP(gpio_w2_aud_pw2,        SPI6,       RSVD2,      SPI2,         I2C1,        0x33ec, N,   N,  N),
+       PINGROUP(gpio_w3_aud_pw3,        SPI6,       SPI1,       SPI2,         I2C1,        0x33f0, N,   N,  N),
+       PINGROUP(usb_vbus_en0_pn4,       USB,        RSVD2,      RSVD3,        RSVD4,       0x33f4, Y,   N,  N),
+       PINGROUP(usb_vbus_en1_pn5,       USB,        RSVD2,      RSVD3,        RSVD4,       0x33f8, Y,   N,  N),
+       PINGROUP(sdmmc3_clk_lb_in_pee5,  SDMMC3,     RSVD2,      RSVD3,        RSVD4,       0x33fc, N,   N,  N),
+       PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3,     RSVD2,      RSVD3,        RSVD4,       0x3400, N,   N,  N),
+       PINGROUP(gmi_clk_lb,             SDMMC2,     RSVD2,      GMI,          RSVD4,       0x3404, N,   N,  N),
+       PINGROUP(reset_out_n,            RSVD1,      RSVD2,      RSVD3,        RESET_OUT_N, 0x3408, N,   N,  N),
+       PINGROUP(kb_row16_pt0,           KBC,        RSVD2,      RSVD3,        UARTC,       0x340c, N,   N,  N),
+       PINGROUP(kb_row17_pt1,           KBC,        RSVD2,      RSVD3,        UARTC,       0x3410, N,   N,  N),
+       PINGROUP(usb_vbus_en2_pff1,      USB,        RSVD2,      RSVD3,        RSVD4,       0x3414, Y,   N,  N),
+       PINGROUP(pff2,                   SATA,       RSVD2,      RSVD3,        RSVD4,       0x3418, Y,   N,  N),
+       PINGROUP(dp_hpd_pff0,            DP,         RSVD2,      RSVD3,        RSVD4,       0x3430, N,   N,  N),
+
+       /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */
+       DRV_PINGROUP(ao1,         0x868,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(ao2,         0x86c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(at1,         0x870,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(at2,         0x874,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(at3,         0x878,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(at4,         0x87c,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(at5,         0x880,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(cdev1,       0x884,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(cdev2,       0x888,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dap1,        0x890,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dap2,        0x894,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dap3,        0x898,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dap4,        0x89c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dbg,         0x8a0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(sdio3,       0x8b0,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(spi,         0x8b4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uaa,         0x8b8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uab,         0x8bc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uart2,       0x8c0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uart3,       0x8c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(sdio1,       0x8ec,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(ddc,         0x8fc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gma,         0x900,  2,  3,  4,  14,  5,  20,  5,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(gme,         0x910,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gmf,         0x914,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gmg,         0x918,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gmh,         0x91c,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(owr,         0x920,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(uda,         0x924,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(gpv,         0x928,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(dev3,        0x92c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(cec,         0x938,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(at6,         0x994,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+       DRV_PINGROUP(dap5,        0x998,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(usb_vbus_en, 0x99c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(ao3,         0x9a8,  2,  3,  4,  12,  5,  -1, -1,  28,  2,  -1, -1,  N),
+       DRV_PINGROUP(ao0,         0x9b0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(hv0,         0x9b4,  2,  3,  4,  12,  5,  -1, -1,  28,  2,  -1, -1,  N),
+       DRV_PINGROUP(sdio4,       0x9c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2,  N),
+       DRV_PINGROUP(ao4,         0x9c8,  2,  3,  4,  12,  7,  20,  7,  28,  2,  30,  2,  Y),
+
+       /*                     pg_name, r,     b, f0,  f1 */
+       MIPI_PAD_CTRL_PINGROUP(dsi_b,   0x820, 1, CSI, DSI_B),
+};
+
+static const struct tegra_pinctrl_soc_data tegra124_pinctrl = {
+       .ngpios = NUM_GPIOS,
+       .pins = tegra124_pins,
+       .npins = ARRAY_SIZE(tegra124_pins),
+       .functions = tegra124_functions,
+       .nfunctions = ARRAY_SIZE(tegra124_functions),
+       .groups = tegra124_groups,
+       .ngroups = ARRAY_SIZE(tegra124_groups),
+       .hsm_in_mux = false,
+       .schmitt_in_mux = false,
+       .drvtype_in_mux = false,
+};
+
+static int tegra124_pinctrl_probe(struct platform_device *pdev)
+{
+       return tegra_pinctrl_probe(pdev, &tegra124_pinctrl);
+}
+
+static const struct of_device_id tegra124_pinctrl_of_match[] = {
+       { .compatible = "nvidia,tegra124-pinmux", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, tegra124_pinctrl_of_match);
+
+static struct platform_driver tegra124_pinctrl_driver = {
+       .driver = {
+               .name = "tegra124-pinctrl",
+               .of_match_table = tegra124_pinctrl_of_match,
+       },
+       .probe = tegra124_pinctrl_probe,
+       .remove = tegra_pinctrl_remove,
+};
+module_platform_driver(tegra124_pinctrl_driver);
+
+MODULE_AUTHOR("Ashwini Ghuge <aghuge@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra124 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c
new file mode 100644 (file)
index 0000000..4833db4
--- /dev/null
@@ -0,0 +1,2252 @@
+/*
+ * Pinctrl data for the NVIDIA Tegra20 pinmux
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Derived from code:
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/*
+ * Most pins affected by the pinmux can also be GPIOs. Define these first.
+ * These must match how the GPIO driver names/numbers its pins.
+ */
+#define _GPIO(offset)                  (offset)
+
+#define TEGRA_PIN_VI_GP6_PA0           _GPIO(0)
+#define TEGRA_PIN_UART3_CTS_N_PA1      _GPIO(1)
+#define TEGRA_PIN_DAP2_FS_PA2          _GPIO(2)
+#define TEGRA_PIN_DAP2_SCLK_PA3                _GPIO(3)
+#define TEGRA_PIN_DAP2_DIN_PA4         _GPIO(4)
+#define TEGRA_PIN_DAP2_DOUT_PA5                _GPIO(5)
+#define TEGRA_PIN_SDIO3_CLK_PA6                _GPIO(6)
+#define TEGRA_PIN_SDIO3_CMD_PA7                _GPIO(7)
+#define TEGRA_PIN_GMI_AD17_PB0         _GPIO(8)
+#define TEGRA_PIN_GMI_AD18_PB1         _GPIO(9)
+#define TEGRA_PIN_LCD_PWR0_PB2         _GPIO(10)
+#define TEGRA_PIN_LCD_PCLK_PB3         _GPIO(11)
+#define TEGRA_PIN_SDIO3_DAT3_PB4       _GPIO(12)
+#define TEGRA_PIN_SDIO3_DAT2_PB5       _GPIO(13)
+#define TEGRA_PIN_SDIO3_DAT1_PB6       _GPIO(14)
+#define TEGRA_PIN_SDIO3_DAT0_PB7       _GPIO(15)
+#define TEGRA_PIN_UART3_RTS_N_PC0      _GPIO(16)
+#define TEGRA_PIN_LCD_PWR1_PC1         _GPIO(17)
+#define TEGRA_PIN_UART2_TXD_PC2                _GPIO(18)
+#define TEGRA_PIN_UART2_RXD_PC3                _GPIO(19)
+#define TEGRA_PIN_GEN1_I2C_SCL_PC4     _GPIO(20)
+#define TEGRA_PIN_GEN1_I2C_SDA_PC5     _GPIO(21)
+#define TEGRA_PIN_LCD_PWR2_PC6         _GPIO(22)
+#define TEGRA_PIN_GMI_WP_N_PC7         _GPIO(23)
+#define TEGRA_PIN_SDIO3_DAT5_PD0       _GPIO(24)
+#define TEGRA_PIN_SDIO3_DAT4_PD1       _GPIO(25)
+#define TEGRA_PIN_VI_GP5_PD2           _GPIO(26)
+#define TEGRA_PIN_SDIO3_DAT6_PD3       _GPIO(27)
+#define TEGRA_PIN_SDIO3_DAT7_PD4       _GPIO(28)
+#define TEGRA_PIN_VI_D1_PD5            _GPIO(29)
+#define TEGRA_PIN_VI_VSYNC_PD6         _GPIO(30)
+#define TEGRA_PIN_VI_HSYNC_PD7         _GPIO(31)
+#define TEGRA_PIN_LCD_D0_PE0           _GPIO(32)
+#define TEGRA_PIN_LCD_D1_PE1           _GPIO(33)
+#define TEGRA_PIN_LCD_D2_PE2           _GPIO(34)
+#define TEGRA_PIN_LCD_D3_PE3           _GPIO(35)
+#define TEGRA_PIN_LCD_D4_PE4           _GPIO(36)
+#define TEGRA_PIN_LCD_D5_PE5           _GPIO(37)
+#define TEGRA_PIN_LCD_D6_PE6           _GPIO(38)
+#define TEGRA_PIN_LCD_D7_PE7           _GPIO(39)
+#define TEGRA_PIN_LCD_D8_PF0           _GPIO(40)
+#define TEGRA_PIN_LCD_D9_PF1           _GPIO(41)
+#define TEGRA_PIN_LCD_D10_PF2          _GPIO(42)
+#define TEGRA_PIN_LCD_D11_PF3          _GPIO(43)
+#define TEGRA_PIN_LCD_D12_PF4          _GPIO(44)
+#define TEGRA_PIN_LCD_D13_PF5          _GPIO(45)
+#define TEGRA_PIN_LCD_D14_PF6          _GPIO(46)
+#define TEGRA_PIN_LCD_D15_PF7          _GPIO(47)
+#define TEGRA_PIN_GMI_AD0_PG0          _GPIO(48)
+#define TEGRA_PIN_GMI_AD1_PG1          _GPIO(49)
+#define TEGRA_PIN_GMI_AD2_PG2          _GPIO(50)
+#define TEGRA_PIN_GMI_AD3_PG3          _GPIO(51)
+#define TEGRA_PIN_GMI_AD4_PG4          _GPIO(52)
+#define TEGRA_PIN_GMI_AD5_PG5          _GPIO(53)
+#define TEGRA_PIN_GMI_AD6_PG6          _GPIO(54)
+#define TEGRA_PIN_GMI_AD7_PG7          _GPIO(55)
+#define TEGRA_PIN_GMI_AD8_PH0          _GPIO(56)
+#define TEGRA_PIN_GMI_AD9_PH1          _GPIO(57)
+#define TEGRA_PIN_GMI_AD10_PH2         _GPIO(58)
+#define TEGRA_PIN_GMI_AD11_PH3         _GPIO(59)
+#define TEGRA_PIN_GMI_AD12_PH4         _GPIO(60)
+#define TEGRA_PIN_GMI_AD13_PH5         _GPIO(61)
+#define TEGRA_PIN_GMI_AD14_PH6         _GPIO(62)
+#define TEGRA_PIN_GMI_AD15_PH7         _GPIO(63)
+#define TEGRA_PIN_GMI_HIOW_N_PI0       _GPIO(64)
+#define TEGRA_PIN_GMI_HIOR_N_PI1       _GPIO(65)
+#define TEGRA_PIN_GMI_CS5_N_PI2                _GPIO(66)
+#define TEGRA_PIN_GMI_CS6_N_PI3                _GPIO(67)
+#define TEGRA_PIN_GMI_RST_N_PI4                _GPIO(68)
+#define TEGRA_PIN_GMI_IORDY_PI5                _GPIO(69)
+#define TEGRA_PIN_GMI_CS7_N_PI6                _GPIO(70)
+#define TEGRA_PIN_GMI_WAIT_PI7         _GPIO(71)
+#define TEGRA_PIN_GMI_CS0_N_PJ0                _GPIO(72)
+#define TEGRA_PIN_LCD_DE_PJ1           _GPIO(73)
+#define TEGRA_PIN_GMI_CS1_N_PJ2                _GPIO(74)
+#define TEGRA_PIN_LCD_HSYNC_PJ3                _GPIO(75)
+#define TEGRA_PIN_LCD_VSYNC_PJ4                _GPIO(76)
+#define TEGRA_PIN_UART2_CTS_N_PJ5      _GPIO(77)
+#define TEGRA_PIN_UART2_RTS_N_PJ6      _GPIO(78)
+#define TEGRA_PIN_GMI_AD16_PJ7         _GPIO(79)
+#define TEGRA_PIN_GMI_ADV_N_PK0                _GPIO(80)
+#define TEGRA_PIN_GMI_CLK_PK1          _GPIO(81)
+#define TEGRA_PIN_GMI_CS4_N_PK2                _GPIO(82)
+#define TEGRA_PIN_GMI_CS2_N_PK3                _GPIO(83)
+#define TEGRA_PIN_GMI_CS3_N_PK4                _GPIO(84)
+#define TEGRA_PIN_SPDIF_OUT_PK5                _GPIO(85)
+#define TEGRA_PIN_SPDIF_IN_PK6         _GPIO(86)
+#define TEGRA_PIN_GMI_AD19_PK7         _GPIO(87)
+#define TEGRA_PIN_VI_D2_PL0            _GPIO(88)
+#define TEGRA_PIN_VI_D3_PL1            _GPIO(89)
+#define TEGRA_PIN_VI_D4_PL2            _GPIO(90)
+#define TEGRA_PIN_VI_D5_PL3            _GPIO(91)
+#define TEGRA_PIN_VI_D6_PL4            _GPIO(92)
+#define TEGRA_PIN_VI_D7_PL5            _GPIO(93)
+#define TEGRA_PIN_VI_D8_PL6            _GPIO(94)
+#define TEGRA_PIN_VI_D9_PL7            _GPIO(95)
+#define TEGRA_PIN_LCD_D16_PM0          _GPIO(96)
+#define TEGRA_PIN_LCD_D17_PM1          _GPIO(97)
+#define TEGRA_PIN_LCD_D18_PM2          _GPIO(98)
+#define TEGRA_PIN_LCD_D19_PM3          _GPIO(99)
+#define TEGRA_PIN_LCD_D20_PM4          _GPIO(100)
+#define TEGRA_PIN_LCD_D21_PM5          _GPIO(101)
+#define TEGRA_PIN_LCD_D22_PM6          _GPIO(102)
+#define TEGRA_PIN_LCD_D23_PM7          _GPIO(103)
+#define TEGRA_PIN_DAP1_FS_PN0          _GPIO(104)
+#define TEGRA_PIN_DAP1_DIN_PN1         _GPIO(105)
+#define TEGRA_PIN_DAP1_DOUT_PN2                _GPIO(106)
+#define TEGRA_PIN_DAP1_SCLK_PN3                _GPIO(107)
+#define TEGRA_PIN_LCD_CS0_N_PN4                _GPIO(108)
+#define TEGRA_PIN_LCD_SDOUT_PN5                _GPIO(109)
+#define TEGRA_PIN_LCD_DC0_PN6          _GPIO(110)
+#define TEGRA_PIN_HDMI_INT_N_PN7       _GPIO(111)
+#define TEGRA_PIN_ULPI_DATA7_PO0       _GPIO(112)
+#define TEGRA_PIN_ULPI_DATA0_PO1       _GPIO(113)
+#define TEGRA_PIN_ULPI_DATA1_PO2       _GPIO(114)
+#define TEGRA_PIN_ULPI_DATA2_PO3       _GPIO(115)
+#define TEGRA_PIN_ULPI_DATA3_PO4       _GPIO(116)
+#define TEGRA_PIN_ULPI_DATA4_PO5       _GPIO(117)
+#define TEGRA_PIN_ULPI_DATA5_PO6       _GPIO(118)
+#define TEGRA_PIN_ULPI_DATA6_PO7       _GPIO(119)
+#define TEGRA_PIN_DAP3_FS_PP0          _GPIO(120)
+#define TEGRA_PIN_DAP3_DIN_PP1         _GPIO(121)
+#define TEGRA_PIN_DAP3_DOUT_PP2                _GPIO(122)
+#define TEGRA_PIN_DAP3_SCLK_PP3                _GPIO(123)
+#define TEGRA_PIN_DAP4_FS_PP4          _GPIO(124)
+#define TEGRA_PIN_DAP4_DIN_PP5         _GPIO(125)
+#define TEGRA_PIN_DAP4_DOUT_PP6                _GPIO(126)
+#define TEGRA_PIN_DAP4_SCLK_PP7                _GPIO(127)
+#define TEGRA_PIN_KB_COL0_PQ0          _GPIO(128)
+#define TEGRA_PIN_KB_COL1_PQ1          _GPIO(129)
+#define TEGRA_PIN_KB_COL2_PQ2          _GPIO(130)
+#define TEGRA_PIN_KB_COL3_PQ3          _GPIO(131)
+#define TEGRA_PIN_KB_COL4_PQ4          _GPIO(132)
+#define TEGRA_PIN_KB_COL5_PQ5          _GPIO(133)
+#define TEGRA_PIN_KB_COL6_PQ6          _GPIO(134)
+#define TEGRA_PIN_KB_COL7_PQ7          _GPIO(135)
+#define TEGRA_PIN_KB_ROW0_PR0          _GPIO(136)
+#define TEGRA_PIN_KB_ROW1_PR1          _GPIO(137)
+#define TEGRA_PIN_KB_ROW2_PR2          _GPIO(138)
+#define TEGRA_PIN_KB_ROW3_PR3          _GPIO(139)
+#define TEGRA_PIN_KB_ROW4_PR4          _GPIO(140)
+#define TEGRA_PIN_KB_ROW5_PR5          _GPIO(141)
+#define TEGRA_PIN_KB_ROW6_PR6          _GPIO(142)
+#define TEGRA_PIN_KB_ROW7_PR7          _GPIO(143)
+#define TEGRA_PIN_KB_ROW8_PS0          _GPIO(144)
+#define TEGRA_PIN_KB_ROW9_PS1          _GPIO(145)
+#define TEGRA_PIN_KB_ROW10_PS2         _GPIO(146)
+#define TEGRA_PIN_KB_ROW11_PS3         _GPIO(147)
+#define TEGRA_PIN_KB_ROW12_PS4         _GPIO(148)
+#define TEGRA_PIN_KB_ROW13_PS5         _GPIO(149)
+#define TEGRA_PIN_KB_ROW14_PS6         _GPIO(150)
+#define TEGRA_PIN_KB_ROW15_PS7         _GPIO(151)
+#define TEGRA_PIN_VI_PCLK_PT0          _GPIO(152)
+#define TEGRA_PIN_VI_MCLK_PT1          _GPIO(153)
+#define TEGRA_PIN_VI_D10_PT2           _GPIO(154)
+#define TEGRA_PIN_VI_D11_PT3           _GPIO(155)
+#define TEGRA_PIN_VI_D0_PT4            _GPIO(156)
+#define TEGRA_PIN_GEN2_I2C_SCL_PT5     _GPIO(157)
+#define TEGRA_PIN_GEN2_I2C_SDA_PT6     _GPIO(158)
+#define TEGRA_PIN_GMI_DPD_PT7          _GPIO(159)
+#define TEGRA_PIN_PU0                  _GPIO(160)
+#define TEGRA_PIN_PU1                  _GPIO(161)
+#define TEGRA_PIN_PU2                  _GPIO(162)
+#define TEGRA_PIN_PU3                  _GPIO(163)
+#define TEGRA_PIN_PU4                  _GPIO(164)
+#define TEGRA_PIN_PU5                  _GPIO(165)
+#define TEGRA_PIN_PU6                  _GPIO(166)
+#define TEGRA_PIN_JTAG_RTCK_PU7                _GPIO(167)
+#define TEGRA_PIN_PV0                  _GPIO(168)
+#define TEGRA_PIN_PV1                  _GPIO(169)
+#define TEGRA_PIN_PV2                  _GPIO(170)
+#define TEGRA_PIN_PV3                  _GPIO(171)
+#define TEGRA_PIN_PV4                  _GPIO(172)
+#define TEGRA_PIN_PV5                  _GPIO(173)
+#define TEGRA_PIN_PV6                  _GPIO(174)
+#define TEGRA_PIN_LCD_DC1_PV7          _GPIO(175)
+#define TEGRA_PIN_LCD_CS1_N_PW0                _GPIO(176)
+#define TEGRA_PIN_LCD_M1_PW1           _GPIO(177)
+#define TEGRA_PIN_SPI2_CS1_N_PW2       _GPIO(178)
+#define TEGRA_PIN_SPI2_CS2_N_PW3       _GPIO(179)
+#define TEGRA_PIN_DAP_MCLK1_PW4                _GPIO(180)
+#define TEGRA_PIN_DAP_MCLK2_PW5                _GPIO(181)
+#define TEGRA_PIN_UART3_TXD_PW6                _GPIO(182)
+#define TEGRA_PIN_UART3_RXD_PW7                _GPIO(183)
+#define TEGRA_PIN_SPI2_MOSI_PX0                _GPIO(184)
+#define TEGRA_PIN_SPI2_MISO_PX1                _GPIO(185)
+#define TEGRA_PIN_SPI2_SCK_PX2         _GPIO(186)
+#define TEGRA_PIN_SPI2_CS0_N_PX3       _GPIO(187)
+#define TEGRA_PIN_SPI1_MOSI_PX4                _GPIO(188)
+#define TEGRA_PIN_SPI1_SCK_PX5         _GPIO(189)
+#define TEGRA_PIN_SPI1_CS0_N_PX6       _GPIO(190)
+#define TEGRA_PIN_SPI1_MISO_PX7                _GPIO(191)
+#define TEGRA_PIN_ULPI_CLK_PY0         _GPIO(192)
+#define TEGRA_PIN_ULPI_DIR_PY1         _GPIO(193)
+#define TEGRA_PIN_ULPI_NXT_PY2         _GPIO(194)
+#define TEGRA_PIN_ULPI_STP_PY3         _GPIO(195)
+#define TEGRA_PIN_SDIO1_DAT3_PY4       _GPIO(196)
+#define TEGRA_PIN_SDIO1_DAT2_PY5       _GPIO(197)
+#define TEGRA_PIN_SDIO1_DAT1_PY6       _GPIO(198)
+#define TEGRA_PIN_SDIO1_DAT0_PY7       _GPIO(199)
+#define TEGRA_PIN_SDIO1_CLK_PZ0                _GPIO(200)
+#define TEGRA_PIN_SDIO1_CMD_PZ1                _GPIO(201)
+#define TEGRA_PIN_LCD_SDIN_PZ2         _GPIO(202)
+#define TEGRA_PIN_LCD_WR_N_PZ3         _GPIO(203)
+#define TEGRA_PIN_LCD_SCK_PZ4          _GPIO(204)
+#define TEGRA_PIN_SYS_CLK_REQ_PZ5      _GPIO(205)
+#define TEGRA_PIN_PWR_I2C_SCL_PZ6      _GPIO(206)
+#define TEGRA_PIN_PWR_I2C_SDA_PZ7      _GPIO(207)
+#define TEGRA_PIN_GMI_AD20_PAA0                _GPIO(208)
+#define TEGRA_PIN_GMI_AD21_PAA1                _GPIO(209)
+#define TEGRA_PIN_GMI_AD22_PAA2                _GPIO(210)
+#define TEGRA_PIN_GMI_AD23_PAA3                _GPIO(211)
+#define TEGRA_PIN_GMI_AD24_PAA4                _GPIO(212)
+#define TEGRA_PIN_GMI_AD25_PAA5                _GPIO(213)
+#define TEGRA_PIN_GMI_AD26_PAA6                _GPIO(214)
+#define TEGRA_PIN_GMI_AD27_PAA7                _GPIO(215)
+#define TEGRA_PIN_LED_BLINK_PBB0       _GPIO(216)
+#define TEGRA_PIN_VI_GP0_PBB1          _GPIO(217)
+#define TEGRA_PIN_CAM_I2C_SCL_PBB2     _GPIO(218)
+#define TEGRA_PIN_CAM_I2C_SDA_PBB3     _GPIO(219)
+#define TEGRA_PIN_VI_GP3_PBB4          _GPIO(220)
+#define TEGRA_PIN_VI_GP4_PBB5          _GPIO(221)
+#define TEGRA_PIN_PBB6                 _GPIO(222)
+#define TEGRA_PIN_PBB7                 _GPIO(223)
+
+/* All non-GPIO pins follow */
+#define NUM_GPIOS                      (TEGRA_PIN_PBB7 + 1)
+#define _PIN(offset)                   (NUM_GPIOS + (offset))
+
+#define TEGRA_PIN_CRT_HSYNC            _PIN(30)
+#define TEGRA_PIN_CRT_VSYNC            _PIN(31)
+#define TEGRA_PIN_DDC_SCL              _PIN(32)
+#define TEGRA_PIN_DDC_SDA              _PIN(33)
+#define TEGRA_PIN_OWC                  _PIN(34)
+#define TEGRA_PIN_CORE_PWR_REQ         _PIN(35)
+#define TEGRA_PIN_CPU_PWR_REQ          _PIN(36)
+#define TEGRA_PIN_PWR_INT_N            _PIN(37)
+#define TEGRA_PIN_CLK_32_K_IN          _PIN(38)
+#define TEGRA_PIN_DDR_COMP_PD          _PIN(39)
+#define TEGRA_PIN_DDR_COMP_PU          _PIN(40)
+#define TEGRA_PIN_DDR_A0               _PIN(41)
+#define TEGRA_PIN_DDR_A1               _PIN(42)
+#define TEGRA_PIN_DDR_A2               _PIN(43)
+#define TEGRA_PIN_DDR_A3               _PIN(44)
+#define TEGRA_PIN_DDR_A4               _PIN(45)
+#define TEGRA_PIN_DDR_A5               _PIN(46)
+#define TEGRA_PIN_DDR_A6               _PIN(47)
+#define TEGRA_PIN_DDR_A7               _PIN(48)
+#define TEGRA_PIN_DDR_A8               _PIN(49)
+#define TEGRA_PIN_DDR_A9               _PIN(50)
+#define TEGRA_PIN_DDR_A10              _PIN(51)
+#define TEGRA_PIN_DDR_A11              _PIN(52)
+#define TEGRA_PIN_DDR_A12              _PIN(53)
+#define TEGRA_PIN_DDR_A13              _PIN(54)
+#define TEGRA_PIN_DDR_A14              _PIN(55)
+#define TEGRA_PIN_DDR_CAS_N            _PIN(56)
+#define TEGRA_PIN_DDR_BA0              _PIN(57)
+#define TEGRA_PIN_DDR_BA1              _PIN(58)
+#define TEGRA_PIN_DDR_BA2              _PIN(59)
+#define TEGRA_PIN_DDR_DQS0P            _PIN(60)
+#define TEGRA_PIN_DDR_DQS0N            _PIN(61)
+#define TEGRA_PIN_DDR_DQS1P            _PIN(62)
+#define TEGRA_PIN_DDR_DQS1N            _PIN(63)
+#define TEGRA_PIN_DDR_DQS2P            _PIN(64)
+#define TEGRA_PIN_DDR_DQS2N            _PIN(65)
+#define TEGRA_PIN_DDR_DQS3P            _PIN(66)
+#define TEGRA_PIN_DDR_DQS3N            _PIN(67)
+#define TEGRA_PIN_DDR_CKE0             _PIN(68)
+#define TEGRA_PIN_DDR_CKE1             _PIN(69)
+#define TEGRA_PIN_DDR_CLK              _PIN(70)
+#define TEGRA_PIN_DDR_CLK_N            _PIN(71)
+#define TEGRA_PIN_DDR_DM0              _PIN(72)
+#define TEGRA_PIN_DDR_DM1              _PIN(73)
+#define TEGRA_PIN_DDR_DM2              _PIN(74)
+#define TEGRA_PIN_DDR_DM3              _PIN(75)
+#define TEGRA_PIN_DDR_ODT              _PIN(76)
+#define TEGRA_PIN_DDR_QUSE0            _PIN(77)
+#define TEGRA_PIN_DDR_QUSE1            _PIN(78)
+#define TEGRA_PIN_DDR_QUSE2            _PIN(79)
+#define TEGRA_PIN_DDR_QUSE3            _PIN(80)
+#define TEGRA_PIN_DDR_RAS_N            _PIN(81)
+#define TEGRA_PIN_DDR_WE_N             _PIN(82)
+#define TEGRA_PIN_DDR_DQ0              _PIN(83)
+#define TEGRA_PIN_DDR_DQ1              _PIN(84)
+#define TEGRA_PIN_DDR_DQ2              _PIN(85)
+#define TEGRA_PIN_DDR_DQ3              _PIN(86)
+#define TEGRA_PIN_DDR_DQ4              _PIN(87)
+#define TEGRA_PIN_DDR_DQ5              _PIN(88)
+#define TEGRA_PIN_DDR_DQ6              _PIN(89)
+#define TEGRA_PIN_DDR_DQ7              _PIN(90)
+#define TEGRA_PIN_DDR_DQ8              _PIN(91)
+#define TEGRA_PIN_DDR_DQ9              _PIN(92)
+#define TEGRA_PIN_DDR_DQ10             _PIN(93)
+#define TEGRA_PIN_DDR_DQ11             _PIN(94)
+#define TEGRA_PIN_DDR_DQ12             _PIN(95)
+#define TEGRA_PIN_DDR_DQ13             _PIN(96)
+#define TEGRA_PIN_DDR_DQ14             _PIN(97)
+#define TEGRA_PIN_DDR_DQ15             _PIN(98)
+#define TEGRA_PIN_DDR_DQ16             _PIN(99)
+#define TEGRA_PIN_DDR_DQ17             _PIN(100)
+#define TEGRA_PIN_DDR_DQ18             _PIN(101)
+#define TEGRA_PIN_DDR_DQ19             _PIN(102)
+#define TEGRA_PIN_DDR_DQ20             _PIN(103)
+#define TEGRA_PIN_DDR_DQ21             _PIN(104)
+#define TEGRA_PIN_DDR_DQ22             _PIN(105)
+#define TEGRA_PIN_DDR_DQ23             _PIN(106)
+#define TEGRA_PIN_DDR_DQ24             _PIN(107)
+#define TEGRA_PIN_DDR_DQ25             _PIN(108)
+#define TEGRA_PIN_DDR_DQ26             _PIN(109)
+#define TEGRA_PIN_DDR_DQ27             _PIN(110)
+#define TEGRA_PIN_DDR_DQ28             _PIN(111)
+#define TEGRA_PIN_DDR_DQ29             _PIN(112)
+#define TEGRA_PIN_DDR_DQ30             _PIN(113)
+#define TEGRA_PIN_DDR_DQ31             _PIN(114)
+#define TEGRA_PIN_DDR_CS0_N            _PIN(115)
+#define TEGRA_PIN_DDR_CS1_N            _PIN(116)
+#define TEGRA_PIN_SYS_RESET            _PIN(117)
+#define TEGRA_PIN_JTAG_TRST_N          _PIN(118)
+#define TEGRA_PIN_JTAG_TDO             _PIN(119)
+#define TEGRA_PIN_JTAG_TMS             _PIN(120)
+#define TEGRA_PIN_JTAG_TCK             _PIN(121)
+#define TEGRA_PIN_JTAG_TDI             _PIN(122)
+#define TEGRA_PIN_TEST_MODE_EN         _PIN(123)
+
+static const struct pinctrl_pin_desc tegra20_pins[] = {
+       PINCTRL_PIN(TEGRA_PIN_VI_GP6_PA0, "VI_GP6 PA0"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_CLK_PA6, "SDIO3_CLK PA6"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_CMD_PA7, "SDIO3_CMD PA7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD17_PB0, "GMI_AD17 PB0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD18_PB1, "GMI_AD18 PB1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT3_PB4, "SDIO3_DAT3 PB4"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT2_PB5, "SDIO3_DAT2 PB5"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT1_PB6, "SDIO3_DAT1 PB6"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT0_PB7, "SDIO3_DAT0 PB7"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT5_PD0, "SDIO3_DAT5 PD0"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT4_PD1, "SDIO3_DAT4 PD1"),
+       PINCTRL_PIN(TEGRA_PIN_VI_GP5_PD2, "VI_GP5 PD2"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT6_PD3, "SDIO3_DAT6 PD3"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT7_PD4, "SDIO3_DAT7 PD4"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"),
+       PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"),
+       PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_HIOW_N_PI0, "GMI_HIOW_N PI0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_HIOR_N_PI1, "GMI_HIOR_N PI1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS5_N_PI2, "GMI_CS5_N PI2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD16_PJ7, "GMI_AD16 PJ7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD19_PK7, "GMI_AD19 PK7"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_N_PN7, "HDMI_INT_N PN7"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"),
+       PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"),
+       PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VD_D10 PT2"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_DPD_PT7, "GMI_DPD PT7"),
+       /* PU0..6: GPIO only */
+       PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"),
+       PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"),
+       PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"),
+       PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"),
+       PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"),
+       PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"),
+       PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"),
+       /* PV0..1: GPIO only */
+       PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"),
+       PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"),
+       /* PV2..3: Balls are named after GPIO not function */
+       PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"),
+       PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"),
+       /* PV4..6: GPIO only */
+       PINCTRL_PIN(TEGRA_PIN_PV4, "PV4"),
+       PINCTRL_PIN(TEGRA_PIN_PV5, "PV5"),
+       PINCTRL_PIN(TEGRA_PIN_PV6, "PV6"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PV7, "LCD_DC1 PV7"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP_MCLK2_PW5, "DAP_MCLK2 PW5"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT3_PY4, "SDIO1_DAT3 PY4"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT2_PY5, "SDIO1_DAT2 PY5"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT1_PY6, "SDIO1_DAT1 PY6"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT0_PY7, "SDIO1_DAT0 PY7"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO1_CLK_PZ0, "SDIO1_CLK PZ0"),
+       PINCTRL_PIN(TEGRA_PIN_SDIO1_CMD_PZ1, "SDIO1_CMD PZ1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"),
+       PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD20_PAA0, "GMI_AD20 PAA0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD21_PAA1, "GMI_AD21 PAA1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD22_PAA2, "GMI_AD22 PAA2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD23_PAA3, "GMI_AD23 PAA3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD24_PAA4, "GMI_AD24 PAA4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD25_PAA5, "GMI_AD25 PAA5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD26_PAA6, "GMI_AD26 PAA6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD27_PAA7, "GMI_AD27 PAA7"),
+       PINCTRL_PIN(TEGRA_PIN_LED_BLINK_PBB0, "LED_BLINK PBB0"),
+       PINCTRL_PIN(TEGRA_PIN_VI_GP0_PBB1, "VI_GP0 PBB1"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB2, "CAM_I2C_SCL PBB2"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB3, "CAM_I2C_SDA PBB3"),
+       PINCTRL_PIN(TEGRA_PIN_VI_GP3_PBB4, "VI_GP3 PBB4"),
+       PINCTRL_PIN(TEGRA_PIN_VI_GP4_PBB5, "VI_GP4 PBB5"),
+       PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"),
+       PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"),
+       PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC, "CRT_HSYNC"),
+       PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC, "CRT_VSYNC"),
+       PINCTRL_PIN(TEGRA_PIN_DDC_SCL, "DDC_SCL"),
+       PINCTRL_PIN(TEGRA_PIN_DDC_SDA, "DDC_SDA"),
+       PINCTRL_PIN(TEGRA_PIN_OWC, "OWC"),
+       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_32_K_IN, "CLK_32_K_IN"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PD, "DDR_COMP_PD"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PU, "DDR_COMP_PU"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A0, "DDR_A0"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A1, "DDR_A1"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A2, "DDR_A2"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A3, "DDR_A3"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A4, "DDR_A4"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A5, "DDR_A5"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A6, "DDR_A6"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A7, "DDR_A7"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A8, "DDR_A8"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A9, "DDR_A9"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A10, "DDR_A10"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A11, "DDR_A11"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A12, "DDR_A12"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A13, "DDR_A13"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_A14, "DDR_A14"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_CAS_N, "DDR_CAS_N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_BA0, "DDR_BA0"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_BA1, "DDR_BA1"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_BA2, "DDR_BA2"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQS0P, "DDR_DQS0P"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQS0N, "DDR_DQS0N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQS1P, "DDR_DQS1P"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQS1N, "DDR_DQS1N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQS2P, "DDR_DQS2P"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQS2N, "DDR_DQS2N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQS3P, "DDR_DQS3P"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQS3N, "DDR_DQS3N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_CKE0, "DDR_CKE0"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_CKE1, "DDR_CKE1"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_CLK, "DDR_CLK"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_CLK_N, "DDR_CLK_N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DM0, "DDR_DM0"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DM1, "DDR_DM1"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DM2, "DDR_DM2"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DM3, "DDR_DM3"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_ODT, "DDR_ODT"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_QUSE0, "DDR_QUSE0"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_QUSE1, "DDR_QUSE1"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_QUSE2, "DDR_QUSE2"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_QUSE3, "DDR_QUSE3"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_RAS_N, "DDR_RAS_N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_WE_N, "DDR_WE_N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ0, "DDR_DQ0"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ1, "DDR_DQ1"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ2, "DDR_DQ2"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ3, "DDR_DQ3"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ4, "DDR_DQ4"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ5, "DDR_DQ5"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ6, "DDR_DQ6"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ7, "DDR_DQ7"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ8, "DDR_DQ8"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ9, "DDR_DQ9"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ10, "DDR_DQ10"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ11, "DDR_DQ11"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ12, "DDR_DQ12"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ13, "DDR_DQ13"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ14, "DDR_DQ14"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ15, "DDR_DQ15"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ16, "DDR_DQ16"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ17, "DDR_DQ17"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ18, "DDR_DQ18"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ19, "DDR_DQ19"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ20, "DDR_DQ20"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ21, "DDR_DQ21"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ22, "DDR_DQ22"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ23, "DDR_DQ23"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ24, "DDR_DQ24"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ25, "DDR_DQ25"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ26, "DDR_DQ26"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ27, "DDR_DQ27"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ28, "DDR_DQ28"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ29, "DDR_DQ29"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ30, "DDR_DQ30"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_DQ31, "DDR_DQ31"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_CS0_N, "DDR_CS0_N"),
+       PINCTRL_PIN(TEGRA_PIN_DDR_CS1_N, "DDR_CS1_N"),
+       PINCTRL_PIN(TEGRA_PIN_SYS_RESET, "SYS_RESET"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"),
+       PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"),
+};
+
+static const unsigned ata_pins[] = {
+       TEGRA_PIN_GMI_CS6_N_PI3,
+       TEGRA_PIN_GMI_CS7_N_PI6,
+       TEGRA_PIN_GMI_RST_N_PI4,
+};
+
+static const unsigned atb_pins[] = {
+       TEGRA_PIN_GMI_CS5_N_PI2,
+       TEGRA_PIN_GMI_DPD_PT7,
+};
+
+static const unsigned atc_pins[] = {
+       TEGRA_PIN_GMI_IORDY_PI5,
+       TEGRA_PIN_GMI_WAIT_PI7,
+       TEGRA_PIN_GMI_ADV_N_PK0,
+       TEGRA_PIN_GMI_CLK_PK1,
+       TEGRA_PIN_GMI_CS2_N_PK3,
+       TEGRA_PIN_GMI_CS3_N_PK4,
+       TEGRA_PIN_GMI_CS4_N_PK2,
+       TEGRA_PIN_GMI_AD0_PG0,
+       TEGRA_PIN_GMI_AD1_PG1,
+       TEGRA_PIN_GMI_AD2_PG2,
+       TEGRA_PIN_GMI_AD3_PG3,
+       TEGRA_PIN_GMI_AD4_PG4,
+       TEGRA_PIN_GMI_AD5_PG5,
+       TEGRA_PIN_GMI_AD6_PG6,
+       TEGRA_PIN_GMI_AD7_PG7,
+       TEGRA_PIN_GMI_HIOW_N_PI0,
+       TEGRA_PIN_GMI_HIOR_N_PI1,
+};
+
+static const unsigned atd_pins[] = {
+       TEGRA_PIN_GMI_AD8_PH0,
+       TEGRA_PIN_GMI_AD9_PH1,
+       TEGRA_PIN_GMI_AD10_PH2,
+       TEGRA_PIN_GMI_AD11_PH3,
+};
+
+static const unsigned ate_pins[] = {
+       TEGRA_PIN_GMI_AD12_PH4,
+       TEGRA_PIN_GMI_AD13_PH5,
+       TEGRA_PIN_GMI_AD14_PH6,
+       TEGRA_PIN_GMI_AD15_PH7,
+};
+
+static const unsigned cdev1_pins[] = {
+       TEGRA_PIN_DAP_MCLK1_PW4,
+};
+
+static const unsigned cdev2_pins[] = {
+       TEGRA_PIN_DAP_MCLK2_PW5,
+};
+
+static const unsigned crtp_pins[] = {
+       TEGRA_PIN_CRT_HSYNC,
+       TEGRA_PIN_CRT_VSYNC,
+};
+
+static const unsigned csus_pins[] = {
+       TEGRA_PIN_VI_MCLK_PT1,
+};
+
+static const unsigned dap1_pins[] = {
+       TEGRA_PIN_DAP1_FS_PN0,
+       TEGRA_PIN_DAP1_DIN_PN1,
+       TEGRA_PIN_DAP1_DOUT_PN2,
+       TEGRA_PIN_DAP1_SCLK_PN3,
+};
+
+static const unsigned dap2_pins[] = {
+       TEGRA_PIN_DAP2_FS_PA2,
+       TEGRA_PIN_DAP2_SCLK_PA3,
+       TEGRA_PIN_DAP2_DIN_PA4,
+       TEGRA_PIN_DAP2_DOUT_PA5,
+};
+
+static const unsigned dap3_pins[] = {
+       TEGRA_PIN_DAP3_FS_PP0,
+       TEGRA_PIN_DAP3_DIN_PP1,
+       TEGRA_PIN_DAP3_DOUT_PP2,
+       TEGRA_PIN_DAP3_SCLK_PP3,
+};
+
+static const unsigned dap4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PP4,
+       TEGRA_PIN_DAP4_DIN_PP5,
+       TEGRA_PIN_DAP4_DOUT_PP6,
+       TEGRA_PIN_DAP4_SCLK_PP7,
+};
+
+static const unsigned ddc_pins[] = {
+       TEGRA_PIN_DDC_SCL,
+       TEGRA_PIN_DDC_SDA,
+};
+
+static const unsigned dta_pins[] = {
+       TEGRA_PIN_VI_D0_PT4,
+       TEGRA_PIN_VI_D1_PD5,
+};
+
+static const unsigned dtb_pins[] = {
+       TEGRA_PIN_VI_D10_PT2,
+       TEGRA_PIN_VI_D11_PT3,
+};
+
+static const unsigned dtc_pins[] = {
+       TEGRA_PIN_VI_HSYNC_PD7,
+       TEGRA_PIN_VI_VSYNC_PD6,
+};
+
+static const unsigned dtd_pins[] = {
+       TEGRA_PIN_VI_PCLK_PT0,
+       TEGRA_PIN_VI_D2_PL0,
+       TEGRA_PIN_VI_D3_PL1,
+       TEGRA_PIN_VI_D4_PL2,
+       TEGRA_PIN_VI_D5_PL3,
+       TEGRA_PIN_VI_D6_PL4,
+       TEGRA_PIN_VI_D7_PL5,
+       TEGRA_PIN_VI_D8_PL6,
+       TEGRA_PIN_VI_D9_PL7,
+};
+
+static const unsigned dte_pins[] = {
+       TEGRA_PIN_VI_GP0_PBB1,
+       TEGRA_PIN_VI_GP3_PBB4,
+       TEGRA_PIN_VI_GP4_PBB5,
+       TEGRA_PIN_VI_GP5_PD2,
+       TEGRA_PIN_VI_GP6_PA0,
+};
+
+static const unsigned dtf_pins[] = {
+       TEGRA_PIN_CAM_I2C_SCL_PBB2,
+       TEGRA_PIN_CAM_I2C_SDA_PBB3,
+};
+
+static const unsigned gma_pins[] = {
+       TEGRA_PIN_GMI_AD20_PAA0,
+       TEGRA_PIN_GMI_AD21_PAA1,
+       TEGRA_PIN_GMI_AD22_PAA2,
+       TEGRA_PIN_GMI_AD23_PAA3,
+};
+
+static const unsigned gmb_pins[] = {
+       TEGRA_PIN_GMI_WP_N_PC7,
+};
+
+static const unsigned gmc_pins[] = {
+       TEGRA_PIN_GMI_AD16_PJ7,
+       TEGRA_PIN_GMI_AD17_PB0,
+       TEGRA_PIN_GMI_AD18_PB1,
+       TEGRA_PIN_GMI_AD19_PK7,
+};
+
+static const unsigned gmd_pins[] = {
+       TEGRA_PIN_GMI_CS0_N_PJ0,
+       TEGRA_PIN_GMI_CS1_N_PJ2,
+};
+
+static const unsigned gme_pins[] = {
+       TEGRA_PIN_GMI_AD24_PAA4,
+       TEGRA_PIN_GMI_AD25_PAA5,
+       TEGRA_PIN_GMI_AD26_PAA6,
+       TEGRA_PIN_GMI_AD27_PAA7,
+};
+
+static const unsigned gpu_pins[] = {
+       TEGRA_PIN_PU0,
+       TEGRA_PIN_PU1,
+       TEGRA_PIN_PU2,
+       TEGRA_PIN_PU3,
+       TEGRA_PIN_PU4,
+       TEGRA_PIN_PU5,
+       TEGRA_PIN_PU6,
+};
+
+static const unsigned gpu7_pins[] = {
+       TEGRA_PIN_JTAG_RTCK_PU7,
+};
+
+static const unsigned gpv_pins[] = {
+       TEGRA_PIN_PV4,
+       TEGRA_PIN_PV5,
+       TEGRA_PIN_PV6,
+};
+
+static const unsigned hdint_pins[] = {
+       TEGRA_PIN_HDMI_INT_N_PN7,
+};
+
+static const unsigned i2cp_pins[] = {
+       TEGRA_PIN_PWR_I2C_SCL_PZ6,
+       TEGRA_PIN_PWR_I2C_SDA_PZ7,
+};
+
+static const unsigned irrx_pins[] = {
+       TEGRA_PIN_UART2_RTS_N_PJ6,
+};
+
+static const unsigned irtx_pins[] = {
+       TEGRA_PIN_UART2_CTS_N_PJ5,
+};
+
+static const unsigned kbca_pins[] = {
+       TEGRA_PIN_KB_ROW0_PR0,
+       TEGRA_PIN_KB_ROW1_PR1,
+       TEGRA_PIN_KB_ROW2_PR2,
+};
+
+static const unsigned kbcb_pins[] = {
+       TEGRA_PIN_KB_ROW7_PR7,
+       TEGRA_PIN_KB_ROW8_PS0,
+       TEGRA_PIN_KB_ROW9_PS1,
+       TEGRA_PIN_KB_ROW10_PS2,
+       TEGRA_PIN_KB_ROW11_PS3,
+       TEGRA_PIN_KB_ROW12_PS4,
+       TEGRA_PIN_KB_ROW13_PS5,
+       TEGRA_PIN_KB_ROW14_PS6,
+       TEGRA_PIN_KB_ROW15_PS7,
+};
+
+static const unsigned kbcc_pins[] = {
+       TEGRA_PIN_KB_COL0_PQ0,
+       TEGRA_PIN_KB_COL1_PQ1,
+};
+
+static const unsigned kbcd_pins[] = {
+       TEGRA_PIN_KB_ROW3_PR3,
+       TEGRA_PIN_KB_ROW4_PR4,
+       TEGRA_PIN_KB_ROW5_PR5,
+       TEGRA_PIN_KB_ROW6_PR6,
+};
+
+static const unsigned kbce_pins[] = {
+       TEGRA_PIN_KB_COL7_PQ7,
+};
+
+static const unsigned kbcf_pins[] = {
+       TEGRA_PIN_KB_COL2_PQ2,
+       TEGRA_PIN_KB_COL3_PQ3,
+       TEGRA_PIN_KB_COL4_PQ4,
+       TEGRA_PIN_KB_COL5_PQ5,
+       TEGRA_PIN_KB_COL6_PQ6,
+};
+
+static const unsigned lcsn_pins[] = {
+       TEGRA_PIN_LCD_CS0_N_PN4,
+};
+
+static const unsigned ld0_pins[] = {
+       TEGRA_PIN_LCD_D0_PE0,
+};
+
+static const unsigned ld1_pins[] = {
+       TEGRA_PIN_LCD_D1_PE1,
+};
+
+static const unsigned ld2_pins[] = {
+       TEGRA_PIN_LCD_D2_PE2,
+};
+
+static const unsigned ld3_pins[] = {
+       TEGRA_PIN_LCD_D3_PE3,
+};
+
+static const unsigned ld4_pins[] = {
+       TEGRA_PIN_LCD_D4_PE4,
+};
+
+static const unsigned ld5_pins[] = {
+       TEGRA_PIN_LCD_D5_PE5,
+};
+
+static const unsigned ld6_pins[] = {
+       TEGRA_PIN_LCD_D6_PE6,
+};
+
+static const unsigned ld7_pins[] = {
+       TEGRA_PIN_LCD_D7_PE7,
+};
+
+static const unsigned ld8_pins[] = {
+       TEGRA_PIN_LCD_D8_PF0,
+};
+
+static const unsigned ld9_pins[] = {
+       TEGRA_PIN_LCD_D9_PF1,
+};
+
+static const unsigned ld10_pins[] = {
+       TEGRA_PIN_LCD_D10_PF2,
+};
+
+static const unsigned ld11_pins[] = {
+       TEGRA_PIN_LCD_D11_PF3,
+};
+
+static const unsigned ld12_pins[] = {
+       TEGRA_PIN_LCD_D12_PF4,
+};
+
+static const unsigned ld13_pins[] = {
+       TEGRA_PIN_LCD_D13_PF5,
+};
+
+static const unsigned ld14_pins[] = {
+       TEGRA_PIN_LCD_D14_PF6,
+};
+
+static const unsigned ld15_pins[] = {
+       TEGRA_PIN_LCD_D15_PF7,
+};
+
+static const unsigned ld16_pins[] = {
+       TEGRA_PIN_LCD_D16_PM0,
+};
+
+static const unsigned ld17_pins[] = {
+       TEGRA_PIN_LCD_D17_PM1,
+};
+
+static const unsigned ldc_pins[] = {
+       TEGRA_PIN_LCD_DC0_PN6,
+};
+
+static const unsigned ldi_pins[] = {
+       TEGRA_PIN_LCD_D22_PM6,
+};
+
+static const unsigned lhp0_pins[] = {
+       TEGRA_PIN_LCD_D21_PM5,
+};
+
+static const unsigned lhp1_pins[] = {
+       TEGRA_PIN_LCD_D18_PM2,
+};
+
+static const unsigned lhp2_pins[] = {
+       TEGRA_PIN_LCD_D19_PM3,
+};
+
+static const unsigned lhs_pins[] = {
+       TEGRA_PIN_LCD_HSYNC_PJ3,
+};
+
+static const unsigned lm0_pins[] = {
+       TEGRA_PIN_LCD_CS1_N_PW0,
+};
+
+static const unsigned lm1_pins[] = {
+       TEGRA_PIN_LCD_M1_PW1,
+};
+
+static const unsigned lpp_pins[] = {
+       TEGRA_PIN_LCD_D23_PM7,
+};
+
+static const unsigned lpw0_pins[] = {
+       TEGRA_PIN_LCD_PWR0_PB2,
+};
+
+static const unsigned lpw1_pins[] = {
+       TEGRA_PIN_LCD_PWR1_PC1,
+};
+
+static const unsigned lpw2_pins[] = {
+       TEGRA_PIN_LCD_PWR2_PC6,
+};
+
+static const unsigned lsc0_pins[] = {
+       TEGRA_PIN_LCD_PCLK_PB3,
+};
+
+static const unsigned lsc1_pins[] = {
+       TEGRA_PIN_LCD_WR_N_PZ3,
+};
+
+static const unsigned lsck_pins[] = {
+       TEGRA_PIN_LCD_SCK_PZ4,
+};
+
+static const unsigned lsda_pins[] = {
+       TEGRA_PIN_LCD_SDOUT_PN5,
+};
+
+static const unsigned lsdi_pins[] = {
+       TEGRA_PIN_LCD_SDIN_PZ2,
+};
+
+static const unsigned lspi_pins[] = {
+       TEGRA_PIN_LCD_DE_PJ1,
+};
+
+static const unsigned lvp0_pins[] = {
+       TEGRA_PIN_LCD_DC1_PV7,
+};
+
+static const unsigned lvp1_pins[] = {
+       TEGRA_PIN_LCD_D20_PM4,
+};
+
+static const unsigned lvs_pins[] = {
+       TEGRA_PIN_LCD_VSYNC_PJ4,
+};
+
+static const unsigned ls_pins[] = {
+       TEGRA_PIN_LCD_PWR0_PB2,
+       TEGRA_PIN_LCD_PWR1_PC1,
+       TEGRA_PIN_LCD_PWR2_PC6,
+       TEGRA_PIN_LCD_SDIN_PZ2,
+       TEGRA_PIN_LCD_SDOUT_PN5,
+       TEGRA_PIN_LCD_WR_N_PZ3,
+       TEGRA_PIN_LCD_CS0_N_PN4,
+       TEGRA_PIN_LCD_DC0_PN6,
+       TEGRA_PIN_LCD_SCK_PZ4,
+};
+
+static const unsigned lc_pins[] = {
+       TEGRA_PIN_LCD_PCLK_PB3,
+       TEGRA_PIN_LCD_DE_PJ1,
+       TEGRA_PIN_LCD_HSYNC_PJ3,
+       TEGRA_PIN_LCD_VSYNC_PJ4,
+       TEGRA_PIN_LCD_CS1_N_PW0,
+       TEGRA_PIN_LCD_M1_PW1,
+       TEGRA_PIN_LCD_DC1_PV7,
+       TEGRA_PIN_HDMI_INT_N_PN7,
+};
+
+static const unsigned ld17_0_pins[] = {
+       TEGRA_PIN_LCD_D0_PE0,
+       TEGRA_PIN_LCD_D1_PE1,
+       TEGRA_PIN_LCD_D2_PE2,
+       TEGRA_PIN_LCD_D3_PE3,
+       TEGRA_PIN_LCD_D4_PE4,
+       TEGRA_PIN_LCD_D5_PE5,
+       TEGRA_PIN_LCD_D6_PE6,
+       TEGRA_PIN_LCD_D7_PE7,
+       TEGRA_PIN_LCD_D8_PF0,
+       TEGRA_PIN_LCD_D9_PF1,
+       TEGRA_PIN_LCD_D10_PF2,
+       TEGRA_PIN_LCD_D11_PF3,
+       TEGRA_PIN_LCD_D12_PF4,
+       TEGRA_PIN_LCD_D13_PF5,
+       TEGRA_PIN_LCD_D14_PF6,
+       TEGRA_PIN_LCD_D15_PF7,
+       TEGRA_PIN_LCD_D16_PM0,
+       TEGRA_PIN_LCD_D17_PM1,
+};
+
+static const unsigned ld19_18_pins[] = {
+       TEGRA_PIN_LCD_D18_PM2,
+       TEGRA_PIN_LCD_D19_PM3,
+};
+
+static const unsigned ld21_20_pins[] = {
+       TEGRA_PIN_LCD_D20_PM4,
+       TEGRA_PIN_LCD_D21_PM5,
+};
+
+static const unsigned ld23_22_pins[] = {
+       TEGRA_PIN_LCD_D22_PM6,
+       TEGRA_PIN_LCD_D23_PM7,
+};
+
+static const unsigned owc_pins[] = {
+       TEGRA_PIN_OWC,
+};
+
+static const unsigned pmc_pins[] = {
+       TEGRA_PIN_LED_BLINK_PBB0,
+       TEGRA_PIN_SYS_CLK_REQ_PZ5,
+       TEGRA_PIN_CORE_PWR_REQ,
+       TEGRA_PIN_CPU_PWR_REQ,
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned pta_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PT5,
+       TEGRA_PIN_GEN2_I2C_SDA_PT6,
+};
+
+static const unsigned rm_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PC4,
+       TEGRA_PIN_GEN1_I2C_SDA_PC5,
+};
+
+static const unsigned sdb_pins[] = {
+       TEGRA_PIN_SDIO3_CMD_PA7,
+};
+
+static const unsigned sdc_pins[] = {
+       TEGRA_PIN_SDIO3_DAT0_PB7,
+       TEGRA_PIN_SDIO3_DAT1_PB6,
+       TEGRA_PIN_SDIO3_DAT2_PB5,
+       TEGRA_PIN_SDIO3_DAT3_PB4,
+};
+
+static const unsigned sdd_pins[] = {
+       TEGRA_PIN_SDIO3_CLK_PA6,
+};
+
+static const unsigned sdio1_pins[] = {
+       TEGRA_PIN_SDIO1_CLK_PZ0,
+       TEGRA_PIN_SDIO1_CMD_PZ1,
+       TEGRA_PIN_SDIO1_DAT0_PY7,
+       TEGRA_PIN_SDIO1_DAT1_PY6,
+       TEGRA_PIN_SDIO1_DAT2_PY5,
+       TEGRA_PIN_SDIO1_DAT3_PY4,
+};
+
+static const unsigned slxa_pins[] = {
+       TEGRA_PIN_SDIO3_DAT4_PD1,
+};
+
+static const unsigned slxc_pins[] = {
+       TEGRA_PIN_SDIO3_DAT6_PD3,
+};
+
+static const unsigned slxd_pins[] = {
+       TEGRA_PIN_SDIO3_DAT7_PD4,
+};
+
+static const unsigned slxk_pins[] = {
+       TEGRA_PIN_SDIO3_DAT5_PD0,
+};
+
+static const unsigned spdi_pins[] = {
+       TEGRA_PIN_SPDIF_IN_PK6,
+};
+
+static const unsigned spdo_pins[] = {
+       TEGRA_PIN_SPDIF_OUT_PK5,
+};
+
+static const unsigned spia_pins[] = {
+       TEGRA_PIN_SPI2_MOSI_PX0,
+};
+
+static const unsigned spib_pins[] = {
+       TEGRA_PIN_SPI2_MISO_PX1,
+};
+
+static const unsigned spic_pins[] = {
+       TEGRA_PIN_SPI2_CS0_N_PX3,
+       TEGRA_PIN_SPI2_SCK_PX2,
+};
+
+static const unsigned spid_pins[] = {
+       TEGRA_PIN_SPI1_MOSI_PX4,
+};
+
+static const unsigned spie_pins[] = {
+       TEGRA_PIN_SPI1_CS0_N_PX6,
+       TEGRA_PIN_SPI1_SCK_PX5,
+};
+
+static const unsigned spif_pins[] = {
+       TEGRA_PIN_SPI1_MISO_PX7,
+};
+
+static const unsigned spig_pins[] = {
+       TEGRA_PIN_SPI2_CS1_N_PW2,
+};
+
+static const unsigned spih_pins[] = {
+       TEGRA_PIN_SPI2_CS2_N_PW3,
+};
+
+static const unsigned uaa_pins[] = {
+       TEGRA_PIN_ULPI_DATA0_PO1,
+       TEGRA_PIN_ULPI_DATA1_PO2,
+       TEGRA_PIN_ULPI_DATA2_PO3,
+       TEGRA_PIN_ULPI_DATA3_PO4,
+};
+
+static const unsigned uab_pins[] = {
+       TEGRA_PIN_ULPI_DATA4_PO5,
+       TEGRA_PIN_ULPI_DATA5_PO6,
+       TEGRA_PIN_ULPI_DATA6_PO7,
+       TEGRA_PIN_ULPI_DATA7_PO0,
+};
+
+static const unsigned uac_pins[] = {
+       TEGRA_PIN_PV0,
+       TEGRA_PIN_PV1,
+       TEGRA_PIN_PV2,
+       TEGRA_PIN_PV3,
+};
+
+static const unsigned ck32_pins[] = {
+       TEGRA_PIN_CLK_32_K_IN,
+};
+
+static const unsigned uad_pins[] = {
+       TEGRA_PIN_UART2_RXD_PC3,
+       TEGRA_PIN_UART2_TXD_PC2,
+};
+
+static const unsigned uca_pins[] = {
+       TEGRA_PIN_UART3_RXD_PW7,
+       TEGRA_PIN_UART3_TXD_PW6,
+};
+
+static const unsigned ucb_pins[] = {
+       TEGRA_PIN_UART3_CTS_N_PA1,
+       TEGRA_PIN_UART3_RTS_N_PC0,
+};
+
+static const unsigned uda_pins[] = {
+       TEGRA_PIN_ULPI_CLK_PY0,
+       TEGRA_PIN_ULPI_DIR_PY1,
+       TEGRA_PIN_ULPI_NXT_PY2,
+       TEGRA_PIN_ULPI_STP_PY3,
+};
+
+static const unsigned ddrc_pins[] = {
+       TEGRA_PIN_DDR_COMP_PD,
+       TEGRA_PIN_DDR_COMP_PU,
+};
+
+static const unsigned pmca_pins[] = {
+       TEGRA_PIN_LED_BLINK_PBB0,
+};
+
+static const unsigned pmcb_pins[] = {
+       TEGRA_PIN_SYS_CLK_REQ_PZ5,
+};
+
+static const unsigned pmcc_pins[] = {
+       TEGRA_PIN_CORE_PWR_REQ,
+};
+
+static const unsigned pmcd_pins[] = {
+       TEGRA_PIN_CPU_PWR_REQ,
+};
+
+static const unsigned pmce_pins[] = {
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned xm2c_pins[] = {
+       TEGRA_PIN_DDR_A0,
+       TEGRA_PIN_DDR_A1,
+       TEGRA_PIN_DDR_A2,
+       TEGRA_PIN_DDR_A3,
+       TEGRA_PIN_DDR_A4,
+       TEGRA_PIN_DDR_A5,
+       TEGRA_PIN_DDR_A6,
+       TEGRA_PIN_DDR_A7,
+       TEGRA_PIN_DDR_A8,
+       TEGRA_PIN_DDR_A9,
+       TEGRA_PIN_DDR_A10,
+       TEGRA_PIN_DDR_A11,
+       TEGRA_PIN_DDR_A12,
+       TEGRA_PIN_DDR_A13,
+       TEGRA_PIN_DDR_A14,
+       TEGRA_PIN_DDR_CAS_N,
+       TEGRA_PIN_DDR_BA0,
+       TEGRA_PIN_DDR_BA1,
+       TEGRA_PIN_DDR_BA2,
+       TEGRA_PIN_DDR_DQS0P,
+       TEGRA_PIN_DDR_DQS0N,
+       TEGRA_PIN_DDR_DQS1P,
+       TEGRA_PIN_DDR_DQS1N,
+       TEGRA_PIN_DDR_DQS2P,
+       TEGRA_PIN_DDR_DQS2N,
+       TEGRA_PIN_DDR_DQS3P,
+       TEGRA_PIN_DDR_DQS3N,
+       TEGRA_PIN_DDR_CS0_N,
+       TEGRA_PIN_DDR_CS1_N,
+       TEGRA_PIN_DDR_CKE0,
+       TEGRA_PIN_DDR_CKE1,
+       TEGRA_PIN_DDR_CLK,
+       TEGRA_PIN_DDR_CLK_N,
+       TEGRA_PIN_DDR_DM0,
+       TEGRA_PIN_DDR_DM1,
+       TEGRA_PIN_DDR_DM2,
+       TEGRA_PIN_DDR_DM3,
+       TEGRA_PIN_DDR_ODT,
+       TEGRA_PIN_DDR_RAS_N,
+       TEGRA_PIN_DDR_WE_N,
+       TEGRA_PIN_DDR_QUSE0,
+       TEGRA_PIN_DDR_QUSE1,
+       TEGRA_PIN_DDR_QUSE2,
+       TEGRA_PIN_DDR_QUSE3,
+};
+
+static const unsigned xm2d_pins[] = {
+       TEGRA_PIN_DDR_DQ0,
+       TEGRA_PIN_DDR_DQ1,
+       TEGRA_PIN_DDR_DQ2,
+       TEGRA_PIN_DDR_DQ3,
+       TEGRA_PIN_DDR_DQ4,
+       TEGRA_PIN_DDR_DQ5,
+       TEGRA_PIN_DDR_DQ6,
+       TEGRA_PIN_DDR_DQ7,
+       TEGRA_PIN_DDR_DQ8,
+       TEGRA_PIN_DDR_DQ9,
+       TEGRA_PIN_DDR_DQ10,
+       TEGRA_PIN_DDR_DQ11,
+       TEGRA_PIN_DDR_DQ12,
+       TEGRA_PIN_DDR_DQ13,
+       TEGRA_PIN_DDR_DQ14,
+       TEGRA_PIN_DDR_DQ15,
+       TEGRA_PIN_DDR_DQ16,
+       TEGRA_PIN_DDR_DQ17,
+       TEGRA_PIN_DDR_DQ18,
+       TEGRA_PIN_DDR_DQ19,
+       TEGRA_PIN_DDR_DQ20,
+       TEGRA_PIN_DDR_DQ21,
+       TEGRA_PIN_DDR_DQ22,
+       TEGRA_PIN_DDR_DQ23,
+       TEGRA_PIN_DDR_DQ24,
+       TEGRA_PIN_DDR_DQ25,
+       TEGRA_PIN_DDR_DQ26,
+       TEGRA_PIN_DDR_DQ27,
+       TEGRA_PIN_DDR_DQ28,
+       TEGRA_PIN_DDR_DQ29,
+       TEGRA_PIN_DDR_DQ30,
+       TEGRA_PIN_DDR_DQ31,
+};
+
+static const unsigned drive_ao1_pins[] = {
+       TEGRA_PIN_SYS_RESET,
+       TEGRA_PIN_PWR_I2C_SCL_PZ6,
+       TEGRA_PIN_PWR_I2C_SDA_PZ7,
+       TEGRA_PIN_KB_ROW0_PR0,
+       TEGRA_PIN_KB_ROW1_PR1,
+       TEGRA_PIN_KB_ROW2_PR2,
+       TEGRA_PIN_KB_ROW3_PR3,
+       TEGRA_PIN_KB_ROW4_PR4,
+       TEGRA_PIN_KB_ROW5_PR5,
+       TEGRA_PIN_KB_ROW6_PR6,
+       TEGRA_PIN_KB_ROW7_PR7,
+};
+
+static const unsigned drive_ao2_pins[] = {
+       TEGRA_PIN_KB_ROW8_PS0,
+       TEGRA_PIN_KB_ROW9_PS1,
+       TEGRA_PIN_KB_ROW10_PS2,
+       TEGRA_PIN_KB_ROW11_PS3,
+       TEGRA_PIN_KB_ROW12_PS4,
+       TEGRA_PIN_KB_ROW13_PS5,
+       TEGRA_PIN_KB_ROW14_PS6,
+       TEGRA_PIN_KB_ROW15_PS7,
+       TEGRA_PIN_KB_COL0_PQ0,
+       TEGRA_PIN_KB_COL1_PQ1,
+       TEGRA_PIN_KB_COL2_PQ2,
+       TEGRA_PIN_KB_COL3_PQ3,
+       TEGRA_PIN_KB_COL4_PQ4,
+       TEGRA_PIN_KB_COL5_PQ5,
+       TEGRA_PIN_KB_COL6_PQ6,
+       TEGRA_PIN_KB_COL7_PQ7,
+       TEGRA_PIN_LED_BLINK_PBB0,
+       TEGRA_PIN_SYS_CLK_REQ_PZ5,
+       TEGRA_PIN_CORE_PWR_REQ,
+       TEGRA_PIN_CPU_PWR_REQ,
+       TEGRA_PIN_PWR_INT_N,
+       TEGRA_PIN_CLK_32_K_IN,
+};
+
+static const unsigned drive_at1_pins[] = {
+       TEGRA_PIN_GMI_IORDY_PI5,
+       TEGRA_PIN_GMI_AD8_PH0,
+       TEGRA_PIN_GMI_AD9_PH1,
+       TEGRA_PIN_GMI_AD10_PH2,
+       TEGRA_PIN_GMI_AD11_PH3,
+       TEGRA_PIN_GMI_AD12_PH4,
+       TEGRA_PIN_GMI_AD13_PH5,
+       TEGRA_PIN_GMI_AD14_PH6,
+       TEGRA_PIN_GMI_AD15_PH7,
+       TEGRA_PIN_GMI_CS7_N_PI6,
+       TEGRA_PIN_GMI_DPD_PT7,
+       TEGRA_PIN_GEN2_I2C_SCL_PT5,
+       TEGRA_PIN_GEN2_I2C_SDA_PT6,
+};
+
+static const unsigned drive_at2_pins[] = {
+       TEGRA_PIN_GMI_WAIT_PI7,
+       TEGRA_PIN_GMI_ADV_N_PK0,
+       TEGRA_PIN_GMI_CLK_PK1,
+       TEGRA_PIN_GMI_CS6_N_PI3,
+       TEGRA_PIN_GMI_CS5_N_PI2,
+       TEGRA_PIN_GMI_CS4_N_PK2,
+       TEGRA_PIN_GMI_CS3_N_PK4,
+       TEGRA_PIN_GMI_CS2_N_PK3,
+       TEGRA_PIN_GMI_AD0_PG0,
+       TEGRA_PIN_GMI_AD1_PG1,
+       TEGRA_PIN_GMI_AD2_PG2,
+       TEGRA_PIN_GMI_AD3_PG3,
+       TEGRA_PIN_GMI_AD4_PG4,
+       TEGRA_PIN_GMI_AD5_PG5,
+       TEGRA_PIN_GMI_AD6_PG6,
+       TEGRA_PIN_GMI_AD7_PG7,
+       TEGRA_PIN_GMI_HIOW_N_PI0,
+       TEGRA_PIN_GMI_HIOR_N_PI1,
+       TEGRA_PIN_GMI_RST_N_PI4,
+};
+
+static const unsigned drive_cdev1_pins[] = {
+       TEGRA_PIN_DAP_MCLK1_PW4,
+};
+
+static const unsigned drive_cdev2_pins[] = {
+       TEGRA_PIN_DAP_MCLK2_PW5,
+};
+
+static const unsigned drive_csus_pins[] = {
+       TEGRA_PIN_VI_MCLK_PT1,
+};
+
+static const unsigned drive_dap1_pins[] = {
+       TEGRA_PIN_DAP1_FS_PN0,
+       TEGRA_PIN_DAP1_DIN_PN1,
+       TEGRA_PIN_DAP1_DOUT_PN2,
+       TEGRA_PIN_DAP1_SCLK_PN3,
+       TEGRA_PIN_SPDIF_OUT_PK5,
+       TEGRA_PIN_SPDIF_IN_PK6,
+};
+
+static const unsigned drive_dap2_pins[] = {
+       TEGRA_PIN_DAP2_FS_PA2,
+       TEGRA_PIN_DAP2_SCLK_PA3,
+       TEGRA_PIN_DAP2_DIN_PA4,
+       TEGRA_PIN_DAP2_DOUT_PA5,
+};
+
+static const unsigned drive_dap3_pins[] = {
+       TEGRA_PIN_DAP3_FS_PP0,
+       TEGRA_PIN_DAP3_DIN_PP1,
+       TEGRA_PIN_DAP3_DOUT_PP2,
+       TEGRA_PIN_DAP3_SCLK_PP3,
+};
+
+static const unsigned drive_dap4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PP4,
+       TEGRA_PIN_DAP4_DIN_PP5,
+       TEGRA_PIN_DAP4_DOUT_PP6,
+       TEGRA_PIN_DAP4_SCLK_PP7,
+};
+
+static const unsigned drive_dbg_pins[] = {
+       TEGRA_PIN_PU0,
+       TEGRA_PIN_PU1,
+       TEGRA_PIN_PU2,
+       TEGRA_PIN_PU3,
+       TEGRA_PIN_PU4,
+       TEGRA_PIN_PU5,
+       TEGRA_PIN_PU6,
+       TEGRA_PIN_JTAG_RTCK_PU7,
+       TEGRA_PIN_GEN1_I2C_SDA_PC5,
+       TEGRA_PIN_GEN1_I2C_SCL_PC4,
+       TEGRA_PIN_JTAG_TRST_N,
+       TEGRA_PIN_JTAG_TDO,
+       TEGRA_PIN_JTAG_TMS,
+       TEGRA_PIN_JTAG_TCK,
+       TEGRA_PIN_JTAG_TDI,
+       TEGRA_PIN_TEST_MODE_EN,
+};
+
+static const unsigned drive_lcd1_pins[] = {
+       TEGRA_PIN_LCD_PWR1_PC1,
+       TEGRA_PIN_LCD_PWR2_PC6,
+       TEGRA_PIN_LCD_SDIN_PZ2,
+       TEGRA_PIN_LCD_SDOUT_PN5,
+       TEGRA_PIN_LCD_WR_N_PZ3,
+       TEGRA_PIN_LCD_CS0_N_PN4,
+       TEGRA_PIN_LCD_DC0_PN6,
+       TEGRA_PIN_LCD_SCK_PZ4,
+};
+
+static const unsigned drive_lcd2_pins[] = {
+       TEGRA_PIN_LCD_PWR0_PB2,
+       TEGRA_PIN_LCD_PCLK_PB3,
+       TEGRA_PIN_LCD_DE_PJ1,
+       TEGRA_PIN_LCD_HSYNC_PJ3,
+       TEGRA_PIN_LCD_VSYNC_PJ4,
+       TEGRA_PIN_LCD_D0_PE0,
+       TEGRA_PIN_LCD_D1_PE1,
+       TEGRA_PIN_LCD_D2_PE2,
+       TEGRA_PIN_LCD_D3_PE3,
+       TEGRA_PIN_LCD_D4_PE4,
+       TEGRA_PIN_LCD_D5_PE5,
+       TEGRA_PIN_LCD_D6_PE6,
+       TEGRA_PIN_LCD_D7_PE7,
+       TEGRA_PIN_LCD_D8_PF0,
+       TEGRA_PIN_LCD_D9_PF1,
+       TEGRA_PIN_LCD_D10_PF2,
+       TEGRA_PIN_LCD_D11_PF3,
+       TEGRA_PIN_LCD_D12_PF4,
+       TEGRA_PIN_LCD_D13_PF5,
+       TEGRA_PIN_LCD_D14_PF6,
+       TEGRA_PIN_LCD_D15_PF7,
+       TEGRA_PIN_LCD_D16_PM0,
+       TEGRA_PIN_LCD_D17_PM1,
+       TEGRA_PIN_LCD_D18_PM2,
+       TEGRA_PIN_LCD_D19_PM3,
+       TEGRA_PIN_LCD_D20_PM4,
+       TEGRA_PIN_LCD_D21_PM5,
+       TEGRA_PIN_LCD_D22_PM6,
+       TEGRA_PIN_LCD_D23_PM7,
+       TEGRA_PIN_LCD_CS1_N_PW0,
+       TEGRA_PIN_LCD_M1_PW1,
+       TEGRA_PIN_LCD_DC1_PV7,
+       TEGRA_PIN_HDMI_INT_N_PN7,
+};
+
+static const unsigned drive_sdmmc2_pins[] = {
+       TEGRA_PIN_SDIO3_DAT4_PD1,
+       TEGRA_PIN_SDIO3_DAT5_PD0,
+       TEGRA_PIN_SDIO3_DAT6_PD3,
+       TEGRA_PIN_SDIO3_DAT7_PD4,
+};
+
+static const unsigned drive_sdmmc3_pins[] = {
+       TEGRA_PIN_SDIO3_CLK_PA6,
+       TEGRA_PIN_SDIO3_CMD_PA7,
+       TEGRA_PIN_SDIO3_DAT0_PB7,
+       TEGRA_PIN_SDIO3_DAT1_PB6,
+       TEGRA_PIN_SDIO3_DAT2_PB5,
+       TEGRA_PIN_SDIO3_DAT3_PB4,
+       TEGRA_PIN_PV4,
+       TEGRA_PIN_PV5,
+       TEGRA_PIN_PV6,
+};
+
+static const unsigned drive_spi_pins[] = {
+       TEGRA_PIN_SPI2_MOSI_PX0,
+       TEGRA_PIN_SPI2_MISO_PX1,
+       TEGRA_PIN_SPI2_SCK_PX2,
+       TEGRA_PIN_SPI2_CS0_N_PX3,
+       TEGRA_PIN_SPI1_MOSI_PX4,
+       TEGRA_PIN_SPI1_SCK_PX5,
+       TEGRA_PIN_SPI1_CS0_N_PX6,
+       TEGRA_PIN_SPI1_MISO_PX7,
+       TEGRA_PIN_SPI2_CS1_N_PW2,
+       TEGRA_PIN_SPI2_CS2_N_PW3,
+};
+
+static const unsigned drive_uaa_pins[] = {
+       TEGRA_PIN_ULPI_DATA0_PO1,
+       TEGRA_PIN_ULPI_DATA1_PO2,
+       TEGRA_PIN_ULPI_DATA2_PO3,
+       TEGRA_PIN_ULPI_DATA3_PO4,
+};
+
+static const unsigned drive_uab_pins[] = {
+       TEGRA_PIN_ULPI_DATA4_PO5,
+       TEGRA_PIN_ULPI_DATA5_PO6,
+       TEGRA_PIN_ULPI_DATA6_PO7,
+       TEGRA_PIN_ULPI_DATA7_PO0,
+       TEGRA_PIN_PV0,
+       TEGRA_PIN_PV1,
+       TEGRA_PIN_PV2,
+       TEGRA_PIN_PV3,
+};
+
+static const unsigned drive_uart2_pins[] = {
+       TEGRA_PIN_UART2_TXD_PC2,
+       TEGRA_PIN_UART2_RXD_PC3,
+       TEGRA_PIN_UART2_RTS_N_PJ6,
+       TEGRA_PIN_UART2_CTS_N_PJ5,
+};
+
+static const unsigned drive_uart3_pins[] = {
+       TEGRA_PIN_UART3_TXD_PW6,
+       TEGRA_PIN_UART3_RXD_PW7,
+       TEGRA_PIN_UART3_RTS_N_PC0,
+       TEGRA_PIN_UART3_CTS_N_PA1,
+};
+
+static const unsigned drive_vi1_pins[] = {
+       TEGRA_PIN_VI_D0_PT4,
+       TEGRA_PIN_VI_D1_PD5,
+       TEGRA_PIN_VI_D2_PL0,
+       TEGRA_PIN_VI_D3_PL1,
+       TEGRA_PIN_VI_D4_PL2,
+       TEGRA_PIN_VI_D5_PL3,
+       TEGRA_PIN_VI_D6_PL4,
+       TEGRA_PIN_VI_D7_PL5,
+       TEGRA_PIN_VI_D8_PL6,
+       TEGRA_PIN_VI_D9_PL7,
+       TEGRA_PIN_VI_D10_PT2,
+       TEGRA_PIN_VI_D11_PT3,
+       TEGRA_PIN_VI_PCLK_PT0,
+       TEGRA_PIN_VI_VSYNC_PD6,
+       TEGRA_PIN_VI_HSYNC_PD7,
+};
+
+static const unsigned drive_vi2_pins[] = {
+       TEGRA_PIN_VI_GP0_PBB1,
+       TEGRA_PIN_CAM_I2C_SCL_PBB2,
+       TEGRA_PIN_CAM_I2C_SDA_PBB3,
+       TEGRA_PIN_VI_GP3_PBB4,
+       TEGRA_PIN_VI_GP4_PBB5,
+       TEGRA_PIN_VI_GP5_PD2,
+       TEGRA_PIN_VI_GP6_PA0,
+};
+
+static const unsigned drive_xm2a_pins[] = {
+       TEGRA_PIN_DDR_A0,
+       TEGRA_PIN_DDR_A1,
+       TEGRA_PIN_DDR_A2,
+       TEGRA_PIN_DDR_A3,
+       TEGRA_PIN_DDR_A4,
+       TEGRA_PIN_DDR_A5,
+       TEGRA_PIN_DDR_A6,
+       TEGRA_PIN_DDR_A7,
+       TEGRA_PIN_DDR_A8,
+       TEGRA_PIN_DDR_A9,
+       TEGRA_PIN_DDR_A10,
+       TEGRA_PIN_DDR_A11,
+       TEGRA_PIN_DDR_A12,
+       TEGRA_PIN_DDR_A13,
+       TEGRA_PIN_DDR_A14,
+       TEGRA_PIN_DDR_BA0,
+       TEGRA_PIN_DDR_BA1,
+       TEGRA_PIN_DDR_BA2,
+       TEGRA_PIN_DDR_CS0_N,
+       TEGRA_PIN_DDR_CS1_N,
+       TEGRA_PIN_DDR_ODT,
+       TEGRA_PIN_DDR_RAS_N,
+       TEGRA_PIN_DDR_CAS_N,
+       TEGRA_PIN_DDR_WE_N,
+       TEGRA_PIN_DDR_CKE0,
+       TEGRA_PIN_DDR_CKE1,
+};
+
+static const unsigned drive_xm2c_pins[] = {
+       TEGRA_PIN_DDR_DQS0P,
+       TEGRA_PIN_DDR_DQS0N,
+       TEGRA_PIN_DDR_DQS1P,
+       TEGRA_PIN_DDR_DQS1N,
+       TEGRA_PIN_DDR_DQS2P,
+       TEGRA_PIN_DDR_DQS2N,
+       TEGRA_PIN_DDR_DQS3P,
+       TEGRA_PIN_DDR_DQS3N,
+       TEGRA_PIN_DDR_QUSE0,
+       TEGRA_PIN_DDR_QUSE1,
+       TEGRA_PIN_DDR_QUSE2,
+       TEGRA_PIN_DDR_QUSE3,
+};
+
+static const unsigned drive_xm2d_pins[] = {
+       TEGRA_PIN_DDR_DQ0,
+       TEGRA_PIN_DDR_DQ1,
+       TEGRA_PIN_DDR_DQ2,
+       TEGRA_PIN_DDR_DQ3,
+       TEGRA_PIN_DDR_DQ4,
+       TEGRA_PIN_DDR_DQ5,
+       TEGRA_PIN_DDR_DQ6,
+       TEGRA_PIN_DDR_DQ7,
+       TEGRA_PIN_DDR_DQ8,
+       TEGRA_PIN_DDR_DQ9,
+       TEGRA_PIN_DDR_DQ10,
+       TEGRA_PIN_DDR_DQ11,
+       TEGRA_PIN_DDR_DQ12,
+       TEGRA_PIN_DDR_DQ13,
+       TEGRA_PIN_DDR_DQ14,
+       TEGRA_PIN_DDR_DQ15,
+       TEGRA_PIN_DDR_DQ16,
+       TEGRA_PIN_DDR_DQ17,
+       TEGRA_PIN_DDR_DQ18,
+       TEGRA_PIN_DDR_DQ19,
+       TEGRA_PIN_DDR_DQ20,
+       TEGRA_PIN_DDR_DQ21,
+       TEGRA_PIN_DDR_DQ22,
+       TEGRA_PIN_DDR_DQ23,
+       TEGRA_PIN_DDR_DQ24,
+       TEGRA_PIN_DDR_DQ25,
+       TEGRA_PIN_DDR_DQ26,
+       TEGRA_PIN_DDR_DQ27,
+       TEGRA_PIN_DDR_DQ28,
+       TEGRA_PIN_DDR_DQ29,
+       TEGRA_PIN_DDR_DQ30,
+       TEGRA_PIN_DDR_DQ31,
+       TEGRA_PIN_DDR_DM0,
+       TEGRA_PIN_DDR_DM1,
+       TEGRA_PIN_DDR_DM2,
+       TEGRA_PIN_DDR_DM3,
+};
+
+static const unsigned drive_xm2clk_pins[] = {
+       TEGRA_PIN_DDR_CLK,
+       TEGRA_PIN_DDR_CLK_N,
+};
+
+static const unsigned drive_sdio1_pins[] = {
+       TEGRA_PIN_SDIO1_CLK_PZ0,
+       TEGRA_PIN_SDIO1_CMD_PZ1,
+       TEGRA_PIN_SDIO1_DAT0_PY7,
+       TEGRA_PIN_SDIO1_DAT1_PY6,
+       TEGRA_PIN_SDIO1_DAT2_PY5,
+       TEGRA_PIN_SDIO1_DAT3_PY4,
+};
+
+static const unsigned drive_crt_pins[] = {
+       TEGRA_PIN_CRT_HSYNC,
+       TEGRA_PIN_CRT_VSYNC,
+};
+
+static const unsigned drive_ddc_pins[] = {
+       TEGRA_PIN_DDC_SCL,
+       TEGRA_PIN_DDC_SDA,
+};
+
+static const unsigned drive_gma_pins[] = {
+       TEGRA_PIN_GMI_AD20_PAA0,
+       TEGRA_PIN_GMI_AD21_PAA1,
+       TEGRA_PIN_GMI_AD22_PAA2,
+       TEGRA_PIN_GMI_AD23_PAA3,
+};
+
+static const unsigned drive_gmb_pins[] = {
+       TEGRA_PIN_GMI_WP_N_PC7,
+};
+
+static const unsigned drive_gmc_pins[] = {
+       TEGRA_PIN_GMI_AD16_PJ7,
+       TEGRA_PIN_GMI_AD17_PB0,
+       TEGRA_PIN_GMI_AD18_PB1,
+       TEGRA_PIN_GMI_AD19_PK7,
+};
+
+static const unsigned drive_gmd_pins[] = {
+       TEGRA_PIN_GMI_CS0_N_PJ0,
+       TEGRA_PIN_GMI_CS1_N_PJ2,
+};
+
+static const unsigned drive_gme_pins[] = {
+       TEGRA_PIN_GMI_AD24_PAA4,
+       TEGRA_PIN_GMI_AD25_PAA5,
+       TEGRA_PIN_GMI_AD26_PAA6,
+       TEGRA_PIN_GMI_AD27_PAA7,
+};
+
+static const unsigned drive_owr_pins[] = {
+       TEGRA_PIN_OWC,
+};
+
+static const unsigned drive_uda_pins[] = {
+       TEGRA_PIN_ULPI_CLK_PY0,
+       TEGRA_PIN_ULPI_DIR_PY1,
+       TEGRA_PIN_ULPI_NXT_PY2,
+       TEGRA_PIN_ULPI_STP_PY3,
+};
+
+enum tegra_mux {
+       TEGRA_MUX_AHB_CLK,
+       TEGRA_MUX_APB_CLK,
+       TEGRA_MUX_AUDIO_SYNC,
+       TEGRA_MUX_CRT,
+       TEGRA_MUX_DAP1,
+       TEGRA_MUX_DAP2,
+       TEGRA_MUX_DAP3,
+       TEGRA_MUX_DAP4,
+       TEGRA_MUX_DAP5,
+       TEGRA_MUX_DISPLAYA,
+       TEGRA_MUX_DISPLAYB,
+       TEGRA_MUX_EMC_TEST0_DLL,
+       TEGRA_MUX_EMC_TEST1_DLL,
+       TEGRA_MUX_GMI,
+       TEGRA_MUX_GMI_INT,
+       TEGRA_MUX_HDMI,
+       TEGRA_MUX_I2CP,
+       TEGRA_MUX_I2C1,
+       TEGRA_MUX_I2C2,
+       TEGRA_MUX_I2C3,
+       TEGRA_MUX_IDE,
+       TEGRA_MUX_IRDA,
+       TEGRA_MUX_KBC,
+       TEGRA_MUX_MIO,
+       TEGRA_MUX_MIPI_HS,
+       TEGRA_MUX_NAND,
+       TEGRA_MUX_OSC,
+       TEGRA_MUX_OWR,
+       TEGRA_MUX_PCIE,
+       TEGRA_MUX_PLLA_OUT,
+       TEGRA_MUX_PLLC_OUT1,
+       TEGRA_MUX_PLLM_OUT1,
+       TEGRA_MUX_PLLP_OUT2,
+       TEGRA_MUX_PLLP_OUT3,
+       TEGRA_MUX_PLLP_OUT4,
+       TEGRA_MUX_PWM,
+       TEGRA_MUX_PWR_INTR,
+       TEGRA_MUX_PWR_ON,
+       TEGRA_MUX_RSVD1,
+       TEGRA_MUX_RSVD2,
+       TEGRA_MUX_RSVD3,
+       TEGRA_MUX_RSVD4,
+       TEGRA_MUX_RTCK,
+       TEGRA_MUX_SDIO1,
+       TEGRA_MUX_SDIO2,
+       TEGRA_MUX_SDIO3,
+       TEGRA_MUX_SDIO4,
+       TEGRA_MUX_SFLASH,
+       TEGRA_MUX_SPDIF,
+       TEGRA_MUX_SPI1,
+       TEGRA_MUX_SPI2,
+       TEGRA_MUX_SPI2_ALT,
+       TEGRA_MUX_SPI3,
+       TEGRA_MUX_SPI4,
+       TEGRA_MUX_TRACE,
+       TEGRA_MUX_TWC,
+       TEGRA_MUX_UARTA,
+       TEGRA_MUX_UARTB,
+       TEGRA_MUX_UARTC,
+       TEGRA_MUX_UARTD,
+       TEGRA_MUX_UARTE,
+       TEGRA_MUX_ULPI,
+       TEGRA_MUX_VI,
+       TEGRA_MUX_VI_SENSOR_CLK,
+       TEGRA_MUX_XIO,
+};
+
+#define FUNCTION(fname)                                        \
+       {                                               \
+               .name = #fname,                         \
+       }
+
+static struct tegra_function tegra20_functions[] = {
+       FUNCTION(ahb_clk),
+       FUNCTION(apb_clk),
+       FUNCTION(audio_sync),
+       FUNCTION(crt),
+       FUNCTION(dap1),
+       FUNCTION(dap2),
+       FUNCTION(dap3),
+       FUNCTION(dap4),
+       FUNCTION(dap5),
+       FUNCTION(displaya),
+       FUNCTION(displayb),
+       FUNCTION(emc_test0_dll),
+       FUNCTION(emc_test1_dll),
+       FUNCTION(gmi),
+       FUNCTION(gmi_int),
+       FUNCTION(hdmi),
+       FUNCTION(i2cp),
+       FUNCTION(i2c1),
+       FUNCTION(i2c2),
+       FUNCTION(i2c3),
+       FUNCTION(ide),
+       FUNCTION(irda),
+       FUNCTION(kbc),
+       FUNCTION(mio),
+       FUNCTION(mipi_hs),
+       FUNCTION(nand),
+       FUNCTION(osc),
+       FUNCTION(owr),
+       FUNCTION(pcie),
+       FUNCTION(plla_out),
+       FUNCTION(pllc_out1),
+       FUNCTION(pllm_out1),
+       FUNCTION(pllp_out2),
+       FUNCTION(pllp_out3),
+       FUNCTION(pllp_out4),
+       FUNCTION(pwm),
+       FUNCTION(pwr_intr),
+       FUNCTION(pwr_on),
+       FUNCTION(rsvd1),
+       FUNCTION(rsvd2),
+       FUNCTION(rsvd3),
+       FUNCTION(rsvd4),
+       FUNCTION(rtck),
+       FUNCTION(sdio1),
+       FUNCTION(sdio2),
+       FUNCTION(sdio3),
+       FUNCTION(sdio4),
+       FUNCTION(sflash),
+       FUNCTION(spdif),
+       FUNCTION(spi1),
+       FUNCTION(spi2),
+       FUNCTION(spi2_alt),
+       FUNCTION(spi3),
+       FUNCTION(spi4),
+       FUNCTION(trace),
+       FUNCTION(twc),
+       FUNCTION(uarta),
+       FUNCTION(uartb),
+       FUNCTION(uartc),
+       FUNCTION(uartd),
+       FUNCTION(uarte),
+       FUNCTION(ulpi),
+       FUNCTION(vi),
+       FUNCTION(vi_sensor_clk),
+       FUNCTION(xio),
+};
+
+#define TRISTATE_REG_A         0x14
+#define PIN_MUX_CTL_REG_A      0x80
+#define PULLUPDOWN_REG_A       0xa0
+#define PINGROUP_REG_A         0x868
+
+/* Pin group with mux control, and typically tri-state and pull-up/down too */
+#define MUX_PG(pg_name, f0, f1, f2, f3,                                \
+              tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)      \
+       {                                                       \
+               .name = #pg_name,                               \
+               .pins = pg_name##_pins,                         \
+               .npins = ARRAY_SIZE(pg_name##_pins),            \
+               .funcs = {                                      \
+                       TEGRA_MUX_ ## f0,                       \
+                       TEGRA_MUX_ ## f1,                       \
+                       TEGRA_MUX_ ## f2,                       \
+                       TEGRA_MUX_ ## f3,                       \
+               },                                              \
+               .mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A),       \
+               .mux_bank = 1,                                  \
+               .mux_bit = mux_b,                               \
+               .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A),      \
+               .pupd_bank = 2,                                 \
+               .pupd_bit = pupd_b,                             \
+               .tri_reg = ((tri_r) - TRISTATE_REG_A),          \
+               .tri_bank = 0,                                  \
+               .tri_bit = tri_b,                               \
+               .einput_bit = -1,                               \
+               .odrain_bit = -1,                               \
+               .lock_bit = -1,                                 \
+               .ioreset_bit = -1,                              \
+               .rcv_sel_bit = -1,                              \
+               .drv_reg = -1,                                  \
+       }
+
+/* Pin groups with only pull up and pull down control */
+#define PULL_PG(pg_name, pupd_r, pupd_b)                       \
+       {                                                       \
+               .name = #pg_name,                               \
+               .pins = pg_name##_pins,                         \
+               .npins = ARRAY_SIZE(pg_name##_pins),            \
+               .mux_reg = -1,                                  \
+               .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A),      \
+               .pupd_bank = 2,                                 \
+               .pupd_bit = pupd_b,                             \
+               .drv_reg = -1,                                  \
+       }
+
+/* Pin groups for drive strength registers (configurable version) */
+#define DRV_PG_EXT(pg_name, r, hsm_b, schmitt_b, lpmd_b,       \
+                  drvdn_b, drvup_b,                            \
+                  slwr_b, slwr_w, slwf_b, slwf_w)              \
+       {                                                       \
+               .name = "drive_" #pg_name,                      \
+               .pins = drive_##pg_name##_pins,                 \
+               .npins = ARRAY_SIZE(drive_##pg_name##_pins),    \
+               .mux_reg = -1,                                  \
+               .pupd_reg = -1,                                 \
+               .tri_reg = -1,                                  \
+               .drv_reg = ((r) - PINGROUP_REG_A),              \
+               .drv_bank = 3,                                  \
+               .hsm_bit = hsm_b,                               \
+               .schmitt_bit = schmitt_b,                       \
+               .lpmd_bit = lpmd_b,                             \
+               .drvdn_bit = drvdn_b,                           \
+               .drvdn_width = 5,                               \
+               .drvup_bit = drvup_b,                           \
+               .drvup_width = 5,                               \
+               .slwr_bit = slwr_b,                             \
+               .slwr_width = slwr_w,                           \
+               .slwf_bit = slwf_b,                             \
+               .slwf_width = slwf_w,                           \
+               .drvtype_bit = -1,                              \
+       }
+
+/* Pin groups for drive strength registers (simple version) */
+#define DRV_PG(pg_name, r) \
+       DRV_PG_EXT(pg_name, r, 2,  3,  4, 12, 20, 28, 2, 30, 2)
+
+static const struct tegra_pingroup tegra20_groups[] = {
+       /*     name,   f0,        f1,        f2,        f3,            tri r/b,  mux r/b,  pupd r/b */
+       MUX_PG(ata,    IDE,       NAND,      GMI,       RSVD4,         0x14, 0,  0x80, 24, 0xa0, 0),
+       MUX_PG(atb,    IDE,       NAND,      GMI,       SDIO4,         0x14, 1,  0x80, 16, 0xa0, 2),
+       MUX_PG(atc,    IDE,       NAND,      GMI,       SDIO4,         0x14, 2,  0x80, 22, 0xa0, 4),
+       MUX_PG(atd,    IDE,       NAND,      GMI,       SDIO4,         0x14, 3,  0x80, 20, 0xa0, 6),
+       MUX_PG(ate,    IDE,       NAND,      GMI,       RSVD4,         0x18, 25, 0x80, 12, 0xa0, 8),
+       MUX_PG(cdev1,  OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    0x14, 4,  0x88, 2,  0xa8, 0),
+       MUX_PG(cdev2,  OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     0x14, 5,  0x88, 4,  0xa8, 2),
+       MUX_PG(crtp,   CRT,       RSVD2,     RSVD3,     RSVD4,         0x20, 14, 0x98, 20, 0xa4, 24),
+       MUX_PG(csus,   PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, 0x14, 6,  0x88, 6,  0xac, 24),
+       MUX_PG(dap1,   DAP1,      RSVD2,     GMI,       SDIO2,         0x14, 7,  0x88, 20, 0xa0, 10),
+       MUX_PG(dap2,   DAP2,      TWC,       RSVD3,     GMI,           0x14, 8,  0x88, 22, 0xa0, 12),
+       MUX_PG(dap3,   DAP3,      RSVD2,     RSVD3,     RSVD4,         0x14, 9,  0x88, 24, 0xa0, 14),
+       MUX_PG(dap4,   DAP4,      RSVD2,     GMI,       RSVD4,         0x14, 10, 0x88, 26, 0xa0, 16),
+       MUX_PG(ddc,    I2C2,      RSVD2,     RSVD3,     RSVD4,         0x18, 31, 0x88, 0,  0xb0, 28),
+       MUX_PG(dta,    RSVD1,     SDIO2,     VI,        RSVD4,         0x14, 11, 0x84, 20, 0xa0, 18),
+       MUX_PG(dtb,    RSVD1,     RSVD2,     VI,        SPI1,          0x14, 12, 0x84, 22, 0xa0, 20),
+       MUX_PG(dtc,    RSVD1,     RSVD2,     VI,        RSVD4,         0x14, 13, 0x84, 26, 0xa0, 22),
+       MUX_PG(dtd,    RSVD1,     SDIO2,     VI,        RSVD4,         0x14, 14, 0x84, 28, 0xa0, 24),
+       MUX_PG(dte,    RSVD1,     RSVD2,     VI,        SPI1,          0x14, 15, 0x84, 30, 0xa0, 26),
+       MUX_PG(dtf,    I2C3,      RSVD2,     VI,        RSVD4,         0x20, 12, 0x98, 30, 0xa0, 28),
+       MUX_PG(gma,    UARTE,     SPI3,      GMI,       SDIO4,         0x14, 28, 0x84, 0,  0xb0, 20),
+       MUX_PG(gmb,    IDE,       NAND,      GMI,       GMI_INT,       0x18, 29, 0x88, 28, 0xb0, 22),
+       MUX_PG(gmc,    UARTD,     SPI4,      GMI,       SFLASH,        0x14, 29, 0x84, 2,  0xb0, 24),
+       MUX_PG(gmd,    RSVD1,     NAND,      GMI,       SFLASH,        0x18, 30, 0x88, 30, 0xb0, 26),
+       MUX_PG(gme,    RSVD1,     DAP5,      GMI,       SDIO4,         0x18, 0,  0x8c, 0,  0xa8, 24),
+       MUX_PG(gpu,    PWM,       UARTA,     GMI,       RSVD4,         0x14, 16, 0x8c, 4,  0xa4, 20),
+       MUX_PG(gpu7,   RTCK,      RSVD2,     RSVD3,     RSVD4,         0x20, 11, 0x98, 28, 0xa4, 6),
+       MUX_PG(gpv,    PCIE,      RSVD2,     RSVD3,     RSVD4,         0x14, 17, 0x8c, 2,  0xa0, 30),
+       MUX_PG(hdint,  HDMI,      RSVD2,     RSVD3,     RSVD4,         0x1c, 23, 0x84, 4,  -1,   -1),
+       MUX_PG(i2cp,   I2CP,      RSVD2,     RSVD3,     RSVD4,         0x14, 18, 0x88, 8,  0xa4, 2),
+       MUX_PG(irrx,   UARTA,     UARTB,     GMI,       SPI4,          0x14, 20, 0x88, 18, 0xa8, 22),
+       MUX_PG(irtx,   UARTA,     UARTB,     GMI,       SPI4,          0x14, 19, 0x88, 16, 0xa8, 20),
+       MUX_PG(kbca,   KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, 0x14, 22, 0x88, 10, 0xa4, 8),
+       MUX_PG(kbcb,   KBC,       NAND,      SDIO2,     MIO,           0x14, 21, 0x88, 12, 0xa4, 10),
+       MUX_PG(kbcc,   KBC,       NAND,      TRACE,     EMC_TEST1_DLL, 0x18, 26, 0x88, 14, 0xa4, 12),
+       MUX_PG(kbcd,   KBC,       NAND,      SDIO2,     MIO,           0x20, 10, 0x98, 26, 0xa4, 14),
+       MUX_PG(kbce,   KBC,       NAND,      OWR,       RSVD4,         0x14, 26, 0x80, 28, 0xb0, 2),
+       MUX_PG(kbcf,   KBC,       NAND,      TRACE,     MIO,           0x14, 27, 0x80, 26, 0xb0, 0),
+       MUX_PG(lcsn,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD4,         0x1c, 31, 0x90, 12, -1,   -1),
+       MUX_PG(ld0,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 0,  0x94, 0,  -1,   -1),
+       MUX_PG(ld1,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 1,  0x94, 2,  -1,   -1),
+       MUX_PG(ld2,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 2,  0x94, 4,  -1,   -1),
+       MUX_PG(ld3,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 3,  0x94, 6,  -1,   -1),
+       MUX_PG(ld4,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 4,  0x94, 8,  -1,   -1),
+       MUX_PG(ld5,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 5,  0x94, 10, -1,   -1),
+       MUX_PG(ld6,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 6,  0x94, 12, -1,   -1),
+       MUX_PG(ld7,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 7,  0x94, 14, -1,   -1),
+       MUX_PG(ld8,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 8,  0x94, 16, -1,   -1),
+       MUX_PG(ld9,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 9,  0x94, 18, -1,   -1),
+       MUX_PG(ld10,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 10, 0x94, 20, -1,   -1),
+       MUX_PG(ld11,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 11, 0x94, 22, -1,   -1),
+       MUX_PG(ld12,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 12, 0x94, 24, -1,   -1),
+       MUX_PG(ld13,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 13, 0x94, 26, -1,   -1),
+       MUX_PG(ld14,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 14, 0x94, 28, -1,   -1),
+       MUX_PG(ld15,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 15, 0x94, 30, -1,   -1),
+       MUX_PG(ld16,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 16, 0x98, 0,  -1,   -1),
+       MUX_PG(ld17,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 17, 0x98, 2,  -1,   -1),
+       MUX_PG(ldc,    DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 30, 0x90, 14, -1,   -1),
+       MUX_PG(ldi,    DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x20, 6,  0x98, 16, -1,   -1),
+       MUX_PG(lhp0,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 18, 0x98, 10, -1,   -1),
+       MUX_PG(lhp1,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 19, 0x98, 4,  -1,   -1),
+       MUX_PG(lhp2,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 20, 0x98, 6,  -1,   -1),
+       MUX_PG(lhs,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x20, 7,  0x90, 22, -1,   -1),
+       MUX_PG(lm0,    DISPLAYA,  DISPLAYB,  SPI3,      RSVD4,         0x1c, 24, 0x90, 26, -1,   -1),
+       MUX_PG(lm1,    DISPLAYA,  DISPLAYB,  RSVD3,     CRT,           0x1c, 25, 0x90, 28, -1,   -1),
+       MUX_PG(lpp,    DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x20, 8,  0x98, 14, -1,   -1),
+       MUX_PG(lpw0,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x20, 3,  0x90, 0,  -1,   -1),
+       MUX_PG(lpw1,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x20, 4,  0x90, 2,  -1,   -1),
+       MUX_PG(lpw2,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x20, 5,  0x90, 4,  -1,   -1),
+       MUX_PG(lsc0,   DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 27, 0x90, 18, -1,   -1),
+       MUX_PG(lsc1,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x1c, 28, 0x90, 20, -1,   -1),
+       MUX_PG(lsck,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x1c, 29, 0x90, 16, -1,   -1),
+       MUX_PG(lsda,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          0x20, 1,  0x90, 8,  -1,   -1),
+       MUX_PG(lsdi,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD4,         0x20, 2,  0x90, 6,  -1,   -1),
+       MUX_PG(lspi,   DISPLAYA,  DISPLAYB,  XIO,       HDMI,          0x20, 0,  0x90, 10, -1,   -1),
+       MUX_PG(lvp0,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 21, 0x90, 30, -1,   -1),
+       MUX_PG(lvp1,   DISPLAYA,  DISPLAYB,  RSVD3,     RSVD4,         0x1c, 22, 0x98, 8,  -1,   -1),
+       MUX_PG(lvs,    DISPLAYA,  DISPLAYB,  XIO,       RSVD4,         0x1c, 26, 0x90, 24, -1,   -1),
+       MUX_PG(owc,    OWR,       RSVD2,     RSVD3,     RSVD4,         0x14, 31, 0x84, 8,  0xb0, 30),
+       MUX_PG(pmc,    PWR_ON,    PWR_INTR,  RSVD3,     RSVD4,         0x14, 23, 0x98, 18, -1,   -1),
+       MUX_PG(pta,    I2C2,      HDMI,      GMI,       RSVD4,         0x14, 24, 0x98, 22, 0xa4, 4),
+       MUX_PG(rm,     I2C1,      RSVD2,     RSVD3,     RSVD4,         0x14, 25, 0x80, 14, 0xa4, 0),
+       MUX_PG(sdb,    UARTA,     PWM,       SDIO3,     SPI2,          0x20, 15, 0x8c, 10, -1,   -1),
+       MUX_PG(sdc,    PWM,       TWC,       SDIO3,     SPI3,          0x18, 1,  0x8c, 12, 0xac, 28),
+       MUX_PG(sdd,    UARTA,     PWM,       SDIO3,     SPI3,          0x18, 2,  0x8c, 14, 0xac, 30),
+       MUX_PG(sdio1,  SDIO1,     RSVD2,     UARTE,     UARTA,         0x14, 30, 0x80, 30, 0xb0, 18),
+       MUX_PG(slxa,   PCIE,      SPI4,      SDIO3,     SPI2,          0x18, 3,  0x84, 6,  0xa4, 22),
+       MUX_PG(slxc,   SPDIF,     SPI4,      SDIO3,     SPI2,          0x18, 5,  0x84, 10, 0xa4, 26),
+       MUX_PG(slxd,   SPDIF,     SPI4,      SDIO3,     SPI2,          0x18, 6,  0x84, 12, 0xa4, 28),
+       MUX_PG(slxk,   PCIE,      SPI4,      SDIO3,     SPI2,          0x18, 7,  0x84, 14, 0xa4, 30),
+       MUX_PG(spdi,   SPDIF,     RSVD2,     I2C1,      SDIO2,         0x18, 8,  0x8c, 8,  0xa4, 16),
+       MUX_PG(spdo,   SPDIF,     RSVD2,     I2C1,      SDIO2,         0x18, 9,  0x8c, 6,  0xa4, 18),
+       MUX_PG(spia,   SPI1,      SPI2,      SPI3,      GMI,           0x18, 10, 0x8c, 30, 0xa8, 4),
+       MUX_PG(spib,   SPI1,      SPI2,      SPI3,      GMI,           0x18, 11, 0x8c, 28, 0xa8, 6),
+       MUX_PG(spic,   SPI1,      SPI2,      SPI3,      GMI,           0x18, 12, 0x8c, 26, 0xa8, 8),
+       MUX_PG(spid,   SPI2,      SPI1,      SPI2_ALT,  GMI,           0x18, 13, 0x8c, 24, 0xa8, 10),
+       MUX_PG(spie,   SPI2,      SPI1,      SPI2_ALT,  GMI,           0x18, 14, 0x8c, 22, 0xa8, 12),
+       MUX_PG(spif,   SPI3,      SPI1,      SPI2,      RSVD4,         0x18, 15, 0x8c, 20, 0xa8, 14),
+       MUX_PG(spig,   SPI3,      SPI2,      SPI2_ALT,  I2C1,          0x18, 16, 0x8c, 18, 0xa8, 16),
+       MUX_PG(spih,   SPI3,      SPI2,      SPI2_ALT,  I2C1,          0x18, 17, 0x8c, 16, 0xa8, 18),
+       MUX_PG(uaa,    SPI3,      MIPI_HS,   UARTA,     ULPI,          0x18, 18, 0x80, 0,  0xac, 0),
+       MUX_PG(uab,    SPI2,      MIPI_HS,   UARTA,     ULPI,          0x18, 19, 0x80, 2,  0xac, 2),
+       MUX_PG(uac,    OWR,       RSVD2,     RSVD3,     RSVD4,         0x18, 20, 0x80, 4,  0xac, 4),
+       MUX_PG(uad,    IRDA,      SPDIF,     UARTA,     SPI4,          0x18, 21, 0x80, 6,  0xac, 6),
+       MUX_PG(uca,    UARTC,     RSVD2,     GMI,       RSVD4,         0x18, 22, 0x84, 16, 0xac, 8),
+       MUX_PG(ucb,    UARTC,     PWM,       GMI,       RSVD4,         0x18, 23, 0x84, 18, 0xac, 10),
+       MUX_PG(uda,    SPI1,      RSVD2,     UARTD,     ULPI,          0x20, 13, 0x80, 8,  0xb0, 16),
+       /*      pg_name, pupd_r/b */
+       PULL_PG(ck32,    0xb0, 14),
+       PULL_PG(ddrc,    0xac, 26),
+       PULL_PG(pmca,    0xb0, 4),
+       PULL_PG(pmcb,    0xb0, 6),
+       PULL_PG(pmcc,    0xb0, 8),
+       PULL_PG(pmcd,    0xb0, 10),
+       PULL_PG(pmce,    0xb0, 12),
+       PULL_PG(xm2c,    0xa8, 30),
+       PULL_PG(xm2d,    0xa8, 28),
+       PULL_PG(ls,      0xac, 20),
+       PULL_PG(lc,      0xac, 22),
+       PULL_PG(ld17_0,  0xac, 12),
+       PULL_PG(ld19_18, 0xac, 14),
+       PULL_PG(ld21_20, 0xac, 16),
+       PULL_PG(ld23_22, 0xac, 18),
+       /*     pg_name,    r */
+       DRV_PG(ao1,        0x868),
+       DRV_PG(ao2,        0x86c),
+       DRV_PG(at1,        0x870),
+       DRV_PG(at2,        0x874),
+       DRV_PG(cdev1,      0x878),
+       DRV_PG(cdev2,      0x87c),
+       DRV_PG(csus,       0x880),
+       DRV_PG(dap1,       0x884),
+       DRV_PG(dap2,       0x888),
+       DRV_PG(dap3,       0x88c),
+       DRV_PG(dap4,       0x890),
+       DRV_PG(dbg,        0x894),
+       DRV_PG(lcd1,       0x898),
+       DRV_PG(lcd2,       0x89c),
+       DRV_PG(sdmmc2,     0x8a0),
+       DRV_PG(sdmmc3,     0x8a4),
+       DRV_PG(spi,        0x8a8),
+       DRV_PG(uaa,        0x8ac),
+       DRV_PG(uab,        0x8b0),
+       DRV_PG(uart2,      0x8b4),
+       DRV_PG(uart3,      0x8b8),
+       DRV_PG(vi1,        0x8bc),
+       DRV_PG(vi2,        0x8c0),
+       /*         pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvup_b, slwr_b, slwr_w, slwf_b, slwf_w */
+       DRV_PG_EXT(xm2a,   0x8c4, -1, -1,  4, 14, 19, 24, 4, 28, 4),
+       DRV_PG_EXT(xm2c,   0x8c8, -1,  3, -1, 14, 19, 24, 4, 28, 4),
+       DRV_PG_EXT(xm2d,   0x8cc, -1,  3, -1, 14, 19, 24, 4, 28, 4),
+       DRV_PG_EXT(xm2clk, 0x8d0, -1, -1, -1, 14, 19, 24, 4, 28, 4),
+       /*     pg_name,    r */
+       DRV_PG(sdio1,      0x8e0),
+       DRV_PG(crt,        0x8ec),
+       DRV_PG(ddc,        0x8f0),
+       DRV_PG(gma,        0x8f4),
+       DRV_PG(gmb,        0x8f8),
+       DRV_PG(gmc,        0x8fc),
+       DRV_PG(gmd,        0x900),
+       DRV_PG(gme,        0x904),
+       DRV_PG(owr,        0x908),
+       DRV_PG(uda,        0x90c),
+};
+
+static const struct tegra_pinctrl_soc_data tegra20_pinctrl = {
+       .ngpios = NUM_GPIOS,
+       .pins = tegra20_pins,
+       .npins = ARRAY_SIZE(tegra20_pins),
+       .functions = tegra20_functions,
+       .nfunctions = ARRAY_SIZE(tegra20_functions),
+       .groups = tegra20_groups,
+       .ngroups = ARRAY_SIZE(tegra20_groups),
+       .hsm_in_mux = false,
+       .schmitt_in_mux = false,
+       .drvtype_in_mux = false,
+};
+
+static int tegra20_pinctrl_probe(struct platform_device *pdev)
+{
+       return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
+}
+
+static const struct of_device_id tegra20_pinctrl_of_match[] = {
+       { .compatible = "nvidia,tegra20-pinmux", },
+       { },
+};
+
+static struct platform_driver tegra20_pinctrl_driver = {
+       .driver = {
+               .name = "tegra20-pinctrl",
+               .of_match_table = tegra20_pinctrl_of_match,
+       },
+       .probe = tegra20_pinctrl_probe,
+       .remove = tegra_pinctrl_remove,
+};
+module_platform_driver(tegra20_pinctrl_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match);
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c
new file mode 100644 (file)
index 0000000..252b464
--- /dev/null
@@ -0,0 +1,1588 @@
+/*
+ * Pinctrl data for the NVIDIA Tegra210 pinmux
+ *
+ * Copyright (c) 2015, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/*
+ * Most pins affected by the pinmux can also be GPIOs. Define these first.
+ * These must match how the GPIO driver names/numbers its pins.
+ */
+#define _GPIO(offset)                          (offset)
+
+#define TEGRA_PIN_PEX_L0_RST_N_PA0             _GPIO(0)
+#define TEGRA_PIN_PEX_L0_CLKREQ_N_PA1          _GPIO(1)
+#define TEGRA_PIN_PEX_WAKE_N_PA2               _GPIO(2)
+#define TEGRA_PIN_PEX_L1_RST_N_PA3             _GPIO(3)
+#define TEGRA_PIN_PEX_L1_CLKREQ_N_PA4          _GPIO(4)
+#define TEGRA_PIN_SATA_LED_ACTIVE_PA5          _GPIO(5)
+#define TEGRA_PIN_PA6                          _GPIO(6)
+#define TEGRA_PIN_DAP1_FS_PB0                  _GPIO(8)
+#define TEGRA_PIN_DAP1_DIN_PB1                 _GPIO(9)
+#define TEGRA_PIN_DAP1_DOUT_PB2                        _GPIO(10)
+#define TEGRA_PIN_DAP1_SCLK_PB3                        _GPIO(11)
+#define TEGRA_PIN_SPI2_MOSI_PB4                        _GPIO(12)
+#define TEGRA_PIN_SPI2_MISO_PB5                        _GPIO(13)
+#define TEGRA_PIN_SPI2_SCK_PB6                 _GPIO(14)
+#define TEGRA_PIN_SPI2_CS0_PB7                 _GPIO(15)
+#define TEGRA_PIN_SPI1_MOSI_PC0                        _GPIO(16)
+#define TEGRA_PIN_SPI1_MISO_PC1                        _GPIO(17)
+#define TEGRA_PIN_SPI1_SCK_PC2                 _GPIO(18)
+#define TEGRA_PIN_SPI1_CS0_PC3                 _GPIO(19)
+#define TEGRA_PIN_SPI1_CS1_PC4                 _GPIO(20)
+#define TEGRA_PIN_SPI4_SCK_PC5                 _GPIO(21)
+#define TEGRA_PIN_SPI4_CS0_PC6                 _GPIO(22)
+#define TEGRA_PIN_SPI4_MOSI_PC7                        _GPIO(23)
+#define TEGRA_PIN_SPI4_MISO_PD0                        _GPIO(24)
+#define TEGRA_PIN_UART3_TX_PD1                 _GPIO(25)
+#define TEGRA_PIN_UART3_RX_PD2                 _GPIO(26)
+#define TEGRA_PIN_UART3_RTS_PD3                        _GPIO(27)
+#define TEGRA_PIN_UART3_CTS_PD4                        _GPIO(28)
+#define TEGRA_PIN_DMIC1_CLK_PE0                        _GPIO(32)
+#define TEGRA_PIN_DMIC1_DAT_PE1                        _GPIO(33)
+#define TEGRA_PIN_DMIC2_CLK_PE2                        _GPIO(34)
+#define TEGRA_PIN_DMIC2_DAT_PE3                        _GPIO(35)
+#define TEGRA_PIN_DMIC3_CLK_PE4                        _GPIO(36)
+#define TEGRA_PIN_DMIC3_DAT_PE5                        _GPIO(37)
+#define TEGRA_PIN_PE6                          _GPIO(38)
+#define TEGRA_PIN_PE7                          _GPIO(39)
+#define TEGRA_PIN_GEN3_I2C_SCL_PF0             _GPIO(40)
+#define TEGRA_PIN_GEN3_I2C_SDA_PF1             _GPIO(41)
+#define TEGRA_PIN_UART2_TX_PG0                 _GPIO(48)
+#define TEGRA_PIN_UART2_RX_PG1                 _GPIO(49)
+#define TEGRA_PIN_UART2_RTS_PG2                        _GPIO(50)
+#define TEGRA_PIN_UART2_CTS_PG3                        _GPIO(51)
+#define TEGRA_PIN_WIFI_EN_PH0                  _GPIO(56)
+#define TEGRA_PIN_WIFI_RST_PH1                 _GPIO(57)
+#define TEGRA_PIN_WIFI_WAKE_AP_PH2             _GPIO(58)
+#define TEGRA_PIN_AP_WAKE_BT_PH3               _GPIO(59)
+#define TEGRA_PIN_BT_RST_PH4                   _GPIO(60)
+#define TEGRA_PIN_BT_WAKE_AP_PH5               _GPIO(61)
+#define TEGRA_PIN_PH6                          _GPIO(62)
+#define TEGRA_PIN_AP_WAKE_NFC_PH7              _GPIO(63)
+#define TEGRA_PIN_NFC_EN_PI0                   _GPIO(64)
+#define TEGRA_PIN_NFC_INT_PI1                  _GPIO(65)
+#define TEGRA_PIN_GPS_EN_PI2                   _GPIO(66)
+#define TEGRA_PIN_GPS_RST_PI3                  _GPIO(67)
+#define TEGRA_PIN_UART4_TX_PI4                 _GPIO(68)
+#define TEGRA_PIN_UART4_RX_PI5                 _GPIO(69)
+#define TEGRA_PIN_UART4_RTS_PI6                        _GPIO(70)
+#define TEGRA_PIN_UART4_CTS_PI7                        _GPIO(71)
+#define TEGRA_PIN_GEN1_I2C_SDA_PJ0             _GPIO(72)
+#define TEGRA_PIN_GEN1_I2C_SCL_PJ1             _GPIO(73)
+#define TEGRA_PIN_GEN2_I2C_SCL_PJ2             _GPIO(74)
+#define TEGRA_PIN_GEN2_I2C_SDA_PJ3             _GPIO(75)
+#define TEGRA_PIN_DAP4_FS_PJ4                  _GPIO(76)
+#define TEGRA_PIN_DAP4_DIN_PJ5                 _GPIO(77)
+#define TEGRA_PIN_DAP4_DOUT_PJ6                        _GPIO(78)
+#define TEGRA_PIN_DAP4_SCLK_PJ7                        _GPIO(79)
+#define TEGRA_PIN_PK0                          _GPIO(80)
+#define TEGRA_PIN_PK1                          _GPIO(81)
+#define TEGRA_PIN_PK2                          _GPIO(82)
+#define TEGRA_PIN_PK3                          _GPIO(83)
+#define TEGRA_PIN_PK4                          _GPIO(84)
+#define TEGRA_PIN_PK5                          _GPIO(85)
+#define TEGRA_PIN_PK6                          _GPIO(86)
+#define TEGRA_PIN_PK7                          _GPIO(87)
+#define TEGRA_PIN_PL0                          _GPIO(88)
+#define TEGRA_PIN_PL1                          _GPIO(89)
+#define TEGRA_PIN_SDMMC1_CLK_PM0               _GPIO(96)
+#define TEGRA_PIN_SDMMC1_CMD_PM1               _GPIO(97)
+#define TEGRA_PIN_SDMMC1_DAT3_PM2              _GPIO(98)
+#define TEGRA_PIN_SDMMC1_DAT2_PM3              _GPIO(99)
+#define TEGRA_PIN_SDMMC1_DAT1_PM4              _GPIO(100)
+#define TEGRA_PIN_SDMMC1_DAT0_PM5              _GPIO(101)
+#define TEGRA_PIN_SDMMC3_CLK_PP0               _GPIO(120)
+#define TEGRA_PIN_SDMMC3_CMD_PP1               _GPIO(121)
+#define TEGRA_PIN_SDMMC3_DAT3_PP2              _GPIO(122)
+#define TEGRA_PIN_SDMMC3_DAT2_PP3              _GPIO(123)
+#define TEGRA_PIN_SDMMC3_DAT1_PP4              _GPIO(124)
+#define TEGRA_PIN_SDMMC3_DAT0_PP5              _GPIO(125)
+#define TEGRA_PIN_CAM1_MCLK_PS0                        _GPIO(144)
+#define TEGRA_PIN_CAM2_MCLK_PS1                        _GPIO(145)
+#define TEGRA_PIN_CAM_I2C_SCL_PS2              _GPIO(146)
+#define TEGRA_PIN_CAM_I2C_SDA_PS3              _GPIO(147)
+#define TEGRA_PIN_CAM_RST_PS4                  _GPIO(148)
+#define TEGRA_PIN_CAM_AF_EN_PS5                        _GPIO(149)
+#define TEGRA_PIN_CAM_FLASH_EN_PS6             _GPIO(150)
+#define TEGRA_PIN_CAM1_PWDN_PS7                        _GPIO(151)
+#define TEGRA_PIN_CAM2_PWDN_PT0                        _GPIO(152)
+#define TEGRA_PIN_CAM1_STROBE_PT1              _GPIO(153)
+#define TEGRA_PIN_UART1_TX_PU0                 _GPIO(160)
+#define TEGRA_PIN_UART1_RX_PU1                 _GPIO(161)
+#define TEGRA_PIN_UART1_RTS_PU2                        _GPIO(162)
+#define TEGRA_PIN_UART1_CTS_PU3                        _GPIO(163)
+#define TEGRA_PIN_LCD_BL_PWM_PV0               _GPIO(168)
+#define TEGRA_PIN_LCD_BL_EN_PV1                        _GPIO(169)
+#define TEGRA_PIN_LCD_RST_PV2                  _GPIO(170)
+#define TEGRA_PIN_LCD_GPIO1_PV3                        _GPIO(171)
+#define TEGRA_PIN_LCD_GPIO2_PV4                        _GPIO(172)
+#define TEGRA_PIN_AP_READY_PV5                 _GPIO(173)
+#define TEGRA_PIN_TOUCH_RST_PV6                        _GPIO(174)
+#define TEGRA_PIN_TOUCH_CLK_PV7                        _GPIO(175)
+#define TEGRA_PIN_MODEM_WAKE_AP_PX0            _GPIO(184)
+#define TEGRA_PIN_TOUCH_INT_PX1                        _GPIO(185)
+#define TEGRA_PIN_MOTION_INT_PX2               _GPIO(186)
+#define TEGRA_PIN_ALS_PROX_INT_PX3             _GPIO(187)
+#define TEGRA_PIN_TEMP_ALERT_PX4               _GPIO(188)
+#define TEGRA_PIN_BUTTON_POWER_ON_PX5          _GPIO(189)
+#define TEGRA_PIN_BUTTON_VOL_UP_PX6            _GPIO(190)
+#define TEGRA_PIN_BUTTON_VOL_DOWN_PX7          _GPIO(191)
+#define TEGRA_PIN_BUTTON_SLIDE_SW_PY0          _GPIO(192)
+#define TEGRA_PIN_BUTTON_HOME_PY1              _GPIO(193)
+#define TEGRA_PIN_LCD_TE_PY2                   _GPIO(194)
+#define TEGRA_PIN_PWR_I2C_SCL_PY3              _GPIO(195)
+#define TEGRA_PIN_PWR_I2C_SDA_PY4              _GPIO(196)
+#define TEGRA_PIN_CLK_32K_OUT_PY5              _GPIO(197)
+#define TEGRA_PIN_PZ0                          _GPIO(200)
+#define TEGRA_PIN_PZ1                          _GPIO(201)
+#define TEGRA_PIN_PZ2                          _GPIO(202)
+#define TEGRA_PIN_PZ3                          _GPIO(203)
+#define TEGRA_PIN_PZ4                          _GPIO(204)
+#define TEGRA_PIN_PZ5                          _GPIO(205)
+#define TEGRA_PIN_DAP2_FS_PAA0                 _GPIO(208)
+#define TEGRA_PIN_DAP2_SCLK_PAA1               _GPIO(209)
+#define TEGRA_PIN_DAP2_DIN_PAA2                        _GPIO(210)
+#define TEGRA_PIN_DAP2_DOUT_PAA3               _GPIO(211)
+#define TEGRA_PIN_AUD_MCLK_PBB0                        _GPIO(216)
+#define TEGRA_PIN_DVFS_PWM_PBB1                        _GPIO(217)
+#define TEGRA_PIN_DVFS_CLK_PBB2                        _GPIO(218)
+#define TEGRA_PIN_GPIO_X1_AUD_PBB3             _GPIO(219)
+#define TEGRA_PIN_GPIO_X3_AUD_PBB4             _GPIO(220)
+#define TEGRA_PIN_HDMI_CEC_PCC0                        _GPIO(224)
+#define TEGRA_PIN_HDMI_INT_DP_HPD_PCC1         _GPIO(225)
+#define TEGRA_PIN_SPDIF_OUT_PCC2               _GPIO(226)
+#define TEGRA_PIN_SPDIF_IN_PCC3                        _GPIO(227)
+#define TEGRA_PIN_USB_VBUS_EN0_PCC4            _GPIO(228)
+#define TEGRA_PIN_USB_VBUS_EN1_PCC5            _GPIO(229)
+#define TEGRA_PIN_DP_HPD0_PCC6                 _GPIO(230)
+#define TEGRA_PIN_PCC7                         _GPIO(231)
+#define TEGRA_PIN_SPI2_CS1_PDD0                        _GPIO(232)
+#define TEGRA_PIN_QSPI_SCK_PEE0                        _GPIO(240)
+#define TEGRA_PIN_QSPI_CS_N_PEE1               _GPIO(241)
+#define TEGRA_PIN_QSPI_IO0_PEE2                        _GPIO(242)
+#define TEGRA_PIN_QSPI_IO1_PEE3                        _GPIO(243)
+#define TEGRA_PIN_QSPI_IO2_PEE4                        _GPIO(244)
+#define TEGRA_PIN_QSPI_IO3_PEE5                        _GPIO(245)
+
+/* All non-GPIO pins follow */
+#define NUM_GPIOS                              (TEGRA_PIN_QSPI_IO3_PEE5 + 1)
+#define _PIN(offset)                           (NUM_GPIOS + (offset))
+
+/* Non-GPIO pins */
+#define TEGRA_PIN_CORE_PWR_REQ                 _PIN(0)
+#define TEGRA_PIN_CPU_PWR_REQ                  _PIN(1)
+#define TEGRA_PIN_PWR_INT_N                    _PIN(2)
+#define TEGRA_PIN_CLK_32K_IN                   _PIN(3)
+#define TEGRA_PIN_JTAG_RTCK                    _PIN(4)
+#define TEGRA_PIN_BATT_BCL                     _PIN(5)
+#define TEGRA_PIN_CLK_REQ                      _PIN(6)
+#define TEGRA_PIN_SHUTDOWN                     _PIN(7)
+
+static const struct pinctrl_pin_desc tegra210_pins[] = {
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PA0, "PEX_L0_RST_N PA0"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, "PEX_L0_CLKREQ_N PA1"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PA2, "PEX_WAKE_N PA2"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PA3, "PEX_L1_RST_N PA3"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, "PEX_L1_CLKREQ_N PA4"),
+       PINCTRL_PIN(TEGRA_PIN_SATA_LED_ACTIVE_PA5, "SATA_LED_ACTIVE PA5"),
+       PINCTRL_PIN(TEGRA_PIN_PA6, "PA6"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PB0, "DAP1_FS PB0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PB1, "DAP1_DIN PB1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PB2, "DAP1_DOUT PB2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PB3, "DAP1_SCLK PB3"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PB4, "SPI2_MOSI PB4"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PB5, "SPI2_MISO PB5"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PB6, "SPI2_SCK PB6"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PB7, "SPI2_CS0 PB7"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PC0, "SPI1_MOSI PC0"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PC1, "SPI1_MISO PC1"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PC2, "SPI1_SCK PC2"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PC3, "SPI1_CS0 PC3"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PC4, "SPI1_CS1 PC4"),
+       PINCTRL_PIN(TEGRA_PIN_SPI4_SCK_PC5, "SPI4_SCK PC5"),
+       PINCTRL_PIN(TEGRA_PIN_SPI4_CS0_PC6, "SPI4_CS0 PC6"),
+       PINCTRL_PIN(TEGRA_PIN_SPI4_MOSI_PC7, "SPI4_MOSI PC7"),
+       PINCTRL_PIN(TEGRA_PIN_SPI4_MISO_PD0, "SPI4_MISO PD0"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_TX_PD1, "UART3_TX PD1"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RX_PD2, "UART3_RX PD2"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_PD3, "UART3_RTS PD3"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_PD4, "UART3_CTS PD4"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC1_CLK_PE0, "DMIC1_CLK PE0"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC1_DAT_PE1, "DMIC1_DAT PE1"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC2_CLK_PE2, "DMIC2_CLK PE2"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC2_DAT_PE3, "DMIC2_DAT PE3"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC3_CLK_PE4, "DMIC3_CLK PE4"),
+       PINCTRL_PIN(TEGRA_PIN_DMIC3_DAT_PE5, "DMIC3_DAT PE5"),
+       PINCTRL_PIN(TEGRA_PIN_PE6, "PE6"),
+       PINCTRL_PIN(TEGRA_PIN_PE7, "PE7"),
+       PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SCL_PF0, "GEN3_I2C_SCL PF0"),
+       PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SDA_PF1, "GEN3_I2C_SDA PF1"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_TX_PG0, "UART2_TX PG0"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RX_PG1, "UART2_RX PG1"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PG2, "UART2_RTS PG2"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PG3, "UART2_CTS PG3"),
+       PINCTRL_PIN(TEGRA_PIN_WIFI_EN_PH0, "WIFI_EN PH0"),
+       PINCTRL_PIN(TEGRA_PIN_WIFI_RST_PH1, "WIFI_RST PH1"),
+       PINCTRL_PIN(TEGRA_PIN_WIFI_WAKE_AP_PH2, "WIFI_WAKE_AP PH2"),
+       PINCTRL_PIN(TEGRA_PIN_AP_WAKE_BT_PH3, "AP_WAKE_BT PH3"),
+       PINCTRL_PIN(TEGRA_PIN_BT_RST_PH4, "BT_RST PH4"),
+       PINCTRL_PIN(TEGRA_PIN_BT_WAKE_AP_PH5, "BT_WAKE_AP PH5"),
+       PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"),
+       PINCTRL_PIN(TEGRA_PIN_AP_WAKE_NFC_PH7, "AP_WAKE_NFC PH7"),
+       PINCTRL_PIN(TEGRA_PIN_NFC_EN_PI0, "NFC_EN PI0"),
+       PINCTRL_PIN(TEGRA_PIN_NFC_INT_PI1, "NFC_INT PI1"),
+       PINCTRL_PIN(TEGRA_PIN_GPS_EN_PI2, "GPS_EN PI2"),
+       PINCTRL_PIN(TEGRA_PIN_GPS_RST_PI3, "GPS_RST PI3"),
+       PINCTRL_PIN(TEGRA_PIN_UART4_TX_PI4, "UART4_TX PI4"),
+       PINCTRL_PIN(TEGRA_PIN_UART4_RX_PI5, "UART4_RX PI5"),
+       PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PI6, "UART4_RTS PI6"),
+       PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PI7, "UART4_CTS PI7"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PJ0, "GEN1_I2C_SDA PJ0"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PJ1, "GEN1_I2C_SCL PJ1"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PJ2, "GEN2_I2C_SCL PJ2"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PJ3, "GEN2_I2C_SDA PJ3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PJ4, "DAP4_FS PJ4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PJ5, "DAP4_DIN PJ5"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PJ6, "DAP4_DOUT PJ6"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PJ7, "DAP4_SCLK PJ7"),
+       PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"),
+       PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"),
+       PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"),
+       PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"),
+       PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"),
+       PINCTRL_PIN(TEGRA_PIN_PK5, "PK5"),
+       PINCTRL_PIN(TEGRA_PIN_PK6, "PK6"),
+       PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"),
+       PINCTRL_PIN(TEGRA_PIN_PL0, "PL0"),
+       PINCTRL_PIN(TEGRA_PIN_PL1, "PL1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PM0, "SDMMC1_CLK PM0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PM1, "SDMMC1_CMD PM1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PM2, "SDMMC1_DAT3 PM2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PM3, "SDMMC1_DAT2 PM3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PM4, "SDMMC1_DAT1 PM4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PM5, "SDMMC1_DAT0 PM5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PP0, "SDMMC3_CLK PP0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PP1, "SDMMC3_CMD PP1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PP2, "SDMMC3_DAT3 PP2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PP3, "SDMMC3_DAT2 PP3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PP4, "SDMMC3_DAT1 PP4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PP5, "SDMMC3_DAT0 PP5"),
+       PINCTRL_PIN(TEGRA_PIN_CAM1_MCLK_PS0, "CAM1_MCLK PS0"),
+       PINCTRL_PIN(TEGRA_PIN_CAM2_MCLK_PS1, "CAM2_MCLK PS1"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PS2, "CAM_I2C_SCL PS2"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PS3, "CAM_I2C_SDA PS3"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_RST_PS4, "CAM_RST PS4"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_AF_EN_PS5, "CAM_AF_EN PS5"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_FLASH_EN_PS6, "CAM_FLASH_EN PS6"),
+       PINCTRL_PIN(TEGRA_PIN_CAM1_PWDN_PS7, "CAM1_PWDN PS7"),
+       PINCTRL_PIN(TEGRA_PIN_CAM2_PWDN_PT0, "CAM2_PWDN PT0"),
+       PINCTRL_PIN(TEGRA_PIN_CAM1_STROBE_PT1, "CAM1_STROBE PT1"),
+       PINCTRL_PIN(TEGRA_PIN_UART1_TX_PU0, "UART1_TX PU0"),
+       PINCTRL_PIN(TEGRA_PIN_UART1_RX_PU1, "UART1_RX PU1"),
+       PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PU2, "UART1_RTS PU2"),
+       PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PU3, "UART1_CTS PU3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_BL_PWM_PV0, "LCD_BL_PWM PV0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_BL_EN_PV1, "LCD_BL_EN PV1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_RST_PV2, "LCD_RST PV2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_GPIO1_PV3, "LCD_GPIO1 PV3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_GPIO2_PV4, "LCD_GPIO2 PV4"),
+       PINCTRL_PIN(TEGRA_PIN_AP_READY_PV5, "AP_READY PV5"),
+       PINCTRL_PIN(TEGRA_PIN_TOUCH_RST_PV6, "TOUCH_RST PV6"),
+       PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PV7, "TOUCH_CLK PV7"),
+       PINCTRL_PIN(TEGRA_PIN_MODEM_WAKE_AP_PX0, "MODEM_WAKE_AP PX0"),
+       PINCTRL_PIN(TEGRA_PIN_TOUCH_INT_PX1, "TOUCH_INT PX1"),
+       PINCTRL_PIN(TEGRA_PIN_MOTION_INT_PX2, "MOTION_INT PX2"),
+       PINCTRL_PIN(TEGRA_PIN_ALS_PROX_INT_PX3, "ALS_PROX_INT PX3"),
+       PINCTRL_PIN(TEGRA_PIN_TEMP_ALERT_PX4, "TEMP_ALERT PX4"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_POWER_ON_PX5, "BUTTON_POWER_ON PX5"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_UP_PX6, "BUTTON_VOL_UP PX6"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_DOWN_PX7, "BUTTON_VOL_DOWN PX7"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_SLIDE_SW_PY0, "BUTTON_SLIDE_SW PY0"),
+       PINCTRL_PIN(TEGRA_PIN_BUTTON_HOME_PY1, "BUTTON_HOME PY1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_TE_PY2, "LCD_TE PY2"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PY3, "PWR_I2C_SCL PY3"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PY4, "PWR_I2C_SDA PY4"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PY5, "CLK_32K_OUT PY5"),
+       PINCTRL_PIN(TEGRA_PIN_PZ0, "PZ0"),
+       PINCTRL_PIN(TEGRA_PIN_PZ1, "PZ1"),
+       PINCTRL_PIN(TEGRA_PIN_PZ2, "PZ2"),
+       PINCTRL_PIN(TEGRA_PIN_PZ3, "PZ3"),
+       PINCTRL_PIN(TEGRA_PIN_PZ4, "PZ4"),
+       PINCTRL_PIN(TEGRA_PIN_PZ5, "PZ5"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PAA0, "DAP2_FS PAA0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PAA1, "DAP2_SCLK PAA1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PAA2, "DAP2_DIN PAA2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PAA3, "DAP2_DOUT PAA3"),
+       PINCTRL_PIN(TEGRA_PIN_AUD_MCLK_PBB0, "AUD_MCLK PBB0"),
+       PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PBB1, "DVFS_PWM PBB1"),
+       PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PBB2, "DVFS_CLK PBB2"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PBB3, "GPIO_X1_AUD PBB3"),
+       PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PBB4, "GPIO_X3_AUD PBB4"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PCC0, "HDMI_CEC PCC0"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, "HDMI_INT_DP_HPD PCC1"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PCC2, "SPDIF_OUT PCC2"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PCC3, "SPDIF_IN PCC3"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PCC4, "USB_VBUS_EN0 PCC4"),
+       PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PCC5, "USB_VBUS_EN1 PCC5"),
+       PINCTRL_PIN(TEGRA_PIN_DP_HPD0_PCC6, "DP_HPD0 PCC6"),
+       PINCTRL_PIN(TEGRA_PIN_PCC7, "PCC7"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_PDD0, "SPI2_CS1 PDD0"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_SCK_PEE0, "QSPI_SCK PEE0"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_CS_N_PEE1, "QSPI_CS_N PEE1"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_IO0_PEE2, "QSPI_IO0 PEE2"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_IO1_PEE3, "QSPI_IO1 PEE3"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_IO2_PEE4, "QSPI_IO2 PEE4"),
+       PINCTRL_PIN(TEGRA_PIN_QSPI_IO3_PEE5, "QSPI_IO3 PEE5"),
+       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"),
+       PINCTRL_PIN(TEGRA_PIN_BATT_BCL, "BATT_BCL"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_REQ, "CLK_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_SHUTDOWN, "SHUTDOWN"),
+};
+
+static const unsigned pex_l0_rst_n_pa0_pins[] = {
+       TEGRA_PIN_PEX_L0_RST_N_PA0,
+};
+
+static const unsigned pex_l0_clkreq_n_pa1_pins[] = {
+       TEGRA_PIN_PEX_L0_CLKREQ_N_PA1,
+};
+
+static const unsigned pex_wake_n_pa2_pins[] = {
+       TEGRA_PIN_PEX_WAKE_N_PA2,
+};
+
+static const unsigned pex_l1_rst_n_pa3_pins[] = {
+       TEGRA_PIN_PEX_L1_RST_N_PA3,
+};
+
+static const unsigned pex_l1_clkreq_n_pa4_pins[] = {
+       TEGRA_PIN_PEX_L1_CLKREQ_N_PA4,
+};
+
+static const unsigned sata_led_active_pa5_pins[] = {
+       TEGRA_PIN_SATA_LED_ACTIVE_PA5,
+};
+
+static const unsigned pa6_pins[] = {
+       TEGRA_PIN_PA6,
+};
+
+static const unsigned dap1_fs_pb0_pins[] = {
+       TEGRA_PIN_DAP1_FS_PB0,
+};
+
+static const unsigned dap1_din_pb1_pins[] = {
+       TEGRA_PIN_DAP1_DIN_PB1,
+};
+
+static const unsigned dap1_dout_pb2_pins[] = {
+       TEGRA_PIN_DAP1_DOUT_PB2,
+};
+
+static const unsigned dap1_sclk_pb3_pins[] = {
+       TEGRA_PIN_DAP1_SCLK_PB3,
+};
+
+static const unsigned spi2_mosi_pb4_pins[] = {
+       TEGRA_PIN_SPI2_MOSI_PB4,
+};
+
+static const unsigned spi2_miso_pb5_pins[] = {
+       TEGRA_PIN_SPI2_MISO_PB5,
+};
+
+static const unsigned spi2_sck_pb6_pins[] = {
+       TEGRA_PIN_SPI2_SCK_PB6,
+};
+
+static const unsigned spi2_cs0_pb7_pins[] = {
+       TEGRA_PIN_SPI2_CS0_PB7,
+};
+
+static const unsigned spi1_mosi_pc0_pins[] = {
+       TEGRA_PIN_SPI1_MOSI_PC0,
+};
+
+static const unsigned spi1_miso_pc1_pins[] = {
+       TEGRA_PIN_SPI1_MISO_PC1,
+};
+
+static const unsigned spi1_sck_pc2_pins[] = {
+       TEGRA_PIN_SPI1_SCK_PC2,
+};
+
+static const unsigned spi1_cs0_pc3_pins[] = {
+       TEGRA_PIN_SPI1_CS0_PC3,
+};
+
+static const unsigned spi1_cs1_pc4_pins[] = {
+       TEGRA_PIN_SPI1_CS1_PC4,
+};
+
+static const unsigned spi4_sck_pc5_pins[] = {
+       TEGRA_PIN_SPI4_SCK_PC5,
+};
+
+static const unsigned spi4_cs0_pc6_pins[] = {
+       TEGRA_PIN_SPI4_CS0_PC6,
+};
+
+static const unsigned spi4_mosi_pc7_pins[] = {
+       TEGRA_PIN_SPI4_MOSI_PC7,
+};
+
+static const unsigned spi4_miso_pd0_pins[] = {
+       TEGRA_PIN_SPI4_MISO_PD0,
+};
+
+static const unsigned uart3_tx_pd1_pins[] = {
+       TEGRA_PIN_UART3_TX_PD1,
+};
+
+static const unsigned uart3_rx_pd2_pins[] = {
+       TEGRA_PIN_UART3_RX_PD2,
+};
+
+static const unsigned uart3_rts_pd3_pins[] = {
+       TEGRA_PIN_UART3_RTS_PD3,
+};
+
+static const unsigned uart3_cts_pd4_pins[] = {
+       TEGRA_PIN_UART3_CTS_PD4,
+};
+
+static const unsigned dmic1_clk_pe0_pins[] = {
+       TEGRA_PIN_DMIC1_CLK_PE0,
+};
+
+static const unsigned dmic1_dat_pe1_pins[] = {
+       TEGRA_PIN_DMIC1_DAT_PE1,
+};
+
+static const unsigned dmic2_clk_pe2_pins[] = {
+       TEGRA_PIN_DMIC2_CLK_PE2,
+};
+
+static const unsigned dmic2_dat_pe3_pins[] = {
+       TEGRA_PIN_DMIC2_DAT_PE3,
+};
+
+static const unsigned dmic3_clk_pe4_pins[] = {
+       TEGRA_PIN_DMIC3_CLK_PE4,
+};
+
+static const unsigned dmic3_dat_pe5_pins[] = {
+       TEGRA_PIN_DMIC3_DAT_PE5,
+};
+
+static const unsigned pe6_pins[] = {
+       TEGRA_PIN_PE6,
+};
+
+static const unsigned pe7_pins[] = {
+       TEGRA_PIN_PE7,
+};
+
+static const unsigned gen3_i2c_scl_pf0_pins[] = {
+       TEGRA_PIN_GEN3_I2C_SCL_PF0,
+};
+
+static const unsigned gen3_i2c_sda_pf1_pins[] = {
+       TEGRA_PIN_GEN3_I2C_SDA_PF1,
+};
+
+static const unsigned uart2_tx_pg0_pins[] = {
+       TEGRA_PIN_UART2_TX_PG0,
+};
+
+static const unsigned uart2_rx_pg1_pins[] = {
+       TEGRA_PIN_UART2_RX_PG1,
+};
+
+static const unsigned uart2_rts_pg2_pins[] = {
+       TEGRA_PIN_UART2_RTS_PG2,
+};
+
+static const unsigned uart2_cts_pg3_pins[] = {
+       TEGRA_PIN_UART2_CTS_PG3,
+};
+
+static const unsigned wifi_en_ph0_pins[] = {
+       TEGRA_PIN_WIFI_EN_PH0,
+};
+
+static const unsigned wifi_rst_ph1_pins[] = {
+       TEGRA_PIN_WIFI_RST_PH1,
+};
+
+static const unsigned wifi_wake_ap_ph2_pins[] = {
+       TEGRA_PIN_WIFI_WAKE_AP_PH2,
+};
+
+static const unsigned ap_wake_bt_ph3_pins[] = {
+       TEGRA_PIN_AP_WAKE_BT_PH3,
+};
+
+static const unsigned bt_rst_ph4_pins[] = {
+       TEGRA_PIN_BT_RST_PH4,
+};
+
+static const unsigned bt_wake_ap_ph5_pins[] = {
+       TEGRA_PIN_BT_WAKE_AP_PH5,
+};
+
+static const unsigned ph6_pins[] = {
+       TEGRA_PIN_PH6,
+};
+
+static const unsigned ap_wake_nfc_ph7_pins[] = {
+       TEGRA_PIN_AP_WAKE_NFC_PH7,
+};
+
+static const unsigned nfc_en_pi0_pins[] = {
+       TEGRA_PIN_NFC_EN_PI0,
+};
+
+static const unsigned nfc_int_pi1_pins[] = {
+       TEGRA_PIN_NFC_INT_PI1,
+};
+
+static const unsigned gps_en_pi2_pins[] = {
+       TEGRA_PIN_GPS_EN_PI2,
+};
+
+static const unsigned gps_rst_pi3_pins[] = {
+       TEGRA_PIN_GPS_RST_PI3,
+};
+
+static const unsigned uart4_tx_pi4_pins[] = {
+       TEGRA_PIN_UART4_TX_PI4,
+};
+
+static const unsigned uart4_rx_pi5_pins[] = {
+       TEGRA_PIN_UART4_RX_PI5,
+};
+
+static const unsigned uart4_rts_pi6_pins[] = {
+       TEGRA_PIN_UART4_RTS_PI6,
+};
+
+static const unsigned uart4_cts_pi7_pins[] = {
+       TEGRA_PIN_UART4_CTS_PI7,
+};
+
+static const unsigned gen1_i2c_sda_pj0_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SDA_PJ0,
+};
+
+static const unsigned gen1_i2c_scl_pj1_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PJ1,
+};
+
+static const unsigned gen2_i2c_scl_pj2_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PJ2,
+};
+
+static const unsigned gen2_i2c_sda_pj3_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SDA_PJ3,
+};
+
+static const unsigned dap4_fs_pj4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PJ4,
+};
+
+static const unsigned dap4_din_pj5_pins[] = {
+       TEGRA_PIN_DAP4_DIN_PJ5,
+};
+
+static const unsigned dap4_dout_pj6_pins[] = {
+       TEGRA_PIN_DAP4_DOUT_PJ6,
+};
+
+static const unsigned dap4_sclk_pj7_pins[] = {
+       TEGRA_PIN_DAP4_SCLK_PJ7,
+};
+
+static const unsigned pk0_pins[] = {
+       TEGRA_PIN_PK0,
+};
+
+static const unsigned pk1_pins[] = {
+       TEGRA_PIN_PK1,
+};
+
+static const unsigned pk2_pins[] = {
+       TEGRA_PIN_PK2,
+};
+
+static const unsigned pk3_pins[] = {
+       TEGRA_PIN_PK3,
+};
+
+static const unsigned pk4_pins[] = {
+       TEGRA_PIN_PK4,
+};
+
+static const unsigned pk5_pins[] = {
+       TEGRA_PIN_PK5,
+};
+
+static const unsigned pk6_pins[] = {
+       TEGRA_PIN_PK6,
+};
+
+static const unsigned pk7_pins[] = {
+       TEGRA_PIN_PK7,
+};
+
+static const unsigned pl0_pins[] = {
+       TEGRA_PIN_PL0,
+};
+
+static const unsigned pl1_pins[] = {
+       TEGRA_PIN_PL1,
+};
+
+static const unsigned sdmmc1_clk_pm0_pins[] = {
+       TEGRA_PIN_SDMMC1_CLK_PM0,
+};
+
+static const unsigned sdmmc1_cmd_pm1_pins[] = {
+       TEGRA_PIN_SDMMC1_CMD_PM1,
+};
+
+static const unsigned sdmmc1_dat3_pm2_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT3_PM2,
+};
+
+static const unsigned sdmmc1_dat2_pm3_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT2_PM3,
+};
+
+static const unsigned sdmmc1_dat1_pm4_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT1_PM4,
+};
+
+static const unsigned sdmmc1_dat0_pm5_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT0_PM5,
+};
+
+static const unsigned sdmmc3_clk_pp0_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PP0,
+};
+
+static const unsigned sdmmc3_cmd_pp1_pins[] = {
+       TEGRA_PIN_SDMMC3_CMD_PP1,
+};
+
+static const unsigned sdmmc3_dat3_pp2_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT3_PP2,
+};
+
+static const unsigned sdmmc3_dat2_pp3_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT2_PP3,
+};
+
+static const unsigned sdmmc3_dat1_pp4_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT1_PP4,
+};
+
+static const unsigned sdmmc3_dat0_pp5_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT0_PP5,
+};
+
+static const unsigned cam1_mclk_ps0_pins[] = {
+       TEGRA_PIN_CAM1_MCLK_PS0,
+};
+
+static const unsigned cam2_mclk_ps1_pins[] = {
+       TEGRA_PIN_CAM2_MCLK_PS1,
+};
+
+static const unsigned cam_i2c_scl_ps2_pins[] = {
+       TEGRA_PIN_CAM_I2C_SCL_PS2,
+};
+
+static const unsigned cam_i2c_sda_ps3_pins[] = {
+       TEGRA_PIN_CAM_I2C_SDA_PS3,
+};
+
+static const unsigned cam_rst_ps4_pins[] = {
+       TEGRA_PIN_CAM_RST_PS4,
+};
+
+static const unsigned cam_af_en_ps5_pins[] = {
+       TEGRA_PIN_CAM_AF_EN_PS5,
+};
+
+static const unsigned cam_flash_en_ps6_pins[] = {
+       TEGRA_PIN_CAM_FLASH_EN_PS6,
+};
+
+static const unsigned cam1_pwdn_ps7_pins[] = {
+       TEGRA_PIN_CAM1_PWDN_PS7,
+};
+
+static const unsigned cam2_pwdn_pt0_pins[] = {
+       TEGRA_PIN_CAM2_PWDN_PT0,
+};
+
+static const unsigned cam1_strobe_pt1_pins[] = {
+       TEGRA_PIN_CAM1_STROBE_PT1,
+};
+
+static const unsigned uart1_tx_pu0_pins[] = {
+       TEGRA_PIN_UART1_TX_PU0,
+};
+
+static const unsigned uart1_rx_pu1_pins[] = {
+       TEGRA_PIN_UART1_RX_PU1,
+};
+
+static const unsigned uart1_rts_pu2_pins[] = {
+       TEGRA_PIN_UART1_RTS_PU2,
+};
+
+static const unsigned uart1_cts_pu3_pins[] = {
+       TEGRA_PIN_UART1_CTS_PU3,
+};
+
+static const unsigned lcd_bl_pwm_pv0_pins[] = {
+       TEGRA_PIN_LCD_BL_PWM_PV0,
+};
+
+static const unsigned lcd_bl_en_pv1_pins[] = {
+       TEGRA_PIN_LCD_BL_EN_PV1,
+};
+
+static const unsigned lcd_rst_pv2_pins[] = {
+       TEGRA_PIN_LCD_RST_PV2,
+};
+
+static const unsigned lcd_gpio1_pv3_pins[] = {
+       TEGRA_PIN_LCD_GPIO1_PV3,
+};
+
+static const unsigned lcd_gpio2_pv4_pins[] = {
+       TEGRA_PIN_LCD_GPIO2_PV4,
+};
+
+static const unsigned ap_ready_pv5_pins[] = {
+       TEGRA_PIN_AP_READY_PV5,
+};
+
+static const unsigned touch_rst_pv6_pins[] = {
+       TEGRA_PIN_TOUCH_RST_PV6,
+};
+
+static const unsigned touch_clk_pv7_pins[] = {
+       TEGRA_PIN_TOUCH_CLK_PV7,
+};
+
+static const unsigned modem_wake_ap_px0_pins[] = {
+       TEGRA_PIN_MODEM_WAKE_AP_PX0,
+};
+
+static const unsigned touch_int_px1_pins[] = {
+       TEGRA_PIN_TOUCH_INT_PX1,
+};
+
+static const unsigned motion_int_px2_pins[] = {
+       TEGRA_PIN_MOTION_INT_PX2,
+};
+
+static const unsigned als_prox_int_px3_pins[] = {
+       TEGRA_PIN_ALS_PROX_INT_PX3,
+};
+
+static const unsigned temp_alert_px4_pins[] = {
+       TEGRA_PIN_TEMP_ALERT_PX4,
+};
+
+static const unsigned button_power_on_px5_pins[] = {
+       TEGRA_PIN_BUTTON_POWER_ON_PX5,
+};
+
+static const unsigned button_vol_up_px6_pins[] = {
+       TEGRA_PIN_BUTTON_VOL_UP_PX6,
+};
+
+static const unsigned button_vol_down_px7_pins[] = {
+       TEGRA_PIN_BUTTON_VOL_DOWN_PX7,
+};
+
+static const unsigned button_slide_sw_py0_pins[] = {
+       TEGRA_PIN_BUTTON_SLIDE_SW_PY0,
+};
+
+static const unsigned button_home_py1_pins[] = {
+       TEGRA_PIN_BUTTON_HOME_PY1,
+};
+
+static const unsigned lcd_te_py2_pins[] = {
+       TEGRA_PIN_LCD_TE_PY2,
+};
+
+static const unsigned pwr_i2c_scl_py3_pins[] = {
+       TEGRA_PIN_PWR_I2C_SCL_PY3,
+};
+
+static const unsigned pwr_i2c_sda_py4_pins[] = {
+       TEGRA_PIN_PWR_I2C_SDA_PY4,
+};
+
+static const unsigned clk_32k_out_py5_pins[] = {
+       TEGRA_PIN_CLK_32K_OUT_PY5,
+};
+
+static const unsigned pz0_pins[] = {
+       TEGRA_PIN_PZ0,
+};
+
+static const unsigned pz1_pins[] = {
+       TEGRA_PIN_PZ1,
+};
+
+static const unsigned pz2_pins[] = {
+       TEGRA_PIN_PZ2,
+};
+
+static const unsigned pz3_pins[] = {
+       TEGRA_PIN_PZ3,
+};
+
+static const unsigned pz4_pins[] = {
+       TEGRA_PIN_PZ4,
+};
+
+static const unsigned pz5_pins[] = {
+       TEGRA_PIN_PZ5,
+};
+
+static const unsigned dap2_fs_paa0_pins[] = {
+       TEGRA_PIN_DAP2_FS_PAA0,
+};
+
+static const unsigned dap2_sclk_paa1_pins[] = {
+       TEGRA_PIN_DAP2_SCLK_PAA1,
+};
+
+static const unsigned dap2_din_paa2_pins[] = {
+       TEGRA_PIN_DAP2_DIN_PAA2,
+};
+
+static const unsigned dap2_dout_paa3_pins[] = {
+       TEGRA_PIN_DAP2_DOUT_PAA3,
+};
+
+static const unsigned aud_mclk_pbb0_pins[] = {
+       TEGRA_PIN_AUD_MCLK_PBB0,
+};
+
+static const unsigned dvfs_pwm_pbb1_pins[] = {
+       TEGRA_PIN_DVFS_PWM_PBB1,
+};
+
+static const unsigned dvfs_clk_pbb2_pins[] = {
+       TEGRA_PIN_DVFS_CLK_PBB2,
+};
+
+static const unsigned gpio_x1_aud_pbb3_pins[] = {
+       TEGRA_PIN_GPIO_X1_AUD_PBB3,
+};
+
+static const unsigned gpio_x3_aud_pbb4_pins[] = {
+       TEGRA_PIN_GPIO_X3_AUD_PBB4,
+};
+
+static const unsigned hdmi_cec_pcc0_pins[] = {
+       TEGRA_PIN_HDMI_CEC_PCC0,
+};
+
+static const unsigned hdmi_int_dp_hpd_pcc1_pins[] = {
+       TEGRA_PIN_HDMI_INT_DP_HPD_PCC1,
+};
+
+static const unsigned spdif_out_pcc2_pins[] = {
+       TEGRA_PIN_SPDIF_OUT_PCC2,
+};
+
+static const unsigned spdif_in_pcc3_pins[] = {
+       TEGRA_PIN_SPDIF_IN_PCC3,
+};
+
+static const unsigned usb_vbus_en0_pcc4_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN0_PCC4,
+};
+
+static const unsigned usb_vbus_en1_pcc5_pins[] = {
+       TEGRA_PIN_USB_VBUS_EN1_PCC5,
+};
+
+static const unsigned dp_hpd0_pcc6_pins[] = {
+       TEGRA_PIN_DP_HPD0_PCC6,
+};
+
+static const unsigned pcc7_pins[] = {
+       TEGRA_PIN_PCC7,
+};
+
+static const unsigned spi2_cs1_pdd0_pins[] = {
+       TEGRA_PIN_SPI2_CS1_PDD0,
+};
+
+static const unsigned qspi_sck_pee0_pins[] = {
+       TEGRA_PIN_QSPI_SCK_PEE0,
+};
+
+static const unsigned qspi_cs_n_pee1_pins[] = {
+       TEGRA_PIN_QSPI_CS_N_PEE1,
+};
+
+static const unsigned qspi_io0_pee2_pins[] = {
+       TEGRA_PIN_QSPI_IO0_PEE2,
+};
+
+static const unsigned qspi_io1_pee3_pins[] = {
+       TEGRA_PIN_QSPI_IO1_PEE3,
+};
+
+static const unsigned qspi_io2_pee4_pins[] = {
+       TEGRA_PIN_QSPI_IO2_PEE4,
+};
+
+static const unsigned qspi_io3_pee5_pins[] = {
+       TEGRA_PIN_QSPI_IO3_PEE5,
+};
+
+static const unsigned core_pwr_req_pins[] = {
+       TEGRA_PIN_CORE_PWR_REQ,
+};
+
+static const unsigned cpu_pwr_req_pins[] = {
+       TEGRA_PIN_CPU_PWR_REQ,
+};
+
+static const unsigned pwr_int_n_pins[] = {
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned clk_32k_in_pins[] = {
+       TEGRA_PIN_CLK_32K_IN,
+};
+
+static const unsigned jtag_rtck_pins[] = {
+       TEGRA_PIN_JTAG_RTCK,
+};
+
+static const unsigned batt_bcl_pins[] = {
+       TEGRA_PIN_BATT_BCL,
+};
+
+static const unsigned clk_req_pins[] = {
+       TEGRA_PIN_CLK_REQ,
+};
+
+static const unsigned shutdown_pins[] = {
+       TEGRA_PIN_SHUTDOWN,
+};
+
+static const unsigned drive_pa6_pins[] = {
+       TEGRA_PIN_PA6,
+};
+
+static const unsigned drive_pcc7_pins[] = {
+       TEGRA_PIN_PCC7,
+};
+
+static const unsigned drive_pe6_pins[] = {
+       TEGRA_PIN_PE6,
+};
+
+static const unsigned drive_pe7_pins[] = {
+       TEGRA_PIN_PE7,
+};
+
+static const unsigned drive_ph6_pins[] = {
+       TEGRA_PIN_PH6,
+};
+
+static const unsigned drive_pk0_pins[] = {
+       TEGRA_PIN_PK0,
+};
+
+static const unsigned drive_pk1_pins[] = {
+       TEGRA_PIN_PK1,
+};
+
+static const unsigned drive_pk2_pins[] = {
+       TEGRA_PIN_PK2,
+};
+
+static const unsigned drive_pk3_pins[] = {
+       TEGRA_PIN_PK3,
+};
+
+static const unsigned drive_pk4_pins[] = {
+       TEGRA_PIN_PK4,
+};
+
+static const unsigned drive_pk5_pins[] = {
+       TEGRA_PIN_PK5,
+};
+
+static const unsigned drive_pk6_pins[] = {
+       TEGRA_PIN_PK6,
+};
+
+static const unsigned drive_pk7_pins[] = {
+       TEGRA_PIN_PK7,
+};
+
+static const unsigned drive_pl0_pins[] = {
+       TEGRA_PIN_PL0,
+};
+
+static const unsigned drive_pl1_pins[] = {
+       TEGRA_PIN_PL1,
+};
+
+static const unsigned drive_pz0_pins[] = {
+       TEGRA_PIN_PZ0,
+};
+
+static const unsigned drive_pz1_pins[] = {
+       TEGRA_PIN_PZ1,
+};
+
+static const unsigned drive_pz2_pins[] = {
+       TEGRA_PIN_PZ2,
+};
+
+static const unsigned drive_pz3_pins[] = {
+       TEGRA_PIN_PZ3,
+};
+
+static const unsigned drive_pz4_pins[] = {
+       TEGRA_PIN_PZ4,
+};
+
+static const unsigned drive_pz5_pins[] = {
+       TEGRA_PIN_PZ5,
+};
+
+static const unsigned drive_sdmmc1_pins[] = {
+       TEGRA_PIN_SDMMC1_CLK_PM0,
+       TEGRA_PIN_SDMMC1_CMD_PM1,
+       TEGRA_PIN_SDMMC1_DAT3_PM2,
+       TEGRA_PIN_SDMMC1_DAT2_PM3,
+       TEGRA_PIN_SDMMC1_DAT1_PM4,
+       TEGRA_PIN_SDMMC1_DAT0_PM5,
+};
+
+static const unsigned drive_sdmmc2_pins[] = {
+};
+
+static const unsigned drive_sdmmc3_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PP0,
+       TEGRA_PIN_SDMMC3_CMD_PP1,
+       TEGRA_PIN_SDMMC3_DAT3_PP2,
+       TEGRA_PIN_SDMMC3_DAT2_PP3,
+       TEGRA_PIN_SDMMC3_DAT1_PP4,
+       TEGRA_PIN_SDMMC3_DAT0_PP5,
+};
+
+static const unsigned drive_sdmmc4_pins[] = {
+};
+
+enum tegra_mux {
+       TEGRA_MUX_AUD,
+       TEGRA_MUX_BCL,
+       TEGRA_MUX_BLINK,
+       TEGRA_MUX_CCLA,
+       TEGRA_MUX_CEC,
+       TEGRA_MUX_CLDVFS,
+       TEGRA_MUX_CLK,
+       TEGRA_MUX_CORE,
+       TEGRA_MUX_CPU,
+       TEGRA_MUX_DISPLAYA,
+       TEGRA_MUX_DISPLAYB,
+       TEGRA_MUX_DMIC1,
+       TEGRA_MUX_DMIC2,
+       TEGRA_MUX_DMIC3,
+       TEGRA_MUX_DP,
+       TEGRA_MUX_DTV,
+       TEGRA_MUX_EXTPERIPH3,
+       TEGRA_MUX_I2C1,
+       TEGRA_MUX_I2C2,
+       TEGRA_MUX_I2C3,
+       TEGRA_MUX_I2CPMU,
+       TEGRA_MUX_I2CVI,
+       TEGRA_MUX_I2S1,
+       TEGRA_MUX_I2S2,
+       TEGRA_MUX_I2S3,
+       TEGRA_MUX_I2S4A,
+       TEGRA_MUX_I2S4B,
+       TEGRA_MUX_I2S5A,
+       TEGRA_MUX_I2S5B,
+       TEGRA_MUX_IQC0,
+       TEGRA_MUX_IQC1,
+       TEGRA_MUX_JTAG,
+       TEGRA_MUX_PE,
+       TEGRA_MUX_PE0,
+       TEGRA_MUX_PE1,
+       TEGRA_MUX_PMI,
+       TEGRA_MUX_PWM0,
+       TEGRA_MUX_PWM1,
+       TEGRA_MUX_PWM2,
+       TEGRA_MUX_PWM3,
+       TEGRA_MUX_QSPI,
+       TEGRA_MUX_RSVD0,
+       TEGRA_MUX_RSVD1,
+       TEGRA_MUX_RSVD2,
+       TEGRA_MUX_RSVD3,
+       TEGRA_MUX_SATA,
+       TEGRA_MUX_SDMMC1,
+       TEGRA_MUX_SDMMC3,
+       TEGRA_MUX_SHUTDOWN,
+       TEGRA_MUX_SOC,
+       TEGRA_MUX_SOR0,
+       TEGRA_MUX_SOR1,
+       TEGRA_MUX_SPDIF,
+       TEGRA_MUX_SPI1,
+       TEGRA_MUX_SPI2,
+       TEGRA_MUX_SPI3,
+       TEGRA_MUX_SPI4,
+       TEGRA_MUX_SYS,
+       TEGRA_MUX_TOUCH,
+       TEGRA_MUX_UART,
+       TEGRA_MUX_UARTA,
+       TEGRA_MUX_UARTB,
+       TEGRA_MUX_UARTC,
+       TEGRA_MUX_UARTD,
+       TEGRA_MUX_USB,
+       TEGRA_MUX_VGP1,
+       TEGRA_MUX_VGP2,
+       TEGRA_MUX_VGP3,
+       TEGRA_MUX_VGP4,
+       TEGRA_MUX_VGP5,
+       TEGRA_MUX_VGP6,
+       TEGRA_MUX_VIMCLK,
+       TEGRA_MUX_VIMCLK2,
+};
+
+#define FUNCTION(fname)                                        \
+       {                                               \
+               .name = #fname,                         \
+       }
+
+static struct tegra_function tegra210_functions[] = {
+       FUNCTION(aud),
+       FUNCTION(bcl),
+       FUNCTION(blink),
+       FUNCTION(ccla),
+       FUNCTION(cec),
+       FUNCTION(cldvfs),
+       FUNCTION(clk),
+       FUNCTION(core),
+       FUNCTION(cpu),
+       FUNCTION(displaya),
+       FUNCTION(displayb),
+       FUNCTION(dmic1),
+       FUNCTION(dmic2),
+       FUNCTION(dmic3),
+       FUNCTION(dp),
+       FUNCTION(dtv),
+       FUNCTION(extperiph3),
+       FUNCTION(i2c1),
+       FUNCTION(i2c2),
+       FUNCTION(i2c3),
+       FUNCTION(i2cpmu),
+       FUNCTION(i2cvi),
+       FUNCTION(i2s1),
+       FUNCTION(i2s2),
+       FUNCTION(i2s3),
+       FUNCTION(i2s4a),
+       FUNCTION(i2s4b),
+       FUNCTION(i2s5a),
+       FUNCTION(i2s5b),
+       FUNCTION(iqc0),
+       FUNCTION(iqc1),
+       FUNCTION(jtag),
+       FUNCTION(pe),
+       FUNCTION(pe0),
+       FUNCTION(pe1),
+       FUNCTION(pmi),
+       FUNCTION(pwm0),
+       FUNCTION(pwm1),
+       FUNCTION(pwm2),
+       FUNCTION(pwm3),
+       FUNCTION(qspi),
+       FUNCTION(rsvd0),
+       FUNCTION(rsvd1),
+       FUNCTION(rsvd2),
+       FUNCTION(rsvd3),
+       FUNCTION(sata),
+       FUNCTION(sdmmc1),
+       FUNCTION(sdmmc3),
+       FUNCTION(shutdown),
+       FUNCTION(soc),
+       FUNCTION(sor0),
+       FUNCTION(sor1),
+       FUNCTION(spdif),
+       FUNCTION(spi1),
+       FUNCTION(spi2),
+       FUNCTION(spi3),
+       FUNCTION(spi4),
+       FUNCTION(sys),
+       FUNCTION(touch),
+       FUNCTION(uart),
+       FUNCTION(uarta),
+       FUNCTION(uartb),
+       FUNCTION(uartc),
+       FUNCTION(uartd),
+       FUNCTION(usb),
+       FUNCTION(vgp1),
+       FUNCTION(vgp2),
+       FUNCTION(vgp3),
+       FUNCTION(vgp4),
+       FUNCTION(vgp5),
+       FUNCTION(vgp6),
+       FUNCTION(vimclk),
+       FUNCTION(vimclk2),
+};
+
+#define DRV_PINGROUP_REG_A             0x8d4   /* bank 0 */
+#define PINGROUP_REG_A                 0x3000  /* bank 1 */
+
+#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
+#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
+
+#define PINGROUP_BIT_Y(b)              (b)
+#define PINGROUP_BIT_N(b)              (-1)
+
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv,    \
+                rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b,      \
+                slwr_w, slwf_b, slwf_w)                                \
+       {                                                               \
+               .name = #pg_name,                                       \
+               .pins = pg_name##_pins,                                 \
+               .npins = ARRAY_SIZE(pg_name##_pins),                    \
+               .funcs = {                                              \
+                       TEGRA_MUX_##f0,                                 \
+                       TEGRA_MUX_##f1,                                 \
+                       TEGRA_MUX_##f2,                                 \
+                       TEGRA_MUX_##f3,                                 \
+               },                                                      \
+               .mux_reg = PINGROUP_REG(r),                             \
+               .mux_bank = 1,                                          \
+               .mux_bit = 0,                                           \
+               .pupd_reg = PINGROUP_REG(r),                            \
+               .pupd_bank = 1,                                         \
+               .pupd_bit = 2,                                          \
+               .tri_reg = PINGROUP_REG(r),                             \
+               .tri_bank = 1,                                          \
+               .tri_bit = 4,                                           \
+               .einput_bit = 6,                                        \
+               .odrain_bit = 11,                                       \
+               .lock_bit = 7,                                          \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10),              \
+               .hsm_bit = PINGROUP_BIT_##hsm(9),                       \
+               .schmitt_bit = 12,                                      \
+               .drvtype_bit = PINGROUP_BIT_##drvtype(13),              \
+               .drv_reg = DRV_PINGROUP_REG(rdrv),                      \
+               .drv_bank = 0,                                          \
+               .lpmd_bit = -1,                                         \
+               .drvdn_bit = drvdn_b,                                   \
+               .drvdn_width = drvdn_w,                                 \
+               .drvup_bit = drvup_b,                                   \
+               .drvup_width = drvup_w,                                 \
+               .slwr_bit = slwr_b,                                     \
+               .slwr_width = slwr_w,                                   \
+               .slwf_bit = slwf_b,                                     \
+               .slwf_width = slwf_w,                                   \
+       }
+
+#define DRV_PINGROUP(pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w,   \
+                    slwr_b, slwr_w, slwf_b, slwf_w)                    \
+       {                                                               \
+               .name = "drive_" #pg_name,                              \
+               .pins = drive_##pg_name##_pins,                         \
+               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
+               .mux_reg = -1,                                          \
+               .pupd_reg = -1,                                         \
+               .tri_reg = -1,                                          \
+               .einput_bit = -1,                                       \
+               .odrain_bit = -1,                                       \
+               .lock_bit = -1,                                         \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = DRV_PINGROUP_REG(r),                         \
+               .drv_bank = 0,                                          \
+               .hsm_bit = -1,                                          \
+               .schmitt_bit = -1,                                      \
+               .lpmd_bit = -1,                                         \
+               .drvdn_bit = drvdn_b,                                   \
+               .drvdn_width = drvdn_w,                                 \
+               .drvup_bit = drvup_b,                                   \
+               .drvup_width = drvup_w,                                 \
+               .slwr_bit = slwr_b,                                     \
+               .slwr_width = slwr_w,                                   \
+               .slwf_bit = slwf_b,                                     \
+               .slwf_width = slwf_w,                                   \
+               .drvtype_bit = -1,                                      \
+       }
+
+static const struct tegra_pingroup tegra210_groups[] = {
+       /*       pg_name,              f0,         f1,     f2,    f3,    r,      hsm, drvtype, e_io_hv, rdrv,  drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
+       PINGROUP(sdmmc1_clk_pm0,       SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x3000, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_cmd_pm1,       SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3004, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_dat3_pm2,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3008, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_dat2_pm3,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x300c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_dat1_pm4,      SDMMC1,     SPI3,   RSVD2, RSVD3, 0x3010, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc1_dat0_pm5,      SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x3014, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_clk_pp0,       SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x301c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_cmd_pp1,       SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3020, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_dat0_pp5,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3024, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_dat1_pp4,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3028, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_dat2_pp3,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x302c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(sdmmc3_dat3_pp2,      SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3030, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pex_l0_rst_n_pa0,     PE0,        RSVD1,  RSVD2, RSVD3, 0x3038, N,   N,       Y,       0xa5c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pex_l0_clkreq_n_pa1,  PE0,        RSVD1,  RSVD2, RSVD3, 0x303c, N,   N,       Y,       0xa58, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pex_wake_n_pa2,       PE,         RSVD1,  RSVD2, RSVD3, 0x3040, N,   N,       Y,       0xa68, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pex_l1_rst_n_pa3,     PE1,        RSVD1,  RSVD2, RSVD3, 0x3044, N,   N,       Y,       0xa64, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pex_l1_clkreq_n_pa4,  PE1,        RSVD1,  RSVD2, RSVD3, 0x3048, N,   N,       Y,       0xa60, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(sata_led_active_pa5,  SATA,       RSVD1,  RSVD2, RSVD3, 0x304c, N,   N,       N,       0xa94, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(spi1_mosi_pc0,        SPI1,       RSVD1,  RSVD2, RSVD3, 0x3050, Y,   Y,       N,       0xae0, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi1_miso_pc1,        SPI1,       RSVD1,  RSVD2, RSVD3, 0x3054, Y,   Y,       N,       0xadc, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi1_sck_pc2,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x3058, Y,   Y,       N,       0xae4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi1_cs0_pc3,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x305c, Y,   Y,       N,       0xad4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi1_cs1_pc4,         SPI1,       RSVD1,  RSVD2, RSVD3, 0x3060, Y,   Y,       N,       0xad8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_mosi_pb4,        SPI2,       DTV,    RSVD2, RSVD3, 0x3064, Y,   Y,       N,       0xaf4, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_miso_pb5,        SPI2,       DTV,    RSVD2, RSVD3, 0x3068, Y,   Y,       N,       0xaf0, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_sck_pb6,         SPI2,       DTV,    RSVD2, RSVD3, 0x306c, Y,   Y,       N,       0xaf8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_cs0_pb7,         SPI2,       DTV,    RSVD2, RSVD3, 0x3070, Y,   Y,       N,       0xae8, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi2_cs1_pdd0,        SPI2,       RSVD1,  RSVD2, RSVD3, 0x3074, Y,   Y,       N,       0xaec, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi4_mosi_pc7,        SPI4,       RSVD1,  RSVD2, RSVD3, 0x3078, Y,   Y,       N,       0xb04, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi4_miso_pd0,        SPI4,       RSVD1,  RSVD2, RSVD3, 0x307c, Y,   Y,       N,       0xb00, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi4_sck_pc5,         SPI4,       RSVD1,  RSVD2, RSVD3, 0x3080, Y,   Y,       N,       0xb08, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(spi4_cs0_pc6,         SPI4,       RSVD1,  RSVD2, RSVD3, 0x3084, Y,   Y,       N,       0xafc, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(qspi_sck_pee0,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3088, Y,   Y,       N,       0xa90, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(qspi_cs_n_pee1,       QSPI,       RSVD1,  RSVD2, RSVD3, 0x308c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(qspi_io0_pee2,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3090, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(qspi_io1_pee3,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3094, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(qspi_io2_pee4,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x3098, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(qspi_io3_pee5,        QSPI,       RSVD1,  RSVD2, RSVD3, 0x309c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(dmic1_clk_pe0,        DMIC1,      I2S3,   RSVD2, RSVD3, 0x30a4, N,   N,       N,       0x984, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic1_dat_pe1,        DMIC1,      I2S3,   RSVD2, RSVD3, 0x30a8, N,   N,       N,       0x988, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic2_clk_pe2,        DMIC2,      I2S3,   RSVD2, RSVD3, 0x30ac, N,   N,       N,       0x98c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic2_dat_pe3,        DMIC2,      I2S3,   RSVD2, RSVD3, 0x30b0, N,   N,       N,       0x990, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic3_clk_pe4,        DMIC3,      I2S5A,  RSVD2, RSVD3, 0x30b4, N,   N,       N,       0x994, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dmic3_dat_pe5,        DMIC3,      I2S5A,  RSVD2, RSVD3, 0x30b8, N,   N,       N,       0x998, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen1_i2c_scl_pj1,     I2C1,       RSVD1,  RSVD2, RSVD3, 0x30bc, N,   N,       Y,       0x9a8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen1_i2c_sda_pj0,     I2C1,       RSVD1,  RSVD2, RSVD3, 0x30c0, N,   N,       Y,       0x9ac, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen2_i2c_scl_pj2,     I2C2,       RSVD1,  RSVD2, RSVD3, 0x30c4, N,   N,       Y,       0x9b0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen2_i2c_sda_pj3,     I2C2,       RSVD1,  RSVD2, RSVD3, 0x30c8, N,   N,       Y,       0x9b4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen3_i2c_scl_pf0,     I2C3,       RSVD1,  RSVD2, RSVD3, 0x30cc, N,   N,       Y,       0x9b8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gen3_i2c_sda_pf1,     I2C3,       RSVD1,  RSVD2, RSVD3, 0x30d0, N,   N,       Y,       0x9bc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_i2c_scl_ps2,      I2C3,       I2CVI,  RSVD2, RSVD3, 0x30d4, N,   N,       Y,       0x934, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_i2c_sda_ps3,      I2C3,       I2CVI,  RSVD2, RSVD3, 0x30d8, N,   N,       Y,       0x938, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pwr_i2c_scl_py3,      I2CPMU,     RSVD1,  RSVD2, RSVD3, 0x30dc, N,   N,       Y,       0xa6c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pwr_i2c_sda_py4,      I2CPMU,     RSVD1,  RSVD2, RSVD3, 0x30e0, N,   N,       Y,       0xa70, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart1_tx_pu0,         UARTA,      RSVD1,  RSVD2, RSVD3, 0x30e4, N,   N,       N,       0xb28, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart1_rx_pu1,         UARTA,      RSVD1,  RSVD2, RSVD3, 0x30e8, N,   N,       N,       0xb24, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart1_rts_pu2,        UARTA,      RSVD1,  RSVD2, RSVD3, 0x30ec, N,   N,       N,       0xb20, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart1_cts_pu3,        UARTA,      RSVD1,  RSVD2, RSVD3, 0x30f0, N,   N,       N,       0xb1c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart2_tx_pg0,         UARTB,      I2S4A,  SPDIF, UART,  0x30f4, N,   N,       N,       0xb38, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart2_rx_pg1,         UARTB,      I2S4A,  SPDIF, UART,  0x30f8, N,   N,       N,       0xb34, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart2_rts_pg2,        UARTB,      I2S4A,  RSVD2, UART,  0x30fc, N,   N,       N,       0xb30, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart2_cts_pg3,        UARTB,      I2S4A,  RSVD2, UART,  0x3100, N,   N,       N,       0xb2c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart3_tx_pd1,         UARTC,      SPI4,   RSVD2, RSVD3, 0x3104, N,   N,       N,       0xb48, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart3_rx_pd2,         UARTC,      SPI4,   RSVD2, RSVD3, 0x3108, N,   N,       N,       0xb44, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart3_rts_pd3,        UARTC,      SPI4,   RSVD2, RSVD3, 0x310c, N,   N,       N,       0xb40, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart3_cts_pd4,        UARTC,      SPI4,   RSVD2, RSVD3, 0x3110, N,   N,       N,       0xb3c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart4_tx_pi4,         UARTD,      UART,   RSVD2, RSVD3, 0x3114, N,   N,       N,       0xb58, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart4_rx_pi5,         UARTD,      UART,   RSVD2, RSVD3, 0x3118, N,   N,       N,       0xb54, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart4_rts_pi6,        UARTD,      UART,   RSVD2, RSVD3, 0x311c, N,   N,       N,       0xb50, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(uart4_cts_pi7,        UARTD,      UART,   RSVD2, RSVD3, 0x3120, N,   N,       N,       0xb4c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dap1_fs_pb0,          I2S1,       RSVD1,  RSVD2, RSVD3, 0x3124, Y,   Y,       N,       0x95c, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap1_din_pb1,         I2S1,       RSVD1,  RSVD2, RSVD3, 0x3128, Y,   Y,       N,       0x954, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap1_dout_pb2,        I2S1,       RSVD1,  RSVD2, RSVD3, 0x312c, Y,   Y,       N,       0x958, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap1_sclk_pb3,        I2S1,       RSVD1,  RSVD2, RSVD3, 0x3130, Y,   Y,       N,       0x960, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap2_fs_paa0,         I2S2,       RSVD1,  RSVD2, RSVD3, 0x3134, Y,   Y,       N,       0x96c, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap2_din_paa2,        I2S2,       RSVD1,  RSVD2, RSVD3, 0x3138, Y,   Y,       N,       0x964, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap2_dout_paa3,       I2S2,       RSVD1,  RSVD2, RSVD3, 0x313c, Y,   Y,       N,       0x968, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap2_sclk_paa1,       I2S2,       RSVD1,  RSVD2, RSVD3, 0x3140, Y,   Y,       N,       0x970, -1,      -1,      -1,      -1,      28,     2,      30,     2),
+       PINGROUP(dap4_fs_pj4,          I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3144, N,   N,       N,       0x97c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dap4_din_pj5,         I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3148, N,   N,       N,       0x974, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dap4_dout_pj6,        I2S4B,      RSVD1,  RSVD2, RSVD3, 0x314c, N,   N,       N,       0x978, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dap4_sclk_pj7,        I2S4B,      RSVD1,  RSVD2, RSVD3, 0x3150, N,   N,       N,       0x980, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam1_mclk_ps0,        EXTPERIPH3, RSVD1,  RSVD2, RSVD3, 0x3154, N,   N,       N,       0x918, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam2_mclk_ps1,        EXTPERIPH3, RSVD1,  RSVD2, RSVD3, 0x3158, N,   N,       N,       0x924, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(jtag_rtck,            JTAG,       RSVD1,  RSVD2, RSVD3, 0x315c, N,   N,       N,       0xa2c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(clk_32k_in,           CLK,        RSVD1,  RSVD2, RSVD3, 0x3160, N,   N,       N,       0x940, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(clk_32k_out_py5,      SOC,        BLINK,  RSVD2, RSVD3, 0x3164, N,   N,       N,       0x944, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(batt_bcl,             BCL,        RSVD1,  RSVD2, RSVD3, 0x3168, N,   N,       Y,       0x8f8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(clk_req,              SYS,        RSVD1,  RSVD2, RSVD3, 0x316c, N,   N,       N,       0x948, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cpu_pwr_req,          CPU,        RSVD1,  RSVD2, RSVD3, 0x3170, N,   N,       N,       0x950, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pwr_int_n,            PMI,        RSVD1,  RSVD2, RSVD3, 0x3174, N,   N,       N,       0xa74, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(shutdown,             SHUTDOWN,   RSVD1,  RSVD2, RSVD3, 0x3178, N,   N,       N,       0xac8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(core_pwr_req,         CORE,       RSVD1,  RSVD2, RSVD3, 0x317c, N,   N,       N,       0x94c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(aud_mclk_pbb0,        AUD,        RSVD1,  RSVD2, RSVD3, 0x3180, N,   N,       N,       0x8f4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dvfs_pwm_pbb1,        RSVD0,      CLDVFS, SPI3,  RSVD3, 0x3184, N,   N,       N,       0x9a4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dvfs_clk_pbb2,        RSVD0,      CLDVFS, SPI3,  RSVD3, 0x3188, N,   N,       N,       0x9a0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gpio_x1_aud_pbb3,     RSVD0,      RSVD1,  SPI3,  RSVD3, 0x318c, N,   N,       N,       0xa14, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gpio_x3_aud_pbb4,     RSVD0,      RSVD1,  SPI3,  RSVD3, 0x3190, N,   N,       N,       0xa18, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pcc7,                 RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3194, N,   N,       Y,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(hdmi_cec_pcc0,        CEC,        RSVD1,  RSVD2, RSVD3, 0x3198, N,   N,       Y,       0xa24, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(hdmi_int_dp_hpd_pcc1, DP,         RSVD1,  RSVD2, RSVD3, 0x319c, N,   N,       Y,       0xa28, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(spdif_out_pcc2,       SPDIF,      RSVD1,  RSVD2, RSVD3, 0x31a0, N,   N,       N,       0xad0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(spdif_in_pcc3,        SPDIF,      RSVD1,  RSVD2, RSVD3, 0x31a4, N,   N,       N,       0xacc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(usb_vbus_en0_pcc4,    USB,        RSVD1,  RSVD2, RSVD3, 0x31a8, N,   N,       Y,       0xb5c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(usb_vbus_en1_pcc5,    USB,        RSVD1,  RSVD2, RSVD3, 0x31ac, N,   N,       Y,       0xb60, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(dp_hpd0_pcc6,         DP,         RSVD1,  RSVD2, RSVD3, 0x31b0, N,   N,       N,       0x99c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(wifi_en_ph0,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31b4, N,   N,       N,       0xb64, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(wifi_rst_ph1,         RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31b8, N,   N,       N,       0xb68, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(wifi_wake_ap_ph2,     RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31bc, N,   N,       N,       0xb6c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(ap_wake_bt_ph3,       RSVD0,      UARTB,  SPDIF, RSVD3, 0x31c0, N,   N,       N,       0x8ec, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(bt_rst_ph4,           RSVD0,      UARTB,  SPDIF, RSVD3, 0x31c4, N,   N,       N,       0x8fc, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(bt_wake_ap_ph5,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31c8, N,   N,       N,       0x900, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(ap_wake_nfc_ph7,      RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31cc, N,   N,       N,       0x8f0, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(nfc_en_pi0,           RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d0, N,   N,       N,       0xa50, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(nfc_int_pi1,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d4, N,   N,       N,       0xa54, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gps_en_pi2,           RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31d8, N,   N,       N,       0xa1c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(gps_rst_pi3,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x31dc, N,   N,       N,       0xa20, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_rst_ps4,          VGP1,       RSVD1,  RSVD2, RSVD3, 0x31e0, N,   N,       N,       0x93c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_af_en_ps5,        VIMCLK,     VGP2,   RSVD2, RSVD3, 0x31e4, N,   N,       N,       0x92c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam_flash_en_ps6,     VIMCLK,     VGP3,   RSVD2, RSVD3, 0x31e8, N,   N,       N,       0x930, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam1_pwdn_ps7,        VGP4,       RSVD1,  RSVD2, RSVD3, 0x31ec, N,   N,       N,       0x91c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam2_pwdn_pt0,        VGP5,       RSVD1,  RSVD2, RSVD3, 0x31f0, N,   N,       N,       0x928, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(cam1_strobe_pt1,      VGP6,       RSVD1,  RSVD2, RSVD3, 0x31f4, N,   N,       N,       0x920, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_te_py2,           DISPLAYA,   RSVD1,  RSVD2, RSVD3, 0x31f8, N,   N,       N,       0xa44, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_bl_pwm_pv0,       DISPLAYA,   PWM0,   SOR0,  RSVD3, 0x31fc, N,   N,       N,       0xa34, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_bl_en_pv1,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3200, N,   N,       N,       0xa30, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_rst_pv2,          RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3204, N,   N,       N,       0xa40, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_gpio1_pv3,        DISPLAYB,   RSVD1,  RSVD2, RSVD3, 0x3208, N,   N,       N,       0xa38, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(lcd_gpio2_pv4,        DISPLAYB,   PWM1,   RSVD2, SOR1,  0x320c, N,   N,       N,       0xa3c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(ap_ready_pv5,         RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3210, N,   N,       N,       0x8e8, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(touch_rst_pv6,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3214, N,   N,       N,       0xb18, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(touch_clk_pv7,        TOUCH,      RSVD1,  RSVD2, RSVD3, 0x3218, N,   N,       N,       0xb10, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(modem_wake_ap_px0,    RSVD0,      RSVD1,  RSVD2, RSVD3, 0x321c, N,   N,       N,       0xa48, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(touch_int_px1,        RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3220, N,   N,       N,       0xb14, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(motion_int_px2,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3224, N,   N,       N,       0xa4c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(als_prox_int_px3,     RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3228, N,   N,       N,       0x8e4, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(temp_alert_px4,       RSVD0,      RSVD1,  RSVD2, RSVD3, 0x322c, N,   N,       N,       0xb0c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_power_on_px5,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3230, N,   N,       N,       0x908, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_vol_up_px6,    RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3234, N,   N,       N,       0x914, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_vol_down_px7,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3238, N,   N,       N,       0x910, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_slide_sw_py0,  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x323c, N,   N,       N,       0x90c, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(button_home_py1,      RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3240, N,   N,       N,       0x904, 12,      5,       20,      5,       -1,     -1,     -1,     -1),
+       PINGROUP(pa6,                  SATA,       RSVD1,  RSVD2, RSVD3, 0x3244, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pe6,                  RSVD0,      I2S5A,  PWM2,  RSVD3, 0x3248, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pe7,                  RSVD0,      I2S5A,  PWM3,  RSVD3, 0x324c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(ph6,                  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3250, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk0,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3254, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk1,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3258, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk2,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x325c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk3,                  IQC0,       I2S5B,  RSVD2, RSVD3, 0x3260, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk4,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3264, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk5,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3268, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk6,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x326c, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pk7,                  IQC1,       RSVD1,  RSVD2, RSVD3, 0x3270, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pl0,                  RSVD0,      RSVD1,  RSVD2, RSVD3, 0x3274, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pl1,                  SOC,        RSVD1,  RSVD2, RSVD3, 0x3278, Y,   Y,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz0,                  VIMCLK2,    RSVD1,  RSVD2, RSVD3, 0x327c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz1,                  VIMCLK2,    SDMMC1, RSVD2, RSVD3, 0x3280, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz2,                  SDMMC3,     CCLA,   RSVD2, RSVD3, 0x3284, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz3,                  SDMMC3,     RSVD1,  RSVD2, RSVD3, 0x3288, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz4,                  SDMMC1,     RSVD1,  RSVD2, RSVD3, 0x328c, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+       PINGROUP(pz5,                  SOC,        RSVD1,  RSVD2, RSVD3, 0x3290, N,   N,       N,       -1,    -1,      -1,      -1,      -1,      -1,     -1,     -1,     -1),
+
+       /* pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
+       DRV_PINGROUP(pa6,    0x9c0, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(pcc7,   0x9c4, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(pe6,    0x9c8, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(pe7,    0x9cc, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(ph6,    0x9d0, 12, 5,  20, 5,  -1, -1, -1, -1),
+       DRV_PINGROUP(pk0,    0x9d4, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk1,    0x9d8, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk2,    0x9dc, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk3,    0x9e0, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk4,    0x9e4, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk5,    0x9e8, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk6,    0x9ec, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pk7,    0x9f0, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pl0,    0x9f4, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pl1,    0x9f8, -1, -1, -1, -1, 28, 2,  30, 2),
+       DRV_PINGROUP(pz0,    0x9fc, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz1,    0xa00, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz2,    0xa04, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz3,    0xa08, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz4,    0xa0c, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(pz5,    0xa10, 12, 7,  20, 7,  -1, -1, -1, -1),
+       DRV_PINGROUP(sdmmc1, 0xa98, 12, 7,  20, 7,  28, 2,  30, 2),
+       DRV_PINGROUP(sdmmc2, 0xa9c, 2,  6,  8,  6,  28, 2,  30, 2),
+       DRV_PINGROUP(sdmmc3, 0xab0, 12, 7,  20, 7,  28, 2,  30, 2),
+       DRV_PINGROUP(sdmmc4, 0xab4, 2,  6,  8,  6,  28, 2,  30, 2),
+};
+
+static const struct tegra_pinctrl_soc_data tegra210_pinctrl = {
+       .ngpios = NUM_GPIOS,
+       .pins = tegra210_pins,
+       .npins = ARRAY_SIZE(tegra210_pins),
+       .functions = tegra210_functions,
+       .nfunctions = ARRAY_SIZE(tegra210_functions),
+       .groups = tegra210_groups,
+       .ngroups = ARRAY_SIZE(tegra210_groups),
+       .hsm_in_mux = true,
+       .schmitt_in_mux = true,
+       .drvtype_in_mux = true,
+};
+
+static int tegra210_pinctrl_probe(struct platform_device *pdev)
+{
+       return tegra_pinctrl_probe(pdev, &tegra210_pinctrl);
+}
+
+static const struct of_device_id tegra210_pinctrl_of_match[] = {
+       { .compatible = "nvidia,tegra210-pinmux", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, tegra210_pinctrl_of_match);
+
+static struct platform_driver tegra210_pinctrl_driver = {
+       .driver = {
+               .name = "tegra210-pinctrl",
+               .of_match_table = tegra210_pinctrl_of_match,
+       },
+       .probe = tegra210_pinctrl_probe,
+       .remove = tegra_pinctrl_remove,
+};
+module_platform_driver(tegra210_pinctrl_driver);
+
+MODULE_AUTHOR("NVIDIA");
+MODULE_DESCRIPTION("NVIDIA Tegra210 pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c
new file mode 100644 (file)
index 0000000..47b2fd8
--- /dev/null
@@ -0,0 +1,2507 @@
+/*
+ * Pinctrl data for the NVIDIA Tegra30 pinmux
+ *
+ * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "pinctrl-tegra.h"
+
+/*
+ * Most pins affected by the pinmux can also be GPIOs. Define these first.
+ * These must match how the GPIO driver names/numbers its pins.
+ */
+#define _GPIO(offset)                  (offset)
+
+#define TEGRA_PIN_CLK_32K_OUT_PA0      _GPIO(0)
+#define TEGRA_PIN_UART3_CTS_N_PA1      _GPIO(1)
+#define TEGRA_PIN_DAP2_FS_PA2          _GPIO(2)
+#define TEGRA_PIN_DAP2_SCLK_PA3                _GPIO(3)
+#define TEGRA_PIN_DAP2_DIN_PA4         _GPIO(4)
+#define TEGRA_PIN_DAP2_DOUT_PA5                _GPIO(5)
+#define TEGRA_PIN_SDMMC3_CLK_PA6       _GPIO(6)
+#define TEGRA_PIN_SDMMC3_CMD_PA7       _GPIO(7)
+#define TEGRA_PIN_GMI_A17_PB0          _GPIO(8)
+#define TEGRA_PIN_GMI_A18_PB1          _GPIO(9)
+#define TEGRA_PIN_LCD_PWR0_PB2         _GPIO(10)
+#define TEGRA_PIN_LCD_PCLK_PB3         _GPIO(11)
+#define TEGRA_PIN_SDMMC3_DAT3_PB4      _GPIO(12)
+#define TEGRA_PIN_SDMMC3_DAT2_PB5      _GPIO(13)
+#define TEGRA_PIN_SDMMC3_DAT1_PB6      _GPIO(14)
+#define TEGRA_PIN_SDMMC3_DAT0_PB7      _GPIO(15)
+#define TEGRA_PIN_UART3_RTS_N_PC0      _GPIO(16)
+#define TEGRA_PIN_LCD_PWR1_PC1         _GPIO(17)
+#define TEGRA_PIN_UART2_TXD_PC2                _GPIO(18)
+#define TEGRA_PIN_UART2_RXD_PC3                _GPIO(19)
+#define TEGRA_PIN_GEN1_I2C_SCL_PC4     _GPIO(20)
+#define TEGRA_PIN_GEN1_I2C_SDA_PC5     _GPIO(21)
+#define TEGRA_PIN_LCD_PWR2_PC6         _GPIO(22)
+#define TEGRA_PIN_GMI_WP_N_PC7         _GPIO(23)
+#define TEGRA_PIN_SDMMC3_DAT5_PD0      _GPIO(24)
+#define TEGRA_PIN_SDMMC3_DAT4_PD1      _GPIO(25)
+#define TEGRA_PIN_LCD_DC1_PD2          _GPIO(26)
+#define TEGRA_PIN_SDMMC3_DAT6_PD3      _GPIO(27)
+#define TEGRA_PIN_SDMMC3_DAT7_PD4      _GPIO(28)
+#define TEGRA_PIN_VI_D1_PD5            _GPIO(29)
+#define TEGRA_PIN_VI_VSYNC_PD6         _GPIO(30)
+#define TEGRA_PIN_VI_HSYNC_PD7         _GPIO(31)
+#define TEGRA_PIN_LCD_D0_PE0           _GPIO(32)
+#define TEGRA_PIN_LCD_D1_PE1           _GPIO(33)
+#define TEGRA_PIN_LCD_D2_PE2           _GPIO(34)
+#define TEGRA_PIN_LCD_D3_PE3           _GPIO(35)
+#define TEGRA_PIN_LCD_D4_PE4           _GPIO(36)
+#define TEGRA_PIN_LCD_D5_PE5           _GPIO(37)
+#define TEGRA_PIN_LCD_D6_PE6           _GPIO(38)
+#define TEGRA_PIN_LCD_D7_PE7           _GPIO(39)
+#define TEGRA_PIN_LCD_D8_PF0           _GPIO(40)
+#define TEGRA_PIN_LCD_D9_PF1           _GPIO(41)
+#define TEGRA_PIN_LCD_D10_PF2          _GPIO(42)
+#define TEGRA_PIN_LCD_D11_PF3          _GPIO(43)
+#define TEGRA_PIN_LCD_D12_PF4          _GPIO(44)
+#define TEGRA_PIN_LCD_D13_PF5          _GPIO(45)
+#define TEGRA_PIN_LCD_D14_PF6          _GPIO(46)
+#define TEGRA_PIN_LCD_D15_PF7          _GPIO(47)
+#define TEGRA_PIN_GMI_AD0_PG0          _GPIO(48)
+#define TEGRA_PIN_GMI_AD1_PG1          _GPIO(49)
+#define TEGRA_PIN_GMI_AD2_PG2          _GPIO(50)
+#define TEGRA_PIN_GMI_AD3_PG3          _GPIO(51)
+#define TEGRA_PIN_GMI_AD4_PG4          _GPIO(52)
+#define TEGRA_PIN_GMI_AD5_PG5          _GPIO(53)
+#define TEGRA_PIN_GMI_AD6_PG6          _GPIO(54)
+#define TEGRA_PIN_GMI_AD7_PG7          _GPIO(55)
+#define TEGRA_PIN_GMI_AD8_PH0          _GPIO(56)
+#define TEGRA_PIN_GMI_AD9_PH1          _GPIO(57)
+#define TEGRA_PIN_GMI_AD10_PH2         _GPIO(58)
+#define TEGRA_PIN_GMI_AD11_PH3         _GPIO(59)
+#define TEGRA_PIN_GMI_AD12_PH4         _GPIO(60)
+#define TEGRA_PIN_GMI_AD13_PH5         _GPIO(61)
+#define TEGRA_PIN_GMI_AD14_PH6         _GPIO(62)
+#define TEGRA_PIN_GMI_AD15_PH7         _GPIO(63)
+#define TEGRA_PIN_GMI_WR_N_PI0         _GPIO(64)
+#define TEGRA_PIN_GMI_OE_N_PI1         _GPIO(65)
+#define TEGRA_PIN_GMI_DQS_PI2          _GPIO(66)
+#define TEGRA_PIN_GMI_CS6_N_PI3                _GPIO(67)
+#define TEGRA_PIN_GMI_RST_N_PI4                _GPIO(68)
+#define TEGRA_PIN_GMI_IORDY_PI5                _GPIO(69)
+#define TEGRA_PIN_GMI_CS7_N_PI6                _GPIO(70)
+#define TEGRA_PIN_GMI_WAIT_PI7         _GPIO(71)
+#define TEGRA_PIN_GMI_CS0_N_PJ0                _GPIO(72)
+#define TEGRA_PIN_LCD_DE_PJ1           _GPIO(73)
+#define TEGRA_PIN_GMI_CS1_N_PJ2                _GPIO(74)
+#define TEGRA_PIN_LCD_HSYNC_PJ3                _GPIO(75)
+#define TEGRA_PIN_LCD_VSYNC_PJ4                _GPIO(76)
+#define TEGRA_PIN_UART2_CTS_N_PJ5      _GPIO(77)
+#define TEGRA_PIN_UART2_RTS_N_PJ6      _GPIO(78)
+#define TEGRA_PIN_GMI_A16_PJ7          _GPIO(79)
+#define TEGRA_PIN_GMI_ADV_N_PK0                _GPIO(80)
+#define TEGRA_PIN_GMI_CLK_PK1          _GPIO(81)
+#define TEGRA_PIN_GMI_CS4_N_PK2                _GPIO(82)
+#define TEGRA_PIN_GMI_CS2_N_PK3                _GPIO(83)
+#define TEGRA_PIN_GMI_CS3_N_PK4                _GPIO(84)
+#define TEGRA_PIN_SPDIF_OUT_PK5                _GPIO(85)
+#define TEGRA_PIN_SPDIF_IN_PK6         _GPIO(86)
+#define TEGRA_PIN_GMI_A19_PK7          _GPIO(87)
+#define TEGRA_PIN_VI_D2_PL0            _GPIO(88)
+#define TEGRA_PIN_VI_D3_PL1            _GPIO(89)
+#define TEGRA_PIN_VI_D4_PL2            _GPIO(90)
+#define TEGRA_PIN_VI_D5_PL3            _GPIO(91)
+#define TEGRA_PIN_VI_D6_PL4            _GPIO(92)
+#define TEGRA_PIN_VI_D7_PL5            _GPIO(93)
+#define TEGRA_PIN_VI_D8_PL6            _GPIO(94)
+#define TEGRA_PIN_VI_D9_PL7            _GPIO(95)
+#define TEGRA_PIN_LCD_D16_PM0          _GPIO(96)
+#define TEGRA_PIN_LCD_D17_PM1          _GPIO(97)
+#define TEGRA_PIN_LCD_D18_PM2          _GPIO(98)
+#define TEGRA_PIN_LCD_D19_PM3          _GPIO(99)
+#define TEGRA_PIN_LCD_D20_PM4          _GPIO(100)
+#define TEGRA_PIN_LCD_D21_PM5          _GPIO(101)
+#define TEGRA_PIN_LCD_D22_PM6          _GPIO(102)
+#define TEGRA_PIN_LCD_D23_PM7          _GPIO(103)
+#define TEGRA_PIN_DAP1_FS_PN0          _GPIO(104)
+#define TEGRA_PIN_DAP1_DIN_PN1         _GPIO(105)
+#define TEGRA_PIN_DAP1_DOUT_PN2                _GPIO(106)
+#define TEGRA_PIN_DAP1_SCLK_PN3                _GPIO(107)
+#define TEGRA_PIN_LCD_CS0_N_PN4                _GPIO(108)
+#define TEGRA_PIN_LCD_SDOUT_PN5                _GPIO(109)
+#define TEGRA_PIN_LCD_DC0_PN6          _GPIO(110)
+#define TEGRA_PIN_HDMI_INT_PN7         _GPIO(111)
+#define TEGRA_PIN_ULPI_DATA7_PO0       _GPIO(112)
+#define TEGRA_PIN_ULPI_DATA0_PO1       _GPIO(113)
+#define TEGRA_PIN_ULPI_DATA1_PO2       _GPIO(114)
+#define TEGRA_PIN_ULPI_DATA2_PO3       _GPIO(115)
+#define TEGRA_PIN_ULPI_DATA3_PO4       _GPIO(116)
+#define TEGRA_PIN_ULPI_DATA4_PO5       _GPIO(117)
+#define TEGRA_PIN_ULPI_DATA5_PO6       _GPIO(118)
+#define TEGRA_PIN_ULPI_DATA6_PO7       _GPIO(119)
+#define TEGRA_PIN_DAP3_FS_PP0          _GPIO(120)
+#define TEGRA_PIN_DAP3_DIN_PP1         _GPIO(121)
+#define TEGRA_PIN_DAP3_DOUT_PP2                _GPIO(122)
+#define TEGRA_PIN_DAP3_SCLK_PP3                _GPIO(123)
+#define TEGRA_PIN_DAP4_FS_PP4          _GPIO(124)
+#define TEGRA_PIN_DAP4_DIN_PP5         _GPIO(125)
+#define TEGRA_PIN_DAP4_DOUT_PP6                _GPIO(126)
+#define TEGRA_PIN_DAP4_SCLK_PP7                _GPIO(127)
+#define TEGRA_PIN_KB_COL0_PQ0          _GPIO(128)
+#define TEGRA_PIN_KB_COL1_PQ1          _GPIO(129)
+#define TEGRA_PIN_KB_COL2_PQ2          _GPIO(130)
+#define TEGRA_PIN_KB_COL3_PQ3          _GPIO(131)
+#define TEGRA_PIN_KB_COL4_PQ4          _GPIO(132)
+#define TEGRA_PIN_KB_COL5_PQ5          _GPIO(133)
+#define TEGRA_PIN_KB_COL6_PQ6          _GPIO(134)
+#define TEGRA_PIN_KB_COL7_PQ7          _GPIO(135)
+#define TEGRA_PIN_KB_ROW0_PR0          _GPIO(136)
+#define TEGRA_PIN_KB_ROW1_PR1          _GPIO(137)
+#define TEGRA_PIN_KB_ROW2_PR2          _GPIO(138)
+#define TEGRA_PIN_KB_ROW3_PR3          _GPIO(139)
+#define TEGRA_PIN_KB_ROW4_PR4          _GPIO(140)
+#define TEGRA_PIN_KB_ROW5_PR5          _GPIO(141)
+#define TEGRA_PIN_KB_ROW6_PR6          _GPIO(142)
+#define TEGRA_PIN_KB_ROW7_PR7          _GPIO(143)
+#define TEGRA_PIN_KB_ROW8_PS0          _GPIO(144)
+#define TEGRA_PIN_KB_ROW9_PS1          _GPIO(145)
+#define TEGRA_PIN_KB_ROW10_PS2         _GPIO(146)
+#define TEGRA_PIN_KB_ROW11_PS3         _GPIO(147)
+#define TEGRA_PIN_KB_ROW12_PS4         _GPIO(148)
+#define TEGRA_PIN_KB_ROW13_PS5         _GPIO(149)
+#define TEGRA_PIN_KB_ROW14_PS6         _GPIO(150)
+#define TEGRA_PIN_KB_ROW15_PS7         _GPIO(151)
+#define TEGRA_PIN_VI_PCLK_PT0          _GPIO(152)
+#define TEGRA_PIN_VI_MCLK_PT1          _GPIO(153)
+#define TEGRA_PIN_VI_D10_PT2           _GPIO(154)
+#define TEGRA_PIN_VI_D11_PT3           _GPIO(155)
+#define TEGRA_PIN_VI_D0_PT4            _GPIO(156)
+#define TEGRA_PIN_GEN2_I2C_SCL_PT5     _GPIO(157)
+#define TEGRA_PIN_GEN2_I2C_SDA_PT6     _GPIO(158)
+#define TEGRA_PIN_SDMMC4_CMD_PT7       _GPIO(159)
+#define TEGRA_PIN_PU0                  _GPIO(160)
+#define TEGRA_PIN_PU1                  _GPIO(161)
+#define TEGRA_PIN_PU2                  _GPIO(162)
+#define TEGRA_PIN_PU3                  _GPIO(163)
+#define TEGRA_PIN_PU4                  _GPIO(164)
+#define TEGRA_PIN_PU5                  _GPIO(165)
+#define TEGRA_PIN_PU6                  _GPIO(166)
+#define TEGRA_PIN_JTAG_RTCK_PU7                _GPIO(167)
+#define TEGRA_PIN_PV0                  _GPIO(168)
+#define TEGRA_PIN_PV1                  _GPIO(169)
+#define TEGRA_PIN_PV2                  _GPIO(170)
+#define TEGRA_PIN_PV3                  _GPIO(171)
+#define TEGRA_PIN_DDC_SCL_PV4          _GPIO(172)
+#define TEGRA_PIN_DDC_SDA_PV5          _GPIO(173)
+#define TEGRA_PIN_CRT_HSYNC_PV6                _GPIO(174)
+#define TEGRA_PIN_CRT_VSYNC_PV7                _GPIO(175)
+#define TEGRA_PIN_LCD_CS1_N_PW0                _GPIO(176)
+#define TEGRA_PIN_LCD_M1_PW1           _GPIO(177)
+#define TEGRA_PIN_SPI2_CS1_N_PW2       _GPIO(178)
+#define TEGRA_PIN_SPI2_CS2_N_PW3       _GPIO(179)
+#define TEGRA_PIN_CLK1_OUT_PW4         _GPIO(180)
+#define TEGRA_PIN_CLK2_OUT_PW5         _GPIO(181)
+#define TEGRA_PIN_UART3_TXD_PW6                _GPIO(182)
+#define TEGRA_PIN_UART3_RXD_PW7                _GPIO(183)
+#define TEGRA_PIN_SPI2_MOSI_PX0                _GPIO(184)
+#define TEGRA_PIN_SPI2_MISO_PX1                _GPIO(185)
+#define TEGRA_PIN_SPI2_SCK_PX2         _GPIO(186)
+#define TEGRA_PIN_SPI2_CS0_N_PX3       _GPIO(187)
+#define TEGRA_PIN_SPI1_MOSI_PX4                _GPIO(188)
+#define TEGRA_PIN_SPI1_SCK_PX5         _GPIO(189)
+#define TEGRA_PIN_SPI1_CS0_N_PX6       _GPIO(190)
+#define TEGRA_PIN_SPI1_MISO_PX7                _GPIO(191)
+#define TEGRA_PIN_ULPI_CLK_PY0         _GPIO(192)
+#define TEGRA_PIN_ULPI_DIR_PY1         _GPIO(193)
+#define TEGRA_PIN_ULPI_NXT_PY2         _GPIO(194)
+#define TEGRA_PIN_ULPI_STP_PY3         _GPIO(195)
+#define TEGRA_PIN_SDMMC1_DAT3_PY4      _GPIO(196)
+#define TEGRA_PIN_SDMMC1_DAT2_PY5      _GPIO(197)
+#define TEGRA_PIN_SDMMC1_DAT1_PY6      _GPIO(198)
+#define TEGRA_PIN_SDMMC1_DAT0_PY7      _GPIO(199)
+#define TEGRA_PIN_SDMMC1_CLK_PZ0       _GPIO(200)
+#define TEGRA_PIN_SDMMC1_CMD_PZ1       _GPIO(201)
+#define TEGRA_PIN_LCD_SDIN_PZ2         _GPIO(202)
+#define TEGRA_PIN_LCD_WR_N_PZ3         _GPIO(203)
+#define TEGRA_PIN_LCD_SCK_PZ4          _GPIO(204)
+#define TEGRA_PIN_SYS_CLK_REQ_PZ5      _GPIO(205)
+#define TEGRA_PIN_PWR_I2C_SCL_PZ6      _GPIO(206)
+#define TEGRA_PIN_PWR_I2C_SDA_PZ7      _GPIO(207)
+#define TEGRA_PIN_SDMMC4_DAT0_PAA0     _GPIO(208)
+#define TEGRA_PIN_SDMMC4_DAT1_PAA1     _GPIO(209)
+#define TEGRA_PIN_SDMMC4_DAT2_PAA2     _GPIO(210)
+#define TEGRA_PIN_SDMMC4_DAT3_PAA3     _GPIO(211)
+#define TEGRA_PIN_SDMMC4_DAT4_PAA4     _GPIO(212)
+#define TEGRA_PIN_SDMMC4_DAT5_PAA5     _GPIO(213)
+#define TEGRA_PIN_SDMMC4_DAT6_PAA6     _GPIO(214)
+#define TEGRA_PIN_SDMMC4_DAT7_PAA7     _GPIO(215)
+#define TEGRA_PIN_PBB0                 _GPIO(216)
+#define TEGRA_PIN_CAM_I2C_SCL_PBB1     _GPIO(217)
+#define TEGRA_PIN_CAM_I2C_SDA_PBB2     _GPIO(218)
+#define TEGRA_PIN_PBB3                 _GPIO(219)
+#define TEGRA_PIN_PBB4                 _GPIO(220)
+#define TEGRA_PIN_PBB5                 _GPIO(221)
+#define TEGRA_PIN_PBB6                 _GPIO(222)
+#define TEGRA_PIN_PBB7                 _GPIO(223)
+#define TEGRA_PIN_CAM_MCLK_PCC0                _GPIO(224)
+#define TEGRA_PIN_PCC1                 _GPIO(225)
+#define TEGRA_PIN_PCC2                 _GPIO(226)
+#define TEGRA_PIN_SDMMC4_RST_N_PCC3    _GPIO(227)
+#define TEGRA_PIN_SDMMC4_CLK_PCC4      _GPIO(228)
+#define TEGRA_PIN_CLK2_REQ_PCC5                _GPIO(229)
+#define TEGRA_PIN_PEX_L2_RST_N_PCC6    _GPIO(230)
+#define TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7 _GPIO(231)
+#define TEGRA_PIN_PEX_L0_PRSNT_N_PDD0  _GPIO(232)
+#define TEGRA_PIN_PEX_L0_RST_N_PDD1    _GPIO(233)
+#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234)
+#define TEGRA_PIN_PEX_WAKE_N_PDD3      _GPIO(235)
+#define TEGRA_PIN_PEX_L1_PRSNT_N_PDD4  _GPIO(236)
+#define TEGRA_PIN_PEX_L1_RST_N_PDD5    _GPIO(237)
+#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238)
+#define TEGRA_PIN_PEX_L2_PRSNT_N_PDD7  _GPIO(239)
+#define TEGRA_PIN_CLK3_OUT_PEE0                _GPIO(240)
+#define TEGRA_PIN_CLK3_REQ_PEE1                _GPIO(241)
+#define TEGRA_PIN_CLK1_REQ_PEE2                _GPIO(242)
+#define TEGRA_PIN_HDMI_CEC_PEE3                _GPIO(243)
+#define TEGRA_PIN_PEE4                 _GPIO(244)
+#define TEGRA_PIN_PEE5                 _GPIO(245)
+#define TEGRA_PIN_PEE6                 _GPIO(246)
+#define TEGRA_PIN_PEE7                 _GPIO(247)
+
+/* All non-GPIO pins follow */
+#define NUM_GPIOS                      (TEGRA_PIN_PEE7 + 1)
+#define _PIN(offset)                   (NUM_GPIOS + (offset))
+
+/* Non-GPIO pins */
+#define TEGRA_PIN_CLK_32K_IN           _PIN(0)
+#define TEGRA_PIN_CORE_PWR_REQ         _PIN(1)
+#define TEGRA_PIN_CPU_PWR_REQ          _PIN(2)
+#define TEGRA_PIN_JTAG_TCK             _PIN(3)
+#define TEGRA_PIN_JTAG_TDI             _PIN(4)
+#define TEGRA_PIN_JTAG_TDO             _PIN(5)
+#define TEGRA_PIN_JTAG_TMS             _PIN(6)
+#define TEGRA_PIN_JTAG_TRST_N          _PIN(7)
+#define TEGRA_PIN_OWR                  _PIN(8)
+#define TEGRA_PIN_PWR_INT_N            _PIN(9)
+#define TEGRA_PIN_SYS_RESET_N          _PIN(10)
+#define TEGRA_PIN_TEST_MODE_EN         _PIN(11)
+
+static const struct pinctrl_pin_desc tegra30_pins[] = {
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"),
+       PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT5_PD0, "SDMMC3_DAT5 PD0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT4_PD1, "SDMMC3_DAT4 PD1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PD2, "LCD_DC1 PD2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT6_PD3, "SDMMC3_DAT6 PD3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT7_PD4, "SDMMC3_DAT7 PD4"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"),
+       PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"),
+       PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_DQS_PI2, "GMI_DQS PI2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"),
+       PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"),
+       PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"),
+       PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"),
+       PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"),
+       PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"),
+       PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"),
+       PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"),
+       PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VI_D10 PT2"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"),
+       PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"),
+       PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"),
+       PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"),
+       PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"),
+       PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"),
+       PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"),
+       PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"),
+       PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"),
+       PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"),
+       PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"),
+       PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"),
+       PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"),
+       PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"),
+       PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"),
+       PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"),
+       PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC_PV6, "CRT_HSYNC PV6"),
+       PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC_PV7, "CRT_VSYNC PV7"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"),
+       PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"),
+       PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"),
+       PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"),
+       PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"),
+       PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"),
+       PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"),
+       PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"),
+       PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"),
+       PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"),
+       PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"),
+       PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"),
+       PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"),
+       PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"),
+       PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"),
+       PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"),
+       PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"),
+       PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_RST_N_PCC3, "SDMMC4_RST_N PCC3"),
+       PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"),
+       PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PCC6, "PEX_L2_RST_N PCC6"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, "PEX_L2_CLKREQ_N PCC7"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, "PEX_L0_PRSNT_N PDD0"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, "PEX_L1_PRSNT_N PDD4"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"),
+       PINCTRL_PIN(TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, "PEX_L2_PRSNT_N PDD7"),
+       PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"),
+       PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"),
+       PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"),
+       PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"),
+       PINCTRL_PIN(TEGRA_PIN_PEE4, "PEE4"),
+       PINCTRL_PIN(TEGRA_PIN_PEE5, "PEE5"),
+       PINCTRL_PIN(TEGRA_PIN_PEE6, "PEE6"),
+       PINCTRL_PIN(TEGRA_PIN_PEE7, "PEE7"),
+       PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"),
+       PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"),
+       PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"),
+       PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"),
+       PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"),
+       PINCTRL_PIN(TEGRA_PIN_SYS_RESET_N, "SYS_RESET_N"),
+       PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"),
+};
+
+static const unsigned clk_32k_out_pa0_pins[] = {
+       TEGRA_PIN_CLK_32K_OUT_PA0,
+};
+
+static const unsigned uart3_cts_n_pa1_pins[] = {
+       TEGRA_PIN_UART3_CTS_N_PA1,
+};
+
+static const unsigned dap2_fs_pa2_pins[] = {
+       TEGRA_PIN_DAP2_FS_PA2,
+};
+
+static const unsigned dap2_sclk_pa3_pins[] = {
+       TEGRA_PIN_DAP2_SCLK_PA3,
+};
+
+static const unsigned dap2_din_pa4_pins[] = {
+       TEGRA_PIN_DAP2_DIN_PA4,
+};
+
+static const unsigned dap2_dout_pa5_pins[] = {
+       TEGRA_PIN_DAP2_DOUT_PA5,
+};
+
+static const unsigned sdmmc3_clk_pa6_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PA6,
+};
+
+static const unsigned sdmmc3_cmd_pa7_pins[] = {
+       TEGRA_PIN_SDMMC3_CMD_PA7,
+};
+
+static const unsigned gmi_a17_pb0_pins[] = {
+       TEGRA_PIN_GMI_A17_PB0,
+};
+
+static const unsigned gmi_a18_pb1_pins[] = {
+       TEGRA_PIN_GMI_A18_PB1,
+};
+
+static const unsigned lcd_pwr0_pb2_pins[] = {
+       TEGRA_PIN_LCD_PWR0_PB2,
+};
+
+static const unsigned lcd_pclk_pb3_pins[] = {
+       TEGRA_PIN_LCD_PCLK_PB3,
+};
+
+static const unsigned sdmmc3_dat3_pb4_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT3_PB4,
+};
+
+static const unsigned sdmmc3_dat2_pb5_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT2_PB5,
+};
+
+static const unsigned sdmmc3_dat1_pb6_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT1_PB6,
+};
+
+static const unsigned sdmmc3_dat0_pb7_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT0_PB7,
+};
+
+static const unsigned uart3_rts_n_pc0_pins[] = {
+       TEGRA_PIN_UART3_RTS_N_PC0,
+};
+
+static const unsigned lcd_pwr1_pc1_pins[] = {
+       TEGRA_PIN_LCD_PWR1_PC1,
+};
+
+static const unsigned uart2_txd_pc2_pins[] = {
+       TEGRA_PIN_UART2_TXD_PC2,
+};
+
+static const unsigned uart2_rxd_pc3_pins[] = {
+       TEGRA_PIN_UART2_RXD_PC3,
+};
+
+static const unsigned gen1_i2c_scl_pc4_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PC4,
+};
+
+static const unsigned gen1_i2c_sda_pc5_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SDA_PC5,
+};
+
+static const unsigned lcd_pwr2_pc6_pins[] = {
+       TEGRA_PIN_LCD_PWR2_PC6,
+};
+
+static const unsigned gmi_wp_n_pc7_pins[] = {
+       TEGRA_PIN_GMI_WP_N_PC7,
+};
+
+static const unsigned sdmmc3_dat5_pd0_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT5_PD0,
+};
+
+static const unsigned sdmmc3_dat4_pd1_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT4_PD1,
+};
+
+static const unsigned lcd_dc1_pd2_pins[] = {
+       TEGRA_PIN_LCD_DC1_PD2,
+};
+
+static const unsigned sdmmc3_dat6_pd3_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT6_PD3,
+};
+
+static const unsigned sdmmc3_dat7_pd4_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT7_PD4,
+};
+
+static const unsigned vi_d1_pd5_pins[] = {
+       TEGRA_PIN_VI_D1_PD5,
+};
+
+static const unsigned vi_vsync_pd6_pins[] = {
+       TEGRA_PIN_VI_VSYNC_PD6,
+};
+
+static const unsigned vi_hsync_pd7_pins[] = {
+       TEGRA_PIN_VI_HSYNC_PD7,
+};
+
+static const unsigned lcd_d0_pe0_pins[] = {
+       TEGRA_PIN_LCD_D0_PE0,
+};
+
+static const unsigned lcd_d1_pe1_pins[] = {
+       TEGRA_PIN_LCD_D1_PE1,
+};
+
+static const unsigned lcd_d2_pe2_pins[] = {
+       TEGRA_PIN_LCD_D2_PE2,
+};
+
+static const unsigned lcd_d3_pe3_pins[] = {
+       TEGRA_PIN_LCD_D3_PE3,
+};
+
+static const unsigned lcd_d4_pe4_pins[] = {
+       TEGRA_PIN_LCD_D4_PE4,
+};
+
+static const unsigned lcd_d5_pe5_pins[] = {
+       TEGRA_PIN_LCD_D5_PE5,
+};
+
+static const unsigned lcd_d6_pe6_pins[] = {
+       TEGRA_PIN_LCD_D6_PE6,
+};
+
+static const unsigned lcd_d7_pe7_pins[] = {
+       TEGRA_PIN_LCD_D7_PE7,
+};
+
+static const unsigned lcd_d8_pf0_pins[] = {
+       TEGRA_PIN_LCD_D8_PF0,
+};
+
+static const unsigned lcd_d9_pf1_pins[] = {
+       TEGRA_PIN_LCD_D9_PF1,
+};
+
+static const unsigned lcd_d10_pf2_pins[] = {
+       TEGRA_PIN_LCD_D10_PF2,
+};
+
+static const unsigned lcd_d11_pf3_pins[] = {
+       TEGRA_PIN_LCD_D11_PF3,
+};
+
+static const unsigned lcd_d12_pf4_pins[] = {
+       TEGRA_PIN_LCD_D12_PF4,
+};
+
+static const unsigned lcd_d13_pf5_pins[] = {
+       TEGRA_PIN_LCD_D13_PF5,
+};
+
+static const unsigned lcd_d14_pf6_pins[] = {
+       TEGRA_PIN_LCD_D14_PF6,
+};
+
+static const unsigned lcd_d15_pf7_pins[] = {
+       TEGRA_PIN_LCD_D15_PF7,
+};
+
+static const unsigned gmi_ad0_pg0_pins[] = {
+       TEGRA_PIN_GMI_AD0_PG0,
+};
+
+static const unsigned gmi_ad1_pg1_pins[] = {
+       TEGRA_PIN_GMI_AD1_PG1,
+};
+
+static const unsigned gmi_ad2_pg2_pins[] = {
+       TEGRA_PIN_GMI_AD2_PG2,
+};
+
+static const unsigned gmi_ad3_pg3_pins[] = {
+       TEGRA_PIN_GMI_AD3_PG3,
+};
+
+static const unsigned gmi_ad4_pg4_pins[] = {
+       TEGRA_PIN_GMI_AD4_PG4,
+};
+
+static const unsigned gmi_ad5_pg5_pins[] = {
+       TEGRA_PIN_GMI_AD5_PG5,
+};
+
+static const unsigned gmi_ad6_pg6_pins[] = {
+       TEGRA_PIN_GMI_AD6_PG6,
+};
+
+static const unsigned gmi_ad7_pg7_pins[] = {
+       TEGRA_PIN_GMI_AD7_PG7,
+};
+
+static const unsigned gmi_ad8_ph0_pins[] = {
+       TEGRA_PIN_GMI_AD8_PH0,
+};
+
+static const unsigned gmi_ad9_ph1_pins[] = {
+       TEGRA_PIN_GMI_AD9_PH1,
+};
+
+static const unsigned gmi_ad10_ph2_pins[] = {
+       TEGRA_PIN_GMI_AD10_PH2,
+};
+
+static const unsigned gmi_ad11_ph3_pins[] = {
+       TEGRA_PIN_GMI_AD11_PH3,
+};
+
+static const unsigned gmi_ad12_ph4_pins[] = {
+       TEGRA_PIN_GMI_AD12_PH4,
+};
+
+static const unsigned gmi_ad13_ph5_pins[] = {
+       TEGRA_PIN_GMI_AD13_PH5,
+};
+
+static const unsigned gmi_ad14_ph6_pins[] = {
+       TEGRA_PIN_GMI_AD14_PH6,
+};
+
+static const unsigned gmi_ad15_ph7_pins[] = {
+       TEGRA_PIN_GMI_AD15_PH7,
+};
+
+static const unsigned gmi_wr_n_pi0_pins[] = {
+       TEGRA_PIN_GMI_WR_N_PI0,
+};
+
+static const unsigned gmi_oe_n_pi1_pins[] = {
+       TEGRA_PIN_GMI_OE_N_PI1,
+};
+
+static const unsigned gmi_dqs_pi2_pins[] = {
+       TEGRA_PIN_GMI_DQS_PI2,
+};
+
+static const unsigned gmi_cs6_n_pi3_pins[] = {
+       TEGRA_PIN_GMI_CS6_N_PI3,
+};
+
+static const unsigned gmi_rst_n_pi4_pins[] = {
+       TEGRA_PIN_GMI_RST_N_PI4,
+};
+
+static const unsigned gmi_iordy_pi5_pins[] = {
+       TEGRA_PIN_GMI_IORDY_PI5,
+};
+
+static const unsigned gmi_cs7_n_pi6_pins[] = {
+       TEGRA_PIN_GMI_CS7_N_PI6,
+};
+
+static const unsigned gmi_wait_pi7_pins[] = {
+       TEGRA_PIN_GMI_WAIT_PI7,
+};
+
+static const unsigned gmi_cs0_n_pj0_pins[] = {
+       TEGRA_PIN_GMI_CS0_N_PJ0,
+};
+
+static const unsigned lcd_de_pj1_pins[] = {
+       TEGRA_PIN_LCD_DE_PJ1,
+};
+
+static const unsigned gmi_cs1_n_pj2_pins[] = {
+       TEGRA_PIN_GMI_CS1_N_PJ2,
+};
+
+static const unsigned lcd_hsync_pj3_pins[] = {
+       TEGRA_PIN_LCD_HSYNC_PJ3,
+};
+
+static const unsigned lcd_vsync_pj4_pins[] = {
+       TEGRA_PIN_LCD_VSYNC_PJ4,
+};
+
+static const unsigned uart2_cts_n_pj5_pins[] = {
+       TEGRA_PIN_UART2_CTS_N_PJ5,
+};
+
+static const unsigned uart2_rts_n_pj6_pins[] = {
+       TEGRA_PIN_UART2_RTS_N_PJ6,
+};
+
+static const unsigned gmi_a16_pj7_pins[] = {
+       TEGRA_PIN_GMI_A16_PJ7,
+};
+
+static const unsigned gmi_adv_n_pk0_pins[] = {
+       TEGRA_PIN_GMI_ADV_N_PK0,
+};
+
+static const unsigned gmi_clk_pk1_pins[] = {
+       TEGRA_PIN_GMI_CLK_PK1,
+};
+
+static const unsigned gmi_cs4_n_pk2_pins[] = {
+       TEGRA_PIN_GMI_CS4_N_PK2,
+};
+
+static const unsigned gmi_cs2_n_pk3_pins[] = {
+       TEGRA_PIN_GMI_CS2_N_PK3,
+};
+
+static const unsigned gmi_cs3_n_pk4_pins[] = {
+       TEGRA_PIN_GMI_CS3_N_PK4,
+};
+
+static const unsigned spdif_out_pk5_pins[] = {
+       TEGRA_PIN_SPDIF_OUT_PK5,
+};
+
+static const unsigned spdif_in_pk6_pins[] = {
+       TEGRA_PIN_SPDIF_IN_PK6,
+};
+
+static const unsigned gmi_a19_pk7_pins[] = {
+       TEGRA_PIN_GMI_A19_PK7,
+};
+
+static const unsigned vi_d2_pl0_pins[] = {
+       TEGRA_PIN_VI_D2_PL0,
+};
+
+static const unsigned vi_d3_pl1_pins[] = {
+       TEGRA_PIN_VI_D3_PL1,
+};
+
+static const unsigned vi_d4_pl2_pins[] = {
+       TEGRA_PIN_VI_D4_PL2,
+};
+
+static const unsigned vi_d5_pl3_pins[] = {
+       TEGRA_PIN_VI_D5_PL3,
+};
+
+static const unsigned vi_d6_pl4_pins[] = {
+       TEGRA_PIN_VI_D6_PL4,
+};
+
+static const unsigned vi_d7_pl5_pins[] = {
+       TEGRA_PIN_VI_D7_PL5,
+};
+
+static const unsigned vi_d8_pl6_pins[] = {
+       TEGRA_PIN_VI_D8_PL6,
+};
+
+static const unsigned vi_d9_pl7_pins[] = {
+       TEGRA_PIN_VI_D9_PL7,
+};
+
+static const unsigned lcd_d16_pm0_pins[] = {
+       TEGRA_PIN_LCD_D16_PM0,
+};
+
+static const unsigned lcd_d17_pm1_pins[] = {
+       TEGRA_PIN_LCD_D17_PM1,
+};
+
+static const unsigned lcd_d18_pm2_pins[] = {
+       TEGRA_PIN_LCD_D18_PM2,
+};
+
+static const unsigned lcd_d19_pm3_pins[] = {
+       TEGRA_PIN_LCD_D19_PM3,
+};
+
+static const unsigned lcd_d20_pm4_pins[] = {
+       TEGRA_PIN_LCD_D20_PM4,
+};
+
+static const unsigned lcd_d21_pm5_pins[] = {
+       TEGRA_PIN_LCD_D21_PM5,
+};
+
+static const unsigned lcd_d22_pm6_pins[] = {
+       TEGRA_PIN_LCD_D22_PM6,
+};
+
+static const unsigned lcd_d23_pm7_pins[] = {
+       TEGRA_PIN_LCD_D23_PM7,
+};
+
+static const unsigned dap1_fs_pn0_pins[] = {
+       TEGRA_PIN_DAP1_FS_PN0,
+};
+
+static const unsigned dap1_din_pn1_pins[] = {
+       TEGRA_PIN_DAP1_DIN_PN1,
+};
+
+static const unsigned dap1_dout_pn2_pins[] = {
+       TEGRA_PIN_DAP1_DOUT_PN2,
+};
+
+static const unsigned dap1_sclk_pn3_pins[] = {
+       TEGRA_PIN_DAP1_SCLK_PN3,
+};
+
+static const unsigned lcd_cs0_n_pn4_pins[] = {
+       TEGRA_PIN_LCD_CS0_N_PN4,
+};
+
+static const unsigned lcd_sdout_pn5_pins[] = {
+       TEGRA_PIN_LCD_SDOUT_PN5,
+};
+
+static const unsigned lcd_dc0_pn6_pins[] = {
+       TEGRA_PIN_LCD_DC0_PN6,
+};
+
+static const unsigned hdmi_int_pn7_pins[] = {
+       TEGRA_PIN_HDMI_INT_PN7,
+};
+
+static const unsigned ulpi_data7_po0_pins[] = {
+       TEGRA_PIN_ULPI_DATA7_PO0,
+};
+
+static const unsigned ulpi_data0_po1_pins[] = {
+       TEGRA_PIN_ULPI_DATA0_PO1,
+};
+
+static const unsigned ulpi_data1_po2_pins[] = {
+       TEGRA_PIN_ULPI_DATA1_PO2,
+};
+
+static const unsigned ulpi_data2_po3_pins[] = {
+       TEGRA_PIN_ULPI_DATA2_PO3,
+};
+
+static const unsigned ulpi_data3_po4_pins[] = {
+       TEGRA_PIN_ULPI_DATA3_PO4,
+};
+
+static const unsigned ulpi_data4_po5_pins[] = {
+       TEGRA_PIN_ULPI_DATA4_PO5,
+};
+
+static const unsigned ulpi_data5_po6_pins[] = {
+       TEGRA_PIN_ULPI_DATA5_PO6,
+};
+
+static const unsigned ulpi_data6_po7_pins[] = {
+       TEGRA_PIN_ULPI_DATA6_PO7,
+};
+
+static const unsigned dap3_fs_pp0_pins[] = {
+       TEGRA_PIN_DAP3_FS_PP0,
+};
+
+static const unsigned dap3_din_pp1_pins[] = {
+       TEGRA_PIN_DAP3_DIN_PP1,
+};
+
+static const unsigned dap3_dout_pp2_pins[] = {
+       TEGRA_PIN_DAP3_DOUT_PP2,
+};
+
+static const unsigned dap3_sclk_pp3_pins[] = {
+       TEGRA_PIN_DAP3_SCLK_PP3,
+};
+
+static const unsigned dap4_fs_pp4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PP4,
+};
+
+static const unsigned dap4_din_pp5_pins[] = {
+       TEGRA_PIN_DAP4_DIN_PP5,
+};
+
+static const unsigned dap4_dout_pp6_pins[] = {
+       TEGRA_PIN_DAP4_DOUT_PP6,
+};
+
+static const unsigned dap4_sclk_pp7_pins[] = {
+       TEGRA_PIN_DAP4_SCLK_PP7,
+};
+
+static const unsigned kb_col0_pq0_pins[] = {
+       TEGRA_PIN_KB_COL0_PQ0,
+};
+
+static const unsigned kb_col1_pq1_pins[] = {
+       TEGRA_PIN_KB_COL1_PQ1,
+};
+
+static const unsigned kb_col2_pq2_pins[] = {
+       TEGRA_PIN_KB_COL2_PQ2,
+};
+
+static const unsigned kb_col3_pq3_pins[] = {
+       TEGRA_PIN_KB_COL3_PQ3,
+};
+
+static const unsigned kb_col4_pq4_pins[] = {
+       TEGRA_PIN_KB_COL4_PQ4,
+};
+
+static const unsigned kb_col5_pq5_pins[] = {
+       TEGRA_PIN_KB_COL5_PQ5,
+};
+
+static const unsigned kb_col6_pq6_pins[] = {
+       TEGRA_PIN_KB_COL6_PQ6,
+};
+
+static const unsigned kb_col7_pq7_pins[] = {
+       TEGRA_PIN_KB_COL7_PQ7,
+};
+
+static const unsigned kb_row0_pr0_pins[] = {
+       TEGRA_PIN_KB_ROW0_PR0,
+};
+
+static const unsigned kb_row1_pr1_pins[] = {
+       TEGRA_PIN_KB_ROW1_PR1,
+};
+
+static const unsigned kb_row2_pr2_pins[] = {
+       TEGRA_PIN_KB_ROW2_PR2,
+};
+
+static const unsigned kb_row3_pr3_pins[] = {
+       TEGRA_PIN_KB_ROW3_PR3,
+};
+
+static const unsigned kb_row4_pr4_pins[] = {
+       TEGRA_PIN_KB_ROW4_PR4,
+};
+
+static const unsigned kb_row5_pr5_pins[] = {
+       TEGRA_PIN_KB_ROW5_PR5,
+};
+
+static const unsigned kb_row6_pr6_pins[] = {
+       TEGRA_PIN_KB_ROW6_PR6,
+};
+
+static const unsigned kb_row7_pr7_pins[] = {
+       TEGRA_PIN_KB_ROW7_PR7,
+};
+
+static const unsigned kb_row8_ps0_pins[] = {
+       TEGRA_PIN_KB_ROW8_PS0,
+};
+
+static const unsigned kb_row9_ps1_pins[] = {
+       TEGRA_PIN_KB_ROW9_PS1,
+};
+
+static const unsigned kb_row10_ps2_pins[] = {
+       TEGRA_PIN_KB_ROW10_PS2,
+};
+
+static const unsigned kb_row11_ps3_pins[] = {
+       TEGRA_PIN_KB_ROW11_PS3,
+};
+
+static const unsigned kb_row12_ps4_pins[] = {
+       TEGRA_PIN_KB_ROW12_PS4,
+};
+
+static const unsigned kb_row13_ps5_pins[] = {
+       TEGRA_PIN_KB_ROW13_PS5,
+};
+
+static const unsigned kb_row14_ps6_pins[] = {
+       TEGRA_PIN_KB_ROW14_PS6,
+};
+
+static const unsigned kb_row15_ps7_pins[] = {
+       TEGRA_PIN_KB_ROW15_PS7,
+};
+
+static const unsigned vi_pclk_pt0_pins[] = {
+       TEGRA_PIN_VI_PCLK_PT0,
+};
+
+static const unsigned vi_mclk_pt1_pins[] = {
+       TEGRA_PIN_VI_MCLK_PT1,
+};
+
+static const unsigned vi_d10_pt2_pins[] = {
+       TEGRA_PIN_VI_D10_PT2,
+};
+
+static const unsigned vi_d11_pt3_pins[] = {
+       TEGRA_PIN_VI_D11_PT3,
+};
+
+static const unsigned vi_d0_pt4_pins[] = {
+       TEGRA_PIN_VI_D0_PT4,
+};
+
+static const unsigned gen2_i2c_scl_pt5_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PT5,
+};
+
+static const unsigned gen2_i2c_sda_pt6_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SDA_PT6,
+};
+
+static const unsigned sdmmc4_cmd_pt7_pins[] = {
+       TEGRA_PIN_SDMMC4_CMD_PT7,
+};
+
+static const unsigned pu0_pins[] = {
+       TEGRA_PIN_PU0,
+};
+
+static const unsigned pu1_pins[] = {
+       TEGRA_PIN_PU1,
+};
+
+static const unsigned pu2_pins[] = {
+       TEGRA_PIN_PU2,
+};
+
+static const unsigned pu3_pins[] = {
+       TEGRA_PIN_PU3,
+};
+
+static const unsigned pu4_pins[] = {
+       TEGRA_PIN_PU4,
+};
+
+static const unsigned pu5_pins[] = {
+       TEGRA_PIN_PU5,
+};
+
+static const unsigned pu6_pins[] = {
+       TEGRA_PIN_PU6,
+};
+
+static const unsigned jtag_rtck_pu7_pins[] = {
+       TEGRA_PIN_JTAG_RTCK_PU7,
+};
+
+static const unsigned pv0_pins[] = {
+       TEGRA_PIN_PV0,
+};
+
+static const unsigned pv1_pins[] = {
+       TEGRA_PIN_PV1,
+};
+
+static const unsigned pv2_pins[] = {
+       TEGRA_PIN_PV2,
+};
+
+static const unsigned pv3_pins[] = {
+       TEGRA_PIN_PV3,
+};
+
+static const unsigned ddc_scl_pv4_pins[] = {
+       TEGRA_PIN_DDC_SCL_PV4,
+};
+
+static const unsigned ddc_sda_pv5_pins[] = {
+       TEGRA_PIN_DDC_SDA_PV5,
+};
+
+static const unsigned crt_hsync_pv6_pins[] = {
+       TEGRA_PIN_CRT_HSYNC_PV6,
+};
+
+static const unsigned crt_vsync_pv7_pins[] = {
+       TEGRA_PIN_CRT_VSYNC_PV7,
+};
+
+static const unsigned lcd_cs1_n_pw0_pins[] = {
+       TEGRA_PIN_LCD_CS1_N_PW0,
+};
+
+static const unsigned lcd_m1_pw1_pins[] = {
+       TEGRA_PIN_LCD_M1_PW1,
+};
+
+static const unsigned spi2_cs1_n_pw2_pins[] = {
+       TEGRA_PIN_SPI2_CS1_N_PW2,
+};
+
+static const unsigned spi2_cs2_n_pw3_pins[] = {
+       TEGRA_PIN_SPI2_CS2_N_PW3,
+};
+
+static const unsigned clk1_out_pw4_pins[] = {
+       TEGRA_PIN_CLK1_OUT_PW4,
+};
+
+static const unsigned clk2_out_pw5_pins[] = {
+       TEGRA_PIN_CLK2_OUT_PW5,
+};
+
+static const unsigned uart3_txd_pw6_pins[] = {
+       TEGRA_PIN_UART3_TXD_PW6,
+};
+
+static const unsigned uart3_rxd_pw7_pins[] = {
+       TEGRA_PIN_UART3_RXD_PW7,
+};
+
+static const unsigned spi2_mosi_px0_pins[] = {
+       TEGRA_PIN_SPI2_MOSI_PX0,
+};
+
+static const unsigned spi2_miso_px1_pins[] = {
+       TEGRA_PIN_SPI2_MISO_PX1,
+};
+
+static const unsigned spi2_sck_px2_pins[] = {
+       TEGRA_PIN_SPI2_SCK_PX2,
+};
+
+static const unsigned spi2_cs0_n_px3_pins[] = {
+       TEGRA_PIN_SPI2_CS0_N_PX3,
+};
+
+static const unsigned spi1_mosi_px4_pins[] = {
+       TEGRA_PIN_SPI1_MOSI_PX4,
+};
+
+static const unsigned spi1_sck_px5_pins[] = {
+       TEGRA_PIN_SPI1_SCK_PX5,
+};
+
+static const unsigned spi1_cs0_n_px6_pins[] = {
+       TEGRA_PIN_SPI1_CS0_N_PX6,
+};
+
+static const unsigned spi1_miso_px7_pins[] = {
+       TEGRA_PIN_SPI1_MISO_PX7,
+};
+
+static const unsigned ulpi_clk_py0_pins[] = {
+       TEGRA_PIN_ULPI_CLK_PY0,
+};
+
+static const unsigned ulpi_dir_py1_pins[] = {
+       TEGRA_PIN_ULPI_DIR_PY1,
+};
+
+static const unsigned ulpi_nxt_py2_pins[] = {
+       TEGRA_PIN_ULPI_NXT_PY2,
+};
+
+static const unsigned ulpi_stp_py3_pins[] = {
+       TEGRA_PIN_ULPI_STP_PY3,
+};
+
+static const unsigned sdmmc1_dat3_py4_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT3_PY4,
+};
+
+static const unsigned sdmmc1_dat2_py5_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT2_PY5,
+};
+
+static const unsigned sdmmc1_dat1_py6_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT1_PY6,
+};
+
+static const unsigned sdmmc1_dat0_py7_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT0_PY7,
+};
+
+static const unsigned sdmmc1_clk_pz0_pins[] = {
+       TEGRA_PIN_SDMMC1_CLK_PZ0,
+};
+
+static const unsigned sdmmc1_cmd_pz1_pins[] = {
+       TEGRA_PIN_SDMMC1_CMD_PZ1,
+};
+
+static const unsigned lcd_sdin_pz2_pins[] = {
+       TEGRA_PIN_LCD_SDIN_PZ2,
+};
+
+static const unsigned lcd_wr_n_pz3_pins[] = {
+       TEGRA_PIN_LCD_WR_N_PZ3,
+};
+
+static const unsigned lcd_sck_pz4_pins[] = {
+       TEGRA_PIN_LCD_SCK_PZ4,
+};
+
+static const unsigned sys_clk_req_pz5_pins[] = {
+       TEGRA_PIN_SYS_CLK_REQ_PZ5,
+};
+
+static const unsigned pwr_i2c_scl_pz6_pins[] = {
+       TEGRA_PIN_PWR_I2C_SCL_PZ6,
+};
+
+static const unsigned pwr_i2c_sda_pz7_pins[] = {
+       TEGRA_PIN_PWR_I2C_SDA_PZ7,
+};
+
+static const unsigned sdmmc4_dat0_paa0_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT0_PAA0,
+};
+
+static const unsigned sdmmc4_dat1_paa1_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT1_PAA1,
+};
+
+static const unsigned sdmmc4_dat2_paa2_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT2_PAA2,
+};
+
+static const unsigned sdmmc4_dat3_paa3_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT3_PAA3,
+};
+
+static const unsigned sdmmc4_dat4_paa4_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT4_PAA4,
+};
+
+static const unsigned sdmmc4_dat5_paa5_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT5_PAA5,
+};
+
+static const unsigned sdmmc4_dat6_paa6_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT6_PAA6,
+};
+
+static const unsigned sdmmc4_dat7_paa7_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT7_PAA7,
+};
+
+static const unsigned pbb0_pins[] = {
+       TEGRA_PIN_PBB0,
+};
+
+static const unsigned cam_i2c_scl_pbb1_pins[] = {
+       TEGRA_PIN_CAM_I2C_SCL_PBB1,
+};
+
+static const unsigned cam_i2c_sda_pbb2_pins[] = {
+       TEGRA_PIN_CAM_I2C_SDA_PBB2,
+};
+
+static const unsigned pbb3_pins[] = {
+       TEGRA_PIN_PBB3,
+};
+
+static const unsigned pbb4_pins[] = {
+       TEGRA_PIN_PBB4,
+};
+
+static const unsigned pbb5_pins[] = {
+       TEGRA_PIN_PBB5,
+};
+
+static const unsigned pbb6_pins[] = {
+       TEGRA_PIN_PBB6,
+};
+
+static const unsigned pbb7_pins[] = {
+       TEGRA_PIN_PBB7,
+};
+
+static const unsigned cam_mclk_pcc0_pins[] = {
+       TEGRA_PIN_CAM_MCLK_PCC0,
+};
+
+static const unsigned pcc1_pins[] = {
+       TEGRA_PIN_PCC1,
+};
+
+static const unsigned pcc2_pins[] = {
+       TEGRA_PIN_PCC2,
+};
+
+static const unsigned sdmmc4_rst_n_pcc3_pins[] = {
+       TEGRA_PIN_SDMMC4_RST_N_PCC3,
+};
+
+static const unsigned sdmmc4_clk_pcc4_pins[] = {
+       TEGRA_PIN_SDMMC4_CLK_PCC4,
+};
+
+static const unsigned clk2_req_pcc5_pins[] = {
+       TEGRA_PIN_CLK2_REQ_PCC5,
+};
+
+static const unsigned pex_l2_rst_n_pcc6_pins[] = {
+       TEGRA_PIN_PEX_L2_RST_N_PCC6,
+};
+
+static const unsigned pex_l2_clkreq_n_pcc7_pins[] = {
+       TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7,
+};
+
+static const unsigned pex_l0_prsnt_n_pdd0_pins[] = {
+       TEGRA_PIN_PEX_L0_PRSNT_N_PDD0,
+};
+
+static const unsigned pex_l0_rst_n_pdd1_pins[] = {
+       TEGRA_PIN_PEX_L0_RST_N_PDD1,
+};
+
+static const unsigned pex_l0_clkreq_n_pdd2_pins[] = {
+       TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2,
+};
+
+static const unsigned pex_wake_n_pdd3_pins[] = {
+       TEGRA_PIN_PEX_WAKE_N_PDD3,
+};
+
+static const unsigned pex_l1_prsnt_n_pdd4_pins[] = {
+       TEGRA_PIN_PEX_L1_PRSNT_N_PDD4,
+};
+
+static const unsigned pex_l1_rst_n_pdd5_pins[] = {
+       TEGRA_PIN_PEX_L1_RST_N_PDD5,
+};
+
+static const unsigned pex_l1_clkreq_n_pdd6_pins[] = {
+       TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6,
+};
+
+static const unsigned pex_l2_prsnt_n_pdd7_pins[] = {
+       TEGRA_PIN_PEX_L2_PRSNT_N_PDD7,
+};
+
+static const unsigned clk3_out_pee0_pins[] = {
+       TEGRA_PIN_CLK3_OUT_PEE0,
+};
+
+static const unsigned clk3_req_pee1_pins[] = {
+       TEGRA_PIN_CLK3_REQ_PEE1,
+};
+
+static const unsigned clk1_req_pee2_pins[] = {
+       TEGRA_PIN_CLK1_REQ_PEE2,
+};
+
+static const unsigned hdmi_cec_pee3_pins[] = {
+       TEGRA_PIN_HDMI_CEC_PEE3,
+};
+
+static const unsigned clk_32k_in_pins[] = {
+       TEGRA_PIN_CLK_32K_IN,
+};
+
+static const unsigned core_pwr_req_pins[] = {
+       TEGRA_PIN_CORE_PWR_REQ,
+};
+
+static const unsigned cpu_pwr_req_pins[] = {
+       TEGRA_PIN_CPU_PWR_REQ,
+};
+
+static const unsigned owr_pins[] = {
+       TEGRA_PIN_OWR,
+};
+
+static const unsigned pwr_int_n_pins[] = {
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned drive_ao1_pins[] = {
+       TEGRA_PIN_KB_ROW0_PR0,
+       TEGRA_PIN_KB_ROW1_PR1,
+       TEGRA_PIN_KB_ROW2_PR2,
+       TEGRA_PIN_KB_ROW3_PR3,
+       TEGRA_PIN_KB_ROW4_PR4,
+       TEGRA_PIN_KB_ROW5_PR5,
+       TEGRA_PIN_KB_ROW6_PR6,
+       TEGRA_PIN_KB_ROW7_PR7,
+       TEGRA_PIN_PWR_I2C_SCL_PZ6,
+       TEGRA_PIN_PWR_I2C_SDA_PZ7,
+       TEGRA_PIN_SYS_RESET_N,
+};
+
+static const unsigned drive_ao2_pins[] = {
+       TEGRA_PIN_CLK_32K_OUT_PA0,
+       TEGRA_PIN_KB_COL0_PQ0,
+       TEGRA_PIN_KB_COL1_PQ1,
+       TEGRA_PIN_KB_COL2_PQ2,
+       TEGRA_PIN_KB_COL3_PQ3,
+       TEGRA_PIN_KB_COL4_PQ4,
+       TEGRA_PIN_KB_COL5_PQ5,
+       TEGRA_PIN_KB_COL6_PQ6,
+       TEGRA_PIN_KB_COL7_PQ7,
+       TEGRA_PIN_KB_ROW8_PS0,
+       TEGRA_PIN_KB_ROW9_PS1,
+       TEGRA_PIN_KB_ROW10_PS2,
+       TEGRA_PIN_KB_ROW11_PS3,
+       TEGRA_PIN_KB_ROW12_PS4,
+       TEGRA_PIN_KB_ROW13_PS5,
+       TEGRA_PIN_KB_ROW14_PS6,
+       TEGRA_PIN_KB_ROW15_PS7,
+       TEGRA_PIN_SYS_CLK_REQ_PZ5,
+       TEGRA_PIN_CLK_32K_IN,
+       TEGRA_PIN_CORE_PWR_REQ,
+       TEGRA_PIN_CPU_PWR_REQ,
+       TEGRA_PIN_PWR_INT_N,
+};
+
+static const unsigned drive_at1_pins[] = {
+       TEGRA_PIN_GMI_AD8_PH0,
+       TEGRA_PIN_GMI_AD9_PH1,
+       TEGRA_PIN_GMI_AD10_PH2,
+       TEGRA_PIN_GMI_AD11_PH3,
+       TEGRA_PIN_GMI_AD12_PH4,
+       TEGRA_PIN_GMI_AD13_PH5,
+       TEGRA_PIN_GMI_AD14_PH6,
+       TEGRA_PIN_GMI_AD15_PH7,
+       TEGRA_PIN_GMI_IORDY_PI5,
+       TEGRA_PIN_GMI_CS7_N_PI6,
+};
+
+static const unsigned drive_at2_pins[] = {
+       TEGRA_PIN_GMI_AD0_PG0,
+       TEGRA_PIN_GMI_AD1_PG1,
+       TEGRA_PIN_GMI_AD2_PG2,
+       TEGRA_PIN_GMI_AD3_PG3,
+       TEGRA_PIN_GMI_AD4_PG4,
+       TEGRA_PIN_GMI_AD5_PG5,
+       TEGRA_PIN_GMI_AD6_PG6,
+       TEGRA_PIN_GMI_AD7_PG7,
+       TEGRA_PIN_GMI_WR_N_PI0,
+       TEGRA_PIN_GMI_OE_N_PI1,
+       TEGRA_PIN_GMI_DQS_PI2,
+       TEGRA_PIN_GMI_CS6_N_PI3,
+       TEGRA_PIN_GMI_RST_N_PI4,
+       TEGRA_PIN_GMI_WAIT_PI7,
+       TEGRA_PIN_GMI_ADV_N_PK0,
+       TEGRA_PIN_GMI_CLK_PK1,
+       TEGRA_PIN_GMI_CS4_N_PK2,
+       TEGRA_PIN_GMI_CS2_N_PK3,
+       TEGRA_PIN_GMI_CS3_N_PK4,
+};
+
+static const unsigned drive_at3_pins[] = {
+       TEGRA_PIN_GMI_WP_N_PC7,
+       TEGRA_PIN_GMI_CS0_N_PJ0,
+};
+
+static const unsigned drive_at4_pins[] = {
+       TEGRA_PIN_GMI_A17_PB0,
+       TEGRA_PIN_GMI_A18_PB1,
+       TEGRA_PIN_GMI_CS1_N_PJ2,
+       TEGRA_PIN_GMI_A16_PJ7,
+       TEGRA_PIN_GMI_A19_PK7,
+};
+
+static const unsigned drive_at5_pins[] = {
+       TEGRA_PIN_GEN2_I2C_SCL_PT5,
+       TEGRA_PIN_GEN2_I2C_SDA_PT6,
+};
+
+static const unsigned drive_cdev1_pins[] = {
+       TEGRA_PIN_CLK1_OUT_PW4,
+       TEGRA_PIN_CLK1_REQ_PEE2,
+};
+
+static const unsigned drive_cdev2_pins[] = {
+       TEGRA_PIN_CLK2_OUT_PW5,
+       TEGRA_PIN_CLK2_REQ_PCC5,
+};
+
+static const unsigned drive_cec_pins[] = {
+       TEGRA_PIN_HDMI_CEC_PEE3,
+};
+
+static const unsigned drive_crt_pins[] = {
+       TEGRA_PIN_CRT_HSYNC_PV6,
+       TEGRA_PIN_CRT_VSYNC_PV7,
+};
+
+static const unsigned drive_csus_pins[] = {
+       TEGRA_PIN_VI_MCLK_PT1,
+};
+
+static const unsigned drive_dap1_pins[] = {
+       TEGRA_PIN_SPDIF_OUT_PK5,
+       TEGRA_PIN_SPDIF_IN_PK6,
+       TEGRA_PIN_DAP1_FS_PN0,
+       TEGRA_PIN_DAP1_DIN_PN1,
+       TEGRA_PIN_DAP1_DOUT_PN2,
+       TEGRA_PIN_DAP1_SCLK_PN3,
+};
+
+static const unsigned drive_dap2_pins[] = {
+       TEGRA_PIN_DAP2_FS_PA2,
+       TEGRA_PIN_DAP2_SCLK_PA3,
+       TEGRA_PIN_DAP2_DIN_PA4,
+       TEGRA_PIN_DAP2_DOUT_PA5,
+};
+
+static const unsigned drive_dap3_pins[] = {
+       TEGRA_PIN_DAP3_FS_PP0,
+       TEGRA_PIN_DAP3_DIN_PP1,
+       TEGRA_PIN_DAP3_DOUT_PP2,
+       TEGRA_PIN_DAP3_SCLK_PP3,
+};
+
+static const unsigned drive_dap4_pins[] = {
+       TEGRA_PIN_DAP4_FS_PP4,
+       TEGRA_PIN_DAP4_DIN_PP5,
+       TEGRA_PIN_DAP4_DOUT_PP6,
+       TEGRA_PIN_DAP4_SCLK_PP7,
+};
+
+static const unsigned drive_dbg_pins[] = {
+       TEGRA_PIN_GEN1_I2C_SCL_PC4,
+       TEGRA_PIN_GEN1_I2C_SDA_PC5,
+       TEGRA_PIN_PU0,
+       TEGRA_PIN_PU1,
+       TEGRA_PIN_PU2,
+       TEGRA_PIN_PU3,
+       TEGRA_PIN_PU4,
+       TEGRA_PIN_PU5,
+       TEGRA_PIN_PU6,
+       TEGRA_PIN_JTAG_RTCK_PU7,
+       TEGRA_PIN_JTAG_TCK,
+       TEGRA_PIN_JTAG_TDI,
+       TEGRA_PIN_JTAG_TDO,
+       TEGRA_PIN_JTAG_TMS,
+       TEGRA_PIN_JTAG_TRST_N,
+       TEGRA_PIN_TEST_MODE_EN,
+};
+
+static const unsigned drive_ddc_pins[] = {
+       TEGRA_PIN_DDC_SCL_PV4,
+       TEGRA_PIN_DDC_SDA_PV5,
+};
+
+static const unsigned drive_dev3_pins[] = {
+       TEGRA_PIN_CLK3_OUT_PEE0,
+       TEGRA_PIN_CLK3_REQ_PEE1,
+};
+
+static const unsigned drive_gma_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT0_PAA0,
+       TEGRA_PIN_SDMMC4_DAT1_PAA1,
+       TEGRA_PIN_SDMMC4_DAT2_PAA2,
+       TEGRA_PIN_SDMMC4_DAT3_PAA3,
+       TEGRA_PIN_SDMMC4_RST_N_PCC3,
+};
+
+static const unsigned drive_gmb_pins[] = {
+       TEGRA_PIN_SDMMC4_DAT4_PAA4,
+       TEGRA_PIN_SDMMC4_DAT5_PAA5,
+       TEGRA_PIN_SDMMC4_DAT6_PAA6,
+       TEGRA_PIN_SDMMC4_DAT7_PAA7,
+};
+
+static const unsigned drive_gmc_pins[] = {
+       TEGRA_PIN_SDMMC4_CLK_PCC4,
+};
+
+static const unsigned drive_gmd_pins[] = {
+       TEGRA_PIN_SDMMC4_CMD_PT7,
+};
+
+static const unsigned drive_gme_pins[] = {
+       TEGRA_PIN_PBB0,
+       TEGRA_PIN_CAM_I2C_SCL_PBB1,
+       TEGRA_PIN_CAM_I2C_SDA_PBB2,
+       TEGRA_PIN_PBB3,
+       TEGRA_PIN_PCC2,
+};
+
+static const unsigned drive_gmf_pins[] = {
+       TEGRA_PIN_PBB4,
+       TEGRA_PIN_PBB5,
+       TEGRA_PIN_PBB6,
+       TEGRA_PIN_PBB7,
+};
+
+static const unsigned drive_gmg_pins[] = {
+       TEGRA_PIN_CAM_MCLK_PCC0,
+};
+
+static const unsigned drive_gmh_pins[] = {
+       TEGRA_PIN_PCC1,
+};
+
+static const unsigned drive_gpv_pins[] = {
+       TEGRA_PIN_PEX_L2_RST_N_PCC6,
+       TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7,
+       TEGRA_PIN_PEX_L0_PRSNT_N_PDD0,
+       TEGRA_PIN_PEX_L0_RST_N_PDD1,
+       TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2,
+       TEGRA_PIN_PEX_WAKE_N_PDD3,
+       TEGRA_PIN_PEX_L1_PRSNT_N_PDD4,
+       TEGRA_PIN_PEX_L1_RST_N_PDD5,
+       TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6,
+       TEGRA_PIN_PEX_L2_PRSNT_N_PDD7,
+};
+
+static const unsigned drive_lcd1_pins[] = {
+       TEGRA_PIN_LCD_PWR1_PC1,
+       TEGRA_PIN_LCD_PWR2_PC6,
+       TEGRA_PIN_LCD_CS0_N_PN4,
+       TEGRA_PIN_LCD_SDOUT_PN5,
+       TEGRA_PIN_LCD_DC0_PN6,
+       TEGRA_PIN_LCD_SDIN_PZ2,
+       TEGRA_PIN_LCD_WR_N_PZ3,
+       TEGRA_PIN_LCD_SCK_PZ4,
+};
+
+static const unsigned drive_lcd2_pins[] = {
+       TEGRA_PIN_LCD_PWR0_PB2,
+       TEGRA_PIN_LCD_PCLK_PB3,
+       TEGRA_PIN_LCD_DC1_PD2,
+       TEGRA_PIN_LCD_D0_PE0,
+       TEGRA_PIN_LCD_D1_PE1,
+       TEGRA_PIN_LCD_D2_PE2,
+       TEGRA_PIN_LCD_D3_PE3,
+       TEGRA_PIN_LCD_D4_PE4,
+       TEGRA_PIN_LCD_D5_PE5,
+       TEGRA_PIN_LCD_D6_PE6,
+       TEGRA_PIN_LCD_D7_PE7,
+       TEGRA_PIN_LCD_D8_PF0,
+       TEGRA_PIN_LCD_D9_PF1,
+       TEGRA_PIN_LCD_D10_PF2,
+       TEGRA_PIN_LCD_D11_PF3,
+       TEGRA_PIN_LCD_D12_PF4,
+       TEGRA_PIN_LCD_D13_PF5,
+       TEGRA_PIN_LCD_D14_PF6,
+       TEGRA_PIN_LCD_D15_PF7,
+       TEGRA_PIN_LCD_DE_PJ1,
+       TEGRA_PIN_LCD_HSYNC_PJ3,
+       TEGRA_PIN_LCD_VSYNC_PJ4,
+       TEGRA_PIN_LCD_D16_PM0,
+       TEGRA_PIN_LCD_D17_PM1,
+       TEGRA_PIN_LCD_D18_PM2,
+       TEGRA_PIN_LCD_D19_PM3,
+       TEGRA_PIN_LCD_D20_PM4,
+       TEGRA_PIN_LCD_D21_PM5,
+       TEGRA_PIN_LCD_D22_PM6,
+       TEGRA_PIN_LCD_D23_PM7,
+       TEGRA_PIN_HDMI_INT_PN7,
+       TEGRA_PIN_LCD_CS1_N_PW0,
+       TEGRA_PIN_LCD_M1_PW1,
+};
+
+static const unsigned drive_owr_pins[] = {
+       TEGRA_PIN_OWR,
+};
+
+static const unsigned drive_sdio1_pins[] = {
+       TEGRA_PIN_SDMMC1_DAT3_PY4,
+       TEGRA_PIN_SDMMC1_DAT2_PY5,
+       TEGRA_PIN_SDMMC1_DAT1_PY6,
+       TEGRA_PIN_SDMMC1_DAT0_PY7,
+       TEGRA_PIN_SDMMC1_CLK_PZ0,
+       TEGRA_PIN_SDMMC1_CMD_PZ1,
+};
+
+static const unsigned drive_sdio2_pins[] = {
+       TEGRA_PIN_SDMMC3_DAT5_PD0,
+       TEGRA_PIN_SDMMC3_DAT4_PD1,
+       TEGRA_PIN_SDMMC3_DAT6_PD3,
+       TEGRA_PIN_SDMMC3_DAT7_PD4,
+};
+
+static const unsigned drive_sdio3_pins[] = {
+       TEGRA_PIN_SDMMC3_CLK_PA6,
+       TEGRA_PIN_SDMMC3_CMD_PA7,
+       TEGRA_PIN_SDMMC3_DAT3_PB4,
+       TEGRA_PIN_SDMMC3_DAT2_PB5,
+       TEGRA_PIN_SDMMC3_DAT1_PB6,
+       TEGRA_PIN_SDMMC3_DAT0_PB7,
+};
+
+static const unsigned drive_spi_pins[] = {
+       TEGRA_PIN_SPI2_CS1_N_PW2,
+       TEGRA_PIN_SPI2_CS2_N_PW3,
+       TEGRA_PIN_SPI2_MOSI_PX0,
+       TEGRA_PIN_SPI2_MISO_PX1,
+       TEGRA_PIN_SPI2_SCK_PX2,
+       TEGRA_PIN_SPI2_CS0_N_PX3,
+       TEGRA_PIN_SPI1_MOSI_PX4,
+       TEGRA_PIN_SPI1_SCK_PX5,
+       TEGRA_PIN_SPI1_CS0_N_PX6,
+       TEGRA_PIN_SPI1_MISO_PX7,
+};
+
+static const unsigned drive_uaa_pins[] = {
+       TEGRA_PIN_ULPI_DATA0_PO1,
+       TEGRA_PIN_ULPI_DATA1_PO2,
+       TEGRA_PIN_ULPI_DATA2_PO3,
+       TEGRA_PIN_ULPI_DATA3_PO4,
+};
+
+static const unsigned drive_uab_pins[] = {
+       TEGRA_PIN_ULPI_DATA7_PO0,
+       TEGRA_PIN_ULPI_DATA4_PO5,
+       TEGRA_PIN_ULPI_DATA5_PO6,
+       TEGRA_PIN_ULPI_DATA6_PO7,
+       TEGRA_PIN_PV0,
+       TEGRA_PIN_PV1,
+       TEGRA_PIN_PV2,
+       TEGRA_PIN_PV3,
+};
+
+static const unsigned drive_uart2_pins[] = {
+       TEGRA_PIN_UART2_TXD_PC2,
+       TEGRA_PIN_UART2_RXD_PC3,
+       TEGRA_PIN_UART2_CTS_N_PJ5,
+       TEGRA_PIN_UART2_RTS_N_PJ6,
+};
+
+static const unsigned drive_uart3_pins[] = {
+       TEGRA_PIN_UART3_CTS_N_PA1,
+       TEGRA_PIN_UART3_RTS_N_PC0,
+       TEGRA_PIN_UART3_TXD_PW6,
+       TEGRA_PIN_UART3_RXD_PW7,
+};
+
+static const unsigned drive_uda_pins[] = {
+       TEGRA_PIN_ULPI_CLK_PY0,
+       TEGRA_PIN_ULPI_DIR_PY1,
+       TEGRA_PIN_ULPI_NXT_PY2,
+       TEGRA_PIN_ULPI_STP_PY3,
+};
+
+static const unsigned drive_vi1_pins[] = {
+       TEGRA_PIN_VI_D1_PD5,
+       TEGRA_PIN_VI_VSYNC_PD6,
+       TEGRA_PIN_VI_HSYNC_PD7,
+       TEGRA_PIN_VI_D2_PL0,
+       TEGRA_PIN_VI_D3_PL1,
+       TEGRA_PIN_VI_D4_PL2,
+       TEGRA_PIN_VI_D5_PL3,
+       TEGRA_PIN_VI_D6_PL4,
+       TEGRA_PIN_VI_D7_PL5,
+       TEGRA_PIN_VI_D8_PL6,
+       TEGRA_PIN_VI_D9_PL7,
+       TEGRA_PIN_VI_PCLK_PT0,
+       TEGRA_PIN_VI_D10_PT2,
+       TEGRA_PIN_VI_D11_PT3,
+       TEGRA_PIN_VI_D0_PT4,
+};
+
+enum tegra_mux {
+       TEGRA_MUX_BLINK,
+       TEGRA_MUX_CEC,
+       TEGRA_MUX_CLK_12M_OUT,
+       TEGRA_MUX_CLK_32K_IN,
+       TEGRA_MUX_CORE_PWR_REQ,
+       TEGRA_MUX_CPU_PWR_REQ,
+       TEGRA_MUX_CRT,
+       TEGRA_MUX_DAP,
+       TEGRA_MUX_DDR,
+       TEGRA_MUX_DEV3,
+       TEGRA_MUX_DISPLAYA,
+       TEGRA_MUX_DISPLAYB,
+       TEGRA_MUX_DTV,
+       TEGRA_MUX_EXTPERIPH1,
+       TEGRA_MUX_EXTPERIPH2,
+       TEGRA_MUX_EXTPERIPH3,
+       TEGRA_MUX_GMI,
+       TEGRA_MUX_GMI_ALT,
+       TEGRA_MUX_HDA,
+       TEGRA_MUX_HDCP,
+       TEGRA_MUX_HDMI,
+       TEGRA_MUX_HSI,
+       TEGRA_MUX_I2C1,
+       TEGRA_MUX_I2C2,
+       TEGRA_MUX_I2C3,
+       TEGRA_MUX_I2C4,
+       TEGRA_MUX_I2CPWR,
+       TEGRA_MUX_I2S0,
+       TEGRA_MUX_I2S1,
+       TEGRA_MUX_I2S2,
+       TEGRA_MUX_I2S3,
+       TEGRA_MUX_I2S4,
+       TEGRA_MUX_INVALID,
+       TEGRA_MUX_KBC,
+       TEGRA_MUX_MIO,
+       TEGRA_MUX_NAND,
+       TEGRA_MUX_NAND_ALT,
+       TEGRA_MUX_OWR,
+       TEGRA_MUX_PCIE,
+       TEGRA_MUX_PWM0,
+       TEGRA_MUX_PWM1,
+       TEGRA_MUX_PWM2,
+       TEGRA_MUX_PWM3,
+       TEGRA_MUX_PWR_INT_N,
+       TEGRA_MUX_RSVD1,
+       TEGRA_MUX_RSVD2,
+       TEGRA_MUX_RSVD3,
+       TEGRA_MUX_RSVD4,
+       TEGRA_MUX_RTCK,
+       TEGRA_MUX_SATA,
+       TEGRA_MUX_SDMMC1,
+       TEGRA_MUX_SDMMC2,
+       TEGRA_MUX_SDMMC3,
+       TEGRA_MUX_SDMMC4,
+       TEGRA_MUX_SPDIF,
+       TEGRA_MUX_SPI1,
+       TEGRA_MUX_SPI2,
+       TEGRA_MUX_SPI2_ALT,
+       TEGRA_MUX_SPI3,
+       TEGRA_MUX_SPI4,
+       TEGRA_MUX_SPI5,
+       TEGRA_MUX_SPI6,
+       TEGRA_MUX_SYSCLK,
+       TEGRA_MUX_TEST,
+       TEGRA_MUX_TRACE,
+       TEGRA_MUX_UARTA,
+       TEGRA_MUX_UARTB,
+       TEGRA_MUX_UARTC,
+       TEGRA_MUX_UARTD,
+       TEGRA_MUX_UARTE,
+       TEGRA_MUX_ULPI,
+       TEGRA_MUX_VGP1,
+       TEGRA_MUX_VGP2,
+       TEGRA_MUX_VGP3,
+       TEGRA_MUX_VGP4,
+       TEGRA_MUX_VGP5,
+       TEGRA_MUX_VGP6,
+       TEGRA_MUX_VI,
+       TEGRA_MUX_VI_ALT1,
+       TEGRA_MUX_VI_ALT2,
+       TEGRA_MUX_VI_ALT3,
+};
+
+#define FUNCTION(fname)                                        \
+       {                                               \
+               .name = #fname,                         \
+       }
+
+static struct tegra_function tegra30_functions[] = {
+       FUNCTION(blink),
+       FUNCTION(cec),
+       FUNCTION(clk_12m_out),
+       FUNCTION(clk_32k_in),
+       FUNCTION(core_pwr_req),
+       FUNCTION(cpu_pwr_req),
+       FUNCTION(crt),
+       FUNCTION(dap),
+       FUNCTION(ddr),
+       FUNCTION(dev3),
+       FUNCTION(displaya),
+       FUNCTION(displayb),
+       FUNCTION(dtv),
+       FUNCTION(extperiph1),
+       FUNCTION(extperiph2),
+       FUNCTION(extperiph3),
+       FUNCTION(gmi),
+       FUNCTION(gmi_alt),
+       FUNCTION(hda),
+       FUNCTION(hdcp),
+       FUNCTION(hdmi),
+       FUNCTION(hsi),
+       FUNCTION(i2c1),
+       FUNCTION(i2c2),
+       FUNCTION(i2c3),
+       FUNCTION(i2c4),
+       FUNCTION(i2cpwr),
+       FUNCTION(i2s0),
+       FUNCTION(i2s1),
+       FUNCTION(i2s2),
+       FUNCTION(i2s3),
+       FUNCTION(i2s4),
+       FUNCTION(invalid),
+       FUNCTION(kbc),
+       FUNCTION(mio),
+       FUNCTION(nand),
+       FUNCTION(nand_alt),
+       FUNCTION(owr),
+       FUNCTION(pcie),
+       FUNCTION(pwm0),
+       FUNCTION(pwm1),
+       FUNCTION(pwm2),
+       FUNCTION(pwm3),
+       FUNCTION(pwr_int_n),
+       FUNCTION(rsvd1),
+       FUNCTION(rsvd2),
+       FUNCTION(rsvd3),
+       FUNCTION(rsvd4),
+       FUNCTION(rtck),
+       FUNCTION(sata),
+       FUNCTION(sdmmc1),
+       FUNCTION(sdmmc2),
+       FUNCTION(sdmmc3),
+       FUNCTION(sdmmc4),
+       FUNCTION(spdif),
+       FUNCTION(spi1),
+       FUNCTION(spi2),
+       FUNCTION(spi2_alt),
+       FUNCTION(spi3),
+       FUNCTION(spi4),
+       FUNCTION(spi5),
+       FUNCTION(spi6),
+       FUNCTION(sysclk),
+       FUNCTION(test),
+       FUNCTION(trace),
+       FUNCTION(uarta),
+       FUNCTION(uartb),
+       FUNCTION(uartc),
+       FUNCTION(uartd),
+       FUNCTION(uarte),
+       FUNCTION(ulpi),
+       FUNCTION(vgp1),
+       FUNCTION(vgp2),
+       FUNCTION(vgp3),
+       FUNCTION(vgp4),
+       FUNCTION(vgp5),
+       FUNCTION(vgp6),
+       FUNCTION(vi),
+       FUNCTION(vi_alt1),
+       FUNCTION(vi_alt2),
+       FUNCTION(vi_alt3),
+};
+
+#define DRV_PINGROUP_REG_A             0x868   /* bank 0 */
+#define PINGROUP_REG_A                 0x3000  /* bank 1 */
+
+#define DRV_PINGROUP_REG(r)            ((r) - DRV_PINGROUP_REG_A)
+#define PINGROUP_REG(r)                        ((r) - PINGROUP_REG_A)
+
+#define PINGROUP_BIT_Y(b)              (b)
+#define PINGROUP_BIT_N(b)              (-1)
+
+#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior)                  \
+       {                                                               \
+               .name = #pg_name,                                       \
+               .pins = pg_name##_pins,                                 \
+               .npins = ARRAY_SIZE(pg_name##_pins),                    \
+               .funcs = {                                              \
+                       TEGRA_MUX_##f0,                                 \
+                       TEGRA_MUX_##f1,                                 \
+                       TEGRA_MUX_##f2,                                 \
+                       TEGRA_MUX_##f3,                                 \
+               },                                                      \
+               .mux_reg = PINGROUP_REG(r),                             \
+               .mux_bank = 1,                                          \
+               .mux_bit = 0,                                           \
+               .pupd_reg = PINGROUP_REG(r),                            \
+               .pupd_bank = 1,                                         \
+               .pupd_bit = 2,                                          \
+               .tri_reg = PINGROUP_REG(r),                             \
+               .tri_bank = 1,                                          \
+               .tri_bit = 4,                                           \
+               .einput_bit = 5,                                        \
+               .odrain_bit = PINGROUP_BIT_##od(6),                     \
+               .lock_bit = 7,                                          \
+               .ioreset_bit = PINGROUP_BIT_##ior(8),                   \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = -1,                                          \
+       }
+
+#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b,    \
+                    drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w,         \
+                    slwf_b, slwf_w)                                    \
+       {                                                               \
+               .name = "drive_" #pg_name,                              \
+               .pins = drive_##pg_name##_pins,                         \
+               .npins = ARRAY_SIZE(drive_##pg_name##_pins),            \
+               .mux_reg = -1,                                          \
+               .pupd_reg = -1,                                         \
+               .tri_reg = -1,                                          \
+               .einput_bit = -1,                                       \
+               .odrain_bit = -1,                                       \
+               .lock_bit = -1,                                         \
+               .ioreset_bit = -1,                                      \
+               .rcv_sel_bit = -1,                                      \
+               .drv_reg = DRV_PINGROUP_REG(r),                         \
+               .drv_bank = 0,                                          \
+               .hsm_bit = hsm_b,                                       \
+               .schmitt_bit = schmitt_b,                               \
+               .lpmd_bit = lpmd_b,                                     \
+               .drvdn_bit = drvdn_b,                                   \
+               .drvdn_width = drvdn_w,                                 \
+               .drvup_bit = drvup_b,                                   \
+               .drvup_width = drvup_w,                                 \
+               .slwr_bit = slwr_b,                                     \
+               .slwr_width = slwr_w,                                   \
+               .slwf_bit = slwf_b,                                     \
+               .slwf_width = slwf_w,                                   \
+               .drvtype_bit = -1,                                      \
+       }
+
+static const struct tegra_pingroup tegra30_groups[] = {
+       /*       pg_name,              f0,           f1,           f2,           f3,           r,      od, ior */
+       PINGROUP(clk_32k_out_pa0,      BLINK,        RSVD2,        RSVD3,        RSVD4,        0x331c, N, N),
+       PINGROUP(uart3_cts_n_pa1,      UARTC,        RSVD2,        GMI,          RSVD4,        0x317c, N, N),
+       PINGROUP(dap2_fs_pa2,          I2S1,         HDA,          RSVD3,        GMI,          0x3358, N, N),
+       PINGROUP(dap2_sclk_pa3,        I2S1,         HDA,          RSVD3,        GMI,          0x3364, N, N),
+       PINGROUP(dap2_din_pa4,         I2S1,         HDA,          RSVD3,        GMI,          0x335c, N, N),
+       PINGROUP(dap2_dout_pa5,        I2S1,         HDA,          RSVD3,        GMI,          0x3360, N, N),
+       PINGROUP(sdmmc3_clk_pa6,       UARTA,        PWM2,         SDMMC3,       SPI3,         0x3390, N, N),
+       PINGROUP(sdmmc3_cmd_pa7,       UARTA,        PWM3,         SDMMC3,       SPI2,         0x3394, N, N),
+       PINGROUP(gmi_a17_pb0,          UARTD,        SPI4,         GMI,          DTV,          0x3234, N, N),
+       PINGROUP(gmi_a18_pb1,          UARTD,        SPI4,         GMI,          DTV,          0x3238, N, N),
+       PINGROUP(lcd_pwr0_pb2,         DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x3090, N, N),
+       PINGROUP(lcd_pclk_pb3,         DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3094, N, N),
+       PINGROUP(sdmmc3_dat3_pb4,      RSVD1,        PWM0,         SDMMC3,       SPI3,         0x33a4, N, N),
+       PINGROUP(sdmmc3_dat2_pb5,      RSVD1,        PWM1,         SDMMC3,       SPI3,         0x33a0, N, N),
+       PINGROUP(sdmmc3_dat1_pb6,      RSVD1,        RSVD2,        SDMMC3,       SPI3,         0x339c, N, N),
+       PINGROUP(sdmmc3_dat0_pb7,      RSVD1,        RSVD2,        SDMMC3,       SPI3,         0x3398, N, N),
+       PINGROUP(uart3_rts_n_pc0,      UARTC,        PWM0,         GMI,          RSVD4,        0x3180, N, N),
+       PINGROUP(lcd_pwr1_pc1,         DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3070, N, N),
+       PINGROUP(uart2_txd_pc2,        UARTB,        SPDIF,        UARTA,        SPI4,         0x3168, N, N),
+       PINGROUP(uart2_rxd_pc3,        UARTB,        SPDIF,        UARTA,        SPI4,         0x3164, N, N),
+       PINGROUP(gen1_i2c_scl_pc4,     I2C1,         RSVD2,        RSVD3,        RSVD4,        0x31a4, Y, N),
+       PINGROUP(gen1_i2c_sda_pc5,     I2C1,         RSVD2,        RSVD3,        RSVD4,        0x31a0, Y, N),
+       PINGROUP(lcd_pwr2_pc6,         DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x3074, N, N),
+       PINGROUP(gmi_wp_n_pc7,         RSVD1,        NAND,         GMI,          GMI_ALT,      0x31c0, N, N),
+       PINGROUP(sdmmc3_dat5_pd0,      PWM0,         SPI4,         SDMMC3,       SPI2,         0x33ac, N, N),
+       PINGROUP(sdmmc3_dat4_pd1,      PWM1,         SPI4,         SDMMC3,       SPI2,         0x33a8, N, N),
+       PINGROUP(lcd_dc1_pd2,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x310c, N, N),
+       PINGROUP(sdmmc3_dat6_pd3,      SPDIF,        SPI4,         SDMMC3,       SPI2,         0x33b0, N, N),
+       PINGROUP(sdmmc3_dat7_pd4,      SPDIF,        SPI4,         SDMMC3,       SPI2,         0x33b4, N, N),
+       PINGROUP(vi_d1_pd5,            DDR,          SDMMC2,       VI,           RSVD4,        0x3128, N, Y),
+       PINGROUP(vi_vsync_pd6,         DDR,          RSVD2,        VI,           RSVD4,        0x315c, N, Y),
+       PINGROUP(vi_hsync_pd7,         DDR,          RSVD2,        VI,           RSVD4,        0x3160, N, Y),
+       PINGROUP(lcd_d0_pe0,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30a4, N, N),
+       PINGROUP(lcd_d1_pe1,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30a8, N, N),
+       PINGROUP(lcd_d2_pe2,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30ac, N, N),
+       PINGROUP(lcd_d3_pe3,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30b0, N, N),
+       PINGROUP(lcd_d4_pe4,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30b4, N, N),
+       PINGROUP(lcd_d5_pe5,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30b8, N, N),
+       PINGROUP(lcd_d6_pe6,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30bc, N, N),
+       PINGROUP(lcd_d7_pe7,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30c0, N, N),
+       PINGROUP(lcd_d8_pf0,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30c4, N, N),
+       PINGROUP(lcd_d9_pf1,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30c8, N, N),
+       PINGROUP(lcd_d10_pf2,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30cc, N, N),
+       PINGROUP(lcd_d11_pf3,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30d0, N, N),
+       PINGROUP(lcd_d12_pf4,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30d4, N, N),
+       PINGROUP(lcd_d13_pf5,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30d8, N, N),
+       PINGROUP(lcd_d14_pf6,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30dc, N, N),
+       PINGROUP(lcd_d15_pf7,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30e0, N, N),
+       PINGROUP(gmi_ad0_pg0,          RSVD1,        NAND,         GMI,          RSVD4,        0x31f0, N, N),
+       PINGROUP(gmi_ad1_pg1,          RSVD1,        NAND,         GMI,          RSVD4,        0x31f4, N, N),
+       PINGROUP(gmi_ad2_pg2,          RSVD1,        NAND,         GMI,          RSVD4,        0x31f8, N, N),
+       PINGROUP(gmi_ad3_pg3,          RSVD1,        NAND,         GMI,          RSVD4,        0x31fc, N, N),
+       PINGROUP(gmi_ad4_pg4,          RSVD1,        NAND,         GMI,          RSVD4,        0x3200, N, N),
+       PINGROUP(gmi_ad5_pg5,          RSVD1,        NAND,         GMI,          RSVD4,        0x3204, N, N),
+       PINGROUP(gmi_ad6_pg6,          RSVD1,        NAND,         GMI,          RSVD4,        0x3208, N, N),
+       PINGROUP(gmi_ad7_pg7,          RSVD1,        NAND,         GMI,          RSVD4,        0x320c, N, N),
+       PINGROUP(gmi_ad8_ph0,          PWM0,         NAND,         GMI,          RSVD4,        0x3210, N, N),
+       PINGROUP(gmi_ad9_ph1,          PWM1,         NAND,         GMI,          RSVD4,        0x3214, N, N),
+       PINGROUP(gmi_ad10_ph2,         PWM2,         NAND,         GMI,          RSVD4,        0x3218, N, N),
+       PINGROUP(gmi_ad11_ph3,         PWM3,         NAND,         GMI,          RSVD4,        0x321c, N, N),
+       PINGROUP(gmi_ad12_ph4,         RSVD1,        NAND,         GMI,          RSVD4,        0x3220, N, N),
+       PINGROUP(gmi_ad13_ph5,         RSVD1,        NAND,         GMI,          RSVD4,        0x3224, N, N),
+       PINGROUP(gmi_ad14_ph6,         RSVD1,        NAND,         GMI,          RSVD4,        0x3228, N, N),
+       PINGROUP(gmi_ad15_ph7,         RSVD1,        NAND,         GMI,          RSVD4,        0x322c, N, N),
+       PINGROUP(gmi_wr_n_pi0,         RSVD1,        NAND,         GMI,          RSVD4,        0x3240, N, N),
+       PINGROUP(gmi_oe_n_pi1,         RSVD1,        NAND,         GMI,          RSVD4,        0x3244, N, N),
+       PINGROUP(gmi_dqs_pi2,          RSVD1,        NAND,         GMI,          RSVD4,        0x3248, N, N),
+       PINGROUP(gmi_cs6_n_pi3,        NAND,         NAND_ALT,     GMI,          SATA,         0x31e8, N, N),
+       PINGROUP(gmi_rst_n_pi4,        NAND,         NAND_ALT,     GMI,          RSVD4,        0x324c, N, N),
+       PINGROUP(gmi_iordy_pi5,        RSVD1,        NAND,         GMI,          RSVD4,        0x31c4, N, N),
+       PINGROUP(gmi_cs7_n_pi6,        NAND,         NAND_ALT,     GMI,          GMI_ALT,      0x31ec, N, N),
+       PINGROUP(gmi_wait_pi7,         RSVD1,        NAND,         GMI,          RSVD4,        0x31c8, N, N),
+       PINGROUP(gmi_cs0_n_pj0,        RSVD1,        NAND,         GMI,          DTV,          0x31d4, N, N),
+       PINGROUP(lcd_de_pj1,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3098, N, N),
+       PINGROUP(gmi_cs1_n_pj2,        RSVD1,        NAND,         GMI,          DTV,          0x31d8, N, N),
+       PINGROUP(lcd_hsync_pj3,        DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x309c, N, N),
+       PINGROUP(lcd_vsync_pj4,        DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30a0, N, N),
+       PINGROUP(uart2_cts_n_pj5,      UARTA,        UARTB,        GMI,          SPI4,         0x3170, N, N),
+       PINGROUP(uart2_rts_n_pj6,      UARTA,        UARTB,        GMI,          SPI4,         0x316c, N, N),
+       PINGROUP(gmi_a16_pj7,          UARTD,        SPI4,         GMI,          GMI_ALT,      0x3230, N, N),
+       PINGROUP(gmi_adv_n_pk0,        RSVD1,        NAND,         GMI,          RSVD4,        0x31cc, N, N),
+       PINGROUP(gmi_clk_pk1,          RSVD1,        NAND,         GMI,          RSVD4,        0x31d0, N, N),
+       PINGROUP(gmi_cs4_n_pk2,        RSVD1,        NAND,         GMI,          RSVD4,        0x31e4, N, N),
+       PINGROUP(gmi_cs2_n_pk3,        RSVD1,        NAND,         GMI,          RSVD4,        0x31dc, N, N),
+       PINGROUP(gmi_cs3_n_pk4,        RSVD1,        NAND,         GMI,          GMI_ALT,      0x31e0, N, N),
+       PINGROUP(spdif_out_pk5,        SPDIF,        RSVD2,        I2C1,         SDMMC2,       0x3354, N, N),
+       PINGROUP(spdif_in_pk6,         SPDIF,        HDA,          I2C1,         SDMMC2,       0x3350, N, N),
+       PINGROUP(gmi_a19_pk7,          UARTD,        SPI4,         GMI,          RSVD4,        0x323c, N, N),
+       PINGROUP(vi_d2_pl0,            DDR,          SDMMC2,       VI,           RSVD4,        0x312c, N, Y),
+       PINGROUP(vi_d3_pl1,            DDR,          SDMMC2,       VI,           RSVD4,        0x3130, N, Y),
+       PINGROUP(vi_d4_pl2,            DDR,          SDMMC2,       VI,           RSVD4,        0x3134, N, Y),
+       PINGROUP(vi_d5_pl3,            DDR,          SDMMC2,       VI,           RSVD4,        0x3138, N, Y),
+       PINGROUP(vi_d6_pl4,            DDR,          SDMMC2,       VI,           RSVD4,        0x313c, N, Y),
+       PINGROUP(vi_d7_pl5,            DDR,          SDMMC2,       VI,           RSVD4,        0x3140, N, Y),
+       PINGROUP(vi_d8_pl6,            DDR,          SDMMC2,       VI,           RSVD4,        0x3144, N, Y),
+       PINGROUP(vi_d9_pl7,            DDR,          SDMMC2,       VI,           RSVD4,        0x3148, N, Y),
+       PINGROUP(lcd_d16_pm0,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30e4, N, N),
+       PINGROUP(lcd_d17_pm1,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30e8, N, N),
+       PINGROUP(lcd_d18_pm2,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30ec, N, N),
+       PINGROUP(lcd_d19_pm3,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30f0, N, N),
+       PINGROUP(lcd_d20_pm4,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30f4, N, N),
+       PINGROUP(lcd_d21_pm5,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30f8, N, N),
+       PINGROUP(lcd_d22_pm6,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x30fc, N, N),
+       PINGROUP(lcd_d23_pm7,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3100, N, N),
+       PINGROUP(dap1_fs_pn0,          I2S0,         HDA,          GMI,          SDMMC2,       0x3338, N, N),
+       PINGROUP(dap1_din_pn1,         I2S0,         HDA,          GMI,          SDMMC2,       0x333c, N, N),
+       PINGROUP(dap1_dout_pn2,        I2S0,         HDA,          GMI,          SDMMC2,       0x3340, N, N),
+       PINGROUP(dap1_sclk_pn3,        I2S0,         HDA,          GMI,          SDMMC2,       0x3344, N, N),
+       PINGROUP(lcd_cs0_n_pn4,        DISPLAYA,     DISPLAYB,     SPI5,         RSVD4,        0x3084, N, N),
+       PINGROUP(lcd_sdout_pn5,        DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x307c, N, N),
+       PINGROUP(lcd_dc0_pn6,          DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3088, N, N),
+       PINGROUP(hdmi_int_pn7,         HDMI,         RSVD2,        RSVD3,        RSVD4,        0x3110, N, N),
+       PINGROUP(ulpi_data7_po0,       SPI2,         HSI,          UARTA,        ULPI,         0x301c, N, N),
+       PINGROUP(ulpi_data0_po1,       SPI3,         HSI,          UARTA,        ULPI,         0x3000, N, N),
+       PINGROUP(ulpi_data1_po2,       SPI3,         HSI,          UARTA,        ULPI,         0x3004, N, N),
+       PINGROUP(ulpi_data2_po3,       SPI3,         HSI,          UARTA,        ULPI,         0x3008, N, N),
+       PINGROUP(ulpi_data3_po4,       SPI3,         HSI,          UARTA,        ULPI,         0x300c, N, N),
+       PINGROUP(ulpi_data4_po5,       SPI2,         HSI,          UARTA,        ULPI,         0x3010, N, N),
+       PINGROUP(ulpi_data5_po6,       SPI2,         HSI,          UARTA,        ULPI,         0x3014, N, N),
+       PINGROUP(ulpi_data6_po7,       SPI2,         HSI,          UARTA,        ULPI,         0x3018, N, N),
+       PINGROUP(dap3_fs_pp0,          I2S2,         RSVD2,        DISPLAYA,     DISPLAYB,     0x3030, N, N),
+       PINGROUP(dap3_din_pp1,         I2S2,         RSVD2,        DISPLAYA,     DISPLAYB,     0x3034, N, N),
+       PINGROUP(dap3_dout_pp2,        I2S2,         RSVD2,        DISPLAYA,     DISPLAYB,     0x3038, N, N),
+       PINGROUP(dap3_sclk_pp3,        I2S2,         RSVD2,        DISPLAYA,     DISPLAYB,     0x303c, N, N),
+       PINGROUP(dap4_fs_pp4,          I2S3,         RSVD2,        GMI,          RSVD4,        0x31a8, N, N),
+       PINGROUP(dap4_din_pp5,         I2S3,         RSVD2,        GMI,          RSVD4,        0x31ac, N, N),
+       PINGROUP(dap4_dout_pp6,        I2S3,         RSVD2,        GMI,          RSVD4,        0x31b0, N, N),
+       PINGROUP(dap4_sclk_pp7,        I2S3,         RSVD2,        GMI,          RSVD4,        0x31b4, N, N),
+       PINGROUP(kb_col0_pq0,          KBC,          NAND,         TRACE,        TEST,         0x32fc, N, N),
+       PINGROUP(kb_col1_pq1,          KBC,          NAND,         TRACE,        TEST,         0x3300, N, N),
+       PINGROUP(kb_col2_pq2,          KBC,          NAND,         TRACE,        RSVD4,        0x3304, N, N),
+       PINGROUP(kb_col3_pq3,          KBC,          NAND,         TRACE,        RSVD4,        0x3308, N, N),
+       PINGROUP(kb_col4_pq4,          KBC,          NAND,         TRACE,        RSVD4,        0x330c, N, N),
+       PINGROUP(kb_col5_pq5,          KBC,          NAND,         TRACE,        RSVD4,        0x3310, N, N),
+       PINGROUP(kb_col6_pq6,          KBC,          NAND,         TRACE,        MIO,          0x3314, N, N),
+       PINGROUP(kb_col7_pq7,          KBC,          NAND,         TRACE,        MIO,          0x3318, N, N),
+       PINGROUP(kb_row0_pr0,          KBC,          NAND,         RSVD3,        RSVD4,        0x32bc, N, N),
+       PINGROUP(kb_row1_pr1,          KBC,          NAND,         RSVD3,        RSVD4,        0x32c0, N, N),
+       PINGROUP(kb_row2_pr2,          KBC,          NAND,         RSVD3,        RSVD4,        0x32c4, N, N),
+       PINGROUP(kb_row3_pr3,          KBC,          NAND,         RSVD3,        INVALID,      0x32c8, N, N),
+       PINGROUP(kb_row4_pr4,          KBC,          NAND,         TRACE,        RSVD4,        0x32cc, N, N),
+       PINGROUP(kb_row5_pr5,          KBC,          NAND,         TRACE,        OWR,          0x32d0, N, N),
+       PINGROUP(kb_row6_pr6,          KBC,          NAND,         SDMMC2,       MIO,          0x32d4, N, N),
+       PINGROUP(kb_row7_pr7,          KBC,          NAND,         SDMMC2,       MIO,          0x32d8, N, N),
+       PINGROUP(kb_row8_ps0,          KBC,          NAND,         SDMMC2,       MIO,          0x32dc, N, N),
+       PINGROUP(kb_row9_ps1,          KBC,          NAND,         SDMMC2,       MIO,          0x32e0, N, N),
+       PINGROUP(kb_row10_ps2,         KBC,          NAND,         SDMMC2,       MIO,          0x32e4, N, N),
+       PINGROUP(kb_row11_ps3,         KBC,          NAND,         SDMMC2,       MIO,          0x32e8, N, N),
+       PINGROUP(kb_row12_ps4,         KBC,          NAND,         SDMMC2,       MIO,          0x32ec, N, N),
+       PINGROUP(kb_row13_ps5,         KBC,          NAND,         SDMMC2,       MIO,          0x32f0, N, N),
+       PINGROUP(kb_row14_ps6,         KBC,          NAND,         SDMMC2,       MIO,          0x32f4, N, N),
+       PINGROUP(kb_row15_ps7,         KBC,          NAND,         SDMMC2,       MIO,          0x32f8, N, N),
+       PINGROUP(vi_pclk_pt0,          RSVD1,        SDMMC2,       VI,           RSVD4,        0x3154, N, Y),
+       PINGROUP(vi_mclk_pt1,          VI,           VI_ALT1,      VI_ALT2,      VI_ALT3,      0x3158, N, Y),
+       PINGROUP(vi_d10_pt2,           DDR,          RSVD2,        VI,           RSVD4,        0x314c, N, Y),
+       PINGROUP(vi_d11_pt3,           DDR,          RSVD2,        VI,           RSVD4,        0x3150, N, Y),
+       PINGROUP(vi_d0_pt4,            DDR,          RSVD2,        VI,           RSVD4,        0x3124, N, Y),
+       PINGROUP(gen2_i2c_scl_pt5,     I2C2,         HDCP,         GMI,          RSVD4,        0x3250, Y, N),
+       PINGROUP(gen2_i2c_sda_pt6,     I2C2,         HDCP,         GMI,          RSVD4,        0x3254, Y, N),
+       PINGROUP(sdmmc4_cmd_pt7,       I2C3,         NAND,         GMI,          SDMMC4,       0x325c, N, Y),
+       PINGROUP(pu0,                  OWR,          UARTA,        GMI,          RSVD4,        0x3184, N, N),
+       PINGROUP(pu1,                  RSVD1,        UARTA,        GMI,          RSVD4,        0x3188, N, N),
+       PINGROUP(pu2,                  RSVD1,        UARTA,        GMI,          RSVD4,        0x318c, N, N),
+       PINGROUP(pu3,                  PWM0,         UARTA,        GMI,          RSVD4,        0x3190, N, N),
+       PINGROUP(pu4,                  PWM1,         UARTA,        GMI,          RSVD4,        0x3194, N, N),
+       PINGROUP(pu5,                  PWM2,         UARTA,        GMI,          RSVD4,        0x3198, N, N),
+       PINGROUP(pu6,                  PWM3,         UARTA,        GMI,          RSVD4,        0x319c, N, N),
+       PINGROUP(jtag_rtck_pu7,        RTCK,         RSVD2,        RSVD3,        RSVD4,        0x32b0, N, N),
+       PINGROUP(pv0,                  RSVD1,        RSVD2,        RSVD3,        RSVD4,        0x3040, N, N),
+       PINGROUP(pv1,                  RSVD1,        RSVD2,        RSVD3,        RSVD4,        0x3044, N, N),
+       PINGROUP(pv2,                  OWR,          RSVD2,        RSVD3,        RSVD4,        0x3060, N, N),
+       PINGROUP(pv3,                  CLK_12M_OUT,  RSVD2,        RSVD3,        RSVD4,        0x3064, N, N),
+       PINGROUP(ddc_scl_pv4,          I2C4,         RSVD2,        RSVD3,        RSVD4,        0x3114, N, N),
+       PINGROUP(ddc_sda_pv5,          I2C4,         RSVD2,        RSVD3,        RSVD4,        0x3118, N, N),
+       PINGROUP(crt_hsync_pv6,        CRT,          RSVD2,        RSVD3,        RSVD4,        0x311c, N, N),
+       PINGROUP(crt_vsync_pv7,        CRT,          RSVD2,        RSVD3,        RSVD4,        0x3120, N, N),
+       PINGROUP(lcd_cs1_n_pw0,        DISPLAYA,     DISPLAYB,     SPI5,         RSVD4,        0x3104, N, N),
+       PINGROUP(lcd_m1_pw1,           DISPLAYA,     DISPLAYB,     RSVD3,        RSVD4,        0x3108, N, N),
+       PINGROUP(spi2_cs1_n_pw2,       SPI3,         SPI2,         SPI2_ALT,     I2C1,         0x3388, N, N),
+       PINGROUP(spi2_cs2_n_pw3,       SPI3,         SPI2,         SPI2_ALT,     I2C1,         0x338c, N, N),
+       PINGROUP(clk1_out_pw4,         EXTPERIPH1,   RSVD2,        RSVD3,        RSVD4,        0x334c, N, N),
+       PINGROUP(clk2_out_pw5,         EXTPERIPH2,   RSVD2,        RSVD3,        RSVD4,        0x3068, N, N),
+       PINGROUP(uart3_txd_pw6,        UARTC,        RSVD2,        GMI,          RSVD4,        0x3174, N, N),
+       PINGROUP(uart3_rxd_pw7,        UARTC,        RSVD2,        GMI,          RSVD4,        0x3178, N, N),
+       PINGROUP(spi2_mosi_px0,        SPI6,         SPI2,         SPI3,         GMI,          0x3368, N, N),
+       PINGROUP(spi2_miso_px1,        SPI6,         SPI2,         SPI3,         GMI,          0x336c, N, N),
+       PINGROUP(spi2_sck_px2,         SPI6,         SPI2,         SPI3,         GMI,          0x3374, N, N),
+       PINGROUP(spi2_cs0_n_px3,       SPI6,         SPI2,         SPI3,         GMI,          0x3370, N, N),
+       PINGROUP(spi1_mosi_px4,        SPI2,         SPI1,         SPI2_ALT,     GMI,          0x3378, N, N),
+       PINGROUP(spi1_sck_px5,         SPI2,         SPI1,         SPI2_ALT,     GMI,          0x337c, N, N),
+       PINGROUP(spi1_cs0_n_px6,       SPI2,         SPI1,         SPI2_ALT,     GMI,          0x3380, N, N),
+       PINGROUP(spi1_miso_px7,        SPI3,         SPI1,         SPI2_ALT,     RSVD4,        0x3384, N, N),
+       PINGROUP(ulpi_clk_py0,         SPI1,         RSVD2,        UARTD,        ULPI,         0x3020, N, N),
+       PINGROUP(ulpi_dir_py1,         SPI1,         RSVD2,        UARTD,        ULPI,         0x3024, N, N),
+       PINGROUP(ulpi_nxt_py2,         SPI1,         RSVD2,        UARTD,        ULPI,         0x3028, N, N),
+       PINGROUP(ulpi_stp_py3,         SPI1,         RSVD2,        UARTD,        ULPI,         0x302c, N, N),
+       PINGROUP(sdmmc1_dat3_py4,      SDMMC1,       RSVD2,        UARTE,        UARTA,        0x3050, N, N),
+       PINGROUP(sdmmc1_dat2_py5,      SDMMC1,       RSVD2,        UARTE,        UARTA,        0x3054, N, N),
+       PINGROUP(sdmmc1_dat1_py6,      SDMMC1,       RSVD2,        UARTE,        UARTA,        0x3058, N, N),
+       PINGROUP(sdmmc1_dat0_py7,      SDMMC1,       RSVD2,        UARTE,        UARTA,        0x305c, N, N),
+       PINGROUP(sdmmc1_clk_pz0,       SDMMC1,       RSVD2,        RSVD3,        UARTA,        0x3048, N, N),
+       PINGROUP(sdmmc1_cmd_pz1,       SDMMC1,       RSVD2,        RSVD3,        UARTA,        0x304c, N, N),
+       PINGROUP(lcd_sdin_pz2,         DISPLAYA,     DISPLAYB,     SPI5,         RSVD4,        0x3078, N, N),
+       PINGROUP(lcd_wr_n_pz3,         DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x3080, N, N),
+       PINGROUP(lcd_sck_pz4,          DISPLAYA,     DISPLAYB,     SPI5,         HDCP,         0x308c, N, N),
+       PINGROUP(sys_clk_req_pz5,      SYSCLK,       RSVD2,        RSVD3,        RSVD4,        0x3320, N, N),
+       PINGROUP(pwr_i2c_scl_pz6,      I2CPWR,       RSVD2,        RSVD3,        RSVD4,        0x32b4, Y, N),
+       PINGROUP(pwr_i2c_sda_pz7,      I2CPWR,       RSVD2,        RSVD3,        RSVD4,        0x32b8, Y, N),
+       PINGROUP(sdmmc4_dat0_paa0,     UARTE,        SPI3,         GMI,          SDMMC4,       0x3260, N, Y),
+       PINGROUP(sdmmc4_dat1_paa1,     UARTE,        SPI3,         GMI,          SDMMC4,       0x3264, N, Y),
+       PINGROUP(sdmmc4_dat2_paa2,     UARTE,        SPI3,         GMI,          SDMMC4,       0x3268, N, Y),
+       PINGROUP(sdmmc4_dat3_paa3,     UARTE,        SPI3,         GMI,          SDMMC4,       0x326c, N, Y),
+       PINGROUP(sdmmc4_dat4_paa4,     I2C3,         I2S4,         GMI,          SDMMC4,       0x3270, N, Y),
+       PINGROUP(sdmmc4_dat5_paa5,     VGP3,         I2S4,         GMI,          SDMMC4,       0x3274, N, Y),
+       PINGROUP(sdmmc4_dat6_paa6,     VGP4,         I2S4,         GMI,          SDMMC4,       0x3278, N, Y),
+       PINGROUP(sdmmc4_dat7_paa7,     VGP5,         I2S4,         GMI,          SDMMC4,       0x327c, N, Y),
+       PINGROUP(pbb0,                 I2S4,         RSVD2,        RSVD3,        SDMMC4,       0x328c, N, N),
+       PINGROUP(cam_i2c_scl_pbb1,     VGP1,         I2C3,         RSVD3,        SDMMC4,       0x3290, Y, N),
+       PINGROUP(cam_i2c_sda_pbb2,     VGP2,         I2C3,         RSVD3,        SDMMC4,       0x3294, Y, N),
+       PINGROUP(pbb3,                 VGP3,         DISPLAYA,     DISPLAYB,     SDMMC4,       0x3298, N, N),
+       PINGROUP(pbb4,                 VGP4,         DISPLAYA,     DISPLAYB,     SDMMC4,       0x329c, N, N),
+       PINGROUP(pbb5,                 VGP5,         DISPLAYA,     DISPLAYB,     SDMMC4,       0x32a0, N, N),
+       PINGROUP(pbb6,                 VGP6,         DISPLAYA,     DISPLAYB,     SDMMC4,       0x32a4, N, N),
+       PINGROUP(pbb7,                 I2S4,         RSVD2,        RSVD3,        SDMMC4,       0x32a8, N, N),
+       PINGROUP(cam_mclk_pcc0,        VI,           VI_ALT1,      VI_ALT3,      SDMMC4,       0x3284, N, N),
+       PINGROUP(pcc1,                 I2S4,         RSVD2,        RSVD3,        SDMMC4,       0x3288, N, N),
+       PINGROUP(pcc2,                 I2S4,         RSVD2,        RSVD3,        RSVD4,        0x32ac, N, N),
+       PINGROUP(sdmmc4_rst_n_pcc3,    VGP6,         RSVD2,        RSVD3,        SDMMC4,       0x3280, N, Y),
+       PINGROUP(sdmmc4_clk_pcc4,      INVALID,      NAND,         GMI,          SDMMC4,       0x3258, N, Y),
+       PINGROUP(clk2_req_pcc5,        DAP,          RSVD2,        RSVD3,        RSVD4,        0x306c, N, N),
+       PINGROUP(pex_l2_rst_n_pcc6,    PCIE,         HDA,          RSVD3,        RSVD4,        0x33d8, N, N),
+       PINGROUP(pex_l2_clkreq_n_pcc7, PCIE,         HDA,          RSVD3,        RSVD4,        0x33dc, N, N),
+       PINGROUP(pex_l0_prsnt_n_pdd0,  PCIE,         HDA,          RSVD3,        RSVD4,        0x33b8, N, N),
+       PINGROUP(pex_l0_rst_n_pdd1,    PCIE,         HDA,          RSVD3,        RSVD4,        0x33bc, N, N),
+       PINGROUP(pex_l0_clkreq_n_pdd2, PCIE,         HDA,          RSVD3,        RSVD4,        0x33c0, N, N),
+       PINGROUP(pex_wake_n_pdd3,      PCIE,         HDA,          RSVD3,        RSVD4,        0x33c4, N, N),
+       PINGROUP(pex_l1_prsnt_n_pdd4,  PCIE,         HDA,          RSVD3,        RSVD4,        0x33c8, N, N),
+       PINGROUP(pex_l1_rst_n_pdd5,    PCIE,         HDA,          RSVD3,        RSVD4,        0x33cc, N, N),
+       PINGROUP(pex_l1_clkreq_n_pdd6, PCIE,         HDA,          RSVD3,        RSVD4,        0x33d0, N, N),
+       PINGROUP(pex_l2_prsnt_n_pdd7,  PCIE,         HDA,          RSVD3,        RSVD4,        0x33d4, N, N),
+       PINGROUP(clk3_out_pee0,        EXTPERIPH3,   RSVD2,        RSVD3,        RSVD4,        0x31b8, N, N),
+       PINGROUP(clk3_req_pee1,        DEV3,         RSVD2,        RSVD3,        RSVD4,        0x31bc, N, N),
+       PINGROUP(clk1_req_pee2,        DAP,          HDA,          RSVD3,        RSVD4,        0x3348, N, N),
+       PINGROUP(hdmi_cec_pee3,        CEC,          RSVD2,        RSVD3,        RSVD4,        0x33e0, Y, N),
+       PINGROUP(clk_32k_in,           CLK_32K_IN,   RSVD2,        RSVD3,        RSVD4,        0x3330, N, N),
+       PINGROUP(core_pwr_req,         CORE_PWR_REQ, RSVD2,        RSVD3,        RSVD4,        0x3324, N, N),
+       PINGROUP(cpu_pwr_req,          CPU_PWR_REQ,  RSVD2,        RSVD3,        RSVD4,        0x3328, N, N),
+       PINGROUP(owr,                  OWR,          CEC,          RSVD3,        RSVD4,        0x3334, N, N),
+       PINGROUP(pwr_int_n,            PWR_INT_N,    RSVD2,        RSVD3,        RSVD4,        0x332c, N, N),
+       /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */
+       DRV_PINGROUP(ao1,   0x868,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(ao2,   0x86c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(at1,   0x870,  2,  3,  4,  14,  5,  19,  5,  24,  2,  28,  2),
+       DRV_PINGROUP(at2,   0x874,  2,  3,  4,  14,  5,  19,  5,  24,  2,  28,  2),
+       DRV_PINGROUP(at3,   0x878,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(at4,   0x87c,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(at5,   0x880,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(cdev1, 0x884,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(cdev2, 0x888,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(cec,   0x938,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(crt,   0x8f8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(csus,  0x88c, -1, -1, -1,  12,  5,  19,  5,  24,  4,  28,  4),
+       DRV_PINGROUP(dap1,  0x890,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(dap2,  0x894,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(dap3,  0x898,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(dap4,  0x89c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(dbg,   0x8a0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(ddc,   0x8fc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(dev3,  0x92c,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(gma,   0x900, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
+       DRV_PINGROUP(gmb,   0x904, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
+       DRV_PINGROUP(gmc,   0x908, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
+       DRV_PINGROUP(gmd,   0x90c, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
+       DRV_PINGROUP(gme,   0x910,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(gmf,   0x914,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(gmg,   0x918,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(gmh,   0x91c,  2,  3,  4,  14,  5,  19,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(gpv,   0x928,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(lcd1,  0x8a4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(lcd2,  0x8a8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(owr,   0x920,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(sdio1, 0x8ec,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2),
+       DRV_PINGROUP(sdio2, 0x8ac,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2),
+       DRV_PINGROUP(sdio3, 0x8b0,  2,  3, -1,  12,  7,  20,  7,  28,  2,  30,  2),
+       DRV_PINGROUP(spi,   0x8b4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(uaa,   0x8b8,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(uab,   0x8bc,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(uart2, 0x8c0,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(uart3, 0x8c4,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(uda,   0x924,  2,  3,  4,  12,  5,  20,  5,  28,  2,  30,  2),
+       DRV_PINGROUP(vi1,   0x8c8, -1, -1, -1,  14,  5,  19,  5,  24,  4,  28,  4),
+};
+
+static const struct tegra_pinctrl_soc_data tegra30_pinctrl = {
+       .ngpios = NUM_GPIOS,
+       .pins = tegra30_pins,
+       .npins = ARRAY_SIZE(tegra30_pins),
+       .functions = tegra30_functions,
+       .nfunctions = ARRAY_SIZE(tegra30_functions),
+       .groups = tegra30_groups,
+       .ngroups = ARRAY_SIZE(tegra30_groups),
+       .hsm_in_mux = false,
+       .schmitt_in_mux = false,
+       .drvtype_in_mux = false,
+};
+
+static int tegra30_pinctrl_probe(struct platform_device *pdev)
+{
+       return tegra_pinctrl_probe(pdev, &tegra30_pinctrl);
+}
+
+static const struct of_device_id tegra30_pinctrl_of_match[] = {
+       { .compatible = "nvidia,tegra30-pinmux", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match);
+
+static struct platform_driver tegra30_pinctrl_driver = {
+       .driver = {
+               .name = "tegra30-pinctrl",
+               .of_match_table = tegra30_pinctrl_of_match,
+       },
+       .probe = tegra30_pinctrl_probe,
+       .remove = tegra_pinctrl_remove,
+};
+module_platform_driver(tegra30_pinctrl_driver);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver");
+MODULE_LICENSE("GPL v2");
index 7abd614dc38361a1dbbd081c12121f4558493f99..0b40ded5738f57689097f06e53bb3c8ba8af66ad 100644 (file)
@@ -1,6 +1,6 @@
 menuconfig PINCTRL_UNIPHIER
        bool "UniPhier SoC pinctrl drivers"
-       depends on ARCH_UNIPHIER
+       depends on ARCH_UNIPHIER || COMPILE_TEST
        depends on OF && MFD_SYSCON
        default y
        select PINMUX
@@ -8,27 +8,27 @@ menuconfig PINCTRL_UNIPHIER
 
 if PINCTRL_UNIPHIER
 
-config PINCTRL_UNIPHIER_PH1_LD4
+config PINCTRL_UNIPHIER_LD4
        tristate "UniPhier PH1-LD4 SoC pinctrl driver"
        default y
 
-config PINCTRL_UNIPHIER_PH1_PRO4
+config PINCTRL_UNIPHIER_PRO4
        tristate "UniPhier PH1-Pro4 SoC pinctrl driver"
        default y
 
-config PINCTRL_UNIPHIER_PH1_SLD8
+config PINCTRL_UNIPHIER_SLD8
        tristate "UniPhier PH1-sLD8 SoC pinctrl driver"
        default y
 
-config PINCTRL_UNIPHIER_PH1_PRO5
+config PINCTRL_UNIPHIER_PRO5
        tristate "UniPhier PH1-Pro5 SoC pinctrl driver"
        default y
 
-config PINCTRL_UNIPHIER_PROXSTREAM2
+config PINCTRL_UNIPHIER_PXS2
        tristate "UniPhier ProXstream2 SoC pinctrl driver"
        default y
 
-config PINCTRL_UNIPHIER_PH1_LD6B
+config PINCTRL_UNIPHIER_LD6B
        tristate "UniPhier PH1-LD6b SoC pinctrl driver"
        default y
 
index e7ce9670306cb15399f7aee571cb63fd7c310c98..3b8f9ee0bb6fd22ac30ddd482ebd5c45d252d744 100644 (file)
@@ -1,8 +1,8 @@
-obj-y                                          += pinctrl-uniphier-core.o
+obj-y                                  += pinctrl-uniphier-core.o
 
-obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_LD4)         += pinctrl-ph1-ld4.o
-obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_PRO4)                += pinctrl-ph1-pro4.o
-obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_SLD8)                += pinctrl-ph1-sld8.o
-obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_PRO5)                += pinctrl-ph1-pro5.o
-obj-$(CONFIG_PINCTRL_UNIPHIER_PROXSTREAM2)     += pinctrl-proxstream2.o
-obj-$(CONFIG_PINCTRL_UNIPHIER_PH1_LD6B)                += pinctrl-ph1-ld6b.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_LD4)     += pinctrl-uniphier-ld4.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_PRO4)    += pinctrl-uniphier-pro4.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_SLD8)    += pinctrl-uniphier-sld8.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_PRO5)    += pinctrl-uniphier-pro5.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_PXS2)    += pinctrl-uniphier-pxs2.o
+obj-$(CONFIG_PINCTRL_UNIPHIER_LD6B)    += pinctrl-uniphier-ld6b.o
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c b/drivers/pinctrl/uniphier/pinctrl-ph1-ld4.c
deleted file mode 100644 (file)
index a7056dc..0000000
+++ /dev/null
@@ -1,891 +0,0 @@
-/*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/platform_device.h>
-
-#include "pinctrl-uniphier.h"
-
-#define DRIVER_NAME "ph1-ld4-pinctrl"
-
-static const struct pinctrl_pin_desc ph1_ld4_pins[] = {
-       UNIPHIER_PINCTRL_PIN(0, "EA1", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_4_8,
-                            8, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(1, "EA2", UNIPHIER_PIN_IECTRL_NONE,
-                            9, UNIPHIER_PIN_DRV_4_8,
-                            9, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(2, "EA3", UNIPHIER_PIN_IECTRL_NONE,
-                            10, UNIPHIER_PIN_DRV_4_8,
-                            10, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(3, "EA4", UNIPHIER_PIN_IECTRL_NONE,
-                            11, UNIPHIER_PIN_DRV_4_8,
-                            11, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(4, "EA5", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_4_8,
-                            12, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(5, "EA6", UNIPHIER_PIN_IECTRL_NONE,
-                            13, UNIPHIER_PIN_DRV_4_8,
-                            13, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(6, "EA7", UNIPHIER_PIN_IECTRL_NONE,
-                            14, UNIPHIER_PIN_DRV_4_8,
-                            14, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(7, "EA8", 0,
-                            15, UNIPHIER_PIN_DRV_4_8,
-                            15, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(8, "EA9", 0,
-                            16, UNIPHIER_PIN_DRV_4_8,
-                            16, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(9, "EA10", 0,
-                            17, UNIPHIER_PIN_DRV_4_8,
-                            17, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(10, "EA11", 0,
-                            18, UNIPHIER_PIN_DRV_4_8,
-                            18, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(11, "EA12", 0,
-                            19, UNIPHIER_PIN_DRV_4_8,
-                            19, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(12, "EA13", 0,
-                            20, UNIPHIER_PIN_DRV_4_8,
-                            20, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(13, "EA14", 0,
-                            21, UNIPHIER_PIN_DRV_4_8,
-                            21, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(14, "EA15", 0,
-                            22, UNIPHIER_PIN_DRV_4_8,
-                            22, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(15, "ECLK", UNIPHIER_PIN_IECTRL_NONE,
-                            23, UNIPHIER_PIN_DRV_4_8,
-                            23, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(16, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
-                            24, UNIPHIER_PIN_DRV_4_8,
-                            24, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(17, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
-                            25, UNIPHIER_PIN_DRV_4_8,
-                            25, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(18, "ES0", UNIPHIER_PIN_IECTRL_NONE,
-                            27, UNIPHIER_PIN_DRV_4_8,
-                            27, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(19, "ES1", UNIPHIER_PIN_IECTRL_NONE,
-                            28, UNIPHIER_PIN_DRV_4_8,
-                            28, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(20, "ES2", UNIPHIER_PIN_IECTRL_NONE,
-                            29, UNIPHIER_PIN_DRV_4_8,
-                            29, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(21, "XERST", UNIPHIER_PIN_IECTRL_NONE,
-                            38, UNIPHIER_PIN_DRV_4_8,
-                            38, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(22, "MMCCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            0, UNIPHIER_PIN_DRV_8_12_16_20,
-                            146, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(23, "MMCCMD", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_8_12_16_20,
-                            147, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(24, "MMCDAT0", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_8_12_16_20,
-                            148, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(25, "MMCDAT1", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_8_12_16_20,
-                            149, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(26, "MMCDAT2", UNIPHIER_PIN_IECTRL_NONE,
-                            16, UNIPHIER_PIN_DRV_8_12_16_20,
-                            150, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(27, "MMCDAT3", UNIPHIER_PIN_IECTRL_NONE,
-                            20, UNIPHIER_PIN_DRV_8_12_16_20,
-                            151, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(28, "MMCDAT4", UNIPHIER_PIN_IECTRL_NONE,
-                            24, UNIPHIER_PIN_DRV_8_12_16_20,
-                            152, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(29, "MMCDAT5", UNIPHIER_PIN_IECTRL_NONE,
-                            28, UNIPHIER_PIN_DRV_8_12_16_20,
-                            153, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(30, "MMCDAT6", UNIPHIER_PIN_IECTRL_NONE,
-                            32, UNIPHIER_PIN_DRV_8_12_16_20,
-                            154, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(31, "MMCDAT7", UNIPHIER_PIN_IECTRL_NONE,
-                            36, UNIPHIER_PIN_DRV_8_12_16_20,
-                            155, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(32, "RMII_RXD0", 6,
-                            39, UNIPHIER_PIN_DRV_4_8,
-                            39, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(33, "RMII_RXD1", 6,
-                            40, UNIPHIER_PIN_DRV_4_8,
-                            40, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(34, "RMII_CRS_DV", 6,
-                            41, UNIPHIER_PIN_DRV_4_8,
-                            41, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(35, "RMII_RXER", 6,
-                            42, UNIPHIER_PIN_DRV_4_8,
-                            42, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(36, "RMII_REFCLK", 6,
-                            43, UNIPHIER_PIN_DRV_4_8,
-                            43, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(37, "RMII_TXD0", 6,
-                            44, UNIPHIER_PIN_DRV_4_8,
-                            44, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(38, "RMII_TXD1", 6,
-                            45, UNIPHIER_PIN_DRV_4_8,
-                            45, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(39, "RMII_TXEN", 6,
-                            46, UNIPHIER_PIN_DRV_4_8,
-                            46, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(40, "MDC", 6,
-                            47, UNIPHIER_PIN_DRV_4_8,
-                            47, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(41, "MDIO", 6,
-                            48, UNIPHIER_PIN_DRV_4_8,
-                            48, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(42, "MDIO_INTL", 6,
-                            49, UNIPHIER_PIN_DRV_4_8,
-                            49, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(43, "PHYRSTL", 6,
-                            50, UNIPHIER_PIN_DRV_4_8,
-                            50, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(44, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            40, UNIPHIER_PIN_DRV_8_12_16_20,
-                            156, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(45, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
-                            44, UNIPHIER_PIN_DRV_8_12_16_20,
-                            157, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(46, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
-                            48, UNIPHIER_PIN_DRV_8_12_16_20,
-                            158, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(47, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
-                            52, UNIPHIER_PIN_DRV_8_12_16_20,
-                            159, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(48, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
-                            56, UNIPHIER_PIN_DRV_8_12_16_20,
-                            160, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(49, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
-                            60, UNIPHIER_PIN_DRV_8_12_16_20,
-                            161, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(50, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
-                            51, UNIPHIER_PIN_DRV_4_8,
-                            51, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(51, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
-                            52, UNIPHIER_PIN_DRV_4_8,
-                            52, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(52, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
-                            53, UNIPHIER_PIN_DRV_4_8,
-                            53, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(53, "USB0VBUS", 0,
-                            54, UNIPHIER_PIN_DRV_4_8,
-                            54, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(54, "USB0OD", 0,
-                            55, UNIPHIER_PIN_DRV_4_8,
-                            55, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(55, "USB1VBUS", 0,
-                            56, UNIPHIER_PIN_DRV_4_8,
-                            56, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(56, "USB1OD", 0,
-                            57, UNIPHIER_PIN_DRV_4_8,
-                            57, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(57, "PCRESET", 0,
-                            58, UNIPHIER_PIN_DRV_4_8,
-                            58, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(58, "PCREG", 0,
-                            59, UNIPHIER_PIN_DRV_4_8,
-                            59, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(59, "PCCE2", 0,
-                            60, UNIPHIER_PIN_DRV_4_8,
-                            60, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(60, "PCVS1", 0,
-                            61, UNIPHIER_PIN_DRV_4_8,
-                            61, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(61, "PCCD2", 0,
-                            62, UNIPHIER_PIN_DRV_4_8,
-                            62, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(62, "PCCD1", 0,
-                            63, UNIPHIER_PIN_DRV_4_8,
-                            63, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(63, "PCREADY", 0,
-                            64, UNIPHIER_PIN_DRV_4_8,
-                            64, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(64, "PCDOE", 0,
-                            65, UNIPHIER_PIN_DRV_4_8,
-                            65, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(65, "PCCE1", 0,
-                            66, UNIPHIER_PIN_DRV_4_8,
-                            66, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(66, "PCWE", 0,
-                            67, UNIPHIER_PIN_DRV_4_8,
-                            67, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(67, "PCOE", 0,
-                            68, UNIPHIER_PIN_DRV_4_8,
-                            68, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(68, "PCWAIT", 0,
-                            69, UNIPHIER_PIN_DRV_4_8,
-                            69, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(69, "PCIOWR", 0,
-                            70, UNIPHIER_PIN_DRV_4_8,
-                            70, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(70, "PCIORD", 0,
-                            71, UNIPHIER_PIN_DRV_4_8,
-                            71, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(71, "HS0DIN0", 0,
-                            72, UNIPHIER_PIN_DRV_4_8,
-                            72, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(72, "HS0DIN1", 0,
-                            73, UNIPHIER_PIN_DRV_4_8,
-                            73, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(73, "HS0DIN2", 0,
-                            74, UNIPHIER_PIN_DRV_4_8,
-                            74, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(74, "HS0DIN3", 0,
-                            75, UNIPHIER_PIN_DRV_4_8,
-                            75, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(75, "HS0DIN4", 0,
-                            76, UNIPHIER_PIN_DRV_4_8,
-                            76, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(76, "HS0DIN5", 0,
-                            77, UNIPHIER_PIN_DRV_4_8,
-                            77, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(77, "HS0DIN6", 0,
-                            78, UNIPHIER_PIN_DRV_4_8,
-                            78, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(78, "HS0DIN7", 0,
-                            79, UNIPHIER_PIN_DRV_4_8,
-                            79, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(79, "HS0BCLKIN", 0,
-                            80, UNIPHIER_PIN_DRV_4_8,
-                            80, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(80, "HS0VALIN", 0,
-                            81, UNIPHIER_PIN_DRV_4_8,
-                            81, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(81, "HS0SYNCIN", 0,
-                            82, UNIPHIER_PIN_DRV_4_8,
-                            82, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(82, "HSDOUT0", 0,
-                            83, UNIPHIER_PIN_DRV_4_8,
-                            83, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(83, "HSDOUT1", 0,
-                            84, UNIPHIER_PIN_DRV_4_8,
-                            84, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(84, "HSDOUT2", 0,
-                            85, UNIPHIER_PIN_DRV_4_8,
-                            85, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(85, "HSDOUT3", 0,
-                            86, UNIPHIER_PIN_DRV_4_8,
-                            86, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(86, "HSDOUT4", 0,
-                            87, UNIPHIER_PIN_DRV_4_8,
-                            87, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(87, "HSDOUT5", 0,
-                            88, UNIPHIER_PIN_DRV_4_8,
-                            88, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(88, "HSDOUT6", 0,
-                            89, UNIPHIER_PIN_DRV_4_8,
-                            89, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(89, "HSDOUT7", 0,
-                            90, UNIPHIER_PIN_DRV_4_8,
-                            90, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(90, "HSBCLKOUT", 0,
-                            91, UNIPHIER_PIN_DRV_4_8,
-                            91, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(91, "HSVALOUT", 0,
-                            92, UNIPHIER_PIN_DRV_4_8,
-                            92, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(92, "HSSYNCOUT", 0,
-                            93, UNIPHIER_PIN_DRV_4_8,
-                            93, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(93, "AGCI", 3,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            162, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(94, "AGCR", 4,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            163, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(95, "AGCBS", 5,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            164, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(96, "IECOUT", 0,
-                            94, UNIPHIER_PIN_DRV_4_8,
-                            94, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(97, "ASMCK", 0,
-                            95, UNIPHIER_PIN_DRV_4_8,
-                            95, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(98, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
-                            96, UNIPHIER_PIN_DRV_4_8,
-                            96, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(99, "ALRCKO", UNIPHIER_PIN_IECTRL_NONE,
-                            97, UNIPHIER_PIN_DRV_4_8,
-                            97, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(100, "ASDOUT0", UNIPHIER_PIN_IECTRL_NONE,
-                            98, UNIPHIER_PIN_DRV_4_8,
-                            98, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(101, "ARCOUT", 0,
-                            99, UNIPHIER_PIN_DRV_4_8,
-                            99, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(102, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(103, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(104, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(105, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
-                            100, UNIPHIER_PIN_DRV_4_8,
-                            100, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
-                            101, UNIPHIER_PIN_DRV_4_8,
-                            101, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(112, "HIN", 1,
-                            -1, UNIPHIER_PIN_DRV_FIXED_5,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(113, "VIN", 2,
-                            -1, UNIPHIER_PIN_DRV_FIXED_5,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(114, "TCON0", UNIPHIER_PIN_IECTRL_NONE,
-                            102, UNIPHIER_PIN_DRV_4_8,
-                            102, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(115, "TCON1", UNIPHIER_PIN_IECTRL_NONE,
-                            103, UNIPHIER_PIN_DRV_4_8,
-                            103, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(116, "TCON2", UNIPHIER_PIN_IECTRL_NONE,
-                            104, UNIPHIER_PIN_DRV_4_8,
-                            104, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(117, "TCON3", UNIPHIER_PIN_IECTRL_NONE,
-                            105, UNIPHIER_PIN_DRV_4_8,
-                            105, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(118, "TCON4", UNIPHIER_PIN_IECTRL_NONE,
-                            106, UNIPHIER_PIN_DRV_4_8,
-                            106, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(119, "TCON5", UNIPHIER_PIN_IECTRL_NONE,
-                            107, UNIPHIER_PIN_DRV_4_8,
-                            107, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(120, "TCON6", 0,
-                            108, UNIPHIER_PIN_DRV_4_8,
-                            108, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(121, "TCON7", 0,
-                            109, UNIPHIER_PIN_DRV_4_8,
-                            109, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(122, "PWMA", 0,
-                            110, UNIPHIER_PIN_DRV_4_8,
-                            110, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(123, "XIRQ1", 0,
-                            111, UNIPHIER_PIN_DRV_4_8,
-                            111, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(124, "XIRQ2", 0,
-                            112, UNIPHIER_PIN_DRV_4_8,
-                            112, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(125, "XIRQ3", 0,
-                            113, UNIPHIER_PIN_DRV_4_8,
-                            113, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(126, "XIRQ4", 0,
-                            114, UNIPHIER_PIN_DRV_4_8,
-                            114, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(127, "XIRQ5", 0,
-                            115, UNIPHIER_PIN_DRV_4_8,
-                            115, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(128, "XIRQ6", 0,
-                            116, UNIPHIER_PIN_DRV_4_8,
-                            116, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(129, "XIRQ7", 0,
-                            117, UNIPHIER_PIN_DRV_4_8,
-                            117, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(130, "XIRQ8", 0,
-                            118, UNIPHIER_PIN_DRV_4_8,
-                            118, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(131, "XIRQ9", 0,
-                            119, UNIPHIER_PIN_DRV_4_8,
-                            119, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(132, "XIRQ10", 0,
-                            120, UNIPHIER_PIN_DRV_4_8,
-                            120, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(133, "XIRQ11", 0,
-                            121, UNIPHIER_PIN_DRV_4_8,
-                            121, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(134, "XIRQ14", 0,
-                            122, UNIPHIER_PIN_DRV_4_8,
-                            122, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(135, "PORT00", 0,
-                            123, UNIPHIER_PIN_DRV_4_8,
-                            123, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(136, "PORT01", 0,
-                            124, UNIPHIER_PIN_DRV_4_8,
-                            124, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(137, "PORT02", 0,
-                            125, UNIPHIER_PIN_DRV_4_8,
-                            125, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(138, "PORT03", 0,
-                            126, UNIPHIER_PIN_DRV_4_8,
-                            126, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(139, "PORT04", 0,
-                            127, UNIPHIER_PIN_DRV_4_8,
-                            127, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(140, "PORT05", 0,
-                            128, UNIPHIER_PIN_DRV_4_8,
-                            128, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(141, "PORT06", 0,
-                            129, UNIPHIER_PIN_DRV_4_8,
-                            129, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(142, "PORT07", 0,
-                            130, UNIPHIER_PIN_DRV_4_8,
-                            130, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(143, "PORT10", 0,
-                            131, UNIPHIER_PIN_DRV_4_8,
-                            131, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(144, "PORT11", 0,
-                            132, UNIPHIER_PIN_DRV_4_8,
-                            132, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(145, "PORT12", 0,
-                            133, UNIPHIER_PIN_DRV_4_8,
-                            133, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(146, "PORT13", 0,
-                            134, UNIPHIER_PIN_DRV_4_8,
-                            134, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(147, "PORT14", 0,
-                            135, UNIPHIER_PIN_DRV_4_8,
-                            135, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(148, "PORT15", 0,
-                            136, UNIPHIER_PIN_DRV_4_8,
-                            136, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(149, "PORT16", 0,
-                            137, UNIPHIER_PIN_DRV_4_8,
-                            137, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(150, "PORT17", UNIPHIER_PIN_IECTRL_NONE,
-                            138, UNIPHIER_PIN_DRV_4_8,
-                            138, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(151, "PORT20", 0,
-                            139, UNIPHIER_PIN_DRV_4_8,
-                            139, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(152, "PORT21", 0,
-                            140, UNIPHIER_PIN_DRV_4_8,
-                            140, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(153, "PORT22", 0,
-                            141, UNIPHIER_PIN_DRV_4_8,
-                            141, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(154, "PORT23", 0,
-                            142, UNIPHIER_PIN_DRV_4_8,
-                            142, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(155, "PORT24", UNIPHIER_PIN_IECTRL_NONE,
-                            143, UNIPHIER_PIN_DRV_4_8,
-                            143, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(156, "PORT25", 0,
-                            144, UNIPHIER_PIN_DRV_4_8,
-                            144, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(157, "PORT26", 0,
-                            145, UNIPHIER_PIN_DRV_4_8,
-                            145, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(158, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
-                            31, UNIPHIER_PIN_DRV_4_8,
-                            31, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(159, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
-                            32, UNIPHIER_PIN_DRV_4_8,
-                            32, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(160, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
-                            33, UNIPHIER_PIN_DRV_4_8,
-                            33, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(161, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
-                            34, UNIPHIER_PIN_DRV_4_8,
-                            34, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(162, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
-                            35, UNIPHIER_PIN_DRV_4_8,
-                            35, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(163, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
-                            36, UNIPHIER_PIN_DRV_4_8,
-                            36, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(164, "NANDRYBY0", UNIPHIER_PIN_IECTRL_NONE,
-                            37, UNIPHIER_PIN_DRV_4_8,
-                            37, UNIPHIER_PIN_PULL_UP),
-};
-
-static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
-static const unsigned emmc_muxvals[] = {0, 1, 1, 1, 1, 1, 1};
-static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
-static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
-static const unsigned i2c0_pins[] = {102, 103};
-static const unsigned i2c0_muxvals[] = {0, 0};
-static const unsigned i2c1_pins[] = {104, 105};
-static const unsigned i2c1_muxvals[] = {0, 0};
-static const unsigned i2c2_pins[] = {108, 109};
-static const unsigned i2c2_muxvals[] = {2, 2};
-static const unsigned i2c3_pins[] = {108, 109};
-static const unsigned i2c3_muxvals[] = {3, 3};
-static const unsigned nand_pins[] = {24, 25, 26, 27, 28, 29, 30, 31, 158, 159,
-                                    160, 161, 162, 163, 164};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0};
-static const unsigned nand_cs1_pins[] = {22, 23};
-static const unsigned nand_cs1_muxvals[] = {0, 0};
-static const unsigned sd_pins[] = {44, 45, 46, 47, 48, 49, 50, 51, 52};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-static const unsigned uart0_pins[] = {85, 88};
-static const unsigned uart0_muxvals[] = {1, 1};
-static const unsigned uart1_pins[] = {155, 156};
-static const unsigned uart1_muxvals[] = {13, 13};
-static const unsigned uart1b_pins[] = {69, 70};
-static const unsigned uart1b_muxvals[] = {23, 23};
-static const unsigned uart2_pins[] = {128, 129};
-static const unsigned uart2_muxvals[] = {13, 13};
-static const unsigned uart3_pins[] = {110, 111};
-static const unsigned uart3_muxvals[] = {1, 1};
-static const unsigned usb0_pins[] = {53, 54};
-static const unsigned usb0_muxvals[] = {0, 0};
-static const unsigned usb1_pins[] = {55, 56};
-static const unsigned usb1_muxvals[] = {0, 0};
-static const unsigned usb2_pins[] = {155, 156};
-static const unsigned usb2_muxvals[] = {4, 4};
-static const unsigned usb2b_pins[] = {67, 68};
-static const unsigned usb2b_muxvals[] = {23, 23};
-static const unsigned port_range0_pins[] = {
-       135, 136, 137, 138, 139, 140, 141, 142,         /* PORT0x */
-       143, 144, 145, 146, 147, 148, 149, 150,         /* PORT1x */
-       151, 152, 153, 154, 155, 156, 157, 0,           /* PORT2x */
-       1, 2, 3, 4, 5, 120, 121, 122,                   /* PORT3x */
-       24, 25, 26, 27, 28, 29, 30, 31,                 /* PORT4x */
-       40, 41, 42, 43, 44, 45, 46, 47,                 /* PORT5x */
-       48, 49, 50, 51, 52, 53, 54, 55,                 /* PORT6x */
-       56, 85, 84, 59, 82, 61, 64, 65,                 /* PORT7x */
-       8, 9, 10, 11, 12, 13, 14, 15,                   /* PORT8x */
-       66, 67, 68, 69, 70, 71, 72, 73,                 /* PORT9x */
-       74, 75, 89, 86, 78, 79, 80, 81,                 /* PORT10x */
-       60, 83, 58, 57, 88, 87, 77, 76,                 /* PORT11x */
-       90, 91, 92, 93, 94, 95, 96, 97,                 /* PORT12x */
-       98, 99, 100, 6, 101, 114, 115, 116,             /* PORT13x */
-       103, 108, 21, 22, 23, 117, 118, 119,            /* PORT14x */
-};
-static const unsigned port_range0_muxvals[] = {
-       0, 0, 0, 0, 0, 0, 0, 0,                         /* PORT0x */
-       0, 0, 0, 0, 0, 0, 0, 0,                         /* PORT1x */
-       0, 0, 0, 0, 0, 0, 0, 15,                        /* PORT2x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT11x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT12x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT13x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
-};
-static const unsigned port_range1_pins[] = {
-       7,                                              /* PORT166 */
-};
-static const unsigned port_range1_muxvals[] = {
-       15,                                             /* PORT166 */
-};
-static const unsigned xirq_range0_pins[] = {
-       151, 123, 124, 125, 126, 127, 128, 129,         /* XIRQ0-7 */
-       130, 131, 132, 133, 62,                         /* XIRQ8-12 */
-};
-static const unsigned xirq_range0_muxvals[] = {
-       14, 0, 0, 0, 0, 0, 0, 0,                        /* XIRQ0-7 */
-       0, 0, 0, 0, 14,                                 /* XIRQ8-12 */
-};
-static const unsigned xirq_range1_pins[] = {
-       134, 63,                                        /* XIRQ14-15 */
-};
-static const unsigned xirq_range1_muxvals[] = {
-       0, 14,                                          /* XIRQ14-15 */
-};
-
-static const struct uniphier_pinctrl_group ph1_ld4_groups[] = {
-       UNIPHIER_PINCTRL_GROUP(emmc),
-       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
-       UNIPHIER_PINCTRL_GROUP(i2c0),
-       UNIPHIER_PINCTRL_GROUP(i2c1),
-       UNIPHIER_PINCTRL_GROUP(i2c2),
-       UNIPHIER_PINCTRL_GROUP(i2c3),
-       UNIPHIER_PINCTRL_GROUP(nand),
-       UNIPHIER_PINCTRL_GROUP(nand_cs1),
-       UNIPHIER_PINCTRL_GROUP(sd),
-       UNIPHIER_PINCTRL_GROUP(uart0),
-       UNIPHIER_PINCTRL_GROUP(uart1),
-       UNIPHIER_PINCTRL_GROUP(uart1b),
-       UNIPHIER_PINCTRL_GROUP(uart2),
-       UNIPHIER_PINCTRL_GROUP(uart3),
-       UNIPHIER_PINCTRL_GROUP(usb0),
-       UNIPHIER_PINCTRL_GROUP(usb1),
-       UNIPHIER_PINCTRL_GROUP(usb2),
-       UNIPHIER_PINCTRL_GROUP(usb2b),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range0),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range0, 101),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range0, 102),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range0, 103),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range0, 104),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range0, 105),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range0, 106),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range0, 107),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range0, 108),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range0, 109),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range0, 110),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range0, 111),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range0, 112),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range0, 113),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range0, 114),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range0, 115),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range0, 116),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range0, 117),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range0, 118),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range0, 119),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port165, port_range1, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq_range0, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq_range0, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq_range0, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq_range0, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq_range0, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq_range0, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq_range0, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq_range0, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq_range0, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq_range0, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq_range0, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq_range0, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq_range0, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq_range1, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq_range1, 1),
-};
-
-static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
-static const char * const i2c0_groups[] = {"i2c0"};
-static const char * const i2c1_groups[] = {"i2c1"};
-static const char * const i2c2_groups[] = {"i2c2"};
-static const char * const i2c3_groups[] = {"i2c3"};
-static const char * const nand_groups[] = {"nand", "nand_cs1"};
-static const char * const sd_groups[] = {"sd"};
-static const char * const uart0_groups[] = {"uart0"};
-static const char * const uart1_groups[] = {"uart1", "uart1b"};
-static const char * const uart2_groups[] = {"uart2"};
-static const char * const uart3_groups[] = {"uart3"};
-static const char * const usb0_groups[] = {"usb0"};
-static const char * const usb1_groups[] = {"usb1"};
-static const char * const usb2_groups[] = {"usb2", "usb2b"};
-static const char * const port_groups[] = {
-       "port00",  "port01",  "port02",  "port03",
-       "port04",  "port05",  "port06",  "port07",
-       "port10",  "port11",  "port12",  "port13",
-       "port14",  "port15",  "port16",  "port17",
-       "port20",  "port21",  "port22",  "port23",
-       "port24",  "port25",  "port26",  "port27",
-       "port30",  "port31",  "port32",  "port33",
-       "port34",  "port35",  "port36",  "port37",
-       "port40",  "port41",  "port42",  "port43",
-       "port44",  "port45",  "port46",  "port47",
-       "port50",  "port51",  "port52",  "port53",
-       "port54",  "port55",  "port56",  "port57",
-       "port60",  "port61",  "port62",  "port63",
-       "port64",  "port65",  "port66",  "port67",
-       "port70",  "port71",  "port72",  "port73",
-       "port74",  "port75",  "port76",  "port77",
-       "port80",  "port81",  "port82",  "port83",
-       "port84",  "port85",  "port86",  "port87",
-       "port90",  "port91",  "port92",  "port93",
-       "port94",  "port95",  "port96",  "port97",
-       "port100", "port101", "port102", "port103",
-       "port104", "port105", "port106", "port107",
-       "port110", "port111", "port112", "port113",
-       "port114", "port115", "port116", "port117",
-       "port120", "port121", "port122", "port123",
-       "port124", "port125", "port126", "port127",
-       "port130", "port131", "port132", "port133",
-       "port134", "port135", "port136", "port137",
-       "port140", "port141", "port142", "port143",
-       "port144", "port145", "port146", "port147",
-       /* port150-164 missing */
-       /* none */ "port165",
-};
-static const char * const xirq_groups[] = {
-       "xirq0",  "xirq1",  "xirq2",  "xirq3",
-       "xirq4",  "xirq5",  "xirq6",  "xirq7",
-       "xirq8",  "xirq9",  "xirq10", "xirq11",
-       "xirq12", /* none*/ "xirq14", "xirq15",
-};
-
-static const struct uniphier_pinmux_function ph1_ld4_functions[] = {
-       UNIPHIER_PINMUX_FUNCTION(emmc),
-       UNIPHIER_PINMUX_FUNCTION(i2c0),
-       UNIPHIER_PINMUX_FUNCTION(i2c1),
-       UNIPHIER_PINMUX_FUNCTION(i2c2),
-       UNIPHIER_PINMUX_FUNCTION(i2c3),
-       UNIPHIER_PINMUX_FUNCTION(nand),
-       UNIPHIER_PINMUX_FUNCTION(sd),
-       UNIPHIER_PINMUX_FUNCTION(uart0),
-       UNIPHIER_PINMUX_FUNCTION(uart1),
-       UNIPHIER_PINMUX_FUNCTION(uart2),
-       UNIPHIER_PINMUX_FUNCTION(uart3),
-       UNIPHIER_PINMUX_FUNCTION(usb0),
-       UNIPHIER_PINMUX_FUNCTION(usb1),
-       UNIPHIER_PINMUX_FUNCTION(usb2),
-       UNIPHIER_PINMUX_FUNCTION(port),
-       UNIPHIER_PINMUX_FUNCTION(xirq),
-};
-
-static struct uniphier_pinctrl_socdata ph1_ld4_pindata = {
-       .groups = ph1_ld4_groups,
-       .groups_count = ARRAY_SIZE(ph1_ld4_groups),
-       .functions = ph1_ld4_functions,
-       .functions_count = ARRAY_SIZE(ph1_ld4_functions),
-       .mux_bits = 8,
-       .reg_stride = 4,
-       .load_pinctrl = false,
-};
-
-static struct pinctrl_desc ph1_ld4_pinctrl_desc = {
-       .name = DRIVER_NAME,
-       .pins = ph1_ld4_pins,
-       .npins = ARRAY_SIZE(ph1_ld4_pins),
-       .owner = THIS_MODULE,
-};
-
-static int ph1_ld4_pinctrl_probe(struct platform_device *pdev)
-{
-       return uniphier_pinctrl_probe(pdev, &ph1_ld4_pinctrl_desc,
-                                     &ph1_ld4_pindata);
-}
-
-static const struct of_device_id ph1_ld4_pinctrl_match[] = {
-       { .compatible = "socionext,ph1-ld4-pinctrl" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, ph1_ld4_pinctrl_match);
-
-static struct platform_driver ph1_ld4_pinctrl_driver = {
-       .probe = ph1_ld4_pinctrl_probe,
-       .remove = uniphier_pinctrl_remove,
-       .driver = {
-               .name = DRIVER_NAME,
-               .of_match_table = ph1_ld4_pinctrl_match,
-       },
-};
-module_platform_driver(ph1_ld4_pinctrl_driver);
-
-MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
-MODULE_DESCRIPTION("UniPhier PH1-LD4 pinctrl driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-ph1-ld6b.c
deleted file mode 100644 (file)
index 1824831..0000000
+++ /dev/null
@@ -1,1279 +0,0 @@
-/*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/platform_device.h>
-
-#include "pinctrl-uniphier.h"
-
-#define DRIVER_NAME "ph1-ld6b-pinctrl"
-
-static const struct pinctrl_pin_desc ph1_ld6b_pins[] = {
-       UNIPHIER_PINCTRL_PIN(0, "ED0", UNIPHIER_PIN_IECTRL_NONE,
-                            0, UNIPHIER_PIN_DRV_4_8,
-                            0, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(1, "ED1", UNIPHIER_PIN_IECTRL_NONE,
-                            1, UNIPHIER_PIN_DRV_4_8,
-                            1, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(2, "ED2", UNIPHIER_PIN_IECTRL_NONE,
-                            2, UNIPHIER_PIN_DRV_4_8,
-                            2, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(3, "ED3", UNIPHIER_PIN_IECTRL_NONE,
-                            3, UNIPHIER_PIN_DRV_4_8,
-                            3, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(4, "ED4", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_4_8,
-                            4, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(5, "ED5", UNIPHIER_PIN_IECTRL_NONE,
-                            5, UNIPHIER_PIN_DRV_4_8,
-                            5, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(6, "ED6", UNIPHIER_PIN_IECTRL_NONE,
-                            6, UNIPHIER_PIN_DRV_4_8,
-                            6, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(7, "ED7", UNIPHIER_PIN_IECTRL_NONE,
-                            7, UNIPHIER_PIN_DRV_4_8,
-                            7, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(8, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_4_8,
-                            8, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(9, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
-                            9, UNIPHIER_PIN_DRV_4_8,
-                            9, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(10, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
-                            10, UNIPHIER_PIN_DRV_4_8,
-                            10, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(11, "ES0", UNIPHIER_PIN_IECTRL_NONE,
-                            11, UNIPHIER_PIN_DRV_4_8,
-                            11, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(12, "ES1", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_4_8,
-                            12, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(13, "ES2", UNIPHIER_PIN_IECTRL_NONE,
-                            13, UNIPHIER_PIN_DRV_4_8,
-                            13, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(14, "XECS1", UNIPHIER_PIN_IECTRL_NONE,
-                            14, UNIPHIER_PIN_DRV_4_8,
-                            14, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(15, "PCA00", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            15, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(16, "PCA01", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            16, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(17, "PCA02", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            17, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(18, "PCA03", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            18, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(19, "PCA04", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            19, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(20, "PCA05", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            20, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(21, "PCA06", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            21, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(22, "PCA07", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            22, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(23, "PCA08", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            23, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(24, "PCA09", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            24, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(25, "PCA10", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            25, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(26, "PCA11", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            26, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(27, "PCA12", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            27, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(28, "PCA13", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            28, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(29, "PCA14", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            29, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(30, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
-                            30, UNIPHIER_PIN_DRV_4_8,
-                            30, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(31, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
-                            31, UNIPHIER_PIN_DRV_4_8,
-                            31, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(32, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
-                            32, UNIPHIER_PIN_DRV_4_8,
-                            32, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(33, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
-                            33, UNIPHIER_PIN_DRV_4_8,
-                            33, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(34, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
-                            34, UNIPHIER_PIN_DRV_4_8,
-                            34, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(35, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
-                            35, UNIPHIER_PIN_DRV_4_8,
-                            35, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(36, "NFRYBY0", UNIPHIER_PIN_IECTRL_NONE,
-                            36, UNIPHIER_PIN_DRV_4_8,
-                            36, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(37, "XNFCE1", UNIPHIER_PIN_IECTRL_NONE,
-                            37, UNIPHIER_PIN_DRV_4_8,
-                            37, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(38, "NFRYBY1", UNIPHIER_PIN_IECTRL_NONE,
-                            38, UNIPHIER_PIN_DRV_4_8,
-                            38, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(39, "NFD0", UNIPHIER_PIN_IECTRL_NONE,
-                            39, UNIPHIER_PIN_DRV_4_8,
-                            39, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(40, "NFD1", UNIPHIER_PIN_IECTRL_NONE,
-                            40, UNIPHIER_PIN_DRV_4_8,
-                            40, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(41, "NFD2", UNIPHIER_PIN_IECTRL_NONE,
-                            41, UNIPHIER_PIN_DRV_4_8,
-                            41, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(42, "NFD3", UNIPHIER_PIN_IECTRL_NONE,
-                            42, UNIPHIER_PIN_DRV_4_8,
-                            42, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(43, "NFD4", UNIPHIER_PIN_IECTRL_NONE,
-                            43, UNIPHIER_PIN_DRV_4_8,
-                            43, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(44, "NFD5", UNIPHIER_PIN_IECTRL_NONE,
-                            44, UNIPHIER_PIN_DRV_4_8,
-                            44, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(45, "NFD6", UNIPHIER_PIN_IECTRL_NONE,
-                            45, UNIPHIER_PIN_DRV_4_8,
-                            45, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(46, "NFD7", UNIPHIER_PIN_IECTRL_NONE,
-                            46, UNIPHIER_PIN_DRV_4_8,
-                            46, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(47, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            0, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(48, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(49, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(50, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(51, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
-                            16, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(52, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
-                            20, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(53, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            53, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(54, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            54, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(55, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            55, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(56, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            56, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(57, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            57, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(58, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            58, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(59, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            59, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(60, "USB2VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            60, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(61, "USB2OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            61, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(62, "USB3VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            62, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(63, "USB3OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            63, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(64, "HS0BCLKOUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            64, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(65, "HS0SYNCOUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            65, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(66, "HS0VALOUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            66, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(67, "HS0DOUT0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            67, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(68, "HS0DOUT1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            68, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(69, "HS0DOUT2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            69, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(70, "HS0DOUT3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            70, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(71, "HS0DOUT4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            71, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(72, "HS0DOUT5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            72, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(73, "HS0DOUT6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            73, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(74, "HS0DOUT7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            74, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(75, "HS1BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            75, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(76, "HS1SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            76, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(77, "HS1VALIN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            77, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(78, "HS1DIN0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            78, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(79, "HS1DIN1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            79, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(80, "HS1DIN2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            80, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(81, "HS1DIN3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            81, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(82, "HS1DIN4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            82, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(83, "HS1DIN5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            83, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(84, "HS1DIN6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            84, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(85, "HS1DIN7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            85, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(86, "HS2BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            86, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(87, "HS2SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            87, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(88, "HS2VALIN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            88, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(89, "HS2DIN0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            89, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(90, "HS2DIN1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            90, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(91, "HS2DIN2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            91, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(92, "HS2DIN3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            92, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(93, "HS2DIN4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            93, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(94, "HS2DIN5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            94, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(95, "HS2DIN6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            95, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(96, "HS2DIN7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            96, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(97, "AO1IEC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            97, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(98, "AO1DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            98, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(99, "AO1BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            99, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(100, "AO1LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            100, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(101, "AO1D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            101, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(102, "AO1D1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            102, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(103, "AO1D2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            103, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(104, "AO1D3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            104, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(105, "AO2DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            105, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(106, "AO2BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            106, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(107, "AO2LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            107, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(108, "AO2D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            108, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(109, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            109, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(110, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            110, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(111, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            111, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(112, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            112, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(113, "SBO0", 0,
-                            113, UNIPHIER_PIN_DRV_4_8,
-                            113, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(114, "SBI0", 0,
-                            114, UNIPHIER_PIN_DRV_4_8,
-                            114, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(115, "TXD1", 0,
-                            115, UNIPHIER_PIN_DRV_4_8,
-                            115, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(116, "RXD1", 0,
-                            116, UNIPHIER_PIN_DRV_4_8,
-                            116, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(117, "PWSRA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            117, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(118, "XIRQ0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            118, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(119, "XIRQ1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            119, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(120, "XIRQ2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            120, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(121, "XIRQ3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            121, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(122, "XIRQ4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            122, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(123, "XIRQ5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            123, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(124, "XIRQ6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            124, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(125, "XIRQ7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            125, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(126, "XIRQ8", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            126, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(127, "PORT00", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            127, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(128, "PORT01", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            128, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(129, "PORT02", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            129, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(130, "PORT03", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            130, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(131, "PORT04", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            131, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(132, "PORT05", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            132, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(133, "PORT06", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            133, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(134, "PORT07", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            134, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(135, "PORT10", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            135, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(136, "PORT11", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            136, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(137, "PORT12", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            137, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(138, "PORT13", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            138, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(139, "PORT14", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            139, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(140, "PORT15", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            140, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(141, "PORT16", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            141, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(142, "LPST", UNIPHIER_PIN_IECTRL_NONE,
-                            142, UNIPHIER_PIN_DRV_4_8,
-                            142, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(143, "MDC", 0,
-                            143, UNIPHIER_PIN_DRV_4_8,
-                            143, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(144, "MDIO", 0,
-                            144, UNIPHIER_PIN_DRV_4_8,
-                            144, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(145, "MDIO_INTL", 0,
-                            145, UNIPHIER_PIN_DRV_4_8,
-                            145, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(146, "PHYRSTL", 0,
-                            146, UNIPHIER_PIN_DRV_4_8,
-                            146, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(147, "RGMII_RXCLK", 0,
-                            147, UNIPHIER_PIN_DRV_4_8,
-                            147, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(148, "RGMII_RXD0", 0,
-                            148, UNIPHIER_PIN_DRV_4_8,
-                            148, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(149, "RGMII_RXD1", 0,
-                            149, UNIPHIER_PIN_DRV_4_8,
-                            149, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(150, "RGMII_RXD2", 0,
-                            150, UNIPHIER_PIN_DRV_4_8,
-                            150, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(151, "RGMII_RXD3", 0,
-                            151, UNIPHIER_PIN_DRV_4_8,
-                            151, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(152, "RGMII_RXCTL", 0,
-                            152, UNIPHIER_PIN_DRV_4_8,
-                            152, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(153, "RGMII_TXCLK", 0,
-                            153, UNIPHIER_PIN_DRV_4_8,
-                            153, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(154, "RGMII_TXD0", 0,
-                            154, UNIPHIER_PIN_DRV_4_8,
-                            154, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(155, "RGMII_TXD1", 0,
-                            155, UNIPHIER_PIN_DRV_4_8,
-                            155, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(156, "RGMII_TXD2", 0,
-                            156, UNIPHIER_PIN_DRV_4_8,
-                            156, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(157, "RGMII_TXD3", 0,
-                            157, UNIPHIER_PIN_DRV_4_8,
-                            157, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(158, "RGMII_TXCTL", 0,
-                            158, UNIPHIER_PIN_DRV_4_8,
-                            158, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(159, "A_D_PCD00OUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            159, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(160, "A_D_PCD01OUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            160, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(161, "A_D_PCD02OUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            161, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(162, "A_D_PCD03OUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            162, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(163, "A_D_PCD04OUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            163, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(164, "A_D_PCD05OUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            164, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(165, "A_D_PCD06OUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            165, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(166, "A_D_PCD07OUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            166, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(167, "A_D_PCD00IN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            167, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(168, "A_D_PCD01IN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            168, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(169, "A_D_PCD02IN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            169, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(170, "A_D_PCD03IN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            170, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(171, "A_D_PCD04IN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            171, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(172, "A_D_PCD05IN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            172, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(173, "A_D_PCD06IN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            173, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(174, "A_D_PCD07IN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            174, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(175, "A_D_PCDNOE", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            175, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(176, "A_D_PC0READY", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            176, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(177, "A_D_PC0CD1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            177, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(178, "A_D_PC0CD2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            178, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(179, "A_D_PC0WAIT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            179, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(180, "A_D_PC0RESET", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            180, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(181, "A_D_PC0CE1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            181, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(182, "A_D_PC0WE", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            182, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(183, "A_D_PC0OE", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            183, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(184, "A_D_PC0IOWR", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            184, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(185, "A_D_PC0IORD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            185, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(186, "A_D_PC0NOE", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            186, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(187, "A_D_HS0BCLKIN", 0,
-                            187, UNIPHIER_PIN_DRV_4_8,
-                            187, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(188, "A_D_HS0SYNCIN", 0,
-                            188, UNIPHIER_PIN_DRV_4_8,
-                            188, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(189, "A_D_HS0VALIN", 0,
-                            189, UNIPHIER_PIN_DRV_4_8,
-                            189, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(190, "A_D_HS0DIN0", 0,
-                            190, UNIPHIER_PIN_DRV_4_8,
-                            190, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(191, "A_D_HS0DIN1", 0,
-                            191, UNIPHIER_PIN_DRV_4_8,
-                            191, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(192, "A_D_HS0DIN2", 0,
-                            192, UNIPHIER_PIN_DRV_4_8,
-                            192, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(193, "A_D_HS0DIN3", 0,
-                            193, UNIPHIER_PIN_DRV_4_8,
-                            193, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(194, "A_D_HS0DIN4", 0,
-                            194, UNIPHIER_PIN_DRV_4_8,
-                            194, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(195, "A_D_HS0DIN5", 0,
-                            195, UNIPHIER_PIN_DRV_4_8,
-                            195, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(196, "A_D_HS0DIN6", 0,
-                            196, UNIPHIER_PIN_DRV_4_8,
-                            196, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(197, "A_D_HS0DIN7", 0,
-                            197, UNIPHIER_PIN_DRV_4_8,
-                            197, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(198, "A_D_AO1ARC", 0,
-                            198, UNIPHIER_PIN_DRV_4_8,
-                            198, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(199, "A_D_SPIXRST", UNIPHIER_PIN_IECTRL_NONE,
-                            199, UNIPHIER_PIN_DRV_4_8,
-                            199, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(200, "A_D_SPISCLK0", UNIPHIER_PIN_IECTRL_NONE,
-                            200, UNIPHIER_PIN_DRV_4_8,
-                            200, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(201, "A_D_SPITXD0", UNIPHIER_PIN_IECTRL_NONE,
-                            201, UNIPHIER_PIN_DRV_4_8,
-                            201, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(202, "A_D_SPIRXD0", UNIPHIER_PIN_IECTRL_NONE,
-                            202, UNIPHIER_PIN_DRV_4_8,
-                            202, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(203, "A_D_DMDCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            203, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(204, "A_D_DMDPSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            204, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(205, "A_D_DMDVAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            205, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(206, "A_D_DMDDATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            206, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(207, "A_D_HDMIRXXIRQ", 0,
-                            207, UNIPHIER_PIN_DRV_4_8,
-                            207, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(208, "A_D_VBIXIRQ", 0,
-                            208, UNIPHIER_PIN_DRV_4_8,
-                            208, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(209, "A_D_HDMITXXIRQ", 0,
-                            209, UNIPHIER_PIN_DRV_4_8,
-                            209, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(210, "A_D_DMDIRQ", UNIPHIER_PIN_IECTRL_NONE,
-                            210, UNIPHIER_PIN_DRV_4_8,
-                            210, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(211, "A_D_SPICIRQ", UNIPHIER_PIN_IECTRL_NONE,
-                            211, UNIPHIER_PIN_DRV_4_8,
-                            211, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(212, "A_D_SPIBIRQ", UNIPHIER_PIN_IECTRL_NONE,
-                            212, UNIPHIER_PIN_DRV_4_8,
-                            212, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(213, "A_D_BESDAOUT", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            213, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(214, "A_D_BESDAIN", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            214, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(215, "A_D_BESCLOUT", UNIPHIER_PIN_IECTRL_NONE,
-                            215, UNIPHIER_PIN_DRV_4_8,
-                            215, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(216, "A_D_VDACCLKOUT", 0,
-                            216, UNIPHIER_PIN_DRV_4_8,
-                            216, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(217, "A_D_VDACDOUT5", 0,
-                            217, UNIPHIER_PIN_DRV_4_8,
-                            217, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(218, "A_D_VDACDOUT6", 0,
-                            218, UNIPHIER_PIN_DRV_4_8,
-                            218, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(219, "A_D_VDACDOUT7", 0,
-                            219, UNIPHIER_PIN_DRV_4_8,
-                            219, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(220, "A_D_VDACDOUT8", 0,
-                            220, UNIPHIER_PIN_DRV_4_8,
-                            220, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(221, "A_D_VDACDOUT9", 0,
-                            221, UNIPHIER_PIN_DRV_4_8,
-                            221, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(222, "A_D_SIFBCKIN", 0,
-                            222, UNIPHIER_PIN_DRV_4_8,
-                            222, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(223, "A_D_SIFLRCKIN", 0,
-                            223, UNIPHIER_PIN_DRV_4_8,
-                            223, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(224, "A_D_SIFDIN", 0,
-                            224, UNIPHIER_PIN_DRV_4_8,
-                            224, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(225, "A_D_LIBCKOUT", 0,
-                            225, UNIPHIER_PIN_DRV_4_8,
-                            225, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(226, "A_D_LILRCKOUT", 0,
-                            226, UNIPHIER_PIN_DRV_4_8,
-                            226, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(227, "A_D_LIDIN", 0,
-                            227, UNIPHIER_PIN_DRV_4_8,
-                            227, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(228, "A_D_LODOUT", 0,
-                            228, UNIPHIER_PIN_DRV_4_8,
-                            228, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(229, "A_D_HPDOUT", 0,
-                            229, UNIPHIER_PIN_DRV_4_8,
-                            229, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(230, "A_D_MCLK", 0,
-                            230, UNIPHIER_PIN_DRV_4_8,
-                            230, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(231, "A_D_A2PLLREFOUT", 0,
-                            231, UNIPHIER_PIN_DRV_4_8,
-                            231, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(232, "A_D_HDMI3DSDAOUT", 0,
-                            232, UNIPHIER_PIN_DRV_4_8,
-                            232, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(233, "A_D_HDMI3DSDAIN", 0,
-                            233, UNIPHIER_PIN_DRV_4_8,
-                            233, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(234, "A_D_HDMI3DSCLIN", 0,
-                            234, UNIPHIER_PIN_DRV_4_8,
-                            234, UNIPHIER_PIN_PULL_DOWN),
-};
-
-static const unsigned adinter_pins[] = {
-       159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
-       173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
-       187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
-       201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
-       215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
-       229, 230, 231, 232, 233, 234,
-};
-static const unsigned adinter_muxvals[] = {
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0,
-};
-static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
-static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
-static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
-static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
-static const unsigned i2c0_pins[] = {109, 110};
-static const unsigned i2c0_muxvals[] = {0, 0};
-static const unsigned i2c1_pins[] = {111, 112};
-static const unsigned i2c1_muxvals[] = {0, 0};
-static const unsigned i2c2_pins[] = {115, 116};
-static const unsigned i2c2_muxvals[] = {1, 1};
-static const unsigned i2c3_pins[] = {118, 119};
-static const unsigned i2c3_muxvals[] = {1, 1};
-static const unsigned nand_pins[] = {30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
-                                    42, 43, 44, 45, 46};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0};
-static const unsigned nand_cs1_pins[] = {37, 38};
-static const unsigned nand_cs1_muxvals[] = {0, 0};
-static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-static const unsigned uart0_pins[] = {135, 136};
-static const unsigned uart0_muxvals[] = {3, 3};
-static const unsigned uart0b_pins[] = {11, 12};
-static const unsigned uart0b_muxvals[] = {2, 2};
-static const unsigned uart1_pins[] = {115, 116};
-static const unsigned uart1_muxvals[] = {0, 0};
-static const unsigned uart1b_pins[] = {113, 114};
-static const unsigned uart1b_muxvals[] = {1, 1};
-static const unsigned uart2_pins[] = {113, 114};
-static const unsigned uart2_muxvals[] = {2, 2};
-static const unsigned uart2b_pins[] = {86, 87};
-static const unsigned uart2b_muxvals[] = {1, 1};
-static const unsigned usb0_pins[] = {56, 57};
-static const unsigned usb0_muxvals[] = {0, 0};
-static const unsigned usb1_pins[] = {58, 59};
-static const unsigned usb1_muxvals[] = {0, 0};
-static const unsigned usb2_pins[] = {60, 61};
-static const unsigned usb2_muxvals[] = {0, 0};
-static const unsigned usb3_pins[] = {62, 63};
-static const unsigned usb3_muxvals[] = {0, 0};
-static const unsigned port_range0_pins[] = {
-       127, 128, 129, 130, 131, 132, 133, 134,         /* PORT0x */
-       135, 136, 137, 138, 139, 140, 141, 142,         /* PORT1x */
-       0, 1, 2, 3, 4, 5, 6, 7,                         /* PORT2x */
-       8, 9, 10, 11, 12, 13, 14, 15,                   /* PORT3x */
-       16, 17, 18, 19, 21, 22, 23, 24,                 /* PORT4x */
-       25, 30, 31, 32, 33, 34, 35, 36,                 /* PORT5x */
-       37, 38, 39, 40, 41, 42, 43, 44,                 /* PORT6x */
-       45, 46, 47, 48, 49, 50, 51, 52,                 /* PORT7x */
-       53, 54, 55, 56, 57, 58, 59, 60,                 /* PORT8x */
-       61, 62, 63, 64, 65, 66, 67, 68,                 /* PORT9x */
-       69, 70, 71, 76, 77, 78, 79, 80,                 /* PORT10x */
-};
-static const unsigned port_range0_muxvals[] = {
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT0x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT1x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT2x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
-};
-static const unsigned port_range1_pins[] = {
-       81, 82, 83, 84, 85, 86, 87, 88,                 /* PORT12x */
-       89, 90, 95, 96, 97, 98, 99, 100,                /* PORT13x */
-       101, 102, 103, 104, 105, 106, 107, 108,         /* PORT14x */
-       118, 119, 120, 121, 122, 123, 124, 125,         /* PORT15x */
-       126, 72, 73, 92, 177, 93, 94, 176,              /* PORT16x */
-       74, 91, 27, 28, 29, 75, 20, 26,                 /* PORT17x */
-       109, 110, 111, 112, 113, 114, 115, 116,         /* PORT18x */
-       117, 143, 144, 145, 146, 147, 148, 149,         /* PORT19x */
-       150, 151, 152, 153, 154, 155, 156, 157,         /* PORT20x */
-       158, 159, 160, 161, 162, 163, 164, 165,         /* PORT21x */
-       166, 178, 179, 180, 181, 182, 183, 184,         /* PORT22x */
-       185, 187, 188, 189, 190, 191, 192, 193,         /* PORT23x */
-       194, 195, 196, 197, 198, 199, 200, 201,         /* PORT24x */
-       202, 203, 204, 205, 206, 207, 208, 209,         /* PORT25x */
-       210, 211, 212, 213, 214, 215, 216, 217,         /* PORT26x */
-       218, 219, 220, 221, 223, 224, 225, 226,         /* PORT27x */
-       227, 228, 229, 230, 231, 232, 233, 234,         /* PORT28x */
-};
-static const unsigned port_range1_muxvals[] = {
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT12x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT13x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT15x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT16x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT17x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT18x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT19x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT20x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT21x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT22x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT23x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT24x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT25x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT26x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT27x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT28x */
-};
-static const unsigned xirq_pins[] = {
-       118, 119, 120, 121, 122, 123, 124, 125,         /* XIRQ0-7 */
-       126, 72, 73, 92, 177, 93, 94, 176,              /* XIRQ8-15 */
-       74, 91, 27, 28, 29, 75, 20, 26,                 /* XIRQ16-23 */
-};
-static const unsigned xirq_muxvals[] = {
-       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ0-7 */
-       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ8-15 */
-       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ16-23 */
-};
-
-static const struct uniphier_pinctrl_group ph1_ld6b_groups[] = {
-       UNIPHIER_PINCTRL_GROUP(adinter),
-       UNIPHIER_PINCTRL_GROUP(emmc),
-       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
-       UNIPHIER_PINCTRL_GROUP(i2c0),
-       UNIPHIER_PINCTRL_GROUP(i2c1),
-       UNIPHIER_PINCTRL_GROUP(i2c2),
-       UNIPHIER_PINCTRL_GROUP(i2c3),
-       UNIPHIER_PINCTRL_GROUP(nand),
-       UNIPHIER_PINCTRL_GROUP(nand_cs1),
-       UNIPHIER_PINCTRL_GROUP(sd),
-       UNIPHIER_PINCTRL_GROUP(uart0),
-       UNIPHIER_PINCTRL_GROUP(uart0b),
-       UNIPHIER_PINCTRL_GROUP(uart1),
-       UNIPHIER_PINCTRL_GROUP(uart1b),
-       UNIPHIER_PINCTRL_GROUP(uart2),
-       UNIPHIER_PINCTRL_GROUP(uart2b),
-       UNIPHIER_PINCTRL_GROUP(usb0),
-       UNIPHIER_PINCTRL_GROUP(usb1),
-       UNIPHIER_PINCTRL_GROUP(usb2),
-       UNIPHIER_PINCTRL_GROUP(usb3),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range1, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range1, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range1, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range1, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range1, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range1, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range1, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range1, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range1, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range1, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range1, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range1, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range1, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range1, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range1, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range1, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range1, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range1, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range1, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range1, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range1, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range1, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range1, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range1, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port150, port_range1, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port151, port_range1, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port152, port_range1, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port153, port_range1, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port154, port_range1, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port155, port_range1, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port156, port_range1, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port157, port_range1, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port160, port_range1, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port161, port_range1, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port162, port_range1, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port163, port_range1, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port164, port_range1, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port165, port_range1, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port166, port_range1, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port167, port_range1, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port170, port_range1, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port171, port_range1, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port172, port_range1, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port173, port_range1, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port174, port_range1, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port175, port_range1, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port176, port_range1, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port177, port_range1, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range1, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range1, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range1, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range1, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range1, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range1, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range1, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range1, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port190, port_range1, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port191, port_range1, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port192, port_range1, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port193, port_range1, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port194, port_range1, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port195, port_range1, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port196, port_range1, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port197, port_range1, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range1, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range1, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range1, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range1, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range1, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range1, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range1, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range1, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range1, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range1, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range1, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range1, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range1, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range1, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range1, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range1, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range1, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range1, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range1, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range1, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range1, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range1, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range1, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range1, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range1, 88),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range1, 89),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range1, 90),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range1, 91),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range1, 92),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range1, 93),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range1, 94),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range1, 95),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range1, 96),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range1, 97),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range1, 98),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range1, 99),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range1, 100),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range1, 101),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range1, 102),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range1, 103),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range1, 104),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range1, 105),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range1, 106),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range1, 107),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range1, 108),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port255, port_range1, 109),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port256, port_range1, 110),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port257, port_range1, 111),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port260, port_range1, 112),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port261, port_range1, 113),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port262, port_range1, 114),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port263, port_range1, 115),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port264, port_range1, 116),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port265, port_range1, 117),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port266, port_range1, 118),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port267, port_range1, 119),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port270, port_range1, 120),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port271, port_range1, 121),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port272, port_range1, 122),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port273, port_range1, 123),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port274, port_range1, 124),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port275, port_range1, 125),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port276, port_range1, 126),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port277, port_range1, 127),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port280, port_range1, 128),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port281, port_range1, 129),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port282, port_range1, 130),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port283, port_range1, 131),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port284, port_range1, 132),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port285, port_range1, 133),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port286, port_range1, 134),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port287, port_range1, 135),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21, xirq, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22, xirq, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23, xirq, 23),
-};
-
-static const char * const adinter_groups[] = {"adinter"};
-static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
-static const char * const i2c0_groups[] = {"i2c0"};
-static const char * const i2c1_groups[] = {"i2c1"};
-static const char * const i2c2_groups[] = {"i2c2"};
-static const char * const i2c3_groups[] = {"i2c3"};
-static const char * const nand_groups[] = {"nand", "nand_cs1"};
-static const char * const sd_groups[] = {"sd"};
-static const char * const uart0_groups[] = {"uart0", "uart0b"};
-static const char * const uart1_groups[] = {"uart1", "uart1b"};
-static const char * const uart2_groups[] = {"uart2", "uart2b"};
-static const char * const usb0_groups[] = {"usb0"};
-static const char * const usb1_groups[] = {"usb1"};
-static const char * const usb2_groups[] = {"usb2"};
-static const char * const usb3_groups[] = {"usb3"};
-static const char * const port_groups[] = {
-       "port00",  "port01",  "port02",  "port03",
-       "port04",  "port05",  "port06",  "port07",
-       "port10",  "port11",  "port12",  "port13",
-       "port14",  "port15",  "port16",  "port17",
-       "port20",  "port21",  "port22",  "port23",
-       "port24",  "port25",  "port26",  "port27",
-       "port30",  "port31",  "port32",  "port33",
-       "port34",  "port35",  "port36",  "port37",
-       "port40",  "port41",  "port42",  "port43",
-       "port44",  "port45",  "port46",  "port47",
-       "port50",  "port51",  "port52",  "port53",
-       "port54",  "port55",  "port56",  "port57",
-       "port60",  "port61",  "port62",  "port63",
-       "port64",  "port65",  "port66",  "port67",
-       "port70",  "port71",  "port72",  "port73",
-       "port74",  "port75",  "port76",  "port77",
-       "port80",  "port81",  "port82",  "port83",
-       "port84",  "port85",  "port86",  "port87",
-       "port90",  "port91",  "port92",  "port93",
-       "port94",  "port95",  "port96",  "port97",
-       "port100", "port101", "port102", "port103",
-       "port104", "port105", "port106", "port107",
-       /* port110-117 missing */
-       "port120", "port121", "port122", "port123",
-       "port124", "port125", "port126", "port127",
-       "port130", "port131", "port132", "port133",
-       "port134", "port135", "port136", "port137",
-       "port140", "port141", "port142", "port143",
-       "port144", "port145", "port146", "port147",
-       "port150", "port151", "port152", "port153",
-       "port154", "port155", "port156", "port157",
-       "port160", "port161", "port162", "port163",
-       "port164", "port165", "port166", "port167",
-       "port170", "port171", "port172", "port173",
-       "port174", "port175", "port176", "port177",
-       "port180", "port181", "port182", "port183",
-       "port184", "port185", "port186", "port187",
-       "port190", "port191", "port192", "port193",
-       "port194", "port195", "port196", "port197",
-       "port200", "port201", "port202", "port203",
-       "port204", "port205", "port206", "port207",
-       "port210", "port211", "port212", "port213",
-       "port214", "port215", "port216", "port217",
-       "port220", "port221", "port222", "port223",
-       "port224", "port225", "port226", "port227",
-       "port230", "port231", "port232", "port233",
-       "port234", "port235", "port236", "port237",
-       "port240", "port241", "port242", "port243",
-       "port244", "port245", "port246", "port247",
-       "port250", "port251", "port252", "port253",
-       "port254", "port255", "port256", "port257",
-       "port260", "port261", "port262", "port263",
-       "port264", "port265", "port266", "port267",
-       "port270", "port271", "port272", "port273",
-       "port274", "port275", "port276", "port277",
-       "port280", "port281", "port282", "port283",
-       "port284", "port285", "port286", "port287",
-};
-static const char * const xirq_groups[] = {
-       "xirq0",  "xirq1",  "xirq2",  "xirq3",
-       "xirq4",  "xirq5",  "xirq6",  "xirq7",
-       "xirq8",  "xirq9",  "xirq10", "xirq11",
-       "xirq12", "xirq13", "xirq14", "xirq15",
-       "xirq16", "xirq17", "xirq18", "xirq19",
-       "xirq20", "xirq21", "xirq22", "xirq23",
-};
-
-static const struct uniphier_pinmux_function ph1_ld6b_functions[] = {
-       UNIPHIER_PINMUX_FUNCTION(adinter), /* Achip-Dchip interconnect */
-       UNIPHIER_PINMUX_FUNCTION(emmc),
-       UNIPHIER_PINMUX_FUNCTION(i2c0),
-       UNIPHIER_PINMUX_FUNCTION(i2c1),
-       UNIPHIER_PINMUX_FUNCTION(i2c2),
-       UNIPHIER_PINMUX_FUNCTION(i2c3),
-       UNIPHIER_PINMUX_FUNCTION(nand),
-       UNIPHIER_PINMUX_FUNCTION(sd),
-       UNIPHIER_PINMUX_FUNCTION(uart0),
-       UNIPHIER_PINMUX_FUNCTION(uart1),
-       UNIPHIER_PINMUX_FUNCTION(uart2),
-       UNIPHIER_PINMUX_FUNCTION(usb0),
-       UNIPHIER_PINMUX_FUNCTION(usb1),
-       UNIPHIER_PINMUX_FUNCTION(usb2),
-       UNIPHIER_PINMUX_FUNCTION(usb3),
-       UNIPHIER_PINMUX_FUNCTION(port),
-       UNIPHIER_PINMUX_FUNCTION(xirq),
-};
-
-static struct uniphier_pinctrl_socdata ph1_ld6b_pindata = {
-       .groups = ph1_ld6b_groups,
-       .groups_count = ARRAY_SIZE(ph1_ld6b_groups),
-       .functions = ph1_ld6b_functions,
-       .functions_count = ARRAY_SIZE(ph1_ld6b_functions),
-       .mux_bits = 8,
-       .reg_stride = 4,
-       .load_pinctrl = false,
-};
-
-static struct pinctrl_desc ph1_ld6b_pinctrl_desc = {
-       .name = DRIVER_NAME,
-       .pins = ph1_ld6b_pins,
-       .npins = ARRAY_SIZE(ph1_ld6b_pins),
-       .owner = THIS_MODULE,
-};
-
-static int ph1_ld6b_pinctrl_probe(struct platform_device *pdev)
-{
-       return uniphier_pinctrl_probe(pdev, &ph1_ld6b_pinctrl_desc,
-                                     &ph1_ld6b_pindata);
-}
-
-static const struct of_device_id ph1_ld6b_pinctrl_match[] = {
-       { .compatible = "socionext,ph1-ld6b-pinctrl" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, ph1_ld6b_pinctrl_match);
-
-static struct platform_driver ph1_ld6b_pinctrl_driver = {
-       .probe = ph1_ld6b_pinctrl_probe,
-       .remove = uniphier_pinctrl_remove,
-       .driver = {
-               .name = DRIVER_NAME,
-               .of_match_table = ph1_ld6b_pinctrl_match,
-       },
-};
-module_platform_driver(ph1_ld6b_pinctrl_driver);
-
-MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
-MODULE_DESCRIPTION("UniPhier PH1-LD6b pinctrl driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c b/drivers/pinctrl/uniphier/pinctrl-ph1-pro4.c
deleted file mode 100644 (file)
index ec8e92d..0000000
+++ /dev/null
@@ -1,1565 +0,0 @@
-/*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program5 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/platform_device.h>
-
-#include "pinctrl-uniphier.h"
-
-#define DRIVER_NAME "ph1-pro4-pinctrl"
-
-static const struct pinctrl_pin_desc ph1_pro4_pins[] = {
-       UNIPHIER_PINCTRL_PIN(0, "CK24O", UNIPHIER_PIN_IECTRL_NONE,
-                            0, UNIPHIER_PIN_DRV_4_8,
-                            0, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(1, "VC27A", UNIPHIER_PIN_IECTRL_NONE,
-                            1, UNIPHIER_PIN_DRV_4_8,
-                            1, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(2, "CK27AI", UNIPHIER_PIN_IECTRL_NONE,
-                            2, UNIPHIER_PIN_DRV_4_8,
-                            2, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(3, "CK27AO", UNIPHIER_PIN_IECTRL_NONE,
-                            3, UNIPHIER_PIN_DRV_4_8,
-                            3, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(4, "CKSEL", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_4_8,
-                            4, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(5, "CK27AV", UNIPHIER_PIN_IECTRL_NONE,
-                            5, UNIPHIER_PIN_DRV_4_8,
-                            5, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(6, "AEXCKA", UNIPHIER_PIN_IECTRL_NONE,
-                            6, UNIPHIER_PIN_DRV_4_8,
-                            6, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(7, "ASEL", UNIPHIER_PIN_IECTRL_NONE,
-                            7, UNIPHIER_PIN_DRV_4_8,
-                            7, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(8, "ARCRESET", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_4_8,
-                            8, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(9, "ARCUNLOCK", UNIPHIER_PIN_IECTRL_NONE,
-                            9, UNIPHIER_PIN_DRV_4_8,
-                            9, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(10, "XSRST", UNIPHIER_PIN_IECTRL_NONE,
-                            10, UNIPHIER_PIN_DRV_4_8,
-                            10, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(11, "XNMIRQ", UNIPHIER_PIN_IECTRL_NONE,
-                            11, UNIPHIER_PIN_DRV_4_8,
-                            11, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(12, "XSCIRQ", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_4_8,
-                            12, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(13, "EXTRG", UNIPHIER_PIN_IECTRL_NONE,
-                            13, UNIPHIER_PIN_DRV_4_8,
-                            13, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(14, "TRCCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            14, UNIPHIER_PIN_DRV_4_8,
-                            14, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(15, "TRCCTL", UNIPHIER_PIN_IECTRL_NONE,
-                            15, UNIPHIER_PIN_DRV_4_8,
-                            15, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(16, "TRCD0", UNIPHIER_PIN_IECTRL_NONE,
-                            16, UNIPHIER_PIN_DRV_4_8,
-                            16, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(17, "TRCD1", UNIPHIER_PIN_IECTRL_NONE,
-                            17, UNIPHIER_PIN_DRV_4_8,
-                            17, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(18, "TRCD2", UNIPHIER_PIN_IECTRL_NONE,
-                            18, UNIPHIER_PIN_DRV_4_8,
-                            18, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(19, "TRCD3", UNIPHIER_PIN_IECTRL_NONE,
-                            19, UNIPHIER_PIN_DRV_4_8,
-                            19, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(20, "TRCD4", UNIPHIER_PIN_IECTRL_NONE,
-                            20, UNIPHIER_PIN_DRV_4_8,
-                            20, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(21, "TRCD5", UNIPHIER_PIN_IECTRL_NONE,
-                            21, UNIPHIER_PIN_DRV_4_8,
-                            21, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(22, "TRCD6", UNIPHIER_PIN_IECTRL_NONE,
-                            22, UNIPHIER_PIN_DRV_4_8,
-                            22, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(23, "TRCD7", UNIPHIER_PIN_IECTRL_NONE,
-                            23, UNIPHIER_PIN_DRV_4_8,
-                            23, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(24, "XECS1", UNIPHIER_PIN_IECTRL_NONE,
-                            24, UNIPHIER_PIN_DRV_4_8,
-                            24, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(25, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
-                            25, UNIPHIER_PIN_DRV_4_8,
-                            25, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(26, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
-                            26, UNIPHIER_PIN_DRV_4_8,
-                            26, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(27, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
-                            27, UNIPHIER_PIN_DRV_4_8,
-                            27, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(28, "ES0", UNIPHIER_PIN_IECTRL_NONE,
-                            28, UNIPHIER_PIN_DRV_4_8,
-                            28, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(29, "ES1", UNIPHIER_PIN_IECTRL_NONE,
-                            29, UNIPHIER_PIN_DRV_4_8,
-                            29, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(30, "ES2", UNIPHIER_PIN_IECTRL_NONE,
-                            30, UNIPHIER_PIN_DRV_4_8,
-                            30, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(31, "ED0", UNIPHIER_PIN_IECTRL_NONE,
-                            31, UNIPHIER_PIN_DRV_4_8,
-                            31, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(32, "ED1", UNIPHIER_PIN_IECTRL_NONE,
-                            32, UNIPHIER_PIN_DRV_4_8,
-                            32, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(33, "ED2", UNIPHIER_PIN_IECTRL_NONE,
-                            33, UNIPHIER_PIN_DRV_4_8,
-                            33, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(34, "ED3", UNIPHIER_PIN_IECTRL_NONE,
-                            34, UNIPHIER_PIN_DRV_4_8,
-                            34, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(35, "ED4", UNIPHIER_PIN_IECTRL_NONE,
-                            35, UNIPHIER_PIN_DRV_4_8,
-                            35, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(36, "ED5", UNIPHIER_PIN_IECTRL_NONE,
-                            36, UNIPHIER_PIN_DRV_4_8,
-                            36, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(37, "ED6", UNIPHIER_PIN_IECTRL_NONE,
-                            37, UNIPHIER_PIN_DRV_4_8,
-                            37, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(38, "ED7", UNIPHIER_PIN_IECTRL_NONE,
-                            38, UNIPHIER_PIN_DRV_4_8,
-                            38, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(39, "BOOTSWAP", UNIPHIER_PIN_IECTRL_NONE,
-                            39, UNIPHIER_PIN_DRV_NONE,
-                            39, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(40, "NFD0", UNIPHIER_PIN_IECTRL_NONE,
-                            2, UNIPHIER_PIN_DRV_8_12_16_20,
-                            40, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(41, "NFD1", UNIPHIER_PIN_IECTRL_NONE,
-                            3, UNIPHIER_PIN_DRV_8_12_16_20,
-                            41, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(42, "NFD2", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_8_12_16_20,
-                            42, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(43, "NFD3", UNIPHIER_PIN_IECTRL_NONE,
-                            5, UNIPHIER_PIN_DRV_8_12_16_20,
-                            43, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(44, "NFD4", UNIPHIER_PIN_IECTRL_NONE,
-                            6, UNIPHIER_PIN_DRV_8_12_16_20,
-                            44, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(45, "NFD5", UNIPHIER_PIN_IECTRL_NONE,
-                            7, UNIPHIER_PIN_DRV_8_12_16_20,
-                            45, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(46, "NFD6", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_8_12_16_20,
-                            46, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(47, "NFD7", UNIPHIER_PIN_IECTRL_NONE,
-                            9, UNIPHIER_PIN_DRV_8_12_16_20,
-                            47, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(48, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
-                            48, UNIPHIER_PIN_DRV_4_8,
-                            48, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(49, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
-                            49, UNIPHIER_PIN_DRV_4_8,
-                            49, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(50, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
-                            50, UNIPHIER_PIN_DRV_4_8,
-                            50, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(51, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
-                            0, UNIPHIER_PIN_DRV_8_12_16_20,
-                            51, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(52, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
-                            52, UNIPHIER_PIN_DRV_4_8,
-                            52, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(53, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
-                            1, UNIPHIER_PIN_DRV_8_12_16_20,
-                            53, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(54, "NRYBY0", UNIPHIER_PIN_IECTRL_NONE,
-                            54, UNIPHIER_PIN_DRV_4_8,
-                            54, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(55, "DMDSCLTST", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_NONE,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(56, "DMDSDATST", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(57, "AGCI0", 3,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            55, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(58, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(59, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(60, "AGCBS0", 5,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            56, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(61, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(62, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(63, "ANTSHORT", UNIPHIER_PIN_IECTRL_NONE,
-                            57, UNIPHIER_PIN_DRV_4_8,
-                            57, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(64, "CH0CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            58, UNIPHIER_PIN_DRV_4_8,
-                            58, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(65, "CH0VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            59, UNIPHIER_PIN_DRV_4_8,
-                            59, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(66, "CH0PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            60, UNIPHIER_PIN_DRV_4_8,
-                            60, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(67, "CH0DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            61, UNIPHIER_PIN_DRV_4_8,
-                            61, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(68, "CH1CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            62, UNIPHIER_PIN_DRV_4_8,
-                            62, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(69, "CH1VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            63, UNIPHIER_PIN_DRV_4_8,
-                            63, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(70, "CH1PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            64, UNIPHIER_PIN_DRV_4_8,
-                            64, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(71, "CH1DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            65, UNIPHIER_PIN_DRV_4_8,
-                            65, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(72, "CH2CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            66, UNIPHIER_PIN_DRV_4_8,
-                            66, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(73, "CH2VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            67, UNIPHIER_PIN_DRV_4_8,
-                            67, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(74, "CH2PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            68, UNIPHIER_PIN_DRV_4_8,
-                            68, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(75, "CH2DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            69, UNIPHIER_PIN_DRV_4_8,
-                            69, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(76, "CH3CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            70, UNIPHIER_PIN_DRV_4_8,
-                            70, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(77, "CH3VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            71, UNIPHIER_PIN_DRV_4_8,
-                            71, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(78, "CH3PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            72, UNIPHIER_PIN_DRV_4_8,
-                            72, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(79, "CH3DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            73, UNIPHIER_PIN_DRV_4_8,
-                            73, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(80, "CH4CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            74, UNIPHIER_PIN_DRV_4_8,
-                            74, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(81, "CH4VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            75, UNIPHIER_PIN_DRV_4_8,
-                            75, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(82, "CH4PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            76, UNIPHIER_PIN_DRV_4_8,
-                            76, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(83, "CH4DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            77, UNIPHIER_PIN_DRV_4_8,
-                            77, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(84, "CH5CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            78, UNIPHIER_PIN_DRV_4_8,
-                            78, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(85, "CH5VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            79, UNIPHIER_PIN_DRV_4_8,
-                            79, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(86, "CH5PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            80, UNIPHIER_PIN_DRV_4_8,
-                            80, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(87, "CH5DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            81, UNIPHIER_PIN_DRV_4_8,
-                            81, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(88, "CH6CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            82, UNIPHIER_PIN_DRV_4_8,
-                            82, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(89, "CH6VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            83, UNIPHIER_PIN_DRV_4_8,
-                            83, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(90, "CH6PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            84, UNIPHIER_PIN_DRV_4_8,
-                            84, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(91, "CH6DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            85, UNIPHIER_PIN_DRV_4_8,
-                            85, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(92, "CKFEO", UNIPHIER_PIN_IECTRL_NONE,
-                            86, UNIPHIER_PIN_DRV_4_8,
-                            86, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(93, "XFERST", UNIPHIER_PIN_IECTRL_NONE,
-                            87, UNIPHIER_PIN_DRV_4_8,
-                            87, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(94, "P_FE_ON", UNIPHIER_PIN_IECTRL_NONE,
-                            88, UNIPHIER_PIN_DRV_4_8,
-                            88, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(95, "P_TU0_ON", UNIPHIER_PIN_IECTRL_NONE,
-                            89, UNIPHIER_PIN_DRV_4_8,
-                            89, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(96, "XFEIRQ0", UNIPHIER_PIN_IECTRL_NONE,
-                            90, UNIPHIER_PIN_DRV_4_8,
-                            90, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(97, "XFEIRQ1", UNIPHIER_PIN_IECTRL_NONE,
-                            91, UNIPHIER_PIN_DRV_4_8,
-                            91, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(98, "XFEIRQ2", UNIPHIER_PIN_IECTRL_NONE,
-                            92, UNIPHIER_PIN_DRV_4_8,
-                            92, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(99, "XFEIRQ3", UNIPHIER_PIN_IECTRL_NONE,
-                            93, UNIPHIER_PIN_DRV_4_8,
-                            93, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(100, "XFEIRQ4", UNIPHIER_PIN_IECTRL_NONE,
-                            94, UNIPHIER_PIN_DRV_4_8,
-                            94, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(101, "XFEIRQ5", UNIPHIER_PIN_IECTRL_NONE,
-                            95, UNIPHIER_PIN_DRV_4_8,
-                            95, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(102, "XFEIRQ6", UNIPHIER_PIN_IECTRL_NONE,
-                            96, UNIPHIER_PIN_DRV_4_8,
-                            96, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(103, "SMTCLK0", UNIPHIER_PIN_IECTRL_NONE,
-                            97, UNIPHIER_PIN_DRV_4_8,
-                            97, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(104, "SMTRST0", UNIPHIER_PIN_IECTRL_NONE,
-                            98, UNIPHIER_PIN_DRV_4_8,
-                            98, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(105, "SMTCMD0", UNIPHIER_PIN_IECTRL_NONE,
-                            99, UNIPHIER_PIN_DRV_4_8,
-                            99, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(106, "SMTD0", UNIPHIER_PIN_IECTRL_NONE,
-                            100, UNIPHIER_PIN_DRV_4_8,
-                            100, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(107, "SMTSEL0", UNIPHIER_PIN_IECTRL_NONE,
-                            101, UNIPHIER_PIN_DRV_4_8,
-                            101, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(108, "SMTDET0", UNIPHIER_PIN_IECTRL_NONE,
-                            102, UNIPHIER_PIN_DRV_4_8,
-                            102, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(109, "SMTCLK1", UNIPHIER_PIN_IECTRL_NONE,
-                            103, UNIPHIER_PIN_DRV_4_8,
-                            103, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(110, "SMTRST1", UNIPHIER_PIN_IECTRL_NONE,
-                            104, UNIPHIER_PIN_DRV_4_8,
-                            104, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(111, "SMTCMD1", UNIPHIER_PIN_IECTRL_NONE,
-                            105, UNIPHIER_PIN_DRV_4_8,
-                            105, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(112, "SMTD1", UNIPHIER_PIN_IECTRL_NONE,
-                            106, UNIPHIER_PIN_DRV_4_8,
-                            106, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(113, "SMTSEL1", UNIPHIER_PIN_IECTRL_NONE,
-                            107, UNIPHIER_PIN_DRV_4_8,
-                            107, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(114, "SMTDET1", UNIPHIER_PIN_IECTRL_NONE,
-                            108, UNIPHIER_PIN_DRV_4_8,
-                            108, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(115, "XINTM", UNIPHIER_PIN_IECTRL_NONE,
-                            109, UNIPHIER_PIN_DRV_4_8,
-                            109, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(116, "SCLKM", UNIPHIER_PIN_IECTRL_NONE,
-                            110, UNIPHIER_PIN_DRV_4_8,
-                            110, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(117, "SBMTP", UNIPHIER_PIN_IECTRL_NONE,
-                            111, UNIPHIER_PIN_DRV_4_8,
-                            111, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(118, "SBPTM", UNIPHIER_PIN_IECTRL_NONE,
-                            112, UNIPHIER_PIN_DRV_4_8,
-                            112, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(119, "XMPREQ", UNIPHIER_PIN_IECTRL_NONE,
-                            113, UNIPHIER_PIN_DRV_4_8,
-                            113, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(120, "XINTP", UNIPHIER_PIN_IECTRL_NONE,
-                            114, UNIPHIER_PIN_DRV_4_8,
-                            114, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(121, "LPST", UNIPHIER_PIN_IECTRL_NONE,
-                            115, UNIPHIER_PIN_DRV_4_8,
-                            115, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(122, "SDBOOT", UNIPHIER_PIN_IECTRL_NONE,
-                            116, UNIPHIER_PIN_DRV_4_8,
-                            116, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(123, "BFAIL", UNIPHIER_PIN_IECTRL_NONE,
-                            117, UNIPHIER_PIN_DRV_4_8,
-                            117, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(124, "XFWE", UNIPHIER_PIN_IECTRL_NONE,
-                            118, UNIPHIER_PIN_DRV_4_8,
-                            118, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(125, "RF_COM_RDY", UNIPHIER_PIN_IECTRL_NONE,
-                            119, UNIPHIER_PIN_DRV_4_8,
-                            119, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(126, "XDIAG0", UNIPHIER_PIN_IECTRL_NONE,
-                            120, UNIPHIER_PIN_DRV_4_8,
-                            120, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(127, "RXD0", UNIPHIER_PIN_IECTRL_NONE,
-                            121, UNIPHIER_PIN_DRV_4_8,
-                            121, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(128, "TXD0", UNIPHIER_PIN_IECTRL_NONE,
-                            122, UNIPHIER_PIN_DRV_4_8,
-                            122, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(129, "RXD1", UNIPHIER_PIN_IECTRL_NONE,
-                            123, UNIPHIER_PIN_DRV_4_8,
-                            123, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(130, "TXD1", UNIPHIER_PIN_IECTRL_NONE,
-                            124, UNIPHIER_PIN_DRV_4_8,
-                            124, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(131, "RXD2", UNIPHIER_PIN_IECTRL_NONE,
-                            125, UNIPHIER_PIN_DRV_4_8,
-                            125, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(132, "TXD2", UNIPHIER_PIN_IECTRL_NONE,
-                            126, UNIPHIER_PIN_DRV_4_8,
-                            126, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(133, "SS0CS", UNIPHIER_PIN_IECTRL_NONE,
-                            127, UNIPHIER_PIN_DRV_4_8,
-                            127, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(134, "SS0CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            128, UNIPHIER_PIN_DRV_4_8,
-                            128, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(135, "SS0DO", UNIPHIER_PIN_IECTRL_NONE,
-                            129, UNIPHIER_PIN_DRV_4_8,
-                            129, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(136, "SS0DI", UNIPHIER_PIN_IECTRL_NONE,
-                            130, UNIPHIER_PIN_DRV_4_8,
-                            130, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(137, "MS0CS0", UNIPHIER_PIN_IECTRL_NONE,
-                            131, UNIPHIER_PIN_DRV_4_8,
-                            131, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(138, "MS0CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            132, UNIPHIER_PIN_DRV_4_8,
-                            132, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(139, "MS0DI", UNIPHIER_PIN_IECTRL_NONE,
-                            133, UNIPHIER_PIN_DRV_4_8,
-                            133, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(140, "MS0DO", UNIPHIER_PIN_IECTRL_NONE,
-                            134, UNIPHIER_PIN_DRV_4_8,
-                            134, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(141, "XMDMRST", UNIPHIER_PIN_IECTRL_NONE,
-                            135, UNIPHIER_PIN_DRV_4_8,
-                            135, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(142, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(143, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(144, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(145, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(146, "SCL2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(147, "SDA2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(148, "SCL3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(149, "SDA3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(150, "SD0DAT0", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_8_12_16_20,
-                            136, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(151, "SD0DAT1", UNIPHIER_PIN_IECTRL_NONE,
-                            13, UNIPHIER_PIN_DRV_8_12_16_20,
-                            137, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(152, "SD0DAT2", UNIPHIER_PIN_IECTRL_NONE,
-                            14, UNIPHIER_PIN_DRV_8_12_16_20,
-                            138, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(153, "SD0DAT3", UNIPHIER_PIN_IECTRL_NONE,
-                            15, UNIPHIER_PIN_DRV_8_12_16_20,
-                            139, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(154, "SD0CMD", UNIPHIER_PIN_IECTRL_NONE,
-                            11, UNIPHIER_PIN_DRV_8_12_16_20,
-                            141, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(155, "SD0CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            10, UNIPHIER_PIN_DRV_8_12_16_20,
-                            140, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(156, "SD0CD", UNIPHIER_PIN_IECTRL_NONE,
-                            142, UNIPHIER_PIN_DRV_4_8,
-                            142, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(157, "SD0WP", UNIPHIER_PIN_IECTRL_NONE,
-                            143, UNIPHIER_PIN_DRV_4_8,
-                            143, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(158, "SD0VTCG", UNIPHIER_PIN_IECTRL_NONE,
-                            144, UNIPHIER_PIN_DRV_4_8,
-                            144, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(159, "CK25O", UNIPHIER_PIN_IECTRL_NONE,
-                            145, UNIPHIER_PIN_DRV_4_8,
-                            145, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(160, "RGMII_TXCLK", 6,
-                            146, UNIPHIER_PIN_DRV_4_8,
-                            146, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(161, "RGMII_TXD0", 6,
-                            147, UNIPHIER_PIN_DRV_4_8,
-                            147, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(162, "RGMII_TXD1", 6,
-                            148, UNIPHIER_PIN_DRV_4_8,
-                            148, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(163, "RGMII_TXD2", 6,
-                            149, UNIPHIER_PIN_DRV_4_8,
-                            149, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(164, "RGMII_TXD3", 6,
-                            150, UNIPHIER_PIN_DRV_4_8,
-                            150, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(165, "RGMII_TXCTL", 6,
-                            151, UNIPHIER_PIN_DRV_4_8,
-                            151, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(166, "MII_TXER", UNIPHIER_PIN_IECTRL_NONE,
-                            152, UNIPHIER_PIN_DRV_4_8,
-                            152, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(167, "RGMII_RXCLK", 6,
-                            153, UNIPHIER_PIN_DRV_4_8,
-                            153, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(168, "RGMII_RXD0", 6,
-                            154, UNIPHIER_PIN_DRV_4_8,
-                            154, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(169, "RGMII_RXD1", 6,
-                            155, UNIPHIER_PIN_DRV_4_8,
-                            155, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(170, "RGMII_RXD2", 6,
-                            156, UNIPHIER_PIN_DRV_4_8,
-                            156, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(171, "RGMII_RXD3", 6,
-                            157, UNIPHIER_PIN_DRV_4_8,
-                            157, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(172, "RGMII_RXCTL", 6,
-                            158, UNIPHIER_PIN_DRV_4_8,
-                            158, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(173, "MII_RXER", 6,
-                            159, UNIPHIER_PIN_DRV_4_8,
-                            159, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(174, "MII_CRS", 6,
-                            160, UNIPHIER_PIN_DRV_4_8,
-                            160, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(175, "MII_COL", 6,
-                            161, UNIPHIER_PIN_DRV_4_8,
-                            161, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(176, "MDC", 6,
-                            162, UNIPHIER_PIN_DRV_4_8,
-                            162, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(177, "MDIO", 6,
-                            163, UNIPHIER_PIN_DRV_4_8,
-                            163, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(178, "MDIO_INTL", 6,
-                            164, UNIPHIER_PIN_DRV_4_8,
-                            164, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(179, "XETH_RST", 6,
-                            165, UNIPHIER_PIN_DRV_4_8,
-                            165, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(180, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            166, UNIPHIER_PIN_DRV_4_8,
-                            166, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(181, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
-                            167, UNIPHIER_PIN_DRV_4_8,
-                            167, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(182, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            168, UNIPHIER_PIN_DRV_4_8,
-                            168, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(183, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
-                            169, UNIPHIER_PIN_DRV_4_8,
-                            169, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(184, "USB2VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            170, UNIPHIER_PIN_DRV_4_8,
-                            170, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(185, "USB2OD", UNIPHIER_PIN_IECTRL_NONE,
-                            171, UNIPHIER_PIN_DRV_4_8,
-                            171, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(186, "USB2ID", UNIPHIER_PIN_IECTRL_NONE,
-                            172, UNIPHIER_PIN_DRV_4_8,
-                            172, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(187, "USB3VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            173, UNIPHIER_PIN_DRV_4_8,
-                            173, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(188, "USB3OD", UNIPHIER_PIN_IECTRL_NONE,
-                            174, UNIPHIER_PIN_DRV_4_8,
-                            174, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(189, "LINKCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            175, UNIPHIER_PIN_DRV_4_8,
-                            175, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(190, "LINKREQ", UNIPHIER_PIN_IECTRL_NONE,
-                            176, UNIPHIER_PIN_DRV_4_8,
-                            176, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(191, "LINKCTL0", UNIPHIER_PIN_IECTRL_NONE,
-                            177, UNIPHIER_PIN_DRV_4_8,
-                            177, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(192, "LINKCTL1", UNIPHIER_PIN_IECTRL_NONE,
-                            178, UNIPHIER_PIN_DRV_4_8,
-                            178, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(193, "LINKDT0", UNIPHIER_PIN_IECTRL_NONE,
-                            179, UNIPHIER_PIN_DRV_4_8,
-                            179, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(194, "LINKDT1", UNIPHIER_PIN_IECTRL_NONE,
-                            180, UNIPHIER_PIN_DRV_4_8,
-                            180, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(195, "LINKDT2", UNIPHIER_PIN_IECTRL_NONE,
-                            181, UNIPHIER_PIN_DRV_4_8,
-                            181, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(196, "LINKDT3", UNIPHIER_PIN_IECTRL_NONE,
-                            182, UNIPHIER_PIN_DRV_4_8,
-                            182, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(197, "LINKDT4", UNIPHIER_PIN_IECTRL_NONE,
-                            183, UNIPHIER_PIN_DRV_4_8,
-                            183, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(198, "LINKDT5", UNIPHIER_PIN_IECTRL_NONE,
-                            184, UNIPHIER_PIN_DRV_4_8,
-                            184, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(199, "LINKDT6", UNIPHIER_PIN_IECTRL_NONE,
-                            185, UNIPHIER_PIN_DRV_4_8,
-                            185, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(200, "LINKDT7", UNIPHIER_PIN_IECTRL_NONE,
-                            186, UNIPHIER_PIN_DRV_4_8,
-                            186, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(201, "CKDVO", UNIPHIER_PIN_IECTRL_NONE,
-                            187, UNIPHIER_PIN_DRV_4_8,
-                            187, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(202, "PHY_PD", UNIPHIER_PIN_IECTRL_NONE,
-                            188, UNIPHIER_PIN_DRV_4_8,
-                            188, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(203, "X1394_RST", UNIPHIER_PIN_IECTRL_NONE,
-                            189, UNIPHIER_PIN_DRV_4_8,
-                            189, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(204, "VOUT_MUTE_L", UNIPHIER_PIN_IECTRL_NONE,
-                            190, UNIPHIER_PIN_DRV_4_8,
-                            190, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(205, "CLK54O", UNIPHIER_PIN_IECTRL_NONE,
-                            191, UNIPHIER_PIN_DRV_4_8,
-                            191, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(206, "CLK54I", UNIPHIER_PIN_IECTRL_NONE,
-                            192, UNIPHIER_PIN_DRV_NONE,
-                            192, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(207, "YIN0", UNIPHIER_PIN_IECTRL_NONE,
-                            193, UNIPHIER_PIN_DRV_4_8,
-                            193, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(208, "YIN1", UNIPHIER_PIN_IECTRL_NONE,
-                            194, UNIPHIER_PIN_DRV_4_8,
-                            194, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(209, "YIN2", UNIPHIER_PIN_IECTRL_NONE,
-                            195, UNIPHIER_PIN_DRV_4_8,
-                            195, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(210, "YIN3", UNIPHIER_PIN_IECTRL_NONE,
-                            196, UNIPHIER_PIN_DRV_4_8,
-                            196, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(211, "YIN4", UNIPHIER_PIN_IECTRL_NONE,
-                            197, UNIPHIER_PIN_DRV_4_8,
-                            197, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(212, "YIN5", UNIPHIER_PIN_IECTRL_NONE,
-                            198, UNIPHIER_PIN_DRV_4_8,
-                            198, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(213, "CIN0", UNIPHIER_PIN_IECTRL_NONE,
-                            199, UNIPHIER_PIN_DRV_4_8,
-                            199, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(214, "CIN1", UNIPHIER_PIN_IECTRL_NONE,
-                            200, UNIPHIER_PIN_DRV_4_8,
-                            200, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(215, "CIN2", UNIPHIER_PIN_IECTRL_NONE,
-                            201, UNIPHIER_PIN_DRV_4_8,
-                            201, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(216, "CIN3", UNIPHIER_PIN_IECTRL_NONE,
-                            202, UNIPHIER_PIN_DRV_4_8,
-                            202, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(217, "CIN4", UNIPHIER_PIN_IECTRL_NONE,
-                            203, UNIPHIER_PIN_DRV_4_8,
-                            203, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(218, "CIN5", UNIPHIER_PIN_IECTRL_NONE,
-                            204, UNIPHIER_PIN_DRV_4_8,
-                            204, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(219, "GCP", UNIPHIER_PIN_IECTRL_NONE,
-                            205, UNIPHIER_PIN_DRV_4_8,
-                            205, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(220, "ADFLG", UNIPHIER_PIN_IECTRL_NONE,
-                            206, UNIPHIER_PIN_DRV_4_8,
-                            206, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(221, "CK27AIOF", UNIPHIER_PIN_IECTRL_NONE,
-                            207, UNIPHIER_PIN_DRV_4_8,
-                            207, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(222, "DACOUT", UNIPHIER_PIN_IECTRL_NONE,
-                            208, UNIPHIER_PIN_DRV_4_8,
-                            208, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(223, "DAFLG", UNIPHIER_PIN_IECTRL_NONE,
-                            209, UNIPHIER_PIN_DRV_4_8,
-                            209, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(224, "VBIH", UNIPHIER_PIN_IECTRL_NONE,
-                            210, UNIPHIER_PIN_DRV_4_8,
-                            210, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(225, "VBIL", UNIPHIER_PIN_IECTRL_NONE,
-                            211, UNIPHIER_PIN_DRV_4_8,
-                            211, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(226, "XSUB_RST", UNIPHIER_PIN_IECTRL_NONE,
-                            212, UNIPHIER_PIN_DRV_4_8,
-                            212, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(227, "XADC_PD", UNIPHIER_PIN_IECTRL_NONE,
-                            213, UNIPHIER_PIN_DRV_4_8,
-                            213, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(228, "AI1ADCCK", UNIPHIER_PIN_IECTRL_NONE,
-                            214, UNIPHIER_PIN_DRV_4_8,
-                            214, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(229, "AI1BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            215, UNIPHIER_PIN_DRV_4_8,
-                            215, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(230, "AI1LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            216, UNIPHIER_PIN_DRV_4_8,
-                            216, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(231, "AI1DMIX", UNIPHIER_PIN_IECTRL_NONE,
-                            217, UNIPHIER_PIN_DRV_4_8,
-                            217, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(232, "CK27HD", UNIPHIER_PIN_IECTRL_NONE,
-                            218, UNIPHIER_PIN_DRV_4_8,
-                            218, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(233, "XHD_RST", UNIPHIER_PIN_IECTRL_NONE,
-                            219, UNIPHIER_PIN_DRV_4_8,
-                            219, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(234, "INTHD", UNIPHIER_PIN_IECTRL_NONE,
-                            220, UNIPHIER_PIN_DRV_4_8,
-                            220, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(235, "VO1HDCK", UNIPHIER_PIN_IECTRL_NONE,
-                            221, UNIPHIER_PIN_DRV_4_8,
-                            221, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(236, "VO1HSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            222, UNIPHIER_PIN_DRV_4_8,
-                            222, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(237, "VO1VSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            223, UNIPHIER_PIN_DRV_4_8,
-                            223, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(238, "VO1DE", UNIPHIER_PIN_IECTRL_NONE,
-                            224, UNIPHIER_PIN_DRV_4_8,
-                            224, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(239, "VO1Y0", UNIPHIER_PIN_IECTRL_NONE,
-                            225, UNIPHIER_PIN_DRV_4_8,
-                            225, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(240, "VO1Y1", UNIPHIER_PIN_IECTRL_NONE,
-                            226, UNIPHIER_PIN_DRV_4_8,
-                            226, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(241, "VO1Y2", UNIPHIER_PIN_IECTRL_NONE,
-                            227, UNIPHIER_PIN_DRV_4_8,
-                            227, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(242, "VO1Y3", UNIPHIER_PIN_IECTRL_NONE,
-                            228, UNIPHIER_PIN_DRV_4_8,
-                            228, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(243, "VO1Y4", UNIPHIER_PIN_IECTRL_NONE,
-                            229, UNIPHIER_PIN_DRV_4_8,
-                            229, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(244, "VO1Y5", UNIPHIER_PIN_IECTRL_NONE,
-                            230, UNIPHIER_PIN_DRV_4_8,
-                            230, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(245, "VO1Y6", UNIPHIER_PIN_IECTRL_NONE,
-                            231, UNIPHIER_PIN_DRV_4_8,
-                            231, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(246, "VO1Y7", UNIPHIER_PIN_IECTRL_NONE,
-                            232, UNIPHIER_PIN_DRV_4_8,
-                            232, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(247, "VO1Y8", UNIPHIER_PIN_IECTRL_NONE,
-                            233, UNIPHIER_PIN_DRV_4_8,
-                            233, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(248, "VO1Y9", UNIPHIER_PIN_IECTRL_NONE,
-                            234, UNIPHIER_PIN_DRV_4_8,
-                            234, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(249, "VO1Y10", UNIPHIER_PIN_IECTRL_NONE,
-                            235, UNIPHIER_PIN_DRV_4_8,
-                            235, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(250, "VO1Y11", UNIPHIER_PIN_IECTRL_NONE,
-                            236, UNIPHIER_PIN_DRV_4_8,
-                            236, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(251, "VO1CB0", UNIPHIER_PIN_IECTRL_NONE,
-                            237, UNIPHIER_PIN_DRV_4_8,
-                            237, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(252, "VO1CB1", UNIPHIER_PIN_IECTRL_NONE,
-                            238, UNIPHIER_PIN_DRV_4_8,
-                            238, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(253, "VO1CB2", UNIPHIER_PIN_IECTRL_NONE,
-                            239, UNIPHIER_PIN_DRV_4_8,
-                            239, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(254, "VO1CB3", UNIPHIER_PIN_IECTRL_NONE,
-                            240, UNIPHIER_PIN_DRV_4_8,
-                            240, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(255, "VO1CB4", UNIPHIER_PIN_IECTRL_NONE,
-                            241, UNIPHIER_PIN_DRV_4_8,
-                            241, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(256, "VO1CB5", UNIPHIER_PIN_IECTRL_NONE,
-                            242, UNIPHIER_PIN_DRV_4_8,
-                            242, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(257, "VO1CB6", UNIPHIER_PIN_IECTRL_NONE,
-                            243, UNIPHIER_PIN_DRV_4_8,
-                            243, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(258, "VO1CB7", UNIPHIER_PIN_IECTRL_NONE,
-                            244, UNIPHIER_PIN_DRV_4_8,
-                            244, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(259, "VO1CB8", UNIPHIER_PIN_IECTRL_NONE,
-                            245, UNIPHIER_PIN_DRV_4_8,
-                            245, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(260, "VO1CB9", UNIPHIER_PIN_IECTRL_NONE,
-                            246, UNIPHIER_PIN_DRV_4_8,
-                            246, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(261, "VO1CB10", UNIPHIER_PIN_IECTRL_NONE,
-                            247, UNIPHIER_PIN_DRV_4_8,
-                            247, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(262, "VO1CB11", UNIPHIER_PIN_IECTRL_NONE,
-                            248, UNIPHIER_PIN_DRV_4_8,
-                            248, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(263, "VO1CR0", UNIPHIER_PIN_IECTRL_NONE,
-                            249, UNIPHIER_PIN_DRV_4_8,
-                            249, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(264, "VO1CR1", UNIPHIER_PIN_IECTRL_NONE,
-                            250, UNIPHIER_PIN_DRV_4_8,
-                            250, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(265, "VO1CR2", UNIPHIER_PIN_IECTRL_NONE,
-                            251, UNIPHIER_PIN_DRV_4_8,
-                            251, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(266, "VO1CR3", UNIPHIER_PIN_IECTRL_NONE,
-                            252, UNIPHIER_PIN_DRV_4_8,
-                            252, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(267, "VO1CR4", UNIPHIER_PIN_IECTRL_NONE,
-                            253, UNIPHIER_PIN_DRV_4_8,
-                            253, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(268, "VO1CR5", UNIPHIER_PIN_IECTRL_NONE,
-                            254, UNIPHIER_PIN_DRV_4_8,
-                            254, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(269, "VO1CR6", UNIPHIER_PIN_IECTRL_NONE,
-                            255, UNIPHIER_PIN_DRV_4_8,
-                            255, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(270, "VO1CR7", UNIPHIER_PIN_IECTRL_NONE,
-                            256, UNIPHIER_PIN_DRV_4_8,
-                            256, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(271, "VO1CR8", UNIPHIER_PIN_IECTRL_NONE,
-                            257, UNIPHIER_PIN_DRV_4_8,
-                            257, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(272, "VO1CR9", UNIPHIER_PIN_IECTRL_NONE,
-                            258, UNIPHIER_PIN_DRV_4_8,
-                            258, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(273, "VO1CR10", UNIPHIER_PIN_IECTRL_NONE,
-                            259, UNIPHIER_PIN_DRV_4_8,
-                            259, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(274, "VO1CR11", UNIPHIER_PIN_IECTRL_NONE,
-                            260, UNIPHIER_PIN_DRV_4_8,
-                            260, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(275, "VO1EX0", UNIPHIER_PIN_IECTRL_NONE,
-                            261, UNIPHIER_PIN_DRV_4_8,
-                            261, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(276, "VO1EX1", UNIPHIER_PIN_IECTRL_NONE,
-                            262, UNIPHIER_PIN_DRV_4_8,
-                            262, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(277, "VO1EX2", UNIPHIER_PIN_IECTRL_NONE,
-                            263, UNIPHIER_PIN_DRV_4_8,
-                            263, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(278, "VO1EX3", UNIPHIER_PIN_IECTRL_NONE,
-                            264, UNIPHIER_PIN_DRV_4_8,
-                            264, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(279, "VEXCKA", UNIPHIER_PIN_IECTRL_NONE,
-                            265, UNIPHIER_PIN_DRV_4_8,
-                            265, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(280, "VSEL0", UNIPHIER_PIN_IECTRL_NONE,
-                            266, UNIPHIER_PIN_DRV_4_8,
-                            266, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(281, "VSEL1", UNIPHIER_PIN_IECTRL_NONE,
-                            267, UNIPHIER_PIN_DRV_4_8,
-                            267, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(282, "AO1DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            268, UNIPHIER_PIN_DRV_4_8,
-                            268, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(283, "AO1BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            269, UNIPHIER_PIN_DRV_4_8,
-                            269, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(284, "AO1LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            270, UNIPHIER_PIN_DRV_4_8,
-                            270, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(285, "AO1D0", UNIPHIER_PIN_IECTRL_NONE,
-                            271, UNIPHIER_PIN_DRV_4_8,
-                            271, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(286, "AO1D1", UNIPHIER_PIN_IECTRL_NONE,
-                            272, UNIPHIER_PIN_DRV_4_8,
-                            272, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(287, "AO1D2", UNIPHIER_PIN_IECTRL_NONE,
-                            273, UNIPHIER_PIN_DRV_4_8,
-                            273, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(288, "AO1D3", UNIPHIER_PIN_IECTRL_NONE,
-                            274, UNIPHIER_PIN_DRV_4_8,
-                            274, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(289, "AO1IEC", UNIPHIER_PIN_IECTRL_NONE,
-                            275, UNIPHIER_PIN_DRV_4_8,
-                            275, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(290, "XDAC_PD", UNIPHIER_PIN_IECTRL_NONE,
-                            276, UNIPHIER_PIN_DRV_4_8,
-                            276, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(291, "EX_A_MUTE", UNIPHIER_PIN_IECTRL_NONE,
-                            277, UNIPHIER_PIN_DRV_4_8,
-                            277, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(292, "AO2DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            278, UNIPHIER_PIN_DRV_4_8,
-                            278, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(293, "AO2BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            279, UNIPHIER_PIN_DRV_4_8,
-                            279, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(294, "AO2LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            280, UNIPHIER_PIN_DRV_4_8,
-                            280, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(295, "AO2DMIX", UNIPHIER_PIN_IECTRL_NONE,
-                            281, UNIPHIER_PIN_DRV_4_8,
-                            281, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(296, "AO2IEC", UNIPHIER_PIN_IECTRL_NONE,
-                            282, UNIPHIER_PIN_DRV_4_8,
-                            282, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(297, "HTHPD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_5,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(298, "HTSCL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_5,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(299, "HTSDA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_5,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(300, "PORT00", UNIPHIER_PIN_IECTRL_NONE,
-                            284, UNIPHIER_PIN_DRV_4_8,
-                            284, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(301, "PORT01", UNIPHIER_PIN_IECTRL_NONE,
-                            285, UNIPHIER_PIN_DRV_4_8,
-                            285, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(302, "PORT02", UNIPHIER_PIN_IECTRL_NONE,
-                            286, UNIPHIER_PIN_DRV_4_8,
-                            286, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(303, "PORT03", UNIPHIER_PIN_IECTRL_NONE,
-                            287, UNIPHIER_PIN_DRV_4_8,
-                            287, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(304, "PORT04", UNIPHIER_PIN_IECTRL_NONE,
-                            288, UNIPHIER_PIN_DRV_4_8,
-                            288, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(305, "PORT05", UNIPHIER_PIN_IECTRL_NONE,
-                            289, UNIPHIER_PIN_DRV_4_8,
-                            289, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(306, "PORT06", UNIPHIER_PIN_IECTRL_NONE,
-                            290, UNIPHIER_PIN_DRV_4_8,
-                            290, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(307, "PORT07", UNIPHIER_PIN_IECTRL_NONE,
-                            291, UNIPHIER_PIN_DRV_4_8,
-                            291, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(308, "PORT10", UNIPHIER_PIN_IECTRL_NONE,
-                            292, UNIPHIER_PIN_DRV_4_8,
-                            292, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(309, "PORT11", UNIPHIER_PIN_IECTRL_NONE,
-                            293, UNIPHIER_PIN_DRV_4_8,
-                            293, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(310, "PORT12", UNIPHIER_PIN_IECTRL_NONE,
-                            294, UNIPHIER_PIN_DRV_4_8,
-                            294, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(311, "PORT13", UNIPHIER_PIN_IECTRL_NONE,
-                            295, UNIPHIER_PIN_DRV_4_8,
-                            295, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(312, "PORT14", UNIPHIER_PIN_IECTRL_NONE,
-                            296, UNIPHIER_PIN_DRV_4_8,
-                            296, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(313, "PORT15", UNIPHIER_PIN_IECTRL_NONE,
-                            297, UNIPHIER_PIN_DRV_4_8,
-                            297, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(314, "PORT16", UNIPHIER_PIN_IECTRL_NONE,
-                            298, UNIPHIER_PIN_DRV_4_8,
-                            298, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(315, "PORT17", UNIPHIER_PIN_IECTRL_NONE,
-                            299, UNIPHIER_PIN_DRV_4_8,
-                            299, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(316, "PORT20", UNIPHIER_PIN_IECTRL_NONE,
-                            300, UNIPHIER_PIN_DRV_4_8,
-                            300, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(317, "PORT21", UNIPHIER_PIN_IECTRL_NONE,
-                            301, UNIPHIER_PIN_DRV_4_8,
-                            301, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(318, "PORT22", UNIPHIER_PIN_IECTRL_NONE,
-                            302, UNIPHIER_PIN_DRV_4_8,
-                            302, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(319, "SD1DAT0", UNIPHIER_PIN_IECTRL_NONE,
-                            303, UNIPHIER_PIN_DRV_4_8,
-                            303, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(320, "SD1DAT1", UNIPHIER_PIN_IECTRL_NONE,
-                            304, UNIPHIER_PIN_DRV_4_8,
-                            304, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(321, "SD1DAT2", UNIPHIER_PIN_IECTRL_NONE,
-                            305, UNIPHIER_PIN_DRV_4_8,
-                            305, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(322, "SD1DAT3", UNIPHIER_PIN_IECTRL_NONE,
-                            306, UNIPHIER_PIN_DRV_4_8,
-                            306, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(323, "SD1CMD", UNIPHIER_PIN_IECTRL_NONE,
-                            307, UNIPHIER_PIN_DRV_4_8,
-                            307, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(324, "SD1CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            308, UNIPHIER_PIN_DRV_4_8,
-                            308, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(325, "SD1CD", UNIPHIER_PIN_IECTRL_NONE,
-                            309, UNIPHIER_PIN_DRV_4_8,
-                            309, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(326, "SD1WP", UNIPHIER_PIN_IECTRL_NONE,
-                            310, UNIPHIER_PIN_DRV_4_8,
-                            310, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(327, "SD1VTCG", UNIPHIER_PIN_IECTRL_NONE,
-                            311, UNIPHIER_PIN_DRV_4_8,
-                            311, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(328, "DMDISO", UNIPHIER_PIN_IECTRL_NONE,
-                            312, UNIPHIER_PIN_DRV_NONE,
-                            312, UNIPHIER_PIN_PULL_DOWN),
-};
-
-static const unsigned emmc_pins[] = {40, 41, 42, 43, 51, 52, 53};
-static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
-static const unsigned emmc_dat8_pins[] = {44, 45, 46, 47};
-static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
-static const unsigned i2c0_pins[] = {142, 143};
-static const unsigned i2c0_muxvals[] = {0, 0};
-static const unsigned i2c1_pins[] = {144, 145};
-static const unsigned i2c1_muxvals[] = {0, 0};
-static const unsigned i2c2_pins[] = {146, 147};
-static const unsigned i2c2_muxvals[] = {0, 0};
-static const unsigned i2c3_pins[] = {148, 149};
-static const unsigned i2c3_muxvals[] = {0, 0};
-static const unsigned i2c6_pins[] = {308, 309};
-static const unsigned i2c6_muxvals[] = {6, 6};
-static const unsigned nand_pins[] = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
-                                    50, 51, 52, 53, 54};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0};
-static const unsigned nand_cs1_pins[] = {131, 132};
-static const unsigned nand_cs1_muxvals[] = {1, 1};
-static const unsigned sd_pins[] = {150, 151, 152, 153, 154, 155, 156, 157, 158};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-static const unsigned sd1_pins[] = {319, 320, 321, 322, 323, 324, 325, 326,
-                                   327};
-static const unsigned sd1_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-static const unsigned uart0_pins[] = {127, 128};
-static const unsigned uart0_muxvals[] = {0, 0};
-static const unsigned uart1_pins[] = {129, 130};
-static const unsigned uart1_muxvals[] = {0, 0};
-static const unsigned uart2_pins[] = {131, 132};
-static const unsigned uart2_muxvals[] = {0, 0};
-static const unsigned uart3_pins[] = {88, 89};
-static const unsigned uart3_muxvals[] = {2, 2};
-static const unsigned usb0_pins[] = {180, 181};
-static const unsigned usb0_muxvals[] = {0, 0};
-static const unsigned usb1_pins[] = {182, 183};
-static const unsigned usb1_muxvals[] = {0, 0};
-static const unsigned usb2_pins[] = {184, 185};
-static const unsigned usb2_muxvals[] = {0, 0};
-static const unsigned usb3_pins[] = {186, 187};
-static const unsigned usb3_muxvals[] = {0, 0};
-static const unsigned port_range0_pins[] = {
-       300, 301, 302, 303, 304, 305, 306, 307,         /* PORT0x */
-       308, 309, 310, 311, 312, 313, 314, 315,         /* PORT1x */
-       316, 317, 318, 16, 17, 18, 19, 20,              /* PORT2x */
-       21, 22, 23, 4, 93, 94, 95, 63,                  /* PORT3x */
-       123, 122, 124, 125, 126, 141, 202, 203,         /* PORT4x */
-       204, 226, 227, 290, 291, 233, 280, 281,         /* PORT5x */
-       8, 7, 10, 29, 30, 48, 49, 50,                   /* PORT6x */
-       40, 41, 42, 43, 44, 45, 46, 47,                 /* PORT7x */
-       54, 51, 52, 53, 127, 128, 129, 130,             /* PORT8x */
-       131, 132, 57, 60, 134, 133, 135, 136,           /* PORT9x */
-       138, 137, 140, 139, 64, 65, 66, 67,             /* PORT10x */
-       107, 106, 105, 104, 113, 112, 111, 110,         /* PORT11x */
-       68, 69, 70, 71, 72, 73, 74, 75,                 /* PORT12x */
-       76, 77, 78, 79, 80, 81, 82, 83,                 /* PORT13x */
-       84, 85, 86, 87, 88, 89, 90, 91,                 /* PORT14x */
-};
-static const unsigned port_range0_muxvals[] = {
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT0x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT1x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT2x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT3x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT4x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT5x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT6x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT7x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT8x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT9x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT10x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT11x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT12x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT13x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT14x */
-};
-static const unsigned port_range1_pins[] = {
-       13, 14, 15,                                     /* PORT175-177 */
-       157, 158, 156, 154, 150, 151, 152, 153,         /* PORT18x */
-       326, 327, 325, 323, 319, 320, 321, 322,         /* PORT19x */
-       160, 161, 162, 163, 164, 165, 166, 167,         /* PORT20x */
-       168, 169, 170, 171, 172, 173, 174, 175,         /* PORT21x */
-       180, 181, 182, 183, 184, 185, 187, 188,         /* PORT22x */
-       193, 194, 195, 196, 197, 198, 199, 200,         /* PORT23x */
-       191, 192, 215, 216, 217, 218, 219, 220,         /* PORT24x */
-       222, 223, 224, 225, 228, 229, 230, 231,         /* PORT25x */
-       282, 283, 284, 285, 286, 287, 288, 289,         /* PORT26x */
-       292, 293, 294, 295, 296, 236, 237, 238,         /* PORT27x */
-       275, 276, 277, 278, 239, 240, 249, 250,         /* PORT28x */
-       251, 252, 261, 262, 263, 264, 273, 274,         /* PORT29x */
-       31, 32, 33, 34, 35, 36, 37, 38,                 /* PORT30x */
-};
-static const unsigned port_range1_muxvals[] = {
-       7, 7, 7,                                        /* PORT175-177 */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT18x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT19x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT20x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT21x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT22x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT23x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT24x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT25x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT26x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT27x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT28x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT29x */
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT30x */
-};
-static const unsigned xirq_pins[] = {
-       11, 9, 12, 96, 97, 98, 108, 114,                /* XIRQ0-7 */
-       234, 186, 99, 100, 101, 102, 184, 301,          /* XIRQ8-15 */
-       302, 303, 304, 305, 306,                        /* XIRQ16-20 */
-};
-static const unsigned xirq_muxvals[] = {
-       7, 7, 7, 7, 7, 7, 7, 7,                         /* XIRQ0-7 */
-       7, 7, 7, 7, 7, 7, 2, 2,                         /* XIRQ8-15 */
-       2, 2, 2, 2, 2,                                  /* XIRQ16-20 */
-};
-static const unsigned xirq_alternatives_pins[] = {
-       184, 310, 316,
-};
-static const unsigned xirq_alternatives_muxvals[] = {
-       2, 2, 2,
-};
-
-static const struct uniphier_pinctrl_group ph1_pro4_groups[] = {
-       UNIPHIER_PINCTRL_GROUP(emmc),
-       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
-       UNIPHIER_PINCTRL_GROUP(i2c0),
-       UNIPHIER_PINCTRL_GROUP(i2c1),
-       UNIPHIER_PINCTRL_GROUP(i2c2),
-       UNIPHIER_PINCTRL_GROUP(i2c3),
-       UNIPHIER_PINCTRL_GROUP(i2c6),
-       UNIPHIER_PINCTRL_GROUP(nand),
-       UNIPHIER_PINCTRL_GROUP(nand_cs1),
-       UNIPHIER_PINCTRL_GROUP(sd),
-       UNIPHIER_PINCTRL_GROUP(sd1),
-       UNIPHIER_PINCTRL_GROUP(uart0),
-       UNIPHIER_PINCTRL_GROUP(uart1),
-       UNIPHIER_PINCTRL_GROUP(uart2),
-       UNIPHIER_PINCTRL_GROUP(uart3),
-       UNIPHIER_PINCTRL_GROUP(usb0),
-       UNIPHIER_PINCTRL_GROUP(usb1),
-       UNIPHIER_PINCTRL_GROUP(usb2),
-       UNIPHIER_PINCTRL_GROUP(usb3),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_alternatives),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range0, 101),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range0, 102),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range0, 103),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range0, 104),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range0, 105),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range0, 106),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range0, 107),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range0, 108),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range0, 109),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range0, 110),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range0, 111),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range0, 112),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range0, 113),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range0, 114),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range0, 115),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range0, 116),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range0, 117),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range0, 118),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range0, 119),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port175, port_range1, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port176, port_range1, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port177, port_range1, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range1, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range1, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range1, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range1, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range1, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range1, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range1, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range1, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port190, port_range1, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port191, port_range1, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port192, port_range1, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port193, port_range1, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port194, port_range1, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port195, port_range1, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port196, port_range1, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port197, port_range1, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range1, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range1, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range1, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range1, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range1, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range1, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range1, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range1, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range1, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range1, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range1, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range1, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range1, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range1, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range1, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range1, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range1, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range1, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range1, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range1, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range1, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range1, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range1, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range1, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range1, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range1, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range1, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range1, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range1, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range1, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range1, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range1, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range1, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range1, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range1, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range1, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range1, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range1, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range1, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range1, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range1, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range1, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range1, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range1, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range1, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port255, port_range1, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port256, port_range1, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port257, port_range1, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port260, port_range1, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port261, port_range1, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port262, port_range1, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port263, port_range1, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port264, port_range1, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port265, port_range1, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port266, port_range1, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port267, port_range1, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port270, port_range1, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port271, port_range1, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port272, port_range1, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port273, port_range1, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port274, port_range1, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port275, port_range1, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port276, port_range1, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port277, port_range1, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port280, port_range1, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port281, port_range1, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port282, port_range1, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port283, port_range1, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port284, port_range1, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port285, port_range1, 88),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port286, port_range1, 89),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port287, port_range1, 90),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port290, port_range1, 91),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port291, port_range1, 92),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port292, port_range1, 93),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port293, port_range1, 94),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port294, port_range1, 95),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port295, port_range1, 96),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port296, port_range1, 97),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port297, port_range1, 98),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port300, port_range1, 99),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port301, port_range1, 100),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port302, port_range1, 101),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port303, port_range1, 102),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port304, port_range1, 103),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port305, port_range1, 104),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port306, port_range1, 105),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port307, port_range1, 106),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14b, xirq_alternatives, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17b, xirq_alternatives, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18b, xirq_alternatives, 2),
-};
-
-static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
-static const char * const i2c0_groups[] = {"i2c0"};
-static const char * const i2c1_groups[] = {"i2c1"};
-static const char * const i2c2_groups[] = {"i2c2"};
-static const char * const i2c3_groups[] = {"i2c3"};
-static const char * const i2c6_groups[] = {"i2c6"};
-static const char * const nand_groups[] = {"nand", "nand_cs1"};
-static const char * const sd_groups[] = {"sd"};
-static const char * const sd1_groups[] = {"sd1"};
-static const char * const uart0_groups[] = {"uart0"};
-static const char * const uart1_groups[] = {"uart1"};
-static const char * const uart2_groups[] = {"uart2"};
-static const char * const uart3_groups[] = {"uart3"};
-static const char * const usb0_groups[] = {"usb0"};
-static const char * const usb1_groups[] = {"usb1"};
-static const char * const usb2_groups[] = {"usb2"};
-static const char * const usb3_groups[] = {"usb3"};
-static const char * const port_groups[] = {
-       "port00",  "port01",  "port02",  "port03",
-       "port04",  "port05",  "port06",  "port07",
-       "port10",  "port11",  "port12",  "port13",
-       "port14",  "port15",  "port16",  "port17",
-       "port20",  "port21",  "port22",  "port23",
-       "port24",  "port25",  "port26",  "port27",
-       "port30",  "port31",  "port32",  "port33",
-       "port34",  "port35",  "port36",  "port37",
-       "port40",  "port41",  "port42",  "port43",
-       "port44",  "port45",  "port46",  "port47",
-       "port50",  "port51",  "port52",  "port53",
-       "port54",  "port55",  "port56",  "port57",
-       "port60",  "port61",  "port62",  "port63",
-       "port64",  "port65",  "port66",  "port67",
-       "port70",  "port71",  "port72",  "port73",
-       "port74",  "port75",  "port76",  "port77",
-       "port80",  "port81",  "port82",  "port83",
-       "port84",  "port85",  "port86",  "port87",
-       "port90",  "port91",  "port92",  "port93",
-       "port94",  "port95",  "port96",  "port97",
-       "port100", "port101", "port102", "port103",
-       "port104", "port105", "port106", "port107",
-       "port110", "port111", "port112", "port113",
-       "port114", "port115", "port116", "port117",
-       "port120", "port121", "port122", "port123",
-       "port124", "port125", "port126", "port127",
-       "port130", "port131", "port132", "port133",
-       "port134", "port135", "port136", "port137",
-       "port140", "port141", "port142", "port143",
-       "port144", "port145", "port146", "port147",
-       /* port150-174 missing */
-       /* none */ "port175", "port176", "port177",
-       "port180", "port181", "port182", "port183",
-       "port184", "port185", "port186", "port187",
-       "port190", "port191", "port192", "port193",
-       "port194", "port195", "port196", "port197",
-       "port200", "port201", "port202", "port203",
-       "port204", "port205", "port206", "port207",
-       "port210", "port211", "port212", "port213",
-       "port214", "port215", "port216", "port217",
-       "port220", "port221", "port222", "port223",
-       "port224", "port225", "port226", "port227",
-       "port230", "port231", "port232", "port233",
-       "port234", "port235", "port236", "port237",
-       "port240", "port241", "port242", "port243",
-       "port244", "port245", "port246", "port247",
-       "port250", "port251", "port252", "port253",
-       "port254", "port255", "port256", "port257",
-       "port260", "port261", "port262", "port263",
-       "port264", "port265", "port266", "port267",
-       "port270", "port271", "port272", "port273",
-       "port274", "port275", "port276", "port277",
-       "port280", "port281", "port282", "port283",
-       "port284", "port285", "port286", "port287",
-       "port290", "port291", "port292", "port293",
-       "port294", "port295", "port296", "port297",
-       "port300", "port301", "port302", "port303",
-       "port304", "port305", "port306", "port307",
-};
-static const char * const xirq_groups[] = {
-       "xirq0",  "xirq1",  "xirq2",  "xirq3",
-       "xirq4",  "xirq5",  "xirq6",  "xirq7",
-       "xirq8",  "xirq9",  "xirq10", "xirq11",
-       "xirq12", "xirq13", "xirq14", "xirq15",
-       "xirq16", "xirq17", "xirq18", "xirq19",
-       "xirq20",
-       "xirq14b", "xirq17b", "xirq18b",
-};
-
-static const struct uniphier_pinmux_function ph1_pro4_functions[] = {
-       UNIPHIER_PINMUX_FUNCTION(emmc),
-       UNIPHIER_PINMUX_FUNCTION(i2c0),
-       UNIPHIER_PINMUX_FUNCTION(i2c1),
-       UNIPHIER_PINMUX_FUNCTION(i2c2),
-       UNIPHIER_PINMUX_FUNCTION(i2c3),
-       UNIPHIER_PINMUX_FUNCTION(i2c6),
-       UNIPHIER_PINMUX_FUNCTION(nand),
-       UNIPHIER_PINMUX_FUNCTION(sd),
-       UNIPHIER_PINMUX_FUNCTION(sd1),
-       UNIPHIER_PINMUX_FUNCTION(uart0),
-       UNIPHIER_PINMUX_FUNCTION(uart1),
-       UNIPHIER_PINMUX_FUNCTION(uart2),
-       UNIPHIER_PINMUX_FUNCTION(uart3),
-       UNIPHIER_PINMUX_FUNCTION(usb0),
-       UNIPHIER_PINMUX_FUNCTION(usb1),
-       UNIPHIER_PINMUX_FUNCTION(usb2),
-       UNIPHIER_PINMUX_FUNCTION(usb3),
-       UNIPHIER_PINMUX_FUNCTION(port),
-       UNIPHIER_PINMUX_FUNCTION(xirq),
-};
-
-static struct uniphier_pinctrl_socdata ph1_pro4_pindata = {
-       .groups = ph1_pro4_groups,
-       .groups_count = ARRAY_SIZE(ph1_pro4_groups),
-       .functions = ph1_pro4_functions,
-       .functions_count = ARRAY_SIZE(ph1_pro4_functions),
-       .mux_bits = 4,
-       .reg_stride = 8,
-       .load_pinctrl = true,
-};
-
-static struct pinctrl_desc ph1_pro4_pinctrl_desc = {
-       .name = DRIVER_NAME,
-       .pins = ph1_pro4_pins,
-       .npins = ARRAY_SIZE(ph1_pro4_pins),
-       .owner = THIS_MODULE,
-};
-
-static int ph1_pro4_pinctrl_probe(struct platform_device *pdev)
-{
-       return uniphier_pinctrl_probe(pdev, &ph1_pro4_pinctrl_desc,
-                                     &ph1_pro4_pindata);
-}
-
-static const struct of_device_id ph1_pro4_pinctrl_match[] = {
-       { .compatible = "socionext,ph1-pro4-pinctrl" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, ph1_pro4_pinctrl_match);
-
-static struct platform_driver ph1_pro4_pinctrl_driver = {
-       .probe = ph1_pro4_pinctrl_probe,
-       .remove = uniphier_pinctrl_remove,
-       .driver = {
-               .name = DRIVER_NAME,
-               .of_match_table = ph1_pro4_pinctrl_match,
-       },
-};
-module_platform_driver(ph1_pro4_pinctrl_driver);
-
-MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
-MODULE_DESCRIPTION("UniPhier PH1-Pro4 pinctrl driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c b/drivers/pinctrl/uniphier/pinctrl-ph1-pro5.c
deleted file mode 100644 (file)
index e3d648e..0000000
+++ /dev/null
@@ -1,1356 +0,0 @@
-/*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program5 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/platform_device.h>
-
-#include "pinctrl-uniphier.h"
-
-#define DRIVER_NAME "ph1-pro5-pinctrl"
-
-static const struct pinctrl_pin_desc ph1_pro5_pins[] = {
-       UNIPHIER_PINCTRL_PIN(0, "AEXCKA1", 0,
-                            0, UNIPHIER_PIN_DRV_4_8,
-                            0, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(1, "AEXCKA2", 0,
-                            1, UNIPHIER_PIN_DRV_4_8,
-                            1, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(2, "CK27EXI", 0,
-                            2, UNIPHIER_PIN_DRV_4_8,
-                            2, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(3, "CK54EXI", 0,
-                            3, UNIPHIER_PIN_DRV_4_8,
-                            3, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(4, "ED0", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_4_8,
-                            4, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(5, "ED1", UNIPHIER_PIN_IECTRL_NONE,
-                            5, UNIPHIER_PIN_DRV_4_8,
-                            5, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(6, "ED2", UNIPHIER_PIN_IECTRL_NONE,
-                            6, UNIPHIER_PIN_DRV_4_8,
-                            6, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(7, "ED3", UNIPHIER_PIN_IECTRL_NONE,
-                            7, UNIPHIER_PIN_DRV_4_8,
-                            7, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(8, "ED4", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_4_8,
-                            8, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(9, "ED5", UNIPHIER_PIN_IECTRL_NONE,
-                            9, UNIPHIER_PIN_DRV_4_8,
-                            9, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(10, "ED6", UNIPHIER_PIN_IECTRL_NONE,
-                            10, UNIPHIER_PIN_DRV_4_8,
-                            10, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(11, "ED7", UNIPHIER_PIN_IECTRL_NONE,
-                            11, UNIPHIER_PIN_DRV_4_8,
-                            11, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(12, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_4_8,
-                            12, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(13, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
-                            13, UNIPHIER_PIN_DRV_4_8,
-                            13, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(14, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
-                            14, UNIPHIER_PIN_DRV_4_8,
-                            14, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(15, "ES0", UNIPHIER_PIN_IECTRL_NONE,
-                            15, UNIPHIER_PIN_DRV_4_8,
-                            15, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(16, "ES1", UNIPHIER_PIN_IECTRL_NONE,
-                            16, UNIPHIER_PIN_DRV_4_8,
-                            16, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(17, "ES2", UNIPHIER_PIN_IECTRL_NONE,
-                            17, UNIPHIER_PIN_DRV_4_8,
-                            17, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(18, "XECS1", UNIPHIER_PIN_IECTRL_NONE,
-                            18, UNIPHIER_PIN_DRV_4_8,
-                            18, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(19, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
-                            19, UNIPHIER_PIN_DRV_4_8,
-                            19, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(20, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
-                            20, UNIPHIER_PIN_DRV_4_8,
-                            20, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(21, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
-                            21, UNIPHIER_PIN_DRV_4_8,
-                            21, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(22, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
-                            22, UNIPHIER_PIN_DRV_4_8,
-                            22, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(23, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
-                            23, UNIPHIER_PIN_DRV_4_8,
-                            23, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(24, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
-                            24, UNIPHIER_PIN_DRV_4_8,
-                            24, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(25, "NFRYBY0", UNIPHIER_PIN_IECTRL_NONE,
-                            25, UNIPHIER_PIN_DRV_4_8,
-                            25, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(26, "XNFCE1", UNIPHIER_PIN_IECTRL_NONE,
-                            26, UNIPHIER_PIN_DRV_4_8,
-                            26, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(27, "NFRYBY1", UNIPHIER_PIN_IECTRL_NONE,
-                            27, UNIPHIER_PIN_DRV_4_8,
-                            27, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(28, "NFD0", UNIPHIER_PIN_IECTRL_NONE,
-                            28, UNIPHIER_PIN_DRV_4_8,
-                            28, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(29, "NFD1", UNIPHIER_PIN_IECTRL_NONE,
-                            29, UNIPHIER_PIN_DRV_4_8,
-                            29, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(30, "NFD2", UNIPHIER_PIN_IECTRL_NONE,
-                            30, UNIPHIER_PIN_DRV_4_8,
-                            30, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(31, "NFD3", UNIPHIER_PIN_IECTRL_NONE,
-                            31, UNIPHIER_PIN_DRV_4_8,
-                            31, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(32, "NFD4", UNIPHIER_PIN_IECTRL_NONE,
-                            32, UNIPHIER_PIN_DRV_4_8,
-                            32, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(33, "NFD5", UNIPHIER_PIN_IECTRL_NONE,
-                            33, UNIPHIER_PIN_DRV_4_8,
-                            33, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(34, "NFD6", UNIPHIER_PIN_IECTRL_NONE,
-                            34, UNIPHIER_PIN_DRV_4_8,
-                            34, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(35, "NFD7", UNIPHIER_PIN_IECTRL_NONE,
-                            35, UNIPHIER_PIN_DRV_4_8,
-                            35, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(36, "XERST", UNIPHIER_PIN_IECTRL_NONE,
-                            36, UNIPHIER_PIN_DRV_4_8,
-                            36, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(37, "MMCCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            37, UNIPHIER_PIN_DRV_4_8,
-                            37, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(38, "MMCCMD", UNIPHIER_PIN_IECTRL_NONE,
-                            38, UNIPHIER_PIN_DRV_4_8,
-                            38, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(39, "MMCDAT0", UNIPHIER_PIN_IECTRL_NONE,
-                            39, UNIPHIER_PIN_DRV_4_8,
-                            39, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(40, "MMCDAT1", UNIPHIER_PIN_IECTRL_NONE,
-                            40, UNIPHIER_PIN_DRV_4_8,
-                            40, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(41, "MMCDAT2", UNIPHIER_PIN_IECTRL_NONE,
-                            41, UNIPHIER_PIN_DRV_4_8,
-                            41, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(42, "MMCDAT3", UNIPHIER_PIN_IECTRL_NONE,
-                            42, UNIPHIER_PIN_DRV_4_8,
-                            42, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(43, "MMCDAT4", UNIPHIER_PIN_IECTRL_NONE,
-                            43, UNIPHIER_PIN_DRV_4_8,
-                            43, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(44, "MMCDAT5", UNIPHIER_PIN_IECTRL_NONE,
-                            44, UNIPHIER_PIN_DRV_4_8,
-                            44, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(45, "MMCDAT6", UNIPHIER_PIN_IECTRL_NONE,
-                            45, UNIPHIER_PIN_DRV_4_8,
-                            45, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(46, "MMCDAT7", UNIPHIER_PIN_IECTRL_NONE,
-                            46, UNIPHIER_PIN_DRV_4_8,
-                            46, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(47, "TXD0", 0,
-                            47, UNIPHIER_PIN_DRV_4_8,
-                            47, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(48, "RXD0", 0,
-                            48, UNIPHIER_PIN_DRV_4_8,
-                            48, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(49, "TXD1", 0,
-                            49, UNIPHIER_PIN_DRV_4_8,
-                            49, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(50, "RXD1", 0,
-                            50, UNIPHIER_PIN_DRV_4_8,
-                            50, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(51, "TXD2", UNIPHIER_PIN_IECTRL_NONE,
-                            51, UNIPHIER_PIN_DRV_4_8,
-                            51, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(52, "RXD2", UNIPHIER_PIN_IECTRL_NONE,
-                            52, UNIPHIER_PIN_DRV_4_8,
-                            52, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(53, "TXD3", 0,
-                            53, UNIPHIER_PIN_DRV_4_8,
-                            53, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(54, "RXD3", 0,
-                            54, UNIPHIER_PIN_DRV_4_8,
-                            54, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(55, "MS0CS0", 0,
-                            55, UNIPHIER_PIN_DRV_4_8,
-                            55, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(56, "MS0DO", 0,
-                            56, UNIPHIER_PIN_DRV_4_8,
-                            56, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(57, "MS0DI", 0,
-                            57, UNIPHIER_PIN_DRV_4_8,
-                            57, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(58, "MS0CLK", 0,
-                            58, UNIPHIER_PIN_DRV_4_8,
-                            58, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(59, "CSCLK", 0,
-                            59, UNIPHIER_PIN_DRV_4_8,
-                            59, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(60, "CSBPTM", 0,
-                            60, UNIPHIER_PIN_DRV_4_8,
-                            60, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(61, "CSBMTP", 0,
-                            61, UNIPHIER_PIN_DRV_4_8,
-                            61, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(62, "XCINTP", 0,
-                            62, UNIPHIER_PIN_DRV_4_8,
-                            62, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(63, "XCINTM", 0,
-                            63, UNIPHIER_PIN_DRV_4_8,
-                            63, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(64, "XCMPREQ", 0,
-                            64, UNIPHIER_PIN_DRV_4_8,
-                            64, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(65, "XSRST", 0,
-                            65, UNIPHIER_PIN_DRV_4_8,
-                            65, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(66, "LPST", UNIPHIER_PIN_IECTRL_NONE,
-                            66, UNIPHIER_PIN_DRV_4_8,
-                            66, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(67, "PWMA", 0,
-                            67, UNIPHIER_PIN_DRV_4_8,
-                            67, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(68, "XIRQ0", 0,
-                            68, UNIPHIER_PIN_DRV_4_8,
-                            68, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(69, "XIRQ1", 0,
-                            69, UNIPHIER_PIN_DRV_4_8,
-                            69, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(70, "XIRQ2", 0,
-                            70, UNIPHIER_PIN_DRV_4_8,
-                            70, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(71, "XIRQ3", 0,
-                            71, UNIPHIER_PIN_DRV_4_8,
-                            71, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(72, "XIRQ4", 0,
-                            72, UNIPHIER_PIN_DRV_4_8,
-                            72, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(73, "XIRQ5", 0,
-                            73, UNIPHIER_PIN_DRV_4_8,
-                            73, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(74, "XIRQ6", 0,
-                            74, UNIPHIER_PIN_DRV_4_8,
-                            74, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(75, "XIRQ7", 0,
-                            75, UNIPHIER_PIN_DRV_4_8,
-                            75, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(76, "XIRQ8", 0,
-                            76, UNIPHIER_PIN_DRV_4_8,
-                            76, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(77, "XIRQ9", 0,
-                            77, UNIPHIER_PIN_DRV_4_8,
-                            77, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(78, "XIRQ10", 0,
-                            78, UNIPHIER_PIN_DRV_4_8,
-                            78, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(79, "XIRQ11", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            79, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(80, "XIRQ12", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            80, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(81, "XIRQ13", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            81, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(82, "XIRQ14", 0,
-                            82, UNIPHIER_PIN_DRV_4_8,
-                            82, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(83, "XIRQ15", 0,
-                            83, UNIPHIER_PIN_DRV_4_8,
-                            83, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(84, "XIRQ16", 0,
-                            84, UNIPHIER_PIN_DRV_4_8,
-                            84, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(85, "XIRQ17", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            85, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(86, "XIRQ18", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            86, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(87, "XIRQ19", 0,
-                            87, UNIPHIER_PIN_DRV_4_8,
-                            87, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(88, "XIRQ20", 0,
-                            88, UNIPHIER_PIN_DRV_4_8,
-                            88, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(89, "PORT00", 0,
-                            89, UNIPHIER_PIN_DRV_4_8,
-                            89, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(90, "PORT01", 0,
-                            90, UNIPHIER_PIN_DRV_4_8,
-                            90, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(91, "PORT02", 0,
-                            91, UNIPHIER_PIN_DRV_4_8,
-                            91, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(92, "PORT03", 0,
-                            92, UNIPHIER_PIN_DRV_4_8,
-                            92, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(93, "PORT04", 0,
-                            93, UNIPHIER_PIN_DRV_4_8,
-                            93, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(94, "PORT05", 0,
-                            94, UNIPHIER_PIN_DRV_4_8,
-                            94, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(95, "PORT06", 0,
-                            95, UNIPHIER_PIN_DRV_4_8,
-                            95, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(96, "PORT07", 0,
-                            96, UNIPHIER_PIN_DRV_4_8,
-                            96, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(97, "PORT10", 0,
-                            97, UNIPHIER_PIN_DRV_4_8,
-                            97, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(98, "PORT11", 0,
-                            98, UNIPHIER_PIN_DRV_4_8,
-                            98, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(99, "PORT12", 0,
-                            99, UNIPHIER_PIN_DRV_4_8,
-                            99, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(100, "PORT13", 0,
-                            100, UNIPHIER_PIN_DRV_4_8,
-                            100, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(101, "PORT14", 0,
-                            101, UNIPHIER_PIN_DRV_4_8,
-                            101, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(102, "PORT15", 0,
-                            102, UNIPHIER_PIN_DRV_4_8,
-                            102, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(103, "PORT16", 0,
-                            103, UNIPHIER_PIN_DRV_4_8,
-                            103, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(104, "PORT17", 0,
-                            104, UNIPHIER_PIN_DRV_4_8,
-                            104, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(105, "T0HPD", 0,
-                            105, UNIPHIER_PIN_DRV_4_8,
-                            105, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(106, "T1HPD", 0,
-                            106, UNIPHIER_PIN_DRV_4_8,
-                            106, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(107, "R0HPD", 0,
-                            107, UNIPHIER_PIN_DRV_4_8,
-                            107, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(108, "R1HPD", 0,
-                            108, UNIPHIER_PIN_DRV_4_8,
-                            108, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(109, "XPERST", 0,
-                            109, UNIPHIER_PIN_DRV_4_8,
-                            109, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(110, "XPEWAKE", 0,
-                            110, UNIPHIER_PIN_DRV_4_8,
-                            110, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(111, "XPECLKRQ", 0,
-                            111, UNIPHIER_PIN_DRV_4_8,
-                            111, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(112, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            112, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(113, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            113, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(114, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            114, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(115, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            115, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(116, "SDA2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            116, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(117, "SCL2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            117, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(118, "SDA3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            118, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(119, "SCL3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            119, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(120, "SPISYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            120, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(121, "SPISCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            121, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(122, "SPITXD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            122, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(123, "SPIRXD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            123, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(124, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            124, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(125, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            125, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(126, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            126, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(127, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            127, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(128, "USB2VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            128, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(129, "USB2OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            129, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(130, "SMTRST0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            130, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(131, "SMTCMD0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            131, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(132, "SMTD0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            132, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(133, "SMTSEL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            133, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(134, "SMTCLK0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            134, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(135, "SMTRST1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            135, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(136, "SMTCMD1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            136, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(137, "SMTD1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            137, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(138, "SMTSEL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            138, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(139, "SMTCLK1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            139, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(140, "CH0CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            140, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(141, "CH0PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            141, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(142, "CH0VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            142, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(143, "CH0DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            143, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(144, "CH1CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            144, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(145, "CH1PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            145, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(146, "CH1VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            146, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(147, "CH1DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            147, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(148, "CH2CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            148, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(149, "CH2PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            149, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(150, "CH2VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            150, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(151, "CH2DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            151, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(152, "CH3CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            152, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(153, "CH3PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            153, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(154, "CH3VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            154, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(155, "CH3DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            155, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(156, "CH4CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            156, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(157, "CH4PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            157, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(158, "CH4VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            158, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(159, "CH4DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            159, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(160, "CH5CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            160, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(161, "CH5PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            161, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(162, "CH5VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            162, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(163, "CH5DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            163, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(164, "CH6CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            164, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(165, "CH6PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            165, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(166, "CH6VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            166, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(167, "CH6DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            167, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(168, "CH7CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            168, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(169, "CH7PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            169, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(170, "CH7VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            170, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(171, "CH7DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            171, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(172, "AI1ADCCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            172, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(173, "AI1BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            173, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(174, "AI1LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            174, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(175, "AI1D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            175, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(176, "AI1D1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            176, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(177, "AI1D2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            177, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(178, "AI1D3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            178, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(179, "AI2ADCCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            179, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(180, "AI2BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            180, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(181, "AI2LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            181, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(182, "AI2D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            182, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(183, "AI2D1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            183, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(184, "AI2D2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            184, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(185, "AI2D3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            185, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(186, "AI3ADCCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            186, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(187, "AI3BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            187, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(188, "AI3LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            188, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(189, "AI3D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            189, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(190, "AO1IEC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            190, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(191, "AO1DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            191, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(192, "AO1BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            192, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(193, "AO1LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            193, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(194, "AO1D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            194, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(195, "AO1D1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            195, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(196, "AO1D2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            196, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(197, "AO1D3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            197, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(198, "AO2IEC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            198, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(199, "AO2DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            199, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(200, "AO2BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            200, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(201, "AO2LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            201, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(202, "AO2D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            202, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(203, "AO2D1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            203, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(204, "AO2D2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            204, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(205, "AO2D3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            205, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(206, "AO3DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            206, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(207, "AO3BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            207, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(208, "AO3LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            208, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(209, "AO3DMIX", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            209, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(210, "AO4DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            210, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(211, "AO4BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            211, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(212, "AO4LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            212, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(213, "AO4DMIX", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            213, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(214, "VI1CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            214, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(215, "VI1C0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            215, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(216, "VI1C1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            216, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(217, "VI1C2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            217, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(218, "VI1C3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            218, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(219, "VI1C4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            219, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(220, "VI1C5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            220, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(221, "VI1C6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            221, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(222, "VI1C7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            222, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(223, "VI1C8", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            223, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(224, "VI1C9", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            224, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(225, "VI1Y0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            225, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(226, "VI1Y1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            226, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(227, "VI1Y2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            227, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(228, "VI1Y3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            228, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(229, "VI1Y4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            229, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(230, "VI1Y5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            230, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(231, "VI1Y6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            231, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(232, "VI1Y7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            232, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(233, "VI1Y8", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            233, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(234, "VI1Y9", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            234, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(235, "VI1DE", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            235, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(236, "VI1HSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            236, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(237, "VI1VSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            237, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(238, "VO1CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            238, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(239, "VO1D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            239, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(240, "VO1D1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            240, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(241, "VO1D2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            241, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(242, "VO1D3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            242, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(243, "VO1D4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            243, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(244, "VO1D5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            244, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(245, "VO1D6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            245, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(246, "VO1D7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            246, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(247, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            247, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(248, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            248, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(249, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            249, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(250, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            40, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(251, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
-                            44, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(252, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
-                            48, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(253, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
-                            52, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(254, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
-                            56, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(255, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
-                            60, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-};
-
-static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
-static const unsigned emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0};
-static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
-static const unsigned emmc_dat8_muxvals[] = {0, 0, 0, 0};
-static const unsigned i2c0_pins[] = {112, 113};
-static const unsigned i2c0_muxvals[] = {0, 0};
-static const unsigned i2c1_pins[] = {114, 115};
-static const unsigned i2c1_muxvals[] = {0, 0};
-static const unsigned i2c2_pins[] = {116, 117};
-static const unsigned i2c2_muxvals[] = {0, 0};
-static const unsigned i2c3_pins[] = {118, 119};
-static const unsigned i2c3_muxvals[] = {0, 0};
-static const unsigned i2c5_pins[] = {87, 88};
-static const unsigned i2c5_muxvals[] = {2, 2};
-static const unsigned i2c5b_pins[] = {196, 197};
-static const unsigned i2c5b_muxvals[] = {2, 2};
-static const unsigned i2c5c_pins[] = {215, 216};
-static const unsigned i2c5c_muxvals[] = {2, 2};
-static const unsigned i2c6_pins[] = {101, 102};
-static const unsigned i2c6_muxvals[] = {2, 2};
-static const unsigned nand_pins[] = {19, 20, 21, 22, 23, 24, 25, 28, 29, 30,
-                                    31, 32, 33, 34, 35};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0};
-static const unsigned nand_cs1_pins[] = {26, 27};
-static const unsigned nand_cs1_muxvals[] = {0, 0};
-static const unsigned sd_pins[] = {250, 251, 252, 253, 254, 255, 256, 257, 258};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-static const unsigned uart0_pins[] = {47, 48};
-static const unsigned uart0_muxvals[] = {0, 0};
-static const unsigned uart0b_pins[] = {227, 228};
-static const unsigned uart0b_muxvals[] = {3, 3};
-static const unsigned uart1_pins[] = {49, 50};
-static const unsigned uart1_muxvals[] = {0, 0};
-static const unsigned uart2_pins[] = {51, 52};
-static const unsigned uart2_muxvals[] = {0, 0};
-static const unsigned uart3_pins[] = {53, 54};
-static const unsigned uart3_muxvals[] = {0, 0};
-static const unsigned usb0_pins[] = {124, 125};
-static const unsigned usb0_muxvals[] = {0, 0};
-static const unsigned usb1_pins[] = {126, 127};
-static const unsigned usb1_muxvals[] = {0, 0};
-static const unsigned usb2_pins[] = {128, 129};
-static const unsigned usb2_muxvals[] = {0, 0};
-static const unsigned port_range0_pins[] = {
-       89, 90, 91, 92, 93, 94, 95, 96,                 /* PORT0x */
-       97, 98, 99, 100, 101, 102, 103, 104,            /* PORT1x */
-       251, 252, 253, 254, 255, 247, 248, 249,         /* PORT2x */
-       39, 40, 41, 42, 43, 44, 45, 46,                 /* PORT3x */
-       156, 157, 158, 159, 160, 161, 162, 163,         /* PORT4x */
-       164, 165, 166, 167, 168, 169, 170, 171,         /* PORT5x */
-       190, 191, 192, 193, 194, 195, 196, 197,         /* PORT6x */
-       198, 199, 200, 201, 202, 203, 204, 205,         /* PORT7x */
-       120, 121, 122, 123, 55, 56, 57, 58,             /* PORT8x */
-       124, 125, 126, 127, 49, 50, 53, 54,             /* PORT9x */
-       148, 149, 150, 151, 152, 153, 154, 155,         /* PORT10x */
-       133, 134, 131, 130, 138, 139, 136, 135,         /* PORT11x */
-       28, 29, 30, 31, 32, 33, 34, 35,                 /* PORT12x */
-       179, 180, 181, 182, 186, 187, 188, 189,         /* PORT13x */
-       4, 5, 6, 7, 8, 9, 10, 11,                       /* PORT14x */
-};
-static const unsigned port_range0_muxvals[] = {
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT0x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT1x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT2x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT11x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT12x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT13x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
-};
-static const unsigned port_range1_pins[] = {
-       109, 110, 111,                                  /* PORT175-177 */
-       206, 207, 208, 209, 210, 211, 212, 213,         /* PORT18x */
-       12, 13, 14, 15, 16, 17, 107, 108,               /* PORT19x */
-       140, 141, 142, 143, 144, 145, 146, 147,         /* PORT20x */
-       59, 60, 61, 62, 63, 64, 65, 66,                 /* PORT21x */
-       214, 215, 216, 217, 218, 219, 220, 221,         /* PORT22x */
-       222, 223, 224, 225, 226, 227, 228, 229,         /* PORT23x */
-       19, 20, 21, 22, 23, 24, 25, 26,                 /* PORT24x */
-       230, 231, 232, 233, 234, 235, 236, 237,         /* PORT25x */
-       239, 240, 241, 242, 243, 244, 245, 246,         /* PORT26x */
-       172, 173, 174, 175, 176, 177, 178, 129,         /* PORT27x */
-       0, 1, 2, 67, 85, 86, 87, 88,                    /* PORT28x */
-       105, 106, 18, 27, 36, 128, 132, 137,            /* PORT29x */
-       183, 184, 185, 84, 47, 48, 51, 52,              /* PORT30x */
-};
-static const unsigned port_range1_muxvals[] = {
-       15, 15, 15,                                     /* PORT175-177 */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT18x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT19x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT20x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT21x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT22x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT23x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT24x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT25x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT26x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT27x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT28x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT29x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT30x */
-};
-static const unsigned xirq_pins[] = {
-       68, 69, 70, 71, 72, 73, 74, 75,                 /* XIRQ0-7 */
-       76, 77, 78, 79, 80, 81, 82, 83,                 /* XIRQ8-15 */
-       84, 85, 86, 87, 88,                             /* XIRQ16-20 */
-};
-static const unsigned xirq_muxvals[] = {
-       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ0-7 */
-       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ8-15 */
-       14, 14, 14, 14, 14,                             /* XIRQ16-20 */
-};
-static const unsigned xirq_alternatives_pins[] = {
-       91, 92, 239, 144, 240, 156, 241, 106, 128,
-};
-static const unsigned xirq_alternatives_muxvals[] = {
-       14, 14, 14, 14, 14, 14, 14, 14, 14,
-};
-
-static const struct uniphier_pinctrl_group ph1_pro5_groups[] = {
-       UNIPHIER_PINCTRL_GROUP(nand),
-       UNIPHIER_PINCTRL_GROUP(nand_cs1),
-       UNIPHIER_PINCTRL_GROUP(emmc),
-       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
-       UNIPHIER_PINCTRL_GROUP(i2c0),
-       UNIPHIER_PINCTRL_GROUP(i2c1),
-       UNIPHIER_PINCTRL_GROUP(i2c2),
-       UNIPHIER_PINCTRL_GROUP(i2c3),
-       UNIPHIER_PINCTRL_GROUP(i2c5),
-       UNIPHIER_PINCTRL_GROUP(i2c5b),
-       UNIPHIER_PINCTRL_GROUP(i2c5c),
-       UNIPHIER_PINCTRL_GROUP(i2c6),
-       UNIPHIER_PINCTRL_GROUP(sd),
-       UNIPHIER_PINCTRL_GROUP(uart0),
-       UNIPHIER_PINCTRL_GROUP(uart0b),
-       UNIPHIER_PINCTRL_GROUP(uart1),
-       UNIPHIER_PINCTRL_GROUP(uart2),
-       UNIPHIER_PINCTRL_GROUP(uart3),
-       UNIPHIER_PINCTRL_GROUP(usb0),
-       UNIPHIER_PINCTRL_GROUP(usb1),
-       UNIPHIER_PINCTRL_GROUP(usb2),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_alternatives),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range0, 101),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range0, 102),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range0, 103),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range0, 104),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range0, 105),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range0, 106),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range0, 107),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range0, 108),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range0, 109),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range0, 110),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range0, 111),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range0, 112),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range0, 113),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range0, 114),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range0, 115),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range0, 116),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range0, 117),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range0, 118),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range0, 119),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port175, port_range1, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port176, port_range1, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port177, port_range1, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range1, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range1, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range1, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range1, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range1, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range1, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range1, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range1, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port190, port_range1, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port191, port_range1, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port192, port_range1, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port193, port_range1, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port194, port_range1, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port195, port_range1, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port196, port_range1, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port197, port_range1, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range1, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range1, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range1, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range1, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range1, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range1, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range1, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range1, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range1, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range1, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range1, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range1, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range1, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range1, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range1, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range1, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range1, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range1, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range1, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range1, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range1, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range1, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range1, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range1, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range1, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range1, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range1, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range1, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range1, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range1, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range1, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range1, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range1, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range1, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range1, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range1, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range1, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range1, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range1, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range1, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range1, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range1, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range1, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range1, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range1, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port255, port_range1, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port256, port_range1, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port257, port_range1, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port260, port_range1, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port261, port_range1, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port262, port_range1, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port263, port_range1, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port264, port_range1, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port265, port_range1, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port266, port_range1, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port267, port_range1, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port270, port_range1, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port271, port_range1, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port272, port_range1, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port273, port_range1, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port274, port_range1, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port275, port_range1, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port276, port_range1, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port277, port_range1, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port280, port_range1, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port281, port_range1, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port282, port_range1, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port283, port_range1, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port284, port_range1, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port285, port_range1, 88),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port286, port_range1, 89),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port287, port_range1, 90),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port290, port_range1, 91),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port291, port_range1, 92),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port292, port_range1, 93),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port293, port_range1, 94),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port294, port_range1, 95),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port295, port_range1, 96),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port296, port_range1, 97),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port297, port_range1, 98),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port300, port_range1, 99),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port301, port_range1, 100),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port302, port_range1, 101),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port303, port_range1, 102),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port304, port_range1, 103),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port305, port_range1, 104),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port306, port_range1, 105),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port307, port_range1, 106),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3b, xirq_alternatives, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4b, xirq_alternatives, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16b, xirq_alternatives, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17b, xirq_alternatives, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17c, xirq_alternatives, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18b, xirq_alternatives, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18c, xirq_alternatives, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19b, xirq_alternatives, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20b, xirq_alternatives, 8),
-};
-
-static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
-static const char * const i2c0_groups[] = {"i2c0"};
-static const char * const i2c1_groups[] = {"i2c1"};
-static const char * const i2c2_groups[] = {"i2c2"};
-static const char * const i2c3_groups[] = {"i2c3"};
-static const char * const i2c5_groups[] = {"i2c5", "i2c5b", "i2c5c"};
-static const char * const i2c6_groups[] = {"i2c6"};
-static const char * const nand_groups[] = {"nand", "nand_cs1"};
-static const char * const sd_groups[] = {"sd"};
-static const char * const uart0_groups[] = {"uart0", "uart0b"};
-static const char * const uart1_groups[] = {"uart1"};
-static const char * const uart2_groups[] = {"uart2"};
-static const char * const uart3_groups[] = {"uart3"};
-static const char * const usb0_groups[] = {"usb0"};
-static const char * const usb1_groups[] = {"usb1"};
-static const char * const usb2_groups[] = {"usb2"};
-static const char * const port_groups[] = {
-       "port00",  "port01",  "port02",  "port03",
-       "port04",  "port05",  "port06",  "port07",
-       "port10",  "port11",  "port12",  "port13",
-       "port14",  "port15",  "port16",  "port17",
-       "port20",  "port21",  "port22",  "port23",
-       "port24",  "port25",  "port26",  "port27",
-       "port30",  "port31",  "port32",  "port33",
-       "port34",  "port35",  "port36",  "port37",
-       "port40",  "port41",  "port42",  "port43",
-       "port44",  "port45",  "port46",  "port47",
-       "port50",  "port51",  "port52",  "port53",
-       "port54",  "port55",  "port56",  "port57",
-       "port60",  "port61",  "port62",  "port63",
-       "port64",  "port65",  "port66",  "port67",
-       "port70",  "port71",  "port72",  "port73",
-       "port74",  "port75",  "port76",  "port77",
-       "port80",  "port81",  "port82",  "port83",
-       "port84",  "port85",  "port86",  "port87",
-       "port90",  "port91",  "port92",  "port93",
-       "port94",  "port95",  "port96",  "port97",
-       "port100", "port101", "port102", "port103",
-       "port104", "port105", "port106", "port107",
-       "port110", "port111", "port112", "port113",
-       "port114", "port115", "port116", "port117",
-       "port120", "port121", "port122", "port123",
-       "port124", "port125", "port126", "port127",
-       "port130", "port131", "port132", "port133",
-       "port134", "port135", "port136", "port137",
-       "port140", "port141", "port142", "port143",
-       "port144", "port145", "port146", "port147",
-       /* port150-174 missing */
-       /* none */ "port175", "port176", "port177",
-       "port180", "port181", "port182", "port183",
-       "port184", "port185", "port186", "port187",
-       "port190", "port191", "port192", "port193",
-       "port194", "port195", "port196", "port197",
-       "port200", "port201", "port202", "port203",
-       "port204", "port205", "port206", "port207",
-       "port210", "port211", "port212", "port213",
-       "port214", "port215", "port216", "port217",
-       "port220", "port221", "port222", "port223",
-       "port224", "port225", "port226", "port227",
-       "port230", "port231", "port232", "port233",
-       "port234", "port235", "port236", "port237",
-       "port240", "port241", "port242", "port243",
-       "port244", "port245", "port246", "port247",
-       "port250", "port251", "port252", "port253",
-       "port254", "port255", "port256", "port257",
-       "port260", "port261", "port262", "port263",
-       "port264", "port265", "port266", "port267",
-       "port270", "port271", "port272", "port273",
-       "port274", "port275", "port276", "port277",
-       "port280", "port281", "port282", "port283",
-       "port284", "port285", "port286", "port287",
-       "port290", "port291", "port292", "port293",
-       "port294", "port295", "port296", "port297",
-       "port300", "port301", "port302", "port303",
-       "port304", "port305", "port306", "port307",
-};
-static const char * const xirq_groups[] = {
-       "xirq0",  "xirq1",  "xirq2",  "xirq3",
-       "xirq4",  "xirq5",  "xirq6",  "xirq7",
-       "xirq8",  "xirq9",  "xirq10", "xirq11",
-       "xirq12", "xirq13", "xirq14", "xirq15",
-       "xirq16", "xirq17", "xirq18", "xirq19",
-       "xirq20",
-       "xirq3b", "xirq4b", "xirq16b", "xirq17b", "xirq17c",
-       "xirq18b", "xirq18c", "xirq19b", "xirq20b",
-};
-
-static const struct uniphier_pinmux_function ph1_pro5_functions[] = {
-       UNIPHIER_PINMUX_FUNCTION(emmc),
-       UNIPHIER_PINMUX_FUNCTION(i2c0),
-       UNIPHIER_PINMUX_FUNCTION(i2c1),
-       UNIPHIER_PINMUX_FUNCTION(i2c2),
-       UNIPHIER_PINMUX_FUNCTION(i2c3),
-       UNIPHIER_PINMUX_FUNCTION(i2c5),
-       UNIPHIER_PINMUX_FUNCTION(i2c6),
-       UNIPHIER_PINMUX_FUNCTION(nand),
-       UNIPHIER_PINMUX_FUNCTION(sd),
-       UNIPHIER_PINMUX_FUNCTION(uart0),
-       UNIPHIER_PINMUX_FUNCTION(uart1),
-       UNIPHIER_PINMUX_FUNCTION(uart2),
-       UNIPHIER_PINMUX_FUNCTION(uart3),
-       UNIPHIER_PINMUX_FUNCTION(usb0),
-       UNIPHIER_PINMUX_FUNCTION(usb1),
-       UNIPHIER_PINMUX_FUNCTION(usb2),
-       UNIPHIER_PINMUX_FUNCTION(port),
-       UNIPHIER_PINMUX_FUNCTION(xirq),
-};
-
-static struct uniphier_pinctrl_socdata ph1_pro5_pindata = {
-       .groups = ph1_pro5_groups,
-       .groups_count = ARRAY_SIZE(ph1_pro5_groups),
-       .functions = ph1_pro5_functions,
-       .functions_count = ARRAY_SIZE(ph1_pro5_functions),
-       .mux_bits = 4,
-       .reg_stride = 8,
-       .load_pinctrl = true,
-};
-
-static struct pinctrl_desc ph1_pro5_pinctrl_desc = {
-       .name = DRIVER_NAME,
-       .pins = ph1_pro5_pins,
-       .npins = ARRAY_SIZE(ph1_pro5_pins),
-       .owner = THIS_MODULE,
-};
-
-static int ph1_pro5_pinctrl_probe(struct platform_device *pdev)
-{
-       return uniphier_pinctrl_probe(pdev, &ph1_pro5_pinctrl_desc,
-                                     &ph1_pro5_pindata);
-}
-
-static const struct of_device_id ph1_pro5_pinctrl_match[] = {
-       { .compatible = "socionext,ph1-pro5-pinctrl" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, ph1_pro5_pinctrl_match);
-
-static struct platform_driver ph1_pro5_pinctrl_driver = {
-       .probe = ph1_pro5_pinctrl_probe,
-       .remove = uniphier_pinctrl_remove,
-       .driver = {
-               .name = DRIVER_NAME,
-               .of_match_table = ph1_pro5_pinctrl_match,
-       },
-};
-module_platform_driver(ph1_pro5_pinctrl_driver);
-
-MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
-MODULE_DESCRIPTION("UniPhier PH1-Pro5 pinctrl driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c b/drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
deleted file mode 100644 (file)
index c3700a3..0000000
+++ /dev/null
@@ -1,799 +0,0 @@
-/*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/platform_device.h>
-
-#include "pinctrl-uniphier.h"
-
-#define DRIVER_NAME "ph1-sld8-pinctrl"
-
-static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
-       UNIPHIER_PINCTRL_PIN(0, "PCA00", 0,
-                            15, UNIPHIER_PIN_DRV_4_8,
-                            15, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(1, "PCA01", 0,
-                            16, UNIPHIER_PIN_DRV_4_8,
-                            16, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(2, "PCA02", 0,
-                            17, UNIPHIER_PIN_DRV_4_8,
-                            17, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(3, "PCA03", 0,
-                            18, UNIPHIER_PIN_DRV_4_8,
-                            18, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(4, "PCA04", 0,
-                            19, UNIPHIER_PIN_DRV_4_8,
-                            19, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(5, "PCA05", 0,
-                            20, UNIPHIER_PIN_DRV_4_8,
-                            20, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(6, "PCA06", 0,
-                            21, UNIPHIER_PIN_DRV_4_8,
-                            21, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(7, "PCA07", 0,
-                            22, UNIPHIER_PIN_DRV_4_8,
-                            22, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(8, "PCA08", 0,
-                            23, UNIPHIER_PIN_DRV_4_8,
-                            23, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(9, "PCA09", 0,
-                            24, UNIPHIER_PIN_DRV_4_8,
-                            24, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(10, "PCA10", 0,
-                            25, UNIPHIER_PIN_DRV_4_8,
-                            25, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(11, "PCA11", 0,
-                            26, UNIPHIER_PIN_DRV_4_8,
-                            26, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(12, "PCA12", 0,
-                            27, UNIPHIER_PIN_DRV_4_8,
-                            27, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(13, "PCA13", 0,
-                            28, UNIPHIER_PIN_DRV_4_8,
-                            28, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(14, "PCA14", 0,
-                            29, UNIPHIER_PIN_DRV_4_8,
-                            29, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(15, "XNFRE_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            30, UNIPHIER_PIN_DRV_4_8,
-                            30, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(16, "XNFWE_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            31, UNIPHIER_PIN_DRV_4_8,
-                            31, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(17, "NFALE_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            32, UNIPHIER_PIN_DRV_4_8,
-                            32, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(18, "NFCLE_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            33, UNIPHIER_PIN_DRV_4_8,
-                            33, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(19, "XNFWP_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            34, UNIPHIER_PIN_DRV_4_8,
-                            34, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(20, "XNFCE0_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            35, UNIPHIER_PIN_DRV_4_8,
-                            35, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(21, "NANDRYBY0_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            36, UNIPHIER_PIN_DRV_4_8,
-                            36, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(22, "XNFCE1_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            0, UNIPHIER_PIN_DRV_8_12_16_20,
-                            119, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(23, "NANDRYBY1_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_8_12_16_20,
-                            120, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(24, "NFD0_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_8_12_16_20,
-                            121, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(25, "NFD1_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_8_12_16_20,
-                            122, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(26, "NFD2_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            16, UNIPHIER_PIN_DRV_8_12_16_20,
-                            123, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(27, "NFD3_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            20, UNIPHIER_PIN_DRV_8_12_16_20,
-                            124, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(28, "NFD4_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            24, UNIPHIER_PIN_DRV_8_12_16_20,
-                            125, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(29, "NFD5_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            28, UNIPHIER_PIN_DRV_8_12_16_20,
-                            126, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(30, "NFD6_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            32, UNIPHIER_PIN_DRV_8_12_16_20,
-                            127, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(31, "NFD7_GB", UNIPHIER_PIN_IECTRL_NONE,
-                            36, UNIPHIER_PIN_DRV_8_12_16_20,
-                            128, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(32, "SDCLK", 8,
-                            40, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(33, "SDCMD", 8,
-                            44, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(34, "SDDAT0", 8,
-                            48, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(35, "SDDAT1", 8,
-                            52, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(36, "SDDAT2", 8,
-                            56, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(37, "SDDAT3", 8,
-                            60, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(38, "SDCD", 8,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            129, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(39, "SDWP", 8,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            130, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(40, "SDVOLC", 9,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            131, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", 0,
-                            37, UNIPHIER_PIN_DRV_4_8,
-                            37, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(42, "USB0OD", 0,
-                            38, UNIPHIER_PIN_DRV_4_8,
-                            38, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", 0,
-                            39, UNIPHIER_PIN_DRV_4_8,
-                            39, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(44, "USB1OD", 0,
-                            40, UNIPHIER_PIN_DRV_4_8,
-                            40, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(45, "PCRESET", 0,
-                            41, UNIPHIER_PIN_DRV_4_8,
-                            41, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(46, "PCREG", 0,
-                            42, UNIPHIER_PIN_DRV_4_8,
-                            42, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(47, "PCCE2", 0,
-                            43, UNIPHIER_PIN_DRV_4_8,
-                            43, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(48, "PCVS1", 0,
-                            44, UNIPHIER_PIN_DRV_4_8,
-                            44, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(49, "PCCD2", 0,
-                            45, UNIPHIER_PIN_DRV_4_8,
-                            45, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(50, "PCCD1", 0,
-                            46, UNIPHIER_PIN_DRV_4_8,
-                            46, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(51, "PCREADY", 0,
-                            47, UNIPHIER_PIN_DRV_4_8,
-                            47, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(52, "PCDOE", 0,
-                            48, UNIPHIER_PIN_DRV_4_8,
-                            48, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(53, "PCCE1", 0,
-                            49, UNIPHIER_PIN_DRV_4_8,
-                            49, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(54, "PCWE", 0,
-                            50, UNIPHIER_PIN_DRV_4_8,
-                            50, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(55, "PCOE", 0,
-                            51, UNIPHIER_PIN_DRV_4_8,
-                            51, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(56, "PCWAIT", 0,
-                            52, UNIPHIER_PIN_DRV_4_8,
-                            52, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(57, "PCIOWR", 0,
-                            53, UNIPHIER_PIN_DRV_4_8,
-                            53, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(58, "PCIORD", 0,
-                            54, UNIPHIER_PIN_DRV_4_8,
-                            54, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", 0,
-                            55, UNIPHIER_PIN_DRV_4_8,
-                            55, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", 0,
-                            56, UNIPHIER_PIN_DRV_4_8,
-                            56, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", 0,
-                            57, UNIPHIER_PIN_DRV_4_8,
-                            57, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", 0,
-                            58, UNIPHIER_PIN_DRV_4_8,
-                            58, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", 0,
-                            59, UNIPHIER_PIN_DRV_4_8,
-                            59, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", 0,
-                            60, UNIPHIER_PIN_DRV_4_8,
-                            60, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", 0,
-                            61, UNIPHIER_PIN_DRV_4_8,
-                            61, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", 0,
-                            62, UNIPHIER_PIN_DRV_4_8,
-                            62, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", 0,
-                            63, UNIPHIER_PIN_DRV_4_8,
-                            63, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", 0,
-                            64, UNIPHIER_PIN_DRV_4_8,
-                            64, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", 0,
-                            65, UNIPHIER_PIN_DRV_4_8,
-                            65, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", 0,
-                            66, UNIPHIER_PIN_DRV_4_8,
-                            66, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", 0,
-                            67, UNIPHIER_PIN_DRV_4_8,
-                            67, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", 0,
-                            68, UNIPHIER_PIN_DRV_4_8,
-                            68, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", 0,
-                            69, UNIPHIER_PIN_DRV_4_8,
-                            69, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", 0,
-                            70, UNIPHIER_PIN_DRV_4_8,
-                            70, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", 0,
-                            71, UNIPHIER_PIN_DRV_4_8,
-                            71, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", 0,
-                            72, UNIPHIER_PIN_DRV_4_8,
-                            72, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", 0,
-                            73, UNIPHIER_PIN_DRV_4_8,
-                            73, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", 0,
-                            74, UNIPHIER_PIN_DRV_4_8,
-                            74, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", 0,
-                            75, UNIPHIER_PIN_DRV_4_8,
-                            75, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", 0,
-                            76, UNIPHIER_PIN_DRV_4_8,
-                            76, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", 0,
-                            77, UNIPHIER_PIN_DRV_4_8,
-                            77, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", 0,
-                            78, UNIPHIER_PIN_DRV_4_8,
-                            78, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", 0,
-                            79, UNIPHIER_PIN_DRV_4_8,
-                            79, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", 0,
-                            80, UNIPHIER_PIN_DRV_4_8,
-                            80, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", 0,
-                            81, UNIPHIER_PIN_DRV_4_8,
-                            81, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", 0,
-                            82, UNIPHIER_PIN_DRV_4_8,
-                            82, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", 0,
-                            83, UNIPHIER_PIN_DRV_4_8,
-                            83, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", 0,
-                            84, UNIPHIER_PIN_DRV_4_8,
-                            84, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", 0,
-                            85, UNIPHIER_PIN_DRV_4_8,
-                            85, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", 0,
-                            86, UNIPHIER_PIN_DRV_4_8,
-                            86, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", 0,
-                            87, UNIPHIER_PIN_DRV_4_8,
-                            87, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(92, "AGCI", 3,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            132, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(93, "AGCR", 4,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            133, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(94, "AGCBS", 5,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            134, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(95, "IECOUT", 0,
-                            88, UNIPHIER_PIN_DRV_4_8,
-                            88, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(96, "ASMCK", 0,
-                            89, UNIPHIER_PIN_DRV_4_8,
-                            89, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(97, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
-                            90, UNIPHIER_PIN_DRV_4_8,
-                            90, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(98, "ALRCKO", UNIPHIER_PIN_IECTRL_NONE,
-                            91, UNIPHIER_PIN_DRV_4_8,
-                            91, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(99, "ASDOUT0", UNIPHIER_PIN_IECTRL_NONE,
-                            92, UNIPHIER_PIN_DRV_4_8,
-                            92, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(100, "ASDOUT1", UNIPHIER_PIN_IECTRL_NONE,
-                            93, UNIPHIER_PIN_DRV_4_8,
-                            93, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(101, "ARCOUT", 0,
-                            94, UNIPHIER_PIN_DRV_4_8,
-                            94, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(102, "SDA0", 10,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(103, "SCL0", 10,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(104, "SDA1", 11,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(105, "SCL1", 11,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", 12,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", 12,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", 13,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", 13,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
-                            95, UNIPHIER_PIN_DRV_4_8,
-                            95, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
-                            96, UNIPHIER_PIN_DRV_4_8,
-                            96, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(112, "SBO1", 0,
-                            97, UNIPHIER_PIN_DRV_4_8,
-                            97, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(113, "SBI1", 0,
-                            98, UNIPHIER_PIN_DRV_4_8,
-                            98, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(114, "TXD1", 0,
-                            99, UNIPHIER_PIN_DRV_4_8,
-                            99, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(115, "RXD1", 0,
-                            100, UNIPHIER_PIN_DRV_4_8,
-                            100, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(116, "HIN", 1,
-                            -1, UNIPHIER_PIN_DRV_FIXED_5,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(117, "VIN", 2,
-                            -1, UNIPHIER_PIN_DRV_FIXED_5,
-                            -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(118, "TCON0", 0,
-                            101, UNIPHIER_PIN_DRV_4_8,
-                            101, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(119, "TCON1", 0,
-                            102, UNIPHIER_PIN_DRV_4_8,
-                            102, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(120, "TCON2", 0,
-                            103, UNIPHIER_PIN_DRV_4_8,
-                            103, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(121, "TCON3", 0,
-                            104, UNIPHIER_PIN_DRV_4_8,
-                            104, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(122, "TCON4", 0,
-                            105, UNIPHIER_PIN_DRV_4_8,
-                            105, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(123, "TCON5", 0,
-                            106, UNIPHIER_PIN_DRV_4_8,
-                            106, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(124, "TCON6", 0,
-                            107, UNIPHIER_PIN_DRV_4_8,
-                            107, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(125, "TCON7", 0,
-                            108, UNIPHIER_PIN_DRV_4_8,
-                            108, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(126, "TCON8", 0,
-                            109, UNIPHIER_PIN_DRV_4_8,
-                            109, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(127, "PWMA", 0,
-                            110, UNIPHIER_PIN_DRV_4_8,
-                            110, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(128, "XIRQ0", 0,
-                            111, UNIPHIER_PIN_DRV_4_8,
-                            111, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(129, "XIRQ1", 0,
-                            112, UNIPHIER_PIN_DRV_4_8,
-                            112, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(130, "XIRQ2", 0,
-                            113, UNIPHIER_PIN_DRV_4_8,
-                            113, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(131, "XIRQ3", 0,
-                            114, UNIPHIER_PIN_DRV_4_8,
-                            114, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(132, "XIRQ4", 0,
-                            115, UNIPHIER_PIN_DRV_4_8,
-                            115, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(133, "XIRQ5", 0,
-                            116, UNIPHIER_PIN_DRV_4_8,
-                            116, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(134, "XIRQ6", 0,
-                            117, UNIPHIER_PIN_DRV_4_8,
-                            117, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(135, "XIRQ7", 0,
-                            118, UNIPHIER_PIN_DRV_4_8,
-                            118, UNIPHIER_PIN_PULL_DOWN),
-};
-
-static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
-static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
-static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
-static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
-static const unsigned i2c0_pins[] = {102, 103};
-static const unsigned i2c0_muxvals[] = {0, 0};
-static const unsigned i2c1_pins[] = {104, 105};
-static const unsigned i2c1_muxvals[] = {0, 0};
-static const unsigned i2c2_pins[] = {108, 109};
-static const unsigned i2c2_muxvals[] = {2, 2};
-static const unsigned i2c3_pins[] = {108, 109};
-static const unsigned i2c3_muxvals[] = {3, 3};
-static const unsigned nand_pins[] = {15, 16, 17, 18, 19, 20, 21, 24, 25, 26,
-                                    27, 28, 29, 30, 31};
-static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                       0, 0};
-static const unsigned nand_cs1_pins[] = {22, 23};
-static const unsigned nand_cs1_muxvals[] = {0, 0};
-static const unsigned sd_pins[] = {32, 33, 34, 35, 36, 37, 38, 39, 40};
-static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
-static const unsigned uart0_pins[] = {70, 71};
-static const unsigned uart0_muxvals[] = {3, 3};
-static const unsigned uart1_pins[] = {114, 115};
-static const unsigned uart1_muxvals[] = {0, 0};
-static const unsigned uart2_pins[] = {112, 113};
-static const unsigned uart2_muxvals[] = {1, 1};
-static const unsigned uart3_pins[] = {110, 111};
-static const unsigned uart3_muxvals[] = {1, 1};
-static const unsigned usb0_pins[] = {41, 42};
-static const unsigned usb0_muxvals[] = {0, 0};
-static const unsigned usb1_pins[] = {43, 44};
-static const unsigned usb1_muxvals[] = {0, 0};
-static const unsigned usb2_pins[] = {114, 115};
-static const unsigned usb2_muxvals[] = {1, 1};
-static const unsigned port_range0_pins[] = {
-       0, 1, 2, 3, 4, 5, 6, 7,                         /* PORT0x */
-       8, 9, 10, 11, 12, 13, 14, 15,                   /* PORT1x */
-       32, 33, 34, 35, 36, 37, 38, 39,                 /* PORT2x */
-       59, 60, 61, 62, 63, 64, 65, 66,                 /* PORT3x */
-       95, 96, 97, 98, 99, 100, 101, 57,               /* PORT4x */
-       70, 71, 72, 73, 74, 75, 76, 77,                 /* PORT5x */
-       81, 83, 84, 85, 86, 89, 90, 91,                 /* PORT6x */
-       118, 119, 120, 121, 122, 53, 54, 55,            /* PORT7x */
-       41, 42, 43, 44, 79, 80, 18, 19,                 /* PORT8x */
-       110, 111, 112, 113, 114, 115, 16, 17,           /* PORT9x */
-       40, 67, 68, 69, 78, 92, 93, 94,                 /* PORT10x */
-       48, 49, 46, 45, 123, 124, 125, 126,             /* PORT11x */
-       47, 127, 20, 56, 22,                            /* PORT120-124 */
-};
-static const unsigned port_range0_muxvals[] = {
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT0x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT1x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT2x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT11x */
-       15, 15, 15, 15, 15,                             /* PORT120-124 */
-};
-static const unsigned port_range1_pins[] = {
-       116, 117,                                       /* PORT130-131 */
-};
-static const unsigned port_range1_muxvals[] = {
-       15, 15,                                         /* PORT130-131 */
-};
-static const unsigned port_range2_pins[] = {
-       102, 103, 104, 105, 106, 107, 108, 109,         /* PORT14x */
-};
-static const unsigned port_range2_muxvals[] = {
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
-};
-static const unsigned port_range3_pins[] = {
-       23,                                             /* PORT166 */
-};
-static const unsigned port_range3_muxvals[] = {
-       15,                                             /* PORT166 */
-};
-static const unsigned xirq_range0_pins[] = {
-       128, 129, 130, 131, 132, 133, 134, 135,         /* XIRQ0-7 */
-       82, 87, 88, 50, 51,                             /* XIRQ8-12 */
-};
-static const unsigned xirq_range0_muxvals[] = {
-       0, 0, 0, 0, 0, 0, 0, 0,                         /* XIRQ0-7 */
-       14, 14, 14, 14, 14,                             /* XIRQ8-12 */
-};
-static const unsigned xirq_range1_pins[] = {
-       52, 58,                                         /* XIRQ14-15 */
-};
-static const unsigned xirq_range1_muxvals[] = {
-       14, 14,                                         /* XIRQ14-15 */
-};
-
-static const struct uniphier_pinctrl_group ph1_sld8_groups[] = {
-       UNIPHIER_PINCTRL_GROUP(emmc),
-       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
-       UNIPHIER_PINCTRL_GROUP(i2c0),
-       UNIPHIER_PINCTRL_GROUP(i2c1),
-       UNIPHIER_PINCTRL_GROUP(i2c2),
-       UNIPHIER_PINCTRL_GROUP(i2c3),
-       UNIPHIER_PINCTRL_GROUP(nand),
-       UNIPHIER_PINCTRL_GROUP(nand_cs1),
-       UNIPHIER_PINCTRL_GROUP(sd),
-       UNIPHIER_PINCTRL_GROUP(uart0),
-       UNIPHIER_PINCTRL_GROUP(uart1),
-       UNIPHIER_PINCTRL_GROUP(uart2),
-       UNIPHIER_PINCTRL_GROUP(uart3),
-       UNIPHIER_PINCTRL_GROUP(usb0),
-       UNIPHIER_PINCTRL_GROUP(usb1),
-       UNIPHIER_PINCTRL_GROUP(usb2),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range2),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range3),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range0),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range1, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range1, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range2, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range2, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range2, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range2, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range2, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range2, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range2, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range2, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port166, port_range3, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq_range0, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq_range0, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq_range0, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq_range0, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq_range0, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq_range0, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq_range0, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq_range0, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq_range0, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq_range0, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq_range0, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq_range0, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq_range0, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq_range1, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq_range1, 1),
-};
-
-static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
-static const char * const i2c0_groups[] = {"i2c0"};
-static const char * const i2c1_groups[] = {"i2c1"};
-static const char * const i2c2_groups[] = {"i2c2"};
-static const char * const i2c3_groups[] = {"i2c3"};
-static const char * const nand_groups[] = {"nand", "nand_cs1"};
-static const char * const sd_groups[] = {"sd"};
-static const char * const uart0_groups[] = {"uart0"};
-static const char * const uart1_groups[] = {"uart1"};
-static const char * const uart2_groups[] = {"uart2"};
-static const char * const uart3_groups[] = {"uart3"};
-static const char * const usb0_groups[] = {"usb0"};
-static const char * const usb1_groups[] = {"usb1"};
-static const char * const usb2_groups[] = {"usb2"};
-static const char * const port_groups[] = {
-       "port00",  "port01",  "port02",  "port03",
-       "port04",  "port05",  "port06",  "port07",
-       "port10",  "port11",  "port12",  "port13",
-       "port14",  "port15",  "port16",  "port17",
-       "port20",  "port21",  "port22",  "port23",
-       "port24",  "port25",  "port26",  "port27",
-       "port30",  "port31",  "port32",  "port33",
-       "port34",  "port35",  "port36",  "port37",
-       "port40",  "port41",  "port42",  "port43",
-       "port44",  "port45",  "port46",  "port47",
-       "port50",  "port51",  "port52",  "port53",
-       "port54",  "port55",  "port56",  "port57",
-       "port60",  "port61",  "port62",  "port63",
-       "port64",  "port65",  "port66",  "port67",
-       "port70",  "port71",  "port72",  "port73",
-       "port74",  "port75",  "port76",  "port77",
-       "port80",  "port81",  "port82",  "port83",
-       "port84",  "port85",  "port86",  "port87",
-       "port90",  "port91",  "port92",  "port93",
-       "port94",  "port95",  "port96",  "port97",
-       "port100", "port101", "port102", "port103",
-       "port104", "port105", "port106", "port107",
-       "port110", "port111", "port112", "port113",
-       "port114", "port115", "port116", "port117",
-       "port120", "port121", "port122", "port123",
-       "port124", "port125", "port126", "port127",
-       "port130", "port131", "port132", "port133",
-       "port134", "port135", "port136", "port137",
-       "port140", "port141", "port142", "port143",
-       "port144", "port145", "port146", "port147",
-       /* port150-164 missing */
-       /* none */ "port165",
-};
-static const char * const xirq_groups[] = {
-       "xirq0",  "xirq1",  "xirq2",  "xirq3",
-       "xirq4",  "xirq5",  "xirq6",  "xirq7",
-       "xirq8",  "xirq9",  "xirq10", "xirq11",
-       "xirq12", /* none*/ "xirq14", "xirq15",
-};
-
-static const struct uniphier_pinmux_function ph1_sld8_functions[] = {
-       UNIPHIER_PINMUX_FUNCTION(emmc),
-       UNIPHIER_PINMUX_FUNCTION(i2c0),
-       UNIPHIER_PINMUX_FUNCTION(i2c1),
-       UNIPHIER_PINMUX_FUNCTION(i2c2),
-       UNIPHIER_PINMUX_FUNCTION(i2c3),
-       UNIPHIER_PINMUX_FUNCTION(nand),
-       UNIPHIER_PINMUX_FUNCTION(sd),
-       UNIPHIER_PINMUX_FUNCTION(uart0),
-       UNIPHIER_PINMUX_FUNCTION(uart1),
-       UNIPHIER_PINMUX_FUNCTION(uart2),
-       UNIPHIER_PINMUX_FUNCTION(uart3),
-       UNIPHIER_PINMUX_FUNCTION(usb0),
-       UNIPHIER_PINMUX_FUNCTION(usb1),
-       UNIPHIER_PINMUX_FUNCTION(usb2),
-       UNIPHIER_PINMUX_FUNCTION(port),
-       UNIPHIER_PINMUX_FUNCTION(xirq),
-};
-
-static struct uniphier_pinctrl_socdata ph1_sld8_pindata = {
-       .groups = ph1_sld8_groups,
-       .groups_count = ARRAY_SIZE(ph1_sld8_groups),
-       .functions = ph1_sld8_functions,
-       .functions_count = ARRAY_SIZE(ph1_sld8_functions),
-       .mux_bits = 8,
-       .reg_stride = 4,
-       .load_pinctrl = false,
-};
-
-static struct pinctrl_desc ph1_sld8_pinctrl_desc = {
-       .name = DRIVER_NAME,
-       .pins = ph1_sld8_pins,
-       .npins = ARRAY_SIZE(ph1_sld8_pins),
-       .owner = THIS_MODULE,
-};
-
-static int ph1_sld8_pinctrl_probe(struct platform_device *pdev)
-{
-       return uniphier_pinctrl_probe(pdev, &ph1_sld8_pinctrl_desc,
-                                     &ph1_sld8_pindata);
-}
-
-static const struct of_device_id ph1_sld8_pinctrl_match[] = {
-       { .compatible = "socionext,ph1-sld8-pinctrl" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, ph1_sld8_pinctrl_match);
-
-static struct platform_driver ph1_sld8_pinctrl_driver = {
-       .probe = ph1_sld8_pinctrl_probe,
-       .remove = uniphier_pinctrl_remove,
-       .driver = {
-               .name = DRIVER_NAME,
-               .of_match_table = ph1_sld8_pinctrl_match,
-       },
-};
-module_platform_driver(ph1_sld8_pinctrl_driver);
-
-MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
-MODULE_DESCRIPTION("UniPhier PH1-sLD8 pinctrl driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-proxstream2.c b/drivers/pinctrl/uniphier/pinctrl-proxstream2.c
deleted file mode 100644 (file)
index bc00d75..0000000
+++ /dev/null
@@ -1,1274 +0,0 @@
-/*
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/platform_device.h>
-
-#include "pinctrl-uniphier.h"
-
-#define DRIVER_NAME "proxstream2-pinctrl"
-
-static const struct pinctrl_pin_desc proxstream2_pins[] = {
-       UNIPHIER_PINCTRL_PIN(0, "ED0", UNIPHIER_PIN_IECTRL_NONE,
-                            0, UNIPHIER_PIN_DRV_4_8,
-                            0, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(1, "ED1", UNIPHIER_PIN_IECTRL_NONE,
-                            1, UNIPHIER_PIN_DRV_4_8,
-                            1, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(2, "ED2", UNIPHIER_PIN_IECTRL_NONE,
-                            2, UNIPHIER_PIN_DRV_4_8,
-                            2, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(3, "ED3", UNIPHIER_PIN_IECTRL_NONE,
-                            3, UNIPHIER_PIN_DRV_4_8,
-                            3, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(4, "ED4", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_4_8,
-                            4, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(5, "ED5", UNIPHIER_PIN_IECTRL_NONE,
-                            5, UNIPHIER_PIN_DRV_4_8,
-                            5, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(6, "ED6", UNIPHIER_PIN_IECTRL_NONE,
-                            6, UNIPHIER_PIN_DRV_4_8,
-                            6, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(7, "ED7", UNIPHIER_PIN_IECTRL_NONE,
-                            7, UNIPHIER_PIN_DRV_4_8,
-                            7, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(8, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_4_8,
-                            8, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(9, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
-                            9, UNIPHIER_PIN_DRV_4_8,
-                            9, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(10, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
-                            10, UNIPHIER_PIN_DRV_4_8,
-                            10, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(11, "ES0", UNIPHIER_PIN_IECTRL_NONE,
-                            11, UNIPHIER_PIN_DRV_4_8,
-                            11, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(12, "ES1", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_4_8,
-                            12, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(13, "ES2", UNIPHIER_PIN_IECTRL_NONE,
-                            13, UNIPHIER_PIN_DRV_4_8,
-                            13, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(14, "XECS1", UNIPHIER_PIN_IECTRL_NONE,
-                            14, UNIPHIER_PIN_DRV_4_8,
-                            14, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(15, "SMTRST0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            15, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(16, "SMTCMD0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            16, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(17, "SMTD0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            17, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(18, "SMTSEL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            18, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(19, "SMTCLK0CG", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            19, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(20, "SMTDET0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            20, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(21, "SMTRST1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            21, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(22, "SMTCMD1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            22, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(23, "SMTD1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            23, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(24, "SMTSEL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            24, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(25, "SMTCLK1CG", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            25, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(26, "SMTDET1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            26, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(27, "XIRQ18", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            27, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(28, "XIRQ19", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            28, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(29, "XIRQ20", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            29, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(30, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
-                            30, UNIPHIER_PIN_DRV_4_8,
-                            30, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(31, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
-                            31, UNIPHIER_PIN_DRV_4_8,
-                            31, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(32, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
-                            32, UNIPHIER_PIN_DRV_4_8,
-                            32, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(33, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
-                            33, UNIPHIER_PIN_DRV_4_8,
-                            33, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(34, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
-                            34, UNIPHIER_PIN_DRV_4_8,
-                            34, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(35, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
-                            35, UNIPHIER_PIN_DRV_4_8,
-                            35, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(36, "NFRYBY0", UNIPHIER_PIN_IECTRL_NONE,
-                            36, UNIPHIER_PIN_DRV_4_8,
-                            36, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(37, "XNFCE1", UNIPHIER_PIN_IECTRL_NONE,
-                            37, UNIPHIER_PIN_DRV_4_8,
-                            37, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(38, "NFRYBY1", UNIPHIER_PIN_IECTRL_NONE,
-                            38, UNIPHIER_PIN_DRV_4_8,
-                            38, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(39, "NFD0", UNIPHIER_PIN_IECTRL_NONE,
-                            39, UNIPHIER_PIN_DRV_4_8,
-                            39, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(40, "NFD1", UNIPHIER_PIN_IECTRL_NONE,
-                            40, UNIPHIER_PIN_DRV_4_8,
-                            40, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(41, "NFD2", UNIPHIER_PIN_IECTRL_NONE,
-                            41, UNIPHIER_PIN_DRV_4_8,
-                            41, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(42, "NFD3", UNIPHIER_PIN_IECTRL_NONE,
-                            42, UNIPHIER_PIN_DRV_4_8,
-                            42, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(43, "NFD4", UNIPHIER_PIN_IECTRL_NONE,
-                            43, UNIPHIER_PIN_DRV_4_8,
-                            43, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(44, "NFD5", UNIPHIER_PIN_IECTRL_NONE,
-                            44, UNIPHIER_PIN_DRV_4_8,
-                            44, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(45, "NFD6", UNIPHIER_PIN_IECTRL_NONE,
-                            45, UNIPHIER_PIN_DRV_4_8,
-                            45, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(46, "NFD7", UNIPHIER_PIN_IECTRL_NONE,
-                            46, UNIPHIER_PIN_DRV_4_8,
-                            46, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(47, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
-                            0, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(48, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
-                            4, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(49, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
-                            8, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(50, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
-                            12, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(51, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
-                            16, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(52, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
-                            20, UNIPHIER_PIN_DRV_8_12_16_20,
-                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
-       UNIPHIER_PINCTRL_PIN(53, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            53, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(54, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            54, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(55, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            55, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(56, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            56, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(57, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            57, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(58, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            58, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(59, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            59, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(60, "USB2VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            60, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(61, "USB2OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            61, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(62, "USB3VBUS", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            62, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(63, "USB3OD", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            63, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(64, "CH0CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            64, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(65, "CH0PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            65, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(66, "CH0VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            66, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(67, "CH0DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            67, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(68, "CH1CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            68, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(69, "CH1PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            69, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(70, "CH1VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            70, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(71, "CH1DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            71, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(72, "XIRQ9", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            72, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(73, "XIRQ10", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            73, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(74, "XIRQ16", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            74, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(75, "CH4CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            75, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(76, "CH4PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            76, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(77, "CH4VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            77, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(78, "CH4DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            78, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(79, "CH5CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            79, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(80, "CH5PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            80, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(81, "CH5VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            81, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(82, "CH5DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            82, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(83, "CH6CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            83, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(84, "CH6PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            84, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(85, "CH6VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            85, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(86, "CH6DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            86, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(87, "STS0CLKO", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            87, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(88, "STS0SYNCO", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            88, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(89, "STS0VALO", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            89, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(90, "STS0DATAO", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            90, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(91, "XIRQ17", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            91, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(92, "PORT163", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            92, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(93, "PORT165", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            93, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(94, "PORT166", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            94, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(95, "PORT132", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            95, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(96, "PORT133", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            96, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(97, "AO2IEC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            97, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(98, "AI2ADCCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            98, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(99, "AI2BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            99, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(100, "AI2LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            100, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(101, "AI2D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            101, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(102, "AI2D1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            102, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(103, "AI2D2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            103, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(104, "AI2D3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            104, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(105, "AO3DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            105, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(106, "AO3BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            106, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(107, "AO3LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            107, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(108, "AO3DMIX", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            108, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(109, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            109, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(110, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            110, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(111, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            111, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(112, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            112, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(113, "TXD2", 0,
-                            113, UNIPHIER_PIN_DRV_4_8,
-                            113, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(114, "RXD2", 0,
-                            114, UNIPHIER_PIN_DRV_4_8,
-                            114, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(115, "TXD1", 0,
-                            115, UNIPHIER_PIN_DRV_4_8,
-                            115, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(116, "RXD1", 0,
-                            116, UNIPHIER_PIN_DRV_4_8,
-                            116, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(117, "PORT190", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            117, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(118, "VI1HSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            118, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(119, "VI1VSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            119, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(120, "VI1DE", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            120, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(121, "XIRQ3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            121, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(122, "XIRQ4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            122, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(123, "VI1G2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            123, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(124, "VI1G3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            124, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(125, "VI1G4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            125, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(126, "VI1G5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            126, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(127, "VI1G6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            127, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(128, "VI1G7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            128, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(129, "VI1G8", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            129, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(130, "VI1G9", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            130, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(131, "VI1CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            131, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(132, "PORT05", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            132, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(133, "PORT06", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            133, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(134, "VI1R2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            134, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(135, "VI1R3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            135, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(136, "VI1R4", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            136, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(137, "VI1R5", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            137, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(138, "VI1R6", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            138, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(139, "VI1R7", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            139, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(140, "VI1R8", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            140, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(141, "VI1R9", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            141, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(142, "LPST", UNIPHIER_PIN_IECTRL_NONE,
-                            142, UNIPHIER_PIN_DRV_4_8,
-                            142, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(143, "MDC", 0,
-                            143, UNIPHIER_PIN_DRV_4_8,
-                            143, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(144, "MDIO", 0,
-                            144, UNIPHIER_PIN_DRV_4_8,
-                            144, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(145, "MDIO_INTL", 0,
-                            145, UNIPHIER_PIN_DRV_4_8,
-                            145, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(146, "PHYRSTL", 0,
-                            146, UNIPHIER_PIN_DRV_4_8,
-                            146, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(147, "RGMII_RXCLK", 0,
-                            147, UNIPHIER_PIN_DRV_4_8,
-                            147, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(148, "RGMII_RXD0", 0,
-                            148, UNIPHIER_PIN_DRV_4_8,
-                            148, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(149, "RGMII_RXD1", 0,
-                            149, UNIPHIER_PIN_DRV_4_8,
-                            149, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(150, "RGMII_RXD2", 0,
-                            150, UNIPHIER_PIN_DRV_4_8,
-                            150, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(151, "RGMII_RXD3", 0,
-                            151, UNIPHIER_PIN_DRV_4_8,
-                            151, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(152, "RGMII_RXCTL", 0,
-                            152, UNIPHIER_PIN_DRV_4_8,
-                            152, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(153, "RGMII_TXCLK", 0,
-                            153, UNIPHIER_PIN_DRV_4_8,
-                            153, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(154, "RGMII_TXD0", 0,
-                            154, UNIPHIER_PIN_DRV_4_8,
-                            154, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(155, "RGMII_TXD1", 0,
-                            155, UNIPHIER_PIN_DRV_4_8,
-                            155, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(156, "RGMII_TXD2", 0,
-                            156, UNIPHIER_PIN_DRV_4_8,
-                            156, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(157, "RGMII_TXD3", 0,
-                            157, UNIPHIER_PIN_DRV_4_8,
-                            157, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(158, "RGMII_TXCTL", 0,
-                            158, UNIPHIER_PIN_DRV_4_8,
-                            158, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(159, "SDA3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            159, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(160, "SCL3", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            160, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(161, "AI1ADCCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            161, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(162, "AI1BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            162, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(163, "CH2CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            163, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(164, "CH2PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            164, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(165, "CH2VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            165, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(166, "CH2DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            166, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(167, "CH3CLK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            167, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(168, "CH3PSYNC", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            168, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(169, "CH3VAL", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            169, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(170, "CH3DATA", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            170, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(171, "SDA2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            171, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(172, "SCL2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            172, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(173, "AI1LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            173, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(174, "AI1D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            174, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(175, "AO2LRCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            175, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(176, "AO2D0", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            176, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(177, "AO2DACCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            177, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(178, "AO2BCK", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            178, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(179, "PORT222", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            179, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(180, "PORT223", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            180, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(181, "PORT224", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            181, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(182, "PORT225", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            182, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(183, "PORT226", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            183, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(184, "PORT227", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            184, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(185, "PORT230", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            185, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(186, "FANPWM", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            186, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(187, "HRDDCSDA0", 0,
-                            187, UNIPHIER_PIN_DRV_4_8,
-                            187, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(188, "HRDDCSCL0", 0,
-                            188, UNIPHIER_PIN_DRV_4_8,
-                            188, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(189, "HRDDCSDA1", 0,
-                            189, UNIPHIER_PIN_DRV_4_8,
-                            189, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(190, "HRDDCSCL1", 0,
-                            190, UNIPHIER_PIN_DRV_4_8,
-                            190, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(191, "HTDDCSDA0", 0,
-                            191, UNIPHIER_PIN_DRV_4_8,
-                            191, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(192, "HTDDCSCL0", 0,
-                            192, UNIPHIER_PIN_DRV_4_8,
-                            192, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(193, "HTDDCSDA1", 0,
-                            193, UNIPHIER_PIN_DRV_4_8,
-                            193, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(194, "HTDDCSCL1", 0,
-                            194, UNIPHIER_PIN_DRV_4_8,
-                            194, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(195, "PORT241", 0,
-                            195, UNIPHIER_PIN_DRV_4_8,
-                            195, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(196, "PORT242", 0,
-                            196, UNIPHIER_PIN_DRV_4_8,
-                            196, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(197, "PORT243", 0,
-                            197, UNIPHIER_PIN_DRV_4_8,
-                            197, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(198, "MVSYNC", 0,
-                            198, UNIPHIER_PIN_DRV_4_8,
-                            198, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(199, "SPISYNC0", UNIPHIER_PIN_IECTRL_NONE,
-                            199, UNIPHIER_PIN_DRV_4_8,
-                            199, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(200, "SPISCLK0", UNIPHIER_PIN_IECTRL_NONE,
-                            200, UNIPHIER_PIN_DRV_4_8,
-                            200, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(201, "SPITXD0", UNIPHIER_PIN_IECTRL_NONE,
-                            201, UNIPHIER_PIN_DRV_4_8,
-                            201, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(202, "SPIRXD0", UNIPHIER_PIN_IECTRL_NONE,
-                            202, UNIPHIER_PIN_DRV_4_8,
-                            202, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(203, "CK54EXI", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            203, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(204, "AEXCKA1", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            204, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(205, "AEXCKA2", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            205, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(206, "CK27EXI", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_8,
-                            206, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(207, "STCDIN", 0,
-                            207, UNIPHIER_PIN_DRV_4_8,
-                            207, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(208, "PHSYNI", 0,
-                            208, UNIPHIER_PIN_DRV_4_8,
-                            208, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(209, "PVSYNI", 0,
-                            209, UNIPHIER_PIN_DRV_4_8,
-                            209, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(210, "MVSYN", UNIPHIER_PIN_IECTRL_NONE,
-                            210, UNIPHIER_PIN_DRV_4_8,
-                            210, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(211, "STCV", UNIPHIER_PIN_IECTRL_NONE,
-                            211, UNIPHIER_PIN_DRV_4_8,
-                            211, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(212, "PORT262", UNIPHIER_PIN_IECTRL_NONE,
-                            212, UNIPHIER_PIN_DRV_4_8,
-                            212, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(213, "USB0VBUS_IRQ", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            213, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(214, "USB1VBUS_IRQ", UNIPHIER_PIN_IECTRL_NONE,
-                            -1, UNIPHIER_PIN_DRV_FIXED_4,
-                            214, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(215, "PORT265", UNIPHIER_PIN_IECTRL_NONE,
-                            215, UNIPHIER_PIN_DRV_4_8,
-                            215, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(216, "CK25O", 0,
-                            216, UNIPHIER_PIN_DRV_4_8,
-                            216, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(217, "TXD0", 0,
-                            217, UNIPHIER_PIN_DRV_4_8,
-                            217, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(218, "RXD0", 0,
-                            218, UNIPHIER_PIN_DRV_4_8,
-                            218, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(219, "TXD3", 0,
-                            219, UNIPHIER_PIN_DRV_4_8,
-                            219, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(220, "RXD3", 0,
-                            220, UNIPHIER_PIN_DRV_4_8,
-                            220, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(221, "PORT273", 0,
-                            221, UNIPHIER_PIN_DRV_4_8,
-                            221, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(222, "STCDOUTC", 0,
-                            222, UNIPHIER_PIN_DRV_4_8,
-                            222, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(223, "PORT274", 0,
-                            223, UNIPHIER_PIN_DRV_4_8,
-                            223, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(224, "PORT275", 0,
-                            224, UNIPHIER_PIN_DRV_4_8,
-                            224, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(225, "PORT276", 0,
-                            225, UNIPHIER_PIN_DRV_4_8,
-                            225, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(226, "PORT277", 0,
-                            226, UNIPHIER_PIN_DRV_4_8,
-                            226, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(227, "PORT280", 0,
-                            227, UNIPHIER_PIN_DRV_4_8,
-                            227, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(228, "PORT281", 0,
-                            228, UNIPHIER_PIN_DRV_4_8,
-                            228, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(229, "PORT282", 0,
-                            229, UNIPHIER_PIN_DRV_4_8,
-                            229, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(230, "PORT283", 0,
-                            230, UNIPHIER_PIN_DRV_4_8,
-                            230, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(231, "PORT284", 0,
-                            231, UNIPHIER_PIN_DRV_4_8,
-                            231, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(232, "PORT285", 0,
-                            232, UNIPHIER_PIN_DRV_4_8,
-                            232, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(233, "T0HPD", 0,
-                            233, UNIPHIER_PIN_DRV_4_8,
-                            233, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(234, "T1HPD", 0,
-                            234, UNIPHIER_PIN_DRV_4_8,
-                            234, UNIPHIER_PIN_PULL_DOWN),
-};
-
-static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
-static const unsigned emmc_muxvals[] = {9, 9, 9, 9, 9, 9, 9};
-static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
-static const unsigned emmc_dat8_muxvals[] = {9, 9, 9, 9};
-static const unsigned i2c0_pins[] = {109, 110};
-static const unsigned i2c0_muxvals[] = {8, 8};
-static const unsigned i2c1_pins[] = {111, 112};
-static const unsigned i2c1_muxvals[] = {8, 8};
-static const unsigned i2c2_pins[] = {171, 172};
-static const unsigned i2c2_muxvals[] = {8, 8};
-static const unsigned i2c3_pins[] = {159, 160};
-static const unsigned i2c3_muxvals[] = {8, 8};
-static const unsigned i2c5_pins[] = {183, 184};
-static const unsigned i2c5_muxvals[] = {11, 11};
-static const unsigned i2c6_pins[] = {185, 186};
-static const unsigned i2c6_muxvals[] = {11, 11};
-static const unsigned nand_pins[] = {30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
-                                    42, 43, 44, 45, 46};
-static const unsigned nand_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-                                       8, 8};
-static const unsigned nand_cs1_pins[] = {37, 38};
-static const unsigned nand_cs1_muxvals[] = {8, 8};
-static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
-static const unsigned sd_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8};
-static const unsigned uart0_pins[] = {217, 218};
-static const unsigned uart0_muxvals[] = {8, 8};
-static const unsigned uart0b_pins[] = {179, 180};
-static const unsigned uart0b_muxvals[] = {10, 10};
-static const unsigned uart1_pins[] = {115, 116};
-static const unsigned uart1_muxvals[] = {8, 8};
-static const unsigned uart2_pins[] = {113, 114};
-static const unsigned uart2_muxvals[] = {8, 8};
-static const unsigned uart3_pins[] = {219, 220};
-static const unsigned uart3_muxvals[] = {8, 8};
-static const unsigned uart3b_pins[] = {181, 182};
-static const unsigned uart3b_muxvals[] = {10, 10};
-static const unsigned usb0_pins[] = {56, 57};
-static const unsigned usb0_muxvals[] = {8, 8};
-static const unsigned usb1_pins[] = {58, 59};
-static const unsigned usb1_muxvals[] = {8, 8};
-static const unsigned usb2_pins[] = {60, 61};
-static const unsigned usb2_muxvals[] = {8, 8};
-static const unsigned usb3_pins[] = {62, 63};
-static const unsigned usb3_muxvals[] = {8, 8};
-static const unsigned port_range0_pins[] = {
-       127, 128, 129, 130, 131, 132, 133, 134,         /* PORT0x */
-       135, 136, 137, 138, 139, 140, 141, 142,         /* PORT1x */
-       0, 1, 2, 3, 4, 5, 6, 7,                         /* PORT2x */
-       8, 9, 10, 11, 12, 13, 14, 15,                   /* PORT3x */
-       16, 17, 18, 19, 21, 22, 23, 24,                 /* PORT4x */
-       25, 30, 31, 32, 33, 34, 35, 36,                 /* PORT5x */
-       37, 38, 39, 40, 41, 42, 43, 44,                 /* PORT6x */
-       45, 46, 47, 48, 49, 50, 51, 52,                 /* PORT7x */
-       53, 54, 55, 56, 57, 58, 59, 60,                 /* PORT8x */
-       61, 62, 63, 64, 65, 66, 67, 68,                 /* PORT9x */
-       69, 70, 71, 76, 77, 78, 79, 80,                 /* PORT10x */
-};
-static const unsigned port_range0_muxvals[] = {
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT0x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT1x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT2x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
-};
-static const unsigned port_range1_pins[] = {
-       81, 82, 83, 84, 85, 86, 87, 88,                 /* PORT12x */
-       89, 90, 95, 96, 97, 98, 99, 100,                /* PORT13x */
-       101, 102, 103, 104, 105, 106, 107, 108,         /* PORT14x */
-       118, 119, 120, 121, 122, 123, 124, 125,         /* PORT15x */
-       126, 72, 73, 92, 177, 93, 94, 176,              /* PORT16x */
-       74, 91, 27, 28, 29, 75, 20, 26,                 /* PORT17x */
-       109, 110, 111, 112, 113, 114, 115, 116,         /* PORT18x */
-       117, 143, 144, 145, 146, 147, 148, 149,         /* PORT19x */
-       150, 151, 152, 153, 154, 155, 156, 157,         /* PORT20x */
-       158, 159, 160, 161, 162, 163, 164, 165,         /* PORT21x */
-       166, 178, 179, 180, 181, 182, 183, 184,         /* PORT22x */
-       185, 187, 188, 189, 190, 191, 192, 193,         /* PORT23x */
-       194, 195, 196, 197, 198, 199, 200, 201,         /* PORT24x */
-       202, 203, 204, 205, 206, 207, 208, 209,         /* PORT25x */
-       210, 211, 212, 213, 214, 215, 216, 217,         /* PORT26x */
-       218, 219, 220, 221, 223, 224, 225, 226,         /* PORT27x */
-       227, 228, 229, 230, 231, 232, 233, 234,         /* PORT28x */
-};
-static const unsigned port_range1_muxvals[] = {
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT12x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT13x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT15x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT16x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT17x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT18x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT19x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT20x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT21x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT22x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT23x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT24x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT25x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT26x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT27x */
-       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT28x */
-};
-static const unsigned xirq_pins[] = {
-       118, 119, 120, 121, 122, 123, 124, 125,         /* XIRQ0-7 */
-       126, 72, 73, 92, 177, 93, 94, 176,              /* XIRQ8-15 */
-       74, 91, 27, 28, 29, 75, 20, 26,                 /* XIRQ16-23 */
-};
-static const unsigned xirq_muxvals[] = {
-       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ0-7 */
-       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ8-15 */
-       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ16-23 */
-};
-
-static const struct uniphier_pinctrl_group proxstream2_groups[] = {
-       UNIPHIER_PINCTRL_GROUP(emmc),
-       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
-       UNIPHIER_PINCTRL_GROUP(i2c0),
-       UNIPHIER_PINCTRL_GROUP(i2c1),
-       UNIPHIER_PINCTRL_GROUP(i2c2),
-       UNIPHIER_PINCTRL_GROUP(i2c3),
-       UNIPHIER_PINCTRL_GROUP(i2c5),
-       UNIPHIER_PINCTRL_GROUP(i2c6),
-       UNIPHIER_PINCTRL_GROUP(nand),
-       UNIPHIER_PINCTRL_GROUP(nand_cs1),
-       UNIPHIER_PINCTRL_GROUP(sd),
-       UNIPHIER_PINCTRL_GROUP(uart0),
-       UNIPHIER_PINCTRL_GROUP(uart0b),
-       UNIPHIER_PINCTRL_GROUP(uart1),
-       UNIPHIER_PINCTRL_GROUP(uart2),
-       UNIPHIER_PINCTRL_GROUP(uart3),
-       UNIPHIER_PINCTRL_GROUP(uart3b),
-       UNIPHIER_PINCTRL_GROUP(usb0),
-       UNIPHIER_PINCTRL_GROUP(usb1),
-       UNIPHIER_PINCTRL_GROUP(usb2),
-       UNIPHIER_PINCTRL_GROUP(usb3),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
-       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range1, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range1, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range1, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range1, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range1, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range1, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range1, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range1, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range1, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range1, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range1, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range1, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range1, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range1, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range1, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range1, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range1, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range1, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range1, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range1, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range1, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range1, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range1, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range1, 23),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port150, port_range1, 24),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port151, port_range1, 25),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port152, port_range1, 26),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port153, port_range1, 27),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port154, port_range1, 28),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port155, port_range1, 29),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port156, port_range1, 30),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port157, port_range1, 31),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port160, port_range1, 32),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port161, port_range1, 33),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port162, port_range1, 34),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port163, port_range1, 35),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port164, port_range1, 36),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port165, port_range1, 37),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port166, port_range1, 38),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port167, port_range1, 39),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port170, port_range1, 40),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port171, port_range1, 41),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port172, port_range1, 42),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port173, port_range1, 43),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port174, port_range1, 44),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port175, port_range1, 45),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port176, port_range1, 46),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port177, port_range1, 47),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range1, 48),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range1, 49),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range1, 50),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range1, 51),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range1, 52),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range1, 53),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range1, 54),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range1, 55),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port190, port_range1, 56),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port191, port_range1, 57),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port192, port_range1, 58),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port193, port_range1, 59),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port194, port_range1, 60),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port195, port_range1, 61),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port196, port_range1, 62),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port197, port_range1, 63),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range1, 64),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range1, 65),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range1, 66),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range1, 67),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range1, 68),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range1, 69),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range1, 70),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range1, 71),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range1, 72),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range1, 73),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range1, 74),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range1, 75),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range1, 76),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range1, 77),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range1, 78),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range1, 79),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range1, 80),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range1, 81),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range1, 82),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range1, 83),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range1, 84),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range1, 85),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range1, 86),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range1, 87),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range1, 88),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range1, 89),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range1, 90),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range1, 91),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range1, 92),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range1, 93),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range1, 94),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range1, 95),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range1, 96),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range1, 97),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range1, 98),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range1, 99),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range1, 100),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range1, 101),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range1, 102),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range1, 103),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range1, 104),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range1, 105),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range1, 106),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range1, 107),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range1, 108),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port255, port_range1, 109),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port256, port_range1, 110),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port257, port_range1, 111),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port260, port_range1, 112),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port261, port_range1, 113),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port262, port_range1, 114),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port263, port_range1, 115),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port264, port_range1, 116),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port265, port_range1, 117),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port266, port_range1, 118),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port267, port_range1, 119),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port270, port_range1, 120),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port271, port_range1, 121),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port272, port_range1, 122),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port273, port_range1, 123),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port274, port_range1, 124),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port275, port_range1, 125),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port276, port_range1, 126),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port277, port_range1, 127),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port280, port_range1, 128),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port281, port_range1, 129),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port282, port_range1, 130),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port283, port_range1, 131),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port284, port_range1, 132),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port285, port_range1, 133),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port286, port_range1, 134),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(port287, port_range1, 135),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21, xirq, 21),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22, xirq, 22),
-       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23, xirq, 23),
-};
-
-static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
-static const char * const i2c0_groups[] = {"i2c0"};
-static const char * const i2c1_groups[] = {"i2c1"};
-static const char * const i2c2_groups[] = {"i2c2"};
-static const char * const i2c3_groups[] = {"i2c3"};
-static const char * const i2c5_groups[] = {"i2c5"};
-static const char * const i2c6_groups[] = {"i2c6"};
-static const char * const nand_groups[] = {"nand", "nand_cs1"};
-static const char * const sd_groups[] = {"sd"};
-static const char * const uart0_groups[] = {"uart0", "uart0b"};
-static const char * const uart1_groups[] = {"uart1"};
-static const char * const uart2_groups[] = {"uart2"};
-static const char * const uart3_groups[] = {"uart3", "uart3b"};
-static const char * const usb0_groups[] = {"usb0"};
-static const char * const usb1_groups[] = {"usb1"};
-static const char * const usb2_groups[] = {"usb2"};
-static const char * const usb3_groups[] = {"usb3"};
-static const char * const port_groups[] = {
-       "port00",  "port01",  "port02",  "port03",
-       "port04",  "port05",  "port06",  "port07",
-       "port10",  "port11",  "port12",  "port13",
-       "port14",  "port15",  "port16",  "port17",
-       "port20",  "port21",  "port22",  "port23",
-       "port24",  "port25",  "port26",  "port27",
-       "port30",  "port31",  "port32",  "port33",
-       "port34",  "port35",  "port36",  "port37",
-       "port40",  "port41",  "port42",  "port43",
-       "port44",  "port45",  "port46",  "port47",
-       "port50",  "port51",  "port52",  "port53",
-       "port54",  "port55",  "port56",  "port57",
-       "port60",  "port61",  "port62",  "port63",
-       "port64",  "port65",  "port66",  "port67",
-       "port70",  "port71",  "port72",  "port73",
-       "port74",  "port75",  "port76",  "port77",
-       "port80",  "port81",  "port82",  "port83",
-       "port84",  "port85",  "port86",  "port87",
-       "port90",  "port91",  "port92",  "port93",
-       "port94",  "port95",  "port96",  "port97",
-       "port100", "port101", "port102", "port103",
-       "port104", "port105", "port106", "port107",
-       /* port110-117 missing */
-       "port120", "port121", "port122", "port123",
-       "port124", "port125", "port126", "port127",
-       "port130", "port131", "port132", "port133",
-       "port134", "port135", "port136", "port137",
-       "port140", "port141", "port142", "port143",
-       "port144", "port145", "port146", "port147",
-       "port150", "port151", "port152", "port153",
-       "port154", "port155", "port156", "port157",
-       "port160", "port161", "port162", "port163",
-       "port164", "port165", "port166", "port167",
-       "port170", "port171", "port172", "port173",
-       "port174", "port175", "port176", "port177",
-       "port180", "port181", "port182", "port183",
-       "port184", "port185", "port186", "port187",
-       "port190", "port191", "port192", "port193",
-       "port194", "port195", "port196", "port197",
-       "port200", "port201", "port202", "port203",
-       "port204", "port205", "port206", "port207",
-       "port210", "port211", "port212", "port213",
-       "port214", "port215", "port216", "port217",
-       "port220", "port221", "port222", "port223",
-       "port224", "port225", "port226", "port227",
-       "port230", "port231", "port232", "port233",
-       "port234", "port235", "port236", "port237",
-       "port240", "port241", "port242", "port243",
-       "port244", "port245", "port246", "port247",
-       "port250", "port251", "port252", "port253",
-       "port254", "port255", "port256", "port257",
-       "port260", "port261", "port262", "port263",
-       "port264", "port265", "port266", "port267",
-       "port270", "port271", "port272", "port273",
-       "port274", "port275", "port276", "port277",
-       "port280", "port281", "port282", "port283",
-       "port284", "port285", "port286", "port287",
-};
-static const char * const xirq_groups[] = {
-       "xirq0",  "xirq1",  "xirq2",  "xirq3",
-       "xirq4",  "xirq5",  "xirq6",  "xirq7",
-       "xirq8",  "xirq9",  "xirq10", "xirq11",
-       "xirq12", "xirq13", "xirq14", "xirq15",
-       "xirq16", "xirq17", "xirq18", "xirq19",
-       "xirq20", "xirq21", "xirq22", "xirq23",
-};
-
-static const struct uniphier_pinmux_function proxstream2_functions[] = {
-       UNIPHIER_PINMUX_FUNCTION(emmc),
-       UNIPHIER_PINMUX_FUNCTION(i2c0),
-       UNIPHIER_PINMUX_FUNCTION(i2c1),
-       UNIPHIER_PINMUX_FUNCTION(i2c2),
-       UNIPHIER_PINMUX_FUNCTION(i2c3),
-       UNIPHIER_PINMUX_FUNCTION(i2c5),
-       UNIPHIER_PINMUX_FUNCTION(i2c6),
-       UNIPHIER_PINMUX_FUNCTION(nand),
-       UNIPHIER_PINMUX_FUNCTION(sd),
-       UNIPHIER_PINMUX_FUNCTION(uart0),
-       UNIPHIER_PINMUX_FUNCTION(uart1),
-       UNIPHIER_PINMUX_FUNCTION(uart2),
-       UNIPHIER_PINMUX_FUNCTION(uart3),
-       UNIPHIER_PINMUX_FUNCTION(usb0),
-       UNIPHIER_PINMUX_FUNCTION(usb1),
-       UNIPHIER_PINMUX_FUNCTION(usb2),
-       UNIPHIER_PINMUX_FUNCTION(usb3),
-       UNIPHIER_PINMUX_FUNCTION(port),
-       UNIPHIER_PINMUX_FUNCTION(xirq),
-};
-
-static struct uniphier_pinctrl_socdata proxstream2_pindata = {
-       .groups = proxstream2_groups,
-       .groups_count = ARRAY_SIZE(proxstream2_groups),
-       .functions = proxstream2_functions,
-       .functions_count = ARRAY_SIZE(proxstream2_functions),
-       .mux_bits = 8,
-       .reg_stride = 4,
-       .load_pinctrl = false,
-};
-
-static struct pinctrl_desc proxstream2_pinctrl_desc = {
-       .name = DRIVER_NAME,
-       .pins = proxstream2_pins,
-       .npins = ARRAY_SIZE(proxstream2_pins),
-       .owner = THIS_MODULE,
-};
-
-static int proxstream2_pinctrl_probe(struct platform_device *pdev)
-{
-       return uniphier_pinctrl_probe(pdev, &proxstream2_pinctrl_desc,
-                                     &proxstream2_pindata);
-}
-
-static const struct of_device_id proxstream2_pinctrl_match[] = {
-       { .compatible = "socionext,proxstream2-pinctrl" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, proxstream2_pinctrl_match);
-
-static struct platform_driver proxstream2_pinctrl_driver = {
-       .probe = proxstream2_pinctrl_probe,
-       .remove = uniphier_pinctrl_remove,
-       .driver = {
-               .name = DRIVER_NAME,
-               .of_match_table = proxstream2_pinctrl_match,
-       },
-};
-module_platform_driver(proxstream2_pinctrl_driver);
-
-MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
-MODULE_DESCRIPTION("UniPhier ProXstream2 pinctrl driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld4.c
new file mode 100644 (file)
index 0000000..a7056dc
--- /dev/null
@@ -0,0 +1,891 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-uniphier.h"
+
+#define DRIVER_NAME "ph1-ld4-pinctrl"
+
+static const struct pinctrl_pin_desc ph1_ld4_pins[] = {
+       UNIPHIER_PINCTRL_PIN(0, "EA1", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_4_8,
+                            8, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(1, "EA2", UNIPHIER_PIN_IECTRL_NONE,
+                            9, UNIPHIER_PIN_DRV_4_8,
+                            9, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(2, "EA3", UNIPHIER_PIN_IECTRL_NONE,
+                            10, UNIPHIER_PIN_DRV_4_8,
+                            10, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(3, "EA4", UNIPHIER_PIN_IECTRL_NONE,
+                            11, UNIPHIER_PIN_DRV_4_8,
+                            11, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(4, "EA5", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_4_8,
+                            12, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(5, "EA6", UNIPHIER_PIN_IECTRL_NONE,
+                            13, UNIPHIER_PIN_DRV_4_8,
+                            13, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(6, "EA7", UNIPHIER_PIN_IECTRL_NONE,
+                            14, UNIPHIER_PIN_DRV_4_8,
+                            14, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(7, "EA8", 0,
+                            15, UNIPHIER_PIN_DRV_4_8,
+                            15, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(8, "EA9", 0,
+                            16, UNIPHIER_PIN_DRV_4_8,
+                            16, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(9, "EA10", 0,
+                            17, UNIPHIER_PIN_DRV_4_8,
+                            17, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(10, "EA11", 0,
+                            18, UNIPHIER_PIN_DRV_4_8,
+                            18, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(11, "EA12", 0,
+                            19, UNIPHIER_PIN_DRV_4_8,
+                            19, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(12, "EA13", 0,
+                            20, UNIPHIER_PIN_DRV_4_8,
+                            20, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(13, "EA14", 0,
+                            21, UNIPHIER_PIN_DRV_4_8,
+                            21, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(14, "EA15", 0,
+                            22, UNIPHIER_PIN_DRV_4_8,
+                            22, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(15, "ECLK", UNIPHIER_PIN_IECTRL_NONE,
+                            23, UNIPHIER_PIN_DRV_4_8,
+                            23, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(16, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
+                            24, UNIPHIER_PIN_DRV_4_8,
+                            24, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(17, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
+                            25, UNIPHIER_PIN_DRV_4_8,
+                            25, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(18, "ES0", UNIPHIER_PIN_IECTRL_NONE,
+                            27, UNIPHIER_PIN_DRV_4_8,
+                            27, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(19, "ES1", UNIPHIER_PIN_IECTRL_NONE,
+                            28, UNIPHIER_PIN_DRV_4_8,
+                            28, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(20, "ES2", UNIPHIER_PIN_IECTRL_NONE,
+                            29, UNIPHIER_PIN_DRV_4_8,
+                            29, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(21, "XERST", UNIPHIER_PIN_IECTRL_NONE,
+                            38, UNIPHIER_PIN_DRV_4_8,
+                            38, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(22, "MMCCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            0, UNIPHIER_PIN_DRV_8_12_16_20,
+                            146, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(23, "MMCCMD", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_8_12_16_20,
+                            147, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(24, "MMCDAT0", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_8_12_16_20,
+                            148, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(25, "MMCDAT1", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_8_12_16_20,
+                            149, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(26, "MMCDAT2", UNIPHIER_PIN_IECTRL_NONE,
+                            16, UNIPHIER_PIN_DRV_8_12_16_20,
+                            150, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(27, "MMCDAT3", UNIPHIER_PIN_IECTRL_NONE,
+                            20, UNIPHIER_PIN_DRV_8_12_16_20,
+                            151, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(28, "MMCDAT4", UNIPHIER_PIN_IECTRL_NONE,
+                            24, UNIPHIER_PIN_DRV_8_12_16_20,
+                            152, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(29, "MMCDAT5", UNIPHIER_PIN_IECTRL_NONE,
+                            28, UNIPHIER_PIN_DRV_8_12_16_20,
+                            153, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(30, "MMCDAT6", UNIPHIER_PIN_IECTRL_NONE,
+                            32, UNIPHIER_PIN_DRV_8_12_16_20,
+                            154, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(31, "MMCDAT7", UNIPHIER_PIN_IECTRL_NONE,
+                            36, UNIPHIER_PIN_DRV_8_12_16_20,
+                            155, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(32, "RMII_RXD0", 6,
+                            39, UNIPHIER_PIN_DRV_4_8,
+                            39, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(33, "RMII_RXD1", 6,
+                            40, UNIPHIER_PIN_DRV_4_8,
+                            40, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(34, "RMII_CRS_DV", 6,
+                            41, UNIPHIER_PIN_DRV_4_8,
+                            41, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(35, "RMII_RXER", 6,
+                            42, UNIPHIER_PIN_DRV_4_8,
+                            42, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(36, "RMII_REFCLK", 6,
+                            43, UNIPHIER_PIN_DRV_4_8,
+                            43, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(37, "RMII_TXD0", 6,
+                            44, UNIPHIER_PIN_DRV_4_8,
+                            44, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(38, "RMII_TXD1", 6,
+                            45, UNIPHIER_PIN_DRV_4_8,
+                            45, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(39, "RMII_TXEN", 6,
+                            46, UNIPHIER_PIN_DRV_4_8,
+                            46, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(40, "MDC", 6,
+                            47, UNIPHIER_PIN_DRV_4_8,
+                            47, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(41, "MDIO", 6,
+                            48, UNIPHIER_PIN_DRV_4_8,
+                            48, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(42, "MDIO_INTL", 6,
+                            49, UNIPHIER_PIN_DRV_4_8,
+                            49, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(43, "PHYRSTL", 6,
+                            50, UNIPHIER_PIN_DRV_4_8,
+                            50, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(44, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            40, UNIPHIER_PIN_DRV_8_12_16_20,
+                            156, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(45, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
+                            44, UNIPHIER_PIN_DRV_8_12_16_20,
+                            157, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(46, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
+                            48, UNIPHIER_PIN_DRV_8_12_16_20,
+                            158, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(47, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
+                            52, UNIPHIER_PIN_DRV_8_12_16_20,
+                            159, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(48, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
+                            56, UNIPHIER_PIN_DRV_8_12_16_20,
+                            160, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(49, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
+                            60, UNIPHIER_PIN_DRV_8_12_16_20,
+                            161, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(50, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
+                            51, UNIPHIER_PIN_DRV_4_8,
+                            51, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(51, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
+                            52, UNIPHIER_PIN_DRV_4_8,
+                            52, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(52, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
+                            53, UNIPHIER_PIN_DRV_4_8,
+                            53, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(53, "USB0VBUS", 0,
+                            54, UNIPHIER_PIN_DRV_4_8,
+                            54, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(54, "USB0OD", 0,
+                            55, UNIPHIER_PIN_DRV_4_8,
+                            55, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(55, "USB1VBUS", 0,
+                            56, UNIPHIER_PIN_DRV_4_8,
+                            56, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(56, "USB1OD", 0,
+                            57, UNIPHIER_PIN_DRV_4_8,
+                            57, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(57, "PCRESET", 0,
+                            58, UNIPHIER_PIN_DRV_4_8,
+                            58, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(58, "PCREG", 0,
+                            59, UNIPHIER_PIN_DRV_4_8,
+                            59, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(59, "PCCE2", 0,
+                            60, UNIPHIER_PIN_DRV_4_8,
+                            60, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(60, "PCVS1", 0,
+                            61, UNIPHIER_PIN_DRV_4_8,
+                            61, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(61, "PCCD2", 0,
+                            62, UNIPHIER_PIN_DRV_4_8,
+                            62, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(62, "PCCD1", 0,
+                            63, UNIPHIER_PIN_DRV_4_8,
+                            63, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(63, "PCREADY", 0,
+                            64, UNIPHIER_PIN_DRV_4_8,
+                            64, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(64, "PCDOE", 0,
+                            65, UNIPHIER_PIN_DRV_4_8,
+                            65, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(65, "PCCE1", 0,
+                            66, UNIPHIER_PIN_DRV_4_8,
+                            66, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(66, "PCWE", 0,
+                            67, UNIPHIER_PIN_DRV_4_8,
+                            67, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(67, "PCOE", 0,
+                            68, UNIPHIER_PIN_DRV_4_8,
+                            68, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(68, "PCWAIT", 0,
+                            69, UNIPHIER_PIN_DRV_4_8,
+                            69, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(69, "PCIOWR", 0,
+                            70, UNIPHIER_PIN_DRV_4_8,
+                            70, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(70, "PCIORD", 0,
+                            71, UNIPHIER_PIN_DRV_4_8,
+                            71, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(71, "HS0DIN0", 0,
+                            72, UNIPHIER_PIN_DRV_4_8,
+                            72, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(72, "HS0DIN1", 0,
+                            73, UNIPHIER_PIN_DRV_4_8,
+                            73, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(73, "HS0DIN2", 0,
+                            74, UNIPHIER_PIN_DRV_4_8,
+                            74, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(74, "HS0DIN3", 0,
+                            75, UNIPHIER_PIN_DRV_4_8,
+                            75, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(75, "HS0DIN4", 0,
+                            76, UNIPHIER_PIN_DRV_4_8,
+                            76, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(76, "HS0DIN5", 0,
+                            77, UNIPHIER_PIN_DRV_4_8,
+                            77, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(77, "HS0DIN6", 0,
+                            78, UNIPHIER_PIN_DRV_4_8,
+                            78, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(78, "HS0DIN7", 0,
+                            79, UNIPHIER_PIN_DRV_4_8,
+                            79, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(79, "HS0BCLKIN", 0,
+                            80, UNIPHIER_PIN_DRV_4_8,
+                            80, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(80, "HS0VALIN", 0,
+                            81, UNIPHIER_PIN_DRV_4_8,
+                            81, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(81, "HS0SYNCIN", 0,
+                            82, UNIPHIER_PIN_DRV_4_8,
+                            82, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(82, "HSDOUT0", 0,
+                            83, UNIPHIER_PIN_DRV_4_8,
+                            83, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(83, "HSDOUT1", 0,
+                            84, UNIPHIER_PIN_DRV_4_8,
+                            84, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(84, "HSDOUT2", 0,
+                            85, UNIPHIER_PIN_DRV_4_8,
+                            85, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(85, "HSDOUT3", 0,
+                            86, UNIPHIER_PIN_DRV_4_8,
+                            86, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(86, "HSDOUT4", 0,
+                            87, UNIPHIER_PIN_DRV_4_8,
+                            87, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(87, "HSDOUT5", 0,
+                            88, UNIPHIER_PIN_DRV_4_8,
+                            88, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(88, "HSDOUT6", 0,
+                            89, UNIPHIER_PIN_DRV_4_8,
+                            89, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(89, "HSDOUT7", 0,
+                            90, UNIPHIER_PIN_DRV_4_8,
+                            90, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(90, "HSBCLKOUT", 0,
+                            91, UNIPHIER_PIN_DRV_4_8,
+                            91, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(91, "HSVALOUT", 0,
+                            92, UNIPHIER_PIN_DRV_4_8,
+                            92, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(92, "HSSYNCOUT", 0,
+                            93, UNIPHIER_PIN_DRV_4_8,
+                            93, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(93, "AGCI", 3,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            162, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(94, "AGCR", 4,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            163, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(95, "AGCBS", 5,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            164, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(96, "IECOUT", 0,
+                            94, UNIPHIER_PIN_DRV_4_8,
+                            94, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(97, "ASMCK", 0,
+                            95, UNIPHIER_PIN_DRV_4_8,
+                            95, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(98, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
+                            96, UNIPHIER_PIN_DRV_4_8,
+                            96, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(99, "ALRCKO", UNIPHIER_PIN_IECTRL_NONE,
+                            97, UNIPHIER_PIN_DRV_4_8,
+                            97, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(100, "ASDOUT0", UNIPHIER_PIN_IECTRL_NONE,
+                            98, UNIPHIER_PIN_DRV_4_8,
+                            98, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(101, "ARCOUT", 0,
+                            99, UNIPHIER_PIN_DRV_4_8,
+                            99, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(102, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(103, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(104, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(105, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
+                            100, UNIPHIER_PIN_DRV_4_8,
+                            100, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
+                            101, UNIPHIER_PIN_DRV_4_8,
+                            101, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(112, "HIN", 1,
+                            -1, UNIPHIER_PIN_DRV_FIXED_5,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(113, "VIN", 2,
+                            -1, UNIPHIER_PIN_DRV_FIXED_5,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(114, "TCON0", UNIPHIER_PIN_IECTRL_NONE,
+                            102, UNIPHIER_PIN_DRV_4_8,
+                            102, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(115, "TCON1", UNIPHIER_PIN_IECTRL_NONE,
+                            103, UNIPHIER_PIN_DRV_4_8,
+                            103, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(116, "TCON2", UNIPHIER_PIN_IECTRL_NONE,
+                            104, UNIPHIER_PIN_DRV_4_8,
+                            104, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(117, "TCON3", UNIPHIER_PIN_IECTRL_NONE,
+                            105, UNIPHIER_PIN_DRV_4_8,
+                            105, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(118, "TCON4", UNIPHIER_PIN_IECTRL_NONE,
+                            106, UNIPHIER_PIN_DRV_4_8,
+                            106, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(119, "TCON5", UNIPHIER_PIN_IECTRL_NONE,
+                            107, UNIPHIER_PIN_DRV_4_8,
+                            107, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(120, "TCON6", 0,
+                            108, UNIPHIER_PIN_DRV_4_8,
+                            108, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(121, "TCON7", 0,
+                            109, UNIPHIER_PIN_DRV_4_8,
+                            109, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(122, "PWMA", 0,
+                            110, UNIPHIER_PIN_DRV_4_8,
+                            110, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(123, "XIRQ1", 0,
+                            111, UNIPHIER_PIN_DRV_4_8,
+                            111, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(124, "XIRQ2", 0,
+                            112, UNIPHIER_PIN_DRV_4_8,
+                            112, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(125, "XIRQ3", 0,
+                            113, UNIPHIER_PIN_DRV_4_8,
+                            113, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(126, "XIRQ4", 0,
+                            114, UNIPHIER_PIN_DRV_4_8,
+                            114, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(127, "XIRQ5", 0,
+                            115, UNIPHIER_PIN_DRV_4_8,
+                            115, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(128, "XIRQ6", 0,
+                            116, UNIPHIER_PIN_DRV_4_8,
+                            116, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(129, "XIRQ7", 0,
+                            117, UNIPHIER_PIN_DRV_4_8,
+                            117, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(130, "XIRQ8", 0,
+                            118, UNIPHIER_PIN_DRV_4_8,
+                            118, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(131, "XIRQ9", 0,
+                            119, UNIPHIER_PIN_DRV_4_8,
+                            119, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(132, "XIRQ10", 0,
+                            120, UNIPHIER_PIN_DRV_4_8,
+                            120, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(133, "XIRQ11", 0,
+                            121, UNIPHIER_PIN_DRV_4_8,
+                            121, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(134, "XIRQ14", 0,
+                            122, UNIPHIER_PIN_DRV_4_8,
+                            122, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(135, "PORT00", 0,
+                            123, UNIPHIER_PIN_DRV_4_8,
+                            123, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(136, "PORT01", 0,
+                            124, UNIPHIER_PIN_DRV_4_8,
+                            124, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(137, "PORT02", 0,
+                            125, UNIPHIER_PIN_DRV_4_8,
+                            125, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(138, "PORT03", 0,
+                            126, UNIPHIER_PIN_DRV_4_8,
+                            126, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(139, "PORT04", 0,
+                            127, UNIPHIER_PIN_DRV_4_8,
+                            127, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(140, "PORT05", 0,
+                            128, UNIPHIER_PIN_DRV_4_8,
+                            128, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(141, "PORT06", 0,
+                            129, UNIPHIER_PIN_DRV_4_8,
+                            129, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(142, "PORT07", 0,
+                            130, UNIPHIER_PIN_DRV_4_8,
+                            130, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(143, "PORT10", 0,
+                            131, UNIPHIER_PIN_DRV_4_8,
+                            131, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(144, "PORT11", 0,
+                            132, UNIPHIER_PIN_DRV_4_8,
+                            132, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(145, "PORT12", 0,
+                            133, UNIPHIER_PIN_DRV_4_8,
+                            133, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(146, "PORT13", 0,
+                            134, UNIPHIER_PIN_DRV_4_8,
+                            134, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(147, "PORT14", 0,
+                            135, UNIPHIER_PIN_DRV_4_8,
+                            135, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(148, "PORT15", 0,
+                            136, UNIPHIER_PIN_DRV_4_8,
+                            136, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(149, "PORT16", 0,
+                            137, UNIPHIER_PIN_DRV_4_8,
+                            137, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(150, "PORT17", UNIPHIER_PIN_IECTRL_NONE,
+                            138, UNIPHIER_PIN_DRV_4_8,
+                            138, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(151, "PORT20", 0,
+                            139, UNIPHIER_PIN_DRV_4_8,
+                            139, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(152, "PORT21", 0,
+                            140, UNIPHIER_PIN_DRV_4_8,
+                            140, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(153, "PORT22", 0,
+                            141, UNIPHIER_PIN_DRV_4_8,
+                            141, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(154, "PORT23", 0,
+                            142, UNIPHIER_PIN_DRV_4_8,
+                            142, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(155, "PORT24", UNIPHIER_PIN_IECTRL_NONE,
+                            143, UNIPHIER_PIN_DRV_4_8,
+                            143, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(156, "PORT25", 0,
+                            144, UNIPHIER_PIN_DRV_4_8,
+                            144, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(157, "PORT26", 0,
+                            145, UNIPHIER_PIN_DRV_4_8,
+                            145, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(158, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
+                            31, UNIPHIER_PIN_DRV_4_8,
+                            31, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(159, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
+                            32, UNIPHIER_PIN_DRV_4_8,
+                            32, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(160, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
+                            33, UNIPHIER_PIN_DRV_4_8,
+                            33, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(161, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
+                            34, UNIPHIER_PIN_DRV_4_8,
+                            34, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(162, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
+                            35, UNIPHIER_PIN_DRV_4_8,
+                            35, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(163, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
+                            36, UNIPHIER_PIN_DRV_4_8,
+                            36, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(164, "NANDRYBY0", UNIPHIER_PIN_IECTRL_NONE,
+                            37, UNIPHIER_PIN_DRV_4_8,
+                            37, UNIPHIER_PIN_PULL_UP),
+};
+
+static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
+static const unsigned emmc_muxvals[] = {0, 1, 1, 1, 1, 1, 1};
+static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
+static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const unsigned i2c0_pins[] = {102, 103};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {104, 105};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {108, 109};
+static const unsigned i2c2_muxvals[] = {2, 2};
+static const unsigned i2c3_pins[] = {108, 109};
+static const unsigned i2c3_muxvals[] = {3, 3};
+static const unsigned nand_pins[] = {24, 25, 26, 27, 28, 29, 30, 31, 158, 159,
+                                    160, 161, 162, 163, 164};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0};
+static const unsigned nand_cs1_pins[] = {22, 23};
+static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {44, 45, 46, 47, 48, 49, 50, 51, 52};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {85, 88};
+static const unsigned uart0_muxvals[] = {1, 1};
+static const unsigned uart1_pins[] = {155, 156};
+static const unsigned uart1_muxvals[] = {13, 13};
+static const unsigned uart1b_pins[] = {69, 70};
+static const unsigned uart1b_muxvals[] = {23, 23};
+static const unsigned uart2_pins[] = {128, 129};
+static const unsigned uart2_muxvals[] = {13, 13};
+static const unsigned uart3_pins[] = {110, 111};
+static const unsigned uart3_muxvals[] = {1, 1};
+static const unsigned usb0_pins[] = {53, 54};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {55, 56};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {155, 156};
+static const unsigned usb2_muxvals[] = {4, 4};
+static const unsigned usb2b_pins[] = {67, 68};
+static const unsigned usb2b_muxvals[] = {23, 23};
+static const unsigned port_range0_pins[] = {
+       135, 136, 137, 138, 139, 140, 141, 142,         /* PORT0x */
+       143, 144, 145, 146, 147, 148, 149, 150,         /* PORT1x */
+       151, 152, 153, 154, 155, 156, 157, 0,           /* PORT2x */
+       1, 2, 3, 4, 5, 120, 121, 122,                   /* PORT3x */
+       24, 25, 26, 27, 28, 29, 30, 31,                 /* PORT4x */
+       40, 41, 42, 43, 44, 45, 46, 47,                 /* PORT5x */
+       48, 49, 50, 51, 52, 53, 54, 55,                 /* PORT6x */
+       56, 85, 84, 59, 82, 61, 64, 65,                 /* PORT7x */
+       8, 9, 10, 11, 12, 13, 14, 15,                   /* PORT8x */
+       66, 67, 68, 69, 70, 71, 72, 73,                 /* PORT9x */
+       74, 75, 89, 86, 78, 79, 80, 81,                 /* PORT10x */
+       60, 83, 58, 57, 88, 87, 77, 76,                 /* PORT11x */
+       90, 91, 92, 93, 94, 95, 96, 97,                 /* PORT12x */
+       98, 99, 100, 6, 101, 114, 115, 116,             /* PORT13x */
+       103, 108, 21, 22, 23, 117, 118, 119,            /* PORT14x */
+};
+static const unsigned port_range0_muxvals[] = {
+       0, 0, 0, 0, 0, 0, 0, 0,                         /* PORT0x */
+       0, 0, 0, 0, 0, 0, 0, 0,                         /* PORT1x */
+       0, 0, 0, 0, 0, 0, 0, 15,                        /* PORT2x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT11x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT12x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT13x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
+};
+static const unsigned port_range1_pins[] = {
+       7,                                              /* PORT166 */
+};
+static const unsigned port_range1_muxvals[] = {
+       15,                                             /* PORT166 */
+};
+static const unsigned xirq_range0_pins[] = {
+       151, 123, 124, 125, 126, 127, 128, 129,         /* XIRQ0-7 */
+       130, 131, 132, 133, 62,                         /* XIRQ8-12 */
+};
+static const unsigned xirq_range0_muxvals[] = {
+       14, 0, 0, 0, 0, 0, 0, 0,                        /* XIRQ0-7 */
+       0, 0, 0, 0, 14,                                 /* XIRQ8-12 */
+};
+static const unsigned xirq_range1_pins[] = {
+       134, 63,                                        /* XIRQ14-15 */
+};
+static const unsigned xirq_range1_muxvals[] = {
+       0, 14,                                          /* XIRQ14-15 */
+};
+
+static const struct uniphier_pinctrl_group ph1_ld4_groups[] = {
+       UNIPHIER_PINCTRL_GROUP(emmc),
+       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+       UNIPHIER_PINCTRL_GROUP(i2c0),
+       UNIPHIER_PINCTRL_GROUP(i2c1),
+       UNIPHIER_PINCTRL_GROUP(i2c2),
+       UNIPHIER_PINCTRL_GROUP(i2c3),
+       UNIPHIER_PINCTRL_GROUP(nand),
+       UNIPHIER_PINCTRL_GROUP(nand_cs1),
+       UNIPHIER_PINCTRL_GROUP(sd),
+       UNIPHIER_PINCTRL_GROUP(uart0),
+       UNIPHIER_PINCTRL_GROUP(uart1),
+       UNIPHIER_PINCTRL_GROUP(uart1b),
+       UNIPHIER_PINCTRL_GROUP(uart2),
+       UNIPHIER_PINCTRL_GROUP(uart3),
+       UNIPHIER_PINCTRL_GROUP(usb0),
+       UNIPHIER_PINCTRL_GROUP(usb1),
+       UNIPHIER_PINCTRL_GROUP(usb2),
+       UNIPHIER_PINCTRL_GROUP(usb2b),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range0),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range0, 101),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range0, 102),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range0, 103),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range0, 104),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range0, 105),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range0, 106),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range0, 107),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range0, 108),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range0, 109),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range0, 110),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range0, 111),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range0, 112),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range0, 113),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range0, 114),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range0, 115),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range0, 116),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range0, 117),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range0, 118),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range0, 119),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port165, port_range1, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq_range0, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq_range0, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq_range0, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq_range0, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq_range0, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq_range0, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq_range0, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq_range0, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq_range0, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq_range0, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq_range0, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq_range0, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq_range0, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq_range1, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq_range1, 1),
+};
+
+static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
+static const char * const i2c0_groups[] = {"i2c0"};
+static const char * const i2c1_groups[] = {"i2c1"};
+static const char * const i2c2_groups[] = {"i2c2"};
+static const char * const i2c3_groups[] = {"i2c3"};
+static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const uart0_groups[] = {"uart0"};
+static const char * const uart1_groups[] = {"uart1", "uart1b"};
+static const char * const uart2_groups[] = {"uart2"};
+static const char * const uart3_groups[] = {"uart3"};
+static const char * const usb0_groups[] = {"usb0"};
+static const char * const usb1_groups[] = {"usb1"};
+static const char * const usb2_groups[] = {"usb2", "usb2b"};
+static const char * const port_groups[] = {
+       "port00",  "port01",  "port02",  "port03",
+       "port04",  "port05",  "port06",  "port07",
+       "port10",  "port11",  "port12",  "port13",
+       "port14",  "port15",  "port16",  "port17",
+       "port20",  "port21",  "port22",  "port23",
+       "port24",  "port25",  "port26",  "port27",
+       "port30",  "port31",  "port32",  "port33",
+       "port34",  "port35",  "port36",  "port37",
+       "port40",  "port41",  "port42",  "port43",
+       "port44",  "port45",  "port46",  "port47",
+       "port50",  "port51",  "port52",  "port53",
+       "port54",  "port55",  "port56",  "port57",
+       "port60",  "port61",  "port62",  "port63",
+       "port64",  "port65",  "port66",  "port67",
+       "port70",  "port71",  "port72",  "port73",
+       "port74",  "port75",  "port76",  "port77",
+       "port80",  "port81",  "port82",  "port83",
+       "port84",  "port85",  "port86",  "port87",
+       "port90",  "port91",  "port92",  "port93",
+       "port94",  "port95",  "port96",  "port97",
+       "port100", "port101", "port102", "port103",
+       "port104", "port105", "port106", "port107",
+       "port110", "port111", "port112", "port113",
+       "port114", "port115", "port116", "port117",
+       "port120", "port121", "port122", "port123",
+       "port124", "port125", "port126", "port127",
+       "port130", "port131", "port132", "port133",
+       "port134", "port135", "port136", "port137",
+       "port140", "port141", "port142", "port143",
+       "port144", "port145", "port146", "port147",
+       /* port150-164 missing */
+       /* none */ "port165",
+};
+static const char * const xirq_groups[] = {
+       "xirq0",  "xirq1",  "xirq2",  "xirq3",
+       "xirq4",  "xirq5",  "xirq6",  "xirq7",
+       "xirq8",  "xirq9",  "xirq10", "xirq11",
+       "xirq12", /* none*/ "xirq14", "xirq15",
+};
+
+static const struct uniphier_pinmux_function ph1_ld4_functions[] = {
+       UNIPHIER_PINMUX_FUNCTION(emmc),
+       UNIPHIER_PINMUX_FUNCTION(i2c0),
+       UNIPHIER_PINMUX_FUNCTION(i2c1),
+       UNIPHIER_PINMUX_FUNCTION(i2c2),
+       UNIPHIER_PINMUX_FUNCTION(i2c3),
+       UNIPHIER_PINMUX_FUNCTION(nand),
+       UNIPHIER_PINMUX_FUNCTION(sd),
+       UNIPHIER_PINMUX_FUNCTION(uart0),
+       UNIPHIER_PINMUX_FUNCTION(uart1),
+       UNIPHIER_PINMUX_FUNCTION(uart2),
+       UNIPHIER_PINMUX_FUNCTION(uart3),
+       UNIPHIER_PINMUX_FUNCTION(usb0),
+       UNIPHIER_PINMUX_FUNCTION(usb1),
+       UNIPHIER_PINMUX_FUNCTION(usb2),
+       UNIPHIER_PINMUX_FUNCTION(port),
+       UNIPHIER_PINMUX_FUNCTION(xirq),
+};
+
+static struct uniphier_pinctrl_socdata ph1_ld4_pindata = {
+       .groups = ph1_ld4_groups,
+       .groups_count = ARRAY_SIZE(ph1_ld4_groups),
+       .functions = ph1_ld4_functions,
+       .functions_count = ARRAY_SIZE(ph1_ld4_functions),
+       .mux_bits = 8,
+       .reg_stride = 4,
+       .load_pinctrl = false,
+};
+
+static struct pinctrl_desc ph1_ld4_pinctrl_desc = {
+       .name = DRIVER_NAME,
+       .pins = ph1_ld4_pins,
+       .npins = ARRAY_SIZE(ph1_ld4_pins),
+       .owner = THIS_MODULE,
+};
+
+static int ph1_ld4_pinctrl_probe(struct platform_device *pdev)
+{
+       return uniphier_pinctrl_probe(pdev, &ph1_ld4_pinctrl_desc,
+                                     &ph1_ld4_pindata);
+}
+
+static const struct of_device_id ph1_ld4_pinctrl_match[] = {
+       { .compatible = "socionext,ph1-ld4-pinctrl" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ph1_ld4_pinctrl_match);
+
+static struct platform_driver ph1_ld4_pinctrl_driver = {
+       .probe = ph1_ld4_pinctrl_probe,
+       .remove = uniphier_pinctrl_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .of_match_table = ph1_ld4_pinctrl_match,
+       },
+};
+module_platform_driver(ph1_ld4_pinctrl_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD4 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-ld6b.c
new file mode 100644 (file)
index 0000000..1824831
--- /dev/null
@@ -0,0 +1,1279 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-uniphier.h"
+
+#define DRIVER_NAME "ph1-ld6b-pinctrl"
+
+static const struct pinctrl_pin_desc ph1_ld6b_pins[] = {
+       UNIPHIER_PINCTRL_PIN(0, "ED0", UNIPHIER_PIN_IECTRL_NONE,
+                            0, UNIPHIER_PIN_DRV_4_8,
+                            0, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(1, "ED1", UNIPHIER_PIN_IECTRL_NONE,
+                            1, UNIPHIER_PIN_DRV_4_8,
+                            1, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(2, "ED2", UNIPHIER_PIN_IECTRL_NONE,
+                            2, UNIPHIER_PIN_DRV_4_8,
+                            2, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(3, "ED3", UNIPHIER_PIN_IECTRL_NONE,
+                            3, UNIPHIER_PIN_DRV_4_8,
+                            3, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(4, "ED4", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_4_8,
+                            4, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(5, "ED5", UNIPHIER_PIN_IECTRL_NONE,
+                            5, UNIPHIER_PIN_DRV_4_8,
+                            5, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(6, "ED6", UNIPHIER_PIN_IECTRL_NONE,
+                            6, UNIPHIER_PIN_DRV_4_8,
+                            6, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(7, "ED7", UNIPHIER_PIN_IECTRL_NONE,
+                            7, UNIPHIER_PIN_DRV_4_8,
+                            7, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(8, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_4_8,
+                            8, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(9, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
+                            9, UNIPHIER_PIN_DRV_4_8,
+                            9, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(10, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
+                            10, UNIPHIER_PIN_DRV_4_8,
+                            10, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(11, "ES0", UNIPHIER_PIN_IECTRL_NONE,
+                            11, UNIPHIER_PIN_DRV_4_8,
+                            11, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(12, "ES1", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_4_8,
+                            12, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(13, "ES2", UNIPHIER_PIN_IECTRL_NONE,
+                            13, UNIPHIER_PIN_DRV_4_8,
+                            13, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(14, "XECS1", UNIPHIER_PIN_IECTRL_NONE,
+                            14, UNIPHIER_PIN_DRV_4_8,
+                            14, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(15, "PCA00", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            15, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(16, "PCA01", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            16, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(17, "PCA02", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            17, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(18, "PCA03", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            18, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(19, "PCA04", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            19, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(20, "PCA05", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            20, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(21, "PCA06", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            21, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(22, "PCA07", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            22, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(23, "PCA08", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            23, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(24, "PCA09", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            24, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(25, "PCA10", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            25, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(26, "PCA11", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            26, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(27, "PCA12", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            27, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(28, "PCA13", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            28, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(29, "PCA14", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            29, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(30, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
+                            30, UNIPHIER_PIN_DRV_4_8,
+                            30, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(31, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
+                            31, UNIPHIER_PIN_DRV_4_8,
+                            31, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(32, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
+                            32, UNIPHIER_PIN_DRV_4_8,
+                            32, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(33, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
+                            33, UNIPHIER_PIN_DRV_4_8,
+                            33, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(34, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
+                            34, UNIPHIER_PIN_DRV_4_8,
+                            34, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(35, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
+                            35, UNIPHIER_PIN_DRV_4_8,
+                            35, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(36, "NFRYBY0", UNIPHIER_PIN_IECTRL_NONE,
+                            36, UNIPHIER_PIN_DRV_4_8,
+                            36, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(37, "XNFCE1", UNIPHIER_PIN_IECTRL_NONE,
+                            37, UNIPHIER_PIN_DRV_4_8,
+                            37, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(38, "NFRYBY1", UNIPHIER_PIN_IECTRL_NONE,
+                            38, UNIPHIER_PIN_DRV_4_8,
+                            38, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(39, "NFD0", UNIPHIER_PIN_IECTRL_NONE,
+                            39, UNIPHIER_PIN_DRV_4_8,
+                            39, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(40, "NFD1", UNIPHIER_PIN_IECTRL_NONE,
+                            40, UNIPHIER_PIN_DRV_4_8,
+                            40, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(41, "NFD2", UNIPHIER_PIN_IECTRL_NONE,
+                            41, UNIPHIER_PIN_DRV_4_8,
+                            41, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(42, "NFD3", UNIPHIER_PIN_IECTRL_NONE,
+                            42, UNIPHIER_PIN_DRV_4_8,
+                            42, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(43, "NFD4", UNIPHIER_PIN_IECTRL_NONE,
+                            43, UNIPHIER_PIN_DRV_4_8,
+                            43, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(44, "NFD5", UNIPHIER_PIN_IECTRL_NONE,
+                            44, UNIPHIER_PIN_DRV_4_8,
+                            44, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(45, "NFD6", UNIPHIER_PIN_IECTRL_NONE,
+                            45, UNIPHIER_PIN_DRV_4_8,
+                            45, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(46, "NFD7", UNIPHIER_PIN_IECTRL_NONE,
+                            46, UNIPHIER_PIN_DRV_4_8,
+                            46, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(47, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            0, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(48, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(49, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(50, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(51, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
+                            16, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(52, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
+                            20, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(53, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            53, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(54, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            54, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(55, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            55, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(56, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            56, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(57, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            57, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(58, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            58, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(59, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            59, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(60, "USB2VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            60, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(61, "USB2OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            61, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(62, "USB3VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            62, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(63, "USB3OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            63, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(64, "HS0BCLKOUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            64, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(65, "HS0SYNCOUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            65, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(66, "HS0VALOUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            66, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(67, "HS0DOUT0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            67, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(68, "HS0DOUT1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            68, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(69, "HS0DOUT2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            69, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(70, "HS0DOUT3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            70, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(71, "HS0DOUT4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            71, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(72, "HS0DOUT5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            72, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(73, "HS0DOUT6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            73, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(74, "HS0DOUT7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            74, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(75, "HS1BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            75, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(76, "HS1SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            76, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(77, "HS1VALIN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            77, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(78, "HS1DIN0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            78, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(79, "HS1DIN1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            79, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(80, "HS1DIN2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            80, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(81, "HS1DIN3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            81, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(82, "HS1DIN4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            82, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(83, "HS1DIN5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            83, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(84, "HS1DIN6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            84, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(85, "HS1DIN7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            85, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(86, "HS2BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            86, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(87, "HS2SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            87, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(88, "HS2VALIN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            88, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(89, "HS2DIN0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            89, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(90, "HS2DIN1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            90, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(91, "HS2DIN2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            91, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(92, "HS2DIN3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            92, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(93, "HS2DIN4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            93, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(94, "HS2DIN5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            94, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(95, "HS2DIN6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            95, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(96, "HS2DIN7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            96, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(97, "AO1IEC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            97, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(98, "AO1DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            98, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(99, "AO1BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            99, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(100, "AO1LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            100, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(101, "AO1D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            101, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(102, "AO1D1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            102, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(103, "AO1D2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            103, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(104, "AO1D3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            104, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(105, "AO2DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            105, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(106, "AO2BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            106, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(107, "AO2LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            107, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(108, "AO2D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            108, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(109, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            109, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(110, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            110, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(111, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            111, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(112, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            112, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(113, "SBO0", 0,
+                            113, UNIPHIER_PIN_DRV_4_8,
+                            113, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(114, "SBI0", 0,
+                            114, UNIPHIER_PIN_DRV_4_8,
+                            114, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(115, "TXD1", 0,
+                            115, UNIPHIER_PIN_DRV_4_8,
+                            115, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(116, "RXD1", 0,
+                            116, UNIPHIER_PIN_DRV_4_8,
+                            116, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(117, "PWSRA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            117, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(118, "XIRQ0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            118, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(119, "XIRQ1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            119, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(120, "XIRQ2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            120, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(121, "XIRQ3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            121, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(122, "XIRQ4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            122, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(123, "XIRQ5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            123, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(124, "XIRQ6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            124, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(125, "XIRQ7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            125, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(126, "XIRQ8", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            126, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(127, "PORT00", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            127, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(128, "PORT01", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            128, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(129, "PORT02", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            129, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(130, "PORT03", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            130, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(131, "PORT04", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            131, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(132, "PORT05", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            132, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(133, "PORT06", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            133, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(134, "PORT07", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            134, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(135, "PORT10", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            135, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(136, "PORT11", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            136, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(137, "PORT12", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            137, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(138, "PORT13", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            138, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(139, "PORT14", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            139, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(140, "PORT15", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            140, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(141, "PORT16", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            141, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(142, "LPST", UNIPHIER_PIN_IECTRL_NONE,
+                            142, UNIPHIER_PIN_DRV_4_8,
+                            142, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(143, "MDC", 0,
+                            143, UNIPHIER_PIN_DRV_4_8,
+                            143, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(144, "MDIO", 0,
+                            144, UNIPHIER_PIN_DRV_4_8,
+                            144, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(145, "MDIO_INTL", 0,
+                            145, UNIPHIER_PIN_DRV_4_8,
+                            145, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(146, "PHYRSTL", 0,
+                            146, UNIPHIER_PIN_DRV_4_8,
+                            146, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(147, "RGMII_RXCLK", 0,
+                            147, UNIPHIER_PIN_DRV_4_8,
+                            147, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(148, "RGMII_RXD0", 0,
+                            148, UNIPHIER_PIN_DRV_4_8,
+                            148, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(149, "RGMII_RXD1", 0,
+                            149, UNIPHIER_PIN_DRV_4_8,
+                            149, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(150, "RGMII_RXD2", 0,
+                            150, UNIPHIER_PIN_DRV_4_8,
+                            150, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(151, "RGMII_RXD3", 0,
+                            151, UNIPHIER_PIN_DRV_4_8,
+                            151, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(152, "RGMII_RXCTL", 0,
+                            152, UNIPHIER_PIN_DRV_4_8,
+                            152, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(153, "RGMII_TXCLK", 0,
+                            153, UNIPHIER_PIN_DRV_4_8,
+                            153, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(154, "RGMII_TXD0", 0,
+                            154, UNIPHIER_PIN_DRV_4_8,
+                            154, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(155, "RGMII_TXD1", 0,
+                            155, UNIPHIER_PIN_DRV_4_8,
+                            155, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(156, "RGMII_TXD2", 0,
+                            156, UNIPHIER_PIN_DRV_4_8,
+                            156, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(157, "RGMII_TXD3", 0,
+                            157, UNIPHIER_PIN_DRV_4_8,
+                            157, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(158, "RGMII_TXCTL", 0,
+                            158, UNIPHIER_PIN_DRV_4_8,
+                            158, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(159, "A_D_PCD00OUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            159, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(160, "A_D_PCD01OUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            160, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(161, "A_D_PCD02OUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            161, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(162, "A_D_PCD03OUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            162, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(163, "A_D_PCD04OUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            163, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(164, "A_D_PCD05OUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            164, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(165, "A_D_PCD06OUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            165, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(166, "A_D_PCD07OUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            166, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(167, "A_D_PCD00IN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            167, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(168, "A_D_PCD01IN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            168, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(169, "A_D_PCD02IN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            169, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(170, "A_D_PCD03IN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            170, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(171, "A_D_PCD04IN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            171, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(172, "A_D_PCD05IN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            172, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(173, "A_D_PCD06IN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            173, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(174, "A_D_PCD07IN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            174, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(175, "A_D_PCDNOE", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            175, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(176, "A_D_PC0READY", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            176, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(177, "A_D_PC0CD1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            177, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(178, "A_D_PC0CD2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            178, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(179, "A_D_PC0WAIT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            179, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(180, "A_D_PC0RESET", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            180, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(181, "A_D_PC0CE1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            181, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(182, "A_D_PC0WE", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            182, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(183, "A_D_PC0OE", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            183, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(184, "A_D_PC0IOWR", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            184, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(185, "A_D_PC0IORD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            185, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(186, "A_D_PC0NOE", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            186, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(187, "A_D_HS0BCLKIN", 0,
+                            187, UNIPHIER_PIN_DRV_4_8,
+                            187, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(188, "A_D_HS0SYNCIN", 0,
+                            188, UNIPHIER_PIN_DRV_4_8,
+                            188, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(189, "A_D_HS0VALIN", 0,
+                            189, UNIPHIER_PIN_DRV_4_8,
+                            189, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(190, "A_D_HS0DIN0", 0,
+                            190, UNIPHIER_PIN_DRV_4_8,
+                            190, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(191, "A_D_HS0DIN1", 0,
+                            191, UNIPHIER_PIN_DRV_4_8,
+                            191, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(192, "A_D_HS0DIN2", 0,
+                            192, UNIPHIER_PIN_DRV_4_8,
+                            192, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(193, "A_D_HS0DIN3", 0,
+                            193, UNIPHIER_PIN_DRV_4_8,
+                            193, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(194, "A_D_HS0DIN4", 0,
+                            194, UNIPHIER_PIN_DRV_4_8,
+                            194, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(195, "A_D_HS0DIN5", 0,
+                            195, UNIPHIER_PIN_DRV_4_8,
+                            195, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(196, "A_D_HS0DIN6", 0,
+                            196, UNIPHIER_PIN_DRV_4_8,
+                            196, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(197, "A_D_HS0DIN7", 0,
+                            197, UNIPHIER_PIN_DRV_4_8,
+                            197, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(198, "A_D_AO1ARC", 0,
+                            198, UNIPHIER_PIN_DRV_4_8,
+                            198, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(199, "A_D_SPIXRST", UNIPHIER_PIN_IECTRL_NONE,
+                            199, UNIPHIER_PIN_DRV_4_8,
+                            199, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(200, "A_D_SPISCLK0", UNIPHIER_PIN_IECTRL_NONE,
+                            200, UNIPHIER_PIN_DRV_4_8,
+                            200, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(201, "A_D_SPITXD0", UNIPHIER_PIN_IECTRL_NONE,
+                            201, UNIPHIER_PIN_DRV_4_8,
+                            201, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(202, "A_D_SPIRXD0", UNIPHIER_PIN_IECTRL_NONE,
+                            202, UNIPHIER_PIN_DRV_4_8,
+                            202, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(203, "A_D_DMDCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            203, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(204, "A_D_DMDPSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            204, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(205, "A_D_DMDVAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            205, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(206, "A_D_DMDDATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            206, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(207, "A_D_HDMIRXXIRQ", 0,
+                            207, UNIPHIER_PIN_DRV_4_8,
+                            207, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(208, "A_D_VBIXIRQ", 0,
+                            208, UNIPHIER_PIN_DRV_4_8,
+                            208, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(209, "A_D_HDMITXXIRQ", 0,
+                            209, UNIPHIER_PIN_DRV_4_8,
+                            209, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(210, "A_D_DMDIRQ", UNIPHIER_PIN_IECTRL_NONE,
+                            210, UNIPHIER_PIN_DRV_4_8,
+                            210, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(211, "A_D_SPICIRQ", UNIPHIER_PIN_IECTRL_NONE,
+                            211, UNIPHIER_PIN_DRV_4_8,
+                            211, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(212, "A_D_SPIBIRQ", UNIPHIER_PIN_IECTRL_NONE,
+                            212, UNIPHIER_PIN_DRV_4_8,
+                            212, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(213, "A_D_BESDAOUT", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            213, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(214, "A_D_BESDAIN", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            214, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(215, "A_D_BESCLOUT", UNIPHIER_PIN_IECTRL_NONE,
+                            215, UNIPHIER_PIN_DRV_4_8,
+                            215, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(216, "A_D_VDACCLKOUT", 0,
+                            216, UNIPHIER_PIN_DRV_4_8,
+                            216, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(217, "A_D_VDACDOUT5", 0,
+                            217, UNIPHIER_PIN_DRV_4_8,
+                            217, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(218, "A_D_VDACDOUT6", 0,
+                            218, UNIPHIER_PIN_DRV_4_8,
+                            218, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(219, "A_D_VDACDOUT7", 0,
+                            219, UNIPHIER_PIN_DRV_4_8,
+                            219, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(220, "A_D_VDACDOUT8", 0,
+                            220, UNIPHIER_PIN_DRV_4_8,
+                            220, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(221, "A_D_VDACDOUT9", 0,
+                            221, UNIPHIER_PIN_DRV_4_8,
+                            221, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(222, "A_D_SIFBCKIN", 0,
+                            222, UNIPHIER_PIN_DRV_4_8,
+                            222, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(223, "A_D_SIFLRCKIN", 0,
+                            223, UNIPHIER_PIN_DRV_4_8,
+                            223, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(224, "A_D_SIFDIN", 0,
+                            224, UNIPHIER_PIN_DRV_4_8,
+                            224, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(225, "A_D_LIBCKOUT", 0,
+                            225, UNIPHIER_PIN_DRV_4_8,
+                            225, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(226, "A_D_LILRCKOUT", 0,
+                            226, UNIPHIER_PIN_DRV_4_8,
+                            226, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(227, "A_D_LIDIN", 0,
+                            227, UNIPHIER_PIN_DRV_4_8,
+                            227, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(228, "A_D_LODOUT", 0,
+                            228, UNIPHIER_PIN_DRV_4_8,
+                            228, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(229, "A_D_HPDOUT", 0,
+                            229, UNIPHIER_PIN_DRV_4_8,
+                            229, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(230, "A_D_MCLK", 0,
+                            230, UNIPHIER_PIN_DRV_4_8,
+                            230, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(231, "A_D_A2PLLREFOUT", 0,
+                            231, UNIPHIER_PIN_DRV_4_8,
+                            231, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(232, "A_D_HDMI3DSDAOUT", 0,
+                            232, UNIPHIER_PIN_DRV_4_8,
+                            232, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(233, "A_D_HDMI3DSDAIN", 0,
+                            233, UNIPHIER_PIN_DRV_4_8,
+                            233, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(234, "A_D_HDMI3DSCLIN", 0,
+                            234, UNIPHIER_PIN_DRV_4_8,
+                            234, UNIPHIER_PIN_PULL_DOWN),
+};
+
+static const unsigned adinter_pins[] = {
+       159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+       173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+       187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
+       201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+       215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+       229, 230, 231, 232, 233, 234,
+};
+static const unsigned adinter_muxvals[] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0,
+};
+static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
+static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
+static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const unsigned i2c0_pins[] = {109, 110};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {111, 112};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {115, 116};
+static const unsigned i2c2_muxvals[] = {1, 1};
+static const unsigned i2c3_pins[] = {118, 119};
+static const unsigned i2c3_muxvals[] = {1, 1};
+static const unsigned nand_pins[] = {30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
+                                    42, 43, 44, 45, 46};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0};
+static const unsigned nand_cs1_pins[] = {37, 38};
+static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {135, 136};
+static const unsigned uart0_muxvals[] = {3, 3};
+static const unsigned uart0b_pins[] = {11, 12};
+static const unsigned uart0b_muxvals[] = {2, 2};
+static const unsigned uart1_pins[] = {115, 116};
+static const unsigned uart1_muxvals[] = {0, 0};
+static const unsigned uart1b_pins[] = {113, 114};
+static const unsigned uart1b_muxvals[] = {1, 1};
+static const unsigned uart2_pins[] = {113, 114};
+static const unsigned uart2_muxvals[] = {2, 2};
+static const unsigned uart2b_pins[] = {86, 87};
+static const unsigned uart2b_muxvals[] = {1, 1};
+static const unsigned usb0_pins[] = {56, 57};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {58, 59};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {60, 61};
+static const unsigned usb2_muxvals[] = {0, 0};
+static const unsigned usb3_pins[] = {62, 63};
+static const unsigned usb3_muxvals[] = {0, 0};
+static const unsigned port_range0_pins[] = {
+       127, 128, 129, 130, 131, 132, 133, 134,         /* PORT0x */
+       135, 136, 137, 138, 139, 140, 141, 142,         /* PORT1x */
+       0, 1, 2, 3, 4, 5, 6, 7,                         /* PORT2x */
+       8, 9, 10, 11, 12, 13, 14, 15,                   /* PORT3x */
+       16, 17, 18, 19, 21, 22, 23, 24,                 /* PORT4x */
+       25, 30, 31, 32, 33, 34, 35, 36,                 /* PORT5x */
+       37, 38, 39, 40, 41, 42, 43, 44,                 /* PORT6x */
+       45, 46, 47, 48, 49, 50, 51, 52,                 /* PORT7x */
+       53, 54, 55, 56, 57, 58, 59, 60,                 /* PORT8x */
+       61, 62, 63, 64, 65, 66, 67, 68,                 /* PORT9x */
+       69, 70, 71, 76, 77, 78, 79, 80,                 /* PORT10x */
+};
+static const unsigned port_range0_muxvals[] = {
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT0x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT1x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT2x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
+};
+static const unsigned port_range1_pins[] = {
+       81, 82, 83, 84, 85, 86, 87, 88,                 /* PORT12x */
+       89, 90, 95, 96, 97, 98, 99, 100,                /* PORT13x */
+       101, 102, 103, 104, 105, 106, 107, 108,         /* PORT14x */
+       118, 119, 120, 121, 122, 123, 124, 125,         /* PORT15x */
+       126, 72, 73, 92, 177, 93, 94, 176,              /* PORT16x */
+       74, 91, 27, 28, 29, 75, 20, 26,                 /* PORT17x */
+       109, 110, 111, 112, 113, 114, 115, 116,         /* PORT18x */
+       117, 143, 144, 145, 146, 147, 148, 149,         /* PORT19x */
+       150, 151, 152, 153, 154, 155, 156, 157,         /* PORT20x */
+       158, 159, 160, 161, 162, 163, 164, 165,         /* PORT21x */
+       166, 178, 179, 180, 181, 182, 183, 184,         /* PORT22x */
+       185, 187, 188, 189, 190, 191, 192, 193,         /* PORT23x */
+       194, 195, 196, 197, 198, 199, 200, 201,         /* PORT24x */
+       202, 203, 204, 205, 206, 207, 208, 209,         /* PORT25x */
+       210, 211, 212, 213, 214, 215, 216, 217,         /* PORT26x */
+       218, 219, 220, 221, 223, 224, 225, 226,         /* PORT27x */
+       227, 228, 229, 230, 231, 232, 233, 234,         /* PORT28x */
+};
+static const unsigned port_range1_muxvals[] = {
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT12x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT13x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT15x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT16x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT17x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT18x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT19x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT20x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT21x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT22x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT23x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT24x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT25x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT26x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT27x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT28x */
+};
+static const unsigned xirq_pins[] = {
+       118, 119, 120, 121, 122, 123, 124, 125,         /* XIRQ0-7 */
+       126, 72, 73, 92, 177, 93, 94, 176,              /* XIRQ8-15 */
+       74, 91, 27, 28, 29, 75, 20, 26,                 /* XIRQ16-23 */
+};
+static const unsigned xirq_muxvals[] = {
+       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ0-7 */
+       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ8-15 */
+       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ16-23 */
+};
+
+static const struct uniphier_pinctrl_group ph1_ld6b_groups[] = {
+       UNIPHIER_PINCTRL_GROUP(adinter),
+       UNIPHIER_PINCTRL_GROUP(emmc),
+       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+       UNIPHIER_PINCTRL_GROUP(i2c0),
+       UNIPHIER_PINCTRL_GROUP(i2c1),
+       UNIPHIER_PINCTRL_GROUP(i2c2),
+       UNIPHIER_PINCTRL_GROUP(i2c3),
+       UNIPHIER_PINCTRL_GROUP(nand),
+       UNIPHIER_PINCTRL_GROUP(nand_cs1),
+       UNIPHIER_PINCTRL_GROUP(sd),
+       UNIPHIER_PINCTRL_GROUP(uart0),
+       UNIPHIER_PINCTRL_GROUP(uart0b),
+       UNIPHIER_PINCTRL_GROUP(uart1),
+       UNIPHIER_PINCTRL_GROUP(uart1b),
+       UNIPHIER_PINCTRL_GROUP(uart2),
+       UNIPHIER_PINCTRL_GROUP(uart2b),
+       UNIPHIER_PINCTRL_GROUP(usb0),
+       UNIPHIER_PINCTRL_GROUP(usb1),
+       UNIPHIER_PINCTRL_GROUP(usb2),
+       UNIPHIER_PINCTRL_GROUP(usb3),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range1, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range1, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range1, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range1, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range1, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range1, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range1, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range1, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range1, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range1, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range1, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range1, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range1, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range1, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range1, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range1, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range1, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range1, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range1, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range1, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range1, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range1, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range1, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range1, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port150, port_range1, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port151, port_range1, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port152, port_range1, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port153, port_range1, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port154, port_range1, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port155, port_range1, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port156, port_range1, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port157, port_range1, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port160, port_range1, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port161, port_range1, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port162, port_range1, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port163, port_range1, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port164, port_range1, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port165, port_range1, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port166, port_range1, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port167, port_range1, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port170, port_range1, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port171, port_range1, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port172, port_range1, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port173, port_range1, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port174, port_range1, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port175, port_range1, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port176, port_range1, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port177, port_range1, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range1, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range1, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range1, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range1, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range1, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range1, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range1, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range1, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port190, port_range1, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port191, port_range1, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port192, port_range1, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port193, port_range1, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port194, port_range1, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port195, port_range1, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port196, port_range1, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port197, port_range1, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range1, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range1, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range1, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range1, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range1, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range1, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range1, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range1, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range1, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range1, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range1, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range1, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range1, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range1, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range1, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range1, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range1, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range1, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range1, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range1, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range1, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range1, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range1, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range1, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range1, 88),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range1, 89),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range1, 90),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range1, 91),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range1, 92),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range1, 93),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range1, 94),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range1, 95),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range1, 96),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range1, 97),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range1, 98),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range1, 99),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range1, 100),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range1, 101),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range1, 102),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range1, 103),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range1, 104),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range1, 105),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range1, 106),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range1, 107),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range1, 108),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port255, port_range1, 109),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port256, port_range1, 110),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port257, port_range1, 111),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port260, port_range1, 112),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port261, port_range1, 113),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port262, port_range1, 114),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port263, port_range1, 115),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port264, port_range1, 116),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port265, port_range1, 117),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port266, port_range1, 118),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port267, port_range1, 119),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port270, port_range1, 120),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port271, port_range1, 121),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port272, port_range1, 122),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port273, port_range1, 123),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port274, port_range1, 124),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port275, port_range1, 125),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port276, port_range1, 126),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port277, port_range1, 127),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port280, port_range1, 128),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port281, port_range1, 129),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port282, port_range1, 130),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port283, port_range1, 131),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port284, port_range1, 132),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port285, port_range1, 133),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port286, port_range1, 134),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port287, port_range1, 135),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21, xirq, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22, xirq, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23, xirq, 23),
+};
+
+static const char * const adinter_groups[] = {"adinter"};
+static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
+static const char * const i2c0_groups[] = {"i2c0"};
+static const char * const i2c1_groups[] = {"i2c1"};
+static const char * const i2c2_groups[] = {"i2c2"};
+static const char * const i2c3_groups[] = {"i2c3"};
+static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const uart0_groups[] = {"uart0", "uart0b"};
+static const char * const uart1_groups[] = {"uart1", "uart1b"};
+static const char * const uart2_groups[] = {"uart2", "uart2b"};
+static const char * const usb0_groups[] = {"usb0"};
+static const char * const usb1_groups[] = {"usb1"};
+static const char * const usb2_groups[] = {"usb2"};
+static const char * const usb3_groups[] = {"usb3"};
+static const char * const port_groups[] = {
+       "port00",  "port01",  "port02",  "port03",
+       "port04",  "port05",  "port06",  "port07",
+       "port10",  "port11",  "port12",  "port13",
+       "port14",  "port15",  "port16",  "port17",
+       "port20",  "port21",  "port22",  "port23",
+       "port24",  "port25",  "port26",  "port27",
+       "port30",  "port31",  "port32",  "port33",
+       "port34",  "port35",  "port36",  "port37",
+       "port40",  "port41",  "port42",  "port43",
+       "port44",  "port45",  "port46",  "port47",
+       "port50",  "port51",  "port52",  "port53",
+       "port54",  "port55",  "port56",  "port57",
+       "port60",  "port61",  "port62",  "port63",
+       "port64",  "port65",  "port66",  "port67",
+       "port70",  "port71",  "port72",  "port73",
+       "port74",  "port75",  "port76",  "port77",
+       "port80",  "port81",  "port82",  "port83",
+       "port84",  "port85",  "port86",  "port87",
+       "port90",  "port91",  "port92",  "port93",
+       "port94",  "port95",  "port96",  "port97",
+       "port100", "port101", "port102", "port103",
+       "port104", "port105", "port106", "port107",
+       /* port110-117 missing */
+       "port120", "port121", "port122", "port123",
+       "port124", "port125", "port126", "port127",
+       "port130", "port131", "port132", "port133",
+       "port134", "port135", "port136", "port137",
+       "port140", "port141", "port142", "port143",
+       "port144", "port145", "port146", "port147",
+       "port150", "port151", "port152", "port153",
+       "port154", "port155", "port156", "port157",
+       "port160", "port161", "port162", "port163",
+       "port164", "port165", "port166", "port167",
+       "port170", "port171", "port172", "port173",
+       "port174", "port175", "port176", "port177",
+       "port180", "port181", "port182", "port183",
+       "port184", "port185", "port186", "port187",
+       "port190", "port191", "port192", "port193",
+       "port194", "port195", "port196", "port197",
+       "port200", "port201", "port202", "port203",
+       "port204", "port205", "port206", "port207",
+       "port210", "port211", "port212", "port213",
+       "port214", "port215", "port216", "port217",
+       "port220", "port221", "port222", "port223",
+       "port224", "port225", "port226", "port227",
+       "port230", "port231", "port232", "port233",
+       "port234", "port235", "port236", "port237",
+       "port240", "port241", "port242", "port243",
+       "port244", "port245", "port246", "port247",
+       "port250", "port251", "port252", "port253",
+       "port254", "port255", "port256", "port257",
+       "port260", "port261", "port262", "port263",
+       "port264", "port265", "port266", "port267",
+       "port270", "port271", "port272", "port273",
+       "port274", "port275", "port276", "port277",
+       "port280", "port281", "port282", "port283",
+       "port284", "port285", "port286", "port287",
+};
+static const char * const xirq_groups[] = {
+       "xirq0",  "xirq1",  "xirq2",  "xirq3",
+       "xirq4",  "xirq5",  "xirq6",  "xirq7",
+       "xirq8",  "xirq9",  "xirq10", "xirq11",
+       "xirq12", "xirq13", "xirq14", "xirq15",
+       "xirq16", "xirq17", "xirq18", "xirq19",
+       "xirq20", "xirq21", "xirq22", "xirq23",
+};
+
+static const struct uniphier_pinmux_function ph1_ld6b_functions[] = {
+       UNIPHIER_PINMUX_FUNCTION(adinter), /* Achip-Dchip interconnect */
+       UNIPHIER_PINMUX_FUNCTION(emmc),
+       UNIPHIER_PINMUX_FUNCTION(i2c0),
+       UNIPHIER_PINMUX_FUNCTION(i2c1),
+       UNIPHIER_PINMUX_FUNCTION(i2c2),
+       UNIPHIER_PINMUX_FUNCTION(i2c3),
+       UNIPHIER_PINMUX_FUNCTION(nand),
+       UNIPHIER_PINMUX_FUNCTION(sd),
+       UNIPHIER_PINMUX_FUNCTION(uart0),
+       UNIPHIER_PINMUX_FUNCTION(uart1),
+       UNIPHIER_PINMUX_FUNCTION(uart2),
+       UNIPHIER_PINMUX_FUNCTION(usb0),
+       UNIPHIER_PINMUX_FUNCTION(usb1),
+       UNIPHIER_PINMUX_FUNCTION(usb2),
+       UNIPHIER_PINMUX_FUNCTION(usb3),
+       UNIPHIER_PINMUX_FUNCTION(port),
+       UNIPHIER_PINMUX_FUNCTION(xirq),
+};
+
+static struct uniphier_pinctrl_socdata ph1_ld6b_pindata = {
+       .groups = ph1_ld6b_groups,
+       .groups_count = ARRAY_SIZE(ph1_ld6b_groups),
+       .functions = ph1_ld6b_functions,
+       .functions_count = ARRAY_SIZE(ph1_ld6b_functions),
+       .mux_bits = 8,
+       .reg_stride = 4,
+       .load_pinctrl = false,
+};
+
+static struct pinctrl_desc ph1_ld6b_pinctrl_desc = {
+       .name = DRIVER_NAME,
+       .pins = ph1_ld6b_pins,
+       .npins = ARRAY_SIZE(ph1_ld6b_pins),
+       .owner = THIS_MODULE,
+};
+
+static int ph1_ld6b_pinctrl_probe(struct platform_device *pdev)
+{
+       return uniphier_pinctrl_probe(pdev, &ph1_ld6b_pinctrl_desc,
+                                     &ph1_ld6b_pindata);
+}
+
+static const struct of_device_id ph1_ld6b_pinctrl_match[] = {
+       { .compatible = "socionext,ph1-ld6b-pinctrl" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ph1_ld6b_pinctrl_match);
+
+static struct platform_driver ph1_ld6b_pinctrl_driver = {
+       .probe = ph1_ld6b_pinctrl_probe,
+       .remove = uniphier_pinctrl_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .of_match_table = ph1_ld6b_pinctrl_match,
+       },
+};
+module_platform_driver(ph1_ld6b_pinctrl_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-LD6b pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro4.c
new file mode 100644 (file)
index 0000000..ec8e92d
--- /dev/null
@@ -0,0 +1,1565 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program5 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-uniphier.h"
+
+#define DRIVER_NAME "ph1-pro4-pinctrl"
+
+static const struct pinctrl_pin_desc ph1_pro4_pins[] = {
+       UNIPHIER_PINCTRL_PIN(0, "CK24O", UNIPHIER_PIN_IECTRL_NONE,
+                            0, UNIPHIER_PIN_DRV_4_8,
+                            0, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(1, "VC27A", UNIPHIER_PIN_IECTRL_NONE,
+                            1, UNIPHIER_PIN_DRV_4_8,
+                            1, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(2, "CK27AI", UNIPHIER_PIN_IECTRL_NONE,
+                            2, UNIPHIER_PIN_DRV_4_8,
+                            2, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(3, "CK27AO", UNIPHIER_PIN_IECTRL_NONE,
+                            3, UNIPHIER_PIN_DRV_4_8,
+                            3, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(4, "CKSEL", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_4_8,
+                            4, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(5, "CK27AV", UNIPHIER_PIN_IECTRL_NONE,
+                            5, UNIPHIER_PIN_DRV_4_8,
+                            5, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(6, "AEXCKA", UNIPHIER_PIN_IECTRL_NONE,
+                            6, UNIPHIER_PIN_DRV_4_8,
+                            6, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(7, "ASEL", UNIPHIER_PIN_IECTRL_NONE,
+                            7, UNIPHIER_PIN_DRV_4_8,
+                            7, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(8, "ARCRESET", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_4_8,
+                            8, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(9, "ARCUNLOCK", UNIPHIER_PIN_IECTRL_NONE,
+                            9, UNIPHIER_PIN_DRV_4_8,
+                            9, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(10, "XSRST", UNIPHIER_PIN_IECTRL_NONE,
+                            10, UNIPHIER_PIN_DRV_4_8,
+                            10, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(11, "XNMIRQ", UNIPHIER_PIN_IECTRL_NONE,
+                            11, UNIPHIER_PIN_DRV_4_8,
+                            11, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(12, "XSCIRQ", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_4_8,
+                            12, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(13, "EXTRG", UNIPHIER_PIN_IECTRL_NONE,
+                            13, UNIPHIER_PIN_DRV_4_8,
+                            13, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(14, "TRCCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            14, UNIPHIER_PIN_DRV_4_8,
+                            14, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(15, "TRCCTL", UNIPHIER_PIN_IECTRL_NONE,
+                            15, UNIPHIER_PIN_DRV_4_8,
+                            15, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(16, "TRCD0", UNIPHIER_PIN_IECTRL_NONE,
+                            16, UNIPHIER_PIN_DRV_4_8,
+                            16, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(17, "TRCD1", UNIPHIER_PIN_IECTRL_NONE,
+                            17, UNIPHIER_PIN_DRV_4_8,
+                            17, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(18, "TRCD2", UNIPHIER_PIN_IECTRL_NONE,
+                            18, UNIPHIER_PIN_DRV_4_8,
+                            18, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(19, "TRCD3", UNIPHIER_PIN_IECTRL_NONE,
+                            19, UNIPHIER_PIN_DRV_4_8,
+                            19, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(20, "TRCD4", UNIPHIER_PIN_IECTRL_NONE,
+                            20, UNIPHIER_PIN_DRV_4_8,
+                            20, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(21, "TRCD5", UNIPHIER_PIN_IECTRL_NONE,
+                            21, UNIPHIER_PIN_DRV_4_8,
+                            21, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(22, "TRCD6", UNIPHIER_PIN_IECTRL_NONE,
+                            22, UNIPHIER_PIN_DRV_4_8,
+                            22, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(23, "TRCD7", UNIPHIER_PIN_IECTRL_NONE,
+                            23, UNIPHIER_PIN_DRV_4_8,
+                            23, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(24, "XECS1", UNIPHIER_PIN_IECTRL_NONE,
+                            24, UNIPHIER_PIN_DRV_4_8,
+                            24, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(25, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
+                            25, UNIPHIER_PIN_DRV_4_8,
+                            25, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(26, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
+                            26, UNIPHIER_PIN_DRV_4_8,
+                            26, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(27, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
+                            27, UNIPHIER_PIN_DRV_4_8,
+                            27, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(28, "ES0", UNIPHIER_PIN_IECTRL_NONE,
+                            28, UNIPHIER_PIN_DRV_4_8,
+                            28, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(29, "ES1", UNIPHIER_PIN_IECTRL_NONE,
+                            29, UNIPHIER_PIN_DRV_4_8,
+                            29, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(30, "ES2", UNIPHIER_PIN_IECTRL_NONE,
+                            30, UNIPHIER_PIN_DRV_4_8,
+                            30, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(31, "ED0", UNIPHIER_PIN_IECTRL_NONE,
+                            31, UNIPHIER_PIN_DRV_4_8,
+                            31, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(32, "ED1", UNIPHIER_PIN_IECTRL_NONE,
+                            32, UNIPHIER_PIN_DRV_4_8,
+                            32, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(33, "ED2", UNIPHIER_PIN_IECTRL_NONE,
+                            33, UNIPHIER_PIN_DRV_4_8,
+                            33, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(34, "ED3", UNIPHIER_PIN_IECTRL_NONE,
+                            34, UNIPHIER_PIN_DRV_4_8,
+                            34, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(35, "ED4", UNIPHIER_PIN_IECTRL_NONE,
+                            35, UNIPHIER_PIN_DRV_4_8,
+                            35, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(36, "ED5", UNIPHIER_PIN_IECTRL_NONE,
+                            36, UNIPHIER_PIN_DRV_4_8,
+                            36, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(37, "ED6", UNIPHIER_PIN_IECTRL_NONE,
+                            37, UNIPHIER_PIN_DRV_4_8,
+                            37, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(38, "ED7", UNIPHIER_PIN_IECTRL_NONE,
+                            38, UNIPHIER_PIN_DRV_4_8,
+                            38, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(39, "BOOTSWAP", UNIPHIER_PIN_IECTRL_NONE,
+                            39, UNIPHIER_PIN_DRV_NONE,
+                            39, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(40, "NFD0", UNIPHIER_PIN_IECTRL_NONE,
+                            2, UNIPHIER_PIN_DRV_8_12_16_20,
+                            40, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(41, "NFD1", UNIPHIER_PIN_IECTRL_NONE,
+                            3, UNIPHIER_PIN_DRV_8_12_16_20,
+                            41, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(42, "NFD2", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_8_12_16_20,
+                            42, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(43, "NFD3", UNIPHIER_PIN_IECTRL_NONE,
+                            5, UNIPHIER_PIN_DRV_8_12_16_20,
+                            43, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(44, "NFD4", UNIPHIER_PIN_IECTRL_NONE,
+                            6, UNIPHIER_PIN_DRV_8_12_16_20,
+                            44, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(45, "NFD5", UNIPHIER_PIN_IECTRL_NONE,
+                            7, UNIPHIER_PIN_DRV_8_12_16_20,
+                            45, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(46, "NFD6", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_8_12_16_20,
+                            46, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(47, "NFD7", UNIPHIER_PIN_IECTRL_NONE,
+                            9, UNIPHIER_PIN_DRV_8_12_16_20,
+                            47, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(48, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
+                            48, UNIPHIER_PIN_DRV_4_8,
+                            48, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(49, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
+                            49, UNIPHIER_PIN_DRV_4_8,
+                            49, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(50, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
+                            50, UNIPHIER_PIN_DRV_4_8,
+                            50, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(51, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
+                            0, UNIPHIER_PIN_DRV_8_12_16_20,
+                            51, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(52, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
+                            52, UNIPHIER_PIN_DRV_4_8,
+                            52, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(53, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
+                            1, UNIPHIER_PIN_DRV_8_12_16_20,
+                            53, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(54, "NRYBY0", UNIPHIER_PIN_IECTRL_NONE,
+                            54, UNIPHIER_PIN_DRV_4_8,
+                            54, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(55, "DMDSCLTST", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_NONE,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(56, "DMDSDATST", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(57, "AGCI0", 3,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            55, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(58, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(59, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(60, "AGCBS0", 5,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            56, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(61, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(62, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(63, "ANTSHORT", UNIPHIER_PIN_IECTRL_NONE,
+                            57, UNIPHIER_PIN_DRV_4_8,
+                            57, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(64, "CH0CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            58, UNIPHIER_PIN_DRV_4_8,
+                            58, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(65, "CH0VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            59, UNIPHIER_PIN_DRV_4_8,
+                            59, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(66, "CH0PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            60, UNIPHIER_PIN_DRV_4_8,
+                            60, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(67, "CH0DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            61, UNIPHIER_PIN_DRV_4_8,
+                            61, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(68, "CH1CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            62, UNIPHIER_PIN_DRV_4_8,
+                            62, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(69, "CH1VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            63, UNIPHIER_PIN_DRV_4_8,
+                            63, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(70, "CH1PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            64, UNIPHIER_PIN_DRV_4_8,
+                            64, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(71, "CH1DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            65, UNIPHIER_PIN_DRV_4_8,
+                            65, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(72, "CH2CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            66, UNIPHIER_PIN_DRV_4_8,
+                            66, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(73, "CH2VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            67, UNIPHIER_PIN_DRV_4_8,
+                            67, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(74, "CH2PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            68, UNIPHIER_PIN_DRV_4_8,
+                            68, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(75, "CH2DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            69, UNIPHIER_PIN_DRV_4_8,
+                            69, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(76, "CH3CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            70, UNIPHIER_PIN_DRV_4_8,
+                            70, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(77, "CH3VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            71, UNIPHIER_PIN_DRV_4_8,
+                            71, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(78, "CH3PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            72, UNIPHIER_PIN_DRV_4_8,
+                            72, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(79, "CH3DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            73, UNIPHIER_PIN_DRV_4_8,
+                            73, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(80, "CH4CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            74, UNIPHIER_PIN_DRV_4_8,
+                            74, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(81, "CH4VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            75, UNIPHIER_PIN_DRV_4_8,
+                            75, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(82, "CH4PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            76, UNIPHIER_PIN_DRV_4_8,
+                            76, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(83, "CH4DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            77, UNIPHIER_PIN_DRV_4_8,
+                            77, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(84, "CH5CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            78, UNIPHIER_PIN_DRV_4_8,
+                            78, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(85, "CH5VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            79, UNIPHIER_PIN_DRV_4_8,
+                            79, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(86, "CH5PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            80, UNIPHIER_PIN_DRV_4_8,
+                            80, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(87, "CH5DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            81, UNIPHIER_PIN_DRV_4_8,
+                            81, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(88, "CH6CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            82, UNIPHIER_PIN_DRV_4_8,
+                            82, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(89, "CH6VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            83, UNIPHIER_PIN_DRV_4_8,
+                            83, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(90, "CH6PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            84, UNIPHIER_PIN_DRV_4_8,
+                            84, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(91, "CH6DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            85, UNIPHIER_PIN_DRV_4_8,
+                            85, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(92, "CKFEO", UNIPHIER_PIN_IECTRL_NONE,
+                            86, UNIPHIER_PIN_DRV_4_8,
+                            86, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(93, "XFERST", UNIPHIER_PIN_IECTRL_NONE,
+                            87, UNIPHIER_PIN_DRV_4_8,
+                            87, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(94, "P_FE_ON", UNIPHIER_PIN_IECTRL_NONE,
+                            88, UNIPHIER_PIN_DRV_4_8,
+                            88, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(95, "P_TU0_ON", UNIPHIER_PIN_IECTRL_NONE,
+                            89, UNIPHIER_PIN_DRV_4_8,
+                            89, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(96, "XFEIRQ0", UNIPHIER_PIN_IECTRL_NONE,
+                            90, UNIPHIER_PIN_DRV_4_8,
+                            90, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(97, "XFEIRQ1", UNIPHIER_PIN_IECTRL_NONE,
+                            91, UNIPHIER_PIN_DRV_4_8,
+                            91, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(98, "XFEIRQ2", UNIPHIER_PIN_IECTRL_NONE,
+                            92, UNIPHIER_PIN_DRV_4_8,
+                            92, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(99, "XFEIRQ3", UNIPHIER_PIN_IECTRL_NONE,
+                            93, UNIPHIER_PIN_DRV_4_8,
+                            93, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(100, "XFEIRQ4", UNIPHIER_PIN_IECTRL_NONE,
+                            94, UNIPHIER_PIN_DRV_4_8,
+                            94, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(101, "XFEIRQ5", UNIPHIER_PIN_IECTRL_NONE,
+                            95, UNIPHIER_PIN_DRV_4_8,
+                            95, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(102, "XFEIRQ6", UNIPHIER_PIN_IECTRL_NONE,
+                            96, UNIPHIER_PIN_DRV_4_8,
+                            96, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(103, "SMTCLK0", UNIPHIER_PIN_IECTRL_NONE,
+                            97, UNIPHIER_PIN_DRV_4_8,
+                            97, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(104, "SMTRST0", UNIPHIER_PIN_IECTRL_NONE,
+                            98, UNIPHIER_PIN_DRV_4_8,
+                            98, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(105, "SMTCMD0", UNIPHIER_PIN_IECTRL_NONE,
+                            99, UNIPHIER_PIN_DRV_4_8,
+                            99, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(106, "SMTD0", UNIPHIER_PIN_IECTRL_NONE,
+                            100, UNIPHIER_PIN_DRV_4_8,
+                            100, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(107, "SMTSEL0", UNIPHIER_PIN_IECTRL_NONE,
+                            101, UNIPHIER_PIN_DRV_4_8,
+                            101, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(108, "SMTDET0", UNIPHIER_PIN_IECTRL_NONE,
+                            102, UNIPHIER_PIN_DRV_4_8,
+                            102, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(109, "SMTCLK1", UNIPHIER_PIN_IECTRL_NONE,
+                            103, UNIPHIER_PIN_DRV_4_8,
+                            103, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(110, "SMTRST1", UNIPHIER_PIN_IECTRL_NONE,
+                            104, UNIPHIER_PIN_DRV_4_8,
+                            104, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(111, "SMTCMD1", UNIPHIER_PIN_IECTRL_NONE,
+                            105, UNIPHIER_PIN_DRV_4_8,
+                            105, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(112, "SMTD1", UNIPHIER_PIN_IECTRL_NONE,
+                            106, UNIPHIER_PIN_DRV_4_8,
+                            106, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(113, "SMTSEL1", UNIPHIER_PIN_IECTRL_NONE,
+                            107, UNIPHIER_PIN_DRV_4_8,
+                            107, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(114, "SMTDET1", UNIPHIER_PIN_IECTRL_NONE,
+                            108, UNIPHIER_PIN_DRV_4_8,
+                            108, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(115, "XINTM", UNIPHIER_PIN_IECTRL_NONE,
+                            109, UNIPHIER_PIN_DRV_4_8,
+                            109, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(116, "SCLKM", UNIPHIER_PIN_IECTRL_NONE,
+                            110, UNIPHIER_PIN_DRV_4_8,
+                            110, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(117, "SBMTP", UNIPHIER_PIN_IECTRL_NONE,
+                            111, UNIPHIER_PIN_DRV_4_8,
+                            111, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(118, "SBPTM", UNIPHIER_PIN_IECTRL_NONE,
+                            112, UNIPHIER_PIN_DRV_4_8,
+                            112, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(119, "XMPREQ", UNIPHIER_PIN_IECTRL_NONE,
+                            113, UNIPHIER_PIN_DRV_4_8,
+                            113, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(120, "XINTP", UNIPHIER_PIN_IECTRL_NONE,
+                            114, UNIPHIER_PIN_DRV_4_8,
+                            114, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(121, "LPST", UNIPHIER_PIN_IECTRL_NONE,
+                            115, UNIPHIER_PIN_DRV_4_8,
+                            115, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(122, "SDBOOT", UNIPHIER_PIN_IECTRL_NONE,
+                            116, UNIPHIER_PIN_DRV_4_8,
+                            116, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(123, "BFAIL", UNIPHIER_PIN_IECTRL_NONE,
+                            117, UNIPHIER_PIN_DRV_4_8,
+                            117, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(124, "XFWE", UNIPHIER_PIN_IECTRL_NONE,
+                            118, UNIPHIER_PIN_DRV_4_8,
+                            118, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(125, "RF_COM_RDY", UNIPHIER_PIN_IECTRL_NONE,
+                            119, UNIPHIER_PIN_DRV_4_8,
+                            119, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(126, "XDIAG0", UNIPHIER_PIN_IECTRL_NONE,
+                            120, UNIPHIER_PIN_DRV_4_8,
+                            120, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(127, "RXD0", UNIPHIER_PIN_IECTRL_NONE,
+                            121, UNIPHIER_PIN_DRV_4_8,
+                            121, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(128, "TXD0", UNIPHIER_PIN_IECTRL_NONE,
+                            122, UNIPHIER_PIN_DRV_4_8,
+                            122, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(129, "RXD1", UNIPHIER_PIN_IECTRL_NONE,
+                            123, UNIPHIER_PIN_DRV_4_8,
+                            123, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(130, "TXD1", UNIPHIER_PIN_IECTRL_NONE,
+                            124, UNIPHIER_PIN_DRV_4_8,
+                            124, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(131, "RXD2", UNIPHIER_PIN_IECTRL_NONE,
+                            125, UNIPHIER_PIN_DRV_4_8,
+                            125, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(132, "TXD2", UNIPHIER_PIN_IECTRL_NONE,
+                            126, UNIPHIER_PIN_DRV_4_8,
+                            126, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(133, "SS0CS", UNIPHIER_PIN_IECTRL_NONE,
+                            127, UNIPHIER_PIN_DRV_4_8,
+                            127, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(134, "SS0CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            128, UNIPHIER_PIN_DRV_4_8,
+                            128, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(135, "SS0DO", UNIPHIER_PIN_IECTRL_NONE,
+                            129, UNIPHIER_PIN_DRV_4_8,
+                            129, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(136, "SS0DI", UNIPHIER_PIN_IECTRL_NONE,
+                            130, UNIPHIER_PIN_DRV_4_8,
+                            130, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(137, "MS0CS0", UNIPHIER_PIN_IECTRL_NONE,
+                            131, UNIPHIER_PIN_DRV_4_8,
+                            131, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(138, "MS0CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            132, UNIPHIER_PIN_DRV_4_8,
+                            132, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(139, "MS0DI", UNIPHIER_PIN_IECTRL_NONE,
+                            133, UNIPHIER_PIN_DRV_4_8,
+                            133, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(140, "MS0DO", UNIPHIER_PIN_IECTRL_NONE,
+                            134, UNIPHIER_PIN_DRV_4_8,
+                            134, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(141, "XMDMRST", UNIPHIER_PIN_IECTRL_NONE,
+                            135, UNIPHIER_PIN_DRV_4_8,
+                            135, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(142, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(143, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(144, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(145, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(146, "SCL2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(147, "SDA2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(148, "SCL3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(149, "SDA3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(150, "SD0DAT0", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_8_12_16_20,
+                            136, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(151, "SD0DAT1", UNIPHIER_PIN_IECTRL_NONE,
+                            13, UNIPHIER_PIN_DRV_8_12_16_20,
+                            137, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(152, "SD0DAT2", UNIPHIER_PIN_IECTRL_NONE,
+                            14, UNIPHIER_PIN_DRV_8_12_16_20,
+                            138, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(153, "SD0DAT3", UNIPHIER_PIN_IECTRL_NONE,
+                            15, UNIPHIER_PIN_DRV_8_12_16_20,
+                            139, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(154, "SD0CMD", UNIPHIER_PIN_IECTRL_NONE,
+                            11, UNIPHIER_PIN_DRV_8_12_16_20,
+                            141, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(155, "SD0CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            10, UNIPHIER_PIN_DRV_8_12_16_20,
+                            140, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(156, "SD0CD", UNIPHIER_PIN_IECTRL_NONE,
+                            142, UNIPHIER_PIN_DRV_4_8,
+                            142, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(157, "SD0WP", UNIPHIER_PIN_IECTRL_NONE,
+                            143, UNIPHIER_PIN_DRV_4_8,
+                            143, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(158, "SD0VTCG", UNIPHIER_PIN_IECTRL_NONE,
+                            144, UNIPHIER_PIN_DRV_4_8,
+                            144, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(159, "CK25O", UNIPHIER_PIN_IECTRL_NONE,
+                            145, UNIPHIER_PIN_DRV_4_8,
+                            145, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(160, "RGMII_TXCLK", 6,
+                            146, UNIPHIER_PIN_DRV_4_8,
+                            146, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(161, "RGMII_TXD0", 6,
+                            147, UNIPHIER_PIN_DRV_4_8,
+                            147, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(162, "RGMII_TXD1", 6,
+                            148, UNIPHIER_PIN_DRV_4_8,
+                            148, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(163, "RGMII_TXD2", 6,
+                            149, UNIPHIER_PIN_DRV_4_8,
+                            149, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(164, "RGMII_TXD3", 6,
+                            150, UNIPHIER_PIN_DRV_4_8,
+                            150, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(165, "RGMII_TXCTL", 6,
+                            151, UNIPHIER_PIN_DRV_4_8,
+                            151, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(166, "MII_TXER", UNIPHIER_PIN_IECTRL_NONE,
+                            152, UNIPHIER_PIN_DRV_4_8,
+                            152, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(167, "RGMII_RXCLK", 6,
+                            153, UNIPHIER_PIN_DRV_4_8,
+                            153, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(168, "RGMII_RXD0", 6,
+                            154, UNIPHIER_PIN_DRV_4_8,
+                            154, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(169, "RGMII_RXD1", 6,
+                            155, UNIPHIER_PIN_DRV_4_8,
+                            155, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(170, "RGMII_RXD2", 6,
+                            156, UNIPHIER_PIN_DRV_4_8,
+                            156, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(171, "RGMII_RXD3", 6,
+                            157, UNIPHIER_PIN_DRV_4_8,
+                            157, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(172, "RGMII_RXCTL", 6,
+                            158, UNIPHIER_PIN_DRV_4_8,
+                            158, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(173, "MII_RXER", 6,
+                            159, UNIPHIER_PIN_DRV_4_8,
+                            159, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(174, "MII_CRS", 6,
+                            160, UNIPHIER_PIN_DRV_4_8,
+                            160, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(175, "MII_COL", 6,
+                            161, UNIPHIER_PIN_DRV_4_8,
+                            161, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(176, "MDC", 6,
+                            162, UNIPHIER_PIN_DRV_4_8,
+                            162, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(177, "MDIO", 6,
+                            163, UNIPHIER_PIN_DRV_4_8,
+                            163, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(178, "MDIO_INTL", 6,
+                            164, UNIPHIER_PIN_DRV_4_8,
+                            164, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(179, "XETH_RST", 6,
+                            165, UNIPHIER_PIN_DRV_4_8,
+                            165, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(180, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            166, UNIPHIER_PIN_DRV_4_8,
+                            166, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(181, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
+                            167, UNIPHIER_PIN_DRV_4_8,
+                            167, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(182, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            168, UNIPHIER_PIN_DRV_4_8,
+                            168, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(183, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
+                            169, UNIPHIER_PIN_DRV_4_8,
+                            169, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(184, "USB2VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            170, UNIPHIER_PIN_DRV_4_8,
+                            170, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(185, "USB2OD", UNIPHIER_PIN_IECTRL_NONE,
+                            171, UNIPHIER_PIN_DRV_4_8,
+                            171, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(186, "USB2ID", UNIPHIER_PIN_IECTRL_NONE,
+                            172, UNIPHIER_PIN_DRV_4_8,
+                            172, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(187, "USB3VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            173, UNIPHIER_PIN_DRV_4_8,
+                            173, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(188, "USB3OD", UNIPHIER_PIN_IECTRL_NONE,
+                            174, UNIPHIER_PIN_DRV_4_8,
+                            174, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(189, "LINKCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            175, UNIPHIER_PIN_DRV_4_8,
+                            175, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(190, "LINKREQ", UNIPHIER_PIN_IECTRL_NONE,
+                            176, UNIPHIER_PIN_DRV_4_8,
+                            176, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(191, "LINKCTL0", UNIPHIER_PIN_IECTRL_NONE,
+                            177, UNIPHIER_PIN_DRV_4_8,
+                            177, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(192, "LINKCTL1", UNIPHIER_PIN_IECTRL_NONE,
+                            178, UNIPHIER_PIN_DRV_4_8,
+                            178, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(193, "LINKDT0", UNIPHIER_PIN_IECTRL_NONE,
+                            179, UNIPHIER_PIN_DRV_4_8,
+                            179, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(194, "LINKDT1", UNIPHIER_PIN_IECTRL_NONE,
+                            180, UNIPHIER_PIN_DRV_4_8,
+                            180, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(195, "LINKDT2", UNIPHIER_PIN_IECTRL_NONE,
+                            181, UNIPHIER_PIN_DRV_4_8,
+                            181, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(196, "LINKDT3", UNIPHIER_PIN_IECTRL_NONE,
+                            182, UNIPHIER_PIN_DRV_4_8,
+                            182, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(197, "LINKDT4", UNIPHIER_PIN_IECTRL_NONE,
+                            183, UNIPHIER_PIN_DRV_4_8,
+                            183, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(198, "LINKDT5", UNIPHIER_PIN_IECTRL_NONE,
+                            184, UNIPHIER_PIN_DRV_4_8,
+                            184, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(199, "LINKDT6", UNIPHIER_PIN_IECTRL_NONE,
+                            185, UNIPHIER_PIN_DRV_4_8,
+                            185, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(200, "LINKDT7", UNIPHIER_PIN_IECTRL_NONE,
+                            186, UNIPHIER_PIN_DRV_4_8,
+                            186, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(201, "CKDVO", UNIPHIER_PIN_IECTRL_NONE,
+                            187, UNIPHIER_PIN_DRV_4_8,
+                            187, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(202, "PHY_PD", UNIPHIER_PIN_IECTRL_NONE,
+                            188, UNIPHIER_PIN_DRV_4_8,
+                            188, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(203, "X1394_RST", UNIPHIER_PIN_IECTRL_NONE,
+                            189, UNIPHIER_PIN_DRV_4_8,
+                            189, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(204, "VOUT_MUTE_L", UNIPHIER_PIN_IECTRL_NONE,
+                            190, UNIPHIER_PIN_DRV_4_8,
+                            190, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(205, "CLK54O", UNIPHIER_PIN_IECTRL_NONE,
+                            191, UNIPHIER_PIN_DRV_4_8,
+                            191, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(206, "CLK54I", UNIPHIER_PIN_IECTRL_NONE,
+                            192, UNIPHIER_PIN_DRV_NONE,
+                            192, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(207, "YIN0", UNIPHIER_PIN_IECTRL_NONE,
+                            193, UNIPHIER_PIN_DRV_4_8,
+                            193, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(208, "YIN1", UNIPHIER_PIN_IECTRL_NONE,
+                            194, UNIPHIER_PIN_DRV_4_8,
+                            194, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(209, "YIN2", UNIPHIER_PIN_IECTRL_NONE,
+                            195, UNIPHIER_PIN_DRV_4_8,
+                            195, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(210, "YIN3", UNIPHIER_PIN_IECTRL_NONE,
+                            196, UNIPHIER_PIN_DRV_4_8,
+                            196, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(211, "YIN4", UNIPHIER_PIN_IECTRL_NONE,
+                            197, UNIPHIER_PIN_DRV_4_8,
+                            197, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(212, "YIN5", UNIPHIER_PIN_IECTRL_NONE,
+                            198, UNIPHIER_PIN_DRV_4_8,
+                            198, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(213, "CIN0", UNIPHIER_PIN_IECTRL_NONE,
+                            199, UNIPHIER_PIN_DRV_4_8,
+                            199, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(214, "CIN1", UNIPHIER_PIN_IECTRL_NONE,
+                            200, UNIPHIER_PIN_DRV_4_8,
+                            200, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(215, "CIN2", UNIPHIER_PIN_IECTRL_NONE,
+                            201, UNIPHIER_PIN_DRV_4_8,
+                            201, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(216, "CIN3", UNIPHIER_PIN_IECTRL_NONE,
+                            202, UNIPHIER_PIN_DRV_4_8,
+                            202, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(217, "CIN4", UNIPHIER_PIN_IECTRL_NONE,
+                            203, UNIPHIER_PIN_DRV_4_8,
+                            203, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(218, "CIN5", UNIPHIER_PIN_IECTRL_NONE,
+                            204, UNIPHIER_PIN_DRV_4_8,
+                            204, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(219, "GCP", UNIPHIER_PIN_IECTRL_NONE,
+                            205, UNIPHIER_PIN_DRV_4_8,
+                            205, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(220, "ADFLG", UNIPHIER_PIN_IECTRL_NONE,
+                            206, UNIPHIER_PIN_DRV_4_8,
+                            206, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(221, "CK27AIOF", UNIPHIER_PIN_IECTRL_NONE,
+                            207, UNIPHIER_PIN_DRV_4_8,
+                            207, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(222, "DACOUT", UNIPHIER_PIN_IECTRL_NONE,
+                            208, UNIPHIER_PIN_DRV_4_8,
+                            208, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(223, "DAFLG", UNIPHIER_PIN_IECTRL_NONE,
+                            209, UNIPHIER_PIN_DRV_4_8,
+                            209, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(224, "VBIH", UNIPHIER_PIN_IECTRL_NONE,
+                            210, UNIPHIER_PIN_DRV_4_8,
+                            210, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(225, "VBIL", UNIPHIER_PIN_IECTRL_NONE,
+                            211, UNIPHIER_PIN_DRV_4_8,
+                            211, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(226, "XSUB_RST", UNIPHIER_PIN_IECTRL_NONE,
+                            212, UNIPHIER_PIN_DRV_4_8,
+                            212, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(227, "XADC_PD", UNIPHIER_PIN_IECTRL_NONE,
+                            213, UNIPHIER_PIN_DRV_4_8,
+                            213, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(228, "AI1ADCCK", UNIPHIER_PIN_IECTRL_NONE,
+                            214, UNIPHIER_PIN_DRV_4_8,
+                            214, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(229, "AI1BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            215, UNIPHIER_PIN_DRV_4_8,
+                            215, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(230, "AI1LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            216, UNIPHIER_PIN_DRV_4_8,
+                            216, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(231, "AI1DMIX", UNIPHIER_PIN_IECTRL_NONE,
+                            217, UNIPHIER_PIN_DRV_4_8,
+                            217, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(232, "CK27HD", UNIPHIER_PIN_IECTRL_NONE,
+                            218, UNIPHIER_PIN_DRV_4_8,
+                            218, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(233, "XHD_RST", UNIPHIER_PIN_IECTRL_NONE,
+                            219, UNIPHIER_PIN_DRV_4_8,
+                            219, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(234, "INTHD", UNIPHIER_PIN_IECTRL_NONE,
+                            220, UNIPHIER_PIN_DRV_4_8,
+                            220, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(235, "VO1HDCK", UNIPHIER_PIN_IECTRL_NONE,
+                            221, UNIPHIER_PIN_DRV_4_8,
+                            221, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(236, "VO1HSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            222, UNIPHIER_PIN_DRV_4_8,
+                            222, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(237, "VO1VSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            223, UNIPHIER_PIN_DRV_4_8,
+                            223, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(238, "VO1DE", UNIPHIER_PIN_IECTRL_NONE,
+                            224, UNIPHIER_PIN_DRV_4_8,
+                            224, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(239, "VO1Y0", UNIPHIER_PIN_IECTRL_NONE,
+                            225, UNIPHIER_PIN_DRV_4_8,
+                            225, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(240, "VO1Y1", UNIPHIER_PIN_IECTRL_NONE,
+                            226, UNIPHIER_PIN_DRV_4_8,
+                            226, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(241, "VO1Y2", UNIPHIER_PIN_IECTRL_NONE,
+                            227, UNIPHIER_PIN_DRV_4_8,
+                            227, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(242, "VO1Y3", UNIPHIER_PIN_IECTRL_NONE,
+                            228, UNIPHIER_PIN_DRV_4_8,
+                            228, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(243, "VO1Y4", UNIPHIER_PIN_IECTRL_NONE,
+                            229, UNIPHIER_PIN_DRV_4_8,
+                            229, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(244, "VO1Y5", UNIPHIER_PIN_IECTRL_NONE,
+                            230, UNIPHIER_PIN_DRV_4_8,
+                            230, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(245, "VO1Y6", UNIPHIER_PIN_IECTRL_NONE,
+                            231, UNIPHIER_PIN_DRV_4_8,
+                            231, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(246, "VO1Y7", UNIPHIER_PIN_IECTRL_NONE,
+                            232, UNIPHIER_PIN_DRV_4_8,
+                            232, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(247, "VO1Y8", UNIPHIER_PIN_IECTRL_NONE,
+                            233, UNIPHIER_PIN_DRV_4_8,
+                            233, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(248, "VO1Y9", UNIPHIER_PIN_IECTRL_NONE,
+                            234, UNIPHIER_PIN_DRV_4_8,
+                            234, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(249, "VO1Y10", UNIPHIER_PIN_IECTRL_NONE,
+                            235, UNIPHIER_PIN_DRV_4_8,
+                            235, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(250, "VO1Y11", UNIPHIER_PIN_IECTRL_NONE,
+                            236, UNIPHIER_PIN_DRV_4_8,
+                            236, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(251, "VO1CB0", UNIPHIER_PIN_IECTRL_NONE,
+                            237, UNIPHIER_PIN_DRV_4_8,
+                            237, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(252, "VO1CB1", UNIPHIER_PIN_IECTRL_NONE,
+                            238, UNIPHIER_PIN_DRV_4_8,
+                            238, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(253, "VO1CB2", UNIPHIER_PIN_IECTRL_NONE,
+                            239, UNIPHIER_PIN_DRV_4_8,
+                            239, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(254, "VO1CB3", UNIPHIER_PIN_IECTRL_NONE,
+                            240, UNIPHIER_PIN_DRV_4_8,
+                            240, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(255, "VO1CB4", UNIPHIER_PIN_IECTRL_NONE,
+                            241, UNIPHIER_PIN_DRV_4_8,
+                            241, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(256, "VO1CB5", UNIPHIER_PIN_IECTRL_NONE,
+                            242, UNIPHIER_PIN_DRV_4_8,
+                            242, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(257, "VO1CB6", UNIPHIER_PIN_IECTRL_NONE,
+                            243, UNIPHIER_PIN_DRV_4_8,
+                            243, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(258, "VO1CB7", UNIPHIER_PIN_IECTRL_NONE,
+                            244, UNIPHIER_PIN_DRV_4_8,
+                            244, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(259, "VO1CB8", UNIPHIER_PIN_IECTRL_NONE,
+                            245, UNIPHIER_PIN_DRV_4_8,
+                            245, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(260, "VO1CB9", UNIPHIER_PIN_IECTRL_NONE,
+                            246, UNIPHIER_PIN_DRV_4_8,
+                            246, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(261, "VO1CB10", UNIPHIER_PIN_IECTRL_NONE,
+                            247, UNIPHIER_PIN_DRV_4_8,
+                            247, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(262, "VO1CB11", UNIPHIER_PIN_IECTRL_NONE,
+                            248, UNIPHIER_PIN_DRV_4_8,
+                            248, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(263, "VO1CR0", UNIPHIER_PIN_IECTRL_NONE,
+                            249, UNIPHIER_PIN_DRV_4_8,
+                            249, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(264, "VO1CR1", UNIPHIER_PIN_IECTRL_NONE,
+                            250, UNIPHIER_PIN_DRV_4_8,
+                            250, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(265, "VO1CR2", UNIPHIER_PIN_IECTRL_NONE,
+                            251, UNIPHIER_PIN_DRV_4_8,
+                            251, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(266, "VO1CR3", UNIPHIER_PIN_IECTRL_NONE,
+                            252, UNIPHIER_PIN_DRV_4_8,
+                            252, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(267, "VO1CR4", UNIPHIER_PIN_IECTRL_NONE,
+                            253, UNIPHIER_PIN_DRV_4_8,
+                            253, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(268, "VO1CR5", UNIPHIER_PIN_IECTRL_NONE,
+                            254, UNIPHIER_PIN_DRV_4_8,
+                            254, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(269, "VO1CR6", UNIPHIER_PIN_IECTRL_NONE,
+                            255, UNIPHIER_PIN_DRV_4_8,
+                            255, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(270, "VO1CR7", UNIPHIER_PIN_IECTRL_NONE,
+                            256, UNIPHIER_PIN_DRV_4_8,
+                            256, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(271, "VO1CR8", UNIPHIER_PIN_IECTRL_NONE,
+                            257, UNIPHIER_PIN_DRV_4_8,
+                            257, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(272, "VO1CR9", UNIPHIER_PIN_IECTRL_NONE,
+                            258, UNIPHIER_PIN_DRV_4_8,
+                            258, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(273, "VO1CR10", UNIPHIER_PIN_IECTRL_NONE,
+                            259, UNIPHIER_PIN_DRV_4_8,
+                            259, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(274, "VO1CR11", UNIPHIER_PIN_IECTRL_NONE,
+                            260, UNIPHIER_PIN_DRV_4_8,
+                            260, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(275, "VO1EX0", UNIPHIER_PIN_IECTRL_NONE,
+                            261, UNIPHIER_PIN_DRV_4_8,
+                            261, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(276, "VO1EX1", UNIPHIER_PIN_IECTRL_NONE,
+                            262, UNIPHIER_PIN_DRV_4_8,
+                            262, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(277, "VO1EX2", UNIPHIER_PIN_IECTRL_NONE,
+                            263, UNIPHIER_PIN_DRV_4_8,
+                            263, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(278, "VO1EX3", UNIPHIER_PIN_IECTRL_NONE,
+                            264, UNIPHIER_PIN_DRV_4_8,
+                            264, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(279, "VEXCKA", UNIPHIER_PIN_IECTRL_NONE,
+                            265, UNIPHIER_PIN_DRV_4_8,
+                            265, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(280, "VSEL0", UNIPHIER_PIN_IECTRL_NONE,
+                            266, UNIPHIER_PIN_DRV_4_8,
+                            266, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(281, "VSEL1", UNIPHIER_PIN_IECTRL_NONE,
+                            267, UNIPHIER_PIN_DRV_4_8,
+                            267, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(282, "AO1DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            268, UNIPHIER_PIN_DRV_4_8,
+                            268, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(283, "AO1BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            269, UNIPHIER_PIN_DRV_4_8,
+                            269, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(284, "AO1LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            270, UNIPHIER_PIN_DRV_4_8,
+                            270, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(285, "AO1D0", UNIPHIER_PIN_IECTRL_NONE,
+                            271, UNIPHIER_PIN_DRV_4_8,
+                            271, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(286, "AO1D1", UNIPHIER_PIN_IECTRL_NONE,
+                            272, UNIPHIER_PIN_DRV_4_8,
+                            272, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(287, "AO1D2", UNIPHIER_PIN_IECTRL_NONE,
+                            273, UNIPHIER_PIN_DRV_4_8,
+                            273, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(288, "AO1D3", UNIPHIER_PIN_IECTRL_NONE,
+                            274, UNIPHIER_PIN_DRV_4_8,
+                            274, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(289, "AO1IEC", UNIPHIER_PIN_IECTRL_NONE,
+                            275, UNIPHIER_PIN_DRV_4_8,
+                            275, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(290, "XDAC_PD", UNIPHIER_PIN_IECTRL_NONE,
+                            276, UNIPHIER_PIN_DRV_4_8,
+                            276, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(291, "EX_A_MUTE", UNIPHIER_PIN_IECTRL_NONE,
+                            277, UNIPHIER_PIN_DRV_4_8,
+                            277, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(292, "AO2DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            278, UNIPHIER_PIN_DRV_4_8,
+                            278, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(293, "AO2BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            279, UNIPHIER_PIN_DRV_4_8,
+                            279, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(294, "AO2LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            280, UNIPHIER_PIN_DRV_4_8,
+                            280, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(295, "AO2DMIX", UNIPHIER_PIN_IECTRL_NONE,
+                            281, UNIPHIER_PIN_DRV_4_8,
+                            281, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(296, "AO2IEC", UNIPHIER_PIN_IECTRL_NONE,
+                            282, UNIPHIER_PIN_DRV_4_8,
+                            282, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(297, "HTHPD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_5,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(298, "HTSCL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_5,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(299, "HTSDA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_5,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(300, "PORT00", UNIPHIER_PIN_IECTRL_NONE,
+                            284, UNIPHIER_PIN_DRV_4_8,
+                            284, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(301, "PORT01", UNIPHIER_PIN_IECTRL_NONE,
+                            285, UNIPHIER_PIN_DRV_4_8,
+                            285, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(302, "PORT02", UNIPHIER_PIN_IECTRL_NONE,
+                            286, UNIPHIER_PIN_DRV_4_8,
+                            286, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(303, "PORT03", UNIPHIER_PIN_IECTRL_NONE,
+                            287, UNIPHIER_PIN_DRV_4_8,
+                            287, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(304, "PORT04", UNIPHIER_PIN_IECTRL_NONE,
+                            288, UNIPHIER_PIN_DRV_4_8,
+                            288, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(305, "PORT05", UNIPHIER_PIN_IECTRL_NONE,
+                            289, UNIPHIER_PIN_DRV_4_8,
+                            289, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(306, "PORT06", UNIPHIER_PIN_IECTRL_NONE,
+                            290, UNIPHIER_PIN_DRV_4_8,
+                            290, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(307, "PORT07", UNIPHIER_PIN_IECTRL_NONE,
+                            291, UNIPHIER_PIN_DRV_4_8,
+                            291, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(308, "PORT10", UNIPHIER_PIN_IECTRL_NONE,
+                            292, UNIPHIER_PIN_DRV_4_8,
+                            292, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(309, "PORT11", UNIPHIER_PIN_IECTRL_NONE,
+                            293, UNIPHIER_PIN_DRV_4_8,
+                            293, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(310, "PORT12", UNIPHIER_PIN_IECTRL_NONE,
+                            294, UNIPHIER_PIN_DRV_4_8,
+                            294, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(311, "PORT13", UNIPHIER_PIN_IECTRL_NONE,
+                            295, UNIPHIER_PIN_DRV_4_8,
+                            295, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(312, "PORT14", UNIPHIER_PIN_IECTRL_NONE,
+                            296, UNIPHIER_PIN_DRV_4_8,
+                            296, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(313, "PORT15", UNIPHIER_PIN_IECTRL_NONE,
+                            297, UNIPHIER_PIN_DRV_4_8,
+                            297, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(314, "PORT16", UNIPHIER_PIN_IECTRL_NONE,
+                            298, UNIPHIER_PIN_DRV_4_8,
+                            298, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(315, "PORT17", UNIPHIER_PIN_IECTRL_NONE,
+                            299, UNIPHIER_PIN_DRV_4_8,
+                            299, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(316, "PORT20", UNIPHIER_PIN_IECTRL_NONE,
+                            300, UNIPHIER_PIN_DRV_4_8,
+                            300, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(317, "PORT21", UNIPHIER_PIN_IECTRL_NONE,
+                            301, UNIPHIER_PIN_DRV_4_8,
+                            301, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(318, "PORT22", UNIPHIER_PIN_IECTRL_NONE,
+                            302, UNIPHIER_PIN_DRV_4_8,
+                            302, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(319, "SD1DAT0", UNIPHIER_PIN_IECTRL_NONE,
+                            303, UNIPHIER_PIN_DRV_4_8,
+                            303, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(320, "SD1DAT1", UNIPHIER_PIN_IECTRL_NONE,
+                            304, UNIPHIER_PIN_DRV_4_8,
+                            304, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(321, "SD1DAT2", UNIPHIER_PIN_IECTRL_NONE,
+                            305, UNIPHIER_PIN_DRV_4_8,
+                            305, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(322, "SD1DAT3", UNIPHIER_PIN_IECTRL_NONE,
+                            306, UNIPHIER_PIN_DRV_4_8,
+                            306, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(323, "SD1CMD", UNIPHIER_PIN_IECTRL_NONE,
+                            307, UNIPHIER_PIN_DRV_4_8,
+                            307, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(324, "SD1CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            308, UNIPHIER_PIN_DRV_4_8,
+                            308, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(325, "SD1CD", UNIPHIER_PIN_IECTRL_NONE,
+                            309, UNIPHIER_PIN_DRV_4_8,
+                            309, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(326, "SD1WP", UNIPHIER_PIN_IECTRL_NONE,
+                            310, UNIPHIER_PIN_DRV_4_8,
+                            310, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(327, "SD1VTCG", UNIPHIER_PIN_IECTRL_NONE,
+                            311, UNIPHIER_PIN_DRV_4_8,
+                            311, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(328, "DMDISO", UNIPHIER_PIN_IECTRL_NONE,
+                            312, UNIPHIER_PIN_DRV_NONE,
+                            312, UNIPHIER_PIN_PULL_DOWN),
+};
+
+static const unsigned emmc_pins[] = {40, 41, 42, 43, 51, 52, 53};
+static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const unsigned emmc_dat8_pins[] = {44, 45, 46, 47};
+static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const unsigned i2c0_pins[] = {142, 143};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {144, 145};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {146, 147};
+static const unsigned i2c2_muxvals[] = {0, 0};
+static const unsigned i2c3_pins[] = {148, 149};
+static const unsigned i2c3_muxvals[] = {0, 0};
+static const unsigned i2c6_pins[] = {308, 309};
+static const unsigned i2c6_muxvals[] = {6, 6};
+static const unsigned nand_pins[] = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+                                    50, 51, 52, 53, 54};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0};
+static const unsigned nand_cs1_pins[] = {131, 132};
+static const unsigned nand_cs1_muxvals[] = {1, 1};
+static const unsigned sd_pins[] = {150, 151, 152, 153, 154, 155, 156, 157, 158};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned sd1_pins[] = {319, 320, 321, 322, 323, 324, 325, 326,
+                                   327};
+static const unsigned sd1_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {127, 128};
+static const unsigned uart0_muxvals[] = {0, 0};
+static const unsigned uart1_pins[] = {129, 130};
+static const unsigned uart1_muxvals[] = {0, 0};
+static const unsigned uart2_pins[] = {131, 132};
+static const unsigned uart2_muxvals[] = {0, 0};
+static const unsigned uart3_pins[] = {88, 89};
+static const unsigned uart3_muxvals[] = {2, 2};
+static const unsigned usb0_pins[] = {180, 181};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {182, 183};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {184, 185};
+static const unsigned usb2_muxvals[] = {0, 0};
+static const unsigned usb3_pins[] = {186, 187};
+static const unsigned usb3_muxvals[] = {0, 0};
+static const unsigned port_range0_pins[] = {
+       300, 301, 302, 303, 304, 305, 306, 307,         /* PORT0x */
+       308, 309, 310, 311, 312, 313, 314, 315,         /* PORT1x */
+       316, 317, 318, 16, 17, 18, 19, 20,              /* PORT2x */
+       21, 22, 23, 4, 93, 94, 95, 63,                  /* PORT3x */
+       123, 122, 124, 125, 126, 141, 202, 203,         /* PORT4x */
+       204, 226, 227, 290, 291, 233, 280, 281,         /* PORT5x */
+       8, 7, 10, 29, 30, 48, 49, 50,                   /* PORT6x */
+       40, 41, 42, 43, 44, 45, 46, 47,                 /* PORT7x */
+       54, 51, 52, 53, 127, 128, 129, 130,             /* PORT8x */
+       131, 132, 57, 60, 134, 133, 135, 136,           /* PORT9x */
+       138, 137, 140, 139, 64, 65, 66, 67,             /* PORT10x */
+       107, 106, 105, 104, 113, 112, 111, 110,         /* PORT11x */
+       68, 69, 70, 71, 72, 73, 74, 75,                 /* PORT12x */
+       76, 77, 78, 79, 80, 81, 82, 83,                 /* PORT13x */
+       84, 85, 86, 87, 88, 89, 90, 91,                 /* PORT14x */
+};
+static const unsigned port_range0_muxvals[] = {
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT0x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT1x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT2x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT3x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT4x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT5x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT6x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT7x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT8x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT9x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT10x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT11x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT12x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT13x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT14x */
+};
+static const unsigned port_range1_pins[] = {
+       13, 14, 15,                                     /* PORT175-177 */
+       157, 158, 156, 154, 150, 151, 152, 153,         /* PORT18x */
+       326, 327, 325, 323, 319, 320, 321, 322,         /* PORT19x */
+       160, 161, 162, 163, 164, 165, 166, 167,         /* PORT20x */
+       168, 169, 170, 171, 172, 173, 174, 175,         /* PORT21x */
+       180, 181, 182, 183, 184, 185, 187, 188,         /* PORT22x */
+       193, 194, 195, 196, 197, 198, 199, 200,         /* PORT23x */
+       191, 192, 215, 216, 217, 218, 219, 220,         /* PORT24x */
+       222, 223, 224, 225, 228, 229, 230, 231,         /* PORT25x */
+       282, 283, 284, 285, 286, 287, 288, 289,         /* PORT26x */
+       292, 293, 294, 295, 296, 236, 237, 238,         /* PORT27x */
+       275, 276, 277, 278, 239, 240, 249, 250,         /* PORT28x */
+       251, 252, 261, 262, 263, 264, 273, 274,         /* PORT29x */
+       31, 32, 33, 34, 35, 36, 37, 38,                 /* PORT30x */
+};
+static const unsigned port_range1_muxvals[] = {
+       7, 7, 7,                                        /* PORT175-177 */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT18x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT19x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT20x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT21x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT22x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT23x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT24x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT25x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT26x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT27x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT28x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT29x */
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* PORT30x */
+};
+static const unsigned xirq_pins[] = {
+       11, 9, 12, 96, 97, 98, 108, 114,                /* XIRQ0-7 */
+       234, 186, 99, 100, 101, 102, 184, 301,          /* XIRQ8-15 */
+       302, 303, 304, 305, 306,                        /* XIRQ16-20 */
+};
+static const unsigned xirq_muxvals[] = {
+       7, 7, 7, 7, 7, 7, 7, 7,                         /* XIRQ0-7 */
+       7, 7, 7, 7, 7, 7, 2, 2,                         /* XIRQ8-15 */
+       2, 2, 2, 2, 2,                                  /* XIRQ16-20 */
+};
+static const unsigned xirq_alternatives_pins[] = {
+       184, 310, 316,
+};
+static const unsigned xirq_alternatives_muxvals[] = {
+       2, 2, 2,
+};
+
+static const struct uniphier_pinctrl_group ph1_pro4_groups[] = {
+       UNIPHIER_PINCTRL_GROUP(emmc),
+       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+       UNIPHIER_PINCTRL_GROUP(i2c0),
+       UNIPHIER_PINCTRL_GROUP(i2c1),
+       UNIPHIER_PINCTRL_GROUP(i2c2),
+       UNIPHIER_PINCTRL_GROUP(i2c3),
+       UNIPHIER_PINCTRL_GROUP(i2c6),
+       UNIPHIER_PINCTRL_GROUP(nand),
+       UNIPHIER_PINCTRL_GROUP(nand_cs1),
+       UNIPHIER_PINCTRL_GROUP(sd),
+       UNIPHIER_PINCTRL_GROUP(sd1),
+       UNIPHIER_PINCTRL_GROUP(uart0),
+       UNIPHIER_PINCTRL_GROUP(uart1),
+       UNIPHIER_PINCTRL_GROUP(uart2),
+       UNIPHIER_PINCTRL_GROUP(uart3),
+       UNIPHIER_PINCTRL_GROUP(usb0),
+       UNIPHIER_PINCTRL_GROUP(usb1),
+       UNIPHIER_PINCTRL_GROUP(usb2),
+       UNIPHIER_PINCTRL_GROUP(usb3),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_alternatives),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range0, 101),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range0, 102),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range0, 103),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range0, 104),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range0, 105),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range0, 106),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range0, 107),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range0, 108),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range0, 109),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range0, 110),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range0, 111),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range0, 112),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range0, 113),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range0, 114),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range0, 115),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range0, 116),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range0, 117),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range0, 118),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range0, 119),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port175, port_range1, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port176, port_range1, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port177, port_range1, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range1, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range1, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range1, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range1, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range1, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range1, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range1, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range1, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port190, port_range1, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port191, port_range1, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port192, port_range1, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port193, port_range1, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port194, port_range1, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port195, port_range1, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port196, port_range1, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port197, port_range1, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range1, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range1, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range1, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range1, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range1, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range1, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range1, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range1, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range1, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range1, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range1, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range1, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range1, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range1, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range1, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range1, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range1, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range1, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range1, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range1, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range1, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range1, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range1, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range1, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range1, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range1, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range1, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range1, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range1, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range1, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range1, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range1, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range1, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range1, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range1, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range1, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range1, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range1, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range1, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range1, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range1, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range1, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range1, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range1, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range1, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port255, port_range1, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port256, port_range1, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port257, port_range1, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port260, port_range1, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port261, port_range1, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port262, port_range1, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port263, port_range1, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port264, port_range1, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port265, port_range1, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port266, port_range1, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port267, port_range1, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port270, port_range1, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port271, port_range1, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port272, port_range1, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port273, port_range1, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port274, port_range1, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port275, port_range1, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port276, port_range1, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port277, port_range1, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port280, port_range1, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port281, port_range1, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port282, port_range1, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port283, port_range1, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port284, port_range1, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port285, port_range1, 88),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port286, port_range1, 89),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port287, port_range1, 90),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port290, port_range1, 91),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port291, port_range1, 92),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port292, port_range1, 93),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port293, port_range1, 94),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port294, port_range1, 95),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port295, port_range1, 96),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port296, port_range1, 97),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port297, port_range1, 98),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port300, port_range1, 99),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port301, port_range1, 100),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port302, port_range1, 101),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port303, port_range1, 102),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port304, port_range1, 103),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port305, port_range1, 104),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port306, port_range1, 105),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port307, port_range1, 106),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14b, xirq_alternatives, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17b, xirq_alternatives, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18b, xirq_alternatives, 2),
+};
+
+static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
+static const char * const i2c0_groups[] = {"i2c0"};
+static const char * const i2c1_groups[] = {"i2c1"};
+static const char * const i2c2_groups[] = {"i2c2"};
+static const char * const i2c3_groups[] = {"i2c3"};
+static const char * const i2c6_groups[] = {"i2c6"};
+static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const sd1_groups[] = {"sd1"};
+static const char * const uart0_groups[] = {"uart0"};
+static const char * const uart1_groups[] = {"uart1"};
+static const char * const uart2_groups[] = {"uart2"};
+static const char * const uart3_groups[] = {"uart3"};
+static const char * const usb0_groups[] = {"usb0"};
+static const char * const usb1_groups[] = {"usb1"};
+static const char * const usb2_groups[] = {"usb2"};
+static const char * const usb3_groups[] = {"usb3"};
+static const char * const port_groups[] = {
+       "port00",  "port01",  "port02",  "port03",
+       "port04",  "port05",  "port06",  "port07",
+       "port10",  "port11",  "port12",  "port13",
+       "port14",  "port15",  "port16",  "port17",
+       "port20",  "port21",  "port22",  "port23",
+       "port24",  "port25",  "port26",  "port27",
+       "port30",  "port31",  "port32",  "port33",
+       "port34",  "port35",  "port36",  "port37",
+       "port40",  "port41",  "port42",  "port43",
+       "port44",  "port45",  "port46",  "port47",
+       "port50",  "port51",  "port52",  "port53",
+       "port54",  "port55",  "port56",  "port57",
+       "port60",  "port61",  "port62",  "port63",
+       "port64",  "port65",  "port66",  "port67",
+       "port70",  "port71",  "port72",  "port73",
+       "port74",  "port75",  "port76",  "port77",
+       "port80",  "port81",  "port82",  "port83",
+       "port84",  "port85",  "port86",  "port87",
+       "port90",  "port91",  "port92",  "port93",
+       "port94",  "port95",  "port96",  "port97",
+       "port100", "port101", "port102", "port103",
+       "port104", "port105", "port106", "port107",
+       "port110", "port111", "port112", "port113",
+       "port114", "port115", "port116", "port117",
+       "port120", "port121", "port122", "port123",
+       "port124", "port125", "port126", "port127",
+       "port130", "port131", "port132", "port133",
+       "port134", "port135", "port136", "port137",
+       "port140", "port141", "port142", "port143",
+       "port144", "port145", "port146", "port147",
+       /* port150-174 missing */
+       /* none */ "port175", "port176", "port177",
+       "port180", "port181", "port182", "port183",
+       "port184", "port185", "port186", "port187",
+       "port190", "port191", "port192", "port193",
+       "port194", "port195", "port196", "port197",
+       "port200", "port201", "port202", "port203",
+       "port204", "port205", "port206", "port207",
+       "port210", "port211", "port212", "port213",
+       "port214", "port215", "port216", "port217",
+       "port220", "port221", "port222", "port223",
+       "port224", "port225", "port226", "port227",
+       "port230", "port231", "port232", "port233",
+       "port234", "port235", "port236", "port237",
+       "port240", "port241", "port242", "port243",
+       "port244", "port245", "port246", "port247",
+       "port250", "port251", "port252", "port253",
+       "port254", "port255", "port256", "port257",
+       "port260", "port261", "port262", "port263",
+       "port264", "port265", "port266", "port267",
+       "port270", "port271", "port272", "port273",
+       "port274", "port275", "port276", "port277",
+       "port280", "port281", "port282", "port283",
+       "port284", "port285", "port286", "port287",
+       "port290", "port291", "port292", "port293",
+       "port294", "port295", "port296", "port297",
+       "port300", "port301", "port302", "port303",
+       "port304", "port305", "port306", "port307",
+};
+static const char * const xirq_groups[] = {
+       "xirq0",  "xirq1",  "xirq2",  "xirq3",
+       "xirq4",  "xirq5",  "xirq6",  "xirq7",
+       "xirq8",  "xirq9",  "xirq10", "xirq11",
+       "xirq12", "xirq13", "xirq14", "xirq15",
+       "xirq16", "xirq17", "xirq18", "xirq19",
+       "xirq20",
+       "xirq14b", "xirq17b", "xirq18b",
+};
+
+static const struct uniphier_pinmux_function ph1_pro4_functions[] = {
+       UNIPHIER_PINMUX_FUNCTION(emmc),
+       UNIPHIER_PINMUX_FUNCTION(i2c0),
+       UNIPHIER_PINMUX_FUNCTION(i2c1),
+       UNIPHIER_PINMUX_FUNCTION(i2c2),
+       UNIPHIER_PINMUX_FUNCTION(i2c3),
+       UNIPHIER_PINMUX_FUNCTION(i2c6),
+       UNIPHIER_PINMUX_FUNCTION(nand),
+       UNIPHIER_PINMUX_FUNCTION(sd),
+       UNIPHIER_PINMUX_FUNCTION(sd1),
+       UNIPHIER_PINMUX_FUNCTION(uart0),
+       UNIPHIER_PINMUX_FUNCTION(uart1),
+       UNIPHIER_PINMUX_FUNCTION(uart2),
+       UNIPHIER_PINMUX_FUNCTION(uart3),
+       UNIPHIER_PINMUX_FUNCTION(usb0),
+       UNIPHIER_PINMUX_FUNCTION(usb1),
+       UNIPHIER_PINMUX_FUNCTION(usb2),
+       UNIPHIER_PINMUX_FUNCTION(usb3),
+       UNIPHIER_PINMUX_FUNCTION(port),
+       UNIPHIER_PINMUX_FUNCTION(xirq),
+};
+
+static struct uniphier_pinctrl_socdata ph1_pro4_pindata = {
+       .groups = ph1_pro4_groups,
+       .groups_count = ARRAY_SIZE(ph1_pro4_groups),
+       .functions = ph1_pro4_functions,
+       .functions_count = ARRAY_SIZE(ph1_pro4_functions),
+       .mux_bits = 4,
+       .reg_stride = 8,
+       .load_pinctrl = true,
+};
+
+static struct pinctrl_desc ph1_pro4_pinctrl_desc = {
+       .name = DRIVER_NAME,
+       .pins = ph1_pro4_pins,
+       .npins = ARRAY_SIZE(ph1_pro4_pins),
+       .owner = THIS_MODULE,
+};
+
+static int ph1_pro4_pinctrl_probe(struct platform_device *pdev)
+{
+       return uniphier_pinctrl_probe(pdev, &ph1_pro4_pinctrl_desc,
+                                     &ph1_pro4_pindata);
+}
+
+static const struct of_device_id ph1_pro4_pinctrl_match[] = {
+       { .compatible = "socionext,ph1-pro4-pinctrl" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ph1_pro4_pinctrl_match);
+
+static struct platform_driver ph1_pro4_pinctrl_driver = {
+       .probe = ph1_pro4_pinctrl_probe,
+       .remove = uniphier_pinctrl_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .of_match_table = ph1_pro4_pinctrl_match,
+       },
+};
+module_platform_driver(ph1_pro4_pinctrl_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-Pro4 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pro5.c
new file mode 100644 (file)
index 0000000..e3d648e
--- /dev/null
@@ -0,0 +1,1356 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program5 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-uniphier.h"
+
+#define DRIVER_NAME "ph1-pro5-pinctrl"
+
+static const struct pinctrl_pin_desc ph1_pro5_pins[] = {
+       UNIPHIER_PINCTRL_PIN(0, "AEXCKA1", 0,
+                            0, UNIPHIER_PIN_DRV_4_8,
+                            0, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(1, "AEXCKA2", 0,
+                            1, UNIPHIER_PIN_DRV_4_8,
+                            1, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(2, "CK27EXI", 0,
+                            2, UNIPHIER_PIN_DRV_4_8,
+                            2, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(3, "CK54EXI", 0,
+                            3, UNIPHIER_PIN_DRV_4_8,
+                            3, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(4, "ED0", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_4_8,
+                            4, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(5, "ED1", UNIPHIER_PIN_IECTRL_NONE,
+                            5, UNIPHIER_PIN_DRV_4_8,
+                            5, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(6, "ED2", UNIPHIER_PIN_IECTRL_NONE,
+                            6, UNIPHIER_PIN_DRV_4_8,
+                            6, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(7, "ED3", UNIPHIER_PIN_IECTRL_NONE,
+                            7, UNIPHIER_PIN_DRV_4_8,
+                            7, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(8, "ED4", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_4_8,
+                            8, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(9, "ED5", UNIPHIER_PIN_IECTRL_NONE,
+                            9, UNIPHIER_PIN_DRV_4_8,
+                            9, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(10, "ED6", UNIPHIER_PIN_IECTRL_NONE,
+                            10, UNIPHIER_PIN_DRV_4_8,
+                            10, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(11, "ED7", UNIPHIER_PIN_IECTRL_NONE,
+                            11, UNIPHIER_PIN_DRV_4_8,
+                            11, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(12, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_4_8,
+                            12, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(13, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
+                            13, UNIPHIER_PIN_DRV_4_8,
+                            13, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(14, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
+                            14, UNIPHIER_PIN_DRV_4_8,
+                            14, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(15, "ES0", UNIPHIER_PIN_IECTRL_NONE,
+                            15, UNIPHIER_PIN_DRV_4_8,
+                            15, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(16, "ES1", UNIPHIER_PIN_IECTRL_NONE,
+                            16, UNIPHIER_PIN_DRV_4_8,
+                            16, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(17, "ES2", UNIPHIER_PIN_IECTRL_NONE,
+                            17, UNIPHIER_PIN_DRV_4_8,
+                            17, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(18, "XECS1", UNIPHIER_PIN_IECTRL_NONE,
+                            18, UNIPHIER_PIN_DRV_4_8,
+                            18, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(19, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
+                            19, UNIPHIER_PIN_DRV_4_8,
+                            19, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(20, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
+                            20, UNIPHIER_PIN_DRV_4_8,
+                            20, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(21, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
+                            21, UNIPHIER_PIN_DRV_4_8,
+                            21, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(22, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
+                            22, UNIPHIER_PIN_DRV_4_8,
+                            22, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(23, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
+                            23, UNIPHIER_PIN_DRV_4_8,
+                            23, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(24, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
+                            24, UNIPHIER_PIN_DRV_4_8,
+                            24, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(25, "NFRYBY0", UNIPHIER_PIN_IECTRL_NONE,
+                            25, UNIPHIER_PIN_DRV_4_8,
+                            25, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(26, "XNFCE1", UNIPHIER_PIN_IECTRL_NONE,
+                            26, UNIPHIER_PIN_DRV_4_8,
+                            26, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(27, "NFRYBY1", UNIPHIER_PIN_IECTRL_NONE,
+                            27, UNIPHIER_PIN_DRV_4_8,
+                            27, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(28, "NFD0", UNIPHIER_PIN_IECTRL_NONE,
+                            28, UNIPHIER_PIN_DRV_4_8,
+                            28, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(29, "NFD1", UNIPHIER_PIN_IECTRL_NONE,
+                            29, UNIPHIER_PIN_DRV_4_8,
+                            29, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(30, "NFD2", UNIPHIER_PIN_IECTRL_NONE,
+                            30, UNIPHIER_PIN_DRV_4_8,
+                            30, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(31, "NFD3", UNIPHIER_PIN_IECTRL_NONE,
+                            31, UNIPHIER_PIN_DRV_4_8,
+                            31, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(32, "NFD4", UNIPHIER_PIN_IECTRL_NONE,
+                            32, UNIPHIER_PIN_DRV_4_8,
+                            32, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(33, "NFD5", UNIPHIER_PIN_IECTRL_NONE,
+                            33, UNIPHIER_PIN_DRV_4_8,
+                            33, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(34, "NFD6", UNIPHIER_PIN_IECTRL_NONE,
+                            34, UNIPHIER_PIN_DRV_4_8,
+                            34, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(35, "NFD7", UNIPHIER_PIN_IECTRL_NONE,
+                            35, UNIPHIER_PIN_DRV_4_8,
+                            35, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(36, "XERST", UNIPHIER_PIN_IECTRL_NONE,
+                            36, UNIPHIER_PIN_DRV_4_8,
+                            36, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(37, "MMCCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            37, UNIPHIER_PIN_DRV_4_8,
+                            37, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(38, "MMCCMD", UNIPHIER_PIN_IECTRL_NONE,
+                            38, UNIPHIER_PIN_DRV_4_8,
+                            38, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(39, "MMCDAT0", UNIPHIER_PIN_IECTRL_NONE,
+                            39, UNIPHIER_PIN_DRV_4_8,
+                            39, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(40, "MMCDAT1", UNIPHIER_PIN_IECTRL_NONE,
+                            40, UNIPHIER_PIN_DRV_4_8,
+                            40, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(41, "MMCDAT2", UNIPHIER_PIN_IECTRL_NONE,
+                            41, UNIPHIER_PIN_DRV_4_8,
+                            41, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(42, "MMCDAT3", UNIPHIER_PIN_IECTRL_NONE,
+                            42, UNIPHIER_PIN_DRV_4_8,
+                            42, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(43, "MMCDAT4", UNIPHIER_PIN_IECTRL_NONE,
+                            43, UNIPHIER_PIN_DRV_4_8,
+                            43, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(44, "MMCDAT5", UNIPHIER_PIN_IECTRL_NONE,
+                            44, UNIPHIER_PIN_DRV_4_8,
+                            44, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(45, "MMCDAT6", UNIPHIER_PIN_IECTRL_NONE,
+                            45, UNIPHIER_PIN_DRV_4_8,
+                            45, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(46, "MMCDAT7", UNIPHIER_PIN_IECTRL_NONE,
+                            46, UNIPHIER_PIN_DRV_4_8,
+                            46, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(47, "TXD0", 0,
+                            47, UNIPHIER_PIN_DRV_4_8,
+                            47, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(48, "RXD0", 0,
+                            48, UNIPHIER_PIN_DRV_4_8,
+                            48, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(49, "TXD1", 0,
+                            49, UNIPHIER_PIN_DRV_4_8,
+                            49, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(50, "RXD1", 0,
+                            50, UNIPHIER_PIN_DRV_4_8,
+                            50, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(51, "TXD2", UNIPHIER_PIN_IECTRL_NONE,
+                            51, UNIPHIER_PIN_DRV_4_8,
+                            51, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(52, "RXD2", UNIPHIER_PIN_IECTRL_NONE,
+                            52, UNIPHIER_PIN_DRV_4_8,
+                            52, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(53, "TXD3", 0,
+                            53, UNIPHIER_PIN_DRV_4_8,
+                            53, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(54, "RXD3", 0,
+                            54, UNIPHIER_PIN_DRV_4_8,
+                            54, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(55, "MS0CS0", 0,
+                            55, UNIPHIER_PIN_DRV_4_8,
+                            55, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(56, "MS0DO", 0,
+                            56, UNIPHIER_PIN_DRV_4_8,
+                            56, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(57, "MS0DI", 0,
+                            57, UNIPHIER_PIN_DRV_4_8,
+                            57, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(58, "MS0CLK", 0,
+                            58, UNIPHIER_PIN_DRV_4_8,
+                            58, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(59, "CSCLK", 0,
+                            59, UNIPHIER_PIN_DRV_4_8,
+                            59, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(60, "CSBPTM", 0,
+                            60, UNIPHIER_PIN_DRV_4_8,
+                            60, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(61, "CSBMTP", 0,
+                            61, UNIPHIER_PIN_DRV_4_8,
+                            61, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(62, "XCINTP", 0,
+                            62, UNIPHIER_PIN_DRV_4_8,
+                            62, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(63, "XCINTM", 0,
+                            63, UNIPHIER_PIN_DRV_4_8,
+                            63, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(64, "XCMPREQ", 0,
+                            64, UNIPHIER_PIN_DRV_4_8,
+                            64, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(65, "XSRST", 0,
+                            65, UNIPHIER_PIN_DRV_4_8,
+                            65, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(66, "LPST", UNIPHIER_PIN_IECTRL_NONE,
+                            66, UNIPHIER_PIN_DRV_4_8,
+                            66, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(67, "PWMA", 0,
+                            67, UNIPHIER_PIN_DRV_4_8,
+                            67, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(68, "XIRQ0", 0,
+                            68, UNIPHIER_PIN_DRV_4_8,
+                            68, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(69, "XIRQ1", 0,
+                            69, UNIPHIER_PIN_DRV_4_8,
+                            69, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(70, "XIRQ2", 0,
+                            70, UNIPHIER_PIN_DRV_4_8,
+                            70, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(71, "XIRQ3", 0,
+                            71, UNIPHIER_PIN_DRV_4_8,
+                            71, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(72, "XIRQ4", 0,
+                            72, UNIPHIER_PIN_DRV_4_8,
+                            72, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(73, "XIRQ5", 0,
+                            73, UNIPHIER_PIN_DRV_4_8,
+                            73, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(74, "XIRQ6", 0,
+                            74, UNIPHIER_PIN_DRV_4_8,
+                            74, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(75, "XIRQ7", 0,
+                            75, UNIPHIER_PIN_DRV_4_8,
+                            75, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(76, "XIRQ8", 0,
+                            76, UNIPHIER_PIN_DRV_4_8,
+                            76, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(77, "XIRQ9", 0,
+                            77, UNIPHIER_PIN_DRV_4_8,
+                            77, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(78, "XIRQ10", 0,
+                            78, UNIPHIER_PIN_DRV_4_8,
+                            78, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(79, "XIRQ11", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            79, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(80, "XIRQ12", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            80, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(81, "XIRQ13", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            81, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(82, "XIRQ14", 0,
+                            82, UNIPHIER_PIN_DRV_4_8,
+                            82, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(83, "XIRQ15", 0,
+                            83, UNIPHIER_PIN_DRV_4_8,
+                            83, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(84, "XIRQ16", 0,
+                            84, UNIPHIER_PIN_DRV_4_8,
+                            84, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(85, "XIRQ17", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            85, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(86, "XIRQ18", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            86, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(87, "XIRQ19", 0,
+                            87, UNIPHIER_PIN_DRV_4_8,
+                            87, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(88, "XIRQ20", 0,
+                            88, UNIPHIER_PIN_DRV_4_8,
+                            88, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(89, "PORT00", 0,
+                            89, UNIPHIER_PIN_DRV_4_8,
+                            89, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(90, "PORT01", 0,
+                            90, UNIPHIER_PIN_DRV_4_8,
+                            90, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(91, "PORT02", 0,
+                            91, UNIPHIER_PIN_DRV_4_8,
+                            91, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(92, "PORT03", 0,
+                            92, UNIPHIER_PIN_DRV_4_8,
+                            92, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(93, "PORT04", 0,
+                            93, UNIPHIER_PIN_DRV_4_8,
+                            93, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(94, "PORT05", 0,
+                            94, UNIPHIER_PIN_DRV_4_8,
+                            94, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(95, "PORT06", 0,
+                            95, UNIPHIER_PIN_DRV_4_8,
+                            95, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(96, "PORT07", 0,
+                            96, UNIPHIER_PIN_DRV_4_8,
+                            96, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(97, "PORT10", 0,
+                            97, UNIPHIER_PIN_DRV_4_8,
+                            97, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(98, "PORT11", 0,
+                            98, UNIPHIER_PIN_DRV_4_8,
+                            98, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(99, "PORT12", 0,
+                            99, UNIPHIER_PIN_DRV_4_8,
+                            99, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(100, "PORT13", 0,
+                            100, UNIPHIER_PIN_DRV_4_8,
+                            100, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(101, "PORT14", 0,
+                            101, UNIPHIER_PIN_DRV_4_8,
+                            101, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(102, "PORT15", 0,
+                            102, UNIPHIER_PIN_DRV_4_8,
+                            102, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(103, "PORT16", 0,
+                            103, UNIPHIER_PIN_DRV_4_8,
+                            103, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(104, "PORT17", 0,
+                            104, UNIPHIER_PIN_DRV_4_8,
+                            104, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(105, "T0HPD", 0,
+                            105, UNIPHIER_PIN_DRV_4_8,
+                            105, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(106, "T1HPD", 0,
+                            106, UNIPHIER_PIN_DRV_4_8,
+                            106, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(107, "R0HPD", 0,
+                            107, UNIPHIER_PIN_DRV_4_8,
+                            107, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(108, "R1HPD", 0,
+                            108, UNIPHIER_PIN_DRV_4_8,
+                            108, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(109, "XPERST", 0,
+                            109, UNIPHIER_PIN_DRV_4_8,
+                            109, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(110, "XPEWAKE", 0,
+                            110, UNIPHIER_PIN_DRV_4_8,
+                            110, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(111, "XPECLKRQ", 0,
+                            111, UNIPHIER_PIN_DRV_4_8,
+                            111, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(112, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            112, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(113, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            113, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(114, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            114, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(115, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            115, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(116, "SDA2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            116, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(117, "SCL2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            117, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(118, "SDA3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            118, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(119, "SCL3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            119, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(120, "SPISYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            120, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(121, "SPISCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            121, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(122, "SPITXD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            122, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(123, "SPIRXD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            123, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(124, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            124, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(125, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            125, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(126, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            126, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(127, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            127, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(128, "USB2VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            128, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(129, "USB2OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            129, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(130, "SMTRST0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            130, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(131, "SMTCMD0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            131, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(132, "SMTD0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            132, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(133, "SMTSEL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            133, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(134, "SMTCLK0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            134, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(135, "SMTRST1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            135, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(136, "SMTCMD1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            136, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(137, "SMTD1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            137, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(138, "SMTSEL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            138, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(139, "SMTCLK1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            139, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(140, "CH0CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            140, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(141, "CH0PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            141, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(142, "CH0VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            142, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(143, "CH0DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            143, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(144, "CH1CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            144, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(145, "CH1PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            145, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(146, "CH1VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            146, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(147, "CH1DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            147, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(148, "CH2CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            148, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(149, "CH2PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            149, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(150, "CH2VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            150, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(151, "CH2DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            151, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(152, "CH3CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            152, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(153, "CH3PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            153, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(154, "CH3VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            154, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(155, "CH3DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            155, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(156, "CH4CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            156, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(157, "CH4PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            157, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(158, "CH4VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            158, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(159, "CH4DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            159, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(160, "CH5CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            160, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(161, "CH5PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            161, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(162, "CH5VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            162, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(163, "CH5DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            163, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(164, "CH6CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            164, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(165, "CH6PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            165, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(166, "CH6VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            166, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(167, "CH6DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            167, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(168, "CH7CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            168, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(169, "CH7PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            169, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(170, "CH7VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            170, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(171, "CH7DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            171, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(172, "AI1ADCCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            172, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(173, "AI1BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            173, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(174, "AI1LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            174, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(175, "AI1D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            175, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(176, "AI1D1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            176, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(177, "AI1D2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            177, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(178, "AI1D3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            178, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(179, "AI2ADCCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            179, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(180, "AI2BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            180, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(181, "AI2LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            181, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(182, "AI2D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            182, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(183, "AI2D1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            183, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(184, "AI2D2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            184, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(185, "AI2D3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            185, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(186, "AI3ADCCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            186, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(187, "AI3BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            187, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(188, "AI3LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            188, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(189, "AI3D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            189, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(190, "AO1IEC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            190, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(191, "AO1DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            191, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(192, "AO1BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            192, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(193, "AO1LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            193, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(194, "AO1D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            194, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(195, "AO1D1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            195, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(196, "AO1D2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            196, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(197, "AO1D3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            197, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(198, "AO2IEC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            198, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(199, "AO2DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            199, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(200, "AO2BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            200, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(201, "AO2LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            201, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(202, "AO2D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            202, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(203, "AO2D1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            203, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(204, "AO2D2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            204, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(205, "AO2D3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            205, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(206, "AO3DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            206, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(207, "AO3BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            207, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(208, "AO3LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            208, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(209, "AO3DMIX", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            209, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(210, "AO4DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            210, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(211, "AO4BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            211, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(212, "AO4LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            212, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(213, "AO4DMIX", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            213, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(214, "VI1CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            214, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(215, "VI1C0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            215, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(216, "VI1C1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            216, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(217, "VI1C2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            217, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(218, "VI1C3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            218, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(219, "VI1C4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            219, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(220, "VI1C5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            220, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(221, "VI1C6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            221, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(222, "VI1C7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            222, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(223, "VI1C8", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            223, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(224, "VI1C9", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            224, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(225, "VI1Y0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            225, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(226, "VI1Y1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            226, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(227, "VI1Y2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            227, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(228, "VI1Y3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            228, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(229, "VI1Y4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            229, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(230, "VI1Y5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            230, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(231, "VI1Y6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            231, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(232, "VI1Y7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            232, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(233, "VI1Y8", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            233, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(234, "VI1Y9", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            234, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(235, "VI1DE", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            235, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(236, "VI1HSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            236, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(237, "VI1VSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            237, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(238, "VO1CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            238, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(239, "VO1D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            239, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(240, "VO1D1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            240, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(241, "VO1D2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            241, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(242, "VO1D3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            242, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(243, "VO1D4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            243, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(244, "VO1D5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            244, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(245, "VO1D6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            245, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(246, "VO1D7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            246, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(247, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            247, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(248, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            248, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(249, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            249, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(250, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            40, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(251, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
+                            44, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(252, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
+                            48, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(253, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
+                            52, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(254, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
+                            56, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(255, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
+                            60, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+};
+
+static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
+static const unsigned emmc_muxvals[] = {0, 0, 0, 0, 0, 0, 0};
+static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
+static const unsigned emmc_dat8_muxvals[] = {0, 0, 0, 0};
+static const unsigned i2c0_pins[] = {112, 113};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {114, 115};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {116, 117};
+static const unsigned i2c2_muxvals[] = {0, 0};
+static const unsigned i2c3_pins[] = {118, 119};
+static const unsigned i2c3_muxvals[] = {0, 0};
+static const unsigned i2c5_pins[] = {87, 88};
+static const unsigned i2c5_muxvals[] = {2, 2};
+static const unsigned i2c5b_pins[] = {196, 197};
+static const unsigned i2c5b_muxvals[] = {2, 2};
+static const unsigned i2c5c_pins[] = {215, 216};
+static const unsigned i2c5c_muxvals[] = {2, 2};
+static const unsigned i2c6_pins[] = {101, 102};
+static const unsigned i2c6_muxvals[] = {2, 2};
+static const unsigned nand_pins[] = {19, 20, 21, 22, 23, 24, 25, 28, 29, 30,
+                                    31, 32, 33, 34, 35};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0};
+static const unsigned nand_cs1_pins[] = {26, 27};
+static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {250, 251, 252, 253, 254, 255, 256, 257, 258};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {47, 48};
+static const unsigned uart0_muxvals[] = {0, 0};
+static const unsigned uart0b_pins[] = {227, 228};
+static const unsigned uart0b_muxvals[] = {3, 3};
+static const unsigned uart1_pins[] = {49, 50};
+static const unsigned uart1_muxvals[] = {0, 0};
+static const unsigned uart2_pins[] = {51, 52};
+static const unsigned uart2_muxvals[] = {0, 0};
+static const unsigned uart3_pins[] = {53, 54};
+static const unsigned uart3_muxvals[] = {0, 0};
+static const unsigned usb0_pins[] = {124, 125};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {126, 127};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {128, 129};
+static const unsigned usb2_muxvals[] = {0, 0};
+static const unsigned port_range0_pins[] = {
+       89, 90, 91, 92, 93, 94, 95, 96,                 /* PORT0x */
+       97, 98, 99, 100, 101, 102, 103, 104,            /* PORT1x */
+       251, 252, 253, 254, 255, 247, 248, 249,         /* PORT2x */
+       39, 40, 41, 42, 43, 44, 45, 46,                 /* PORT3x */
+       156, 157, 158, 159, 160, 161, 162, 163,         /* PORT4x */
+       164, 165, 166, 167, 168, 169, 170, 171,         /* PORT5x */
+       190, 191, 192, 193, 194, 195, 196, 197,         /* PORT6x */
+       198, 199, 200, 201, 202, 203, 204, 205,         /* PORT7x */
+       120, 121, 122, 123, 55, 56, 57, 58,             /* PORT8x */
+       124, 125, 126, 127, 49, 50, 53, 54,             /* PORT9x */
+       148, 149, 150, 151, 152, 153, 154, 155,         /* PORT10x */
+       133, 134, 131, 130, 138, 139, 136, 135,         /* PORT11x */
+       28, 29, 30, 31, 32, 33, 34, 35,                 /* PORT12x */
+       179, 180, 181, 182, 186, 187, 188, 189,         /* PORT13x */
+       4, 5, 6, 7, 8, 9, 10, 11,                       /* PORT14x */
+};
+static const unsigned port_range0_muxvals[] = {
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT0x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT1x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT2x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT11x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT12x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT13x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
+};
+static const unsigned port_range1_pins[] = {
+       109, 110, 111,                                  /* PORT175-177 */
+       206, 207, 208, 209, 210, 211, 212, 213,         /* PORT18x */
+       12, 13, 14, 15, 16, 17, 107, 108,               /* PORT19x */
+       140, 141, 142, 143, 144, 145, 146, 147,         /* PORT20x */
+       59, 60, 61, 62, 63, 64, 65, 66,                 /* PORT21x */
+       214, 215, 216, 217, 218, 219, 220, 221,         /* PORT22x */
+       222, 223, 224, 225, 226, 227, 228, 229,         /* PORT23x */
+       19, 20, 21, 22, 23, 24, 25, 26,                 /* PORT24x */
+       230, 231, 232, 233, 234, 235, 236, 237,         /* PORT25x */
+       239, 240, 241, 242, 243, 244, 245, 246,         /* PORT26x */
+       172, 173, 174, 175, 176, 177, 178, 129,         /* PORT27x */
+       0, 1, 2, 67, 85, 86, 87, 88,                    /* PORT28x */
+       105, 106, 18, 27, 36, 128, 132, 137,            /* PORT29x */
+       183, 184, 185, 84, 47, 48, 51, 52,              /* PORT30x */
+};
+static const unsigned port_range1_muxvals[] = {
+       15, 15, 15,                                     /* PORT175-177 */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT18x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT19x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT20x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT21x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT22x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT23x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT24x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT25x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT26x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT27x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT28x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT29x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT30x */
+};
+static const unsigned xirq_pins[] = {
+       68, 69, 70, 71, 72, 73, 74, 75,                 /* XIRQ0-7 */
+       76, 77, 78, 79, 80, 81, 82, 83,                 /* XIRQ8-15 */
+       84, 85, 86, 87, 88,                             /* XIRQ16-20 */
+};
+static const unsigned xirq_muxvals[] = {
+       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ0-7 */
+       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ8-15 */
+       14, 14, 14, 14, 14,                             /* XIRQ16-20 */
+};
+static const unsigned xirq_alternatives_pins[] = {
+       91, 92, 239, 144, 240, 156, 241, 106, 128,
+};
+static const unsigned xirq_alternatives_muxvals[] = {
+       14, 14, 14, 14, 14, 14, 14, 14, 14,
+};
+
+static const struct uniphier_pinctrl_group ph1_pro5_groups[] = {
+       UNIPHIER_PINCTRL_GROUP(nand),
+       UNIPHIER_PINCTRL_GROUP(nand_cs1),
+       UNIPHIER_PINCTRL_GROUP(emmc),
+       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+       UNIPHIER_PINCTRL_GROUP(i2c0),
+       UNIPHIER_PINCTRL_GROUP(i2c1),
+       UNIPHIER_PINCTRL_GROUP(i2c2),
+       UNIPHIER_PINCTRL_GROUP(i2c3),
+       UNIPHIER_PINCTRL_GROUP(i2c5),
+       UNIPHIER_PINCTRL_GROUP(i2c5b),
+       UNIPHIER_PINCTRL_GROUP(i2c5c),
+       UNIPHIER_PINCTRL_GROUP(i2c6),
+       UNIPHIER_PINCTRL_GROUP(sd),
+       UNIPHIER_PINCTRL_GROUP(uart0),
+       UNIPHIER_PINCTRL_GROUP(uart0b),
+       UNIPHIER_PINCTRL_GROUP(uart1),
+       UNIPHIER_PINCTRL_GROUP(uart2),
+       UNIPHIER_PINCTRL_GROUP(uart3),
+       UNIPHIER_PINCTRL_GROUP(usb0),
+       UNIPHIER_PINCTRL_GROUP(usb1),
+       UNIPHIER_PINCTRL_GROUP(usb2),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_alternatives),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range0, 101),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range0, 102),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range0, 103),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range0, 104),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range0, 105),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range0, 106),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range0, 107),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range0, 108),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range0, 109),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range0, 110),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range0, 111),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range0, 112),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range0, 113),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range0, 114),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range0, 115),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range0, 116),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range0, 117),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range0, 118),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range0, 119),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port175, port_range1, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port176, port_range1, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port177, port_range1, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range1, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range1, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range1, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range1, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range1, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range1, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range1, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range1, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port190, port_range1, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port191, port_range1, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port192, port_range1, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port193, port_range1, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port194, port_range1, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port195, port_range1, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port196, port_range1, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port197, port_range1, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range1, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range1, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range1, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range1, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range1, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range1, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range1, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range1, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range1, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range1, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range1, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range1, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range1, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range1, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range1, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range1, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range1, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range1, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range1, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range1, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range1, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range1, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range1, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range1, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range1, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range1, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range1, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range1, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range1, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range1, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range1, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range1, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range1, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range1, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range1, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range1, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range1, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range1, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range1, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range1, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range1, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range1, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range1, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range1, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range1, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port255, port_range1, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port256, port_range1, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port257, port_range1, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port260, port_range1, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port261, port_range1, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port262, port_range1, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port263, port_range1, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port264, port_range1, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port265, port_range1, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port266, port_range1, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port267, port_range1, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port270, port_range1, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port271, port_range1, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port272, port_range1, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port273, port_range1, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port274, port_range1, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port275, port_range1, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port276, port_range1, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port277, port_range1, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port280, port_range1, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port281, port_range1, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port282, port_range1, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port283, port_range1, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port284, port_range1, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port285, port_range1, 88),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port286, port_range1, 89),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port287, port_range1, 90),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port290, port_range1, 91),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port291, port_range1, 92),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port292, port_range1, 93),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port293, port_range1, 94),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port294, port_range1, 95),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port295, port_range1, 96),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port296, port_range1, 97),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port297, port_range1, 98),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port300, port_range1, 99),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port301, port_range1, 100),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port302, port_range1, 101),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port303, port_range1, 102),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port304, port_range1, 103),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port305, port_range1, 104),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port306, port_range1, 105),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port307, port_range1, 106),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3b, xirq_alternatives, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4b, xirq_alternatives, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16b, xirq_alternatives, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17b, xirq_alternatives, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17c, xirq_alternatives, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18b, xirq_alternatives, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18c, xirq_alternatives, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19b, xirq_alternatives, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20b, xirq_alternatives, 8),
+};
+
+static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
+static const char * const i2c0_groups[] = {"i2c0"};
+static const char * const i2c1_groups[] = {"i2c1"};
+static const char * const i2c2_groups[] = {"i2c2"};
+static const char * const i2c3_groups[] = {"i2c3"};
+static const char * const i2c5_groups[] = {"i2c5", "i2c5b", "i2c5c"};
+static const char * const i2c6_groups[] = {"i2c6"};
+static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const uart0_groups[] = {"uart0", "uart0b"};
+static const char * const uart1_groups[] = {"uart1"};
+static const char * const uart2_groups[] = {"uart2"};
+static const char * const uart3_groups[] = {"uart3"};
+static const char * const usb0_groups[] = {"usb0"};
+static const char * const usb1_groups[] = {"usb1"};
+static const char * const usb2_groups[] = {"usb2"};
+static const char * const port_groups[] = {
+       "port00",  "port01",  "port02",  "port03",
+       "port04",  "port05",  "port06",  "port07",
+       "port10",  "port11",  "port12",  "port13",
+       "port14",  "port15",  "port16",  "port17",
+       "port20",  "port21",  "port22",  "port23",
+       "port24",  "port25",  "port26",  "port27",
+       "port30",  "port31",  "port32",  "port33",
+       "port34",  "port35",  "port36",  "port37",
+       "port40",  "port41",  "port42",  "port43",
+       "port44",  "port45",  "port46",  "port47",
+       "port50",  "port51",  "port52",  "port53",
+       "port54",  "port55",  "port56",  "port57",
+       "port60",  "port61",  "port62",  "port63",
+       "port64",  "port65",  "port66",  "port67",
+       "port70",  "port71",  "port72",  "port73",
+       "port74",  "port75",  "port76",  "port77",
+       "port80",  "port81",  "port82",  "port83",
+       "port84",  "port85",  "port86",  "port87",
+       "port90",  "port91",  "port92",  "port93",
+       "port94",  "port95",  "port96",  "port97",
+       "port100", "port101", "port102", "port103",
+       "port104", "port105", "port106", "port107",
+       "port110", "port111", "port112", "port113",
+       "port114", "port115", "port116", "port117",
+       "port120", "port121", "port122", "port123",
+       "port124", "port125", "port126", "port127",
+       "port130", "port131", "port132", "port133",
+       "port134", "port135", "port136", "port137",
+       "port140", "port141", "port142", "port143",
+       "port144", "port145", "port146", "port147",
+       /* port150-174 missing */
+       /* none */ "port175", "port176", "port177",
+       "port180", "port181", "port182", "port183",
+       "port184", "port185", "port186", "port187",
+       "port190", "port191", "port192", "port193",
+       "port194", "port195", "port196", "port197",
+       "port200", "port201", "port202", "port203",
+       "port204", "port205", "port206", "port207",
+       "port210", "port211", "port212", "port213",
+       "port214", "port215", "port216", "port217",
+       "port220", "port221", "port222", "port223",
+       "port224", "port225", "port226", "port227",
+       "port230", "port231", "port232", "port233",
+       "port234", "port235", "port236", "port237",
+       "port240", "port241", "port242", "port243",
+       "port244", "port245", "port246", "port247",
+       "port250", "port251", "port252", "port253",
+       "port254", "port255", "port256", "port257",
+       "port260", "port261", "port262", "port263",
+       "port264", "port265", "port266", "port267",
+       "port270", "port271", "port272", "port273",
+       "port274", "port275", "port276", "port277",
+       "port280", "port281", "port282", "port283",
+       "port284", "port285", "port286", "port287",
+       "port290", "port291", "port292", "port293",
+       "port294", "port295", "port296", "port297",
+       "port300", "port301", "port302", "port303",
+       "port304", "port305", "port306", "port307",
+};
+static const char * const xirq_groups[] = {
+       "xirq0",  "xirq1",  "xirq2",  "xirq3",
+       "xirq4",  "xirq5",  "xirq6",  "xirq7",
+       "xirq8",  "xirq9",  "xirq10", "xirq11",
+       "xirq12", "xirq13", "xirq14", "xirq15",
+       "xirq16", "xirq17", "xirq18", "xirq19",
+       "xirq20",
+       "xirq3b", "xirq4b", "xirq16b", "xirq17b", "xirq17c",
+       "xirq18b", "xirq18c", "xirq19b", "xirq20b",
+};
+
+static const struct uniphier_pinmux_function ph1_pro5_functions[] = {
+       UNIPHIER_PINMUX_FUNCTION(emmc),
+       UNIPHIER_PINMUX_FUNCTION(i2c0),
+       UNIPHIER_PINMUX_FUNCTION(i2c1),
+       UNIPHIER_PINMUX_FUNCTION(i2c2),
+       UNIPHIER_PINMUX_FUNCTION(i2c3),
+       UNIPHIER_PINMUX_FUNCTION(i2c5),
+       UNIPHIER_PINMUX_FUNCTION(i2c6),
+       UNIPHIER_PINMUX_FUNCTION(nand),
+       UNIPHIER_PINMUX_FUNCTION(sd),
+       UNIPHIER_PINMUX_FUNCTION(uart0),
+       UNIPHIER_PINMUX_FUNCTION(uart1),
+       UNIPHIER_PINMUX_FUNCTION(uart2),
+       UNIPHIER_PINMUX_FUNCTION(uart3),
+       UNIPHIER_PINMUX_FUNCTION(usb0),
+       UNIPHIER_PINMUX_FUNCTION(usb1),
+       UNIPHIER_PINMUX_FUNCTION(usb2),
+       UNIPHIER_PINMUX_FUNCTION(port),
+       UNIPHIER_PINMUX_FUNCTION(xirq),
+};
+
+static struct uniphier_pinctrl_socdata ph1_pro5_pindata = {
+       .groups = ph1_pro5_groups,
+       .groups_count = ARRAY_SIZE(ph1_pro5_groups),
+       .functions = ph1_pro5_functions,
+       .functions_count = ARRAY_SIZE(ph1_pro5_functions),
+       .mux_bits = 4,
+       .reg_stride = 8,
+       .load_pinctrl = true,
+};
+
+static struct pinctrl_desc ph1_pro5_pinctrl_desc = {
+       .name = DRIVER_NAME,
+       .pins = ph1_pro5_pins,
+       .npins = ARRAY_SIZE(ph1_pro5_pins),
+       .owner = THIS_MODULE,
+};
+
+static int ph1_pro5_pinctrl_probe(struct platform_device *pdev)
+{
+       return uniphier_pinctrl_probe(pdev, &ph1_pro5_pinctrl_desc,
+                                     &ph1_pro5_pindata);
+}
+
+static const struct of_device_id ph1_pro5_pinctrl_match[] = {
+       { .compatible = "socionext,ph1-pro5-pinctrl" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ph1_pro5_pinctrl_match);
+
+static struct platform_driver ph1_pro5_pinctrl_driver = {
+       .probe = ph1_pro5_pinctrl_probe,
+       .remove = uniphier_pinctrl_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .of_match_table = ph1_pro5_pinctrl_match,
+       },
+};
+module_platform_driver(ph1_pro5_pinctrl_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-Pro5 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-pxs2.c
new file mode 100644 (file)
index 0000000..bc00d75
--- /dev/null
@@ -0,0 +1,1274 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-uniphier.h"
+
+#define DRIVER_NAME "proxstream2-pinctrl"
+
+static const struct pinctrl_pin_desc proxstream2_pins[] = {
+       UNIPHIER_PINCTRL_PIN(0, "ED0", UNIPHIER_PIN_IECTRL_NONE,
+                            0, UNIPHIER_PIN_DRV_4_8,
+                            0, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(1, "ED1", UNIPHIER_PIN_IECTRL_NONE,
+                            1, UNIPHIER_PIN_DRV_4_8,
+                            1, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(2, "ED2", UNIPHIER_PIN_IECTRL_NONE,
+                            2, UNIPHIER_PIN_DRV_4_8,
+                            2, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(3, "ED3", UNIPHIER_PIN_IECTRL_NONE,
+                            3, UNIPHIER_PIN_DRV_4_8,
+                            3, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(4, "ED4", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_4_8,
+                            4, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(5, "ED5", UNIPHIER_PIN_IECTRL_NONE,
+                            5, UNIPHIER_PIN_DRV_4_8,
+                            5, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(6, "ED6", UNIPHIER_PIN_IECTRL_NONE,
+                            6, UNIPHIER_PIN_DRV_4_8,
+                            6, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(7, "ED7", UNIPHIER_PIN_IECTRL_NONE,
+                            7, UNIPHIER_PIN_DRV_4_8,
+                            7, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(8, "XERWE0", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_4_8,
+                            8, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(9, "XERWE1", UNIPHIER_PIN_IECTRL_NONE,
+                            9, UNIPHIER_PIN_DRV_4_8,
+                            9, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(10, "ERXW", UNIPHIER_PIN_IECTRL_NONE,
+                            10, UNIPHIER_PIN_DRV_4_8,
+                            10, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(11, "ES0", UNIPHIER_PIN_IECTRL_NONE,
+                            11, UNIPHIER_PIN_DRV_4_8,
+                            11, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(12, "ES1", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_4_8,
+                            12, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(13, "ES2", UNIPHIER_PIN_IECTRL_NONE,
+                            13, UNIPHIER_PIN_DRV_4_8,
+                            13, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(14, "XECS1", UNIPHIER_PIN_IECTRL_NONE,
+                            14, UNIPHIER_PIN_DRV_4_8,
+                            14, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(15, "SMTRST0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            15, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(16, "SMTCMD0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            16, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(17, "SMTD0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            17, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(18, "SMTSEL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            18, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(19, "SMTCLK0CG", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            19, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(20, "SMTDET0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            20, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(21, "SMTRST1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            21, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(22, "SMTCMD1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            22, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(23, "SMTD1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            23, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(24, "SMTSEL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            24, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(25, "SMTCLK1CG", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            25, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(26, "SMTDET1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            26, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(27, "XIRQ18", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            27, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(28, "XIRQ19", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            28, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(29, "XIRQ20", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            29, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(30, "XNFRE", UNIPHIER_PIN_IECTRL_NONE,
+                            30, UNIPHIER_PIN_DRV_4_8,
+                            30, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(31, "XNFWE", UNIPHIER_PIN_IECTRL_NONE,
+                            31, UNIPHIER_PIN_DRV_4_8,
+                            31, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(32, "NFALE", UNIPHIER_PIN_IECTRL_NONE,
+                            32, UNIPHIER_PIN_DRV_4_8,
+                            32, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(33, "NFCLE", UNIPHIER_PIN_IECTRL_NONE,
+                            33, UNIPHIER_PIN_DRV_4_8,
+                            33, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(34, "XNFWP", UNIPHIER_PIN_IECTRL_NONE,
+                            34, UNIPHIER_PIN_DRV_4_8,
+                            34, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(35, "XNFCE0", UNIPHIER_PIN_IECTRL_NONE,
+                            35, UNIPHIER_PIN_DRV_4_8,
+                            35, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(36, "NFRYBY0", UNIPHIER_PIN_IECTRL_NONE,
+                            36, UNIPHIER_PIN_DRV_4_8,
+                            36, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(37, "XNFCE1", UNIPHIER_PIN_IECTRL_NONE,
+                            37, UNIPHIER_PIN_DRV_4_8,
+                            37, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(38, "NFRYBY1", UNIPHIER_PIN_IECTRL_NONE,
+                            38, UNIPHIER_PIN_DRV_4_8,
+                            38, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(39, "NFD0", UNIPHIER_PIN_IECTRL_NONE,
+                            39, UNIPHIER_PIN_DRV_4_8,
+                            39, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(40, "NFD1", UNIPHIER_PIN_IECTRL_NONE,
+                            40, UNIPHIER_PIN_DRV_4_8,
+                            40, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(41, "NFD2", UNIPHIER_PIN_IECTRL_NONE,
+                            41, UNIPHIER_PIN_DRV_4_8,
+                            41, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(42, "NFD3", UNIPHIER_PIN_IECTRL_NONE,
+                            42, UNIPHIER_PIN_DRV_4_8,
+                            42, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(43, "NFD4", UNIPHIER_PIN_IECTRL_NONE,
+                            43, UNIPHIER_PIN_DRV_4_8,
+                            43, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(44, "NFD5", UNIPHIER_PIN_IECTRL_NONE,
+                            44, UNIPHIER_PIN_DRV_4_8,
+                            44, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(45, "NFD6", UNIPHIER_PIN_IECTRL_NONE,
+                            45, UNIPHIER_PIN_DRV_4_8,
+                            45, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(46, "NFD7", UNIPHIER_PIN_IECTRL_NONE,
+                            46, UNIPHIER_PIN_DRV_4_8,
+                            46, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(47, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
+                            0, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(48, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(49, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(50, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(51, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
+                            16, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(52, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
+                            20, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_UP_FIXED),
+       UNIPHIER_PINCTRL_PIN(53, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            53, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(54, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            54, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(55, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            55, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(56, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            56, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(57, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            57, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(58, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            58, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(59, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            59, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(60, "USB2VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            60, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(61, "USB2OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            61, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(62, "USB3VBUS", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            62, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(63, "USB3OD", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            63, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(64, "CH0CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            64, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(65, "CH0PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            65, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(66, "CH0VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            66, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(67, "CH0DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            67, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(68, "CH1CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            68, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(69, "CH1PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            69, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(70, "CH1VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            70, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(71, "CH1DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            71, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(72, "XIRQ9", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            72, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(73, "XIRQ10", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            73, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(74, "XIRQ16", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            74, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(75, "CH4CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            75, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(76, "CH4PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            76, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(77, "CH4VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            77, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(78, "CH4DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            78, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(79, "CH5CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            79, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(80, "CH5PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            80, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(81, "CH5VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            81, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(82, "CH5DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            82, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(83, "CH6CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            83, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(84, "CH6PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            84, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(85, "CH6VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            85, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(86, "CH6DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            86, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(87, "STS0CLKO", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            87, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(88, "STS0SYNCO", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            88, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(89, "STS0VALO", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            89, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(90, "STS0DATAO", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            90, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(91, "XIRQ17", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            91, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(92, "PORT163", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            92, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(93, "PORT165", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            93, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(94, "PORT166", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            94, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(95, "PORT132", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            95, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(96, "PORT133", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            96, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(97, "AO2IEC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            97, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(98, "AI2ADCCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            98, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(99, "AI2BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            99, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(100, "AI2LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            100, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(101, "AI2D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            101, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(102, "AI2D1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            102, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(103, "AI2D2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            103, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(104, "AI2D3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            104, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(105, "AO3DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            105, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(106, "AO3BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            106, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(107, "AO3LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            107, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(108, "AO3DMIX", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            108, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(109, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            109, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(110, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            110, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(111, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            111, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(112, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            112, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(113, "TXD2", 0,
+                            113, UNIPHIER_PIN_DRV_4_8,
+                            113, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(114, "RXD2", 0,
+                            114, UNIPHIER_PIN_DRV_4_8,
+                            114, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(115, "TXD1", 0,
+                            115, UNIPHIER_PIN_DRV_4_8,
+                            115, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(116, "RXD1", 0,
+                            116, UNIPHIER_PIN_DRV_4_8,
+                            116, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(117, "PORT190", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            117, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(118, "VI1HSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            118, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(119, "VI1VSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            119, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(120, "VI1DE", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            120, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(121, "XIRQ3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            121, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(122, "XIRQ4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            122, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(123, "VI1G2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            123, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(124, "VI1G3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            124, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(125, "VI1G4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            125, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(126, "VI1G5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            126, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(127, "VI1G6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            127, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(128, "VI1G7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            128, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(129, "VI1G8", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            129, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(130, "VI1G9", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            130, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(131, "VI1CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            131, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(132, "PORT05", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            132, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(133, "PORT06", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            133, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(134, "VI1R2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            134, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(135, "VI1R3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            135, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(136, "VI1R4", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            136, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(137, "VI1R5", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            137, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(138, "VI1R6", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            138, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(139, "VI1R7", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            139, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(140, "VI1R8", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            140, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(141, "VI1R9", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            141, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(142, "LPST", UNIPHIER_PIN_IECTRL_NONE,
+                            142, UNIPHIER_PIN_DRV_4_8,
+                            142, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(143, "MDC", 0,
+                            143, UNIPHIER_PIN_DRV_4_8,
+                            143, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(144, "MDIO", 0,
+                            144, UNIPHIER_PIN_DRV_4_8,
+                            144, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(145, "MDIO_INTL", 0,
+                            145, UNIPHIER_PIN_DRV_4_8,
+                            145, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(146, "PHYRSTL", 0,
+                            146, UNIPHIER_PIN_DRV_4_8,
+                            146, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(147, "RGMII_RXCLK", 0,
+                            147, UNIPHIER_PIN_DRV_4_8,
+                            147, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(148, "RGMII_RXD0", 0,
+                            148, UNIPHIER_PIN_DRV_4_8,
+                            148, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(149, "RGMII_RXD1", 0,
+                            149, UNIPHIER_PIN_DRV_4_8,
+                            149, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(150, "RGMII_RXD2", 0,
+                            150, UNIPHIER_PIN_DRV_4_8,
+                            150, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(151, "RGMII_RXD3", 0,
+                            151, UNIPHIER_PIN_DRV_4_8,
+                            151, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(152, "RGMII_RXCTL", 0,
+                            152, UNIPHIER_PIN_DRV_4_8,
+                            152, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(153, "RGMII_TXCLK", 0,
+                            153, UNIPHIER_PIN_DRV_4_8,
+                            153, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(154, "RGMII_TXD0", 0,
+                            154, UNIPHIER_PIN_DRV_4_8,
+                            154, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(155, "RGMII_TXD1", 0,
+                            155, UNIPHIER_PIN_DRV_4_8,
+                            155, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(156, "RGMII_TXD2", 0,
+                            156, UNIPHIER_PIN_DRV_4_8,
+                            156, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(157, "RGMII_TXD3", 0,
+                            157, UNIPHIER_PIN_DRV_4_8,
+                            157, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(158, "RGMII_TXCTL", 0,
+                            158, UNIPHIER_PIN_DRV_4_8,
+                            158, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(159, "SDA3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            159, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(160, "SCL3", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            160, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(161, "AI1ADCCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            161, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(162, "AI1BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            162, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(163, "CH2CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            163, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(164, "CH2PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            164, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(165, "CH2VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            165, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(166, "CH2DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            166, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(167, "CH3CLK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            167, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(168, "CH3PSYNC", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            168, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(169, "CH3VAL", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            169, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(170, "CH3DATA", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            170, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(171, "SDA2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            171, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(172, "SCL2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            172, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(173, "AI1LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            173, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(174, "AI1D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            174, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(175, "AO2LRCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            175, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(176, "AO2D0", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            176, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(177, "AO2DACCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            177, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(178, "AO2BCK", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            178, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(179, "PORT222", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            179, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(180, "PORT223", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            180, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(181, "PORT224", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            181, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(182, "PORT225", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            182, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(183, "PORT226", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            183, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(184, "PORT227", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            184, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(185, "PORT230", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            185, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(186, "FANPWM", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            186, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(187, "HRDDCSDA0", 0,
+                            187, UNIPHIER_PIN_DRV_4_8,
+                            187, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(188, "HRDDCSCL0", 0,
+                            188, UNIPHIER_PIN_DRV_4_8,
+                            188, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(189, "HRDDCSDA1", 0,
+                            189, UNIPHIER_PIN_DRV_4_8,
+                            189, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(190, "HRDDCSCL1", 0,
+                            190, UNIPHIER_PIN_DRV_4_8,
+                            190, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(191, "HTDDCSDA0", 0,
+                            191, UNIPHIER_PIN_DRV_4_8,
+                            191, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(192, "HTDDCSCL0", 0,
+                            192, UNIPHIER_PIN_DRV_4_8,
+                            192, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(193, "HTDDCSDA1", 0,
+                            193, UNIPHIER_PIN_DRV_4_8,
+                            193, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(194, "HTDDCSCL1", 0,
+                            194, UNIPHIER_PIN_DRV_4_8,
+                            194, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(195, "PORT241", 0,
+                            195, UNIPHIER_PIN_DRV_4_8,
+                            195, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(196, "PORT242", 0,
+                            196, UNIPHIER_PIN_DRV_4_8,
+                            196, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(197, "PORT243", 0,
+                            197, UNIPHIER_PIN_DRV_4_8,
+                            197, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(198, "MVSYNC", 0,
+                            198, UNIPHIER_PIN_DRV_4_8,
+                            198, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(199, "SPISYNC0", UNIPHIER_PIN_IECTRL_NONE,
+                            199, UNIPHIER_PIN_DRV_4_8,
+                            199, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(200, "SPISCLK0", UNIPHIER_PIN_IECTRL_NONE,
+                            200, UNIPHIER_PIN_DRV_4_8,
+                            200, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(201, "SPITXD0", UNIPHIER_PIN_IECTRL_NONE,
+                            201, UNIPHIER_PIN_DRV_4_8,
+                            201, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(202, "SPIRXD0", UNIPHIER_PIN_IECTRL_NONE,
+                            202, UNIPHIER_PIN_DRV_4_8,
+                            202, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(203, "CK54EXI", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            203, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(204, "AEXCKA1", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            204, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(205, "AEXCKA2", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            205, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(206, "CK27EXI", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_8,
+                            206, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(207, "STCDIN", 0,
+                            207, UNIPHIER_PIN_DRV_4_8,
+                            207, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(208, "PHSYNI", 0,
+                            208, UNIPHIER_PIN_DRV_4_8,
+                            208, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(209, "PVSYNI", 0,
+                            209, UNIPHIER_PIN_DRV_4_8,
+                            209, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(210, "MVSYN", UNIPHIER_PIN_IECTRL_NONE,
+                            210, UNIPHIER_PIN_DRV_4_8,
+                            210, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(211, "STCV", UNIPHIER_PIN_IECTRL_NONE,
+                            211, UNIPHIER_PIN_DRV_4_8,
+                            211, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(212, "PORT262", UNIPHIER_PIN_IECTRL_NONE,
+                            212, UNIPHIER_PIN_DRV_4_8,
+                            212, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(213, "USB0VBUS_IRQ", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            213, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(214, "USB1VBUS_IRQ", UNIPHIER_PIN_IECTRL_NONE,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            214, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(215, "PORT265", UNIPHIER_PIN_IECTRL_NONE,
+                            215, UNIPHIER_PIN_DRV_4_8,
+                            215, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(216, "CK25O", 0,
+                            216, UNIPHIER_PIN_DRV_4_8,
+                            216, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(217, "TXD0", 0,
+                            217, UNIPHIER_PIN_DRV_4_8,
+                            217, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(218, "RXD0", 0,
+                            218, UNIPHIER_PIN_DRV_4_8,
+                            218, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(219, "TXD3", 0,
+                            219, UNIPHIER_PIN_DRV_4_8,
+                            219, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(220, "RXD3", 0,
+                            220, UNIPHIER_PIN_DRV_4_8,
+                            220, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(221, "PORT273", 0,
+                            221, UNIPHIER_PIN_DRV_4_8,
+                            221, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(222, "STCDOUTC", 0,
+                            222, UNIPHIER_PIN_DRV_4_8,
+                            222, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(223, "PORT274", 0,
+                            223, UNIPHIER_PIN_DRV_4_8,
+                            223, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(224, "PORT275", 0,
+                            224, UNIPHIER_PIN_DRV_4_8,
+                            224, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(225, "PORT276", 0,
+                            225, UNIPHIER_PIN_DRV_4_8,
+                            225, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(226, "PORT277", 0,
+                            226, UNIPHIER_PIN_DRV_4_8,
+                            226, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(227, "PORT280", 0,
+                            227, UNIPHIER_PIN_DRV_4_8,
+                            227, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(228, "PORT281", 0,
+                            228, UNIPHIER_PIN_DRV_4_8,
+                            228, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(229, "PORT282", 0,
+                            229, UNIPHIER_PIN_DRV_4_8,
+                            229, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(230, "PORT283", 0,
+                            230, UNIPHIER_PIN_DRV_4_8,
+                            230, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(231, "PORT284", 0,
+                            231, UNIPHIER_PIN_DRV_4_8,
+                            231, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(232, "PORT285", 0,
+                            232, UNIPHIER_PIN_DRV_4_8,
+                            232, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(233, "T0HPD", 0,
+                            233, UNIPHIER_PIN_DRV_4_8,
+                            233, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(234, "T1HPD", 0,
+                            234, UNIPHIER_PIN_DRV_4_8,
+                            234, UNIPHIER_PIN_PULL_DOWN),
+};
+
+static const unsigned emmc_pins[] = {36, 37, 38, 39, 40, 41, 42};
+static const unsigned emmc_muxvals[] = {9, 9, 9, 9, 9, 9, 9};
+static const unsigned emmc_dat8_pins[] = {43, 44, 45, 46};
+static const unsigned emmc_dat8_muxvals[] = {9, 9, 9, 9};
+static const unsigned i2c0_pins[] = {109, 110};
+static const unsigned i2c0_muxvals[] = {8, 8};
+static const unsigned i2c1_pins[] = {111, 112};
+static const unsigned i2c1_muxvals[] = {8, 8};
+static const unsigned i2c2_pins[] = {171, 172};
+static const unsigned i2c2_muxvals[] = {8, 8};
+static const unsigned i2c3_pins[] = {159, 160};
+static const unsigned i2c3_muxvals[] = {8, 8};
+static const unsigned i2c5_pins[] = {183, 184};
+static const unsigned i2c5_muxvals[] = {11, 11};
+static const unsigned i2c6_pins[] = {185, 186};
+static const unsigned i2c6_muxvals[] = {11, 11};
+static const unsigned nand_pins[] = {30, 31, 32, 33, 34, 35, 36, 39, 40, 41,
+                                    42, 43, 44, 45, 46};
+static const unsigned nand_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+                                       8, 8};
+static const unsigned nand_cs1_pins[] = {37, 38};
+static const unsigned nand_cs1_muxvals[] = {8, 8};
+static const unsigned sd_pins[] = {47, 48, 49, 50, 51, 52, 53, 54, 55};
+static const unsigned sd_muxvals[] = {8, 8, 8, 8, 8, 8, 8, 8, 8};
+static const unsigned uart0_pins[] = {217, 218};
+static const unsigned uart0_muxvals[] = {8, 8};
+static const unsigned uart0b_pins[] = {179, 180};
+static const unsigned uart0b_muxvals[] = {10, 10};
+static const unsigned uart1_pins[] = {115, 116};
+static const unsigned uart1_muxvals[] = {8, 8};
+static const unsigned uart2_pins[] = {113, 114};
+static const unsigned uart2_muxvals[] = {8, 8};
+static const unsigned uart3_pins[] = {219, 220};
+static const unsigned uart3_muxvals[] = {8, 8};
+static const unsigned uart3b_pins[] = {181, 182};
+static const unsigned uart3b_muxvals[] = {10, 10};
+static const unsigned usb0_pins[] = {56, 57};
+static const unsigned usb0_muxvals[] = {8, 8};
+static const unsigned usb1_pins[] = {58, 59};
+static const unsigned usb1_muxvals[] = {8, 8};
+static const unsigned usb2_pins[] = {60, 61};
+static const unsigned usb2_muxvals[] = {8, 8};
+static const unsigned usb3_pins[] = {62, 63};
+static const unsigned usb3_muxvals[] = {8, 8};
+static const unsigned port_range0_pins[] = {
+       127, 128, 129, 130, 131, 132, 133, 134,         /* PORT0x */
+       135, 136, 137, 138, 139, 140, 141, 142,         /* PORT1x */
+       0, 1, 2, 3, 4, 5, 6, 7,                         /* PORT2x */
+       8, 9, 10, 11, 12, 13, 14, 15,                   /* PORT3x */
+       16, 17, 18, 19, 21, 22, 23, 24,                 /* PORT4x */
+       25, 30, 31, 32, 33, 34, 35, 36,                 /* PORT5x */
+       37, 38, 39, 40, 41, 42, 43, 44,                 /* PORT6x */
+       45, 46, 47, 48, 49, 50, 51, 52,                 /* PORT7x */
+       53, 54, 55, 56, 57, 58, 59, 60,                 /* PORT8x */
+       61, 62, 63, 64, 65, 66, 67, 68,                 /* PORT9x */
+       69, 70, 71, 76, 77, 78, 79, 80,                 /* PORT10x */
+};
+static const unsigned port_range0_muxvals[] = {
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT0x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT1x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT2x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
+};
+static const unsigned port_range1_pins[] = {
+       81, 82, 83, 84, 85, 86, 87, 88,                 /* PORT12x */
+       89, 90, 95, 96, 97, 98, 99, 100,                /* PORT13x */
+       101, 102, 103, 104, 105, 106, 107, 108,         /* PORT14x */
+       118, 119, 120, 121, 122, 123, 124, 125,         /* PORT15x */
+       126, 72, 73, 92, 177, 93, 94, 176,              /* PORT16x */
+       74, 91, 27, 28, 29, 75, 20, 26,                 /* PORT17x */
+       109, 110, 111, 112, 113, 114, 115, 116,         /* PORT18x */
+       117, 143, 144, 145, 146, 147, 148, 149,         /* PORT19x */
+       150, 151, 152, 153, 154, 155, 156, 157,         /* PORT20x */
+       158, 159, 160, 161, 162, 163, 164, 165,         /* PORT21x */
+       166, 178, 179, 180, 181, 182, 183, 184,         /* PORT22x */
+       185, 187, 188, 189, 190, 191, 192, 193,         /* PORT23x */
+       194, 195, 196, 197, 198, 199, 200, 201,         /* PORT24x */
+       202, 203, 204, 205, 206, 207, 208, 209,         /* PORT25x */
+       210, 211, 212, 213, 214, 215, 216, 217,         /* PORT26x */
+       218, 219, 220, 221, 223, 224, 225, 226,         /* PORT27x */
+       227, 228, 229, 230, 231, 232, 233, 234,         /* PORT28x */
+};
+static const unsigned port_range1_muxvals[] = {
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT12x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT13x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT15x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT16x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT17x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT18x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT19x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT20x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT21x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT22x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT23x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT24x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT25x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT26x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT27x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT28x */
+};
+static const unsigned xirq_pins[] = {
+       118, 119, 120, 121, 122, 123, 124, 125,         /* XIRQ0-7 */
+       126, 72, 73, 92, 177, 93, 94, 176,              /* XIRQ8-15 */
+       74, 91, 27, 28, 29, 75, 20, 26,                 /* XIRQ16-23 */
+};
+static const unsigned xirq_muxvals[] = {
+       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ0-7 */
+       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ8-15 */
+       14, 14, 14, 14, 14, 14, 14, 14,                 /* XIRQ16-23 */
+};
+
+static const struct uniphier_pinctrl_group proxstream2_groups[] = {
+       UNIPHIER_PINCTRL_GROUP(emmc),
+       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+       UNIPHIER_PINCTRL_GROUP(i2c0),
+       UNIPHIER_PINCTRL_GROUP(i2c1),
+       UNIPHIER_PINCTRL_GROUP(i2c2),
+       UNIPHIER_PINCTRL_GROUP(i2c3),
+       UNIPHIER_PINCTRL_GROUP(i2c5),
+       UNIPHIER_PINCTRL_GROUP(i2c6),
+       UNIPHIER_PINCTRL_GROUP(nand),
+       UNIPHIER_PINCTRL_GROUP(nand_cs1),
+       UNIPHIER_PINCTRL_GROUP(sd),
+       UNIPHIER_PINCTRL_GROUP(uart0),
+       UNIPHIER_PINCTRL_GROUP(uart0b),
+       UNIPHIER_PINCTRL_GROUP(uart1),
+       UNIPHIER_PINCTRL_GROUP(uart2),
+       UNIPHIER_PINCTRL_GROUP(uart3),
+       UNIPHIER_PINCTRL_GROUP(uart3b),
+       UNIPHIER_PINCTRL_GROUP(usb0),
+       UNIPHIER_PINCTRL_GROUP(usb1),
+       UNIPHIER_PINCTRL_GROUP(usb2),
+       UNIPHIER_PINCTRL_GROUP(usb3),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range1, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range1, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range1, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range1, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range1, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port125, port_range1, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port126, port_range1, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port127, port_range1, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range1, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range1, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port132, port_range1, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port133, port_range1, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port134, port_range1, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port135, port_range1, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port136, port_range1, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port137, port_range1, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range1, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range1, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range1, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range1, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range1, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range1, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range1, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range1, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port150, port_range1, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port151, port_range1, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port152, port_range1, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port153, port_range1, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port154, port_range1, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port155, port_range1, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port156, port_range1, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port157, port_range1, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port160, port_range1, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port161, port_range1, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port162, port_range1, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port163, port_range1, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port164, port_range1, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port165, port_range1, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port166, port_range1, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port167, port_range1, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port170, port_range1, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port171, port_range1, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port172, port_range1, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port173, port_range1, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port174, port_range1, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port175, port_range1, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port176, port_range1, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port177, port_range1, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port180, port_range1, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port181, port_range1, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port182, port_range1, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port183, port_range1, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port184, port_range1, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port185, port_range1, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port186, port_range1, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port187, port_range1, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port190, port_range1, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port191, port_range1, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port192, port_range1, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port193, port_range1, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port194, port_range1, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port195, port_range1, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port196, port_range1, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port197, port_range1, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port200, port_range1, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port201, port_range1, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port202, port_range1, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port203, port_range1, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port204, port_range1, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port205, port_range1, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port206, port_range1, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port207, port_range1, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port210, port_range1, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port211, port_range1, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port212, port_range1, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port213, port_range1, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port214, port_range1, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port215, port_range1, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port216, port_range1, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port217, port_range1, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port220, port_range1, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port221, port_range1, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port222, port_range1, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port223, port_range1, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port224, port_range1, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port225, port_range1, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port226, port_range1, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port227, port_range1, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port230, port_range1, 88),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port231, port_range1, 89),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port232, port_range1, 90),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port233, port_range1, 91),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port234, port_range1, 92),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port235, port_range1, 93),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port236, port_range1, 94),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port237, port_range1, 95),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port240, port_range1, 96),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port241, port_range1, 97),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port242, port_range1, 98),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port243, port_range1, 99),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port244, port_range1, 100),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port245, port_range1, 101),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port246, port_range1, 102),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port247, port_range1, 103),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port250, port_range1, 104),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port251, port_range1, 105),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port252, port_range1, 106),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port253, port_range1, 107),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port254, port_range1, 108),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port255, port_range1, 109),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port256, port_range1, 110),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port257, port_range1, 111),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port260, port_range1, 112),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port261, port_range1, 113),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port262, port_range1, 114),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port263, port_range1, 115),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port264, port_range1, 116),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port265, port_range1, 117),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port266, port_range1, 118),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port267, port_range1, 119),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port270, port_range1, 120),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port271, port_range1, 121),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port272, port_range1, 122),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port273, port_range1, 123),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port274, port_range1, 124),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port275, port_range1, 125),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port276, port_range1, 126),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port277, port_range1, 127),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port280, port_range1, 128),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port281, port_range1, 129),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port282, port_range1, 130),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port283, port_range1, 131),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port284, port_range1, 132),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port285, port_range1, 133),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port286, port_range1, 134),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port287, port_range1, 135),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq13, xirq, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq16, xirq, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq17, xirq, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq18, xirq, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq19, xirq, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq20, xirq, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq21, xirq, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq22, xirq, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq23, xirq, 23),
+};
+
+static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
+static const char * const i2c0_groups[] = {"i2c0"};
+static const char * const i2c1_groups[] = {"i2c1"};
+static const char * const i2c2_groups[] = {"i2c2"};
+static const char * const i2c3_groups[] = {"i2c3"};
+static const char * const i2c5_groups[] = {"i2c5"};
+static const char * const i2c6_groups[] = {"i2c6"};
+static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const uart0_groups[] = {"uart0", "uart0b"};
+static const char * const uart1_groups[] = {"uart1"};
+static const char * const uart2_groups[] = {"uart2"};
+static const char * const uart3_groups[] = {"uart3", "uart3b"};
+static const char * const usb0_groups[] = {"usb0"};
+static const char * const usb1_groups[] = {"usb1"};
+static const char * const usb2_groups[] = {"usb2"};
+static const char * const usb3_groups[] = {"usb3"};
+static const char * const port_groups[] = {
+       "port00",  "port01",  "port02",  "port03",
+       "port04",  "port05",  "port06",  "port07",
+       "port10",  "port11",  "port12",  "port13",
+       "port14",  "port15",  "port16",  "port17",
+       "port20",  "port21",  "port22",  "port23",
+       "port24",  "port25",  "port26",  "port27",
+       "port30",  "port31",  "port32",  "port33",
+       "port34",  "port35",  "port36",  "port37",
+       "port40",  "port41",  "port42",  "port43",
+       "port44",  "port45",  "port46",  "port47",
+       "port50",  "port51",  "port52",  "port53",
+       "port54",  "port55",  "port56",  "port57",
+       "port60",  "port61",  "port62",  "port63",
+       "port64",  "port65",  "port66",  "port67",
+       "port70",  "port71",  "port72",  "port73",
+       "port74",  "port75",  "port76",  "port77",
+       "port80",  "port81",  "port82",  "port83",
+       "port84",  "port85",  "port86",  "port87",
+       "port90",  "port91",  "port92",  "port93",
+       "port94",  "port95",  "port96",  "port97",
+       "port100", "port101", "port102", "port103",
+       "port104", "port105", "port106", "port107",
+       /* port110-117 missing */
+       "port120", "port121", "port122", "port123",
+       "port124", "port125", "port126", "port127",
+       "port130", "port131", "port132", "port133",
+       "port134", "port135", "port136", "port137",
+       "port140", "port141", "port142", "port143",
+       "port144", "port145", "port146", "port147",
+       "port150", "port151", "port152", "port153",
+       "port154", "port155", "port156", "port157",
+       "port160", "port161", "port162", "port163",
+       "port164", "port165", "port166", "port167",
+       "port170", "port171", "port172", "port173",
+       "port174", "port175", "port176", "port177",
+       "port180", "port181", "port182", "port183",
+       "port184", "port185", "port186", "port187",
+       "port190", "port191", "port192", "port193",
+       "port194", "port195", "port196", "port197",
+       "port200", "port201", "port202", "port203",
+       "port204", "port205", "port206", "port207",
+       "port210", "port211", "port212", "port213",
+       "port214", "port215", "port216", "port217",
+       "port220", "port221", "port222", "port223",
+       "port224", "port225", "port226", "port227",
+       "port230", "port231", "port232", "port233",
+       "port234", "port235", "port236", "port237",
+       "port240", "port241", "port242", "port243",
+       "port244", "port245", "port246", "port247",
+       "port250", "port251", "port252", "port253",
+       "port254", "port255", "port256", "port257",
+       "port260", "port261", "port262", "port263",
+       "port264", "port265", "port266", "port267",
+       "port270", "port271", "port272", "port273",
+       "port274", "port275", "port276", "port277",
+       "port280", "port281", "port282", "port283",
+       "port284", "port285", "port286", "port287",
+};
+static const char * const xirq_groups[] = {
+       "xirq0",  "xirq1",  "xirq2",  "xirq3",
+       "xirq4",  "xirq5",  "xirq6",  "xirq7",
+       "xirq8",  "xirq9",  "xirq10", "xirq11",
+       "xirq12", "xirq13", "xirq14", "xirq15",
+       "xirq16", "xirq17", "xirq18", "xirq19",
+       "xirq20", "xirq21", "xirq22", "xirq23",
+};
+
+static const struct uniphier_pinmux_function proxstream2_functions[] = {
+       UNIPHIER_PINMUX_FUNCTION(emmc),
+       UNIPHIER_PINMUX_FUNCTION(i2c0),
+       UNIPHIER_PINMUX_FUNCTION(i2c1),
+       UNIPHIER_PINMUX_FUNCTION(i2c2),
+       UNIPHIER_PINMUX_FUNCTION(i2c3),
+       UNIPHIER_PINMUX_FUNCTION(i2c5),
+       UNIPHIER_PINMUX_FUNCTION(i2c6),
+       UNIPHIER_PINMUX_FUNCTION(nand),
+       UNIPHIER_PINMUX_FUNCTION(sd),
+       UNIPHIER_PINMUX_FUNCTION(uart0),
+       UNIPHIER_PINMUX_FUNCTION(uart1),
+       UNIPHIER_PINMUX_FUNCTION(uart2),
+       UNIPHIER_PINMUX_FUNCTION(uart3),
+       UNIPHIER_PINMUX_FUNCTION(usb0),
+       UNIPHIER_PINMUX_FUNCTION(usb1),
+       UNIPHIER_PINMUX_FUNCTION(usb2),
+       UNIPHIER_PINMUX_FUNCTION(usb3),
+       UNIPHIER_PINMUX_FUNCTION(port),
+       UNIPHIER_PINMUX_FUNCTION(xirq),
+};
+
+static struct uniphier_pinctrl_socdata proxstream2_pindata = {
+       .groups = proxstream2_groups,
+       .groups_count = ARRAY_SIZE(proxstream2_groups),
+       .functions = proxstream2_functions,
+       .functions_count = ARRAY_SIZE(proxstream2_functions),
+       .mux_bits = 8,
+       .reg_stride = 4,
+       .load_pinctrl = false,
+};
+
+static struct pinctrl_desc proxstream2_pinctrl_desc = {
+       .name = DRIVER_NAME,
+       .pins = proxstream2_pins,
+       .npins = ARRAY_SIZE(proxstream2_pins),
+       .owner = THIS_MODULE,
+};
+
+static int proxstream2_pinctrl_probe(struct platform_device *pdev)
+{
+       return uniphier_pinctrl_probe(pdev, &proxstream2_pinctrl_desc,
+                                     &proxstream2_pindata);
+}
+
+static const struct of_device_id proxstream2_pinctrl_match[] = {
+       { .compatible = "socionext,proxstream2-pinctrl" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, proxstream2_pinctrl_match);
+
+static struct platform_driver proxstream2_pinctrl_driver = {
+       .probe = proxstream2_pinctrl_probe,
+       .remove = uniphier_pinctrl_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .of_match_table = proxstream2_pinctrl_match,
+       },
+};
+module_platform_driver(proxstream2_pinctrl_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier ProXstream2 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c b/drivers/pinctrl/uniphier/pinctrl-uniphier-sld8.c
new file mode 100644 (file)
index 0000000..c3700a3
--- /dev/null
@@ -0,0 +1,799 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+
+#include "pinctrl-uniphier.h"
+
+#define DRIVER_NAME "ph1-sld8-pinctrl"
+
+static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
+       UNIPHIER_PINCTRL_PIN(0, "PCA00", 0,
+                            15, UNIPHIER_PIN_DRV_4_8,
+                            15, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(1, "PCA01", 0,
+                            16, UNIPHIER_PIN_DRV_4_8,
+                            16, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(2, "PCA02", 0,
+                            17, UNIPHIER_PIN_DRV_4_8,
+                            17, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(3, "PCA03", 0,
+                            18, UNIPHIER_PIN_DRV_4_8,
+                            18, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(4, "PCA04", 0,
+                            19, UNIPHIER_PIN_DRV_4_8,
+                            19, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(5, "PCA05", 0,
+                            20, UNIPHIER_PIN_DRV_4_8,
+                            20, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(6, "PCA06", 0,
+                            21, UNIPHIER_PIN_DRV_4_8,
+                            21, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(7, "PCA07", 0,
+                            22, UNIPHIER_PIN_DRV_4_8,
+                            22, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(8, "PCA08", 0,
+                            23, UNIPHIER_PIN_DRV_4_8,
+                            23, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(9, "PCA09", 0,
+                            24, UNIPHIER_PIN_DRV_4_8,
+                            24, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(10, "PCA10", 0,
+                            25, UNIPHIER_PIN_DRV_4_8,
+                            25, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(11, "PCA11", 0,
+                            26, UNIPHIER_PIN_DRV_4_8,
+                            26, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(12, "PCA12", 0,
+                            27, UNIPHIER_PIN_DRV_4_8,
+                            27, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(13, "PCA13", 0,
+                            28, UNIPHIER_PIN_DRV_4_8,
+                            28, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(14, "PCA14", 0,
+                            29, UNIPHIER_PIN_DRV_4_8,
+                            29, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(15, "XNFRE_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            30, UNIPHIER_PIN_DRV_4_8,
+                            30, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(16, "XNFWE_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            31, UNIPHIER_PIN_DRV_4_8,
+                            31, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(17, "NFALE_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            32, UNIPHIER_PIN_DRV_4_8,
+                            32, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(18, "NFCLE_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            33, UNIPHIER_PIN_DRV_4_8,
+                            33, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(19, "XNFWP_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            34, UNIPHIER_PIN_DRV_4_8,
+                            34, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(20, "XNFCE0_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            35, UNIPHIER_PIN_DRV_4_8,
+                            35, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(21, "NANDRYBY0_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            36, UNIPHIER_PIN_DRV_4_8,
+                            36, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(22, "XNFCE1_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            0, UNIPHIER_PIN_DRV_8_12_16_20,
+                            119, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(23, "NANDRYBY1_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            4, UNIPHIER_PIN_DRV_8_12_16_20,
+                            120, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(24, "NFD0_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            8, UNIPHIER_PIN_DRV_8_12_16_20,
+                            121, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(25, "NFD1_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            12, UNIPHIER_PIN_DRV_8_12_16_20,
+                            122, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(26, "NFD2_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            16, UNIPHIER_PIN_DRV_8_12_16_20,
+                            123, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(27, "NFD3_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            20, UNIPHIER_PIN_DRV_8_12_16_20,
+                            124, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(28, "NFD4_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            24, UNIPHIER_PIN_DRV_8_12_16_20,
+                            125, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(29, "NFD5_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            28, UNIPHIER_PIN_DRV_8_12_16_20,
+                            126, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(30, "NFD6_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            32, UNIPHIER_PIN_DRV_8_12_16_20,
+                            127, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(31, "NFD7_GB", UNIPHIER_PIN_IECTRL_NONE,
+                            36, UNIPHIER_PIN_DRV_8_12_16_20,
+                            128, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(32, "SDCLK", 8,
+                            40, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(33, "SDCMD", 8,
+                            44, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(34, "SDDAT0", 8,
+                            48, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(35, "SDDAT1", 8,
+                            52, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(36, "SDDAT2", 8,
+                            56, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(37, "SDDAT3", 8,
+                            60, UNIPHIER_PIN_DRV_8_12_16_20,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(38, "SDCD", 8,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            129, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(39, "SDWP", 8,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            130, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(40, "SDVOLC", 9,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            131, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", 0,
+                            37, UNIPHIER_PIN_DRV_4_8,
+                            37, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(42, "USB0OD", 0,
+                            38, UNIPHIER_PIN_DRV_4_8,
+                            38, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", 0,
+                            39, UNIPHIER_PIN_DRV_4_8,
+                            39, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(44, "USB1OD", 0,
+                            40, UNIPHIER_PIN_DRV_4_8,
+                            40, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(45, "PCRESET", 0,
+                            41, UNIPHIER_PIN_DRV_4_8,
+                            41, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(46, "PCREG", 0,
+                            42, UNIPHIER_PIN_DRV_4_8,
+                            42, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(47, "PCCE2", 0,
+                            43, UNIPHIER_PIN_DRV_4_8,
+                            43, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(48, "PCVS1", 0,
+                            44, UNIPHIER_PIN_DRV_4_8,
+                            44, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(49, "PCCD2", 0,
+                            45, UNIPHIER_PIN_DRV_4_8,
+                            45, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(50, "PCCD1", 0,
+                            46, UNIPHIER_PIN_DRV_4_8,
+                            46, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(51, "PCREADY", 0,
+                            47, UNIPHIER_PIN_DRV_4_8,
+                            47, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(52, "PCDOE", 0,
+                            48, UNIPHIER_PIN_DRV_4_8,
+                            48, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(53, "PCCE1", 0,
+                            49, UNIPHIER_PIN_DRV_4_8,
+                            49, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(54, "PCWE", 0,
+                            50, UNIPHIER_PIN_DRV_4_8,
+                            50, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(55, "PCOE", 0,
+                            51, UNIPHIER_PIN_DRV_4_8,
+                            51, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(56, "PCWAIT", 0,
+                            52, UNIPHIER_PIN_DRV_4_8,
+                            52, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(57, "PCIOWR", 0,
+                            53, UNIPHIER_PIN_DRV_4_8,
+                            53, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(58, "PCIORD", 0,
+                            54, UNIPHIER_PIN_DRV_4_8,
+                            54, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", 0,
+                            55, UNIPHIER_PIN_DRV_4_8,
+                            55, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", 0,
+                            56, UNIPHIER_PIN_DRV_4_8,
+                            56, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", 0,
+                            57, UNIPHIER_PIN_DRV_4_8,
+                            57, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", 0,
+                            58, UNIPHIER_PIN_DRV_4_8,
+                            58, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", 0,
+                            59, UNIPHIER_PIN_DRV_4_8,
+                            59, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", 0,
+                            60, UNIPHIER_PIN_DRV_4_8,
+                            60, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", 0,
+                            61, UNIPHIER_PIN_DRV_4_8,
+                            61, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", 0,
+                            62, UNIPHIER_PIN_DRV_4_8,
+                            62, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", 0,
+                            63, UNIPHIER_PIN_DRV_4_8,
+                            63, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", 0,
+                            64, UNIPHIER_PIN_DRV_4_8,
+                            64, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", 0,
+                            65, UNIPHIER_PIN_DRV_4_8,
+                            65, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", 0,
+                            66, UNIPHIER_PIN_DRV_4_8,
+                            66, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", 0,
+                            67, UNIPHIER_PIN_DRV_4_8,
+                            67, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", 0,
+                            68, UNIPHIER_PIN_DRV_4_8,
+                            68, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", 0,
+                            69, UNIPHIER_PIN_DRV_4_8,
+                            69, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", 0,
+                            70, UNIPHIER_PIN_DRV_4_8,
+                            70, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", 0,
+                            71, UNIPHIER_PIN_DRV_4_8,
+                            71, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", 0,
+                            72, UNIPHIER_PIN_DRV_4_8,
+                            72, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", 0,
+                            73, UNIPHIER_PIN_DRV_4_8,
+                            73, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", 0,
+                            74, UNIPHIER_PIN_DRV_4_8,
+                            74, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", 0,
+                            75, UNIPHIER_PIN_DRV_4_8,
+                            75, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", 0,
+                            76, UNIPHIER_PIN_DRV_4_8,
+                            76, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", 0,
+                            77, UNIPHIER_PIN_DRV_4_8,
+                            77, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", 0,
+                            78, UNIPHIER_PIN_DRV_4_8,
+                            78, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", 0,
+                            79, UNIPHIER_PIN_DRV_4_8,
+                            79, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", 0,
+                            80, UNIPHIER_PIN_DRV_4_8,
+                            80, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", 0,
+                            81, UNIPHIER_PIN_DRV_4_8,
+                            81, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", 0,
+                            82, UNIPHIER_PIN_DRV_4_8,
+                            82, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", 0,
+                            83, UNIPHIER_PIN_DRV_4_8,
+                            83, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", 0,
+                            84, UNIPHIER_PIN_DRV_4_8,
+                            84, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", 0,
+                            85, UNIPHIER_PIN_DRV_4_8,
+                            85, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", 0,
+                            86, UNIPHIER_PIN_DRV_4_8,
+                            86, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", 0,
+                            87, UNIPHIER_PIN_DRV_4_8,
+                            87, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(92, "AGCI", 3,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            132, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(93, "AGCR", 4,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            133, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(94, "AGCBS", 5,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            134, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(95, "IECOUT", 0,
+                            88, UNIPHIER_PIN_DRV_4_8,
+                            88, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(96, "ASMCK", 0,
+                            89, UNIPHIER_PIN_DRV_4_8,
+                            89, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(97, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
+                            90, UNIPHIER_PIN_DRV_4_8,
+                            90, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(98, "ALRCKO", UNIPHIER_PIN_IECTRL_NONE,
+                            91, UNIPHIER_PIN_DRV_4_8,
+                            91, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(99, "ASDOUT0", UNIPHIER_PIN_IECTRL_NONE,
+                            92, UNIPHIER_PIN_DRV_4_8,
+                            92, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(100, "ASDOUT1", UNIPHIER_PIN_IECTRL_NONE,
+                            93, UNIPHIER_PIN_DRV_4_8,
+                            93, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(101, "ARCOUT", 0,
+                            94, UNIPHIER_PIN_DRV_4_8,
+                            94, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(102, "SDA0", 10,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(103, "SCL0", 10,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(104, "SDA1", 11,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(105, "SCL1", 11,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", 12,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", 12,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", 13,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", 13,
+                            -1, UNIPHIER_PIN_DRV_FIXED_4,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
+                            95, UNIPHIER_PIN_DRV_4_8,
+                            95, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
+                            96, UNIPHIER_PIN_DRV_4_8,
+                            96, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(112, "SBO1", 0,
+                            97, UNIPHIER_PIN_DRV_4_8,
+                            97, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(113, "SBI1", 0,
+                            98, UNIPHIER_PIN_DRV_4_8,
+                            98, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(114, "TXD1", 0,
+                            99, UNIPHIER_PIN_DRV_4_8,
+                            99, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(115, "RXD1", 0,
+                            100, UNIPHIER_PIN_DRV_4_8,
+                            100, UNIPHIER_PIN_PULL_UP),
+       UNIPHIER_PINCTRL_PIN(116, "HIN", 1,
+                            -1, UNIPHIER_PIN_DRV_FIXED_5,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(117, "VIN", 2,
+                            -1, UNIPHIER_PIN_DRV_FIXED_5,
+                            -1, UNIPHIER_PIN_PULL_NONE),
+       UNIPHIER_PINCTRL_PIN(118, "TCON0", 0,
+                            101, UNIPHIER_PIN_DRV_4_8,
+                            101, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(119, "TCON1", 0,
+                            102, UNIPHIER_PIN_DRV_4_8,
+                            102, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(120, "TCON2", 0,
+                            103, UNIPHIER_PIN_DRV_4_8,
+                            103, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(121, "TCON3", 0,
+                            104, UNIPHIER_PIN_DRV_4_8,
+                            104, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(122, "TCON4", 0,
+                            105, UNIPHIER_PIN_DRV_4_8,
+                            105, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(123, "TCON5", 0,
+                            106, UNIPHIER_PIN_DRV_4_8,
+                            106, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(124, "TCON6", 0,
+                            107, UNIPHIER_PIN_DRV_4_8,
+                            107, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(125, "TCON7", 0,
+                            108, UNIPHIER_PIN_DRV_4_8,
+                            108, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(126, "TCON8", 0,
+                            109, UNIPHIER_PIN_DRV_4_8,
+                            109, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(127, "PWMA", 0,
+                            110, UNIPHIER_PIN_DRV_4_8,
+                            110, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(128, "XIRQ0", 0,
+                            111, UNIPHIER_PIN_DRV_4_8,
+                            111, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(129, "XIRQ1", 0,
+                            112, UNIPHIER_PIN_DRV_4_8,
+                            112, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(130, "XIRQ2", 0,
+                            113, UNIPHIER_PIN_DRV_4_8,
+                            113, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(131, "XIRQ3", 0,
+                            114, UNIPHIER_PIN_DRV_4_8,
+                            114, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(132, "XIRQ4", 0,
+                            115, UNIPHIER_PIN_DRV_4_8,
+                            115, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(133, "XIRQ5", 0,
+                            116, UNIPHIER_PIN_DRV_4_8,
+                            116, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(134, "XIRQ6", 0,
+                            117, UNIPHIER_PIN_DRV_4_8,
+                            117, UNIPHIER_PIN_PULL_DOWN),
+       UNIPHIER_PINCTRL_PIN(135, "XIRQ7", 0,
+                            118, UNIPHIER_PIN_DRV_4_8,
+                            118, UNIPHIER_PIN_PULL_DOWN),
+};
+
+static const unsigned emmc_pins[] = {21, 22, 23, 24, 25, 26, 27};
+static const unsigned emmc_muxvals[] = {1, 1, 1, 1, 1, 1, 1};
+static const unsigned emmc_dat8_pins[] = {28, 29, 30, 31};
+static const unsigned emmc_dat8_muxvals[] = {1, 1, 1, 1};
+static const unsigned i2c0_pins[] = {102, 103};
+static const unsigned i2c0_muxvals[] = {0, 0};
+static const unsigned i2c1_pins[] = {104, 105};
+static const unsigned i2c1_muxvals[] = {0, 0};
+static const unsigned i2c2_pins[] = {108, 109};
+static const unsigned i2c2_muxvals[] = {2, 2};
+static const unsigned i2c3_pins[] = {108, 109};
+static const unsigned i2c3_muxvals[] = {3, 3};
+static const unsigned nand_pins[] = {15, 16, 17, 18, 19, 20, 21, 24, 25, 26,
+                                    27, 28, 29, 30, 31};
+static const unsigned nand_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                       0, 0};
+static const unsigned nand_cs1_pins[] = {22, 23};
+static const unsigned nand_cs1_muxvals[] = {0, 0};
+static const unsigned sd_pins[] = {32, 33, 34, 35, 36, 37, 38, 39, 40};
+static const unsigned sd_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const unsigned uart0_pins[] = {70, 71};
+static const unsigned uart0_muxvals[] = {3, 3};
+static const unsigned uart1_pins[] = {114, 115};
+static const unsigned uart1_muxvals[] = {0, 0};
+static const unsigned uart2_pins[] = {112, 113};
+static const unsigned uart2_muxvals[] = {1, 1};
+static const unsigned uart3_pins[] = {110, 111};
+static const unsigned uart3_muxvals[] = {1, 1};
+static const unsigned usb0_pins[] = {41, 42};
+static const unsigned usb0_muxvals[] = {0, 0};
+static const unsigned usb1_pins[] = {43, 44};
+static const unsigned usb1_muxvals[] = {0, 0};
+static const unsigned usb2_pins[] = {114, 115};
+static const unsigned usb2_muxvals[] = {1, 1};
+static const unsigned port_range0_pins[] = {
+       0, 1, 2, 3, 4, 5, 6, 7,                         /* PORT0x */
+       8, 9, 10, 11, 12, 13, 14, 15,                   /* PORT1x */
+       32, 33, 34, 35, 36, 37, 38, 39,                 /* PORT2x */
+       59, 60, 61, 62, 63, 64, 65, 66,                 /* PORT3x */
+       95, 96, 97, 98, 99, 100, 101, 57,               /* PORT4x */
+       70, 71, 72, 73, 74, 75, 76, 77,                 /* PORT5x */
+       81, 83, 84, 85, 86, 89, 90, 91,                 /* PORT6x */
+       118, 119, 120, 121, 122, 53, 54, 55,            /* PORT7x */
+       41, 42, 43, 44, 79, 80, 18, 19,                 /* PORT8x */
+       110, 111, 112, 113, 114, 115, 16, 17,           /* PORT9x */
+       40, 67, 68, 69, 78, 92, 93, 94,                 /* PORT10x */
+       48, 49, 46, 45, 123, 124, 125, 126,             /* PORT11x */
+       47, 127, 20, 56, 22,                            /* PORT120-124 */
+};
+static const unsigned port_range0_muxvals[] = {
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT0x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT1x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT2x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT3x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT4x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT5x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT6x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT7x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT8x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT9x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT10x */
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT11x */
+       15, 15, 15, 15, 15,                             /* PORT120-124 */
+};
+static const unsigned port_range1_pins[] = {
+       116, 117,                                       /* PORT130-131 */
+};
+static const unsigned port_range1_muxvals[] = {
+       15, 15,                                         /* PORT130-131 */
+};
+static const unsigned port_range2_pins[] = {
+       102, 103, 104, 105, 106, 107, 108, 109,         /* PORT14x */
+};
+static const unsigned port_range2_muxvals[] = {
+       15, 15, 15, 15, 15, 15, 15, 15,                 /* PORT14x */
+};
+static const unsigned port_range3_pins[] = {
+       23,                                             /* PORT166 */
+};
+static const unsigned port_range3_muxvals[] = {
+       15,                                             /* PORT166 */
+};
+static const unsigned xirq_range0_pins[] = {
+       128, 129, 130, 131, 132, 133, 134, 135,         /* XIRQ0-7 */
+       82, 87, 88, 50, 51,                             /* XIRQ8-12 */
+};
+static const unsigned xirq_range0_muxvals[] = {
+       0, 0, 0, 0, 0, 0, 0, 0,                         /* XIRQ0-7 */
+       14, 14, 14, 14, 14,                             /* XIRQ8-12 */
+};
+static const unsigned xirq_range1_pins[] = {
+       52, 58,                                         /* XIRQ14-15 */
+};
+static const unsigned xirq_range1_muxvals[] = {
+       14, 14,                                         /* XIRQ14-15 */
+};
+
+static const struct uniphier_pinctrl_group ph1_sld8_groups[] = {
+       UNIPHIER_PINCTRL_GROUP(emmc),
+       UNIPHIER_PINCTRL_GROUP(emmc_dat8),
+       UNIPHIER_PINCTRL_GROUP(i2c0),
+       UNIPHIER_PINCTRL_GROUP(i2c1),
+       UNIPHIER_PINCTRL_GROUP(i2c2),
+       UNIPHIER_PINCTRL_GROUP(i2c3),
+       UNIPHIER_PINCTRL_GROUP(nand),
+       UNIPHIER_PINCTRL_GROUP(nand_cs1),
+       UNIPHIER_PINCTRL_GROUP(sd),
+       UNIPHIER_PINCTRL_GROUP(uart0),
+       UNIPHIER_PINCTRL_GROUP(uart1),
+       UNIPHIER_PINCTRL_GROUP(uart2),
+       UNIPHIER_PINCTRL_GROUP(uart3),
+       UNIPHIER_PINCTRL_GROUP(usb0),
+       UNIPHIER_PINCTRL_GROUP(usb1),
+       UNIPHIER_PINCTRL_GROUP(usb2),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range0),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range1),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range2),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_PORT(port_range3),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range0),
+       UNIPHIER_PINCTRL_GROUP_GPIO_RANGE_IRQ(xirq_range1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port00, port_range0, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port01, port_range0, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port02, port_range0, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port03, port_range0, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port04, port_range0, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port05, port_range0, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port06, port_range0, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port07, port_range0, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port10, port_range0, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port11, port_range0, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port12, port_range0, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port13, port_range0, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port14, port_range0, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port15, port_range0, 13),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port16, port_range0, 14),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port17, port_range0, 15),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port20, port_range0, 16),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port21, port_range0, 17),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port22, port_range0, 18),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port23, port_range0, 19),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port24, port_range0, 20),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port25, port_range0, 21),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port26, port_range0, 22),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port27, port_range0, 23),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port30, port_range0, 24),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port31, port_range0, 25),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port32, port_range0, 26),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port33, port_range0, 27),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port34, port_range0, 28),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port35, port_range0, 29),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port36, port_range0, 30),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port37, port_range0, 31),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port40, port_range0, 32),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port41, port_range0, 33),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port42, port_range0, 34),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port43, port_range0, 35),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port44, port_range0, 36),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port45, port_range0, 37),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port46, port_range0, 38),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port47, port_range0, 39),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port50, port_range0, 40),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port51, port_range0, 41),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port52, port_range0, 42),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port53, port_range0, 43),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port54, port_range0, 44),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port55, port_range0, 45),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port56, port_range0, 46),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port57, port_range0, 47),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port60, port_range0, 48),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port61, port_range0, 49),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port62, port_range0, 50),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port63, port_range0, 51),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port64, port_range0, 52),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port65, port_range0, 53),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port66, port_range0, 54),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port67, port_range0, 55),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port70, port_range0, 56),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port71, port_range0, 57),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port72, port_range0, 58),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port73, port_range0, 59),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port74, port_range0, 60),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port75, port_range0, 61),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port76, port_range0, 62),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port77, port_range0, 63),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port80, port_range0, 64),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port81, port_range0, 65),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port82, port_range0, 66),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port83, port_range0, 67),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port84, port_range0, 68),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port85, port_range0, 69),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port86, port_range0, 70),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port87, port_range0, 71),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port90, port_range0, 72),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port91, port_range0, 73),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port92, port_range0, 74),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port93, port_range0, 75),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port94, port_range0, 76),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port95, port_range0, 77),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port96, port_range0, 78),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port97, port_range0, 79),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port100, port_range0, 80),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port101, port_range0, 81),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port102, port_range0, 82),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port103, port_range0, 83),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port104, port_range0, 84),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port105, port_range0, 85),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port106, port_range0, 86),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port107, port_range0, 87),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port110, port_range0, 88),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port111, port_range0, 89),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port112, port_range0, 90),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port113, port_range0, 91),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port114, port_range0, 92),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port115, port_range0, 93),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port116, port_range0, 94),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port117, port_range0, 95),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port120, port_range0, 96),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port121, port_range0, 97),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port122, port_range0, 98),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port123, port_range0, 99),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port124, port_range0, 100),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port130, port_range1, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port131, port_range1, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port140, port_range2, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port141, port_range2, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port142, port_range2, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port143, port_range2, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port144, port_range2, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port145, port_range2, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port146, port_range2, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port147, port_range2, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(port166, port_range3, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq0, xirq_range0, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq1, xirq_range0, 1),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq2, xirq_range0, 2),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq3, xirq_range0, 3),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq4, xirq_range0, 4),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq5, xirq_range0, 5),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq6, xirq_range0, 6),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq7, xirq_range0, 7),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq8, xirq_range0, 8),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq9, xirq_range0, 9),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq10, xirq_range0, 10),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq11, xirq_range0, 11),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq12, xirq_range0, 12),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq14, xirq_range1, 0),
+       UNIPHIER_PINCTRL_GROUP_SINGLE(xirq15, xirq_range1, 1),
+};
+
+static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
+static const char * const i2c0_groups[] = {"i2c0"};
+static const char * const i2c1_groups[] = {"i2c1"};
+static const char * const i2c2_groups[] = {"i2c2"};
+static const char * const i2c3_groups[] = {"i2c3"};
+static const char * const nand_groups[] = {"nand", "nand_cs1"};
+static const char * const sd_groups[] = {"sd"};
+static const char * const uart0_groups[] = {"uart0"};
+static const char * const uart1_groups[] = {"uart1"};
+static const char * const uart2_groups[] = {"uart2"};
+static const char * const uart3_groups[] = {"uart3"};
+static const char * const usb0_groups[] = {"usb0"};
+static const char * const usb1_groups[] = {"usb1"};
+static const char * const usb2_groups[] = {"usb2"};
+static const char * const port_groups[] = {
+       "port00",  "port01",  "port02",  "port03",
+       "port04",  "port05",  "port06",  "port07",
+       "port10",  "port11",  "port12",  "port13",
+       "port14",  "port15",  "port16",  "port17",
+       "port20",  "port21",  "port22",  "port23",
+       "port24",  "port25",  "port26",  "port27",
+       "port30",  "port31",  "port32",  "port33",
+       "port34",  "port35",  "port36",  "port37",
+       "port40",  "port41",  "port42",  "port43",
+       "port44",  "port45",  "port46",  "port47",
+       "port50",  "port51",  "port52",  "port53",
+       "port54",  "port55",  "port56",  "port57",
+       "port60",  "port61",  "port62",  "port63",
+       "port64",  "port65",  "port66",  "port67",
+       "port70",  "port71",  "port72",  "port73",
+       "port74",  "port75",  "port76",  "port77",
+       "port80",  "port81",  "port82",  "port83",
+       "port84",  "port85",  "port86",  "port87",
+       "port90",  "port91",  "port92",  "port93",
+       "port94",  "port95",  "port96",  "port97",
+       "port100", "port101", "port102", "port103",
+       "port104", "port105", "port106", "port107",
+       "port110", "port111", "port112", "port113",
+       "port114", "port115", "port116", "port117",
+       "port120", "port121", "port122", "port123",
+       "port124", "port125", "port126", "port127",
+       "port130", "port131", "port132", "port133",
+       "port134", "port135", "port136", "port137",
+       "port140", "port141", "port142", "port143",
+       "port144", "port145", "port146", "port147",
+       /* port150-164 missing */
+       /* none */ "port165",
+};
+static const char * const xirq_groups[] = {
+       "xirq0",  "xirq1",  "xirq2",  "xirq3",
+       "xirq4",  "xirq5",  "xirq6",  "xirq7",
+       "xirq8",  "xirq9",  "xirq10", "xirq11",
+       "xirq12", /* none*/ "xirq14", "xirq15",
+};
+
+static const struct uniphier_pinmux_function ph1_sld8_functions[] = {
+       UNIPHIER_PINMUX_FUNCTION(emmc),
+       UNIPHIER_PINMUX_FUNCTION(i2c0),
+       UNIPHIER_PINMUX_FUNCTION(i2c1),
+       UNIPHIER_PINMUX_FUNCTION(i2c2),
+       UNIPHIER_PINMUX_FUNCTION(i2c3),
+       UNIPHIER_PINMUX_FUNCTION(nand),
+       UNIPHIER_PINMUX_FUNCTION(sd),
+       UNIPHIER_PINMUX_FUNCTION(uart0),
+       UNIPHIER_PINMUX_FUNCTION(uart1),
+       UNIPHIER_PINMUX_FUNCTION(uart2),
+       UNIPHIER_PINMUX_FUNCTION(uart3),
+       UNIPHIER_PINMUX_FUNCTION(usb0),
+       UNIPHIER_PINMUX_FUNCTION(usb1),
+       UNIPHIER_PINMUX_FUNCTION(usb2),
+       UNIPHIER_PINMUX_FUNCTION(port),
+       UNIPHIER_PINMUX_FUNCTION(xirq),
+};
+
+static struct uniphier_pinctrl_socdata ph1_sld8_pindata = {
+       .groups = ph1_sld8_groups,
+       .groups_count = ARRAY_SIZE(ph1_sld8_groups),
+       .functions = ph1_sld8_functions,
+       .functions_count = ARRAY_SIZE(ph1_sld8_functions),
+       .mux_bits = 8,
+       .reg_stride = 4,
+       .load_pinctrl = false,
+};
+
+static struct pinctrl_desc ph1_sld8_pinctrl_desc = {
+       .name = DRIVER_NAME,
+       .pins = ph1_sld8_pins,
+       .npins = ARRAY_SIZE(ph1_sld8_pins),
+       .owner = THIS_MODULE,
+};
+
+static int ph1_sld8_pinctrl_probe(struct platform_device *pdev)
+{
+       return uniphier_pinctrl_probe(pdev, &ph1_sld8_pinctrl_desc,
+                                     &ph1_sld8_pindata);
+}
+
+static const struct of_device_id ph1_sld8_pinctrl_match[] = {
+       { .compatible = "socionext,ph1-sld8-pinctrl" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ph1_sld8_pinctrl_match);
+
+static struct platform_driver ph1_sld8_pinctrl_driver = {
+       .probe = ph1_sld8_pinctrl_probe,
+       .remove = uniphier_pinctrl_remove,
+       .driver = {
+               .name = DRIVER_NAME,
+               .of_match_table = ph1_sld8_pinctrl_match,
+       },
+};
+module_platform_driver(ph1_sld8_pinctrl_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("UniPhier PH1-sLD8 pinctrl driver");
+MODULE_LICENSE("GPL");
index 05796495be0e4ada9ba9b2995be1698c79fed1e8..4b717c69931327d2045810ccea33164c012c6417 100644 (file)
@@ -252,6 +252,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
        case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
                break;
 
+       case ACPI_RESOURCE_TYPE_SERIAL_BUS:
+               /* serial bus connections (I2C/SPI/UART) are not pnp */
+               break;
+
        default:
                dev_warn(&dev->dev, "unknown resource type %d in _CRS\n",
                         res->type);
index 9429e66be09641fd818f8da593d47c45124d3efe..8eafc6f0df88be5fbf26c6725beb656e49464c0b 100644 (file)
@@ -21,6 +21,9 @@
 
 #include <linux/power/bq27xxx_battery.h>
 
+static DEFINE_IDR(battery_id);
+static DEFINE_MUTEX(battery_mutex);
+
 static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data)
 {
        struct bq27xxx_device_info *di = data;
@@ -70,19 +73,33 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
 {
        struct bq27xxx_device_info *di;
        int ret;
+       char *name;
+       int num;
+
+       /* Get new ID for the new battery device */
+       mutex_lock(&battery_mutex);
+       num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL);
+       mutex_unlock(&battery_mutex);
+       if (num < 0)
+               return num;
+
+       name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num);
+       if (!name)
+               goto err_mem;
 
        di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
        if (!di)
-               return -ENOMEM;
+               goto err_mem;
 
+       di->id = num;
        di->dev = &client->dev;
        di->chip = id->driver_data;
-       di->name = id->name;
+       di->name = name;
        di->bus.read = bq27xxx_battery_i2c_read;
 
        ret = bq27xxx_battery_setup(di);
        if (ret)
-               return ret;
+               goto err_failed;
 
        /* Schedule a polling after about 1 min */
        schedule_delayed_work(&di->work, 60 * HZ);
@@ -103,6 +120,16 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client,
        }
 
        return 0;
+
+err_mem:
+       ret = -ENOMEM;
+
+err_failed:
+       mutex_lock(&battery_mutex);
+       idr_remove(&battery_id, num);
+       mutex_unlock(&battery_mutex);
+
+       return ret;
 }
 
 static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
@@ -111,6 +138,10 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client *client)
 
        bq27xxx_battery_teardown(di);
 
+       mutex_lock(&battery_mutex);
+       idr_remove(&battery_id, di->id);
+       mutex_unlock(&battery_mutex);
+
        return 0;
 }
 
index 6c592dc71aeef9c360123365d2b177cda37ac0e8..cdfd01f0adb84f96a1bacf391a28419fe6564d4d 100644 (file)
@@ -133,6 +133,12 @@ struct rapl_domain_data {
        unsigned long timestamp;
 };
 
+struct msrl_action {
+       u32 msr_no;
+       u64 clear_mask;
+       u64 set_mask;
+       int err;
+};
 
 #define        DOMAIN_STATE_INACTIVE           BIT(0)
 #define        DOMAIN_STATE_POWER_LIMIT_SET    BIT(1)
@@ -149,6 +155,7 @@ struct rapl_power_limit {
 static const char pl1_name[] = "long_term";
 static const char pl2_name[] = "short_term";
 
+struct rapl_package;
 struct rapl_domain {
        const char *name;
        enum rapl_domain_type id;
@@ -159,7 +166,7 @@ struct rapl_domain {
        u64 attr_map; /* track capabilities */
        unsigned int state;
        unsigned int domain_energy_unit;
-       int package_id;
+       struct rapl_package *rp;
 };
 #define power_zone_to_rapl_domain(_zone) \
        container_of(_zone, struct rapl_domain, power_zone)
@@ -184,6 +191,7 @@ struct rapl_package {
                                        * notify interrupt enable status.
                                        */
        struct list_head plist;
+       int lead_cpu; /* one active cpu per package for access */
 };
 
 struct rapl_defaults {
@@ -231,10 +239,10 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
 static int rapl_write_data_raw(struct rapl_domain *rd,
                        enum rapl_primitives prim,
                        unsigned long long value);
-static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
+static u64 rapl_unit_xlate(struct rapl_domain *rd,
                        enum unit_type type, u64 value,
                        int to_raw);
-static void package_power_limit_irq_save(int package_id);
+static void package_power_limit_irq_save(struct rapl_package *rp);
 
 static LIST_HEAD(rapl_packages); /* guarded by CPU hotplug lock */
 
@@ -260,20 +268,6 @@ static struct rapl_package *find_package_by_id(int id)
        return NULL;
 }
 
-/* caller to ensure CPU hotplug lock is held */
-static int find_active_cpu_on_package(int package_id)
-{
-       int i;
-
-       for_each_online_cpu(i) {
-               if (topology_physical_package_id(i) == package_id)
-                       return i;
-       }
-       /* all CPUs on this package are offline */
-
-       return -ENODEV;
-}
-
 /* caller must hold cpu hotplug lock */
 static void rapl_cleanup_data(void)
 {
@@ -312,25 +306,19 @@ static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy)
 {
        struct rapl_domain *rd = power_zone_to_rapl_domain(pcd_dev);
 
-       *energy = rapl_unit_xlate(rd, 0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
+       *energy = rapl_unit_xlate(rd, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
        return 0;
 }
 
 static int release_zone(struct powercap_zone *power_zone)
 {
        struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
-       struct rapl_package *rp;
+       struct rapl_package *rp = rd->rp;
 
        /* package zone is the last zone of a package, we can free
         * memory here since all children has been unregistered.
         */
        if (rd->id == RAPL_DOMAIN_PACKAGE) {
-               rp = find_package_by_id(rd->package_id);
-               if (!rp) {
-                       dev_warn(&power_zone->dev, "no package id %s\n",
-                               rd->name);
-                       return -ENODEV;
-               }
                kfree(rd);
                rp->domains = NULL;
        }
@@ -432,11 +420,7 @@ static int set_power_limit(struct powercap_zone *power_zone, int id,
 
        get_online_cpus();
        rd = power_zone_to_rapl_domain(power_zone);
-       rp = find_package_by_id(rd->package_id);
-       if (!rp) {
-               ret = -ENODEV;
-               goto set_exit;
-       }
+       rp = rd->rp;
 
        if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
                dev_warn(&power_zone->dev, "%s locked by BIOS, monitoring only\n",
@@ -456,7 +440,7 @@ static int set_power_limit(struct powercap_zone *power_zone, int id,
                ret = -EINVAL;
        }
        if (!ret)
-               package_power_limit_irq_save(rd->package_id);
+               package_power_limit_irq_save(rp);
 set_exit:
        put_online_cpus();
        return ret;
@@ -655,24 +639,19 @@ static void rapl_init_domains(struct rapl_package *rp)
                        break;
                }
                if (mask) {
-                       rd->package_id = rp->id;
+                       rd->rp = rp;
                        rd++;
                }
        }
 }
 
-static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
-                       enum unit_type type, u64 value,
-                       int to_raw)
+static u64 rapl_unit_xlate(struct rapl_domain *rd, enum unit_type type,
+                       u64 value, int to_raw)
 {
        u64 units = 1;
-       struct rapl_package *rp;
+       struct rapl_package *rp = rd->rp;
        u64 scale = 1;
 
-       rp = find_package_by_id(package);
-       if (!rp)
-               return value;
-
        switch (type) {
        case POWER_UNIT:
                units = rp->power_unit;
@@ -769,10 +748,8 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
        msr = rd->msrs[rp->id];
        if (!msr)
                return -EINVAL;
-       /* use physical package id to look up active cpus */
-       cpu = find_active_cpu_on_package(rd->package_id);
-       if (cpu < 0)
-               return cpu;
+
+       cpu = rd->rp->lead_cpu;
 
        /* special-case package domain, which uses a different bit*/
        if (prim == FW_LOCK && rd->id == RAPL_DOMAIN_PACKAGE) {
@@ -793,42 +770,66 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
        final = value & rp->mask;
        final = final >> rp->shift;
        if (xlate)
-               *data = rapl_unit_xlate(rd, rd->package_id, rp->unit, final, 0);
+               *data = rapl_unit_xlate(rd, rp->unit, final, 0);
        else
                *data = final;
 
        return 0;
 }
 
+
+static int msrl_update_safe(u32 msr_no, u64 clear_mask, u64 set_mask)
+{
+       int err;
+       u64 val;
+
+       err = rdmsrl_safe(msr_no, &val);
+       if (err)
+               goto out;
+
+       val &= ~clear_mask;
+       val |= set_mask;
+
+       err = wrmsrl_safe(msr_no, val);
+
+out:
+       return err;
+}
+
+static void msrl_update_func(void *info)
+{
+       struct msrl_action *ma = info;
+
+       ma->err = msrl_update_safe(ma->msr_no, ma->clear_mask, ma->set_mask);
+}
+
 /* Similar use of primitive info in the read counterpart */
 static int rapl_write_data_raw(struct rapl_domain *rd,
                        enum rapl_primitives prim,
                        unsigned long long value)
 {
-       u64 msr_val;
-       u32 msr;
        struct rapl_primitive_info *rp = &rpi[prim];
        int cpu;
+       u64 bits;
+       struct msrl_action ma;
+       int ret;
 
-       cpu = find_active_cpu_on_package(rd->package_id);
-       if (cpu < 0)
-               return cpu;
-       msr = rd->msrs[rp->id];
-       if (rdmsrl_safe_on_cpu(cpu, msr, &msr_val)) {
-               dev_dbg(&rd->power_zone.dev,
-                       "failed to read msr 0x%x on cpu %d\n", msr, cpu);
-               return -EIO;
-       }
-       value = rapl_unit_xlate(rd, rd->package_id, rp->unit, value, 1);
-       msr_val &= ~rp->mask;
-       msr_val |= value << rp->shift;
-       if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) {
-               dev_dbg(&rd->power_zone.dev,
-                       "failed to write msr 0x%x on cpu %d\n", msr, cpu);
-               return -EIO;
-       }
+       cpu = rd->rp->lead_cpu;
+       bits = rapl_unit_xlate(rd, rp->unit, value, 1);
+       bits |= bits << rp->shift;
+       memset(&ma, 0, sizeof(ma));
 
-       return 0;
+       ma.msr_no = rd->msrs[rp->id];
+       ma.clear_mask = rp->mask;
+       ma.set_mask = bits;
+
+       ret = smp_call_function_single(cpu, msrl_update_func, &ma, 1);
+       if (ret)
+               WARN_ON_ONCE(ret);
+       else
+               ret = ma.err;
+
+       return ret;
 }
 
 /*
@@ -893,6 +894,21 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
        return 0;
 }
 
+static void power_limit_irq_save_cpu(void *info)
+{
+       u32 l, h = 0;
+       struct rapl_package *rp = (struct rapl_package *)info;
+
+       /* save the state of PLN irq mask bit before disabling it */
+       rdmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
+       if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) {
+               rp->power_limit_irq = l & PACKAGE_THERM_INT_PLN_ENABLE;
+               rp->power_limit_irq |= PACKAGE_PLN_INT_SAVED;
+       }
+       l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
+       wrmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+}
+
 
 /* REVISIT:
  * When package power limit is set artificially low by RAPL, LVT
@@ -904,61 +920,40 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
  * to do by adding an atomic notifier.
  */
 
-static void package_power_limit_irq_save(int package_id)
+static void package_power_limit_irq_save(struct rapl_package *rp)
 {
-       u32 l, h = 0;
-       int cpu;
-       struct rapl_package *rp;
-
-       rp = find_package_by_id(package_id);
-       if (!rp)
-               return;
-
        if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
                return;
 
-       cpu = find_active_cpu_on_package(package_id);
-       if (cpu < 0)
-               return;
-       /* save the state of PLN irq mask bit before disabling it */
-       rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
-       if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) {
-               rp->power_limit_irq = l & PACKAGE_THERM_INT_PLN_ENABLE;
-               rp->power_limit_irq |= PACKAGE_PLN_INT_SAVED;
-       }
-       l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
-       wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+       smp_call_function_single(rp->lead_cpu, power_limit_irq_save_cpu, rp, 1);
 }
 
-/* restore per package power limit interrupt enable state */
-static void package_power_limit_irq_restore(int package_id)
+static void power_limit_irq_restore_cpu(void *info)
 {
-       u32 l, h;
-       int cpu;
-       struct rapl_package *rp;
+       u32 l, h = 0;
+       struct rapl_package *rp = (struct rapl_package *)info;
 
-       rp = find_package_by_id(package_id);
-       if (!rp)
-               return;
+       rdmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
 
-       if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
-               return;
+       if (rp->power_limit_irq & PACKAGE_THERM_INT_PLN_ENABLE)
+               l |= PACKAGE_THERM_INT_PLN_ENABLE;
+       else
+               l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
+
+       wrmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+}
 
-       cpu = find_active_cpu_on_package(package_id);
-       if (cpu < 0)
+/* restore per package power limit interrupt enable state */
+static void package_power_limit_irq_restore(struct rapl_package *rp)
+{
+       if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
                return;
 
        /* irq enable state not saved, nothing to restore */
        if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED))
                return;
-       rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
-
-       if (rp->power_limit_irq & PACKAGE_THERM_INT_PLN_ENABLE)
-               l |= PACKAGE_THERM_INT_PLN_ENABLE;
-       else
-               l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
 
-       wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+       smp_call_function_single(rp->lead_cpu, power_limit_irq_restore_cpu, rp, 1);
 }
 
 static void set_floor_freq_default(struct rapl_domain *rd, bool mode)
@@ -1141,7 +1136,7 @@ static int rapl_unregister_powercap(void)
         * hotplug lock held
         */
        list_for_each_entry(rp, &rapl_packages, plist) {
-               package_power_limit_irq_restore(rp->id);
+               package_power_limit_irq_restore(rp);
 
                for (rd = rp->domains; rd < rp->domains + rp->nr_domains;
                     rd++) {
@@ -1392,7 +1387,8 @@ static int rapl_detect_topology(void)
                        /* add the new package to the list */
                        new_package->id = phy_package_id;
                        new_package->nr_cpus = 1;
-
+                       /* use the first active cpu of the package to access */
+                       new_package->lead_cpu = i;
                        /* check if the package contains valid domains */
                        if (rapl_detect_domains(new_package, i) ||
                                rapl_defaults->check_unit(new_package, i)) {
@@ -1448,6 +1444,8 @@ static int rapl_add_package(int cpu)
        /* add the new package to the list */
        rp->id = phy_package_id;
        rp->nr_cpus = 1;
+       rp->lead_cpu = cpu;
+
        /* check if the package contains valid domains */
        if (rapl_detect_domains(rp, cpu) ||
                rapl_defaults->check_unit(rp, cpu)) {
@@ -1480,6 +1478,7 @@ static int rapl_cpu_callback(struct notifier_block *nfb,
        unsigned long cpu = (unsigned long)hcpu;
        int phy_package_id;
        struct rapl_package *rp;
+       int lead_cpu;
 
        phy_package_id = topology_physical_package_id(cpu);
        switch (action) {
@@ -1500,6 +1499,15 @@ static int rapl_cpu_callback(struct notifier_block *nfb,
                        break;
                if (--rp->nr_cpus == 0)
                        rapl_remove_package(rp);
+               else if (cpu == rp->lead_cpu) {
+                       /* choose another active cpu in the package */
+                       lead_cpu = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+                       if (lead_cpu < nr_cpu_ids)
+                               rp->lead_cpu = lead_cpu;
+                       else /* should never go here */
+                               pr_err("no active cpu available for package %d\n",
+                                       phy_package_id);
+               }
        }
 
        return NOTIFY_OK;
index da7bae9915523195def56ead30b186881c025fa4..579fd65299a0cfc18b98e8e51a619e26bf82945f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/timekeeping.h>
 
 #include "ptp_private.h"
 
@@ -120,11 +121,13 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
        struct ptp_clock_caps caps;
        struct ptp_clock_request req;
        struct ptp_sys_offset *sysoff = NULL;
+       struct ptp_sys_offset_precise precise_offset;
        struct ptp_pin_desc pd;
        struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
        struct ptp_clock_info *ops = ptp->info;
        struct ptp_clock_time *pct;
        struct timespec64 ts;
+       struct system_device_crosststamp xtstamp;
        int enable, err = 0;
        unsigned int i, pin_index;
 
@@ -138,6 +141,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
                caps.n_per_out = ptp->info->n_per_out;
                caps.pps = ptp->info->pps;
                caps.n_pins = ptp->info->n_pins;
+               caps.cross_timestamping = ptp->info->getcrosststamp != NULL;
                if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
                        err = -EFAULT;
                break;
@@ -180,6 +184,29 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
                err = ops->enable(ops, &req, enable);
                break;
 
+       case PTP_SYS_OFFSET_PRECISE:
+               if (!ptp->info->getcrosststamp) {
+                       err = -EOPNOTSUPP;
+                       break;
+               }
+               err = ptp->info->getcrosststamp(ptp->info, &xtstamp);
+               if (err)
+                       break;
+
+               ts = ktime_to_timespec64(xtstamp.device);
+               precise_offset.device.sec = ts.tv_sec;
+               precise_offset.device.nsec = ts.tv_nsec;
+               ts = ktime_to_timespec64(xtstamp.sys_realtime);
+               precise_offset.sys_realtime.sec = ts.tv_sec;
+               precise_offset.sys_realtime.nsec = ts.tv_nsec;
+               ts = ktime_to_timespec64(xtstamp.sys_monoraw);
+               precise_offset.sys_monoraw.sec = ts.tv_sec;
+               precise_offset.sys_monoraw.nsec = ts.tv_nsec;
+               if (copy_to_user((void __user *)arg, &precise_offset,
+                                sizeof(precise_offset)))
+                       err = -EFAULT;
+               break;
+
        case PTP_SYS_OFFSET:
                sysoff = kmalloc(sizeof(*sysoff), GFP_KERNEL);
                if (!sysoff) {
index d7b87c64b7cd261c6ec6a1b22ddce040747679d9..e220edc85c68a12bda653b0177255cf38459c7d2 100644 (file)
@@ -117,7 +117,7 @@ int rio_request_inb_mbox(struct rio_mport *mport,
        if (mport->ops->open_inb_mbox == NULL)
                goto out;
 
-       res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 
        if (res) {
                rio_init_mbox_res(res, mbox, mbox);
@@ -185,7 +185,7 @@ int rio_request_outb_mbox(struct rio_mport *mport,
        if (mport->ops->open_outb_mbox == NULL)
                goto out;
 
-       res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+       res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 
        if (res) {
                rio_init_mbox_res(res, mbox, mbox);
@@ -285,7 +285,7 @@ int rio_request_inb_dbell(struct rio_mport *mport,
 {
        int rc = 0;
 
-       struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+       struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 
        if (res) {
                rio_init_dbell_res(res, start, end);
@@ -360,7 +360,7 @@ int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end)
 struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start,
                                        u16 end)
 {
-       struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+       struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 
        if (res) {
                rio_init_dbell_res(res, start, end);
index 8155e80dd3f8cb1af05636eb07af16e799566127..91040ec8e2427bc6e8f3dab6a27a80959afea450 100644 (file)
@@ -78,6 +78,15 @@ config REGULATOR_ACT8865
          This driver controls a active-semi act8865 voltage output
          regulator via I2C bus.
 
+config REGULATOR_ACT8945A
+       tristate "Active-semi ACT8945A voltage regulator"
+       depends on MFD_ACT8945A
+       help
+         This driver controls a active-semi ACT8945A voltage regulator
+         via I2C bus. The ACT8945A features three step-down DC/DC converters
+         and four low-dropout linear regulators, along with a ActivePath
+         battery charger.
+
 config REGULATOR_AD5398
        tristate "Analog Devices AD5398/AD5821 regulators"
        depends on I2C
@@ -261,6 +270,14 @@ config REGULATOR_HI6421
          21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All
          of them come with support to either ECO (idle) or sleep mode.
 
+config REGULATOR_HI655X
+       tristate "Hisilicon HI655X PMIC regulators support"
+       depends on ARCH_HISI || COMPILE_TEST
+       depends on MFD_HI655X_PMIC && OF
+       help
+         This driver provides support for the voltage regulators of the
+         Hisilicon Hi655x PMIC device.
+
 config REGULATOR_ISL9305
        tristate "Intersil ISL9305 regulator"
        depends on I2C
@@ -343,6 +360,15 @@ config REGULATOR_MAX1586
          regulator via I2C bus. The provided regulator is suitable
          for PXA27x chips to control VCC_CORE and VCC_USIM voltages.
 
+config REGULATOR_MAX77620
+       tristate "Maxim 77620/MAX20024 voltage regulator"
+       depends on MFD_MAX77620
+       help
+         This driver controls Maxim MAX77620 voltage output regulator
+         via I2C bus. The provided regulator is suitable for Tegra
+         chip to control Step-Down DC-DC and LDOs. Say Y here to
+         enable the regulator driver.
+
 config REGULATOR_MAX8649
        tristate "Maxim 8649 voltage regulator"
        depends on I2C
index 980b1943fa8153dd0c7cb1d286c5f5a23aacdbf4..61bfbb9d4a0c9fe8724fb0a0aad0cafd7d08176c 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
 obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
 obj-$(CONFIG_REGULATOR_AB8500) += ab8500-ext.o ab8500.o
 obj-$(CONFIG_REGULATOR_ACT8865) += act8865-regulator.o
+obj-$(CONFIG_REGULATOR_ACT8945A) += act8945a-regulator.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
 obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
+obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
 obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o
@@ -46,6 +48,7 @@ obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o
 obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o
 obj-$(CONFIG_REGULATOR_MAX14577) += max14577.o
 obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
+obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8649)        += max8649.o
 obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
 obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
@@ -54,9 +57,9 @@ obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
 obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
 obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
-obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
+obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o
 obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o
-obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o
+obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
 obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
@@ -98,7 +101,7 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
-obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
+obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
index f8d4cd3d139738ca6e46b109bb6f810aeccec146..000d566e32a4e106744ee652dd25967a02fcb190 100644 (file)
@@ -218,7 +218,7 @@ static const struct regulator_desc act8600_regulators[] = {
                .ops = &act8865_ldo_ops,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = 1,
-               .fixed_uV = 1800000,
+               .fixed_uV = 3300000,
                .enable_reg = ACT8600_LDO910_CTRL,
                .enable_mask = ACT8865_ENA,
                .owner = THIS_MODULE,
@@ -369,7 +369,7 @@ static int act8865_pdata_from_dt(struct device *dev,
        for (i = 0; i < num_matches; i++) {
                regulator->id = i;
                regulator->name = matches[i].name;
-               regulator->platform_data = matches[i].init_data;
+               regulator->init_data = matches[i].init_data;
                of_node[i] = matches[i].of_node;
                regulator++;
        }
@@ -396,7 +396,7 @@ static struct regulator_init_data
 
        for (i = 0; i < pdata->num_regulators; i++) {
                if (pdata->regulators[i].id == id)
-                       return pdata->regulators[i].platform_data;
+                       return pdata->regulators[i].init_data;
        }
 
        return NULL;
@@ -415,7 +415,7 @@ static void act8865_power_off(void)
 static int act8865_pmic_probe(struct i2c_client *client,
                              const struct i2c_device_id *i2c_id)
 {
-       static const struct regulator_desc *regulators;
+       const struct regulator_desc *regulators;
        struct act8865_platform_data pdata_of, *pdata;
        struct device *dev = &client->dev;
        struct device_node **of_node;
diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c
new file mode 100644 (file)
index 0000000..441864b
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Voltage regulation driver for active-semi ACT8945A PMIC
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Author: Wenyou Yang <wenyou.yang@atmel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+/**
+ * ACT8945A Global Register Map.
+ */
+#define ACT8945A_SYS_MODE      0x00
+#define ACT8945A_SYS_CTRL      0x01
+#define ACT8945A_DCDC1_VSET1   0x20
+#define ACT8945A_DCDC1_VSET2   0x21
+#define ACT8945A_DCDC1_CTRL    0x22
+#define ACT8945A_DCDC2_VSET1   0x30
+#define ACT8945A_DCDC2_VSET2   0x31
+#define ACT8945A_DCDC2_CTRL    0x32
+#define ACT8945A_DCDC3_VSET1   0x40
+#define ACT8945A_DCDC3_VSET2   0x41
+#define ACT8945A_DCDC3_CTRL    0x42
+#define ACT8945A_LDO1_VSET     0x50
+#define ACT8945A_LDO1_CTRL     0x51
+#define ACT8945A_LDO2_VSET     0x54
+#define ACT8945A_LDO2_CTRL     0x55
+#define ACT8945A_LDO3_VSET     0x60
+#define ACT8945A_LDO3_CTRL     0x61
+#define ACT8945A_LDO4_VSET     0x64
+#define ACT8945A_LDO4_CTRL     0x65
+
+/**
+ * Field Definitions.
+ */
+#define ACT8945A_ENA           0x80    /* ON - [7] */
+#define ACT8945A_VSEL_MASK     0x3F    /* VSET - [5:0] */
+
+/**
+ * ACT8945A Voltage Number
+ */
+#define ACT8945A_VOLTAGE_NUM   64
+
+enum {
+       ACT8945A_ID_DCDC1,
+       ACT8945A_ID_DCDC2,
+       ACT8945A_ID_DCDC3,
+       ACT8945A_ID_LDO1,
+       ACT8945A_ID_LDO2,
+       ACT8945A_ID_LDO3,
+       ACT8945A_ID_LDO4,
+       ACT8945A_REG_NUM,
+};
+
+static const struct regulator_linear_range act8945a_voltage_ranges[] = {
+       REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000),
+       REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000),
+       REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
+};
+
+static struct regulator_ops act8945a_ops = {
+       .list_voltage           = regulator_list_voltage_linear_range,
+       .map_voltage            = regulator_map_voltage_linear_range,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .is_enabled             = regulator_is_enabled_regmap,
+};
+
+#define ACT89xx_REG(_name, _family, _id, _vsel_reg, _supply)           \
+       [_family##_ID_##_id] = {                                        \
+               .name                   = _name,                        \
+               .supply_name            = _supply,                      \
+               .of_match               = of_match_ptr("REG_"#_id),     \
+               .regulators_node        = of_match_ptr("regulators"),   \
+               .id                     = _family##_ID_##_id,           \
+               .type                   = REGULATOR_VOLTAGE,            \
+               .ops                    = &act8945a_ops,                \
+               .n_voltages             = ACT8945A_VOLTAGE_NUM,         \
+               .linear_ranges          = act8945a_voltage_ranges,      \
+               .n_linear_ranges        = ARRAY_SIZE(act8945a_voltage_ranges), \
+               .vsel_reg               = _family##_##_id##_##_vsel_reg, \
+               .vsel_mask              = ACT8945A_VSEL_MASK,           \
+               .enable_reg             = _family##_##_id##_CTRL,       \
+               .enable_mask            = ACT8945A_ENA,                 \
+               .owner                  = THIS_MODULE,                  \
+       }
+
+static const struct regulator_desc act8945a_regulators[] = {
+       ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET1, "vp1"),
+       ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET1, "vp2"),
+       ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET1, "vp3"),
+       ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"),
+       ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"),
+       ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"),
+       ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"),
+};
+
+static const struct regulator_desc act8945a_alt_regulators[] = {
+       ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET2, "vp1"),
+       ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET2, "vp2"),
+       ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET2, "vp3"),
+       ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"),
+       ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"),
+       ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"),
+       ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"),
+};
+
+static int act8945a_pmic_probe(struct platform_device *pdev)
+{
+       struct regulator_config config = { };
+       const struct regulator_desc *regulators;
+       struct regulator_dev *rdev;
+       int i, num_regulators;
+       bool voltage_select;
+
+       voltage_select = of_property_read_bool(pdev->dev.parent->of_node,
+                                              "active-semi,vsel-high");
+
+       if (voltage_select) {
+               regulators = act8945a_alt_regulators;
+               num_regulators = ARRAY_SIZE(act8945a_alt_regulators);
+       } else {
+               regulators = act8945a_regulators;
+               num_regulators = ARRAY_SIZE(act8945a_regulators);
+       }
+
+       config.dev = &pdev->dev;
+       config.dev->of_node = pdev->dev.parent->of_node;
+       for (i = 0; i < num_regulators; i++) {
+               rdev = devm_regulator_register(&pdev->dev, &regulators[i], &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev,
+                               "failed to register %s regulator\n",
+                               regulators[i].name);
+                       return PTR_ERR(rdev);
+               }
+       }
+
+       return 0;
+}
+
+static struct platform_driver act8945a_pmic_driver = {
+       .driver = {
+               .name = "act8945a-regulator",
+       },
+       .probe = act8945a_pmic_probe,
+};
+module_platform_driver(act8945a_pmic_driver);
+
+MODULE_DESCRIPTION("Active-semi ACT8945A voltage regulator driver");
+MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
+MODULE_LICENSE("GPL");
index ea50a886ba6397f9dd185125d99f19e238357e6a..8b0f788a9bbb61afb97390097b83458681e6c94c 100644 (file)
@@ -58,10 +58,12 @@ static int ad5398_write_reg(struct i2c_client *client, const unsigned short data
 
        val = cpu_to_be16(data);
        ret = i2c_master_send(client, (char *)&val, 2);
-       if (ret < 0)
+       if (ret != 2) {
                dev_err(&client->dev, "I2C write error\n");
+               return ret < 0 ? ret : -EIO;
+       }
 
-       return ret;
+       return 0;
 }
 
 static int ad5398_get_current_limit(struct regulator_dev *rdev)
index f2e1a39ce0f35258447093fd84223fc25b087e29..214e815e98eb0d3197dc9f6441d4498863746344 100644 (file)
@@ -39,7 +39,7 @@
 #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,   \
                    _vmask, _ereg, _emask, _enable_val, _disable_val)           \
        [_family##_##_id] = {                                                   \
-               .name           = #_id,                                         \
+               .name           = (_match),                                     \
                .supply_name    = (_supply),                                    \
                .of_match       = of_match_ptr(_match),                         \
                .regulators_node = of_match_ptr("regulators"),                  \
@@ -61,7 +61,7 @@
 #define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg,      \
                 _vmask, _ereg, _emask)                                         \
        [_family##_##_id] = {                                                   \
-               .name           = #_id,                                         \
+               .name           = (_match),                                     \
                .supply_name    = (_supply),                                    \
                .of_match       = of_match_ptr(_match),                         \
                .regulators_node = of_match_ptr("regulators"),                  \
                .ops            = &axp20x_ops,                                  \
        }
 
-#define AXP_DESC_SW(_family, _id, _match, _supply, _min, _max, _step, _vreg,   \
-                   _vmask, _ereg, _emask)                                      \
+#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask)              \
        [_family##_##_id] = {                                                   \
-               .name           = #_id,                                         \
+               .name           = (_match),                                     \
                .supply_name    = (_supply),                                    \
                .of_match       = of_match_ptr(_match),                         \
                .regulators_node = of_match_ptr("regulators"),                  \
                .type           = REGULATOR_VOLTAGE,                            \
                .id             = _family##_##_id,                              \
-               .n_voltages     = (((_max) - (_min)) / (_step) + 1),            \
                .owner          = THIS_MODULE,                                  \
-               .min_uV         = (_min) * 1000,                                \
-               .uV_step        = (_step) * 1000,                               \
-               .vsel_reg       = (_vreg),                                      \
-               .vsel_mask      = (_vmask),                                     \
                .enable_reg     = (_ereg),                                      \
                .enable_mask    = (_emask),                                     \
                .ops            = &axp20x_ops_sw,                               \
 
 #define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt)                   \
        [_family##_##_id] = {                                                   \
-               .name           = #_id,                                         \
+               .name           = (_match),                                     \
                .supply_name    = (_supply),                                    \
                .of_match       = of_match_ptr(_match),                         \
                .regulators_node = of_match_ptr("regulators"),                  \
                .ops            = &axp20x_ops_fixed                             \
        }
 
-#define AXP_DESC_TABLE(_family, _id, _match, _supply, _table, _vreg, _vmask,   \
-                      _ereg, _emask)                                           \
+#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages,   \
+                       _vreg, _vmask, _ereg, _emask)                           \
        [_family##_##_id] = {                                                   \
-               .name           = #_id,                                         \
+               .name           = (_match),                                     \
                .supply_name    = (_supply),                                    \
                .of_match       = of_match_ptr(_match),                         \
                .regulators_node = of_match_ptr("regulators"),                  \
                .type           = REGULATOR_VOLTAGE,                            \
                .id             = _family##_##_id,                              \
-               .n_voltages     = ARRAY_SIZE(_table),                           \
+               .n_voltages     = (_n_voltages),                                \
                .owner          = THIS_MODULE,                                  \
                .vsel_reg       = (_vreg),                                      \
                .vsel_mask      = (_vmask),                                     \
                .enable_reg     = (_ereg),                                      \
                .enable_mask    = (_emask),                                     \
-               .volt_table     = (_table),                                     \
-               .ops            = &axp20x_ops_table,                            \
+               .linear_ranges  = (_ranges),                                    \
+               .n_linear_ranges = ARRAY_SIZE(_ranges),                         \
+               .ops            = &axp20x_ops_range,                            \
        }
 
-static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000,
-                                       1700000, 1800000, 1900000, 2000000, 2500000,
-                                       2700000, 2800000, 3000000, 3100000, 3200000,
-                                       3300000 };
-
 static struct regulator_ops axp20x_ops_fixed = {
        .list_voltage           = regulator_list_voltage_linear,
 };
 
-static struct regulator_ops axp20x_ops_table = {
+static struct regulator_ops axp20x_ops_range = {
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .list_voltage           = regulator_list_voltage_table,
-       .map_voltage            = regulator_map_voltage_ascend,
+       .list_voltage           = regulator_list_voltage_linear_range,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .is_enabled             = regulator_is_enabled_regmap,
@@ -160,13 +149,17 @@ static struct regulator_ops axp20x_ops = {
 };
 
 static struct regulator_ops axp20x_ops_sw = {
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .list_voltage           = regulator_list_voltage_linear,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .is_enabled             = regulator_is_enabled_regmap,
 };
 
+static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
+       REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
+       REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000),
+       REGULATOR_LINEAR_RANGE(2500000, 0x9, 0xf, 100000),
+};
+
 static const struct regulator_desc axp20x_regulators[] = {
        AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25,
                 AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10),
@@ -177,8 +170,9 @@ static const struct regulator_desc axp20x_regulators[] = {
                 AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04),
        AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
                 AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40),
-       AXP_DESC_TABLE(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_data,
-                      AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08),
+       AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_ranges,
+                       16, AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL,
+                       0x08),
        AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
                    AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07,
                    AXP20X_IO_ENABLED, AXP20X_IO_DISABLED),
@@ -196,8 +190,8 @@ static const struct regulator_desc axp22x_regulators[] = {
        AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
                 AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
        /* secondary switchable output of DCDC1 */
-       AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, 1600, 3400, 100,
-                   AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(7)),
+       AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
+                   BIT(7)),
        /* LDO regulator internally chained to DCDC5 */
        AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
                 AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
index 744c9889f88d4f83e27c05687ac14427c833c0c5..e0b7642847731390ed44bbc3e8718fd5dd9e7116 100644 (file)
@@ -1057,18 +1057,18 @@ static int set_machine_constraints(struct regulator_dev *rdev,
 
        ret = machine_constraints_voltage(rdev, rdev->constraints);
        if (ret != 0)
-               goto out;
+               return ret;
 
        ret = machine_constraints_current(rdev, rdev->constraints);
        if (ret != 0)
-               goto out;
+               return ret;
 
        if (rdev->constraints->ilim_uA && ops->set_input_current_limit) {
                ret = ops->set_input_current_limit(rdev,
                                                   rdev->constraints->ilim_uA);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set input limit\n");
-                       goto out;
+                       return ret;
                }
        }
 
@@ -1077,21 +1077,20 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = suspend_prepare(rdev, rdev->constraints->initial_state);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set suspend state\n");
-                       goto out;
+                       return ret;
                }
        }
 
        if (rdev->constraints->initial_mode) {
                if (!ops->set_mode) {
                        rdev_err(rdev, "no set_mode operation\n");
-                       ret = -EINVAL;
-                       goto out;
+                       return -EINVAL;
                }
 
                ret = ops->set_mode(rdev, rdev->constraints->initial_mode);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set initial mode: %d\n", ret);
-                       goto out;
+                       return ret;
                }
        }
 
@@ -1102,7 +1101,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = _regulator_do_enable(rdev);
                if (ret < 0 && ret != -EINVAL) {
                        rdev_err(rdev, "failed to enable\n");
-                       goto out;
+                       return ret;
                }
        }
 
@@ -1111,7 +1110,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set ramp_delay\n");
-                       goto out;
+                       return ret;
                }
        }
 
@@ -1119,7 +1118,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = ops->set_pull_down(rdev);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set pull down\n");
-                       goto out;
+                       return ret;
                }
        }
 
@@ -1127,7 +1126,7 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = ops->set_soft_start(rdev);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set soft start\n");
-                       goto out;
+                       return ret;
                }
        }
 
@@ -1136,16 +1135,34 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = ops->set_over_current_protection(rdev);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set over current protection\n");
-                       goto out;
+                       return ret;
+               }
+       }
+
+       if (rdev->constraints->active_discharge && ops->set_active_discharge) {
+               bool ad_state = (rdev->constraints->active_discharge ==
+                             REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false;
+
+               ret = ops->set_active_discharge(rdev, ad_state);
+               if (ret < 0) {
+                       rdev_err(rdev, "failed to set active discharge\n");
+                       return ret;
+               }
+       }
+
+       if (rdev->constraints->active_discharge && ops->set_active_discharge) {
+               bool ad_state = (rdev->constraints->active_discharge ==
+                             REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false;
+
+               ret = ops->set_active_discharge(rdev, ad_state);
+               if (ret < 0) {
+                       rdev_err(rdev, "failed to set active discharge\n");
+                       return ret;
                }
        }
 
        print_constraints(rdev);
        return 0;
-out:
-       kfree(rdev->constraints);
-       rdev->constraints = NULL;
-       return ret;
 }
 
 /**
@@ -3918,6 +3935,16 @@ regulator_register(const struct regulator_desc *regulator_desc,
                        goto clean;
        }
 
+       if ((config->ena_gpio || config->ena_gpio_initialized) &&
+           gpio_is_valid(config->ena_gpio)) {
+               ret = regulator_ena_gpio_request(rdev, config);
+               if (ret != 0) {
+                       rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
+                                config->ena_gpio, ret);
+                       goto clean;
+               }
+       }
+
        /* register with sysfs */
        rdev->dev.class = &regulator_class;
        rdev->dev.parent = dev;
@@ -3926,21 +3953,11 @@ regulator_register(const struct regulator_desc *regulator_desc,
        ret = device_register(&rdev->dev);
        if (ret != 0) {
                put_device(&rdev->dev);
-               goto clean;
+               goto wash;
        }
 
        dev_set_drvdata(&rdev->dev, rdev);
 
-       if ((config->ena_gpio || config->ena_gpio_initialized) &&
-           gpio_is_valid(config->ena_gpio)) {
-               ret = regulator_ena_gpio_request(rdev, config);
-               if (ret != 0) {
-                       rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
-                                config->ena_gpio, ret);
-                       goto wash;
-               }
-       }
-
        /* set regulator constraints */
        if (init_data)
                constraints = &init_data->constraints;
@@ -3979,13 +3996,13 @@ unset_supplies:
 
 scrub:
        regulator_ena_gpio_free(rdev);
-       kfree(rdev->constraints);
-wash:
        device_unregister(&rdev->dev);
        /* device core frees rdev */
        rdev = ERR_PTR(ret);
        goto out;
 
+wash:
+       regulator_ena_gpio_free(rdev);
 clean:
        kfree(rdev);
        rdev = ERR_PTR(ret);
index 8b3cc9f0cd64c0fa323685c4e36842eb52318d54..01c0e3709b6659aded1d79cbbb5423c7d373d5e9 100644 (file)
@@ -132,6 +132,8 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
        if (error < 0)
                goto error_i2c;
 
+       mutex_lock(&chip->rdev->mutex);
+
        if (val & DA9210_E_OVCURR) {
                regulator_notifier_call_chain(chip->rdev,
                                              REGULATOR_EVENT_OVER_CURRENT,
@@ -155,6 +157,9 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
                                              NULL);
                handled |= DA9210_E_VMAX;
        }
+
+       mutex_unlock(&chip->rdev->mutex);
+
        if (handled) {
                /* Clear handled events */
                error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled);
index 4940e8287df68090104a78cc6239ab90e22423c6..2cb5cc311610a12c467d518336dbdde814665667 100644 (file)
@@ -114,6 +114,22 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
        return 0;
 }
 
+static int fan53555_set_suspend_enable(struct regulator_dev *rdev)
+{
+       struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+
+       return regmap_update_bits(di->regmap, di->sleep_reg,
+                                 VSEL_BUCK_EN, VSEL_BUCK_EN);
+}
+
+static int fan53555_set_suspend_disable(struct regulator_dev *rdev)
+{
+       struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+
+       return regmap_update_bits(di->regmap, di->sleep_reg,
+                                 VSEL_BUCK_EN, 0);
+}
+
 static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
        struct fan53555_device_info *di = rdev_get_drvdata(rdev);
@@ -192,6 +208,8 @@ static struct regulator_ops fan53555_regulator_ops = {
        .set_mode = fan53555_set_mode,
        .get_mode = fan53555_get_mode,
        .set_ramp_delay = fan53555_set_ramp,
+       .set_suspend_enable = fan53555_set_suspend_enable,
+       .set_suspend_disable = fan53555_set_suspend_disable,
 };
 
 static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
index 7bba8b747f30280cc0f6c72853cc17272ea8d87d..a8718e98674a273939f20d06627be943aab6aee7 100644 (file)
@@ -283,8 +283,10 @@ static int gpio_regulator_probe(struct platform_device *pdev)
                drvdata->nr_gpios = config->nr_gpios;
                ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
                if (ret) {
-                       dev_err(&pdev->dev,
-                       "Could not obtain regulator setting GPIOs: %d\n", ret);
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(&pdev->dev,
+                                       "Could not obtain regulator setting GPIOs: %d\n",
+                                       ret);
                        goto err_memstate;
                }
        }
index 3bbb32680a94265069eac502d1d2b679e22fa673..b1e32e7482e92256c01541b1cdca95e05ebd097a 100644 (file)
@@ -465,3 +465,26 @@ int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
        return 0;
 }
 EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
+
+/**
+ * regulator_set_active_discharge_regmap - Default set_active_discharge()
+ *                                        using regmap
+ *
+ * @rdev: device to operate on.
+ * @enable: state to set, 0 to disable and 1 to enable.
+ */
+int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
+                                         bool enable)
+{
+       unsigned int val;
+
+       if (enable)
+               val = rdev->desc->active_discharge_on;
+       else
+               val = rdev->desc->active_discharge_off;
+
+       return regmap_update_bits(rdev->regmap,
+                                 rdev->desc->active_discharge_reg,
+                                 rdev->desc->active_discharge_mask, val);
+}
+EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap);
diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c
new file mode 100644 (file)
index 0000000..aca1846
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Device driver for regulators in Hi655x IC
+ *
+ * Copyright (c) 2016 Hisilicon.
+ *
+ * Authors:
+ * Chen Feng <puck.chen@hisilicon.com>
+ * Fei  Wang <w.f@huawei.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.
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/hi655x-pmic.h>
+
+struct hi655x_regulator {
+       unsigned int disable_reg;
+       unsigned int status_reg;
+       unsigned int ctrl_regs;
+       unsigned int ctrl_mask;
+       struct regulator_desc rdesc;
+};
+
+/* LDO7 & LDO10 */
+static const unsigned int ldo7_voltages[] = {
+       1800000, 1850000, 2850000, 2900000,
+       3000000, 3100000, 3200000, 3300000,
+};
+
+static const unsigned int ldo19_voltages[] = {
+       1800000, 1850000, 1900000, 1750000,
+       2800000, 2850000, 2900000, 3000000,
+};
+
+static const unsigned int ldo22_voltages[] = {
+        900000, 1000000, 1050000, 1100000,
+       1150000, 1175000, 1185000, 1200000,
+};
+
+enum hi655x_regulator_id {
+       HI655X_LDO0,
+       HI655X_LDO1,
+       HI655X_LDO2,
+       HI655X_LDO3,
+       HI655X_LDO4,
+       HI655X_LDO5,
+       HI655X_LDO6,
+       HI655X_LDO7,
+       HI655X_LDO8,
+       HI655X_LDO9,
+       HI655X_LDO10,
+       HI655X_LDO11,
+       HI655X_LDO12,
+       HI655X_LDO13,
+       HI655X_LDO14,
+       HI655X_LDO15,
+       HI655X_LDO16,
+       HI655X_LDO17,
+       HI655X_LDO18,
+       HI655X_LDO19,
+       HI655X_LDO20,
+       HI655X_LDO21,
+       HI655X_LDO22,
+};
+
+static int hi655x_is_enabled(struct regulator_dev *rdev)
+{
+       unsigned int value = 0;
+
+       struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
+
+       regmap_read(rdev->regmap, regulator->status_reg, &value);
+       return (value & BIT(regulator->ctrl_mask));
+}
+
+static int hi655x_disable(struct regulator_dev *rdev)
+{
+       int ret = 0;
+
+       struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
+
+       ret = regmap_write(rdev->regmap, regulator->disable_reg,
+                          BIT(regulator->ctrl_mask));
+       return ret;
+}
+
+static struct regulator_ops hi655x_regulator_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = hi655x_disable,
+       .is_enabled = hi655x_is_enabled,
+       .list_voltage = regulator_list_voltage_table,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static struct regulator_ops hi655x_ldo_linear_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = hi655x_disable,
+       .is_enabled = hi655x_is_enabled,
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+#define HI655X_LDO(_ID, vreg, vmask, ereg, dreg,                 \
+                  sreg, cmask, vtable) {                        \
+       .rdesc = {                                               \
+               .name            = #_ID,                         \
+               .of_match        = of_match_ptr(#_ID),           \
+               .ops             = &hi655x_regulator_ops,        \
+               .regulators_node = of_match_ptr("regulators"),   \
+               .type            = REGULATOR_VOLTAGE,            \
+               .id              = HI655X_##_ID,                 \
+               .owner           = THIS_MODULE,                  \
+               .n_voltages      = ARRAY_SIZE(vtable),           \
+               .volt_table      = vtable,                       \
+               .vsel_reg        = HI655X_BUS_ADDR(vreg),        \
+               .vsel_mask       = vmask,                        \
+               .enable_reg      = HI655X_BUS_ADDR(ereg),        \
+               .enable_mask     = BIT(cmask),                   \
+       },                                                       \
+       .disable_reg = HI655X_BUS_ADDR(dreg),                    \
+       .status_reg = HI655X_BUS_ADDR(sreg),                     \
+       .ctrl_mask = cmask,                                      \
+}
+
+#define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg,          \
+                         sreg, cmask, minv, nvolt, vstep) {     \
+       .rdesc = {                                               \
+               .name            = #_ID,                         \
+               .of_match        = of_match_ptr(#_ID),           \
+               .ops             = &hi655x_ldo_linear_ops,       \
+               .regulators_node = of_match_ptr("regulators"),   \
+               .type            = REGULATOR_VOLTAGE,            \
+               .id              = HI655X_##_ID,                 \
+               .owner           = THIS_MODULE,                  \
+               .min_uV          = minv,                         \
+               .n_voltages      = nvolt,                        \
+               .uV_step         = vstep,                        \
+               .vsel_reg        = HI655X_BUS_ADDR(vreg),        \
+               .vsel_mask       = vmask,                        \
+               .enable_reg      = HI655X_BUS_ADDR(ereg),        \
+               .enable_mask     = BIT(cmask),                   \
+       },                                                       \
+       .disable_reg = HI655X_BUS_ADDR(dreg),                    \
+       .status_reg = HI655X_BUS_ADDR(sreg),                     \
+       .ctrl_mask = cmask,                                      \
+}
+
+static struct hi655x_regulator regulators[] = {
+       HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01,
+                         2500000, 8, 100000),
+       HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages),
+       HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages),
+       HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04,
+                         1600000, 8, 50000),
+       HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05,
+                         2500000, 8, 100000),
+       HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06,
+                         1600000, 8, 50000),
+       HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00,
+                         2500000, 8, 100000),
+       HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages),
+       HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04,
+                         1650000, 8, 50000),
+       HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages),
+};
+
+static int hi655x_regulator_probe(struct platform_device *pdev)
+{
+       unsigned int i;
+       struct hi655x_regulator *regulator;
+       struct hi655x_pmic *pmic;
+       struct regulator_config config = { };
+       struct regulator_dev *rdev;
+
+       pmic = dev_get_drvdata(pdev->dev.parent);
+       if (!pmic) {
+               dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
+               return -ENODEV;
+       }
+
+       regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL);
+       if (!regulator)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, regulator);
+
+       config.dev = pdev->dev.parent;
+       config.regmap = pmic->regmap;
+       config.driver_data = regulator;
+       for (i = 0; i < ARRAY_SIZE(regulators); i++) {
+               rdev = devm_regulator_register(&pdev->dev,
+                                              &regulators[i].rdesc,
+                                              &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "failed to register regulator %s\n",
+                               regulator->rdesc.name);
+                       return PTR_ERR(rdev);
+               }
+       }
+       return 0;
+}
+
+static struct platform_driver hi655x_regulator_driver = {
+       .driver = {
+               .name   = "hi655x-regulator",
+       },
+       .probe  = hi655x_regulator_probe,
+};
+module_platform_driver(hi655x_regulator_driver);
+
+MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
+MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver");
+MODULE_LICENSE("GPL v2");
index 19d75848655311c4afb7d343a5ce5b1242610627..38992112fd6e2c3838fc95ab49a261abc6eab5bf 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/regmap.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 #include <linux/regulator/lp872x.h>
 #include <linux/regulator/driver.h>
 #include <linux/platform_device.h>
@@ -738,10 +739,8 @@ static int lp872x_init_dvs(struct lp872x *lp)
                goto set_default_dvs_mode;
 
        gpio = dvs->gpio;
-       if (!gpio_is_valid(gpio)) {
-               dev_warn(lp->dev, "invalid gpio: %d\n", gpio);
+       if (!gpio_is_valid(gpio))
                goto set_default_dvs_mode;
-       }
 
        pinstate = dvs->init_state;
        ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS");
@@ -759,6 +758,33 @@ set_default_dvs_mode:
                                default_dvs_mode[lp->chipid]);
 }
 
+static int lp872x_hw_enable(struct lp872x *lp)
+{
+       int ret, gpio;
+
+       if (!lp->pdata)
+               return -EINVAL;
+
+       gpio = lp->pdata->enable_gpio;
+       if (!gpio_is_valid(gpio))
+               return 0;
+
+       /* Always set enable GPIO high. */
+       ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X EN");
+       if (ret) {
+               dev_err(lp->dev, "gpio request err: %d\n", ret);
+               return ret;
+       }
+
+       /* Each chip has a different enable delay. */
+       if (lp->chipid == LP8720)
+               usleep_range(LP8720_ENABLE_DELAY, 1.5 * LP8720_ENABLE_DELAY);
+       else
+               usleep_range(LP8725_ENABLE_DELAY, 1.5 * LP8725_ENABLE_DELAY);
+
+       return 0;
+}
+
 static int lp872x_config(struct lp872x *lp)
 {
        struct lp872x_platform_data *pdata = lp->pdata;
@@ -877,6 +903,8 @@ static struct lp872x_platform_data
        of_property_read_u8(np, "ti,dvs-state", &dvs_state);
        pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW;
 
+       pdata->enable_gpio = of_get_named_gpio(np, "enable-gpios", 0);
+
        if (of_get_child_count(np) == 0)
                goto out;
 
@@ -950,6 +978,10 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
        lp->chipid = id->driver_data;
        i2c_set_clientdata(cl, lp);
 
+       ret = lp872x_hw_enable(lp);
+       if (ret)
+               return ret;
+
        ret = lp872x_config(lp);
        if (ret)
                return ret;
index 972c386b269024180e512cab2c65da0e069817c6..47bef328fb58b356c061f2a7d408da9e8a971be7 100644 (file)
@@ -520,12 +520,15 @@ static int ltc3589_probe(struct i2c_client *client,
                }
        }
 
-       ret = devm_request_threaded_irq(dev, client->irq, NULL, ltc3589_isr,
-                                       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-                                       client->name, ltc3589);
-       if (ret) {
-               dev_err(dev, "Failed to request IRQ: %d\n", ret);
-               return ret;
+       if (client->irq) {
+               ret = devm_request_threaded_irq(dev, client->irq, NULL,
+                                               ltc3589_isr,
+                                               IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+                                               client->name, ltc3589);
+               if (ret) {
+                       dev_err(dev, "Failed to request IRQ: %d\n", ret);
+                       return ret;
+               }
        }
 
        return 0;
diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c
new file mode 100644 (file)
index 0000000..73a3356
--- /dev/null
@@ -0,0 +1,813 @@
+/*
+ * Maxim MAX77620 Regulator driver
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author: Mallikarjun Kasoju <mkasoju@nvidia.com>
+ *     Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/mfd/max77620.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#define max77620_rails(_name)  "max77620-"#_name
+
+/* Power Mode */
+#define MAX77620_POWER_MODE_NORMAL             3
+#define MAX77620_POWER_MODE_LPM                        2
+#define MAX77620_POWER_MODE_GLPM               1
+#define MAX77620_POWER_MODE_DISABLE            0
+
+/* SD Slew Rate */
+#define MAX77620_SD_SR_13_75                   0
+#define MAX77620_SD_SR_27_5                    1
+#define MAX77620_SD_SR_55                      2
+#define MAX77620_SD_SR_100                     3
+
+enum max77620_regulators {
+       MAX77620_REGULATOR_ID_SD0,
+       MAX77620_REGULATOR_ID_SD1,
+       MAX77620_REGULATOR_ID_SD2,
+       MAX77620_REGULATOR_ID_SD3,
+       MAX77620_REGULATOR_ID_SD4,
+       MAX77620_REGULATOR_ID_LDO0,
+       MAX77620_REGULATOR_ID_LDO1,
+       MAX77620_REGULATOR_ID_LDO2,
+       MAX77620_REGULATOR_ID_LDO3,
+       MAX77620_REGULATOR_ID_LDO4,
+       MAX77620_REGULATOR_ID_LDO5,
+       MAX77620_REGULATOR_ID_LDO6,
+       MAX77620_REGULATOR_ID_LDO7,
+       MAX77620_REGULATOR_ID_LDO8,
+       MAX77620_NUM_REGS,
+};
+
+/* Regulator types */
+enum max77620_regulator_type {
+       MAX77620_REGULATOR_TYPE_SD,
+       MAX77620_REGULATOR_TYPE_LDO_N,
+       MAX77620_REGULATOR_TYPE_LDO_P,
+};
+
+struct max77620_regulator_info {
+       u8 type;
+       u8 fps_addr;
+       u8 volt_addr;
+       u8 cfg_addr;
+       u8 power_mode_mask;
+       u8 power_mode_shift;
+       u8 remote_sense_addr;
+       u8 remote_sense_mask;
+       struct regulator_desc desc;
+};
+
+struct max77620_regulator_pdata {
+       struct regulator_init_data *reg_idata;
+       int active_fps_src;
+       int active_fps_pd_slot;
+       int active_fps_pu_slot;
+       int suspend_fps_src;
+       int suspend_fps_pd_slot;
+       int suspend_fps_pu_slot;
+       int current_mode;
+};
+
+struct max77620_regulator {
+       struct device *dev;
+       struct regmap *rmap;
+       struct max77620_regulator_info *rinfo[MAX77620_NUM_REGS];
+       struct max77620_regulator_pdata reg_pdata[MAX77620_NUM_REGS];
+       int enable_power_mode[MAX77620_NUM_REGS];
+       int current_power_mode[MAX77620_NUM_REGS];
+       int active_fps_src[MAX77620_NUM_REGS];
+};
+
+#define fps_src_name(fps_src)  \
+       (fps_src == MAX77620_FPS_SRC_0 ? "FPS_SRC_0" :  \
+       fps_src == MAX77620_FPS_SRC_1 ? "FPS_SRC_1" :   \
+       fps_src == MAX77620_FPS_SRC_2 ? "FPS_SRC_2" : "FPS_SRC_NONE")
+
+static int max77620_regulator_get_fps_src(struct max77620_regulator *pmic,
+                                         int id)
+{
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(pmic->rmap, rinfo->fps_addr, &val);
+       if (ret < 0) {
+               dev_err(pmic->dev, "Reg 0x%02x read failed %d\n",
+                       rinfo->fps_addr, ret);
+               return ret;
+       }
+
+       return (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
+}
+
+static int max77620_regulator_set_fps_src(struct max77620_regulator *pmic,
+                                         int fps_src, int id)
+{
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       unsigned int val;
+       int ret;
+
+       switch (fps_src) {
+       case MAX77620_FPS_SRC_0:
+       case MAX77620_FPS_SRC_1:
+       case MAX77620_FPS_SRC_2:
+       case MAX77620_FPS_SRC_NONE:
+               break;
+
+       case MAX77620_FPS_SRC_DEF:
+               ret = regmap_read(pmic->rmap, rinfo->fps_addr, &val);
+               if (ret < 0) {
+                       dev_err(pmic->dev, "Reg 0x%02x read failed %d\n",
+                               rinfo->fps_addr, ret);
+                       return ret;
+               }
+               ret = (val & MAX77620_FPS_SRC_MASK) >> MAX77620_FPS_SRC_SHIFT;
+               pmic->active_fps_src[id] = ret;
+               return 0;
+
+       default:
+               dev_err(pmic->dev, "Invalid FPS %d for regulator %d\n",
+                       fps_src, id);
+               return -EINVAL;
+       }
+
+       ret = regmap_update_bits(pmic->rmap, rinfo->fps_addr,
+                                MAX77620_FPS_SRC_MASK,
+                                fps_src << MAX77620_FPS_SRC_SHIFT);
+       if (ret < 0) {
+               dev_err(pmic->dev, "Reg 0x%02x update failed %d\n",
+                       rinfo->fps_addr, ret);
+               return ret;
+       }
+       pmic->active_fps_src[id] = fps_src;
+
+       return 0;
+}
+
+static int max77620_regulator_set_fps_slots(struct max77620_regulator *pmic,
+                                           int id, bool is_suspend)
+{
+       struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       unsigned int val = 0;
+       unsigned int mask = 0;
+       int pu = rpdata->active_fps_pu_slot;
+       int pd = rpdata->active_fps_pd_slot;
+       int ret = 0;
+
+       if (is_suspend) {
+               pu = rpdata->suspend_fps_pu_slot;
+               pd = rpdata->suspend_fps_pd_slot;
+       }
+
+       /* FPS power up period setting */
+       if (pu >= 0) {
+               val |= (pu << MAX77620_FPS_PU_PERIOD_SHIFT);
+               mask |= MAX77620_FPS_PU_PERIOD_MASK;
+       }
+
+       /* FPS power down period setting */
+       if (pd >= 0) {
+               val |= (pd << MAX77620_FPS_PD_PERIOD_SHIFT);
+               mask |= MAX77620_FPS_PD_PERIOD_MASK;
+       }
+
+       if (mask) {
+               ret = regmap_update_bits(pmic->rmap, rinfo->fps_addr,
+                                        mask, val);
+               if (ret < 0) {
+                       dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
+                               rinfo->fps_addr, ret);
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static int max77620_regulator_set_power_mode(struct max77620_regulator *pmic,
+                                            int power_mode, int id)
+{
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       u8 mask = rinfo->power_mode_mask;
+       u8 shift = rinfo->power_mode_shift;
+       u8 addr;
+       int ret;
+
+       switch (rinfo->type) {
+       case MAX77620_REGULATOR_TYPE_SD:
+               addr = rinfo->cfg_addr;
+               break;
+       default:
+               addr = rinfo->volt_addr;
+               break;
+       }
+
+       ret = regmap_update_bits(pmic->rmap, addr, mask, power_mode << shift);
+       if (ret < 0) {
+               dev_err(pmic->dev, "Regulator %d mode set failed: %d\n",
+                       id, ret);
+               return ret;
+       }
+       pmic->current_power_mode[id] = power_mode;
+
+       return ret;
+}
+
+static int max77620_regulator_get_power_mode(struct max77620_regulator *pmic,
+                                            int id)
+{
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       unsigned int val, addr;
+       u8 mask = rinfo->power_mode_mask;
+       u8 shift = rinfo->power_mode_shift;
+       int ret;
+
+       switch (rinfo->type) {
+       case MAX77620_REGULATOR_TYPE_SD:
+               addr = rinfo->cfg_addr;
+               break;
+       default:
+               addr = rinfo->volt_addr;
+               break;
+       }
+
+       ret = regmap_read(pmic->rmap, addr, &val);
+       if (ret < 0) {
+               dev_err(pmic->dev, "Regulator %d: Reg 0x%02x read failed: %d\n",
+                       id, addr, ret);
+               return ret;
+       }
+
+       return (val & mask) >> shift;
+}
+
+static int max77620_read_slew_rate(struct max77620_regulator *pmic, int id)
+{
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       unsigned int rval;
+       int slew_rate;
+       int ret;
+
+       ret = regmap_read(pmic->rmap, rinfo->cfg_addr, &rval);
+       if (ret < 0) {
+               dev_err(pmic->dev, "Register 0x%02x read failed: %d\n",
+                       rinfo->cfg_addr, ret);
+               return ret;
+       }
+
+       switch (rinfo->type) {
+       case MAX77620_REGULATOR_TYPE_SD:
+               slew_rate = (rval >> MAX77620_SD_SR_SHIFT) & 0x3;
+               switch (slew_rate) {
+               case 0:
+                       slew_rate = 13750;
+                       break;
+               case 1:
+                       slew_rate = 27500;
+                       break;
+               case 2:
+                       slew_rate = 55000;
+                       break;
+               case 3:
+                       slew_rate = 100000;
+                       break;
+               }
+               rinfo->desc.ramp_delay = slew_rate;
+               break;
+       default:
+               slew_rate = rval & 0x1;
+               switch (slew_rate) {
+               case 0:
+                       slew_rate = 100000;
+                       break;
+               case 1:
+                       slew_rate = 5000;
+                       break;
+               }
+               rinfo->desc.ramp_delay = slew_rate;
+               break;
+       }
+
+       return 0;
+}
+
+static int max77620_init_pmic(struct max77620_regulator *pmic, int id)
+{
+       struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
+       int ret;
+
+       /* Update power mode */
+       ret = max77620_regulator_get_power_mode(pmic, id);
+       if (ret < 0)
+               return ret;
+
+       pmic->current_power_mode[id] = ret;
+       pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
+
+       if (rpdata->active_fps_src == MAX77620_FPS_SRC_DEF) {
+               ret = max77620_regulator_get_fps_src(pmic, id);
+               if (ret < 0)
+                       return ret;
+               rpdata->active_fps_src = ret;
+       }
+
+        /* If rails are externally control of FPS then enable it always. */
+       if (rpdata->active_fps_src == MAX77620_FPS_SRC_NONE) {
+               ret = max77620_regulator_set_power_mode(pmic,
+                                       pmic->enable_power_mode[id], id);
+               if (ret < 0)
+                       return ret;
+       } else {
+               if (pmic->current_power_mode[id] !=
+                    pmic->enable_power_mode[id]) {
+                       ret = max77620_regulator_set_power_mode(pmic,
+                                       pmic->enable_power_mode[id], id);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
+       ret = max77620_regulator_set_fps_src(pmic, rpdata->active_fps_src, id);
+       if (ret < 0)
+               return ret;
+
+       ret = max77620_regulator_set_fps_slots(pmic, id, false);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int max77620_regulator_enable(struct regulator_dev *rdev)
+{
+       struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+
+       if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
+               return 0;
+
+       return max77620_regulator_set_power_mode(pmic,
+                       pmic->enable_power_mode[id], id);
+}
+
+static int max77620_regulator_disable(struct regulator_dev *rdev)
+{
+       struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+
+       if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
+               return 0;
+
+       return max77620_regulator_set_power_mode(pmic,
+                       MAX77620_POWER_MODE_DISABLE, id);
+}
+
+static int max77620_regulator_is_enabled(struct regulator_dev *rdev)
+{
+       struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       int ret = 1;
+
+       if (pmic->active_fps_src[id] != MAX77620_FPS_SRC_NONE)
+               return 1;
+
+       ret = max77620_regulator_get_power_mode(pmic, id);
+       if (ret < 0)
+               return ret;
+
+       if (ret != MAX77620_POWER_MODE_DISABLE)
+               return 1;
+
+       return 0;
+}
+
+static int max77620_regulator_set_mode(struct regulator_dev *rdev,
+                                      unsigned int mode)
+{
+       struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id];
+       bool fpwm = false;
+       int power_mode;
+       int ret;
+       u8 val;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               fpwm = true;
+               power_mode = MAX77620_POWER_MODE_NORMAL;
+               break;
+
+       case REGULATOR_MODE_NORMAL:
+               power_mode = MAX77620_POWER_MODE_NORMAL;
+               break;
+
+       case REGULATOR_MODE_IDLE:
+               power_mode = MAX77620_POWER_MODE_LPM;
+               break;
+
+       default:
+               dev_err(pmic->dev, "Regulator %d mode %d is invalid\n",
+                       id, mode);
+               return -EINVAL;
+       }
+
+       if (rinfo->type != MAX77620_REGULATOR_TYPE_SD)
+               goto skip_fpwm;
+
+       val = (fpwm) ? MAX77620_SD_FPWM_MASK : 0;
+       ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr,
+                                MAX77620_SD_FPWM_MASK, val);
+       if (ret < 0) {
+               dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
+                       rinfo->cfg_addr, ret);
+               return ret;
+       }
+       rpdata->current_mode = mode;
+
+skip_fpwm:
+       ret = max77620_regulator_set_power_mode(pmic, power_mode, id);
+       if (ret < 0)
+               return ret;
+
+       pmic->enable_power_mode[id] = power_mode;
+
+       return 0;
+}
+
+static unsigned int max77620_regulator_get_mode(struct regulator_dev *rdev)
+{
+       struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       int fpwm = 0;
+       int ret;
+       int pm_mode, reg_mode;
+       unsigned int val;
+
+       ret = max77620_regulator_get_power_mode(pmic, id);
+       if (ret < 0)
+               return 0;
+
+       pm_mode = ret;
+
+       if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) {
+               ret = regmap_read(pmic->rmap, rinfo->cfg_addr, &val);
+               if (ret < 0) {
+                       dev_err(pmic->dev, "Reg 0x%02x read failed: %d\n",
+                               rinfo->cfg_addr, ret);
+                       return ret;
+               }
+               fpwm = !!(val & MAX77620_SD_FPWM_MASK);
+       }
+
+       switch (pm_mode) {
+       case MAX77620_POWER_MODE_NORMAL:
+       case MAX77620_POWER_MODE_DISABLE:
+               if (fpwm)
+                       reg_mode = REGULATOR_MODE_FAST;
+               else
+                       reg_mode = REGULATOR_MODE_NORMAL;
+               break;
+       case MAX77620_POWER_MODE_LPM:
+       case MAX77620_POWER_MODE_GLPM:
+               reg_mode = REGULATOR_MODE_IDLE;
+               break;
+       default:
+               return 0;
+       }
+
+       return reg_mode;
+}
+
+static int max77620_regulator_set_ramp_delay(struct regulator_dev *rdev,
+                                            int ramp_delay)
+{
+       struct max77620_regulator *pmic = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       struct max77620_regulator_info *rinfo = pmic->rinfo[id];
+       int ret, val;
+       u8 mask;
+
+       if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) {
+               if (ramp_delay <= 13750)
+                       val = 0;
+               else if (ramp_delay <= 27500)
+                       val = 1;
+               else if (ramp_delay <= 55000)
+                       val = 2;
+               else
+                       val = 3;
+               val <<= MAX77620_SD_SR_SHIFT;
+               mask = MAX77620_SD_SR_MASK;
+       } else {
+               if (ramp_delay <= 5000)
+                       val = 1;
+               else
+                       val = 0;
+               mask = MAX77620_LDO_SLEW_RATE_MASK;
+       }
+
+       ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr, mask, val);
+       if (ret < 0)
+               dev_err(pmic->dev, "Reg 0x%02x update failed: %d\n",
+                       rinfo->cfg_addr, ret);
+
+       return ret;
+}
+
+static int max77620_of_parse_cb(struct device_node *np,
+                               const struct regulator_desc *desc,
+                               struct regulator_config *config)
+{
+       struct max77620_regulator *pmic = config->driver_data;
+       struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[desc->id];
+       u32 pval;
+       int ret;
+
+       ret = of_property_read_u32(np, "maxim,active-fps-source", &pval);
+       rpdata->active_fps_src = (!ret) ? pval : MAX77620_FPS_SRC_DEF;
+
+       ret = of_property_read_u32(np, "maxim,active-fps-power-up-slot", &pval);
+       rpdata->active_fps_pu_slot = (!ret) ? pval : -1;
+
+       ret = of_property_read_u32(
+                       np, "maxim,active-fps-power-down-slot", &pval);
+       rpdata->active_fps_pd_slot = (!ret) ? pval : -1;
+
+       ret = of_property_read_u32(np, "maxim,suspend-fps-source", &pval);
+       rpdata->suspend_fps_src = (!ret) ? pval : -1;
+
+       ret = of_property_read_u32(
+                       np, "maxim,suspend-fps-power-up-slot", &pval);
+       rpdata->suspend_fps_pu_slot = (!ret) ? pval : -1;
+
+       ret = of_property_read_u32(
+                       np, "maxim,suspend-fps-power-down-slot", &pval);
+       rpdata->suspend_fps_pd_slot = (!ret) ? pval : -1;
+
+       return max77620_init_pmic(pmic, desc->id);
+}
+
+static struct regulator_ops max77620_regulator_ops = {
+       .is_enabled = max77620_regulator_is_enabled,
+       .enable = max77620_regulator_enable,
+       .disable = max77620_regulator_disable,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .set_mode = max77620_regulator_set_mode,
+       .get_mode = max77620_regulator_get_mode,
+       .set_ramp_delay = max77620_regulator_set_ramp_delay,
+       .set_voltage_time_sel = regulator_set_voltage_time_sel,
+       .set_active_discharge = regulator_set_active_discharge_regmap,
+};
+
+#define MAX77620_SD_CNF2_ROVS_EN_NONE  0
+#define RAIL_SD(_id, _name, _sname, _volt_mask, _min_uV, _max_uV,      \
+               _step_uV, _rs_add, _rs_mask)                            \
+       [MAX77620_REGULATOR_ID_##_id] = {                               \
+               .type = MAX77620_REGULATOR_TYPE_SD,                     \
+               .volt_addr = MAX77620_REG_##_id,                        \
+               .cfg_addr = MAX77620_REG_##_id##_CFG,                   \
+               .fps_addr = MAX77620_REG_FPS_##_id,                     \
+               .remote_sense_addr = _rs_add,                           \
+               .remote_sense_mask = MAX77620_SD_CNF2_ROVS_EN_##_rs_mask, \
+               .power_mode_mask = MAX77620_SD_POWER_MODE_MASK,         \
+               .power_mode_shift = MAX77620_SD_POWER_MODE_SHIFT,       \
+               .desc = {                                               \
+                       .name = max77620_rails(_name),                  \
+                       .of_match = of_match_ptr(#_name),               \
+                       .regulators_node = of_match_ptr("regulators"),  \
+                       .of_parse_cb = max77620_of_parse_cb,            \
+                       .supply_name = _sname,                          \
+                       .id = MAX77620_REGULATOR_ID_##_id,              \
+                       .ops = &max77620_regulator_ops,                 \
+                       .n_voltages = ((_max_uV - _min_uV) / _step_uV) + 1, \
+                       .min_uV = _min_uV,                              \
+                       .uV_step = _step_uV,                            \
+                       .enable_time = 500,                             \
+                       .vsel_mask = MAX77620_##_volt_mask##_VOLT_MASK, \
+                       .vsel_reg = MAX77620_REG_##_id,                 \
+                       .active_discharge_off = 0,                      \
+                       .active_discharge_on = MAX77620_SD_CFG1_ADE_ENABLE, \
+                       .active_discharge_mask = MAX77620_SD_CFG1_ADE_MASK, \
+                       .active_discharge_reg = MAX77620_REG_##_id##_CFG, \
+                       .type = REGULATOR_VOLTAGE,                      \
+               },                                                      \
+       }
+
+#define RAIL_LDO(_id, _name, _sname, _type, _min_uV, _max_uV, _step_uV) \
+       [MAX77620_REGULATOR_ID_##_id] = {                               \
+               .type = MAX77620_REGULATOR_TYPE_LDO_##_type,            \
+               .volt_addr = MAX77620_REG_##_id##_CFG,                  \
+               .cfg_addr = MAX77620_REG_##_id##_CFG2,                  \
+               .fps_addr = MAX77620_REG_FPS_##_id,                     \
+               .remote_sense_addr = 0xFF,                              \
+               .power_mode_mask = MAX77620_LDO_POWER_MODE_MASK,        \
+               .power_mode_shift = MAX77620_LDO_POWER_MODE_SHIFT,      \
+               .desc = {                                               \
+                       .name = max77620_rails(_name),                  \
+                       .of_match = of_match_ptr(#_name),               \
+                       .regulators_node = of_match_ptr("regulators"),  \
+                       .of_parse_cb = max77620_of_parse_cb,            \
+                       .supply_name = _sname,                          \
+                       .id = MAX77620_REGULATOR_ID_##_id,              \
+                       .ops = &max77620_regulator_ops,                 \
+                       .n_voltages = ((_max_uV - _min_uV) / _step_uV) + 1, \
+                       .min_uV = _min_uV,                              \
+                       .uV_step = _step_uV,                            \
+                       .enable_time = 500,                             \
+                       .vsel_mask = MAX77620_LDO_VOLT_MASK,            \
+                       .vsel_reg = MAX77620_REG_##_id##_CFG,           \
+                       .active_discharge_off = 0,                      \
+                       .active_discharge_on = MAX77620_LDO_CFG2_ADE_ENABLE, \
+                       .active_discharge_mask = MAX77620_LDO_CFG2_ADE_MASK, \
+                       .active_discharge_reg = MAX77620_REG_##_id##_CFG2, \
+                       .type = REGULATOR_VOLTAGE,                      \
+               },                                                      \
+       }
+
+static struct max77620_regulator_info max77620_regs_info[MAX77620_NUM_REGS] = {
+       RAIL_SD(SD0, sd0, "in-sd0", SD0, 600000, 1400000, 12500, 0x22, SD0),
+       RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 1550000, 12500, 0x22, SD1),
+       RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+       RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+       RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+
+       RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
+       RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
+       RAIL_LDO(LDO2, ldo2, "in-ldo2",   P, 800000, 3950000, 50000),
+       RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
+       RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
+       RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
+       RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
+       RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
+       RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
+};
+
+static struct max77620_regulator_info max20024_regs_info[MAX77620_NUM_REGS] = {
+       RAIL_SD(SD0, sd0, "in-sd0", SD0, 800000, 1587500, 12500, 0x22, SD0),
+       RAIL_SD(SD1, sd1, "in-sd1", SD1, 600000, 3387500, 12500, 0x22, SD1),
+       RAIL_SD(SD2, sd2, "in-sd2", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+       RAIL_SD(SD3, sd3, "in-sd3", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+       RAIL_SD(SD4, sd4, "in-sd4", SDX, 600000, 3787500, 12500, 0xFF, NONE),
+
+       RAIL_LDO(LDO0, ldo0, "in-ldo0-1", N, 800000, 2375000, 25000),
+       RAIL_LDO(LDO1, ldo1, "in-ldo0-1", N, 800000, 2375000, 25000),
+       RAIL_LDO(LDO2, ldo2, "in-ldo2",   P, 800000, 3950000, 50000),
+       RAIL_LDO(LDO3, ldo3, "in-ldo3-5", P, 800000, 3950000, 50000),
+       RAIL_LDO(LDO4, ldo4, "in-ldo4-6", P, 800000, 1587500, 12500),
+       RAIL_LDO(LDO5, ldo5, "in-ldo3-5", P, 800000, 3950000, 50000),
+       RAIL_LDO(LDO6, ldo6, "in-ldo4-6", P, 800000, 3950000, 50000),
+       RAIL_LDO(LDO7, ldo7, "in-ldo7-8", N, 800000, 3950000, 50000),
+       RAIL_LDO(LDO8, ldo8, "in-ldo7-8", N, 800000, 3950000, 50000),
+};
+
+static int max77620_regulator_probe(struct platform_device *pdev)
+{
+       struct max77620_chip *max77620_chip = dev_get_drvdata(pdev->dev.parent);
+       struct max77620_regulator_info *rinfo;
+       struct device *dev = &pdev->dev;
+       struct regulator_config config = { };
+       struct max77620_regulator *pmic;
+       int ret = 0;
+       int id;
+
+       pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+       if (!pmic)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, pmic);
+       pmic->dev = dev;
+       pmic->rmap = max77620_chip->rmap;
+       if (!dev->of_node)
+               dev->of_node = pdev->dev.parent->of_node;
+
+       switch (max77620_chip->chip_id) {
+       case MAX77620:
+               rinfo = max77620_regs_info;
+               break;
+       default:
+               rinfo = max20024_regs_info;
+               break;
+       }
+
+       config.regmap = pmic->rmap;
+       config.dev = dev;
+       config.driver_data = pmic;
+
+       for (id = 0; id < MAX77620_NUM_REGS; id++) {
+               struct regulator_dev *rdev;
+               struct regulator_desc *rdesc;
+
+               if ((max77620_chip->chip_id == MAX77620) &&
+                   (id == MAX77620_REGULATOR_ID_SD4))
+                       continue;
+
+               rdesc = &rinfo[id].desc;
+               pmic->rinfo[id] = &max77620_regs_info[id];
+               pmic->enable_power_mode[id] = MAX77620_POWER_MODE_NORMAL;
+
+               ret = max77620_read_slew_rate(pmic, id);
+               if (ret < 0)
+                       return ret;
+
+               rdev = devm_regulator_register(dev, rdesc, &config);
+               if (IS_ERR(rdev)) {
+                       ret = PTR_ERR(rdev);
+                       dev_err(dev, "Regulator registration %s failed: %d\n",
+                               rdesc->name, ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int max77620_regulator_suspend(struct device *dev)
+{
+       struct max77620_regulator *pmic = dev_get_drvdata(dev);
+       struct max77620_regulator_pdata *reg_pdata;
+       int id;
+
+       for (id = 0; id < MAX77620_NUM_REGS; id++) {
+               reg_pdata = &pmic->reg_pdata[id];
+
+               max77620_regulator_set_fps_slots(pmic, id, true);
+               if (reg_pdata->suspend_fps_src < 0)
+                       continue;
+
+               max77620_regulator_set_fps_src(pmic, reg_pdata->suspend_fps_src,
+                                              id);
+       }
+
+       return 0;
+}
+
+static int max77620_regulator_resume(struct device *dev)
+{
+       struct max77620_regulator *pmic = dev_get_drvdata(dev);
+       struct max77620_regulator_pdata *reg_pdata;
+       int id;
+
+       for (id = 0; id < MAX77620_NUM_REGS; id++) {
+               reg_pdata = &pmic->reg_pdata[id];
+
+               max77620_regulator_set_fps_slots(pmic, id, false);
+               if (reg_pdata->active_fps_src < 0)
+                       continue;
+               max77620_regulator_set_fps_src(pmic, reg_pdata->active_fps_src,
+                                              id);
+       }
+
+       return 0;
+}
+#endif
+
+static const struct dev_pm_ops max77620_regulator_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(max77620_regulator_suspend,
+                               max77620_regulator_resume)
+};
+
+static const struct platform_device_id max77620_regulator_devtype[] = {
+       { .name = "max77620-pmic", },
+       { .name = "max20024-pmic", },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, max77620_regulator_devtype);
+
+static struct platform_driver max77620_regulator_driver = {
+       .probe = max77620_regulator_probe,
+       .id_table = max77620_regulator_devtype,
+       .driver = {
+               .name = "max77620-pmic",
+               .pm = &max77620_regulator_pm_ops,
+       },
+};
+
+module_platform_driver(max77620_regulator_driver);
+
+MODULE_DESCRIPTION("MAX77620/MAX20024 regulator driver");
+MODULE_AUTHOR("Mallikarjun Kasoju <mkasoju@nvidia.com>");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/max77686-regulator.c b/drivers/regulator/max77686-regulator.c
new file mode 100644 (file)
index 0000000..17ccf36
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+ * max77686.c - Regulator driver for the Maxim 77686
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Chiwoong Byun <woong.byun@samsung.com>
+ * Jonghwa Lee <jonghwa3.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * This driver is based on max8997.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/max77686.h>
+#include <linux/mfd/max77686-private.h>
+
+#define MAX77686_LDO_MINUV     800000
+#define MAX77686_LDO_UVSTEP    50000
+#define MAX77686_LDO_LOW_MINUV 800000
+#define MAX77686_LDO_LOW_UVSTEP        25000
+#define MAX77686_BUCK_MINUV    750000
+#define MAX77686_BUCK_UVSTEP   50000
+#define MAX77686_RAMP_DELAY    100000                  /* uV/us */
+#define MAX77686_DVS_RAMP_DELAY        27500                   /* uV/us */
+#define MAX77686_DVS_MINUV     600000
+#define MAX77686_DVS_UVSTEP    12500
+
+/*
+ * Value for configuring buck[89] and LDO{20,21,22} as GPIO control.
+ * It is the same as 'off' for other regulators.
+ */
+#define MAX77686_GPIO_CONTROL          0x0
+/*
+ * Values used for configuring LDOs and bucks.
+ * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26
+ */
+#define MAX77686_LDO_LOWPOWER          0x1
+/*
+ * On/off controlled by PWRREQ:
+ *  - LDO2, 6-8, 10-12, 14-16
+ *  - buck[1234]
+ */
+#define MAX77686_OFF_PWRREQ            0x1
+/* Low power mode controlled by PWRREQ: All LDOs */
+#define MAX77686_LDO_LOWPOWER_PWRREQ   0x2
+/* Forcing low power mode: buck[234] */
+#define MAX77686_BUCK_LOWPOWER         0x2
+#define MAX77686_NORMAL                        0x3
+
+#define MAX77686_OPMODE_SHIFT  6
+#define MAX77686_OPMODE_BUCK234_SHIFT  4
+#define MAX77686_OPMODE_MASK   0x3
+
+#define MAX77686_VSEL_MASK     0x3F
+#define MAX77686_DVS_VSEL_MASK 0xFF
+
+#define MAX77686_RAMP_RATE_MASK        0xC0
+
+#define MAX77686_REGULATORS    MAX77686_REG_MAX
+#define MAX77686_LDOS          26
+
+enum max77686_ramp_rate {
+       RAMP_RATE_13P75MV,
+       RAMP_RATE_27P5MV,
+       RAMP_RATE_55MV,
+       RAMP_RATE_NO_CTRL,      /* 100mV/us */
+};
+
+struct max77686_data {
+       DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS);
+
+       /* Array indexed by regulator id */
+       unsigned int opmode[MAX77686_REGULATORS];
+};
+
+static unsigned int max77686_get_opmode_shift(int id)
+{
+       switch (id) {
+       case MAX77686_BUCK1:
+       case MAX77686_BUCK5 ... MAX77686_BUCK9:
+               return 0;
+       case MAX77686_BUCK2 ... MAX77686_BUCK4:
+               return MAX77686_OPMODE_BUCK234_SHIFT;
+       default:
+               /* all LDOs */
+               return MAX77686_OPMODE_SHIFT;
+       }
+}
+
+/*
+ * When regulator is configured for GPIO control then it
+ * replaces "normal" mode. Any change from low power mode to normal
+ * should actually change to GPIO control.
+ * Map normal mode to proper value for such regulators.
+ */
+static unsigned int max77686_map_normal_mode(struct max77686_data *max77686,
+                                            int id)
+{
+       switch (id) {
+       case MAX77686_BUCK8:
+       case MAX77686_BUCK9:
+       case MAX77686_LDO20 ... MAX77686_LDO22:
+               if (test_bit(id, max77686->gpio_enabled))
+                       return MAX77686_GPIO_CONTROL;
+       }
+
+       return MAX77686_NORMAL;
+}
+
+/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */
+static int max77686_set_suspend_disable(struct regulator_dev *rdev)
+{
+       unsigned int val, shift;
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+       int ret, id = rdev_get_id(rdev);
+
+       shift = max77686_get_opmode_shift(id);
+       val = MAX77686_OFF_PWRREQ;
+
+       ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                rdev->desc->enable_mask, val << shift);
+       if (ret)
+               return ret;
+
+       max77686->opmode[id] = val;
+       return 0;
+}
+
+/* Some LDOs supports [LPM/Normal]ON mode during suspend state */
+static int max77686_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+       unsigned int val;
+       int ret, id = rdev_get_id(rdev);
+
+       /* BUCK[5-9] doesn't support this feature */
+       if (id >= MAX77686_BUCK5)
+               return 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
+               val = MAX77686_LDO_LOWPOWER_PWRREQ;
+               break;
+       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
+               val = max77686_map_normal_mode(max77686, id);
+               break;
+       default:
+               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+                       rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val << MAX77686_OPMODE_SHIFT);
+       if (ret)
+               return ret;
+
+       max77686->opmode[id] = val;
+       return 0;
+}
+
+/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
+static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       unsigned int val;
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+       int ret, id = rdev_get_id(rdev);
+
+       switch (mode) {
+       case REGULATOR_MODE_STANDBY:                    /* switch off */
+               val = MAX77686_OFF_PWRREQ;
+               break;
+       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
+               val = MAX77686_LDO_LOWPOWER_PWRREQ;
+               break;
+       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
+               val = max77686_map_normal_mode(max77686, id);
+               break;
+       default:
+               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+                       rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                rdev->desc->enable_mask,
+                                val << MAX77686_OPMODE_SHIFT);
+       if (ret)
+               return ret;
+
+       max77686->opmode[id] = val;
+       return 0;
+}
+
+static int max77686_enable(struct regulator_dev *rdev)
+{
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+       unsigned int shift;
+       int id = rdev_get_id(rdev);
+
+       shift = max77686_get_opmode_shift(id);
+
+       if (max77686->opmode[id] == MAX77686_OFF_PWRREQ)
+               max77686->opmode[id] = max77686_map_normal_mode(max77686, id);
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 max77686->opmode[id] << shift);
+}
+
+static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+       unsigned int ramp_value = RAMP_RATE_NO_CTRL;
+
+       switch (ramp_delay) {
+       case 1 ... 13750:
+               ramp_value = RAMP_RATE_13P75MV;
+               break;
+       case 13751 ... 27500:
+               ramp_value = RAMP_RATE_27P5MV;
+               break;
+       case 27501 ... 55000:
+               ramp_value = RAMP_RATE_55MV;
+               break;
+       case 55001 ... 100000:
+               break;
+       default:
+               pr_warn("%s: ramp_delay: %d not supported, setting 100000\n",
+                       rdev->desc->name, ramp_delay);
+       }
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 MAX77686_RAMP_RATE_MASK, ramp_value << 6);
+}
+
+static int max77686_of_parse_cb(struct device_node *np,
+               const struct regulator_desc *desc,
+               struct regulator_config *config)
+{
+       struct max77686_data *max77686 = config->driver_data;
+
+       switch (desc->id) {
+       case MAX77686_BUCK8:
+       case MAX77686_BUCK9:
+       case MAX77686_LDO20 ... MAX77686_LDO22:
+               config->ena_gpio = of_get_named_gpio(np,
+                                       "maxim,ena-gpios", 0);
+               config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+               config->ena_gpio_initialized = true;
+               break;
+       default:
+               return 0;
+       }
+
+       if (gpio_is_valid(config->ena_gpio)) {
+               set_bit(desc->id, max77686->gpio_enabled);
+
+               return regmap_update_bits(config->regmap, desc->enable_reg,
+                                         desc->enable_mask,
+                                         MAX77686_GPIO_CONTROL);
+       }
+
+       return 0;
+}
+
+static struct regulator_ops max77686_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_mode       = max77686_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_ldo_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_mode       = max77686_ldo_set_suspend_mode,
+       .set_suspend_disable    = max77686_set_suspend_disable,
+};
+
+static struct regulator_ops max77686_buck1_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_disable    = max77686_set_suspend_disable,
+};
+
+static struct regulator_ops max77686_buck_dvs_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = max77686_set_ramp_delay,
+       .set_suspend_disable    = max77686_set_suspend_disable,
+};
+
+#define regulator_desc_ldo(num)                {                               \
+       .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
+       .of_parse_cb    = max77686_of_parse_cb,                         \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_MINUV,                           \
+       .uV_step        = MAX77686_LDO_UVSTEP,                          \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_lpm_ldo(num)    {                               \
+       .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ldo_ops,                            \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_MINUV,                           \
+       .uV_step        = MAX77686_LDO_UVSTEP,                          \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_ldo_low(num)            {                       \
+       .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ldo_ops,                            \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
+       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_ldo1_low(num)           {                       \
+       .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
+       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_buck(num)               {                       \
+       .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
+       .of_parse_cb    = max77686_of_parse_cb,                         \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_BUCK_MINUV,                          \
+       .uV_step        = MAX77686_BUCK_UVSTEP,                         \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_BUCK5OUT + (num - 5) * 2,        \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_BUCK5CTRL + (num - 5) * 2,       \
+       .enable_mask    = MAX77686_OPMODE_MASK,                         \
+}
+#define regulator_desc_buck1(num)              {                       \
+       .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_buck1_ops,                          \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_BUCK_MINUV,                          \
+       .uV_step        = MAX77686_BUCK_UVSTEP,                         \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_BUCK1OUT,                        \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_BUCK1CTRL,                       \
+       .enable_mask    = MAX77686_OPMODE_MASK,                         \
+}
+#define regulator_desc_buck_dvs(num)           {                       \
+       .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("voltage-regulators"),   \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_buck_dvs_ops,                       \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_DVS_MINUV,                           \
+       .uV_step        = MAX77686_DVS_UVSTEP,                          \
+       .ramp_delay     = MAX77686_DVS_RAMP_DELAY,                      \
+       .n_voltages     = MAX77686_DVS_VSEL_MASK + 1,                   \
+       .vsel_reg       = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10,      \
+       .vsel_mask      = MAX77686_DVS_VSEL_MASK,                       \
+       .enable_reg     = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10,     \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_BUCK234_SHIFT,               \
+}
+
+static const struct regulator_desc regulators[] = {
+       regulator_desc_ldo1_low(1),
+       regulator_desc_ldo_low(2),
+       regulator_desc_ldo(3),
+       regulator_desc_ldo(4),
+       regulator_desc_ldo(5),
+       regulator_desc_ldo_low(6),
+       regulator_desc_ldo_low(7),
+       regulator_desc_ldo_low(8),
+       regulator_desc_ldo(9),
+       regulator_desc_lpm_ldo(10),
+       regulator_desc_lpm_ldo(11),
+       regulator_desc_lpm_ldo(12),
+       regulator_desc_ldo(13),
+       regulator_desc_lpm_ldo(14),
+       regulator_desc_ldo_low(15),
+       regulator_desc_lpm_ldo(16),
+       regulator_desc_ldo(17),
+       regulator_desc_ldo(18),
+       regulator_desc_ldo(19),
+       regulator_desc_ldo(20),
+       regulator_desc_ldo(21),
+       regulator_desc_ldo(22),
+       regulator_desc_ldo(23),
+       regulator_desc_ldo(24),
+       regulator_desc_ldo(25),
+       regulator_desc_ldo(26),
+       regulator_desc_buck1(1),
+       regulator_desc_buck_dvs(2),
+       regulator_desc_buck_dvs(3),
+       regulator_desc_buck_dvs(4),
+       regulator_desc_buck(5),
+       regulator_desc_buck(6),
+       regulator_desc_buck(7),
+       regulator_desc_buck(8),
+       regulator_desc_buck(9),
+};
+
+static int max77686_pmic_probe(struct platform_device *pdev)
+{
+       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct max77686_data *max77686;
+       int i;
+       struct regulator_config config = { };
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
+                               GFP_KERNEL);
+       if (!max77686)
+               return -ENOMEM;
+
+       config.dev = iodev->dev;
+       config.regmap = iodev->regmap;
+       config.driver_data = max77686;
+       platform_set_drvdata(pdev, max77686);
+
+       for (i = 0; i < MAX77686_REGULATORS; i++) {
+               struct regulator_dev *rdev;
+               int id = regulators[i].id;
+
+               max77686->opmode[id] = MAX77686_NORMAL;
+               rdev = devm_regulator_register(&pdev->dev,
+                                               &regulators[i], &config);
+               if (IS_ERR(rdev)) {
+                       int ret = PTR_ERR(rdev);
+                       dev_err(&pdev->dev,
+                               "regulator init failed for %d: %d\n", i, ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct platform_device_id max77686_pmic_id[] = {
+       {"max77686-pmic", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(platform, max77686_pmic_id);
+
+static struct platform_driver max77686_pmic_driver = {
+       .driver = {
+               .name = "max77686-pmic",
+       },
+       .probe = max77686_pmic_probe,
+       .id_table = max77686_pmic_id,
+};
+
+static int __init max77686_pmic_init(void)
+{
+       return platform_driver_register(&max77686_pmic_driver);
+}
+subsys_initcall(max77686_pmic_init);
+
+static void __exit max77686_pmic_cleanup(void)
+{
+       platform_driver_unregister(&max77686_pmic_driver);
+}
+module_exit(max77686_pmic_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");
+MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
deleted file mode 100644 (file)
index 17ccf36..0000000
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * max77686.c - Regulator driver for the Maxim 77686
- *
- * Copyright (C) 2012 Samsung Electronics
- * Chiwoong Byun <woong.byun@samsung.com>
- * Jonghwa Lee <jonghwa3.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * This driver is based on max8997.c
- */
-
-#include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/mfd/max77686.h>
-#include <linux/mfd/max77686-private.h>
-
-#define MAX77686_LDO_MINUV     800000
-#define MAX77686_LDO_UVSTEP    50000
-#define MAX77686_LDO_LOW_MINUV 800000
-#define MAX77686_LDO_LOW_UVSTEP        25000
-#define MAX77686_BUCK_MINUV    750000
-#define MAX77686_BUCK_UVSTEP   50000
-#define MAX77686_RAMP_DELAY    100000                  /* uV/us */
-#define MAX77686_DVS_RAMP_DELAY        27500                   /* uV/us */
-#define MAX77686_DVS_MINUV     600000
-#define MAX77686_DVS_UVSTEP    12500
-
-/*
- * Value for configuring buck[89] and LDO{20,21,22} as GPIO control.
- * It is the same as 'off' for other regulators.
- */
-#define MAX77686_GPIO_CONTROL          0x0
-/*
- * Values used for configuring LDOs and bucks.
- * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26
- */
-#define MAX77686_LDO_LOWPOWER          0x1
-/*
- * On/off controlled by PWRREQ:
- *  - LDO2, 6-8, 10-12, 14-16
- *  - buck[1234]
- */
-#define MAX77686_OFF_PWRREQ            0x1
-/* Low power mode controlled by PWRREQ: All LDOs */
-#define MAX77686_LDO_LOWPOWER_PWRREQ   0x2
-/* Forcing low power mode: buck[234] */
-#define MAX77686_BUCK_LOWPOWER         0x2
-#define MAX77686_NORMAL                        0x3
-
-#define MAX77686_OPMODE_SHIFT  6
-#define MAX77686_OPMODE_BUCK234_SHIFT  4
-#define MAX77686_OPMODE_MASK   0x3
-
-#define MAX77686_VSEL_MASK     0x3F
-#define MAX77686_DVS_VSEL_MASK 0xFF
-
-#define MAX77686_RAMP_RATE_MASK        0xC0
-
-#define MAX77686_REGULATORS    MAX77686_REG_MAX
-#define MAX77686_LDOS          26
-
-enum max77686_ramp_rate {
-       RAMP_RATE_13P75MV,
-       RAMP_RATE_27P5MV,
-       RAMP_RATE_55MV,
-       RAMP_RATE_NO_CTRL,      /* 100mV/us */
-};
-
-struct max77686_data {
-       DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS);
-
-       /* Array indexed by regulator id */
-       unsigned int opmode[MAX77686_REGULATORS];
-};
-
-static unsigned int max77686_get_opmode_shift(int id)
-{
-       switch (id) {
-       case MAX77686_BUCK1:
-       case MAX77686_BUCK5 ... MAX77686_BUCK9:
-               return 0;
-       case MAX77686_BUCK2 ... MAX77686_BUCK4:
-               return MAX77686_OPMODE_BUCK234_SHIFT;
-       default:
-               /* all LDOs */
-               return MAX77686_OPMODE_SHIFT;
-       }
-}
-
-/*
- * When regulator is configured for GPIO control then it
- * replaces "normal" mode. Any change from low power mode to normal
- * should actually change to GPIO control.
- * Map normal mode to proper value for such regulators.
- */
-static unsigned int max77686_map_normal_mode(struct max77686_data *max77686,
-                                            int id)
-{
-       switch (id) {
-       case MAX77686_BUCK8:
-       case MAX77686_BUCK9:
-       case MAX77686_LDO20 ... MAX77686_LDO22:
-               if (test_bit(id, max77686->gpio_enabled))
-                       return MAX77686_GPIO_CONTROL;
-       }
-
-       return MAX77686_NORMAL;
-}
-
-/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */
-static int max77686_set_suspend_disable(struct regulator_dev *rdev)
-{
-       unsigned int val, shift;
-       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
-       int ret, id = rdev_get_id(rdev);
-
-       shift = max77686_get_opmode_shift(id);
-       val = MAX77686_OFF_PWRREQ;
-
-       ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                rdev->desc->enable_mask, val << shift);
-       if (ret)
-               return ret;
-
-       max77686->opmode[id] = val;
-       return 0;
-}
-
-/* Some LDOs supports [LPM/Normal]ON mode during suspend state */
-static int max77686_set_suspend_mode(struct regulator_dev *rdev,
-                                    unsigned int mode)
-{
-       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
-       unsigned int val;
-       int ret, id = rdev_get_id(rdev);
-
-       /* BUCK[5-9] doesn't support this feature */
-       if (id >= MAX77686_BUCK5)
-               return 0;
-
-       switch (mode) {
-       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
-               val = MAX77686_LDO_LOWPOWER_PWRREQ;
-               break;
-       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
-               val = max77686_map_normal_mode(max77686, id);
-               break;
-       default:
-               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
-                       rdev->desc->name, mode);
-               return -EINVAL;
-       }
-
-       ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask,
-                                 val << MAX77686_OPMODE_SHIFT);
-       if (ret)
-               return ret;
-
-       max77686->opmode[id] = val;
-       return 0;
-}
-
-/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
-static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
-                                    unsigned int mode)
-{
-       unsigned int val;
-       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
-       int ret, id = rdev_get_id(rdev);
-
-       switch (mode) {
-       case REGULATOR_MODE_STANDBY:                    /* switch off */
-               val = MAX77686_OFF_PWRREQ;
-               break;
-       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
-               val = MAX77686_LDO_LOWPOWER_PWRREQ;
-               break;
-       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
-               val = max77686_map_normal_mode(max77686, id);
-               break;
-       default:
-               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
-                       rdev->desc->name, mode);
-               return -EINVAL;
-       }
-
-       ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                rdev->desc->enable_mask,
-                                val << MAX77686_OPMODE_SHIFT);
-       if (ret)
-               return ret;
-
-       max77686->opmode[id] = val;
-       return 0;
-}
-
-static int max77686_enable(struct regulator_dev *rdev)
-{
-       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
-       unsigned int shift;
-       int id = rdev_get_id(rdev);
-
-       shift = max77686_get_opmode_shift(id);
-
-       if (max77686->opmode[id] == MAX77686_OFF_PWRREQ)
-               max77686->opmode[id] = max77686_map_normal_mode(max77686, id);
-
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask,
-                                 max77686->opmode[id] << shift);
-}
-
-static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
-{
-       unsigned int ramp_value = RAMP_RATE_NO_CTRL;
-
-       switch (ramp_delay) {
-       case 1 ... 13750:
-               ramp_value = RAMP_RATE_13P75MV;
-               break;
-       case 13751 ... 27500:
-               ramp_value = RAMP_RATE_27P5MV;
-               break;
-       case 27501 ... 55000:
-               ramp_value = RAMP_RATE_55MV;
-               break;
-       case 55001 ... 100000:
-               break;
-       default:
-               pr_warn("%s: ramp_delay: %d not supported, setting 100000\n",
-                       rdev->desc->name, ramp_delay);
-       }
-
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 MAX77686_RAMP_RATE_MASK, ramp_value << 6);
-}
-
-static int max77686_of_parse_cb(struct device_node *np,
-               const struct regulator_desc *desc,
-               struct regulator_config *config)
-{
-       struct max77686_data *max77686 = config->driver_data;
-
-       switch (desc->id) {
-       case MAX77686_BUCK8:
-       case MAX77686_BUCK9:
-       case MAX77686_LDO20 ... MAX77686_LDO22:
-               config->ena_gpio = of_get_named_gpio(np,
-                                       "maxim,ena-gpios", 0);
-               config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
-               config->ena_gpio_initialized = true;
-               break;
-       default:
-               return 0;
-       }
-
-       if (gpio_is_valid(config->ena_gpio)) {
-               set_bit(desc->id, max77686->gpio_enabled);
-
-               return regmap_update_bits(config->regmap, desc->enable_reg,
-                                         desc->enable_mask,
-                                         MAX77686_GPIO_CONTROL);
-       }
-
-       return 0;
-}
-
-static struct regulator_ops max77686_ops = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77686_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_mode       = max77686_set_suspend_mode,
-};
-
-static struct regulator_ops max77686_ldo_ops = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77686_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_mode       = max77686_ldo_set_suspend_mode,
-       .set_suspend_disable    = max77686_set_suspend_disable,
-};
-
-static struct regulator_ops max77686_buck1_ops = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77686_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_disable    = max77686_set_suspend_disable,
-};
-
-static struct regulator_ops max77686_buck_dvs_ops = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77686_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_ramp_delay         = max77686_set_ramp_delay,
-       .set_suspend_disable    = max77686_set_suspend_disable,
-};
-
-#define regulator_desc_ldo(num)                {                               \
-       .name           = "LDO"#num,                                    \
-       .of_match       = of_match_ptr("LDO"#num),                      \
-       .regulators_node        = of_match_ptr("voltage-regulators"),   \
-       .of_parse_cb    = max77686_of_parse_cb,                         \
-       .id             = MAX77686_LDO##num,                            \
-       .ops            = &max77686_ops,                                \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = MAX77686_LDO_MINUV,                           \
-       .uV_step        = MAX77686_LDO_UVSTEP,                          \
-       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
-       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
-       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
-       .vsel_mask      = MAX77686_VSEL_MASK,                           \
-       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
-       .enable_mask    = MAX77686_OPMODE_MASK                          \
-                       << MAX77686_OPMODE_SHIFT,                       \
-}
-#define regulator_desc_lpm_ldo(num)    {                               \
-       .name           = "LDO"#num,                                    \
-       .of_match       = of_match_ptr("LDO"#num),                      \
-       .regulators_node        = of_match_ptr("voltage-regulators"),   \
-       .id             = MAX77686_LDO##num,                            \
-       .ops            = &max77686_ldo_ops,                            \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = MAX77686_LDO_MINUV,                           \
-       .uV_step        = MAX77686_LDO_UVSTEP,                          \
-       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
-       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
-       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
-       .vsel_mask      = MAX77686_VSEL_MASK,                           \
-       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
-       .enable_mask    = MAX77686_OPMODE_MASK                          \
-                       << MAX77686_OPMODE_SHIFT,                       \
-}
-#define regulator_desc_ldo_low(num)            {                       \
-       .name           = "LDO"#num,                                    \
-       .of_match       = of_match_ptr("LDO"#num),                      \
-       .regulators_node        = of_match_ptr("voltage-regulators"),   \
-       .id             = MAX77686_LDO##num,                            \
-       .ops            = &max77686_ldo_ops,                            \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
-       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
-       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
-       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
-       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
-       .vsel_mask      = MAX77686_VSEL_MASK,                           \
-       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
-       .enable_mask    = MAX77686_OPMODE_MASK                          \
-                       << MAX77686_OPMODE_SHIFT,                       \
-}
-#define regulator_desc_ldo1_low(num)           {                       \
-       .name           = "LDO"#num,                                    \
-       .of_match       = of_match_ptr("LDO"#num),                      \
-       .regulators_node        = of_match_ptr("voltage-regulators"),   \
-       .id             = MAX77686_LDO##num,                            \
-       .ops            = &max77686_ops,                                \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
-       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
-       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
-       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
-       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
-       .vsel_mask      = MAX77686_VSEL_MASK,                           \
-       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
-       .enable_mask    = MAX77686_OPMODE_MASK                          \
-                       << MAX77686_OPMODE_SHIFT,                       \
-}
-#define regulator_desc_buck(num)               {                       \
-       .name           = "BUCK"#num,                                   \
-       .of_match       = of_match_ptr("BUCK"#num),                     \
-       .regulators_node        = of_match_ptr("voltage-regulators"),   \
-       .of_parse_cb    = max77686_of_parse_cb,                         \
-       .id             = MAX77686_BUCK##num,                           \
-       .ops            = &max77686_ops,                                \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = MAX77686_BUCK_MINUV,                          \
-       .uV_step        = MAX77686_BUCK_UVSTEP,                         \
-       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
-       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
-       .vsel_reg       = MAX77686_REG_BUCK5OUT + (num - 5) * 2,        \
-       .vsel_mask      = MAX77686_VSEL_MASK,                           \
-       .enable_reg     = MAX77686_REG_BUCK5CTRL + (num - 5) * 2,       \
-       .enable_mask    = MAX77686_OPMODE_MASK,                         \
-}
-#define regulator_desc_buck1(num)              {                       \
-       .name           = "BUCK"#num,                                   \
-       .of_match       = of_match_ptr("BUCK"#num),                     \
-       .regulators_node        = of_match_ptr("voltage-regulators"),   \
-       .id             = MAX77686_BUCK##num,                           \
-       .ops            = &max77686_buck1_ops,                          \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = MAX77686_BUCK_MINUV,                          \
-       .uV_step        = MAX77686_BUCK_UVSTEP,                         \
-       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
-       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
-       .vsel_reg       = MAX77686_REG_BUCK1OUT,                        \
-       .vsel_mask      = MAX77686_VSEL_MASK,                           \
-       .enable_reg     = MAX77686_REG_BUCK1CTRL,                       \
-       .enable_mask    = MAX77686_OPMODE_MASK,                         \
-}
-#define regulator_desc_buck_dvs(num)           {                       \
-       .name           = "BUCK"#num,                                   \
-       .of_match       = of_match_ptr("BUCK"#num),                     \
-       .regulators_node        = of_match_ptr("voltage-regulators"),   \
-       .id             = MAX77686_BUCK##num,                           \
-       .ops            = &max77686_buck_dvs_ops,                       \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = MAX77686_DVS_MINUV,                           \
-       .uV_step        = MAX77686_DVS_UVSTEP,                          \
-       .ramp_delay     = MAX77686_DVS_RAMP_DELAY,                      \
-       .n_voltages     = MAX77686_DVS_VSEL_MASK + 1,                   \
-       .vsel_reg       = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10,      \
-       .vsel_mask      = MAX77686_DVS_VSEL_MASK,                       \
-       .enable_reg     = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10,     \
-       .enable_mask    = MAX77686_OPMODE_MASK                          \
-                       << MAX77686_OPMODE_BUCK234_SHIFT,               \
-}
-
-static const struct regulator_desc regulators[] = {
-       regulator_desc_ldo1_low(1),
-       regulator_desc_ldo_low(2),
-       regulator_desc_ldo(3),
-       regulator_desc_ldo(4),
-       regulator_desc_ldo(5),
-       regulator_desc_ldo_low(6),
-       regulator_desc_ldo_low(7),
-       regulator_desc_ldo_low(8),
-       regulator_desc_ldo(9),
-       regulator_desc_lpm_ldo(10),
-       regulator_desc_lpm_ldo(11),
-       regulator_desc_lpm_ldo(12),
-       regulator_desc_ldo(13),
-       regulator_desc_lpm_ldo(14),
-       regulator_desc_ldo_low(15),
-       regulator_desc_lpm_ldo(16),
-       regulator_desc_ldo(17),
-       regulator_desc_ldo(18),
-       regulator_desc_ldo(19),
-       regulator_desc_ldo(20),
-       regulator_desc_ldo(21),
-       regulator_desc_ldo(22),
-       regulator_desc_ldo(23),
-       regulator_desc_ldo(24),
-       regulator_desc_ldo(25),
-       regulator_desc_ldo(26),
-       regulator_desc_buck1(1),
-       regulator_desc_buck_dvs(2),
-       regulator_desc_buck_dvs(3),
-       regulator_desc_buck_dvs(4),
-       regulator_desc_buck(5),
-       regulator_desc_buck(6),
-       regulator_desc_buck(7),
-       regulator_desc_buck(8),
-       regulator_desc_buck(9),
-};
-
-static int max77686_pmic_probe(struct platform_device *pdev)
-{
-       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max77686_data *max77686;
-       int i;
-       struct regulator_config config = { };
-
-       dev_dbg(&pdev->dev, "%s\n", __func__);
-
-       max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
-                               GFP_KERNEL);
-       if (!max77686)
-               return -ENOMEM;
-
-       config.dev = iodev->dev;
-       config.regmap = iodev->regmap;
-       config.driver_data = max77686;
-       platform_set_drvdata(pdev, max77686);
-
-       for (i = 0; i < MAX77686_REGULATORS; i++) {
-               struct regulator_dev *rdev;
-               int id = regulators[i].id;
-
-               max77686->opmode[id] = MAX77686_NORMAL;
-               rdev = devm_regulator_register(&pdev->dev,
-                                               &regulators[i], &config);
-               if (IS_ERR(rdev)) {
-                       int ret = PTR_ERR(rdev);
-                       dev_err(&pdev->dev,
-                               "regulator init failed for %d: %d\n", i, ret);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static const struct platform_device_id max77686_pmic_id[] = {
-       {"max77686-pmic", 0},
-       { },
-};
-MODULE_DEVICE_TABLE(platform, max77686_pmic_id);
-
-static struct platform_driver max77686_pmic_driver = {
-       .driver = {
-               .name = "max77686-pmic",
-       },
-       .probe = max77686_pmic_probe,
-       .id_table = max77686_pmic_id,
-};
-
-static int __init max77686_pmic_init(void)
-{
-       return platform_driver_register(&max77686_pmic_driver);
-}
-subsys_initcall(max77686_pmic_init);
-
-static void __exit max77686_pmic_cleanup(void)
-{
-       platform_driver_unregister(&max77686_pmic_driver);
-}
-module_exit(max77686_pmic_cleanup);
-
-MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");
-MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c
new file mode 100644 (file)
index 0000000..c07ee13
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ * max77802.c - Regulator driver for the Maxim 77802
+ *
+ * Copyright (C) 2013-2014 Google, Inc
+ * Simon Glass <sjg@chromium.org>
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Chiwoong Byun <woong.byun@smasung.com>
+ * Jonghwa Lee <jonghwa3.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This driver is based on max8997.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/max77686.h>
+#include <linux/mfd/max77686-private.h>
+#include <dt-bindings/regulator/maxim,max77802.h>
+
+/* Default ramp delay in case it is not manually set */
+#define MAX77802_RAMP_DELAY            100000          /* uV/us */
+
+#define MAX77802_OPMODE_SHIFT_LDO      6
+#define MAX77802_OPMODE_BUCK234_SHIFT  4
+#define MAX77802_OPMODE_MASK           0x3
+
+#define MAX77802_VSEL_MASK             0x3F
+#define MAX77802_DVS_VSEL_MASK         0xFF
+
+#define MAX77802_RAMP_RATE_MASK_2BIT   0xC0
+#define MAX77802_RAMP_RATE_SHIFT_2BIT  6
+#define MAX77802_RAMP_RATE_MASK_4BIT   0xF0
+#define MAX77802_RAMP_RATE_SHIFT_4BIT  4
+
+#define MAX77802_STATUS_OFF            0x0
+#define MAX77802_OFF_PWRREQ            0x1
+#define MAX77802_LP_PWRREQ             0x2
+
+/* MAX77802 has two register formats: 2-bit and 4-bit */
+static const unsigned int ramp_table_77802_2bit[] = {
+       12500,
+       25000,
+       50000,
+       100000,
+};
+
+static unsigned int ramp_table_77802_4bit[] = {
+       1000,   2000,   3030,   4000,
+       5000,   5880,   7140,   8330,
+       9090,   10000,  11110,  12500,
+       16670,  25000,  50000,  100000,
+};
+
+struct max77802_regulator_prv {
+       /* Array indexed by regulator id */
+       unsigned int opmode[MAX77802_REG_MAX];
+};
+
+static inline unsigned int max77802_map_mode(unsigned int mode)
+{
+       return mode == MAX77802_OPMODE_NORMAL ?
+               REGULATOR_MODE_NORMAL : REGULATOR_MODE_STANDBY;
+}
+
+static int max77802_get_opmode_shift(int id)
+{
+       if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 &&
+                                    id <= MAX77802_BUCK10))
+               return 0;
+
+       if (id >= MAX77802_BUCK2 && id <= MAX77802_BUCK4)
+               return MAX77802_OPMODE_BUCK234_SHIFT;
+
+       if (id >= MAX77802_LDO1 && id <= MAX77802_LDO35)
+               return MAX77802_OPMODE_SHIFT_LDO;
+
+       return -EINVAL;
+}
+
+/**
+ * max77802_set_suspend_disable - Disable the regulator during system suspend
+ * @rdev: regulator to mark as disabled
+ *
+ * All regulators expect LDO 1, 3, 20 and 21 support OFF by PWRREQ.
+ * Configure the regulator so the PMIC will turn it OFF during system suspend.
+ */
+static int max77802_set_suspend_disable(struct regulator_dev *rdev)
+{
+       unsigned int val = MAX77802_OFF_PWRREQ;
+       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       int shift = max77802_get_opmode_shift(id);
+
+       max77802->opmode[id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask, val << shift);
+}
+
+/*
+ * Some LDOs support Low Power Mode while the system is running.
+ *
+ * LDOs 1, 3, 20, 21.
+ */
+static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       unsigned int val;
+       int shift = max77802_get_opmode_shift(id);
+
+       switch (mode) {
+       case REGULATOR_MODE_STANDBY:
+               val = MAX77802_OPMODE_LP;       /* ON in Low Power Mode */
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = MAX77802_OPMODE_NORMAL;   /* ON in Normal Mode */
+               break;
+       default:
+               dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
+                        rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       max77802->opmode[id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask, val << shift);
+}
+
+static unsigned max77802_get_mode(struct regulator_dev *rdev)
+{
+       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+
+       return max77802_map_mode(max77802->opmode[id]);
+}
+
+/**
+ * max77802_set_suspend_mode - set regulator opmode when the system is suspended
+ * @rdev: regulator to change mode
+ * @mode: operating mode to be set
+ *
+ * Will set the operating mode for the regulators during system suspend.
+ * This function is valid for the three different enable control logics:
+ *
+ * Enable Control Logic1 by PWRREQ (BUCK 2-4 and LDOs 2, 4-19, 22-35)
+ * Enable Control Logic2 by PWRREQ (LDOs 1, 20, 21)
+ * Enable Control Logic3 by PWRREQ (LDO 3)
+ *
+ * If setting the regulator mode fails, the function only warns but does
+ * not return an error code to avoid the regulator core to stop setting
+ * the operating mode for the remaining regulators.
+ */
+static int max77802_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       unsigned int val;
+       int shift = max77802_get_opmode_shift(id);
+
+       /*
+        * If the regulator has been disabled for suspend
+        * then is invalid to try setting a suspend mode.
+        */
+       if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) {
+               dev_warn(&rdev->dev, "%s: is disabled, mode: 0x%x not set\n",
+                        rdev->desc->name, mode);
+               return 0;
+       }
+
+       switch (mode) {
+       case REGULATOR_MODE_STANDBY:
+               /*
+                * If the regulator opmode is normal then enable
+                * ON in Low Power Mode by PWRREQ. If the mode is
+                * already Low Power then no action is required.
+                */
+               if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL)
+                       val = MAX77802_LP_PWRREQ;
+               else
+                       return 0;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               /*
+                * If the regulator operating mode is Low Power then
+                * normal is not a valid opmode in suspend. If the
+                * mode is already normal then no action is required.
+                */
+               if (max77802->opmode[id] == MAX77802_OPMODE_LP)
+                       dev_warn(&rdev->dev, "%s: in Low Power: 0x%x invalid\n",
+                                rdev->desc->name, mode);
+               return 0;
+       default:
+               dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
+                        rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask, val << shift);
+}
+
+static int max77802_enable(struct regulator_dev *rdev)
+{
+       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       int shift = max77802_get_opmode_shift(id);
+
+       if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
+               max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 max77802->opmode[id] << shift);
+}
+
+static int max77802_find_ramp_value(struct regulator_dev *rdev,
+                                   const unsigned int limits[], int size,
+                                   unsigned int ramp_delay)
+{
+       int i;
+
+       for (i = 0; i < size; i++) {
+               if (ramp_delay <= limits[i])
+                       return i;
+       }
+
+       /* Use maximum value for no ramp control */
+       dev_warn(&rdev->dev, "%s: ramp_delay: %d not supported, setting 100000\n",
+                rdev->desc->name, ramp_delay);
+       return size - 1;
+}
+
+/* Used for BUCKs 2-4 */
+static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev,
+                                       int ramp_delay)
+{
+       int id = rdev_get_id(rdev);
+       unsigned int ramp_value;
+
+       if (id > MAX77802_BUCK4) {
+                       dev_warn(&rdev->dev,
+                                "%s: regulator: ramp delay not supported\n",
+                                rdev->desc->name);
+               return -EINVAL;
+       }
+       ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit,
+                               ARRAY_SIZE(ramp_table_77802_2bit), ramp_delay);
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 MAX77802_RAMP_RATE_MASK_2BIT,
+                                 ramp_value << MAX77802_RAMP_RATE_SHIFT_2BIT);
+}
+
+/* For BUCK1, 6 */
+static int max77802_set_ramp_delay_4bit(struct regulator_dev *rdev,
+                                           int ramp_delay)
+{
+       unsigned int ramp_value;
+
+       ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_4bit,
+                               ARRAY_SIZE(ramp_table_77802_4bit), ramp_delay);
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 MAX77802_RAMP_RATE_MASK_4BIT,
+                                 ramp_value << MAX77802_RAMP_RATE_SHIFT_4BIT);
+}
+
+/*
+ * LDOs 2, 4-19, 22-35
+ */
+static struct regulator_ops max77802_ldo_ops_logic1 = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77802_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_disable    = max77802_set_suspend_disable,
+       .set_suspend_mode       = max77802_set_suspend_mode,
+};
+
+/*
+ * LDOs 1, 20, 21, 3
+ */
+static struct regulator_ops max77802_ldo_ops_logic2 = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77802_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_mode               = max77802_set_mode,
+       .get_mode               = max77802_get_mode,
+       .set_suspend_mode       = max77802_set_suspend_mode,
+};
+
+/* BUCKS 1, 6 */
+static struct regulator_ops max77802_buck_16_dvs_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77802_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = max77802_set_ramp_delay_4bit,
+       .set_suspend_disable    = max77802_set_suspend_disable,
+};
+
+/* BUCKs 2-4 */
+static struct regulator_ops max77802_buck_234_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77802_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = max77802_set_ramp_delay_2bit,
+       .set_suspend_disable    = max77802_set_suspend_disable,
+       .set_suspend_mode       = max77802_set_suspend_mode,
+};
+
+/* BUCKs 5, 7-10 */
+static struct regulator_ops max77802_buck_dvs_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77802_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = max77802_set_ramp_delay_2bit,
+       .set_suspend_disable    = max77802_set_suspend_disable,
+};
+
+/* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */
+#define regulator_77802_desc_p_ldo(num, supply, log)   {               \
+       .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("regulators"),           \
+       .id             = MAX77802_LDO##num,                            \
+       .supply_name    = "inl"#supply,                                 \
+       .ops            = &max77802_ldo_ops_logic##log,                 \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = 800000,                                       \
+       .uV_step        = 50000,                                        \
+       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
+       .n_voltages     = 1 << 6,                                       \
+       .vsel_reg       = MAX77802_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77802_VSEL_MASK,                           \
+       .enable_reg     = MAX77802_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
+       .of_map_mode    = max77802_map_mode,                            \
+}
+
+/* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */
+#define regulator_77802_desc_n_ldo(num, supply, log)   {               \
+       .name           = "LDO"#num,                                    \
+       .of_match       = of_match_ptr("LDO"#num),                      \
+       .regulators_node        = of_match_ptr("regulators"),           \
+       .id             = MAX77802_LDO##num,                            \
+       .supply_name    = "inl"#supply,                                 \
+       .ops            = &max77802_ldo_ops_logic##log,                 \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = 800000,                                       \
+       .uV_step        = 25000,                                        \
+       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
+       .n_voltages     = 1 << 6,                                       \
+       .vsel_reg       = MAX77802_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77802_VSEL_MASK,                           \
+       .enable_reg     = MAX77802_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
+       .of_map_mode    = max77802_map_mode,                            \
+}
+
+/* BUCKs 1, 6 */
+#define regulator_77802_desc_16_buck(num)      {               \
+       .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("regulators"),           \
+       .id             = MAX77802_BUCK##num,                           \
+       .supply_name    = "inb"#num,                                    \
+       .ops            = &max77802_buck_16_dvs_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = 612500,                                       \
+       .uV_step        = 6250,                                         \
+       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
+       .n_voltages     = 1 << 8,                                       \
+       .vsel_reg       = MAX77802_REG_BUCK ## num ## DVS1,             \
+       .vsel_mask      = MAX77802_DVS_VSEL_MASK,                       \
+       .enable_reg     = MAX77802_REG_BUCK ## num ## CTRL,             \
+       .enable_mask    = MAX77802_OPMODE_MASK,                         \
+       .of_map_mode    = max77802_map_mode,                            \
+}
+
+/* BUCKS 2-4 */
+#define regulator_77802_desc_234_buck(num)     {               \
+       .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("regulators"),           \
+       .id             = MAX77802_BUCK##num,                           \
+       .supply_name    = "inb"#num,                                    \
+       .ops            = &max77802_buck_234_ops,                       \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = 600000,                                       \
+       .uV_step        = 6250,                                         \
+       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
+       .n_voltages     = 0x91,                                         \
+       .vsel_reg       = MAX77802_REG_BUCK ## num ## DVS1,             \
+       .vsel_mask      = MAX77802_DVS_VSEL_MASK,                       \
+       .enable_reg     = MAX77802_REG_BUCK ## num ## CTRL1,            \
+       .enable_mask    = MAX77802_OPMODE_MASK <<                       \
+                               MAX77802_OPMODE_BUCK234_SHIFT,          \
+       .of_map_mode    = max77802_map_mode,                            \
+}
+
+/* BUCK 5 */
+#define regulator_77802_desc_buck5(num)                {               \
+       .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("regulators"),           \
+       .id             = MAX77802_BUCK##num,                           \
+       .supply_name    = "inb"#num,                                    \
+       .ops            = &max77802_buck_dvs_ops,                       \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = 750000,                                       \
+       .uV_step        = 50000,                                        \
+       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
+       .n_voltages     = 1 << 6,                                       \
+       .vsel_reg       = MAX77802_REG_BUCK5OUT,                        \
+       .vsel_mask      = MAX77802_VSEL_MASK,                           \
+       .enable_reg     = MAX77802_REG_BUCK5CTRL,                       \
+       .enable_mask    = MAX77802_OPMODE_MASK,                         \
+       .of_map_mode    = max77802_map_mode,                            \
+}
+
+/* BUCKs 7-10 */
+#define regulator_77802_desc_buck7_10(num)     {               \
+       .name           = "BUCK"#num,                                   \
+       .of_match       = of_match_ptr("BUCK"#num),                     \
+       .regulators_node        = of_match_ptr("regulators"),           \
+       .id             = MAX77802_BUCK##num,                           \
+       .supply_name    = "inb"#num,                                    \
+       .ops            = &max77802_buck_dvs_ops,                       \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = 750000,                                       \
+       .uV_step        = 50000,                                        \
+       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
+       .n_voltages     = 1 << 6,                                       \
+       .vsel_reg       = MAX77802_REG_BUCK7OUT + (num - 7) * 3,        \
+       .vsel_mask      = MAX77802_VSEL_MASK,                           \
+       .enable_reg     = MAX77802_REG_BUCK7CTRL + (num - 7) * 3,       \
+       .enable_mask    = MAX77802_OPMODE_MASK,                         \
+       .of_map_mode    = max77802_map_mode,                            \
+}
+
+static const struct regulator_desc regulators[] = {
+       regulator_77802_desc_16_buck(1),
+       regulator_77802_desc_234_buck(2),
+       regulator_77802_desc_234_buck(3),
+       regulator_77802_desc_234_buck(4),
+       regulator_77802_desc_buck5(5),
+       regulator_77802_desc_16_buck(6),
+       regulator_77802_desc_buck7_10(7),
+       regulator_77802_desc_buck7_10(8),
+       regulator_77802_desc_buck7_10(9),
+       regulator_77802_desc_buck7_10(10),
+       regulator_77802_desc_n_ldo(1, 10, 2),
+       regulator_77802_desc_n_ldo(2, 10, 1),
+       regulator_77802_desc_p_ldo(3, 3, 2),
+       regulator_77802_desc_p_ldo(4, 6, 1),
+       regulator_77802_desc_p_ldo(5, 3, 1),
+       regulator_77802_desc_p_ldo(6, 3, 1),
+       regulator_77802_desc_p_ldo(7, 3, 1),
+       regulator_77802_desc_n_ldo(8, 1, 1),
+       regulator_77802_desc_p_ldo(9, 5, 1),
+       regulator_77802_desc_p_ldo(10, 4, 1),
+       regulator_77802_desc_p_ldo(11, 4, 1),
+       regulator_77802_desc_p_ldo(12, 9, 1),
+       regulator_77802_desc_p_ldo(13, 4, 1),
+       regulator_77802_desc_p_ldo(14, 4, 1),
+       regulator_77802_desc_n_ldo(15, 1, 1),
+       regulator_77802_desc_n_ldo(17, 2, 1),
+       regulator_77802_desc_p_ldo(18, 7, 1),
+       regulator_77802_desc_p_ldo(19, 5, 1),
+       regulator_77802_desc_p_ldo(20, 7, 2),
+       regulator_77802_desc_p_ldo(21, 6, 2),
+       regulator_77802_desc_p_ldo(23, 9, 1),
+       regulator_77802_desc_p_ldo(24, 6, 1),
+       regulator_77802_desc_p_ldo(25, 9, 1),
+       regulator_77802_desc_p_ldo(26, 9, 1),
+       regulator_77802_desc_n_ldo(27, 2, 1),
+       regulator_77802_desc_p_ldo(28, 7, 1),
+       regulator_77802_desc_p_ldo(29, 7, 1),
+       regulator_77802_desc_n_ldo(30, 2, 1),
+       regulator_77802_desc_p_ldo(32, 9, 1),
+       regulator_77802_desc_p_ldo(33, 6, 1),
+       regulator_77802_desc_p_ldo(34, 9, 1),
+       regulator_77802_desc_n_ldo(35, 2, 1),
+};
+
+static int max77802_pmic_probe(struct platform_device *pdev)
+{
+       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct max77802_regulator_prv *max77802;
+       int i, val;
+       struct regulator_config config = { };
+
+       max77802 = devm_kzalloc(&pdev->dev,
+                               sizeof(struct max77802_regulator_prv),
+                               GFP_KERNEL);
+       if (!max77802)
+               return -ENOMEM;
+
+       config.dev = iodev->dev;
+       config.regmap = iodev->regmap;
+       config.driver_data = max77802;
+       platform_set_drvdata(pdev, max77802);
+
+       for (i = 0; i < MAX77802_REG_MAX; i++) {
+               struct regulator_dev *rdev;
+               int id = regulators[i].id;
+               int shift = max77802_get_opmode_shift(id);
+               int ret;
+
+               ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val);
+               if (ret < 0) {
+                       dev_warn(&pdev->dev,
+                               "cannot read current mode for %d\n", i);
+                       val = MAX77802_OPMODE_NORMAL;
+               } else {
+                       val = val >> shift & MAX77802_OPMODE_MASK;
+               }
+
+               /*
+                * If the regulator is disabled and the system warm rebooted,
+                * the hardware reports OFF as the regulator operating mode.
+                * Default to operating mode NORMAL in that case.
+                */
+               if (val == MAX77802_STATUS_OFF)
+                       max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
+               else
+                       max77802->opmode[id] = val;
+
+               rdev = devm_regulator_register(&pdev->dev,
+                                              &regulators[i], &config);
+               if (IS_ERR(rdev)) {
+                       ret = PTR_ERR(rdev);
+                       dev_err(&pdev->dev,
+                               "regulator init failed for %d: %d\n", i, ret);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct platform_device_id max77802_pmic_id[] = {
+       {"max77802-pmic", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(platform, max77802_pmic_id);
+
+static struct platform_driver max77802_pmic_driver = {
+       .driver = {
+               .name = "max77802-pmic",
+       },
+       .probe = max77802_pmic_probe,
+       .id_table = max77802_pmic_id,
+};
+
+module_platform_driver(max77802_pmic_driver);
+
+MODULE_DESCRIPTION("MAXIM 77802 Regulator Driver");
+MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/max77802.c b/drivers/regulator/max77802.c
deleted file mode 100644 (file)
index c07ee13..0000000
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * max77802.c - Regulator driver for the Maxim 77802
- *
- * Copyright (C) 2013-2014 Google, Inc
- * Simon Glass <sjg@chromium.org>
- *
- * Copyright (C) 2012 Samsung Electronics
- * Chiwoong Byun <woong.byun@smasung.com>
- * Jonghwa Lee <jonghwa3.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This driver is based on max8997.c
- */
-
-#include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/gpio/consumer.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/mfd/max77686.h>
-#include <linux/mfd/max77686-private.h>
-#include <dt-bindings/regulator/maxim,max77802.h>
-
-/* Default ramp delay in case it is not manually set */
-#define MAX77802_RAMP_DELAY            100000          /* uV/us */
-
-#define MAX77802_OPMODE_SHIFT_LDO      6
-#define MAX77802_OPMODE_BUCK234_SHIFT  4
-#define MAX77802_OPMODE_MASK           0x3
-
-#define MAX77802_VSEL_MASK             0x3F
-#define MAX77802_DVS_VSEL_MASK         0xFF
-
-#define MAX77802_RAMP_RATE_MASK_2BIT   0xC0
-#define MAX77802_RAMP_RATE_SHIFT_2BIT  6
-#define MAX77802_RAMP_RATE_MASK_4BIT   0xF0
-#define MAX77802_RAMP_RATE_SHIFT_4BIT  4
-
-#define MAX77802_STATUS_OFF            0x0
-#define MAX77802_OFF_PWRREQ            0x1
-#define MAX77802_LP_PWRREQ             0x2
-
-/* MAX77802 has two register formats: 2-bit and 4-bit */
-static const unsigned int ramp_table_77802_2bit[] = {
-       12500,
-       25000,
-       50000,
-       100000,
-};
-
-static unsigned int ramp_table_77802_4bit[] = {
-       1000,   2000,   3030,   4000,
-       5000,   5880,   7140,   8330,
-       9090,   10000,  11110,  12500,
-       16670,  25000,  50000,  100000,
-};
-
-struct max77802_regulator_prv {
-       /* Array indexed by regulator id */
-       unsigned int opmode[MAX77802_REG_MAX];
-};
-
-static inline unsigned int max77802_map_mode(unsigned int mode)
-{
-       return mode == MAX77802_OPMODE_NORMAL ?
-               REGULATOR_MODE_NORMAL : REGULATOR_MODE_STANDBY;
-}
-
-static int max77802_get_opmode_shift(int id)
-{
-       if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 &&
-                                    id <= MAX77802_BUCK10))
-               return 0;
-
-       if (id >= MAX77802_BUCK2 && id <= MAX77802_BUCK4)
-               return MAX77802_OPMODE_BUCK234_SHIFT;
-
-       if (id >= MAX77802_LDO1 && id <= MAX77802_LDO35)
-               return MAX77802_OPMODE_SHIFT_LDO;
-
-       return -EINVAL;
-}
-
-/**
- * max77802_set_suspend_disable - Disable the regulator during system suspend
- * @rdev: regulator to mark as disabled
- *
- * All regulators expect LDO 1, 3, 20 and 21 support OFF by PWRREQ.
- * Configure the regulator so the PMIC will turn it OFF during system suspend.
- */
-static int max77802_set_suspend_disable(struct regulator_dev *rdev)
-{
-       unsigned int val = MAX77802_OFF_PWRREQ;
-       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-       int id = rdev_get_id(rdev);
-       int shift = max77802_get_opmode_shift(id);
-
-       max77802->opmode[id] = val;
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask, val << shift);
-}
-
-/*
- * Some LDOs support Low Power Mode while the system is running.
- *
- * LDOs 1, 3, 20, 21.
- */
-static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
-{
-       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-       int id = rdev_get_id(rdev);
-       unsigned int val;
-       int shift = max77802_get_opmode_shift(id);
-
-       switch (mode) {
-       case REGULATOR_MODE_STANDBY:
-               val = MAX77802_OPMODE_LP;       /* ON in Low Power Mode */
-               break;
-       case REGULATOR_MODE_NORMAL:
-               val = MAX77802_OPMODE_NORMAL;   /* ON in Normal Mode */
-               break;
-       default:
-               dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
-                        rdev->desc->name, mode);
-               return -EINVAL;
-       }
-
-       max77802->opmode[id] = val;
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask, val << shift);
-}
-
-static unsigned max77802_get_mode(struct regulator_dev *rdev)
-{
-       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-       int id = rdev_get_id(rdev);
-
-       return max77802_map_mode(max77802->opmode[id]);
-}
-
-/**
- * max77802_set_suspend_mode - set regulator opmode when the system is suspended
- * @rdev: regulator to change mode
- * @mode: operating mode to be set
- *
- * Will set the operating mode for the regulators during system suspend.
- * This function is valid for the three different enable control logics:
- *
- * Enable Control Logic1 by PWRREQ (BUCK 2-4 and LDOs 2, 4-19, 22-35)
- * Enable Control Logic2 by PWRREQ (LDOs 1, 20, 21)
- * Enable Control Logic3 by PWRREQ (LDO 3)
- *
- * If setting the regulator mode fails, the function only warns but does
- * not return an error code to avoid the regulator core to stop setting
- * the operating mode for the remaining regulators.
- */
-static int max77802_set_suspend_mode(struct regulator_dev *rdev,
-                                    unsigned int mode)
-{
-       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-       int id = rdev_get_id(rdev);
-       unsigned int val;
-       int shift = max77802_get_opmode_shift(id);
-
-       /*
-        * If the regulator has been disabled for suspend
-        * then is invalid to try setting a suspend mode.
-        */
-       if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) {
-               dev_warn(&rdev->dev, "%s: is disabled, mode: 0x%x not set\n",
-                        rdev->desc->name, mode);
-               return 0;
-       }
-
-       switch (mode) {
-       case REGULATOR_MODE_STANDBY:
-               /*
-                * If the regulator opmode is normal then enable
-                * ON in Low Power Mode by PWRREQ. If the mode is
-                * already Low Power then no action is required.
-                */
-               if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL)
-                       val = MAX77802_LP_PWRREQ;
-               else
-                       return 0;
-               break;
-       case REGULATOR_MODE_NORMAL:
-               /*
-                * If the regulator operating mode is Low Power then
-                * normal is not a valid opmode in suspend. If the
-                * mode is already normal then no action is required.
-                */
-               if (max77802->opmode[id] == MAX77802_OPMODE_LP)
-                       dev_warn(&rdev->dev, "%s: in Low Power: 0x%x invalid\n",
-                                rdev->desc->name, mode);
-               return 0;
-       default:
-               dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n",
-                        rdev->desc->name, mode);
-               return -EINVAL;
-       }
-
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask, val << shift);
-}
-
-static int max77802_enable(struct regulator_dev *rdev)
-{
-       struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-       int id = rdev_get_id(rdev);
-       int shift = max77802_get_opmode_shift(id);
-
-       if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
-               max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
-
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask,
-                                 max77802->opmode[id] << shift);
-}
-
-static int max77802_find_ramp_value(struct regulator_dev *rdev,
-                                   const unsigned int limits[], int size,
-                                   unsigned int ramp_delay)
-{
-       int i;
-
-       for (i = 0; i < size; i++) {
-               if (ramp_delay <= limits[i])
-                       return i;
-       }
-
-       /* Use maximum value for no ramp control */
-       dev_warn(&rdev->dev, "%s: ramp_delay: %d not supported, setting 100000\n",
-                rdev->desc->name, ramp_delay);
-       return size - 1;
-}
-
-/* Used for BUCKs 2-4 */
-static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev,
-                                       int ramp_delay)
-{
-       int id = rdev_get_id(rdev);
-       unsigned int ramp_value;
-
-       if (id > MAX77802_BUCK4) {
-                       dev_warn(&rdev->dev,
-                                "%s: regulator: ramp delay not supported\n",
-                                rdev->desc->name);
-               return -EINVAL;
-       }
-       ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit,
-                               ARRAY_SIZE(ramp_table_77802_2bit), ramp_delay);
-
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 MAX77802_RAMP_RATE_MASK_2BIT,
-                                 ramp_value << MAX77802_RAMP_RATE_SHIFT_2BIT);
-}
-
-/* For BUCK1, 6 */
-static int max77802_set_ramp_delay_4bit(struct regulator_dev *rdev,
-                                           int ramp_delay)
-{
-       unsigned int ramp_value;
-
-       ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_4bit,
-                               ARRAY_SIZE(ramp_table_77802_4bit), ramp_delay);
-
-       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 MAX77802_RAMP_RATE_MASK_4BIT,
-                                 ramp_value << MAX77802_RAMP_RATE_SHIFT_4BIT);
-}
-
-/*
- * LDOs 2, 4-19, 22-35
- */
-static struct regulator_ops max77802_ldo_ops_logic1 = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77802_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_suspend_disable    = max77802_set_suspend_disable,
-       .set_suspend_mode       = max77802_set_suspend_mode,
-};
-
-/*
- * LDOs 1, 20, 21, 3
- */
-static struct regulator_ops max77802_ldo_ops_logic2 = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77802_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_mode               = max77802_set_mode,
-       .get_mode               = max77802_get_mode,
-       .set_suspend_mode       = max77802_set_suspend_mode,
-};
-
-/* BUCKS 1, 6 */
-static struct regulator_ops max77802_buck_16_dvs_ops = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77802_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_ramp_delay         = max77802_set_ramp_delay_4bit,
-       .set_suspend_disable    = max77802_set_suspend_disable,
-};
-
-/* BUCKs 2-4 */
-static struct regulator_ops max77802_buck_234_ops = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77802_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_ramp_delay         = max77802_set_ramp_delay_2bit,
-       .set_suspend_disable    = max77802_set_suspend_disable,
-       .set_suspend_mode       = max77802_set_suspend_mode,
-};
-
-/* BUCKs 5, 7-10 */
-static struct regulator_ops max77802_buck_dvs_ops = {
-       .list_voltage           = regulator_list_voltage_linear,
-       .map_voltage            = regulator_map_voltage_linear,
-       .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = max77802_enable,
-       .disable                = regulator_disable_regmap,
-       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
-       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
-       .set_ramp_delay         = max77802_set_ramp_delay_2bit,
-       .set_suspend_disable    = max77802_set_suspend_disable,
-};
-
-/* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */
-#define regulator_77802_desc_p_ldo(num, supply, log)   {               \
-       .name           = "LDO"#num,                                    \
-       .of_match       = of_match_ptr("LDO"#num),                      \
-       .regulators_node        = of_match_ptr("regulators"),           \
-       .id             = MAX77802_LDO##num,                            \
-       .supply_name    = "inl"#supply,                                 \
-       .ops            = &max77802_ldo_ops_logic##log,                 \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = 800000,                                       \
-       .uV_step        = 50000,                                        \
-       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
-       .n_voltages     = 1 << 6,                                       \
-       .vsel_reg       = MAX77802_REG_LDO1CTRL1 + num - 1,             \
-       .vsel_mask      = MAX77802_VSEL_MASK,                           \
-       .enable_reg     = MAX77802_REG_LDO1CTRL1 + num - 1,             \
-       .enable_mask    = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
-       .of_map_mode    = max77802_map_mode,                            \
-}
-
-/* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */
-#define regulator_77802_desc_n_ldo(num, supply, log)   {               \
-       .name           = "LDO"#num,                                    \
-       .of_match       = of_match_ptr("LDO"#num),                      \
-       .regulators_node        = of_match_ptr("regulators"),           \
-       .id             = MAX77802_LDO##num,                            \
-       .supply_name    = "inl"#supply,                                 \
-       .ops            = &max77802_ldo_ops_logic##log,                 \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = 800000,                                       \
-       .uV_step        = 25000,                                        \
-       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
-       .n_voltages     = 1 << 6,                                       \
-       .vsel_reg       = MAX77802_REG_LDO1CTRL1 + num - 1,             \
-       .vsel_mask      = MAX77802_VSEL_MASK,                           \
-       .enable_reg     = MAX77802_REG_LDO1CTRL1 + num - 1,             \
-       .enable_mask    = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \
-       .of_map_mode    = max77802_map_mode,                            \
-}
-
-/* BUCKs 1, 6 */
-#define regulator_77802_desc_16_buck(num)      {               \
-       .name           = "BUCK"#num,                                   \
-       .of_match       = of_match_ptr("BUCK"#num),                     \
-       .regulators_node        = of_match_ptr("regulators"),           \
-       .id             = MAX77802_BUCK##num,                           \
-       .supply_name    = "inb"#num,                                    \
-       .ops            = &max77802_buck_16_dvs_ops,                    \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = 612500,                                       \
-       .uV_step        = 6250,                                         \
-       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
-       .n_voltages     = 1 << 8,                                       \
-       .vsel_reg       = MAX77802_REG_BUCK ## num ## DVS1,             \
-       .vsel_mask      = MAX77802_DVS_VSEL_MASK,                       \
-       .enable_reg     = MAX77802_REG_BUCK ## num ## CTRL,             \
-       .enable_mask    = MAX77802_OPMODE_MASK,                         \
-       .of_map_mode    = max77802_map_mode,                            \
-}
-
-/* BUCKS 2-4 */
-#define regulator_77802_desc_234_buck(num)     {               \
-       .name           = "BUCK"#num,                                   \
-       .of_match       = of_match_ptr("BUCK"#num),                     \
-       .regulators_node        = of_match_ptr("regulators"),           \
-       .id             = MAX77802_BUCK##num,                           \
-       .supply_name    = "inb"#num,                                    \
-       .ops            = &max77802_buck_234_ops,                       \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = 600000,                                       \
-       .uV_step        = 6250,                                         \
-       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
-       .n_voltages     = 0x91,                                         \
-       .vsel_reg       = MAX77802_REG_BUCK ## num ## DVS1,             \
-       .vsel_mask      = MAX77802_DVS_VSEL_MASK,                       \
-       .enable_reg     = MAX77802_REG_BUCK ## num ## CTRL1,            \
-       .enable_mask    = MAX77802_OPMODE_MASK <<                       \
-                               MAX77802_OPMODE_BUCK234_SHIFT,          \
-       .of_map_mode    = max77802_map_mode,                            \
-}
-
-/* BUCK 5 */
-#define regulator_77802_desc_buck5(num)                {               \
-       .name           = "BUCK"#num,                                   \
-       .of_match       = of_match_ptr("BUCK"#num),                     \
-       .regulators_node        = of_match_ptr("regulators"),           \
-       .id             = MAX77802_BUCK##num,                           \
-       .supply_name    = "inb"#num,                                    \
-       .ops            = &max77802_buck_dvs_ops,                       \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = 750000,                                       \
-       .uV_step        = 50000,                                        \
-       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
-       .n_voltages     = 1 << 6,                                       \
-       .vsel_reg       = MAX77802_REG_BUCK5OUT,                        \
-       .vsel_mask      = MAX77802_VSEL_MASK,                           \
-       .enable_reg     = MAX77802_REG_BUCK5CTRL,                       \
-       .enable_mask    = MAX77802_OPMODE_MASK,                         \
-       .of_map_mode    = max77802_map_mode,                            \
-}
-
-/* BUCKs 7-10 */
-#define regulator_77802_desc_buck7_10(num)     {               \
-       .name           = "BUCK"#num,                                   \
-       .of_match       = of_match_ptr("BUCK"#num),                     \
-       .regulators_node        = of_match_ptr("regulators"),           \
-       .id             = MAX77802_BUCK##num,                           \
-       .supply_name    = "inb"#num,                                    \
-       .ops            = &max77802_buck_dvs_ops,                       \
-       .type           = REGULATOR_VOLTAGE,                            \
-       .owner          = THIS_MODULE,                                  \
-       .min_uV         = 750000,                                       \
-       .uV_step        = 50000,                                        \
-       .ramp_delay     = MAX77802_RAMP_DELAY,                          \
-       .n_voltages     = 1 << 6,                                       \
-       .vsel_reg       = MAX77802_REG_BUCK7OUT + (num - 7) * 3,        \
-       .vsel_mask      = MAX77802_VSEL_MASK,                           \
-       .enable_reg     = MAX77802_REG_BUCK7CTRL + (num - 7) * 3,       \
-       .enable_mask    = MAX77802_OPMODE_MASK,                         \
-       .of_map_mode    = max77802_map_mode,                            \
-}
-
-static const struct regulator_desc regulators[] = {
-       regulator_77802_desc_16_buck(1),
-       regulator_77802_desc_234_buck(2),
-       regulator_77802_desc_234_buck(3),
-       regulator_77802_desc_234_buck(4),
-       regulator_77802_desc_buck5(5),
-       regulator_77802_desc_16_buck(6),
-       regulator_77802_desc_buck7_10(7),
-       regulator_77802_desc_buck7_10(8),
-       regulator_77802_desc_buck7_10(9),
-       regulator_77802_desc_buck7_10(10),
-       regulator_77802_desc_n_ldo(1, 10, 2),
-       regulator_77802_desc_n_ldo(2, 10, 1),
-       regulator_77802_desc_p_ldo(3, 3, 2),
-       regulator_77802_desc_p_ldo(4, 6, 1),
-       regulator_77802_desc_p_ldo(5, 3, 1),
-       regulator_77802_desc_p_ldo(6, 3, 1),
-       regulator_77802_desc_p_ldo(7, 3, 1),
-       regulator_77802_desc_n_ldo(8, 1, 1),
-       regulator_77802_desc_p_ldo(9, 5, 1),
-       regulator_77802_desc_p_ldo(10, 4, 1),
-       regulator_77802_desc_p_ldo(11, 4, 1),
-       regulator_77802_desc_p_ldo(12, 9, 1),
-       regulator_77802_desc_p_ldo(13, 4, 1),
-       regulator_77802_desc_p_ldo(14, 4, 1),
-       regulator_77802_desc_n_ldo(15, 1, 1),
-       regulator_77802_desc_n_ldo(17, 2, 1),
-       regulator_77802_desc_p_ldo(18, 7, 1),
-       regulator_77802_desc_p_ldo(19, 5, 1),
-       regulator_77802_desc_p_ldo(20, 7, 2),
-       regulator_77802_desc_p_ldo(21, 6, 2),
-       regulator_77802_desc_p_ldo(23, 9, 1),
-       regulator_77802_desc_p_ldo(24, 6, 1),
-       regulator_77802_desc_p_ldo(25, 9, 1),
-       regulator_77802_desc_p_ldo(26, 9, 1),
-       regulator_77802_desc_n_ldo(27, 2, 1),
-       regulator_77802_desc_p_ldo(28, 7, 1),
-       regulator_77802_desc_p_ldo(29, 7, 1),
-       regulator_77802_desc_n_ldo(30, 2, 1),
-       regulator_77802_desc_p_ldo(32, 9, 1),
-       regulator_77802_desc_p_ldo(33, 6, 1),
-       regulator_77802_desc_p_ldo(34, 9, 1),
-       regulator_77802_desc_n_ldo(35, 2, 1),
-};
-
-static int max77802_pmic_probe(struct platform_device *pdev)
-{
-       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max77802_regulator_prv *max77802;
-       int i, val;
-       struct regulator_config config = { };
-
-       max77802 = devm_kzalloc(&pdev->dev,
-                               sizeof(struct max77802_regulator_prv),
-                               GFP_KERNEL);
-       if (!max77802)
-               return -ENOMEM;
-
-       config.dev = iodev->dev;
-       config.regmap = iodev->regmap;
-       config.driver_data = max77802;
-       platform_set_drvdata(pdev, max77802);
-
-       for (i = 0; i < MAX77802_REG_MAX; i++) {
-               struct regulator_dev *rdev;
-               int id = regulators[i].id;
-               int shift = max77802_get_opmode_shift(id);
-               int ret;
-
-               ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val);
-               if (ret < 0) {
-                       dev_warn(&pdev->dev,
-                               "cannot read current mode for %d\n", i);
-                       val = MAX77802_OPMODE_NORMAL;
-               } else {
-                       val = val >> shift & MAX77802_OPMODE_MASK;
-               }
-
-               /*
-                * If the regulator is disabled and the system warm rebooted,
-                * the hardware reports OFF as the regulator operating mode.
-                * Default to operating mode NORMAL in that case.
-                */
-               if (val == MAX77802_STATUS_OFF)
-                       max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
-               else
-                       max77802->opmode[id] = val;
-
-               rdev = devm_regulator_register(&pdev->dev,
-                                              &regulators[i], &config);
-               if (IS_ERR(rdev)) {
-                       ret = PTR_ERR(rdev);
-                       dev_err(&pdev->dev,
-                               "regulator init failed for %d: %d\n", i, ret);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-static const struct platform_device_id max77802_pmic_id[] = {
-       {"max77802-pmic", 0},
-       { },
-};
-MODULE_DEVICE_TABLE(platform, max77802_pmic_id);
-
-static struct platform_driver max77802_pmic_driver = {
-       .driver = {
-               .name = "max77802-pmic",
-       },
-       .probe = max77802_pmic_probe,
-       .id_table = max77802_pmic_id,
-};
-
-module_platform_driver(max77802_pmic_driver);
-
-MODULE_DESCRIPTION("MAXIM 77802 Regulator Driver");
-MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
-MODULE_LICENSE("GPL");
index a5b2f4762677c706c59712417a8c44627670773c..17a5b6c2d6a9f5d71c0bafded4f56d26c89fb3ce 100644 (file)
@@ -317,11 +317,25 @@ static int mt6397_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
+static const struct platform_device_id mt6397_platform_ids[] = {
+       {"mt6397-regulator", 0},
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(platform, mt6397_platform_ids);
+
+static const struct of_device_id mt6397_of_match[] = {
+       { .compatible = "mediatek,mt6397-regulator", },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mt6397_of_match);
+
 static struct platform_driver mt6397_regulator_driver = {
        .driver = {
                .name = "mt6397-regulator",
+               .of_match_table = of_match_ptr(mt6397_of_match),
        },
        .probe = mt6397_regulator_probe,
+       .id_table = mt6397_platform_ids,
 };
 
 module_platform_driver(mt6397_regulator_driver);
@@ -329,4 +343,3 @@ module_platform_driver(mt6397_regulator_driver);
 MODULE_AUTHOR("Flora Fu <flora.fu@mediatek.com>");
 MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:mt6397-regulator");
index 499e437c7e919f2576c694ef6b6466898d006dbf..6b0aa80b22fd1b4817c65995dfc1424fbb3d0c31 100644 (file)
@@ -28,7 +28,6 @@ static void of_get_regulation_constraints(struct device_node *np,
                                        struct regulator_init_data **init_data,
                                        const struct regulator_desc *desc)
 {
-       const __be32 *min_uV, *max_uV;
        struct regulation_constraints *constraints = &(*init_data)->constraints;
        struct regulator_state *suspend_state;
        struct device_node *suspend_np;
@@ -37,18 +36,18 @@ static void of_get_regulation_constraints(struct device_node *np,
 
        constraints->name = of_get_property(np, "regulator-name", NULL);
 
-       min_uV = of_get_property(np, "regulator-min-microvolt", NULL);
-       if (min_uV)
-               constraints->min_uV = be32_to_cpu(*min_uV);
-       max_uV = of_get_property(np, "regulator-max-microvolt", NULL);
-       if (max_uV)
-               constraints->max_uV = be32_to_cpu(*max_uV);
+       if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
+               constraints->min_uV = pval;
+
+       if (!of_property_read_u32(np, "regulator-max-microvolt", &pval))
+               constraints->max_uV = pval;
 
        /* Voltage change possible? */
        if (constraints->min_uV != constraints->max_uV)
                constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
        /* Only one voltage?  Then make sure it's set. */
-       if (min_uV && max_uV && constraints->min_uV == constraints->max_uV)
+       if (constraints->min_uV && constraints->max_uV &&
+           constraints->min_uV == constraints->max_uV)
                constraints->apply_uV = true;
 
        if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
@@ -93,6 +92,12 @@ static void of_get_regulation_constraints(struct device_node *np,
 
        constraints->soft_start = of_property_read_bool(np,
                                        "regulator-soft-start");
+       ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
+       if (!ret) {
+               constraints->active_discharge =
+                               (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
+                                       REGULATOR_ACTIVE_DISCHARGE_DISABLE;
+       }
 
        if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
                if (desc && desc->of_map_mode) {
index 094376c8de4bdb1ae8a5de350d209c267f15a2fd..c448b727f5f81702aa7fb2ad8604abf8338f5f66 100644 (file)
@@ -285,8 +285,8 @@ static irqreturn_t pv88060_irq_handler(int irq, void *data)
                        }
                }
 
-               err = regmap_update_bits(chip->regmap, PV88060_REG_EVENT_A,
-                       PV88060_E_VDD_FLT, PV88060_E_VDD_FLT);
+               err = regmap_write(chip->regmap, PV88060_REG_EVENT_A,
+                       PV88060_E_VDD_FLT);
                if (err < 0)
                        goto error_i2c;
 
@@ -302,8 +302,8 @@ static irqreturn_t pv88060_irq_handler(int irq, void *data)
                        }
                }
 
-               err = regmap_update_bits(chip->regmap, PV88060_REG_EVENT_A,
-                       PV88060_E_OVER_TEMP, PV88060_E_OVER_TEMP);
+               err = regmap_write(chip->regmap, PV88060_REG_EVENT_A,
+                       PV88060_E_OVER_TEMP);
                if (err < 0)
                        goto error_i2c;
 
index ac15f31b5fe0cc83061ef002b32b9c7aaae5dc06..0057c6740d6f569f0921164ddcbfec27dd4cd91d 100644 (file)
@@ -283,8 +283,8 @@ static irqreturn_t pv88090_irq_handler(int irq, void *data)
                        }
                }
 
-               err = regmap_update_bits(chip->regmap, PV88090_REG_EVENT_A,
-                       PV88090_E_VDD_FLT, PV88090_E_VDD_FLT);
+               err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
+                       PV88090_E_VDD_FLT);
                if (err < 0)
                        goto error_i2c;
 
@@ -300,8 +300,8 @@ static irqreturn_t pv88090_irq_handler(int irq, void *data)
                        }
                }
 
-               err = regmap_update_bits(chip->regmap, PV88090_REG_EVENT_A,
-                       PV88090_E_OVER_TEMP, PV88090_E_OVER_TEMP);
+               err = regmap_write(chip->regmap, PV88090_REG_EVENT_A,
+                       PV88090_E_OVER_TEMP);
                if (err < 0)
                        goto error_i2c;
 
index 3aca067b990114f7e0618fdfb963d6f66c21c37a..4689d62f48414a986dbd9f0ea7cdaf4d2c872b22 100644 (file)
@@ -27,6 +27,13 @@ struct pwm_regulator_data {
 
        /* Voltage table */
        struct pwm_voltages *duty_cycle_table;
+
+       /* regulator descriptor */
+       struct regulator_desc desc;
+
+       /* Regulator ops */
+       struct regulator_ops ops;
+
        int state;
 
        /* Continuous voltage */
@@ -115,7 +122,7 @@ static int pwm_voltage_to_duty_cycle_percentage(struct regulator_dev *rdev, int
        int max_uV = rdev->constraints->max_uV;
        int diff = max_uV - min_uV;
 
-       return 100 - (((req_uV * 100) - (min_uV * 100)) / diff);
+       return ((req_uV * 100) - (min_uV * 100)) / diff;
 }
 
 static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
@@ -212,8 +219,10 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
        }
 
        drvdata->duty_cycle_table       = duty_cycle_table;
-       pwm_regulator_desc.ops          = &pwm_regulator_voltage_table_ops;
-       pwm_regulator_desc.n_voltages   = length / sizeof(*duty_cycle_table);
+       memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops,
+              sizeof(drvdata->ops));
+       drvdata->desc.ops = &drvdata->ops;
+       drvdata->desc.n_voltages        = length / sizeof(*duty_cycle_table);
 
        return 0;
 }
@@ -221,8 +230,10 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
 static int pwm_regulator_init_continuous(struct platform_device *pdev,
                                         struct pwm_regulator_data *drvdata)
 {
-       pwm_regulator_desc.ops = &pwm_regulator_voltage_continuous_ops;
-       pwm_regulator_desc.continuous_voltage_range = true;
+       memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops,
+              sizeof(drvdata->ops));
+       drvdata->desc.ops = &drvdata->ops;
+       drvdata->desc.continuous_voltage_range = true;
 
        return 0;
 }
@@ -245,6 +256,8 @@ static int pwm_regulator_probe(struct platform_device *pdev)
        if (!drvdata)
                return -ENOMEM;
 
+       memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(drvdata->desc));
+
        if (of_find_property(np, "voltage-table", NULL))
                ret = pwm_regulator_init_table(pdev, drvdata);
        else
@@ -253,7 +266,7 @@ static int pwm_regulator_probe(struct platform_device *pdev)
                return ret;
 
        init_data = of_get_regulator_init_data(&pdev->dev, np,
-                                              &pwm_regulator_desc);
+                                              &drvdata->desc);
        if (!init_data)
                return -ENOMEM;
 
@@ -269,10 +282,10 @@ static int pwm_regulator_probe(struct platform_device *pdev)
        }
 
        regulator = devm_regulator_register(&pdev->dev,
-                                           &pwm_regulator_desc, &config);
+                                           &drvdata->desc, &config);
        if (IS_ERR(regulator)) {
                dev_err(&pdev->dev, "Failed to register regulator %s\n",
-                       pwm_regulator_desc.name);
+                       drvdata->desc.name);
                return PTR_ERR(regulator);
        }
 
index 3242ffc0cb25afdfa8adad11fd40878b6153f1b6..d24e2c783dc5c9a093220c4e98980813ad9e309f 100644 (file)
@@ -38,7 +38,6 @@
 /* The highest number of possible regulators for supported devices. */
 #define S2MPS_REGULATOR_MAX            S2MPS13_REGULATOR_MAX
 struct s2mps11_info {
-       unsigned int rdev_num;
        int ramp_delay2;
        int ramp_delay34;
        int ramp_delay5;
@@ -54,7 +53,10 @@ struct s2mps11_info {
         */
        DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX);
 
-       /* Array of size rdev_num with GPIO-s for external sleep control */
+       /*
+        * Array (size: number of regulators) with GPIO-s for external
+        * sleep control.
+        */
        int *ext_control_gpio;
 };
 
@@ -819,7 +821,8 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
 }
 
 static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
-               struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
+               struct of_regulator_match *rdata, struct s2mps11_info *s2mps11,
+               unsigned int rdev_num)
 {
        struct device_node *reg_np;
 
@@ -829,7 +832,7 @@ static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
                return -EINVAL;
        }
 
-       of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
+       of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num);
        if (s2mps11->dev_type == S2MPS14X)
                s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
 
@@ -1077,6 +1080,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
        struct of_regulator_match *rdata = NULL;
        struct regulator_config config = { };
        struct s2mps11_info *s2mps11;
+       unsigned int rdev_num = 0;
        int i, ret = 0;
        const struct regulator_desc *regulators;
 
@@ -1088,28 +1092,29 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
        s2mps11->dev_type = platform_get_device_id(pdev)->driver_data;
        switch (s2mps11->dev_type) {
        case S2MPS11X:
-               s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
+               rdev_num = ARRAY_SIZE(s2mps11_regulators);
                regulators = s2mps11_regulators;
-               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
+               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps11_regulators));
                break;
        case S2MPS13X:
-               s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
+               rdev_num = ARRAY_SIZE(s2mps13_regulators);
                regulators = s2mps13_regulators;
-               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
+               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps13_regulators));
                break;
        case S2MPS14X:
-               s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
+               rdev_num = ARRAY_SIZE(s2mps14_regulators);
                regulators = s2mps14_regulators;
-               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
+               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps14_regulators));
                break;
        case S2MPS15X:
-               s2mps11->rdev_num = ARRAY_SIZE(s2mps15_regulators);
+               rdev_num = ARRAY_SIZE(s2mps15_regulators);
                regulators = s2mps15_regulators;
+               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mps15_regulators));
                break;
        case S2MPU02:
-               s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
+               rdev_num = ARRAY_SIZE(s2mpu02_regulators);
                regulators = s2mpu02_regulators;
-               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
+               BUILD_BUG_ON(S2MPS_REGULATOR_MAX < ARRAY_SIZE(s2mpu02_regulators));
                break;
        default:
                dev_err(&pdev->dev, "Invalid device type: %u\n",
@@ -1118,7 +1123,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
        }
 
        s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev,
-                       sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num,
+                       sizeof(*s2mps11->ext_control_gpio) * rdev_num,
                        GFP_KERNEL);
        if (!s2mps11->ext_control_gpio)
                return -ENOMEM;
@@ -1126,7 +1131,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
         * 0 is a valid GPIO so initialize all GPIO-s to negative value
         * to indicate that external control won't be used for this regulator.
         */
-       for (i = 0; i < s2mps11->rdev_num; i++)
+       for (i = 0; i < rdev_num; i++)
                s2mps11->ext_control_gpio[i] = -EINVAL;
 
        if (!iodev->dev->of_node) {
@@ -1140,14 +1145,14 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
                }
        }
 
-       rdata = kzalloc(sizeof(*rdata) * s2mps11->rdev_num, GFP_KERNEL);
+       rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL);
        if (!rdata)
                return -ENOMEM;
 
-       for (i = 0; i < s2mps11->rdev_num; i++)
+       for (i = 0; i < rdev_num; i++)
                rdata[i].name = regulators[i].name;
 
-       ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11);
+       ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, rdev_num);
        if (ret)
                goto out;
 
@@ -1159,7 +1164,7 @@ common_reg:
        config.driver_data = s2mps11;
        config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
        config.ena_gpio_initialized = true;
-       for (i = 0; i < s2mps11->rdev_num; i++) {
+       for (i = 0; i < rdev_num; i++) {
                struct regulator_dev *regulator;
 
                if (pdata) {
index 58f5d3b8e9818a224c58e1299fdb769f94fd4f98..27343e1c43ef8bee1b3e10dbaf79f293bd81b70f 100644 (file)
@@ -202,9 +202,10 @@ static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id,
                }
        }
 
-       if (i < s5m8767->num_regulators)
-               *enable_ctrl =
-               s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
+       if (i >= s5m8767->num_regulators)
+               return -EINVAL;
+
+       *enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
 
        return 0;
 }
@@ -937,8 +938,12 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
                        else
                                regulators[id].vsel_mask = 0xff;
 
-                       s5m8767_get_register(s5m8767, id, &enable_reg,
+                       ret = s5m8767_get_register(s5m8767, id, &enable_reg,
                                             &enable_val);
+                       if (ret) {
+                               dev_err(s5m8767->dev, "error reading registers\n");
+                               return ret;
+                       }
                        regulators[id].enable_reg = enable_reg;
                        regulators[id].enable_mask = S5M8767_ENCTRL_MASK;
                        regulators[id].enable_val = enable_val;
diff --git a/drivers/regulator/vexpress-regulator.c b/drivers/regulator/vexpress-regulator.c
new file mode 100644 (file)
index 0000000..c810cbb
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-regulator"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/vexpress.h>
+
+struct vexpress_regulator {
+       struct regulator_desc desc;
+       struct regulator_dev *regdev;
+       struct regmap *regmap;
+};
+
+static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+       u32 uV;
+       int err = regmap_read(reg->regmap, 0, &uV);
+
+       return err ? err : uV;
+}
+
+static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
+               int min_uV, int max_uV, unsigned *selector)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+
+       return regmap_write(reg->regmap, 0, min_uV);
+}
+
+static struct regulator_ops vexpress_regulator_ops_ro = {
+       .get_voltage = vexpress_regulator_get_voltage,
+};
+
+static struct regulator_ops vexpress_regulator_ops = {
+       .get_voltage = vexpress_regulator_get_voltage,
+       .set_voltage = vexpress_regulator_set_voltage,
+};
+
+static int vexpress_regulator_probe(struct platform_device *pdev)
+{
+       struct vexpress_regulator *reg;
+       struct regulator_init_data *init_data;
+       struct regulator_config config = { };
+
+       reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
+       if (!reg)
+               return -ENOMEM;
+
+       reg->regmap = devm_regmap_init_vexpress_config(&pdev->dev);
+       if (IS_ERR(reg->regmap))
+               return PTR_ERR(reg->regmap);
+
+       reg->desc.name = dev_name(&pdev->dev);
+       reg->desc.type = REGULATOR_VOLTAGE;
+       reg->desc.owner = THIS_MODULE;
+       reg->desc.continuous_voltage_range = true;
+
+       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
+                                              &reg->desc);
+       if (!init_data)
+               return -EINVAL;
+
+       init_data->constraints.apply_uV = 0;
+       if (init_data->constraints.min_uV && init_data->constraints.max_uV)
+               reg->desc.ops = &vexpress_regulator_ops;
+       else
+               reg->desc.ops = &vexpress_regulator_ops_ro;
+
+       config.dev = &pdev->dev;
+       config.init_data = init_data;
+       config.driver_data = reg;
+       config.of_node = pdev->dev.of_node;
+
+       reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config);
+       if (IS_ERR(reg->regdev))
+               return PTR_ERR(reg->regdev);
+
+       platform_set_drvdata(pdev, reg);
+
+       return 0;
+}
+
+static const struct of_device_id vexpress_regulator_of_match[] = {
+       { .compatible = "arm,vexpress-volt", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, vexpress_regulator_of_match);
+
+static struct platform_driver vexpress_regulator_driver = {
+       .probe = vexpress_regulator_probe,
+       .driver = {
+               .name = DRVNAME,
+               .of_match_table = vexpress_regulator_of_match,
+       },
+};
+
+module_platform_driver(vexpress_regulator_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-regulator");
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
deleted file mode 100644 (file)
index c810cbb..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * Copyright (C) 2012 ARM Limited
- */
-
-#define DRVNAME "vexpress-regulator"
-#define pr_fmt(fmt) DRVNAME ": " fmt
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/vexpress.h>
-
-struct vexpress_regulator {
-       struct regulator_desc desc;
-       struct regulator_dev *regdev;
-       struct regmap *regmap;
-};
-
-static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
-{
-       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
-       u32 uV;
-       int err = regmap_read(reg->regmap, 0, &uV);
-
-       return err ? err : uV;
-}
-
-static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
-               int min_uV, int max_uV, unsigned *selector)
-{
-       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
-
-       return regmap_write(reg->regmap, 0, min_uV);
-}
-
-static struct regulator_ops vexpress_regulator_ops_ro = {
-       .get_voltage = vexpress_regulator_get_voltage,
-};
-
-static struct regulator_ops vexpress_regulator_ops = {
-       .get_voltage = vexpress_regulator_get_voltage,
-       .set_voltage = vexpress_regulator_set_voltage,
-};
-
-static int vexpress_regulator_probe(struct platform_device *pdev)
-{
-       struct vexpress_regulator *reg;
-       struct regulator_init_data *init_data;
-       struct regulator_config config = { };
-
-       reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
-       if (!reg)
-               return -ENOMEM;
-
-       reg->regmap = devm_regmap_init_vexpress_config(&pdev->dev);
-       if (IS_ERR(reg->regmap))
-               return PTR_ERR(reg->regmap);
-
-       reg->desc.name = dev_name(&pdev->dev);
-       reg->desc.type = REGULATOR_VOLTAGE;
-       reg->desc.owner = THIS_MODULE;
-       reg->desc.continuous_voltage_range = true;
-
-       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node,
-                                              &reg->desc);
-       if (!init_data)
-               return -EINVAL;
-
-       init_data->constraints.apply_uV = 0;
-       if (init_data->constraints.min_uV && init_data->constraints.max_uV)
-               reg->desc.ops = &vexpress_regulator_ops;
-       else
-               reg->desc.ops = &vexpress_regulator_ops_ro;
-
-       config.dev = &pdev->dev;
-       config.init_data = init_data;
-       config.driver_data = reg;
-       config.of_node = pdev->dev.of_node;
-
-       reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config);
-       if (IS_ERR(reg->regdev))
-               return PTR_ERR(reg->regdev);
-
-       platform_set_drvdata(pdev, reg);
-
-       return 0;
-}
-
-static const struct of_device_id vexpress_regulator_of_match[] = {
-       { .compatible = "arm,vexpress-volt", },
-       { }
-};
-MODULE_DEVICE_TABLE(of, vexpress_regulator_of_match);
-
-static struct platform_driver vexpress_regulator_driver = {
-       .probe = vexpress_regulator_probe,
-       .driver = {
-               .name = DRVNAME,
-               .of_match_table = vexpress_regulator_of_match,
-       },
-};
-
-module_platform_driver(vexpress_regulator_driver);
-
-MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
-MODULE_DESCRIPTION("Versatile Express regulator");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:vexpress-regulator");
index 376322f71fd5723c90863298f4b4ed3eb7750d6e..544bd3493852a0fcca9599a94f62c72f02767f49 100644 (file)
@@ -140,7 +140,6 @@ config RTC_DRV_TEST
          will be called rtc-test.
 
 comment "I2C RTC drivers"
-       depends on I2C
 
 if I2C
 
@@ -212,6 +211,15 @@ config RTC_DRV_DS1307
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1307.
 
+config RTC_DRV_DS1307_HWMON
+       bool "HWMON support for rtc-ds1307"
+       depends on RTC_DRV_DS1307 && HWMON
+       depends on !(RTC_DRV_DS1307=y && HWMON=m)
+       default y
+       help
+         Say Y here if you want to expose temperature sensor data on
+         rtc-ds1307 (only DS3231)
+
 config RTC_DRV_DS1374
        tristate "Dallas/Maxim DS1374"
        help
@@ -239,16 +247,6 @@ config RTC_DRV_DS1672
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1672.
 
-config RTC_DRV_DS3232
-       tristate "Dallas/Maxim DS3232"
-       help
-         If you say yes here you get support for Dallas Semiconductor
-         DS3232 real-time clock chips. If an interrupt is associated
-         with the device, the alarm functionality is supported.
-
-         This driver can also be built as a module.  If so, the module
-         will be called rtc-ds3232.
-
 config RTC_DRV_HYM8563
        tristate "Haoyu Microelectronics HYM8563"
        depends on OF
@@ -317,10 +315,10 @@ config RTC_DRV_MAX8997
 
 config RTC_DRV_MAX77686
        tristate "Maxim MAX77686"
-       depends on MFD_MAX77686
+       depends on MFD_MAX77686 || MFD_MAX77620
        help
          If you say yes here you will get support for the
-         RTC of Maxim MAX77686 PMIC.
+         RTC of Maxim MAX77686/MAX77620/MAX77802 PMIC.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-max77686.
@@ -335,16 +333,6 @@ config RTC_DRV_RK808
          This driver can also be built as a module. If so, the module
          will be called rk808-rtc.
 
-config RTC_DRV_MAX77802
-       tristate "Maxim 77802 RTC"
-       depends on MFD_MAX77686
-       help
-         If you say yes here you will get support for the
-         RTC of Maxim MAX77802 PMIC.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-max77802.
-
 config RTC_DRV_RS5C372
        tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
        help
@@ -391,25 +379,6 @@ config RTC_DRV_X1205
          This driver can also be built as a module. If so, the module
          will be called rtc-x1205.
 
-config RTC_DRV_PALMAS
-       tristate "TI Palmas RTC driver"
-       depends on MFD_PALMAS
-       help
-         If you say yes here you get support for the RTC of TI PALMA series PMIC
-         chips.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-palma.
-
-config RTC_DRV_PCF2127
-       tristate "NXP PCF2127"
-       help
-         If you say yes here you get support for the NXP PCF2127/29 RTC
-         chips.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-pcf2127.
-
 config RTC_DRV_PCF8523
        tristate "NXP PCF8523"
        help
@@ -419,6 +388,14 @@ config RTC_DRV_PCF8523
          This driver can also be built as a module. If so, the module
          will be called rtc-pcf8523.
 
+config RTC_DRV_PCF85063
+       tristate "NXP PCF85063"
+       help
+         If you say yes here you get support for the PCF85063 RTC chip
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-pcf85063.
+
 config RTC_DRV_PCF8563
        tristate "Philips PCF8563/Epson RTC8564"
        help
@@ -429,14 +406,6 @@ config RTC_DRV_PCF8563
          This driver can also be built as a module. If so, the module
          will be called rtc-pcf8563.
 
-config RTC_DRV_PCF85063
-       tristate "nxp PCF85063"
-       help
-         If you say yes here you get support for the PCF85063 RTC chip
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-pcf85063.
-
 config RTC_DRV_PCF8583
        tristate "Philips PCF8583"
        help
@@ -501,6 +470,16 @@ config RTC_DRV_TWL4030
          This driver can also be built as a module. If so, the module
          will be called rtc-twl.
 
+config RTC_DRV_PALMAS
+       tristate "TI Palmas RTC driver"
+       depends on MFD_PALMAS
+       help
+         If you say yes here you get support for the RTC of TI PALMA series PMIC
+         chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-palma.
+
 config RTC_DRV_TPS6586X
        tristate "TI TPS6586X RTC driver"
        depends on MFD_TPS6586X
@@ -595,14 +574,23 @@ config RTC_DRV_EM3027
          will be called rtc-em3027.
 
 config RTC_DRV_RV3029C2
-       tristate "Micro Crystal RTC"
+       tristate "Micro Crystal RV3029"
        help
          If you say yes here you get support for the Micro Crystal
-         RV3029-C2 RTC chips.
+         RV3029 RTC chips.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-rv3029c2.
 
+config RTC_DRV_RV3029_HWMON
+       bool "HWMON support for RV3029"
+       depends on RTC_DRV_RV3029C2 && HWMON
+       depends on !(RTC_DRV_RV3029C2=y && HWMON=m)
+       default y
+       help
+         Say Y here if you want to expose temperature sensor data on
+         rtc-rv3029c2.
+
 config RTC_DRV_RV8803
        tristate "Micro Crystal RV8803"
        help
@@ -691,15 +679,6 @@ config RTC_DRV_DS1390
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1390.
 
-config RTC_DRV_MAX6902
-       tristate "Maxim MAX6902"
-       help
-         If you say yes here you will get support for the
-         Maxim MAX6902 SPI RTC chip.
-
-         This driver can also be built as a module. If so, the module
-         will be called rtc-max6902.
-
 config RTC_DRV_R9701
        tristate "Epson RTC-9701JE"
        help
@@ -709,6 +688,23 @@ config RTC_DRV_R9701
          This driver can also be built as a module. If so, the module
          will be called rtc-r9701.
 
+config RTC_DRV_RX4581
+       tristate "Epson RX-4581"
+       help
+         If you say yes here you will get support for the Epson RX-4581.
+
+         This driver can also be built as a module. If so the module
+         will be called rtc-rx4581.
+
+config RTC_DRV_RX6110
+       tristate "Epson RX-6110"
+       select REGMAP_SPI
+       help
+         If you say yes here you will get support for the Epson RX-6610.
+
+         This driver can also be built as a module. If so the module
+         will be called rtc-rx6110.
+
 config RTC_DRV_RS5C348
        tristate "Ricoh RS5C348A/B"
        help
@@ -718,14 +714,14 @@ config RTC_DRV_RS5C348
          This driver can also be built as a module. If so, the module
          will be called rtc-rs5c348.
 
-config RTC_DRV_DS3234
-       tristate "Maxim/Dallas DS3234"
+config RTC_DRV_MAX6902
+       tristate "Maxim MAX6902"
        help
-         If you say yes here you get support for the
-         Maxim/Dallas DS3234 SPI RTC chip.
+         If you say yes here you will get support for the
+         Maxim MAX6902 SPI RTC chip.
 
          This driver can also be built as a module. If so, the module
-         will be called rtc-ds3234.
+         will be called rtc-max6902.
 
 config RTC_DRV_PCF2123
        tristate "NXP PCF2123"
@@ -736,14 +732,6 @@ config RTC_DRV_PCF2123
          This driver can also be built as a module. If so, the module
          will be called rtc-pcf2123.
 
-config RTC_DRV_RX4581
-       tristate "Epson RX-4581"
-       help
-         If you say yes here you will get support for the Epson RX-4581.
-
-         This driver can also be built as a module. If so the module
-         will be called rtc-rx4581.
-
 config RTC_DRV_MCP795
        tristate "Microchip MCP795"
        help
@@ -754,6 +742,41 @@ config RTC_DRV_MCP795
 
 endif # SPI_MASTER
 
+#
+# Helper to resolve issues with configs that have SPI enabled but I2C
+# modular.  See SND_SOC_I2C_AND_SPI for more information
+#
+config RTC_I2C_AND_SPI
+       tristate
+       default m if I2C=m
+       default y if I2C=y
+       default y if SPI_MASTER=y
+       select REGMAP_I2C if I2C
+       select REGMAP_SPI if SPI_MASTER
+
+comment "SPI and I2C RTC drivers"
+
+config RTC_DRV_DS3232
+       tristate "Dallas/Maxim DS3232/DS3234"
+       depends on RTC_I2C_AND_SPI
+       help
+         If you say yes here you get support for Dallas Semiconductor
+         DS3232 and DS3234 real-time clock chips. If an interrupt is associated
+         with the device, the alarm functionality is supported.
+
+         This driver can also be built as a module.  If so, the module
+         will be called rtc-ds3232.
+
+config RTC_DRV_PCF2127
+       tristate "NXP PCF2127"
+       depends on RTC_I2C_AND_SPI
+       help
+         If you say yes here you get support for the NXP PCF2127/29 RTC
+         chips.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-pcf2127.
+
 comment "Platform RTC drivers"
 
 # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
@@ -1087,7 +1110,7 @@ config RTC_DRV_WM8350
 
 config RTC_DRV_SPEAR
        tristate "SPEAR ST RTC"
-       depends on PLAT_SPEAR
+       depends on PLAT_SPEAR || COMPILE_TEST
        default y
        help
         If you say Y here you will get support for the RTC found on
@@ -1119,7 +1142,7 @@ config RTC_DRV_AB8500
 
 config RTC_DRV_NUC900
        tristate "NUC910/NUC920 RTC driver"
-       depends on ARCH_W90X900
+       depends on ARCH_W90X900 || COMPILE_TEST
        help
          If you say yes here you get support for the RTC subsystem of the
          NUC910/NUC920 used in embedded systems.
@@ -1144,9 +1167,19 @@ config RTC_DRV_ZYNQMP
 
 comment "on-CPU RTC drivers"
 
+config RTC_DRV_ASM9260
+       tristate "Alphascale asm9260 RTC"
+       depends on MACH_ASM9260
+       help
+         If you say yes here you get support for the RTC on the
+         Alphascale asm9260 SoC.
+
+         This driver can also be built as a module. If so, the module
+         will be called rtc-asm9260.
+
 config RTC_DRV_DAVINCI
        tristate "TI DaVinci RTC"
-       depends on ARCH_DAVINCI_DM365
+       depends on ARCH_DAVINCI_DM365 || COMPILE_TEST
        help
          If you say yes here you get support for the RTC on the
          DaVinci platforms (DM365).
@@ -1156,7 +1189,7 @@ config RTC_DRV_DAVINCI
 
 config RTC_DRV_DIGICOLOR
        tristate "Conexant Digicolor RTC"
-       depends on ARCH_DIGICOLOR
+       depends on ARCH_DIGICOLOR || COMPILE_TEST
        help
          If you say yes here you get support for the RTC on Conexant
          Digicolor platforms. This currently includes the CX92755 SoC.
@@ -1175,7 +1208,7 @@ config RTC_DRV_IMXDI
 
 config RTC_DRV_OMAP
        tristate "TI OMAP Real Time Clock"
-       depends on ARCH_OMAP || ARCH_DAVINCI
+       depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST
        help
          Say "yes" here to support the on chip real time clock
          present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
@@ -1192,7 +1225,7 @@ config HAVE_S3C_RTC
 
 config RTC_DRV_S3C
        tristate "Samsung S3C series SoC RTC"
-       depends on ARCH_S3C64XX || HAVE_S3C_RTC
+       depends on ARCH_S3C64XX || HAVE_S3C_RTC || COMPILE_TEST
        help
          RTC (Realtime Clock) driver for the clock inbuilt into the
          Samsung S3C24XX series of SoCs. This can provide periodic
@@ -1208,7 +1241,7 @@ config RTC_DRV_S3C
 
 config RTC_DRV_EP93XX
        tristate "Cirrus Logic EP93XX"
-       depends on ARCH_EP93XX
+       depends on ARCH_EP93XX || COMPILE_TEST
        help
          If you say yes here you get support for the
          RTC embedded in the Cirrus Logic EP93XX processors.
@@ -1238,7 +1271,7 @@ config RTC_DRV_SH
 
 config RTC_DRV_VR41XX
        tristate "NEC VR41XX"
-       depends on CPU_VR41XX
+       depends on CPU_VR41XX || COMPILE_TEST
        help
          If you say Y here you will get access to the real time clock
          built into your NEC VR41XX CPU.
@@ -1268,14 +1301,14 @@ config RTC_DRV_PL031
 
 config RTC_DRV_AT32AP700X
        tristate "AT32AP700X series RTC"
-       depends on PLATFORM_AT32AP
+       depends on PLATFORM_AT32AP || COMPILE_TEST
        help
          Driver for the internal RTC (Realtime Clock) on Atmel AVR32
          AT32AP700x family processors.
 
 config RTC_DRV_AT91RM9200
        tristate "AT91RM9200 or some AT91SAM9 RTC"
-       depends on ARCH_AT91
+       depends on ARCH_AT91 || COMPILE_TEST
        help
          Driver for the internal RTC (Realtime Clock) module found on
          Atmel AT91RM9200's and some  AT91SAM9 chips. On AT91SAM9 chips
@@ -1283,7 +1316,7 @@ config RTC_DRV_AT91RM9200
 
 config RTC_DRV_AT91SAM9
        tristate "AT91SAM9 RTT as RTC"
-       depends on ARCH_AT91
+       depends on ARCH_AT91 || COMPILE_TEST
        select MFD_SYSCON
        help
          Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which
@@ -1325,17 +1358,17 @@ config RTC_DRV_GENERIC
        tristate "Generic RTC support"
        # Please consider writing a new RTC driver instead of using the generic
        # RTC abstraction
-       depends on PARISC || M68K || PPC || SUPERH32
+       depends on PARISC || M68K || PPC || SUPERH32 || COMPILE_TEST
        help
          Say Y or M here to enable RTC support on systems using the generic
          RTC abstraction. If you do not know what you are doing, you should
          just say Y.
 
 config RTC_DRV_PXA
-       tristate "PXA27x/PXA3xx"
-       depends on ARCH_PXA
-       select RTC_DRV_SA1100
-       help
+       tristate "PXA27x/PXA3xx"
+       depends on ARCH_PXA
+       select RTC_DRV_SA1100
+       help
          If you say Y here you will get access to the real time clock
          built into your PXA27x or PXA3xx CPU. This RTC is actually 2 RTCs
          consisting of an SA1100 compatible RTC and the extended PXA RTC.
@@ -1345,7 +1378,7 @@ config RTC_DRV_PXA
 
 config RTC_DRV_VT8500
        tristate "VIA/WonderMedia 85xx SoC RTC"
-       depends on ARCH_VT8500
+       depends on ARCH_VT8500 || COMPILE_TEST
        help
          If you say Y here you will get access to the real time clock
          built into your VIA VT8500 SoC or its relatives.
@@ -1360,14 +1393,15 @@ config RTC_DRV_SUN4V
 
 config RTC_DRV_SUN6I
        tristate "Allwinner A31 RTC"
-       depends on MACH_SUN6I || MACH_SUN8I
+       default MACH_SUN6I || MACH_SUN8I || COMPILE_TEST
+       depends on ARCH_SUNXI
        help
-         If you say Y here you will get support for the RTC found on
-         Allwinner A31.
+         If you say Y here you will get support for the RTC found in
+         some Allwinner SoCs like the A31 or the A64.
 
 config RTC_DRV_SUNXI
        tristate "Allwinner sun4i/sun7i RTC"
-       depends on MACH_SUN4I || MACH_SUN7I
+       depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
        help
          If you say Y here you will get support for the RTC found on
          Allwinner A10/A20.
@@ -1388,7 +1422,7 @@ config RTC_DRV_TX4939
 
 config RTC_DRV_MV
        tristate "Marvell SoC RTC"
-       depends on ARCH_DOVE || ARCH_MVEBU
+       depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST
        help
          If you say yes here you will get support for the in-chip RTC
          that can be found in some of Marvell's SoC devices, such as
@@ -1399,7 +1433,7 @@ config RTC_DRV_MV
 
 config RTC_DRV_ARMADA38X
        tristate "Armada 38x Marvell SoC RTC"
-       depends on ARCH_MVEBU
+       depends on ARCH_MVEBU || COMPILE_TEST
        help
          If you say yes here you will get support for the in-chip RTC
          that can be found in the Armada 38x Marvell's SoC device
@@ -1429,7 +1463,7 @@ config RTC_DRV_PS3
 
 config RTC_DRV_COH901331
        tristate "ST-Ericsson COH 901 331 RTC"
-       depends on ARCH_U300
+       depends on ARCH_U300 || COMPILE_TEST
        help
          If you say Y here you will get access to ST-Ericsson
          COH 901 331 RTC clock found in some ST-Ericsson Mobile
@@ -1441,7 +1475,7 @@ config RTC_DRV_COH901331
 
 config RTC_DRV_STMP
        tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC"
-       depends on ARCH_MXS
+       depends on ARCH_MXS || COMPILE_TEST
        select STMP_DEVICE
        help
          If you say yes here you will get support for the onboard
@@ -1476,7 +1510,7 @@ config RTC_DRV_MPC5121
 
 config RTC_DRV_JZ4740
        tristate "Ingenic JZ4740 SoC"
-       depends on MACH_JZ4740
+       depends on MACH_JZ4740 || COMPILE_TEST
        help
          If you say yes here you get support for the Ingenic JZ4740 SoC RTC
          controller.
@@ -1497,7 +1531,7 @@ config RTC_DRV_LPC24XX
          so, the module will be called rtc-lpc24xx.
 
 config RTC_DRV_LPC32XX
-       depends on ARCH_LPC32XX
+       depends on ARCH_LPC32XX || COMPILE_TEST
        tristate "NXP LPC32XX RTC"
        help
          This enables support for the NXP RTC in the LPC32XX
@@ -1507,7 +1541,7 @@ config RTC_DRV_LPC32XX
 
 config RTC_DRV_PM8XXX
        tristate "Qualcomm PMIC8XXX RTC"
-       depends on MFD_PM8XXX || MFD_SPMI_PMIC
+       depends on MFD_PM8XXX || MFD_SPMI_PMIC || COMPILE_TEST
        help
          If you say yes here you get support for the
          Qualcomm PMIC8XXX RTC.
@@ -1517,7 +1551,7 @@ config RTC_DRV_PM8XXX
 
 config RTC_DRV_TEGRA
        tristate "NVIDIA Tegra Internal RTC driver"
-       depends on ARCH_TEGRA
+       depends on ARCH_TEGRA || COMPILE_TEST
        help
          If you say yes here you get support for the
          Tegra 200 series internal RTC module.
@@ -1603,7 +1637,7 @@ config RTC_DRV_MOXART
 
 config RTC_DRV_MT6397
        tristate "Mediatek Real Time Clock driver"
-       depends on MFD_MT6397 || COMPILE_TEST
+       depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
        help
          This selects the Mediatek(R) RTC driver. RTC is part of Mediatek
          MT6397 PMIC. You should enable MT6397 PMIC MFD before select
@@ -1622,6 +1656,16 @@ config RTC_DRV_XGENE
          This driver can also be built as a module, if so, the module
          will be called "rtc-xgene".
 
+config RTC_DRV_PIC32
+       tristate "Microchip PIC32 RTC"
+       depends on MACH_PIC32
+       default y
+       help
+          If you say yes here you get support for the PIC32 RTC module.
+
+          This driver can also be built as a module. If so, the module
+          will be called rtc-pic32
+
 comment "HID Sensor RTC drivers"
 
 config RTC_DRV_HID_SENSOR_TIME
index 62d61b26ca7e600a30c38cf754353457c19723f9..ea2833723fa9b561c840757727cc98b4b8ab869d 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_ABB5ZES3)        += rtc-ab-b5ze-s3.o
 obj-$(CONFIG_RTC_DRV_ABX80X)   += rtc-abx80x.o
 obj-$(CONFIG_RTC_DRV_ARMADA38X)        += rtc-armada38x.o
 obj-$(CONFIG_RTC_DRV_AS3722)   += rtc-as3722.o
+obj-$(CONFIG_RTC_DRV_ASM9260)  += rtc-asm9260.o
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
 obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
@@ -59,7 +60,6 @@ obj-$(CONFIG_RTC_DRV_DS1685_FAMILY)   += rtc-ds1685.o
 obj-$(CONFIG_RTC_DRV_DS1742)   += rtc-ds1742.o
 obj-$(CONFIG_RTC_DRV_DS2404)   += rtc-ds2404.o
 obj-$(CONFIG_RTC_DRV_DS3232)   += rtc-ds3232.o
-obj-$(CONFIG_RTC_DRV_DS3234)   += rtc-ds3234.o
 obj-$(CONFIG_RTC_DRV_EFI)      += rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EM3027)   += rtc-em3027.o
 obj-$(CONFIG_RTC_DRV_EP93XX)   += rtc-ep93xx.o
@@ -86,7 +86,6 @@ obj-$(CONFIG_RTC_DRV_M48T86)  += rtc-m48t86.o
 obj-$(CONFIG_RTC_DRV_MAX6900)  += rtc-max6900.o
 obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
-obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o
 obj-$(CONFIG_RTC_DRV_MAX8907)  += rtc-max8907.o
 obj-$(CONFIG_RTC_DRV_MAX8925)  += rtc-max8925.o
 obj-$(CONFIG_RTC_DRV_MAX8997)  += rtc-max8997.o
@@ -112,6 +111,7 @@ obj-$(CONFIG_RTC_DRV_PCF85063)      += rtc-pcf85063.o
 obj-$(CONFIG_RTC_DRV_PCF8523)  += rtc-pcf8523.o
 obj-$(CONFIG_RTC_DRV_PCF8563)  += rtc-pcf8563.o
 obj-$(CONFIG_RTC_DRV_PCF8583)  += rtc-pcf8583.o
+obj-$(CONFIG_RTC_DRV_PIC32)    += rtc-pic32.o
 obj-$(CONFIG_RTC_DRV_PL030)    += rtc-pl030.o
 obj-$(CONFIG_RTC_DRV_PL031)    += rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_PM8XXX)   += rtc-pm8xxx.o
@@ -128,6 +128,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372)       += rtc-rs5c372.o
 obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
 obj-$(CONFIG_RTC_DRV_RV8803)   += rtc-rv8803.o
 obj-$(CONFIG_RTC_DRV_RX4581)   += rtc-rx4581.o
+obj-$(CONFIG_RTC_DRV_RX6110)   += rtc-rx6110.o
 obj-$(CONFIG_RTC_DRV_RX8010)   += rtc-rx8010.o
 obj-$(CONFIG_RTC_DRV_RX8025)   += rtc-rx8025.o
 obj-$(CONFIG_RTC_DRV_RX8581)   += rtc-rx8581.o
index de86578bcd6d79ed4b4f7428a58930832709cbbf..74fd9746aecad52cd40c7159008a274d9364fa47 100644 (file)
@@ -361,17 +361,4 @@ static int __init rtc_init(void)
        rtc_dev_init();
        return 0;
 }
-
-static void __exit rtc_exit(void)
-{
-       rtc_dev_exit();
-       class_destroy(rtc_class);
-       ida_destroy(&rtc_ida);
-}
-
 subsys_initcall(rtc_init);
-module_exit(rtc_exit);
-
-MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
-MODULE_DESCRIPTION("RTC class support");
-MODULE_LICENSE("GPL");
index 5836751b8203eb576a7af9f049c706ba27ee8d93..9ef5f6f89f98af8d97da7595aa4ce5a90c6d2566 100644 (file)
@@ -939,4 +939,58 @@ void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
        mutex_unlock(&rtc->ops_lock);
 }
 
+/**
+ * rtc_read_offset - Read the amount of rtc offset in parts per billion
+ * @ rtc: rtc device to be used
+ * @ offset: the offset in parts per billion
+ *
+ * see below for details.
+ *
+ * Kernel interface to read rtc clock offset
+ * Returns 0 on success, or a negative number on error.
+ * If read_offset() is not implemented for the rtc, return -EINVAL
+ */
+int rtc_read_offset(struct rtc_device *rtc, long *offset)
+{
+       int ret;
+
+       if (!rtc->ops)
+               return -ENODEV;
+
+       if (!rtc->ops->read_offset)
+               return -EINVAL;
+
+       mutex_lock(&rtc->ops_lock);
+       ret = rtc->ops->read_offset(rtc->dev.parent, offset);
+       mutex_unlock(&rtc->ops_lock);
+       return ret;
+}
 
+/**
+ * rtc_set_offset - Adjusts the duration of the average second
+ * @ rtc: rtc device to be used
+ * @ offset: the offset in parts per billion
+ *
+ * Some rtc's allow an adjustment to the average duration of a second
+ * to compensate for differences in the actual clock rate due to temperature,
+ * the crystal, capacitor, etc.
+ *
+ * Kernel interface to adjust an rtc clock offset.
+ * Return 0 on success, or a negative number on error.
+ * If the rtc offset is not setable (or not implemented), return -EINVAL
+ */
+int rtc_set_offset(struct rtc_device *rtc, long offset)
+{
+       int ret;
+
+       if (!rtc->ops)
+               return -ENODEV;
+
+       if (!rtc->ops->set_offset)
+               return -EINVAL;
+
+       mutex_lock(&rtc->ops_lock);
+       ret = rtc->ops->set_offset(rtc->dev.parent, offset);
+       mutex_unlock(&rtc->ops_lock);
+       return ret;
+}
index 56cc5821118bfbcaf1c71eb5a334595d93fbc18e..6ef0c887e6cad2f2d11003c941bc7ac3af854abc 100644 (file)
@@ -210,7 +210,7 @@ static int as3722_rtc_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq);
 
        ret = devm_request_threaded_irq(&pdev->dev, as3722_rtc->alarm_irq, NULL,
-                       as3722_alarm_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME,
+                       as3722_alarm_irq, IRQF_ONESHOT,
                        "rtc-alarm", as3722_rtc);
        if (ret < 0) {
                dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c
new file mode 100644 (file)
index 0000000..14e08c4
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2016 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+/* Miscellaneous registers */
+/* Interrupt Location Register */
+#define HW_ILR                 0x00
+#define BM_RTCALF              BIT(1)
+#define BM_RTCCIF              BIT(0)
+
+/* Clock Control Register */
+#define HW_CCR                 0x08
+/* Calibration counter disable */
+#define BM_CCALOFF             BIT(4)
+/* Reset internal oscillator divider */
+#define BM_CTCRST              BIT(1)
+/* Clock Enable */
+#define BM_CLKEN               BIT(0)
+
+/* Counter Increment Interrupt Register */
+#define HW_CIIR                        0x0C
+#define BM_CIIR_IMYEAR         BIT(7)
+#define BM_CIIR_IMMON          BIT(6)
+#define BM_CIIR_IMDOY          BIT(5)
+#define BM_CIIR_IMDOW          BIT(4)
+#define BM_CIIR_IMDOM          BIT(3)
+#define BM_CIIR_IMHOUR         BIT(2)
+#define BM_CIIR_IMMIN          BIT(1)
+#define BM_CIIR_IMSEC          BIT(0)
+
+/* Alarm Mask Register */
+#define HW_AMR                 0x10
+#define BM_AMR_IMYEAR          BIT(7)
+#define BM_AMR_IMMON           BIT(6)
+#define BM_AMR_IMDOY           BIT(5)
+#define BM_AMR_IMDOW           BIT(4)
+#define BM_AMR_IMDOM           BIT(3)
+#define BM_AMR_IMHOUR          BIT(2)
+#define BM_AMR_IMMIN           BIT(1)
+#define BM_AMR_IMSEC           BIT(0)
+#define BM_AMR_OFF             0xff
+
+/* Consolidated time registers */
+#define HW_CTIME0              0x14
+#define BM_CTIME0_DOW_S                24
+#define BM_CTIME0_DOW_M                0x7
+#define BM_CTIME0_HOUR_S       16
+#define BM_CTIME0_HOUR_M       0x1f
+#define BM_CTIME0_MIN_S                8
+#define BM_CTIME0_MIN_M                0x3f
+#define BM_CTIME0_SEC_S                0
+#define BM_CTIME0_SEC_M                0x3f
+
+#define HW_CTIME1              0x18
+#define BM_CTIME1_YEAR_S       16
+#define BM_CTIME1_YEAR_M       0xfff
+#define BM_CTIME1_MON_S                8
+#define BM_CTIME1_MON_M                0xf
+#define BM_CTIME1_DOM_S                0
+#define BM_CTIME1_DOM_M                0x1f
+
+#define HW_CTIME2              0x1C
+#define BM_CTIME2_DOY_S                0
+#define BM_CTIME2_DOY_M                0xfff
+
+/* Time counter registers */
+#define HW_SEC                 0x20
+#define HW_MIN                 0x24
+#define HW_HOUR                        0x28
+#define HW_DOM                 0x2C
+#define HW_DOW                 0x30
+#define HW_DOY                 0x34
+#define HW_MONTH               0x38
+#define HW_YEAR                        0x3C
+
+#define HW_CALIBRATION         0x40
+#define BM_CALDIR_BACK         BIT(17)
+#define BM_CALVAL_M            0x1ffff
+
+/* General purpose registers */
+#define HW_GPREG0              0x44
+#define HW_GPREG1              0x48
+#define HW_GPREG2              0x4C
+#define HW_GPREG3              0x50
+#define HW_GPREG4              0x54
+
+/* Alarm register group */
+#define HW_ALSEC               0x60
+#define HW_ALMIN               0x64
+#define HW_ALHOUR              0x68
+#define HW_ALDOM               0x6C
+#define HW_ALDOW               0x70
+#define HW_ALDOY               0x74
+#define HW_ALMON               0x78
+#define HW_ALYEAR              0x7C
+
+struct asm9260_rtc_priv {
+       struct device           *dev;
+       void __iomem            *iobase;
+       struct rtc_device       *rtc;
+       struct clk              *clk;
+       /* io lock */
+       spinlock_t              lock;
+};
+
+static irqreturn_t asm9260_rtc_irq(int irq, void *dev_id)
+{
+       struct asm9260_rtc_priv *priv = dev_id;
+       u32 isr;
+       unsigned long events = 0;
+
+       isr = ioread32(priv->iobase + HW_CIIR);
+       if (!isr)
+               return IRQ_NONE;
+
+       iowrite32(0, priv->iobase + HW_CIIR);
+
+       events |= RTC_AF | RTC_IRQF;
+
+       rtc_update_irq(priv->rtc, 1, events);
+
+       return IRQ_HANDLED;
+}
+
+static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+       u32 ctime0, ctime1, ctime2;
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&priv->lock, irq_flags);
+       ctime0 = ioread32(priv->iobase + HW_CTIME0);
+       ctime1 = ioread32(priv->iobase + HW_CTIME1);
+       ctime2 = ioread32(priv->iobase + HW_CTIME2);
+
+       if (ctime1 != ioread32(priv->iobase + HW_CTIME1)) {
+               /*
+                * woops, counter flipped right now. Now we are safe
+                * to reread.
+                */
+               ctime0 = ioread32(priv->iobase + HW_CTIME0);
+               ctime1 = ioread32(priv->iobase + HW_CTIME1);
+               ctime2 = ioread32(priv->iobase + HW_CTIME2);
+       }
+       spin_unlock_irqrestore(&priv->lock, irq_flags);
+
+       tm->tm_sec  = (ctime0 >> BM_CTIME0_SEC_S)  & BM_CTIME0_SEC_M;
+       tm->tm_min  = (ctime0 >> BM_CTIME0_MIN_S)  & BM_CTIME0_MIN_M;
+       tm->tm_hour = (ctime0 >> BM_CTIME0_HOUR_S) & BM_CTIME0_HOUR_M;
+       tm->tm_wday = (ctime0 >> BM_CTIME0_DOW_S)  & BM_CTIME0_DOW_M;
+
+       tm->tm_mday = (ctime1 >> BM_CTIME1_DOM_S)  & BM_CTIME1_DOM_M;
+       tm->tm_mon  = (ctime1 >> BM_CTIME1_MON_S)  & BM_CTIME1_MON_M;
+       tm->tm_year = (ctime1 >> BM_CTIME1_YEAR_S) & BM_CTIME1_YEAR_M;
+
+       tm->tm_yday = (ctime2 >> BM_CTIME2_DOY_S)  & BM_CTIME2_DOY_M;
+
+       return 0;
+}
+
+static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&priv->lock, irq_flags);
+       /*
+        * make sure SEC counter will not flip other counter on write time,
+        * real value will be written at the enf of sequence.
+        */
+       iowrite32(0, priv->iobase + HW_SEC);
+
+       iowrite32(tm->tm_year, priv->iobase + HW_YEAR);
+       iowrite32(tm->tm_mon,  priv->iobase + HW_MONTH);
+       iowrite32(tm->tm_mday, priv->iobase + HW_DOM);
+       iowrite32(tm->tm_wday, priv->iobase + HW_DOW);
+       iowrite32(tm->tm_yday, priv->iobase + HW_DOY);
+       iowrite32(tm->tm_hour, priv->iobase + HW_HOUR);
+       iowrite32(tm->tm_min,  priv->iobase + HW_MIN);
+       iowrite32(tm->tm_sec,  priv->iobase + HW_SEC);
+       spin_unlock_irqrestore(&priv->lock, irq_flags);
+
+       return 0;
+}
+
+static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&priv->lock, irq_flags);
+       alrm->time.tm_year = ioread32(priv->iobase + HW_ALYEAR);
+       alrm->time.tm_mon  = ioread32(priv->iobase + HW_ALMON);
+       alrm->time.tm_mday = ioread32(priv->iobase + HW_ALDOM);
+       alrm->time.tm_wday = ioread32(priv->iobase + HW_ALDOW);
+       alrm->time.tm_yday = ioread32(priv->iobase + HW_ALDOY);
+       alrm->time.tm_hour = ioread32(priv->iobase + HW_ALHOUR);
+       alrm->time.tm_min  = ioread32(priv->iobase + HW_ALMIN);
+       alrm->time.tm_sec  = ioread32(priv->iobase + HW_ALSEC);
+
+       alrm->enabled = ioread32(priv->iobase + HW_AMR) ? 1 : 0;
+       alrm->pending = ioread32(priv->iobase + HW_CIIR) ? 1 : 0;
+       spin_unlock_irqrestore(&priv->lock, irq_flags);
+
+       return rtc_valid_tm(&alrm->time);
+}
+
+static int asm9260_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&priv->lock, irq_flags);
+       iowrite32(alrm->time.tm_year, priv->iobase + HW_ALYEAR);
+       iowrite32(alrm->time.tm_mon,  priv->iobase + HW_ALMON);
+       iowrite32(alrm->time.tm_mday, priv->iobase + HW_ALDOM);
+       iowrite32(alrm->time.tm_wday, priv->iobase + HW_ALDOW);
+       iowrite32(alrm->time.tm_yday, priv->iobase + HW_ALDOY);
+       iowrite32(alrm->time.tm_hour, priv->iobase + HW_ALHOUR);
+       iowrite32(alrm->time.tm_min,  priv->iobase + HW_ALMIN);
+       iowrite32(alrm->time.tm_sec,  priv->iobase + HW_ALSEC);
+
+       iowrite32(alrm->enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
+       spin_unlock_irqrestore(&priv->lock, irq_flags);
+
+       return 0;
+}
+
+static int asm9260_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+       struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
+
+       iowrite32(enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
+       return 0;
+}
+
+static const struct rtc_class_ops asm9260_rtc_ops = {
+       .read_time              = asm9260_rtc_read_time,
+       .set_time               = asm9260_rtc_set_time,
+       .read_alarm             = asm9260_rtc_read_alarm,
+       .set_alarm              = asm9260_rtc_set_alarm,
+       .alarm_irq_enable       = asm9260_alarm_irq_enable,
+};
+
+static int __init asm9260_rtc_probe(struct platform_device *pdev)
+{
+       struct asm9260_rtc_priv *priv;
+       struct device *dev = &pdev->dev;
+       struct resource *res;
+       int irq_alarm, ret;
+       u32 ccr;
+
+       priv = devm_kzalloc(dev, sizeof(struct asm9260_rtc_priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->dev = &pdev->dev;
+       platform_set_drvdata(pdev, priv);
+
+       irq_alarm = platform_get_irq(pdev, 0);
+       if (irq_alarm < 0) {
+               dev_err(dev, "No alarm IRQ resource defined\n");
+               return irq_alarm;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       priv->iobase = devm_ioremap_resource(dev, res);
+       if (IS_ERR(priv->iobase))
+               return PTR_ERR(priv->iobase);
+
+       priv->clk = devm_clk_get(dev, "ahb");
+       ret = clk_prepare_enable(priv->clk);
+       if (ret) {
+               dev_err(dev, "Failed to enable clk!\n");
+               return ret;
+       }
+
+       ccr = ioread32(priv->iobase + HW_CCR);
+       /* if dev is not enabled, reset it */
+       if ((ccr & (BM_CLKEN | BM_CTCRST)) != BM_CLKEN) {
+               iowrite32(BM_CTCRST, priv->iobase + HW_CCR);
+               ccr = 0;
+       }
+
+       iowrite32(BM_CLKEN | ccr, priv->iobase + HW_CCR);
+       iowrite32(0, priv->iobase + HW_CIIR);
+       iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
+
+       priv->rtc = devm_rtc_device_register(dev, dev_name(dev),
+                                            &asm9260_rtc_ops, THIS_MODULE);
+       if (IS_ERR(priv->rtc)) {
+               ret = PTR_ERR(priv->rtc);
+               dev_err(dev, "Failed to register RTC device: %d\n", ret);
+               goto err_return;
+       }
+
+       ret = devm_request_threaded_irq(dev, irq_alarm, NULL,
+                                       asm9260_rtc_irq, IRQF_ONESHOT,
+                                       dev_name(dev), priv);
+       if (ret < 0) {
+               dev_err(dev, "can't get irq %i, err %d\n",
+                       irq_alarm, ret);
+               goto err_return;
+       }
+
+       return 0;
+
+err_return:
+       clk_disable_unprepare(priv->clk);
+       return ret;
+}
+
+static int __exit asm9260_rtc_remove(struct platform_device *pdev)
+{
+       struct asm9260_rtc_priv *priv = platform_get_drvdata(pdev);
+
+       /* Disable alarm matching */
+       iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
+       clk_disable_unprepare(priv->clk);
+       return 0;
+}
+
+static const struct of_device_id asm9260_dt_ids[] = {
+       { .compatible = "alphascale,asm9260-rtc", },
+       {}
+};
+
+static struct platform_driver asm9260_rtc_driver = {
+       .probe          = asm9260_rtc_probe,
+       .remove         = asm9260_rtc_remove,
+       .driver         = {
+               .name   = "asm9260-rtc",
+               .owner  = THIS_MODULE,
+               .of_match_table = asm9260_dt_ids,
+       },
+};
+
+module_platform_driver(asm9260_rtc_driver);
+
+MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>");
+MODULE_DESCRIPTION("Alphascale asm9260 SoC Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");
index f39691eea7360272f6c7449a2d25202e6c4106b3..8e41c4613e5135cbd4db573586f85ef60678447e 100644 (file)
@@ -532,7 +532,7 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj,
        struct spi_transfer     x[2];
        int                     status;
 
-       spi = container_of(kobj, struct spi_device, dev.kobj);
+       spi = to_spi_device(kobj_to_dev(kobj));
 
        addr = DS1305_NVRAM + off;
        msg_init(&m, x, &addr, count, NULL, buf);
@@ -554,7 +554,7 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj,
        struct spi_transfer     x[2];
        int                     status;
 
-       spi = container_of(kobj, struct spi_device, dev.kobj);
+       spi = to_spi_device(kobj_to_dev(kobj));
 
        addr = (DS1305_WRITE | DS1305_NVRAM) + off;
        msg_init(&m, x, &addr, count, buf, NULL);
index cf685f67b391669df4f51d8b50c746e839bd396e..b2156ee5bae1a50f72b8cbf69d68741ef0082671 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/rtc.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/clk-provider.h>
 
 /*
  * We can't determine type by probing, but if we expect pre-Linux code
@@ -89,6 +92,7 @@ enum ds_type {
 #      define DS1340_BIT_OSF           0x80
 #define DS1337_REG_STATUS      0x0f
 #      define DS1337_BIT_OSF           0x80
+#      define DS3231_BIT_EN32KHZ       0x08
 #      define DS1337_BIT_A2I           0x02
 #      define DS1337_BIT_A1I           0x01
 #define DS1339_REG_ALARM1_SECS 0x07
@@ -118,6 +122,9 @@ struct ds1307 {
                               u8 length, u8 *values);
        s32 (*write_block_data)(const struct i2c_client *client, u8 command,
                                u8 length, const u8 *values);
+#ifdef CONFIG_COMMON_CLK
+       struct clk_hw           clks[2];
+#endif
 };
 
 struct chip_desc {
@@ -842,6 +849,378 @@ out:
        return;
 }
 
+/*----------------------------------------------------------------------*/
+
+#ifdef CONFIG_RTC_DRV_DS1307_HWMON
+
+/*
+ * Temperature sensor support for ds3231 devices.
+ */
+
+#define DS3231_REG_TEMPERATURE 0x11
+
+/*
+ * A user-initiated temperature conversion is not started by this function,
+ * so the temperature is updated once every 64 seconds.
+ */
+static int ds3231_hwmon_read_temp(struct device *dev, s16 *mC)
+{
+       struct ds1307 *ds1307 = dev_get_drvdata(dev);
+       u8 temp_buf[2];
+       s16 temp;
+       int ret;
+
+       ret = ds1307->read_block_data(ds1307->client, DS3231_REG_TEMPERATURE,
+                                       sizeof(temp_buf), temp_buf);
+       if (ret < 0)
+               return ret;
+       if (ret != sizeof(temp_buf))
+               return -EIO;
+
+       /*
+        * Temperature is represented as a 10-bit code with a resolution of
+        * 0.25 degree celsius and encoded in two's complement format.
+        */
+       temp = (temp_buf[0] << 8) | temp_buf[1];
+       temp >>= 6;
+       *mC = temp * 250;
+
+       return 0;
+}
+
+static ssize_t ds3231_hwmon_show_temp(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       int ret;
+       s16 temp;
+
+       ret = ds3231_hwmon_read_temp(dev, &temp);
+       if (ret)
+               return ret;
+
+       return sprintf(buf, "%d\n", temp);
+}
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ds3231_hwmon_show_temp,
+                       NULL, 0);
+
+static struct attribute *ds3231_hwmon_attrs[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(ds3231_hwmon);
+
+static void ds1307_hwmon_register(struct ds1307 *ds1307)
+{
+       struct device *dev;
+
+       if (ds1307->type != ds_3231)
+               return;
+
+       dev = devm_hwmon_device_register_with_groups(&ds1307->client->dev,
+                                               ds1307->client->name,
+                                               ds1307, ds3231_hwmon_groups);
+       if (IS_ERR(dev)) {
+               dev_warn(&ds1307->client->dev,
+                       "unable to register hwmon device %ld\n", PTR_ERR(dev));
+       }
+}
+
+#else
+
+static void ds1307_hwmon_register(struct ds1307 *ds1307)
+{
+}
+
+#endif /* CONFIG_RTC_DRV_DS1307_HWMON */
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * Square-wave output support for DS3231
+ * Datasheet: https://datasheets.maximintegrated.com/en/ds/DS3231.pdf
+ */
+#ifdef CONFIG_COMMON_CLK
+
+enum {
+       DS3231_CLK_SQW = 0,
+       DS3231_CLK_32KHZ,
+};
+
+#define clk_sqw_to_ds1307(clk) \
+       container_of(clk, struct ds1307, clks[DS3231_CLK_SQW])
+#define clk_32khz_to_ds1307(clk)       \
+       container_of(clk, struct ds1307, clks[DS3231_CLK_32KHZ])
+
+static int ds3231_clk_sqw_rates[] = {
+       1,
+       1024,
+       4096,
+       8192,
+};
+
+static int ds1337_write_control(struct ds1307 *ds1307, u8 mask, u8 value)
+{
+       struct i2c_client *client = ds1307->client;
+       struct mutex *lock = &ds1307->rtc->ops_lock;
+       int control;
+       int ret;
+
+       mutex_lock(lock);
+
+       control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+       if (control < 0) {
+               ret = control;
+               goto out;
+       }
+
+       control &= ~mask;
+       control |= value;
+
+       ret = i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);
+out:
+       mutex_unlock(lock);
+
+       return ret;
+}
+
+static unsigned long ds3231_clk_sqw_recalc_rate(struct clk_hw *hw,
+                                               unsigned long parent_rate)
+{
+       struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+       int control;
+       int rate_sel = 0;
+
+       control = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_CONTROL);
+       if (control < 0)
+               return control;
+       if (control & DS1337_BIT_RS1)
+               rate_sel += 1;
+       if (control & DS1337_BIT_RS2)
+               rate_sel += 2;
+
+       return ds3231_clk_sqw_rates[rate_sel];
+}
+
+static long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long *prate)
+{
+       int i;
+
+       for (i = ARRAY_SIZE(ds3231_clk_sqw_rates) - 1; i >= 0; i--) {
+               if (ds3231_clk_sqw_rates[i] <= rate)
+                       return ds3231_clk_sqw_rates[i];
+       }
+
+       return 0;
+}
+
+static int ds3231_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
+                                       unsigned long parent_rate)
+{
+       struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+       int control = 0;
+       int rate_sel;
+
+       for (rate_sel = 0; rate_sel < ARRAY_SIZE(ds3231_clk_sqw_rates);
+                       rate_sel++) {
+               if (ds3231_clk_sqw_rates[rate_sel] == rate)
+                       break;
+       }
+
+       if (rate_sel == ARRAY_SIZE(ds3231_clk_sqw_rates))
+               return -EINVAL;
+
+       if (rate_sel & 1)
+               control |= DS1337_BIT_RS1;
+       if (rate_sel & 2)
+               control |= DS1337_BIT_RS2;
+
+       return ds1337_write_control(ds1307, DS1337_BIT_RS1 | DS1337_BIT_RS2,
+                               control);
+}
+
+static int ds3231_clk_sqw_prepare(struct clk_hw *hw)
+{
+       struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+
+       return ds1337_write_control(ds1307, DS1337_BIT_INTCN, 0);
+}
+
+static void ds3231_clk_sqw_unprepare(struct clk_hw *hw)
+{
+       struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+
+       ds1337_write_control(ds1307, DS1337_BIT_INTCN, DS1337_BIT_INTCN);
+}
+
+static int ds3231_clk_sqw_is_prepared(struct clk_hw *hw)
+{
+       struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
+       int control;
+
+       control = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_CONTROL);
+       if (control < 0)
+               return control;
+
+       return !(control & DS1337_BIT_INTCN);
+}
+
+static const struct clk_ops ds3231_clk_sqw_ops = {
+       .prepare = ds3231_clk_sqw_prepare,
+       .unprepare = ds3231_clk_sqw_unprepare,
+       .is_prepared = ds3231_clk_sqw_is_prepared,
+       .recalc_rate = ds3231_clk_sqw_recalc_rate,
+       .round_rate = ds3231_clk_sqw_round_rate,
+       .set_rate = ds3231_clk_sqw_set_rate,
+};
+
+static unsigned long ds3231_clk_32khz_recalc_rate(struct clk_hw *hw,
+                                               unsigned long parent_rate)
+{
+       return 32768;
+}
+
+static int ds3231_clk_32khz_control(struct ds1307 *ds1307, bool enable)
+{
+       struct i2c_client *client = ds1307->client;
+       struct mutex *lock = &ds1307->rtc->ops_lock;
+       int status;
+       int ret;
+
+       mutex_lock(lock);
+
+       status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+       if (status < 0) {
+               ret = status;
+               goto out;
+       }
+
+       if (enable)
+               status |= DS3231_BIT_EN32KHZ;
+       else
+               status &= ~DS3231_BIT_EN32KHZ;
+
+       ret = i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, status);
+out:
+       mutex_unlock(lock);
+
+       return ret;
+}
+
+static int ds3231_clk_32khz_prepare(struct clk_hw *hw)
+{
+       struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
+
+       return ds3231_clk_32khz_control(ds1307, true);
+}
+
+static void ds3231_clk_32khz_unprepare(struct clk_hw *hw)
+{
+       struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
+
+       ds3231_clk_32khz_control(ds1307, false);
+}
+
+static int ds3231_clk_32khz_is_prepared(struct clk_hw *hw)
+{
+       struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
+       int status;
+
+       status = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_STATUS);
+       if (status < 0)
+               return status;
+
+       return !!(status & DS3231_BIT_EN32KHZ);
+}
+
+static const struct clk_ops ds3231_clk_32khz_ops = {
+       .prepare = ds3231_clk_32khz_prepare,
+       .unprepare = ds3231_clk_32khz_unprepare,
+       .is_prepared = ds3231_clk_32khz_is_prepared,
+       .recalc_rate = ds3231_clk_32khz_recalc_rate,
+};
+
+static struct clk_init_data ds3231_clks_init[] = {
+       [DS3231_CLK_SQW] = {
+               .name = "ds3231_clk_sqw",
+               .ops = &ds3231_clk_sqw_ops,
+               .flags = CLK_IS_ROOT,
+       },
+       [DS3231_CLK_32KHZ] = {
+               .name = "ds3231_clk_32khz",
+               .ops = &ds3231_clk_32khz_ops,
+               .flags = CLK_IS_ROOT,
+       },
+};
+
+static int ds3231_clks_register(struct ds1307 *ds1307)
+{
+       struct i2c_client *client = ds1307->client;
+       struct device_node *node = client->dev.of_node;
+       struct clk_onecell_data *onecell;
+       int i;
+
+       onecell = devm_kzalloc(&client->dev, sizeof(*onecell), GFP_KERNEL);
+       if (!onecell)
+               return -ENOMEM;
+
+       onecell->clk_num = ARRAY_SIZE(ds3231_clks_init);
+       onecell->clks = devm_kcalloc(&client->dev, onecell->clk_num,
+                                       sizeof(onecell->clks[0]), GFP_KERNEL);
+       if (!onecell->clks)
+               return -ENOMEM;
+
+       for (i = 0; i < ARRAY_SIZE(ds3231_clks_init); i++) {
+               struct clk_init_data init = ds3231_clks_init[i];
+
+               /*
+                * Interrupt signal due to alarm conditions and square-wave
+                * output share same pin, so don't initialize both.
+                */
+               if (i == DS3231_CLK_SQW && test_bit(HAS_ALARM, &ds1307->flags))
+                       continue;
+
+               /* optional override of the clockname */
+               of_property_read_string_index(node, "clock-output-names", i,
+                                               &init.name);
+               ds1307->clks[i].init = &init;
+
+               onecell->clks[i] = devm_clk_register(&client->dev,
+                                                       &ds1307->clks[i]);
+               if (IS_ERR(onecell->clks[i]))
+                       return PTR_ERR(onecell->clks[i]);
+       }
+
+       if (!node)
+               return 0;
+
+       of_clk_add_provider(node, of_clk_src_onecell_get, onecell);
+
+       return 0;
+}
+
+static void ds1307_clks_register(struct ds1307 *ds1307)
+{
+       int ret;
+
+       if (ds1307->type != ds_3231)
+               return;
+
+       ret = ds3231_clks_register(ds1307);
+       if (ret) {
+               dev_warn(&ds1307->client->dev,
+                       "unable to register clock device %d\n", ret);
+       }
+}
+
+#else
+
+static void ds1307_clks_register(struct ds1307 *ds1307)
+{
+}
+
+#endif /* CONFIG_COMMON_CLK */
+
 static int ds1307_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
@@ -851,6 +1230,7 @@ static int ds1307_probe(struct i2c_client *client,
        struct chip_desc        *chip = &chips[id->driver_data];
        struct i2c_adapter      *adapter = to_i2c_adapter(client->dev.parent);
        bool                    want_irq = false;
+       bool                    ds1307_can_wakeup_device = false;
        unsigned char           *buf;
        struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
        irq_handler_t   irq_handler = ds1307_irq;
@@ -898,6 +1278,20 @@ static int ds1307_probe(struct i2c_client *client,
                ds1307->write_block_data = ds1307_write_block_data;
        }
 
+#ifdef CONFIG_OF
+/*
+ * For devices with no IRQ directly connected to the SoC, the RTC chip
+ * can be forced as a wakeup source by stating that explicitly in
+ * the device's .dts file using the "wakeup-source" boolean property.
+ * If the "wakeup-source" property is set, don't request an IRQ.
+ * This will guarantee the 'wakealarm' sysfs entry is available on the device,
+ * if supported by the RTC.
+ */
+       if (of_property_read_bool(client->dev.of_node, "wakeup-source")) {
+               ds1307_can_wakeup_device = true;
+       }
+#endif
+
        switch (ds1307->type) {
        case ds_1337:
        case ds_1339:
@@ -916,11 +1310,13 @@ static int ds1307_probe(struct i2c_client *client,
                        ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
 
                /*
-                * Using IRQ?  Disable the square wave and both alarms.
+                * Using IRQ or defined as wakeup-source?
+                * Disable the square wave and both alarms.
                 * For some variants, be sure alarms can trigger when we're
                 * running on Vbackup (BBSQI/BBSQW)
                 */
-               if (ds1307->client->irq > 0 && chip->alarm) {
+               if (chip->alarm && (ds1307->client->irq > 0 ||
+                                               ds1307_can_wakeup_device)) {
                        ds1307->regs[0] |= DS1337_BIT_INTCN
                                        | bbsqi_bitpos[ds1307->type];
                        ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
@@ -1135,6 +1531,14 @@ read_rtc:
                return PTR_ERR(ds1307->rtc);
        }
 
+       if (ds1307_can_wakeup_device) {
+               /* Disable request for an IRQ */
+               want_irq = false;
+               dev_info(&client->dev, "'wakeup-source' is set, request for an IRQ is disabled!\n");
+               /* We cannot support UIE mode if we do not have an IRQ line */
+               ds1307->rtc->uie_unsupported = 1;
+       }
+
        if (want_irq) {
                err = devm_request_threaded_irq(&client->dev,
                                                client->irq, NULL, irq_handler,
@@ -1182,6 +1586,9 @@ read_rtc:
                }
        }
 
+       ds1307_hwmon_register(ds1307);
+       ds1307_clks_register(ds1307);
+
        return 0;
 
 exit:
index 535050fc5e9fd2fd20b60b7dc88a437afaa29bd8..1e6cfc84b1f6ce6c8daba1ec1470af5dfc95b8cf 100644 (file)
@@ -187,9 +187,9 @@ ds1685_rtc_end_data_access(struct ds1685_priv *rtc)
  * Only use this where you are certain another lock will not be held.
  */
 static inline void
-ds1685_rtc_begin_ctrl_access(struct ds1685_priv *rtc, unsigned long flags)
+ds1685_rtc_begin_ctrl_access(struct ds1685_priv *rtc, unsigned long *flags)
 {
-       spin_lock_irqsave(&rtc->lock, flags);
+       spin_lock_irqsave(&rtc->lock, *flags);
        ds1685_rtc_switch_to_bank1(rtc);
 }
 
@@ -1300,7 +1300,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
 {
        struct ds1685_priv *rtc = dev_get_drvdata(dev);
        u8 reg = 0, bit = 0, tmp;
-       unsigned long flags = 0;
+       unsigned long flags;
        long int val = 0;
        const struct ds1685_rtc_ctrl_regs *reg_info =
                ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
@@ -1321,7 +1321,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
        bit = reg_info->bit;
 
        /* Safe to spinlock during a write. */
-       ds1685_rtc_begin_ctrl_access(rtc, flags);
+       ds1685_rtc_begin_ctrl_access(rtc, &flags);
        tmp = rtc->read(rtc, reg);
        rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit))));
        ds1685_rtc_end_ctrl_access(rtc, flags);
@@ -2161,6 +2161,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev)
        /* Check for valid RTC data, else, spin forever. */
        if (unlikely(!pdev)) {
                pr_emerg("platform device data not available, spinning forever ...\n");
+               while(1);
                unreachable();
        } else {
                /* Get the rtc data. */
index 4e99ace66f74d10a9beba95a2ec3208d79c50182..7edc889729c51f0db0c2b7c3c231258ead1bb6b0 100644 (file)
@@ -1,19 +1,15 @@
 /*
- * RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
+ * RTC client/driver for the Maxim/Dallas DS3232/DS3234 Real-Time Clock
  *
  * Copyright (C) 2009-2011 Freescale Semiconductor.
  * Author: Jack Lan <jack.lan@freescale.com>
+ * Copyright (C) 2008 MIMOMax Wireless Ltd.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
-/*
- * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
- * recommened in .../Documentation/i2c/writing-clients section
- * "Sending and receiving", using SMBus level communication is preferred.
- */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/rtc.h>
 #include <linux/bcd.h>
-#include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
 
 #define DS3232_REG_SECONDS     0x00
 #define DS3232_REG_MINUTES     0x01
 #       define DS3232_REG_SR_A1F   0x01
 
 struct ds3232 {
-       struct i2c_client *client;
+       struct device *dev;
+       struct regmap *regmap;
+       int irq;
        struct rtc_device *rtc;
-       struct work_struct work;
 
-       /* The mutex protects alarm operations, and prevents a race
-        * between the enable_irq() in the workqueue and the free_irq()
-        * in the remove function.
-        */
-       struct mutex mutex;
        bool suspended;
-       int exiting;
 };
 
-static struct i2c_driver ds3232_driver;
-
-static int ds3232_check_rtc_status(struct i2c_client *client)
+static int ds3232_check_rtc_status(struct device *dev)
 {
+       struct ds3232 *ds3232 = dev_get_drvdata(dev);
        int ret = 0;
        int control, stat;
 
-       stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
-       if (stat < 0)
-               return stat;
+       ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
+       if (ret)
+               return ret;
 
        if (stat & DS3232_REG_SR_OSF)
-               dev_warn(&client->dev,
+               dev_warn(dev,
                                "oscillator discontinuity flagged, "
                                "time unreliable\n");
 
        stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
 
-       ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
-       if (ret < 0)
+       ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
+       if (ret)
                return ret;
 
        /* If the alarm is pending, clear it before requesting
@@ -90,31 +81,28 @@ static int ds3232_check_rtc_status(struct i2c_client *client)
         * before everything is initialized.
         */
 
-       control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-       if (control < 0)
-               return control;
+       ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+       if (ret)
+               return ret;
 
        control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
        control |= DS3232_REG_CR_INTCN;
 
-       return i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
+       return regmap_write(ds3232->regmap, DS3232_REG_CR, control);
 }
 
 static int ds3232_read_time(struct device *dev, struct rtc_time *time)
 {
-       struct i2c_client *client = to_i2c_client(dev);
+       struct ds3232 *ds3232 = dev_get_drvdata(dev);
        int ret;
        u8 buf[7];
        unsigned int year, month, day, hour, minute, second;
        unsigned int week, twelve_hr, am_pm;
        unsigned int century, add_century = 0;
 
-       ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_SECONDS, 7, buf);
-
-       if (ret < 0)
+       ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
+       if (ret)
                return ret;
-       if (ret < 7)
-               return -EIO;
 
        second = buf[0];
        minute = buf[1];
@@ -159,7 +147,7 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
 
 static int ds3232_set_time(struct device *dev, struct rtc_time *time)
 {
-       struct i2c_client *client = to_i2c_client(dev);
+       struct ds3232 *ds3232 = dev_get_drvdata(dev);
        u8 buf[7];
 
        /* Extract time from rtc_time and load into ds3232*/
@@ -179,8 +167,7 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
                buf[6] = bin2bcd(time->tm_year);
        }
 
-       return i2c_smbus_write_i2c_block_data(client,
-                                             DS3232_REG_SECONDS, 7, buf);
+       return regmap_bulk_write(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
 }
 
 /*
@@ -190,24 +177,19 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
  */
 static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct ds3232 *ds3232 = i2c_get_clientdata(client);
+       struct ds3232 *ds3232 = dev_get_drvdata(dev);
        int control, stat;
        int ret;
        u8 buf[4];
 
-       mutex_lock(&ds3232->mutex);
-
-       ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
-       if (ret < 0)
+       ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
+       if (ret)
                goto out;
-       stat = ret;
-       ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-       if (ret < 0)
+       ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+       if (ret)
                goto out;
-       control = ret;
-       ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
-       if (ret < 0)
+       ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
+       if (ret)
                goto out;
 
        alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
@@ -226,7 +208,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 
        ret = 0;
 out:
-       mutex_unlock(&ds3232->mutex);
        return ret;
 }
 
@@ -236,166 +217,129 @@ out:
  */
 static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct ds3232 *ds3232 = i2c_get_clientdata(client);
+       struct ds3232 *ds3232 = dev_get_drvdata(dev);
        int control, stat;
        int ret;
        u8 buf[4];
 
-       if (client->irq <= 0)
+       if (ds3232->irq <= 0)
                return -EINVAL;
 
-       mutex_lock(&ds3232->mutex);
-
        buf[0] = bin2bcd(alarm->time.tm_sec);
        buf[1] = bin2bcd(alarm->time.tm_min);
        buf[2] = bin2bcd(alarm->time.tm_hour);
        buf[3] = bin2bcd(alarm->time.tm_mday);
 
        /* clear alarm interrupt enable bit */
-       ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-       if (ret < 0)
+       ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+       if (ret)
                goto out;
-       control = ret;
        control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
-       ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
-       if (ret < 0)
+       ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
+       if (ret)
                goto out;
 
        /* clear any pending alarm flag */
-       ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
-       if (ret < 0)
+       ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
+       if (ret)
                goto out;
-       stat = ret;
        stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
-       ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
-       if (ret < 0)
+       ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
+       if (ret)
                goto out;
 
-       ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
+       ret = regmap_bulk_write(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
+       if (ret)
+               goto out;
 
        if (alarm->enabled) {
                control |= DS3232_REG_CR_A1IE;
-               ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
+               ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
        }
 out:
-       mutex_unlock(&ds3232->mutex);
        return ret;
 }
 
-static void ds3232_update_alarm(struct i2c_client *client)
+static int ds3232_update_alarm(struct device *dev, unsigned int enabled)
 {
-       struct ds3232 *ds3232 = i2c_get_clientdata(client);
+       struct ds3232 *ds3232 = dev_get_drvdata(dev);
        int control;
        int ret;
-       u8 buf[4];
-
-       mutex_lock(&ds3232->mutex);
-
-       ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
-       if (ret < 0)
-               goto unlock;
-
-       buf[0] = bcd2bin(buf[0]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
-                                                               0x80 : buf[0];
-       buf[1] = bcd2bin(buf[1]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
-                                                               0x80 : buf[1];
-       buf[2] = bcd2bin(buf[2]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
-                                                               0x80 : buf[2];
-       buf[3] = bcd2bin(buf[3]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
-                                                               0x80 : buf[3];
-
-       ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
-       if (ret < 0)
-               goto unlock;
 
-       control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-       if (control < 0)
-               goto unlock;
+       ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+       if (ret)
+               return ret;
 
-       if (ds3232->rtc->irq_data & (RTC_AF | RTC_UF))
+       if (enabled)
                /* enable alarm1 interrupt */
                control |= DS3232_REG_CR_A1IE;
        else
                /* disable alarm1 interrupt */
                control &= ~(DS3232_REG_CR_A1IE);
-       i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
+       ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
 
-unlock:
-       mutex_unlock(&ds3232->mutex);
+       return ret;
 }
 
 static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct ds3232 *ds3232 = i2c_get_clientdata(client);
+       struct ds3232 *ds3232 = dev_get_drvdata(dev);
 
-       if (client->irq <= 0)
+       if (ds3232->irq <= 0)
                return -EINVAL;
 
-       if (enabled)
-               ds3232->rtc->irq_data |= RTC_AF;
-       else
-               ds3232->rtc->irq_data &= ~RTC_AF;
-
-       ds3232_update_alarm(client);
-       return 0;
+       return ds3232_update_alarm(dev, enabled);
 }
 
 static irqreturn_t ds3232_irq(int irq, void *dev_id)
 {
-       struct i2c_client *client = dev_id;
-       struct ds3232 *ds3232 = i2c_get_clientdata(client);
-
-       disable_irq_nosync(irq);
-
-       /*
-        * If rtc as a wakeup source, can't schedule the work
-        * at system resume flow, because at this time the i2c bus
-        * has not been resumed.
-        */
-       if (!ds3232->suspended)
-               schedule_work(&ds3232->work);
-
-       return IRQ_HANDLED;
-}
-
-static void ds3232_work(struct work_struct *work)
-{
-       struct ds3232 *ds3232 = container_of(work, struct ds3232, work);
-       struct i2c_client *client = ds3232->client;
+       struct device *dev = dev_id;
+       struct ds3232 *ds3232 = dev_get_drvdata(dev);
+       struct mutex *lock = &ds3232->rtc->ops_lock;
+       int ret;
        int stat, control;
 
-       mutex_lock(&ds3232->mutex);
+       mutex_lock(lock);
 
-       stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
-       if (stat < 0)
+       ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
+       if (ret)
                goto unlock;
 
        if (stat & DS3232_REG_SR_A1F) {
-               control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
-               if (control < 0) {
-                       pr_warn("Read Control Register error - Disable IRQ%d\n",
-                               client->irq);
+               ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
+               if (ret) {
+                       dev_warn(ds3232->dev,
+                                "Read Control Register error %d\n", ret);
                } else {
                        /* disable alarm1 interrupt */
                        control &= ~(DS3232_REG_CR_A1IE);
-                       i2c_smbus_write_byte_data(client, DS3232_REG_CR,
-                                               control);
+                       ret = regmap_write(ds3232->regmap, DS3232_REG_CR,
+                                          control);
+                       if (ret) {
+                               dev_warn(ds3232->dev,
+                                        "Write Control Register error %d\n",
+                                        ret);
+                               goto unlock;
+                       }
 
                        /* clear the alarm pend flag */
                        stat &= ~DS3232_REG_SR_A1F;
-                       i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
+                       ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
+                       if (ret) {
+                               dev_warn(ds3232->dev,
+                                        "Write Status Register error %d\n",
+                                        ret);
+                               goto unlock;
+                       }
 
                        rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
-
-                       if (!ds3232->exiting)
-                               enable_irq(client->irq);
                }
        }
 
 unlock:
-       mutex_unlock(&ds3232->mutex);
+       mutex_unlock(lock);
+
+       return IRQ_HANDLED;
 }
 
 static const struct rtc_class_ops ds3232_rtc_ops = {
@@ -406,67 +350,50 @@ static const struct rtc_class_ops ds3232_rtc_ops = {
        .alarm_irq_enable = ds3232_alarm_irq_enable,
 };
 
-static int ds3232_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
+static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq,
+                       const char *name)
 {
        struct ds3232 *ds3232;
        int ret;
 
-       ds3232 = devm_kzalloc(&client->dev, sizeof(struct ds3232), GFP_KERNEL);
+       ds3232 = devm_kzalloc(dev, sizeof(*ds3232), GFP_KERNEL);
        if (!ds3232)
                return -ENOMEM;
 
-       ds3232->client = client;
-       i2c_set_clientdata(client, ds3232);
-
-       INIT_WORK(&ds3232->work, ds3232_work);
-       mutex_init(&ds3232->mutex);
+       ds3232->regmap = regmap;
+       ds3232->irq = irq;
+       ds3232->dev = dev;
+       dev_set_drvdata(dev, ds3232);
 
-       ret = ds3232_check_rtc_status(client);
+       ret = ds3232_check_rtc_status(dev);
        if (ret)
                return ret;
 
-       if (client->irq > 0) {
-               ret = devm_request_irq(&client->dev, client->irq, ds3232_irq,
-                                      IRQF_SHARED, "ds3232", client);
+       if (ds3232->irq > 0) {
+               ret = devm_request_threaded_irq(dev, ds3232->irq, NULL,
+                                               ds3232_irq,
+                                               IRQF_SHARED | IRQF_ONESHOT,
+                                               name, dev);
                if (ret) {
-                       dev_err(&client->dev, "unable to request IRQ\n");
-               }
-               device_init_wakeup(&client->dev, 1);
-       }
-       ds3232->rtc = devm_rtc_device_register(&client->dev, client->name,
-                                         &ds3232_rtc_ops, THIS_MODULE);
-       return PTR_ERR_OR_ZERO(ds3232->rtc);
-}
-
-static int ds3232_remove(struct i2c_client *client)
-{
-       struct ds3232 *ds3232 = i2c_get_clientdata(client);
-
-       if (client->irq > 0) {
-               mutex_lock(&ds3232->mutex);
-               ds3232->exiting = 1;
-               mutex_unlock(&ds3232->mutex);
-
-               devm_free_irq(&client->dev, client->irq, client);
-               cancel_work_sync(&ds3232->work);
+                       ds3232->irq = 0;
+                       dev_err(dev, "unable to request IRQ\n");
+               } else
+                       device_init_wakeup(dev, 1);
        }
+       ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops,
+                                               THIS_MODULE);
 
-       return 0;
+       return PTR_ERR_OR_ZERO(ds3232->rtc);
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int ds3232_suspend(struct device *dev)
 {
        struct ds3232 *ds3232 = dev_get_drvdata(dev);
-       struct i2c_client *client = to_i2c_client(dev);
 
-       if (device_can_wakeup(dev)) {
-               ds3232->suspended = true;
-               if (irq_set_irq_wake(client->irq, 1)) {
+       if (device_may_wakeup(dev)) {
+               if (enable_irq_wake(ds3232->irq))
                        dev_warn_once(dev, "Cannot set wakeup source\n");
-                       ds3232->suspended = false;
-               }
        }
 
        return 0;
@@ -475,16 +402,9 @@ static int ds3232_suspend(struct device *dev)
 static int ds3232_resume(struct device *dev)
 {
        struct ds3232 *ds3232 = dev_get_drvdata(dev);
-       struct i2c_client *client = to_i2c_client(dev);
 
-       if (ds3232->suspended) {
-               ds3232->suspended = false;
-
-               /* Clear the hardware alarm pend flag */
-               schedule_work(&ds3232->work);
-
-               irq_set_irq_wake(client->irq, 0);
-       }
+       if (device_may_wakeup(dev))
+               disable_irq_wake(ds3232->irq);
 
        return 0;
 }
@@ -494,6 +414,27 @@ static const struct dev_pm_ops ds3232_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
 };
 
+#if IS_ENABLED(CONFIG_I2C)
+
+static int ds3232_i2c_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
+{
+       struct regmap *regmap;
+       static const struct regmap_config config = {
+               .reg_bits = 8,
+               .val_bits = 8,
+       };
+
+       regmap = devm_regmap_init_i2c(client, &config);
+       if (IS_ERR(regmap)) {
+               dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
+                       __func__, PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       return ds3232_probe(&client->dev, regmap, client->irq, client->name);
+}
+
 static const struct i2c_device_id ds3232_id[] = {
        { "ds3232", 0 },
        { }
@@ -505,13 +446,162 @@ static struct i2c_driver ds3232_driver = {
                .name = "rtc-ds3232",
                .pm     = &ds3232_pm_ops,
        },
-       .probe = ds3232_probe,
-       .remove = ds3232_remove,
+       .probe = ds3232_i2c_probe,
        .id_table = ds3232_id,
 };
 
-module_i2c_driver(ds3232_driver);
+static int ds3232_register_driver(void)
+{
+       return i2c_add_driver(&ds3232_driver);
+}
+
+static void ds3232_unregister_driver(void)
+{
+       i2c_del_driver(&ds3232_driver);
+}
+
+#else
+
+static int ds3232_register_driver(void)
+{
+       return 0;
+}
+
+static void ds3232_unregister_driver(void)
+{
+}
+
+#endif
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static int ds3234_probe(struct spi_device *spi)
+{
+       int res;
+       unsigned int tmp;
+       static const struct regmap_config config = {
+               .reg_bits = 8,
+               .val_bits = 8,
+               .write_flag_mask = 0x80,
+       };
+       struct regmap *regmap;
+
+       regmap = devm_regmap_init_spi(spi, &config);
+       if (IS_ERR(regmap)) {
+               dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
+                       __func__, PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       spi->mode = SPI_MODE_3;
+       spi->bits_per_word = 8;
+       spi_setup(spi);
+
+       res = regmap_read(regmap, DS3232_REG_SECONDS, &tmp);
+       if (res)
+               return res;
+
+       /* Control settings
+        *
+        * CONTROL_REG
+        * BIT 7        6       5       4       3       2       1       0
+        *     EOSC     BBSQW   CONV    RS2     RS1     INTCN   A2IE    A1IE
+        *
+        *     0        0       0       1       1       1       0       0
+        *
+        * CONTROL_STAT_REG
+        * BIT 7        6       5       4       3       2       1       0
+        *     OSF      BB32kHz CRATE1  CRATE0  EN32kHz BSY     A2F     A1F
+        *
+        *     1        0       0       0       1       0       0       0
+        */
+       res = regmap_read(regmap, DS3232_REG_CR, &tmp);
+       if (res)
+               return res;
+       res = regmap_write(regmap, DS3232_REG_CR, tmp & 0x1c);
+       if (res)
+               return res;
+
+       res = regmap_read(regmap, DS3232_REG_SR, &tmp);
+       if (res)
+               return res;
+       res = regmap_write(regmap, DS3232_REG_SR, tmp & 0x88);
+       if (res)
+               return res;
+
+       /* Print our settings */
+       res = regmap_read(regmap, DS3232_REG_CR, &tmp);
+       if (res)
+               return res;
+       dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
+
+       res = regmap_read(regmap, DS3232_REG_SR, &tmp);
+       if (res)
+               return res;
+       dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
+
+       return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234");
+}
+
+static struct spi_driver ds3234_driver = {
+       .driver = {
+               .name    = "ds3234",
+       },
+       .probe   = ds3234_probe,
+};
+
+static int ds3234_register_driver(void)
+{
+       return spi_register_driver(&ds3234_driver);
+}
+
+static void ds3234_unregister_driver(void)
+{
+       spi_unregister_driver(&ds3234_driver);
+}
+
+#else
+
+static int ds3234_register_driver(void)
+{
+       return 0;
+}
+
+static void ds3234_unregister_driver(void)
+{
+}
+
+#endif
+
+static int __init ds323x_init(void)
+{
+       int ret;
+
+       ret = ds3232_register_driver();
+       if (ret) {
+               pr_err("Failed to register ds3232 driver: %d\n", ret);
+               return ret;
+       }
+
+       ret = ds3234_register_driver();
+       if (ret) {
+               pr_err("Failed to register ds3234 driver: %d\n", ret);
+               ds3232_unregister_driver();
+       }
+
+       return ret;
+}
+module_init(ds323x_init)
+
+static void __exit ds323x_exit(void)
+{
+       ds3234_unregister_driver();
+       ds3232_unregister_driver();
+}
+module_exit(ds323x_exit)
 
 MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>");
-MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver");
+MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
+MODULE_DESCRIPTION("Maxim/Dallas DS3232/DS3234 RTC Driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:ds3234");
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c
deleted file mode 100644 (file)
index 570ab28..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/* rtc-ds3234.c
- *
- * Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal
- * and SRAM.
- *
- * Copyright (C) 2008 MIMOMax Wireless Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/rtc.h>
-#include <linux/spi/spi.h>
-#include <linux/bcd.h>
-
-#define DS3234_REG_SECONDS     0x00
-#define DS3234_REG_MINUTES     0x01
-#define DS3234_REG_HOURS       0x02
-#define DS3234_REG_DAY         0x03
-#define DS3234_REG_DATE                0x04
-#define DS3234_REG_MONTH       0x05
-#define DS3234_REG_YEAR                0x06
-#define DS3234_REG_CENTURY     (1 << 7) /* Bit 7 of the Month register */
-
-#define DS3234_REG_CONTROL     0x0E
-#define DS3234_REG_CONT_STAT   0x0F
-
-static int ds3234_set_reg(struct device *dev, unsigned char address,
-                               unsigned char data)
-{
-       struct spi_device *spi = to_spi_device(dev);
-       unsigned char buf[2];
-
-       /* MSB must be '1' to indicate write */
-       buf[0] = address | 0x80;
-       buf[1] = data;
-
-       return spi_write_then_read(spi, buf, 2, NULL, 0);
-}
-
-static int ds3234_get_reg(struct device *dev, unsigned char address,
-                               unsigned char *data)
-{
-       struct spi_device *spi = to_spi_device(dev);
-
-       *data = address & 0x7f;
-
-       return spi_write_then_read(spi, data, 1, data, 1);
-}
-
-static int ds3234_read_time(struct device *dev, struct rtc_time *dt)
-{
-       int err;
-       unsigned char buf[8];
-       struct spi_device *spi = to_spi_device(dev);
-
-       buf[0] = 0x00; /* Start address */
-
-       err = spi_write_then_read(spi, buf, 1, buf, 8);
-       if (err != 0)
-               return err;
-
-       /* Seconds, Minutes, Hours, Day, Date, Month, Year */
-       dt->tm_sec      = bcd2bin(buf[0]);
-       dt->tm_min      = bcd2bin(buf[1]);
-       dt->tm_hour     = bcd2bin(buf[2] & 0x3f);
-       dt->tm_wday     = bcd2bin(buf[3]) - 1; /* 0 = Sun */
-       dt->tm_mday     = bcd2bin(buf[4]);
-       dt->tm_mon      = bcd2bin(buf[5] & 0x1f) - 1; /* 0 = Jan */
-       dt->tm_year     = bcd2bin(buf[6] & 0xff) + 100; /* Assume 20YY */
-
-       return rtc_valid_tm(dt);
-}
-
-static int ds3234_set_time(struct device *dev, struct rtc_time *dt)
-{
-       ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec));
-       ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min));
-       ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f);
-
-       /* 0 = Sun */
-       ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1));
-       ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday));
-
-       /* 0 = Jan */
-       ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1));
-
-       /* Assume 20YY although we just want to make sure not to go negative. */
-       if (dt->tm_year > 100)
-               dt->tm_year -= 100;
-
-       ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year));
-
-       return 0;
-}
-
-static const struct rtc_class_ops ds3234_rtc_ops = {
-       .read_time      = ds3234_read_time,
-       .set_time       = ds3234_set_time,
-};
-
-static int ds3234_probe(struct spi_device *spi)
-{
-       struct rtc_device *rtc;
-       unsigned char tmp;
-       int res;
-
-       spi->mode = SPI_MODE_3;
-       spi->bits_per_word = 8;
-       spi_setup(spi);
-
-       res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp);
-       if (res != 0)
-               return res;
-
-       /* Control settings
-        *
-        * CONTROL_REG
-        * BIT 7        6       5       4       3       2       1       0
-        *     EOSC     BBSQW   CONV    RS2     RS1     INTCN   A2IE    A1IE
-        *
-        *     0        0       0       1       1       1       0       0
-        *
-        * CONTROL_STAT_REG
-        * BIT 7        6       5       4       3       2       1       0
-        *     OSF      BB32kHz CRATE1  CRATE0  EN32kHz BSY     A2F     A1F
-        *
-        *     1        0       0       0       1       0       0       0
-        */
-       ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
-       ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c);
-
-       ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
-       ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88);
-
-       /* Print our settings */
-       ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
-       dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
-
-       ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
-       dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
-
-       rtc = devm_rtc_device_register(&spi->dev, "ds3234",
-                               &ds3234_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc))
-               return PTR_ERR(rtc);
-
-       spi_set_drvdata(spi, rtc);
-
-       return 0;
-}
-
-static struct spi_driver ds3234_driver = {
-       .driver = {
-               .name    = "ds3234",
-       },
-       .probe   = ds3234_probe,
-};
-
-module_spi_driver(ds3234_driver);
-
-MODULE_DESCRIPTION("DS3234 SPI RTC driver");
-MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:ds3234");
index e782ebd719b235fcb10c23b26bf9c17ac82eba79..d726c6aa96a8fab1f69859cc364d969522d93be0 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/platform_device.h>
 #include <linux/rtc.h>
 
+#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \
+    defined(CONFIG_PPC) || defined(CONFIG_SUPERH32)
 #include <asm/rtc.h>
 
 static int generic_get_time(struct device *dev, struct rtc_time *tm)
@@ -33,13 +35,21 @@ static const struct rtc_class_ops generic_rtc_ops = {
        .read_time = generic_get_time,
        .set_time = generic_set_time,
 };
+#else
+#define generic_rtc_ops *(struct rtc_class_ops*)NULL
+#endif
 
 static int __init generic_rtc_probe(struct platform_device *dev)
 {
        struct rtc_device *rtc;
+       const struct rtc_class_ops *ops;
+
+       ops = dev_get_platdata(&dev->dev);
+       if (!ops)
+               ops = &generic_rtc_ops;
 
        rtc = devm_rtc_device_register(&dev->dev, "rtc-generic",
-                                       &generic_rtc_ops, THIS_MODULE);
+                                       ops, THIS_MODULE);
        if (IS_ERR(rtc))
                return PTR_ERR(rtc);
 
index 097325d96db566e08ec8b70aaa9d595f6a044235..b1b4746a0eab5af524791d0868d8132d8014be4b 100644 (file)
@@ -144,7 +144,7 @@ static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
         * it does not seem to carry it over a subsequent write/read.
         * So we'll limit ourself to 100 years, starting at 2000 for now.
         */
-       buf[6] = tm->tm_year - 100;
+       buf[6] = bin2bcd(tm->tm_year - 100);
 
        /*
         * CTL1 only contains TEST-mode bits apart from stop,
index 7184a0eda79384f8a59a5c8be8155018ba1a792e..182fdd00e290d3f2ce79b32a99ee99f2ff382f81 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * RTC driver for Maxim MAX77686
+ * RTC driver for Maxim MAX77686 and MAX77802
  *
  * Copyright (C) 2012 Samsung Electronics Co.Ltd
  *
@@ -12,8 +12,7 @@
  *
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
+#include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/rtc.h>
 #include <linux/delay.h>
 #include <linux/irqdomain.h>
 #include <linux/regmap.h>
 
+#define MAX77686_I2C_ADDR_RTC          (0x0C >> 1)
+#define MAX77620_I2C_ADDR_RTC          0x68
+#define MAX77686_INVALID_I2C_ADDR      (-1)
+
+/* Define non existing register */
+#define MAX77686_INVALID_REG           (-1)
+
 /* RTC Control Register */
 #define BCD_EN_SHIFT                   0
-#define BCD_EN_MASK                    (1 << BCD_EN_SHIFT)
+#define BCD_EN_MASK                    BIT(BCD_EN_SHIFT)
 #define MODEL24_SHIFT                  1
-#define MODEL24_MASK                   (1 << MODEL24_SHIFT)
+#define MODEL24_MASK                   BIT(MODEL24_SHIFT)
 /* RTC Update Register1 */
 #define RTC_UDR_SHIFT                  0
-#define RTC_UDR_MASK                   (1 << RTC_UDR_SHIFT)
+#define RTC_UDR_MASK                   BIT(RTC_UDR_SHIFT)
 #define RTC_RBUDR_SHIFT                        4
-#define RTC_RBUDR_MASK                 (1 << RTC_RBUDR_SHIFT)
+#define RTC_RBUDR_MASK                 BIT(RTC_RBUDR_SHIFT)
 /* RTC Hour register */
 #define HOUR_PM_SHIFT                  6
-#define HOUR_PM_MASK                   (1 << HOUR_PM_SHIFT)
+#define HOUR_PM_MASK                   BIT(HOUR_PM_SHIFT)
 /* RTC Alarm Enable */
 #define ALARM_ENABLE_SHIFT             7
-#define ALARM_ENABLE_MASK              (1 << ALARM_ENABLE_SHIFT)
+#define ALARM_ENABLE_MASK              BIT(ALARM_ENABLE_SHIFT)
 
-#define MAX77686_RTC_UPDATE_DELAY      16
+#define REG_RTC_NONE                   0xdeadbeef
+
+/*
+ * MAX77802 has separate register (RTCAE1) for alarm enable instead
+ * using 1 bit from registers RTC{SEC,MIN,HOUR,DAY,MONTH,YEAR,DATE}
+ * as in done in MAX77686.
+ */
+#define MAX77802_ALARM_ENABLE_VALUE    0x77
 
 enum {
        RTC_SEC = 0,
@@ -54,15 +67,38 @@ enum {
        RTC_NR_TIME
 };
 
+struct max77686_rtc_driver_data {
+       /* Minimum usecs needed for a RTC update */
+       unsigned long           delay;
+       /* Mask used to read RTC registers value */
+       u8                      mask;
+       /* Registers offset to I2C addresses map */
+       const unsigned int      *map;
+       /* Has a separate alarm enable register? */
+       bool                    alarm_enable_reg;
+       /* I2C address for RTC block */
+       int                     rtc_i2c_addr;
+       /* RTC interrupt via platform resource */
+       bool                    rtc_irq_from_platform;
+       /* Pending alarm status register */
+       int                     alarm_pending_status_reg;
+       /* RTC IRQ CHIP for regmap */
+       const struct regmap_irq_chip *rtc_irq_chip;
+};
+
 struct max77686_rtc_info {
        struct device           *dev;
-       struct max77686_dev     *max77686;
        struct i2c_client       *rtc;
        struct rtc_device       *rtc_dev;
        struct mutex            lock;
 
        struct regmap           *regmap;
+       struct regmap           *rtc_regmap;
+
+       const struct max77686_rtc_driver_data *drv_data;
+       struct regmap_irq_chip_data *rtc_irq_data;
 
+       int rtc_irq;
        int virq;
        int rtc_24hr_mode;
 };
@@ -72,29 +108,190 @@ enum MAX77686_RTC_OP {
        MAX77686_RTC_READ,
 };
 
+/* These are not registers but just offsets that are mapped to addresses */
+enum max77686_rtc_reg_offset {
+       REG_RTC_CONTROLM = 0,
+       REG_RTC_CONTROL,
+       REG_RTC_UPDATE0,
+       REG_WTSR_SMPL_CNTL,
+       REG_RTC_SEC,
+       REG_RTC_MIN,
+       REG_RTC_HOUR,
+       REG_RTC_WEEKDAY,
+       REG_RTC_MONTH,
+       REG_RTC_YEAR,
+       REG_RTC_DATE,
+       REG_ALARM1_SEC,
+       REG_ALARM1_MIN,
+       REG_ALARM1_HOUR,
+       REG_ALARM1_WEEKDAY,
+       REG_ALARM1_MONTH,
+       REG_ALARM1_YEAR,
+       REG_ALARM1_DATE,
+       REG_ALARM2_SEC,
+       REG_ALARM2_MIN,
+       REG_ALARM2_HOUR,
+       REG_ALARM2_WEEKDAY,
+       REG_ALARM2_MONTH,
+       REG_ALARM2_YEAR,
+       REG_ALARM2_DATE,
+       REG_RTC_AE1,
+       REG_RTC_END,
+};
+
+/* Maps RTC registers offset to the MAX77686 register addresses */
+static const unsigned int max77686_map[REG_RTC_END] = {
+       [REG_RTC_CONTROLM]   = MAX77686_RTC_CONTROLM,
+       [REG_RTC_CONTROL]    = MAX77686_RTC_CONTROL,
+       [REG_RTC_UPDATE0]    = MAX77686_RTC_UPDATE0,
+       [REG_WTSR_SMPL_CNTL] = MAX77686_WTSR_SMPL_CNTL,
+       [REG_RTC_SEC]        = MAX77686_RTC_SEC,
+       [REG_RTC_MIN]        = MAX77686_RTC_MIN,
+       [REG_RTC_HOUR]       = MAX77686_RTC_HOUR,
+       [REG_RTC_WEEKDAY]    = MAX77686_RTC_WEEKDAY,
+       [REG_RTC_MONTH]      = MAX77686_RTC_MONTH,
+       [REG_RTC_YEAR]       = MAX77686_RTC_YEAR,
+       [REG_RTC_DATE]       = MAX77686_RTC_DATE,
+       [REG_ALARM1_SEC]     = MAX77686_ALARM1_SEC,
+       [REG_ALARM1_MIN]     = MAX77686_ALARM1_MIN,
+       [REG_ALARM1_HOUR]    = MAX77686_ALARM1_HOUR,
+       [REG_ALARM1_WEEKDAY] = MAX77686_ALARM1_WEEKDAY,
+       [REG_ALARM1_MONTH]   = MAX77686_ALARM1_MONTH,
+       [REG_ALARM1_YEAR]    = MAX77686_ALARM1_YEAR,
+       [REG_ALARM1_DATE]    = MAX77686_ALARM1_DATE,
+       [REG_ALARM2_SEC]     = MAX77686_ALARM2_SEC,
+       [REG_ALARM2_MIN]     = MAX77686_ALARM2_MIN,
+       [REG_ALARM2_HOUR]    = MAX77686_ALARM2_HOUR,
+       [REG_ALARM2_WEEKDAY] = MAX77686_ALARM2_WEEKDAY,
+       [REG_ALARM2_MONTH]   = MAX77686_ALARM2_MONTH,
+       [REG_ALARM2_YEAR]    = MAX77686_ALARM2_YEAR,
+       [REG_ALARM2_DATE]    = MAX77686_ALARM2_DATE,
+       [REG_RTC_AE1]        = REG_RTC_NONE,
+};
+
+static const struct regmap_irq max77686_rtc_irqs[] = {
+       /* RTC interrupts */
+       REGMAP_IRQ_REG(0, 0, MAX77686_RTCINT_RTC60S_MSK),
+       REGMAP_IRQ_REG(1, 0, MAX77686_RTCINT_RTCA1_MSK),
+       REGMAP_IRQ_REG(2, 0, MAX77686_RTCINT_RTCA2_MSK),
+       REGMAP_IRQ_REG(3, 0, MAX77686_RTCINT_SMPL_MSK),
+       REGMAP_IRQ_REG(4, 0, MAX77686_RTCINT_RTC1S_MSK),
+       REGMAP_IRQ_REG(5, 0, MAX77686_RTCINT_WTSR_MSK),
+};
+
+static const struct regmap_irq_chip max77686_rtc_irq_chip = {
+       .name           = "max77686-rtc",
+       .status_base    = MAX77686_RTC_INT,
+       .mask_base      = MAX77686_RTC_INTM,
+       .num_regs       = 1,
+       .irqs           = max77686_rtc_irqs,
+       .num_irqs       = ARRAY_SIZE(max77686_rtc_irqs),
+};
+
+static const struct max77686_rtc_driver_data max77686_drv_data = {
+       .delay = 16000,
+       .mask  = 0x7f,
+       .map   = max77686_map,
+       .alarm_enable_reg  = false,
+       .rtc_irq_from_platform = false,
+       .alarm_pending_status_reg = MAX77686_REG_STATUS2,
+       .rtc_i2c_addr = MAX77686_I2C_ADDR_RTC,
+       .rtc_irq_chip = &max77686_rtc_irq_chip,
+};
+
+static const struct max77686_rtc_driver_data max77620_drv_data = {
+       .delay = 16000,
+       .mask  = 0x7f,
+       .map   = max77686_map,
+       .alarm_enable_reg  = false,
+       .rtc_irq_from_platform = true,
+       .alarm_pending_status_reg = MAX77686_INVALID_REG,
+       .rtc_i2c_addr = MAX77620_I2C_ADDR_RTC,
+       .rtc_irq_chip = &max77686_rtc_irq_chip,
+};
+
+static const unsigned int max77802_map[REG_RTC_END] = {
+       [REG_RTC_CONTROLM]   = MAX77802_RTC_CONTROLM,
+       [REG_RTC_CONTROL]    = MAX77802_RTC_CONTROL,
+       [REG_RTC_UPDATE0]    = MAX77802_RTC_UPDATE0,
+       [REG_WTSR_SMPL_CNTL] = MAX77802_WTSR_SMPL_CNTL,
+       [REG_RTC_SEC]        = MAX77802_RTC_SEC,
+       [REG_RTC_MIN]        = MAX77802_RTC_MIN,
+       [REG_RTC_HOUR]       = MAX77802_RTC_HOUR,
+       [REG_RTC_WEEKDAY]    = MAX77802_RTC_WEEKDAY,
+       [REG_RTC_MONTH]      = MAX77802_RTC_MONTH,
+       [REG_RTC_YEAR]       = MAX77802_RTC_YEAR,
+       [REG_RTC_DATE]       = MAX77802_RTC_DATE,
+       [REG_ALARM1_SEC]     = MAX77802_ALARM1_SEC,
+       [REG_ALARM1_MIN]     = MAX77802_ALARM1_MIN,
+       [REG_ALARM1_HOUR]    = MAX77802_ALARM1_HOUR,
+       [REG_ALARM1_WEEKDAY] = MAX77802_ALARM1_WEEKDAY,
+       [REG_ALARM1_MONTH]   = MAX77802_ALARM1_MONTH,
+       [REG_ALARM1_YEAR]    = MAX77802_ALARM1_YEAR,
+       [REG_ALARM1_DATE]    = MAX77802_ALARM1_DATE,
+       [REG_ALARM2_SEC]     = MAX77802_ALARM2_SEC,
+       [REG_ALARM2_MIN]     = MAX77802_ALARM2_MIN,
+       [REG_ALARM2_HOUR]    = MAX77802_ALARM2_HOUR,
+       [REG_ALARM2_WEEKDAY] = MAX77802_ALARM2_WEEKDAY,
+       [REG_ALARM2_MONTH]   = MAX77802_ALARM2_MONTH,
+       [REG_ALARM2_YEAR]    = MAX77802_ALARM2_YEAR,
+       [REG_ALARM2_DATE]    = MAX77802_ALARM2_DATE,
+       [REG_RTC_AE1]        = MAX77802_RTC_AE1,
+};
+
+static const struct regmap_irq_chip max77802_rtc_irq_chip = {
+       .name           = "max77802-rtc",
+       .status_base    = MAX77802_RTC_INT,
+       .mask_base      = MAX77802_RTC_INTM,
+       .num_regs       = 1,
+       .irqs           = max77686_rtc_irqs, /* same masks as 77686 */
+       .num_irqs       = ARRAY_SIZE(max77686_rtc_irqs),
+};
+
+static const struct max77686_rtc_driver_data max77802_drv_data = {
+       .delay = 200,
+       .mask  = 0xff,
+       .map   = max77802_map,
+       .alarm_enable_reg  = true,
+       .rtc_irq_from_platform = false,
+       .alarm_pending_status_reg = MAX77686_REG_STATUS2,
+       .rtc_i2c_addr = MAX77686_INVALID_I2C_ADDR,
+       .rtc_irq_chip = &max77802_rtc_irq_chip,
+};
+
 static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
-                                  int rtc_24hr_mode)
+                                   struct max77686_rtc_info *info)
 {
-       tm->tm_sec = data[RTC_SEC] & 0x7f;
-       tm->tm_min = data[RTC_MIN] & 0x7f;
-       if (rtc_24hr_mode)
+       u8 mask = info->drv_data->mask;
+
+       tm->tm_sec = data[RTC_SEC] & mask;
+       tm->tm_min = data[RTC_MIN] & mask;
+       if (info->rtc_24hr_mode) {
                tm->tm_hour = data[RTC_HOUR] & 0x1f;
-       else {
+       else {
                tm->tm_hour = data[RTC_HOUR] & 0x0f;
                if (data[RTC_HOUR] & HOUR_PM_MASK)
                        tm->tm_hour += 12;
        }
 
        /* Only a single bit is set in data[], so fls() would be equivalent */
-       tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1;
+       tm->tm_wday = ffs(data[RTC_WEEKDAY] & mask) - 1;
        tm->tm_mday = data[RTC_DATE] & 0x1f;
        tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
-       tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100;
+       tm->tm_year = data[RTC_YEAR] & mask;
        tm->tm_yday = 0;
        tm->tm_isdst = 0;
+
+       /*
+        * MAX77686 uses 1 bit from sec/min/hour/etc RTC registers and the
+        * year values are just 0..99 so add 100 to support up to 2099.
+        */
+       if (!info->drv_data->alarm_enable_reg)
+               tm->tm_year += 100;
 }
 
-static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
+static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data,
+                                  struct max77686_rtc_info *info)
 {
        data[RTC_SEC] = tm->tm_sec;
        data[RTC_MIN] = tm->tm_min;
@@ -102,35 +299,44 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
        data[RTC_WEEKDAY] = 1 << tm->tm_wday;
        data[RTC_DATE] = tm->tm_mday;
        data[RTC_MONTH] = tm->tm_mon + 1;
+
+       if (info->drv_data->alarm_enable_reg) {
+               data[RTC_YEAR] = tm->tm_year;
+               return 0;
+       }
+
        data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0;
 
        if (tm->tm_year < 100) {
-               pr_warn("RTC cannot handle the year %d.  Assume it's 2000.\n",
+               dev_err(info->dev, "RTC cannot handle the year %d.\n",
                        1900 + tm->tm_year);
                return -EINVAL;
        }
+
        return 0;
 }
 
 static int max77686_rtc_update(struct max77686_rtc_info *info,
-       enum MAX77686_RTC_OP op)
+                              enum MAX77686_RTC_OP op)
 {
        int ret;
        unsigned int data;
+       unsigned long delay = info->drv_data->delay;
 
        if (op == MAX77686_RTC_WRITE)
                data = 1 << RTC_UDR_SHIFT;
        else
                data = 1 << RTC_RBUDR_SHIFT;
 
-       ret = regmap_update_bits(info->max77686->rtc_regmap,
-                                MAX77686_RTC_UPDATE0, data, data);
+       ret = regmap_update_bits(info->rtc_regmap,
+                                info->drv_data->map[REG_RTC_UPDATE0],
+                                data, data);
        if (ret < 0)
-               dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
-                               __func__, ret, data);
+               dev_err(info->dev, "Fail to write update reg(ret=%d, data=0x%x)\n",
+                       ret, data);
        else {
-               /* Minimum 16ms delay required before RTC update. */
-               msleep(MAX77686_RTC_UPDATE_DELAY);
+               /* Minimum delay required before RTC update. */
+               usleep_range(delay, delay * 2);
        }
 
        return ret;
@@ -148,14 +354,15 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm)
        if (ret < 0)
                goto out;
 
-       ret = regmap_bulk_read(info->max77686->rtc_regmap,
-                               MAX77686_RTC_SEC, data, RTC_NR_TIME);
+       ret = regmap_bulk_read(info->rtc_regmap,
+                              info->drv_data->map[REG_RTC_SEC],
+                              data, ARRAY_SIZE(data));
        if (ret < 0) {
-               dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret);
+               dev_err(info->dev, "Fail to read time reg(%d)\n", ret);
                goto out;
        }
 
-       max77686_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
+       max77686_rtc_data_to_tm(data, tm, info);
 
        ret = rtc_valid_tm(tm);
 
@@ -170,17 +377,17 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm)
        u8 data[RTC_NR_TIME];
        int ret;
 
-       ret = max77686_rtc_tm_to_data(tm, data);
+       ret = max77686_rtc_tm_to_data(tm, data, info);
        if (ret < 0)
                return ret;
 
        mutex_lock(&info->lock);
 
-       ret = regmap_bulk_write(info->max77686->rtc_regmap,
-                                MAX77686_RTC_SEC, data, RTC_NR_TIME);
+       ret = regmap_bulk_write(info->rtc_regmap,
+                               info->drv_data->map[REG_RTC_SEC],
+                               data, ARRAY_SIZE(data));
        if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
-                               ret);
+               dev_err(info->dev, "Fail to write time reg(%d)\n", ret);
                goto out;
        }
 
@@ -196,6 +403,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct max77686_rtc_info *info = dev_get_drvdata(dev);
        u8 data[RTC_NR_TIME];
        unsigned int val;
+       const unsigned int *map = info->drv_data->map;
        int i, ret;
 
        mutex_lock(&info->lock);
@@ -204,29 +412,53 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        if (ret < 0)
                goto out;
 
-       ret = regmap_bulk_read(info->max77686->rtc_regmap,
-                                MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
+       ret = regmap_bulk_read(info->rtc_regmap, map[REG_ALARM1_SEC],
+                              data, ARRAY_SIZE(data));
        if (ret < 0) {
-               dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
-                               __func__, __LINE__, ret);
+               dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
                goto out;
        }
 
-       max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
+       max77686_rtc_data_to_tm(data, &alrm->time, info);
 
        alrm->enabled = 0;
-       for (i = 0; i < RTC_NR_TIME; i++) {
-               if (data[i] & ALARM_ENABLE_MASK) {
+
+       if (info->drv_data->alarm_enable_reg) {
+               if (map[REG_RTC_AE1] == REG_RTC_NONE) {
+                       ret = -EINVAL;
+                       dev_err(info->dev,
+                               "alarm enable register not set(%d)\n", ret);
+                       goto out;
+               }
+
+               ret = regmap_read(info->rtc_regmap, map[REG_RTC_AE1], &val);
+               if (ret < 0) {
+                       dev_err(info->dev,
+                               "fail to read alarm enable(%d)\n", ret);
+                       goto out;
+               }
+
+               if (val)
                        alrm->enabled = 1;
-                       break;
+       } else {
+               for (i = 0; i < ARRAY_SIZE(data); i++) {
+                       if (data[i] & ALARM_ENABLE_MASK) {
+                               alrm->enabled = 1;
+                               break;
+                       }
                }
        }
 
        alrm->pending = 0;
-       ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS2, &val);
+
+       if (info->drv_data->alarm_pending_status_reg == MAX77686_INVALID_REG)
+               goto out;
+
+       ret = regmap_read(info->regmap,
+                         info->drv_data->alarm_pending_status_reg, &val);
        if (ret < 0) {
-               dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
-                               __func__, __LINE__, ret);
+               dev_err(info->dev,
+                       "Fail to read alarm pending status reg(%d)\n", ret);
                goto out;
        }
 
@@ -235,7 +467,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 out:
        mutex_unlock(&info->lock);
-       return 0;
+       return ret;
 }
 
 static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
@@ -243,6 +475,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
        u8 data[RTC_NR_TIME];
        int ret, i;
        struct rtc_time tm;
+       const unsigned int *map = info->drv_data->map;
 
        if (!mutex_is_locked(&info->lock))
                dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
@@ -251,24 +484,34 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info)
        if (ret < 0)
                goto out;
 
-       ret = regmap_bulk_read(info->max77686->rtc_regmap,
-                                MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
-                               __func__, ret);
-               goto out;
-       }
+       if (info->drv_data->alarm_enable_reg) {
+               if (map[REG_RTC_AE1] == REG_RTC_NONE) {
+                       ret = -EINVAL;
+                       dev_err(info->dev,
+                               "alarm enable register not set(%d)\n", ret);
+                       goto out;
+               }
+
+               ret = regmap_write(info->rtc_regmap, map[REG_RTC_AE1], 0);
+       } else {
+               ret = regmap_bulk_read(info->rtc_regmap, map[REG_ALARM1_SEC],
+                                      data, ARRAY_SIZE(data));
+               if (ret < 0) {
+                       dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
+                       goto out;
+               }
 
-       max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode);
+               max77686_rtc_data_to_tm(data, &tm, info);
 
-       for (i = 0; i < RTC_NR_TIME; i++)
-               data[i] &= ~ALARM_ENABLE_MASK;
+               for (i = 0; i < ARRAY_SIZE(data); i++)
+                       data[i] &= ~ALARM_ENABLE_MASK;
+
+               ret = regmap_bulk_write(info->rtc_regmap, map[REG_ALARM1_SEC],
+                                       data, ARRAY_SIZE(data));
+       }
 
-       ret = regmap_bulk_write(info->max77686->rtc_regmap,
-                                MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
        if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-                               __func__, ret);
+               dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
                goto out;
        }
 
@@ -282,6 +525,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info)
        u8 data[RTC_NR_TIME];
        int ret;
        struct rtc_time tm;
+       const unsigned int *map = info->drv_data->map;
 
        if (!mutex_is_locked(&info->lock))
                dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
@@ -290,32 +534,36 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info)
        if (ret < 0)
                goto out;
 
-       ret = regmap_bulk_read(info->max77686->rtc_regmap,
-                                MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
-                               __func__, ret);
-               goto out;
+       if (info->drv_data->alarm_enable_reg) {
+               ret = regmap_write(info->rtc_regmap, map[REG_RTC_AE1],
+                                  MAX77802_ALARM_ENABLE_VALUE);
+       } else {
+               ret = regmap_bulk_read(info->rtc_regmap, map[REG_ALARM1_SEC],
+                                      data, ARRAY_SIZE(data));
+               if (ret < 0) {
+                       dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret);
+                       goto out;
+               }
+
+               max77686_rtc_data_to_tm(data, &tm, info);
+
+               data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT);
+               data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT);
+               data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT);
+               data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK;
+               if (data[RTC_MONTH] & 0xf)
+                       data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT);
+               if (data[RTC_YEAR] & info->drv_data->mask)
+                       data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT);
+               if (data[RTC_DATE] & 0x1f)
+                       data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
+
+               ret = regmap_bulk_write(info->rtc_regmap, map[REG_ALARM1_SEC],
+                                       data, ARRAY_SIZE(data));
        }
 
-       max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode);
-
-       data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT);
-       data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT);
-       data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT);
-       data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK;
-       if (data[RTC_MONTH] & 0xf)
-               data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT);
-       if (data[RTC_YEAR] & 0x7f)
-               data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT);
-       if (data[RTC_DATE] & 0x1f)
-               data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
-
-       ret = regmap_bulk_write(info->max77686->rtc_regmap,
-                                MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
        if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-                               __func__, ret);
+               dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
                goto out;
        }
 
@@ -330,7 +578,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        u8 data[RTC_NR_TIME];
        int ret;
 
-       ret = max77686_rtc_tm_to_data(&alrm->time, data);
+       ret = max77686_rtc_tm_to_data(&alrm->time, data, info);
        if (ret < 0)
                return ret;
 
@@ -340,12 +588,12 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        if (ret < 0)
                goto out;
 
-       ret = regmap_bulk_write(info->max77686->rtc_regmap,
-                                MAX77686_ALARM1_SEC, data, RTC_NR_TIME);
+       ret = regmap_bulk_write(info->rtc_regmap,
+                               info->drv_data->map[REG_ALARM1_SEC],
+                               data, ARRAY_SIZE(data));
 
        if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-                               __func__, ret);
+               dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret);
                goto out;
        }
 
@@ -361,7 +609,7 @@ out:
 }
 
 static int max77686_rtc_alarm_irq_enable(struct device *dev,
-                                       unsigned int enabled)
+                                        unsigned int enabled)
 {
        struct max77686_rtc_info *info = dev_get_drvdata(dev);
        int ret;
@@ -380,7 +628,7 @@ static irqreturn_t max77686_rtc_alarm_irq(int irq, void *data)
 {
        struct max77686_rtc_info *info = data;
 
-       dev_info(info->dev, "%s:irq(%d)\n", __func__, irq);
+       dev_dbg(info->dev, "RTC alarm IRQ: %d\n", irq);
 
        rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
 
@@ -406,10 +654,11 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
 
        info->rtc_24hr_mode = 1;
 
-       ret = regmap_bulk_write(info->max77686->rtc_regmap, MAX77686_RTC_CONTROLM, data, 2);
+       ret = regmap_bulk_write(info->rtc_regmap,
+                               info->drv_data->map[REG_RTC_CONTROLM],
+                               data, ARRAY_SIZE(data));
        if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
-                               __func__, ret);
+               dev_err(info->dev, "Fail to write controlm reg(%d)\n", ret);
                return ret;
        }
 
@@ -417,28 +666,97 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
        return ret;
 }
 
+static const struct regmap_config max77686_rtc_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
+static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
+{
+       struct device *parent = info->dev->parent;
+       struct i2c_client *parent_i2c = to_i2c_client(parent);
+       int ret;
+
+       if (info->drv_data->rtc_irq_from_platform) {
+               struct platform_device *pdev = to_platform_device(info->dev);
+
+               info->rtc_irq = platform_get_irq(pdev, 0);
+               if (info->rtc_irq < 0) {
+                       dev_err(info->dev, "Failed to get rtc interrupts: %d\n",
+                               info->rtc_irq);
+                       return info->rtc_irq;
+               }
+       } else {
+               info->rtc_irq =  parent_i2c->irq;
+       }
+
+       info->regmap = dev_get_regmap(parent, NULL);
+       if (!info->regmap) {
+               dev_err(info->dev, "Failed to get rtc regmap\n");
+               return -ENODEV;
+       }
+
+       if (info->drv_data->rtc_i2c_addr == MAX77686_INVALID_I2C_ADDR) {
+               info->rtc_regmap = info->regmap;
+               goto add_rtc_irq;
+       }
+
+       info->rtc = i2c_new_dummy(parent_i2c->adapter,
+                                 info->drv_data->rtc_i2c_addr);
+       if (!info->rtc) {
+               dev_err(info->dev, "Failed to allocate I2C device for RTC\n");
+               return -ENODEV;
+       }
+
+       info->rtc_regmap = devm_regmap_init_i2c(info->rtc,
+                                               &max77686_rtc_regmap_config);
+       if (IS_ERR(info->rtc_regmap)) {
+               ret = PTR_ERR(info->rtc_regmap);
+               dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret);
+               goto err_unregister_i2c;
+       }
+
+add_rtc_irq:
+       ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq,
+                                 IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+                                 IRQF_SHARED, 0, info->drv_data->rtc_irq_chip,
+                                 &info->rtc_irq_data);
+       if (ret < 0) {
+               dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret);
+               goto err_unregister_i2c;
+       }
+
+       return 0;
+
+err_unregister_i2c:
+       if (info->rtc)
+               i2c_unregister_device(info->rtc);
+       return ret;
+}
+
 static int max77686_rtc_probe(struct platform_device *pdev)
 {
-       struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent);
        struct max77686_rtc_info *info;
+       const struct platform_device_id *id = platform_get_device_id(pdev);
        int ret;
 
-       dev_info(&pdev->dev, "%s\n", __func__);
-
        info = devm_kzalloc(&pdev->dev, sizeof(struct max77686_rtc_info),
-                               GFP_KERNEL);
+                           GFP_KERNEL);
        if (!info)
                return -ENOMEM;
 
        mutex_init(&info->lock);
        info->dev = &pdev->dev;
-       info->max77686 = max77686;
-       info->rtc = max77686->rtc;
+       info->drv_data = (const struct max77686_rtc_driver_data *)
+               id->driver_data;
+
+       ret = max77686_init_rtc_regmap(info);
+       if (ret < 0)
+               return ret;
 
        platform_set_drvdata(pdev, info);
 
        ret = max77686_rtc_init_reg(info);
-
        if (ret < 0) {
                dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
                goto err_rtc;
@@ -446,7 +764,7 @@ static int max77686_rtc_probe(struct platform_device *pdev)
 
        device_init_wakeup(&pdev->dev, 1);
 
-       info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc",
+       info->rtc_dev = devm_rtc_device_register(&pdev->dev, id->name,
                                        &max77686_rtc_ops, THIS_MODULE);
 
        if (IS_ERR(info->rtc_dev)) {
@@ -457,29 +775,43 @@ static int max77686_rtc_probe(struct platform_device *pdev)
                goto err_rtc;
        }
 
-       if (!max77686->rtc_irq_data) {
-               ret = -EINVAL;
-               dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__);
-               goto err_rtc;
-       }
-
-       info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
+       info->virq = regmap_irq_get_virq(info->rtc_irq_data,
                                         MAX77686_RTCIRQ_RTCA1);
-       if (!info->virq) {
+       if (info->virq <= 0) {
                ret = -ENXIO;
                goto err_rtc;
        }
 
-       ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
-                               max77686_rtc_alarm_irq, 0, "rtc-alarm1", info);
-       if (ret < 0)
+       ret = request_threaded_irq(info->virq, NULL, max77686_rtc_alarm_irq, 0,
+                                  "rtc-alarm1", info);
+       if (ret < 0) {
                dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
                        info->virq, ret);
+               goto err_rtc;
+       }
+
+       return 0;
 
 err_rtc:
+       regmap_del_irq_chip(info->rtc_irq, info->rtc_irq_data);
+       if (info->rtc)
+               i2c_unregister_device(info->rtc);
+
        return ret;
 }
 
+static int max77686_rtc_remove(struct platform_device *pdev)
+{
+       struct max77686_rtc_info *info = platform_get_drvdata(pdev);
+
+       free_irq(info->virq, info);
+       regmap_del_irq_chip(info->rtc_irq, info->rtc_irq_data);
+       if (info->rtc)
+               i2c_unregister_device(info->rtc);
+
+       return 0;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int max77686_rtc_suspend(struct device *dev)
 {
@@ -508,7 +840,9 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
                         max77686_rtc_suspend, max77686_rtc_resume);
 
 static const struct platform_device_id rtc_id[] = {
-       { "max77686-rtc", 0 },
+       { "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, },
+       { "max77802-rtc", .driver_data = (kernel_ulong_t)&max77802_drv_data, },
+       { "max77620-rtc", .driver_data = (kernel_ulong_t)&max77620_drv_data, },
        {},
 };
 MODULE_DEVICE_TABLE(platform, rtc_id);
@@ -519,6 +853,7 @@ static struct platform_driver max77686_rtc_driver = {
                .pm     = &max77686_rtc_pm_ops,
        },
        .probe          = max77686_rtc_probe,
+       .remove         = max77686_rtc_remove,
        .id_table       = rtc_id,
 };
 
diff --git a/drivers/rtc/rtc-max77802.c b/drivers/rtc/rtc-max77802.c
deleted file mode 100644 (file)
index 82ffcc5..0000000
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * RTC driver for Maxim MAX77802
- *
- * Copyright (C) 2013 Google, Inc
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- *
- *  based on rtc-max8997.c
- *
- *  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/slab.h>
-#include <linux/rtc.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/max77686-private.h>
-#include <linux/irqdomain.h>
-#include <linux/regmap.h>
-
-/* RTC Control Register */
-#define BCD_EN_SHIFT                   0
-#define BCD_EN_MASK                    (1 << BCD_EN_SHIFT)
-#define MODEL24_SHIFT                  1
-#define MODEL24_MASK                   (1 << MODEL24_SHIFT)
-/* RTC Update Register1 */
-#define RTC_UDR_SHIFT                  0
-#define RTC_UDR_MASK                   (1 << RTC_UDR_SHIFT)
-#define RTC_RBUDR_SHIFT                        4
-#define RTC_RBUDR_MASK                 (1 << RTC_RBUDR_SHIFT)
-/* RTC Hour register */
-#define HOUR_PM_SHIFT                  6
-#define HOUR_PM_MASK                   (1 << HOUR_PM_SHIFT)
-/* RTC Alarm Enable */
-#define ALARM_ENABLE_SHIFT             7
-#define ALARM_ENABLE_MASK              (1 << ALARM_ENABLE_SHIFT)
-
-/* For the RTCAE1 register, we write this value to enable the alarm */
-#define ALARM_ENABLE_VALUE             0x77
-
-#define MAX77802_RTC_UPDATE_DELAY_US   200
-
-enum {
-       RTC_SEC = 0,
-       RTC_MIN,
-       RTC_HOUR,
-       RTC_WEEKDAY,
-       RTC_MONTH,
-       RTC_YEAR,
-       RTC_DATE,
-       RTC_NR_TIME
-};
-
-struct max77802_rtc_info {
-       struct device           *dev;
-       struct max77686_dev     *max77802;
-       struct i2c_client       *rtc;
-       struct rtc_device       *rtc_dev;
-       struct mutex            lock;
-
-       struct regmap           *regmap;
-
-       int virq;
-       int rtc_24hr_mode;
-};
-
-enum MAX77802_RTC_OP {
-       MAX77802_RTC_WRITE,
-       MAX77802_RTC_READ,
-};
-
-static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
-                                  int rtc_24hr_mode)
-{
-       tm->tm_sec = data[RTC_SEC] & 0xff;
-       tm->tm_min = data[RTC_MIN] & 0xff;
-       if (rtc_24hr_mode)
-               tm->tm_hour = data[RTC_HOUR] & 0x1f;
-       else {
-               tm->tm_hour = data[RTC_HOUR] & 0x0f;
-               if (data[RTC_HOUR] & HOUR_PM_MASK)
-                       tm->tm_hour += 12;
-       }
-
-       /* Only a single bit is set in data[], so fls() would be equivalent */
-       tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1;
-       tm->tm_mday = data[RTC_DATE] & 0x1f;
-       tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
-
-       tm->tm_year = data[RTC_YEAR] & 0xff;
-       tm->tm_yday = 0;
-       tm->tm_isdst = 0;
-}
-
-static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
-{
-       data[RTC_SEC] = tm->tm_sec;
-       data[RTC_MIN] = tm->tm_min;
-       data[RTC_HOUR] = tm->tm_hour;
-       data[RTC_WEEKDAY] = 1 << tm->tm_wday;
-       data[RTC_DATE] = tm->tm_mday;
-       data[RTC_MONTH] = tm->tm_mon + 1;
-       data[RTC_YEAR] = tm->tm_year;
-
-       return 0;
-}
-
-static int max77802_rtc_update(struct max77802_rtc_info *info,
-       enum MAX77802_RTC_OP op)
-{
-       int ret;
-       unsigned int data;
-
-       if (op == MAX77802_RTC_WRITE)
-               data = 1 << RTC_UDR_SHIFT;
-       else
-               data = 1 << RTC_RBUDR_SHIFT;
-
-       ret = regmap_update_bits(info->max77802->regmap,
-                                MAX77802_RTC_UPDATE0, data, data);
-       if (ret < 0)
-               dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
-                               __func__, ret, data);
-       else {
-               /* Minimum delay required before RTC update. */
-               usleep_range(MAX77802_RTC_UPDATE_DELAY_US,
-                            MAX77802_RTC_UPDATE_DELAY_US * 2);
-       }
-
-       return ret;
-}
-
-static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
-       struct max77802_rtc_info *info = dev_get_drvdata(dev);
-       u8 data[RTC_NR_TIME];
-       int ret;
-
-       mutex_lock(&info->lock);
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_READ);
-       if (ret < 0)
-               goto out;
-
-       ret = regmap_bulk_read(info->max77802->regmap,
-                               MAX77802_RTC_SEC, data, RTC_NR_TIME);
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
-                       ret);
-               goto out;
-       }
-
-       max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
-
-       ret = rtc_valid_tm(tm);
-
-out:
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
-       struct max77802_rtc_info *info = dev_get_drvdata(dev);
-       u8 data[RTC_NR_TIME];
-       int ret;
-
-       ret = max77802_rtc_tm_to_data(tm, data);
-       if (ret < 0)
-               return ret;
-
-       mutex_lock(&info->lock);
-
-       ret = regmap_bulk_write(info->max77802->regmap,
-                                MAX77802_RTC_SEC, data, RTC_NR_TIME);
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
-                       ret);
-               goto out;
-       }
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-
-out:
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
-       struct max77802_rtc_info *info = dev_get_drvdata(dev);
-       u8 data[RTC_NR_TIME];
-       unsigned int val;
-       int ret;
-
-       mutex_lock(&info->lock);
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_READ);
-       if (ret < 0)
-               goto out;
-
-       ret = regmap_bulk_read(info->max77802->regmap,
-                                MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
-       if (ret < 0) {
-               dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
-                               __func__, __LINE__, ret);
-               goto out;
-       }
-
-       max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
-
-       alrm->enabled = 0;
-       ret = regmap_read(info->max77802->regmap,
-                         MAX77802_RTC_AE1, &val);
-       if (ret < 0) {
-               dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n",
-                       __func__, __LINE__, ret);
-               goto out;
-       }
-       if (val)
-               alrm->enabled = 1;
-
-       alrm->pending = 0;
-       ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val);
-       if (ret < 0) {
-               dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
-                               __func__, __LINE__, ret);
-               goto out;
-       }
-
-       if (val & (1 << 2)) /* RTCA1 */
-               alrm->pending = 1;
-
-out:
-       mutex_unlock(&info->lock);
-       return 0;
-}
-
-static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info)
-{
-       int ret;
-
-       if (!mutex_is_locked(&info->lock))
-               dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_READ);
-       if (ret < 0)
-               goto out;
-
-       ret = regmap_write(info->max77802->regmap,
-                          MAX77802_RTC_AE1, 0);
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-                       __func__, ret);
-               goto out;
-       }
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-out:
-       return ret;
-}
-
-static int max77802_rtc_start_alarm(struct max77802_rtc_info *info)
-{
-       int ret;
-
-       if (!mutex_is_locked(&info->lock))
-               dev_warn(info->dev, "%s: should have mutex locked\n",
-                        __func__);
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_READ);
-       if (ret < 0)
-               goto out;
-
-       ret = regmap_write(info->max77802->regmap,
-                                  MAX77802_RTC_AE1,
-                                  ALARM_ENABLE_VALUE);
-
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
-                               __func__, ret);
-               goto out;
-       }
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-out:
-       return ret;
-}
-
-static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
-{
-       struct max77802_rtc_info *info = dev_get_drvdata(dev);
-       u8 data[RTC_NR_TIME];
-       int ret;
-
-       ret = max77802_rtc_tm_to_data(&alrm->time, data);
-       if (ret < 0)
-               return ret;
-
-       mutex_lock(&info->lock);
-
-       ret = max77802_rtc_stop_alarm(info);
-       if (ret < 0)
-               goto out;
-
-       ret = regmap_bulk_write(info->max77802->regmap,
-                                MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
-
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
-                               __func__, ret);
-               goto out;
-       }
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-       if (ret < 0)
-               goto out;
-
-       if (alrm->enabled)
-               ret = max77802_rtc_start_alarm(info);
-out:
-       mutex_unlock(&info->lock);
-       return ret;
-}
-
-static int max77802_rtc_alarm_irq_enable(struct device *dev,
-                                        unsigned int enabled)
-{
-       struct max77802_rtc_info *info = dev_get_drvdata(dev);
-       int ret;
-
-       mutex_lock(&info->lock);
-       if (enabled)
-               ret = max77802_rtc_start_alarm(info);
-       else
-               ret = max77802_rtc_stop_alarm(info);
-       mutex_unlock(&info->lock);
-
-       return ret;
-}
-
-static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data)
-{
-       struct max77802_rtc_info *info = data;
-
-       dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq);
-
-       rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
-
-       return IRQ_HANDLED;
-}
-
-static const struct rtc_class_ops max77802_rtc_ops = {
-       .read_time = max77802_rtc_read_time,
-       .set_time = max77802_rtc_set_time,
-       .read_alarm = max77802_rtc_read_alarm,
-       .set_alarm = max77802_rtc_set_alarm,
-       .alarm_irq_enable = max77802_rtc_alarm_irq_enable,
-};
-
-static int max77802_rtc_init_reg(struct max77802_rtc_info *info)
-{
-       u8 data[2];
-       int ret;
-
-       max77802_rtc_update(info, MAX77802_RTC_READ);
-
-       /* Set RTC control register : Binary mode, 24hour mdoe */
-       data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
-       data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
-
-       info->rtc_24hr_mode = 1;
-
-       ret = regmap_bulk_write(info->max77802->regmap,
-                               MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data));
-       if (ret < 0) {
-               dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
-                               __func__, ret);
-               return ret;
-       }
-
-       ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
-       return ret;
-}
-
-static int max77802_rtc_probe(struct platform_device *pdev)
-{
-       struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent);
-       struct max77802_rtc_info *info;
-       int ret;
-
-       dev_dbg(&pdev->dev, "%s\n", __func__);
-
-       info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info),
-                           GFP_KERNEL);
-       if (!info)
-               return -ENOMEM;
-
-       mutex_init(&info->lock);
-       info->dev = &pdev->dev;
-       info->max77802 = max77802;
-       info->rtc = max77802->i2c;
-
-       platform_set_drvdata(pdev, info);
-
-       ret = max77802_rtc_init_reg(info);
-
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
-               return ret;
-       }
-
-       device_init_wakeup(&pdev->dev, 1);
-
-       info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc",
-                                                &max77802_rtc_ops, THIS_MODULE);
-
-       if (IS_ERR(info->rtc_dev)) {
-               ret = PTR_ERR(info->rtc_dev);
-               dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
-               if (ret == 0)
-                       ret = -EINVAL;
-               return ret;
-       }
-
-       if (!max77802->rtc_irq_data) {
-               dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
-               return -EINVAL;
-       }
-
-       info->virq = regmap_irq_get_virq(max77802->rtc_irq_data,
-                                        MAX77686_RTCIRQ_RTCA1);
-
-       if (info->virq <= 0) {
-               dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
-                       MAX77686_RTCIRQ_RTCA1);
-               return -EINVAL;
-       }
-
-       ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
-                                       max77802_rtc_alarm_irq, 0, "rtc-alarm1",
-                                       info);
-       if (ret < 0)
-               dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
-                       info->virq, ret);
-
-       return ret;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int max77802_rtc_suspend(struct device *dev)
-{
-       if (device_may_wakeup(dev)) {
-               struct max77802_rtc_info *info = dev_get_drvdata(dev);
-
-               return enable_irq_wake(info->virq);
-       }
-
-       return 0;
-}
-
-static int max77802_rtc_resume(struct device *dev)
-{
-       if (device_may_wakeup(dev)) {
-               struct max77802_rtc_info *info = dev_get_drvdata(dev);
-
-               return disable_irq_wake(info->virq);
-       }
-
-       return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops,
-                        max77802_rtc_suspend, max77802_rtc_resume);
-
-static const struct platform_device_id rtc_id[] = {
-       { "max77802-rtc", 0 },
-       {},
-};
-MODULE_DEVICE_TABLE(platform, rtc_id);
-
-static struct platform_driver max77802_rtc_driver = {
-       .driver         = {
-               .name   = "max77802-rtc",
-               .pm     = &max77802_rtc_pm_ops,
-       },
-       .probe          = max77802_rtc_probe,
-       .id_table       = rtc_id,
-};
-
-module_platform_driver(max77802_rtc_driver);
-
-MODULE_DESCRIPTION("Maxim MAX77802 RTC driver");
-MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
-MODULE_LICENSE("GPL");
index 06a5c52b292f292fd619a4049ba264e84b064f70..44f622c3e0488aaf4481b5accd5b734adc3a39fe 100644 (file)
@@ -419,4 +419,3 @@ module_platform_driver(mtk_rtc_driver);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>");
 MODULE_DESCRIPTION("RTC Driver for MediaTek MT6397 PMIC");
-MODULE_ALIAS("platform:mt6397-rtc");
index 7ea2c471feca3864a20612b9720e25314b5f5e77..6080e0edef6328aa7d221ef48cc69c564b526a7a 100644 (file)
@@ -311,8 +311,7 @@ static int palmas_rtc_probe(struct platform_device *pdev)
 
        ret = devm_request_threaded_irq(&pdev->dev, palmas_rtc->irq, NULL,
                        palmas_rtc_interrupt,
-                       IRQF_TRIGGER_LOW | IRQF_ONESHOT |
-                       IRQF_EARLY_RESUME,
+                       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                        dev_name(&pdev->dev), palmas_rtc);
        if (ret < 0) {
                dev_err(&pdev->dev, "IRQ request failed, err = %d\n", ret);
index ea8a31c91641d46a7a5b44a2225a98e03c4317a3..da27738b12428eaac52771cfc62261995d1aa58e 100644 (file)
@@ -48,6 +48,7 @@
 
 #define DRV_VERSION "0.6"
 
+/* REGISTERS */
 #define PCF2123_REG_CTRL1      (0x00)  /* Control Register 1 */
 #define PCF2123_REG_CTRL2      (0x01)  /* Control Register 2 */
 #define PCF2123_REG_SC         (0x02)  /* datetime */
 #define PCF2123_REG_DW         (0x06)
 #define PCF2123_REG_MO         (0x07)
 #define PCF2123_REG_YR         (0x08)
+#define PCF2123_REG_ALRM_MN    (0x09)  /* Alarm Registers */
+#define PCF2123_REG_ALRM_HR    (0x0a)
+#define PCF2123_REG_ALRM_DM    (0x0b)
+#define PCF2123_REG_ALRM_DW    (0x0c)
+#define PCF2123_REG_OFFSET     (0x0d)  /* Clock Rate Offset Register */
+#define PCF2123_REG_TMR_CLKOUT (0x0e)  /* Timer Registers */
+#define PCF2123_REG_CTDWN_TMR  (0x0f)
+
+/* PCF2123_REG_CTRL1 BITS */
+#define CTRL1_CLEAR            (0)     /* Clear */
+#define CTRL1_CORR_INT         BIT(1)  /* Correction irq enable */
+#define CTRL1_12_HOUR          BIT(2)  /* 12 hour time */
+#define CTRL1_SW_RESET (BIT(3) | BIT(4) | BIT(6))      /* Software reset */
+#define CTRL1_STOP             BIT(5)  /* Stop the clock */
+#define CTRL1_EXT_TEST         BIT(7)  /* External clock test mode */
+
+/* PCF2123_REG_CTRL2 BITS */
+#define CTRL2_TIE              BIT(0)  /* Countdown timer irq enable */
+#define CTRL2_AIE              BIT(1)  /* Alarm irq enable */
+#define CTRL2_TF               BIT(2)  /* Countdown timer flag */
+#define CTRL2_AF               BIT(3)  /* Alarm flag */
+#define CTRL2_TI_TP            BIT(4)  /* Irq pin generates pulse */
+#define CTRL2_MSF              BIT(5)  /* Minute or second irq flag */
+#define CTRL2_SI               BIT(6)  /* Second irq enable */
+#define CTRL2_MI               BIT(7)  /* Minute irq enable */
+
+/* PCF2123_REG_SC BITS */
+#define OSC_HAS_STOPPED                BIT(7)  /* Clock has been stopped */
+
+/* PCF2123_REG_ALRM_XX BITS */
+#define ALRM_ENABLE            BIT(7)  /* MN, HR, DM, or DW alarm enable */
+
+/* PCF2123_REG_TMR_CLKOUT BITS */
+#define CD_TMR_4096KHZ         (0)     /* 4096 KHz countdown timer */
+#define CD_TMR_64HZ            (1)     /* 64 Hz countdown timer */
+#define CD_TMR_1HZ             (2)     /* 1 Hz countdown timer */
+#define CD_TMR_60th_HZ         (3)     /* 60th Hz countdown timer */
+#define CD_TMR_TE              BIT(3)  /* Countdown timer enable */
+
+/* PCF2123_REG_OFFSET BITS */
+#define OFFSET_SIGN_BIT                BIT(6)  /* 2's complement sign bit */
+#define OFFSET_COARSE          BIT(7)  /* Coarse mode offset */
+#define OFFSET_STEP            (2170)  /* Offset step in parts per billion */
+
+/* READ/WRITE ADDRESS BITS */
+#define PCF2123_WRITE          BIT(4)
+#define PCF2123_READ           (BIT(4) | BIT(7))
 
-#define PCF2123_SUBADDR                (1 << 4)
-#define PCF2123_WRITE          ((0 << 7) | PCF2123_SUBADDR)
-#define PCF2123_READ           ((1 << 7) | PCF2123_SUBADDR)
 
 static struct spi_driver pcf2123_driver;
 
@@ -84,12 +129,44 @@ static inline void pcf2123_delay_trec(void)
        ndelay(30);
 }
 
+static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       int ret;
+
+       reg |= PCF2123_READ;
+       ret = spi_write_then_read(spi, &reg, 1, rxbuf, size);
+       pcf2123_delay_trec();
+
+       return ret;
+}
+
+static int pcf2123_write(struct device *dev, u8 *txbuf, size_t size)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       int ret;
+
+       txbuf[0] |= PCF2123_WRITE;
+       ret = spi_write(spi, txbuf, size);
+       pcf2123_delay_trec();
+
+       return ret;
+}
+
+static int pcf2123_write_reg(struct device *dev, u8 reg, u8 val)
+{
+       u8 txbuf[2];
+
+       txbuf[0] = reg;
+       txbuf[1] = val;
+       return pcf2123_write(dev, txbuf, sizeof(txbuf));
+}
+
 static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
                            char *buffer)
 {
-       struct spi_device *spi = to_spi_device(dev);
        struct pcf2123_sysfs_reg *r;
-       u8 txbuf[1], rxbuf[1];
+       u8 rxbuf[1];
        unsigned long reg;
        int ret;
 
@@ -99,19 +176,16 @@ static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
        if (ret)
                return ret;
 
-       txbuf[0] = PCF2123_READ | reg;
-       ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1);
+       ret = pcf2123_read(dev, reg, rxbuf, 1);
        if (ret < 0)
                return -EIO;
-       pcf2123_delay_trec();
+
        return sprintf(buffer, "0x%x\n", rxbuf[0]);
 }
 
 static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
                             const char *buffer, size_t count) {
-       struct spi_device *spi = to_spi_device(dev);
        struct pcf2123_sysfs_reg *r;
-       u8 txbuf[2];
        unsigned long reg;
        unsigned long val;
 
@@ -127,27 +201,78 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
        if (ret)
                return ret;
 
-       txbuf[0] = PCF2123_WRITE | reg;
-       txbuf[1] = val;
-       ret = spi_write(spi, txbuf, sizeof(txbuf));
+       pcf2123_write_reg(dev, reg, val);
        if (ret < 0)
                return -EIO;
-       pcf2123_delay_trec();
        return count;
 }
 
+static int pcf2123_read_offset(struct device *dev, long *offset)
+{
+       int ret;
+       s8 reg;
+
+       ret = pcf2123_read(dev, PCF2123_REG_OFFSET, &reg, 1);
+       if (ret < 0)
+               return ret;
+
+       if (reg & OFFSET_COARSE)
+               reg <<= 1; /* multiply by 2 and sign extend */
+       else
+               reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */
+
+       *offset = ((long)reg) * OFFSET_STEP;
+
+       return 0;
+}
+
+/*
+ * The offset register is a 7 bit signed value with a coarse bit in bit 7.
+ * The main difference between the two is normal offset adjusts the first
+ * second of n minutes every other hour, with 61, 62 and 63 being shoved
+ * into the 60th minute.
+ * The coarse adjustment does the same, but every hour.
+ * the two overlap, with every even normal offset value corresponding
+ * to a coarse offset. Based on this algorithm, it seems that despite the
+ * name, coarse offset is a better fit for overlapping values.
+ */
+static int pcf2123_set_offset(struct device *dev, long offset)
+{
+       s8 reg;
+
+       if (offset > OFFSET_STEP * 127)
+               reg = 127;
+       else if (offset < OFFSET_STEP * -128)
+               reg = -128;
+       else
+               reg = (s8)((offset + (OFFSET_STEP >> 1)) / OFFSET_STEP);
+
+       /* choose fine offset only for odd values in the normal range */
+       if (reg & 1 && reg <= 63 && reg >= -64) {
+               /* Normal offset. Clear the coarse bit */
+               reg &= ~OFFSET_COARSE;
+       } else {
+               /* Coarse offset. Divide by 2 and set the coarse bit */
+               reg >>= 1;
+               reg |= OFFSET_COARSE;
+       }
+
+       return pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg);
+}
+
 static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       struct spi_device *spi = to_spi_device(dev);
-       u8 txbuf[1], rxbuf[7];
+       u8 rxbuf[7];
        int ret;
 
-       txbuf[0] = PCF2123_READ | PCF2123_REG_SC;
-       ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
-                       rxbuf, sizeof(rxbuf));
+       ret = pcf2123_read(dev, PCF2123_REG_SC, rxbuf, sizeof(rxbuf));
        if (ret < 0)
                return ret;
-       pcf2123_delay_trec();
+
+       if (rxbuf[0] & OSC_HAS_STOPPED) {
+               dev_info(dev, "clock was stopped. Time is not valid\n");
+               return -EINVAL;
+       }
 
        tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
        tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
@@ -170,7 +295,6 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-       struct spi_device *spi = to_spi_device(dev);
        u8 txbuf[8];
        int ret;
 
@@ -181,15 +305,12 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
                        tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
        /* Stop the counter first */
-       txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-       txbuf[1] = 0x20;
-       ret = spi_write(spi, txbuf, 2);
+       ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
        if (ret < 0)
                return ret;
-       pcf2123_delay_trec();
 
        /* Set the new time */
-       txbuf[0] = PCF2123_WRITE | PCF2123_REG_SC;
+       txbuf[0] = PCF2123_REG_SC;
        txbuf[1] = bin2bcd(tm->tm_sec & 0x7F);
        txbuf[2] = bin2bcd(tm->tm_min & 0x7F);
        txbuf[3] = bin2bcd(tm->tm_hour & 0x3F);
@@ -198,18 +319,48 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
        txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */
        txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100);
 
-       ret = spi_write(spi, txbuf, sizeof(txbuf));
+       ret = pcf2123_write(dev, txbuf, sizeof(txbuf));
        if (ret < 0)
                return ret;
-       pcf2123_delay_trec();
 
        /* Start the counter */
-       txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-       txbuf[1] = 0x00;
-       ret = spi_write(spi, txbuf, 2);
+       ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int pcf2123_reset(struct device *dev)
+{
+       int ret;
+       u8  rxbuf[2];
+
+       ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_SW_RESET);
+       if (ret < 0)
+               return ret;
+
+       /* Stop the counter */
+       dev_dbg(dev, "stopping RTC\n");
+       ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
+       if (ret < 0)
+               return ret;
+
+       /* See if the counter was actually stopped */
+       dev_dbg(dev, "checking for presence of RTC\n");
+       ret = pcf2123_read(dev, PCF2123_REG_CTRL1, rxbuf, sizeof(rxbuf));
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(dev, "received data from RTC (0x%02X 0x%02X)\n",
+               rxbuf[0], rxbuf[1]);
+       if (!(rxbuf[0] & CTRL1_STOP))
+               return -ENODEV;
+
+       /* Start the counter */
+       ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
        if (ret < 0)
                return ret;
-       pcf2123_delay_trec();
 
        return 0;
 }
@@ -217,13 +368,16 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
 static const struct rtc_class_ops pcf2123_rtc_ops = {
        .read_time      = pcf2123_rtc_read_time,
        .set_time       = pcf2123_rtc_set_time,
+       .read_offset    = pcf2123_read_offset,
+       .set_offset     = pcf2123_set_offset,
+
 };
 
 static int pcf2123_probe(struct spi_device *spi)
 {
        struct rtc_device *rtc;
+       struct rtc_time tm;
        struct pcf2123_plat_data *pdata;
-       u8 txbuf[2], rxbuf[2];
        int ret, i;
 
        pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data),
@@ -232,56 +386,19 @@ static int pcf2123_probe(struct spi_device *spi)
                return -ENOMEM;
        spi->dev.platform_data = pdata;
 
-       /* Send a software reset command */
-       txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-       txbuf[1] = 0x58;
-       dev_dbg(&spi->dev, "resetting RTC (0x%02X 0x%02X)\n",
-                       txbuf[0], txbuf[1]);
-       ret = spi_write(spi, txbuf, 2 * sizeof(u8));
-       if (ret < 0)
-               goto kfree_exit;
-       pcf2123_delay_trec();
-
-       /* Stop the counter */
-       txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-       txbuf[1] = 0x20;
-       dev_dbg(&spi->dev, "stopping RTC (0x%02X 0x%02X)\n",
-                       txbuf[0], txbuf[1]);
-       ret = spi_write(spi, txbuf, 2 * sizeof(u8));
-       if (ret < 0)
-               goto kfree_exit;
-       pcf2123_delay_trec();
-
-       /* See if the counter was actually stopped */
-       txbuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;
-       dev_dbg(&spi->dev, "checking for presence of RTC (0x%02X)\n",
-                       txbuf[0]);
-       ret = spi_write_then_read(spi, txbuf, 1 * sizeof(u8),
-                                       rxbuf, 2 * sizeof(u8));
-       dev_dbg(&spi->dev, "received data from RTC (0x%02X 0x%02X)\n",
-                       rxbuf[0], rxbuf[1]);
-       if (ret < 0)
-               goto kfree_exit;
-       pcf2123_delay_trec();
-
-       if (!(rxbuf[0] & 0x20)) {
-               dev_err(&spi->dev, "chip not found\n");
-               ret = -ENODEV;
-               goto kfree_exit;
+       ret = pcf2123_rtc_read_time(&spi->dev, &tm);
+       if (ret < 0) {
+               ret = pcf2123_reset(&spi->dev);
+               if (ret < 0) {
+                       dev_err(&spi->dev, "chip not found\n");
+                       goto kfree_exit;
+               }
        }
 
        dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n");
        dev_info(&spi->dev, "spiclk %u KHz.\n",
                        (spi->max_speed_hz + 500) / 1000);
 
-       /* Start the counter */
-       txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
-       txbuf[1] = 0x00;
-       ret = spi_write(spi, txbuf, sizeof(txbuf));
-       if (ret < 0)
-               goto kfree_exit;
-       pcf2123_delay_trec();
-
        /* Finalize the initialization */
        rtc = devm_rtc_device_register(&spi->dev, pcf2123_driver.driver.name,
                        &pcf2123_rtc_ops, THIS_MODULE);
index 629bfdf8c74540ac81a0c538f4b79e301bec8638..2bfdf638b67390661f10e1405eea44d544eda6ad 100644 (file)
@@ -1,12 +1,12 @@
 /*
- * An I2C driver for the NXP PCF2127 RTC
+ * An I2C and SPI driver for the NXP PCF2127/29 RTC
  * Copyright 2013 Til-Technologies
  *
  * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
  *
  * based on the other drivers in this same directory.
  *
- * http://www.nxp.com/documents/data_sheet/PCF2127AT.pdf
+ * Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf
  *
  * 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
  */
 
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/regmap.h>
 
 #define PCF2127_REG_CTRL1       (0x00)  /* Control Register 1 */
 #define PCF2127_REG_CTRL2       (0x01)  /* Control Register 2 */
 
 #define PCF2127_OSF             BIT(7)  /* Oscillator Fail flag */
 
-static struct i2c_driver pcf2127_driver;
-
 struct pcf2127 {
        struct rtc_device *rtc;
+       struct regmap *regmap;
 };
 
 /*
  * In the routines that deal directly with the pcf2127 hardware, we use
  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
  */
-static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       unsigned char buf[10] = { PCF2127_REG_CTRL1 };
+       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+       unsigned char buf[10];
+       int ret;
 
-       /* read registers */
-       if (i2c_master_send(client, buf, 1) != 1 ||
-               i2c_master_recv(client, buf, sizeof(buf)) != sizeof(buf)) {
-               dev_err(&client->dev, "%s: read error\n", __func__);
-               return -EIO;
+       ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, buf,
+                               sizeof(buf));
+       if (ret) {
+               dev_err(dev, "%s: read error\n", __func__);
+               return ret;
        }
 
        if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
-               dev_info(&client->dev,
+               dev_info(dev,
                        "low voltage detected, check/replace RTC battery.\n");
 
        if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
@@ -66,12 +69,12 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
                 * no need clear the flag here,
                 * it will be cleared once the new date is saved
                 */
-               dev_warn(&client->dev,
+               dev_warn(dev,
                         "oscillator stop detected, date/time is not reliable\n");
                return -EINVAL;
        }
 
-       dev_dbg(&client->dev,
+       dev_dbg(dev,
                "%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, "
                "sec=%02x, min=%02x, hr=%02x, "
                "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
@@ -91,7 +94,7 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        if (tm->tm_year < 70)
                tm->tm_year += 100;     /* assume we are in 1970...2069 */
 
-       dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+       dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
                "mday=%d, mon=%d, year=%d, wday=%d\n",
                __func__,
                tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -100,20 +103,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        return rtc_valid_tm(tm);
 }
 
-static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-       unsigned char buf[8];
+       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+       unsigned char buf[7];
        int i = 0, err;
 
-       dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+       dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
                "mday=%d, mon=%d, year=%d, wday=%d\n",
                __func__,
                tm->tm_sec, tm->tm_min, tm->tm_hour,
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
-       /* start register address */
-       buf[i++] = PCF2127_REG_SC;
-
        /* hours, minutes and seconds */
        buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */
        buf[i++] = bin2bcd(tm->tm_min);
@@ -128,11 +129,11 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
        buf[i++] = bin2bcd(tm->tm_year % 100);
 
        /* write register's data */
-       err = i2c_master_send(client, buf, i);
-       if (err != i) {
-               dev_err(&client->dev,
+       err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i);
+       if (err) {
+               dev_err(dev,
                        "%s: err=%d", __func__, err);
-               return -EIO;
+               return err;
        }
 
        return 0;
@@ -142,26 +143,17 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 static int pcf2127_rtc_ioctl(struct device *dev,
                                unsigned int cmd, unsigned long arg)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       unsigned char buf = PCF2127_REG_CTRL3;
+       struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
        int touser;
        int ret;
 
        switch (cmd) {
        case RTC_VL_READ:
-               ret = i2c_master_send(client, &buf, 1);
-               if (!ret)
-                       ret = -EIO;
-               if (ret < 0)
-                       return ret;
-
-               ret = i2c_master_recv(client, &buf, 1);
-               if (!ret)
-                       ret = -EIO;
-               if (ret < 0)
+               ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &touser);
+               if (ret)
                        return ret;
 
-               touser = buf & PCF2127_REG_CTRL3_BLF ? 1 : 0;
+               touser = touser & PCF2127_REG_CTRL3_BLF ? 1 : 0;
 
                if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
                        return -EFAULT;
@@ -174,71 +166,270 @@ static int pcf2127_rtc_ioctl(struct device *dev,
 #define pcf2127_rtc_ioctl NULL
 #endif
 
-static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
-       return pcf2127_get_datetime(to_i2c_client(dev), tm);
-}
-
-static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
-       return pcf2127_set_datetime(to_i2c_client(dev), tm);
-}
-
 static const struct rtc_class_ops pcf2127_rtc_ops = {
        .ioctl          = pcf2127_rtc_ioctl,
        .read_time      = pcf2127_rtc_read_time,
        .set_time       = pcf2127_rtc_set_time,
 };
 
-static int pcf2127_probe(struct i2c_client *client,
-                               const struct i2c_device_id *id)
+static int pcf2127_probe(struct device *dev, struct regmap *regmap,
+                       const char *name)
 {
        struct pcf2127 *pcf2127;
 
-       dev_dbg(&client->dev, "%s\n", __func__);
+       dev_dbg(dev, "%s\n", __func__);
 
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-               return -ENODEV;
-
-       pcf2127 = devm_kzalloc(&client->dev, sizeof(struct pcf2127),
-                               GFP_KERNEL);
+       pcf2127 = devm_kzalloc(dev, sizeof(*pcf2127), GFP_KERNEL);
        if (!pcf2127)
                return -ENOMEM;
 
-       i2c_set_clientdata(client, pcf2127);
+       pcf2127->regmap = regmap;
+
+       dev_set_drvdata(dev, pcf2127);
 
-       pcf2127->rtc = devm_rtc_device_register(&client->dev,
-                               pcf2127_driver.driver.name,
-                               &pcf2127_rtc_ops, THIS_MODULE);
+       pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
+                                               THIS_MODULE);
 
        return PTR_ERR_OR_ZERO(pcf2127->rtc);
 }
 
-static const struct i2c_device_id pcf2127_id[] = {
-       { "pcf2127", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, pcf2127_id);
-
 #ifdef CONFIG_OF
 static const struct of_device_id pcf2127_of_match[] = {
        { .compatible = "nxp,pcf2127" },
+       { .compatible = "nxp,pcf2129" },
        {}
 };
 MODULE_DEVICE_TABLE(of, pcf2127_of_match);
 #endif
 
-static struct i2c_driver pcf2127_driver = {
+#if IS_ENABLED(CONFIG_I2C)
+
+static int pcf2127_i2c_write(void *context, const void *data, size_t count)
+{
+       struct device *dev = context;
+       struct i2c_client *client = to_i2c_client(dev);
+       int ret;
+
+       ret = i2c_master_send(client, data, count);
+       if (ret != count)
+               return ret < 0 ? ret : -EIO;
+
+       return 0;
+}
+
+static int pcf2127_i2c_gather_write(void *context,
+                               const void *reg, size_t reg_size,
+                               const void *val, size_t val_size)
+{
+       struct device *dev = context;
+       struct i2c_client *client = to_i2c_client(dev);
+       int ret;
+       void *buf;
+
+       if (WARN_ON(reg_size != 1))
+               return -EINVAL;
+
+       buf = kmalloc(val_size + 1, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       memcpy(buf, reg, 1);
+       memcpy(buf + 1, val, val_size);
+
+       ret = i2c_master_send(client, buf, val_size + 1);
+       if (ret != val_size + 1)
+               return ret < 0 ? ret : -EIO;
+
+       return 0;
+}
+
+static int pcf2127_i2c_read(void *context, const void *reg, size_t reg_size,
+                               void *val, size_t val_size)
+{
+       struct device *dev = context;
+       struct i2c_client *client = to_i2c_client(dev);
+       int ret;
+
+       if (WARN_ON(reg_size != 1))
+               return -EINVAL;
+
+       ret = i2c_master_send(client, reg, 1);
+       if (ret != 1)
+               return ret < 0 ? ret : -EIO;
+
+       ret = i2c_master_recv(client, val, val_size);
+       if (ret != val_size)
+               return ret < 0 ? ret : -EIO;
+
+       return 0;
+}
+
+/*
+ * The reason we need this custom regmap_bus instead of using regmap_init_i2c()
+ * is that the STOP condition is required between set register address and
+ * read register data when reading from registers.
+ */
+static const struct regmap_bus pcf2127_i2c_regmap = {
+       .write = pcf2127_i2c_write,
+       .gather_write = pcf2127_i2c_gather_write,
+       .read = pcf2127_i2c_read,
+};
+
+static struct i2c_driver pcf2127_i2c_driver;
+
+static int pcf2127_i2c_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct regmap *regmap;
+       static const struct regmap_config config = {
+               .reg_bits = 8,
+               .val_bits = 8,
+       };
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -ENODEV;
+
+       regmap = devm_regmap_init(&client->dev, &pcf2127_i2c_regmap,
+                                       &client->dev, &config);
+       if (IS_ERR(regmap)) {
+               dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
+                       __func__, PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       return pcf2127_probe(&client->dev, regmap,
+                               pcf2127_i2c_driver.driver.name);
+}
+
+static const struct i2c_device_id pcf2127_i2c_id[] = {
+       { "pcf2127", 0 },
+       { "pcf2129", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
+
+static struct i2c_driver pcf2127_i2c_driver = {
+       .driver         = {
+               .name   = "rtc-pcf2127-i2c",
+               .of_match_table = of_match_ptr(pcf2127_of_match),
+       },
+       .probe          = pcf2127_i2c_probe,
+       .id_table       = pcf2127_i2c_id,
+};
+
+static int pcf2127_i2c_register_driver(void)
+{
+       return i2c_add_driver(&pcf2127_i2c_driver);
+}
+
+static void pcf2127_i2c_unregister_driver(void)
+{
+       i2c_del_driver(&pcf2127_i2c_driver);
+}
+
+#else
+
+static int pcf2127_i2c_register_driver(void)
+{
+       return 0;
+}
+
+static void pcf2127_i2c_unregister_driver(void)
+{
+}
+
+#endif
+
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static struct spi_driver pcf2127_spi_driver;
+
+static int pcf2127_spi_probe(struct spi_device *spi)
+{
+       static const struct regmap_config config = {
+               .reg_bits = 8,
+               .val_bits = 8,
+               .read_flag_mask = 0xa0,
+               .write_flag_mask = 0x20,
+       };
+       struct regmap *regmap;
+
+       regmap = devm_regmap_init_spi(spi, &config);
+       if (IS_ERR(regmap)) {
+               dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
+                       __func__, PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+
+       return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name);
+}
+
+static const struct spi_device_id pcf2127_spi_id[] = {
+       { "pcf2127", 0 },
+       { "pcf2129", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, pcf2127_spi_id);
+
+static struct spi_driver pcf2127_spi_driver = {
        .driver         = {
-               .name   = "rtc-pcf2127",
+               .name   = "rtc-pcf2127-spi",
                .of_match_table = of_match_ptr(pcf2127_of_match),
        },
-       .probe          = pcf2127_probe,
-       .id_table       = pcf2127_id,
+       .probe          = pcf2127_spi_probe,
+       .id_table       = pcf2127_spi_id,
 };
 
-module_i2c_driver(pcf2127_driver);
+static int pcf2127_spi_register_driver(void)
+{
+       return spi_register_driver(&pcf2127_spi_driver);
+}
+
+static void pcf2127_spi_unregister_driver(void)
+{
+       spi_unregister_driver(&pcf2127_spi_driver);
+}
+
+#else
+
+static int pcf2127_spi_register_driver(void)
+{
+       return 0;
+}
+
+static void pcf2127_spi_unregister_driver(void)
+{
+}
+
+#endif
+
+static int __init pcf2127_init(void)
+{
+       int ret;
+
+       ret = pcf2127_i2c_register_driver();
+       if (ret) {
+               pr_err("Failed to register pcf2127 i2c driver: %d\n", ret);
+               return ret;
+       }
+
+       ret = pcf2127_spi_register_driver();
+       if (ret) {
+               pr_err("Failed to register pcf2127 spi driver: %d\n", ret);
+               pcf2127_i2c_unregister_driver();
+       }
+
+       return ret;
+}
+module_init(pcf2127_init)
+
+static void __exit pcf2127_exit(void)
+{
+       pcf2127_spi_unregister_driver();
+       pcf2127_i2c_unregister_driver();
+}
+module_exit(pcf2127_exit)
 
 MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");
-MODULE_DESCRIPTION("NXP PCF2127 RTC driver");
+MODULE_DESCRIPTION("NXP PCF2127/29 RTC driver");
 MODULE_LICENSE("GPL v2");
index 63334cbeca41d8233b55e674e120ec4bd895a45a..e8ddbb359d11951f0d9592895a23699941280412 100644 (file)
 #include <linux/rtc.h>
 #include <linux/module.h>
 
-#define DRV_VERSION "0.0.1"
-
 #define PCF85063_REG_CTRL1             0x00 /* status */
+#define PCF85063_REG_CTRL1_STOP                BIT(5)
 #define PCF85063_REG_CTRL2             0x01
 
 #define PCF85063_REG_SC                        0x04 /* datetime */
+#define PCF85063_REG_SC_OS             0x80
 #define PCF85063_REG_MN                        0x05
 #define PCF85063_REG_HR                        0x06
 #define PCF85063_REG_DM                        0x07
 #define PCF85063_REG_MO                        0x09
 #define PCF85063_REG_YR                        0x0A
 
-#define PCF85063_MO_C                  0x80 /* century */
-
 static struct i2c_driver pcf85063_driver;
 
-struct pcf85063 {
-       struct rtc_device *rtc;
-       int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
-       int voltage_low; /* indicates if a low_voltage was detected */
-};
+static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
+{
+       s32 ret;
+
+       ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
+       if (ret < 0) {
+               dev_err(&client->dev, "Failing to stop the clock\n");
+               return -EIO;
+       }
+
+       /* stop the clock */
+       ret |= PCF85063_REG_CTRL1_STOP;
+
+       ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret);
+       if (ret < 0) {
+               dev_err(&client->dev, "Failing to stop the clock\n");
+               return -EIO;
+       }
+
+       *ctrl1 = ret;
+
+       return 0;
+}
 
 /*
  * In the routines that deal directly with the pcf85063 hardware, we use
@@ -45,81 +61,85 @@ struct pcf85063 {
  */
 static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-       struct pcf85063 *pcf85063 = i2c_get_clientdata(client);
-       unsigned char buf[13] = { PCF85063_REG_CTRL1 };
-       struct i2c_msg msgs[] = {
-               {/* setup read ptr */
-                       .addr = client->addr,
-                       .len = 1,
-                       .buf = buf
-               },
-               {/* read status + date */
-                       .addr = client->addr,
-                       .flags = I2C_M_RD,
-                       .len = 13,
-                       .buf = buf
-               },
-       };
-
-       /* read registers */
-       if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
-               dev_err(&client->dev, "%s: read error\n", __func__);
+       int rc;
+       u8 regs[7];
+
+       /*
+        * while reading, the time/date registers are blocked and not updated
+        * anymore until the access is finished. To not lose a second
+        * event, the access must be finished within one second. So, read all
+        * time/date registers in one turn.
+        */
+       rc = i2c_smbus_read_i2c_block_data(client, PCF85063_REG_SC,
+                                          sizeof(regs), regs);
+       if (rc != sizeof(regs)) {
+               dev_err(&client->dev, "date/time register read error\n");
                return -EIO;
        }
 
-       tm->tm_sec = bcd2bin(buf[PCF85063_REG_SC] & 0x7F);
-       tm->tm_min = bcd2bin(buf[PCF85063_REG_MN] & 0x7F);
-       tm->tm_hour = bcd2bin(buf[PCF85063_REG_HR] & 0x3F); /* rtc hr 0-23 */
-       tm->tm_mday = bcd2bin(buf[PCF85063_REG_DM] & 0x3F);
-       tm->tm_wday = buf[PCF85063_REG_DW] & 0x07;
-       tm->tm_mon = bcd2bin(buf[PCF85063_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
-       tm->tm_year = bcd2bin(buf[PCF85063_REG_YR]);
+       /* if the clock has lost its power it makes no sense to use its time */
+       if (regs[0] & PCF85063_REG_SC_OS) {
+               dev_warn(&client->dev, "Power loss detected, invalid time\n");
+               return -EINVAL;
+       }
+
+       tm->tm_sec = bcd2bin(regs[0] & 0x7F);
+       tm->tm_min = bcd2bin(regs[1] & 0x7F);
+       tm->tm_hour = bcd2bin(regs[2] & 0x3F); /* rtc hr 0-23 */
+       tm->tm_mday = bcd2bin(regs[3] & 0x3F);
+       tm->tm_wday = regs[4] & 0x07;
+       tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
+       tm->tm_year = bcd2bin(regs[6]);
        if (tm->tm_year < 70)
                tm->tm_year += 100;     /* assume we are in 1970...2069 */
-       /* detect the polarity heuristically. see note above. */
-       pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ?
-               (tm->tm_year >= 100) : (tm->tm_year < 100);
 
        return rtc_valid_tm(tm);
 }
 
 static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-       int i = 0, err = 0;
-       unsigned char buf[11];
+       int rc;
+       u8 regs[8];
 
-       /* Control & status */
-       buf[PCF85063_REG_CTRL1] = 0;
-       buf[PCF85063_REG_CTRL2] = 5;
+       /*
+        * to accurately set the time, reset the divider chain and keep it in
+        * reset state until all time/date registers are written
+        */
+       rc = pcf85063_stop_clock(client, &regs[7]);
+       if (rc != 0)
+               return rc;
 
        /* hours, minutes and seconds */
-       buf[PCF85063_REG_SC] = bin2bcd(tm->tm_sec) & 0x7F;
+       regs[0] = bin2bcd(tm->tm_sec) & 0x7F; /* clear OS flag */
 
-       buf[PCF85063_REG_MN] = bin2bcd(tm->tm_min);
-       buf[PCF85063_REG_HR] = bin2bcd(tm->tm_hour);
+       regs[1] = bin2bcd(tm->tm_min);
+       regs[2] = bin2bcd(tm->tm_hour);
 
        /* Day of month, 1 - 31 */
-       buf[PCF85063_REG_DM] = bin2bcd(tm->tm_mday);
+       regs[3] = bin2bcd(tm->tm_mday);
 
        /* Day, 0 - 6 */
-       buf[PCF85063_REG_DW] = tm->tm_wday & 0x07;
+       regs[4] = tm->tm_wday & 0x07;
 
        /* month, 1 - 12 */
-       buf[PCF85063_REG_MO] = bin2bcd(tm->tm_mon + 1);
+       regs[5] = bin2bcd(tm->tm_mon + 1);
 
        /* year and century */
-       buf[PCF85063_REG_YR] = bin2bcd(tm->tm_year % 100);
-
-       /* write register's data */
-       for (i = 0; i < sizeof(buf); i++) {
-               unsigned char data[2] = { i, buf[i] };
-
-               err = i2c_master_send(client, data, sizeof(data));
-               if (err != sizeof(data)) {
-                       dev_err(&client->dev, "%s: err=%d addr=%02x, data=%02x\n",
-                                       __func__, err, data[0], data[1]);
-                       return -EIO;
-               }
+       regs[6] = bin2bcd(tm->tm_year % 100);
+
+       /*
+        * after all time/date registers are written, let the 'address auto
+        * increment' feature wrap around and write register CTRL1 to re-enable
+        * the clock divider chain again
+        */
+       regs[7] &= ~PCF85063_REG_CTRL1_STOP;
+
+       /* write all registers at once */
+       rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC,
+                                           sizeof(regs), regs);
+       if (rc < 0) {
+               dev_err(&client->dev, "date/time register write error\n");
+               return rc;
        }
 
        return 0;
@@ -143,27 +163,18 @@ static const struct rtc_class_ops pcf85063_rtc_ops = {
 static int pcf85063_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
-       struct pcf85063 *pcf85063;
+       struct rtc_device *rtc;
 
        dev_dbg(&client->dev, "%s\n", __func__);
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
                return -ENODEV;
 
-       pcf85063 = devm_kzalloc(&client->dev, sizeof(struct pcf85063),
-                               GFP_KERNEL);
-       if (!pcf85063)
-               return -ENOMEM;
-
-       dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
-
-       i2c_set_clientdata(client, pcf85063);
-
-       pcf85063->rtc = devm_rtc_device_register(&client->dev,
-                               pcf85063_driver.driver.name,
-                               &pcf85063_rtc_ops, THIS_MODULE);
+       rtc = devm_rtc_device_register(&client->dev,
+                                      pcf85063_driver.driver.name,
+                                      &pcf85063_rtc_ops, THIS_MODULE);
 
-       return PTR_ERR_OR_ZERO(pcf85063->rtc);
+       return PTR_ERR_OR_ZERO(rtc);
 }
 
 static const struct i2c_device_id pcf85063_id[] = {
@@ -194,4 +205,3 @@ module_i2c_driver(pcf85063_driver);
 MODULE_AUTHOR("Søren Andersen <san@rosetechnology.dk>");
 MODULE_DESCRIPTION("PCF85063 RTC driver");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
index 988566caaaa639c7854f3a78c1aecbf21c478139..28c48b3c1946dc8856b7c00a090ba132755dddc7 100644 (file)
@@ -178,28 +178,8 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
        if (err < 0)
                return err;
 
-       if (regs[0] & REG_SECONDS_OS) {
-               /*
-                * If the oscillator was stopped, try to clear the flag. Upon
-                * power-up the flag is always set, but if we cannot clear it
-                * the oscillator isn't running properly for some reason. The
-                * sensible thing therefore is to return an error, signalling
-                * that the clock cannot be assumed to be correct.
-                */
-
-               regs[0] &= ~REG_SECONDS_OS;
-
-               err = pcf8523_write(client, REG_SECONDS, regs[0]);
-               if (err < 0)
-                       return err;
-
-               err = pcf8523_read(client, REG_SECONDS, &regs[0]);
-               if (err < 0)
-                       return err;
-
-               if (regs[0] & REG_SECONDS_OS)
-                       return -EAGAIN;
-       }
+       if (regs[0] & REG_SECONDS_OS)
+               return -EINVAL;
 
        tm->tm_sec = bcd2bin(regs[0] & 0x7f);
        tm->tm_min = bcd2bin(regs[1] & 0x7f);
@@ -235,6 +215,7 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
                return err;
 
        regs[0] = REG_SECONDS;
+       /* This will purposely overwrite REG_SECONDS_OS */
        regs[1] = bin2bcd(tm->tm_sec);
        regs[2] = bin2bcd(tm->tm_min);
        regs[3] = bin2bcd(tm->tm_hour);
diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c
new file mode 100644 (file)
index 0000000..64e1e45
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * PIC32 RTC driver
+ *
+ * Joshua Henderson <joshua.henderson@microchip.com>
+ * Copyright (C) 2016 Microchip Technology Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/mach-pic32/pic32.h>
+
+#define PIC32_RTCCON           0x00
+#define PIC32_RTCCON_ON                BIT(15)
+#define PIC32_RTCCON_SIDL      BIT(13)
+#define PIC32_RTCCON_RTCCLKSEL (3 << 9)
+#define PIC32_RTCCON_RTCCLKON  BIT(6)
+#define PIC32_RTCCON_RTCWREN   BIT(3)
+#define PIC32_RTCCON_RTCSYNC   BIT(2)
+#define PIC32_RTCCON_HALFSEC   BIT(1)
+#define PIC32_RTCCON_RTCOE     BIT(0)
+
+#define PIC32_RTCALRM          0x10
+#define PIC32_RTCALRM_ALRMEN   BIT(15)
+#define PIC32_RTCALRM_CHIME    BIT(14)
+#define PIC32_RTCALRM_PIV      BIT(13)
+#define PIC32_RTCALRM_ALARMSYNC        BIT(12)
+#define PIC32_RTCALRM_AMASK    0x0F00
+#define PIC32_RTCALRM_ARPT     0xFF
+
+#define PIC32_RTCHOUR          0x23
+#define PIC32_RTCMIN           0x22
+#define PIC32_RTCSEC           0x21
+#define PIC32_RTCYEAR          0x33
+#define PIC32_RTCMON           0x32
+#define PIC32_RTCDAY           0x31
+
+#define PIC32_ALRMTIME         0x40
+#define PIC32_ALRMDATE         0x50
+
+#define PIC32_ALRMHOUR         0x43
+#define PIC32_ALRMMIN          0x42
+#define PIC32_ALRMSEC          0x41
+#define PIC32_ALRMYEAR         0x53
+#define PIC32_ALRMMON          0x52
+#define PIC32_ALRMDAY          0x51
+
+struct pic32_rtc_dev {
+       struct rtc_device       *rtc;
+       void __iomem            *reg_base;
+       struct clk              *clk;
+       spinlock_t              alarm_lock;
+       int                     alarm_irq;
+       bool                    alarm_clk_enabled;
+};
+
+static void pic32_rtc_alarm_clk_enable(struct pic32_rtc_dev *pdata,
+                                      bool enable)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&pdata->alarm_lock, flags);
+       if (enable) {
+               if (!pdata->alarm_clk_enabled) {
+                       clk_enable(pdata->clk);
+                       pdata->alarm_clk_enabled = true;
+               }
+       } else {
+               if (pdata->alarm_clk_enabled) {
+                       clk_disable(pdata->clk);
+                       pdata->alarm_clk_enabled = false;
+               }
+       }
+       spin_unlock_irqrestore(&pdata->alarm_lock, flags);
+}
+
+static irqreturn_t pic32_rtc_alarmirq(int irq, void *id)
+{
+       struct pic32_rtc_dev *pdata = (struct pic32_rtc_dev *)id;
+
+       clk_enable(pdata->clk);
+       rtc_update_irq(pdata->rtc, 1, RTC_AF | RTC_IRQF);
+       clk_disable(pdata->clk);
+
+       pic32_rtc_alarm_clk_enable(pdata, false);
+
+       return IRQ_HANDLED;
+}
+
+static int pic32_rtc_setaie(struct device *dev, unsigned int enabled)
+{
+       struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+       void __iomem *base = pdata->reg_base;
+
+       clk_enable(pdata->clk);
+
+       writel(PIC32_RTCALRM_ALRMEN,
+              base + (enabled ? PIC32_SET(PIC32_RTCALRM) :
+                      PIC32_CLR(PIC32_RTCALRM)));
+
+       clk_disable(pdata->clk);
+
+       pic32_rtc_alarm_clk_enable(pdata, enabled);
+
+       return 0;
+}
+
+static int pic32_rtc_setfreq(struct device *dev, int freq)
+{
+       struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+       void __iomem *base = pdata->reg_base;
+
+       clk_enable(pdata->clk);
+
+       writel(PIC32_RTCALRM_AMASK, base + PIC32_CLR(PIC32_RTCALRM));
+       writel(freq << 8, base + PIC32_SET(PIC32_RTCALRM));
+       writel(PIC32_RTCALRM_CHIME, base + PIC32_SET(PIC32_RTCALRM));
+
+       clk_disable(pdata->clk);
+
+       return 0;
+}
+
+static int pic32_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+{
+       struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+       void __iomem *base = pdata->reg_base;
+       unsigned int tries = 0;
+
+       clk_enable(pdata->clk);
+
+       do {
+               rtc_tm->tm_hour = readb(base + PIC32_RTCHOUR);
+               rtc_tm->tm_min = readb(base + PIC32_RTCMIN);
+               rtc_tm->tm_mon  = readb(base + PIC32_RTCMON);
+               rtc_tm->tm_mday = readb(base + PIC32_RTCDAY);
+               rtc_tm->tm_year = readb(base + PIC32_RTCYEAR);
+               rtc_tm->tm_sec  = readb(base + PIC32_RTCSEC);
+
+               /*
+                * The only way to work out whether the system was mid-update
+                * when we read it is to check the second counter, and if it
+                * is zero, then we re-try the entire read.
+                */
+               tries += 1;
+       } while (rtc_tm->tm_sec == 0 && tries < 2);
+
+       rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+       rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+       rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+       rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+       rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon) - 1;
+       rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
+
+       rtc_tm->tm_year += 100;
+
+       dev_dbg(dev, "read time %04d.%02d.%02d %02d:%02d:%02d\n",
+               1900 + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
+               rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
+
+       clk_disable(pdata->clk);
+       return rtc_valid_tm(rtc_tm);
+}
+
+static int pic32_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+       struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+       void __iomem *base = pdata->reg_base;
+       int year = tm->tm_year - 100;
+
+       dev_dbg(dev, "set time %04d.%02d.%02d %02d:%02d:%02d\n",
+               1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+       if (year < 0 || year >= 100) {
+               dev_err(dev, "rtc only supports 100 years\n");
+               return -EINVAL;
+       }
+
+       clk_enable(pdata->clk);
+       writeb(bin2bcd(tm->tm_sec),  base + PIC32_RTCSEC);
+       writeb(bin2bcd(tm->tm_min),  base + PIC32_RTCMIN);
+       writeb(bin2bcd(tm->tm_hour), base + PIC32_RTCHOUR);
+       writeb(bin2bcd(tm->tm_mday), base + PIC32_RTCDAY);
+       writeb(bin2bcd(tm->tm_mon + 1), base + PIC32_RTCMON);
+       writeb(bin2bcd(year), base + PIC32_RTCYEAR);
+       clk_disable(pdata->clk);
+
+       return 0;
+}
+
+static int pic32_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+       struct rtc_time *alm_tm = &alrm->time;
+       void __iomem *base = pdata->reg_base;
+       unsigned int alm_en;
+
+       clk_enable(pdata->clk);
+       alm_tm->tm_sec  = readb(base + PIC32_ALRMSEC);
+       alm_tm->tm_min  = readb(base + PIC32_ALRMMIN);
+       alm_tm->tm_hour = readb(base + PIC32_ALRMHOUR);
+       alm_tm->tm_mon  = readb(base + PIC32_ALRMMON);
+       alm_tm->tm_mday = readb(base + PIC32_ALRMDAY);
+       alm_tm->tm_year = readb(base + PIC32_ALRMYEAR);
+
+       alm_en = readb(base + PIC32_RTCALRM);
+
+       alrm->enabled = (alm_en & PIC32_RTCALRM_ALRMEN) ? 1 : 0;
+
+       dev_dbg(dev, "getalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
+               alm_en,
+               1900 + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
+               alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
+
+       alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
+       alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
+       alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
+       alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
+       alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon) - 1;
+       alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
+
+       clk_disable(pdata->clk);
+       return 0;
+}
+
+static int pic32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+       struct rtc_time *tm = &alrm->time;
+       void __iomem *base = pdata->reg_base;
+
+       clk_enable(pdata->clk);
+       dev_dbg(dev, "setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
+               alrm->enabled,
+               1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+       writel(0x00, base + PIC32_ALRMTIME);
+       writel(0x00, base + PIC32_ALRMDATE);
+
+       pic32_rtc_setaie(dev, alrm->enabled);
+
+       clk_disable(pdata->clk);
+       return 0;
+}
+
+static int pic32_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+       struct pic32_rtc_dev *pdata = dev_get_drvdata(dev);
+       void __iomem *base = pdata->reg_base;
+       unsigned int repeat;
+
+       clk_enable(pdata->clk);
+
+       repeat = readw(base + PIC32_RTCALRM);
+       repeat &= PIC32_RTCALRM_ARPT;
+       seq_printf(seq, "periodic_IRQ\t: %s\n", repeat  ? "yes" : "no");
+
+       clk_disable(pdata->clk);
+       return 0;
+}
+
+static const struct rtc_class_ops pic32_rtcops = {
+       .read_time        = pic32_rtc_gettime,
+       .set_time         = pic32_rtc_settime,
+       .read_alarm       = pic32_rtc_getalarm,
+       .set_alarm        = pic32_rtc_setalarm,
+       .proc             = pic32_rtc_proc,
+       .alarm_irq_enable = pic32_rtc_setaie,
+};
+
+static void pic32_rtc_enable(struct pic32_rtc_dev *pdata, int en)
+{
+       void __iomem *base = pdata->reg_base;
+
+       if (!base)
+               return;
+
+       clk_enable(pdata->clk);
+       if (!en) {
+               writel(PIC32_RTCCON_ON, base + PIC32_CLR(PIC32_RTCCON));
+       } else {
+               pic32_syskey_unlock();
+
+               writel(PIC32_RTCCON_RTCWREN, base + PIC32_SET(PIC32_RTCCON));
+               writel(3 << 9, base + PIC32_CLR(PIC32_RTCCON));
+
+               if (!(readl(base + PIC32_RTCCON) & PIC32_RTCCON_ON))
+                       writel(PIC32_RTCCON_ON, base + PIC32_SET(PIC32_RTCCON));
+       }
+       clk_disable(pdata->clk);
+}
+
+static int pic32_rtc_remove(struct platform_device *pdev)
+{
+       struct pic32_rtc_dev *pdata = platform_get_drvdata(pdev);
+
+       pic32_rtc_setaie(&pdev->dev, 0);
+       clk_unprepare(pdata->clk);
+       pdata->clk = NULL;
+
+       return 0;
+}
+
+static int pic32_rtc_probe(struct platform_device *pdev)
+{
+       struct pic32_rtc_dev *pdata;
+       struct resource *res;
+       int ret;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, pdata);
+
+       pdata->alarm_irq = platform_get_irq(pdev, 0);
+       if (pdata->alarm_irq < 0) {
+               dev_err(&pdev->dev, "no irq for alarm\n");
+               return pdata->alarm_irq;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pdata->reg_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pdata->reg_base))
+               return PTR_ERR(pdata->reg_base);
+
+       pdata->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(pdata->clk)) {
+               dev_err(&pdev->dev, "failed to find rtc clock source\n");
+               ret = PTR_ERR(pdata->clk);
+               pdata->clk = NULL;
+               return ret;
+       }
+
+       spin_lock_init(&pdata->alarm_lock);
+
+       clk_prepare_enable(pdata->clk);
+
+       pic32_rtc_enable(pdata, 1);
+
+       device_init_wakeup(&pdev->dev, 1);
+
+       pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+                                                &pic32_rtcops,
+                                                THIS_MODULE);
+       if (IS_ERR(pdata->rtc)) {
+               ret = PTR_ERR(pdata->rtc);
+               goto err_nortc;
+       }
+
+       pdata->rtc->max_user_freq = 128;
+
+       pic32_rtc_setfreq(&pdev->dev, 1);
+       ret = devm_request_irq(&pdev->dev, pdata->alarm_irq,
+                              pic32_rtc_alarmirq, 0,
+                              dev_name(&pdev->dev), pdata);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "IRQ %d error %d\n", pdata->alarm_irq, ret);
+               goto err_nortc;
+       }
+
+       clk_disable(pdata->clk);
+
+       return 0;
+
+err_nortc:
+       pic32_rtc_enable(pdata, 0);
+       clk_disable_unprepare(pdata->clk);
+
+       return ret;
+}
+
+static const struct of_device_id pic32_rtc_dt_ids[] = {
+       { .compatible = "microchip,pic32mzda-rtc" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pic32_rtc_dt_ids);
+
+static struct platform_driver pic32_rtc_driver = {
+       .probe          = pic32_rtc_probe,
+       .remove         = pic32_rtc_remove,
+       .driver         = {
+               .name   = "pic32-rtc",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(pic32_rtc_dt_ids),
+       },
+};
+module_platform_driver(pic32_rtc_driver);
+
+MODULE_DESCRIPTION("Microchip PIC32 RTC Driver");
+MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>");
+MODULE_LICENSE("GPL");
index e9ac5a43be1a87c2f84f98e3e8d11f0cd922b7bd..d0cbf08040cd1e193bfd458b7e673d8ff01c53de 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Micro Crystal RV-3029C2 rtc class driver
+ * Micro Crystal RV-3029 rtc class driver
  *
  * Author: Gregory Hermant <gregory.hermant@calao-systems.com>
+ *         Michael Buesch <m@bues.ch>
  *
  * based on previously existing rtc class drivers
  *
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * NOTE: Currently this driver only supports the bare minimum for read
- * and write the RTC and alarms. The extra features provided by this chip
- * (trickle charger, eeprom, T° compensation) are unavailable.
  */
 
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
 
 /* Register map */
 /* control section */
-#define RV3029C2_ONOFF_CTRL            0x00
-#define RV3029C2_IRQ_CTRL              0x01
-#define RV3029C2_IRQ_CTRL_AIE          (1 << 0)
-#define RV3029C2_IRQ_FLAGS             0x02
-#define RV3029C2_IRQ_FLAGS_AF          (1 << 0)
-#define RV3029C2_STATUS                        0x03
-#define RV3029C2_STATUS_VLOW1          (1 << 2)
-#define RV3029C2_STATUS_VLOW2          (1 << 3)
-#define RV3029C2_STATUS_SR             (1 << 4)
-#define RV3029C2_STATUS_PON            (1 << 5)
-#define RV3029C2_STATUS_EEBUSY         (1 << 7)
-#define RV3029C2_RST_CTRL              0x04
-#define RV3029C2_CONTROL_SECTION_LEN   0x05
+#define RV3029_ONOFF_CTRL              0x00
+#define RV3029_ONOFF_CTRL_WE           BIT(0)
+#define RV3029_ONOFF_CTRL_TE           BIT(1)
+#define RV3029_ONOFF_CTRL_TAR          BIT(2)
+#define RV3029_ONOFF_CTRL_EERE         BIT(3)
+#define RV3029_ONOFF_CTRL_SRON         BIT(4)
+#define RV3029_ONOFF_CTRL_TD0          BIT(5)
+#define RV3029_ONOFF_CTRL_TD1          BIT(6)
+#define RV3029_ONOFF_CTRL_CLKINT       BIT(7)
+#define RV3029_IRQ_CTRL                        0x01
+#define RV3029_IRQ_CTRL_AIE            BIT(0)
+#define RV3029_IRQ_CTRL_TIE            BIT(1)
+#define RV3029_IRQ_CTRL_V1IE           BIT(2)
+#define RV3029_IRQ_CTRL_V2IE           BIT(3)
+#define RV3029_IRQ_CTRL_SRIE           BIT(4)
+#define RV3029_IRQ_FLAGS               0x02
+#define RV3029_IRQ_FLAGS_AF            BIT(0)
+#define RV3029_IRQ_FLAGS_TF            BIT(1)
+#define RV3029_IRQ_FLAGS_V1IF          BIT(2)
+#define RV3029_IRQ_FLAGS_V2IF          BIT(3)
+#define RV3029_IRQ_FLAGS_SRF           BIT(4)
+#define RV3029_STATUS                  0x03
+#define RV3029_STATUS_VLOW1            BIT(2)
+#define RV3029_STATUS_VLOW2            BIT(3)
+#define RV3029_STATUS_SR               BIT(4)
+#define RV3029_STATUS_PON              BIT(5)
+#define RV3029_STATUS_EEBUSY           BIT(7)
+#define RV3029_RST_CTRL                        0x04
+#define RV3029_RST_CTRL_SYSR           BIT(4)
+#define RV3029_CONTROL_SECTION_LEN     0x05
 
 /* watch section */
-#define RV3029C2_W_SEC                 0x08
-#define RV3029C2_W_MINUTES             0x09
-#define RV3029C2_W_HOURS               0x0A
-#define RV3029C2_REG_HR_12_24          (1<<6)  /* 24h/12h mode */
-#define RV3029C2_REG_HR_PM             (1<<5)  /* PM/AM bit in 12h mode */
-#define RV3029C2_W_DATE                        0x0B
-#define RV3029C2_W_DAYS                        0x0C
-#define RV3029C2_W_MONTHS              0x0D
-#define RV3029C2_W_YEARS               0x0E
-#define RV3029C2_WATCH_SECTION_LEN     0x07
+#define RV3029_W_SEC                   0x08
+#define RV3029_W_MINUTES               0x09
+#define RV3029_W_HOURS                 0x0A
+#define RV3029_REG_HR_12_24            BIT(6) /* 24h/12h mode */
+#define RV3029_REG_HR_PM               BIT(5) /* PM/AM bit in 12h mode */
+#define RV3029_W_DATE                  0x0B
+#define RV3029_W_DAYS                  0x0C
+#define RV3029_W_MONTHS                        0x0D
+#define RV3029_W_YEARS                 0x0E
+#define RV3029_WATCH_SECTION_LEN       0x07
 
 /* alarm section */
-#define RV3029C2_A_SC                  0x10
-#define RV3029C2_A_MN                  0x11
-#define RV3029C2_A_HR                  0x12
-#define RV3029C2_A_DT                  0x13
-#define RV3029C2_A_DW                  0x14
-#define RV3029C2_A_MO                  0x15
-#define RV3029C2_A_YR                  0x16
-#define RV3029C2_ALARM_SECTION_LEN     0x07
+#define RV3029_A_SC                    0x10
+#define RV3029_A_MN                    0x11
+#define RV3029_A_HR                    0x12
+#define RV3029_A_DT                    0x13
+#define RV3029_A_DW                    0x14
+#define RV3029_A_MO                    0x15
+#define RV3029_A_YR                    0x16
+#define RV3029_ALARM_SECTION_LEN       0x07
 
 /* timer section */
-#define RV3029C2_TIMER_LOW             0x18
-#define RV3029C2_TIMER_HIGH            0x19
+#define RV3029_TIMER_LOW               0x18
+#define RV3029_TIMER_HIGH              0x19
 
 /* temperature section */
-#define RV3029C2_TEMP_PAGE             0x20
+#define RV3029_TEMP_PAGE               0x20
 
 /* eeprom data section */
-#define RV3029C2_E2P_EEDATA1           0x28
-#define RV3029C2_E2P_EEDATA2           0x29
+#define RV3029_E2P_EEDATA1             0x28
+#define RV3029_E2P_EEDATA2             0x29
+#define RV3029_E2PDATA_SECTION_LEN     0x02
 
 /* eeprom control section */
-#define RV3029C2_CONTROL_E2P_EECTRL    0x30
-#define RV3029C2_TRICKLE_1K            (1<<0)  /*  1K resistance */
-#define RV3029C2_TRICKLE_5K            (1<<1)  /*  5K resistance */
-#define RV3029C2_TRICKLE_20K           (1<<2)  /* 20K resistance */
-#define RV3029C2_TRICKLE_80K           (1<<3)  /* 80K resistance */
-#define RV3029C2_CONTROL_E2P_XTALOFFSET        0x31
-#define RV3029C2_CONTROL_E2P_QCOEF     0x32
-#define RV3029C2_CONTROL_E2P_TURNOVER  0x33
+#define RV3029_CONTROL_E2P_EECTRL      0x30
+#define RV3029_EECTRL_THP              BIT(0) /* temp scan interval */
+#define RV3029_EECTRL_THE              BIT(1) /* thermometer enable */
+#define RV3029_EECTRL_FD0              BIT(2) /* CLKOUT */
+#define RV3029_EECTRL_FD1              BIT(3) /* CLKOUT */
+#define RV3029_TRICKLE_1K              BIT(4) /* 1.5K resistance */
+#define RV3029_TRICKLE_5K              BIT(5) /* 5K   resistance */
+#define RV3029_TRICKLE_20K             BIT(6) /* 20K  resistance */
+#define RV3029_TRICKLE_80K             BIT(7) /* 80K  resistance */
+#define RV3029_TRICKLE_MASK            (RV3029_TRICKLE_1K |\
+                                        RV3029_TRICKLE_5K |\
+                                        RV3029_TRICKLE_20K |\
+                                        RV3029_TRICKLE_80K)
+#define RV3029_TRICKLE_SHIFT           4
+#define RV3029_CONTROL_E2P_XOFFS       0x31 /* XTAL offset */
+#define RV3029_CONTROL_E2P_XOFFS_SIGN  BIT(7) /* Sign: 1->pos, 0->neg */
+#define RV3029_CONTROL_E2P_QCOEF       0x32 /* XTAL temp drift coef */
+#define RV3029_CONTROL_E2P_TURNOVER    0x33 /* XTAL turnover temp (in *C) */
+#define RV3029_CONTROL_E2P_TOV_MASK    0x3F /* XTAL turnover temp mask */
 
 /* user ram section */
-#define RV3029C2_USR1_RAM_PAGE         0x38
-#define RV3029C2_USR1_SECTION_LEN      0x04
-#define RV3029C2_USR2_RAM_PAGE         0x3C
-#define RV3029C2_USR2_SECTION_LEN      0x04
+#define RV3029_USR1_RAM_PAGE           0x38
+#define RV3029_USR1_SECTION_LEN                0x04
+#define RV3029_USR2_RAM_PAGE           0x3C
+#define RV3029_USR2_SECTION_LEN                0x04
 
 static int
-rv3029c2_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
-       unsigned len)
+rv3029_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
+                    unsigned len)
 {
        int ret;
 
-       if ((reg > RV3029C2_USR1_RAM_PAGE + 7) ||
-               (reg + len > RV3029C2_USR1_RAM_PAGE + 8))
+       if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
+               (reg + len > RV3029_USR1_RAM_PAGE + 8))
                return -EINVAL;
 
        ret = i2c_smbus_read_i2c_block_data(client, reg, len, buf);
@@ -103,20 +135,38 @@ rv3029c2_i2c_read_regs(struct i2c_client *client, u8 reg, u8 *buf,
 }
 
 static int
-rv3029c2_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
-                       unsigned len)
+rv3029_i2c_write_regs(struct i2c_client *client, u8 reg, u8 const buf[],
+                     unsigned len)
 {
-       if ((reg > RV3029C2_USR1_RAM_PAGE + 7) ||
-               (reg + len > RV3029C2_USR1_RAM_PAGE + 8))
+       if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
+               (reg + len > RV3029_USR1_RAM_PAGE + 8))
                return -EINVAL;
 
        return i2c_smbus_write_i2c_block_data(client, reg, len, buf);
 }
 
 static int
-rv3029c2_i2c_get_sr(struct i2c_client *client, u8 *buf)
+rv3029_i2c_update_bits(struct i2c_client *client, u8 reg, u8 mask, u8 set)
+{
+       u8 buf;
+       int ret;
+
+       ret = rv3029_i2c_read_regs(client, reg, &buf, 1);
+       if (ret < 0)
+               return ret;
+       buf &= ~mask;
+       buf |= set & mask;
+       ret = rv3029_i2c_write_regs(client, reg, &buf, 1);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int
+rv3029_i2c_get_sr(struct i2c_client *client, u8 *buf)
 {
-       int ret = rv3029c2_i2c_read_regs(client, RV3029C2_STATUS, buf, 1);
+       int ret = rv3029_i2c_read_regs(client, RV3029_STATUS, buf, 1);
 
        if (ret < 0)
                return -EIO;
@@ -125,83 +175,224 @@ rv3029c2_i2c_get_sr(struct i2c_client *client, u8 *buf)
 }
 
 static int
-rv3029c2_i2c_set_sr(struct i2c_client *client, u8 val)
+rv3029_i2c_set_sr(struct i2c_client *client, u8 val)
 {
        u8 buf[1];
        int sr;
 
        buf[0] = val;
-       sr = rv3029c2_i2c_write_regs(client, RV3029C2_STATUS, buf, 1);
+       sr = rv3029_i2c_write_regs(client, RV3029_STATUS, buf, 1);
        dev_dbg(&client->dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
        if (sr < 0)
                return -EIO;
        return 0;
 }
 
+static int rv3029_eeprom_busywait(struct i2c_client *client)
+{
+       int i, ret;
+       u8 sr;
+
+       for (i = 100; i > 0; i--) {
+               ret = rv3029_i2c_get_sr(client, &sr);
+               if (ret < 0)
+                       break;
+               if (!(sr & RV3029_STATUS_EEBUSY))
+                       break;
+               usleep_range(1000, 10000);
+       }
+       if (i <= 0) {
+               dev_err(&client->dev, "EEPROM busy wait timeout.\n");
+               return -ETIMEDOUT;
+       }
+
+       return ret;
+}
+
+static int rv3029_eeprom_exit(struct i2c_client *client)
+{
+       /* Re-enable eeprom refresh */
+       return rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL,
+                                     RV3029_ONOFF_CTRL_EERE,
+                                     RV3029_ONOFF_CTRL_EERE);
+}
+
+static int rv3029_eeprom_enter(struct i2c_client *client)
+{
+       int ret;
+       u8 sr;
+
+       /* Check whether we are in the allowed voltage range. */
+       ret = rv3029_i2c_get_sr(client, &sr);
+       if (ret < 0)
+               return ret;
+       if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
+               /* We clear the bits and retry once just in case
+                * we had a brown out in early startup.
+                */
+               sr &= ~RV3029_STATUS_VLOW1;
+               sr &= ~RV3029_STATUS_VLOW2;
+               ret = rv3029_i2c_set_sr(client, sr);
+               if (ret < 0)
+                       return ret;
+               usleep_range(1000, 10000);
+               ret = rv3029_i2c_get_sr(client, &sr);
+               if (ret < 0)
+                       return ret;
+               if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
+                       dev_err(&client->dev,
+                               "Supply voltage is too low to safely access the EEPROM.\n");
+                       return -ENODEV;
+               }
+       }
+
+       /* Disable eeprom refresh. */
+       ret = rv3029_i2c_update_bits(client, RV3029_ONOFF_CTRL,
+                                    RV3029_ONOFF_CTRL_EERE, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Wait for any previous eeprom accesses to finish. */
+       ret = rv3029_eeprom_busywait(client);
+       if (ret < 0)
+               rv3029_eeprom_exit(client);
+
+       return ret;
+}
+
+static int rv3029_eeprom_read(struct i2c_client *client, u8 reg,
+                             u8 buf[], size_t len)
+{
+       int ret, err;
+
+       err = rv3029_eeprom_enter(client);
+       if (err < 0)
+               return err;
+
+       ret = rv3029_i2c_read_regs(client, reg, buf, len);
+
+       err = rv3029_eeprom_exit(client);
+       if (err < 0)
+               return err;
+
+       return ret;
+}
+
+static int rv3029_eeprom_write(struct i2c_client *client, u8 reg,
+                              u8 const buf[], size_t len)
+{
+       int ret, err;
+       size_t i;
+       u8 tmp;
+
+       err = rv3029_eeprom_enter(client);
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < len; i++, reg++) {
+               ret = rv3029_i2c_read_regs(client, reg, &tmp, 1);
+               if (ret < 0)
+                       break;
+               if (tmp != buf[i]) {
+                       ret = rv3029_i2c_write_regs(client, reg, &buf[i], 1);
+                       if (ret < 0)
+                               break;
+               }
+               ret = rv3029_eeprom_busywait(client);
+               if (ret < 0)
+                       break;
+       }
+
+       err = rv3029_eeprom_exit(client);
+       if (err < 0)
+               return err;
+
+       return ret;
+}
+
+static int rv3029_eeprom_update_bits(struct i2c_client *client,
+                                    u8 reg, u8 mask, u8 set)
+{
+       u8 buf;
+       int ret;
+
+       ret = rv3029_eeprom_read(client, reg, &buf, 1);
+       if (ret < 0)
+               return ret;
+       buf &= ~mask;
+       buf |= set & mask;
+       ret = rv3029_eeprom_write(client, reg, &buf, 1);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
 static int
-rv3029c2_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
+rv3029_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
 {
        u8 buf[1];
        int ret;
-       u8 regs[RV3029C2_WATCH_SECTION_LEN] = { 0, };
+       u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, };
 
-       ret = rv3029c2_i2c_get_sr(client, buf);
+       ret = rv3029_i2c_get_sr(client, buf);
        if (ret < 0) {
                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
                return -EIO;
        }
 
-       ret = rv3029c2_i2c_read_regs(client, RV3029C2_W_SEC , regs,
-                                       RV3029C2_WATCH_SECTION_LEN);
+       ret = rv3029_i2c_read_regs(client, RV3029_W_SEC, regs,
+                                  RV3029_WATCH_SECTION_LEN);
        if (ret < 0) {
                dev_err(&client->dev, "%s: reading RTC section failed\n",
                        __func__);
                return ret;
        }
 
-       tm->tm_sec = bcd2bin(regs[RV3029C2_W_SEC-RV3029C2_W_SEC]);
-       tm->tm_min = bcd2bin(regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC]);
+       tm->tm_sec = bcd2bin(regs[RV3029_W_SEC-RV3029_W_SEC]);
+       tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES-RV3029_W_SEC]);
 
        /* HR field has a more complex interpretation */
        {
-               const u8 _hr = regs[RV3029C2_W_HOURS-RV3029C2_W_SEC];
-               if (_hr & RV3029C2_REG_HR_12_24) {
+               const u8 _hr = regs[RV3029_W_HOURS-RV3029_W_SEC];
+
+               if (_hr & RV3029_REG_HR_12_24) {
                        /* 12h format */
                        tm->tm_hour = bcd2bin(_hr & 0x1f);
-                       if (_hr & RV3029C2_REG_HR_PM)   /* PM flag set */
+                       if (_hr & RV3029_REG_HR_PM)     /* PM flag set */
                                tm->tm_hour += 12;
                } else /* 24h format */
                        tm->tm_hour = bcd2bin(_hr & 0x3f);
        }
 
-       tm->tm_mday = bcd2bin(regs[RV3029C2_W_DATE-RV3029C2_W_SEC]);
-       tm->tm_mon = bcd2bin(regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC]) - 1;
-       tm->tm_year = bcd2bin(regs[RV3029C2_W_YEARS-RV3029C2_W_SEC]) + 100;
-       tm->tm_wday = bcd2bin(regs[RV3029C2_W_DAYS-RV3029C2_W_SEC]) - 1;
+       tm->tm_mday = bcd2bin(regs[RV3029_W_DATE-RV3029_W_SEC]);
+       tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS-RV3029_W_SEC]) - 1;
+       tm->tm_year = bcd2bin(regs[RV3029_W_YEARS-RV3029_W_SEC]) + 100;
+       tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS-RV3029_W_SEC]) - 1;
 
        return 0;
 }
 
-static int rv3029c2_rtc_read_time(struct device *dev, struct rtc_time *tm)
+static int rv3029_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-       return rv3029c2_i2c_read_time(to_i2c_client(dev), tm);
+       return rv3029_i2c_read_time(to_i2c_client(dev), tm);
 }
 
 static int
-rv3029c2_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
+rv3029_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
 {
        struct rtc_time *const tm = &alarm->time;
        int ret;
        u8 regs[8];
 
-       ret = rv3029c2_i2c_get_sr(client, regs);
+       ret = rv3029_i2c_get_sr(client, regs);
        if (ret < 0) {
                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
                return -EIO;
        }
 
-       ret = rv3029c2_i2c_read_regs(client, RV3029C2_A_SC, regs,
-                                       RV3029C2_ALARM_SECTION_LEN);
+       ret = rv3029_i2c_read_regs(client, RV3029_A_SC, regs,
+                                  RV3029_ALARM_SECTION_LEN);
 
        if (ret < 0) {
                dev_err(&client->dev, "%s: reading alarm section failed\n",
@@ -209,51 +400,42 @@ rv3029c2_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
                return ret;
        }
 
-       tm->tm_sec = bcd2bin(regs[RV3029C2_A_SC-RV3029C2_A_SC] & 0x7f);
-       tm->tm_min = bcd2bin(regs[RV3029C2_A_MN-RV3029C2_A_SC] & 0x7f);
-       tm->tm_hour = bcd2bin(regs[RV3029C2_A_HR-RV3029C2_A_SC] & 0x3f);
-       tm->tm_mday = bcd2bin(regs[RV3029C2_A_DT-RV3029C2_A_SC] & 0x3f);
-       tm->tm_mon = bcd2bin(regs[RV3029C2_A_MO-RV3029C2_A_SC] & 0x1f) - 1;
-       tm->tm_year = bcd2bin(regs[RV3029C2_A_YR-RV3029C2_A_SC] & 0x7f) + 100;
-       tm->tm_wday = bcd2bin(regs[RV3029C2_A_DW-RV3029C2_A_SC] & 0x07) - 1;
+       tm->tm_sec = bcd2bin(regs[RV3029_A_SC-RV3029_A_SC] & 0x7f);
+       tm->tm_min = bcd2bin(regs[RV3029_A_MN-RV3029_A_SC] & 0x7f);
+       tm->tm_hour = bcd2bin(regs[RV3029_A_HR-RV3029_A_SC] & 0x3f);
+       tm->tm_mday = bcd2bin(regs[RV3029_A_DT-RV3029_A_SC] & 0x3f);
+       tm->tm_mon = bcd2bin(regs[RV3029_A_MO-RV3029_A_SC] & 0x1f) - 1;
+       tm->tm_year = bcd2bin(regs[RV3029_A_YR-RV3029_A_SC] & 0x7f) + 100;
+       tm->tm_wday = bcd2bin(regs[RV3029_A_DW-RV3029_A_SC] & 0x07) - 1;
 
        return 0;
 }
 
 static int
-rv3029c2_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+rv3029_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-       return rv3029c2_i2c_read_alarm(to_i2c_client(dev), alarm);
+       return rv3029_i2c_read_alarm(to_i2c_client(dev), alarm);
 }
 
-static int rv3029c2_rtc_i2c_alarm_set_irq(struct i2c_client *client,
+static int rv3029_rtc_i2c_alarm_set_irq(struct i2c_client *client,
                                        int enable)
 {
        int ret;
-       u8 buf[1];
-
-       /* enable AIE irq */
-       ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_CTRL, buf, 1);
-       if (ret < 0) {
-               dev_err(&client->dev, "can't read INT reg\n");
-               return ret;
-       }
-       if (enable)
-               buf[0] |= RV3029C2_IRQ_CTRL_AIE;
-       else
-               buf[0] &= ~RV3029C2_IRQ_CTRL_AIE;
 
-       ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_CTRL, buf, 1);
+       /* enable/disable AIE irq */
+       ret = rv3029_i2c_update_bits(client, RV3029_IRQ_CTRL,
+                                    RV3029_IRQ_CTRL_AIE,
+                                    (enable ? RV3029_IRQ_CTRL_AIE : 0));
        if (ret < 0) {
-               dev_err(&client->dev, "can't set INT reg\n");
+               dev_err(&client->dev, "can't update INT reg\n");
                return ret;
        }
 
        return 0;
 }
 
-static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client,
-                                       struct rtc_wkalrm *alarm)
+static int rv3029_rtc_i2c_set_alarm(struct i2c_client *client,
+                                   struct rtc_wkalrm *alarm)
 {
        struct rtc_time *const tm = &alarm->time;
        int ret;
@@ -267,50 +449,41 @@ static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client,
        if (tm->tm_year < 100)
                return -EINVAL;
 
-       ret = rv3029c2_i2c_get_sr(client, regs);
+       ret = rv3029_i2c_get_sr(client, regs);
        if (ret < 0) {
                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
                return -EIO;
        }
-       regs[RV3029C2_A_SC-RV3029C2_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
-       regs[RV3029C2_A_MN-RV3029C2_A_SC] = bin2bcd(tm->tm_min & 0x7f);
-       regs[RV3029C2_A_HR-RV3029C2_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
-       regs[RV3029C2_A_DT-RV3029C2_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
-       regs[RV3029C2_A_MO-RV3029C2_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
-       regs[RV3029C2_A_DW-RV3029C2_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
-       regs[RV3029C2_A_YR-RV3029C2_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);
-
-       ret = rv3029c2_i2c_write_regs(client, RV3029C2_A_SC, regs,
-                                       RV3029C2_ALARM_SECTION_LEN);
+       regs[RV3029_A_SC-RV3029_A_SC] = bin2bcd(tm->tm_sec & 0x7f);
+       regs[RV3029_A_MN-RV3029_A_SC] = bin2bcd(tm->tm_min & 0x7f);
+       regs[RV3029_A_HR-RV3029_A_SC] = bin2bcd(tm->tm_hour & 0x3f);
+       regs[RV3029_A_DT-RV3029_A_SC] = bin2bcd(tm->tm_mday & 0x3f);
+       regs[RV3029_A_MO-RV3029_A_SC] = bin2bcd((tm->tm_mon & 0x1f) - 1);
+       regs[RV3029_A_DW-RV3029_A_SC] = bin2bcd((tm->tm_wday & 7) - 1);
+       regs[RV3029_A_YR-RV3029_A_SC] = bin2bcd((tm->tm_year & 0x7f) - 100);
+
+       ret = rv3029_i2c_write_regs(client, RV3029_A_SC, regs,
+                                   RV3029_ALARM_SECTION_LEN);
        if (ret < 0)
                return ret;
 
        if (alarm->enabled) {
-               u8 buf[1];
-
                /* clear AF flag */
-               ret = rv3029c2_i2c_read_regs(client, RV3029C2_IRQ_FLAGS,
-                                               buf, 1);
-               if (ret < 0) {
-                       dev_err(&client->dev, "can't read alarm flag\n");
-                       return ret;
-               }
-               buf[0] &= ~RV3029C2_IRQ_FLAGS_AF;
-               ret = rv3029c2_i2c_write_regs(client, RV3029C2_IRQ_FLAGS,
-                                               buf, 1);
+               ret = rv3029_i2c_update_bits(client, RV3029_IRQ_FLAGS,
+                                            RV3029_IRQ_FLAGS_AF, 0);
                if (ret < 0) {
-                       dev_err(&client->dev, "can't set alarm flag\n");
+                       dev_err(&client->dev, "can't clear alarm flag\n");
                        return ret;
                }
                /* enable AIE irq */
-               ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1);
+               ret = rv3029_rtc_i2c_alarm_set_irq(client, 1);
                if (ret)
                        return ret;
 
                dev_dbg(&client->dev, "alarm IRQ armed\n");
        } else {
                /* disable AIE irq */
-               ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 0);
+               ret = rv3029_rtc_i2c_alarm_set_irq(client, 0);
                if (ret)
                        return ret;
 
@@ -320,13 +493,13 @@ static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client,
        return 0;
 }
 
-static int rv3029c2_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int rv3029_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-       return rv3029c2_rtc_i2c_set_alarm(to_i2c_client(dev), alarm);
+       return rv3029_rtc_i2c_set_alarm(to_i2c_client(dev), alarm);
 }
 
 static int
-rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
+rv3029_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
 {
        u8 regs[8];
        int ret;
@@ -339,26 +512,26 @@ rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
        if (tm->tm_year < 100)
                return -EINVAL;
 
-       regs[RV3029C2_W_SEC-RV3029C2_W_SEC] = bin2bcd(tm->tm_sec);
-       regs[RV3029C2_W_MINUTES-RV3029C2_W_SEC] = bin2bcd(tm->tm_min);
-       regs[RV3029C2_W_HOURS-RV3029C2_W_SEC] = bin2bcd(tm->tm_hour);
-       regs[RV3029C2_W_DATE-RV3029C2_W_SEC] = bin2bcd(tm->tm_mday);
-       regs[RV3029C2_W_MONTHS-RV3029C2_W_SEC] = bin2bcd(tm->tm_mon+1);
-       regs[RV3029C2_W_DAYS-RV3029C2_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
-       regs[RV3029C2_W_YEARS-RV3029C2_W_SEC] = bin2bcd(tm->tm_year - 100);
+       regs[RV3029_W_SEC-RV3029_W_SEC] = bin2bcd(tm->tm_sec);
+       regs[RV3029_W_MINUTES-RV3029_W_SEC] = bin2bcd(tm->tm_min);
+       regs[RV3029_W_HOURS-RV3029_W_SEC] = bin2bcd(tm->tm_hour);
+       regs[RV3029_W_DATE-RV3029_W_SEC] = bin2bcd(tm->tm_mday);
+       regs[RV3029_W_MONTHS-RV3029_W_SEC] = bin2bcd(tm->tm_mon+1);
+       regs[RV3029_W_DAYS-RV3029_W_SEC] = bin2bcd((tm->tm_wday & 7)+1);
+       regs[RV3029_W_YEARS-RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);
 
-       ret = rv3029c2_i2c_write_regs(client, RV3029C2_W_SEC, regs,
-                                       RV3029C2_WATCH_SECTION_LEN);
+       ret = rv3029_i2c_write_regs(client, RV3029_W_SEC, regs,
+                                   RV3029_WATCH_SECTION_LEN);
        if (ret < 0)
                return ret;
 
-       ret = rv3029c2_i2c_get_sr(client, regs);
+       ret = rv3029_i2c_get_sr(client, regs);
        if (ret < 0) {
                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
                return ret;
        }
        /* clear PON bit */
-       ret = rv3029c2_i2c_set_sr(client, (regs[0] & ~RV3029C2_STATUS_PON));
+       ret = rv3029_i2c_set_sr(client, (regs[0] & ~RV3029_STATUS_PON));
        if (ret < 0) {
                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
                return ret;
@@ -367,26 +540,238 @@ rv3029c2_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
        return 0;
 }
 
-static int rv3029c2_rtc_set_time(struct device *dev, struct rtc_time *tm)
+static int rv3029_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-       return rv3029c2_i2c_set_time(to_i2c_client(dev), tm);
+       return rv3029_i2c_set_time(to_i2c_client(dev), tm);
 }
 
-static const struct rtc_class_ops rv3029c2_rtc_ops = {
-       .read_time      = rv3029c2_rtc_read_time,
-       .set_time       = rv3029c2_rtc_set_time,
-       .read_alarm     = rv3029c2_rtc_read_alarm,
-       .set_alarm      = rv3029c2_rtc_set_alarm,
+static const struct rv3029_trickle_tab_elem {
+       u32 r;          /* resistance in ohms */
+       u8 conf;        /* trickle config bits */
+} rv3029_trickle_tab[] = {
+       {
+               .r      = 1076,
+               .conf   = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+                         RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
+       }, {
+               .r      = 1091,
+               .conf   = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+                         RV3029_TRICKLE_20K,
+       }, {
+               .r      = 1137,
+               .conf   = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
+                         RV3029_TRICKLE_80K,
+       }, {
+               .r      = 1154,
+               .conf   = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K,
+       }, {
+               .r      = 1371,
+               .conf   = RV3029_TRICKLE_1K | RV3029_TRICKLE_20K |
+                         RV3029_TRICKLE_80K,
+       }, {
+               .r      = 1395,
+               .conf   = RV3029_TRICKLE_1K | RV3029_TRICKLE_20K,
+       }, {
+               .r      = 1472,
+               .conf   = RV3029_TRICKLE_1K | RV3029_TRICKLE_80K,
+       }, {
+               .r      = 1500,
+               .conf   = RV3029_TRICKLE_1K,
+       }, {
+               .r      = 3810,
+               .conf   = RV3029_TRICKLE_5K | RV3029_TRICKLE_20K |
+                         RV3029_TRICKLE_80K,
+       }, {
+               .r      = 4000,
+               .conf   = RV3029_TRICKLE_5K | RV3029_TRICKLE_20K,
+       }, {
+               .r      = 4706,
+               .conf   = RV3029_TRICKLE_5K | RV3029_TRICKLE_80K,
+       }, {
+               .r      = 5000,
+               .conf   = RV3029_TRICKLE_5K,
+       }, {
+               .r      = 16000,
+               .conf   = RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
+       }, {
+               .r      = 20000,
+               .conf   = RV3029_TRICKLE_20K,
+       }, {
+               .r      = 80000,
+               .conf   = RV3029_TRICKLE_80K,
+       },
 };
 
-static struct i2c_device_id rv3029c2_id[] = {
+static void rv3029_trickle_config(struct i2c_client *client)
+{
+       struct device_node *of_node = client->dev.of_node;
+       const struct rv3029_trickle_tab_elem *elem;
+       int i, err;
+       u32 ohms;
+       u8 trickle_set_bits;
+
+       if (!of_node)
+               return;
+
+       /* Configure the trickle charger. */
+       err = of_property_read_u32(of_node, "trickle-resistor-ohms", &ohms);
+       if (err) {
+               /* Disable trickle charger. */
+               trickle_set_bits = 0;
+       } else {
+               /* Enable trickle charger. */
+               for (i = 0; i < ARRAY_SIZE(rv3029_trickle_tab); i++) {
+                       elem = &rv3029_trickle_tab[i];
+                       if (elem->r >= ohms)
+                               break;
+               }
+               trickle_set_bits = elem->conf;
+               dev_info(&client->dev,
+                        "Trickle charger enabled at %d ohms resistance.\n",
+                        elem->r);
+       }
+       err = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL,
+                                       RV3029_TRICKLE_MASK,
+                                       trickle_set_bits);
+       if (err < 0) {
+               dev_err(&client->dev,
+                       "Failed to update trickle charger config\n");
+       }
+}
+
+#ifdef CONFIG_RTC_DRV_RV3029_HWMON
+
+static int rv3029_read_temp(struct i2c_client *client, int *temp_mC)
+{
+       int ret;
+       u8 temp;
+
+       ret = rv3029_i2c_read_regs(client, RV3029_TEMP_PAGE, &temp, 1);
+       if (ret < 0)
+               return ret;
+
+       *temp_mC = ((int)temp - 60) * 1000;
+
+       return 0;
+}
+
+static ssize_t rv3029_hwmon_show_temp(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct i2c_client *client = dev_get_drvdata(dev);
+       int ret, temp_mC;
+
+       ret = rv3029_read_temp(client, &temp_mC);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d\n", temp_mC);
+}
+
+static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
+                                               struct device_attribute *attr,
+                                               const char *buf,
+                                               size_t count)
+{
+       struct i2c_client *client = dev_get_drvdata(dev);
+       unsigned long interval_ms;
+       int ret;
+       u8 th_set_bits = 0;
+
+       ret = kstrtoul(buf, 10, &interval_ms);
+       if (ret < 0)
+               return ret;
+
+       if (interval_ms != 0) {
+               th_set_bits |= RV3029_EECTRL_THE;
+               if (interval_ms >= 16000)
+                       th_set_bits |= RV3029_EECTRL_THP;
+       }
+       ret = rv3029_eeprom_update_bits(client, RV3029_CONTROL_E2P_EECTRL,
+                                       RV3029_EECTRL_THE | RV3029_EECTRL_THP,
+                                       th_set_bits);
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static ssize_t rv3029_hwmon_show_update_interval(struct device *dev,
+                                                struct device_attribute *attr,
+                                                char *buf)
+{
+       struct i2c_client *client = dev_get_drvdata(dev);
+       int ret, interval_ms;
+       u8 eectrl;
+
+       ret = rv3029_eeprom_read(client, RV3029_CONTROL_E2P_EECTRL,
+                                &eectrl, 1);
+       if (ret < 0)
+               return ret;
+
+       if (eectrl & RV3029_EECTRL_THE) {
+               if (eectrl & RV3029_EECTRL_THP)
+                       interval_ms = 16000;
+               else
+                       interval_ms = 1000;
+       } else {
+               interval_ms = 0;
+       }
+
+       return sprintf(buf, "%d\n", interval_ms);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, rv3029_hwmon_show_temp,
+                         NULL, 0);
+static SENSOR_DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO,
+                         rv3029_hwmon_show_update_interval,
+                         rv3029_hwmon_set_update_interval, 0);
+
+static struct attribute *rv3029_hwmon_attrs[] = {
+       &sensor_dev_attr_temp1_input.dev_attr.attr,
+       &sensor_dev_attr_update_interval.dev_attr.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(rv3029_hwmon);
+
+static void rv3029_hwmon_register(struct i2c_client *client)
+{
+       struct device *hwmon_dev;
+
+       hwmon_dev = devm_hwmon_device_register_with_groups(
+               &client->dev, client->name, client, rv3029_hwmon_groups);
+       if (IS_ERR(hwmon_dev)) {
+               dev_warn(&client->dev,
+                       "unable to register hwmon device %ld\n",
+                       PTR_ERR(hwmon_dev));
+       }
+}
+
+#else /* CONFIG_RTC_DRV_RV3029_HWMON */
+
+static void rv3029_hwmon_register(struct i2c_client *client)
+{
+}
+
+#endif /* CONFIG_RTC_DRV_RV3029_HWMON */
+
+static const struct rtc_class_ops rv3029_rtc_ops = {
+       .read_time      = rv3029_rtc_read_time,
+       .set_time       = rv3029_rtc_set_time,
+       .read_alarm     = rv3029_rtc_read_alarm,
+       .set_alarm      = rv3029_rtc_set_alarm,
+};
+
+static struct i2c_device_id rv3029_id[] = {
+       { "rv3029", 0 },
        { "rv3029c2", 0 },
        { }
 };
-MODULE_DEVICE_TABLE(i2c, rv3029c2_id);
+MODULE_DEVICE_TABLE(i2c, rv3029_id);
 
-static int rv3029c2_probe(struct i2c_client *client,
-                         const struct i2c_device_id *id)
+static int rv3029_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
 {
        struct rtc_device *rtc;
        int rc = 0;
@@ -395,14 +780,17 @@ static int rv3029c2_probe(struct i2c_client *client,
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_EMUL))
                return -ENODEV;
 
-       rc = rv3029c2_i2c_get_sr(client, buf);
+       rc = rv3029_i2c_get_sr(client, buf);
        if (rc < 0) {
                dev_err(&client->dev, "reading status failed\n");
                return rc;
        }
 
+       rv3029_trickle_config(client);
+       rv3029_hwmon_register(client);
+
        rtc = devm_rtc_device_register(&client->dev, client->name,
-                                       &rv3029c2_rtc_ops, THIS_MODULE);
+                                      &rv3029_rtc_ops, THIS_MODULE);
 
        if (IS_ERR(rtc))
                return PTR_ERR(rtc);
@@ -412,16 +800,17 @@ static int rv3029c2_probe(struct i2c_client *client,
        return 0;
 }
 
-static struct i2c_driver rv3029c2_driver = {
+static struct i2c_driver rv3029_driver = {
        .driver = {
                .name = "rtc-rv3029c2",
        },
-       .probe = rv3029c2_probe,
-       .id_table = rv3029c2_id,
+       .probe          = rv3029_probe,
+       .id_table       = rv3029_id,
 };
 
-module_i2c_driver(rv3029c2_driver);
+module_i2c_driver(rv3029_driver);
 
 MODULE_AUTHOR("Gregory Hermant <gregory.hermant@calao-systems.com>");
-MODULE_DESCRIPTION("Micro Crystal RV3029C2 RTC driver");
+MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
+MODULE_DESCRIPTION("Micro Crystal RV3029 RTC driver");
 MODULE_LICENSE("GPL");
index 7155c0816aa6ff4624eb0ce9a7233a3e6c9f1b1d..8d9f35ceb8081805c7b932e537cd52fdef41b1da 100644 (file)
@@ -52,7 +52,7 @@
 struct rv8803_data {
        struct i2c_client *client;
        struct rtc_device *rtc;
-       spinlock_t flags_lock;
+       struct mutex flags_lock;
        u8 ctrl;
 };
 
@@ -63,11 +63,11 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
        unsigned long events = 0;
        int flags;
 
-       spin_lock(&rv8803->flags_lock);
+       mutex_lock(&rv8803->flags_lock);
 
        flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
        if (flags <= 0) {
-               spin_unlock(&rv8803->flags_lock);
+               mutex_unlock(&rv8803->flags_lock);
                return IRQ_NONE;
        }
 
@@ -102,7 +102,7 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
                                          rv8803->ctrl);
        }
 
-       spin_unlock(&rv8803->flags_lock);
+       mutex_unlock(&rv8803->flags_lock);
 
        return IRQ_HANDLED;
 }
@@ -155,7 +155,6 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
        struct rv8803_data *rv8803 = dev_get_drvdata(dev);
        u8 date[7];
        int flags, ret;
-       unsigned long irqflags;
 
        if ((tm->tm_year < 100) || (tm->tm_year > 199))
                return -EINVAL;
@@ -173,18 +172,18 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
        if (ret < 0)
                return ret;
 
-       spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+       mutex_lock(&rv8803->flags_lock);
 
        flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
        if (flags < 0) {
-               spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+               mutex_unlock(&rv8803->flags_lock);
                return flags;
        }
 
        ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG,
                                        flags & ~RV8803_FLAG_V2F);
 
-       spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+       mutex_unlock(&rv8803->flags_lock);
 
        return ret;
 }
@@ -226,7 +225,6 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        u8 alarmvals[3];
        u8 ctrl[2];
        int ret, err;
-       unsigned long irqflags;
 
        /* The alarm has no seconds, round up to nearest minute */
        if (alrm->time.tm_sec) {
@@ -236,11 +234,11 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
                rtc_time64_to_tm(alarm_time, &alrm->time);
        }
 
-       spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+       mutex_lock(&rv8803->flags_lock);
 
        ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl);
        if (ret != 2) {
-               spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+               mutex_unlock(&rv8803->flags_lock);
                return ret < 0 ? ret : -EIO;
        }
 
@@ -253,14 +251,14 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
                err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
                                                rv8803->ctrl);
                if (err) {
-                       spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+                       mutex_unlock(&rv8803->flags_lock);
                        return err;
                }
        }
 
        ctrl[1] &= ~RV8803_FLAG_AF;
        err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]);
-       spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+       mutex_unlock(&rv8803->flags_lock);
        if (err)
                return err;
 
@@ -289,7 +287,6 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
        struct i2c_client *client = to_i2c_client(dev);
        struct rv8803_data *rv8803 = dev_get_drvdata(dev);
        int ctrl, flags, err;
-       unsigned long irqflags;
 
        ctrl = rv8803->ctrl;
 
@@ -305,15 +302,15 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
                        ctrl &= ~RV8803_CTRL_AIE;
        }
 
-       spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+       mutex_lock(&rv8803->flags_lock);
        flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
        if (flags < 0) {
-               spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+               mutex_unlock(&rv8803->flags_lock);
                return flags;
        }
        flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF);
        err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
-       spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+       mutex_unlock(&rv8803->flags_lock);
        if (err)
                return err;
 
@@ -333,7 +330,6 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
        struct i2c_client *client = to_i2c_client(dev);
        struct rv8803_data *rv8803 = dev_get_drvdata(dev);
        int flags, ret = 0;
-       unsigned long irqflags;
 
        switch (cmd) {
        case RTC_VL_READ:
@@ -355,16 +351,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
                return 0;
 
        case RTC_VL_CLR:
-               spin_lock_irqsave(&rv8803->flags_lock, irqflags);
+               mutex_lock(&rv8803->flags_lock);
                flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
                if (flags < 0) {
-                       spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+                       mutex_unlock(&rv8803->flags_lock);
                        return flags;
                }
 
                flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F);
                ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
-               spin_unlock_irqrestore(&rv8803->flags_lock, irqflags);
+               mutex_unlock(&rv8803->flags_lock);
                if (ret < 0)
                        return ret;
 
@@ -441,6 +437,7 @@ static int rv8803_probe(struct i2c_client *client,
        if (!rv8803)
                return -ENOMEM;
 
+       mutex_init(&rv8803->flags_lock);
        rv8803->client = client;
        i2c_set_clientdata(client, rv8803);
 
diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c
new file mode 100644 (file)
index 0000000..bbad00b
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * Driver for the Epson RTC module RX-6110 SA
+ *
+ * Copyright(C) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ * Copyright(C) SEIKO EPSON CORPORATION 2013. All rights reserved.
+ *
+ * This driver software is distributed as is, without any warranty of any kind,
+ * either express or implied as further specified in the GNU Public License.
+ * This software may be used and distributed according to the terms of the GNU
+ * Public License, version 2 as published by the Free Software Foundation.
+ * See the file COPYING in the main directory of this archive for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+
+/* RX-6110 Register definitions */
+#define RX6110_REG_SEC         0x10
+#define RX6110_REG_MIN         0x11
+#define RX6110_REG_HOUR                0x12
+#define RX6110_REG_WDAY                0x13
+#define RX6110_REG_MDAY                0x14
+#define RX6110_REG_MONTH       0x15
+#define RX6110_REG_YEAR                0x16
+#define RX6110_REG_RES1                0x17
+#define RX6110_REG_ALMIN       0x18
+#define RX6110_REG_ALHOUR      0x19
+#define RX6110_REG_ALWDAY      0x1A
+#define RX6110_REG_TCOUNT0     0x1B
+#define RX6110_REG_TCOUNT1     0x1C
+#define RX6110_REG_EXT         0x1D
+#define RX6110_REG_FLAG                0x1E
+#define RX6110_REG_CTRL                0x1F
+#define RX6110_REG_USER0       0x20
+#define RX6110_REG_USER1       0x21
+#define RX6110_REG_USER2       0x22
+#define RX6110_REG_USER3       0x23
+#define RX6110_REG_USER4       0x24
+#define RX6110_REG_USER5       0x25
+#define RX6110_REG_USER6       0x26
+#define RX6110_REG_USER7       0x27
+#define RX6110_REG_USER8       0x28
+#define RX6110_REG_USER9       0x29
+#define RX6110_REG_USERA       0x2A
+#define RX6110_REG_USERB       0x2B
+#define RX6110_REG_USERC       0x2C
+#define RX6110_REG_USERD       0x2D
+#define RX6110_REG_USERE       0x2E
+#define RX6110_REG_USERF       0x2F
+#define RX6110_REG_RES2                0x30
+#define RX6110_REG_RES3                0x31
+#define RX6110_REG_IRQ         0x32
+
+#define RX6110_BIT_ALARM_EN            BIT(7)
+
+/* Extension Register (1Dh) bit positions */
+#define RX6110_BIT_EXT_TSEL0           BIT(0)
+#define RX6110_BIT_EXT_TSEL1           BIT(1)
+#define RX6110_BIT_EXT_TSEL2           BIT(2)
+#define RX6110_BIT_EXT_WADA            BIT(3)
+#define RX6110_BIT_EXT_TE              BIT(4)
+#define RX6110_BIT_EXT_USEL            BIT(5)
+#define RX6110_BIT_EXT_FSEL0           BIT(6)
+#define RX6110_BIT_EXT_FSEL1           BIT(7)
+
+/* Flag Register (1Eh) bit positions */
+#define RX6110_BIT_FLAG_VLF            BIT(1)
+#define RX6110_BIT_FLAG_AF             BIT(3)
+#define RX6110_BIT_FLAG_TF             BIT(4)
+#define RX6110_BIT_FLAG_UF             BIT(5)
+
+/* Control Register (1Fh) bit positions */
+#define RX6110_BIT_CTRL_TBKE           BIT(0)
+#define RX6110_BIT_CTRL_TBKON          BIT(1)
+#define RX6110_BIT_CTRL_TSTP           BIT(2)
+#define RX6110_BIT_CTRL_AIE            BIT(3)
+#define RX6110_BIT_CTRL_TIE            BIT(4)
+#define RX6110_BIT_CTRL_UIE            BIT(5)
+#define RX6110_BIT_CTRL_STOP           BIT(6)
+#define RX6110_BIT_CTRL_TEST           BIT(7)
+
+enum {
+       RTC_SEC = 0,
+       RTC_MIN,
+       RTC_HOUR,
+       RTC_WDAY,
+       RTC_MDAY,
+       RTC_MONTH,
+       RTC_YEAR,
+       RTC_NR_TIME
+};
+
+#define RX6110_DRIVER_NAME             "rx6110"
+
+struct rx6110_data {
+       struct rtc_device *rtc;
+       struct regmap *regmap;
+};
+
+/**
+ * rx6110_rtc_tm_to_data - convert rtc_time to native time encoding
+ *
+ * @tm: holds date and time
+ * @data: holds the encoding in rx6110 native form
+ */
+static int rx6110_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
+{
+       pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+                tm->tm_sec, tm->tm_min, tm->tm_hour,
+                tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+       /*
+        * The year in the RTC is a value between 0 and 99.
+        * Assume that this represents the current century
+        * and disregard all other values.
+        */
+       if (tm->tm_year < 100 || tm->tm_year >= 200)
+               return -EINVAL;
+
+       data[RTC_SEC] = bin2bcd(tm->tm_sec);
+       data[RTC_MIN] = bin2bcd(tm->tm_min);
+       data[RTC_HOUR] = bin2bcd(tm->tm_hour);
+       data[RTC_WDAY] = BIT(bin2bcd(tm->tm_wday));
+       data[RTC_MDAY] = bin2bcd(tm->tm_mday);
+       data[RTC_MONTH] = bin2bcd(tm->tm_mon + 1);
+       data[RTC_YEAR] = bin2bcd(tm->tm_year % 100);
+
+       return 0;
+}
+
+/**
+ * rx6110_data_to_rtc_tm - convert native time encoding to rtc_time
+ *
+ * @data: holds the encoding in rx6110 native form
+ * @tm: holds date and time
+ */
+static int rx6110_data_to_rtc_tm(u8 *data, struct rtc_time *tm)
+{
+       tm->tm_sec = bcd2bin(data[RTC_SEC] & 0x7f);
+       tm->tm_min = bcd2bin(data[RTC_MIN] & 0x7f);
+       /* only 24-hour clock */
+       tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f);
+       tm->tm_wday = ffs(data[RTC_WDAY] & 0x7f);
+       tm->tm_mday = bcd2bin(data[RTC_MDAY] & 0x3f);
+       tm->tm_mon = bcd2bin(data[RTC_MONTH] & 0x1f) - 1;
+       tm->tm_year = bcd2bin(data[RTC_YEAR]) + 100;
+
+       pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+                tm->tm_sec, tm->tm_min, tm->tm_hour,
+                tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+       /*
+        * The year in the RTC is a value between 0 and 99.
+        * Assume that this represents the current century
+        * and disregard all other values.
+        */
+       if (tm->tm_year < 100 || tm->tm_year >= 200)
+               return -EINVAL;
+
+       return 0;
+}
+
+/**
+ * rx6110_set_time - set the current time in the rx6110 registers
+ *
+ * @dev: the rtc device in use
+ * @tm: holds date and time
+ *
+ * BUG: The HW assumes every year that is a multiple of 4 to be a leap
+ * year. Next time this is wrong is 2100, which will not be a leap year
+ *
+ * Note: If STOP is not set/cleared, the clock will start when the seconds
+ *       register is written
+ *
+ */
+static int rx6110_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct rx6110_data *rx6110 = dev_get_drvdata(dev);
+       u8 data[RTC_NR_TIME];
+       int ret;
+
+       ret = rx6110_rtc_tm_to_data(tm, data);
+       if (ret < 0)
+               return ret;
+
+       /* set STOP bit before changing clock/calendar */
+       ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
+                                RX6110_BIT_CTRL_STOP, RX6110_BIT_CTRL_STOP);
+       if (ret)
+               return ret;
+
+       ret = regmap_bulk_write(rx6110->regmap, RX6110_REG_SEC, data,
+                               RTC_NR_TIME);
+       if (ret)
+               return ret;
+
+       /* The time in the RTC is valid. Be sure to have VLF cleared. */
+       ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
+                                RX6110_BIT_FLAG_VLF, 0);
+       if (ret)
+               return ret;
+
+       /* clear STOP bit after changing clock/calendar */
+       ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
+                                RX6110_BIT_CTRL_STOP, 0);
+
+       return ret;
+}
+
+/**
+ * rx6110_get_time - get the current time from the rx6110 registers
+ * @dev: the rtc device in use
+ * @tm: holds date and time
+ */
+static int rx6110_get_time(struct device *dev, struct rtc_time *tm)
+{
+       struct rx6110_data *rx6110 = dev_get_drvdata(dev);
+       u8 data[RTC_NR_TIME];
+       int flags;
+       int ret;
+
+       ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags);
+       if (ret)
+               return -EINVAL;
+
+       /* check for VLF Flag (set at power-on) */
+       if ((flags & RX6110_BIT_FLAG_VLF)) {
+               dev_warn(dev, "Voltage low, data is invalid.\n");
+               return -EINVAL;
+       }
+
+       /* read registers to date */
+       ret = regmap_bulk_read(rx6110->regmap, RX6110_REG_SEC, data,
+                              RTC_NR_TIME);
+       if (ret)
+               return ret;
+
+       ret = rx6110_data_to_rtc_tm(data, tm);
+       if (ret)
+               return ret;
+
+       dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
+               tm->tm_sec, tm->tm_min, tm->tm_hour,
+               tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+       return rtc_valid_tm(tm);
+}
+
+static const struct reg_sequence rx6110_default_regs[] = {
+       { RX6110_REG_RES1,   0xB8 },
+       { RX6110_REG_RES2,   0x00 },
+       { RX6110_REG_RES3,   0x10 },
+       { RX6110_REG_IRQ,    0x00 },
+       { RX6110_REG_ALMIN,  0x00 },
+       { RX6110_REG_ALHOUR, 0x00 },
+       { RX6110_REG_ALWDAY, 0x00 },
+};
+
+/**
+ * rx6110_init - initialize the rx6110 registers
+ *
+ * @rx6110: pointer to the rx6110 struct in use
+ *
+ */
+static int rx6110_init(struct rx6110_data *rx6110)
+{
+       struct rtc_device *rtc = rx6110->rtc;
+       int flags;
+       int ret;
+
+       ret = regmap_update_bits(rx6110->regmap, RX6110_REG_EXT,
+                                RX6110_BIT_EXT_TE, 0);
+       if (ret)
+               return ret;
+
+       ret = regmap_register_patch(rx6110->regmap, rx6110_default_regs,
+                                   ARRAY_SIZE(rx6110_default_regs));
+       if (ret)
+               return ret;
+
+       ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags);
+       if (ret)
+               return ret;
+
+       /* check for VLF Flag (set at power-on) */
+       if ((flags & RX6110_BIT_FLAG_VLF))
+               dev_warn(&rtc->dev, "Voltage low, data loss detected.\n");
+
+       /* check for Alarm Flag */
+       if (flags & RX6110_BIT_FLAG_AF)
+               dev_warn(&rtc->dev, "An alarm may have been missed.\n");
+
+       /* check for Periodic Timer Flag */
+       if (flags & RX6110_BIT_FLAG_TF)
+               dev_warn(&rtc->dev, "Periodic timer was detected\n");
+
+       /* check for Update Timer Flag */
+       if (flags & RX6110_BIT_FLAG_UF)
+               dev_warn(&rtc->dev, "Update timer was detected\n");
+
+       /* clear all flags BUT VLF */
+       ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
+                                RX6110_BIT_FLAG_AF |
+                                RX6110_BIT_FLAG_UF |
+                                RX6110_BIT_FLAG_TF,
+                                0);
+
+       return ret;
+}
+
+static struct rtc_class_ops rx6110_rtc_ops = {
+       .read_time = rx6110_get_time,
+       .set_time = rx6110_set_time,
+};
+
+static struct regmap_config regmap_spi_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = RX6110_REG_IRQ,
+       .read_flag_mask = 0x80,
+};
+
+/**
+ * rx6110_probe - initialize rtc driver
+ * @spi: pointer to spi device
+ */
+static int rx6110_probe(struct spi_device *spi)
+{
+       struct rx6110_data *rx6110;
+       int err;
+
+       if ((spi->bits_per_word && spi->bits_per_word != 8) ||
+           (spi->max_speed_hz > 2000000) ||
+           (spi->mode != (SPI_CS_HIGH | SPI_CPOL | SPI_CPHA))) {
+               dev_warn(&spi->dev, "SPI settings: bits_per_word: %d, max_speed_hz: %d, mode: %xh\n",
+                        spi->bits_per_word, spi->max_speed_hz, spi->mode);
+               dev_warn(&spi->dev, "driving device in an unsupported mode");
+       }
+
+       rx6110 = devm_kzalloc(&spi->dev, sizeof(*rx6110), GFP_KERNEL);
+       if (!rx6110)
+               return -ENOMEM;
+
+       rx6110->regmap = devm_regmap_init_spi(spi, &regmap_spi_config);
+       if (IS_ERR(rx6110->regmap)) {
+               dev_err(&spi->dev, "regmap init failed for rtc rx6110\n");
+               return PTR_ERR(rx6110->regmap);
+       }
+
+       spi_set_drvdata(spi, rx6110);
+
+       rx6110->rtc = devm_rtc_device_register(&spi->dev,
+                                              RX6110_DRIVER_NAME,
+                                              &rx6110_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(rx6110->rtc))
+               return PTR_ERR(rx6110->rtc);
+
+       err = rx6110_init(rx6110);
+       if (err)
+               return err;
+
+       rx6110->rtc->max_user_freq = 1;
+
+       return 0;
+}
+
+static int rx6110_remove(struct spi_device *spi)
+{
+       return 0;
+}
+
+static const struct spi_device_id rx6110_id[] = {
+       { "rx6110", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, rx6110_id);
+
+static struct spi_driver rx6110_driver = {
+       .driver = {
+               .name = RX6110_DRIVER_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe          = rx6110_probe,
+       .remove         = rx6110_remove,
+       .id_table       = rx6110_id,
+};
+
+module_spi_driver(rx6110_driver);
+
+MODULE_AUTHOR("Val Krutov <val.krutov@erd.epson.com>");
+MODULE_DESCRIPTION("RX-6110 SA RTC driver");
+MODULE_LICENSE("GPL");
index bd911bafb809a2ede1c46c3f2e2877ac7507fc50..b69647e0be235bd5de1356de7c00d05485a39f5b 100644 (file)
@@ -65,7 +65,6 @@
 
 static const struct i2c_device_id rx8025_id[] = {
        { "rx8025", 0 },
-       { "rv8803", 1 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, rx8025_id);
@@ -147,8 +146,10 @@ static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
 {
        struct i2c_client *client = dev_id;
        struct rx8025_data *rx8025 = i2c_get_clientdata(client);
+       struct mutex *lock = &rx8025->rtc->ops_lock;
        int status;
 
+       mutex_lock(lock);
        status = rx8025_read_reg(client, RX8025_REG_CTRL2);
        if (status < 0)
                goto out;
@@ -173,6 +174,8 @@ static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
        }
 
 out:
+       mutex_unlock(lock);
+
        return IRQ_HANDLED;
 }
 
@@ -341,7 +344,17 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        if (client->irq <= 0)
                return -EINVAL;
 
-       /* Hardware alarm precision is 1 minute! */
+       /*
+        * Hardware alarm precision is 1 minute!
+        * round up to nearest minute
+        */
+       if (t->time.tm_sec) {
+               time64_t alarm_time = rtc_tm_to_time64(&t->time);
+
+               alarm_time += 60 - t->time.tm_sec;
+               rtc_time64_to_tm(alarm_time, &t->time);
+       }
+
        ald[0] = bin2bcd(t->time.tm_min);
        if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224)
                ald[1] = bin2bcd(t->time.tm_hour);
@@ -539,8 +552,9 @@ static int rx8025_probe(struct i2c_client *client,
        if (client->irq > 0) {
                dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
                err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                               rx8025_handle_irq, 0, "rx8025",
-                                               client);
+                                               rx8025_handle_irq,
+                                               IRQF_ONESHOT,
+                                               "rx8025", client);
                if (err) {
                        dev_err(&client->dev, "unable to request IRQ, alarms disabled\n");
                        client->irq = 0;
@@ -549,6 +563,9 @@ static int rx8025_probe(struct i2c_client *client,
 
        rx8025->rtc->max_user_freq = 1;
 
+       /* the rx8025 alarm only supports a minute accuracy */
+       rx8025->rtc->uie_unsupported = 1;
+
        err = rx8025_sysfs_register(&client->dev);
        return err;
 }
index 7407d7394bb46fe2c06b536d76bedd31731bf640..0477678d968fd1ccdec8e36784e57e05910364dc 100644 (file)
@@ -216,7 +216,7 @@ static int s5m8767_tm_to_data(struct rtc_time *tm, u8 *data)
  * Read RTC_UDR_CON register and wait till UDR field is cleared.
  * This indicates that time/alarm update ended.
  */
-static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
+static int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
 {
        int ret, retry = UDR_READ_RETRY_CNT;
        unsigned int data;
@@ -231,7 +231,7 @@ static inline int s5m8767_wait_for_udr_update(struct s5m_rtc_info *info)
        return ret;
 }
 
-static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
+static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
                struct rtc_wkalrm *alarm)
 {
        int ret;
@@ -264,7 +264,7 @@ static inline int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info,
        return 0;
 }
 
-static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
+static int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
 {
        int ret;
        unsigned int data;
@@ -288,7 +288,7 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
        return ret;
 }
 
-static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
+static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
 {
        int ret;
        unsigned int data;
index 463e286064ab3a4cc06e05713bbcd88999bc518a..63b9fb1318c2ae905db045458eb7e42ae4ae3338 100644 (file)
@@ -218,6 +218,34 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RW(wakealarm);
 
+static ssize_t
+offset_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       ssize_t retval;
+       long offset;
+
+       retval = rtc_read_offset(to_rtc_device(dev), &offset);
+       if (retval == 0)
+               retval = sprintf(buf, "%ld\n", offset);
+
+       return retval;
+}
+
+static ssize_t
+offset_store(struct device *dev, struct device_attribute *attr,
+            const char *buf, size_t n)
+{
+       ssize_t retval;
+       long offset;
+
+       retval = kstrtol(buf, 10, &offset);
+       if (retval == 0)
+               retval = rtc_set_offset(to_rtc_device(dev), offset);
+
+       return (retval < 0) ? retval : n;
+}
+static DEVICE_ATTR_RW(offset);
+
 static struct attribute *rtc_attrs[] = {
        &dev_attr_name.attr,
        &dev_attr_date.attr,
@@ -226,6 +254,7 @@ static struct attribute *rtc_attrs[] = {
        &dev_attr_max_user_freq.attr,
        &dev_attr_hctosys.attr,
        &dev_attr_wakealarm.attr,
+       &dev_attr_offset.attr,
        NULL,
 };
 
@@ -249,9 +278,13 @@ static umode_t rtc_attr_is_visible(struct kobject *kobj,
        struct rtc_device *rtc = to_rtc_device(dev);
        umode_t mode = attr->mode;
 
-       if (attr == &dev_attr_wakealarm.attr)
+       if (attr == &dev_attr_wakealarm.attr) {
                if (!rtc_does_wakealarm(rtc))
                        mode = 0;
+       } else if (attr == &dev_attr_offset.attr) {
+               if (!rtc->ops->set_offset)
+                       mode = 0;
+       }
 
        return mode;
 }
index 3b6ce80a769c761d9a6df88cfeda6b7ae6e4b5f9..e404faac68512bdb3adf6dde2904e0222f3b68db 100644 (file)
@@ -286,7 +286,7 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
 
        ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
                                tps6586x_rtc_irq,
-                               IRQF_ONESHOT | IRQF_EARLY_RESUME,
+                               IRQF_ONESHOT,
                                dev_name(&pdev->dev), rtc);
        if (ret < 0) {
                dev_err(&pdev->dev, "request IRQ(%d) failed with ret %d\n",
index f42aa2b2dcba5942cdbe1f6fa37d888d43504716..5a3d53caa485f733c3f38af872b18e8037b751ba 100644 (file)
@@ -268,7 +268,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
-               tps65910_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_EARLY_RESUME,
+               tps65910_rtc_interrupt, IRQF_TRIGGER_LOW,
                dev_name(&pdev->dev), &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "IRQ is not free.\n");
index 27e254cde715f5ef467541d8d216e3310f53074d..737f26eb284a67c03f17ece80696b7825e073323 100644 (file)
@@ -287,7 +287,7 @@ static int tps80031_rtc_probe(struct platform_device *pdev)
 
        ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
                        tps80031_rtc_irq,
-                       IRQF_ONESHOT | IRQF_EARLY_RESUME,
+                       IRQF_ONESHOT,
                        dev_name(&pdev->dev), rtc);
        if (ret < 0) {
                dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n",
index f64c282275b3988a7a3b5a1a43af44f4d5c1f05e..e1b86bb0106233f19ec0eb29de11dceb38a31b6e 100644 (file)
@@ -272,12 +272,13 @@ static irqreturn_t rtclong1_interrupt(int irq, void *dev_id)
 }
 
 static const struct rtc_class_ops vr41xx_rtc_ops = {
-       .release        = vr41xx_rtc_release,
-       .ioctl          = vr41xx_rtc_ioctl,
-       .read_time      = vr41xx_rtc_read_time,
-       .set_time       = vr41xx_rtc_set_time,
-       .read_alarm     = vr41xx_rtc_read_alarm,
-       .set_alarm      = vr41xx_rtc_set_alarm,
+       .release                = vr41xx_rtc_release,
+       .ioctl                  = vr41xx_rtc_ioctl,
+       .read_time              = vr41xx_rtc_read_time,
+       .set_time               = vr41xx_rtc_set_time,
+       .read_alarm             = vr41xx_rtc_read_alarm,
+       .set_alarm              = vr41xx_rtc_set_alarm,
+       .alarm_irq_enable       = vr41xx_rtc_alarm_irq_enable,
 };
 
 static int rtc_probe(struct platform_device *pdev)
index 286782c60da4e3b197d7d9901b7e17c2e69673ac..17ad5749e91d1d461c7bb74456cc029aa5e11764 100644 (file)
@@ -185,14 +185,12 @@ static void _free_lcu(struct alias_lcu *lcu)
  */
 int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        unsigned long flags;
        struct alias_server *server, *newserver;
        struct alias_lcu *lcu, *newlcu;
        struct dasd_uid uid;
 
-       private = (struct dasd_eckd_private *) device->private;
-
        device->discipline->get_uid(device, &uid);
        spin_lock_irqsave(&aliastree.lock, flags);
        server = _find_server(&uid);
@@ -244,14 +242,13 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
  */
 void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        unsigned long flags;
        struct alias_lcu *lcu;
        struct alias_server *server;
        int was_pending;
        struct dasd_uid uid;
 
-       private = (struct dasd_eckd_private *) device->private;
        lcu = private->lcu;
        /* nothing to do if already disconnected */
        if (!lcu)
@@ -316,25 +313,15 @@ static int _add_device_to_lcu(struct alias_lcu *lcu,
                              struct dasd_device *pos)
 {
 
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        struct alias_pav_group *group;
        struct dasd_uid uid;
-       unsigned long flags;
-
-       private = (struct dasd_eckd_private *) device->private;
 
-       /* only lock if not already locked */
-       if (device != pos)
-               spin_lock_irqsave_nested(get_ccwdev_lock(device->cdev), flags,
-                                        CDEV_NESTED_SECOND);
        private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type;
        private->uid.base_unit_addr =
                lcu->uac->unit[private->uid.real_unit_addr].base_ua;
        uid = private->uid;
 
-       if (device != pos)
-               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
-
        /* if we have no PAV anyway, we don't need to bother with PAV groups */
        if (lcu->pav == NO_PAV) {
                list_move(&device->alias_list, &lcu->active_devices);
@@ -370,10 +357,9 @@ static int _add_device_to_lcu(struct alias_lcu *lcu,
 static void _remove_device_from_lcu(struct alias_lcu *lcu,
                                    struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        struct alias_pav_group *group;
 
-       private = (struct dasd_eckd_private *) device->private;
        list_move(&device->alias_list, &lcu->inactive_devices);
        group = private->pavgroup;
        if (!group)
@@ -411,6 +397,130 @@ suborder_not_supported(struct dasd_ccw_req *cqr)
        return 0;
 }
 
+/*
+ * This function tries to lock all devices on an lcu via trylock
+ * return NULL on success otherwise return first failed device
+ */
+static struct dasd_device *_trylock_all_devices_on_lcu(struct alias_lcu *lcu,
+                                                     struct dasd_device *pos)
+
+{
+       struct alias_pav_group *pavgroup;
+       struct dasd_device *device;
+
+       list_for_each_entry(device, &lcu->active_devices, alias_list) {
+               if (device == pos)
+                       continue;
+               if (!spin_trylock(get_ccwdev_lock(device->cdev)))
+                       return device;
+       }
+       list_for_each_entry(device, &lcu->inactive_devices, alias_list) {
+               if (device == pos)
+                       continue;
+               if (!spin_trylock(get_ccwdev_lock(device->cdev)))
+                       return device;
+       }
+       list_for_each_entry(pavgroup, &lcu->grouplist, group) {
+               list_for_each_entry(device, &pavgroup->baselist, alias_list) {
+                       if (device == pos)
+                               continue;
+                       if (!spin_trylock(get_ccwdev_lock(device->cdev)))
+                               return device;
+               }
+               list_for_each_entry(device, &pavgroup->aliaslist, alias_list) {
+                       if (device == pos)
+                               continue;
+                       if (!spin_trylock(get_ccwdev_lock(device->cdev)))
+                               return device;
+               }
+       }
+       return NULL;
+}
+
+/*
+ * unlock all devices except the one that is specified as pos
+ * stop if enddev is specified and reached
+ */
+static void _unlock_all_devices_on_lcu(struct alias_lcu *lcu,
+                                      struct dasd_device *pos,
+                                      struct dasd_device *enddev)
+
+{
+       struct alias_pav_group *pavgroup;
+       struct dasd_device *device;
+
+       list_for_each_entry(device, &lcu->active_devices, alias_list) {
+               if (device == pos)
+                       continue;
+               if (device == enddev)
+                       return;
+               spin_unlock(get_ccwdev_lock(device->cdev));
+       }
+       list_for_each_entry(device, &lcu->inactive_devices, alias_list) {
+               if (device == pos)
+                       continue;
+               if (device == enddev)
+                       return;
+               spin_unlock(get_ccwdev_lock(device->cdev));
+       }
+       list_for_each_entry(pavgroup, &lcu->grouplist, group) {
+               list_for_each_entry(device, &pavgroup->baselist, alias_list) {
+                       if (device == pos)
+                               continue;
+                       if (device == enddev)
+                               return;
+                       spin_unlock(get_ccwdev_lock(device->cdev));
+               }
+               list_for_each_entry(device, &pavgroup->aliaslist, alias_list) {
+                       if (device == pos)
+                               continue;
+                       if (device == enddev)
+                               return;
+                       spin_unlock(get_ccwdev_lock(device->cdev));
+               }
+       }
+}
+
+/*
+ *  this function is needed because the locking order
+ *  device lock -> lcu lock
+ *  needs to be assured when iterating over devices in an LCU
+ *
+ *  if a device is specified in pos then the device lock is already hold
+ */
+static void _trylock_and_lock_lcu_irqsave(struct alias_lcu *lcu,
+                                         struct dasd_device *pos,
+                                         unsigned long *flags)
+{
+       struct dasd_device *failed;
+
+       do {
+               spin_lock_irqsave(&lcu->lock, *flags);
+               failed = _trylock_all_devices_on_lcu(lcu, pos);
+               if (failed) {
+                       _unlock_all_devices_on_lcu(lcu, pos, failed);
+                       spin_unlock_irqrestore(&lcu->lock, *flags);
+                       cpu_relax();
+               }
+       } while (failed);
+}
+
+static void _trylock_and_lock_lcu(struct alias_lcu *lcu,
+                                 struct dasd_device *pos)
+{
+       struct dasd_device *failed;
+
+       do {
+               spin_lock(&lcu->lock);
+               failed = _trylock_all_devices_on_lcu(lcu, pos);
+               if (failed) {
+                       _unlock_all_devices_on_lcu(lcu, pos, failed);
+                       spin_unlock(&lcu->lock);
+                       cpu_relax();
+               }
+       } while (failed);
+}
+
 static int read_unit_address_configuration(struct dasd_device *device,
                                           struct alias_lcu *lcu)
 {
@@ -487,13 +597,13 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)
                list_for_each_entry_safe(device, tempdev, &pavgroup->baselist,
                                         alias_list) {
                        list_move(&device->alias_list, &lcu->active_devices);
-                       private = (struct dasd_eckd_private *) device->private;
+                       private = device->private;
                        private->pavgroup = NULL;
                }
                list_for_each_entry_safe(device, tempdev, &pavgroup->aliaslist,
                                         alias_list) {
                        list_move(&device->alias_list, &lcu->active_devices);
-                       private = (struct dasd_eckd_private *) device->private;
+                       private = device->private;
                        private->pavgroup = NULL;
                }
                list_del(&pavgroup->group);
@@ -505,10 +615,7 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)
        if (rc)
                return rc;
 
-       /* need to take cdev lock before lcu lock */
-       spin_lock_irqsave_nested(get_ccwdev_lock(refdev->cdev), flags,
-                                CDEV_NESTED_FIRST);
-       spin_lock(&lcu->lock);
+       _trylock_and_lock_lcu_irqsave(lcu, NULL, &flags);
        lcu->pav = NO_PAV;
        for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) {
                switch (lcu->uac->unit[i].ua_type) {
@@ -527,8 +634,8 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu)
                                 alias_list) {
                _add_device_to_lcu(lcu, device, refdev);
        }
-       spin_unlock(&lcu->lock);
-       spin_unlock_irqrestore(get_ccwdev_lock(refdev->cdev), flags);
+       _unlock_all_devices_on_lcu(lcu, NULL, NULL);
+       spin_unlock_irqrestore(&lcu->lock, flags);
        return 0;
 }
 
@@ -608,16 +715,13 @@ static int _schedule_lcu_update(struct alias_lcu *lcu,
 
 int dasd_alias_add_device(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        struct alias_lcu *lcu;
        unsigned long flags;
        int rc;
 
-       private = (struct dasd_eckd_private *) device->private;
        lcu = private->lcu;
        rc = 0;
-
-       /* need to take cdev lock before lcu lock */
        spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        spin_lock(&lcu->lock);
        if (!(lcu->flags & UPDATE_PENDING)) {
@@ -636,20 +740,18 @@ int dasd_alias_add_device(struct dasd_device *device)
 
 int dasd_alias_update_add_device(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
-       private = (struct dasd_eckd_private *) device->private;
+       struct dasd_eckd_private *private = device->private;
+
        private->lcu->flags |= UPDATE_PENDING;
        return dasd_alias_add_device(device);
 }
 
 int dasd_alias_remove_device(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
-       struct alias_lcu *lcu;
+       struct dasd_eckd_private *private = device->private;
+       struct alias_lcu *lcu = private->lcu;
        unsigned long flags;
 
-       private = (struct dasd_eckd_private *) device->private;
-       lcu = private->lcu;
        /* nothing to do if already removed */
        if (!lcu)
                return 0;
@@ -661,16 +763,12 @@ int dasd_alias_remove_device(struct dasd_device *device)
 
 struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
 {
-
+       struct dasd_eckd_private *alias_priv, *private = base_device->private;
+       struct alias_pav_group *group = private->pavgroup;
+       struct alias_lcu *lcu = private->lcu;
        struct dasd_device *alias_device;
-       struct alias_pav_group *group;
-       struct alias_lcu *lcu;
-       struct dasd_eckd_private *private, *alias_priv;
        unsigned long flags;
 
-       private = (struct dasd_eckd_private *) base_device->private;
-       group = private->pavgroup;
-       lcu = private->lcu;
        if (!group || !lcu)
                return NULL;
        if (lcu->pav == NO_PAV ||
@@ -706,7 +804,7 @@ struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
                group->next = list_first_entry(&alias_device->alias_list,
                                               struct dasd_device, alias_list);
        spin_unlock_irqrestore(&lcu->lock, flags);
-       alias_priv = (struct dasd_eckd_private *) alias_device->private;
+       alias_priv = alias_device->private;
        if ((alias_priv->count < private->count) && !alias_device->stopped &&
            !test_bit(DASD_FLAG_OFFLINE, &alias_device->flags))
                return alias_device;
@@ -754,30 +852,19 @@ static void _restart_all_base_devices_on_lcu(struct alias_lcu *lcu)
        struct alias_pav_group *pavgroup;
        struct dasd_device *device;
        struct dasd_eckd_private *private;
-       unsigned long flags;
 
        /* active and inactive list can contain alias as well as base devices */
        list_for_each_entry(device, &lcu->active_devices, alias_list) {
-               private = (struct dasd_eckd_private *) device->private;
-               spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
-               if (private->uid.type != UA_BASE_DEVICE) {
-                       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
-                                              flags);
+               private = device->private;
+               if (private->uid.type != UA_BASE_DEVICE)
                        continue;
-               }
-               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
                dasd_schedule_block_bh(device->block);
                dasd_schedule_device_bh(device);
        }
        list_for_each_entry(device, &lcu->inactive_devices, alias_list) {
-               private = (struct dasd_eckd_private *) device->private;
-               spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
-               if (private->uid.type != UA_BASE_DEVICE) {
-                       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
-                                              flags);
+               private = device->private;
+               if (private->uid.type != UA_BASE_DEVICE)
                        continue;
-               }
-               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
                dasd_schedule_block_bh(device->block);
                dasd_schedule_device_bh(device);
        }
@@ -812,7 +899,7 @@ static void flush_all_alias_devices_on_lcu(struct alias_lcu *lcu)
        spin_lock_irqsave(&lcu->lock, flags);
        list_for_each_entry_safe(device, temp, &lcu->active_devices,
                                 alias_list) {
-               private = (struct dasd_eckd_private *) device->private;
+               private = device->private;
                if (private->uid.type == UA_BASE_DEVICE)
                        continue;
                list_move(&device->alias_list, &active);
@@ -834,45 +921,27 @@ static void flush_all_alias_devices_on_lcu(struct alias_lcu *lcu)
                if (device == list_first_entry(&active,
                                               struct dasd_device, alias_list)) {
                        list_move(&device->alias_list, &lcu->active_devices);
-                       private = (struct dasd_eckd_private *) device->private;
+                       private = device->private;
                        private->pavgroup = NULL;
                }
        }
        spin_unlock_irqrestore(&lcu->lock, flags);
 }
 
-static void __stop_device_on_lcu(struct dasd_device *device,
-                                struct dasd_device *pos)
-{
-       /* If pos == device then device is already locked! */
-       if (pos == device) {
-               dasd_device_set_stop_bits(pos, DASD_STOPPED_SU);
-               return;
-       }
-       spin_lock(get_ccwdev_lock(pos->cdev));
-       dasd_device_set_stop_bits(pos, DASD_STOPPED_SU);
-       spin_unlock(get_ccwdev_lock(pos->cdev));
-}
-
-/*
- * This function is called in interrupt context, so the
- * cdev lock for device is already locked!
- */
-static void _stop_all_devices_on_lcu(struct alias_lcu *lcu,
-                                    struct dasd_device *device)
+static void _stop_all_devices_on_lcu(struct alias_lcu *lcu)
 {
        struct alias_pav_group *pavgroup;
-       struct dasd_device *pos;
+       struct dasd_device *device;
 
-       list_for_each_entry(pos, &lcu->active_devices, alias_list)
-               __stop_device_on_lcu(device, pos);
-       list_for_each_entry(pos, &lcu->inactive_devices, alias_list)
-               __stop_device_on_lcu(device, pos);
+       list_for_each_entry(device, &lcu->active_devices, alias_list)
+               dasd_device_set_stop_bits(device, DASD_STOPPED_SU);
+       list_for_each_entry(device, &lcu->inactive_devices, alias_list)
+               dasd_device_set_stop_bits(device, DASD_STOPPED_SU);
        list_for_each_entry(pavgroup, &lcu->grouplist, group) {
-               list_for_each_entry(pos, &pavgroup->baselist, alias_list)
-                       __stop_device_on_lcu(device, pos);
-               list_for_each_entry(pos, &pavgroup->aliaslist, alias_list)
-                       __stop_device_on_lcu(device, pos);
+               list_for_each_entry(device, &pavgroup->baselist, alias_list)
+                       dasd_device_set_stop_bits(device, DASD_STOPPED_SU);
+               list_for_each_entry(device, &pavgroup->aliaslist, alias_list)
+                       dasd_device_set_stop_bits(device, DASD_STOPPED_SU);
        }
 }
 
@@ -880,33 +949,16 @@ static void _unstop_all_devices_on_lcu(struct alias_lcu *lcu)
 {
        struct alias_pav_group *pavgroup;
        struct dasd_device *device;
-       unsigned long flags;
 
-       list_for_each_entry(device, &lcu->active_devices, alias_list) {
-               spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+       list_for_each_entry(device, &lcu->active_devices, alias_list)
                dasd_device_remove_stop_bits(device, DASD_STOPPED_SU);
-               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
-       }
-
-       list_for_each_entry(device, &lcu->inactive_devices, alias_list) {
-               spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+       list_for_each_entry(device, &lcu->inactive_devices, alias_list)
                dasd_device_remove_stop_bits(device, DASD_STOPPED_SU);
-               spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
-       }
-
        list_for_each_entry(pavgroup, &lcu->grouplist, group) {
-               list_for_each_entry(device, &pavgroup->baselist, alias_list) {
-                       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+               list_for_each_entry(device, &pavgroup->baselist, alias_list)
                        dasd_device_remove_stop_bits(device, DASD_STOPPED_SU);
-                       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
-                                              flags);
-               }
-               list_for_each_entry(device, &pavgroup->aliaslist, alias_list) {
-                       spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
+               list_for_each_entry(device, &pavgroup->aliaslist, alias_list)
                        dasd_device_remove_stop_bits(device, DASD_STOPPED_SU);
-                       spin_unlock_irqrestore(get_ccwdev_lock(device->cdev),
-                                              flags);
-               }
        }
 }
 
@@ -932,13 +984,14 @@ static void summary_unit_check_handling_work(struct work_struct *work)
        spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
        reset_summary_unit_check(lcu, device, suc_data->reason);
 
-       spin_lock_irqsave(&lcu->lock, flags);
+       _trylock_and_lock_lcu_irqsave(lcu, NULL, &flags);
        _unstop_all_devices_on_lcu(lcu);
        _restart_all_base_devices_on_lcu(lcu);
        /* 3. read new alias configuration */
        _schedule_lcu_update(lcu, device);
        lcu->suc_data.device = NULL;
        dasd_put_device(device);
+       _unlock_all_devices_on_lcu(lcu, NULL, NULL);
        spin_unlock_irqrestore(&lcu->lock, flags);
 }
 
@@ -948,13 +1001,11 @@ static void summary_unit_check_handling_work(struct work_struct *work)
 void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
                                          struct irb *irb)
 {
+       struct dasd_eckd_private *private = device->private;
        struct alias_lcu *lcu;
        char reason;
-       struct dasd_eckd_private *private;
        char *sense;
 
-       private = (struct dasd_eckd_private *) device->private;
-
        sense = dasd_get_sense(irb);
        if (sense) {
                reason = sense[8];
@@ -974,10 +1025,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
                            " unit check (no lcu structure)");
                return;
        }
-       spin_lock(&lcu->lock);
-       _stop_all_devices_on_lcu(lcu, device);
-       /* prepare for lcu_update */
-       private->lcu->flags |= NEED_UAC_UPDATE | UPDATE_PENDING;
+       _trylock_and_lock_lcu(lcu, device);
        /* If this device is about to be removed just return and wait for
         * the next interrupt on a different device
         */
@@ -985,6 +1033,7 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
                DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "device is in offline processing,"
                            " don't do summary unit check handling");
+               _unlock_all_devices_on_lcu(lcu, device, NULL);
                spin_unlock(&lcu->lock);
                return;
        }
@@ -993,12 +1042,17 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
                DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                            "previous instance of summary unit check worker"
                            " still pending");
+               _unlock_all_devices_on_lcu(lcu, device, NULL);
                spin_unlock(&lcu->lock);
                return ;
        }
+       _stop_all_devices_on_lcu(lcu);
+       /* prepare for lcu_update */
+       private->lcu->flags |= NEED_UAC_UPDATE | UPDATE_PENDING;
        lcu->suc_data.reason = reason;
        lcu->suc_data.device = device;
        dasd_get_device(device);
+       _unlock_all_devices_on_lcu(lcu, device, NULL);
        spin_unlock(&lcu->lock);
        if (!schedule_work(&lcu->suc_data.worker))
                dasd_put_device(device);
index 8286f742436b7b75f40638c77f9414b76b0d45a9..2f18f61092b52ae52e2885173e0bcd71c3d8d770 100644 (file)
@@ -214,8 +214,8 @@ dasd_feature_list(char *str, char **endp)
                else if (len == 8 && !strncmp(str, "failfast", 8))
                        features |= DASD_FEATURE_FAILFAST;
                else {
-                       pr_warning("%*s is not a supported device option\n",
-                                  len, str);
+                       pr_warn("%*s is not a supported device option\n",
+                               len, str);
                        rc = -EINVAL;
                }
                str += len;
@@ -224,8 +224,7 @@ dasd_feature_list(char *str, char **endp)
                str++;
        }
        if (*str != ')') {
-               pr_warning("A closing parenthesis ')' is missing in the "
-                          "dasd= parameter\n");
+               pr_warn("A closing parenthesis ')' is missing in the dasd= parameter\n");
                rc = -EINVAL;
        } else
                str++;
@@ -348,8 +347,7 @@ dasd_parse_range( char *parsestring ) {
                return str + 1;
        if (*str == '\0')
                return str;
-       pr_warning("The dasd= parameter value %s has an invalid ending\n",
-                  str);
+       pr_warn("The dasd= parameter value %s has an invalid ending\n", str);
        return ERR_PTR(-EINVAL);
 }
 
index cb61f300f8b5d111ce7871a39be43a1b7fe3ca80..5667146c6a0ae3c3c513a3180921ff5986cb79ea 100644 (file)
@@ -67,7 +67,7 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
  * and function code cmd.
  * In case of an exception return 3. Otherwise return result of bitwise OR of
  * resulting condition code and DIAG return code. */
-static inline int dia250(void *iob, int cmd)
+static inline int __dia250(void *iob, int cmd)
 {
        register unsigned long reg2 asm ("2") = (unsigned long) iob;
        typedef union {
@@ -77,7 +77,6 @@ static inline int dia250(void *iob, int cmd)
        int rc;
 
        rc = 3;
-       diag_stat_inc(DIAG_STAT_X250);
        asm volatile(
                "       diag    2,%2,0x250\n"
                "0:     ipm     %0\n"
@@ -91,6 +90,12 @@ static inline int dia250(void *iob, int cmd)
        return rc;
 }
 
+static inline int dia250(void *iob, int cmd)
+{
+       diag_stat_inc(DIAG_STAT_X250);
+       return __dia250(iob, cmd);
+}
+
 /* Initialize block I/O to DIAG device using the specified blocksize and
  * block offset. On success, return zero and set end_block to contain the
  * number of blocks on the device minus the specified offset. Return non-zero
@@ -99,12 +104,10 @@ static inline int
 mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
             blocknum_t offset, blocknum_t *end_block)
 {
-       struct dasd_diag_private *private;
-       struct dasd_diag_init_io *iib;
+       struct dasd_diag_private *private = device->private;
+       struct dasd_diag_init_io *iib = &private->iib;
        int rc;
 
-       private = (struct dasd_diag_private *) device->private;
-       iib = &private->iib;
        memset(iib, 0, sizeof (struct dasd_diag_init_io));
 
        iib->dev_nr = private->dev_id.devno;
@@ -125,12 +128,10 @@ mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
 static inline int
 mdsk_term_io(struct dasd_device * device)
 {
-       struct dasd_diag_private *private;
-       struct dasd_diag_init_io *iib;
+       struct dasd_diag_private *private = device->private;
+       struct dasd_diag_init_io *iib = &private->iib;
        int rc;
 
-       private = (struct dasd_diag_private *) device->private;
-       iib = &private->iib;
        memset(iib, 0, sizeof (struct dasd_diag_init_io));
        iib->dev_nr = private->dev_id.devno;
        rc = dia250(iib, TERM_BIO);
@@ -148,14 +149,13 @@ dasd_diag_erp(struct dasd_device *device)
        rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
        if (rc == 4) {
                if (!(test_and_set_bit(DASD_FLAG_DEVICE_RO, &device->flags)))
-                       pr_warning("%s: The access mode of a DIAG device "
-                                  "changed to read-only\n",
-                                  dev_name(&device->cdev->dev));
+                       pr_warn("%s: The access mode of a DIAG device changed to read-only\n",
+                               dev_name(&device->cdev->dev));
                rc = 0;
        }
        if (rc)
-               pr_warning("%s: DIAG ERP failed with "
-                           "rc=%d\n", dev_name(&device->cdev->dev), rc);
+               pr_warn("%s: DIAG ERP failed with rc=%d\n",
+                       dev_name(&device->cdev->dev), rc);
 }
 
 /* Start a given request at the device. Return zero on success, non-zero
@@ -175,8 +175,8 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
                cqr->status = DASD_CQR_ERROR;
                return -EIO;
        }
-       private = (struct dasd_diag_private *) device->private;
-       dreq = (struct dasd_diag_req *) cqr->data;
+       private = device->private;
+       dreq = cqr->data;
 
        private->iob.dev_nr = private->dev_id.devno;
        private->iob.key = 0;
@@ -315,18 +315,17 @@ static void dasd_ext_handler(struct ext_code ext_code,
 static int
 dasd_diag_check_device(struct dasd_device *device)
 {
-       struct dasd_block *block;
-       struct dasd_diag_private *private;
+       struct dasd_diag_private *private = device->private;
        struct dasd_diag_characteristics *rdc_data;
-       struct dasd_diag_bio bio;
        struct vtoc_cms_label *label;
-       blocknum_t end_block;
+       struct dasd_block *block;
+       struct dasd_diag_bio bio;
        unsigned int sb, bsize;
+       blocknum_t end_block;
        int rc;
 
-       private = (struct dasd_diag_private *) device->private;
        if (private == NULL) {
-               private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL);
+               private = kzalloc(sizeof(*private), GFP_KERNEL);
                if (private == NULL) {
                        DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                                "Allocating memory for private DASD data "
@@ -334,7 +333,7 @@ dasd_diag_check_device(struct dasd_device *device)
                        return -ENOMEM;
                }
                ccw_device_get_id(device->cdev, &private->dev_id);
-               device->private = (void *) private;
+               device->private = private;
        }
        block = dasd_alloc_block();
        if (IS_ERR(block)) {
@@ -348,7 +347,7 @@ dasd_diag_check_device(struct dasd_device *device)
        block->base = device;
 
        /* Read Device Characteristics */
-       rdc_data = (void *) &(private->rdc_data);
+       rdc_data = &private->rdc_data;
        rdc_data->dev_nr = private->dev_id.devno;
        rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics);
 
@@ -372,9 +371,9 @@ dasd_diag_check_device(struct dasd_device *device)
                private->pt_block = 2;
                break;
        default:
-               pr_warning("%s: Device type %d is not supported "
-                          "in DIAG mode\n", dev_name(&device->cdev->dev),
-                          private->rdc_data.vdev_class);
+               pr_warn("%s: Device type %d is not supported in DIAG mode\n",
+                       dev_name(&device->cdev->dev),
+                       private->rdc_data.vdev_class);
                rc = -EOPNOTSUPP;
                goto out;
        }
@@ -415,8 +414,8 @@ dasd_diag_check_device(struct dasd_device *device)
                private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
                rc = dia250(&private->iob, RW_BIO);
                if (rc == 3) {
-                       pr_warning("%s: A 64-bit DIAG call failed\n",
-                                  dev_name(&device->cdev->dev));
+                       pr_warn("%s: A 64-bit DIAG call failed\n",
+                               dev_name(&device->cdev->dev));
                        rc = -EOPNOTSUPP;
                        goto out_label;
                }
@@ -425,9 +424,8 @@ dasd_diag_check_device(struct dasd_device *device)
                        break;
        }
        if (bsize > PAGE_SIZE) {
-               pr_warning("%s: Accessing the DASD failed because of an "
-                          "incorrect format (rc=%d)\n",
-                          dev_name(&device->cdev->dev), rc);
+               pr_warn("%s: Accessing the DASD failed because of an incorrect format (rc=%d)\n",
+                       dev_name(&device->cdev->dev), rc);
                rc = -EIO;
                goto out_label;
        }
@@ -445,8 +443,8 @@ dasd_diag_check_device(struct dasd_device *device)
                block->s2b_shift++;
        rc = mdsk_init_io(device, block->bp_block, 0, NULL);
        if (rc && (rc != 4)) {
-               pr_warning("%s: DIAG initialization failed with rc=%d\n",
-                          dev_name(&device->cdev->dev), rc);
+               pr_warn("%s: DIAG initialization failed with rc=%d\n",
+                       dev_name(&device->cdev->dev), rc);
                rc = -EIO;
        } else {
                if (rc == 4)
@@ -596,16 +594,14 @@ static int
 dasd_diag_fill_info(struct dasd_device * device,
                    struct dasd_information2_t * info)
 {
-       struct dasd_diag_private *private;
+       struct dasd_diag_private *private = device->private;
 
-       private = (struct dasd_diag_private *) device->private;
        info->label_block = (unsigned int) private->pt_block;
        info->FBA_layout = 1;
        info->format = DASD_FORMAT_LDL;
-       info->characteristics_size = sizeof (struct dasd_diag_characteristics);
-       memcpy(info->characteristics,
-              &((struct dasd_diag_private *) device->private)->rdc_data,
-              sizeof (struct dasd_diag_characteristics));
+       info->characteristics_size = sizeof(private->rdc_data);
+       memcpy(info->characteristics, &private->rdc_data,
+              sizeof(private->rdc_data));
        info->confdata_size = 0;
        return 0;
 }
index 9083247f55a817cc2592d6b874cf624e09d82cf5..75c032dcf1739ef3871a806818440836c076cc7c 100644 (file)
@@ -212,10 +212,9 @@ check_XRC (struct ccw1         *de_ccw,
            struct DE_eckd_data *data,
            struct dasd_device  *device)
 {
-        struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        int rc;
 
-        private = (struct dasd_eckd_private *) device->private;
        if (!private->rdc_data.facilities.XRC_supported)
                return 0;
 
@@ -237,13 +236,11 @@ static int
 define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk,
              unsigned int totrk, int cmd, struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        u32 begcyl, endcyl;
        u16 heads, beghead, endhead;
        int rc = 0;
 
-       private = (struct dasd_eckd_private *) device->private;
-
        ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
        ccw->flags = 0;
        ccw->count = 16;
@@ -322,10 +319,9 @@ define_extent(struct ccw1 *ccw, struct DE_eckd_data *data, unsigned int trk,
 static int check_XRC_on_prefix(struct PFX_eckd_data *pfxdata,
                               struct dasd_device  *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        int rc;
 
-       private = (struct dasd_eckd_private *) device->private;
        if (!private->rdc_data.facilities.XRC_supported)
                return 0;
 
@@ -346,12 +342,10 @@ static void fill_LRE_data(struct LRE_eckd_data *data, unsigned int trk,
                          struct dasd_device *device, unsigned int reclen,
                          unsigned int tlf)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        int sector;
        int dn, d;
 
-       private = (struct dasd_eckd_private *) device->private;
-
        memset(data, 0, sizeof(*data));
        sector = 0;
        if (rec_on_trk) {
@@ -488,8 +482,8 @@ static int prefix_LRE(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata,
        u16 heads, beghead, endhead;
        int rc = 0;
 
-       basepriv = (struct dasd_eckd_private *) basedev->private;
-       startpriv = (struct dasd_eckd_private *) startdev->private;
+       basepriv = basedev->private;
+       startpriv = startdev->private;
        dedata = &pfxdata->define_extent;
        lredata = &pfxdata->locate_record;
 
@@ -631,12 +625,10 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, unsigned int trk,
              unsigned int rec_on_trk, int no_rec, int cmd,
              struct dasd_device * device, int reclen)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        int sector;
        int dn, d;
 
-       private = (struct dasd_eckd_private *) device->private;
-
        DBF_DEV_EVENT(DBF_INFO, device,
                  "Locate: trk %d, rec %d, no_rec %d, cmd %d, reclen %d",
                  trk, rec_on_trk, no_rec, cmd, reclen);
@@ -800,10 +792,9 @@ static void create_uid(struct dasd_eckd_private *private)
  */
 static int dasd_eckd_generate_uid(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        unsigned long flags;
 
-       private = (struct dasd_eckd_private *) device->private;
        if (!private)
                return -ENODEV;
        if (!private->ned || !private->gneq)
@@ -816,11 +807,10 @@ static int dasd_eckd_generate_uid(struct dasd_device *device)
 
 static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        unsigned long flags;
 
-       if (device->private) {
-               private = (struct dasd_eckd_private *)device->private;
+       if (private) {
                spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
                *uid = private->uid;
                spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
@@ -1034,10 +1024,9 @@ static unsigned char dasd_eckd_path_access(void *conf_data, int conf_len)
 
 static void dasd_eckd_clear_conf_data(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        int i;
 
-       private = (struct dasd_eckd_private *) device->private;
        private->conf_data = NULL;
        private->conf_len = 0;
        for (i = 0; i < 8; i++) {
@@ -1058,7 +1047,7 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
        struct dasd_uid *uid;
        char print_path_uid[60], print_device_uid[60];
 
-       private = (struct dasd_eckd_private *) device->private;
+       private = device->private;
        path_data = &device->path_data;
        opm = ccw_device_get_path_mask(device->cdev);
        conf_data_saved = 0;
@@ -1191,11 +1180,10 @@ static int dasd_eckd_read_conf(struct dasd_device *device)
 
 static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        int mdc;
        u32 fcx_max_data;
 
-       private = (struct dasd_eckd_private *) device->private;
        if (private->fcx_max_data) {
                mdc = ccw_device_get_mdc(device->cdev, lpm);
                if ((mdc < 0)) {
@@ -1221,15 +1209,10 @@ static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
 static int rebuild_device_uid(struct dasd_device *device,
                              struct path_verification_work_data *data)
 {
-       struct dasd_eckd_private *private;
-       struct dasd_path *path_data;
-       __u8 lpm, opm;
-       int rc;
-
-       rc = -ENODEV;
-       private = (struct dasd_eckd_private *) device->private;
-       path_data = &device->path_data;
-       opm = device->path_data.opm;
+       struct dasd_eckd_private *private = device->private;
+       struct dasd_path *path_data = &device->path_data;
+       __u8 lpm, opm = path_data->opm;
+       int rc = -ENODEV;
 
        for (lpm = 0x80; lpm; lpm >>= 1) {
                if (!(lpm & opm))
@@ -1463,14 +1446,13 @@ static int dasd_eckd_verify_path(struct dasd_device *device, __u8 lpm)
 
 static int dasd_eckd_read_features(struct dasd_device *device)
 {
+       struct dasd_eckd_private *private = device->private;
        struct dasd_psf_prssd_data *prssdp;
        struct dasd_rssd_features *features;
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
        int rc;
-       struct dasd_eckd_private *private;
 
-       private = (struct dasd_eckd_private *) device->private;
        memset(&private->features, 0, sizeof(struct dasd_rssd_features));
        cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
                                   (sizeof(struct dasd_psf_prssd_data) +
@@ -1605,11 +1587,9 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav,
 static int dasd_eckd_validate_server(struct dasd_device *device,
                                     unsigned long flags)
 {
-       int rc;
-       struct dasd_eckd_private *private;
-       int enable_pav;
+       struct dasd_eckd_private *private = device->private;
+       int enable_pav, rc;
 
-       private = (struct dasd_eckd_private *) device->private;
        if (private->uid.type == UA_BASE_PAV_ALIAS ||
            private->uid.type == UA_HYPER_PAV_ALIAS)
                return 0;
@@ -1662,14 +1642,13 @@ static void dasd_eckd_kick_validate_server(struct dasd_device *device)
 
 static u32 get_fcx_max_data(struct dasd_device *device)
 {
-       int tpm, mdc;
+       struct dasd_eckd_private *private = device->private;
        int fcx_in_css, fcx_in_gneq, fcx_in_features;
-       struct dasd_eckd_private *private;
+       int tpm, mdc;
 
        if (dasd_nofcx)
                return 0;
        /* is transport mode supported? */
-       private = (struct dasd_eckd_private *) device->private;
        fcx_in_css = css_general_characteristics.fcx;
        fcx_in_gneq = private->gneq->reserved2[7] & 0x04;
        fcx_in_features = private->features.feature[40] & 0x80;
@@ -1694,7 +1673,7 @@ static u32 get_fcx_max_data(struct dasd_device *device)
 static int
 dasd_eckd_check_characteristics(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        struct dasd_block *block;
        struct dasd_uid temp_uid;
        int rc, i;
@@ -1713,7 +1692,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
                dev_info(&device->cdev->dev,
                         "The DASD is not operating in multipath mode\n");
        }
-       private = (struct dasd_eckd_private *) device->private;
        if (!private) {
                private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
                if (!private) {
@@ -1722,7 +1700,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
                                 "failed\n");
                        return -ENOMEM;
                }
-               device->private = (void *) private;
+               device->private = private;
        } else {
                memset(private, 0, sizeof(*private));
        }
@@ -1837,10 +1815,9 @@ out_err1:
 
 static void dasd_eckd_uncheck_device(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        int i;
 
-       private = (struct dasd_eckd_private *) device->private;
        dasd_alias_disconnect_device_from_lcu(device);
        private->ned = NULL;
        private->sneq = NULL;
@@ -1863,7 +1840,7 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device)
 static struct dasd_ccw_req *
 dasd_eckd_analysis_ccw(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        struct eckd_count *count_data;
        struct LO_eckd_data *LO_data;
        struct dasd_ccw_req *cqr;
@@ -1871,8 +1848,6 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
        int cplength, datasize;
        int i;
 
-       private = (struct dasd_eckd_private *) device->private;
-
        cplength = 8;
        datasize = sizeof(struct DE_eckd_data) + 2*sizeof(struct LO_eckd_data);
        cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device);
@@ -1946,11 +1921,9 @@ static int dasd_eckd_analysis_evaluation(struct dasd_ccw_req *init_cqr)
 static void dasd_eckd_analysis_callback(struct dasd_ccw_req *init_cqr,
                                        void *data)
 {
-       struct dasd_eckd_private *private;
-       struct dasd_device *device;
+       struct dasd_device *device = init_cqr->startdev;
+       struct dasd_eckd_private *private = device->private;
 
-       device = init_cqr->startdev;
-       private = (struct dasd_eckd_private *) device->private;
        private->init_cqr_status = dasd_eckd_analysis_evaluation(init_cqr);
        dasd_sfree_request(init_cqr, device);
        dasd_kick_device(device);
@@ -1977,15 +1950,13 @@ static int dasd_eckd_start_analysis(struct dasd_block *block)
 
 static int dasd_eckd_end_analysis(struct dasd_block *block)
 {
-       struct dasd_device *device;
-       struct dasd_eckd_private *private;
+       struct dasd_device *device = block->base;
+       struct dasd_eckd_private *private = device->private;
        struct eckd_count *count_area;
        unsigned int sb, blk_per_trk;
        int status, i;
        struct dasd_ccw_req *init_cqr;
 
-       device = block->base;
-       private = (struct dasd_eckd_private *) device->private;
        status = private->init_cqr_status;
        private->init_cqr_status = -1;
        if (status == INIT_CQR_ERROR) {
@@ -2083,9 +2054,8 @@ raw:
 
 static int dasd_eckd_do_analysis(struct dasd_block *block)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = block->base->private;
 
-       private = (struct dasd_eckd_private *) block->base->private;
        if (private->init_cqr_status < 0)
                return dasd_eckd_start_analysis(block);
        else
@@ -2112,9 +2082,8 @@ static int dasd_eckd_basic_to_known(struct dasd_device *device)
 static int
 dasd_eckd_fill_geometry(struct dasd_block *block, struct hd_geometry *geo)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = block->base->private;
 
-       private = (struct dasd_eckd_private *) block->base->private;
        if (dasd_check_blocksize(block->bp_block) == 0) {
                geo->sectors = recs_per_track(&private->rdc_data,
                                              0, block->bp_block);
@@ -2151,8 +2120,8 @@ dasd_eckd_build_format(struct dasd_device *base,
        if (!startdev)
                startdev = base;
 
-       start_priv = (struct dasd_eckd_private *) startdev->private;
-       base_priv = (struct dasd_eckd_private *) base->private;
+       start_priv = startdev->private;
+       base_priv = base->private;
 
        rpt = recs_per_track(&base_priv->rdc_data, 0, fdata->blksize);
 
@@ -2349,14 +2318,14 @@ dasd_eckd_build_format(struct dasd_device *base,
                                 * when formatting CDL
                                 */
                                if ((intensity & 0x08) &&
-                                   fdata->start_unit == 0) {
+                                   address.cyl == 0 && address.head == 0) {
                                        if (i < 3) {
                                                ect->kl = 4;
                                                ect->dl = sizes_trk0[i] - 4;
                                        }
                                }
                                if ((intensity & 0x08) &&
-                                   fdata->start_unit == 1) {
+                                   address.cyl == 0 && address.head == 1) {
                                        ect->kl = 44;
                                        ect->dl = LABEL_SIZE - 44;
                                }
@@ -2386,23 +2355,24 @@ dasd_eckd_build_format(struct dasd_device *base,
        return fcp;
 }
 
-static int
-dasd_eckd_format_device(struct dasd_device *base,
-                       struct format_data_t *fdata,
-                       int enable_pav)
+/*
+ * Wrapper function to build a CCW request depending on input data
+ */
+static struct dasd_ccw_req *
+dasd_eckd_format_build_ccw_req(struct dasd_device *base,
+                              struct format_data_t *fdata, int enable_pav)
 {
-       struct dasd_ccw_req *cqr, *n;
-       struct dasd_block *block;
-       struct dasd_eckd_private *private;
-       struct list_head format_queue;
-       struct dasd_device *device;
-       int old_stop, format_step;
-       int step, rc = 0, sleep_rc;
+       return dasd_eckd_build_format(base, fdata, enable_pav);
+}
 
-       block = base->block;
-       private = (struct dasd_eckd_private *) base->private;
+/*
+ * Sanity checks on format_data
+ */
+static int dasd_eckd_format_sanity_checks(struct dasd_device *base,
+                                         struct format_data_t *fdata)
+{
+       struct dasd_eckd_private *private = base->private;
 
-       /* Sanity checks. */
        if (fdata->start_unit >=
            (private->real_cyl * private->rdc_data.trk_per_cyl)) {
                dev_warn(&base->cdev->dev,
@@ -2429,75 +2399,98 @@ dasd_eckd_format_device(struct dasd_device *base,
                         fdata->blksize);
                return -EINVAL;
        }
+       return 0;
+}
+
+/*
+ * This function will process format_data originally coming from an IOCTL
+ */
+static int dasd_eckd_format_process_data(struct dasd_device *base,
+                                        struct format_data_t *fdata,
+                                        int enable_pav)
+{
+       struct dasd_eckd_private *private = base->private;
+       struct dasd_ccw_req *cqr, *n;
+       struct list_head format_queue;
+       struct dasd_device *device;
+       int old_start, old_stop, format_step;
+       int step, retry;
+       int rc;
+
+       rc = dasd_eckd_format_sanity_checks(base, fdata);
+       if (rc)
+               return rc;
 
        INIT_LIST_HEAD(&format_queue);
 
+       old_start = fdata->start_unit;
        old_stop = fdata->stop_unit;
-       while (fdata->start_unit <= 1) {
-               fdata->stop_unit = fdata->start_unit;
-               cqr = dasd_eckd_build_format(base, fdata, enable_pav);
-               list_add(&cqr->blocklist, &format_queue);
-
-               fdata->stop_unit = old_stop;
-               fdata->start_unit++;
 
-               if (fdata->start_unit > fdata->stop_unit)
-                       goto sleep;
-       }
+       format_step = DASD_CQR_MAX_CCW / recs_per_track(&private->rdc_data, 0,
+                                                       fdata->blksize);
+       do {
+               retry = 0;
+               while (fdata->start_unit <= old_stop) {
+                       step = fdata->stop_unit - fdata->start_unit + 1;
+                       if (step > format_step) {
+                               fdata->stop_unit =
+                                       fdata->start_unit + format_step - 1;
+                       }
 
-retry:
-       format_step = 255 / recs_per_track(&private->rdc_data, 0,
-                                          fdata->blksize);
-       while (fdata->start_unit <= old_stop) {
-               step = fdata->stop_unit - fdata->start_unit + 1;
-               if (step > format_step)
-                       fdata->stop_unit = fdata->start_unit + format_step - 1;
+                       cqr = dasd_eckd_format_build_ccw_req(base, fdata,
+                                                            enable_pav);
+                       if (IS_ERR(cqr)) {
+                               rc = PTR_ERR(cqr);
+                               if (rc == -ENOMEM) {
+                                       if (list_empty(&format_queue))
+                                               goto out;
+                                       /*
+                                        * not enough memory available, start
+                                        * requests retry after first requests
+                                        * were finished
+                                        */
+                                       retry = 1;
+                                       break;
+                               }
+                               goto out_err;
+                       }
+                       list_add_tail(&cqr->blocklist, &format_queue);
 
-               cqr = dasd_eckd_build_format(base, fdata, enable_pav);
-               if (IS_ERR(cqr)) {
-                       if (PTR_ERR(cqr) == -ENOMEM) {
-                               /*
-                                * not enough memory available
-                                * go to out and start requests
-                                * retry after first requests were finished
-                                */
-                               fdata->stop_unit = old_stop;
-                               goto sleep;
-                       } else
-                               return PTR_ERR(cqr);
+                       fdata->start_unit = fdata->stop_unit + 1;
+                       fdata->stop_unit = old_stop;
                }
-               list_add(&cqr->blocklist, &format_queue);
 
-               fdata->start_unit = fdata->stop_unit + 1;
-               fdata->stop_unit = old_stop;
-       }
+               rc = dasd_sleep_on_queue(&format_queue);
 
-sleep:
-       sleep_rc = dasd_sleep_on_queue(&format_queue);
+out_err:
+               list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
+                       device = cqr->startdev;
+                       private = device->private;
+                       if (cqr->status == DASD_CQR_FAILED)
+                               rc = -EIO;
+                       list_del_init(&cqr->blocklist);
+                       dasd_sfree_request(cqr, device);
+                       private->count--;
+               }
 
-       list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
-               device = cqr->startdev;
-               private = (struct dasd_eckd_private *) device->private;
-               if (cqr->status == DASD_CQR_FAILED)
-                       rc = -EIO;
-               list_del_init(&cqr->blocklist);
-               dasd_sfree_request(cqr, device);
-               private->count--;
-       }
+               if (rc)
+                       goto out;
 
-       if (sleep_rc)
-               return sleep_rc;
+       } while (retry);
 
-       /*
-        * in case of ENOMEM we need to retry after
-        * first requests are finished
-        */
-       if (fdata->start_unit <= fdata->stop_unit)
-               goto retry;
+out:
+       fdata->start_unit = old_start;
+       fdata->stop_unit = old_stop;
 
        return rc;
 }
 
+static int dasd_eckd_format_device(struct dasd_device *base,
+                                  struct format_data_t *fdata, int enable_pav)
+{
+       return dasd_eckd_format_process_data(base, fdata, enable_pav);
+}
+
 static void dasd_eckd_handle_terminated_request(struct dasd_ccw_req *cqr)
 {
        if (cqr->retries < 0) {
@@ -2543,9 +2536,8 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
 {
        char mask;
        char *sense = NULL;
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
 
-       private = (struct dasd_eckd_private *) device->private;
        /* first of all check for state change pending interrupt */
        mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP;
        if ((scsw_dstat(&irb->scsw) & mask) == mask) {
@@ -2634,7 +2626,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
        struct dasd_device *basedev;
 
        basedev = block->base;
-       private = (struct dasd_eckd_private *) basedev->private;
+       private = basedev->private;
        if (rq_data_dir(req) == READ)
                cmd = DASD_ECKD_CCW_READ_MT;
        else if (rq_data_dir(req) == WRITE)
@@ -2990,8 +2982,8 @@ static int prepare_itcw(struct itcw *itcw,
 
 
        /* setup prefix data */
-       basepriv = (struct dasd_eckd_private *) basedev->private;
-       startpriv = (struct dasd_eckd_private *) startdev->private;
+       basepriv = basedev->private;
+       startpriv = startdev->private;
        dedata = &pfxdata.define_extent;
        lredata = &pfxdata.locate_record;
 
@@ -3278,7 +3270,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
        struct dasd_ccw_req *cqr;
 
        basedev = block->base;
-       private = (struct dasd_eckd_private *) basedev->private;
+       private = basedev->private;
 
        /* Calculate number of blocks/records per track. */
        blksize = block->bp_block;
@@ -3503,7 +3495,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req)
 
        if (!dasd_page_cache)
                goto out;
-       private = (struct dasd_eckd_private *) cqr->block->base->private;
+       private = cqr->block->base->private;
        blksize = cqr->block->bp_block;
        blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
        recid = blk_rq_pos(req) >> cqr->block->s2b_shift;
@@ -3587,7 +3579,7 @@ static struct dasd_ccw_req *dasd_eckd_build_alias_cp(struct dasd_device *base,
        startdev = dasd_alias_get_start_dev(base);
        if (!startdev)
                startdev = base;
-       private = (struct dasd_eckd_private *) startdev->private;
+       private = startdev->private;
        if (private->count >= DASD_ECKD_CHANQ_MAX_SIZE)
                return ERR_PTR(-EBUSY);
 
@@ -3610,7 +3602,7 @@ static int dasd_eckd_free_alias_cp(struct dasd_ccw_req *cqr,
        unsigned long flags;
 
        spin_lock_irqsave(get_ccwdev_lock(cqr->memdev->cdev), flags);
-       private = (struct dasd_eckd_private *) cqr->memdev->private;
+       private = cqr->memdev->private;
        private->count--;
        spin_unlock_irqrestore(get_ccwdev_lock(cqr->memdev->cdev), flags);
        return dasd_eckd_free_cp(cqr, req);
@@ -3620,15 +3612,14 @@ static int
 dasd_eckd_fill_info(struct dasd_device * device,
                    struct dasd_information2_t * info)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
 
-       private = (struct dasd_eckd_private *) device->private;
        info->label_block = 2;
        info->FBA_layout = private->uses_cdl ? 0 : 1;
        info->format = private->uses_cdl ? DASD_FORMAT_CDL : DASD_FORMAT_LDL;
-       info->characteristics_size = sizeof(struct dasd_eckd_characteristics);
+       info->characteristics_size = sizeof(private->rdc_data);
        memcpy(info->characteristics, &private->rdc_data,
-              sizeof(struct dasd_eckd_characteristics));
+              sizeof(private->rdc_data));
        info->confdata_size = min((unsigned long)private->conf_len,
                                  sizeof(info->configuration_data));
        memcpy(info->configuration_data, private->conf_data,
@@ -3941,8 +3932,7 @@ dasd_eckd_performance(struct dasd_device *device, void __user *argp)
 static int
 dasd_eckd_get_attrib(struct dasd_device *device, void __user *argp)
 {
-       struct dasd_eckd_private *private =
-               (struct dasd_eckd_private *)device->private;
+       struct dasd_eckd_private *private = device->private;
        struct attrib_data_t attrib = private->attrib;
        int rc;
 
@@ -3966,8 +3956,7 @@ dasd_eckd_get_attrib(struct dasd_device *device, void __user *argp)
 static int
 dasd_eckd_set_attrib(struct dasd_device *device, void __user *argp)
 {
-       struct dasd_eckd_private *private =
-               (struct dasd_eckd_private *)device->private;
+       struct dasd_eckd_private *private = device->private;
        struct attrib_data_t attrib;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -4430,15 +4419,13 @@ static int dasd_eckd_pm_freeze(struct dasd_device *device)
 
 static int dasd_eckd_restore_device(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        struct dasd_eckd_characteristics temp_rdc_data;
        int rc;
        struct dasd_uid temp_uid;
        unsigned long flags;
        unsigned long cqr_flags = 0;
 
-       private = (struct dasd_eckd_private *) device->private;
-
        /* Read Configuration Data */
        rc = dasd_eckd_read_conf(device);
        if (rc) {
@@ -4502,14 +4489,12 @@ out_err:
 
 static int dasd_eckd_reload_device(struct dasd_device *device)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        int rc, old_base;
        char print_uid[60];
        struct dasd_uid uid;
        unsigned long flags;
 
-       private = (struct dasd_eckd_private *) device->private;
-
        spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
        old_base = private->uid.base_unit_addr;
        spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
@@ -4556,12 +4541,10 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device,
 {
        struct dasd_rssd_messages *message_buf;
        struct dasd_psf_prssd_data *prssdp;
-       struct dasd_eckd_private *private;
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
        int rc;
 
-       private = (struct dasd_eckd_private *) device->private;
        cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
                                   (sizeof(struct dasd_psf_prssd_data) +
                                    sizeof(struct dasd_rssd_messages)),
@@ -4686,11 +4669,10 @@ static struct dasd_conf_data *dasd_eckd_get_ref_conf(struct dasd_device *device,
                                                     __u8 lpum,
                                                     struct dasd_cuir_message *cuir)
 {
-       struct dasd_eckd_private *private;
+       struct dasd_eckd_private *private = device->private;
        struct dasd_conf_data *conf_data;
        int path, pos;
 
-       private = (struct dasd_eckd_private *) device->private;
        if (cuir->record_selector == 0)
                goto out;
        for (path = 0x80, pos = 0; path; path >>= 1, pos++) {
@@ -4715,9 +4697,9 @@ out:
 static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
                                struct dasd_cuir_message *cuir)
 {
+       struct dasd_eckd_private *private = device->private;
        struct dasd_conf_data *ref_conf_data;
        unsigned long bitmask = 0, mask = 0;
-       struct dasd_eckd_private *private;
        struct dasd_conf_data *conf_data;
        unsigned int pos, path;
        char *ref_gneq, *gneq;
@@ -4730,7 +4712,6 @@ static int dasd_eckd_cuir_scope(struct dasd_device *device, __u8 lpum,
            !(cuir->neq_map[0] | cuir->neq_map[1] | cuir->neq_map[2]))
                return lpum;
 
-       private = (struct dasd_eckd_private *) device->private;
        /* get reference conf data */
        ref_conf_data = dasd_eckd_get_ref_conf(device, lpum, cuir);
        /* reference ned is determined by ned_map field */
@@ -4829,14 +4810,13 @@ static int dasd_eckd_cuir_quiesce(struct dasd_device *device, __u8 lpum,
                                  struct subchannel_id sch_id,
                                  struct dasd_cuir_message *cuir)
 {
+       struct dasd_eckd_private *private = device->private;
        struct alias_pav_group *pavgroup, *tempgroup;
-       struct dasd_eckd_private *private;
        struct dasd_device *dev, *n;
        unsigned long paths = 0;
        unsigned long flags;
        int tbcpm;
 
-       private = (struct dasd_eckd_private *) device->private;
        /* active devices */
        list_for_each_entry_safe(dev, n, &private->lcu->active_devices,
                                 alias_list) {
@@ -4892,13 +4872,12 @@ static int dasd_eckd_cuir_resume(struct dasd_device *device, __u8 lpum,
                                 struct subchannel_id sch_id,
                                 struct dasd_cuir_message *cuir)
 {
+       struct dasd_eckd_private *private = device->private;
        struct alias_pav_group *pavgroup, *tempgroup;
-       struct dasd_eckd_private *private;
        struct dasd_device *dev, *n;
        unsigned long paths = 0;
        int tbcpm;
 
-       private = (struct dasd_eckd_private *) device->private;
        /*
         * the path may have been added through a generic path event before
         * only trigger path verification if the path is not already in use
index c9262e78938bdf1154531394623dd4d8a3e14b19..d7b5b550364badfd896368d4e5a91bdfc3f1615d 100644 (file)
@@ -125,13 +125,11 @@ locate_record(struct ccw1 * ccw, struct LO_fba_data *data, int rw,
 static int
 dasd_fba_check_characteristics(struct dasd_device *device)
 {
-       struct dasd_block *block;
-       struct dasd_fba_private *private;
+       struct dasd_fba_private *private = device->private;
        struct ccw_device *cdev = device->cdev;
-       int rc;
-       int readonly;
+       struct dasd_block *block;
+       int readonly, rc;
 
-       private = (struct dasd_fba_private *) device->private;
        if (!private) {
                private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
                if (!private) {
@@ -140,7 +138,7 @@ dasd_fba_check_characteristics(struct dasd_device *device)
                                 "data failed\n");
                        return -ENOMEM;
                }
-               device->private = (void *) private;
+               device->private = private;
        } else {
                memset(private, 0, sizeof(*private));
        }
@@ -192,10 +190,9 @@ dasd_fba_check_characteristics(struct dasd_device *device)
 
 static int dasd_fba_do_analysis(struct dasd_block *block)
 {
-       struct dasd_fba_private *private;
+       struct dasd_fba_private *private = block->base->private;
        int sb, rc;
 
-       private = (struct dasd_fba_private *) block->base->private;
        rc = dasd_check_blocksize(private->rdc_data.blk_size);
        if (rc) {
                DBF_DEV_EVENT(DBF_WARNING, block->base, "unknown blocksize %d",
@@ -254,7 +251,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
                                              struct dasd_block *block,
                                              struct request *req)
 {
-       struct dasd_fba_private *private;
+       struct dasd_fba_private *private = block->base->private;
        unsigned long *idaws;
        struct LO_fba_data *LO_data;
        struct dasd_ccw_req *cqr;
@@ -267,7 +264,6 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
        unsigned int blksize, off;
        unsigned char cmd;
 
-       private = (struct dasd_fba_private *) block->base->private;
        if (rq_data_dir(req) == READ) {
                cmd = DASD_FBA_CCW_READ;
        } else if (rq_data_dir(req) == WRITE) {
@@ -379,7 +375,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
 static int
 dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req)
 {
-       struct dasd_fba_private *private;
+       struct dasd_fba_private *private = cqr->block->base->private;
        struct ccw1 *ccw;
        struct req_iterator iter;
        struct bio_vec bv;
@@ -389,7 +385,6 @@ dasd_fba_free_cp(struct dasd_ccw_req *cqr, struct request *req)
 
        if (!dasd_page_cache)
                goto out;
-       private = (struct dasd_fba_private *) cqr->block->base->private;
        blksize = cqr->block->bp_block;
        ccw = cqr->cpaddr;
        /* Skip over define extent & locate record. */
@@ -436,13 +431,14 @@ static int
 dasd_fba_fill_info(struct dasd_device * device,
                   struct dasd_information2_t * info)
 {
+       struct dasd_fba_private *private = device->private;
+
        info->label_block = 1;
        info->FBA_layout = 1;
        info->format = DASD_FORMAT_LDL;
-       info->characteristics_size = sizeof(struct dasd_fba_characteristics);
-       memcpy(info->characteristics,
-              &((struct dasd_fba_private *) device->private)->rdc_data,
-              sizeof (struct dasd_fba_characteristics));
+       info->characteristics_size = sizeof(private->rdc_data);
+       memcpy(info->characteristics, &private->rdc_data,
+              sizeof(private->rdc_data));
        info->confdata_size = 0;
        return 0;
 }
index ef1d9fb06cab28846734a0b90999802b722c674b..31d544a87ba95e1781245e73b5d14754a68a04df 100644 (file)
@@ -178,8 +178,8 @@ int dasd_gendisk_init(void)
        /* Register to static dasd major 94 */
        rc = register_blkdev(DASD_MAJOR, "dasd");
        if (rc != 0) {
-               pr_warning("Registering the device driver with major number "
-                          "%d failed\n", DASD_MAJOR);
+               pr_warn("Registering the device driver with major number %d failed\n",
+                       DASD_MAJOR);
                return rc;
        }
        return 0;
index 4aed5ed708363b0a30be9c1b20201c478f5a7377..8de29be32a56352fe3c09610f59752d850b646ad 100644 (file)
@@ -240,6 +240,13 @@ struct dasd_ccw_req {
 /* Signature for error recovery functions. */
 typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *);
 
+/*
+ * A single CQR can only contain a maximum of 255 CCWs. It is limited by
+ * the locate record and locate record extended count value which can only hold
+ * 1 Byte max.
+ */
+#define DASD_CQR_MAX_CCW 255
+
 /*
  * Unique identifier for dasd device.
  */
@@ -438,7 +445,7 @@ struct dasd_device {
        /* Device discipline stuff. */
        struct dasd_discipline *discipline;
        struct dasd_discipline *base_discipline;
-       char *private;
+       void *private;
        struct dasd_path path_data;
 
        /* Device state and target state. */
index 02837d0ad942e8258157df3095e1568f5a52ea90..90f30cc31561d359b29f5557ac88a63518c0b9e6 100644 (file)
@@ -203,9 +203,7 @@ static int
 dasd_format(struct dasd_block *block, struct format_data_t *fdata)
 {
        struct dasd_device *base;
-       int enable_pav = 1;
-       int rc, retries;
-       int start, stop;
+       int rc;
 
        base = block->base;
        if (base->discipline->format_device == NULL)
@@ -233,30 +231,11 @@ dasd_format(struct dasd_block *block, struct format_data_t *fdata)
                bdput(bdev);
        }
 
-       retries = 255;
-       /* backup start- and endtrack for retries */
-       start = fdata->start_unit;
-       stop = fdata->stop_unit;
-       do {
-               rc = base->discipline->format_device(base, fdata, enable_pav);
-               if (rc) {
-                       if (rc == -EAGAIN) {
-                               retries--;
-                               /* disable PAV in case of errors */
-                               enable_pav = 0;
-                               fdata->start_unit = start;
-                               fdata->stop_unit = stop;
-                       } else
-                               return rc;
-               } else
-                       /* success */
-                       break;
-       } while (retries);
-
-       if (!retries)
-               return -EIO;
-       else
-               return 0;
+       rc = base->discipline->format_device(base, fdata, 1);
+       if (rc == -EAGAIN)
+               rc = base->discipline->format_device(base, fdata, 0);
+
+       return rc;
 }
 
 /*
@@ -286,9 +265,8 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
                return -EFAULT;
        }
        if (bdev != bdev->bd_contains) {
-               pr_warning("%s: The specified DASD is a partition and cannot "
-                          "be formatted\n",
-                          dev_name(&base->cdev->dev));
+               pr_warn("%s: The specified DASD is a partition and cannot be formatted\n",
+                       dev_name(&base->cdev->dev));
                dasd_put_device(base);
                return -EINVAL;
        }
index aa7bb2d1da81154940b7755c69f6744fb710cb15..bad7a196bf8401e053db9d7499058953067e9c5a 100644 (file)
@@ -322,13 +322,12 @@ static ssize_t dasd_stats_proc_write(struct file *file,
        return user_len;
 out_parse_error:
        rc = -EINVAL;
-       pr_warning("%s is not a supported value for /proc/dasd/statistics\n",
-               str);
+       pr_warn("%s is not a supported value for /proc/dasd/statistics\n", str);
 out_error:
        vfree(buffer);
        return rc;
 #else
-       pr_warning("/proc/dasd/statistics: is not activated in this kernel\n");
+       pr_warn("/proc/dasd/statistics: is not activated in this kernel\n");
        return user_len;
 #endif                         /* CONFIG_DASD_PROFILE */
 }
index ce7b7018174051998663377b0168aa221cc33185..1bce9cf51b1e917632fe97bcbf636293e5442adc 100644 (file)
@@ -738,15 +738,15 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch
        dev_info = dcssblk_get_device_by_name(local_buf);
        if (dev_info == NULL) {
                up_write(&dcssblk_devices_sem);
-               pr_warning("Device %s cannot be removed because it is not a "
-                          "known device\n", local_buf);
+               pr_warn("Device %s cannot be removed because it is not a known device\n",
+                       local_buf);
                rc = -ENODEV;
                goto out_buf;
        }
        if (atomic_read(&dev_info->use_count) != 0) {
                up_write(&dcssblk_devices_sem);
-               pr_warning("Device %s cannot be removed while it is in "
-                          "use\n", local_buf);
+               pr_warn("Device %s cannot be removed while it is in use\n",
+                       local_buf);
                rc = -EBUSY;
                goto out_buf;
        }
@@ -850,9 +850,8 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)
                case SEG_TYPE_SC:
                        /* cannot write to these segments */
                        if (bio_data_dir(bio) == WRITE) {
-                               pr_warning("Writing to %s failed because it "
-                                          "is a read-only device\n",
-                                          dev_name(&dev_info->dev));
+                               pr_warn("Writing to %s failed because it is a read-only device\n",
+                                       dev_name(&dev_info->dev));
                                goto fail;
                        }
                }
index fc94bfdceb9537fa36ea5a83ef25844b57582ff8..ebdeaa53182de968ec3216318b2504c5ecdee1d2 100644 (file)
@@ -257,7 +257,7 @@ static void mon_iucv_message_pending(struct iucv_path *path,
        memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
               msg, sizeof(*msg));
        if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
-               pr_warning("The read queue for monitor data is full\n");
+               pr_warn("The read queue for monitor data is full\n");
                monpriv->msg_array[monpriv->write_index]->msglim_reached = 1;
        }
        monpriv->write_index = (monpriv->write_index + 1) % MON_MSGLIM;
@@ -342,8 +342,8 @@ static int mon_close(struct inode *inode, struct file *filp)
        if (monpriv->path) {
                rc = iucv_path_sever(monpriv->path, user_data_sever);
                if (rc)
-                       pr_warning("Disconnecting the z/VM *MONITOR system "
-                                  "service failed with rc=%i\n", rc);
+                       pr_warn("Disconnecting the z/VM *MONITOR system service failed with rc=%i\n",
+                               rc);
                iucv_path_free(monpriv->path);
        }
 
@@ -469,8 +469,8 @@ static int monreader_freeze(struct device *dev)
        if (monpriv->path) {
                rc = iucv_path_sever(monpriv->path, user_data_sever);
                if (rc)
-                       pr_warning("Disconnecting the z/VM *MONITOR system "
-                                  "service failed with rc=%i\n", rc);
+                       pr_warn("Disconnecting the z/VM *MONITOR system service failed with rc=%i\n",
+                               rc);
                iucv_path_free(monpriv->path);
        }
        atomic_set(&monpriv->iucv_severed, 0);
index 806239c2cf2f8cf0f50affabdf9dea215aab8e9b..d3947ea3e351316fb0fa37751c96709f3193f150 100644 (file)
@@ -67,8 +67,8 @@ int sclp_sync_request_timeout(sclp_cmdw_t cmd, void *sccb, int timeout)
 
        /* Check response. */
        if (request->status != SCLP_REQ_DONE) {
-               pr_warning("sync request failed (cmd=0x%08x, "
-                          "status=0x%02x)\n", cmd, request->status);
+               pr_warn("sync request failed (cmd=0x%08x, status=0x%02x)\n",
+                       cmd, request->status);
                rc = -EIO;
        }
 out:
@@ -122,8 +122,8 @@ int sclp_get_core_info(struct sclp_core_info *info)
        if (rc)
                goto out;
        if (sccb->header.response_code != 0x0010) {
-               pr_warning("readcpuinfo failed (response=0x%04x)\n",
-                          sccb->header.response_code);
+               pr_warn("readcpuinfo failed (response=0x%04x)\n",
+                       sccb->header.response_code);
                rc = -EIO;
                goto out;
        }
@@ -160,9 +160,8 @@ static int do_core_configure(sclp_cmdw_t cmd)
        case 0x0120:
                break;
        default:
-               pr_warning("configure cpu failed (cmd=0x%08x, "
-                          "response=0x%04x)\n", cmd,
-                          sccb->header.response_code);
+               pr_warn("configure cpu failed (cmd=0x%08x, response=0x%04x)\n",
+                       cmd, sccb->header.response_code);
                rc = -EIO;
                break;
        }
@@ -230,9 +229,8 @@ static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)
        case 0x0120:
                break;
        default:
-               pr_warning("assign storage failed (cmd=0x%08x, "
-                          "response=0x%04x, rn=0x%04x)\n", cmd,
-                          sccb->header.response_code, rn);
+               pr_warn("assign storage failed (cmd=0x%08x, response=0x%04x, rn=0x%04x)\n",
+                       cmd, sccb->header.response_code, rn);
                rc = -EIO;
                break;
        }
@@ -675,9 +673,8 @@ static int do_chp_configure(sclp_cmdw_t cmd)
        case 0x0450:
                break;
        default:
-               pr_warning("configure channel-path failed "
-                          "(cmd=0x%08x, response=0x%04x)\n", cmd,
-                          sccb->header.response_code);
+               pr_warn("configure channel-path failed (cmd=0x%08x, response=0x%04x)\n",
+                       cmd, sccb->header.response_code);
                rc = -EIO;
                break;
        }
@@ -744,8 +741,8 @@ int sclp_chp_read_info(struct sclp_chp_info *info)
        if (rc)
                goto out;
        if (sccb->header.response_code != 0x0010) {
-               pr_warning("read channel-path info failed "
-                          "(response=0x%04x)\n", sccb->header.response_code);
+               pr_warn("read channel-path info failed (response=0x%04x)\n",
+                       sccb->header.response_code);
                rc = -EIO;
                goto out;
        }
index 2acea809e2accf3f6c6078dd7acec6ed5e3cc256..f344e5bd2d9f047ec28863138b301288480f8bb6 100644 (file)
@@ -154,16 +154,14 @@ static int cpi_req(void)
        wait_for_completion(&completion);
 
        if (req->status != SCLP_REQ_DONE) {
-               pr_warning("request failed (status=0x%02x)\n",
-                          req->status);
+               pr_warn("request failed (status=0x%02x)\n", req->status);
                rc = -EIO;
                goto out_free_req;
        }
 
        response = ((struct cpi_sccb *) req->sccb)->header.response_code;
        if (response != 0x0020) {
-               pr_warning("request failed with response code 0x%x\n",
-                          response);
+               pr_warn("request failed with response code 0x%x\n", response);
                rc = -EIO;
        }
 
index f3b5123faf0822e07d9771fb1c922b5fdfe101b8..3c379da2eef863387c19ce8b706a06522ebc97af 100644 (file)
@@ -699,8 +699,8 @@ tape_generic_remove(struct ccw_device *cdev)
                         */
                        DBF_EVENT(3, "(%08x): Drive in use vanished!\n",
                                device->cdev_id);
-                       pr_warning("%s: A tape unit was detached while in "
-                                  "use\n", dev_name(&device->cdev->dev));
+                       pr_warn("%s: A tape unit was detached while in use\n",
+                               dev_name(&device->cdev->dev));
                        tape_state_set(device, TS_NOT_OPER);
                        __tape_discard_requests(device);
                        spin_unlock_irq(get_ccwdev_lock(device->cdev));
index 799c1524c779f282387b3ed79c5363f95b1fbd98..e883063c72581b61c8d4e8fd0db287476a37e101 100644 (file)
@@ -343,8 +343,7 @@ static int vmlogrdr_open (struct inode *inode, struct file *filp)
        if (logptr->autorecording) {
                ret = vmlogrdr_recording(logptr,1,logptr->autopurge);
                if (ret)
-                       pr_warning("vmlogrdr: failed to start "
-                                  "recording automatically\n");
+                       pr_warn("vmlogrdr: failed to start recording automatically\n");
        }
 
        /* create connection to the system service */
@@ -396,8 +395,7 @@ static int vmlogrdr_release (struct inode *inode, struct file *filp)
        if (logptr->autorecording) {
                ret = vmlogrdr_recording(logptr,0,logptr->autopurge);
                if (ret)
-                       pr_warning("vmlogrdr: failed to stop "
-                                  "recording automatically\n");
+                       pr_warn("vmlogrdr: failed to stop recording automatically\n");
        }
        logptr->dev_in_use = 0;
 
index 20314aad7ab7d1c30eaadedd143a66e95b363bb6..9082476b51db9122a8a41186e7e40e1a97172368 100644 (file)
@@ -51,9 +51,8 @@ static int blacklist_range(range_action action, unsigned int from_ssid,
 {
        if ((from_ssid > to_ssid) || ((from_ssid == to_ssid) && (from > to))) {
                if (msgtrigger)
-                       pr_warning("0.%x.%04x to 0.%x.%04x is not a valid "
-                                  "range for cio_ignore\n", from_ssid, from,
-                                  to_ssid, to);
+                       pr_warn("0.%x.%04x to 0.%x.%04x is not a valid range for cio_ignore\n",
+                               from_ssid, from, to_ssid, to);
 
                return 1;
        }
@@ -140,8 +139,8 @@ static int parse_busid(char *str, unsigned int *cssid, unsigned int *ssid,
        rc = 0;
 out:
        if (rc && msgtrigger)
-               pr_warning("%s is not a valid device for the cio_ignore "
-                          "kernel parameter\n", str);
+               pr_warn("%s is not a valid device for the cio_ignore kernel parameter\n",
+                       str);
 
        return rc;
 }
index 79f59915f71ba5795928fb5b8caad9b214e8c05c..2782100b2c079c739f9bba8cbc4341e6ea1156ae 100644 (file)
@@ -333,13 +333,12 @@ void ccw_request_timeout(struct ccw_device *cdev)
 
        for (chp = 0; chp < 8; chp++) {
                if ((0x80 >> chp) & sch->schib.pmcw.lpum)
-                       pr_warning("%s: No interrupt was received within %lus "
-                                  "(CS=%02x, DS=%02x, CHPID=%x.%02x)\n",
-                                  dev_name(&cdev->dev), req->timeout / HZ,
-                                  scsw_cstat(&sch->schib.scsw),
-                                  scsw_dstat(&sch->schib.scsw),
-                                  sch->schid.cssid,
-                                  sch->schib.pmcw.chpid[chp]);
+                       pr_warn("%s: No interrupt was received within %lus (CS=%02x, DS=%02x, CHPID=%x.%02x)\n",
+                               dev_name(&cdev->dev), req->timeout / HZ,
+                               scsw_cstat(&sch->schib.scsw),
+                               scsw_dstat(&sch->schib.scsw),
+                               sch->schid.cssid,
+                               sch->schib.pmcw.chpid[chp]);
        }
 
        if (!ccwreq_next_path(cdev)) {
index 39a8ae54e9c1df044e9c63ab6103f1944ce24665..de6fccc1312485dd4b582c17ca93c0e8cac322f1 100644 (file)
@@ -656,7 +656,7 @@ struct subchannel *cio_probe_console(void)
 
        sch_no = cio_get_console_sch_no();
        if (sch_no == -1) {
-               pr_warning("No CCW console was found\n");
+               pr_warn("No CCW console was found\n");
                return ERR_PTR(-ENODEV);
        }
        init_subchannel_id(&schid);
index 6aae6841280214f2db3a3aac0461f14f9050cf04..7ada078ffdd04b09c81cc45ddfab4057f397158d 100644 (file)
@@ -364,11 +364,11 @@ int ccw_device_set_offline(struct ccw_device *cdev)
                   cdev->private->state == DEV_STATE_DISCONNECTED));
        /* Inform the user if set offline failed. */
        if (cdev->private->state == DEV_STATE_BOXED) {
-               pr_warning("%s: The device entered boxed state while "
-                          "being set offline\n", dev_name(&cdev->dev));
+               pr_warn("%s: The device entered boxed state while being set offline\n",
+                       dev_name(&cdev->dev));
        } else if (cdev->private->state == DEV_STATE_NOT_OPER) {
-               pr_warning("%s: The device stopped operating while "
-                          "being set offline\n", dev_name(&cdev->dev));
+               pr_warn("%s: The device stopped operating while being set offline\n",
+                       dev_name(&cdev->dev));
        }
        /* Give up reference from ccw_device_set_online(). */
        put_device(&cdev->dev);
@@ -429,13 +429,11 @@ int ccw_device_set_online(struct ccw_device *cdev)
                spin_unlock_irq(cdev->ccwlock);
                /* Inform the user that set online failed. */
                if (cdev->private->state == DEV_STATE_BOXED) {
-                       pr_warning("%s: Setting the device online failed "
-                                  "because it is boxed\n",
-                                  dev_name(&cdev->dev));
+                       pr_warn("%s: Setting the device online failed because it is boxed\n",
+                               dev_name(&cdev->dev));
                } else if (cdev->private->state == DEV_STATE_NOT_OPER) {
-                       pr_warning("%s: Setting the device online failed "
-                                  "because it is not operational\n",
-                                  dev_name(&cdev->dev));
+                       pr_warn("%s: Setting the device online failed because it is not operational\n",
+                               dev_name(&cdev->dev));
                }
                /* Give up online reference since onlining failed. */
                put_device(&cdev->dev);
@@ -619,9 +617,8 @@ initiate_logging(struct device *dev, struct device_attribute *attr,
 
        rc = chsc_siosl(sch->schid);
        if (rc < 0) {
-               pr_warning("Logging for subchannel 0.%x.%04x failed with "
-                          "errno=%d\n",
-                          sch->schid.ssid, sch->schid.sch_no, rc);
+               pr_warn("Logging for subchannel 0.%x.%04x failed with errno=%d\n",
+                       sch->schid.ssid, sch->schid.sch_no, rc);
                return rc;
        }
        pr_notice("Logging for subchannel 0.%x.%04x was triggered\n",
index 2f5b518b0e788c80761553f5b2e77762f06bfb26..251db0a02e73c81c275594d0b72b091ced13137b 100644 (file)
@@ -1761,8 +1761,8 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd)
                        lcs_schedule_recovery(card);
                        break;
                case LCS_CMD_STOPLAN:
-                       pr_warning("Stoplan for %s initiated by LGW.\n",
-                                  card->dev->name);
+                       pr_warn("Stoplan for %s initiated by LGW\n",
+                               card->dev->name);
                        if (card->dev)
                                netif_carrier_off(card->dev);
                        break;
index 7c8c68c26540fdc3e58c8a8a32a17dd924af6db9..ac544330daeb7cffaccc37306f041deffd1475bb 100644 (file)
@@ -3624,7 +3624,7 @@ static int qeth_l3_register_notifiers(void)
                return rc;
        }
 #else
-       pr_warning("There is no IPv6 support for the layer 3 discipline\n");
+       pr_warn("There is no IPv6 support for the layer 3 discipline\n");
 #endif
        return 0;
 }
index 680bf6f0ce767143cdaf40528333f0cf8c4d945c..8f0ea97cf31f688c6548bb627fe5067d48a9e23b 100644 (file)
@@ -166,6 +166,7 @@ static struct attribute_group iscsi_boot_target_attr_group = {
 iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX);
 iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS);
 iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR);
+iscsi_boot_rd_attr(eth_prefix, prefix-len, ISCSI_BOOT_ETH_PREFIX_LEN);
 iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK);
 iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN);
 iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY);
@@ -181,6 +182,7 @@ static struct attribute *ethernet_attrs[] = {
        &iscsi_boot_attr_eth_index.attr,
        &iscsi_boot_attr_eth_flags.attr,
        &iscsi_boot_attr_eth_ip.attr,
+       &iscsi_boot_attr_eth_prefix.attr,
        &iscsi_boot_attr_eth_subnet.attr,
        &iscsi_boot_attr_eth_origin.attr,
        &iscsi_boot_attr_eth_gateway.attr,
@@ -208,6 +210,9 @@ static umode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj,
        else if (attr ==  &iscsi_boot_attr_eth_ip.attr)
                return boot_kobj->is_visible(boot_kobj->data,
                                             ISCSI_BOOT_ETH_IP_ADDR);
+       else if (attr ==  &iscsi_boot_attr_eth_prefix.attr)
+               return boot_kobj->is_visible(boot_kobj->data,
+                                            ISCSI_BOOT_ETH_PREFIX_LEN);
        else if (attr ==  &iscsi_boot_attr_eth_subnet.attr)
                return boot_kobj->is_visible(boot_kobj->data,
                                             ISCSI_BOOT_ETH_SUBNET_MASK);
index 1412266314292dfa59bf473cf2ed3fdb2edebe65..a6682c508c4cbb800a19fd8b010a551f404d55b3 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #include <asm/macio.h>
 
 #include <scsi/scsi.h>
index 555367f002282b238f8da84ab20100526ba7b1c1..1753e42826dd99bf7d69e1ea83f54a9b5ba34309 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
+#include <linux/pci.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -38,7 +39,6 @@
 #include <asm/processor.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
 #include <asm/macio.h>
 
 #include <scsi/scsi.h>
index 91a003011acfacb277e892b47c99771ceae80ffa..a9bac3bf20de14e541a22608fcb1542cad0f6d5f 100644 (file)
@@ -34,7 +34,7 @@ static struct pm_clk_notifier_block platform_bus_notifier = {
 
 static int __init sh_pm_runtime_init(void)
 {
-       if (IS_ENABLED(CONFIG_ARCH_SHMOBILE)) {
+       if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_ARCH_SHMOBILE)) {
                if (!of_find_compatible_node(NULL, NULL,
                                             "renesas,cpg-mstp-clocks"))
                        return 0;
index 2d9e7f3d56115aeaddea8eb250008dba7729d98e..bb1fb771213401a8cbf67b98011f464409ecb699 100644 (file)
@@ -66,7 +66,7 @@ int superhyway_add_device(unsigned long base, struct superhyway_device *sdev,
        superhyway_read_vcr(dev, base, &dev->vcr);
 
        if (!dev->resource) {
-               dev->resource = kmalloc(sizeof(struct resource), GFP_KERNEL);
+               dev->resource = kzalloc(sizeof(struct resource), GFP_KERNEL);
                if (!dev->resource) {
                        kfree(dev);
                        return -ENOMEM;
index 77064160dd762c26f6c1fd184b252b24360163e3..9d8c84bb15446a75153d64f94a5900ab165193ac 100644 (file)
@@ -75,11 +75,26 @@ config SPI_ATMEL
          This selects a driver for the Atmel SPI Controller, present on
          many AT32 (AVR32) and AT91 (ARM) chips.
 
+config SPI_AU1550
+       tristate "Au1550/Au1200/Au1300 SPI Controller"
+       depends on MIPS_ALCHEMY
+       select SPI_BITBANG
+       help
+         If you say yes to this option, support will be included for the
+         PSC SPI controller found on Au1550, Au1200 and Au1300 series.
+
+config SPI_AXI_SPI_ENGINE
+       tristate "Analog Devices AXI SPI Engine controller"
+       depends on HAS_IOMEM
+       help
+         This enables support for the Analog Devices AXI SPI Engine SPI controller.
+         It is part of the SPI Engine framework that is used in some Analog Devices
+         reference designs for FPGAs.
+
 config SPI_BCM2835
        tristate "BCM2835 SPI controller"
        depends on GPIOLIB
        depends on ARCH_BCM2835 || COMPILE_TEST
-       depends on GPIOLIB
        help
          This selects a driver for the Broadcom BCM2835 SPI master.
 
@@ -90,8 +105,7 @@ config SPI_BCM2835
 
 config SPI_BCM2835AUX
        tristate "BCM2835 SPI auxiliary controller"
-       depends on ARCH_BCM2835 || COMPILE_TEST
-       depends on GPIOLIB
+       depends on (ARCH_BCM2835 && GPIOLIB) || COMPILE_TEST
        help
          This selects a driver for the Broadcom BCM2835 SPI aux master.
 
@@ -118,14 +132,6 @@ config SPI_BFIN_SPORT
        help
          Enable support for a SPI bus via the Blackfin SPORT peripheral.
 
-config SPI_AU1550
-       tristate "Au1550/Au1200/Au1300 SPI Controller"
-       depends on MIPS_ALCHEMY
-       select SPI_BITBANG
-       help
-         If you say yes to this option, support will be included for the
-         PSC SPI controller found on Au1550, Au1200 and Au1300 series.
-
 config SPI_BCM53XX
        tristate "Broadcom BCM53xx SPI controller"
        depends on ARCH_BCM_5301X
@@ -197,6 +203,23 @@ config SPI_DAVINCI
        help
          SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules.
 
+config SPI_DESIGNWARE
+       tristate "DesignWare SPI controller core support"
+       help
+         general driver for SPI controller core from DesignWare
+
+config SPI_DW_PCI
+       tristate "PCI interface driver for DW SPI core"
+       depends on SPI_DESIGNWARE && PCI
+
+config SPI_DW_MID_DMA
+       bool "DMA support for DW SPI controller on Intel MID platform"
+       depends on SPI_DW_PCI && DW_DMAC_PCI
+
+config SPI_DW_MMIO
+       tristate "Memory-mapped io interface driver for DW SPI core"
+       depends on SPI_DESIGNWARE
+
 config SPI_DLN2
        tristate "Diolan DLN-2 USB SPI adapter"
        depends on MFD_DLN2
@@ -271,6 +294,16 @@ config SPI_LM70_LLP
          which interfaces to an LM70 temperature sensor using
          a parallel port.
 
+config SPI_LP8841_RTC
+       tristate "ICP DAS LP-8841 SPI Controller for RTC"
+       depends on MACH_PXA27X_DT || COMPILE_TEST
+       help
+         This driver provides an SPI master device to drive Maxim
+         DS-1302 real time clock.
+
+         Say N here unless you plan to run the kernel on an ICP DAS
+         LP-8x4x industrial computer.
+
 config SPI_MPC52xx
        tristate "Freescale MPC52xx SPI (non-PSC) controller support"
        depends on PPC_MPC52xx
@@ -346,6 +379,13 @@ config SPI_MT65XX
          say Y or M here.If you are not sure, say N.
          SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
 
+config SPI_NUC900
+       tristate "Nuvoton NUC900 series SPI"
+       depends on ARCH_W90X900
+       select SPI_BITBANG
+       help
+         SPI driver for Nuvoton NUC900 series ARM SoCs
+
 config SPI_OC_TINY
        tristate "OpenCores tiny SPI"
        depends on GPIOLIB || COMPILE_TEST
@@ -415,10 +455,6 @@ config SPI_PPC4xx
        help
          This selects a driver for the PPC4xx SPI Controller.
 
-config SPI_PXA2XX_DMA
-       def_bool y
-       depends on SPI_PXA2XX
-
 config SPI_PXA2XX
        tristate "PXA2xx SSP SPI master"
        depends on (ARCH_PXA || PCI || ACPI)
@@ -451,7 +487,7 @@ config SPI_RB4XX
 
 config SPI_RSPI
        tristate "Renesas RSPI/QSPI controller"
-       depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
+       depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
        help
          SPI driver for Renesas RSPI and QSPI blocks.
 
@@ -501,7 +537,7 @@ config SPI_SC18IS602
 config SPI_SH_MSIOF
        tristate "SuperH MSIOF SPI controller"
        depends on HAVE_CLK && HAS_DMA
-       depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
+       depends on SUPERH || ARCH_RENESAS || COMPILE_TEST
        help
          SPI driver for SuperH and SH Mobile MSIOF blocks.
 
@@ -520,7 +556,7 @@ config SPI_SH_SCI
 
 config SPI_SH_HSPI
        tristate "SuperH HSPI controller"
-       depends on ARCH_SHMOBILE || COMPILE_TEST
+       depends on ARCH_RENESAS || COMPILE_TEST
        help
          SPI driver for SuperH HSPI blocks.
 
@@ -647,34 +683,10 @@ config SPI_ZYNQMP_GQSPI
        help
          Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC.
 
-config SPI_NUC900
-       tristate "Nuvoton NUC900 series SPI"
-       depends on ARCH_W90X900
-       select SPI_BITBANG
-       help
-         SPI driver for Nuvoton NUC900 series ARM SoCs
-
 #
 # Add new SPI master controllers in alphabetical order above this line
 #
 
-config SPI_DESIGNWARE
-       tristate "DesignWare SPI controller core support"
-       help
-         general driver for SPI controller core from DesignWare
-
-config SPI_DW_PCI
-       tristate "PCI interface driver for DW SPI core"
-       depends on SPI_DESIGNWARE && PCI
-
-config SPI_DW_MID_DMA
-       bool "DMA support for DW SPI controller on Intel MID platform"
-       depends on SPI_DW_PCI && DW_DMAC_PCI
-
-config SPI_DW_MMIO
-       tristate "Memory-mapped io interface driver for DW SPI core"
-       depends on SPI_DESIGNWARE
-
 #
 # There are lots of SPI device types, with sensors and memory
 # being probably the most widely used ones.
index 8991ffce6e12d66682dcbbbcdbecf86f9f08dc3c..fbb255c5a608d270ccdb10f1d7ea8f2bd3e24c45 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ALTERA)              += spi-altera.o
 obj-$(CONFIG_SPI_ATMEL)                        += spi-atmel.o
 obj-$(CONFIG_SPI_ATH79)                        += spi-ath79.o
 obj-$(CONFIG_SPI_AU1550)               += spi-au1550.o
+obj-$(CONFIG_SPI_AXI_SPI_ENGINE)       += spi-axi-spi-engine.o
 obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
 obj-$(CONFIG_SPI_BCM2835AUX)           += spi-bcm2835aux.o
 obj-$(CONFIG_SPI_BCM53XX)              += spi-bcm53xx.o
@@ -46,6 +47,7 @@ obj-$(CONFIG_SPI_GPIO)                        += spi-gpio.o
 obj-$(CONFIG_SPI_IMG_SPFI)             += spi-img-spfi.o
 obj-$(CONFIG_SPI_IMX)                  += spi-imx.o
 obj-$(CONFIG_SPI_LM70_LLP)             += spi-lm70llp.o
+obj-$(CONFIG_SPI_LP8841_RTC)           += spi-lp8841-rtc.o
 obj-$(CONFIG_SPI_MESON_SPIFC)          += spi-meson-spifc.o
 obj-$(CONFIG_SPI_MPC512x_PSC)          += spi-mpc512x-psc.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)          += spi-mpc52xx-psc.o
@@ -62,8 +64,7 @@ obj-$(CONFIG_SPI_TI_QSPI)             += spi-ti-qspi.o
 obj-$(CONFIG_SPI_ORION)                        += spi-orion.o
 obj-$(CONFIG_SPI_PL022)                        += spi-pl022.o
 obj-$(CONFIG_SPI_PPC4xx)               += spi-ppc4xx.o
-spi-pxa2xx-platform-objs               := spi-pxa2xx.o
-spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA)   += spi-pxa2xx-dma.o
+spi-pxa2xx-platform-objs               := spi-pxa2xx.o spi-pxa2xx-dma.o
 obj-$(CONFIG_SPI_PXA2XX)               += spi-pxa2xx-platform.o
 obj-$(CONFIG_SPI_PXA2XX_PCI)           += spi-pxa2xx-pci.o
 obj-$(CONFIG_SPI_QUP)                  += spi-qup.o
diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c
new file mode 100644 (file)
index 0000000..c968ab2
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ * SPI-Engine SPI controller driver
+ * Copyright 2015 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#define SPI_ENGINE_VERSION_MAJOR(x)    ((x >> 16) & 0xff)
+#define SPI_ENGINE_VERSION_MINOR(x)    ((x >> 8) & 0xff)
+#define SPI_ENGINE_VERSION_PATCH(x)    (x & 0xff)
+
+#define SPI_ENGINE_REG_VERSION                 0x00
+
+#define SPI_ENGINE_REG_RESET                   0x40
+
+#define SPI_ENGINE_REG_INT_ENABLE              0x80
+#define SPI_ENGINE_REG_INT_PENDING             0x84
+#define SPI_ENGINE_REG_INT_SOURCE              0x88
+
+#define SPI_ENGINE_REG_SYNC_ID                 0xc0
+
+#define SPI_ENGINE_REG_CMD_FIFO_ROOM           0xd0
+#define SPI_ENGINE_REG_SDO_FIFO_ROOM           0xd4
+#define SPI_ENGINE_REG_SDI_FIFO_LEVEL          0xd8
+
+#define SPI_ENGINE_REG_CMD_FIFO                        0xe0
+#define SPI_ENGINE_REG_SDO_DATA_FIFO           0xe4
+#define SPI_ENGINE_REG_SDI_DATA_FIFO           0xe8
+#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK      0xec
+
+#define SPI_ENGINE_INT_CMD_ALMOST_EMPTY                BIT(0)
+#define SPI_ENGINE_INT_SDO_ALMOST_EMPTY                BIT(1)
+#define SPI_ENGINE_INT_SDI_ALMOST_FULL         BIT(2)
+#define SPI_ENGINE_INT_SYNC                    BIT(3)
+
+#define SPI_ENGINE_CONFIG_CPHA                 BIT(0)
+#define SPI_ENGINE_CONFIG_CPOL                 BIT(1)
+#define SPI_ENGINE_CONFIG_3WIRE                        BIT(2)
+
+#define SPI_ENGINE_INST_TRANSFER               0x0
+#define SPI_ENGINE_INST_ASSERT                 0x1
+#define SPI_ENGINE_INST_WRITE                  0x2
+#define SPI_ENGINE_INST_MISC                   0x3
+
+#define SPI_ENGINE_CMD_REG_CLK_DIV             0x0
+#define SPI_ENGINE_CMD_REG_CONFIG              0x1
+
+#define SPI_ENGINE_MISC_SYNC                   0x0
+#define SPI_ENGINE_MISC_SLEEP                  0x1
+
+#define SPI_ENGINE_TRANSFER_WRITE              0x1
+#define SPI_ENGINE_TRANSFER_READ               0x2
+
+#define SPI_ENGINE_CMD(inst, arg1, arg2) \
+       (((inst) << 12) | ((arg1) << 8) | (arg2))
+
+#define SPI_ENGINE_CMD_TRANSFER(flags, n) \
+       SPI_ENGINE_CMD(SPI_ENGINE_INST_TRANSFER, (flags), (n))
+#define SPI_ENGINE_CMD_ASSERT(delay, cs) \
+       SPI_ENGINE_CMD(SPI_ENGINE_INST_ASSERT, (delay), (cs))
+#define SPI_ENGINE_CMD_WRITE(reg, val) \
+       SPI_ENGINE_CMD(SPI_ENGINE_INST_WRITE, (reg), (val))
+#define SPI_ENGINE_CMD_SLEEP(delay) \
+       SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SLEEP, (delay))
+#define SPI_ENGINE_CMD_SYNC(id) \
+       SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SYNC, (id))
+
+struct spi_engine_program {
+       unsigned int length;
+       uint16_t instructions[];
+};
+
+struct spi_engine {
+       struct clk *clk;
+       struct clk *ref_clk;
+
+       spinlock_t lock;
+
+       void __iomem *base;
+
+       struct spi_message *msg;
+       struct spi_engine_program *p;
+       unsigned cmd_length;
+       const uint16_t *cmd_buf;
+
+       struct spi_transfer *tx_xfer;
+       unsigned int tx_length;
+       const uint8_t *tx_buf;
+
+       struct spi_transfer *rx_xfer;
+       unsigned int rx_length;
+       uint8_t *rx_buf;
+
+       unsigned int sync_id;
+       unsigned int completed_id;
+
+       unsigned int int_enable;
+};
+
+static void spi_engine_program_add_cmd(struct spi_engine_program *p,
+       bool dry, uint16_t cmd)
+{
+       if (!dry)
+               p->instructions[p->length] = cmd;
+       p->length++;
+}
+
+static unsigned int spi_engine_get_config(struct spi_device *spi)
+{
+       unsigned int config = 0;
+
+       if (spi->mode & SPI_CPOL)
+               config |= SPI_ENGINE_CONFIG_CPOL;
+       if (spi->mode & SPI_CPHA)
+               config |= SPI_ENGINE_CONFIG_CPHA;
+       if (spi->mode & SPI_3WIRE)
+               config |= SPI_ENGINE_CONFIG_3WIRE;
+
+       return config;
+}
+
+static unsigned int spi_engine_get_clk_div(struct spi_engine *spi_engine,
+       struct spi_device *spi, struct spi_transfer *xfer)
+{
+       unsigned int clk_div;
+
+       clk_div = DIV_ROUND_UP(clk_get_rate(spi_engine->ref_clk),
+               xfer->speed_hz * 2);
+       if (clk_div > 255)
+               clk_div = 255;
+       else if (clk_div > 0)
+               clk_div -= 1;
+
+       return clk_div;
+}
+
+static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
+       struct spi_transfer *xfer)
+{
+       unsigned int len = xfer->len;
+
+       while (len) {
+               unsigned int n = min(len, 256U);
+               unsigned int flags = 0;
+
+               if (xfer->tx_buf)
+                       flags |= SPI_ENGINE_TRANSFER_WRITE;
+               if (xfer->rx_buf)
+                       flags |= SPI_ENGINE_TRANSFER_READ;
+
+               spi_engine_program_add_cmd(p, dry,
+                       SPI_ENGINE_CMD_TRANSFER(flags, n - 1));
+               len -= n;
+       }
+}
+
+static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry,
+       struct spi_engine *spi_engine, unsigned int clk_div, unsigned int delay)
+{
+       unsigned int spi_clk = clk_get_rate(spi_engine->ref_clk);
+       unsigned int t;
+
+       if (delay == 0)
+               return;
+
+       t = DIV_ROUND_UP(delay * spi_clk, (clk_div + 1) * 2);
+       while (t) {
+               unsigned int n = min(t, 256U);
+
+               spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_SLEEP(n - 1));
+               t -= n;
+       }
+}
+
+static void spi_engine_gen_cs(struct spi_engine_program *p, bool dry,
+               struct spi_device *spi, bool assert)
+{
+       unsigned int mask = 0xff;
+
+       if (assert)
+               mask ^= BIT(spi->chip_select);
+
+       spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_ASSERT(1, mask));
+}
+
+static int spi_engine_compile_message(struct spi_engine *spi_engine,
+       struct spi_message *msg, bool dry, struct spi_engine_program *p)
+{
+       struct spi_device *spi = msg->spi;
+       struct spi_transfer *xfer;
+       int clk_div, new_clk_div;
+       bool cs_change = true;
+
+       clk_div = -1;
+
+       spi_engine_program_add_cmd(p, dry,
+               SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CONFIG,
+                       spi_engine_get_config(spi)));
+
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               new_clk_div = spi_engine_get_clk_div(spi_engine, spi, xfer);
+               if (new_clk_div != clk_div) {
+                       clk_div = new_clk_div;
+                       spi_engine_program_add_cmd(p, dry,
+                               SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CLK_DIV,
+                                       clk_div));
+               }
+
+               if (cs_change)
+                       spi_engine_gen_cs(p, dry, spi, true);
+
+               spi_engine_gen_xfer(p, dry, xfer);
+               spi_engine_gen_sleep(p, dry, spi_engine, clk_div,
+                       xfer->delay_usecs);
+
+               cs_change = xfer->cs_change;
+               if (list_is_last(&xfer->transfer_list, &msg->transfers))
+                       cs_change = !cs_change;
+
+               if (cs_change)
+                       spi_engine_gen_cs(p, dry, spi, false);
+       }
+
+       return 0;
+}
+
+static void spi_engine_xfer_next(struct spi_engine *spi_engine,
+       struct spi_transfer **_xfer)
+{
+       struct spi_message *msg = spi_engine->msg;
+       struct spi_transfer *xfer = *_xfer;
+
+       if (!xfer) {
+               xfer = list_first_entry(&msg->transfers,
+                       struct spi_transfer, transfer_list);
+       } else if (list_is_last(&xfer->transfer_list, &msg->transfers)) {
+               xfer = NULL;
+       } else {
+               xfer = list_next_entry(xfer, transfer_list);
+       }
+
+       *_xfer = xfer;
+}
+
+static void spi_engine_tx_next(struct spi_engine *spi_engine)
+{
+       struct spi_transfer *xfer = spi_engine->tx_xfer;
+
+       do {
+               spi_engine_xfer_next(spi_engine, &xfer);
+       } while (xfer && !xfer->tx_buf);
+
+       spi_engine->tx_xfer = xfer;
+       if (xfer) {
+               spi_engine->tx_length = xfer->len;
+               spi_engine->tx_buf = xfer->tx_buf;
+       } else {
+               spi_engine->tx_buf = NULL;
+       }
+}
+
+static void spi_engine_rx_next(struct spi_engine *spi_engine)
+{
+       struct spi_transfer *xfer = spi_engine->rx_xfer;
+
+       do {
+               spi_engine_xfer_next(spi_engine, &xfer);
+       } while (xfer && !xfer->rx_buf);
+
+       spi_engine->rx_xfer = xfer;
+       if (xfer) {
+               spi_engine->rx_length = xfer->len;
+               spi_engine->rx_buf = xfer->rx_buf;
+       } else {
+               spi_engine->rx_buf = NULL;
+       }
+}
+
+static bool spi_engine_write_cmd_fifo(struct spi_engine *spi_engine)
+{
+       void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_CMD_FIFO;
+       unsigned int n, m, i;
+       const uint16_t *buf;
+
+       n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_CMD_FIFO_ROOM);
+       while (n && spi_engine->cmd_length) {
+               m = min(n, spi_engine->cmd_length);
+               buf = spi_engine->cmd_buf;
+               for (i = 0; i < m; i++)
+                       writel_relaxed(buf[i], addr);
+               spi_engine->cmd_buf += m;
+               spi_engine->cmd_length -= m;
+               n -= m;
+       }
+
+       return spi_engine->cmd_length != 0;
+}
+
+static bool spi_engine_write_tx_fifo(struct spi_engine *spi_engine)
+{
+       void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDO_DATA_FIFO;
+       unsigned int n, m, i;
+       const uint8_t *buf;
+
+       n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDO_FIFO_ROOM);
+       while (n && spi_engine->tx_length) {
+               m = min(n, spi_engine->tx_length);
+               buf = spi_engine->tx_buf;
+               for (i = 0; i < m; i++)
+                       writel_relaxed(buf[i], addr);
+               spi_engine->tx_buf += m;
+               spi_engine->tx_length -= m;
+               n -= m;
+               if (spi_engine->tx_length == 0)
+                       spi_engine_tx_next(spi_engine);
+       }
+
+       return spi_engine->tx_length != 0;
+}
+
+static bool spi_engine_read_rx_fifo(struct spi_engine *spi_engine)
+{
+       void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDI_DATA_FIFO;
+       unsigned int n, m, i;
+       uint8_t *buf;
+
+       n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDI_FIFO_LEVEL);
+       while (n && spi_engine->rx_length) {
+               m = min(n, spi_engine->rx_length);
+               buf = spi_engine->rx_buf;
+               for (i = 0; i < m; i++)
+                       buf[i] = readl_relaxed(addr);
+               spi_engine->rx_buf += m;
+               spi_engine->rx_length -= m;
+               n -= m;
+               if (spi_engine->rx_length == 0)
+                       spi_engine_rx_next(spi_engine);
+       }
+
+       return spi_engine->rx_length != 0;
+}
+
+static irqreturn_t spi_engine_irq(int irq, void *devid)
+{
+       struct spi_master *master = devid;
+       struct spi_engine *spi_engine = spi_master_get_devdata(master);
+       unsigned int disable_int = 0;
+       unsigned int pending;
+
+       pending = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_INT_PENDING);
+
+       if (pending & SPI_ENGINE_INT_SYNC) {
+               writel_relaxed(SPI_ENGINE_INT_SYNC,
+                       spi_engine->base + SPI_ENGINE_REG_INT_PENDING);
+               spi_engine->completed_id = readl_relaxed(
+                       spi_engine->base + SPI_ENGINE_REG_SYNC_ID);
+       }
+
+       spin_lock(&spi_engine->lock);
+
+       if (pending & SPI_ENGINE_INT_CMD_ALMOST_EMPTY) {
+               if (!spi_engine_write_cmd_fifo(spi_engine))
+                       disable_int |= SPI_ENGINE_INT_CMD_ALMOST_EMPTY;
+       }
+
+       if (pending & SPI_ENGINE_INT_SDO_ALMOST_EMPTY) {
+               if (!spi_engine_write_tx_fifo(spi_engine))
+                       disable_int |= SPI_ENGINE_INT_SDO_ALMOST_EMPTY;
+       }
+
+       if (pending & (SPI_ENGINE_INT_SDI_ALMOST_FULL | SPI_ENGINE_INT_SYNC)) {
+               if (!spi_engine_read_rx_fifo(spi_engine))
+                       disable_int |= SPI_ENGINE_INT_SDI_ALMOST_FULL;
+       }
+
+       if (pending & SPI_ENGINE_INT_SYNC) {
+               if (spi_engine->msg &&
+                   spi_engine->completed_id == spi_engine->sync_id) {
+                       struct spi_message *msg = spi_engine->msg;
+
+                       kfree(spi_engine->p);
+                       msg->status = 0;
+                       msg->actual_length = msg->frame_length;
+                       spi_engine->msg = NULL;
+                       spi_finalize_current_message(master);
+                       disable_int |= SPI_ENGINE_INT_SYNC;
+               }
+       }
+
+       if (disable_int) {
+               spi_engine->int_enable &= ~disable_int;
+               writel_relaxed(spi_engine->int_enable,
+                       spi_engine->base + SPI_ENGINE_REG_INT_ENABLE);
+       }
+
+       spin_unlock(&spi_engine->lock);
+
+       return IRQ_HANDLED;
+}
+
+static int spi_engine_transfer_one_message(struct spi_master *master,
+       struct spi_message *msg)
+{
+       struct spi_engine_program p_dry, *p;
+       struct spi_engine *spi_engine = spi_master_get_devdata(master);
+       unsigned int int_enable = 0;
+       unsigned long flags;
+       size_t size;
+
+       p_dry.length = 0;
+       spi_engine_compile_message(spi_engine, msg, true, &p_dry);
+
+       size = sizeof(*p->instructions) * (p_dry.length + 1);
+       p = kzalloc(sizeof(*p) + size, GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+       spi_engine_compile_message(spi_engine, msg, false, p);
+
+       spin_lock_irqsave(&spi_engine->lock, flags);
+       spi_engine->sync_id = (spi_engine->sync_id + 1) & 0xff;
+       spi_engine_program_add_cmd(p, false,
+               SPI_ENGINE_CMD_SYNC(spi_engine->sync_id));
+
+       spi_engine->msg = msg;
+       spi_engine->p = p;
+
+       spi_engine->cmd_buf = p->instructions;
+       spi_engine->cmd_length = p->length;
+       if (spi_engine_write_cmd_fifo(spi_engine))
+               int_enable |= SPI_ENGINE_INT_CMD_ALMOST_EMPTY;
+
+       spi_engine_tx_next(spi_engine);
+       if (spi_engine_write_tx_fifo(spi_engine))
+               int_enable |= SPI_ENGINE_INT_SDO_ALMOST_EMPTY;
+
+       spi_engine_rx_next(spi_engine);
+       if (spi_engine->rx_length != 0)
+               int_enable |= SPI_ENGINE_INT_SDI_ALMOST_FULL;
+
+       int_enable |= SPI_ENGINE_INT_SYNC;
+
+       writel_relaxed(int_enable,
+               spi_engine->base + SPI_ENGINE_REG_INT_ENABLE);
+       spi_engine->int_enable = int_enable;
+       spin_unlock_irqrestore(&spi_engine->lock, flags);
+
+       return 0;
+}
+
+static int spi_engine_probe(struct platform_device *pdev)
+{
+       struct spi_engine *spi_engine;
+       struct spi_master *master;
+       unsigned int version;
+       struct resource *res;
+       int irq;
+       int ret;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq <= 0)
+               return -ENXIO;
+
+       spi_engine = devm_kzalloc(&pdev->dev, sizeof(*spi_engine), GFP_KERNEL);
+       if (!spi_engine)
+               return -ENOMEM;
+
+       master = spi_alloc_master(&pdev->dev, 0);
+       if (!master)
+               return -ENOMEM;
+
+       spi_master_set_devdata(master, spi_engine);
+
+       spin_lock_init(&spi_engine->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       spi_engine->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(spi_engine->base)) {
+               ret = PTR_ERR(spi_engine->base);
+               goto err_put_master;
+       }
+
+       version = readl(spi_engine->base + SPI_ENGINE_REG_VERSION);
+       if (SPI_ENGINE_VERSION_MAJOR(version) != 1) {
+               dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%c\n",
+                       SPI_ENGINE_VERSION_MAJOR(version),
+                       SPI_ENGINE_VERSION_MINOR(version),
+                       SPI_ENGINE_VERSION_PATCH(version));
+               return -ENODEV;
+       }
+
+       spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
+       if (IS_ERR(spi_engine->clk)) {
+               ret = PTR_ERR(spi_engine->clk);
+               goto err_put_master;
+       }
+
+       spi_engine->ref_clk = devm_clk_get(&pdev->dev, "spi_clk");
+       if (IS_ERR(spi_engine->ref_clk)) {
+               ret = PTR_ERR(spi_engine->ref_clk);
+               goto err_put_master;
+       }
+
+       ret = clk_prepare_enable(spi_engine->clk);
+       if (ret)
+               goto err_put_master;
+
+       ret = clk_prepare_enable(spi_engine->ref_clk);
+       if (ret)
+               goto err_clk_disable;
+
+       writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_RESET);
+       writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING);
+       writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE);
+
+       ret = request_irq(irq, spi_engine_irq, 0, pdev->name, master);
+       if (ret)
+               goto err_ref_clk_disable;
+
+       master->dev.parent = &pdev->dev;
+       master->dev.of_node = pdev->dev.of_node;
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+       master->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2;
+       master->transfer_one_message = spi_engine_transfer_one_message;
+       master->num_chipselect = 8;
+
+       ret = spi_register_master(master);
+       if (ret)
+               goto err_free_irq;
+
+       platform_set_drvdata(pdev, master);
+
+       return 0;
+err_free_irq:
+       free_irq(irq, master);
+err_ref_clk_disable:
+       clk_disable_unprepare(spi_engine->ref_clk);
+err_clk_disable:
+       clk_disable_unprepare(spi_engine->clk);
+err_put_master:
+       spi_master_put(master);
+       return ret;
+}
+
+static int spi_engine_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct spi_engine *spi_engine = spi_master_get_devdata(master);
+       int irq = platform_get_irq(pdev, 0);
+
+       spi_unregister_master(master);
+
+       free_irq(irq, master);
+
+       writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING);
+       writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE);
+       writel_relaxed(0x01, spi_engine->base + SPI_ENGINE_REG_RESET);
+
+       clk_disable_unprepare(spi_engine->ref_clk);
+       clk_disable_unprepare(spi_engine->clk);
+
+       return 0;
+}
+
+static const struct of_device_id spi_engine_match_table[] = {
+       { .compatible = "adi,axi-spi-engine-1.00.a" },
+       { },
+};
+
+static struct platform_driver spi_engine_driver = {
+       .probe = spi_engine_probe,
+       .remove = spi_engine_remove,
+       .driver = {
+               .name = "spi-engine",
+               .of_match_table = spi_engine_match_table,
+       },
+};
+module_platform_driver(spi_engine_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices SPI engine peripheral driver");
+MODULE_LICENSE("GPL");
index cf04960cc3e6ca1f5a87ad24f3d88cdbcfaa8a36..f35cc10772f6670397ea923ad30158270dd68578 100644 (file)
@@ -727,11 +727,6 @@ static int bcm2835_spi_setup(struct spi_device *spi)
                        spi->chip_select, spi->cs_gpio, err);
                return err;
        }
-       /* the implementation of pinctrl-bcm2835 currently does not
-        * set the GPIO value when using gpio_direction_output
-        * so we are setting it here explicitly
-        */
-       gpio_set_value(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
 
        return 0;
 }
index ecc73c0a97cf5ebf0d2a6c623cf3ce1ac311e62b..7428091d3f5b8ffa77ed2a3be65a114720cb4bfa 100644 (file)
@@ -64,9 +64,9 @@
 #define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH        0x00004000
 #define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000
 #define BCM2835_AUX_SPI_CNTL0_ENABLE   0x00000800
-#define BCM2835_AUX_SPI_CNTL0_CPHA_IN  0x00000400
+#define BCM2835_AUX_SPI_CNTL0_IN_RISING        0x00000400
 #define BCM2835_AUX_SPI_CNTL0_CLEARFIFO        0x00000200
-#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100
+#define BCM2835_AUX_SPI_CNTL0_OUT_RISING       0x00000100
 #define BCM2835_AUX_SPI_CNTL0_CPOL     0x00000080
 #define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040
 #define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F
@@ -92,9 +92,6 @@
 #define BCM2835_AUX_SPI_POLLING_LIMIT_US       30
 #define BCM2835_AUX_SPI_POLLING_JIFFIES                2
 
-#define BCM2835_AUX_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
-                                 | SPI_NO_CS)
-
 struct bcm2835aux_spi {
        void __iomem *regs;
        struct clk *clk;
@@ -212,9 +209,15 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
                ret = IRQ_HANDLED;
        }
 
-       /* and if rx_len is 0 then wake up completion and disable spi */
+       if (!bs->tx_len) {
+               /* disable tx fifo empty interrupt */
+               bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
+                       BCM2835_AUX_SPI_CNTL1_IDLE);
+       }
+
+       /* and if rx_len is 0 then disable interrupts and wake up completion */
        if (!bs->rx_len) {
-               bcm2835aux_spi_reset_hw(bs);
+               bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
                complete(&master->xfer_completion);
        }
 
@@ -307,9 +310,6 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
                }
        }
 
-       /* Transfer complete - reset SPI HW */
-       bcm2835aux_spi_reset_hw(bs);
-
        /* and return without waiting for completion */
        return 0;
 }
@@ -330,10 +330,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
         * resulting (potentially) in more interrupts when transferring
         * more than 12 bytes
         */
-       bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
-                     BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
-                     BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
-       bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
 
        /* set clock */
        spi_hz = tfr->speed_hz;
@@ -348,17 +344,13 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
        } else { /* the slowest we can go */
                speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
        }
+       /* mask out old speed from previous spi_transfer */
+       bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED);
+       /* set the new speed */
        bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
 
        spi_used_hz = clk_hz / (2 * (speed + 1));
 
-       /* handle all the modes */
-       if (spi->mode & SPI_CPOL)
-               bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
-       if (spi->mode & SPI_CPHA)
-               bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT |
-                              BCM2835_AUX_SPI_CNTL0_CPHA_IN;
-
        /* set transmit buffers and length */
        bs->tx_buf = tfr->tx_buf;
        bs->rx_buf = tfr->rx_buf;
@@ -382,6 +374,40 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master,
        return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
 }
 
+static int bcm2835aux_spi_prepare_message(struct spi_master *master,
+                                         struct spi_message *msg)
+{
+       struct spi_device *spi = msg->spi;
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+       bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
+                     BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
+                     BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
+       bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
+
+       /* handle all the modes */
+       if (spi->mode & SPI_CPOL) {
+               bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
+               bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING;
+       } else {
+               bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING;
+       }
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
+
+       return 0;
+}
+
+static int bcm2835aux_spi_unprepare_message(struct spi_master *master,
+                                           struct spi_message *msg)
+{
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+       bcm2835aux_spi_reset_hw(bs);
+
+       return 0;
+}
+
 static void bcm2835aux_spi_handle_err(struct spi_master *master,
                                      struct spi_message *msg)
 {
@@ -405,11 +431,13 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)
        }
 
        platform_set_drvdata(pdev, master);
-       master->mode_bits = BCM2835_AUX_SPI_MODE_BITS;
+       master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS);
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->num_chipselect = -1;
        master->transfer_one = bcm2835aux_spi_transfer_one;
        master->handle_err = bcm2835aux_spi_handle_err;
+       master->prepare_message = bcm2835aux_spi_prepare_message;
+       master->unprepare_message = bcm2835aux_spi_unprepare_message;
        master->dev.of_node = pdev->dev.of_node;
 
        bs = spi_master_get_devdata(master);
index 9185f6c08459842e68a6292dbae6b6884d53fcde..e31971f91475b1b3d9f1b2011e0b6e4e2ae4697b 100644 (file)
@@ -89,10 +89,10 @@ static void mid_spi_dma_exit(struct dw_spi *dws)
        if (!dws->dma_inited)
                return;
 
-       dmaengine_terminate_all(dws->txchan);
+       dmaengine_terminate_sync(dws->txchan);
        dma_release_channel(dws->txchan);
 
-       dmaengine_terminate_all(dws->rxchan);
+       dmaengine_terminate_sync(dws->rxchan);
        dma_release_channel(dws->rxchan);
 }
 
index a6d7029a85ac8655ce44423751f2ded3b63b8816..447497e9124c922a4e3ecc20af8ab7ee91062e99 100644 (file)
@@ -47,11 +47,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
 
        /* Get basic io resource and map it */
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(&pdev->dev, "no mem resource?\n");
-               return -EINVAL;
-       }
-
        dws->regs = devm_ioremap_resource(&pdev->dev, mem);
        if (IS_ERR(dws->regs)) {
                dev_err(&pdev->dev, "SPI region map failed\n");
index 6a4ff27f4357eb229815c18b535327487f2df580..e7a19be87c38053f1742c785a7bfbf9d17113bfc 100644 (file)
@@ -56,7 +56,6 @@
 
 /* The maximum  bytes that a sdma BD can transfer.*/
 #define MAX_SDMA_BD_BYTES  (1 << 15)
-#define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000))
 struct spi_imx_config {
        unsigned int speed_hz;
        unsigned int bpw;
@@ -86,12 +85,18 @@ struct spi_imx_devtype_data {
 
 struct spi_imx_data {
        struct spi_bitbang bitbang;
+       struct device *dev;
 
        struct completion xfer_done;
        void __iomem *base;
+       unsigned long base_phys;
+
        struct clk *clk_per;
        struct clk *clk_ipg;
        unsigned long spi_clk;
+       unsigned int spi_bus_clk;
+
+       unsigned int bytes_per_word;
 
        unsigned int count;
        void (*tx)(struct spi_imx_data *);
@@ -101,8 +106,6 @@ struct spi_imx_data {
        unsigned int txfifo; /* number of words pushed in tx FIFO */
 
        /* DMA */
-       unsigned int dma_is_inited;
-       unsigned int dma_finished;
        bool usedma;
        u32 wml;
        struct completion dma_rx_completion;
@@ -199,15 +202,35 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
        return 7;
 }
 
+static int spi_imx_bytes_per_word(const int bpw)
+{
+       return DIV_ROUND_UP(bpw, BITS_PER_BYTE);
+}
+
 static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
                         struct spi_transfer *transfer)
 {
        struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+       unsigned int bpw = transfer->bits_per_word;
+
+       if (!master->dma_rx)
+               return false;
 
-       if (spi_imx->dma_is_inited &&
-           transfer->len > spi_imx->wml * sizeof(u32))
-               return true;
-       return false;
+       if (!bpw)
+               bpw = spi->bits_per_word;
+
+       bpw = spi_imx_bytes_per_word(bpw);
+
+       if (bpw != 1 && bpw != 2 && bpw != 4)
+               return false;
+
+       if (transfer->len < spi_imx->wml * bpw)
+               return false;
+
+       if (transfer->len % (spi_imx->wml * bpw))
+               return false;
+
+       return true;
 }
 
 #define MX51_ECSPI_CTRL                0x08
@@ -232,16 +255,13 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 #define MX51_ECSPI_INT_RREN            (1 <<  3)
 
 #define MX51_ECSPI_DMA      0x14
-#define MX51_ECSPI_DMA_TX_WML_OFFSET   0
-#define MX51_ECSPI_DMA_TX_WML_MASK     0x3F
-#define MX51_ECSPI_DMA_RX_WML_OFFSET   16
-#define MX51_ECSPI_DMA_RX_WML_MASK     (0x3F << 16)
-#define MX51_ECSPI_DMA_RXT_WML_OFFSET  24
-#define MX51_ECSPI_DMA_RXT_WML_MASK    (0x3F << 24)
+#define MX51_ECSPI_DMA_TX_WML(wml)     ((wml) & 0x3f)
+#define MX51_ECSPI_DMA_RX_WML(wml)     (((wml) & 0x3f) << 16)
+#define MX51_ECSPI_DMA_RXT_WML(wml)    (((wml) & 0x3f) << 24)
 
-#define MX51_ECSPI_DMA_TEDEN_OFFSET    7
-#define MX51_ECSPI_DMA_RXDEN_OFFSET    23
-#define MX51_ECSPI_DMA_RXTDEN_OFFSET   31
+#define MX51_ECSPI_DMA_TEDEN           (1 << 7)
+#define MX51_ECSPI_DMA_RXDEN           (1 << 23)
+#define MX51_ECSPI_DMA_RXTDEN          (1 << 31)
 
 #define MX51_ECSPI_STAT                0x18
 #define MX51_ECSPI_STAT_RR             (1 <<  3)
@@ -250,14 +270,15 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
 #define MX51_ECSPI_TESTREG_LBC BIT(31)
 
 /* MX51 eCSPI */
-static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
-                                     unsigned int *fres)
+static unsigned int mx51_ecspi_clkdiv(struct spi_imx_data *spi_imx,
+                                     unsigned int fspi, unsigned int *fres)
 {
        /*
         * there are two 4-bit dividers, the pre-divider divides by
         * $pre, the post-divider by 2^$post
         */
        unsigned int pre, post;
+       unsigned int fin = spi_imx->spi_clk;
 
        if (unlikely(fspi > fin))
                return 0;
@@ -270,14 +291,14 @@ static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
 
        post = max(4U, post) - 4;
        if (unlikely(post > 0xf)) {
-               pr_err("%s: cannot set clock freq: %u (base freq: %u)\n",
-                               __func__, fspi, fin);
+               dev_err(spi_imx->dev, "cannot set clock freq: %u (base freq: %u)\n",
+                               fspi, fin);
                return 0xff;
        }
 
        pre = DIV_ROUND_UP(fin, fspi << post) - 1;
 
-       pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
+       dev_dbg(spi_imx->dev, "%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
                        __func__, fin, fspi, post, pre);
 
        /* Resulting frequency for the SCLK line. */
@@ -302,22 +323,17 @@ static void __maybe_unused mx51_ecspi_intctrl(struct spi_imx_data *spi_imx, int
 
 static void __maybe_unused mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
 {
-       u32 reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
+       u32 reg;
 
-       if (!spi_imx->usedma)
-               reg |= MX51_ECSPI_CTRL_XCH;
-       else if (!spi_imx->dma_finished)
-               reg |= MX51_ECSPI_CTRL_SMC;
-       else
-               reg &= ~MX51_ECSPI_CTRL_SMC;
+       reg = readl(spi_imx->base + MX51_ECSPI_CTRL);
+       reg |= MX51_ECSPI_CTRL_XCH;
        writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
 }
 
 static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
                struct spi_imx_config *config)
 {
-       u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
-       u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
+       u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0;
        u32 clk = config->speed_hz, delay, reg;
 
        /*
@@ -330,7 +346,8 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
        ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
 
        /* set clock speed */
-       ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk);
+       ctrl |= mx51_ecspi_clkdiv(spi_imx, config->speed_hz, &clk);
+       spi_imx->spi_bus_clk = clk;
 
        /* set chip select to use */
        ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
@@ -341,20 +358,16 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 
        if (config->mode & SPI_CPHA)
                cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
-       else
-               cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
 
        if (config->mode & SPI_CPOL) {
                cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
                cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
-       } else {
-               cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
-               cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
        }
        if (config->mode & SPI_CS_HIGH)
                cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
-       else
-               cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs);
+
+       if (spi_imx->usedma)
+               ctrl |= MX51_ECSPI_CTRL_SMC;
 
        /* CTRL register always go first to bring out controller from reset */
        writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
@@ -389,22 +402,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
         * Configure the DMA register: setup the watermark
         * and enable DMA request.
         */
-       if (spi_imx->dma_is_inited) {
-               dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-
-               rx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
-               tx_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
-               rxt_wml_cfg = spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
-               dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
-                          & ~MX51_ECSPI_DMA_RX_WML_MASK
-                          & ~MX51_ECSPI_DMA_RXT_WML_MASK)
-                          | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg
-                          |(1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
-                          |(1 << MX51_ECSPI_DMA_RXDEN_OFFSET)
-                          |(1 << MX51_ECSPI_DMA_RXTDEN_OFFSET);
-
-               writel(dma, spi_imx->base + MX51_ECSPI_DMA);
-       }
+
+       writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml) |
+               MX51_ECSPI_DMA_TX_WML(spi_imx->wml) |
+               MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) |
+               MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN |
+               MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA);
 
        return 0;
 }
@@ -784,11 +787,63 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static int spi_imx_dma_configure(struct spi_master *master,
+                                int bytes_per_word)
+{
+       int ret;
+       enum dma_slave_buswidth buswidth;
+       struct dma_slave_config rx = {}, tx = {};
+       struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+       if (bytes_per_word == spi_imx->bytes_per_word)
+               /* Same as last time */
+               return 0;
+
+       switch (bytes_per_word) {
+       case 4:
+               buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+               break;
+       case 2:
+               buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+               break;
+       case 1:
+               buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       tx.direction = DMA_MEM_TO_DEV;
+       tx.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
+       tx.dst_addr_width = buswidth;
+       tx.dst_maxburst = spi_imx->wml;
+       ret = dmaengine_slave_config(master->dma_tx, &tx);
+       if (ret) {
+               dev_err(spi_imx->dev, "TX dma configuration failed with %d\n", ret);
+               return ret;
+       }
+
+       rx.direction = DMA_DEV_TO_MEM;
+       rx.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
+       rx.src_addr_width = buswidth;
+       rx.src_maxburst = spi_imx->wml;
+       ret = dmaengine_slave_config(master->dma_rx, &rx);
+       if (ret) {
+               dev_err(spi_imx->dev, "RX dma configuration failed with %d\n", ret);
+               return ret;
+       }
+
+       spi_imx->bytes_per_word = bytes_per_word;
+
+       return 0;
+}
+
 static int spi_imx_setupxfer(struct spi_device *spi,
                                 struct spi_transfer *t)
 {
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
        struct spi_imx_config config;
+       int ret;
 
        config.bpw = t ? t->bits_per_word : spi->bits_per_word;
        config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
@@ -812,6 +867,18 @@ static int spi_imx_setupxfer(struct spi_device *spi,
                spi_imx->tx = spi_imx_buf_tx_u32;
        }
 
+       if (spi_imx_can_dma(spi_imx->bitbang.master, spi, t))
+               spi_imx->usedma = 1;
+       else
+               spi_imx->usedma = 0;
+
+       if (spi_imx->usedma) {
+               ret = spi_imx_dma_configure(spi->master,
+                                           spi_imx_bytes_per_word(config.bpw));
+               if (ret)
+                       return ret;
+       }
+
        spi_imx->devtype_data->config(spi_imx, &config);
 
        return 0;
@@ -830,15 +897,11 @@ static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx)
                dma_release_channel(master->dma_tx);
                master->dma_tx = NULL;
        }
-
-       spi_imx->dma_is_inited = 0;
 }
 
 static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
-                            struct spi_master *master,
-                            const struct resource *res)
+                            struct spi_master *master)
 {
-       struct dma_slave_config slave_config = {};
        int ret;
 
        /* use pio mode for i.mx6dl chip TKT238285 */
@@ -856,16 +919,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
                goto err;
        }
 
-       slave_config.direction = DMA_MEM_TO_DEV;
-       slave_config.dst_addr = res->start + MXC_CSPITXDATA;
-       slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-       slave_config.dst_maxburst = spi_imx->wml;
-       ret = dmaengine_slave_config(master->dma_tx, &slave_config);
-       if (ret) {
-               dev_err(dev, "error in TX dma configuration.\n");
-               goto err;
-       }
-
        /* Prepare for RX : */
        master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
        if (IS_ERR(master->dma_rx)) {
@@ -875,15 +928,7 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
                goto err;
        }
 
-       slave_config.direction = DMA_DEV_TO_MEM;
-       slave_config.src_addr = res->start + MXC_CSPIRXDATA;
-       slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
-       slave_config.src_maxburst = spi_imx->wml;
-       ret = dmaengine_slave_config(master->dma_rx, &slave_config);
-       if (ret) {
-               dev_err(dev, "error in RX dma configuration.\n");
-               goto err;
-       }
+       spi_imx_dma_configure(master, 1);
 
        init_completion(&spi_imx->dma_rx_completion);
        init_completion(&spi_imx->dma_tx_completion);
@@ -891,7 +936,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx,
        master->max_dma_len = MAX_SDMA_BD_BYTES;
        spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
                                         SPI_MASTER_MUST_TX;
-       spi_imx->dma_is_inited = 1;
 
        return 0;
 err:
@@ -913,108 +957,81 @@ static void spi_imx_dma_tx_callback(void *cookie)
        complete(&spi_imx->dma_tx_completion);
 }
 
+static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
+{
+       unsigned long timeout = 0;
+
+       /* Time with actual data transfer and CS change delay related to HW */
+       timeout = (8 + 4) * size / spi_imx->spi_bus_clk;
+
+       /* Add extra second for scheduler related activities */
+       timeout += 1;
+
+       /* Double calculated timeout */
+       return msecs_to_jiffies(2 * timeout * MSEC_PER_SEC);
+}
+
 static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
                                struct spi_transfer *transfer)
 {
-       struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
-       int ret;
+       struct dma_async_tx_descriptor *desc_tx, *desc_rx;
+       unsigned long transfer_timeout;
        unsigned long timeout;
-       u32 dma;
-       int left;
        struct spi_master *master = spi_imx->bitbang.master;
        struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg;
 
-       if (tx) {
-               desc_tx = dmaengine_prep_slave_sg(master->dma_tx,
-                                       tx->sgl, tx->nents, DMA_MEM_TO_DEV,
-                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (!desc_tx)
-                       goto tx_nodma;
-
-               desc_tx->callback = spi_imx_dma_tx_callback;
-               desc_tx->callback_param = (void *)spi_imx;
-               dmaengine_submit(desc_tx);
-       }
+       /*
+        * The TX DMA setup starts the transfer, so make sure RX is configured
+        * before TX.
+        */
+       desc_rx = dmaengine_prep_slave_sg(master->dma_rx,
+                               rx->sgl, rx->nents, DMA_DEV_TO_MEM,
+                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!desc_rx)
+               return -EINVAL;
 
-       if (rx) {
-               desc_rx = dmaengine_prep_slave_sg(master->dma_rx,
-                                       rx->sgl, rx->nents, DMA_DEV_TO_MEM,
-                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (!desc_rx)
-                       goto rx_nodma;
+       desc_rx->callback = spi_imx_dma_rx_callback;
+       desc_rx->callback_param = (void *)spi_imx;
+       dmaengine_submit(desc_rx);
+       reinit_completion(&spi_imx->dma_rx_completion);
+       dma_async_issue_pending(master->dma_rx);
 
-               desc_rx->callback = spi_imx_dma_rx_callback;
-               desc_rx->callback_param = (void *)spi_imx;
-               dmaengine_submit(desc_rx);
+       desc_tx = dmaengine_prep_slave_sg(master->dma_tx,
+                               tx->sgl, tx->nents, DMA_MEM_TO_DEV,
+                               DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!desc_tx) {
+               dmaengine_terminate_all(master->dma_tx);
+               return -EINVAL;
        }
 
-       reinit_completion(&spi_imx->dma_rx_completion);
+       desc_tx->callback = spi_imx_dma_tx_callback;
+       desc_tx->callback_param = (void *)spi_imx;
+       dmaengine_submit(desc_tx);
        reinit_completion(&spi_imx->dma_tx_completion);
-
-       /* Trigger the cspi module. */
-       spi_imx->dma_finished = 0;
-
-       dma = readl(spi_imx->base + MX51_ECSPI_DMA);
-       dma = dma & (~MX51_ECSPI_DMA_RXT_WML_MASK);
-       /* Change RX_DMA_LENGTH trigger dma fetch tail data */
-       left = transfer->len % spi_imx->wml;
-       if (left)
-               writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
-                               spi_imx->base + MX51_ECSPI_DMA);
-       /*
-        * Set these order to avoid potential RX overflow. The overflow may
-        * happen if we enable SPI HW before starting RX DMA due to rescheduling
-        * for another task and/or interrupt.
-        * So RX DMA enabled first to make sure data would be read out from FIFO
-        * ASAP. TX DMA enabled next to start filling TX FIFO with new data.
-        * And finaly SPI HW enabled to start actual data transfer.
-        */
-       dma_async_issue_pending(master->dma_rx);
        dma_async_issue_pending(master->dma_tx);
-       spi_imx->devtype_data->trigger(spi_imx);
+
+       transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
 
        /* Wait SDMA to finish the data transfer.*/
        timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion,
-                                               IMX_DMA_TIMEOUT);
+                                               transfer_timeout);
        if (!timeout) {
-               pr_warn("%s %s: I/O Error in DMA TX\n",
-                       dev_driver_string(&master->dev),
-                       dev_name(&master->dev));
+               dev_err(spi_imx->dev, "I/O Error in DMA TX\n");
                dmaengine_terminate_all(master->dma_tx);
                dmaengine_terminate_all(master->dma_rx);
-       } else {
-               timeout = wait_for_completion_timeout(
-                               &spi_imx->dma_rx_completion, IMX_DMA_TIMEOUT);
-               if (!timeout) {
-                       pr_warn("%s %s: I/O Error in DMA RX\n",
-                               dev_driver_string(&master->dev),
-                               dev_name(&master->dev));
-                       spi_imx->devtype_data->reset(spi_imx);
-                       dmaengine_terminate_all(master->dma_rx);
-               }
-               dma &= ~MX51_ECSPI_DMA_RXT_WML_MASK;
-               writel(dma |
-                      spi_imx->wml << MX51_ECSPI_DMA_RXT_WML_OFFSET,
-                      spi_imx->base + MX51_ECSPI_DMA);
+               return -ETIMEDOUT;
        }
 
-       spi_imx->dma_finished = 1;
-       spi_imx->devtype_data->trigger(spi_imx);
-
-       if (!timeout)
-               ret = -ETIMEDOUT;
-       else
-               ret = transfer->len;
-
-       return ret;
+       timeout = wait_for_completion_timeout(&spi_imx->dma_rx_completion,
+                                             transfer_timeout);
+       if (!timeout) {
+               dev_err(&master->dev, "I/O Error in DMA RX\n");
+               spi_imx->devtype_data->reset(spi_imx);
+               dmaengine_terminate_all(master->dma_rx);
+               return -ETIMEDOUT;
+       }
 
-rx_nodma:
-       dmaengine_terminate_all(master->dma_tx);
-tx_nodma:
-       pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
-                    dev_driver_string(&master->dev),
-                    dev_name(&master->dev));
-       return -EAGAIN;
+       return transfer->len;
 }
 
 static int spi_imx_pio_transfer(struct spi_device *spi,
@@ -1041,19 +1058,12 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
 static int spi_imx_transfer(struct spi_device *spi,
                                struct spi_transfer *transfer)
 {
-       int ret;
        struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
 
-       if (spi_imx->bitbang.master->can_dma &&
-           spi_imx_can_dma(spi_imx->bitbang.master, spi, transfer)) {
-               spi_imx->usedma = true;
-               ret = spi_imx_dma_transfer(spi_imx, transfer);
-               if (ret != -EAGAIN)
-                       return ret;
-       }
-       spi_imx->usedma = false;
-
-       return spi_imx_pio_transfer(spi, transfer);
+       if (spi_imx->usedma)
+               return spi_imx_dma_transfer(spi_imx, transfer);
+       else
+               return spi_imx_pio_transfer(spi, transfer);
 }
 
 static int spi_imx_setup(struct spi_device *spi)
@@ -1143,6 +1153,7 @@ static int spi_imx_probe(struct platform_device *pdev)
 
        spi_imx = spi_master_get_devdata(master);
        spi_imx->bitbang.master = master;
+       spi_imx->dev = &pdev->dev;
 
        spi_imx->devtype_data = of_id ? of_id->data :
                (struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
@@ -1183,6 +1194,7 @@ static int spi_imx_probe(struct platform_device *pdev)
                ret = PTR_ERR(spi_imx->base);
                goto out_master_put;
        }
+       spi_imx->base_phys = res->start;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -1223,7 +1235,7 @@ static int spi_imx_probe(struct platform_device *pdev)
         * other chips.
         */
        if (is_imx51_ecspi(spi_imx)) {
-               ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master, res);
+               ret = spi_imx_sdma_init(&pdev->dev, spi_imx, master);
                if (ret == -EPROBE_DEFER)
                        goto out_clk_put;
 
diff --git a/drivers/spi/spi-lp8841-rtc.c b/drivers/spi/spi-lp8841-rtc.c
new file mode 100644 (file)
index 0000000..faa577d
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * SPI master driver for ICP DAS LP-8841 RTC
+ *
+ * Copyright (C) 2016 Sergei Ianovich
+ *
+ * based on
+ *
+ * Dallas DS1302 RTC Support
+ * Copyright (C) 2002 David McCullough
+ * Copyright (C) 2003 - 2007 Paul Mundt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+
+#define DRIVER_NAME    "spi_lp8841_rtc"
+
+#define SPI_LP8841_RTC_CE      0x01
+#define SPI_LP8841_RTC_CLK     0x02
+#define SPI_LP8841_RTC_nWE     0x04
+#define SPI_LP8841_RTC_MOSI    0x08
+#define SPI_LP8841_RTC_MISO    0x01
+
+/*
+ * REVISIT If there is support for SPI_3WIRE and SPI_LSB_FIRST in SPI
+ * GPIO driver, this SPI driver can be replaced by a simple GPIO driver
+ * providing 3 GPIO pins.
+ */
+
+struct spi_lp8841_rtc {
+       void            *iomem;
+       unsigned long   state;
+};
+
+static inline void
+setsck(struct spi_lp8841_rtc *data, int is_on)
+{
+       if (is_on)
+               data->state |= SPI_LP8841_RTC_CLK;
+       else
+               data->state &= ~SPI_LP8841_RTC_CLK;
+       writeb(data->state, data->iomem);
+}
+
+static inline void
+setmosi(struct spi_lp8841_rtc *data, int is_on)
+{
+       if (is_on)
+               data->state |= SPI_LP8841_RTC_MOSI;
+       else
+               data->state &= ~SPI_LP8841_RTC_MOSI;
+       writeb(data->state, data->iomem);
+}
+
+static inline int
+getmiso(struct spi_lp8841_rtc *data)
+{
+       return ioread8(data->iomem) & SPI_LP8841_RTC_MISO;
+}
+
+static inline u32
+bitbang_txrx_be_cpha0_lsb(struct spi_lp8841_rtc *data,
+               unsigned usecs, unsigned cpol, unsigned flags,
+               u32 word, u8 bits)
+{
+       /* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */
+
+       u32 shift = 32 - bits;
+       /* clock starts at inactive polarity */
+       for (; likely(bits); bits--) {
+
+               /* setup LSB (to slave) on leading edge */
+               if ((flags & SPI_MASTER_NO_TX) == 0)
+                       setmosi(data, (word & 1));
+
+               usleep_range(usecs, usecs + 1); /* T(setup) */
+
+               /* sample LSB (from slave) on trailing edge */
+               word >>= 1;
+               if ((flags & SPI_MASTER_NO_RX) == 0)
+                       word |= (getmiso(data) << 31);
+
+               setsck(data, !cpol);
+               usleep_range(usecs, usecs + 1);
+
+               setsck(data, cpol);
+       }
+
+       word >>= shift;
+       return word;
+}
+
+static int
+spi_lp8841_rtc_transfer_one(struct spi_master *master,
+                           struct spi_device *spi,
+                           struct spi_transfer *t)
+{
+       struct spi_lp8841_rtc   *data = spi_master_get_devdata(master);
+       unsigned                count = t->len;
+       const u8                *tx = t->tx_buf;
+       u8                      *rx = t->rx_buf;
+       u8                      word = 0;
+       int                     ret = 0;
+
+       if (tx) {
+               data->state &= ~SPI_LP8841_RTC_nWE;
+               writeb(data->state, data->iomem);
+               while (likely(count > 0)) {
+                       word = *tx++;
+                       bitbang_txrx_be_cpha0_lsb(data, 1, 0,
+                                       SPI_MASTER_NO_RX, word, 8);
+                       count--;
+               }
+       } else if (rx) {
+               data->state |= SPI_LP8841_RTC_nWE;
+               writeb(data->state, data->iomem);
+               while (likely(count > 0)) {
+                       word = bitbang_txrx_be_cpha0_lsb(data, 1, 0,
+                                       SPI_MASTER_NO_TX, word, 8);
+                       *rx++ = word;
+                       count--;
+               }
+       } else {
+               ret = -EINVAL;
+       }
+
+       spi_finalize_current_transfer(master);
+
+       return ret;
+}
+
+static void
+spi_lp8841_rtc_set_cs(struct spi_device *spi, bool enable)
+{
+       struct spi_lp8841_rtc *data = spi_master_get_devdata(spi->master);
+
+       data->state = 0;
+       writeb(data->state, data->iomem);
+       if (enable) {
+               usleep_range(4, 5);
+               data->state |= SPI_LP8841_RTC_CE;
+               writeb(data->state, data->iomem);
+               usleep_range(4, 5);
+       }
+}
+
+static int
+spi_lp8841_rtc_setup(struct spi_device *spi)
+{
+       if ((spi->mode & SPI_CS_HIGH) == 0) {
+               dev_err(&spi->dev, "unsupported active low chip select\n");
+               return -EINVAL;
+       }
+
+       if ((spi->mode & SPI_LSB_FIRST) == 0) {
+               dev_err(&spi->dev, "unsupported MSB first mode\n");
+               return -EINVAL;
+       }
+
+       if ((spi->mode & SPI_3WIRE) == 0) {
+               dev_err(&spi->dev, "unsupported wiring. 3 wires required\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id spi_lp8841_rtc_dt_ids[] = {
+       { .compatible = "icpdas,lp8841-spi-rtc" },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, spi_lp8841_rtc_dt_ids);
+#endif
+
+static int
+spi_lp8841_rtc_probe(struct platform_device *pdev)
+{
+       int                             ret;
+       struct spi_master               *master;
+       struct spi_lp8841_rtc           *data;
+       void                            *iomem;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*data));
+       if (!master)
+               return -ENOMEM;
+       platform_set_drvdata(pdev, master);
+
+       master->flags = SPI_MASTER_HALF_DUPLEX;
+       master->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST;
+
+       master->bus_num = pdev->id;
+       master->num_chipselect = 1;
+       master->setup = spi_lp8841_rtc_setup;
+       master->set_cs = spi_lp8841_rtc_set_cs;
+       master->transfer_one = spi_lp8841_rtc_transfer_one;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+#ifdef CONFIG_OF
+       master->dev.of_node = pdev->dev.of_node;
+#endif
+
+       data = spi_master_get_devdata(master);
+
+       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->iomem = devm_ioremap_resource(&pdev->dev, iomem);
+       ret = PTR_ERR_OR_ZERO(data->iomem);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to get IO address\n");
+               goto err_put_master;
+       }
+
+       /* register with the SPI framework */
+       ret = devm_spi_register_master(&pdev->dev, master);
+       if (ret) {
+               dev_err(&pdev->dev, "cannot register spi master\n");
+               goto err_put_master;
+       }
+
+       return ret;
+
+
+err_put_master:
+       spi_master_put(master);
+
+       return ret;
+}
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+
+static struct platform_driver spi_lp8841_rtc_driver = {
+       .driver = {
+               .name   = DRIVER_NAME,
+               .of_match_table = of_match_ptr(spi_lp8841_rtc_dt_ids),
+       },
+       .probe          = spi_lp8841_rtc_probe,
+};
+module_platform_driver(spi_lp8841_rtc_driver);
+
+MODULE_DESCRIPTION("SPI master driver for ICP DAS LP-8841 RTC");
+MODULE_AUTHOR("Sergei Ianovich");
+MODULE_LICENSE("GPL");
index 5e5fd77e27119d6ceb8d64f657884ab4ef9f3759..f7f7ba17b40e97597ae76d2f7e58fae3844ec6ef 100644 (file)
@@ -346,13 +346,6 @@ struct vendor_data {
  * @clk: outgoing clock "SPICLK" for the SPI bus
  * @master: SPI framework hookup
  * @master_info: controller-specific data from machine setup
- * @kworker: thread struct for message pump
- * @kworker_task: pointer to task for message pump kworker thread
- * @pump_messages: work struct for scheduling work to the message pump
- * @queue_lock: spinlock to syncronise access to message queue
- * @queue: message queue
- * @busy: message pump is busy
- * @running: message pump is running
  * @pump_transfers: Tasklet used in Interrupt Transfer mode
  * @cur_msg: Pointer to current spi_message being processed
  * @cur_transfer: Pointer to current spi_transfer
index bd8b369a343c98e0c98141295c9f73d63d65ce72..365fc22c35729372e22dee90271dc3a37820d27c 100644 (file)
@@ -254,8 +254,8 @@ irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data)
        if (status & SSSR_ROR) {
                dev_err(&drv_data->pdev->dev, "FIFO overrun\n");
 
-               dmaengine_terminate_all(drv_data->rx_chan);
-               dmaengine_terminate_all(drv_data->tx_chan);
+               dmaengine_terminate_async(drv_data->rx_chan);
+               dmaengine_terminate_async(drv_data->tx_chan);
 
                pxa2xx_spi_dma_transfer_complete(drv_data, true);
                return IRQ_HANDLED;
@@ -331,13 +331,13 @@ int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
 void pxa2xx_spi_dma_release(struct driver_data *drv_data)
 {
        if (drv_data->rx_chan) {
-               dmaengine_terminate_all(drv_data->rx_chan);
+               dmaengine_terminate_sync(drv_data->rx_chan);
                dma_release_channel(drv_data->rx_chan);
                sg_free_table(&drv_data->rx_sgt);
                drv_data->rx_chan = NULL;
        }
        if (drv_data->tx_chan) {
-               dmaengine_terminate_all(drv_data->tx_chan);
+               dmaengine_terminate_sync(drv_data->tx_chan);
                dma_release_channel(drv_data->tx_chan);
                sg_free_table(&drv_data->tx_sgt);
                drv_data->tx_chan = NULL;
index d19d7f28aecb3c5ac9ca6409fc9c8e2e5f7fc180..520ed1dd57804320859bbef42fa5e15f6a487213 100644 (file)
@@ -19,6 +19,7 @@ enum {
        PORT_BSW1,
        PORT_BSW2,
        PORT_QUARK_X1000,
+       PORT_LPT,
 };
 
 struct pxa_spi_info {
@@ -42,6 +43,9 @@ static struct dw_dma_slave bsw1_rx_param = { .src_id = 7 };
 static struct dw_dma_slave bsw2_tx_param = { .dst_id = 8 };
 static struct dw_dma_slave bsw2_rx_param = { .src_id = 9 };
 
+static struct dw_dma_slave lpt_tx_param = { .dst_id = 0 };
+static struct dw_dma_slave lpt_rx_param = { .src_id = 1 };
+
 static bool lpss_dma_filter(struct dma_chan *chan, void *param)
 {
        struct dw_dma_slave *dws = param;
@@ -98,6 +102,14 @@ static struct pxa_spi_info spi_info_configs[] = {
                .num_chipselect = 1,
                .max_clk_rate = 50000000,
        },
+       [PORT_LPT] = {
+               .type = LPSS_LPT_SSP,
+               .port_id = 0,
+               .num_chipselect = 1,
+               .max_clk_rate = 50000000,
+               .tx_param = &lpt_tx_param,
+               .rx_param = &lpt_rx_param,
+       },
 };
 
 static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
@@ -202,6 +214,7 @@ static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
        { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 },
        { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 },
        { PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 },
+       { PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT },
        { },
 };
 MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices);
index ab9914ad8365a6b1fb31f107dab21dac4ef94b17..85e59a406a4c01fabef55679c5ffb9b9583bd852 100644 (file)
@@ -65,8 +65,6 @@ MODULE_ALIAS("platform:pxa2xx-spi");
 #define LPSS_GENERAL_REG_RXTO_HOLDOFF_DISABLE  BIT(24)
 #define LPSS_CS_CONTROL_SW_MODE                        BIT(0)
 #define LPSS_CS_CONTROL_CS_HIGH                        BIT(1)
-#define LPSS_CS_CONTROL_CS_SEL_SHIFT           8
-#define LPSS_CS_CONTROL_CS_SEL_MASK            (3 << LPSS_CS_CONTROL_CS_SEL_SHIFT)
 #define LPSS_CAPS_CS_EN_SHIFT                  9
 #define LPSS_CAPS_CS_EN_MASK                   (0xf << LPSS_CAPS_CS_EN_SHIFT)
 
@@ -82,6 +80,10 @@ struct lpss_config {
        u32 rx_threshold;
        u32 tx_threshold_lo;
        u32 tx_threshold_hi;
+       /* Chip select control */
+       unsigned cs_sel_shift;
+       unsigned cs_sel_mask;
+       unsigned cs_num;
 };
 
 /* Keep these sorted with enum pxa_ssp_type */
@@ -106,6 +108,19 @@ static const struct lpss_config lpss_platforms[] = {
                .tx_threshold_lo = 160,
                .tx_threshold_hi = 224,
        },
+       {       /* LPSS_BSW_SSP */
+               .offset = 0x400,
+               .reg_general = 0x08,
+               .reg_ssp = 0x0c,
+               .reg_cs_ctrl = 0x18,
+               .reg_capabilities = -1,
+               .rx_threshold = 64,
+               .tx_threshold_lo = 160,
+               .tx_threshold_hi = 224,
+               .cs_sel_shift = 2,
+               .cs_sel_mask = 1 << 2,
+               .cs_num = 2,
+       },
        {       /* LPSS_SPT_SSP */
                .offset = 0x200,
                .reg_general = -1,
@@ -125,6 +140,8 @@ static const struct lpss_config lpss_platforms[] = {
                .rx_threshold = 1,
                .tx_threshold_lo = 16,
                .tx_threshold_hi = 48,
+               .cs_sel_shift = 8,
+               .cs_sel_mask = 3 << 8,
        },
 };
 
@@ -139,6 +156,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
        switch (drv_data->ssp_type) {
        case LPSS_LPT_SSP:
        case LPSS_BYT_SSP:
+       case LPSS_BSW_SSP:
        case LPSS_SPT_SSP:
        case LPSS_BXT_SSP:
                return true;
@@ -288,37 +306,50 @@ static void lpss_ssp_setup(struct driver_data *drv_data)
        }
 }
 
+static void lpss_ssp_select_cs(struct driver_data *drv_data,
+                              const struct lpss_config *config)
+{
+       u32 value, cs;
+
+       if (!config->cs_sel_mask)
+               return;
+
+       value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
+
+       cs = drv_data->cur_msg->spi->chip_select;
+       cs <<= config->cs_sel_shift;
+       if (cs != (value & config->cs_sel_mask)) {
+               /*
+                * When switching another chip select output active the
+                * output must be selected first and wait 2 ssp_clk cycles
+                * before changing state to active. Otherwise a short
+                * glitch will occur on the previous chip select since
+                * output select is latched but state control is not.
+                */
+               value &= ~config->cs_sel_mask;
+               value |= cs;
+               __lpss_ssp_write_priv(drv_data,
+                                     config->reg_cs_ctrl, value);
+               ndelay(1000000000 /
+                      (drv_data->master->max_speed_hz / 2));
+       }
+}
+
 static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
 {
        const struct lpss_config *config;
-       u32 value, cs;
+       u32 value;
 
        config = lpss_get_config(drv_data);
 
+       if (enable)
+               lpss_ssp_select_cs(drv_data, config);
+
        value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl);
-       if (enable) {
-               cs = drv_data->cur_msg->spi->chip_select;
-               cs <<= LPSS_CS_CONTROL_CS_SEL_SHIFT;
-               if (cs != (value & LPSS_CS_CONTROL_CS_SEL_MASK)) {
-                       /*
-                        * When switching another chip select output active
-                        * the output must be selected first and wait 2 ssp_clk
-                        * cycles before changing state to active. Otherwise
-                        * a short glitch will occur on the previous chip
-                        * select since output select is latched but state
-                        * control is not.
-                        */
-                       value &= ~LPSS_CS_CONTROL_CS_SEL_MASK;
-                       value |= cs;
-                       __lpss_ssp_write_priv(drv_data,
-                                             config->reg_cs_ctrl, value);
-                       ndelay(1000000000 /
-                              (drv_data->master->max_speed_hz / 2));
-               }
+       if (enable)
                value &= ~LPSS_CS_CONTROL_CS_HIGH;
-       } else {
+       else
                value |= LPSS_CS_CONTROL_CS_HIGH;
-       }
        __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value);
 }
 
@@ -496,6 +527,7 @@ static void giveback(struct driver_data *drv_data)
 {
        struct spi_transfer* last_transfer;
        struct spi_message *msg;
+       unsigned long timeout;
 
        msg = drv_data->cur_msg;
        drv_data->cur_msg = NULL;
@@ -508,6 +540,12 @@ static void giveback(struct driver_data *drv_data)
        if (last_transfer->delay_usecs)
                udelay(last_transfer->delay_usecs);
 
+       /* Wait until SSP becomes idle before deasserting the CS */
+       timeout = jiffies + msecs_to_jiffies(10);
+       while (pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY &&
+              !time_after(jiffies, timeout))
+               cpu_relax();
+
        /* Drop chip select UNLESS cs_change is true or we are returning
         * a message with an error, or next message is for another chip
         */
@@ -572,7 +610,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg)
 
 static void int_transfer_complete(struct driver_data *drv_data)
 {
-       /* Stop SSP */
+       /* Clear and disable interrupts */
        write_SSSR_CS(drv_data, drv_data->clear_sr);
        reset_sccr1(drv_data);
        if (!pxa25x_ssp_comp(drv_data))
@@ -957,8 +995,6 @@ static void pump_transfers(unsigned long data)
        drv_data->tx_end = drv_data->tx + transfer->len;
        drv_data->rx = transfer->rx_buf;
        drv_data->rx_end = drv_data->rx + transfer->len;
-       drv_data->rx_dma = transfer->rx_dma;
-       drv_data->tx_dma = transfer->tx_dma;
        drv_data->len = transfer->len;
        drv_data->write = drv_data->tx ? chip->write : null_writer;
        drv_data->read = drv_data->rx ? chip->read : null_reader;
@@ -1001,19 +1037,6 @@ static void pump_transfers(unsigned long data)
                                             "pump_transfers: DMA burst size reduced to match bits_per_word\n");
        }
 
-       /* NOTE:  PXA25x_SSP _could_ use external clocking ... */
-       cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits);
-       if (!pxa25x_ssp_comp(drv_data))
-               dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
-                       drv_data->master->max_speed_hz
-                               / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)),
-                       chip->enable_dma ? "DMA" : "PIO");
-       else
-               dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
-                       drv_data->master->max_speed_hz / 2
-                               / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)),
-                       chip->enable_dma ? "DMA" : "PIO");
-
        message->state = RUNNING_STATE;
 
        drv_data->dma_mapped = 0;
@@ -1040,6 +1063,19 @@ static void pump_transfers(unsigned long data)
                write_SSSR_CS(drv_data, drv_data->clear_sr);
        }
 
+       /* NOTE:  PXA25x_SSP _could_ use external clocking ... */
+       cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits);
+       if (!pxa25x_ssp_comp(drv_data))
+               dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
+                       drv_data->master->max_speed_hz
+                               / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)),
+                       drv_data->dma_mapped ? "DMA" : "PIO");
+       else
+               dev_dbg(&message->spi->dev, "%u Hz actual, %s\n",
+                       drv_data->master->max_speed_hz / 2
+                               / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)),
+                       drv_data->dma_mapped ? "DMA" : "PIO");
+
        if (is_lpss_ssp(drv_data)) {
                if ((pxa2xx_spi_read(drv_data, SSIRF) & 0xff)
                    != chip->lpss_rx_threshold)
@@ -1166,6 +1202,7 @@ static int setup(struct spi_device *spi)
                break;
        case LPSS_LPT_SSP:
        case LPSS_BYT_SSP:
+       case LPSS_BSW_SSP:
        case LPSS_SPT_SSP:
        case LPSS_BXT_SSP:
                config = lpss_get_config(drv_data);
@@ -1313,7 +1350,7 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
        { "INT3430", LPSS_LPT_SSP },
        { "INT3431", LPSS_LPT_SSP },
        { "80860F0E", LPSS_BYT_SSP },
-       { "8086228E", LPSS_BYT_SSP },
+       { "8086228E", LPSS_BSW_SSP },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
@@ -1347,10 +1384,14 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
        /* SPT-H */
        { PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
        { PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
-       /* BXT */
+       /* BXT A-Step */
        { PCI_VDEVICE(INTEL, 0x0ac2), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x0ac4), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x0ac6), LPSS_BXT_SSP },
+       /* BXT B-Step */
+       { PCI_VDEVICE(INTEL, 0x1ac2), LPSS_BXT_SSP },
+       { PCI_VDEVICE(INTEL, 0x1ac4), LPSS_BXT_SSP },
+       { PCI_VDEVICE(INTEL, 0x1ac6), LPSS_BXT_SSP },
        /* APL */
        { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
@@ -1438,6 +1479,29 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev)
 }
 #endif
 
+static int pxa2xx_spi_fw_translate_cs(struct spi_master *master, unsigned cs)
+{
+       struct driver_data *drv_data = spi_master_get_devdata(master);
+
+       if (has_acpi_companion(&drv_data->pdev->dev)) {
+               switch (drv_data->ssp_type) {
+               /*
+                * For Atoms the ACPI DeviceSelection used by the Windows
+                * driver starts from 1 instead of 0 so translate it here
+                * to match what Linux expects.
+                */
+               case LPSS_BYT_SSP:
+               case LPSS_BSW_SSP:
+                       return cs - 1;
+
+               default:
+                       break;
+               }
+       }
+
+       return cs;
+}
+
 static int pxa2xx_spi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -1490,6 +1554,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
        master->setup = setup;
        master->transfer_one_message = pxa2xx_spi_transfer_one_message;
        master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer;
+       master->fw_translate_cs = pxa2xx_spi_fw_translate_cs;
        master->auto_runtime_pm = true;
 
        drv_data->ssp_type = ssp->type;
@@ -1576,6 +1641,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
                        tmp &= LPSS_CAPS_CS_EN_MASK;
                        tmp >>= LPSS_CAPS_CS_EN_SHIFT;
                        platform_info->num_chipselect = ffz(tmp);
+               } else if (config->cs_num) {
+                       platform_info->num_chipselect = config->cs_num;
                }
        }
        master->num_chipselect = platform_info->num_chipselect;
index 58efa98313aa0bf5c2aca5d8458032fac566a0eb..a1ef889481447fd4eeeca749bba063014bddc3f6 100644 (file)
@@ -69,8 +69,6 @@ struct driver_data {
        void *rx;
        void *rx_end;
        int dma_mapped;
-       dma_addr_t rx_dma;
-       dma_addr_t tx_dma;
        size_t rx_map_len;
        size_t tx_map_len;
        u8 n_bytes;
@@ -147,20 +145,9 @@ static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val)
 extern int pxa2xx_spi_flush(struct driver_data *drv_data);
 extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data);
 
-/*
- * Select the right DMA implementation.
- */
-#if defined(CONFIG_SPI_PXA2XX_DMA)
-#define SPI_PXA2XX_USE_DMA     1
 #define MAX_DMA_LEN            SZ_64K
 #define DEFAULT_DMA_CR1                (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL)
-#else
-#undef SPI_PXA2XX_USE_DMA
-#define MAX_DMA_LEN            0
-#define DEFAULT_DMA_CR1                0
-#endif
 
-#ifdef SPI_PXA2XX_USE_DMA
 extern bool pxa2xx_spi_dma_is_possible(size_t len);
 extern int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data);
 extern irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data);
@@ -173,29 +160,5 @@ extern int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
                                                  u8 bits_per_word,
                                                  u32 *burst_code,
                                                  u32 *threshold);
-#else
-static inline bool pxa2xx_spi_dma_is_possible(size_t len) { return false; }
-static inline int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data)
-{
-       return 0;
-}
-#define pxa2xx_spi_dma_transfer NULL
-static inline void pxa2xx_spi_dma_prepare(struct driver_data *drv_data,
-                                         u32 dma_burst) {}
-static inline void pxa2xx_spi_dma_start(struct driver_data *drv_data) {}
-static inline int pxa2xx_spi_dma_setup(struct driver_data *drv_data)
-{
-       return 0;
-}
-static inline void pxa2xx_spi_dma_release(struct driver_data *drv_data) {}
-static inline int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip,
-                                                        struct spi_device *spi,
-                                                        u8 bits_per_word,
-                                                        u32 *burst_code,
-                                                        u32 *threshold)
-{
-       return -ENODEV;
-}
-#endif
 
 #endif /* SPI_PXA2XX_H */
index 79a8bc4f6cec9e32ec9c78627a2e68fc85ab5e12..26e2688c104ec9e6ba314264b63318a65048596f 100644 (file)
  *
  */
 
-#include <linux/init.h>
-#include <linux/module.h>
 #include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/slab.h>
 #include <linux/spi/spi.h>
-#include <linux/scatterlist.h>
-#include <linux/of.h>
 #include <linux/pm_runtime.h>
-#include <linux/io.h>
-#include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
 
 #define DRIVER_NAME "rockchip-spi"
 
@@ -179,7 +173,7 @@ struct rockchip_spi {
        u8 tmode;
        u8 bpw;
        u8 n_bytes;
-       u8 rsd_nsecs;
+       u32 rsd_nsecs;
        unsigned len;
        u32 speed;
 
@@ -192,8 +186,6 @@ struct rockchip_spi {
        /* protect state */
        spinlock_t lock;
 
-       struct completion xfer_completion;
-
        u32 use_dma;
        struct sg_table tx_sg;
        struct sg_table rx_sg;
@@ -265,7 +257,10 @@ static inline u32 rx_max(struct rockchip_spi *rs)
 static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
 {
        u32 ser;
-       struct rockchip_spi *rs = spi_master_get_devdata(spi->master);
+       struct spi_master *master = spi->master;
+       struct rockchip_spi *rs = spi_master_get_devdata(master);
+
+       pm_runtime_get_sync(rs->dev);
 
        ser = readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & SER_MASK;
 
@@ -290,6 +285,8 @@ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
                ser &= ~(1 << spi->chip_select);
 
        writel_relaxed(ser, rs->regs + ROCKCHIP_SPI_SER);
+
+       pm_runtime_put_sync(rs->dev);
 }
 
 static int rockchip_spi_prepare_message(struct spi_master *master,
@@ -319,12 +316,12 @@ static void rockchip_spi_handle_err(struct spi_master *master,
         */
        if (rs->use_dma) {
                if (rs->state & RXBUSY) {
-                       dmaengine_terminate_all(rs->dma_rx.ch);
+                       dmaengine_terminate_async(rs->dma_rx.ch);
                        flush_fifo(rs);
                }
 
                if (rs->state & TXBUSY)
-                       dmaengine_terminate_all(rs->dma_tx.ch);
+                       dmaengine_terminate_async(rs->dma_tx.ch);
        }
 
        spin_unlock_irqrestore(&rs->lock, flags);
@@ -433,7 +430,7 @@ static void rockchip_spi_dma_txcb(void *data)
        spin_unlock_irqrestore(&rs->lock, flags);
 }
 
-static void rockchip_spi_prepare_dma(struct rockchip_spi *rs)
+static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 {
        unsigned long flags;
        struct dma_slave_config rxconf, txconf;
@@ -456,6 +453,8 @@ static void rockchip_spi_prepare_dma(struct rockchip_spi *rs)
                                rs->dma_rx.ch,
                                rs->rx_sg.sgl, rs->rx_sg.nents,
                                rs->dma_rx.direction, DMA_PREP_INTERRUPT);
+               if (!rxdesc)
+                       return -EINVAL;
 
                rxdesc->callback = rockchip_spi_dma_rxcb;
                rxdesc->callback_param = rs;
@@ -473,6 +472,11 @@ static void rockchip_spi_prepare_dma(struct rockchip_spi *rs)
                                rs->dma_tx.ch,
                                rs->tx_sg.sgl, rs->tx_sg.nents,
                                rs->dma_tx.direction, DMA_PREP_INTERRUPT);
+               if (!txdesc) {
+                       if (rxdesc)
+                               dmaengine_terminate_sync(rs->dma_rx.ch);
+                       return -EINVAL;
+               }
 
                txdesc->callback = rockchip_spi_dma_txcb;
                txdesc->callback_param = rs;
@@ -494,6 +498,8 @@ static void rockchip_spi_prepare_dma(struct rockchip_spi *rs)
                dmaengine_submit(txdesc);
                dma_async_issue_pending(rs->dma_tx.ch);
        }
+
+       return 0;
 }
 
 static void rockchip_spi_config(struct rockchip_spi *rs)
@@ -503,7 +509,8 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
        int rsd = 0;
 
        u32 cr0 = (CR0_BHT_8BIT << CR0_BHT_OFFSET)
-               | (CR0_SSD_ONE << CR0_SSD_OFFSET);
+               | (CR0_SSD_ONE << CR0_SSD_OFFSET)
+               | (CR0_EM_BIG << CR0_EM_OFFSET);
 
        cr0 |= (rs->n_bytes << CR0_DFS_OFFSET);
        cr0 |= ((rs->mode & 0x3) << CR0_SCPH_OFFSET);
@@ -606,12 +613,12 @@ static int rockchip_spi_transfer_one(
        if (rs->use_dma) {
                if (rs->tmode == CR0_XFM_RO) {
                        /* rx: dma must be prepared first */
-                       rockchip_spi_prepare_dma(rs);
+                       ret = rockchip_spi_prepare_dma(rs);
                        spi_enable_chip(rs, 1);
                } else {
                        /* tx or tr: spi must be enabled first */
                        spi_enable_chip(rs, 1);
-                       rockchip_spi_prepare_dma(rs);
+                       ret = rockchip_spi_prepare_dma(rs);
                }
        } else {
                spi_enable_chip(rs, 1);
@@ -717,8 +724,14 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        master->handle_err = rockchip_spi_handle_err;
 
        rs->dma_tx.ch = dma_request_slave_channel(rs->dev, "tx");
-       if (!rs->dma_tx.ch)
+       if (IS_ERR_OR_NULL(rs->dma_tx.ch)) {
+               /* Check tx to see if we need defer probing driver */
+               if (PTR_ERR(rs->dma_tx.ch) == -EPROBE_DEFER) {
+                       ret = -EPROBE_DEFER;
+                       goto err_get_fifo_len;
+               }
                dev_warn(rs->dev, "Failed to request TX DMA channel\n");
+       }
 
        rs->dma_rx.ch = dma_request_slave_channel(rs->dev, "rx");
        if (!rs->dma_rx.ch) {
@@ -749,6 +762,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
        return 0;
 
 err_register_master:
+       pm_runtime_disable(&pdev->dev);
        if (rs->dma_tx.ch)
                dma_release_channel(rs->dma_tx.ch);
        if (rs->dma_rx.ch)
@@ -778,6 +792,8 @@ static int rockchip_spi_remove(struct platform_device *pdev)
        if (rs->dma_rx.ch)
                dma_release_channel(rs->dma_rx.ch);
 
+       spi_master_put(master);
+
        return 0;
 }
 
@@ -868,6 +884,7 @@ static const struct of_device_id rockchip_spi_dt_match[] = {
        { .compatible = "rockchip,rk3066-spi", },
        { .compatible = "rockchip,rk3188-spi", },
        { .compatible = "rockchip,rk3288-spi", },
+       { .compatible = "rockchip,rk3399-spi", },
        { },
 };
 MODULE_DEVICE_TABLE(of, rockchip_spi_dt_match);
index 64318fcfacf275c989ebe19d157eb8ff9e523ebf..eac3c960b2decb8c4aa73f73894b16ac3021beba 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include <linux/spi/spi.h>
 
@@ -44,8 +46,9 @@ struct ti_qspi {
 
        struct spi_master       *master;
        void __iomem            *base;
-       void __iomem            *ctrl_base;
        void __iomem            *mmap_base;
+       struct regmap           *ctrl_base;
+       unsigned int            ctrl_reg;
        struct clk              *fclk;
        struct device           *dev;
 
@@ -55,7 +58,7 @@ struct ti_qspi {
        u32 cmd;
        u32 dc;
 
-       bool ctrl_mod;
+       bool mmap_enabled;
 };
 
 #define QSPI_PID                       (0x0)
@@ -65,11 +68,8 @@ struct ti_qspi {
 #define QSPI_SPI_CMD_REG               (0x48)
 #define QSPI_SPI_STATUS_REG            (0x4c)
 #define QSPI_SPI_DATA_REG              (0x50)
-#define QSPI_SPI_SETUP0_REG            (0x54)
+#define QSPI_SPI_SETUP_REG(n)          ((0x54 + 4 * n))
 #define QSPI_SPI_SWITCH_REG            (0x64)
-#define QSPI_SPI_SETUP1_REG            (0x58)
-#define QSPI_SPI_SETUP2_REG            (0x5c)
-#define QSPI_SPI_SETUP3_REG            (0x60)
 #define QSPI_SPI_DATA_REG_1            (0x68)
 #define QSPI_SPI_DATA_REG_2            (0x6c)
 #define QSPI_SPI_DATA_REG_3            (0x70)
@@ -109,6 +109,17 @@ struct ti_qspi {
 
 #define QSPI_AUTOSUSPEND_TIMEOUT         2000
 
+#define MEM_CS_EN(n)                   ((n + 1) << 8)
+#define MEM_CS_MASK                    (7 << 8)
+
+#define MM_SWITCH                      0x1
+
+#define QSPI_SETUP_RD_NORMAL           (0x0 << 12)
+#define QSPI_SETUP_RD_DUAL             (0x1 << 12)
+#define QSPI_SETUP_RD_QUAD             (0x3 << 12)
+#define QSPI_SETUP_ADDR_SHIFT          8
+#define QSPI_SETUP_DUMMY_SHIFT         10
+
 static inline unsigned long ti_qspi_read(struct ti_qspi *qspi,
                unsigned long reg)
 {
@@ -366,6 +377,72 @@ static int qspi_transfer_msg(struct ti_qspi *qspi, struct spi_transfer *t)
        return 0;
 }
 
+static void ti_qspi_enable_memory_map(struct spi_device *spi)
+{
+       struct ti_qspi  *qspi = spi_master_get_devdata(spi->master);
+
+       ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG);
+       if (qspi->ctrl_base) {
+               regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
+                                  MEM_CS_EN(spi->chip_select),
+                                  MEM_CS_MASK);
+       }
+       qspi->mmap_enabled = true;
+}
+
+static void ti_qspi_disable_memory_map(struct spi_device *spi)
+{
+       struct ti_qspi  *qspi = spi_master_get_devdata(spi->master);
+
+       ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG);
+       if (qspi->ctrl_base)
+               regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
+                                  0, MEM_CS_MASK);
+       qspi->mmap_enabled = false;
+}
+
+static void ti_qspi_setup_mmap_read(struct spi_device *spi,
+                                   struct spi_flash_read_message *msg)
+{
+       struct ti_qspi  *qspi = spi_master_get_devdata(spi->master);
+       u32 memval = msg->read_opcode;
+
+       switch (msg->data_nbits) {
+       case SPI_NBITS_QUAD:
+               memval |= QSPI_SETUP_RD_QUAD;
+               break;
+       case SPI_NBITS_DUAL:
+               memval |= QSPI_SETUP_RD_DUAL;
+               break;
+       default:
+               memval |= QSPI_SETUP_RD_NORMAL;
+               break;
+       }
+       memval |= ((msg->addr_width - 1) << QSPI_SETUP_ADDR_SHIFT |
+                  msg->dummy_bytes << QSPI_SETUP_DUMMY_SHIFT);
+       ti_qspi_write(qspi, memval,
+                     QSPI_SPI_SETUP_REG(spi->chip_select));
+}
+
+static int ti_qspi_spi_flash_read(struct  spi_device *spi,
+                                 struct spi_flash_read_message *msg)
+{
+       struct ti_qspi *qspi = spi_master_get_devdata(spi->master);
+       int ret = 0;
+
+       mutex_lock(&qspi->list_lock);
+
+       if (!qspi->mmap_enabled)
+               ti_qspi_enable_memory_map(spi);
+       ti_qspi_setup_mmap_read(spi, msg);
+       memcpy_fromio(msg->buf, qspi->mmap_base + msg->from, msg->len);
+       msg->retlen = msg->len;
+
+       mutex_unlock(&qspi->list_lock);
+
+       return ret;
+}
+
 static int ti_qspi_start_transfer_one(struct spi_master *master,
                struct spi_message *m)
 {
@@ -398,6 +475,9 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
 
        mutex_lock(&qspi->list_lock);
 
+       if (qspi->mmap_enabled)
+               ti_qspi_disable_memory_map(spi);
+
        list_for_each_entry(t, &m->transfers, transfer_list) {
                qspi->cmd |= QSPI_WLEN(t->bits_per_word);
 
@@ -441,7 +521,7 @@ static int ti_qspi_probe(struct platform_device *pdev)
 {
        struct  ti_qspi *qspi;
        struct spi_master *master;
-       struct resource         *r, *res_ctrl, *res_mmap;
+       struct resource         *r, *res_mmap;
        struct device_node *np = pdev->dev.of_node;
        u32 max_freq;
        int ret = 0, num_cs, irq;
@@ -487,16 +567,6 @@ static int ti_qspi_probe(struct platform_device *pdev)
                }
        }
 
-       res_ctrl = platform_get_resource_byname(pdev,
-                       IORESOURCE_MEM, "qspi_ctrlmod");
-       if (res_ctrl == NULL) {
-               res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-               if (res_ctrl == NULL) {
-                       dev_dbg(&pdev->dev,
-                               "control module resources not required\n");
-               }
-       }
-
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(&pdev->dev, "no irq resource?\n");
@@ -511,20 +581,31 @@ static int ti_qspi_probe(struct platform_device *pdev)
                goto free_master;
        }
 
-       if (res_ctrl) {
-               qspi->ctrl_mod = true;
-               qspi->ctrl_base = devm_ioremap_resource(&pdev->dev, res_ctrl);
-               if (IS_ERR(qspi->ctrl_base)) {
-                       ret = PTR_ERR(qspi->ctrl_base);
-                       goto free_master;
-               }
-       }
-
        if (res_mmap) {
-               qspi->mmap_base = devm_ioremap_resource(&pdev->dev, res_mmap);
+               qspi->mmap_base = devm_ioremap_resource(&pdev->dev,
+                                                       res_mmap);
+               master->spi_flash_read = ti_qspi_spi_flash_read;
                if (IS_ERR(qspi->mmap_base)) {
-                       ret = PTR_ERR(qspi->mmap_base);
-                       goto free_master;
+                       dev_err(&pdev->dev,
+                               "falling back to PIO mode\n");
+                       master->spi_flash_read = NULL;
+               }
+       }
+       qspi->mmap_enabled = false;
+
+       if (of_property_read_bool(np, "syscon-chipselects")) {
+               qspi->ctrl_base =
+               syscon_regmap_lookup_by_phandle(np,
+                                               "syscon-chipselects");
+               if (IS_ERR(qspi->ctrl_base))
+                       return PTR_ERR(qspi->ctrl_base);
+               ret = of_property_read_u32_index(np,
+                                                "syscon-chipselects",
+                                                1, &qspi->ctrl_reg);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "couldn't get ctrl_mod reg index\n");
+                       return ret;
                }
        }
 
index 47eff8012a7715c362eb3ac3e706f8a9ea6e71c2..de2f2f90d7995a52ce4f803cf41ba32992e2664b 100644 (file)
@@ -144,6 +144,8 @@ SPI_STATISTICS_TRANSFER_BYTES_HISTO(14, "16384-32767");
 SPI_STATISTICS_TRANSFER_BYTES_HISTO(15, "32768-65535");
 SPI_STATISTICS_TRANSFER_BYTES_HISTO(16, "65536+");
 
+SPI_STATISTICS_SHOW(transfers_split_maxsize, "%lu");
+
 static struct attribute *spi_dev_attrs[] = {
        &dev_attr_modalias.attr,
        NULL,
@@ -181,6 +183,7 @@ static struct attribute *spi_device_statistics_attrs[] = {
        &dev_attr_spi_device_transfer_bytes_histo14.attr,
        &dev_attr_spi_device_transfer_bytes_histo15.attr,
        &dev_attr_spi_device_transfer_bytes_histo16.attr,
+       &dev_attr_spi_device_transfers_split_maxsize.attr,
        NULL,
 };
 
@@ -223,6 +226,7 @@ static struct attribute *spi_master_statistics_attrs[] = {
        &dev_attr_spi_master_transfer_bytes_histo14.attr,
        &dev_attr_spi_master_transfer_bytes_histo15.attr,
        &dev_attr_spi_master_transfer_bytes_histo16.attr,
+       &dev_attr_spi_master_transfers_split_maxsize.attr,
        NULL,
 };
 
@@ -702,6 +706,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
                       enum dma_data_direction dir)
 {
        const bool vmalloced_buf = is_vmalloc_addr(buf);
+       unsigned int max_seg_size = dma_get_max_seg_size(dev);
        int desc_len;
        int sgs;
        struct page *vm_page;
@@ -710,10 +715,10 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
        int i, ret;
 
        if (vmalloced_buf) {
-               desc_len = PAGE_SIZE;
+               desc_len = min_t(int, max_seg_size, PAGE_SIZE);
                sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
        } else {
-               desc_len = master->max_dma_len;
+               desc_len = min_t(int, max_seg_size, master->max_dma_len);
                sgs = DIV_ROUND_UP(len, desc_len);
        }
 
@@ -739,7 +744,6 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
                        sg_set_buf(&sgt->sgl[i], sg_buf, min);
                }
 
-
                buf += min;
                len -= min;
        }
@@ -1024,6 +1028,8 @@ out:
        if (msg->status && master->handle_err)
                master->handle_err(master, msg);
 
+       spi_res_release(master, msg);
+
        spi_finalize_current_message(master);
 
        return ret;
@@ -1047,6 +1053,7 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
  * __spi_pump_messages - function which processes spi message queue
  * @master: master to process queue for
  * @in_kthread: true if we are in the context of the message pump thread
+ * @bus_locked: true if the bus mutex is held when calling this function
  *
  * This function checks if there is any spi message in the queue that
  * needs processing and if so call out to the driver to initialize hardware
@@ -1056,7 +1063,8 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
  * inside spi_sync(); the queue extraction handling at the top of the
  * function should deal with this safely.
  */
-static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
+static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
+                               bool bus_locked)
 {
        unsigned long flags;
        bool was_busy = false;
@@ -1152,6 +1160,9 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
                }
        }
 
+       if (!bus_locked)
+               mutex_lock(&master->bus_lock_mutex);
+
        trace_spi_message_start(master->cur_msg);
 
        if (master->prepare_message) {
@@ -1161,7 +1172,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
                                "failed to prepare message: %d\n", ret);
                        master->cur_msg->status = ret;
                        spi_finalize_current_message(master);
-                       return;
+                       goto out;
                }
                master->cur_msg_prepared = true;
        }
@@ -1170,15 +1181,23 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
        if (ret) {
                master->cur_msg->status = ret;
                spi_finalize_current_message(master);
-               return;
+               goto out;
        }
 
        ret = master->transfer_one_message(master, master->cur_msg);
        if (ret) {
                dev_err(&master->dev,
                        "failed to transfer one message from queue\n");
-               return;
+               goto out;
        }
+
+out:
+       if (!bus_locked)
+               mutex_unlock(&master->bus_lock_mutex);
+
+       /* Prod the scheduler in case transfer_one() was busy waiting */
+       if (!ret)
+               cond_resched();
 }
 
 /**
@@ -1190,7 +1209,7 @@ static void spi_pump_messages(struct kthread_work *work)
        struct spi_master *master =
                container_of(work, struct spi_master, pump_messages);
 
-       __spi_pump_messages(master, true);
+       __spi_pump_messages(master, true, false);
 }
 
 static int spi_init_queue(struct spi_master *master)
@@ -1581,13 +1600,30 @@ static void of_register_spi_devices(struct spi_master *master) { }
 static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
 {
        struct spi_device *spi = data;
+       struct spi_master *master = spi->master;
 
        if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
                struct acpi_resource_spi_serialbus *sb;
 
                sb = &ares->data.spi_serial_bus;
                if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
-                       spi->chip_select = sb->device_selection;
+                       /*
+                        * ACPI DeviceSelection numbering is handled by the
+                        * host controller driver in Windows and can vary
+                        * from driver to driver. In Linux we always expect
+                        * 0 .. max - 1 so we need to ask the driver to
+                        * translate between the two schemes.
+                        */
+                       if (master->fw_translate_cs) {
+                               int cs = master->fw_translate_cs(master,
+                                               sb->device_selection);
+                               if (cs < 0)
+                                       return cs;
+                               spi->chip_select = cs;
+                       } else {
+                               spi->chip_select = sb->device_selection;
+                       }
+
                        spi->max_speed_hz = sb->connection_speed;
 
                        if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
@@ -2013,6 +2049,336 @@ struct spi_master *spi_busnum_to_master(u16 bus_num)
 }
 EXPORT_SYMBOL_GPL(spi_busnum_to_master);
 
+/*-------------------------------------------------------------------------*/
+
+/* Core methods for SPI resource management */
+
+/**
+ * spi_res_alloc - allocate a spi resource that is life-cycle managed
+ *                 during the processing of a spi_message while using
+ *                 spi_transfer_one
+ * @spi:     the spi device for which we allocate memory
+ * @release: the release code to execute for this resource
+ * @size:    size to alloc and return
+ * @gfp:     GFP allocation flags
+ *
+ * Return: the pointer to the allocated data
+ *
+ * This may get enhanced in the future to allocate from a memory pool
+ * of the @spi_device or @spi_master to avoid repeated allocations.
+ */
+void *spi_res_alloc(struct spi_device *spi,
+                   spi_res_release_t release,
+                   size_t size, gfp_t gfp)
+{
+       struct spi_res *sres;
+
+       sres = kzalloc(sizeof(*sres) + size, gfp);
+       if (!sres)
+               return NULL;
+
+       INIT_LIST_HEAD(&sres->entry);
+       sres->release = release;
+
+       return sres->data;
+}
+EXPORT_SYMBOL_GPL(spi_res_alloc);
+
+/**
+ * spi_res_free - free an spi resource
+ * @res: pointer to the custom data of a resource
+ *
+ */
+void spi_res_free(void *res)
+{
+       struct spi_res *sres = container_of(res, struct spi_res, data);
+
+       if (!res)
+               return;
+
+       WARN_ON(!list_empty(&sres->entry));
+       kfree(sres);
+}
+EXPORT_SYMBOL_GPL(spi_res_free);
+
+/**
+ * spi_res_add - add a spi_res to the spi_message
+ * @message: the spi message
+ * @res:     the spi_resource
+ */
+void spi_res_add(struct spi_message *message, void *res)
+{
+       struct spi_res *sres = container_of(res, struct spi_res, data);
+
+       WARN_ON(!list_empty(&sres->entry));
+       list_add_tail(&sres->entry, &message->resources);
+}
+EXPORT_SYMBOL_GPL(spi_res_add);
+
+/**
+ * spi_res_release - release all spi resources for this message
+ * @master:  the @spi_master
+ * @message: the @spi_message
+ */
+void spi_res_release(struct spi_master *master,
+                    struct spi_message *message)
+{
+       struct spi_res *res;
+
+       while (!list_empty(&message->resources)) {
+               res = list_last_entry(&message->resources,
+                                     struct spi_res, entry);
+
+               if (res->release)
+                       res->release(master, message, res->data);
+
+               list_del(&res->entry);
+
+               kfree(res);
+       }
+}
+EXPORT_SYMBOL_GPL(spi_res_release);
+
+/*-------------------------------------------------------------------------*/
+
+/* Core methods for spi_message alterations */
+
+static void __spi_replace_transfers_release(struct spi_master *master,
+                                           struct spi_message *msg,
+                                           void *res)
+{
+       struct spi_replaced_transfers *rxfer = res;
+       size_t i;
+
+       /* call extra callback if requested */
+       if (rxfer->release)
+               rxfer->release(master, msg, res);
+
+       /* insert replaced transfers back into the message */
+       list_splice(&rxfer->replaced_transfers, rxfer->replaced_after);
+
+       /* remove the formerly inserted entries */
+       for (i = 0; i < rxfer->inserted; i++)
+               list_del(&rxfer->inserted_transfers[i].transfer_list);
+}
+
+/**
+ * spi_replace_transfers - replace transfers with several transfers
+ *                         and register change with spi_message.resources
+ * @msg:           the spi_message we work upon
+ * @xfer_first:    the first spi_transfer we want to replace
+ * @remove:        number of transfers to remove
+ * @insert:        the number of transfers we want to insert instead
+ * @release:       extra release code necessary in some circumstances
+ * @extradatasize: extra data to allocate (with alignment guarantees
+ *                 of struct @spi_transfer)
+ * @gfp:           gfp flags
+ *
+ * Returns: pointer to @spi_replaced_transfers,
+ *          PTR_ERR(...) in case of errors.
+ */
+struct spi_replaced_transfers *spi_replace_transfers(
+       struct spi_message *msg,
+       struct spi_transfer *xfer_first,
+       size_t remove,
+       size_t insert,
+       spi_replaced_release_t release,
+       size_t extradatasize,
+       gfp_t gfp)
+{
+       struct spi_replaced_transfers *rxfer;
+       struct spi_transfer *xfer;
+       size_t i;
+
+       /* allocate the structure using spi_res */
+       rxfer = spi_res_alloc(msg->spi, __spi_replace_transfers_release,
+                             insert * sizeof(struct spi_transfer)
+                             + sizeof(struct spi_replaced_transfers)
+                             + extradatasize,
+                             gfp);
+       if (!rxfer)
+               return ERR_PTR(-ENOMEM);
+
+       /* the release code to invoke before running the generic release */
+       rxfer->release = release;
+
+       /* assign extradata */
+       if (extradatasize)
+               rxfer->extradata =
+                       &rxfer->inserted_transfers[insert];
+
+       /* init the replaced_transfers list */
+       INIT_LIST_HEAD(&rxfer->replaced_transfers);
+
+       /* assign the list_entry after which we should reinsert
+        * the @replaced_transfers - it may be spi_message.messages!
+        */
+       rxfer->replaced_after = xfer_first->transfer_list.prev;
+
+       /* remove the requested number of transfers */
+       for (i = 0; i < remove; i++) {
+               /* if the entry after replaced_after it is msg->transfers
+                * then we have been requested to remove more transfers
+                * than are in the list
+                */
+               if (rxfer->replaced_after->next == &msg->transfers) {
+                       dev_err(&msg->spi->dev,
+                               "requested to remove more spi_transfers than are available\n");
+                       /* insert replaced transfers back into the message */
+                       list_splice(&rxfer->replaced_transfers,
+                                   rxfer->replaced_after);
+
+                       /* free the spi_replace_transfer structure */
+                       spi_res_free(rxfer);
+
+                       /* and return with an error */
+                       return ERR_PTR(-EINVAL);
+               }
+
+               /* remove the entry after replaced_after from list of
+                * transfers and add it to list of replaced_transfers
+                */
+               list_move_tail(rxfer->replaced_after->next,
+                              &rxfer->replaced_transfers);
+       }
+
+       /* create copy of the given xfer with identical settings
+        * based on the first transfer to get removed
+        */
+       for (i = 0; i < insert; i++) {
+               /* we need to run in reverse order */
+               xfer = &rxfer->inserted_transfers[insert - 1 - i];
+
+               /* copy all spi_transfer data */
+               memcpy(xfer, xfer_first, sizeof(*xfer));
+
+               /* add to list */
+               list_add(&xfer->transfer_list, rxfer->replaced_after);
+
+               /* clear cs_change and delay_usecs for all but the last */
+               if (i) {
+                       xfer->cs_change = false;
+                       xfer->delay_usecs = 0;
+               }
+       }
+
+       /* set up inserted */
+       rxfer->inserted = insert;
+
+       /* and register it with spi_res/spi_message */
+       spi_res_add(msg, rxfer);
+
+       return rxfer;
+}
+EXPORT_SYMBOL_GPL(spi_replace_transfers);
+
+static int __spi_split_transfer_maxsize(struct spi_master *master,
+                                       struct spi_message *msg,
+                                       struct spi_transfer **xferp,
+                                       size_t maxsize,
+                                       gfp_t gfp)
+{
+       struct spi_transfer *xfer = *xferp, *xfers;
+       struct spi_replaced_transfers *srt;
+       size_t offset;
+       size_t count, i;
+
+       /* warn once about this fact that we are splitting a transfer */
+       dev_warn_once(&msg->spi->dev,
+                     "spi_transfer of length %i exceed max length of %zu - needed to split transfers\n",
+                     xfer->len, maxsize);
+
+       /* calculate how many we have to replace */
+       count = DIV_ROUND_UP(xfer->len, maxsize);
+
+       /* create replacement */
+       srt = spi_replace_transfers(msg, xfer, 1, count, NULL, 0, gfp);
+       if (IS_ERR(srt))
+               return PTR_ERR(srt);
+       xfers = srt->inserted_transfers;
+
+       /* now handle each of those newly inserted spi_transfers
+        * note that the replacements spi_transfers all are preset
+        * to the same values as *xferp, so tx_buf, rx_buf and len
+        * are all identical (as well as most others)
+        * so we just have to fix up len and the pointers.
+        *
+        * this also includes support for the depreciated
+        * spi_message.is_dma_mapped interface
+        */
+
+       /* the first transfer just needs the length modified, so we
+        * run it outside the loop
+        */
+       xfers[0].len = min_t(size_t, maxsize, xfer[0].len);
+
+       /* all the others need rx_buf/tx_buf also set */
+       for (i = 1, offset = maxsize; i < count; offset += maxsize, i++) {
+               /* update rx_buf, tx_buf and dma */
+               if (xfers[i].rx_buf)
+                       xfers[i].rx_buf += offset;
+               if (xfers[i].rx_dma)
+                       xfers[i].rx_dma += offset;
+               if (xfers[i].tx_buf)
+                       xfers[i].tx_buf += offset;
+               if (xfers[i].tx_dma)
+                       xfers[i].tx_dma += offset;
+
+               /* update length */
+               xfers[i].len = min(maxsize, xfers[i].len - offset);
+       }
+
+       /* we set up xferp to the last entry we have inserted,
+        * so that we skip those already split transfers
+        */
+       *xferp = &xfers[count - 1];
+
+       /* increment statistics counters */
+       SPI_STATISTICS_INCREMENT_FIELD(&master->statistics,
+                                      transfers_split_maxsize);
+       SPI_STATISTICS_INCREMENT_FIELD(&msg->spi->statistics,
+                                      transfers_split_maxsize);
+
+       return 0;
+}
+
+/**
+ * spi_split_tranfers_maxsize - split spi transfers into multiple transfers
+ *                              when an individual transfer exceeds a
+ *                              certain size
+ * @master:    the @spi_master for this transfer
+ * @msg:   the @spi_message to transform
+ * @maxsize:  the maximum when to apply this
+ * @gfp: GFP allocation flags
+ *
+ * Return: status of transformation
+ */
+int spi_split_transfers_maxsize(struct spi_master *master,
+                               struct spi_message *msg,
+                               size_t maxsize,
+                               gfp_t gfp)
+{
+       struct spi_transfer *xfer;
+       int ret;
+
+       /* iterate over the transfer_list,
+        * but note that xfer is advanced to the last transfer inserted
+        * to avoid checking sizes again unnecessarily (also xfer does
+        * potentiall belong to a different list by the time the
+        * replacement has happened
+        */
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               if (xfer->len > maxsize) {
+                       ret = __spi_split_transfer_maxsize(
+                               master, msg, &xfer, maxsize, gfp);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(spi_split_transfers_maxsize);
 
 /*-------------------------------------------------------------------------*/
 
@@ -2351,6 +2717,46 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message)
 EXPORT_SYMBOL_GPL(spi_async_locked);
 
 
+int spi_flash_read(struct spi_device *spi,
+                  struct spi_flash_read_message *msg)
+
+{
+       struct spi_master *master = spi->master;
+       int ret;
+
+       if ((msg->opcode_nbits == SPI_NBITS_DUAL ||
+            msg->addr_nbits == SPI_NBITS_DUAL) &&
+           !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD)))
+               return -EINVAL;
+       if ((msg->opcode_nbits == SPI_NBITS_QUAD ||
+            msg->addr_nbits == SPI_NBITS_QUAD) &&
+           !(spi->mode & SPI_TX_QUAD))
+               return -EINVAL;
+       if (msg->data_nbits == SPI_NBITS_DUAL &&
+           !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD)))
+               return -EINVAL;
+       if (msg->data_nbits == SPI_NBITS_QUAD &&
+           !(spi->mode &  SPI_RX_QUAD))
+               return -EINVAL;
+
+       if (master->auto_runtime_pm) {
+               ret = pm_runtime_get_sync(master->dev.parent);
+               if (ret < 0) {
+                       dev_err(&master->dev, "Failed to power device: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+       mutex_lock(&master->bus_lock_mutex);
+       ret = master->spi_flash_read(spi, msg);
+       mutex_unlock(&master->bus_lock_mutex);
+       if (master->auto_runtime_pm)
+               pm_runtime_put(master->dev.parent);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(spi_flash_read);
+
 /*-------------------------------------------------------------------------*/
 
 /* Utility methods for SPI master protocol drivers, layered on
@@ -2414,7 +2820,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
                                                       spi_sync_immediate);
                        SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
                                                       spi_sync_immediate);
-                       __spi_pump_messages(master, false);
+                       __spi_pump_messages(master, false, bus_locked);
                }
 
                wait_for_completion(&done);
index 0c675861623f4abeb2054b65c87fe185d8188bf3..d8e4219c2324900c583245407a7c78f20e20325e 100644 (file)
@@ -83,6 +83,7 @@ config SSB_SDIOHOST
 config SSB_HOST_SOC
        bool "Support for SSB bus on SoC"
        depends on SSB && BCM47XX_NVRAM
+       select SSB_SPROM
        help
          Host interface for a SSB directly mapped into memory. This is
          for some Broadcom SoCs from the BCM47xx and BCM53xx lines.
index 3ec7e65a3ffa524efb6e95d98bbc6916592d2a18..db49af90217e3f62cc6f8e3dcf1ec713a732abb2 100644 (file)
@@ -147,7 +147,7 @@ static int vpfe_prepare_pipeline(struct vpfe_video_device *video)
        mutex_lock(&mdev->graph_mutex);
        ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev);
        if (ret) {
-               mutex_unlock(&video->lock);
+               mutex_unlock(&mdev->graph_mutex);
                return -ENOMEM;
        }
        media_entity_graph_walk_start(&graph, entity);
index 82a663ba98009fb5f286a88651c9b3a54cf68bbb..4f229e711e1c1cfc0134abb71b617f9511a6e606 100644 (file)
@@ -177,7 +177,6 @@ void core_tmr_abort_task(
 
                if (!__target_check_io_state(se_cmd, se_sess, 0)) {
                        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
-                       target_put_sess_cmd(se_cmd);
                        goto out;
                }
                list_del_init(&se_cmd->se_cmd_list);
index b59195edf63634a3be94bcd3dc9ede6d87699185..b635ab67490de3a93a9c0df0f17848376ae1d947 100644 (file)
@@ -85,8 +85,8 @@ static int ci_hdrc_pci_probe(struct pci_dev *pdev,
 
        /* register a nop PHY */
        ci->phy = usb_phy_generic_register();
-       if (!ci->phy)
-               return -ENOMEM;
+       if (IS_ERR(ci->phy))
+               return PTR_ERR(ci->phy);
 
        memset(res, 0, sizeof(res));
        res[0].start    = pci_resource_start(pdev, 0);
index a4f7db2e18ddc295fc4ff1a0cad99bc1ff8b04bd..df47110bad2d6f277b3893bf48657ecfde165fcf 100644 (file)
@@ -100,6 +100,9 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
        if (sscanf(buf, "%u", &mode) != 1)
                return -EINVAL;
 
+       if (mode > 255)
+               return -EBADRQC;
+
        pm_runtime_get_sync(ci->dev);
        spin_lock_irqsave(&ci->lock, flags);
        ret = hw_port_test_set(ci, mode);
index 45f86da1d6d37b4650ddfaf216879195ca9c6542..03b6743461d15de129a2d7908e851db450111d3c 100644 (file)
@@ -158,7 +158,7 @@ static void ci_otg_work(struct work_struct *work)
 int ci_hdrc_otg_init(struct ci_hdrc *ci)
 {
        INIT_WORK(&ci->work, ci_otg_work);
-       ci->wq = create_singlethread_workqueue("ci_otg");
+       ci->wq = create_freezable_workqueue("ci_otg");
        if (!ci->wq) {
                dev_err(ci->dev, "can't create workqueue\n");
                return -ENODEV;
index 9eb1cff28bd4b2499e4dfd9ed8b91e53901df184..c3640f8a8fb34440a8cb96b0320c26835131cbef 100644 (file)
@@ -28,7 +28,6 @@
 #ifdef CONFIG_PPC_PMAC
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
 #include <asm/prom.h>
 #endif
 
index 350dcd9af5d86eb2181e6cc8f77f25a33f712cce..51b436918f7892b1249c7ec1b19dad515a9a5755 100644 (file)
@@ -5401,6 +5401,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
        }
 
        bos = udev->bos;
+       udev->bos = NULL;
 
        for (i = 0; i < SET_CONFIG_TRIES; ++i) {
 
@@ -5493,11 +5494,8 @@ done:
        usb_set_usb2_hardware_lpm(udev, 1);
        usb_unlocked_enable_lpm(udev);
        usb_enable_ltm(udev);
-       /* release the new BOS descriptor allocated  by hub_port_init() */
-       if (udev->bos != bos) {
-               usb_release_bos_descriptor(udev);
-               udev->bos = bos;
-       }
+       usb_release_bos_descriptor(udev);
+       udev->bos = bos;
        return 0;
 
 re_enumerate:
index fd95ba6ec317fdacb13478d84c4157656893740c..f0decc0d69b5197d183c29ec16882a8fcc18208e 100644 (file)
@@ -1,5 +1,6 @@
 config USB_DWC2
        tristate "DesignWare USB2 DRD Core Support"
+       depends on HAS_DMA
        depends on USB || USB_GADGET
        help
          Say Y here if your system has a Dual Role Hi-Speed USB
index e991d55914db649804a6357821f42e78355e6e5b..46c4ba75dc2afdb744bd32fbf047949ff50ec1fd 100644 (file)
@@ -619,6 +619,12 @@ void dwc2_force_dr_mode(struct dwc2_hsotg *hsotg)
                         __func__, hsotg->dr_mode);
                break;
        }
+
+       /*
+        * NOTE: This is required for some rockchip soc based
+        * platforms.
+        */
+       msleep(50);
 }
 
 /*
index 36606fc33c0d31f0ed52d85bc626f3fe29e36099..a41274aa52adc5f8e1119544a90e8f79c421c2b5 100644 (file)
@@ -1174,14 +1174,11 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg,
        failed = dwc2_update_non_isoc_urb_state_ddma(hsotg, chan, qtd, dma_desc,
                                                     halt_status, n_bytes,
                                                     xfer_done);
-       if (*xfer_done && urb->status != -EINPROGRESS)
-               failed = 1;
-
-       if (failed) {
+       if (failed || (*xfer_done && urb->status != -EINPROGRESS)) {
                dwc2_host_complete(hsotg, qtd, urb->status);
                dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
-               dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n",
-                        failed, *xfer_done, urb->status);
+               dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x\n",
+                        failed, *xfer_done);
                return failed;
        }
 
@@ -1236,21 +1233,23 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
 
        list_for_each_safe(qtd_item, qtd_tmp, &qh->qtd_list) {
                int i;
+               int qtd_desc_count;
 
                qtd = list_entry(qtd_item, struct dwc2_qtd, qtd_list_entry);
                xfer_done = 0;
+               qtd_desc_count = qtd->n_desc;
 
-               for (i = 0; i < qtd->n_desc; i++) {
+               for (i = 0; i < qtd_desc_count; i++) {
                        if (dwc2_process_non_isoc_desc(hsotg, chan, chnum, qtd,
                                                       desc_num, halt_status,
-                                                      &xfer_done)) {
-                               qtd = NULL;
-                               break;
-                       }
+                                                      &xfer_done))
+                               goto stop_scan;
+
                        desc_num++;
                }
        }
 
+stop_scan:
        if (qh->ep_type != USB_ENDPOINT_XFER_CONTROL) {
                /*
                 * Resetting the data toggle for bulk and interrupt endpoints
@@ -1258,7 +1257,7 @@ static void dwc2_complete_non_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
                 */
                if (halt_status == DWC2_HC_XFER_STALL)
                        qh->data_toggle = DWC2_HC_PID_DATA0;
-               else if (qtd)
+               else
                        dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
        }
 
index f8253803a0507543f617af6e2aacc266b43762de..cadba8b13c4837d3e7a3432a3909d69239a70c5d 100644 (file)
@@ -525,11 +525,19 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
        u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT;
 
        if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) {
+               if (WARN(!chan || !chan->qh,
+                        "chan->qh must be specified for non-control eps\n"))
+                       return;
+
                if (pid == TSIZ_SC_MC_PID_DATA0)
                        chan->qh->data_toggle = DWC2_HC_PID_DATA0;
                else
                        chan->qh->data_toggle = DWC2_HC_PID_DATA1;
        } else {
+               if (WARN(!qtd,
+                        "qtd must be specified for control eps\n"))
+                       return;
+
                if (pid == TSIZ_SC_MC_PID_DATA0)
                        qtd->data_toggle = DWC2_HC_PID_DATA0;
                else
index 29130682e547e568fb92e32734dbf0141a5e1bef..e4f8b90d9627f9baed5fe4f7fd6dcac7963f49f5 100644 (file)
@@ -856,7 +856,6 @@ struct dwc3 {
        unsigned                pullups_connected:1;
        unsigned                resize_fifos:1;
        unsigned                setup_packet_pending:1;
-       unsigned                start_config_issued:1;
        unsigned                three_stage_setup:1;
        unsigned                usb3_lpm_capable:1;
 
index 3a9354abcb68bfc6e9d27cc64c7155d54dec04e0..8d6b75c2f53b2e0d0991ca3dddc784f6dccecadb 100644 (file)
@@ -555,7 +555,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        int ret;
        u32 reg;
 
-       dwc->start_config_issued = false;
        cfg = le16_to_cpu(ctrl->wValue);
 
        switch (state) {
@@ -737,10 +736,6 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
                dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
                ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
                break;
-       case USB_REQ_SET_INTERFACE:
-               dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE");
-               dwc->start_config_issued = false;
-               /* Fall through */
        default:
                dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
                ret = dwc3_ep0_delegate_req(dwc, ctrl);
index 7d1dd82a95ac7325c3da0b45d0d855a31f7f9965..2363bad45af865dd2e7ee0c28e009fff1ae7a7d5 100644 (file)
@@ -385,24 +385,66 @@ static void dwc3_free_trb_pool(struct dwc3_ep *dep)
        dep->trb_pool_dma = 0;
 }
 
+static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep);
+
+/**
+ * dwc3_gadget_start_config - Configure EP resources
+ * @dwc: pointer to our controller context structure
+ * @dep: endpoint that is being enabled
+ *
+ * The assignment of transfer resources cannot perfectly follow the
+ * data book due to the fact that the controller driver does not have
+ * all knowledge of the configuration in advance. It is given this
+ * information piecemeal by the composite gadget framework after every
+ * SET_CONFIGURATION and SET_INTERFACE. Trying to follow the databook
+ * programming model in this scenario can cause errors. For two
+ * reasons:
+ *
+ * 1) The databook says to do DEPSTARTCFG for every SET_CONFIGURATION
+ * and SET_INTERFACE (8.1.5). This is incorrect in the scenario of
+ * multiple interfaces.
+ *
+ * 2) The databook does not mention doing more DEPXFERCFG for new
+ * endpoint on alt setting (8.1.6).
+ *
+ * The following simplified method is used instead:
+ *
+ * All hardware endpoints can be assigned a transfer resource and this
+ * setting will stay persistent until either a core reset or
+ * hibernation. So whenever we do a DEPSTARTCFG(0) we can go ahead and
+ * do DEPXFERCFG for every hardware endpoint as well. We are
+ * guaranteed that there are as many transfer resources as endpoints.
+ *
+ * This function is called for each endpoint when it is being enabled
+ * but is triggered only when called for EP0-out, which always happens
+ * first, and which should only happen in one of the above conditions.
+ */
 static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
 {
        struct dwc3_gadget_ep_cmd_params params;
        u32                     cmd;
+       int                     i;
+       int                     ret;
+
+       if (dep->number)
+               return 0;
 
        memset(&params, 0x00, sizeof(params));
+       cmd = DWC3_DEPCMD_DEPSTARTCFG;
 
-       if (dep->number != 1) {
-               cmd = DWC3_DEPCMD_DEPSTARTCFG;
-               /* XferRscIdx == 0 for ep0 and 2 for the remaining */
-               if (dep->number > 1) {
-                       if (dwc->start_config_issued)
-                               return 0;
-                       dwc->start_config_issued = true;
-                       cmd |= DWC3_DEPCMD_PARAM(2);
-               }
+       ret = dwc3_send_gadget_ep_cmd(dwc, 0, cmd, &params);
+       if (ret)
+               return ret;
 
-               return dwc3_send_gadget_ep_cmd(dwc, 0, cmd, &params);
+       for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) {
+               struct dwc3_ep *dep = dwc->eps[i];
+
+               if (!dep)
+                       continue;
+
+               ret = dwc3_gadget_set_xfer_resource(dwc, dep);
+               if (ret)
+                       return ret;
        }
 
        return 0;
@@ -516,10 +558,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
                struct dwc3_trb *trb_st_hw;
                struct dwc3_trb *trb_link;
 
-               ret = dwc3_gadget_set_xfer_resource(dwc, dep);
-               if (ret)
-                       return ret;
-
                dep->endpoint.desc = desc;
                dep->comp_desc = comp_desc;
                dep->type = usb_endpoint_type(desc);
@@ -1636,8 +1674,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        }
        dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
-       dwc->start_config_issued = false;
-
        /* Start with SuperSpeed Default */
        dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
@@ -2237,7 +2273,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
        dwc3_writel(dwc->regs, DWC3_DCTL, reg);
 
        dwc3_disconnect_gadget(dwc);
-       dwc->start_config_issued = false;
 
        dwc->gadget.speed = USB_SPEED_UNKNOWN;
        dwc->setup_packet_pending = false;
@@ -2288,7 +2323,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 
        dwc3_stop_active_transfers(dwc);
        dwc3_clear_stall_all_ep(dwc);
-       dwc->start_config_issued = false;
 
        /* Reset device address to zero */
        reg = dwc3_readl(dwc->regs, DWC3_DCFG);
index 7e179f81d05cae3e91fd8b976a1f2665e3958cc3..87fb0fd6aaabea260758ba338769d6be70472740 100644 (file)
@@ -130,7 +130,8 @@ struct dev_data {
                                        setup_can_stall : 1,
                                        setup_out_ready : 1,
                                        setup_out_error : 1,
-                                       setup_abort : 1;
+                                       setup_abort : 1,
+                                       gadget_registered : 1;
        unsigned                        setup_wLength;
 
        /* the rest is basically write-once */
@@ -1179,7 +1180,8 @@ dev_release (struct inode *inode, struct file *fd)
 
        /* closing ep0 === shutdown all */
 
-       usb_gadget_unregister_driver (&gadgetfs_driver);
+       if (dev->gadget_registered)
+               usb_gadget_unregister_driver (&gadgetfs_driver);
 
        /* at this point "good" hardware has disconnected the
         * device from USB; the host won't see it any more.
@@ -1847,6 +1849,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                 * kick in after the ep0 descriptor is closed.
                 */
                value = len;
+               dev->gadget_registered = true;
        }
        return value;
 
index cd8764150861cf1c677bb25a52f4a1b00294b52e..39d70b4a89581620d329444af1af61367d8b40ea 100644 (file)
@@ -3397,7 +3397,7 @@ err_pcidev:
 static const struct pci_device_id pci_id[] = {
        {
                PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x2096),
-               .class =        (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class =        PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask =   0xffffffff,
        },
        {},
index 53c0692f1b096eef837624bda521a11ad3181fc4..93d28cb00b76f15de7f281f465a1c791aa7edbbe 100644 (file)
@@ -2340,7 +2340,7 @@ static struct qe_udc *qe_udc_config(struct platform_device *ofdev)
 {
        struct qe_udc *udc;
        struct device_node *np = ofdev->dev.of_node;
-       unsigned int tmp_addr = 0;
+       unsigned long tmp_addr = 0;
        struct usb_device_para __iomem *usbpram;
        unsigned int i;
        u64 size;
index 1fdfec14a3ba13eea57dfced8b170752e452fdb2..d2205d9e0c8b43265901352548342b0e8646ca97 100644 (file)
@@ -1846,7 +1846,7 @@ err:
 /*-------------------------------------------------------------------------*/
 
 static const struct pci_device_id pci_ids[] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       0x102f,         /* Toshiba */
        .device =       0x0107,         /* this UDC */
index 6706aef907f4bdb32b308f148612a2566c2eb3b9..c894b94b234bf58aba86cea8a341abb88941e61a 100644 (file)
@@ -3735,7 +3735,7 @@ static void net2280_shutdown(struct pci_dev *pdev)
 /*-------------------------------------------------------------------------*/
 
 static const struct pci_device_id pci_ids[] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       PCI_VENDOR_ID_PLX_LEGACY,
        .device =       0x2280,
@@ -3743,7 +3743,7 @@ static const struct pci_device_id pci_ids[] = { {
        .subdevice =    PCI_ANY_ID,
        .driver_data =  PLX_LEGACY | PLX_2280,
        }, {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       PCI_VENDOR_ID_PLX_LEGACY,
        .device =       0x2282,
@@ -3752,7 +3752,7 @@ static const struct pci_device_id pci_ids[] = { {
        .driver_data =  PLX_LEGACY,
        },
        {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       PCI_VENDOR_ID_PLX,
        .device =       0x3380,
@@ -3761,7 +3761,7 @@ static const struct pci_device_id pci_ids[] = { {
        .driver_data =  PLX_SUPERSPEED,
         },
        {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class =        PCI_CLASS_SERIAL_USB_DEVICE,
        .class_mask =   ~0,
        .vendor =       PCI_VENDOR_ID_PLX,
        .device =       0x3382,
index 4dff60d34f732097752e59360e0edcf7e5eb90b4..0d32052bf16f90d5e1ace964cedd484c14a6f65d 100644 (file)
@@ -369,9 +369,20 @@ static inline void set_max_speed(struct net2280_ep *ep, u32 max)
        static const u32 ep_enhanced[9] = { 0x10, 0x60, 0x30, 0x80,
                                          0x50, 0x20, 0x70, 0x40, 0x90 };
 
-       if (ep->dev->enhanced_mode)
+       if (ep->dev->enhanced_mode) {
                reg = ep_enhanced[ep->num];
-       else{
+               switch (ep->dev->gadget.speed) {
+               case USB_SPEED_SUPER:
+                       reg += 2;
+                       break;
+               case USB_SPEED_FULL:
+                       reg += 1;
+                       break;
+               case USB_SPEED_HIGH:
+               default:
+                       break;
+               }
+       } else {
                reg = (ep->num + 1) * 0x10;
                if (ep->dev->gadget.speed != USB_SPEED_HIGH)
                        reg += 1;
index 7a04157ff5796883f8c9ec3835b43c16155fbc3d..9571ef54b86b53fcda4ba6517ed75e02f1751abb 100644 (file)
@@ -3234,22 +3234,22 @@ static const struct pci_device_id pch_udc_pcidev_id[] = {
        {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL,
                           PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class = PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask = 0xffffffff,
        },
        {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class = PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask = 0xffffffff,
        },
        {
                PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7213_IOH_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class = PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask = 0xffffffff,
        },
        {
                PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7831_IOH_UDC),
-               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class = PCI_CLASS_SERIAL_USB_DEVICE,
                .class_mask = 0xffffffff,
        },
        { 0 },
index fd73a3ea07c20e4cac1100be1883dce5ea81c033..b86a6f03592ec9e1d42f5bdc813b83c1297b6e52 100644 (file)
@@ -413,9 +413,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
                if (!driver->udc_name || strcmp(driver->udc_name,
                                                dev_name(&udc->dev)) == 0) {
                        ret = udc_bind_to_driver(udc, driver);
+                       if (ret != -EPROBE_DEFER)
+                               list_del(&driver->pending);
                        if (ret)
                                goto err4;
-                       list_del(&driver->pending);
                        break;
                }
        }
index 795a45b1b25bacb016552b4d0635166965ebfce6..58487a4735218518ce50326750ca8718aaa2a516 100644 (file)
@@ -662,7 +662,7 @@ static int musb_tx_dma_set_mode_mentor(struct dma_controller *dma,
                csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE);
                csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */
        }
-       channel->desired_mode = mode;
+       channel->desired_mode = *mode;
        musb_writew(epio, MUSB_TXCSR, csr);
 
        return 0;
@@ -2003,10 +2003,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
                                qh->offset,
                                urb->transfer_buffer_length);
 
-                       done = musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh,
-                                                             urb, xfer_len,
-                                                             iso_err);
-                       if (done)
+                       if (musb_rx_dma_in_inventra_cppi41(c, hw_ep, qh, urb,
+                                                          xfer_len, iso_err))
                                goto finish;
                        else
                                dev_err(musb->controller, "error: rx_dma failed\n");
index 970a30e155cb51bfd1d15126d8cdc65f9adf579c..72b387d592c278eafb5a73e519482b405d921e39 100644 (file)
@@ -757,14 +757,8 @@ static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
        otg->host = host;
        dev_dbg(otg->usb_phy->dev, "host driver registered w/ tranceiver\n");
 
-       /*
-        * Kick the state machine work, if peripheral is not supported
-        * or peripheral is already registered with us.
-        */
-       if (motg->pdata->mode == USB_DR_MODE_HOST || otg->gadget) {
-               pm_runtime_get_sync(otg->usb_phy->dev);
-               schedule_work(&motg->sm_work);
-       }
+       pm_runtime_get_sync(otg->usb_phy->dev);
+       schedule_work(&motg->sm_work);
 
        return 0;
 }
@@ -827,14 +821,8 @@ static int msm_otg_set_peripheral(struct usb_otg *otg,
        dev_dbg(otg->usb_phy->dev,
                "peripheral driver registered w/ tranceiver\n");
 
-       /*
-        * Kick the state machine work, if host is not supported
-        * or host is already registered with us.
-        */
-       if (motg->pdata->mode == USB_DR_MODE_PERIPHERAL || otg->host) {
-               pm_runtime_get_sync(otg->usb_phy->dev);
-               schedule_work(&motg->sm_work);
-       }
+       pm_runtime_get_sync(otg->usb_phy->dev);
+       schedule_work(&motg->sm_work);
 
        return 0;
 }
index f612dda9c9778aaf78da02d7422f2d73a14818c2..56ecb8b5115dd66b8d0db52849e9738e127a2afa 100644 (file)
@@ -475,22 +475,6 @@ config USB_SERIAL_MOS7840
          To compile this driver as a module, choose M here: the
          module will be called mos7840.  If unsure, choose N.
 
-config USB_SERIAL_MXUPORT11
-       tristate "USB Moxa UPORT 11x0 Serial Driver"
-       ---help---
-         Say Y here if you want to use a MOXA UPort 11x0 Serial hub.
-
-         This driver supports:
-
-         - UPort 1110  : 1 port RS-232 USB to Serial Hub.
-         - UPort 1130  : 1 port RS-422/485 USB to Serial Hub.
-         - UPort 1130I : 1 port RS-422/485 USB to Serial Hub with Isolation.
-         - UPort 1150  : 1 port RS-232/422/485 USB to Serial Hub.
-         - UPort 1150I : 1 port RS-232/422/485 USB to Serial Hub with Isolation.
-
-         To compile this driver as a module, choose M here: the
-         module will be called mxu11x0.
-
 config USB_SERIAL_MXUPORT
        tristate "USB Moxa UPORT Serial Driver"
        ---help---
index f3fa5e53702d869faa08cb7c2b05e03beae85390..349d9df0895f5afc4139b046383362bc46348739 100644 (file)
@@ -38,7 +38,6 @@ obj-$(CONFIG_USB_SERIAL_METRO)                        += metro-usb.o
 obj-$(CONFIG_USB_SERIAL_MOS7720)               += mos7720.o
 obj-$(CONFIG_USB_SERIAL_MOS7840)               += mos7840.o
 obj-$(CONFIG_USB_SERIAL_MXUPORT)               += mxuport.o
-obj-$(CONFIG_USB_SERIAL_MXUPORT11)             += mxu11x0.o
 obj-$(CONFIG_USB_SERIAL_NAVMAN)                        += navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)               += omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTICON)               += opticon.o
index 987813b8a7f91e27b6a582a44ca88254dbd49c13..73a366de5102ada85dbf9539c75a9bb70ddaf4fd 100644 (file)
@@ -163,6 +163,9 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
        { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
        { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
+       { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
+       { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
+       { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
        { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
        { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
        { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
diff --git a/drivers/usb/serial/mxu11x0.c b/drivers/usb/serial/mxu11x0.c
deleted file mode 100644 (file)
index 6196073..0000000
+++ /dev/null
@@ -1,1006 +0,0 @@
-/*
- * USB Moxa UPORT 11x0 Serial Driver
- *
- * Copyright (C) 2007 MOXA Technologies Co., Ltd.
- * Copyright (C) 2015 Mathieu Othacehe <m.othacehe@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 Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- *
- * Supports the following Moxa USB to serial converters:
- *  UPort 1110,  1 port RS-232 USB to Serial Hub.
- *  UPort 1130,  1 port RS-422/485 USB to Serial Hub.
- *  UPort 1130I, 1 port RS-422/485 USB to Serial Hub with isolation
- *    protection.
- *  UPort 1150,  1 port RS-232/422/485 USB to Serial Hub.
- *  UPort 1150I, 1 port RS-232/422/485 USB to Serial Hub with isolation
- *  protection.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/jiffies.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-/* Vendor and product ids */
-#define MXU1_VENDOR_ID                         0x110a
-#define MXU1_1110_PRODUCT_ID                   0x1110
-#define MXU1_1130_PRODUCT_ID                   0x1130
-#define MXU1_1150_PRODUCT_ID                   0x1150
-#define MXU1_1151_PRODUCT_ID                   0x1151
-#define MXU1_1131_PRODUCT_ID                   0x1131
-
-/* Commands */
-#define MXU1_GET_VERSION                       0x01
-#define MXU1_GET_PORT_STATUS                   0x02
-#define MXU1_GET_PORT_DEV_INFO                 0x03
-#define MXU1_GET_CONFIG                                0x04
-#define MXU1_SET_CONFIG                                0x05
-#define MXU1_OPEN_PORT                         0x06
-#define MXU1_CLOSE_PORT                                0x07
-#define MXU1_START_PORT                                0x08
-#define MXU1_STOP_PORT                         0x09
-#define MXU1_TEST_PORT                         0x0A
-#define MXU1_PURGE_PORT                                0x0B
-#define MXU1_RESET_EXT_DEVICE                  0x0C
-#define MXU1_GET_OUTQUEUE                      0x0D
-#define MXU1_WRITE_DATA                                0x80
-#define MXU1_READ_DATA                         0x81
-#define MXU1_REQ_TYPE_CLASS                    0x82
-
-/* Module identifiers */
-#define MXU1_I2C_PORT                          0x01
-#define MXU1_IEEE1284_PORT                     0x02
-#define MXU1_UART1_PORT                                0x03
-#define MXU1_UART2_PORT                                0x04
-#define MXU1_RAM_PORT                          0x05
-
-/* Modem status */
-#define MXU1_MSR_DELTA_CTS                     0x01
-#define MXU1_MSR_DELTA_DSR                     0x02
-#define MXU1_MSR_DELTA_RI                      0x04
-#define MXU1_MSR_DELTA_CD                      0x08
-#define MXU1_MSR_CTS                           0x10
-#define MXU1_MSR_DSR                           0x20
-#define MXU1_MSR_RI                            0x40
-#define MXU1_MSR_CD                            0x80
-#define MXU1_MSR_DELTA_MASK                    0x0F
-#define MXU1_MSR_MASK                          0xF0
-
-/* Line status */
-#define MXU1_LSR_OVERRUN_ERROR                 0x01
-#define MXU1_LSR_PARITY_ERROR                  0x02
-#define MXU1_LSR_FRAMING_ERROR                 0x04
-#define MXU1_LSR_BREAK                         0x08
-#define MXU1_LSR_ERROR                         0x0F
-#define MXU1_LSR_RX_FULL                       0x10
-#define MXU1_LSR_TX_EMPTY                      0x20
-
-/* Modem control */
-#define MXU1_MCR_LOOP                          0x04
-#define MXU1_MCR_DTR                           0x10
-#define MXU1_MCR_RTS                           0x20
-
-/* Mask settings */
-#define MXU1_UART_ENABLE_RTS_IN                        0x0001
-#define MXU1_UART_DISABLE_RTS                  0x0002
-#define MXU1_UART_ENABLE_PARITY_CHECKING       0x0008
-#define MXU1_UART_ENABLE_DSR_OUT               0x0010
-#define MXU1_UART_ENABLE_CTS_OUT               0x0020
-#define MXU1_UART_ENABLE_X_OUT                 0x0040
-#define MXU1_UART_ENABLE_XA_OUT                        0x0080
-#define MXU1_UART_ENABLE_X_IN                  0x0100
-#define MXU1_UART_ENABLE_DTR_IN                        0x0800
-#define MXU1_UART_DISABLE_DTR                  0x1000
-#define MXU1_UART_ENABLE_MS_INTS               0x2000
-#define MXU1_UART_ENABLE_AUTO_START_DMA                0x4000
-#define MXU1_UART_SEND_BREAK_SIGNAL            0x8000
-
-/* Parity */
-#define MXU1_UART_NO_PARITY                    0x00
-#define MXU1_UART_ODD_PARITY                   0x01
-#define MXU1_UART_EVEN_PARITY                  0x02
-#define MXU1_UART_MARK_PARITY                  0x03
-#define MXU1_UART_SPACE_PARITY                 0x04
-
-/* Stop bits */
-#define MXU1_UART_1_STOP_BITS                  0x00
-#define MXU1_UART_1_5_STOP_BITS                        0x01
-#define MXU1_UART_2_STOP_BITS                  0x02
-
-/* Bits per character */
-#define MXU1_UART_5_DATA_BITS                  0x00
-#define MXU1_UART_6_DATA_BITS                  0x01
-#define MXU1_UART_7_DATA_BITS                  0x02
-#define MXU1_UART_8_DATA_BITS                  0x03
-
-/* Operation modes */
-#define MXU1_UART_232                          0x00
-#define MXU1_UART_485_RECEIVER_DISABLED                0x01
-#define MXU1_UART_485_RECEIVER_ENABLED         0x02
-
-/* Pipe transfer mode and timeout */
-#define MXU1_PIPE_MODE_CONTINUOUS              0x01
-#define MXU1_PIPE_MODE_MASK                    0x03
-#define MXU1_PIPE_TIMEOUT_MASK                 0x7C
-#define MXU1_PIPE_TIMEOUT_ENABLE               0x80
-
-/* Config struct */
-struct mxu1_uart_config {
-       __be16  wBaudRate;
-       __be16  wFlags;
-       u8      bDataBits;
-       u8      bParity;
-       u8      bStopBits;
-       char    cXon;
-       char    cXoff;
-       u8      bUartMode;
-} __packed;
-
-/* Purge modes */
-#define MXU1_PURGE_OUTPUT                      0x00
-#define MXU1_PURGE_INPUT                       0x80
-
-/* Read/Write data */
-#define MXU1_RW_DATA_ADDR_SFR                  0x10
-#define MXU1_RW_DATA_ADDR_IDATA                        0x20
-#define MXU1_RW_DATA_ADDR_XDATA                        0x30
-#define MXU1_RW_DATA_ADDR_CODE                 0x40
-#define MXU1_RW_DATA_ADDR_GPIO                 0x50
-#define MXU1_RW_DATA_ADDR_I2C                  0x60
-#define MXU1_RW_DATA_ADDR_FLASH                        0x70
-#define MXU1_RW_DATA_ADDR_DSP                  0x80
-
-#define MXU1_RW_DATA_UNSPECIFIED               0x00
-#define MXU1_RW_DATA_BYTE                      0x01
-#define MXU1_RW_DATA_WORD                      0x02
-#define MXU1_RW_DATA_DOUBLE_WORD               0x04
-
-struct mxu1_write_data_bytes {
-       u8      bAddrType;
-       u8      bDataType;
-       u8      bDataCounter;
-       __be16  wBaseAddrHi;
-       __be16  wBaseAddrLo;
-       u8      bData[0];
-} __packed;
-
-/* Interrupt codes */
-#define MXU1_CODE_HARDWARE_ERROR               0xFF
-#define MXU1_CODE_DATA_ERROR                   0x03
-#define MXU1_CODE_MODEM_STATUS                 0x04
-
-static inline int mxu1_get_func_from_code(unsigned char code)
-{
-       return code & 0x0f;
-}
-
-/* Download firmware max packet size */
-#define MXU1_DOWNLOAD_MAX_PACKET_SIZE          64
-
-/* Firmware image header */
-struct mxu1_firmware_header {
-       __le16 wLength;
-       u8 bCheckSum;
-} __packed;
-
-#define MXU1_UART_BASE_ADDR        0xFFA0
-#define MXU1_UART_OFFSET_MCR       0x0004
-
-#define MXU1_BAUD_BASE              923077
-
-#define MXU1_TRANSFER_TIMEOUT      2
-#define MXU1_DOWNLOAD_TIMEOUT       1000
-#define MXU1_DEFAULT_CLOSING_WAIT   4000 /* in .01 secs */
-
-struct mxu1_port {
-       u8 msr;
-       u8 mcr;
-       u8 uart_mode;
-       spinlock_t spinlock; /* Protects msr */
-       struct mutex mutex; /* Protects mcr */
-       bool send_break;
-};
-
-struct mxu1_device {
-       u16 mxd_model;
-};
-
-static const struct usb_device_id mxu1_idtable[] = {
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1110_PRODUCT_ID) },
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1130_PRODUCT_ID) },
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) },
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) },
-       { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) },
-       { }
-};
-
-MODULE_DEVICE_TABLE(usb, mxu1_idtable);
-
-/* Write the given buffer out to the control pipe.  */
-static int mxu1_send_ctrl_data_urb(struct usb_serial *serial,
-                                  u8 request,
-                                  u16 value, u16 index,
-                                  void *data, size_t size)
-{
-       int status;
-
-       status = usb_control_msg(serial->dev,
-                                usb_sndctrlpipe(serial->dev, 0),
-                                request,
-                                (USB_DIR_OUT | USB_TYPE_VENDOR |
-                                 USB_RECIP_DEVICE), value, index,
-                                data, size,
-                                USB_CTRL_SET_TIMEOUT);
-       if (status < 0) {
-               dev_err(&serial->interface->dev,
-                       "%s - usb_control_msg failed: %d\n",
-                       __func__, status);
-               return status;
-       }
-
-       if (status != size) {
-               dev_err(&serial->interface->dev,
-                       "%s - short write (%d / %zd)\n",
-                       __func__, status, size);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-/* Send a vendor request without any data */
-static int mxu1_send_ctrl_urb(struct usb_serial *serial,
-                             u8 request, u16 value, u16 index)
-{
-       return mxu1_send_ctrl_data_urb(serial, request, value, index,
-                                      NULL, 0);
-}
-
-static int mxu1_download_firmware(struct usb_serial *serial,
-                                 const struct firmware *fw_p)
-{
-       int status = 0;
-       int buffer_size;
-       int pos;
-       int len;
-       int done;
-       u8 cs = 0;
-       u8 *buffer;
-       struct usb_device *dev = serial->dev;
-       struct mxu1_firmware_header *header;
-       unsigned int pipe;
-
-       pipe = usb_sndbulkpipe(dev, serial->port[0]->bulk_out_endpointAddress);
-
-       buffer_size = fw_p->size + sizeof(*header);
-       buffer = kmalloc(buffer_size, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
-       memcpy(buffer, fw_p->data, fw_p->size);
-       memset(buffer + fw_p->size, 0xff, buffer_size - fw_p->size);
-
-       for (pos = sizeof(*header); pos < buffer_size; pos++)
-               cs = (u8)(cs + buffer[pos]);
-
-       header = (struct mxu1_firmware_header *)buffer;
-       header->wLength = cpu_to_le16(buffer_size - sizeof(*header));
-       header->bCheckSum = cs;
-
-       dev_dbg(&dev->dev, "%s - downloading firmware\n", __func__);
-
-       for (pos = 0; pos < buffer_size; pos += done) {
-               len = min(buffer_size - pos, MXU1_DOWNLOAD_MAX_PACKET_SIZE);
-
-               status = usb_bulk_msg(dev, pipe, buffer + pos, len, &done,
-                               MXU1_DOWNLOAD_TIMEOUT);
-               if (status)
-                       break;
-       }
-
-       kfree(buffer);
-
-       if (status) {
-               dev_err(&dev->dev, "failed to download firmware: %d\n", status);
-               return status;
-       }
-
-       msleep_interruptible(100);
-       usb_reset_device(dev);
-
-       dev_dbg(&dev->dev, "%s - download successful\n", __func__);
-
-       return 0;
-}
-
-static int mxu1_port_probe(struct usb_serial_port *port)
-{
-       struct mxu1_port *mxport;
-       struct mxu1_device *mxdev;
-
-       if (!port->interrupt_in_urb) {
-               dev_err(&port->dev, "no interrupt urb\n");
-               return -ENODEV;
-       }
-
-       mxport = kzalloc(sizeof(struct mxu1_port), GFP_KERNEL);
-       if (!mxport)
-               return -ENOMEM;
-
-       spin_lock_init(&mxport->spinlock);
-       mutex_init(&mxport->mutex);
-
-       mxdev = usb_get_serial_data(port->serial);
-
-       switch (mxdev->mxd_model) {
-       case MXU1_1110_PRODUCT_ID:
-       case MXU1_1150_PRODUCT_ID:
-       case MXU1_1151_PRODUCT_ID:
-               mxport->uart_mode = MXU1_UART_232;
-               break;
-       case MXU1_1130_PRODUCT_ID:
-       case MXU1_1131_PRODUCT_ID:
-               mxport->uart_mode = MXU1_UART_485_RECEIVER_DISABLED;
-               break;
-       }
-
-       usb_set_serial_port_data(port, mxport);
-
-       port->port.closing_wait =
-                       msecs_to_jiffies(MXU1_DEFAULT_CLOSING_WAIT * 10);
-       port->port.drain_delay = 1;
-
-       return 0;
-}
-
-static int mxu1_port_remove(struct usb_serial_port *port)
-{
-       struct mxu1_port *mxport;
-
-       mxport = usb_get_serial_port_data(port);
-       kfree(mxport);
-
-       return 0;
-}
-
-static int mxu1_startup(struct usb_serial *serial)
-{
-       struct mxu1_device *mxdev;
-       struct usb_device *dev = serial->dev;
-       struct usb_host_interface *cur_altsetting;
-       char fw_name[32];
-       const struct firmware *fw_p = NULL;
-       int err;
-
-       dev_dbg(&serial->interface->dev, "%s - product 0x%04X, num configurations %d, configuration value %d\n",
-               __func__, le16_to_cpu(dev->descriptor.idProduct),
-               dev->descriptor.bNumConfigurations,
-               dev->actconfig->desc.bConfigurationValue);
-
-       /* create device structure */
-       mxdev = kzalloc(sizeof(struct mxu1_device), GFP_KERNEL);
-       if (!mxdev)
-               return -ENOMEM;
-
-       usb_set_serial_data(serial, mxdev);
-
-       mxdev->mxd_model = le16_to_cpu(dev->descriptor.idProduct);
-
-       cur_altsetting = serial->interface->cur_altsetting;
-
-       /* if we have only 1 configuration, download firmware */
-       if (cur_altsetting->desc.bNumEndpoints == 1) {
-
-               snprintf(fw_name,
-                        sizeof(fw_name),
-                        "moxa/moxa-%04x.fw",
-                        mxdev->mxd_model);
-
-               err = request_firmware(&fw_p, fw_name, &serial->interface->dev);
-               if (err) {
-                       dev_err(&serial->interface->dev, "failed to request firmware: %d\n",
-                               err);
-                       goto err_free_mxdev;
-               }
-
-               err = mxu1_download_firmware(serial, fw_p);
-               if (err)
-                       goto err_release_firmware;
-
-               /* device is being reset */
-               err = -ENODEV;
-               goto err_release_firmware;
-       }
-
-       return 0;
-
-err_release_firmware:
-       release_firmware(fw_p);
-err_free_mxdev:
-       kfree(mxdev);
-
-       return err;
-}
-
-static void mxu1_release(struct usb_serial *serial)
-{
-       struct mxu1_device *mxdev;
-
-       mxdev = usb_get_serial_data(serial);
-       kfree(mxdev);
-}
-
-static int mxu1_write_byte(struct usb_serial_port *port, u32 addr,
-                          u8 mask, u8 byte)
-{
-       int status;
-       size_t size;
-       struct mxu1_write_data_bytes *data;
-
-       dev_dbg(&port->dev, "%s - addr 0x%08X, mask 0x%02X, byte 0x%02X\n",
-               __func__, addr, mask, byte);
-
-       size = sizeof(struct mxu1_write_data_bytes) + 2;
-       data = kzalloc(size, GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       data->bAddrType = MXU1_RW_DATA_ADDR_XDATA;
-       data->bDataType = MXU1_RW_DATA_BYTE;
-       data->bDataCounter = 1;
-       data->wBaseAddrHi = cpu_to_be16(addr >> 16);
-       data->wBaseAddrLo = cpu_to_be16(addr);
-       data->bData[0] = mask;
-       data->bData[1] = byte;
-
-       status = mxu1_send_ctrl_data_urb(port->serial, MXU1_WRITE_DATA, 0,
-                                        MXU1_RAM_PORT, data, size);
-       if (status < 0)
-               dev_err(&port->dev, "%s - failed: %d\n", __func__, status);
-
-       kfree(data);
-
-       return status;
-}
-
-static int mxu1_set_mcr(struct usb_serial_port *port, unsigned int mcr)
-{
-       int status;
-
-       status = mxu1_write_byte(port,
-                                MXU1_UART_BASE_ADDR + MXU1_UART_OFFSET_MCR,
-                                MXU1_MCR_RTS | MXU1_MCR_DTR | MXU1_MCR_LOOP,
-                                mcr);
-       return status;
-}
-
-static void mxu1_set_termios(struct tty_struct *tty,
-                            struct usb_serial_port *port,
-                            struct ktermios *old_termios)
-{
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       struct mxu1_uart_config *config;
-       tcflag_t cflag, iflag;
-       speed_t baud;
-       int status;
-       unsigned int mcr;
-
-       cflag = tty->termios.c_cflag;
-       iflag = tty->termios.c_iflag;
-
-       if (old_termios &&
-           !tty_termios_hw_change(&tty->termios, old_termios) &&
-           tty->termios.c_iflag == old_termios->c_iflag) {
-               dev_dbg(&port->dev, "%s - nothing to change\n", __func__);
-               return;
-       }
-
-       dev_dbg(&port->dev,
-               "%s - cflag 0x%08x, iflag 0x%08x\n", __func__, cflag, iflag);
-
-       if (old_termios) {
-               dev_dbg(&port->dev, "%s - old cflag 0x%08x, old iflag 0x%08x\n",
-                       __func__,
-                       old_termios->c_cflag,
-                       old_termios->c_iflag);
-       }
-
-       config = kzalloc(sizeof(*config), GFP_KERNEL);
-       if (!config)
-               return;
-
-       /* these flags must be set */
-       config->wFlags |= MXU1_UART_ENABLE_MS_INTS;
-       config->wFlags |= MXU1_UART_ENABLE_AUTO_START_DMA;
-       if (mxport->send_break)
-               config->wFlags |= MXU1_UART_SEND_BREAK_SIGNAL;
-       config->bUartMode = mxport->uart_mode;
-
-       switch (C_CSIZE(tty)) {
-       case CS5:
-               config->bDataBits = MXU1_UART_5_DATA_BITS;
-               break;
-       case CS6:
-               config->bDataBits = MXU1_UART_6_DATA_BITS;
-               break;
-       case CS7:
-               config->bDataBits = MXU1_UART_7_DATA_BITS;
-               break;
-       default:
-       case CS8:
-               config->bDataBits = MXU1_UART_8_DATA_BITS;
-               break;
-       }
-
-       if (C_PARENB(tty)) {
-               config->wFlags |= MXU1_UART_ENABLE_PARITY_CHECKING;
-               if (C_CMSPAR(tty)) {
-                       if (C_PARODD(tty))
-                               config->bParity = MXU1_UART_MARK_PARITY;
-                       else
-                               config->bParity = MXU1_UART_SPACE_PARITY;
-               } else {
-                       if (C_PARODD(tty))
-                               config->bParity = MXU1_UART_ODD_PARITY;
-                       else
-                               config->bParity = MXU1_UART_EVEN_PARITY;
-               }
-       } else {
-               config->bParity = MXU1_UART_NO_PARITY;
-       }
-
-       if (C_CSTOPB(tty))
-               config->bStopBits = MXU1_UART_2_STOP_BITS;
-       else
-               config->bStopBits = MXU1_UART_1_STOP_BITS;
-
-       if (C_CRTSCTS(tty)) {
-               /* RTS flow control must be off to drop RTS for baud rate B0 */
-               if (C_BAUD(tty) != B0)
-                       config->wFlags |= MXU1_UART_ENABLE_RTS_IN;
-               config->wFlags |= MXU1_UART_ENABLE_CTS_OUT;
-       }
-
-       if (I_IXOFF(tty) || I_IXON(tty)) {
-               config->cXon  = START_CHAR(tty);
-               config->cXoff = STOP_CHAR(tty);
-
-               if (I_IXOFF(tty))
-                       config->wFlags |= MXU1_UART_ENABLE_X_IN;
-
-               if (I_IXON(tty))
-                       config->wFlags |= MXU1_UART_ENABLE_X_OUT;
-       }
-
-       baud = tty_get_baud_rate(tty);
-       if (!baud)
-               baud = 9600;
-       config->wBaudRate = MXU1_BAUD_BASE / baud;
-
-       dev_dbg(&port->dev, "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d\n",
-               __func__, baud, config->wBaudRate, config->wFlags,
-               config->bDataBits, config->bParity, config->bStopBits,
-               config->cXon, config->cXoff, config->bUartMode);
-
-       cpu_to_be16s(&config->wBaudRate);
-       cpu_to_be16s(&config->wFlags);
-
-       status = mxu1_send_ctrl_data_urb(port->serial, MXU1_SET_CONFIG, 0,
-                                        MXU1_UART1_PORT, config,
-                                        sizeof(*config));
-       if (status)
-               dev_err(&port->dev, "cannot set config: %d\n", status);
-
-       mutex_lock(&mxport->mutex);
-       mcr = mxport->mcr;
-
-       if (C_BAUD(tty) == B0)
-               mcr &= ~(MXU1_MCR_DTR | MXU1_MCR_RTS);
-       else if (old_termios && (old_termios->c_cflag & CBAUD) == B0)
-               mcr |= MXU1_MCR_DTR | MXU1_MCR_RTS;
-
-       status = mxu1_set_mcr(port, mcr);
-       if (status)
-               dev_err(&port->dev, "cannot set modem control: %d\n", status);
-       else
-               mxport->mcr = mcr;
-
-       mutex_unlock(&mxport->mutex);
-
-       kfree(config);
-}
-
-static int mxu1_get_serial_info(struct usb_serial_port *port,
-                               struct serial_struct __user *ret_arg)
-{
-       struct serial_struct ret_serial;
-       unsigned cwait;
-
-       if (!ret_arg)
-               return -EFAULT;
-
-       cwait = port->port.closing_wait;
-       if (cwait != ASYNC_CLOSING_WAIT_NONE)
-               cwait = jiffies_to_msecs(cwait) / 10;
-
-       memset(&ret_serial, 0, sizeof(ret_serial));
-
-       ret_serial.type = PORT_16550A;
-       ret_serial.line = port->minor;
-       ret_serial.port = 0;
-       ret_serial.xmit_fifo_size = port->bulk_out_size;
-       ret_serial.baud_base = MXU1_BAUD_BASE;
-       ret_serial.close_delay = 5*HZ;
-       ret_serial.closing_wait = cwait;
-
-       if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int mxu1_set_serial_info(struct usb_serial_port *port,
-                               struct serial_struct __user *new_arg)
-{
-       struct serial_struct new_serial;
-       unsigned cwait;
-
-       if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
-               return -EFAULT;
-
-       cwait = new_serial.closing_wait;
-       if (cwait != ASYNC_CLOSING_WAIT_NONE)
-               cwait = msecs_to_jiffies(10 * new_serial.closing_wait);
-
-       port->port.closing_wait = cwait;
-
-       return 0;
-}
-
-static int mxu1_ioctl(struct tty_struct *tty,
-                     unsigned int cmd, unsigned long arg)
-{
-       struct usb_serial_port *port = tty->driver_data;
-
-       switch (cmd) {
-       case TIOCGSERIAL:
-               return mxu1_get_serial_info(port,
-                                           (struct serial_struct __user *)arg);
-       case TIOCSSERIAL:
-               return mxu1_set_serial_info(port,
-                                           (struct serial_struct __user *)arg);
-       }
-
-       return -ENOIOCTLCMD;
-}
-
-static int mxu1_tiocmget(struct tty_struct *tty)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       unsigned int result;
-       unsigned int msr;
-       unsigned int mcr;
-       unsigned long flags;
-
-       mutex_lock(&mxport->mutex);
-       spin_lock_irqsave(&mxport->spinlock, flags);
-
-       msr = mxport->msr;
-       mcr = mxport->mcr;
-
-       spin_unlock_irqrestore(&mxport->spinlock, flags);
-       mutex_unlock(&mxport->mutex);
-
-       result = ((mcr & MXU1_MCR_DTR)  ? TIOCM_DTR     : 0) |
-                ((mcr & MXU1_MCR_RTS)  ? TIOCM_RTS     : 0) |
-                ((mcr & MXU1_MCR_LOOP) ? TIOCM_LOOP    : 0) |
-                ((msr & MXU1_MSR_CTS)  ? TIOCM_CTS     : 0) |
-                ((msr & MXU1_MSR_CD)   ? TIOCM_CAR     : 0) |
-                ((msr & MXU1_MSR_RI)   ? TIOCM_RI      : 0) |
-                ((msr & MXU1_MSR_DSR)  ? TIOCM_DSR     : 0);
-
-       dev_dbg(&port->dev, "%s - 0x%04X\n", __func__, result);
-
-       return result;
-}
-
-static int mxu1_tiocmset(struct tty_struct *tty,
-                        unsigned int set, unsigned int clear)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       int err;
-       unsigned int mcr;
-
-       mutex_lock(&mxport->mutex);
-       mcr = mxport->mcr;
-
-       if (set & TIOCM_RTS)
-               mcr |= MXU1_MCR_RTS;
-       if (set & TIOCM_DTR)
-               mcr |= MXU1_MCR_DTR;
-       if (set & TIOCM_LOOP)
-               mcr |= MXU1_MCR_LOOP;
-
-       if (clear & TIOCM_RTS)
-               mcr &= ~MXU1_MCR_RTS;
-       if (clear & TIOCM_DTR)
-               mcr &= ~MXU1_MCR_DTR;
-       if (clear & TIOCM_LOOP)
-               mcr &= ~MXU1_MCR_LOOP;
-
-       err = mxu1_set_mcr(port, mcr);
-       if (!err)
-               mxport->mcr = mcr;
-
-       mutex_unlock(&mxport->mutex);
-
-       return err;
-}
-
-static void mxu1_break(struct tty_struct *tty, int break_state)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-
-       if (break_state == -1)
-               mxport->send_break = true;
-       else
-               mxport->send_break = false;
-
-       mxu1_set_termios(tty, port, NULL);
-}
-
-static int mxu1_open(struct tty_struct *tty, struct usb_serial_port *port)
-{
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       struct usb_serial *serial = port->serial;
-       int status;
-       u16 open_settings;
-
-       open_settings = (MXU1_PIPE_MODE_CONTINUOUS |
-                        MXU1_PIPE_TIMEOUT_ENABLE |
-                        (MXU1_TRANSFER_TIMEOUT << 2));
-
-       mxport->msr = 0;
-
-       status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-       if (status) {
-               dev_err(&port->dev, "failed to submit interrupt urb: %d\n",
-                       status);
-               return status;
-       }
-
-       if (tty)
-               mxu1_set_termios(tty, port, NULL);
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_OPEN_PORT,
-                                   open_settings, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot send open command: %d\n", status);
-               goto unlink_int_urb;
-       }
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_START_PORT,
-                                   0, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot send start command: %d\n", status);
-               goto unlink_int_urb;
-       }
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_PURGE_PORT,
-                                   MXU1_PURGE_INPUT, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot clear input buffers: %d\n",
-                       status);
-
-               goto unlink_int_urb;
-       }
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_PURGE_PORT,
-                                   MXU1_PURGE_OUTPUT, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot clear output buffers: %d\n",
-                       status);
-
-               goto unlink_int_urb;
-       }
-
-       /*
-        * reset the data toggle on the bulk endpoints to work around bug in
-        * host controllers where things get out of sync some times
-        */
-       usb_clear_halt(serial->dev, port->write_urb->pipe);
-       usb_clear_halt(serial->dev, port->read_urb->pipe);
-
-       if (tty)
-               mxu1_set_termios(tty, port, NULL);
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_OPEN_PORT,
-                                   open_settings, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot send open command: %d\n", status);
-               goto unlink_int_urb;
-       }
-
-       status = mxu1_send_ctrl_urb(serial, MXU1_START_PORT,
-                                   0, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "cannot send start command: %d\n", status);
-               goto unlink_int_urb;
-       }
-
-       status = usb_serial_generic_open(tty, port);
-       if (status)
-               goto unlink_int_urb;
-
-       return 0;
-
-unlink_int_urb:
-       usb_kill_urb(port->interrupt_in_urb);
-
-       return status;
-}
-
-static void mxu1_close(struct usb_serial_port *port)
-{
-       int status;
-
-       usb_serial_generic_close(port);
-       usb_kill_urb(port->interrupt_in_urb);
-
-       status = mxu1_send_ctrl_urb(port->serial, MXU1_CLOSE_PORT,
-                                   0, MXU1_UART1_PORT);
-       if (status) {
-               dev_err(&port->dev, "failed to send close port command: %d\n",
-                       status);
-       }
-}
-
-static void mxu1_handle_new_msr(struct usb_serial_port *port, u8 msr)
-{
-       struct mxu1_port *mxport = usb_get_serial_port_data(port);
-       struct async_icount *icount;
-       unsigned long flags;
-
-       dev_dbg(&port->dev, "%s - msr 0x%02X\n", __func__, msr);
-
-       spin_lock_irqsave(&mxport->spinlock, flags);
-       mxport->msr = msr & MXU1_MSR_MASK;
-       spin_unlock_irqrestore(&mxport->spinlock, flags);
-
-       if (msr & MXU1_MSR_DELTA_MASK) {
-               icount = &port->icount;
-               if (msr & MXU1_MSR_DELTA_CTS)
-                       icount->cts++;
-               if (msr & MXU1_MSR_DELTA_DSR)
-                       icount->dsr++;
-               if (msr & MXU1_MSR_DELTA_CD)
-                       icount->dcd++;
-               if (msr & MXU1_MSR_DELTA_RI)
-                       icount->rng++;
-
-               wake_up_interruptible(&port->port.delta_msr_wait);
-       }
-}
-
-static void mxu1_interrupt_callback(struct urb *urb)
-{
-       struct usb_serial_port *port = urb->context;
-       unsigned char *data = urb->transfer_buffer;
-       int length = urb->actual_length;
-       int function;
-       int status;
-       u8 msr;
-
-       switch (urb->status) {
-       case 0:
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               dev_dbg(&port->dev, "%s - urb shutting down: %d\n",
-                       __func__, urb->status);
-               return;
-       default:
-               dev_dbg(&port->dev, "%s - nonzero urb status: %d\n",
-                       __func__, urb->status);
-               goto exit;
-       }
-
-       if (length != 2) {
-               dev_dbg(&port->dev, "%s - bad packet size: %d\n",
-                       __func__, length);
-               goto exit;
-       }
-
-       if (data[0] == MXU1_CODE_HARDWARE_ERROR) {
-               dev_err(&port->dev, "hardware error: %d\n", data[1]);
-               goto exit;
-       }
-
-       function = mxu1_get_func_from_code(data[0]);
-
-       dev_dbg(&port->dev, "%s - function %d, data 0x%02X\n",
-                __func__, function, data[1]);
-
-       switch (function) {
-       case MXU1_CODE_DATA_ERROR:
-               dev_dbg(&port->dev, "%s - DATA ERROR, data 0x%02X\n",
-                        __func__, data[1]);
-               break;
-
-       case MXU1_CODE_MODEM_STATUS:
-               msr = data[1];
-               mxu1_handle_new_msr(port, msr);
-               break;
-
-       default:
-               dev_err(&port->dev, "unknown interrupt code: 0x%02X\n",
-                       data[1]);
-               break;
-       }
-
-exit:
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status) {
-               dev_err(&port->dev, "resubmit interrupt urb failed: %d\n",
-                       status);
-       }
-}
-
-static struct usb_serial_driver mxu11x0_device = {
-       .driver = {
-               .owner          = THIS_MODULE,
-               .name           = "mxu11x0",
-       },
-       .description            = "MOXA UPort 11x0",
-       .id_table               = mxu1_idtable,
-       .num_ports              = 1,
-       .port_probe             = mxu1_port_probe,
-       .port_remove            = mxu1_port_remove,
-       .attach                 = mxu1_startup,
-       .release                = mxu1_release,
-       .open                   = mxu1_open,
-       .close                  = mxu1_close,
-       .ioctl                  = mxu1_ioctl,
-       .set_termios            = mxu1_set_termios,
-       .tiocmget               = mxu1_tiocmget,
-       .tiocmset               = mxu1_tiocmset,
-       .tiocmiwait             = usb_serial_generic_tiocmiwait,
-       .get_icount             = usb_serial_generic_get_icount,
-       .break_ctl              = mxu1_break,
-       .read_int_callback      = mxu1_interrupt_callback,
-};
-
-static struct usb_serial_driver *const serial_drivers[] = {
-       &mxu11x0_device, NULL
-};
-
-module_usb_serial_driver(serial_drivers, mxu1_idtable);
-
-MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
-MODULE_DESCRIPTION("MOXA UPort 11x0 USB to Serial Hub Driver");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("moxa/moxa-1110.fw");
-MODULE_FIRMWARE("moxa/moxa-1130.fw");
-MODULE_FIRMWARE("moxa/moxa-1131.fw");
-MODULE_FIRMWARE("moxa/moxa-1150.fw");
-MODULE_FIRMWARE("moxa/moxa-1151.fw");
index db86e512e0fcb3af0548eb9907b04ce68db3a8dc..348e19834b83e12e7aafafa9d46374822fe43f7f 100644 (file)
@@ -270,6 +270,7 @@ static void option_instat_callback(struct urb *urb);
 #define TELIT_PRODUCT_UE910_V2                 0x1012
 #define TELIT_PRODUCT_LE922_USBCFG0            0x1042
 #define TELIT_PRODUCT_LE922_USBCFG3            0x1043
+#define TELIT_PRODUCT_LE922_USBCFG5            0x1045
 #define TELIT_PRODUCT_LE920                    0x1200
 #define TELIT_PRODUCT_LE910                    0x1201
 
@@ -315,6 +316,7 @@ static void option_instat_callback(struct urb *urb);
 #define TOSHIBA_PRODUCT_G450                   0x0d45
 
 #define ALINK_VENDOR_ID                                0x1e0e
+#define SIMCOM_PRODUCT_SIM7100E                        0x9001 /* Yes, ALINK_VENDOR_ID */
 #define ALINK_PRODUCT_PH300                    0x9100
 #define ALINK_PRODUCT_3GU                      0x9200
 
@@ -607,6 +609,10 @@ static const struct option_blacklist_info zte_1255_blacklist = {
        .reserved = BIT(3) | BIT(4),
 };
 
+static const struct option_blacklist_info simcom_sim7100e_blacklist = {
+       .reserved = BIT(5) | BIT(6),
+};
+
 static const struct option_blacklist_info telit_le910_blacklist = {
        .sendsetup = BIT(0),
        .reserved = BIT(1) | BIT(2),
@@ -1122,9 +1128,13 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
+       { USB_DEVICE_AND_INTERFACE_INFO(QUALCOMM_VENDOR_ID, 0x6001, 0xff, 0xff, 0xff), /* 4G LTE usb-modem U901 */
+         .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
@@ -1176,6 +1186,8 @@ static const struct usb_device_id option_ids[] = {
                .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
                .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff),
+               .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
                .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
@@ -1645,6 +1657,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
        { USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) },
        { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
+       { USB_DEVICE(ALINK_VENDOR_ID, SIMCOM_PRODUCT_SIM7100E),
+         .driver_info = (kernel_ulong_t)&simcom_sim7100e_blacklist },
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
          .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
        },
index 9919d2a9faf278177aacf32c149fda22b00a1d83..1bc6089b90083a05e0ef3e4ff71c0ef752e3831a 100644 (file)
@@ -157,14 +157,17 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_SWI(0x1199, 0x9056)},   /* Sierra Wireless Modem */
        {DEVICE_SWI(0x1199, 0x9060)},   /* Sierra Wireless Modem */
        {DEVICE_SWI(0x1199, 0x9061)},   /* Sierra Wireless Modem */
-       {DEVICE_SWI(0x1199, 0x9070)},   /* Sierra Wireless MC74xx/EM74xx */
-       {DEVICE_SWI(0x1199, 0x9071)},   /* Sierra Wireless MC74xx/EM74xx */
+       {DEVICE_SWI(0x1199, 0x9070)},   /* Sierra Wireless MC74xx */
+       {DEVICE_SWI(0x1199, 0x9071)},   /* Sierra Wireless MC74xx */
+       {DEVICE_SWI(0x1199, 0x9078)},   /* Sierra Wireless EM74xx */
+       {DEVICE_SWI(0x1199, 0x9079)},   /* Sierra Wireless EM74xx */
        {DEVICE_SWI(0x413c, 0x81a2)},   /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a3)},   /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a4)},   /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a8)},   /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a9)},   /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81b1)},   /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
+       {DEVICE_SWI(0x413c, 0x81b3)},   /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
 
        /* Huawei devices */
        {DEVICE_HWI(0x03f0, 0x581d)},   /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
index 2760a7ba3f309d1a344781c2f9a4eb6c3b3ff4aa..8c80a48e32335346e426547fa5007e179ff7cec7 100644 (file)
@@ -446,7 +446,8 @@ static long vfio_pci_ioctl(void *device_data,
                info.num_regions = VFIO_PCI_NUM_REGIONS;
                info.num_irqs = VFIO_PCI_NUM_IRQS;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
                struct pci_dev *pdev = vdev->pdev;
@@ -520,7 +521,8 @@ static long vfio_pci_ioctl(void *device_data,
                        return -EINVAL;
                }
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
                struct vfio_irq_info info;
@@ -555,7 +557,8 @@ static long vfio_pci_ioctl(void *device_data,
                else
                        info.flags |= VFIO_IRQ_INFO_NORESIZE;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_SET_IRQS) {
                struct vfio_irq_set hdr;
index 418cdd9ba3f4841353c5cbdddb345e9363578736..e65b142d34222dd4ba548e46c44017d2b762cf06 100644 (file)
@@ -219,7 +219,8 @@ static long vfio_platform_ioctl(void *device_data,
                info.num_regions = vdev->num_regions;
                info.num_irqs = vdev->num_irqs;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
                struct vfio_region_info info;
@@ -240,7 +241,8 @@ static long vfio_platform_ioctl(void *device_data,
                info.size = vdev->regions[info.index].size;
                info.flags = vdev->regions[info.index].flags;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
                struct vfio_irq_info info;
@@ -259,7 +261,8 @@ static long vfio_platform_ioctl(void *device_data,
                info.flags = vdev->irqs[info.index].flags;
                info.count = vdev->irqs[info.index].count;
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_DEVICE_SET_IRQS) {
                struct vfio_irq_set hdr;
index 6f1ea3dddbad9a75dd094d8613fb426742f844e4..75b24e93cedb3da273a589bb129b6ce502b247fd 100644 (file)
@@ -999,7 +999,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 
                info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
 
-               return copy_to_user((void __user *)arg, &info, minsz);
+               return copy_to_user((void __user *)arg, &info, minsz) ?
+                       -EFAULT : 0;
 
        } else if (cmd == VFIO_IOMMU_MAP_DMA) {
                struct vfio_iommu_type1_dma_map map;
@@ -1032,7 +1033,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
                if (ret)
                        return ret;
 
-               return copy_to_user((void __user *)arg, &unmap, minsz);
+               return copy_to_user((void __user *)arg, &unmap, minsz) ?
+                       -EFAULT : 0;
        }
 
        return -ENOTTY;
index ad2146a9ab2d4b19cca5469402c203ade61e8545..236553e81027c15b089cdf2a0d4378f60e3f8d6a 100644 (file)
@@ -1156,6 +1156,8 @@ int vhost_init_used(struct vhost_virtqueue *vq)
 {
        __virtio16 last_used_idx;
        int r;
+       bool is_le = vq->is_le;
+
        if (!vq->private_data) {
                vq->is_le = virtio_legacy_is_little_endian();
                return 0;
@@ -1165,15 +1167,20 @@ int vhost_init_used(struct vhost_virtqueue *vq)
 
        r = vhost_update_used_flags(vq);
        if (r)
-               return r;
+               goto err;
        vq->signalled_used_valid = false;
-       if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx))
-               return -EFAULT;
+       if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx)) {
+               r = -EFAULT;
+               goto err;
+       }
        r = __get_user(last_used_idx, &vq->used->idx);
        if (r)
-               return r;
+               goto err;
        vq->last_used_idx = vhost16_to_cpu(vq, last_used_idx);
        return 0;
+err:
+       vq->is_le = is_le;
+       return r;
 }
 EXPORT_SYMBOL_GPL(vhost_init_used);
 
index 92f394927f241bef338a293170e4a09b9f45c647..6e92917ba77a97477f32a0426ee914c351867a6b 100644 (file)
@@ -709,6 +709,7 @@ static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
        }
 
        if (!err) {
+               ops->cur_blink_jiffies = HZ / 5;
                info->fbcon_par = ops;
 
                if (vc)
@@ -956,6 +957,7 @@ static const char *fbcon_startup(void)
        ops->currcon = -1;
        ops->graphics = 1;
        ops->cur_rotate = -1;
+       ops->cur_blink_jiffies = HZ / 5;
        info->fbcon_par = ops;
        p->con_rotate = initial_rotation;
        set_blitting_type(vc, info);
index a305caea58eea717fdffaac4c5364552673ad5ae..fb75b7e5a19ab52748e4a1980d56046e15716908 100644 (file)
@@ -1040,8 +1040,8 @@ static int acornfb_probe(struct platform_device *dev)
                 * for the framebuffer if we are not using
                 * VRAM.
                 */
-               base = dma_alloc_writecombine(current_par.dev, size, &handle,
-                                             GFP_KERNEL);
+               base = dma_alloc_wc(current_par.dev, size, &handle,
+                                   GFP_KERNEL);
                if (base == NULL) {
                        printk(KERN_ERR "acornfb: unable to allocate screen "
                               "memory\n");
index 7a8afcd4573e5c1e595550f25985ea1181367157..a8a22daa3f9d2a70a6fa1ca5f4e0f526e7380375 100644 (file)
@@ -154,8 +154,8 @@ int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize)
 {
        dma_addr_t dma;
 
-       fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
-                                                   &dma, GFP_KERNEL);
+       fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, framesize, &dma,
+                                         GFP_KERNEL);
        if (!fb->fb.screen_base) {
                pr_err("CLCD: unable to map framebuffer\n");
                return -ENOMEM;
@@ -169,14 +169,12 @@ int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize)
 
 int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma)
 {
-       return dma_mmap_writecombine(&fb->dev->dev, vma,
-                                    fb->fb.screen_base,
-                                    fb->fb.fix.smem_start,
-                                    fb->fb.fix.smem_len);
+       return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
+                          fb->fb.fix.smem_start, fb->fb.fix.smem_len);
 }
 
 void versatile_clcd_remove_dma(struct clcd_fb *fb)
 {
-       dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-                             fb->fb.screen_base, fb->fb.fix.smem_start);
+       dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
+                   fb->fb.fix.smem_start);
 }
index 9362424c2340490585fe02e4dfe950f53f2097af..fe274b5851c77ff5e59b7c88f205cbf09ec61114 100644 (file)
@@ -774,8 +774,8 @@ static int clcdfb_of_dma_setup(struct clcd_fb *fb)
 
 static int clcdfb_of_dma_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
 {
-       return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base,
-                       fb->fb.fix.smem_start, fb->fb.fix.smem_len);
+       return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
+                          fb->fb.fix.smem_start, fb->fb.fix.smem_len);
 }
 
 static void clcdfb_of_dma_remove(struct clcd_fb *fb)
index 19eb42b57d8742089d2faadf5c8a64ce81cc01b3..56c60e67316a57457c1741ea62d614e113d0a00e 100644 (file)
@@ -414,8 +414,8 @@ static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
 {
        struct fb_info *info = sinfo->info;
 
-       dma_free_writecombine(info->device, info->fix.smem_len,
-                               info->screen_base, info->fix.smem_start);
+       dma_free_wc(info->device, info->fix.smem_len, info->screen_base,
+                   info->fix.smem_start);
 }
 
 /**
@@ -435,8 +435,9 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
                    * ((var->bits_per_pixel + 7) / 8));
        info->fix.smem_len = max(smem_len, sinfo->smem_len);
 
-       info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
-                                       (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
+       info->screen_base = dma_alloc_wc(info->device, info->fix.smem_len,
+                                        (dma_addr_t *)&info->fix.smem_start,
+                                        GFP_KERNEL);
 
        if (!info->screen_base) {
                return -ENOMEM;
index c42ce2fdfd441de6a88f7e3ecbc46fa2514028d7..0a4626886b00c1402bc2bbc234fe691bb549ff8a 100644 (file)
@@ -68,7 +68,6 @@
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #include "../macmodes.h"
 #endif
 
index ce0b1d05a388cefc309e177de53b6b936226ae74..218339a4edaac46e5b223d07f12f335b8966c66f 100644 (file)
@@ -76,7 +76,6 @@
 
 #ifdef CONFIG_PPC
 
-#include <asm/pci-bridge.h>
 #include "../macmodes.h"
 
 #ifdef CONFIG_BOOTX_TEXT
index 5b1081030cbbbefb3f7a8ff1f5f7dbed03ebb2fa..75f0db25d19fef774b4903f71b43f9beb5a578f2 100644 (file)
@@ -316,9 +316,8 @@ static int ep93xxfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
        unsigned int offset = vma->vm_pgoff << PAGE_SHIFT;
 
        if (offset < info->fix.smem_len) {
-               return dma_mmap_writecombine(info->dev, vma, info->screen_base,
-                                            info->fix.smem_start,
-                                            info->fix.smem_len);
+               return dma_mmap_wc(info->dev, vma, info->screen_base,
+                                  info->fix.smem_start, info->fix.smem_len);
        }
 
        return -EINVAL;
@@ -428,8 +427,7 @@ static int ep93xxfb_alloc_videomem(struct fb_info *info)
        /* Maximum 16bpp -> used memory is maximum x*y*2 bytes */
        fb_size = EP93XXFB_MAX_XRES * EP93XXFB_MAX_YRES * 2;
 
-       virt_addr = dma_alloc_writecombine(info->dev, fb_size,
-                                          &phys_addr, GFP_KERNEL);
+       virt_addr = dma_alloc_wc(info->dev, fb_size, &phys_addr, GFP_KERNEL);
        if (!virt_addr)
                return -ENOMEM;
 
index b63d55f481fae421cbea5cb71466401835e23a3d..1a242b1338e9a75ff4436e8532f64a37124055cd 100644 (file)
@@ -1185,8 +1185,8 @@ static int gbefb_probe(struct platform_device *p_dev)
        } else {
                /* try to allocate memory with the classical allocator
                 * this has high chance to fail on low memory machines */
-               gbe_mem = dma_alloc_writecombine(NULL, gbe_mem_size,
-                                                &gbe_dma_addr, GFP_KERNEL);
+               gbe_mem = dma_alloc_wc(NULL, gbe_mem_size, &gbe_dma_addr,
+                                      GFP_KERNEL);
                if (!gbe_mem) {
                        printk(KERN_ERR "gbefb: couldn't allocate framebuffer memory\n");
                        ret = -ENOMEM;
@@ -1238,7 +1238,7 @@ static int gbefb_probe(struct platform_device *p_dev)
 out_gbe_unmap:
        arch_phys_wc_del(par->wc_cookie);
        if (gbe_dma_addr)
-               dma_free_writecombine(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
+               dma_free_wc(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
 out_tiles_free:
        dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
                          (void *)gbe_tiles.cpu, gbe_tiles.dma);
@@ -1259,7 +1259,7 @@ static int gbefb_remove(struct platform_device* p_dev)
        gbe_turn_off();
        arch_phys_wc_del(par->wc_cookie);
        if (gbe_dma_addr)
-               dma_free_writecombine(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
+               dma_free_wc(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
        dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
                          (void *)gbe_tiles.cpu, gbe_tiles.dma);
        release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
index 9b167f7ef6c698854a8fe4d05fdf4c3d2e9fffc7..4363c64d74e8c1481842735aa2fc0d1831344b05 100644 (file)
@@ -33,7 +33,6 @@
 #if defined(CONFIG_PPC)
 #include <linux/nvram.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #include "macmodes.h"
 #endif
 
index bb2f1e866020199d31b8ba0b1940cb9e6b87923f..76b6a7784b06c7c752ba79862c26b2edcf51f932 100644 (file)
@@ -937,8 +937,8 @@ static int imxfb_probe(struct platform_device *pdev)
        }
 
        fbi->map_size = PAGE_ALIGN(info->fix.smem_len);
-       info->screen_base = dma_alloc_writecombine(&pdev->dev, fbi->map_size,
-                                                  &fbi->map_dma, GFP_KERNEL);
+       info->screen_base = dma_alloc_wc(&pdev->dev, fbi->map_size,
+                                        &fbi->map_dma, GFP_KERNEL);
 
        if (!info->screen_base) {
                dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
@@ -1005,8 +1005,8 @@ failed_cmap:
        if (pdata && pdata->exit)
                pdata->exit(fbi->pdev);
 failed_platform_init:
-       dma_free_writecombine(&pdev->dev, fbi->map_size, info->screen_base,
-                             fbi->map_dma);
+       dma_free_wc(&pdev->dev, fbi->map_size, info->screen_base,
+                   fbi->map_dma);
 failed_map:
        iounmap(fbi->regs);
 failed_ioremap:
@@ -1041,8 +1041,8 @@ static int imxfb_remove(struct platform_device *pdev)
        kfree(info->pseudo_palette);
        framebuffer_release(info);
 
-       dma_free_writecombine(&pdev->dev, fbi->map_size, info->screen_base,
-                             fbi->map_dma);
+       dma_free_wc(&pdev->dev, fbi->map_size, info->screen_base,
+                   fbi->map_dma);
 
        iounmap(fbi->regs);
        release_mem_region(res->start, resource_size(res));
index 09b02cd1eb0e270f7dc654116167101202b00a27..7a90ea2c4613c772d4b14584a483fd2bbaed92bc 100644 (file)
@@ -47,7 +47,6 @@
 
 #if defined(CONFIG_PPC_PMAC)
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
 #include "../macmodes.h"
 #endif
 
index 7947634ee6b06c6f63707c87ef754d22342e975c..f91b1db262b04a2b131911009e3c69914b254013 100644 (file)
@@ -1336,9 +1336,8 @@ static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
        int retval = 0;
        dma_addr_t addr;
 
-       fbi->screen_base = dma_alloc_writecombine(fbi->device,
-                                                 mem_len,
-                                                 &addr, GFP_DMA | GFP_KERNEL);
+       fbi->screen_base = dma_alloc_wc(fbi->device, mem_len, &addr,
+                                       GFP_DMA | GFP_KERNEL);
 
        if (!fbi->screen_base) {
                dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
@@ -1378,8 +1377,8 @@ err0:
  */
 static int mx3fb_unmap_video_memory(struct fb_info *fbi)
 {
-       dma_free_writecombine(fbi->device, fbi->fix.smem_len,
-                             fbi->screen_base, fbi->fix.smem_start);
+       dma_free_wc(fbi->device, fbi->fix.smem_len, fbi->screen_base,
+                   fbi->fix.smem_start);
 
        fbi->screen_base = NULL;
        mutex_lock(&fbi->mm_lock);
index 389fa2cbb713108623ca07b67941572ccdc3fa85..6680edae4696d1b0dc4dff547dda27ca8c159ab5 100644 (file)
@@ -396,8 +396,8 @@ static int nuc900fb_map_video_memory(struct fb_info *info)
        dev_dbg(fbi->dev, "nuc900fb_map_video_memory(fbi=%p) map_size %lu\n",
                fbi, map_size);
 
-       info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
-                                                       &map_dma, GFP_KERNEL);
+       info->screen_base = dma_alloc_wc(fbi->dev, map_size, &map_dma,
+                                        GFP_KERNEL);
 
        if (!info->screen_base)
                return -ENOMEM;
@@ -411,8 +411,8 @@ static int nuc900fb_map_video_memory(struct fb_info *info)
 static inline void nuc900fb_unmap_video_memory(struct fb_info *info)
 {
        struct nuc900fb_info *fbi = info->par;
-       dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
-                             info->screen_base, info->fix.smem_start);
+       dma_free_wc(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+                   info->screen_base, info->fix.smem_start);
 }
 
 static irqreturn_t nuc900fb_irqhandler(int irq, void *dev_id)
index 43a0a52fc52703c18244dc2b25e54d6dd22c1f61..fb60a8f0cc94c8103d8dc141b25c5eecec5db39c 100644 (file)
 #include <linux/pci.h>
 #include <asm/io.h>
 
-#ifdef CONFIG_PPC64
-#include <asm/pci-bridge.h>
-#endif
-
 #ifdef CONFIG_PPC32
 #include <asm/bootx.h>
 #endif
index 6efa2591eaa8dfa6d72a22cd18eaf7f07c36174d..e3d9b9ea5498e0f840c5189bd1401200494d9ae2 100644 (file)
@@ -612,8 +612,8 @@ static void lcdc_dma_handler(u16 status, void *data)
 
 static int alloc_palette_ram(void)
 {
-       lcdc.palette_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
-               MAX_PALETTE_SIZE, &lcdc.palette_phys, GFP_KERNEL);
+       lcdc.palette_virt = dma_alloc_wc(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
+                                        &lcdc.palette_phys, GFP_KERNEL);
        if (lcdc.palette_virt == NULL) {
                dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");
                return -ENOMEM;
@@ -625,8 +625,8 @@ static int alloc_palette_ram(void)
 
 static void free_palette_ram(void)
 {
-       dma_free_writecombine(lcdc.fbdev->dev, MAX_PALETTE_SIZE,
-                       lcdc.palette_virt, lcdc.palette_phys);
+       dma_free_wc(lcdc.fbdev->dev, MAX_PALETTE_SIZE, lcdc.palette_virt,
+                   lcdc.palette_phys);
 }
 
 static int alloc_fbmem(struct omapfb_mem_region *region)
@@ -642,8 +642,8 @@ static int alloc_fbmem(struct omapfb_mem_region *region)
        if (region->size > frame_size)
                frame_size = region->size;
        lcdc.vram_size = frame_size;
-       lcdc.vram_virt = dma_alloc_writecombine(lcdc.fbdev->dev,
-                       lcdc.vram_size, &lcdc.vram_phys, GFP_KERNEL);
+       lcdc.vram_virt = dma_alloc_wc(lcdc.fbdev->dev, lcdc.vram_size,
+                                     &lcdc.vram_phys, GFP_KERNEL);
        if (lcdc.vram_virt == NULL) {
                dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");
                return -ENOMEM;
@@ -660,8 +660,8 @@ static int alloc_fbmem(struct omapfb_mem_region *region)
 
 static void free_fbmem(void)
 {
-       dma_free_writecombine(lcdc.fbdev->dev, lcdc.vram_size,
-                             lcdc.vram_virt, lcdc.vram_phys);
+       dma_free_wc(lcdc.fbdev->dev, lcdc.vram_size, lcdc.vram_virt,
+                   lcdc.vram_phys);
 }
 
 static int setup_fbmem(struct omapfb_mem_desc *req_md)
index efb57c059997641baed972fe2b25fd85715cf291..def3a501acd64484342f2315c9b32fe697b166a5 100644 (file)
@@ -680,8 +680,8 @@ static int pxa168fb_probe(struct platform_device *pdev)
         */
        info->fix.smem_len = PAGE_ALIGN(DEFAULT_FB_SIZE);
 
-       info->screen_base = dma_alloc_writecombine(fbi->dev, info->fix.smem_len,
-                                               &fbi->fb_start_dma, GFP_KERNEL);
+       info->screen_base = dma_alloc_wc(fbi->dev, info->fix.smem_len,
+                                        &fbi->fb_start_dma, GFP_KERNEL);
        if (info->screen_base == NULL) {
                ret = -ENOMEM;
                goto failed_free_info;
@@ -804,8 +804,8 @@ static int pxa168fb_remove(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
 
-       dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
-                               info->screen_base, info->fix.smem_start);
+       dma_free_wc(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+                   info->screen_base, info->fix.smem_start);
 
        clk_disable(fbi->clk);
 
index 33b2bb315a2a462daefa5bc2c3181806747dc919..2c0487f4f805cf7d4c9153d4c966f7cc67c45c81 100644 (file)
@@ -2446,8 +2446,8 @@ static int pxafb_remove(struct platform_device *dev)
 
        free_pages_exact(fbi->video_mem, fbi->video_mem_size);
 
-       dma_free_writecombine(&dev->dev, fbi->dma_buff_size,
-                       fbi->dma_buff, fbi->dma_buff_phys);
+       dma_free_wc(&dev->dev, fbi->dma_buff_size, fbi->dma_buff,
+                   fbi->dma_buff_phys);
 
        iounmap(fbi->mmio_base);
 
index f72dd12456f962eba79eec43fb706be9dc1cdd39..5f4f696c2ecfd5e677575675be2969b1ba09947d 100644 (file)
@@ -1105,8 +1105,7 @@ static int s3c_fb_alloc_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
 
        dev_dbg(sfb->dev, "want %u bytes for window\n", size);
 
-       fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,
-                                                 &map_dma, GFP_KERNEL);
+       fbi->screen_base = dma_alloc_wc(sfb->dev, size, &map_dma, GFP_KERNEL);
        if (!fbi->screen_base)
                return -ENOMEM;
 
@@ -1131,8 +1130,8 @@ static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
        struct fb_info *fbi = win->fbinfo;
 
        if (fbi->screen_base)
-               dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
-                             fbi->screen_base, fbi->fix.smem_start);
+               dma_free_wc(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
+                           fbi->screen_base, fbi->fix.smem_start);
 }
 
 /**
index d6704add1601c184d217dfbe19dcaa9d91aace27..0dd86be36afbb5bdff4d268ae58c17337a98c6b9 100644 (file)
@@ -645,8 +645,8 @@ static int s3c2410fb_map_video_memory(struct fb_info *info)
 
        dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size);
 
-       info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
-                                                  &map_dma, GFP_KERNEL);
+       info->screen_base = dma_alloc_wc(fbi->dev, map_size, &map_dma,
+                                        GFP_KERNEL);
 
        if (info->screen_base) {
                /* prevent initial garbage on screen */
@@ -667,8 +667,8 @@ static inline void s3c2410fb_unmap_video_memory(struct fb_info *info)
 {
        struct s3c2410fb_info *fbi = info->par;
 
-       dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
-                             info->screen_base, info->fix.smem_start);
+       dma_free_wc(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
+                   info->screen_base, info->fix.smem_start);
 }
 
 static inline void modify_gpio(void __iomem *reg,
index dcf774c1588965032eb93ac3b18cc822f419de18..fc2aaa5aca2347e705c6eb1623ec188b5262e498 100644 (file)
@@ -567,8 +567,8 @@ static int sa1100fb_mmap(struct fb_info *info,
 
        if (off < info->fix.smem_len) {
                vma->vm_pgoff += 1; /* skip over the palette */
-               return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu,
-                                            fbi->map_dma, fbi->map_size);
+               return dma_mmap_wc(fbi->dev, vma, fbi->map_cpu, fbi->map_dma,
+                                  fbi->map_size);
        }
 
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -1099,8 +1099,8 @@ static int sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
         * of the framebuffer.
         */
        fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
-       fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size,
-                                             &fbi->map_dma, GFP_KERNEL);
+       fbi->map_cpu = dma_alloc_wc(fbi->dev, fbi->map_size, &fbi->map_dma,
+                                   GFP_KERNEL);
 
        if (fbi->map_cpu) {
                fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
index f6bed86c17f96f16cfa75f35a15b790287e7ab1f..d9a90582796710d7750942be21d1b6c41ac28a8d 100644 (file)
@@ -467,7 +467,7 @@ static const struct dev_pm_ops virtio_pci_pm_ops = {
 
 /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
 static const struct pci_device_id virtio_pci_id_table[] = {
-       { PCI_DEVICE(0x1af4, PCI_ANY_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_ANY_ID) },
        { 0 }
 };
 
index c0c11fad4611a72a3712c3ef7471193cb5d8fa5d..7760fc1a2218e9ea9e053caf8db2be27dc8d2952 100644 (file)
@@ -679,7 +679,7 @@ int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev)
 
        pci_read_config_dword(pci_dev,
                              notify + offsetof(struct virtio_pci_notify_cap,
-                                               cap.length),
+                                               cap.offset),
                              &notify_offset);
 
        /* We don't know how many VQs we'll map, ahead of the time.
index 0f6d8515ba4f1d06144bb67c12ef26ef4a545da8..80825a7e8e48e1ebd06af14a1bcf208acb733daf 100644 (file)
@@ -1569,6 +1569,17 @@ config WATCHDOG_RIO
          machines.  The watchdog timeout period is normally one minute but
          can be changed with a boot-time parameter.
 
+config WATCHDOG_SUN4V
+       tristate "Sun4v Watchdog support"
+       select WATCHDOG_CORE
+       depends on SPARC64
+       help
+         Say Y here to support the hypervisor watchdog capability embedded
+         in the SPARC sun4v architecture.
+
+         To compile this driver as a module, choose M here. The module will
+         be called sun4v_wdt.
+
 # XTENSA Architecture
 
 # Xen Architecture
index f566753256abbbb74535337d3f9a9cc0442fd78e..f6a6a387c6c71f7a5e9e2cda4cc91ae3f39edf2c 100644 (file)
@@ -179,6 +179,7 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
 
 obj-$(CONFIG_WATCHDOG_RIO)             += riowd.o
 obj-$(CONFIG_WATCHDOG_CP1XXX)          += cpwd.o
+obj-$(CONFIG_WATCHDOG_SUN4V)           += sun4v_wdt.o
 
 # XTENSA Architecture
 
diff --git a/drivers/watchdog/sun4v_wdt.c b/drivers/watchdog/sun4v_wdt.c
new file mode 100644 (file)
index 0000000..1467fe5
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ *     sun4v watchdog timer
+ *     (c) Copyright 2016 Oracle Corporation
+ *
+ *     Implement a simple watchdog driver using the built-in sun4v hypervisor
+ *     watchdog support. If time expires, the hypervisor stops or bounces
+ *     the guest domain.
+ *
+ *     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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/watchdog.h>
+#include <asm/hypervisor.h>
+#include <asm/mdesc.h>
+
+#define WDT_TIMEOUT                    60
+#define WDT_MAX_TIMEOUT                        31536000
+#define WDT_MIN_TIMEOUT                        1
+#define WDT_DEFAULT_RESOLUTION_MS      1000    /* 1 second */
+
+static unsigned int timeout;
+module_param(timeout, uint, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
+       __MODULE_STRING(WDT_TIMEOUT) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, S_IRUGO);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+       __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int sun4v_wdt_stop(struct watchdog_device *wdd)
+{
+       sun4v_mach_set_watchdog(0, NULL);
+
+       return 0;
+}
+
+static int sun4v_wdt_ping(struct watchdog_device *wdd)
+{
+       int hverr;
+
+       /*
+        * HV watchdog timer will round up the timeout
+        * passed in to the nearest multiple of the
+        * watchdog resolution in milliseconds.
+        */
+       hverr = sun4v_mach_set_watchdog(wdd->timeout * 1000, NULL);
+       if (hverr == HV_EINVAL)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int sun4v_wdt_set_timeout(struct watchdog_device *wdd,
+                                unsigned int timeout)
+{
+       wdd->timeout = timeout;
+
+       return 0;
+}
+
+static const struct watchdog_info sun4v_wdt_ident = {
+       .options =      WDIOF_SETTIMEOUT |
+                       WDIOF_MAGICCLOSE |
+                       WDIOF_KEEPALIVEPING,
+       .identity =     "sun4v hypervisor watchdog",
+       .firmware_version = 0,
+};
+
+static struct watchdog_ops sun4v_wdt_ops = {
+       .owner =        THIS_MODULE,
+       .start =        sun4v_wdt_ping,
+       .stop =         sun4v_wdt_stop,
+       .ping =         sun4v_wdt_ping,
+       .set_timeout =  sun4v_wdt_set_timeout,
+};
+
+static struct watchdog_device wdd = {
+       .info = &sun4v_wdt_ident,
+       .ops = &sun4v_wdt_ops,
+       .min_timeout = WDT_MIN_TIMEOUT,
+       .max_timeout = WDT_MAX_TIMEOUT,
+       .timeout = WDT_TIMEOUT,
+};
+
+static int __init sun4v_wdt_init(void)
+{
+       struct mdesc_handle *handle;
+       u64 node;
+       const u64 *value;
+       int err = 0;
+       unsigned long major = 1, minor = 1;
+
+       /*
+        * There are 2 properties that can be set from the control
+        * domain for the watchdog.
+        * watchdog-resolution
+        * watchdog-max-timeout
+        *
+        * We can expect a handle to be returned otherwise something
+        * serious is wrong. Correct to return -ENODEV here.
+        */
+
+       handle = mdesc_grab();
+       if (!handle)
+               return -ENODEV;
+
+       node = mdesc_node_by_name(handle, MDESC_NODE_NULL, "platform");
+       err = -ENODEV;
+       if (node == MDESC_NODE_NULL)
+               goto out_release;
+
+       /*
+        * This is a safe way to validate if we are on the right
+        * platform.
+        */
+       if (sun4v_hvapi_register(HV_GRP_CORE, major, &minor))
+               goto out_hv_unreg;
+
+       /* Allow value of watchdog-resolution up to 1s (default) */
+       value = mdesc_get_property(handle, node, "watchdog-resolution", NULL);
+       err = -EINVAL;
+       if (value) {
+               if (*value == 0 ||
+                   *value > WDT_DEFAULT_RESOLUTION_MS)
+                       goto out_hv_unreg;
+       }
+
+       value = mdesc_get_property(handle, node, "watchdog-max-timeout", NULL);
+       if (value) {
+               /*
+                * If the property value (in ms) is smaller than
+                * min_timeout, return -EINVAL.
+                */
+               if (*value < wdd.min_timeout * 1000)
+                       goto out_hv_unreg;
+
+               /*
+                * If the property value is smaller than
+                * default max_timeout  then set watchdog max_timeout to
+                * the value of the property in seconds.
+                */
+               if (*value < wdd.max_timeout * 1000)
+                       wdd.max_timeout = *value  / 1000;
+       }
+
+       watchdog_init_timeout(&wdd, timeout, NULL);
+
+       watchdog_set_nowayout(&wdd, nowayout);
+
+       err = watchdog_register_device(&wdd);
+       if (err)
+               goto out_hv_unreg;
+
+       pr_info("initialized (timeout=%ds, nowayout=%d)\n",
+                wdd.timeout, nowayout);
+
+       mdesc_release(handle);
+
+       return 0;
+
+out_hv_unreg:
+       sun4v_hvapi_unregister(HV_GRP_CORE);
+
+out_release:
+       mdesc_release(handle);
+       return err;
+}
+
+static void __exit sun4v_wdt_exit(void)
+{
+       sun4v_hvapi_unregister(HV_GRP_CORE);
+       watchdog_unregister_device(&wdd);
+}
+
+module_init(sun4v_wdt_init);
+module_exit(sun4v_wdt_exit);
+
+MODULE_AUTHOR("Wim Coekaerts <wim.coekaerts@oracle.com>");
+MODULE_DESCRIPTION("sun4v watchdog driver");
+MODULE_LICENSE("GPL");
index 73708acce3ca78dfeb2da5fa78d6655e8f6554d4..979a8317204f219bda8a5391c323b85e8f10cb41 100644 (file)
@@ -37,23 +37,30 @@ config XEN_BALLOON_MEMORY_HOTPLUG
 
          Memory could be hotplugged in following steps:
 
-           1) dom0: xl mem-max <domU> <maxmem>
+           1) target domain: ensure that memory auto online policy is in
+              effect by checking /sys/devices/system/memory/auto_online_blocks
+              file (should be 'online').
+
+           2) control domain: xl mem-max <target-domain> <maxmem>
               where <maxmem> is >= requested memory size,
 
-           2) dom0: xl mem-set <domU> <memory>
+           3) control domain: xl mem-set <target-domain> <memory>
               where <memory> is requested memory size; alternatively memory
               could be added by writing proper value to
               /sys/devices/system/xen_memory/xen_memory0/target or
-              /sys/devices/system/xen_memory/xen_memory0/target_kb on dumU,
+              /sys/devices/system/xen_memory/xen_memory0/target_kb on the
+              target domain.
 
-           3) domU: for i in /sys/devices/system/memory/memory*/state; do \
-                      [ "`cat "$i"`" = offline ] && echo online > "$i"; done
+         Alternatively, if memory auto onlining was not requested at step 1
+         the newly added memory can be manually onlined in the target domain
+         by doing the following:
 
-         Memory could be onlined automatically on domU by adding following line to udev rules:
+               for i in /sys/devices/system/memory/memory*/state; do \
+                 [ "`cat "$i"`" = offline ] && echo online > "$i"; done
 
-         SUBSYSTEM=="memory", ACTION=="add", RUN+="/bin/sh -c '[ -f /sys$devpath/state ] && echo online > /sys$devpath/state'"
+         or by adding the following line to udev rules:
 
-         In that case step 3 should be omitted.
+         SUBSYSTEM=="memory", ACTION=="add", RUN+="/bin/sh -c '[ -f /sys$devpath/state ] && echo online > /sys$devpath/state'"
 
 config XEN_BALLOON_MEMORY_HOTPLUG_LIMIT
        int "Hotplugged memory limit (in GiB) for a PV guest"
index 12eab503efd1bb8793fff55eca83649e1f564426..7c8a2cf16f58b440bd4a7f23053fd6dea199f810 100644 (file)
@@ -257,7 +257,7 @@ static struct resource *additional_memory_resource(phys_addr_t size)
                return NULL;
 
        res->name = "System RAM";
-       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
        ret = allocate_resource(&iomem_resource, res,
                                size, 0, -1,
@@ -338,7 +338,16 @@ static enum bp_state reserve_additional_memory(void)
        }
 #endif
 
-       rc = add_memory_resource(nid, resource);
+       /*
+        * add_memory_resource() will call online_pages() which in its turn
+        * will call xen_online_page() callback causing deadlock if we don't
+        * release balloon_mutex here. Unlocking here is safe because the
+        * callers drop the mutex before trying again.
+        */
+       mutex_unlock(&balloon_mutex);
+       rc = add_memory_resource(nid, resource, memhp_auto_online);
+       mutex_lock(&balloon_mutex);
+
        if (rc) {
                pr_warn("Cannot add additional memory (%i)\n", rc);
                goto err;
index 7dd46312c18023c6e9ca6db16fba107c79a9bb84..403fe395539308431eecad718d5e613a94d2ad98 100644 (file)
@@ -38,8 +38,9 @@
 /* Find the first set bit in a evtchn mask */
 #define EVTCHN_FIRST_BIT(w) find_first_bit(BM(&(w)), BITS_PER_EVTCHN_WORD)
 
-static DEFINE_PER_CPU(xen_ulong_t [EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD],
-                     cpu_evtchn_mask);
+#define EVTCHN_MASK_SIZE (EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD)
+
+static DEFINE_PER_CPU(xen_ulong_t [EVTCHN_MASK_SIZE], cpu_evtchn_mask);
 
 static unsigned evtchn_2l_max_channels(void)
 {
index 36b210f9b6b29621fa9e410db063d3df53d7fb75..9282dbf5abdba6b01e059a45e7fc9895002dbd2d 100644 (file)
@@ -65,8 +65,7 @@ static ssize_t zorro_read_config(struct file *filp, struct kobject *kobj,
                                 struct bin_attribute *bin_attr,
                                 char *buf, loff_t off, size_t count)
 {
-       struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
-                                          kobj));
+       struct zorro_dev *z = to_zorro_dev(kobj_to_dev(kobj));
        struct ConfigDev cd;
 
        /* Construct a ConfigDev */
index 0548c53f41d51902a4e0ce7b983f7cd365f656f9..22fc7c802d698766fb5b274e686e89df4e0d76d1 100644 (file)
@@ -511,8 +511,6 @@ affs_do_readpage_ofs(struct page *page, unsigned to)
        pr_debug("%s(%lu, %ld, 0, %d)\n", __func__, inode->i_ino,
                 page->index, to);
        BUG_ON(to > PAGE_CACHE_SIZE);
-       kmap(page);
-       data = page_address(page);
        bsize = AFFS_SB(sb)->s_data_blksize;
        tmp = page->index << PAGE_CACHE_SHIFT;
        bidx = tmp / bsize;
@@ -524,14 +522,15 @@ affs_do_readpage_ofs(struct page *page, unsigned to)
                        return PTR_ERR(bh);
                tmp = min(bsize - boff, to - pos);
                BUG_ON(pos + tmp > to || tmp > bsize);
+               data = kmap_atomic(page);
                memcpy(data + pos, AFFS_DATA(bh) + boff, tmp);
+               kunmap_atomic(data);
                affs_brelse(bh);
                bidx++;
                pos += tmp;
                boff = 0;
        }
        flush_dcache_page(page);
-       kunmap(page);
        return 0;
 }
 
index c37149b929be50442ef40aacc36423eab9b264a2..f0d268b97d19657929ac2f50cd3bc0e1a80436c7 100644 (file)
@@ -1,15 +1,11 @@
-/* -*- c -*- ------------------------------------------------------------- *
- *   
- * linux/fs/autofs/autofs_i.h
- *
- *   Copyright 1997-1998 Transmeta Corporation - All Rights Reserved
- *   Copyright 2005-2006 Ian Kent <raven@themaw.net>
+/*
+ *  Copyright 1997-1998 Transmeta Corporation - All Rights Reserved
+ *  Copyright 2005-2006 Ian Kent <raven@themaw.net>
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
+ */
 
 /* Internal header file for autofs */
 
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <asm/current.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* #define DEBUG */
 
-#define DPRINTK(fmt, ...)                              \
-       pr_debug("pid %d: %s: " fmt "\n",               \
-               current->pid, __func__, ##__VA_ARGS__)
-
-#define AUTOFS_WARN(fmt, ...)                          \
-       printk(KERN_WARNING "pid %d: %s: " fmt "\n",    \
-               current->pid, __func__, ##__VA_ARGS__)
-
-#define AUTOFS_ERROR(fmt, ...)                         \
-       printk(KERN_ERR "pid %d: %s: " fmt "\n",        \
-               current->pid, __func__, ##__VA_ARGS__)
-
-/* Unified info structure.  This is pointed to by both the dentry and
-   inode structures.  Each file in the filesystem has an instance of this
-   structure.  It holds a reference to the dentry, so dentries are never
-   flushed while the file exists.  All name lookups are dealt with at the
-   dentry level, although the filesystem can interfere in the validation
-   process.  Readdir is implemented by traversing the dentry lists. */
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+#define pr_fmt(fmt) KBUILD_MODNAME ":pid:%d:%s: " fmt, current->pid, __func__
+
+/*
+ * Unified info structure.  This is pointed to by both the dentry and
+ * inode structures.  Each file in the filesystem has an instance of this
+ * structure.  It holds a reference to the dentry, so dentries are never
+ * flushed while the file exists.  All name lookups are dealt with at the
+ * dentry level, although the filesystem can interfere in the validation
+ * process.  Readdir is implemented by traversing the dentry lists.
+ */
 struct autofs_info {
        struct dentry   *dentry;
        struct inode    *inode;
@@ -78,7 +69,7 @@ struct autofs_info {
        kgid_t gid;
 };
 
-#define AUTOFS_INF_EXPIRING    (1<<0) /* dentry is in the process of expiring */
+#define AUTOFS_INF_EXPIRING    (1<<0) /* dentry in the process of expiring */
 #define AUTOFS_INF_NO_RCU      (1<<1) /* the dentry is being considered
                                        * for expiry, so RCU_walk is
                                        * not permitted
@@ -140,10 +131,11 @@ static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry)
 }
 
 /* autofs4_oz_mode(): do we see the man behind the curtain?  (The
-   processes which do manipulations for us in user space sees the raw
-   filesystem without "magic".) */
-
-static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) {
+ * processes which do manipulations for us in user space sees the raw
+ * filesystem without "magic".)
+ */
+static inline int autofs4_oz_mode(struct autofs_sb_info *sbi)
+{
        return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp;
 }
 
@@ -154,12 +146,12 @@ void autofs4_free_ino(struct autofs_info *);
 int is_autofs4_dentry(struct dentry *);
 int autofs4_expire_wait(struct dentry *dentry, int rcu_walk);
 int autofs4_expire_run(struct super_block *, struct vfsmount *,
-                       struct autofs_sb_info *,
-                       struct autofs_packet_expire __user *);
+                      struct autofs_sb_info *,
+                      struct autofs_packet_expire __user *);
 int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
                            struct autofs_sb_info *sbi, int when);
 int autofs4_expire_multi(struct super_block *, struct vfsmount *,
-                       struct autofs_sb_info *, int __user *);
+                        struct autofs_sb_info *, int __user *);
 struct dentry *autofs4_expire_direct(struct super_block *sb,
                                     struct vfsmount *mnt,
                                     struct autofs_sb_info *sbi, int how);
@@ -224,8 +216,8 @@ static inline int autofs_prepare_pipe(struct file *pipe)
 
 /* Queue management functions */
 
-int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
-int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
+int autofs4_wait(struct autofs_sb_info *, struct dentry *, enum autofs_notify);
+int autofs4_wait_release(struct autofs_sb_info *, autofs_wqt_t, int);
 void autofs4_catatonic_mode(struct autofs_sb_info *);
 
 static inline u32 autofs4_get_dev(struct autofs_sb_info *sbi)
@@ -242,37 +234,37 @@ static inline void __autofs4_add_expiring(struct dentry *dentry)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
+
        if (ino) {
                if (list_empty(&ino->expiring))
                        list_add(&ino->expiring, &sbi->expiring_list);
        }
-       return;
 }
 
 static inline void autofs4_add_expiring(struct dentry *dentry)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
+
        if (ino) {
                spin_lock(&sbi->lookup_lock);
                if (list_empty(&ino->expiring))
                        list_add(&ino->expiring, &sbi->expiring_list);
                spin_unlock(&sbi->lookup_lock);
        }
-       return;
 }
 
 static inline void autofs4_del_expiring(struct dentry *dentry)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
+
        if (ino) {
                spin_lock(&sbi->lookup_lock);
                if (!list_empty(&ino->expiring))
                        list_del_init(&ino->expiring);
                spin_unlock(&sbi->lookup_lock);
        }
-       return;
 }
 
 extern void autofs4_kill_sb(struct super_block *);
index ac7d921ed9844b0a0c6afd0e6d4eaf4ca718f955..c7fcc743884374cf695f530036701610d78d79a7 100644 (file)
@@ -72,13 +72,13 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param)
 {
        int err = 0;
 
-       if ((AUTOFS_DEV_IOCTL_VERSION_MAJOR != param->ver_major) ||
-           (AUTOFS_DEV_IOCTL_VERSION_MINOR < param->ver_minor)) {
-               AUTOFS_WARN("ioctl control interface version mismatch: "
-                    "kernel(%u.%u), user(%u.%u), cmd(%d)",
-                    AUTOFS_DEV_IOCTL_VERSION_MAJOR,
-                    AUTOFS_DEV_IOCTL_VERSION_MINOR,
-                    param->ver_major, param->ver_minor, cmd);
+       if ((param->ver_major != AUTOFS_DEV_IOCTL_VERSION_MAJOR) ||
+           (param->ver_minor > AUTOFS_DEV_IOCTL_VERSION_MINOR)) {
+               pr_warn("ioctl control interface version mismatch: "
+                       "kernel(%u.%u), user(%u.%u), cmd(%d)\n",
+                       AUTOFS_DEV_IOCTL_VERSION_MAJOR,
+                       AUTOFS_DEV_IOCTL_VERSION_MINOR,
+                       param->ver_major, param->ver_minor, cmd);
                err = -EINVAL;
        }
 
@@ -93,7 +93,8 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param)
  * Copy parameter control struct, including a possible path allocated
  * at the end of the struct.
  */
-static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in)
+static struct autofs_dev_ioctl *
+               copy_dev_ioctl(struct autofs_dev_ioctl __user *in)
 {
        struct autofs_dev_ioctl tmp, *res;
 
@@ -116,7 +117,6 @@ static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *i
 static inline void free_dev_ioctl(struct autofs_dev_ioctl *param)
 {
        kfree(param);
-       return;
 }
 
 /*
@@ -129,24 +129,24 @@ static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
 
        err = check_dev_ioctl_version(cmd, param);
        if (err) {
-               AUTOFS_WARN("invalid device control module version "
-                    "supplied for cmd(0x%08x)", cmd);
+               pr_warn("invalid device control module version "
+                       "supplied for cmd(0x%08x)\n", cmd);
                goto out;
        }
 
        if (param->size > sizeof(*param)) {
                err = invalid_str(param->path, param->size - sizeof(*param));
                if (err) {
-                       AUTOFS_WARN(
-                         "path string terminator missing for cmd(0x%08x)",
+                       pr_warn(
+                         "path string terminator missing for cmd(0x%08x)\n",
                          cmd);
                        goto out;
                }
 
                err = check_name(param->path);
                if (err) {
-                       AUTOFS_WARN("invalid path supplied for cmd(0x%08x)",
-                                   cmd);
+                       pr_warn("invalid path supplied for cmd(0x%08x)\n",
+                               cmd);
                        goto out;
                }
        }
@@ -197,7 +197,9 @@ static int find_autofs_mount(const char *pathname,
                             void *data)
 {
        struct path path;
-       int err = kern_path_mountpoint(AT_FDCWD, pathname, &path, 0);
+       int err;
+
+       err = kern_path_mountpoint(AT_FDCWD, pathname, &path, 0);
        if (err)
                return err;
        err = -ENOENT;
@@ -225,6 +227,7 @@ static int test_by_dev(struct path *path, void *p)
 static int test_by_type(struct path *path, void *p)
 {
        struct autofs_info *ino = autofs4_dentry_ino(path->dentry);
+
        return ino && ino->sbi->type & *(unsigned *)p;
 }
 
@@ -370,7 +373,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
                new_pid = get_task_pid(current, PIDTYPE_PGID);
 
                if (ns_of_pid(new_pid) != ns_of_pid(sbi->oz_pgrp)) {
-                       AUTOFS_WARN("Not allowed to change PID namespace");
+                       pr_warn("not allowed to change PID namespace\n");
                        err = -EINVAL;
                        goto out;
                }
@@ -456,8 +459,10 @@ static int autofs_dev_ioctl_requester(struct file *fp,
                err = 0;
                autofs4_expire_wait(path.dentry, 0);
                spin_lock(&sbi->fs_lock);
-               param->requester.uid = from_kuid_munged(current_user_ns(), ino->uid);
-               param->requester.gid = from_kgid_munged(current_user_ns(), ino->gid);
+               param->requester.uid =
+                       from_kuid_munged(current_user_ns(), ino->uid);
+               param->requester.gid =
+                       from_kgid_munged(current_user_ns(), ino->gid);
                spin_unlock(&sbi->fs_lock);
        }
        path_put(&path);
@@ -619,7 +624,8 @@ static ioctl_fn lookup_dev_ioctl(unsigned int cmd)
 }
 
 /* ioctl dispatcher */
-static int _autofs_dev_ioctl(unsigned int command, struct autofs_dev_ioctl __user *user)
+static int _autofs_dev_ioctl(unsigned int command,
+                            struct autofs_dev_ioctl __user *user)
 {
        struct autofs_dev_ioctl *param;
        struct file *fp;
@@ -655,7 +661,7 @@ static int _autofs_dev_ioctl(unsigned int command, struct autofs_dev_ioctl __use
 
        fn = lookup_dev_ioctl(cmd);
        if (!fn) {
-               AUTOFS_WARN("unknown command 0x%08x", command);
+               pr_warn("unknown command 0x%08x\n", command);
                return -ENOTTY;
        }
 
@@ -711,6 +717,7 @@ out:
 static long autofs_dev_ioctl(struct file *file, uint command, ulong u)
 {
        int err;
+
        err = _autofs_dev_ioctl(command, (struct autofs_dev_ioctl __user *) u);
        return (long) err;
 }
@@ -733,8 +740,8 @@ static const struct file_operations _dev_ioctl_fops = {
 
 static struct miscdevice _autofs_dev_ioctl_misc = {
        .minor          = AUTOFS_MINOR,
-       .name           = AUTOFS_DEVICE_NAME,
-       .fops           = &_dev_ioctl_fops
+       .name           = AUTOFS_DEVICE_NAME,
+       .fops           = &_dev_ioctl_fops
 };
 
 MODULE_ALIAS_MISCDEV(AUTOFS_MINOR);
@@ -747,7 +754,7 @@ int __init autofs_dev_ioctl_init(void)
 
        r = misc_register(&_autofs_dev_ioctl_misc);
        if (r) {
-               AUTOFS_ERROR("misc_register failed for control device");
+               pr_err("misc_register failed for control device\n");
                return r;
        }
 
@@ -757,6 +764,4 @@ int __init autofs_dev_ioctl_init(void)
 void autofs_dev_ioctl_exit(void)
 {
        misc_deregister(&_autofs_dev_ioctl_misc);
-       return;
 }
-
index 1cebc3c52fa5792242144c939908be50040b9e0b..9510d8d2e9cd2fa4ac7919c7bd8bee48c30d6165 100644 (file)
@@ -1,16 +1,12 @@
-/* -*- c -*- --------------------------------------------------------------- *
- *
- * linux/fs/autofs/expire.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *  Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
- *  Copyright 2001-2006 Ian Kent <raven@themaw.net>
+/*
+ * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
+ * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
+ */
 
 #include "autofs_i.h"
 
@@ -18,7 +14,7 @@ static unsigned long now;
 
 /* Check if a dentry can be expired */
 static inline int autofs4_can_expire(struct dentry *dentry,
-                                       unsigned long timeout, int do_now)
+                                    unsigned long timeout, int do_now)
 {
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
 
@@ -41,7 +37,7 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
        struct path path = {.mnt = mnt, .dentry = dentry};
        int status = 1;
 
-       DPRINTK("dentry %p %pd", dentry, dentry);
+       pr_debug("dentry %p %pd\n", dentry, dentry);
 
        path_get(&path);
 
@@ -58,14 +54,16 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
 
        /* Update the expiry counter if fs is busy */
        if (!may_umount_tree(path.mnt)) {
-               struct autofs_info *ino = autofs4_dentry_ino(top);
+               struct autofs_info *ino;
+
+               ino = autofs4_dentry_ino(top);
                ino->last_used = jiffies;
                goto done;
        }
 
        status = 0;
 done:
-       DPRINTK("returning = %d", status);
+       pr_debug("returning = %d\n", status);
        path_put(&path);
        return status;
 }
@@ -74,7 +72,7 @@ done:
  * Calculate and dget next entry in the subdirs list under root.
  */
 static struct dentry *get_next_positive_subdir(struct dentry *prev,
-                                               struct dentry *root)
+                                              struct dentry *root)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
        struct list_head *next;
@@ -121,7 +119,7 @@ cont:
  * Calculate and dget next entry in top down tree traversal.
  */
 static struct dentry *get_next_positive_dentry(struct dentry *prev,
-                                               struct dentry *root)
+                                              struct dentry *root)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);
        struct list_head *next;
@@ -187,15 +185,17 @@ again:
  * autofs submounts.
  */
 static int autofs4_direct_busy(struct vfsmount *mnt,
-                               struct dentry *top,
-                               unsigned long timeout,
-                               int do_now)
+                              struct dentry *top,
+                              unsigned long timeout,
+                              int do_now)
 {
-       DPRINTK("top %p %pd", top, top);
+       pr_debug("top %p %pd\n", top, top);
 
        /* If it's busy update the expiry counters */
        if (!may_umount_tree(mnt)) {
-               struct autofs_info *ino = autofs4_dentry_ino(top);
+               struct autofs_info *ino;
+
+               ino = autofs4_dentry_ino(top);
                if (ino)
                        ino->last_used = jiffies;
                return 1;
@@ -208,7 +208,8 @@ static int autofs4_direct_busy(struct vfsmount *mnt,
        return 0;
 }
 
-/* Check a directory tree of mount points for busyness
+/*
+ * Check a directory tree of mount points for busyness
  * The tree is not busy iff no mountpoints are busy
  */
 static int autofs4_tree_busy(struct vfsmount *mnt,
@@ -219,7 +220,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
        struct autofs_info *top_ino = autofs4_dentry_ino(top);
        struct dentry *p;
 
-       DPRINTK("top %p %pd", top, top);
+       pr_debug("top %p %pd\n", top, top);
 
        /* Negative dentry - give up */
        if (!simple_positive(top))
@@ -227,7 +228,7 @@ static int autofs4_tree_busy(struct vfsmount *mnt,
 
        p = NULL;
        while ((p = get_next_positive_dentry(p, top))) {
-               DPRINTK("dentry %p %pd", p, p);
+               pr_debug("dentry %p %pd\n", p, p);
 
                /*
                 * Is someone visiting anywhere in the subtree ?
@@ -273,11 +274,11 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
 {
        struct dentry *p;
 
-       DPRINTK("parent %p %pd", parent, parent);
+       pr_debug("parent %p %pd\n", parent, parent);
 
        p = NULL;
        while ((p = get_next_positive_dentry(p, parent))) {
-               DPRINTK("dentry %p %pd", p, p);
+               pr_debug("dentry %p %pd\n", p, p);
 
                if (d_mountpoint(p)) {
                        /* Can we umount this guy */
@@ -362,7 +363,7 @@ static struct dentry *should_expire(struct dentry *dentry,
         *         offset (autofs-5.0+).
         */
        if (d_mountpoint(dentry)) {
-               DPRINTK("checking mountpoint %p %pd", dentry, dentry);
+               pr_debug("checking mountpoint %p %pd\n", dentry, dentry);
 
                /* Can we umount this guy */
                if (autofs4_mount_busy(mnt, dentry))
@@ -375,7 +376,7 @@ static struct dentry *should_expire(struct dentry *dentry,
        }
 
        if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
-               DPRINTK("checking symlink %p %pd", dentry, dentry);
+               pr_debug("checking symlink %p %pd\n", dentry, dentry);
                /*
                 * A symlink can't be "busy" in the usual sense so
                 * just check last used for expire timeout.
@@ -404,6 +405,7 @@ static struct dentry *should_expire(struct dentry *dentry,
        } else {
                /* Path walk currently on this dentry? */
                struct dentry *expired;
+
                ino_count = atomic_read(&ino->count) + 1;
                if (d_count(dentry) > ino_count)
                        return NULL;
@@ -471,7 +473,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
        return NULL;
 
 found:
-       DPRINTK("returning %p %pd", expired, expired);
+       pr_debug("returning %p %pd\n", expired, expired);
        ino->flags |= AUTOFS_INF_EXPIRING;
        smp_mb();
        ino->flags &= ~AUTOFS_INF_NO_RCU;
@@ -503,12 +505,12 @@ int autofs4_expire_wait(struct dentry *dentry, int rcu_walk)
        if (ino->flags & AUTOFS_INF_EXPIRING) {
                spin_unlock(&sbi->fs_lock);
 
-               DPRINTK("waiting for expire %p name=%pd", dentry, dentry);
+               pr_debug("waiting for expire %p name=%pd\n", dentry, dentry);
 
                status = autofs4_wait(sbi, dentry, NFY_NONE);
                wait_for_completion(&ino->expire_complete);
 
-               DPRINTK("expire done status=%d", status);
+               pr_debug("expire done status=%d\n", status);
 
                if (d_unhashed(dentry))
                        return -EAGAIN;
@@ -522,21 +524,22 @@ int autofs4_expire_wait(struct dentry *dentry, int rcu_walk)
 
 /* Perform an expiry operation */
 int autofs4_expire_run(struct super_block *sb,
-                     struct vfsmount *mnt,
-                     struct autofs_sb_info *sbi,
-                     struct autofs_packet_expire __user *pkt_p)
+                      struct vfsmount *mnt,
+                      struct autofs_sb_info *sbi,
+                      struct autofs_packet_expire __user *pkt_p)
 {
        struct autofs_packet_expire pkt;
        struct autofs_info *ino;
        struct dentry *dentry;
        int ret = 0;
 
-       memset(&pkt,0,sizeof pkt);
+       memset(&pkt, 0, sizeof(pkt));
 
        pkt.hdr.proto_version = sbi->version;
        pkt.hdr.type = autofs_ptype_expire;
 
-       if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL)
+       dentry = autofs4_expire_indirect(sb, mnt, sbi, 0);
+       if (!dentry)
                return -EAGAIN;
 
        pkt.len = dentry->d_name.len;
@@ -544,7 +547,7 @@ int autofs4_expire_run(struct super_block *sb,
        pkt.name[pkt.len] = '\0';
        dput(dentry);
 
-       if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
+       if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
                ret = -EFAULT;
 
        spin_lock(&sbi->fs_lock);
@@ -573,7 +576,8 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
                struct autofs_info *ino = autofs4_dentry_ino(dentry);
 
                /* This is synchronous because it makes the daemon a
-                   little easier */
+                * little easier
+                */
                ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
 
                spin_lock(&sbi->fs_lock);
@@ -588,8 +592,10 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
        return ret;
 }
 
-/* Call repeatedly until it returns -EAGAIN, meaning there's nothing
-   more to be done */
+/*
+ * Call repeatedly until it returns -EAGAIN, meaning there's nothing
+ * more to be done.
+ */
 int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt,
                        struct autofs_sb_info *sbi, int __user *arg)
 {
index b3db517e89ec12b771a77f46deb2572782b83e09..8cf0e63389ae34c2b86716a674974727629fc63e 100644 (file)
@@ -1,14 +1,10 @@
-/* -*- c -*- --------------------------------------------------------------- *
- *
- * linux/fs/autofs/init.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
+/*
+ * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
+ */
 
 #include <linux/module.h>
 #include <linux/init.h>
index a3ae0b2aeb5a0feeaeb43d5c3016bc13a0ca1d19..61b21051bd5ad9322a58ef1caa7cccc09d25ba2b 100644 (file)
@@ -1,15 +1,11 @@
-/* -*- c -*- --------------------------------------------------------------- *
- *
- * linux/fs/autofs/inode.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *  Copyright 2005-2006 Ian Kent <raven@themaw.net>
+/*
+ * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
+ * Copyright 2005-2006 Ian Kent <raven@themaw.net>
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
+ */
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -24,7 +20,9 @@
 
 struct autofs_info *autofs4_new_ino(struct autofs_sb_info *sbi)
 {
-       struct autofs_info *ino = kzalloc(sizeof(*ino), GFP_KERNEL);
+       struct autofs_info *ino;
+
+       ino = kzalloc(sizeof(*ino), GFP_KERNEL);
        if (ino) {
                INIT_LIST_HEAD(&ino->active);
                INIT_LIST_HEAD(&ino->expiring);
@@ -62,7 +60,7 @@ void autofs4_kill_sb(struct super_block *sb)
                put_pid(sbi->oz_pgrp);
        }
 
-       DPRINTK("shutting down");
+       pr_debug("shutting down\n");
        kill_litter_super(sb);
        if (sbi)
                kfree_rcu(sbi, rcu);
@@ -94,7 +92,12 @@ static int autofs4_show_options(struct seq_file *m, struct dentry *root)
                seq_printf(m, ",direct");
        else
                seq_printf(m, ",indirect");
-
+#ifdef CONFIG_CHECKPOINT_RESTORE
+       if (sbi->pipe)
+               seq_printf(m, ",pipe_ino=%ld", sbi->pipe->f_inode->i_ino);
+       else
+               seq_printf(m, ",pipe_ino=-1");
+#endif
        return 0;
 }
 
@@ -147,6 +150,7 @@ static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
 
        while ((p = strsep(&options, ",")) != NULL) {
                int token;
+
                if (!*p)
                        continue;
 
@@ -204,9 +208,9 @@ static int parse_options(char *options, int *pipefd, kuid_t *uid, kgid_t *gid,
 
 int autofs4_fill_super(struct super_block *s, void *data, int silent)
 {
-       struct inode * root_inode;
-       struct dentry * root;
-       struct file * pipe;
+       struct inode *root_inode;
+       struct dentry *root;
+       struct file *pipe;
        int pipefd;
        struct autofs_sb_info *sbi;
        struct autofs_info *ino;
@@ -217,7 +221,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
-       DPRINTK("starting up, sbi = %p",sbi);
+       pr_debug("starting up, sbi = %p\n", sbi);
 
        s->s_fs_info = sbi;
        sbi->magic = AUTOFS_SBI_MAGIC;
@@ -266,14 +270,14 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid,
                          &pgrp, &pgrp_set, &sbi->type, &sbi->min_proto,
                          &sbi->max_proto)) {
-               printk("autofs: called with bogus options\n");
+               pr_err("called with bogus options\n");
                goto fail_dput;
        }
 
        if (pgrp_set) {
                sbi->oz_pgrp = find_get_pid(pgrp);
                if (!sbi->oz_pgrp) {
-                       pr_warn("autofs: could not find process group %d\n",
+                       pr_err("could not find process group %d\n",
                                pgrp);
                        goto fail_dput;
                }
@@ -290,10 +294,10 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
        /* Couldn't this be tested earlier? */
        if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION ||
            sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) {
-               printk("autofs: kernel does not match daemon version "
+               pr_err("kernel does not match daemon version "
                       "daemon (%d, %d) kernel (%d, %d)\n",
-                       sbi->min_proto, sbi->max_proto,
-                       AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
+                      sbi->min_proto, sbi->max_proto,
+                      AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
                goto fail_dput;
        }
 
@@ -304,11 +308,11 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
                sbi->version = sbi->max_proto;
        sbi->sub_version = AUTOFS_PROTO_SUBVERSION;
 
-       DPRINTK("pipe fd = %d, pgrp = %u", pipefd, pid_nr(sbi->oz_pgrp));
+       pr_debug("pipe fd = %d, pgrp = %u\n", pipefd, pid_nr(sbi->oz_pgrp));
        pipe = fget(pipefd);
 
        if (!pipe) {
-               printk("autofs: could not open pipe file descriptor\n");
+               pr_err("could not open pipe file descriptor\n");
                goto fail_dput;
        }
        ret = autofs_prepare_pipe(pipe);
@@ -323,12 +327,12 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
         */
        s->s_root = root;
        return 0;
-       
+
        /*
         * Failure ... clean up.
         */
 fail_fput:
-       printk("autofs: pipe file descriptor does not contain proper ops\n");
+       pr_err("pipe file descriptor does not contain proper ops\n");
        fput(pipe);
        /* fall through */
 fail_dput:
index c6d7d3dbd52abfa9af11ea0fb7aab955e355bbc9..9328b5861c7a91e7854d5f9c5d5a6a24a46cfce4 100644 (file)
@@ -1,16 +1,12 @@
-/* -*- c -*- --------------------------------------------------------------- *
- *
- * linux/fs/autofs/root.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *  Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
- *  Copyright 2001-2006 Ian Kent <raven@themaw.net>
+/*
+ * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
+ * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
+ */
 
 #include <linux/capability.h>
 #include <linux/errno.h>
 
 #include "autofs_i.h"
 
-static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
-static int autofs4_dir_unlink(struct inode *,struct dentry *);
-static int autofs4_dir_rmdir(struct inode *,struct dentry *);
-static int autofs4_dir_mkdir(struct inode *,struct dentry *,umode_t);
-static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long);
+static int autofs4_dir_symlink(struct inode *, struct dentry *, const char *);
+static int autofs4_dir_unlink(struct inode *, struct dentry *);
+static int autofs4_dir_rmdir(struct inode *, struct dentry *);
+static int autofs4_dir_mkdir(struct inode *, struct dentry *, umode_t);
+static long autofs4_root_ioctl(struct file *, unsigned int, unsigned long);
 #ifdef CONFIG_COMPAT
-static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
+static long autofs4_root_compat_ioctl(struct file *,
+                                     unsigned int, unsigned long);
 #endif
 static int autofs4_dir_open(struct inode *inode, struct file *file);
-static struct dentry *autofs4_lookup(struct inode *,struct dentry *, unsigned int);
+static struct dentry *autofs4_lookup(struct inode *,
+                                    struct dentry *, unsigned int);
 static struct vfsmount *autofs4_d_automount(struct path *);
 static int autofs4_d_manage(struct dentry *, bool);
 static void autofs4_dentry_release(struct dentry *);
@@ -74,7 +72,9 @@ const struct dentry_operations autofs4_dentry_operations = {
 static void autofs4_add_active(struct dentry *dentry)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-       struct autofs_info *ino = autofs4_dentry_ino(dentry);
+       struct autofs_info *ino;
+
+       ino = autofs4_dentry_ino(dentry);
        if (ino) {
                spin_lock(&sbi->lookup_lock);
                if (!ino->active_count) {
@@ -84,13 +84,14 @@ static void autofs4_add_active(struct dentry *dentry)
                ino->active_count++;
                spin_unlock(&sbi->lookup_lock);
        }
-       return;
 }
 
 static void autofs4_del_active(struct dentry *dentry)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-       struct autofs_info *ino = autofs4_dentry_ino(dentry);
+       struct autofs_info *ino;
+
+       ino = autofs4_dentry_ino(dentry);
        if (ino) {
                spin_lock(&sbi->lookup_lock);
                ino->active_count--;
@@ -100,7 +101,6 @@ static void autofs4_del_active(struct dentry *dentry)
                }
                spin_unlock(&sbi->lookup_lock);
        }
-       return;
 }
 
 static int autofs4_dir_open(struct inode *inode, struct file *file)
@@ -108,7 +108,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
        struct dentry *dentry = file->f_path.dentry;
        struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 
-       DPRINTK("file=%p dentry=%p %pd", file, dentry, dentry);
+       pr_debug("file=%p dentry=%p %pd\n", file, dentry, dentry);
 
        if (autofs4_oz_mode(sbi))
                goto out;
@@ -138,7 +138,7 @@ static void autofs4_dentry_release(struct dentry *de)
        struct autofs_info *ino = autofs4_dentry_ino(de);
        struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb);
 
-       DPRINTK("releasing %p", de);
+       pr_debug("releasing %p\n", de);
 
        if (!ino)
                return;
@@ -278,9 +278,9 @@ static int autofs4_mount_wait(struct dentry *dentry, bool rcu_walk)
        if (ino->flags & AUTOFS_INF_PENDING) {
                if (rcu_walk)
                        return -ECHILD;
-               DPRINTK("waiting for mount name=%pd", dentry);
+               pr_debug("waiting for mount name=%pd\n", dentry);
                status = autofs4_wait(sbi, dentry, NFY_MOUNT);
-               DPRINTK("mount wait done status=%d", status);
+               pr_debug("mount wait done status=%d\n", status);
        }
        ino->last_used = jiffies;
        return status;
@@ -320,7 +320,9 @@ static struct dentry *autofs4_mountpoint_changed(struct path *path)
        if (autofs_type_indirect(sbi->type) && d_unhashed(dentry)) {
                struct dentry *parent = dentry->d_parent;
                struct autofs_info *ino;
-               struct dentry *new = d_lookup(parent, &dentry->d_name);
+               struct dentry *new;
+
+               new = d_lookup(parent, &dentry->d_name);
                if (!new)
                        return NULL;
                ino = autofs4_dentry_ino(new);
@@ -338,7 +340,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
        int status;
 
-       DPRINTK("dentry=%p %pd", dentry, dentry);
+       pr_debug("dentry=%p %pd\n", dentry, dentry);
 
        /* The daemon never triggers a mount. */
        if (autofs4_oz_mode(sbi))
@@ -425,7 +427,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
        int status;
 
-       DPRINTK("dentry=%p %pd", dentry, dentry);
+       pr_debug("dentry=%p %pd\n", dentry, dentry);
 
        /* The daemon never waits. */
        if (autofs4_oz_mode(sbi)) {
@@ -455,6 +457,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
                 * a mount-trap.
                 */
                struct inode *inode;
+
                if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))
                        return 0;
                if (d_mountpoint(dentry))
@@ -494,13 +497,14 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
 }
 
 /* Lookups in the root directory */
-static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+static struct dentry *autofs4_lookup(struct inode *dir,
+                                    struct dentry *dentry, unsigned int flags)
 {
        struct autofs_sb_info *sbi;
        struct autofs_info *ino;
        struct dentry *active;
 
-       DPRINTK("name = %pd", dentry);
+       pr_debug("name = %pd\n", dentry);
 
        /* File name too long to exist */
        if (dentry->d_name.len > NAME_MAX)
@@ -508,14 +512,14 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, u
 
        sbi = autofs4_sbi(dir->i_sb);
 
-       DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d",
-               current->pid, task_pgrp_nr(current), sbi->catatonic,
-               autofs4_oz_mode(sbi));
+       pr_debug("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n",
+                current->pid, task_pgrp_nr(current), sbi->catatonic,
+                autofs4_oz_mode(sbi));
 
        active = autofs4_lookup_active(dentry);
-       if (active) {
+       if (active)
                return active;
-       else {
+       else {
                /*
                 * A dentry that is not within the root can never trigger a
                 * mount operation, unless the directory already exists, so we
@@ -526,7 +530,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, u
                        return ERR_PTR(-ENOENT);
 
                /* Mark entries in the root as mount triggers */
-               if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent))
+               if (IS_ROOT(dentry->d_parent) &&
+                   autofs_type_indirect(sbi->type))
                        __managed_dentry_set_managed(dentry);
 
                ino = autofs4_new_ino(sbi);
@@ -554,7 +559,7 @@ static int autofs4_dir_symlink(struct inode *dir,
        size_t size = strlen(symname);
        char *cp;
 
-       DPRINTK("%s <- %pd", symname, dentry);
+       pr_debug("%s <- %pd\n", symname, dentry);
 
        if (!autofs4_oz_mode(sbi))
                return -EACCES;
@@ -613,7 +618,7 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
        struct autofs_info *p_ino;
-       
+
        /* This allows root to remove symlinks */
        if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -664,7 +669,6 @@ static void autofs_set_leaf_automount_flags(struct dentry *dentry)
        if (IS_ROOT(parent->d_parent))
                return;
        managed_dentry_clear_managed(parent);
-       return;
 }
 
 static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
@@ -687,7 +691,6 @@ static void autofs_clear_leaf_automount_flags(struct dentry *dentry)
        if (d_child->next == &parent->d_subdirs &&
            d_child->prev == &parent->d_subdirs)
                managed_dentry_set_managed(parent);
-       return;
 }
 
 static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
@@ -695,8 +698,8 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
        struct autofs_info *p_ino;
-       
-       DPRINTK("dentry %p, removing %pd", dentry, dentry);
+
+       pr_debug("dentry %p, removing %pd\n", dentry, dentry);
 
        if (!autofs4_oz_mode(sbi))
                return -EACCES;
@@ -728,7 +731,8 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
        return 0;
 }
 
-static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+static int autofs4_dir_mkdir(struct inode *dir,
+                            struct dentry *dentry, umode_t mode)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
@@ -738,7 +742,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, umode_t m
        if (!autofs4_oz_mode(sbi))
                return -EACCES;
 
-       DPRINTK("dentry %p, creating %pd", dentry, dentry);
+       pr_debug("dentry %p, creating %pd\n", dentry, dentry);
 
        BUG_ON(!ino);
 
@@ -768,14 +772,18 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, umode_t m
 /* Get/set timeout ioctl() operation */
 #ifdef CONFIG_COMPAT
 static inline int autofs4_compat_get_set_timeout(struct autofs_sb_info *sbi,
-                                        compat_ulong_t __user *p)
+                                                compat_ulong_t __user *p)
 {
-       int rv;
        unsigned long ntimeout;
+       int rv;
 
-       if ((rv = get_user(ntimeout, p)) ||
-            (rv = put_user(sbi->exp_timeout/HZ, p)))
-               return rv;
+       rv = get_user(ntimeout, p);
+       if (rv)
+               goto error;
+
+       rv = put_user(sbi->exp_timeout/HZ, p);
+       if (rv)
+               goto error;
 
        if (ntimeout > UINT_MAX/HZ)
                sbi->exp_timeout = 0;
@@ -783,18 +791,24 @@ static inline int autofs4_compat_get_set_timeout(struct autofs_sb_info *sbi,
                sbi->exp_timeout = ntimeout * HZ;
 
        return 0;
+error:
+       return rv;
 }
 #endif
 
 static inline int autofs4_get_set_timeout(struct autofs_sb_info *sbi,
-                                        unsigned long __user *p)
+                                         unsigned long __user *p)
 {
-       int rv;
        unsigned long ntimeout;
+       int rv;
 
-       if ((rv = get_user(ntimeout, p)) ||
-            (rv = put_user(sbi->exp_timeout/HZ, p)))
-               return rv;
+       rv = get_user(ntimeout, p);
+       if (rv)
+               goto error;
+
+       rv = put_user(sbi->exp_timeout/HZ, p);
+       if (rv)
+               goto error;
 
        if (ntimeout > ULONG_MAX/HZ)
                sbi->exp_timeout = 0;
@@ -802,16 +816,20 @@ static inline int autofs4_get_set_timeout(struct autofs_sb_info *sbi,
                sbi->exp_timeout = ntimeout * HZ;
 
        return 0;
+error:
+       return rv;
 }
 
 /* Return protocol version */
-static inline int autofs4_get_protover(struct autofs_sb_info *sbi, int __user *p)
+static inline int autofs4_get_protover(struct autofs_sb_info *sbi,
+                                      int __user *p)
 {
        return put_user(sbi->version, p);
 }
 
 /* Return protocol sub version */
-static inline int autofs4_get_protosubver(struct autofs_sb_info *sbi, int __user *p)
+static inline int autofs4_get_protosubver(struct autofs_sb_info *sbi,
+                                         int __user *p)
 {
        return put_user(sbi->sub_version, p);
 }
@@ -826,7 +844,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)
        if (may_umount(mnt))
                status = 1;
 
-       DPRINTK("returning %d", status);
+       pr_debug("returning %d\n", status);
 
        status = put_user(status, p);
 
@@ -834,9 +852,9 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p)
 }
 
 /* Identify autofs4_dentries - this is so we can tell if there's
  an extra dentry refcount or not.  We only hold a refcount on the
  dentry if its non-negative (ie, d_inode != NULL)
-*/
* an extra dentry refcount or not.  We only hold a refcount on the
* dentry if its non-negative (ie, d_inode != NULL)
+ */
 int is_autofs4_dentry(struct dentry *dentry)
 {
        return dentry && d_really_is_positive(dentry) &&
@@ -854,21 +872,21 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp,
        struct autofs_sb_info *sbi = autofs4_sbi(inode->i_sb);
        void __user *p = (void __user *)arg;
 
-       DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u",
-               cmd,arg,sbi,task_pgrp_nr(current));
+       pr_debug("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",
+                cmd, arg, sbi, task_pgrp_nr(current));
 
        if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
             _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
                return -ENOTTY;
-       
+
        if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
                return -EPERM;
-       
-       switch(cmd) {
+
+       switch (cmd) {
        case AUTOFS_IOC_READY:  /* Wait queue: go ahead and retry */
-               return autofs4_wait_release(sbi,(autofs_wqt_t)arg,0);
+               return autofs4_wait_release(sbi, (autofs_wqt_t) arg, 0);
        case AUTOFS_IOC_FAIL:   /* Wait queue: fail with ENOENT */
-               return autofs4_wait_release(sbi,(autofs_wqt_t)arg,-ENOENT);
+               return autofs4_wait_release(sbi, (autofs_wqt_t) arg, -ENOENT);
        case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */
                autofs4_catatonic_mode(sbi);
                return 0;
@@ -888,13 +906,15 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp,
 
        /* return a single thing to expire */
        case AUTOFS_IOC_EXPIRE:
-               return autofs4_expire_run(inode->i_sb,filp->f_path.mnt,sbi, p);
+               return autofs4_expire_run(inode->i_sb,
+                                         filp->f_path.mnt, sbi, p);
        /* same as above, but can send multiple expires through pipe */
        case AUTOFS_IOC_EXPIRE_MULTI:
-               return autofs4_expire_multi(inode->i_sb,filp->f_path.mnt,sbi, p);
+               return autofs4_expire_multi(inode->i_sb,
+                                           filp->f_path.mnt, sbi, p);
 
        default:
-               return -ENOSYS;
+               return -EINVAL;
        }
 }
 
@@ -902,12 +922,13 @@ static long autofs4_root_ioctl(struct file *filp,
                               unsigned int cmd, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
+
        return autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
 }
 
 #ifdef CONFIG_COMPAT
 static long autofs4_root_compat_ioctl(struct file *filp,
-                            unsigned int cmd, unsigned long arg)
+                                     unsigned int cmd, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
        int ret;
@@ -916,7 +937,7 @@ static long autofs4_root_compat_ioctl(struct file *filp,
                ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg);
        else
                ret = autofs4_root_ioctl_unlocked(inode, filp, cmd,
-                       (unsigned long)compat_ptr(arg));
+                                             (unsigned long) compat_ptr(arg));
 
        return ret;
 }
index 84e037d1d129336a7d052ad2881db238785bd350..99aab00dc21763505adbe5a1d8d992a83e131aaf 100644 (file)
@@ -1,14 +1,10 @@
-/* -*- c -*- --------------------------------------------------------------- *
- *
- * linux/fs/autofs/symlink.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
+/*
+ * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
+ */
 
 #include "autofs_i.h"
 
@@ -18,6 +14,7 @@ static const char *autofs4_get_link(struct dentry *dentry,
 {
        struct autofs_sb_info *sbi;
        struct autofs_info *ino;
+
        if (!dentry)
                return ERR_PTR(-ECHILD);
        sbi = autofs4_sbi(dentry->d_sb);
index 35b755e79c2d9b311d0eb899dd749580cb42b209..0146d911f468ca46d5fe7c946851c500b624ccb9 100644 (file)
@@ -1,15 +1,11 @@
-/* -*- c -*- --------------------------------------------------------------- *
- *
- * linux/fs/autofs/waitq.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *  Copyright 2001-2006 Ian Kent <raven@themaw.net>
+/*
+ * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
+ * Copyright 2001-2006 Ian Kent <raven@themaw.net>
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
+ */
 
 #include <linux/slab.h>
 #include <linux/time.h>
@@ -18,7 +14,8 @@
 #include "autofs_i.h"
 
 /* We make this a static variable rather than a part of the superblock; it
-   is better if we don't reassign numbers easily even across filesystems */
+ * is better if we don't reassign numbers easily even across filesystems
+ */
 static autofs_wqt_t autofs4_next_wait_queue = 1;
 
 /* These are the signals we allow interrupting a pending mount */
@@ -34,7 +31,7 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi)
                return;
        }
 
-       DPRINTK("entering catatonic mode");
+       pr_debug("entering catatonic mode\n");
 
        sbi->catatonic = 1;
        wq = sbi->queues;
@@ -69,17 +66,19 @@ static int autofs4_write(struct autofs_sb_info *sbi,
        set_fs(KERNEL_DS);
 
        mutex_lock(&sbi->pipe_mutex);
-       while (bytes &&
-              (wr = __vfs_write(file,data,bytes,&file->f_pos)) > 0) {
+       wr = __vfs_write(file, data, bytes, &file->f_pos);
+       while (bytes && wr) {
                data += wr;
                bytes -= wr;
+               wr = __vfs_write(file, data, bytes, &file->f_pos);
        }
        mutex_unlock(&sbi->pipe_mutex);
 
        set_fs(fs);
 
        /* Keep the currently executing process from receiving a
-          SIGPIPE unless it was already supposed to get one */
+        * SIGPIPE unless it was already supposed to get one
+        */
        if (wr == -EPIPE && !sigpipe) {
                spin_lock_irqsave(&current->sighand->siglock, flags);
                sigdelset(&current->pending.signal, SIGPIPE);
@@ -89,7 +88,7 @@ static int autofs4_write(struct autofs_sb_info *sbi,
 
        return (bytes > 0);
 }
-       
+
 static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                                 struct autofs_wait_queue *wq,
                                 int type)
@@ -102,10 +101,11 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
        struct file *pipe = NULL;
        size_t pktsz;
 
-       DPRINTK("wait id = 0x%08lx, name = %.*s, type=%d",
-               (unsigned long) wq->wait_queue_token, wq->name.len, wq->name.name, type);
+       pr_debug("wait id = 0x%08lx, name = %.*s, type=%d\n",
+                (unsigned long) wq->wait_queue_token,
+                wq->name.len, wq->name.name, type);
 
-       memset(&pkt,0,sizeof pkt); /* For security reasons */
+       memset(&pkt, 0, sizeof(pkt)); /* For security reasons */
 
        pkt.hdr.proto_version = sbi->version;
        pkt.hdr.type = type;
@@ -126,7 +126,8 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
        }
        case autofs_ptype_expire_multi:
        {
-               struct autofs_packet_expire_multi *ep = &pkt.v4_pkt.expire_multi;
+               struct autofs_packet_expire_multi *ep =
+                                       &pkt.v4_pkt.expire_multi;
 
                pktsz = sizeof(*ep);
 
@@ -163,7 +164,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
                break;
        }
        default:
-               printk("autofs4_notify_daemon: bad type %d!\n", type);
+               pr_warn("bad type %d!\n", type);
                mutex_unlock(&sbi->wq_mutex);
                return;
        }
@@ -231,7 +232,7 @@ autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr)
                if (wq->name.hash == qstr->hash &&
                    wq->name.len == qstr->len &&
                    wq->name.name &&
-                        !memcmp(wq->name.name, qstr->name, qstr->len))
+                   !memcmp(wq->name.name, qstr->name, qstr->len))
                        break;
        }
        return wq;
@@ -248,7 +249,7 @@ autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr)
 static int validate_request(struct autofs_wait_queue **wait,
                            struct autofs_sb_info *sbi,
                            struct qstr *qstr,
-                           struct dentry*dentry, enum autofs_notify notify)
+                           struct dentry *dentry, enum autofs_notify notify)
 {
        struct autofs_wait_queue *wq;
        struct autofs_info *ino;
@@ -322,8 +323,10 @@ static int validate_request(struct autofs_wait_queue **wait,
                 * continue on and create a new request.
                 */
                if (!IS_ROOT(dentry)) {
-                       if (d_really_is_positive(dentry) && d_unhashed(dentry)) {
+                       if (d_unhashed(dentry) &&
+                           d_really_is_positive(dentry)) {
                                struct dentry *parent = dentry->d_parent;
+
                                new = d_lookup(parent, &dentry->d_name);
                                if (new)
                                        dentry = new;
@@ -340,8 +343,8 @@ static int validate_request(struct autofs_wait_queue **wait,
        return 1;
 }
 
-int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
-               enum autofs_notify notify)
+int autofs4_wait(struct autofs_sb_info *sbi,
+                struct dentry *dentry, enum autofs_notify notify)
 {
        struct autofs_wait_queue *wq;
        struct qstr qstr;
@@ -411,7 +414,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
 
        if (!wq) {
                /* Create a new wait queue */
-               wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
+               wq = kmalloc(sizeof(struct autofs_wait_queue), GFP_KERNEL);
                if (!wq) {
                        kfree(qstr.name);
                        mutex_unlock(&sbi->wq_mutex);
@@ -450,17 +453,19 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                                        autofs_ptype_expire_indirect;
                }
 
-               DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
-                       (unsigned long) wq->wait_queue_token, wq->name.len,
-                       wq->name.name, notify);
+               pr_debug("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
+                        (unsigned long) wq->wait_queue_token, wq->name.len,
+                        wq->name.name, notify);
 
-               /* autofs4_notify_daemon() may block; it will unlock ->wq_mutex */
+               /*
+                * autofs4_notify_daemon() may block; it will unlock ->wq_mutex
+                */
                autofs4_notify_daemon(sbi, wq, type);
        } else {
                wq->wait_ctr++;
-               DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
-                       (unsigned long) wq->wait_queue_token, wq->name.len,
-                       wq->name.name, notify);
+               pr_debug("existing wait id = 0x%08lx, name = %.*s, nfy=%d\n",
+                        (unsigned long) wq->wait_queue_token, wq->name.len,
+                        wq->name.name, notify);
                mutex_unlock(&sbi->wq_mutex);
                kfree(qstr.name);
        }
@@ -471,12 +476,14 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
         */
        if (wq->name.name) {
                /* Block all but "shutdown" signals while waiting */
-               sigset_t oldset;
+               unsigned long shutdown_sigs_mask;
                unsigned long irqflags;
+               sigset_t oldset;
 
                spin_lock_irqsave(&current->sighand->siglock, irqflags);
                oldset = current->blocked;
-               siginitsetinv(&current->blocked, SHUTDOWN_SIGS & ~oldset.sig[0]);
+               shutdown_sigs_mask = SHUTDOWN_SIGS & ~oldset.sig[0];
+               siginitsetinv(&current->blocked, shutdown_sigs_mask);
                recalc_sigpending();
                spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
 
@@ -487,7 +494,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
                recalc_sigpending();
                spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
        } else {
-               DPRINTK("skipped sleeping");
+               pr_debug("skipped sleeping\n");
        }
 
        status = wq->status;
@@ -562,4 +569,3 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok
 
        return 0;
 }
-
index 051ea4809c14037fd0b1efffccb12c3909b3e46b..7d914c67a9d07f7ebb8a3f8f0bea8200d739ee9f 100644 (file)
@@ -653,7 +653,7 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
 
        if ((current->flags & PF_RANDOMIZE) &&
                !(current->personality & ADDR_NO_RANDOMIZE)) {
-               random_variable = (unsigned long) get_random_int();
+               random_variable = get_random_long();
                random_variable &= STACK_RND_MASK;
                random_variable <<= PAGE_SHIFT;
        }
index 39b3a174a4253974b4635bee951e2283cf71b9cf..826b164a4b5b1faa9719aefc9cceccec20eda479 100644 (file)
@@ -1201,7 +1201,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                bdev->bd_disk = disk;
                bdev->bd_queue = disk->queue;
                bdev->bd_contains = bdev;
-               bdev->bd_inode->i_flags = disk->fops->direct_access ? S_DAX : 0;
+               if (IS_ENABLED(CONFIG_BLK_DEV_DAX) && disk->fops->direct_access)
+                       bdev->bd_inode->i_flags = S_DAX;
+               else
+                       bdev->bd_inode->i_flags = 0;
+
                if (!partno) {
                        ret = -ENXIO;
                        bdev->bd_part = disk_get_part(disk, partno);
@@ -1693,13 +1697,24 @@ static int blkdev_releasepage(struct page *page, gfp_t wait)
        return try_to_free_buffers(page);
 }
 
+static int blkdev_writepages(struct address_space *mapping,
+                            struct writeback_control *wbc)
+{
+       if (dax_mapping(mapping)) {
+               struct block_device *bdev = I_BDEV(mapping->host);
+
+               return dax_writeback_mapping_range(mapping, bdev, wbc);
+       }
+       return generic_writepages(mapping, wbc);
+}
+
 static const struct address_space_operations def_blk_aops = {
        .readpage       = blkdev_readpage,
        .readpages      = blkdev_readpages,
        .writepage      = blkdev_writepage,
        .write_begin    = blkdev_write_begin,
        .write_end      = blkdev_write_end,
-       .writepages     = generic_writepages,
+       .writepages     = blkdev_writepages,
        .releasepage    = blkdev_releasepage,
        .direct_IO      = blkdev_direct_IO,
        .is_dirty_writeback = buffer_check_dirty_writeback,
index 4545e2e2ad45a556113eecf30b1a7d49ee7ca260..5699bbc23febaa25614c52f2b2546abe145fd69d 100644 (file)
@@ -931,7 +931,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags)
        if (bio_flags & EXTENT_BIO_TREE_LOG)
                return 0;
 #ifdef CONFIG_X86
-       if (static_cpu_has_safe(X86_FEATURE_XMM4_2))
+       if (static_cpu_has(X86_FEATURE_XMM4_2))
                return 0;
 #endif
        return 1;
index 7cf8509deda7c0ea6e98af02a8ab0acafbe016b2..2c849b08a91b53e0a7f1c475301a77d623cb5293 100644 (file)
@@ -310,8 +310,16 @@ int btrfs_find_orphan_roots(struct btrfs_root *tree_root)
                set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &root->state);
 
                err = btrfs_insert_fs_root(root->fs_info, root);
+               /*
+                * The root might have been inserted already, as before we look
+                * for orphan roots, log replay might have happened, which
+                * triggers a transaction commit and qgroup accounting, which
+                * in turn reads and inserts fs roots while doing backref
+                * walking.
+                */
+               if (err == -EEXIST)
+                       err = 0;
                if (err) {
-                       BUG_ON(err == -EEXIST);
                        btrfs_free_fs_root(root);
                        break;
                }
index e1632abb4ca9fa6a00444f09b30eb9a90ede43fc..33be29675358321117038674a770e814a690e9fb 100644 (file)
@@ -621,17 +621,17 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode);
  * If warn is true, then emit a warning if the page is not uptodate and has
  * not been truncated.
  *
- * The caller must hold mem_cgroup_begin_page_stat() lock.
+ * The caller must hold lock_page_memcg().
  */
 static void __set_page_dirty(struct page *page, struct address_space *mapping,
-                            struct mem_cgroup *memcg, int warn)
+                            int warn)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&mapping->tree_lock, flags);
        if (page->mapping) {    /* Race with truncate? */
                WARN_ON_ONCE(warn && !PageUptodate(page));
-               account_page_dirtied(page, mapping, memcg);
+               account_page_dirtied(page, mapping);
                radix_tree_tag_set(&mapping->page_tree,
                                page_index(page), PAGECACHE_TAG_DIRTY);
        }
@@ -666,7 +666,6 @@ static void __set_page_dirty(struct page *page, struct address_space *mapping,
 int __set_page_dirty_buffers(struct page *page)
 {
        int newly_dirty;
-       struct mem_cgroup *memcg;
        struct address_space *mapping = page_mapping(page);
 
        if (unlikely(!mapping))
@@ -683,17 +682,17 @@ int __set_page_dirty_buffers(struct page *page)
                } while (bh != head);
        }
        /*
-        * Use mem_group_begin_page_stat() to keep PageDirty synchronized with
-        * per-memcg dirty page counters.
+        * Lock out page->mem_cgroup migration to keep PageDirty
+        * synchronized with per-memcg dirty page counters.
         */
-       memcg = mem_cgroup_begin_page_stat(page);
+       lock_page_memcg(page);
        newly_dirty = !TestSetPageDirty(page);
        spin_unlock(&mapping->private_lock);
 
        if (newly_dirty)
-               __set_page_dirty(page, mapping, memcg, 1);
+               __set_page_dirty(page, mapping, 1);
 
-       mem_cgroup_end_page_stat(memcg);
+       unlock_page_memcg(page);
 
        if (newly_dirty)
                __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
@@ -1167,15 +1166,14 @@ void mark_buffer_dirty(struct buffer_head *bh)
        if (!test_set_buffer_dirty(bh)) {
                struct page *page = bh->b_page;
                struct address_space *mapping = NULL;
-               struct mem_cgroup *memcg;
 
-               memcg = mem_cgroup_begin_page_stat(page);
+               lock_page_memcg(page);
                if (!TestSetPageDirty(page)) {
                        mapping = page_mapping(page);
                        if (mapping)
-                               __set_page_dirty(page, mapping, memcg, 0);
+                               __set_page_dirty(page, mapping, 0);
                }
-               mem_cgroup_end_page_stat(memcg);
+               unlock_page_memcg(page);
                if (mapping)
                        __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
        }
index c22213789090f975b3680b10e022a1e5f2f9fdb4..19adeb0ef82a397f122682db3a9ba31f56df5f5d 100644 (file)
@@ -1756,6 +1756,10 @@ int ceph_pool_perm_check(struct ceph_inode_info *ci, int need)
        u32 pool;
        int ret, flags;
 
+       /* does not support pool namespace yet */
+       if (ci->i_pool_ns_len)
+               return -EIO;
+
        if (ceph_test_mount_opt(ceph_inode_to_client(&ci->vfs_inode),
                                NOPOOLPERM))
                return 0;
index cdbf8cf3d52c3354569b7c86a709f4ce3fc09e2c..6fe0ad26a7dfc0430da9e9e0fca8c312a4b2bdc0 100644 (file)
@@ -2753,7 +2753,8 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
                             void *inline_data, int inline_len,
                             struct ceph_buffer *xattr_buf,
                             struct ceph_mds_session *session,
-                            struct ceph_cap *cap, int issued)
+                            struct ceph_cap *cap, int issued,
+                            u32 pool_ns_len)
        __releases(ci->i_ceph_lock)
        __releases(mdsc->snap_rwsem)
 {
@@ -2873,6 +2874,8 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
        if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) {
                /* file layout may have changed */
                ci->i_layout = grant->layout;
+               ci->i_pool_ns_len = pool_ns_len;
+
                /* size/truncate_seq? */
                queue_trunc = ceph_fill_file_size(inode, issued,
                                        le32_to_cpu(grant->truncate_seq),
@@ -3411,6 +3414,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
        u32  inline_len = 0;
        void *snaptrace;
        size_t snaptrace_len;
+       u32 pool_ns_len = 0;
        void *p, *end;
 
        dout("handle_caps from mds%d\n", mds);
@@ -3463,6 +3467,21 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                p += inline_len;
        }
 
+       if (le16_to_cpu(msg->hdr.version) >= 8) {
+               u64 flush_tid;
+               u32 caller_uid, caller_gid;
+               u32 osd_epoch_barrier;
+               /* version >= 5 */
+               ceph_decode_32_safe(&p, end, osd_epoch_barrier, bad);
+               /* version >= 6 */
+               ceph_decode_64_safe(&p, end, flush_tid, bad);
+               /* version >= 7 */
+               ceph_decode_32_safe(&p, end, caller_uid, bad);
+               ceph_decode_32_safe(&p, end, caller_gid, bad);
+               /* version >= 8 */
+               ceph_decode_32_safe(&p, end, pool_ns_len, bad);
+       }
+
        /* lookup ino */
        inode = ceph_find_inode(sb, vino);
        ci = ceph_inode(inode);
@@ -3518,7 +3537,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                                  &cap, &issued);
                handle_cap_grant(mdsc, inode, h,
                                 inline_version, inline_data, inline_len,
-                                msg->middle, session, cap, issued);
+                                msg->middle, session, cap, issued,
+                                pool_ns_len);
                if (realm)
                        ceph_put_snap_realm(mdsc, realm);
                goto done_unlocked;
@@ -3542,7 +3562,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                issued |= __ceph_caps_dirty(ci);
                handle_cap_grant(mdsc, inode, h,
                                 inline_version, inline_data, inline_len,
-                                msg->middle, session, cap, issued);
+                                msg->middle, session, cap, issued,
+                                pool_ns_len);
                goto done_unlocked;
 
        case CEPH_CAP_OP_FLUSH_ACK:
index fb4ba2e4e2a5fa5c5d62afa3b94f758c7906687b..5849b88bbed3cfc333318574db80ded6305e0d9c 100644 (file)
@@ -396,6 +396,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
        ci->i_symlink = NULL;
 
        memset(&ci->i_dir_layout, 0, sizeof(ci->i_dir_layout));
+       ci->i_pool_ns_len = 0;
 
        ci->i_fragtree = RB_ROOT;
        mutex_init(&ci->i_fragtree_mutex);
@@ -756,6 +757,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
                if (ci->i_layout.fl_pg_pool != info->layout.fl_pg_pool)
                        ci->i_ceph_flags &= ~CEPH_I_POOL_PERM;
                ci->i_layout = info->layout;
+               ci->i_pool_ns_len = iinfo->pool_ns_len;
 
                queue_trunc = ceph_fill_file_size(inode, issued,
                                        le32_to_cpu(info->truncate_seq),
index e7b130a637f9f31a34efd67d6cf5789a8fcdef00..911d64d865f176aa4ce28832207abb8651a4fec8 100644 (file)
@@ -100,6 +100,14 @@ static int parse_reply_info_in(void **p, void *end,
        } else
                info->inline_version = CEPH_INLINE_NONE;
 
+       if (features & CEPH_FEATURE_FS_FILE_LAYOUT_V2) {
+               ceph_decode_32_safe(p, end, info->pool_ns_len, bad);
+               ceph_decode_need(p, end, info->pool_ns_len, bad);
+               *p += info->pool_ns_len;
+       } else {
+               info->pool_ns_len = 0;
+       }
+
        return 0;
 bad:
        return err;
@@ -2298,6 +2306,14 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
                ceph_get_cap_refs(ceph_inode(req->r_old_dentry_dir),
                                  CEPH_CAP_PIN);
 
+       /* deny access to directories with pool_ns layouts */
+       if (req->r_inode && S_ISDIR(req->r_inode->i_mode) &&
+           ceph_inode(req->r_inode)->i_pool_ns_len)
+               return -EIO;
+       if (req->r_locked_dir &&
+           ceph_inode(req->r_locked_dir)->i_pool_ns_len)
+               return -EIO;
+
        /* issue */
        mutex_lock(&mdsc->mutex);
        __register_request(mdsc, req, dir);
index ccf11ef0ca8717f79e6bfc9d6cf806ec359b5e8c..37712ccffcc6b67c2f98a866c9c2be40324bc6ae 100644 (file)
@@ -44,6 +44,7 @@ struct ceph_mds_reply_info_in {
        u64 inline_version;
        u32 inline_len;
        char *inline_data;
+       u32 pool_ns_len;
 };
 
 /*
index 75b7d125ce668a9b3f4f851d2be1c688d6d5f964..9c458eb522458da2364238cef2e92530ace87df9 100644 (file)
@@ -287,6 +287,7 @@ struct ceph_inode_info {
 
        struct ceph_dir_layout i_dir_layout;
        struct ceph_file_layout i_layout;
+       size_t i_pool_ns_len;
        char *i_symlink;
 
        /* for dirs */
index c48ca13673e37f2eba7c4045f140e6e8b740e499..2eea40353e6086fc808da8c74deeaaf158a43da9 100644 (file)
@@ -1013,7 +1013,6 @@ const struct file_operations cifs_file_strict_ops = {
        .llseek = cifs_llseek,
        .unlocked_ioctl = cifs_ioctl,
        .clone_file_range = cifs_clone_file_range,
-       .clone_file_range = cifs_clone_file_range,
        .setlease = cifs_setlease,
        .fallocate = cifs_fallocate,
 };
index 68c4547528c486f2477a8177692374dd6033e2bf..83aac8ba50b0e168ec5b2a252c8b77daf9c2428b 100644 (file)
  * so that it will fit. We use hash_64 to convert the value to 31 bits, and
  * then add 1, to ensure that we don't end up with a 0 as the value.
  */
-#if BITS_PER_LONG == 64
 static inline ino_t
 cifs_uniqueid_to_ino_t(u64 fileid)
 {
+       if ((sizeof(ino_t)) < (sizeof(u64)))
+               return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
+
        return (ino_t)fileid;
+
 }
-#else
-static inline ino_t
-cifs_uniqueid_to_ino_t(u64 fileid)
-{
-       return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
-}
-#endif
 
 extern struct file_system_type cifs_fs_type;
 extern const struct address_space_operations cifs_addr_ops;
index 90b4f9f7de660a261b5f93322af59282294953fd..76fcb50295a38b63a58a0d3f656d023e02b988a8 100644 (file)
@@ -1396,11 +1396,10 @@ openRetry:
  * current bigbuf.
  */
 static int
-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+discard_remaining_data(struct TCP_Server_Info *server)
 {
        unsigned int rfclen = get_rfc1002_length(server->smallbuf);
        int remaining = rfclen + 4 - server->total_read;
-       struct cifs_readdata *rdata = mid->callback_data;
 
        while (remaining > 0) {
                int length;
@@ -1414,10 +1413,20 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                remaining -= length;
        }
 
-       dequeue_mid(mid, rdata->result);
        return 0;
 }
 
+static int
+cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+       int length;
+       struct cifs_readdata *rdata = mid->callback_data;
+
+       length = discard_remaining_data(server);
+       dequeue_mid(mid, rdata->result);
+       return length;
+}
+
 int
 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
@@ -1446,6 +1455,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                return length;
        server->total_read += length;
 
+       if (server->ops->is_status_pending &&
+           server->ops->is_status_pending(buf, server, 0)) {
+               discard_remaining_data(server);
+               return -1;
+       }
+
        /* Was the SMB read successful? */
        rdata->result = server->ops->map_error(buf, false);
        if (rdata->result != 0) {
index 10f8d5cf5681e26b843c0ac15821eab69e6eeb22..42e1f440eb1e9ae1ca497c7f8127ff58b7988b77 100644 (file)
@@ -1106,21 +1106,25 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
 {
        char *data_offset;
        struct create_context *cc;
-       unsigned int next = 0;
+       unsigned int next;
+       unsigned int remaining;
        char *name;
 
        data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
+       remaining = le32_to_cpu(rsp->CreateContextsLength);
        cc = (struct create_context *)data_offset;
-       do {
-               cc = (struct create_context *)((char *)cc + next);
+       while (remaining >= sizeof(struct create_context)) {
                name = le16_to_cpu(cc->NameOffset) + (char *)cc;
-               if (le16_to_cpu(cc->NameLength) != 4 ||
-                   strncmp(name, "RqLs", 4)) {
-                       next = le32_to_cpu(cc->Next);
-                       continue;
-               }
-               return server->ops->parse_lease_buf(cc, epoch);
-       } while (next != 0);
+               if (le16_to_cpu(cc->NameLength) == 4 &&
+                   strncmp(name, "RqLs", 4) == 0)
+                       return server->ops->parse_lease_buf(cc, epoch);
+
+               next = le32_to_cpu(cc->Next);
+               if (!next)
+                       break;
+               remaining -= next;
+               cc = (struct create_context *)((char *)cc + next);
+       }
 
        return 0;
 }
index fc2e3141138b285321abdbe059e53dfd40162719..bbb2ad78377020ac85158fb61df067aceadaafe5 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -79,15 +79,14 @@ struct page *read_dax_sector(struct block_device *bdev, sector_t n)
 }
 
 /*
- * dax_clear_blocks() is called from within transaction context from XFS,
+ * dax_clear_sectors() is called from within transaction context from XFS,
  * and hence this means the stack from this point must follow GFP_NOFS
  * semantics for all operations.
  */
-int dax_clear_blocks(struct inode *inode, sector_t block, long _size)
+int dax_clear_sectors(struct block_device *bdev, sector_t _sector, long _size)
 {
-       struct block_device *bdev = inode->i_sb->s_bdev;
        struct blk_dax_ctl dax = {
-               .sector = block << (inode->i_blkbits - 9),
+               .sector = _sector,
                .size = _size,
        };
 
@@ -109,7 +108,7 @@ int dax_clear_blocks(struct inode *inode, sector_t block, long _size)
        wmb_pmem();
        return 0;
 }
-EXPORT_SYMBOL_GPL(dax_clear_blocks);
+EXPORT_SYMBOL_GPL(dax_clear_sectors);
 
 /* the clear_pmem() calls are ordered by a wmb_pmem() in the caller */
 static void dax_new_buf(void __pmem *addr, unsigned size, unsigned first,
@@ -485,11 +484,10 @@ static int dax_writeback_one(struct block_device *bdev,
  * end]. This is required by data integrity operations to ensure file data is
  * on persistent storage prior to completion of the operation.
  */
-int dax_writeback_mapping_range(struct address_space *mapping, loff_t start,
-               loff_t end)
+int dax_writeback_mapping_range(struct address_space *mapping,
+               struct block_device *bdev, struct writeback_control *wbc)
 {
        struct inode *inode = mapping->host;
-       struct block_device *bdev = inode->i_sb->s_bdev;
        pgoff_t start_index, end_index, pmd_index;
        pgoff_t indices[PAGEVEC_SIZE];
        struct pagevec pvec;
@@ -500,8 +498,11 @@ int dax_writeback_mapping_range(struct address_space *mapping, loff_t start,
        if (WARN_ON_ONCE(inode->i_blkbits != PAGE_SHIFT))
                return -EIO;
 
-       start_index = start >> PAGE_CACHE_SHIFT;
-       end_index = end >> PAGE_CACHE_SHIFT;
+       if (!mapping->nrexceptional || wbc->sync_mode != WB_SYNC_ALL)
+               return 0;
+
+       start_index = wbc->range_start >> PAGE_CACHE_SHIFT;
+       end_index = wbc->range_end >> PAGE_CACHE_SHIFT;
        pmd_index = DAX_PMD_INDEX(start_index);
 
        rcu_read_lock();
@@ -1055,6 +1056,7 @@ EXPORT_SYMBOL_GPL(dax_pmd_fault);
 int dax_pfn_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct file *file = vma->vm_file;
+       int error;
 
        /*
         * We pass NO_SECTOR to dax_radix_entry() because we expect that a
@@ -1064,7 +1066,13 @@ int dax_pfn_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
         * saves us from having to make a call to get_block() here to look
         * up the sector.
         */
-       dax_radix_entry(file->f_mapping, vmf->pgoff, NO_SECTOR, false, true);
+       error = dax_radix_entry(file->f_mapping, vmf->pgoff, NO_SECTOR, false,
+                       true);
+
+       if (error == -ENOMEM)
+               return VM_FAULT_OOM;
+       if (error)
+               return VM_FAULT_SIGBUS;
        return VM_FAULT_NOPAGE;
 }
 EXPORT_SYMBOL_GPL(dax_pfn_mkwrite);
index 92d5140de8516c642b6ea5af81f0ffe89399a416..2398f9f9433752aa53dbd3af4cfe0f82aba22d99 100644 (file)
@@ -269,9 +269,6 @@ static inline int dname_external(const struct dentry *dentry)
        return dentry->d_name.name != dentry->d_iname;
 }
 
-/*
- * Make sure other CPUs see the inode attached before the type is set.
- */
 static inline void __d_set_inode_and_type(struct dentry *dentry,
                                          struct inode *inode,
                                          unsigned type_flags)
@@ -279,28 +276,18 @@ static inline void __d_set_inode_and_type(struct dentry *dentry,
        unsigned flags;
 
        dentry->d_inode = inode;
-       smp_wmb();
        flags = READ_ONCE(dentry->d_flags);
        flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
        flags |= type_flags;
        WRITE_ONCE(dentry->d_flags, flags);
 }
 
-/*
- * Ideally, we want to make sure that other CPUs see the flags cleared before
- * the inode is detached, but this is really a violation of RCU principles
- * since the ordering suggests we should always set inode before flags.
- *
- * We should instead replace or discard the entire dentry - but that sucks
- * performancewise on mass deletion/rename.
- */
 static inline void __d_clear_type_and_inode(struct dentry *dentry)
 {
        unsigned flags = READ_ONCE(dentry->d_flags);
 
        flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
        WRITE_ONCE(dentry->d_flags, flags);
-       smp_wmb();
        dentry->d_inode = NULL;
 }
 
@@ -370,9 +357,11 @@ static void dentry_unlink_inode(struct dentry * dentry)
        __releases(dentry->d_inode->i_lock)
 {
        struct inode *inode = dentry->d_inode;
+
+       raw_write_seqcount_begin(&dentry->d_seq);
        __d_clear_type_and_inode(dentry);
        hlist_del_init(&dentry->d_u.d_alias);
-       dentry_rcuwalk_invalidate(dentry);
+       raw_write_seqcount_end(&dentry->d_seq);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&inode->i_lock);
        if (!inode->i_nlink)
@@ -1758,8 +1747,9 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        spin_lock(&dentry->d_lock);
        if (inode)
                hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
+       raw_write_seqcount_begin(&dentry->d_seq);
        __d_set_inode_and_type(dentry, inode, add_flags);
-       dentry_rcuwalk_invalidate(dentry);
+       raw_write_seqcount_end(&dentry->d_seq);
        spin_unlock(&dentry->d_lock);
        fsnotify_d_instantiate(dentry, inode);
 }
index 2c88d683cd918d673c83390aea187e763b5aa78e..c1400b109805b8778d8ee947ecad3060539f5ebe 100644 (file)
@@ -80,23 +80,6 @@ static int ext2_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
        return ret;
 }
 
-static int ext2_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       struct inode *inode = file_inode(vma->vm_file);
-       struct ext2_inode_info *ei = EXT2_I(inode);
-       int ret;
-
-       sb_start_pagefault(inode->i_sb);
-       file_update_time(vma->vm_file);
-       down_read(&ei->dax_sem);
-
-       ret = __dax_mkwrite(vma, vmf, ext2_get_block, NULL);
-
-       up_read(&ei->dax_sem);
-       sb_end_pagefault(inode->i_sb);
-       return ret;
-}
-
 static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma,
                struct vm_fault *vmf)
 {
@@ -124,7 +107,7 @@ static int ext2_dax_pfn_mkwrite(struct vm_area_struct *vma,
 static const struct vm_operations_struct ext2_dax_vm_ops = {
        .fault          = ext2_dax_fault,
        .pmd_fault      = ext2_dax_pmd_fault,
-       .page_mkwrite   = ext2_dax_mkwrite,
+       .page_mkwrite   = ext2_dax_fault,
        .pfn_mkwrite    = ext2_dax_pfn_mkwrite,
 };
 
index 338eefda70c6fc4e2055c0165b590febf1295acb..6bd58e6ff038657f75b93857bad455ebdfedfa0f 100644 (file)
@@ -737,8 +737,10 @@ static int ext2_get_blocks(struct inode *inode,
                 * so that it's not found by another thread before it's
                 * initialised
                 */
-               err = dax_clear_blocks(inode, le32_to_cpu(chain[depth-1].key),
-                                               1 << inode->i_blkbits);
+               err = dax_clear_sectors(inode->i_sb->s_bdev,
+                               le32_to_cpu(chain[depth-1].key) <<
+                               (inode->i_blkbits - 9),
+                               1 << inode->i_blkbits);
                if (err) {
                        mutex_unlock(&ei->truncate_mutex);
                        goto cleanup;
@@ -874,6 +876,14 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t offset)
 static int
 ext2_writepages(struct address_space *mapping, struct writeback_control *wbc)
 {
+#ifdef CONFIG_FS_DAX
+       if (dax_mapping(mapping)) {
+               return dax_writeback_mapping_range(mapping,
+                                                  mapping->host->i_sb->s_bdev,
+                                                  wbc);
+       }
+#endif
+
        return mpage_writepages(mapping, wbc, ext2_get_block);
 }
 
@@ -1296,7 +1306,7 @@ void ext2_set_inode_flags(struct inode *inode)
                inode->i_flags |= S_NOATIME;
        if (flags & EXT2_DIRSYNC_FL)
                inode->i_flags |= S_DIRSYNC;
-       if (test_opt(inode->i_sb, DAX))
+       if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode))
                inode->i_flags |= S_DAX;
 }
 
index 474f1a4d2ca8f45be1c0c97ce8c13a90cf75d34d..4cd318f31cbeff21979d552cab7390c6df76a5c9 100644 (file)
@@ -262,23 +262,8 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
        return result;
 }
 
-static int ext4_dax_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-       int err;
-       struct inode *inode = file_inode(vma->vm_file);
-
-       sb_start_pagefault(inode->i_sb);
-       file_update_time(vma->vm_file);
-       down_read(&EXT4_I(inode)->i_mmap_sem);
-       err = __dax_mkwrite(vma, vmf, ext4_dax_mmap_get_block, NULL);
-       up_read(&EXT4_I(inode)->i_mmap_sem);
-       sb_end_pagefault(inode->i_sb);
-
-       return err;
-}
-
 /*
- * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_mkwrite()
+ * Handle write fault for VM_MIXEDMAP mappings. Similarly to ext4_dax_fault()
  * handler we check for races agaist truncate. Note that since we cycle through
  * i_mmap_sem, we are sure that also any hole punching that began before we
  * were called is finished by now and so if it included part of the file we
@@ -311,7 +296,7 @@ static int ext4_dax_pfn_mkwrite(struct vm_area_struct *vma,
 static const struct vm_operations_struct ext4_dax_vm_ops = {
        .fault          = ext4_dax_fault,
        .pmd_fault      = ext4_dax_pmd_fault,
-       .page_mkwrite   = ext4_dax_mkwrite,
+       .page_mkwrite   = ext4_dax_fault,
        .pfn_mkwrite    = ext4_dax_pfn_mkwrite,
 };
 #else
index 9cc57c3b466123f597dc28c6daed902faa7db081..aee960b1af347e3407dd05f5a7095a7af4d8a96e 100644 (file)
@@ -2478,6 +2478,10 @@ static int ext4_writepages(struct address_space *mapping,
 
        trace_ext4_writepages(inode, wbc);
 
+       if (dax_mapping(mapping))
+               return dax_writeback_mapping_range(mapping, inode->i_sb->s_bdev,
+                                                  wbc);
+
        /*
         * No pages to write? This is mainly a kludge to avoid starting
         * a transaction for special inodes like journal inode on last iput()
@@ -4155,7 +4159,7 @@ void ext4_set_inode_flags(struct inode *inode)
                new_fl |= S_NOATIME;
        if (flags & EXT4_DIRSYNC_FL)
                new_fl |= S_DIRSYNC;
-       if (test_opt(inode->i_sb, DAX))
+       if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode))
                new_fl |= S_DAX;
        inode_set_flags(inode, new_fl,
                        S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX);
index a99b010e2194e32adafcef2f8b721d208f64d0c6..eae5917c534e51b2fddf7bcebfa1293ed76a2841 100644 (file)
@@ -583,6 +583,11 @@ group_extend_out:
                                 "Online defrag not supported with bigalloc");
                        err = -EOPNOTSUPP;
                        goto mext_out;
+               } else if (IS_DAX(inode)) {
+                       ext4_msg(sb, KERN_ERR,
+                                "Online defrag not supported with DAX");
+                       err = -EOPNOTSUPP;
+                       goto mext_out;
                }
 
                err = mnt_want_write_file(filp);
index e032a0423e351cabfd6fe6156cdfc9c53ebff216..4098acc701c3e66d5e8a229ed49828d69997655f 100644 (file)
@@ -390,6 +390,7 @@ data_copy:
                *err = ext4_get_block(orig_inode, orig_blk_offset + i, bh, 0);
                if (*err < 0)
                        break;
+               bh = bh->b_this_page;
        }
        if (!*err)
                *err = block_commit_write(pagep[0], from, from + replaced_size);
index 1f76d8950a57fc7bbdb3f8d98ec056fe89970b5c..5c46ed9f3e14087d4fa7bad553eb360b30fb4fd8 100644 (file)
@@ -223,6 +223,9 @@ static void wb_wait_for_completion(struct backing_dev_info *bdi,
 #define WB_FRN_HIST_MAX_SLOTS  (WB_FRN_HIST_THR_SLOTS / 2 + 1)
                                        /* one round can affect upto 5 slots */
 
+static atomic_t isw_nr_in_flight = ATOMIC_INIT(0);
+static struct workqueue_struct *isw_wq;
+
 void __inode_attach_wb(struct inode *inode, struct page *page)
 {
        struct backing_dev_info *bdi = inode_to_bdi(inode);
@@ -317,7 +320,6 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
        struct inode_switch_wbs_context *isw =
                container_of(work, struct inode_switch_wbs_context, work);
        struct inode *inode = isw->inode;
-       struct super_block *sb = inode->i_sb;
        struct address_space *mapping = inode->i_mapping;
        struct bdi_writeback *old_wb = inode->i_wb;
        struct bdi_writeback *new_wb = isw->new_wb;
@@ -424,8 +426,9 @@ skip_switch:
        wb_put(new_wb);
 
        iput(inode);
-       deactivate_super(sb);
        kfree(isw);
+
+       atomic_dec(&isw_nr_in_flight);
 }
 
 static void inode_switch_wbs_rcu_fn(struct rcu_head *rcu_head)
@@ -435,7 +438,7 @@ static void inode_switch_wbs_rcu_fn(struct rcu_head *rcu_head)
 
        /* needs to grab bh-unsafe locks, bounce to work item */
        INIT_WORK(&isw->work, inode_switch_wbs_work_fn);
-       schedule_work(&isw->work);
+       queue_work(isw_wq, &isw->work);
 }
 
 /**
@@ -471,20 +474,20 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
 
        /* while holding I_WB_SWITCH, no one else can update the association */
        spin_lock(&inode->i_lock);
-
-       if (inode->i_state & (I_WB_SWITCH | I_FREEING) ||
-           inode_to_wb(inode) == isw->new_wb)
-               goto out_unlock;
-
-       if (!atomic_inc_not_zero(&inode->i_sb->s_active))
-               goto out_unlock;
-
+       if (!(inode->i_sb->s_flags & MS_ACTIVE) ||
+           inode->i_state & (I_WB_SWITCH | I_FREEING) ||
+           inode_to_wb(inode) == isw->new_wb) {
+               spin_unlock(&inode->i_lock);
+               goto out_free;
+       }
        inode->i_state |= I_WB_SWITCH;
        spin_unlock(&inode->i_lock);
 
        ihold(inode);
        isw->inode = inode;
 
+       atomic_inc(&isw_nr_in_flight);
+
        /*
         * In addition to synchronizing among switchers, I_WB_SWITCH tells
         * the RCU protected stat update paths to grab the mapping's
@@ -494,8 +497,6 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
        call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
        return;
 
-out_unlock:
-       spin_unlock(&inode->i_lock);
 out_free:
        if (isw->new_wb)
                wb_put(isw->new_wb);
@@ -847,6 +848,33 @@ restart:
                wb_put(last_wb);
 }
 
+/**
+ * cgroup_writeback_umount - flush inode wb switches for umount
+ *
+ * This function is called when a super_block is about to be destroyed and
+ * flushes in-flight inode wb switches.  An inode wb switch goes through
+ * RCU and then workqueue, so the two need to be flushed in order to ensure
+ * that all previously scheduled switches are finished.  As wb switches are
+ * rare occurrences and synchronize_rcu() can take a while, perform
+ * flushing iff wb switches are in flight.
+ */
+void cgroup_writeback_umount(void)
+{
+       if (atomic_read(&isw_nr_in_flight)) {
+               synchronize_rcu();
+               flush_workqueue(isw_wq);
+       }
+}
+
+static int __init cgroup_writeback_init(void)
+{
+       isw_wq = alloc_workqueue("inode_switch_wbs", 0, 0);
+       if (!isw_wq)
+               return -ENOMEM;
+       return 0;
+}
+fs_initcall(cgroup_writeback_init);
+
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
 static struct bdi_writeback *
index 506765afa1a3135d1ff9bccc48f06634439fa69e..bb8d67e2740ac70d7c9c87c078429475f9e0b79d 100644 (file)
@@ -376,12 +376,11 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
        struct inode *inode = d_inode(dentry);
        dnode_secno dno;
        int r;
-       int rep = 0;
        int err;
 
        hpfs_lock(dir->i_sb);
        hpfs_adjust_length(name, &len);
-again:
+
        err = -ENOENT;
        de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
        if (!de)
@@ -401,33 +400,9 @@ again:
                hpfs_error(dir->i_sb, "there was error when removing dirent");
                err = -EFSERROR;
                break;
-       case 2:         /* no space for deleting, try to truncate file */
-
+       case 2:         /* no space for deleting */
                err = -ENOSPC;
-               if (rep++)
-                       break;
-
-               dentry_unhash(dentry);
-               if (!d_unhashed(dentry)) {
-                       hpfs_unlock(dir->i_sb);
-                       return -ENOSPC;
-               }
-               if (generic_permission(inode, MAY_WRITE) ||
-                   !S_ISREG(inode->i_mode) ||
-                   get_write_access(inode)) {
-                       d_rehash(dentry);
-               } else {
-                       struct iattr newattrs;
-                       /*pr_info("truncating file before delete.\n");*/
-                       newattrs.ia_size = 0;
-                       newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-                       err = notify_change(dentry, &newattrs, NULL);
-                       put_write_access(inode);
-                       if (!err)
-                               goto again;
-               }
-               hpfs_unlock(dir->i_sb);
-               return -ENOSPC;
+               break;
        default:
                drop_nlink(inode);
                err = 0;
index 3ea36554107fc7740558ac81daa0328c308b2903..8918ac905a3b1face373e3a0ad456c2d3bf6d95b 100644 (file)
@@ -2,10 +2,6 @@
        JFFS2 LOCKING DOCUMENTATION
        ---------------------------
 
-At least theoretically, JFFS2 does not require the Big Kernel Lock
-(BKL), which was always helpfully obtained for it by Linux 2.4 VFS
-code. It has its own locking, as described below.
-
 This document attempts to describe the existing locking rules for
 JFFS2. It is not expected to remain perfectly up to date, but ought to
 be fairly close.
@@ -69,6 +65,7 @@ Ordering constraints:
           any f->sem held.
        2. Never attempt to lock two file mutexes in one thread.
           No ordering rules have been made for doing so.
+       3. Never lock a page cache page with f->sem held.
 
 
        erase_completion_lock spinlock
index 0ae91ad6df2dc916f077495876ec7fe1e47902ed..b288c8ae1236b0f81f271e0fcfcaf5ee246b2933 100644 (file)
@@ -50,7 +50,8 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c)
 
 
 static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
-                                   struct jffs2_inode_cache *ic)
+                                   struct jffs2_inode_cache *ic,
+                                   int *dir_hardlinks)
 {
        struct jffs2_full_dirent *fd;
 
@@ -69,19 +70,21 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
                        dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n",
                                  fd->name, fd->ino, ic->ino);
                        jffs2_mark_node_obsolete(c, fd->raw);
+                       /* Clear the ic/raw union so it doesn't cause problems later. */
+                       fd->ic = NULL;
                        continue;
                }
 
+               /* From this point, fd->raw is no longer used so we can set fd->ic */
+               fd->ic = child_ic;
+               child_ic->pino_nlink++;
+               /* If we appear (at this stage) to have hard-linked directories,
+                * set a flag to trigger a scan later */
                if (fd->type == DT_DIR) {
-                       if (child_ic->pino_nlink) {
-                               JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n",
-                                           fd->name, fd->ino, ic->ino);
-                               /* TODO: What do we do about it? */
-                       } else {
-                               child_ic->pino_nlink = ic->ino;
-                       }
-               } else
-                       child_ic->pino_nlink++;
+                       child_ic->flags |= INO_FLAGS_IS_DIR;
+                       if (child_ic->pino_nlink > 1)
+                               *dir_hardlinks = 1;
+               }
 
                dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino);
                /* Can't free scan_dents so far. We might need them in pass 2 */
@@ -95,8 +98,7 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
 */
 static int jffs2_build_filesystem(struct jffs2_sb_info *c)
 {
-       int ret;
-       int i;
+       int ret, i, dir_hardlinks = 0;
        struct jffs2_inode_cache *ic;
        struct jffs2_full_dirent *fd;
        struct jffs2_full_dirent *dead_fds = NULL;
@@ -120,7 +122,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
        /* Now scan the directory tree, increasing nlink according to every dirent found. */
        for_each_inode(i, c, ic) {
                if (ic->scan_dents) {
-                       jffs2_build_inode_pass1(c, ic);
+                       jffs2_build_inode_pass1(c, ic, &dir_hardlinks);
                        cond_resched();
                }
        }
@@ -156,6 +158,20 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
        }
 
        dbg_fsbuild("pass 2a complete\n");
+
+       if (dir_hardlinks) {
+               /* If we detected directory hardlinks earlier, *hopefully*
+                * they are gone now because some of the links were from
+                * dead directories which still had some old dirents lying
+                * around and not yet garbage-collected, but which have
+                * been discarded above. So clear the pino_nlink field
+                * in each directory, so that the final scan below can
+                * print appropriate warnings. */
+               for_each_inode(i, c, ic) {
+                       if (ic->flags & INO_FLAGS_IS_DIR)
+                               ic->pino_nlink = 0;
+               }
+       }
        dbg_fsbuild("freeing temporary data structures\n");
 
        /* Finally, we can scan again and free the dirent structs */
@@ -163,6 +179,33 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
                while(ic->scan_dents) {
                        fd = ic->scan_dents;
                        ic->scan_dents = fd->next;
+                       /* We do use the pino_nlink field to count nlink of
+                        * directories during fs build, so set it to the
+                        * parent ino# now. Now that there's hopefully only
+                        * one. */
+                       if (fd->type == DT_DIR) {
+                               if (!fd->ic) {
+                                       /* We'll have complained about it and marked the coresponding
+                                          raw node obsolete already. Just skip it. */
+                                       continue;
+                               }
+
+                               /* We *have* to have set this in jffs2_build_inode_pass1() */
+                               BUG_ON(!(fd->ic->flags & INO_FLAGS_IS_DIR));
+
+                               /* We clear ic->pino_nlink âˆ€ directories' ic *only* if dir_hardlinks
+                                * is set. Otherwise, we know this should never trigger anyway, so
+                                * we don't do the check. And ic->pino_nlink still contains the nlink
+                                * value (which is 1). */
+                               if (dir_hardlinks && fd->ic->pino_nlink) {
+                                       JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u is also hard linked from dir ino #%u\n",
+                                                   fd->name, fd->ino, ic->ino, fd->ic->pino_nlink);
+                                       /* Should we unlink it from its previous parent? */
+                               }
+
+                               /* For directories, ic->pino_nlink holds that parent inode # */
+                               fd->ic->pino_nlink = ic->ino;
+                       }
                        jffs2_free_full_dirent(fd);
                }
                ic->scan_dents = NULL;
@@ -241,11 +284,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c,
 
                        /* Reduce nlink of the child. If it's now zero, stick it on the
                           dead_fds list to be cleaned up later. Else just free the fd */
-
-                       if (fd->type == DT_DIR)
-                               child_ic->pino_nlink = 0;
-                       else
-                               child_ic->pino_nlink--;
+                       child_ic->pino_nlink--;
 
                        if (!child_ic->pino_nlink) {
                                dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n",
index d211b8e18566719c873838268217b143966e5965..30c4c9ebb693faaecf249df4c913c01bbaa58f20 100644 (file)
@@ -843,9 +843,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
 
                pr_notice("%s(): Link succeeded, unlink failed (err %d). You now have a hard link\n",
                          __func__, ret);
-               /* Might as well let the VFS know */
-               d_instantiate(new_dentry, d_inode(old_dentry));
-               ihold(d_inode(old_dentry));
+               /*
+                * We can't keep the target in dcache after that.
+                * For one thing, we can't afford dentry aliases for directories.
+                * For another, if there was a victim, we _can't_ set new inode
+                * for that sucker and we have to trigger mount eviction - the
+                * caller won't do it on its own since we are returning an error.
+                */
+               d_invalidate(new_dentry);
                new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
                return ret;
        }
index c5ac5944bc1bd8ef1362e5911656f3bfb68ea70b..cad86bac345305e5c3231589c63051cba0a2da6c 100644 (file)
@@ -137,39 +137,33 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
        struct page *pg;
        struct inode *inode = mapping->host;
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
-       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
-       struct jffs2_raw_inode ri;
-       uint32_t alloc_len = 0;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
        uint32_t pageofs = index << PAGE_CACHE_SHIFT;
        int ret = 0;
 
-       jffs2_dbg(1, "%s()\n", __func__);
-
-       if (pageofs > inode->i_size) {
-               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
-                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
-               if (ret)
-                       return ret;
-       }
-
-       mutex_lock(&f->sem);
        pg = grab_cache_page_write_begin(mapping, index, flags);
-       if (!pg) {
-               if (alloc_len)
-                       jffs2_complete_reservation(c);
-               mutex_unlock(&f->sem);
+       if (!pg)
                return -ENOMEM;
-       }
        *pagep = pg;
 
-       if (alloc_len) {
+       jffs2_dbg(1, "%s()\n", __func__);
+
+       if (pageofs > inode->i_size) {
                /* Make new hole frag from old EOF to new page */
+               struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+               struct jffs2_raw_inode ri;
                struct jffs2_full_dnode *fn;
+               uint32_t alloc_len;
 
                jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
                          (unsigned int)inode->i_size, pageofs);
 
+               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+               if (ret)
+                       goto out_page;
+
+               mutex_lock(&f->sem);
                memset(&ri, 0, sizeof(ri));
 
                ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -196,6 +190,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
                        jffs2_complete_reservation(c);
+                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -210,10 +205,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                        jffs2_mark_node_obsolete(c, fn->raw);
                        jffs2_free_full_dnode(fn);
                        jffs2_complete_reservation(c);
+                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                jffs2_complete_reservation(c);
                inode->i_size = pageofs;
+               mutex_unlock(&f->sem);
        }
 
        /*
@@ -222,18 +219,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
         * case of a short-copy.
         */
        if (!PageUptodate(pg)) {
+               mutex_lock(&f->sem);
                ret = jffs2_do_readpage_nolock(inode, pg);
+               mutex_unlock(&f->sem);
                if (ret)
                        goto out_page;
        }
-       mutex_unlock(&f->sem);
        jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
        return ret;
 
 out_page:
        unlock_page(pg);
        page_cache_release(pg);
-       mutex_unlock(&f->sem);
        return ret;
 }
 
index 5a2dec2b064c945aba23acac93dcee2820019d68..95d5880a63ee10fe98ad3520b20890f247e36d0c 100644 (file)
@@ -1296,14 +1296,17 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
                BUG_ON(start > orig_start);
        }
 
-       /* First, use readpage() to read the appropriate page into the page cache */
-       /* Q: What happens if we actually try to GC the _same_ page for which commit_write()
-        *    triggered garbage collection in the first place?
-        * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the
-        *    page OK. We'll actually write it out again in commit_write, which is a little
-        *    suboptimal, but at least we're correct.
-        */
+       /* The rules state that we must obtain the page lock *before* f->sem, so
+        * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's
+        * actually going to *change* so we're safe; we only allow reading.
+        *
+        * It is important to note that jffs2_write_begin() will ensure that its
+        * page is marked Uptodate before allocating space. That means that if we
+        * end up here trying to GC the *same* page that jffs2_write_begin() is
+        * trying to write out, read_cache_page() will not deadlock. */
+       mutex_unlock(&f->sem);
        pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg);
+       mutex_lock(&f->sem);
 
        if (IS_ERR(pg_ptr)) {
                pr_warn("read_cache_page() returned error: %ld\n",
index fa35ff79ab358fe79c734f54ff51ebcb21ab9f7f..0637271f377012b51f6684622f3a0c604385d474 100644 (file)
@@ -194,6 +194,7 @@ struct jffs2_inode_cache {
 #define INO_STATE_CLEARING     6       /* In clear_inode() */
 
 #define INO_FLAGS_XATTR_CHECKED        0x01    /* has no duplicate xattr_ref */
+#define INO_FLAGS_IS_DIR       0x02    /* is a directory */
 
 #define RAWNODE_CLASS_INODE_CACHE      0
 #define RAWNODE_CLASS_XATTR_DATUM      1
@@ -249,7 +250,10 @@ struct jffs2_readinode_info
 
 struct jffs2_full_dirent
 {
-       struct jffs2_raw_node_ref *raw;
+       union {
+               struct jffs2_raw_node_ref *raw;
+               struct jffs2_inode_cache *ic; /* Just during part of build */
+       };
        struct jffs2_full_dirent *next;
        uint32_t version;
        uint32_t ino; /* == zero for unlink */
index 1480d3a180370fe3922a7724e613d09b896f9d00..6bd9fd90964e2670808ee1d586b4080d68f2a1f1 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/highmem.h>
 #include <linux/prefetch.h>
 #include <linux/mpage.h>
+#include <linux/mm_inline.h>
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
 #include <linux/pagevec.h>
@@ -366,7 +367,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
        map_bh.b_state = 0;
        map_bh.b_size = 0;
        for (page_idx = 0; page_idx < nr_pages; page_idx++) {
-               struct page *page = list_entry(pages->prev, struct page, lru);
+               struct page *page = lru_to_page(pages);
 
                prefetchw(&page->flags);
                list_del(&page->lru);
index f624d132e01e6f5488fd0d9af13007b015e1e178..9c590e0f66e9c2189f360bf1b742f54f969713aa 100644 (file)
@@ -1712,6 +1712,11 @@ static inline int should_follow_link(struct nameidata *nd, struct path *link,
                return 0;
        if (!follow)
                return 0;
+       /* make sure that d_is_symlink above matches inode */
+       if (nd->flags & LOOKUP_RCU) {
+               if (read_seqcount_retry(&link->dentry->d_seq, seq))
+                       return -ECHILD;
+       }
        return pick_link(nd, link, inode, seq);
 }
 
@@ -1743,11 +1748,11 @@ static int walk_component(struct nameidata *nd, int flags)
                if (err < 0)
                        return err;
 
-               inode = d_backing_inode(path.dentry);
                seq = 0;        /* we are already out of RCU mode */
                err = -ENOENT;
                if (d_is_negative(path.dentry))
                        goto out_path_put;
+               inode = d_backing_inode(path.dentry);
        }
 
        if (flags & WALK_PUT)
@@ -3192,12 +3197,12 @@ retry_lookup:
                return error;
 
        BUG_ON(nd->flags & LOOKUP_RCU);
-       inode = d_backing_inode(path.dentry);
        seq = 0;        /* out of RCU mode, so the value doesn't matter */
        if (unlikely(d_is_negative(path.dentry))) {
                path_to_nameidata(&path, nd);
                return -ENOENT;
        }
+       inode = d_backing_inode(path.dentry);
 finish_lookup:
        if (nd->depth)
                put_link(nd);
@@ -3206,11 +3211,6 @@ finish_lookup:
        if (unlikely(error))
                return error;
 
-       if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
-               path_to_nameidata(&path, nd);
-               return -ELOOP;
-       }
-
        if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
                path_to_nameidata(&path, nd);
        } else {
@@ -3229,6 +3229,10 @@ finish_open:
                return error;
        }
        audit_inode(nd->name, nd->path.dentry, 0);
+       if (unlikely(d_is_symlink(nd->path.dentry)) && !(open_flag & O_PATH)) {
+               error = -ELOOP;
+               goto out;
+       }
        error = -EISDIR;
        if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
                goto out;
@@ -3273,6 +3277,10 @@ opened:
                        goto exit_fput;
        }
 out:
+       if (unlikely(error > 0)) {
+               WARN_ON(1);
+               error = -EINVAL;
+       }
        if (got_write)
                mnt_drop_write(nd->path.mnt);
        path_put(&save_parent);
index 26c2de2de13fd0ce7bb55287c58e268cf4bf37e6..b7f8eaeea5d83d8a1cb66e2d697de5341e7361cd 100644 (file)
@@ -633,7 +633,7 @@ ncp_fill_cache(struct file *file, struct dir_context *ctx,
                                d_rehash(newdent);
                } else {
                        spin_lock(&dentry->d_lock);
-                       NCP_FINFO(inode)->flags &= ~NCPI_DIR_CACHE;
+                       NCP_FINFO(dir)->flags &= ~NCPI_DIR_CACHE;
                        spin_unlock(&dentry->d_lock);
                }
        } else {
index 794fd1587f34a3bc210d60770525a02f3cd59aba..cda0361e95a403e887d912174ec296aa4cbb6e4d 100644 (file)
@@ -956,6 +956,7 @@ clean_orphan:
                tmp_ret = ocfs2_del_inode_from_orphan(osb, inode, di_bh,
                                update_isize, end);
                if (tmp_ret < 0) {
+                       ocfs2_inode_unlock(inode, 1);
                        ret = tmp_ret;
                        mlog_errno(ret);
                        brelse(di_bh);
index a76b9ea7722e6d7d00d8c0c58217a4a0387f0ff0..ef6a2ec494def2cf0f4584c2d3d7c5eafa485b23 100644 (file)
@@ -287,7 +287,6 @@ struct o2hb_bio_wait_ctxt {
 static void o2hb_write_timeout(struct work_struct *work)
 {
        int failed, quorum;
-       unsigned long flags;
        struct o2hb_region *reg =
                container_of(work, struct o2hb_region,
                             hr_write_timeout_work.work);
@@ -297,14 +296,14 @@ static void o2hb_write_timeout(struct work_struct *work)
             jiffies_to_msecs(jiffies - reg->hr_last_timeout_start));
 
        if (o2hb_global_heartbeat_active()) {
-               spin_lock_irqsave(&o2hb_live_lock, flags);
+               spin_lock(&o2hb_live_lock);
                if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
                        set_bit(reg->hr_region_num, o2hb_failed_region_bitmap);
                failed = bitmap_weight(o2hb_failed_region_bitmap,
                                        O2NM_MAX_REGIONS);
                quorum = bitmap_weight(o2hb_quorum_region_bitmap,
                                        O2NM_MAX_REGIONS);
-               spin_unlock_irqrestore(&o2hb_live_lock, flags);
+               spin_unlock(&o2hb_live_lock);
 
                mlog(ML_HEARTBEAT, "Number of regions %d, failed regions %d\n",
                     quorum, failed);
@@ -2425,11 +2424,10 @@ EXPORT_SYMBOL_GPL(o2hb_check_node_heartbeating);
 int o2hb_check_node_heartbeating_no_sem(u8 node_num)
 {
        unsigned long testing_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
-       unsigned long flags;
 
-       spin_lock_irqsave(&o2hb_live_lock, flags);
+       spin_lock(&o2hb_live_lock);
        o2hb_fill_node_map_from_callback(testing_map, sizeof(testing_map));
-       spin_unlock_irqrestore(&o2hb_live_lock, flags);
+       spin_unlock(&o2hb_live_lock);
        if (!test_bit(node_num, testing_map)) {
                mlog(ML_HEARTBEAT,
                     "node (%u) does not have heartbeating enabled.\n",
index 68c607e63ff683404d1406225feaea01001ba568..004f2cbe8f71e7c4ffb8833f8cc1e249680f99c4 100644 (file)
@@ -282,6 +282,7 @@ static inline void __dlm_set_joining_node(struct dlm_ctxt *dlm,
 #define DLM_LOCK_RES_DROPPING_REF         0x00000040
 #define DLM_LOCK_RES_BLOCK_DIRTY          0x00001000
 #define DLM_LOCK_RES_SETREF_INPROG        0x00002000
+#define DLM_LOCK_RES_RECOVERY_WAITING     0x00004000
 
 /* max milliseconds to wait to sync up a network failure with a node death */
 #define DLM_NODE_DEATH_WAIT_MAX (5 * 1000)
@@ -451,6 +452,7 @@ enum {
        DLM_QUERY_REGION                = 519,
        DLM_QUERY_NODEINFO              = 520,
        DLM_BEGIN_EXIT_DOMAIN_MSG       = 521,
+       DLM_DEREF_LOCKRES_DONE          = 522,
 };
 
 struct dlm_reco_node_data
@@ -545,7 +547,7 @@ struct dlm_master_requery
  * };
  *
  * from ../cluster/tcp.h
- *    NET_MAX_PAYLOAD_BYTES  (4096 - sizeof(net_msg))
+ *    O2NET_MAX_PAYLOAD_BYTES  (4096 - sizeof(net_msg))
  *    (roughly 4080 bytes)
  * and sizeof(dlm_migratable_lockres) = 112 bytes
  * and sizeof(dlm_migratable_lock) = 16 bytes
@@ -586,7 +588,7 @@ struct dlm_migratable_lockres
 
 /* from above, 128 bytes
  * for some undetermined future use */
-#define DLM_MIG_LOCKRES_RESERVED   (NET_MAX_PAYLOAD_BYTES - \
+#define DLM_MIG_LOCKRES_RESERVED   (O2NET_MAX_PAYLOAD_BYTES - \
                                    DLM_MIG_LOCKRES_MAX_LEN)
 
 struct dlm_create_lock
@@ -782,6 +784,20 @@ struct dlm_deref_lockres
        u8 name[O2NM_MAX_NAME_LEN];
 };
 
+enum {
+       DLM_DEREF_RESPONSE_DONE = 0,
+       DLM_DEREF_RESPONSE_INPROG = 1,
+};
+
+struct dlm_deref_lockres_done {
+       u32 pad1;
+       u16 pad2;
+       u8 node_idx;
+       u8 namelen;
+
+       u8 name[O2NM_MAX_NAME_LEN];
+};
+
 static inline enum dlm_status
 __dlm_lockres_state_to_status(struct dlm_lock_resource *res)
 {
@@ -789,7 +805,8 @@ __dlm_lockres_state_to_status(struct dlm_lock_resource *res)
 
        assert_spin_locked(&res->spinlock);
 
-       if (res->state & DLM_LOCK_RES_RECOVERING)
+       if (res->state & (DLM_LOCK_RES_RECOVERING|
+                       DLM_LOCK_RES_RECOVERY_WAITING))
                status = DLM_RECOVERING;
        else if (res->state & DLM_LOCK_RES_MIGRATING)
                status = DLM_MIGRATING;
@@ -968,6 +985,8 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data,
 void dlm_assert_master_post_handler(int status, void *data, void *ret_data);
 int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
                              void **ret_data);
+int dlm_deref_lockres_done_handler(struct o2net_msg *msg, u32 len, void *data,
+                             void **ret_data);
 int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
                                void **ret_data);
 int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
@@ -1009,6 +1028,7 @@ static inline void __dlm_wait_on_lockres(struct dlm_lock_resource *res)
 {
        __dlm_wait_on_lockres_flags(res, (DLM_LOCK_RES_IN_PROGRESS|
                                          DLM_LOCK_RES_RECOVERING|
+                                         DLM_LOCK_RES_RECOVERY_WAITING|
                                          DLM_LOCK_RES_MIGRATING));
 }
 
index 2ee7fe747cea4408182aee7c45e8baa37ceaeae1..12e064b8be9aff94cfe89d8bf4b60cc8eb9d6204 100644 (file)
@@ -132,10 +132,13 @@ static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events);
  *     - Message DLM_QUERY_NODEINFO added to allow online node removes
  * New in version 1.2:
  *     - Message DLM_BEGIN_EXIT_DOMAIN_MSG added to mark start of exit domain
+ * New in version 1.3:
+ *     - Message DLM_DEREF_LOCKRES_DONE added to inform non-master that the
+ *       refmap is cleared
  */
 static const struct dlm_protocol_version dlm_protocol = {
        .pv_major = 1,
-       .pv_minor = 2,
+       .pv_minor = 3,
 };
 
 #define DLM_DOMAIN_BACKOFF_MS 200
@@ -1396,7 +1399,7 @@ static int dlm_send_join_cancels(struct dlm_ctxt *dlm,
                                 unsigned int map_size)
 {
        int status, tmpstat;
-       unsigned int node;
+       int node;
 
        if (map_size != (BITS_TO_LONGS(O2NM_MAX_NODES) *
                         sizeof(unsigned long))) {
@@ -1853,7 +1856,13 @@ static int dlm_register_domain_handlers(struct dlm_ctxt *dlm)
                                        sizeof(struct dlm_exit_domain),
                                        dlm_begin_exit_domain_handler,
                                        dlm, NULL, &dlm->dlm_domain_handlers);
+       if (status)
+               goto bail;
 
+       status = o2net_register_handler(DLM_DEREF_LOCKRES_DONE, dlm->key,
+                                       sizeof(struct dlm_deref_lockres_done),
+                                       dlm_deref_lockres_done_handler,
+                                       dlm, NULL, &dlm->dlm_domain_handlers);
 bail:
        if (status)
                dlm_unregister_domain_handlers(dlm);
index 9477d6e1de372427c36849b6eb3dc5a041089f64..9aed6e2022014afb71988de025e583b38aea3892 100644 (file)
@@ -2278,7 +2278,7 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
                dlm_print_one_lock_resource(res);
                BUG();
        }
-       return ret;
+       return ret ? ret : r;
 }
 
 int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
@@ -2345,7 +2345,7 @@ int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
                        res->lockname.len, res->lockname.name, node);
                        dlm_print_one_lock_resource(res);
                }
-               ret = 0;
+               ret = DLM_DEREF_RESPONSE_DONE;
                goto done;
        }
 
@@ -2365,7 +2365,7 @@ int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
        spin_unlock(&dlm->work_lock);
 
        queue_work(dlm->dlm_worker, &dlm->dispatched_work);
-       return 0;
+       return DLM_DEREF_RESPONSE_INPROG;
 
 done:
        if (res)
@@ -2375,6 +2375,122 @@ done:
        return ret;
 }
 
+int dlm_deref_lockres_done_handler(struct o2net_msg *msg, u32 len, void *data,
+                             void **ret_data)
+{
+       struct dlm_ctxt *dlm = data;
+       struct dlm_deref_lockres_done *deref
+                       = (struct dlm_deref_lockres_done *)msg->buf;
+       struct dlm_lock_resource *res = NULL;
+       char *name;
+       unsigned int namelen;
+       int ret = -EINVAL;
+       u8 node;
+       unsigned int hash;
+
+       if (!dlm_grab(dlm))
+               return 0;
+
+       name = deref->name;
+       namelen = deref->namelen;
+       node = deref->node_idx;
+
+       if (namelen > DLM_LOCKID_NAME_MAX) {
+               mlog(ML_ERROR, "Invalid name length!");
+               goto done;
+       }
+       if (deref->node_idx >= O2NM_MAX_NODES) {
+               mlog(ML_ERROR, "Invalid node number: %u\n", node);
+               goto done;
+       }
+
+       hash = dlm_lockid_hash(name, namelen);
+
+       spin_lock(&dlm->spinlock);
+       res = __dlm_lookup_lockres_full(dlm, name, namelen, hash);
+       if (!res) {
+               spin_unlock(&dlm->spinlock);
+               mlog(ML_ERROR, "%s:%.*s: bad lockres name\n",
+                    dlm->name, namelen, name);
+               goto done;
+       }
+
+       spin_lock(&res->spinlock);
+       BUG_ON(!(res->state & DLM_LOCK_RES_DROPPING_REF));
+       if (!list_empty(&res->purge)) {
+               mlog(0, "%s: Removing res %.*s from purgelist\n",
+                       dlm->name, res->lockname.len, res->lockname.name);
+               list_del_init(&res->purge);
+               dlm_lockres_put(res);
+               dlm->purge_count--;
+       }
+
+       if (!__dlm_lockres_unused(res)) {
+               mlog(ML_ERROR, "%s: res %.*s in use after deref\n",
+                       dlm->name, res->lockname.len, res->lockname.name);
+               __dlm_print_one_lock_resource(res);
+               BUG();
+       }
+
+       __dlm_unhash_lockres(dlm, res);
+
+       spin_lock(&dlm->track_lock);
+       if (!list_empty(&res->tracking))
+               list_del_init(&res->tracking);
+       else {
+               mlog(ML_ERROR, "%s: Resource %.*s not on the Tracking list\n",
+                    dlm->name, res->lockname.len, res->lockname.name);
+               __dlm_print_one_lock_resource(res);
+       }
+       spin_unlock(&dlm->track_lock);
+
+       /* lockres is not in the hash now. drop the flag and wake up
+        * any processes waiting in dlm_get_lock_resource.
+        */
+       res->state &= ~DLM_LOCK_RES_DROPPING_REF;
+       spin_unlock(&res->spinlock);
+       wake_up(&res->wq);
+
+       dlm_lockres_put(res);
+
+       spin_unlock(&dlm->spinlock);
+
+done:
+       dlm_put(dlm);
+       return ret;
+}
+
+static void dlm_drop_lockres_ref_done(struct dlm_ctxt *dlm,
+               struct dlm_lock_resource *res, u8 node)
+{
+       struct dlm_deref_lockres_done deref;
+       int ret = 0, r;
+       const char *lockname;
+       unsigned int namelen;
+
+       lockname = res->lockname.name;
+       namelen = res->lockname.len;
+       BUG_ON(namelen > O2NM_MAX_NAME_LEN);
+
+       memset(&deref, 0, sizeof(deref));
+       deref.node_idx = dlm->node_num;
+       deref.namelen = namelen;
+       memcpy(deref.name, lockname, namelen);
+
+       ret = o2net_send_message(DLM_DEREF_LOCKRES_DONE, dlm->key,
+                                &deref, sizeof(deref), node, &r);
+       if (ret < 0) {
+               mlog(ML_ERROR, "%s: res %.*s, error %d send DEREF DONE "
+                               " to node %u\n", dlm->name, namelen,
+                               lockname, ret, node);
+       } else if (r < 0) {
+               /* ignore the error */
+               mlog(ML_ERROR, "%s: res %.*s, DEREF to node %u got %d\n",
+                    dlm->name, namelen, lockname, node, r);
+               dlm_print_one_lock_resource(res);
+       }
+}
+
 static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
 {
        struct dlm_ctxt *dlm;
@@ -2395,6 +2511,8 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
        }
        spin_unlock(&res->spinlock);
 
+       dlm_drop_lockres_ref_done(dlm, res, node);
+
        if (cleared) {
                mlog(0, "%s:%.*s node %u ref dropped in dispatch\n",
                     dlm->name, res->lockname.len, res->lockname.name, node);
@@ -2432,7 +2550,8 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
                return 0;
 
        /* delay migration when the lockres is in RECOCERING state */
-       if (res->state & DLM_LOCK_RES_RECOVERING)
+       if (res->state & (DLM_LOCK_RES_RECOVERING|
+                       DLM_LOCK_RES_RECOVERY_WAITING))
                return 0;
 
        if (res->owner != dlm->node_num)
index b94a425f0175fa84818d78742659c42293d96dba..cd38488a10fc104fba6339cc2d6c9501a4251dfe 100644 (file)
@@ -1403,12 +1403,24 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
         * and RECOVERY flag changed when it completes. */
        hash = dlm_lockid_hash(mres->lockname, mres->lockname_len);
        spin_lock(&dlm->spinlock);
-       res = __dlm_lookup_lockres(dlm, mres->lockname, mres->lockname_len,
+       res = __dlm_lookup_lockres_full(dlm, mres->lockname, mres->lockname_len,
                        hash);
        if (res) {
                /* this will get a ref on res */
                /* mark it as recovering/migrating and hash it */
                spin_lock(&res->spinlock);
+               if (res->state & DLM_LOCK_RES_DROPPING_REF) {
+                       mlog(0, "%s: node is attempting to migrate "
+                               "lockres %.*s, but marked as dropping "
+                               " ref!\n", dlm->name,
+                               mres->lockname_len, mres->lockname);
+                       ret = -EINVAL;
+                       spin_unlock(&res->spinlock);
+                       spin_unlock(&dlm->spinlock);
+                       dlm_lockres_put(res);
+                       goto leave;
+               }
+
                if (mres->flags & DLM_MRES_RECOVERY) {
                        res->state |= DLM_LOCK_RES_RECOVERING;
                } else {
@@ -2163,6 +2175,13 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
        for (i = 0; i < DLM_HASH_BUCKETS; i++) {
                bucket = dlm_lockres_hash(dlm, i);
                hlist_for_each_entry(res, bucket, hash_node) {
+                       if (res->state & DLM_LOCK_RES_RECOVERY_WAITING) {
+                               spin_lock(&res->spinlock);
+                               res->state &= ~DLM_LOCK_RES_RECOVERY_WAITING;
+                               spin_unlock(&res->spinlock);
+                               wake_up(&res->wq);
+                       }
+
                        if (!(res->state & DLM_LOCK_RES_RECOVERING))
                                continue;
 
@@ -2300,6 +2319,7 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
                             res->lockname.len, res->lockname.name, freed, dead_node);
                        __dlm_print_one_lock_resource(res);
                }
+               res->state |= DLM_LOCK_RES_RECOVERY_WAITING;
                dlm_lockres_clear_refmap_bit(dlm, res, dead_node);
        } else if (test_bit(dead_node, res->refmap)) {
                mlog(0, "%s:%.*s: dead node %u had a ref, but had "
@@ -2377,14 +2397,16 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
                        dlm_revalidate_lvb(dlm, res, dead_node);
                        if (res->owner == dead_node) {
                                if (res->state & DLM_LOCK_RES_DROPPING_REF) {
-                                       mlog(ML_NOTICE, "%s: res %.*s, Skip "
-                                            "recovery as it is being freed\n",
-                                            dlm->name, res->lockname.len,
-                                            res->lockname.name);
-                               } else
-                                       dlm_move_lockres_to_recovery_list(dlm,
-                                                                         res);
-
+                                       mlog(0, "%s:%.*s: owned by "
+                                               "dead node %u, this node was "
+                                               "dropping its ref when it died. "
+                                               "continue, dropping the flag.\n",
+                                               dlm->name, res->lockname.len,
+                                               res->lockname.name, dead_node);
+                               }
+                               res->state &= ~DLM_LOCK_RES_DROPPING_REF;
+                               dlm_move_lockres_to_recovery_list(dlm,
+                                               res);
                        } else if (res->owner == dlm->node_num) {
                                dlm_free_dead_locks(dlm, res, dead_node);
                                __dlm_lockres_calc_usage(dlm, res);
index c5f6c241ecd7d3e71006ad71cfcb1b2134e47221..68d239ba0c63c8c925644755d16a1f020298bfba 100644 (file)
@@ -106,7 +106,8 @@ int __dlm_lockres_unused(struct dlm_lock_resource *res)
        if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY)
                return 0;
 
-       if (res->state & DLM_LOCK_RES_RECOVERING)
+       if (res->state & (DLM_LOCK_RES_RECOVERING|
+                       DLM_LOCK_RES_RECOVERY_WAITING))
                return 0;
 
        /* Another node has this resource with this node as the master */
@@ -202,6 +203,13 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm,
                dlm->purge_count--;
        }
 
+       if (!master && ret != 0) {
+               mlog(0, "%s: deref %.*s in progress or master goes down\n",
+                       dlm->name, res->lockname.len, res->lockname.name);
+               spin_unlock(&res->spinlock);
+               return;
+       }
+
        if (!__dlm_lockres_unused(res)) {
                mlog(ML_ERROR, "%s: res %.*s in use after deref\n",
                     dlm->name, res->lockname.len, res->lockname.name);
@@ -700,7 +708,8 @@ static int dlm_thread(void *data)
                         * dirty for a short while. */
                        BUG_ON(res->state & DLM_LOCK_RES_MIGRATING);
                        if (res->state & (DLM_LOCK_RES_IN_PROGRESS |
-                                         DLM_LOCK_RES_RECOVERING)) {
+                                         DLM_LOCK_RES_RECOVERING |
+                                         DLM_LOCK_RES_RECOVERY_WAITING)) {
                                /* move it to the tail and keep going */
                                res->state &= ~DLM_LOCK_RES_DIRTY;
                                spin_unlock(&res->spinlock);
index 9581d190f6e12346e70226c93458df0a1791abe0..77ebc2bc1cca112056501fe4dc160d48cc7069cd 100644 (file)
@@ -147,6 +147,10 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        ret = ocfs2_inode_lock(inode, &di_bh, 1);
        if (ret < 0) {
                mlog_errno(ret);
+               if (ret == -ENOMEM)
+                       ret = VM_FAULT_OOM;
+               else
+                       ret = VM_FAULT_SIGBUS;
                goto out;
        }
 
index faa1365097bcf38c28dfad30ca849c48e5015938..302854ee0985370a4b1a20591d1b7dbf63787c3f 100644 (file)
@@ -236,6 +236,7 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len)
        struct ocfs2_recovery_map *rm = osb->recovery_map;
        struct ocfs2_orphan_scan *os = &osb->osb_orphan_scan;
        int i, out = 0;
+       unsigned long flags;
 
        out += snprintf(buf + out, len - out,
                        "%10s => Id: %-s  Uuid: %-s  Gen: 0x%X  Label: %-s\n",
@@ -271,14 +272,14 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len)
                                cconn->cc_version.pv_minor);
        }
 
-       spin_lock(&osb->dc_task_lock);
+       spin_lock_irqsave(&osb->dc_task_lock, flags);
        out += snprintf(buf + out, len - out,
                        "%10s => Pid: %d  Count: %lu  WakeSeq: %lu  "
                        "WorkSeq: %lu\n", "DownCnvt",
                        (osb->dc_task ?  task_pid_nr(osb->dc_task) : -1),
                        osb->blocked_lock_count, osb->dc_wake_sequence,
                        osb->dc_work_sequence);
-       spin_unlock(&osb->dc_task_lock);
+       spin_unlock_irqrestore(&osb->dc_task_lock, flags);
 
        spin_lock(&osb->osb_lock);
        out += snprintf(buf + out, len - out, "%10s => Pid: %d  Nodes:",
index ed95272d57a61af3f26a58c71cf789d3c94e28ce..52f6de5d40a9211baa29a39fc2a178598a86a92f 100644 (file)
@@ -618,7 +618,8 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir)
         * sole user of this dentry.  Too tricky...  Just unhash for
         * now.
         */
-       d_drop(dentry);
+       if (!err)
+               d_drop(dentry);
        inode_unlock(dir);
 
        return err;
@@ -903,6 +904,13 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
        if (!overwrite && new_is_dir && !old_opaque && new_opaque)
                ovl_remove_opaque(newdentry);
 
+       /*
+        * Old dentry now lives in different location. Dentries in
+        * lowerstack are stale. We cannot drop them here because
+        * access to them is lockless. This could be only pure upper
+        * or opaque directory - numlower is zero. Or upper non-dir
+        * entry - its pureness is tracked by flag opaque.
+        */
        if (old_opaque != new_opaque) {
                ovl_dentry_set_opaque(old, new_opaque);
                if (!overwrite)
index 49e204560655a8f1737a2a03a38b7a88604a5a4c..a4ff5d0d7db91605880b4eb350ea37aa397c9c9d 100644 (file)
@@ -65,6 +65,8 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
 
                inode_lock(upperdentry->d_inode);
                err = notify_change(upperdentry, attr, NULL);
+               if (!err)
+                       ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
                inode_unlock(upperdentry->d_inode);
        }
        ovl_drop_write(dentry);
index 8d826bd56b26b10d641d7ce1f7a47b747851fac9..619ad4b016d209adcb2b6649d6f654049c860b07 100644 (file)
@@ -76,12 +76,14 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry)
        if (oe->__upperdentry) {
                type = __OVL_PATH_UPPER;
 
-               if (oe->numlower) {
-                       if (S_ISDIR(dentry->d_inode->i_mode))
-                               type |= __OVL_PATH_MERGE;
-               } else if (!oe->opaque) {
+               /*
+                * Non-dir dentry can hold lower dentry from previous
+                * location. Its purity depends only on opaque flag.
+                */
+               if (oe->numlower && S_ISDIR(dentry->d_inode->i_mode))
+                       type |= __OVL_PATH_MERGE;
+               else if (!oe->opaque)
                        type |= __OVL_PATH_PURE;
-               }
        } else {
                if (oe->numlower > 1)
                        type |= __OVL_PATH_MERGE;
@@ -341,6 +343,7 @@ static const struct dentry_operations ovl_dentry_operations = {
 
 static const struct dentry_operations ovl_reval_dentry_operations = {
        .d_release = ovl_dentry_release,
+       .d_select_inode = ovl_d_select_inode,
        .d_revalidate = ovl_dentry_revalidate,
        .d_weak_revalidate = ovl_dentry_weak_revalidate,
 };
index 6367e1e435c64144a1d9adb94e9c1cfd1f157dfe..c524fdddc7fb1f601d6d06ddb46d0affcca89c08 100644 (file)
@@ -202,6 +202,11 @@ static struct mount *last_dest, *last_source, *dest_master;
 static struct mountpoint *mp;
 static struct hlist_head *list;
 
+static inline bool peers(struct mount *m1, struct mount *m2)
+{
+       return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id;
+}
+
 static int propagate_one(struct mount *m)
 {
        struct mount *child;
@@ -212,7 +217,7 @@ static int propagate_one(struct mount *m)
        /* skip if mountpoint isn't covered by it */
        if (!is_subdir(mp->m_dentry, m->mnt.mnt_root))
                return 0;
-       if (m->mnt_group_id == last_dest->mnt_group_id) {
+       if (peers(m, last_dest)) {
                type = CL_MAKE_SHARED;
        } else {
                struct mount *n, *p;
@@ -223,7 +228,7 @@ static int propagate_one(struct mount *m)
                                        last_source = last_source->mnt_master;
                                        last_dest = last_source->mnt_parent;
                                }
-                               if (n->mnt_group_id != last_dest->mnt_group_id) {
+                               if (!peers(n, last_dest)) {
                                        last_source = last_source->mnt_master;
                                        last_dest = last_source->mnt_parent;
                                }
index 324ec271cc4e64868c34e3ff2f28ac2c0542475e..dadf24e5c95bb7004d105f0773430576bfc57cf5 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/splice.h>
 #include <linux/compat.h>
 #include <linux/mount.h>
+#include <linux/fs.h>
 #include "internal.h"
 
 #include <asm/uaccess.h>
@@ -183,7 +184,7 @@ loff_t no_seek_end_llseek(struct file *file, loff_t offset, int whence)
        switch (whence) {
        case SEEK_SET: case SEEK_CUR:
                return generic_file_llseek_size(file, offset, whence,
-                                               ~0ULL, 0);
+                                               OFFSET_MAX, 0);
        default:
                return -EINVAL;
        }
@@ -1532,10 +1533,12 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
 
        if (!(file_in->f_mode & FMODE_READ) ||
            !(file_out->f_mode & FMODE_WRITE) ||
-           (file_out->f_flags & O_APPEND) ||
-           !file_in->f_op->clone_file_range)
+           (file_out->f_flags & O_APPEND))
                return -EBADF;
 
+       if (!file_in->f_op->clone_file_range)
+               return -EOPNOTSUPP;
+
        ret = clone_verify_area(file_in, pos_in, len, false);
        if (ret)
                return ret;
index 1182af8fd5ff3ede7459305440d50178821c061b..74914b1bae70ff09d451450cb596fb3b5639d969 100644 (file)
@@ -415,6 +415,7 @@ void generic_shutdown_super(struct super_block *sb)
                sb->s_flags &= ~MS_ACTIVE;
 
                fsnotify_unmount_inodes(sb);
+               cgroup_writeback_umount();
 
                evict_inodes(sb);
 
index 50311703135bc8c699bcc3d26d0b9aa24b5277f3..66cdb44616d5a0ba79a04f60de5fd835805b6e56 100644 (file)
@@ -286,6 +286,12 @@ int handle_userfault(struct vm_area_struct *vma, unsigned long address,
        if (unlikely(ACCESS_ONCE(ctx->released)))
                goto out;
 
+       /*
+        * We don't do userfault handling for the final child pid update.
+        */
+       if (current->flags & PF_EXITING)
+               goto out;
+
        /*
         * Check that we can return VM_FAULT_RETRY.
         *
index 07d0e47f6a7f1968782b2b31be478a6dd3851656..4861322e28e8da2154f46b7b92cbeda576ee1438 100644 (file)
@@ -940,7 +940,7 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
        bool trusted = capable(CAP_SYS_ADMIN);
        struct simple_xattr *xattr;
        ssize_t remaining_size = size;
-       int err;
+       int err = 0;
 
 #ifdef CONFIG_FS_POSIX_ACL
        if (inode->i_acl) {
@@ -965,11 +965,11 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
 
                err = xattr_list_one(&buffer, &remaining_size, xattr->name);
                if (err)
-                       return err;
+                       break;
        }
        spin_unlock(&xattrs->lock);
 
-       return size - remaining_size;
+       return err ? err : size - remaining_size;
 }
 
 /*
index 379c089fb0514a5a34934b51b790181567a3384f..5c57b7b40728904e0ad9c5641563df57400e76f9 100644 (file)
@@ -55,7 +55,7 @@ xfs_count_page_state(
        } while ((bh = bh->b_this_page) != head);
 }
 
-STATIC struct block_device *
+struct block_device *
 xfs_find_bdev_for_inode(
        struct inode            *inode)
 {
@@ -1208,6 +1208,10 @@ xfs_vm_writepages(
        struct writeback_control *wbc)
 {
        xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
+       if (dax_mapping(mapping))
+               return dax_writeback_mapping_range(mapping,
+                               xfs_find_bdev_for_inode(mapping->host), wbc);
+
        return generic_writepages(mapping, wbc);
 }
 
@@ -1953,7 +1957,6 @@ xfs_vm_set_page_dirty(
        loff_t                  end_offset;
        loff_t                  offset;
        int                     newly_dirty;
-       struct mem_cgroup       *memcg;
 
        if (unlikely(!mapping))
                return !TestSetPageDirty(page);
@@ -1974,10 +1977,10 @@ xfs_vm_set_page_dirty(
                } while (bh != head);
        }
        /*
-        * Use mem_group_begin_page_stat() to keep PageDirty synchronized with
-        * per-memcg dirty page counters.
+        * Lock out page->mem_cgroup migration to keep PageDirty
+        * synchronized with per-memcg dirty page counters.
         */
-       memcg = mem_cgroup_begin_page_stat(page);
+       lock_page_memcg(page);
        newly_dirty = !TestSetPageDirty(page);
        spin_unlock(&mapping->private_lock);
 
@@ -1988,13 +1991,13 @@ xfs_vm_set_page_dirty(
                spin_lock_irqsave(&mapping->tree_lock, flags);
                if (page->mapping) {    /* Race with truncate? */
                        WARN_ON_ONCE(!PageUptodate(page));
-                       account_page_dirtied(page, mapping, memcg);
+                       account_page_dirtied(page, mapping);
                        radix_tree_tag_set(&mapping->page_tree,
                                        page_index(page), PAGECACHE_TAG_DIRTY);
                }
                spin_unlock_irqrestore(&mapping->tree_lock, flags);
        }
-       mem_cgroup_end_page_stat(memcg);
+       unlock_page_memcg(page);
        if (newly_dirty)
                __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
        return newly_dirty;
index f6ffc9ae5cebeae7ebf8c2cc7c3598c07c4c68f5..a4343c63fb38c60336abbaf8741a75c2a9298a4d 100644 (file)
@@ -62,5 +62,6 @@ int   xfs_get_blocks_dax_fault(struct inode *inode, sector_t offset,
                                 struct buffer_head *map_bh, int create);
 
 extern void xfs_count_page_state(struct page *, int *, int *);
+extern struct block_device *xfs_find_bdev_for_inode(struct inode *);
 
 #endif /* __XFS_AOPS_H__ */
index 45ec9e40150c3dc44bc2268c274472f108ad188b..6c876012b2e53246bf38ca3af8dd2d23861151fe 100644 (file)
@@ -75,7 +75,8 @@ xfs_zero_extent(
        ssize_t         size = XFS_FSB_TO_B(mp, count_fsb);
 
        if (IS_DAX(VFS_I(ip)))
-               return dax_clear_blocks(VFS_I(ip), block, size);
+               return dax_clear_sectors(xfs_find_bdev_for_inode(VFS_I(ip)),
+                               sector, size);
 
        /*
         * let the block layer decide on the fastest method of
index 594f7e63b432427fd5b6448afa0a75eb0b71d558..be5568839442d1ab50bf5cae293b7b2b133b525e 100644 (file)
@@ -1109,27 +1109,10 @@ xlog_verify_head(
        bool                    tmp_wrapped;
 
        /*
-        * Search backwards through the log looking for the log record header
-        * block. This wraps all the way back around to the head so something is
-        * seriously wrong if we can't find it.
-        */
-       found = xlog_rseek_logrec_hdr(log, *head_blk, *head_blk, 1, bp, rhead_blk,
-                                     rhead, wrapped);
-       if (found < 0)
-               return found;
-       if (!found) {
-               xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__);
-               return -EIO;
-       }
-
-       *tail_blk = BLOCK_LSN(be64_to_cpu((*rhead)->h_tail_lsn));
-
-       /*
-        * Now that we have a tail block, check the head of the log for torn
-        * writes. Search again until we hit the tail or the maximum number of
-        * log record I/Os that could have been in flight at one time. Use a
-        * temporary buffer so we don't trash the rhead/bp pointer from the
-        * call above.
+        * Check the head of the log for torn writes. Search backwards from the
+        * head until we hit the tail or the maximum number of log record I/Os
+        * that could have been in flight at one time. Use a temporary buffer so
+        * we don't trash the rhead/bp pointers from the caller.
         */
        tmp_bp = xlog_get_bp(log, 1);
        if (!tmp_bp)
@@ -1215,6 +1198,115 @@ xlog_verify_head(
        return error;
 }
 
+/*
+ * Check whether the head of the log points to an unmount record. In other
+ * words, determine whether the log is clean. If so, update the in-core state
+ * appropriately.
+ */
+static int
+xlog_check_unmount_rec(
+       struct xlog             *log,
+       xfs_daddr_t             *head_blk,
+       xfs_daddr_t             *tail_blk,
+       struct xlog_rec_header  *rhead,
+       xfs_daddr_t             rhead_blk,
+       struct xfs_buf          *bp,
+       bool                    *clean)
+{
+       struct xlog_op_header   *op_head;
+       xfs_daddr_t             umount_data_blk;
+       xfs_daddr_t             after_umount_blk;
+       int                     hblks;
+       int                     error;
+       char                    *offset;
+
+       *clean = false;
+
+       /*
+        * Look for unmount record. If we find it, then we know there was a
+        * clean unmount. Since 'i' could be the last block in the physical
+        * log, we convert to a log block before comparing to the head_blk.
+        *
+        * Save the current tail lsn to use to pass to xlog_clear_stale_blocks()
+        * below. We won't want to clear the unmount record if there is one, so
+        * we pass the lsn of the unmount record rather than the block after it.
+        */
+       if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+               int     h_size = be32_to_cpu(rhead->h_size);
+               int     h_version = be32_to_cpu(rhead->h_version);
+
+               if ((h_version & XLOG_VERSION_2) &&
+                   (h_size > XLOG_HEADER_CYCLE_SIZE)) {
+                       hblks = h_size / XLOG_HEADER_CYCLE_SIZE;
+                       if (h_size % XLOG_HEADER_CYCLE_SIZE)
+                               hblks++;
+               } else {
+                       hblks = 1;
+               }
+       } else {
+               hblks = 1;
+       }
+       after_umount_blk = rhead_blk + hblks + BTOBB(be32_to_cpu(rhead->h_len));
+       after_umount_blk = do_mod(after_umount_blk, log->l_logBBsize);
+       if (*head_blk == after_umount_blk &&
+           be32_to_cpu(rhead->h_num_logops) == 1) {
+               umount_data_blk = rhead_blk + hblks;
+               umount_data_blk = do_mod(umount_data_blk, log->l_logBBsize);
+               error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
+               if (error)
+                       return error;
+
+               op_head = (struct xlog_op_header *)offset;
+               if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) {
+                       /*
+                        * Set tail and last sync so that newly written log
+                        * records will point recovery to after the current
+                        * unmount record.
+                        */
+                       xlog_assign_atomic_lsn(&log->l_tail_lsn,
+                                       log->l_curr_cycle, after_umount_blk);
+                       xlog_assign_atomic_lsn(&log->l_last_sync_lsn,
+                                       log->l_curr_cycle, after_umount_blk);
+                       *tail_blk = after_umount_blk;
+
+                       *clean = true;
+               }
+       }
+
+       return 0;
+}
+
+static void
+xlog_set_state(
+       struct xlog             *log,
+       xfs_daddr_t             head_blk,
+       struct xlog_rec_header  *rhead,
+       xfs_daddr_t             rhead_blk,
+       bool                    bump_cycle)
+{
+       /*
+        * Reset log values according to the state of the log when we
+        * crashed.  In the case where head_blk == 0, we bump curr_cycle
+        * one because the next write starts a new cycle rather than
+        * continuing the cycle of the last good log record.  At this
+        * point we have guaranteed that all partial log records have been
+        * accounted for.  Therefore, we know that the last good log record
+        * written was complete and ended exactly on the end boundary
+        * of the physical log.
+        */
+       log->l_prev_block = rhead_blk;
+       log->l_curr_block = (int)head_blk;
+       log->l_curr_cycle = be32_to_cpu(rhead->h_cycle);
+       if (bump_cycle)
+               log->l_curr_cycle++;
+       atomic64_set(&log->l_tail_lsn, be64_to_cpu(rhead->h_tail_lsn));
+       atomic64_set(&log->l_last_sync_lsn, be64_to_cpu(rhead->h_lsn));
+       xlog_assign_grant_head(&log->l_reserve_head.grant, log->l_curr_cycle,
+                                       BBTOB(log->l_curr_block));
+       xlog_assign_grant_head(&log->l_write_head.grant, log->l_curr_cycle,
+                                       BBTOB(log->l_curr_block));
+}
+
 /*
  * Find the sync block number or the tail of the log.
  *
@@ -1238,22 +1330,20 @@ xlog_find_tail(
        xfs_daddr_t             *tail_blk)
 {
        xlog_rec_header_t       *rhead;
-       xlog_op_header_t        *op_head;
        char                    *offset = NULL;
        xfs_buf_t               *bp;
        int                     error;
-       xfs_daddr_t             umount_data_blk;
-       xfs_daddr_t             after_umount_blk;
        xfs_daddr_t             rhead_blk;
        xfs_lsn_t               tail_lsn;
-       int                     hblks;
        bool                    wrapped = false;
+       bool                    clean = false;
 
        /*
         * Find previous log record
         */
        if ((error = xlog_find_head(log, head_blk)))
                return error;
+       ASSERT(*head_blk < INT_MAX);
 
        bp = xlog_get_bp(log, 1);
        if (!bp)
@@ -1271,99 +1361,74 @@ xlog_find_tail(
        }
 
        /*
-        * Trim the head block back to skip over torn records. We can have
-        * multiple log I/Os in flight at any time, so we assume CRC failures
-        * back through the previous several records are torn writes and skip
-        * them.
+        * Search backwards through the log looking for the log record header
+        * block. This wraps all the way back around to the head so something is
+        * seriously wrong if we can't find it.
         */
-       ASSERT(*head_blk < INT_MAX);
-       error = xlog_verify_head(log, head_blk, tail_blk, bp, &rhead_blk,
-                                &rhead, &wrapped);
-       if (error)
-               goto done;
+       error = xlog_rseek_logrec_hdr(log, *head_blk, *head_blk, 1, bp,
+                                     &rhead_blk, &rhead, &wrapped);
+       if (error < 0)
+               return error;
+       if (!error) {
+               xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__);
+               return -EIO;
+       }
+       *tail_blk = BLOCK_LSN(be64_to_cpu(rhead->h_tail_lsn));
 
        /*
-        * Reset log values according to the state of the log when we
-        * crashed.  In the case where head_blk == 0, we bump curr_cycle
-        * one because the next write starts a new cycle rather than
-        * continuing the cycle of the last good log record.  At this
-        * point we have guaranteed that all partial log records have been
-        * accounted for.  Therefore, we know that the last good log record
-        * written was complete and ended exactly on the end boundary
-        * of the physical log.
+        * Set the log state based on the current head record.
         */
-       log->l_prev_block = rhead_blk;
-       log->l_curr_block = (int)*head_blk;
-       log->l_curr_cycle = be32_to_cpu(rhead->h_cycle);
-       if (wrapped)
-               log->l_curr_cycle++;
-       atomic64_set(&log->l_tail_lsn, be64_to_cpu(rhead->h_tail_lsn));
-       atomic64_set(&log->l_last_sync_lsn, be64_to_cpu(rhead->h_lsn));
-       xlog_assign_grant_head(&log->l_reserve_head.grant, log->l_curr_cycle,
-                                       BBTOB(log->l_curr_block));
-       xlog_assign_grant_head(&log->l_write_head.grant, log->l_curr_cycle,
-                                       BBTOB(log->l_curr_block));
+       xlog_set_state(log, *head_blk, rhead, rhead_blk, wrapped);
+       tail_lsn = atomic64_read(&log->l_tail_lsn);
 
        /*
-        * Look for unmount record.  If we find it, then we know there
-        * was a clean unmount.  Since 'i' could be the last block in
-        * the physical log, we convert to a log block before comparing
-        * to the head_blk.
+        * Look for an unmount record at the head of the log. This sets the log
+        * state to determine whether recovery is necessary.
+        */
+       error = xlog_check_unmount_rec(log, head_blk, tail_blk, rhead,
+                                      rhead_blk, bp, &clean);
+       if (error)
+               goto done;
+
+       /*
+        * Verify the log head if the log is not clean (e.g., we have anything
+        * but an unmount record at the head). This uses CRC verification to
+        * detect and trim torn writes. If discovered, CRC failures are
+        * considered torn writes and the log head is trimmed accordingly.
         *
-        * Save the current tail lsn to use to pass to
-        * xlog_clear_stale_blocks() below.  We won't want to clear the
-        * unmount record if there is one, so we pass the lsn of the
-        * unmount record rather than the block after it.
+        * Note that we can only run CRC verification when the log is dirty
+        * because there's no guarantee that the log data behind an unmount
+        * record is compatible with the current architecture.
         */
-       if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
-               int     h_size = be32_to_cpu(rhead->h_size);
-               int     h_version = be32_to_cpu(rhead->h_version);
+       if (!clean) {
+               xfs_daddr_t     orig_head = *head_blk;
 
-               if ((h_version & XLOG_VERSION_2) &&
-                   (h_size > XLOG_HEADER_CYCLE_SIZE)) {
-                       hblks = h_size / XLOG_HEADER_CYCLE_SIZE;
-                       if (h_size % XLOG_HEADER_CYCLE_SIZE)
-                               hblks++;
-               } else {
-                       hblks = 1;
-               }
-       } else {
-               hblks = 1;
-       }
-       after_umount_blk = rhead_blk + hblks + BTOBB(be32_to_cpu(rhead->h_len));
-       after_umount_blk = do_mod(after_umount_blk, log->l_logBBsize);
-       tail_lsn = atomic64_read(&log->l_tail_lsn);
-       if (*head_blk == after_umount_blk &&
-           be32_to_cpu(rhead->h_num_logops) == 1) {
-               umount_data_blk = rhead_blk + hblks;
-               umount_data_blk = do_mod(umount_data_blk, log->l_logBBsize);
-               error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
+               error = xlog_verify_head(log, head_blk, tail_blk, bp,
+                                        &rhead_blk, &rhead, &wrapped);
                if (error)
                        goto done;
 
-               op_head = (xlog_op_header_t *)offset;
-               if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) {
-                       /*
-                        * Set tail and last sync so that newly written
-                        * log records will point recovery to after the
-                        * current unmount record.
-                        */
-                       xlog_assign_atomic_lsn(&log->l_tail_lsn,
-                                       log->l_curr_cycle, after_umount_blk);
-                       xlog_assign_atomic_lsn(&log->l_last_sync_lsn,
-                                       log->l_curr_cycle, after_umount_blk);
-                       *tail_blk = after_umount_blk;
-
-                       /*
-                        * Note that the unmount was clean. If the unmount
-                        * was not clean, we need to know this to rebuild the
-                        * superblock counters from the perag headers if we
-                        * have a filesystem using non-persistent counters.
-                        */
-                       log->l_mp->m_flags |= XFS_MOUNT_WAS_CLEAN;
+               /* update in-core state again if the head changed */
+               if (*head_blk != orig_head) {
+                       xlog_set_state(log, *head_blk, rhead, rhead_blk,
+                                      wrapped);
+                       tail_lsn = atomic64_read(&log->l_tail_lsn);
+                       error = xlog_check_unmount_rec(log, head_blk, tail_blk,
+                                                      rhead, rhead_blk, bp,
+                                                      &clean);
+                       if (error)
+                               goto done;
                }
        }
 
+       /*
+        * Note that the unmount was clean. If the unmount was not clean, we
+        * need to know this to rebuild the superblock counters from the perag
+        * headers if we have a filesystem using non-persistent counters.
+        */
+       if (clean)
+               log->l_mp->m_flags |= XFS_MOUNT_WAS_CLEAN;
+
        /*
         * Make sure that there are no blocks in front of the head
         * with the same cycle number as the head.  This can happen
index 5bfc61943f88a90f0b4df3d0cb04d42319a6d731..34f601e7b88d3a75f237a17664da6a253d7857c2 100644 (file)
 #define ACPI_GET_FUNCTION_NAME          _acpi_function_name
 
 /*
- * The Name parameter should be the procedure name as a quoted string.
+ * The Name parameter should be the procedure name as a non-quoted string.
  * The function name is also used by the function exit macros below.
  * Note: (const char) is used to be compatible with the debug interfaces
  * and macros such as __func__.
index c96621e87c196bf8fa6aa7c9f5033c625efc4cb2..17556979dc79bffdb26b928d6f6348edfae4d095 100644 (file)
@@ -897,11 +897,9 @@ ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3)
                                acpi_warning(const char *module_name,
                                             u32 line_number,
                                             const char *format, ...))
-ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3)
+ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(1)
                                void ACPI_INTERNAL_VAR_XFACE
-                               acpi_info(const char *module_name,
-                                         u32 line_number,
-                                         const char *format, ...))
+                               acpi_info(const char *format, ...))
 ACPI_MSG_DEPENDENT_RETURN_VOID(ACPI_PRINTF_LIKE(3)
                                void ACPI_INTERNAL_VAR_XFACE
                                acpi_bios_error(const char *module_name,
index 07fb100bcc688ddc1835b958ac430182ee699128..6f1805dd5d3c60e58e648fdd2750c76bda6d7ec8 100644 (file)
@@ -9,6 +9,7 @@
 #define ACPI_PROCESSOR_CLASS           "processor"
 #define ACPI_PROCESSOR_DEVICE_NAME     "Processor"
 #define ACPI_PROCESSOR_DEVICE_HID      "ACPI0007"
+#define ACPI_PROCESSOR_CONTAINER_HID   "ACPI0010"
 
 #define ACPI_PROCESSOR_BUSY_METRIC     10
 
@@ -394,14 +395,6 @@ static inline int acpi_processor_hotplug(struct acpi_processor *pr)
 }
 #endif /* CONFIG_ACPI_PROCESSOR_IDLE */
 
-#if defined(CONFIG_PM_SLEEP) & defined(CONFIG_ACPI_PROCESSOR_IDLE)
-void acpi_processor_syscore_init(void);
-void acpi_processor_syscore_exit(void);
-#else
-static inline void acpi_processor_syscore_init(void) {}
-static inline void acpi_processor_syscore_exit(void) {}
-#endif
-
 /* in processor_thermal.c */
 int acpi_processor_get_limit_info(struct acpi_processor *pr);
 extern const struct thermal_cooling_device_ops processor_cooling_ops;
diff --git a/include/asm-generic/pci-bridge.h b/include/asm-generic/pci-bridge.h
deleted file mode 100644 (file)
index 20db2e5..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _ASM_GENERIC_PCI_BRIDGE_H
-#define _ASM_GENERIC_PCI_BRIDGE_H
-
-#ifdef __KERNEL__
-
-enum {
-       /* Force re-assigning all resources (ignore firmware
-        * setup completely)
-        */
-       PCI_REASSIGN_ALL_RSRC   = 0x00000001,
-
-       /* Re-assign all bus numbers */
-       PCI_REASSIGN_ALL_BUS    = 0x00000002,
-
-       /* Do not try to assign, just use existing setup */
-       PCI_PROBE_ONLY          = 0x00000004,
-
-       /* Don't bother with ISA alignment unless the bridge has
-        * ISA forwarding enabled
-        */
-       PCI_CAN_SKIP_ISA_ALIGN  = 0x00000008,
-
-       /* Enable domain numbers in /proc */
-       PCI_ENABLE_PROC_DOMAINS = 0x00000010,
-       /* ... except for domain 0 */
-       PCI_COMPAT_DOMAIN_0     = 0x00000020,
-
-       /* PCIe downstream ports are bridges that normally lead to only a
-        * device 0, but if this is set, we scan all possible devices, not
-        * just device 0.
-        */
-       PCI_SCAN_ALL_PCIE_DEVS  = 0x00000040,
-};
-
-#ifdef CONFIG_PCI
-extern unsigned int pci_flags;
-
-static inline void pci_set_flags(int flags)
-{
-       pci_flags = flags;
-}
-
-static inline void pci_add_flags(int flags)
-{
-       pci_flags |= flags;
-}
-
-static inline void pci_clear_flags(int flags)
-{
-       pci_flags &= ~flags;
-}
-
-static inline int pci_has_flag(int flag)
-{
-       return pci_flags & flag;
-}
-#else
-static inline void pci_set_flags(int flags) { }
-static inline void pci_add_flags(int flags) { }
-static inline void pci_clear_flags(int flags) { }
-static inline int pci_has_flag(int flag)
-{
-       return 0;
-}
-#endif /* CONFIG_PCI */
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_GENERIC_PCI_BRIDGE_H */
diff --git a/include/asm-generic/pci-dma-compat.h b/include/asm-generic/pci-dma-compat.h
deleted file mode 100644 (file)
index eafce7b..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/* include this file if the platform implements the dma_ DMA Mapping API
- * and wants to provide the pci_ DMA Mapping API in terms of it */
-
-#ifndef _ASM_GENERIC_PCI_DMA_COMPAT_H
-#define _ASM_GENERIC_PCI_DMA_COMPAT_H
-
-#include <linux/dma-mapping.h>
-
-static inline void *
-pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                    dma_addr_t *dma_handle)
-{
-       return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC);
-}
-
-static inline void *
-pci_zalloc_consistent(struct pci_dev *hwdev, size_t size,
-                     dma_addr_t *dma_handle)
-{
-       return dma_zalloc_coherent(hwdev == NULL ? NULL : &hwdev->dev,
-                                  size, dma_handle, GFP_ATOMIC);
-}
-
-static inline void
-pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                   void *vaddr, dma_addr_t dma_handle)
-{
-       dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, vaddr, dma_handle);
-}
-
-static inline dma_addr_t
-pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
-{
-       return dma_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-                size_t size, int direction)
-{
-       dma_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
-}
-
-static inline dma_addr_t
-pci_map_page(struct pci_dev *hwdev, struct page *page,
-            unsigned long offset, size_t size, int direction)
-{
-       return dma_map_page(hwdev == NULL ? NULL : &hwdev->dev, page, offset, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
-              size_t size, int direction)
-{
-       dma_unmap_page(hwdev == NULL ? NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction)direction);
-}
-
-static inline int
-pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-          int nents, int direction)
-{
-       return dma_map_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-            int nents, int direction)
-{
-       dma_unmap_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
-                   size_t size, int direction)
-{
-       dma_sync_single_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
-                   size_t size, int direction)
-{
-       dma_sync_single_for_device(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
-               int nelems, int direction)
-{
-       dma_sync_sg_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
-}
-
-static inline void
-pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
-               int nelems, int direction)
-{
-       dma_sync_sg_for_device(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
-}
-
-static inline int
-pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr)
-{
-       return dma_mapping_error(&pdev->dev, dma_addr);
-}
-
-#ifdef CONFIG_PCI
-static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       return dma_set_mask(&dev->dev, mask);
-}
-
-static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       return dma_set_coherent_mask(&dev->dev, mask);
-}
-#endif
-
-#endif
index 39e1cb201b8eaa00ffe759ce7147cc8b3647fb5d..35a52a880b2f812b382c905bf44df50290aa4f0c 100644 (file)
@@ -119,11 +119,6 @@ static __always_inline bool virt_spin_lock(struct qspinlock *lock)
 }
 #endif
 
-/*
- * Initializier
- */
-#define        __ARCH_SPIN_LOCK_UNLOCKED       { ATOMIC_INIT(0) }
-
 /*
  * Remapping spinlock architecture specific functions to the corresponding
  * queued spinlock functions.
index 85f888e86761e1b71bd0de2a891a160194e256d7..034acd0c4956b59932f650e85612a9397236dc66 100644 (file)
@@ -32,6 +32,11 @@ typedef struct qspinlock {
        atomic_t        val;
 } arch_spinlock_t;
 
+/*
+ * Initializier
+ */
+#define        __ARCH_SPIN_LOCK_UNLOCKED       { ATOMIC_INIT(0) }
+
 /*
  * Bitfields in the atomic value:
  *
index c4bd0e2c173c011e37f6eef7acfb9bc3920fcca6..772c784ba76301dbceca9f3c0991c626a893e076 100644 (file)
        .rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {           \
                VMLINUX_SYMBOL(__start_rodata) = .;                     \
                *(.rodata) *(.rodata.*)                                 \
+               *(.data..ro_after_init) /* Read only after init */      \
                *(__vermagic)           /* Kernel version magic */      \
                . = ALIGN(8);                                           \
                VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .;         \
diff --git a/include/dt-bindings/pinctrl/mt7623-pinfunc.h b/include/dt-bindings/pinctrl/mt7623-pinfunc.h
new file mode 100644 (file)
index 0000000..2f00bdc
--- /dev/null
@@ -0,0 +1,520 @@
+#ifndef __DTS_MT7623_PINFUNC_H
+#define __DTS_MT7623_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
+#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_PWRAP_SPIDO (MTK_PIN_NO(0) | 1)
+#define MT7623_PIN_0_PWRAP_SPI0_MI_FUNC_PWRAP_SPIDI (MTK_PIN_NO(0) | 2)
+
+#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
+#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_PWRAP_SPIDI (MTK_PIN_NO(1) | 1)
+#define MT7623_PIN_1_PWRAP_SPI0_MO_FUNC_PWRAP_SPIDO (MTK_PIN_NO(1) | 2)
+
+#define MT7623_PIN_2_PWRAP_INT_FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
+#define MT7623_PIN_2_PWRAP_INT_FUNC_PWRAP_INT (MTK_PIN_NO(2) | 1)
+
+#define MT7623_PIN_3_PWRAP_SPI0_CK_FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
+#define MT7623_PIN_3_PWRAP_SPI0_CK_FUNC_PWRAP_SPICK_I (MTK_PIN_NO(3) | 1)
+
+#define MT7623_PIN_4_PWRAP_SPI0_CSN_FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
+#define MT7623_PIN_4_PWRAP_SPI0_CSN_FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(4) | 1)
+
+#define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
+#define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_PWRAP_SPICK2_I (MTK_PIN_NO(5) | 1)
+
+#define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
+#define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_PWRAP_SPICS2_B_I (MTK_PIN_NO(6) | 1)
+
+#define MT7623_PIN_7_SPI1_CSN_FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
+#define MT7623_PIN_7_SPI1_CSN_FUNC_SPI1_CS (MTK_PIN_NO(7) | 1)
+
+#define MT7623_PIN_8_SPI1_MI_FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
+#define MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MI (MTK_PIN_NO(8) | 1)
+#define MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MO (MTK_PIN_NO(8) | 2)
+
+#define MT7623_PIN_9_SPI1_MO_FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
+#define MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MO (MTK_PIN_NO(9) | 1)
+#define MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MI (MTK_PIN_NO(9) | 2)
+
+#define MT7623_PIN_10_RTC32K_CK_FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
+#define MT7623_PIN_10_RTC32K_CK_FUNC_RTC32K_CK (MTK_PIN_NO(10) | 1)
+
+#define MT7623_PIN_11_WATCHDOG_FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
+#define MT7623_PIN_11_WATCHDOG_FUNC_WATCHDOG (MTK_PIN_NO(11) | 1)
+
+#define MT7623_PIN_12_SRCLKENA_FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
+#define MT7623_PIN_12_SRCLKENA_FUNC_SRCLKENA (MTK_PIN_NO(12) | 1)
+
+#define MT7623_PIN_13_SRCLKENAI_FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
+#define MT7623_PIN_13_SRCLKENAI_FUNC_SRCLKENAI (MTK_PIN_NO(13) | 1)
+
+#define MT7623_PIN_14_GPIO14_FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
+#define MT7623_PIN_14_GPIO14_FUNC_URXD2 (MTK_PIN_NO(14) | 1)
+#define MT7623_PIN_14_GPIO14_FUNC_UTXD2 (MTK_PIN_NO(14) | 2)
+
+#define MT7623_PIN_15_GPIO15_FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
+#define MT7623_PIN_15_GPIO15_FUNC_UTXD2 (MTK_PIN_NO(15) | 1)
+#define MT7623_PIN_15_GPIO15_FUNC_URXD2 (MTK_PIN_NO(15) | 2)
+
+#define MT7623_PIN_18_PCM_CLK_FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
+#define MT7623_PIN_18_PCM_CLK_FUNC_PCM_CLK0 (MTK_PIN_NO(18) | 1)
+#define MT7623_PIN_18_PCM_CLK_FUNC_AP_PCM_CLKO (MTK_PIN_NO(18) | 6)
+
+#define MT7623_PIN_19_PCM_SYNC_FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
+#define MT7623_PIN_19_PCM_SYNC_FUNC_PCM_SYNC (MTK_PIN_NO(19) | 1)
+#define MT7623_PIN_19_PCM_SYNC_FUNC_AP_PCM_SYNC (MTK_PIN_NO(19) | 6)
+
+#define MT7623_PIN_20_PCM_RX_FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
+#define MT7623_PIN_20_PCM_RX_FUNC_PCM_RX (MTK_PIN_NO(20) | 1)
+#define MT7623_PIN_20_PCM_RX_FUNC_PCM_TX (MTK_PIN_NO(20) | 4)
+#define MT7623_PIN_20_PCM_RX_FUNC_AP_PCM_RX (MTK_PIN_NO(20) | 6)
+
+#define MT7623_PIN_21_PCM_TX_FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
+#define MT7623_PIN_21_PCM_TX_FUNC_PCM_TX (MTK_PIN_NO(21) | 1)
+#define MT7623_PIN_21_PCM_TX_FUNC_PCM_RX (MTK_PIN_NO(21) | 4)
+#define MT7623_PIN_21_PCM_TX_FUNC_AP_PCM_TX (MTK_PIN_NO(21) | 6)
+
+#define MT7623_PIN_22_EINT0_FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
+#define MT7623_PIN_22_EINT0_FUNC_UCTS0 (MTK_PIN_NO(22) | 1)
+#define MT7623_PIN_22_EINT0_FUNC_PCIE0_PERST_N (MTK_PIN_NO(22) | 2)
+
+#define MT7623_PIN_23_EINT1_FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
+#define MT7623_PIN_23_EINT1_FUNC_URTS0 (MTK_PIN_NO(23) | 1)
+#define MT7623_PIN_23_EINT1_FUNC_PCIE1_PERST_N (MTK_PIN_NO(23) | 2)
+
+#define MT7623_PIN_24_EINT2_FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
+#define MT7623_PIN_24_EINT2_FUNC_UCTS1 (MTK_PIN_NO(24) | 1)
+#define MT7623_PIN_24_EINT2_FUNC_PCIE2_PERST_N (MTK_PIN_NO(24) | 2)
+
+#define MT7623_PIN_25_EINT3_FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
+#define MT7623_PIN_25_EINT3_FUNC_URTS1 (MTK_PIN_NO(25) | 1)
+
+#define MT7623_PIN_26_EINT4_FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
+#define MT7623_PIN_26_EINT4_FUNC_UCTS3 (MTK_PIN_NO(26) | 1)
+#define MT7623_PIN_26_EINT4_FUNC_PCIE2_WAKE_N (MTK_PIN_NO(26) | 6)
+
+#define MT7623_PIN_27_EINT5_FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
+#define MT7623_PIN_27_EINT5_FUNC_URTS3 (MTK_PIN_NO(27) | 1)
+#define MT7623_PIN_27_EINT5_FUNC_PCIE1_WAKE_N (MTK_PIN_NO(27) | 6)
+
+#define MT7623_PIN_28_EINT6_FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
+#define MT7623_PIN_28_EINT6_FUNC_DRV_VBUS (MTK_PIN_NO(28) | 1)
+#define MT7623_PIN_28_EINT6_FUNC_PCIE0_WAKE_N (MTK_PIN_NO(28) | 6)
+
+#define MT7623_PIN_29_EINT7_FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
+#define MT7623_PIN_29_EINT7_FUNC_IDDIG (MTK_PIN_NO(29) | 1)
+#define MT7623_PIN_29_EINT7_FUNC_MSDC1_WP (MTK_PIN_NO(29) | 2)
+#define MT7623_PIN_29_EINT7_FUNC_PCIE2_PERST_N (MTK_PIN_NO(29) | 6)
+
+#define MT7623_PIN_33_I2S1_DATA_FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
+#define MT7623_PIN_33_I2S1_DATA_FUNC_I2S1_DATA (MTK_PIN_NO(33) | 1)
+#define MT7623_PIN_33_I2S1_DATA_FUNC_PCM_TX (MTK_PIN_NO(33) | 3)
+#define MT7623_PIN_33_I2S1_DATA_FUNC_AP_PCM_TX (MTK_PIN_NO(33) | 6)
+
+#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
+#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_I2S1_DATA_IN (MTK_PIN_NO(34) | 1)
+#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_PCM_RX (MTK_PIN_NO(34) | 3)
+#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_AP_PCM_RX (MTK_PIN_NO(34) | 6)
+
+#define MT7623_PIN_35_I2S1_BCK_FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
+#define MT7623_PIN_35_I2S1_BCK_FUNC_I2S1_BCK (MTK_PIN_NO(35) | 1)
+#define MT7623_PIN_35_I2S1_BCK_FUNC_PCM_CLK0 (MTK_PIN_NO(35) | 3)
+#define MT7623_PIN_35_I2S1_BCK_FUNC_AP_PCM_CLKO (MTK_PIN_NO(35) | 6)
+
+#define MT7623_PIN_36_I2S1_LRCK_FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
+#define MT7623_PIN_36_I2S1_LRCK_FUNC_I2S1_LRCK (MTK_PIN_NO(36) | 1)
+#define MT7623_PIN_36_I2S1_LRCK_FUNC_PCM_SYNC (MTK_PIN_NO(36) | 3)
+#define MT7623_PIN_36_I2S1_LRCK_FUNC_AP_PCM_SYNC (MTK_PIN_NO(36) | 6)
+
+#define MT7623_PIN_37_I2S1_MCLK_FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
+#define MT7623_PIN_37_I2S1_MCLK_FUNC_I2S1_MCLK (MTK_PIN_NO(37) | 1)
+
+#define MT7623_PIN_39_JTMS_FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
+#define MT7623_PIN_39_JTMS_FUNC_JTMS (MTK_PIN_NO(39) | 1)
+
+#define MT7623_PIN_40_JTCK_FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
+#define MT7623_PIN_40_JTCK_FUNC_JTCK (MTK_PIN_NO(40) | 1)
+
+#define MT7623_PIN_41_JTDI_FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
+#define MT7623_PIN_41_JTDI_FUNC_JTDI (MTK_PIN_NO(41) | 1)
+
+#define MT7623_PIN_42_JTDO_FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
+#define MT7623_PIN_42_JTDO_FUNC_JTDO (MTK_PIN_NO(42) | 1)
+
+#define MT7623_PIN_43_NCLE_FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
+#define MT7623_PIN_43_NCLE_FUNC_NCLE (MTK_PIN_NO(43) | 1)
+#define MT7623_PIN_43_NCLE_FUNC_EXT_XCS2 (MTK_PIN_NO(43) | 2)
+
+#define MT7623_PIN_44_NCEB1_FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
+#define MT7623_PIN_44_NCEB1_FUNC_NCEB1 (MTK_PIN_NO(44) | 1)
+#define MT7623_PIN_44_NCEB1_FUNC_IDDIG (MTK_PIN_NO(44) | 2)
+
+#define MT7623_PIN_45_NCEB0_FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
+#define MT7623_PIN_45_NCEB0_FUNC_NCEB0 (MTK_PIN_NO(45) | 1)
+#define MT7623_PIN_45_NCEB0_FUNC_DRV_VBUS (MTK_PIN_NO(45) | 2)
+
+#define MT7623_PIN_46_IR_FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
+#define MT7623_PIN_46_IR_FUNC_IR (MTK_PIN_NO(46) | 1)
+
+#define MT7623_PIN_47_NREB_FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
+#define MT7623_PIN_47_NREB_FUNC_NREB (MTK_PIN_NO(47) | 1)
+
+#define MT7623_PIN_48_NRNB_FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
+#define MT7623_PIN_48_NRNB_FUNC_NRNB (MTK_PIN_NO(48) | 1)
+
+#define MT7623_PIN_49_I2S0_DATA_FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
+#define MT7623_PIN_49_I2S0_DATA_FUNC_I2S0_DATA (MTK_PIN_NO(49) | 1)
+#define MT7623_PIN_49_I2S0_DATA_FUNC_PCM_TX (MTK_PIN_NO(49) | 3)
+#define MT7623_PIN_49_I2S0_DATA_FUNC_AP_I2S_DO (MTK_PIN_NO(49) | 6)
+
+#define MT7623_PIN_53_SPI0_CSN_FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
+#define MT7623_PIN_53_SPI0_CSN_FUNC_SPI0_CS (MTK_PIN_NO(53) | 1)
+#define MT7623_PIN_53_SPI0_CSN_FUNC_PWM1 (MTK_PIN_NO(53) | 5)
+
+#define MT7623_PIN_54_SPI0_CK_FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
+#define MT7623_PIN_54_SPI0_CK_FUNC_SPI0_CK (MTK_PIN_NO(54) | 1)
+
+#define MT7623_PIN_55_SPI0_MI_FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
+#define MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MI (MTK_PIN_NO(55) | 1)
+#define MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MO (MTK_PIN_NO(55) | 2)
+#define MT7623_PIN_55_SPI0_MI_FUNC_MSDC1_WP (MTK_PIN_NO(55) | 3)
+#define MT7623_PIN_55_SPI0_MI_FUNC_PWM2 (MTK_PIN_NO(55) | 5)
+
+#define MT7623_PIN_56_SPI0_MO_FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
+#define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MO (MTK_PIN_NO(56) | 1)
+#define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MI (MTK_PIN_NO(56) | 2)
+
+#define MT7623_PIN_60_WB_RSTB_FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
+#define MT7623_PIN_60_WB_RSTB_FUNC_WB_RSTB (MTK_PIN_NO(60) | 1)
+
+#define MT7623_PIN_61_GPIO61_FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
+#define MT7623_PIN_61_GPIO61_FUNC_TEST_FD (MTK_PIN_NO(61) | 1)
+
+#define MT7623_PIN_62_GPIO62_FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
+#define MT7623_PIN_62_GPIO62_FUNC_TEST_FC (MTK_PIN_NO(62) | 1)
+
+#define MT7623_PIN_63_WB_SCLK_FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
+#define MT7623_PIN_63_WB_SCLK_FUNC_WB_SCLK (MTK_PIN_NO(63) | 1)
+
+#define MT7623_PIN_64_WB_SDATA_FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
+#define MT7623_PIN_64_WB_SDATA_FUNC_WB_SDATA (MTK_PIN_NO(64) | 1)
+
+#define MT7623_PIN_65_WB_SEN_FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
+#define MT7623_PIN_65_WB_SEN_FUNC_WB_SEN (MTK_PIN_NO(65) | 1)
+
+#define MT7623_PIN_66_WB_CRTL0_FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
+#define MT7623_PIN_66_WB_CRTL0_FUNC_WB_CRTL0 (MTK_PIN_NO(66) | 1)
+
+#define MT7623_PIN_67_WB_CRTL1_FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
+#define MT7623_PIN_67_WB_CRTL1_FUNC_WB_CRTL1 (MTK_PIN_NO(67) | 1)
+
+#define MT7623_PIN_68_WB_CRTL2_FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
+#define MT7623_PIN_68_WB_CRTL2_FUNC_WB_CRTL2 (MTK_PIN_NO(68) | 1)
+
+#define MT7623_PIN_69_WB_CRTL3_FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
+#define MT7623_PIN_69_WB_CRTL3_FUNC_WB_CRTL3 (MTK_PIN_NO(69) | 1)
+
+#define MT7623_PIN_70_WB_CRTL4_FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
+#define MT7623_PIN_70_WB_CRTL4_FUNC_WB_CRTL4 (MTK_PIN_NO(70) | 1)
+
+#define MT7623_PIN_71_WB_CRTL5_FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
+#define MT7623_PIN_71_WB_CRTL5_FUNC_WB_CRTL5 (MTK_PIN_NO(71) | 1)
+
+#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
+#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_I2S0_DATA_IN (MTK_PIN_NO(72) | 1)
+#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_PCM_RX (MTK_PIN_NO(72) | 3)
+#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_PWM0 (MTK_PIN_NO(72) | 4)
+#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_DISP_PWM (MTK_PIN_NO(72) | 5)
+#define MT7623_PIN_72_I2S0_DATA_IN_FUNC_AP_I2S_DI (MTK_PIN_NO(72) | 6)
+
+#define MT7623_PIN_73_I2S0_LRCK_FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
+#define MT7623_PIN_73_I2S0_LRCK_FUNC_I2S0_LRCK (MTK_PIN_NO(73) | 1)
+#define MT7623_PIN_73_I2S0_LRCK_FUNC_PCM_SYNC (MTK_PIN_NO(73) | 3)
+#define MT7623_PIN_73_I2S0_LRCK_FUNC_AP_I2S_LRCK (MTK_PIN_NO(73) | 6)
+
+#define MT7623_PIN_74_I2S0_BCK_FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
+#define MT7623_PIN_74_I2S0_BCK_FUNC_I2S0_BCK (MTK_PIN_NO(74) | 1)
+#define MT7623_PIN_74_I2S0_BCK_FUNC_PCM_CLK0 (MTK_PIN_NO(74) | 3)
+#define MT7623_PIN_74_I2S0_BCK_FUNC_AP_I2S_BCK (MTK_PIN_NO(74) | 6)
+
+#define MT7623_PIN_75_SDA0_FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
+#define MT7623_PIN_75_SDA0_FUNC_SDA0 (MTK_PIN_NO(75) | 1)
+
+#define MT7623_PIN_76_SCL0_FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+#define MT7623_PIN_76_SCL0_FUNC_SCL0 (MTK_PIN_NO(76) | 1)
+
+#define MT7623_PIN_83_LCM_RST_FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+#define MT7623_PIN_83_LCM_RST_FUNC_LCM_RST (MTK_PIN_NO(83) | 1)
+
+#define MT7623_PIN_84_DSI_TE_FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
+#define MT7623_PIN_84_DSI_TE_FUNC_DSI_TE (MTK_PIN_NO(84) | 1)
+
+#define MT7623_PIN_95_MIPI_TCN_FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
+#define MT7623_PIN_95_MIPI_TCN_FUNC_TCN (MTK_PIN_NO(95) | 1)
+
+#define MT7623_PIN_96_MIPI_TCP_FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
+#define MT7623_PIN_96_MIPI_TCP_FUNC_TCP (MTK_PIN_NO(96) | 1)
+
+#define MT7623_PIN_97_MIPI_TDN1_FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
+#define MT7623_PIN_97_MIPI_TDN1_FUNC_TDN1 (MTK_PIN_NO(97) | 1)
+
+#define MT7623_PIN_98_MIPI_TDP1_FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
+#define MT7623_PIN_98_MIPI_TDP1_FUNC_TDP1 (MTK_PIN_NO(98) | 1)
+
+#define MT7623_PIN_99_MIPI_TDN0_FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
+#define MT7623_PIN_99_MIPI_TDN0_FUNC_TDN0 (MTK_PIN_NO(99) | 1)
+
+#define MT7623_PIN_100_MIPI_TDP0_FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
+#define MT7623_PIN_100_MIPI_TDP0_FUNC_TDP0 (MTK_PIN_NO(100) | 1)
+
+#define MT7623_PIN_105_MSDC1_CMD_FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
+#define MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD (MTK_PIN_NO(105) | 1)
+#define MT7623_PIN_105_MSDC1_CMD_FUNC_SDA1 (MTK_PIN_NO(105) | 3)
+#define MT7623_PIN_105_MSDC1_CMD_FUNC_I2SOUT_BCK (MTK_PIN_NO(105) | 6)
+
+#define MT7623_PIN_106_MSDC1_CLK_FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
+#define MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK (MTK_PIN_NO(106) | 1)
+#define MT7623_PIN_106_MSDC1_CLK_FUNC_SCL1 (MTK_PIN_NO(106) | 3)
+#define MT7623_PIN_106_MSDC1_CLK_FUNC_I2SOUT_LRCK (MTK_PIN_NO(106) | 6)
+
+#define MT7623_PIN_107_MSDC1_DAT0_FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
+#define MT7623_PIN_107_MSDC1_DAT0_FUNC_MSDC1_DAT0 (MTK_PIN_NO(107) | 1)
+#define MT7623_PIN_107_MSDC1_DAT0_FUNC_UTXD0 (MTK_PIN_NO(107) | 5)
+#define MT7623_PIN_107_MSDC1_DAT0_FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(107) | 6)
+
+#define MT7623_PIN_108_MSDC1_DAT1_FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
+#define MT7623_PIN_108_MSDC1_DAT1_FUNC_MSDC1_DAT1 (MTK_PIN_NO(108) | 1)
+#define MT7623_PIN_108_MSDC1_DAT1_FUNC_PWM0 (MTK_PIN_NO(108) | 3)
+#define MT7623_PIN_108_MSDC1_DAT1_FUNC_URXD0 (MTK_PIN_NO(108) | 5)
+#define MT7623_PIN_108_MSDC1_DAT1_FUNC_PWM1 (MTK_PIN_NO(108) | 6)
+
+#define MT7623_PIN_109_MSDC1_DAT2_FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
+#define MT7623_PIN_109_MSDC1_DAT2_FUNC_MSDC1_DAT2 (MTK_PIN_NO(109) | 1)
+#define MT7623_PIN_109_MSDC1_DAT2_FUNC_SDA2 (MTK_PIN_NO(109) | 3)
+#define MT7623_PIN_109_MSDC1_DAT2_FUNC_UTXD1 (MTK_PIN_NO(109) | 5)
+#define MT7623_PIN_109_MSDC1_DAT2_FUNC_PWM2 (MTK_PIN_NO(109) | 6)
+
+#define MT7623_PIN_110_MSDC1_DAT3_FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
+#define MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3 (MTK_PIN_NO(110) | 1)
+#define MT7623_PIN_110_MSDC1_DAT3_FUNC_SCL2 (MTK_PIN_NO(110) | 3)
+#define MT7623_PIN_110_MSDC1_DAT3_FUNC_URXD1 (MTK_PIN_NO(110) | 5)
+#define MT7623_PIN_110_MSDC1_DAT3_FUNC_PWM3 (MTK_PIN_NO(110) | 6)
+
+#define MT7623_PIN_111_MSDC0_DAT7_FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
+#define MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7 (MTK_PIN_NO(111) | 1)
+#define MT7623_PIN_111_MSDC0_DAT7_FUNC_NLD7 (MTK_PIN_NO(111) | 4)
+
+#define MT7623_PIN_112_MSDC0_DAT6_FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
+#define MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6 (MTK_PIN_NO(112) | 1)
+#define MT7623_PIN_112_MSDC0_DAT6_FUNC_NLD6 (MTK_PIN_NO(112) | 4)
+
+#define MT7623_PIN_113_MSDC0_DAT5_FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
+#define MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5 (MTK_PIN_NO(113) | 1)
+#define MT7623_PIN_113_MSDC0_DAT5_FUNC_NLD5 (MTK_PIN_NO(113) | 4)
+
+#define MT7623_PIN_114_MSDC0_DAT4_FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
+#define MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4 (MTK_PIN_NO(114) | 1)
+#define MT7623_PIN_114_MSDC0_DAT4_FUNC_NLD4 (MTK_PIN_NO(114) | 4)
+
+#define MT7623_PIN_115_MSDC0_RSTB_FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
+#define MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB (MTK_PIN_NO(115) | 1)
+#define MT7623_PIN_115_MSDC0_RSTB_FUNC_NLD8 (MTK_PIN_NO(115) | 4)
+
+#define MT7623_PIN_116_MSDC0_CMD_FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
+#define MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD (MTK_PIN_NO(116) | 1)
+#define MT7623_PIN_116_MSDC0_CMD_FUNC_NALE (MTK_PIN_NO(116) | 4)
+
+#define MT7623_PIN_117_MSDC0_CLK_FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
+#define MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK (MTK_PIN_NO(117) | 1)
+#define MT7623_PIN_117_MSDC0_CLK_FUNC_NWEB (MTK_PIN_NO(117) | 4)
+
+#define MT7623_PIN_118_MSDC0_DAT3_FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
+#define MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3 (MTK_PIN_NO(118) | 1)
+#define MT7623_PIN_118_MSDC0_DAT3_FUNC_NLD3 (MTK_PIN_NO(118) | 4)
+
+#define MT7623_PIN_119_MSDC0_DAT2_FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
+#define MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2 (MTK_PIN_NO(119) | 1)
+#define MT7623_PIN_119_MSDC0_DAT2_FUNC_NLD2 (MTK_PIN_NO(119) | 4)
+
+#define MT7623_PIN_120_MSDC0_DAT1_FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
+#define MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1 (MTK_PIN_NO(120) | 1)
+#define MT7623_PIN_120_MSDC0_DAT1_FUNC_NLD1 (MTK_PIN_NO(120) | 4)
+
+#define MT7623_PIN_121_MSDC0_DAT0_FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
+#define MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0 (MTK_PIN_NO(121) | 1)
+#define MT7623_PIN_121_MSDC0_DAT0_FUNC_NLD0 (MTK_PIN_NO(121) | 4)
+#define MT7623_PIN_121_MSDC0_DAT0_FUNC_WATCHDOG (MTK_PIN_NO(121) | 5)
+
+#define MT7623_PIN_122_GPIO122_FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
+#define MT7623_PIN_122_GPIO122_FUNC_TEST (MTK_PIN_NO(122) | 1)
+#define MT7623_PIN_122_GPIO122_FUNC_SDA2 (MTK_PIN_NO(122) | 4)
+#define MT7623_PIN_122_GPIO122_FUNC_URXD0 (MTK_PIN_NO(122) | 5)
+
+#define MT7623_PIN_123_GPIO123_FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+#define MT7623_PIN_123_GPIO123_FUNC_TEST (MTK_PIN_NO(123) | 1)
+#define MT7623_PIN_123_GPIO123_FUNC_SCL2 (MTK_PIN_NO(123) | 4)
+#define MT7623_PIN_123_GPIO123_FUNC_UTXD0 (MTK_PIN_NO(123) | 5)
+
+#define MT7623_PIN_124_GPIO124_FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+#define MT7623_PIN_124_GPIO124_FUNC_TEST (MTK_PIN_NO(124) | 1)
+#define MT7623_PIN_124_GPIO124_FUNC_SDA1 (MTK_PIN_NO(124) | 4)
+#define MT7623_PIN_124_GPIO124_FUNC_PWM3 (MTK_PIN_NO(124) | 5)
+
+#define MT7623_PIN_125_GPIO125_FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
+#define MT7623_PIN_125_GPIO125_FUNC_TEST (MTK_PIN_NO(125) | 1)
+#define MT7623_PIN_125_GPIO125_FUNC_SCL1 (MTK_PIN_NO(125) | 4)
+#define MT7623_PIN_125_GPIO125_FUNC_PWM4 (MTK_PIN_NO(125) | 5)
+
+#define MT7623_PIN_126_I2S0_MCLK_FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
+#define MT7623_PIN_126_I2S0_MCLK_FUNC_I2S0_MCLK (MTK_PIN_NO(126) | 1)
+#define MT7623_PIN_126_I2S0_MCLK_FUNC_AP_I2S_MCLK (MTK_PIN_NO(126) | 6)
+
+#define MT7623_PIN_199_SPI1_CK_FUNC_GPIO199 (MTK_PIN_NO(199) | 0)
+#define MT7623_PIN_199_SPI1_CK_FUNC_SPI1_CK (MTK_PIN_NO(199) | 1)
+
+#define MT7623_PIN_200_URXD2_FUNC_GPIO200 (MTK_PIN_NO(200) | 0)
+#define MT7623_PIN_200_URXD2_FUNC_URXD2 (MTK_PIN_NO(200) | 6)
+
+#define MT7623_PIN_201_UTXD2_FUNC_GPIO201 (MTK_PIN_NO(201) | 0)
+#define MT7623_PIN_201_UTXD2_FUNC_UTXD2 (MTK_PIN_NO(201) | 6)
+
+#define MT7623_PIN_203_PWM0_FUNC_GPIO203 (MTK_PIN_NO(203) | 0)
+#define MT7623_PIN_203_PWM0_FUNC_PWM0 (MTK_PIN_NO(203) | 1)
+#define MT7623_PIN_203_PWM0_FUNC_DISP_PWM (MTK_PIN_NO(203) | 2)
+
+#define MT7623_PIN_204_PWM1_FUNC_GPIO204 (MTK_PIN_NO(204) | 0)
+#define MT7623_PIN_204_PWM1_FUNC_PWM1 (MTK_PIN_NO(204) | 1)
+
+#define MT7623_PIN_205_PWM2_FUNC_GPIO205 (MTK_PIN_NO(205) | 0)
+#define MT7623_PIN_205_PWM2_FUNC_PWM2 (MTK_PIN_NO(205) | 1)
+
+#define MT7623_PIN_206_PWM3_FUNC_GPIO206 (MTK_PIN_NO(206) | 0)
+#define MT7623_PIN_206_PWM3_FUNC_PWM3 (MTK_PIN_NO(206) | 1)
+
+#define MT7623_PIN_207_PWM4_FUNC_GPIO207 (MTK_PIN_NO(207) | 0)
+#define MT7623_PIN_207_PWM4_FUNC_PWM4 (MTK_PIN_NO(207) | 1)
+
+#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_GPIO208 (MTK_PIN_NO(208) | 0)
+#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_AUD_EXT_CK1 (MTK_PIN_NO(208) | 1)
+#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_PWM0 (MTK_PIN_NO(208) | 2)
+#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_PCIE0_PERST_N (MTK_PIN_NO(208) | 3)
+#define MT7623_PIN_208_AUD_EXT_CK1_FUNC_DISP_PWM (MTK_PIN_NO(208) | 5)
+
+#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_GPIO209 (MTK_PIN_NO(209) | 0)
+#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_AUD_EXT_CK2 (MTK_PIN_NO(209) | 1)
+#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_MSDC1_WP (MTK_PIN_NO(209) | 2)
+#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_PCIE1_PERST_N (MTK_PIN_NO(209) | 3)
+#define MT7623_PIN_209_AUD_EXT_CK2_FUNC_PWM1 (MTK_PIN_NO(209) | 5)
+
+#define MT7623_PIN_236_EXT_SDIO3_FUNC_GPIO236 (MTK_PIN_NO(236) | 0)
+#define MT7623_PIN_236_EXT_SDIO3_FUNC_EXT_SDIO3 (MTK_PIN_NO(236) | 1)
+#define MT7623_PIN_236_EXT_SDIO3_FUNC_IDDIG (MTK_PIN_NO(236) | 2)
+
+#define MT7623_PIN_237_EXT_SDIO2_FUNC_GPIO237 (MTK_PIN_NO(237) | 0)
+#define MT7623_PIN_237_EXT_SDIO2_FUNC_EXT_SDIO2 (MTK_PIN_NO(237) | 1)
+#define MT7623_PIN_237_EXT_SDIO2_FUNC_DRV_VBUS (MTK_PIN_NO(237) | 2)
+
+#define MT7623_PIN_238_EXT_SDIO1_FUNC_GPIO238 (MTK_PIN_NO(238) | 0)
+#define MT7623_PIN_238_EXT_SDIO1_FUNC_EXT_SDIO1 (MTK_PIN_NO(238) | 1)
+
+#define MT7623_PIN_239_EXT_SDIO0_FUNC_GPIO239 (MTK_PIN_NO(239) | 0)
+#define MT7623_PIN_239_EXT_SDIO0_FUNC_EXT_SDIO0 (MTK_PIN_NO(239) | 1)
+
+#define MT7623_PIN_240_EXT_XCS_FUNC_GPIO240 (MTK_PIN_NO(240) | 0)
+#define MT7623_PIN_240_EXT_XCS_FUNC_EXT_XCS (MTK_PIN_NO(240) | 1)
+
+#define MT7623_PIN_241_EXT_SCK_FUNC_GPIO241 (MTK_PIN_NO(241) | 0)
+#define MT7623_PIN_241_EXT_SCK_FUNC_EXT_SCK (MTK_PIN_NO(241) | 1)
+
+#define MT7623_PIN_242_URTS2_FUNC_GPIO242 (MTK_PIN_NO(242) | 0)
+#define MT7623_PIN_242_URTS2_FUNC_URTS2 (MTK_PIN_NO(242) | 1)
+#define MT7623_PIN_242_URTS2_FUNC_UTXD3 (MTK_PIN_NO(242) | 2)
+#define MT7623_PIN_242_URTS2_FUNC_URXD3 (MTK_PIN_NO(242) | 3)
+#define MT7623_PIN_242_URTS2_FUNC_SCL1 (MTK_PIN_NO(242) | 4)
+
+#define MT7623_PIN_243_UCTS2_FUNC_GPIO243 (MTK_PIN_NO(243) | 0)
+#define MT7623_PIN_243_UCTS2_FUNC_UCTS2 (MTK_PIN_NO(243) | 1)
+#define MT7623_PIN_243_UCTS2_FUNC_URXD3 (MTK_PIN_NO(243) | 2)
+#define MT7623_PIN_243_UCTS2_FUNC_UTXD3 (MTK_PIN_NO(243) | 3)
+#define MT7623_PIN_243_UCTS2_FUNC_SDA1 (MTK_PIN_NO(243) | 4)
+
+#define MT7623_PIN_250_GPIO250_FUNC_GPIO250 (MTK_PIN_NO(250) | 0)
+#define MT7623_PIN_250_GPIO250_FUNC_TEST_MD7 (MTK_PIN_NO(250) | 1)
+#define MT7623_PIN_250_GPIO250_FUNC_PCIE0_CLKREQ_N (MTK_PIN_NO(250) | 6)
+
+#define MT7623_PIN_251_GPIO251_FUNC_GPIO251 (MTK_PIN_NO(251) | 0)
+#define MT7623_PIN_251_GPIO251_FUNC_TEST_MD6 (MTK_PIN_NO(251) | 1)
+#define MT7623_PIN_251_GPIO251_FUNC_PCIE0_WAKE_N (MTK_PIN_NO(251) | 6)
+
+#define MT7623_PIN_252_GPIO252_FUNC_GPIO252 (MTK_PIN_NO(252) | 0)
+#define MT7623_PIN_252_GPIO252_FUNC_TEST_MD5 (MTK_PIN_NO(252) | 1)
+#define MT7623_PIN_252_GPIO252_FUNC_PCIE1_CLKREQ_N (MTK_PIN_NO(252) | 6)
+
+#define MT7623_PIN_253_GPIO253_FUNC_GPIO253 (MTK_PIN_NO(253) | 0)
+#define MT7623_PIN_253_GPIO253_FUNC_TEST_MD4 (MTK_PIN_NO(253) | 1)
+#define MT7623_PIN_253_GPIO253_FUNC_PCIE1_WAKE_N (MTK_PIN_NO(253) | 6)
+
+#define MT7623_PIN_254_GPIO254_FUNC_GPIO254 (MTK_PIN_NO(254) | 0)
+#define MT7623_PIN_254_GPIO254_FUNC_TEST_MD3 (MTK_PIN_NO(254) | 1)
+#define MT7623_PIN_254_GPIO254_FUNC_PCIE2_CLKREQ_N (MTK_PIN_NO(254) | 6)
+
+#define MT7623_PIN_255_GPIO255_FUNC_GPIO255 (MTK_PIN_NO(255) | 0)
+#define MT7623_PIN_255_GPIO255_FUNC_TEST_MD2 (MTK_PIN_NO(255) | 1)
+#define MT7623_PIN_255_GPIO255_FUNC_PCIE2_WAKE_N (MTK_PIN_NO(255) | 6)
+
+#define MT7623_PIN_256_GPIO256_FUNC_GPIO256 (MTK_PIN_NO(256) | 0)
+#define MT7623_PIN_256_GPIO256_FUNC_TEST_MD1 (MTK_PIN_NO(256) | 1)
+
+#define MT7623_PIN_257_GPIO257_FUNC_GPIO257 (MTK_PIN_NO(257) | 0)
+#define MT7623_PIN_257_GPIO257_FUNC_TEST_MD0 (MTK_PIN_NO(257) | 1)
+
+#define MT7623_PIN_261_MSDC1_INS_FUNC_GPIO261 (MTK_PIN_NO(261) | 0)
+#define MT7623_PIN_261_MSDC1_INS_FUNC_MSDC1_INS (MTK_PIN_NO(261) | 1)
+
+#define MT7623_PIN_262_G2_TXEN_FUNC_GPIO262 (MTK_PIN_NO(262) | 0)
+#define MT7623_PIN_262_G2_TXEN_FUNC_G2_TXEN (MTK_PIN_NO(262) | 1)
+
+#define MT7623_PIN_263_G2_TXD3_FUNC_GPIO263 (MTK_PIN_NO(263) | 0)
+#define MT7623_PIN_263_G2_TXD3_FUNC_G2_TXD3 (MTK_PIN_NO(263) | 1)
+
+#define MT7623_PIN_264_G2_TXD2_FUNC_GPIO264 (MTK_PIN_NO(264) | 0)
+#define MT7623_PIN_264_G2_TXD2_FUNC_G2_TXD2 (MTK_PIN_NO(264) | 1)
+
+#define MT7623_PIN_265_G2_TXD1_FUNC_GPIO265 (MTK_PIN_NO(265) | 0)
+#define MT7623_PIN_265_G2_TXD1_FUNC_G2_TXD1 (MTK_PIN_NO(265) | 1)
+
+#define MT7623_PIN_266_G2_TXD0_FUNC_GPIO266 (MTK_PIN_NO(266) | 0)
+#define MT7623_PIN_266_G2_TXD0_FUNC_G2_TXD0 (MTK_PIN_NO(266) | 1)
+
+#define MT7623_PIN_267_G2_TXCLK_FUNC_GPIO267 (MTK_PIN_NO(267) | 0)
+#define MT7623_PIN_267_G2_TXCLK_FUNC_G2_TXC (MTK_PIN_NO(267) | 1)
+
+#define MT7623_PIN_268_G2_RXCLK_FUNC_GPIO268 (MTK_PIN_NO(268) | 0)
+#define MT7623_PIN_268_G2_RXCLK_FUNC_G2_RXC (MTK_PIN_NO(268) | 1)
+
+#define MT7623_PIN_269_G2_RXD0_FUNC_GPIO269 (MTK_PIN_NO(269) | 0)
+#define MT7623_PIN_269_G2_RXD0_FUNC_G2_RXD0 (MTK_PIN_NO(269) | 1)
+
+#define MT7623_PIN_270_G2_RXD1_FUNC_GPIO270 (MTK_PIN_NO(270) | 0)
+#define MT7623_PIN_270_G2_RXD1_FUNC_G2_RXD1 (MTK_PIN_NO(270) | 1)
+
+#define MT7623_PIN_271_G2_RXD2_FUNC_GPIO271 (MTK_PIN_NO(271) | 0)
+#define MT7623_PIN_271_G2_RXD2_FUNC_G2_RXD2 (MTK_PIN_NO(271) | 1)
+
+#define MT7623_PIN_272_G2_RXD3_FUNC_GPIO272 (MTK_PIN_NO(272) | 0)
+#define MT7623_PIN_272_G2_RXD3_FUNC_G2_RXD3 (MTK_PIN_NO(272) | 1)
+
+#define MT7623_PIN_274_G2_RXDV_FUNC_GPIO274 (MTK_PIN_NO(274) | 0)
+#define MT7623_PIN_274_G2_RXDV_FUNC_G2_RXDV (MTK_PIN_NO(274) | 1)
+
+#define MT7623_PIN_275_G2_MDC_FUNC_GPIO275 (MTK_PIN_NO(275) | 0)
+#define MT7623_PIN_275_G2_MDC_FUNC_MDC (MTK_PIN_NO(275) | 1)
+
+#define MT7623_PIN_276_G2_MDIO_FUNC_GPIO276 (MTK_PIN_NO(276) | 0)
+#define MT7623_PIN_276_G2_MDIO_FUNC_MDIO (MTK_PIN_NO(276) | 1)
+
+#define MT7623_PIN_278_JTAG_RESET_FUNC_GPIO278 (MTK_PIN_NO(278) | 0)
+#define MT7623_PIN_278_JTAG_RESET_FUNC_JTAG_RESET (MTK_PIN_NO(278) | 1)
+
+#endif /* __DTS_MT7623_PINFUNC_H */
index 1800227af9d61fa31fb525a0d3f7408f2c9ab43e..b651aed9dc6b9084ed2dcae8832a033217d4dca4 100644 (file)
@@ -55,6 +55,9 @@ struct arch_timer_cpu {
 
        /* VGIC mapping */
        struct irq_phys_map             *map;
+
+       /* Active IRQ state caching */
+       bool                            active_cleared_last;
 };
 
 int kvm_timer_hyp_init(void);
@@ -74,4 +77,6 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu);
 void kvm_timer_schedule(struct kvm_vcpu *vcpu);
 void kvm_timer_unschedule(struct kvm_vcpu *vcpu);
 
+void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu);
+
 #endif
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
new file mode 100644 (file)
index 0000000..fe389ac
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd.
+ * Author: Shannon Zhao <shannon.zhao@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_ARM_KVM_PMU_H
+#define __ASM_ARM_KVM_PMU_H
+
+#ifdef CONFIG_KVM_ARM_PMU
+
+#include <linux/perf_event.h>
+#include <asm/perf_event.h>
+
+#define ARMV8_PMU_CYCLE_IDX            (ARMV8_PMU_MAX_COUNTERS - 1)
+
+struct kvm_pmc {
+       u8 idx; /* index into the pmu->pmc array */
+       struct perf_event *perf_event;
+       u64 bitmask;
+};
+
+struct kvm_pmu {
+       int irq_num;
+       struct kvm_pmc pmc[ARMV8_PMU_MAX_COUNTERS];
+       bool ready;
+       bool irq_level;
+};
+
+#define kvm_arm_pmu_v3_ready(v)                ((v)->arch.pmu.ready)
+#define kvm_arm_pmu_irq_initialized(v) ((v)->arch.pmu.irq_num >= VGIC_NR_SGIS)
+u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx);
+void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val);
+u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu);
+void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu);
+void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu);
+void kvm_pmu_disable_counter(struct kvm_vcpu *vcpu, u64 val);
+void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val);
+void kvm_pmu_overflow_set(struct kvm_vcpu *vcpu, u64 val);
+void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu);
+void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu);
+void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val);
+void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val);
+void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
+                                   u64 select_idx);
+bool kvm_arm_support_pmu_v3(void);
+int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu,
+                           struct kvm_device_attr *attr);
+int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu,
+                           struct kvm_device_attr *attr);
+int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu,
+                           struct kvm_device_attr *attr);
+#else
+struct kvm_pmu {
+};
+
+#define kvm_arm_pmu_v3_ready(v)                (false)
+#define kvm_arm_pmu_irq_initialized(v) (false)
+static inline u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu,
+                                           u64 select_idx)
+{
+       return 0;
+}
+static inline void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu,
+                                            u64 select_idx, u64 val) {}
+static inline u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
+{
+       return 0;
+}
+static inline void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu) {}
+static inline void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu) {}
+static inline void kvm_pmu_disable_counter(struct kvm_vcpu *vcpu, u64 val) {}
+static inline void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val) {}
+static inline void kvm_pmu_overflow_set(struct kvm_vcpu *vcpu, u64 val) {}
+static inline void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu) {}
+static inline void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu) {}
+static inline void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val) {}
+static inline void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) {}
+static inline void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu,
+                                                 u64 data, u64 select_idx) {}
+static inline bool kvm_arm_support_pmu_v3(void) { return false; }
+static inline int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu,
+                                         struct kvm_device_attr *attr)
+{
+       return -ENXIO;
+}
+static inline int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu,
+                                         struct kvm_device_attr *attr)
+{
+       return -ENXIO;
+}
+static inline int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu,
+                                         struct kvm_device_attr *attr)
+{
+       return -ENXIO;
+}
+#endif
+
+#endif
index 13a3d537811b9f7d12b3fa892b8312330f89d70f..281caf847fad89ba48b9cf8cfb5c402e07a3afbb 100644 (file)
@@ -279,12 +279,6 @@ struct vgic_v2_cpu_if {
        u32             vgic_lr[VGIC_V2_MAX_LRS];
 };
 
-/*
- * LRs are stored in reverse order in memory. make sure we index them
- * correctly.
- */
-#define VGIC_V3_LR_INDEX(lr)           (VGIC_V3_MAX_LRS - 1 - lr)
-
 struct vgic_v3_cpu_if {
 #ifdef CONFIG_KVM_ARM_VGIC_V3
        u32             vgic_hcr;
@@ -321,6 +315,8 @@ struct vgic_cpu {
 
        /* Protected by the distributor's irq_phys_map_lock */
        struct list_head        irq_phys_map_list;
+
+       u64             live_lrs;
 };
 
 #define LR_EMPTY       0xff
index d2992bfa17063a052a08a106b9105284ce4bfa4a..c1a2f345cbe6146352fff77080019eba5d0fe76e 100644 (file)
@@ -487,8 +487,8 @@ enum ata_tf_protocols {
 };
 
 enum ata_ioctls {
-       ATA_IOC_GET_IO32        = 0x309,
-       ATA_IOC_SET_IO32        = 0x324,
+       ATA_IOC_GET_IO32        = 0x309, /* HDIO_GET_32BIT */
+       ATA_IOC_SET_IO32        = 0x324, /* HDIO_SET_32BIT */
 };
 
 /* core structures */
index 301de78d65f75c194720cc5168359dbce6eab59f..6c502cb13c95aa2f93466687c16d23b950b231d6 100644 (file)
@@ -548,6 +548,27 @@ static inline int atomic_dec_if_positive(atomic_t *v)
 }
 #endif
 
+/**
+ * fetch_or - perform *ptr |= mask and return old value of *ptr
+ * @ptr: pointer to value
+ * @mask: mask to OR on the value
+ *
+ * cmpxchg based fetch_or, macro so it works for different integer types
+ */
+#ifndef fetch_or
+#define fetch_or(ptr, mask)                                            \
+({     typeof(*(ptr)) __old, __val = *(ptr);                           \
+       for (;;) {                                                      \
+               __old = cmpxchg((ptr), __val, __val | (mask));          \
+               if (__old == __val)                                     \
+                       break;                                          \
+               __val = __old;                                          \
+       }                                                               \
+       __old;                                                          \
+})
+#endif
+
+
 #ifdef CONFIG_GENERIC_ATOMIC64
 #include <asm-generic/atomic64.h>
 #endif
index 850f39b33e743f927acf0d2ca9777971c873e345..7caaf298f5399c90616838ccaf1f904066cb29e4 100644 (file)
 #define _LINUX_AUTO_DEV_IOCTL_H
 
 #include <linux/auto_fs.h>
-
-#ifdef __KERNEL__
 #include <linux/string.h>
-#else
-#include <string.h>
-#endif /* __KERNEL__ */
 
 #define AUTOFS_DEVICE_NAME             "autofs"
 
@@ -125,7 +120,6 @@ static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in)
        in->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;
        in->size = sizeof(struct autofs_dev_ioctl);
        in->ioctlfd = -1;
-       return;
 }
 
 /*
index fcd704d354c4c345d0c91aa4ebcb2f811b3851fa..b4066bb890836c88be9b41f30de83f3d809114db 100644 (file)
@@ -1,14 +1,10 @@
-/* -*- linux-c -*- ------------------------------------------------------- *
- *   
- * linux/include/linux/auto_fs.h
- *
- *   Copyright 1997 Transmeta Corporation - All Rights Reserved
+/*
+ * Copyright 1997 Transmeta Corporation - All Rights Reserved
  *
  * This file is part of the Linux kernel and is made available under
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
+ */
 
 #ifndef _LINUX_AUTO_FS_H
 #define _LINUX_AUTO_FS_H
index 5349e6816cbb075e2b5d6ac57cac1e8fee373438..88bc64f00bb53cb01fe60ca87dfafd7c9c0f0f4a 100644 (file)
@@ -310,6 +310,38 @@ static inline void bio_clear_flag(struct bio *bio, unsigned int bit)
        bio->bi_flags &= ~(1U << bit);
 }
 
+static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv)
+{
+       *bv = bio_iovec(bio);
+}
+
+static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv)
+{
+       struct bvec_iter iter = bio->bi_iter;
+       int idx;
+
+       if (unlikely(!bio_multiple_segments(bio))) {
+               *bv = bio_iovec(bio);
+               return;
+       }
+
+       bio_advance_iter(bio, &iter, iter.bi_size);
+
+       if (!iter.bi_bvec_done)
+               idx = iter.bi_idx - 1;
+       else    /* in the middle of bvec */
+               idx = iter.bi_idx;
+
+       *bv = bio->bi_io_vec[idx];
+
+       /*
+        * iter.bi_bvec_done records actual length of the last bvec
+        * if this bio ends in the middle of one io vector
+        */
+       if (iter.bi_bvec_done)
+               bv->bv_len = iter.bi_bvec_done;
+}
+
 enum bip_flags {
        BIP_BLOCK_INTEGRITY     = 1 << 0, /* block layer owns integrity data */
        BIP_MAPPED_INTEGRITY    = 1 << 1, /* ref tag has been remapped */
index 4571ef1a12a968ea62a78b87371c83a07e89d8e9..413c84fbc4edafc582c765630ccb3f3117dbc1fc 100644 (file)
@@ -895,7 +895,7 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq)
 {
        struct request_queue *q = rq->q;
 
-       if (unlikely(rq->cmd_type == REQ_TYPE_BLOCK_PC))
+       if (unlikely(rq->cmd_type != REQ_TYPE_FS))
                return q->limits.max_hw_sectors;
 
        if (!q->limits.chunk_sectors || (rq->cmd_flags & REQ_DISCARD))
@@ -1372,6 +1372,13 @@ static inline void put_dev_sector(Sector p)
        page_cache_release(p.v);
 }
 
+static inline bool __bvec_gap_to_prev(struct request_queue *q,
+                               struct bio_vec *bprv, unsigned int offset)
+{
+       return offset ||
+               ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
+}
+
 /*
  * Check if adding a bio_vec after bprv with offset would create a gap in
  * the SG list. Most drivers don't care about this, but some do.
@@ -1381,18 +1388,22 @@ static inline bool bvec_gap_to_prev(struct request_queue *q,
 {
        if (!queue_virt_boundary(q))
                return false;
-       return offset ||
-               ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
+       return __bvec_gap_to_prev(q, bprv, offset);
 }
 
 static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
                         struct bio *next)
 {
-       if (!bio_has_data(prev))
-               return false;
+       if (bio_has_data(prev) && queue_virt_boundary(q)) {
+               struct bio_vec pb, nb;
+
+               bio_get_last_bvec(prev, &pb);
+               bio_get_first_bvec(next, &nb);
 
-       return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1],
-                               next->bi_io_vec[0].bv_offset);
+               return __bvec_gap_to_prev(q, &pb, nb.bv_offset);
+       }
+
+       return false;
 }
 
 static inline bool req_gap_back_merge(struct request *req, struct bio *bio)
index 17e7e82d2aa758f9888419a9c03aa4059e16b247..1be04f8c563a0c60bdfca72a36c120ec96ef327c 100644 (file)
 #define SMP_CACHE_BYTES L1_CACHE_BYTES
 #endif
 
+/*
+ * __read_mostly is used to keep rarely changing variables out of frequently
+ * updated cachelines. If an architecture doesn't support it, ignore the
+ * hint.
+ */
 #ifndef __read_mostly
 #define __read_mostly
 #endif
 
+/*
+ * __ro_after_init is used to mark things that are read-only after init (i.e.
+ * after mark_rodata_ro() has been called). These are effectively read-only,
+ * but may get written to during init, so can't live in .rodata (via "const").
+ */
+#ifndef __ro_after_init
+#define __ro_after_init __attribute__((__section__(".data..ro_after_init")))
+#endif
+
 #ifndef ____cacheline_aligned
 #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
 #endif
index c1ef6f14e7be7f1317e34a0deac61fcb80511eef..15151f3c41202c6b6229475affb654ae0bab272d 100644 (file)
@@ -75,6 +75,7 @@
 #define CEPH_FEATURE_CRUSH_TUNABLES5   (1ULL<<58) /* chooseleaf stable mode */
 // duplicated since it was introduced at the same time as CEPH_FEATURE_CRUSH_TUNABLES5
 #define CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING   (1ULL<<58) /* New, v7 encoding */
+#define CEPH_FEATURE_FS_FILE_LAYOUT_V2       (1ULL<<58) /* file_layout_t */
 
 /*
  * The introduction of CEPH_FEATURE_OSD_SNAPMAPPER caused the feature
index bdcf358dfce2a9d0f5420d9fbde6066b1e2dc73b..0d442e34c34979a503030214007223742b3bc822 100644 (file)
@@ -190,9 +190,9 @@ extern void clockevents_config_and_register(struct clock_event_device *dev,
 extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq);
 
 static inline void
-clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
+clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 maxsec)
 {
-       return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC, freq, minsec);
+       return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC, freq, maxsec);
 }
 
 extern void clockevents_suspend(void);
index 6013021a3b39467ffd8a2fa3d10064fe561ae2e7..a307bf62974fd34d9115d04f663bc9fa3caa0d9d 100644 (file)
@@ -118,6 +118,23 @@ struct clocksource {
 /* simplify initialization of mask field */
 #define CLOCKSOURCE_MASK(bits) (cycle_t)((bits) < 64 ? ((1ULL<<(bits))-1) : -1)
 
+static inline u32 clocksource_freq2mult(u32 freq, u32 shift_constant, u64 from)
+{
+       /*  freq = cyc/from
+        *  mult/2^shift  = ns/cyc
+        *  mult = ns/cyc * 2^shift
+        *  mult = from/freq * 2^shift
+        *  mult = from * 2^shift / freq
+        *  mult = (from<<shift) / freq
+        */
+       u64 tmp = ((u64)from) << shift_constant;
+
+       tmp += freq/2; /* round for do_div */
+       do_div(tmp, freq);
+
+       return (u32)tmp;
+}
+
 /**
  * clocksource_khz2mult - calculates mult from khz and shift
  * @khz:               Clocksource frequency in KHz
@@ -128,19 +145,7 @@ struct clocksource {
  */
 static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant)
 {
-       /*  khz = cyc/(Million ns)
-        *  mult/2^shift  = ns/cyc
-        *  mult = ns/cyc * 2^shift
-        *  mult = 1Million/khz * 2^shift
-        *  mult = 1000000 * 2^shift / khz
-        *  mult = (1000000<<shift) / khz
-        */
-       u64 tmp = ((u64)1000000) << shift_constant;
-
-       tmp += khz/2; /* round for do_div */
-       do_div(tmp, khz);
-
-       return (u32)tmp;
+       return clocksource_freq2mult(khz, shift_constant, NSEC_PER_MSEC);
 }
 
 /**
@@ -154,19 +159,7 @@ static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant)
  */
 static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
 {
-       /*  hz = cyc/(Billion ns)
-        *  mult/2^shift  = ns/cyc
-        *  mult = ns/cyc * 2^shift
-        *  mult = 1Billion/hz * 2^shift
-        *  mult = 1000000000 * 2^shift / hz
-        *  mult = (1000000000<<shift) / hz
-        */
-       u64 tmp = ((u64)1000000000) << shift_constant;
-
-       tmp += hz/2; /* round for do_div */
-       do_div(tmp, hz);
-
-       return (u32)tmp;
+       return clocksource_freq2mult(hz, shift_constant, NSEC_PER_SEC);
 }
 
 /**
index 48f5aab117ae12625d041cd18555031e87c178fc..b5ff9881bef8f9696e921fb8731e1ff0ff072a94 100644 (file)
 # define __pmem                __attribute__((noderef, address_space(5)))
 #ifdef CONFIG_SPARSE_RCU_POINTER
 # define __rcu         __attribute__((noderef, address_space(4)))
-#else
+#else /* CONFIG_SPARSE_RCU_POINTER */
 # define __rcu
-#endif
+#endif /* CONFIG_SPARSE_RCU_POINTER */
+# define __private     __attribute__((noderef))
 extern void __chk_user_ptr(const volatile void __user *);
 extern void __chk_io_ptr(const volatile void __iomem *);
-#else
+# define ACCESS_PRIVATE(p, member) (*((typeof((p)->member) __force *) &(p)->member))
+#else /* __CHECKER__ */
 # define __user
 # define __kernel
 # define __safe
@@ -44,7 +46,9 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 # define __percpu
 # define __rcu
 # define __pmem
-#endif
+# define __private
+# define ACCESS_PRIVATE(p, member) ((p)->member)
+#endif /* __CHECKER__ */
 
 /* Indirect macros required for expanded argument pasting, eg. __LINE__. */
 #define ___PASTE(a,b) a##b
@@ -263,8 +267,9 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
  * In contrast to ACCESS_ONCE these two macros will also work on aggregate
  * data types like structs or unions. If the size of the accessed data
  * type exceeds the word size of the machine (e.g., 32 bits or 64 bits)
- * READ_ONCE() and WRITE_ONCE()  will fall back to memcpy and print a
- * compile-time warning.
+ * READ_ONCE() and WRITE_ONCE() will fall back to memcpy(). There's at
+ * least two memcpy()s: one for the __builtin_memcpy() and then one for
+ * the macro doing the copy of variable - '__u' allocated on the stack.
  *
  * Their two major use cases are: (1) Mediating communication between
  * process-level code and irq/NMI handlers, all running on the same CPU,
index d2ca8c38f9c45c0b279ef329c7abf130fcd0dc61..f9b1fab4388a2052a3cf229eaf64d2249e8ecf8a 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/node.h>
 #include <linux/compiler.h>
 #include <linux/cpumask.h>
+#include <linux/cpuhotplug.h>
 
 struct device;
 struct device_node;
@@ -27,6 +28,9 @@ struct cpu {
        struct device dev;
 };
 
+extern void boot_cpu_init(void);
+extern void boot_cpu_state_init(void);
+
 extern int register_cpu(struct cpu *cpu, int num);
 extern struct device *get_cpu_device(unsigned cpu);
 extern bool cpu_is_hotpluggable(unsigned cpu);
@@ -74,7 +78,7 @@ enum {
        /* migration should happen before other stuff but after perf */
        CPU_PRI_PERF            = 20,
        CPU_PRI_MIGRATION       = 10,
-       CPU_PRI_SMPBOOT         = 9,
+
        /* bring up workqueues before normal notifiers and down after */
        CPU_PRI_WORKQUEUE_UP    = 5,
        CPU_PRI_WORKQUEUE_DOWN  = -5,
@@ -97,9 +101,7 @@ enum {
                                        * Called on the new cpu, just before
                                        * enabling interrupts. Must not sleep,
                                        * must not fail */
-#define CPU_DYING_IDLE         0x000B /* CPU (unsigned)v dying, reached
-                                       * idle loop. */
-#define CPU_BROKEN             0x000C /* CPU (unsigned)v did not die properly,
+#define CPU_BROKEN             0x000B /* CPU (unsigned)v did not die properly,
                                        * perhaps due to preemption. */
 
 /* Used for CPU hotplug events occurring while tasks are frozen due to a suspend
@@ -118,6 +120,7 @@ enum {
 
 
 #ifdef CONFIG_SMP
+extern bool cpuhp_tasks_frozen;
 /* Need to know about CPUs going up/down? */
 #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE)
 #define cpu_notifier(fn, pri) {                                        \
@@ -167,7 +170,6 @@ static inline void __unregister_cpu_notifier(struct notifier_block *nb)
 }
 #endif
 
-void smpboot_thread_init(void);
 int cpu_up(unsigned int cpu);
 void notify_cpu_starting(unsigned int cpu);
 extern void cpu_maps_update_begin(void);
@@ -177,6 +179,7 @@ extern void cpu_maps_update_done(void);
 #define cpu_notifier_register_done     cpu_maps_update_done
 
 #else  /* CONFIG_SMP */
+#define cpuhp_tasks_frozen     0
 
 #define cpu_notifier(fn, pri)  do { (void)(fn); } while (0)
 #define __cpu_notifier(fn, pri)        do { (void)(fn); } while (0)
@@ -215,10 +218,6 @@ static inline void cpu_notifier_register_done(void)
 {
 }
 
-static inline void smpboot_thread_init(void)
-{
-}
-
 #endif /* CONFIG_SMP */
 extern struct bus_type cpu_subsys;
 
@@ -265,11 +264,6 @@ static inline int disable_nonboot_cpus(void) { return 0; }
 static inline void enable_nonboot_cpus(void) {}
 #endif /* !CONFIG_PM_SLEEP_SMP */
 
-enum cpuhp_state {
-       CPUHP_OFFLINE,
-       CPUHP_ONLINE,
-};
-
 void cpu_startup_entry(enum cpuhp_state state);
 
 void cpu_idle_poll_ctrl(bool enable);
@@ -280,14 +274,15 @@ void arch_cpu_idle_enter(void);
 void arch_cpu_idle_exit(void);
 void arch_cpu_idle_dead(void);
 
-DECLARE_PER_CPU(bool, cpu_dead_idle);
-
 int cpu_report_state(int cpu);
 int cpu_check_up_prepare(int cpu);
 void cpu_set_state_online(int cpu);
 #ifdef CONFIG_HOTPLUG_CPU
 bool cpu_wait_death(unsigned int cpu, int seconds);
 bool cpu_report_death(void);
+void cpuhp_report_idle_dead(void);
+#else
+static inline void cpuhp_report_idle_dead(void) { }
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
 #endif /* _LINUX_CPU_H_ */
index 88a4215125bce6be0ac47ef1fda2948eead30c27..718e8725de8aa4d1d13004af368c8585e4f655a4 100644 (file)
@@ -80,7 +80,6 @@ struct cpufreq_policy {
        unsigned int            last_policy; /* policy before unplug */
        struct cpufreq_governor *governor; /* see below */
        void                    *governor_data;
-       bool                    governor_enabled; /* governor start/stop flag */
        char                    last_governor[CPUFREQ_NAME_LEN]; /* last governor used */
 
        struct work_struct      update; /* if update_policy() needs to be
@@ -100,10 +99,6 @@ struct cpufreq_policy {
         * - Any routine that will write to the policy structure and/or may take away
         *   the policy altogether (eg. CPU hotplug), will hold this lock in write
         *   mode before doing so.
-        *
-        * Additional rules:
-        * - Lock should not be held across
-        *     __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
         */
        struct rw_semaphore     rwsem;
 
@@ -464,29 +459,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
 int cpufreq_register_governor(struct cpufreq_governor *governor);
 void cpufreq_unregister_governor(struct cpufreq_governor *governor);
 
-/* CPUFREQ DEFAULT GOVERNOR */
-/*
- * Performance governor is fallback governor if any other gov failed to auto
- * load due latency restrictions
- */
-#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE
-extern struct cpufreq_governor cpufreq_gov_performance;
-#endif
-#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE
-#define CPUFREQ_DEFAULT_GOVERNOR       (&cpufreq_gov_performance)
-#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE)
-extern struct cpufreq_governor cpufreq_gov_powersave;
-#define CPUFREQ_DEFAULT_GOVERNOR       (&cpufreq_gov_powersave)
-#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE)
-extern struct cpufreq_governor cpufreq_gov_userspace;
-#define CPUFREQ_DEFAULT_GOVERNOR       (&cpufreq_gov_userspace)
-#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND)
-extern struct cpufreq_governor cpufreq_gov_ondemand;
-#define CPUFREQ_DEFAULT_GOVERNOR       (&cpufreq_gov_ondemand)
-#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE)
-extern struct cpufreq_governor cpufreq_gov_conservative;
-#define CPUFREQ_DEFAULT_GOVERNOR       (&cpufreq_gov_conservative)
-#endif
+struct cpufreq_governor *cpufreq_default_governor(void);
+struct cpufreq_governor *cpufreq_fallback_governor(void);
 
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
@@ -525,16 +499,6 @@ static inline void dev_pm_opp_free_cpufreq_table(struct device *dev,
 }
 #endif
 
-static inline bool cpufreq_next_valid(struct cpufreq_frequency_table **pos)
-{
-       while ((*pos)->frequency != CPUFREQ_TABLE_END)
-               if ((*pos)->frequency != CPUFREQ_ENTRY_INVALID)
-                       return true;
-               else
-                       (*pos)++;
-       return false;
-}
-
 /*
  * cpufreq_for_each_entry -    iterate over a cpufreq_frequency_table
  * @pos:       the cpufreq_frequency_table * to use as a loop cursor.
@@ -551,8 +515,11 @@ static inline bool cpufreq_next_valid(struct cpufreq_frequency_table **pos)
  * @table:      the cpufreq_frequency_table * to iterate over.
  */
 
-#define cpufreq_for_each_valid_entry(pos, table)       \
-       for (pos = table; cpufreq_next_valid(&pos); pos++)
+#define cpufreq_for_each_valid_entry(pos, table)                       \
+       for (pos = table; pos->frequency != CPUFREQ_TABLE_END; pos++)   \
+               if (pos->frequency == CPUFREQ_ENTRY_INVALID)            \
+                       continue;                                       \
+               else
 
 int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
                                    struct cpufreq_frequency_table *table);
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
new file mode 100644 (file)
index 0000000..5d68e15
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __CPUHOTPLUG_H
+#define __CPUHOTPLUG_H
+
+enum cpuhp_state {
+       CPUHP_OFFLINE,
+       CPUHP_CREATE_THREADS,
+       CPUHP_NOTIFY_PREPARE,
+       CPUHP_BRINGUP_CPU,
+       CPUHP_AP_IDLE_DEAD,
+       CPUHP_AP_OFFLINE,
+       CPUHP_AP_NOTIFY_STARTING,
+       CPUHP_AP_ONLINE,
+       CPUHP_TEARDOWN_CPU,
+       CPUHP_AP_ONLINE_IDLE,
+       CPUHP_AP_SMPBOOT_THREADS,
+       CPUHP_AP_NOTIFY_ONLINE,
+       CPUHP_AP_ONLINE_DYN,
+       CPUHP_AP_ONLINE_DYN_END         = CPUHP_AP_ONLINE_DYN + 30,
+       CPUHP_ONLINE,
+};
+
+int __cpuhp_setup_state(enum cpuhp_state state,        const char *name, bool invoke,
+                       int (*startup)(unsigned int cpu),
+                       int (*teardown)(unsigned int cpu));
+
+/**
+ * cpuhp_setup_state - Setup hotplug state callbacks with calling the callbacks
+ * @state:     The state for which the calls are installed
+ * @name:      Name of the callback (will be used in debug output)
+ * @startup:   startup callback function
+ * @teardown:  teardown callback function
+ *
+ * Installs the callback functions and invokes the startup callback on
+ * the present cpus which have already reached the @state.
+ */
+static inline int cpuhp_setup_state(enum cpuhp_state state,
+                                   const char *name,
+                                   int (*startup)(unsigned int cpu),
+                                   int (*teardown)(unsigned int cpu))
+{
+       return __cpuhp_setup_state(state, name, true, startup, teardown);
+}
+
+/**
+ * cpuhp_setup_state_nocalls - Setup hotplug state callbacks without calling the
+ *                            callbacks
+ * @state:     The state for which the calls are installed
+ * @name:      Name of the callback.
+ * @startup:   startup callback function
+ * @teardown:  teardown callback function
+ *
+ * Same as @cpuhp_setup_state except that no calls are executed are invoked
+ * during installation of this callback. NOP if SMP=n or HOTPLUG_CPU=n.
+ */
+static inline int cpuhp_setup_state_nocalls(enum cpuhp_state state,
+                                           const char *name,
+                                           int (*startup)(unsigned int cpu),
+                                           int (*teardown)(unsigned int cpu))
+{
+       return __cpuhp_setup_state(state, name, false, startup, teardown);
+}
+
+void __cpuhp_remove_state(enum cpuhp_state state, bool invoke);
+
+/**
+ * cpuhp_remove_state - Remove hotplug state callbacks and invoke the teardown
+ * @state:     The state for which the calls are removed
+ *
+ * Removes the callback functions and invokes the teardown callback on
+ * the present cpus which have already reached the @state.
+ */
+static inline void cpuhp_remove_state(enum cpuhp_state state)
+{
+       __cpuhp_remove_state(state, true);
+}
+
+/**
+ * cpuhp_remove_state_nocalls - Remove hotplug state callbacks without invoking
+ *                             teardown
+ * @state:     The state for which the calls are removed
+ */
+static inline void cpuhp_remove_state_nocalls(enum cpuhp_state state)
+{
+       __cpuhp_remove_state(state, false);
+}
+
+#ifdef CONFIG_SMP
+void cpuhp_online_idle(enum cpuhp_state state);
+#else
+static inline void cpuhp_online_idle(enum cpuhp_state state) { }
+#endif
+
+#endif
index 818e45078929b94af5780a8c91f0e84d82da8e0c..636dd59ab505c6633ae3184b9c283cad06ab893f 100644 (file)
@@ -7,7 +7,7 @@
 
 ssize_t dax_do_io(struct kiocb *, struct inode *, struct iov_iter *, loff_t,
                  get_block_t, dio_iodone_t, int flags);
-int dax_clear_blocks(struct inode *, sector_t block, long size);
+int dax_clear_sectors(struct block_device *bdev, sector_t _sector, long _size);
 int dax_zero_page_range(struct inode *, loff_t from, unsigned len, get_block_t);
 int dax_truncate_page(struct inode *, loff_t from, get_block_t);
 int dax_fault(struct vm_area_struct *, struct vm_fault *, get_block_t,
@@ -52,6 +52,8 @@ static inline bool dax_mapping(struct address_space *mapping)
 {
        return mapping->host && IS_DAX(mapping->host);
 }
-int dax_writeback_mapping_range(struct address_space *mapping, loff_t start,
-               loff_t end);
+
+struct writeback_control;
+int dax_writeback_mapping_range(struct address_space *mapping,
+               struct block_device *bdev, struct writeback_control *wbc);
 #endif
index 7781ce11050353a44cd7a3982c97949651956103..c4b5f4b3f8f8bba5af054b2b22e5c2c6fcf72b89 100644 (file)
@@ -409,9 +409,7 @@ static inline bool d_mountpoint(const struct dentry *dentry)
  */
 static inline unsigned __d_entry_type(const struct dentry *dentry)
 {
-       unsigned type = READ_ONCE(dentry->d_flags);
-       smp_rmb();
-       return type & DCACHE_ENTRY_TYPE;
+       return dentry->d_flags & DCACHE_ENTRY_TYPE;
 }
 
 static inline bool d_is_miss(const struct dentry *dentry)
index 75857cda38e989e5a44150c5abb9bd1bd4872957..5e45cf930a3f53fc7071f42a5759fe3dd5fd6a31 100644 (file)
@@ -386,7 +386,7 @@ static inline void dma_free_attrs(struct device *dev, size_t size,
        if (dma_release_from_coherent(dev, get_order(size), cpu_addr))
                return;
 
-       if (!ops->free)
+       if (!ops->free || !cpu_addr)
                return;
 
        debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
@@ -641,31 +641,40 @@ static inline void dmam_release_declared_memory(struct device *dev)
 }
 #endif /* CONFIG_HAVE_GENERIC_DMA_COHERENT */
 
-static inline void *dma_alloc_writecombine(struct device *dev, size_t size,
-                                          dma_addr_t *dma_addr, gfp_t gfp)
+static inline void *dma_alloc_wc(struct device *dev, size_t size,
+                                dma_addr_t *dma_addr, gfp_t gfp)
 {
        DEFINE_DMA_ATTRS(attrs);
        dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
        return dma_alloc_attrs(dev, size, dma_addr, gfp, &attrs);
 }
+#ifndef dma_alloc_writecombine
+#define dma_alloc_writecombine dma_alloc_wc
+#endif
 
-static inline void dma_free_writecombine(struct device *dev, size_t size,
-                                        void *cpu_addr, dma_addr_t dma_addr)
+static inline void dma_free_wc(struct device *dev, size_t size,
+                              void *cpu_addr, dma_addr_t dma_addr)
 {
        DEFINE_DMA_ATTRS(attrs);
        dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
        return dma_free_attrs(dev, size, cpu_addr, dma_addr, &attrs);
 }
+#ifndef dma_free_writecombine
+#define dma_free_writecombine dma_free_wc
+#endif
 
-static inline int dma_mmap_writecombine(struct device *dev,
-                                       struct vm_area_struct *vma,
-                                       void *cpu_addr, dma_addr_t dma_addr,
-                                       size_t size)
+static inline int dma_mmap_wc(struct device *dev,
+                             struct vm_area_struct *vma,
+                             void *cpu_addr, dma_addr_t dma_addr,
+                             size_t size)
 {
        DEFINE_DMA_ATTRS(attrs);
        dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
        return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
 }
+#ifndef dma_mmap_writecombine
+#define dma_mmap_writecombine dma_mmap_wc
+#endif
 
 #ifdef CONFIG_NEED_DMA_MAP_STATE
 #define DEFINE_DMA_UNMAP_ADDR(ADDR_NAME)        dma_addr_t ADDR_NAME
index 3159a7dba034bed547a531b2dcd511b29a679e89..9f4956d8601c111c57d27ca7205a04792d7e75dd 100644 (file)
@@ -62,10 +62,9 @@ static inline struct dentry *fault_create_debugfs_attr(const char *name,
 #endif /* CONFIG_FAULT_INJECTION */
 
 #ifdef CONFIG_FAILSLAB
-extern bool should_failslab(size_t size, gfp_t gfpflags, unsigned long flags);
+extern bool should_failslab(struct kmem_cache *s, gfp_t gfpflags);
 #else
-static inline bool should_failslab(size_t size, gfp_t gfpflags,
-                               unsigned long flags)
+static inline bool should_failslab(struct kmem_cache *s, gfp_t gfpflags)
 {
        return false;
 }
index c2b340e23f62d3240abc6360ab0412a82a12f21a..6d9df3f7e334c3a942728237dca471f7bb602f98 100644 (file)
@@ -713,6 +713,18 @@ static inline void __ftrace_enabled_restore(int enabled)
 #define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
 #define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
 
+static inline unsigned long get_lock_parent_ip(void)
+{
+       unsigned long addr = CALLER_ADDR0;
+
+       if (!in_lock_functions(addr))
+               return addr;
+       addr = CALLER_ADDR1;
+       if (!in_lock_functions(addr))
+               return addr;
+       return CALLER_ADDR2;
+}
+
 #ifdef CONFIG_IRQSOFF_TRACER
   extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
   extern void time_hardirqs_off(unsigned long a0, unsigned long a1);
index af1f2b24bbe4172f6055407229f0670ee90dc534..bb16dfeb917e3ccc3ea52ba6407d2db02d52c315 100644 (file)
@@ -9,6 +9,11 @@
 
 struct vm_area_struct;
 
+/*
+ * In case of changes, please don't forget to update
+ * include/trace/events/mmflags.h and tools/perf/builtin-kmem.c
+ */
+
 /* Plain integer GFP bitmasks. Do not use this directly. */
 #define ___GFP_DMA             0x01u
 #define ___GFP_HIGHMEM         0x02u
@@ -48,7 +53,6 @@ struct vm_area_struct;
 #define __GFP_DMA      ((__force gfp_t)___GFP_DMA)
 #define __GFP_HIGHMEM  ((__force gfp_t)___GFP_HIGHMEM)
 #define __GFP_DMA32    ((__force gfp_t)___GFP_DMA32)
-#define __GFP_MOVABLE  ((__force gfp_t)___GFP_MOVABLE)  /* Page is movable */
 #define __GFP_MOVABLE  ((__force gfp_t)___GFP_MOVABLE)  /* ZONE_MOVABLE allowed */
 #define GFP_ZONEMASK   (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
 
@@ -515,13 +519,7 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp);
 void drain_all_pages(struct zone *zone);
 void drain_local_pages(struct zone *zone);
 
-#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
 void page_alloc_init_late(void);
-#else
-static inline void page_alloc_init_late(void)
-{
-}
-#endif
 
 /*
  * gfp_allowed_mask is set to GFP_BOOT_MASK during early boot to restrict what
index b449f378f995ae647077f521d9f7af3af9480a70..aedb254abc37204a091b790eedfde857dc22155f 100644 (file)
@@ -142,6 +142,10 @@ void prepare_namespace(void);
 void __init load_default_modules(void);
 int __init init_rootfs(void);
 
+#ifdef CONFIG_DEBUG_RODATA
+void mark_rodata_ro(void);
+#endif
+
 extern void (*late_time_init)(void);
 
 extern bool initcall_debug;
index 0e95fcc75b2ac141ceeb3ebb3b2f79d7a5d2ddad..358076eda364ec929d5a5181c4c37663e4d78c40 100644 (file)
@@ -125,6 +125,16 @@ struct irqaction {
 
 extern irqreturn_t no_action(int cpl, void *dev_id);
 
+/*
+ * If a (PCI) device interrupt is not connected we set dev->irq to
+ * IRQ_NOTCONNECTED. This causes request_irq() to fail with -ENOTCONN, so we
+ * can distingiush that case from other error returns.
+ *
+ * 0x80000000 is guaranteed to be outside the available range of interrupts
+ * and easy to distinguish from other possible incorrect values.
+ */
+#define IRQ_NOTCONNECTED       (1U << 31)
+
 extern int __must_check
 request_threaded_irq(unsigned int irq, irq_handler_t handler,
                     irq_handler_t thread_fn,
index 24bea087e7af8083b3c81596a289d70530c64285..212a8e69d7c0deb5dbc923a66e19bd1a7792e596 100644 (file)
@@ -20,6 +20,7 @@ struct resource {
        resource_size_t end;
        const char *name;
        unsigned long flags;
+       unsigned long desc;
        struct resource *parent, *sibling, *child;
 };
 
@@ -49,12 +50,19 @@ struct resource {
 #define IORESOURCE_WINDOW      0x00200000      /* forwarded by bridge */
 #define IORESOURCE_MUXED       0x00400000      /* Resource is software muxed */
 
+#define IORESOURCE_EXT_TYPE_BITS 0x01000000    /* Resource extended types */
+#define IORESOURCE_SYSRAM      0x01000000      /* System RAM (modifier) */
+
 #define IORESOURCE_EXCLUSIVE   0x08000000      /* Userland may not map this resource */
+
 #define IORESOURCE_DISABLED    0x10000000
 #define IORESOURCE_UNSET       0x20000000      /* No address assigned yet */
 #define IORESOURCE_AUTO                0x40000000
 #define IORESOURCE_BUSY                0x80000000      /* Driver has marked this resource busy */
 
+/* I/O resource extended types */
+#define IORESOURCE_SYSTEM_RAM          (IORESOURCE_MEM|IORESOURCE_SYSRAM)
+
 /* PnP IRQ specific bits (IORESOURCE_BITS) */
 #define IORESOURCE_IRQ_HIGHEDGE                (1<<0)
 #define IORESOURCE_IRQ_LOWEDGE         (1<<1)
@@ -98,13 +106,27 @@ struct resource {
 
 /* PCI ROM control bits (IORESOURCE_BITS) */
 #define IORESOURCE_ROM_ENABLE          (1<<0)  /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
-#define IORESOURCE_ROM_SHADOW          (1<<1)  /* ROM is copy at C000:0 */
-#define IORESOURCE_ROM_COPY            (1<<2)  /* ROM is alloc'd copy, resource field overlaid */
-#define IORESOURCE_ROM_BIOS_COPY       (1<<3)  /* ROM is BIOS copy, resource field overlaid */
+#define IORESOURCE_ROM_SHADOW          (1<<1)  /* Use RAM image, not ROM BAR */
 
 /* PCI control bits.  Shares IORESOURCE_BITS with above PCI ROM.  */
 #define IORESOURCE_PCI_FIXED           (1<<4)  /* Do not move resource */
 
+/*
+ * I/O Resource Descriptors
+ *
+ * Descriptors are used by walk_iomem_res_desc() and region_intersects()
+ * for searching a specific resource range in the iomem table.  Assign
+ * a new descriptor when a resource range supports the search interfaces.
+ * Otherwise, resource.desc must be set to IORES_DESC_NONE (0).
+ */
+enum {
+       IORES_DESC_NONE                         = 0,
+       IORES_DESC_CRASH_KERNEL                 = 1,
+       IORES_DESC_ACPI_TABLES                  = 2,
+       IORES_DESC_ACPI_NV_STORAGE              = 3,
+       IORES_DESC_PERSISTENT_MEMORY            = 4,
+       IORES_DESC_PERSISTENT_MEMORY_LEGACY     = 5,
+};
 
 /* helpers to define resources */
 #define DEFINE_RES_NAMED(_start, _size, _name, _flags)                 \
@@ -113,6 +135,7 @@ struct resource {
                .end = (_start) + (_size) - 1,                          \
                .name = (_name),                                        \
                .flags = (_flags),                                      \
+               .desc = IORES_DESC_NONE,                                \
        }
 
 #define DEFINE_RES_IO_NAMED(_start, _size, _name)                      \
@@ -170,6 +193,10 @@ static inline unsigned long resource_type(const struct resource *res)
 {
        return res->flags & IORESOURCE_TYPE_BITS;
 }
+static inline unsigned long resource_ext_type(const struct resource *res)
+{
+       return res->flags & IORESOURCE_EXT_TYPE_BITS;
+}
 /* True iff r1 completely contains r2 */
 static inline bool resource_contains(struct resource *r1, struct resource *r2)
 {
@@ -239,8 +266,8 @@ extern int
 walk_system_ram_res(u64 start, u64 end, void *arg,
                    int (*func)(u64, u64, void *));
 extern int
-walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, void *arg,
-              int (*func)(u64, u64, void *));
+walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end,
+                   void *arg, int (*func)(u64, u64, void *));
 
 /* True if any part of r1 overlaps r2 */
 static inline bool resource_overlaps(struct resource *r1, struct resource *r2)
index 3c1c96786248cb02d2d9792cce455892323ef275..c4de62348ff229194c85b133d45f0d220642b082 100644 (file)
@@ -133,17 +133,23 @@ struct irq_domain;
  *                     Use accessor functions to deal with it
  * @node:              node index useful for balancing
  * @handler_data:      per-IRQ data for the irq_chip methods
- * @affinity:          IRQ affinity on SMP
+ * @affinity:          IRQ affinity on SMP. If this is an IPI
+ *                     related irq, then this is the mask of the
+ *                     CPUs to which an IPI can be sent.
  * @msi_desc:          MSI descriptor
+ * @ipi_offset:                Offset of first IPI target cpu in @affinity. Optional.
  */
 struct irq_common_data {
-       unsigned int            state_use_accessors;
+       unsigned int            __private state_use_accessors;
 #ifdef CONFIG_NUMA
        unsigned int            node;
 #endif
        void                    *handler_data;
        struct msi_desc         *msi_desc;
        cpumask_var_t           affinity;
+#ifdef CONFIG_GENERIC_IRQ_IPI
+       unsigned int            ipi_offset;
+#endif
 };
 
 /**
@@ -208,7 +214,7 @@ enum {
        IRQD_FORWARDED_TO_VCPU          = (1 << 20),
 };
 
-#define __irqd_to_state(d)             ((d)->common->state_use_accessors)
+#define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
 
 static inline bool irqd_is_setaffinity_pending(struct irq_data *d)
 {
@@ -299,6 +305,8 @@ static inline void irqd_clr_forwarded_to_vcpu(struct irq_data *d)
        __irqd_to_state(d) &= ~IRQD_FORWARDED_TO_VCPU;
 }
 
+#undef __irqd_to_state
+
 static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
 {
        return d->hwirq;
@@ -341,6 +349,8 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
  * @irq_get_irqchip_state:     return the internal state of an interrupt
  * @irq_set_irqchip_state:     set the internal state of a interrupt
  * @irq_set_vcpu_affinity:     optional to target a vCPU in a virtual machine
+ * @ipi_send_single:   send a single IPI to destination cpus
+ * @ipi_send_mask:     send an IPI to destination cpus in cpumask
  * @flags:             chip specific flags
  */
 struct irq_chip {
@@ -385,6 +395,9 @@ struct irq_chip {
 
        int             (*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);
 
+       void            (*ipi_send_single)(struct irq_data *data, unsigned int cpu);
+       void            (*ipi_send_mask)(struct irq_data *data, const struct cpumask *dest);
+
        unsigned long   flags;
 };
 
@@ -934,4 +947,12 @@ static inline u32 irq_reg_readl(struct irq_chip_generic *gc,
                return readl(gc->reg_base + reg_offset);
 }
 
+/* Contrary to Linux irqs, for hardware irqs the irq number 0 is valid */
+#define INVALID_HWIRQ  (~0UL)
+irq_hw_number_t ipi_get_hwirq(unsigned int irq, unsigned int cpu);
+int __ipi_send_single(struct irq_desc *desc, unsigned int cpu);
+int __ipi_send_mask(struct irq_desc *desc, const struct cpumask *dest);
+int ipi_send_single(unsigned int virq, unsigned int cpu);
+int ipi_send_mask(unsigned int virq, const struct cpumask *dest);
+
 #endif /* _LINUX_IRQ_H */
index ce824db48d64c7fd29fc41babb0df6923da0774f..80f89e4a29ac5d714a4cd8e239b408367edd9d37 100644 (file)
@@ -261,9 +261,6 @@ extern void gic_write_compare(cycle_t cnt);
 extern void gic_write_cpu_compare(cycle_t cnt, int cpu);
 extern void gic_start_count(void);
 extern void gic_stop_count(void);
-extern void gic_send_ipi(unsigned int intr);
-extern unsigned int plat_ipi_call_int_xlate(unsigned int);
-extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern int gic_get_c0_compare_int(void);
 extern int gic_get_c0_perfcount_int(void);
 extern int gic_get_c0_fdc_int(void);
index 04579d9fbce4f3b5c0a8484116500ee3034b93f7..ed48594e96d2562ddc1de9c1dc94559629f7a4da 100644 (file)
@@ -74,6 +74,7 @@ enum irq_domain_bus_token {
        DOMAIN_BUS_PCI_MSI,
        DOMAIN_BUS_PLATFORM_MSI,
        DOMAIN_BUS_NEXUS,
+       DOMAIN_BUS_IPI,
 };
 
 /**
@@ -172,6 +173,12 @@ enum {
        /* Core calls alloc/free recursive through the domain hierarchy. */
        IRQ_DOMAIN_FLAG_AUTO_RECURSIVE  = (1 << 1),
 
+       /* Irq domain is an IPI domain with virq per cpu */
+       IRQ_DOMAIN_FLAG_IPI_PER_CPU     = (1 << 2),
+
+       /* Irq domain is an IPI domain with single virq */
+       IRQ_DOMAIN_FLAG_IPI_SINGLE      = (1 << 3),
+
        /*
         * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
         * for implementation specific purposes and ignored by the
@@ -206,6 +213,8 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
 extern struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
                                                   enum irq_domain_bus_token bus_token);
 extern void irq_set_default_host(struct irq_domain *host);
+extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
+                                 irq_hw_number_t hwirq, int node);
 
 static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
 {
@@ -335,6 +344,11 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
                        const u32 *intspec, unsigned int intsize,
                        irq_hw_number_t *out_hwirq, unsigned int *out_type);
 
+/* IPI functions */
+unsigned int irq_reserve_ipi(struct irq_domain *domain,
+                            const struct cpumask *dest);
+void irq_destroy_ipi(unsigned int irq);
+
 /* V2 interfaces to support hierarchy IRQ domains. */
 extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
                                                unsigned int virq);
@@ -400,6 +414,22 @@ static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
        return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY;
 }
+
+static inline bool irq_domain_is_ipi(struct irq_domain *domain)
+{
+       return domain->flags &
+               (IRQ_DOMAIN_FLAG_IPI_PER_CPU | IRQ_DOMAIN_FLAG_IPI_SINGLE);
+}
+
+static inline bool irq_domain_is_ipi_per_cpu(struct irq_domain *domain)
+{
+       return domain->flags & IRQ_DOMAIN_FLAG_IPI_PER_CPU;
+}
+
+static inline bool irq_domain_is_ipi_single(struct irq_domain *domain)
+{
+       return domain->flags & IRQ_DOMAIN_FLAG_IPI_SINGLE;
+}
 #else  /* CONFIG_IRQ_DOMAIN_HIERARCHY */
 static inline void irq_domain_activate_irq(struct irq_data *data) { }
 static inline void irq_domain_deactivate_irq(struct irq_data *data) { }
@@ -413,6 +443,21 @@ static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
        return false;
 }
+
+static inline bool irq_domain_is_ipi(struct irq_domain *domain)
+{
+       return false;
+}
+
+static inline bool irq_domain_is_ipi_per_cpu(struct irq_domain *domain)
+{
+       return false;
+}
+
+static inline bool irq_domain_is_ipi_single(struct irq_domain *domain)
+{
+       return false;
+}
 #endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
 
 #else /* CONFIG_IRQ_DOMAIN */
index 2a8b1659bf3579aa41a36483fd1b8350eb7ca545..548d5539548886994f38ac77e427f5623794dd08 100644 (file)
@@ -23,6 +23,7 @@ enum iscsi_boot_eth_properties_enum {
        ISCSI_BOOT_ETH_INDEX,
        ISCSI_BOOT_ETH_FLAGS,
        ISCSI_BOOT_ETH_IP_ADDR,
+       ISCSI_BOOT_ETH_PREFIX_LEN,
        ISCSI_BOOT_ETH_SUBNET_MASK,
        ISCSI_BOOT_ETH_ORIGIN,
        ISCSI_BOOT_ETH_GATEWAY,
index 4b9f85c963d0738e20ee7c89e2dcb28ba3cc1aaa..0fdc798e3ff795a9dffd75e36e90ce2b61141562 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _LINUX_KASAN_H
 #define _LINUX_KASAN_H
 
+#include <linux/sched.h>
 #include <linux/types.h>
 
 struct kmem_cache;
@@ -13,7 +14,6 @@ struct vm_struct;
 
 #include <asm/kasan.h>
 #include <asm/pgtable.h>
-#include <linux/sched.h>
 
 extern unsigned char kasan_zero_page[PAGE_SIZE];
 extern pte_t kasan_zero_pte[PTRS_PER_PTE];
@@ -43,6 +43,8 @@ static inline void kasan_disable_current(void)
 
 void kasan_unpoison_shadow(const void *address, size_t size);
 
+void kasan_unpoison_task_stack(struct task_struct *task);
+
 void kasan_alloc_pages(struct page *page, unsigned int order);
 void kasan_free_pages(struct page *page, unsigned int order);
 
@@ -66,6 +68,8 @@ void kasan_free_shadow(const struct vm_struct *vm);
 
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
 
+static inline void kasan_unpoison_task_stack(struct task_struct *task) {}
+
 static inline void kasan_enable_current(void) {}
 static inline void kasan_disable_current(void) {}
 
index 861f690aa79118a0203d90f896bf860e3374820e..5276fe0916fcc63a8944af0a288b1afeccc100b0 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/irqflags.h>
 #include <linux/context_tracking.h>
 #include <linux/irqbypass.h>
+#include <linux/swait.h>
 #include <asm/signal.h>
 
 #include <linux/kvm.h>
@@ -218,7 +219,7 @@ struct kvm_vcpu {
        int fpu_active;
        int guest_fpu_loaded, guest_xcr0_loaded;
        unsigned char fpu_counter;
-       wait_queue_head_t wq;
+       struct swait_queue_head wq;
        struct pid *pid;
        int sigset_active;
        sigset_t sigset;
@@ -782,7 +783,7 @@ static inline bool kvm_arch_has_assigned_device(struct kvm *kvm)
 }
 #endif
 
-static inline wait_queue_head_t *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
+static inline struct swait_queue_head *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu)
 {
 #ifdef __KVM_HAVE_ARCH_WQP
        return vcpu->arch.wqp;
index e23121f9d82a042a9b10907fe40e468e5711f99f..59ccab297ae061ba03494ccede8eae2d7a5236a1 100644 (file)
@@ -37,6 +37,9 @@ account_scheduler_latency(struct task_struct *task, int usecs, int inter)
 
 void clear_all_latency_tracing(struct task_struct *p);
 
+extern int sysctl_latencytop(struct ctl_table *table, int write,
+                       void __user *buffer, size_t *lenp, loff_t *ppos);
+
 #else
 
 static inline void
index bc1476fda96eb3206995b270e32cb54a49305eea..f203a8f89d30d0f3e214b43d2c72efea1bdad9f9 100644 (file)
@@ -39,6 +39,7 @@ struct led_classdev {
 
        /* Lower 16 bits reflect status */
 #define LED_SUSPENDED          (1 << 0)
+#define LED_UNREGISTERING      (1 << 1)
        /* Upper 16 bits reflect control information */
 #define LED_CORE_SUSPENDRESUME (1 << 16)
 #define LED_BLINK_ONESHOT      (1 << 17)
@@ -48,9 +49,12 @@ struct led_classdev {
 #define LED_BLINK_DISABLE      (1 << 21)
 #define LED_SYSFS_DISABLE      (1 << 22)
 #define LED_DEV_CAP_FLASH      (1 << 23)
+#define LED_HW_PLUGGABLE       (1 << 24)
 
-       /* Set LED brightness level */
-       /* Must not sleep, use a workqueue if needed */
+       /* Set LED brightness level
+        * Must not sleep. Use brightness_set_blocking for drivers
+        * that can sleep while setting brightness.
+        */
        void            (*brightness_set)(struct led_classdev *led_cdev,
                                          enum led_brightness brightness);
        /*
index bec2abbd7ab28485cbf32bfefa7430b6a47c81e4..2c4ebef79d0c61b596efed901eb834d8a436492d 100644 (file)
@@ -720,7 +720,7 @@ struct ata_device {
        union {
                u16             id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
                u32             gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
-       };
+       } ____cacheline_aligned;
 
        /* DEVSLP Timing Variables from Identify Device Data Log */
        u8                      devslp_timing[ATA_LOG_DEVSLP_SIZE];
index bed40dff0e86999b5c39c82ebadc29f25e0060ec..141ffdd59960d7b31583f629140b0f7dd9916b37 100644 (file)
@@ -26,9 +26,8 @@ enum {
 
        /* need to set a limit somewhere, but yes, this is likely overkill */
        ND_IOCTL_MAX_BUFLEN = SZ_4M,
-       ND_CMD_MAX_ELEM = 4,
+       ND_CMD_MAX_ELEM = 5,
        ND_CMD_MAX_ENVELOPE = 16,
-       ND_CMD_ARS_STATUS_MAX = SZ_4K,
        ND_MAX_MAPPINGS = 32,
 
        /* region flag indicating to direct-map persistent memory by default */
index 30cf4200ab40ee40fdae694291e36fe869b508bc..5356f4d661a721ba0446b1183e2a834f3bf3b56f 100644 (file)
@@ -113,17 +113,6 @@ extern void __list_del_entry(struct list_head *entry);
 extern void list_del(struct list_head *entry);
 #endif
 
-#ifdef CONFIG_DEBUG_LIST
-/*
- * See devm_memremap_pages() which wants DEBUG_LIST=y to assert if one
- * of the pages it allocates is ever passed to list_add()
- */
-extern void list_force_poison(struct list_head *entry);
-#else
-/* fallback to the less strict LIST_POISON* definitions */
-#define list_force_poison list_del
-#endif
-
 /**
  * list_replace - replace old entry by new one
  * @old : the element to be replaced
index 4dca42fd32f52d17326e436c4d9fcbd86a0e8d24..d026b190c53066d25753ce98f0d7c66d864a6c0a 100644 (file)
@@ -261,7 +261,6 @@ struct held_lock {
 /*
  * Initialization, self-test and debugging-output methods:
  */
-extern void lockdep_init(void);
 extern void lockdep_info(void);
 extern void lockdep_reset(void);
 extern void lockdep_reset_lock(struct lockdep_map *lock);
@@ -392,7 +391,6 @@ static inline void lockdep_on(void)
 # define lockdep_set_current_reclaim_state(g)  do { } while (0)
 # define lockdep_clear_current_reclaim_state() do { } while (0)
 # define lockdep_trace_alloc(g)                        do { } while (0)
-# define lockdep_init()                                do { } while (0)
 # define lockdep_info()                                do { } while (0)
 # define lockdep_init_map(lock, name, key, sub) \
                do { (void)(name); (void)(key); } while (0)
index 792c8981e63365b06a03e7feda7e647eafb533c0..f0c4bec6565bf6f69fbb8ad98230515dc3479b8f 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/eventfd.h>
 #include <linux/mmzone.h>
 #include <linux/writeback.h>
+#include <linux/page-flags.h>
 
 struct mem_cgroup;
 struct page;
@@ -89,6 +90,10 @@ enum mem_cgroup_events_target {
 };
 
 #ifdef CONFIG_MEMCG
+
+#define MEM_CGROUP_ID_SHIFT    16
+#define MEM_CGROUP_ID_MAX      USHRT_MAX
+
 struct mem_cgroup_stat_cpu {
        long count[MEMCG_NR_STAT];
        unsigned long events[MEMCG_NR_EVENTS];
@@ -265,6 +270,11 @@ struct mem_cgroup {
 
 extern struct mem_cgroup *root_mem_cgroup;
 
+static inline bool mem_cgroup_disabled(void)
+{
+       return !cgroup_subsys_enabled(memory_cgrp_subsys);
+}
+
 /**
  * mem_cgroup_events - count memory events against a cgroup
  * @memcg: the memory cgroup
@@ -291,7 +301,7 @@ void mem_cgroup_cancel_charge(struct page *page, struct mem_cgroup *memcg,
 void mem_cgroup_uncharge(struct page *page);
 void mem_cgroup_uncharge_list(struct list_head *page_list);
 
-void mem_cgroup_replace_page(struct page *oldpage, struct page *newpage);
+void mem_cgroup_migrate(struct page *oldpage, struct page *newpage);
 
 struct lruvec *mem_cgroup_zone_lruvec(struct zone *, struct mem_cgroup *);
 struct lruvec *mem_cgroup_page_lruvec(struct page *, struct zone *);
@@ -312,6 +322,28 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *,
                                   struct mem_cgroup_reclaim_cookie *);
 void mem_cgroup_iter_break(struct mem_cgroup *, struct mem_cgroup *);
 
+static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
+{
+       if (mem_cgroup_disabled())
+               return 0;
+
+       return memcg->css.id;
+}
+
+/**
+ * mem_cgroup_from_id - look up a memcg from an id
+ * @id: the id to look up
+ *
+ * Caller must hold rcu_read_lock() and use css_tryget() as necessary.
+ */
+static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
+{
+       struct cgroup_subsys_state *css;
+
+       css = css_from_id(id, &memory_cgrp_subsys);
+       return mem_cgroup_from_css(css);
+}
+
 /**
  * parent_mem_cgroup - find the accounting parent of a memcg
  * @memcg: memcg whose parent to find
@@ -353,11 +385,6 @@ static inline bool mm_match_cgroup(struct mm_struct *mm,
 struct cgroup_subsys_state *mem_cgroup_css_from_page(struct page *page);
 ino_t page_cgroup_ino(struct page *page);
 
-static inline bool mem_cgroup_disabled(void)
-{
-       return !cgroup_subsys_enabled(memory_cgrp_subsys);
-}
-
 static inline bool mem_cgroup_online(struct mem_cgroup *memcg)
 {
        if (mem_cgroup_disabled())
@@ -429,36 +456,43 @@ bool mem_cgroup_oom_synchronize(bool wait);
 extern int do_swap_account;
 #endif
 
-struct mem_cgroup *mem_cgroup_begin_page_stat(struct page *page);
-void mem_cgroup_end_page_stat(struct mem_cgroup *memcg);
+void lock_page_memcg(struct page *page);
+void unlock_page_memcg(struct page *page);
 
 /**
  * mem_cgroup_update_page_stat - update page state statistics
- * @memcg: memcg to account against
+ * @page: the page
  * @idx: page state item to account
  * @val: number of pages (positive or negative)
  *
- * See mem_cgroup_begin_page_stat() for locking requirements.
+ * The @page must be locked or the caller must use lock_page_memcg()
+ * to prevent double accounting when the page is concurrently being
+ * moved to another memcg:
+ *
+ *   lock_page(page) or lock_page_memcg(page)
+ *   if (TestClearPageState(page))
+ *     mem_cgroup_update_page_stat(page, state, -1);
+ *   unlock_page(page) or unlock_page_memcg(page)
  */
-static inline void mem_cgroup_update_page_stat(struct mem_cgroup *memcg,
+static inline void mem_cgroup_update_page_stat(struct page *page,
                                 enum mem_cgroup_stat_index idx, int val)
 {
-       VM_BUG_ON(!rcu_read_lock_held());
+       VM_BUG_ON(!(rcu_read_lock_held() || PageLocked(page)));
 
-       if (memcg)
-               this_cpu_add(memcg->stat->count[idx], val);
+       if (page->mem_cgroup)
+               this_cpu_add(page->mem_cgroup->stat->count[idx], val);
 }
 
-static inline void mem_cgroup_inc_page_stat(struct mem_cgroup *memcg,
+static inline void mem_cgroup_inc_page_stat(struct page *page,
                                            enum mem_cgroup_stat_index idx)
 {
-       mem_cgroup_update_page_stat(memcg, idx, 1);
+       mem_cgroup_update_page_stat(page, idx, 1);
 }
 
-static inline void mem_cgroup_dec_page_stat(struct mem_cgroup *memcg,
+static inline void mem_cgroup_dec_page_stat(struct page *page,
                                            enum mem_cgroup_stat_index idx)
 {
-       mem_cgroup_update_page_stat(memcg, idx, -1);
+       mem_cgroup_update_page_stat(page, idx, -1);
 }
 
 unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
@@ -496,8 +530,17 @@ void mem_cgroup_split_huge_fixup(struct page *head);
 #endif
 
 #else /* CONFIG_MEMCG */
+
+#define MEM_CGROUP_ID_SHIFT    0
+#define MEM_CGROUP_ID_MAX      0
+
 struct mem_cgroup;
 
+static inline bool mem_cgroup_disabled(void)
+{
+       return true;
+}
+
 static inline void mem_cgroup_events(struct mem_cgroup *memcg,
                                     enum mem_cgroup_events_index idx,
                                     unsigned int nr)
@@ -539,7 +582,7 @@ static inline void mem_cgroup_uncharge_list(struct list_head *page_list)
 {
 }
 
-static inline void mem_cgroup_replace_page(struct page *old, struct page *new)
+static inline void mem_cgroup_migrate(struct page *old, struct page *new)
 {
 }
 
@@ -580,9 +623,16 @@ static inline void mem_cgroup_iter_break(struct mem_cgroup *root,
 {
 }
 
-static inline bool mem_cgroup_disabled(void)
+static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
 {
-       return true;
+       return 0;
+}
+
+static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
+{
+       WARN_ON_ONCE(id);
+       /* XXX: This should always return root_mem_cgroup */
+       return NULL;
 }
 
 static inline bool mem_cgroup_online(struct mem_cgroup *memcg)
@@ -613,12 +663,11 @@ mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
 {
 }
 
-static inline struct mem_cgroup *mem_cgroup_begin_page_stat(struct page *page)
+static inline void lock_page_memcg(struct page *page)
 {
-       return NULL;
 }
 
-static inline void mem_cgroup_end_page_stat(struct mem_cgroup *memcg)
+static inline void unlock_page_memcg(struct page *page)
 {
 }
 
@@ -644,12 +693,12 @@ static inline bool mem_cgroup_oom_synchronize(bool wait)
        return false;
 }
 
-static inline void mem_cgroup_inc_page_stat(struct mem_cgroup *memcg,
+static inline void mem_cgroup_inc_page_stat(struct page *page,
                                            enum mem_cgroup_stat_index idx)
 {
 }
 
-static inline void mem_cgroup_dec_page_stat(struct mem_cgroup *memcg,
+static inline void mem_cgroup_dec_page_stat(struct page *page,
                                            enum mem_cgroup_stat_index idx)
 {
 }
@@ -765,7 +814,7 @@ int __memcg_kmem_charge(struct page *page, gfp_t gfp, int order);
 void __memcg_kmem_uncharge(struct page *page, int order);
 
 /*
- * helper for acessing a memcg's index. It will be used as an index in the
+ * helper for accessing a memcg's index. It will be used as an index in the
  * child cache array in kmem_cache, and also to derive its name. This function
  * will return -1 when this is not a kmem-limited memcg.
  */
index 8b8d8d12348e59219dbbce03c22a749a49368deb..82730adba950ed196bb7006fa953704393f6578e 100644 (file)
@@ -109,6 +109,9 @@ extern void unregister_memory_notifier(struct notifier_block *nb);
 extern int register_memory_isolate_notifier(struct notifier_block *nb);
 extern void unregister_memory_isolate_notifier(struct notifier_block *nb);
 extern int register_new_memory(int, struct mem_section *);
+extern int memory_block_change_state(struct memory_block *mem,
+                                    unsigned long to_state,
+                                    unsigned long from_state_req);
 #ifdef CONFIG_MEMORY_HOTREMOVE
 extern int unregister_memory_section(struct mem_section *);
 #endif
index 43405992d0277367eb55afeb847745acc09ed968..adbef586e696311ef2897886df2f356d54d5a52b 100644 (file)
@@ -99,6 +99,8 @@ extern void __online_page_free(struct page *page);
 
 extern int try_online_node(int nid);
 
+extern bool memhp_auto_online;
+
 #ifdef CONFIG_MEMORY_HOTREMOVE
 extern bool is_pageblock_removable_nolock(struct page *page);
 extern int arch_remove_memory(u64 start, u64 size);
@@ -196,6 +198,9 @@ void put_online_mems(void);
 void mem_hotplug_begin(void);
 void mem_hotplug_done(void);
 
+extern void set_zone_contiguous(struct zone *zone);
+extern void clear_zone_contiguous(struct zone *zone);
+
 #else /* ! CONFIG_MEMORY_HOTPLUG */
 /*
  * Stub functions for when hotplug is off
@@ -267,7 +272,7 @@ static inline void remove_memory(int nid, u64 start, u64 size) {}
 extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
                void *arg, int (*func)(struct memory_block *, void *));
 extern int add_memory(int nid, u64 start, u64 size);
-extern int add_memory_resource(int nid, struct resource *resource);
+extern int add_memory_resource(int nid, struct resource *resource, bool online);
 extern int zone_for_memory(int nid, u64 start, u64 size, int zone_default,
                bool for_device);
 extern int arch_add_memory(int nid, u64 start, u64 size, bool for_device);
index f5043490d67c95956cf57247386d83fe71b76000..643dae777b4326e5f6e1669baa045a76605f2bdb 100644 (file)
@@ -437,14 +437,11 @@ enum max77686_irq {
 struct max77686_dev {
        struct device *dev;
        struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
-       struct i2c_client *rtc; /* slave addr 0x0c */
 
        unsigned long type;
 
        struct regmap *regmap;          /* regmap for mfd */
-       struct regmap *rtc_regmap;      /* regmap for rtc */
        struct regmap_irq_chip_data *irq_data;
-       struct regmap_irq_chip_data *rtc_irq_data;
 
        int irq;
        struct mutex irqlock;
index cac1c0904d5fb40c2a5729ca3eabd47f76a9134e..9b50325e4ddfebf4aae82c49866f617a4145ec5a 100644 (file)
@@ -23,9 +23,13 @@ enum migrate_reason {
        MR_SYSCALL,             /* also applies to cpusets */
        MR_MEMPOLICY_MBIND,
        MR_NUMA_MISPLACED,
-       MR_CMA
+       MR_CMA,
+       MR_TYPES
 };
 
+/* In mm/debug.c; also keep sync with include/trace/events/migrate.h */
+extern char *migrate_reason_names[MR_TYPES];
+
 #ifdef CONFIG_MIGRATION
 
 extern void putback_movable_pages(struct list_head *l);
index 51f1e540fc2b83bf9dd143637bad8acdbc44d0fd..58eef02edc7e81ab2dcd14aace9c722b76a89623 100644 (file)
@@ -4245,7 +4245,9 @@ struct mlx5_ifc_modify_tir_bitmask_bits {
 
        u8         reserved_at_20[0x1b];
        u8         self_lb_en[0x1];
-       u8         reserved_at_3c[0x3];
+       u8         reserved_at_3c[0x1];
+       u8         hash[0x1];
+       u8         reserved_at_3e[0x1];
        u8         lro[0x1];
 };
 
index 516e149443397dcf712e4e62aca6fb3c78e542b6..dbf1eddab9646170580974eed619aace466e4e02 100644 (file)
@@ -387,7 +387,8 @@ enum {
        REGION_MIXED,
 };
 
-int region_intersects(resource_size_t offset, size_t size, const char *type);
+int region_intersects(resource_size_t offset, size_t size, unsigned long flags,
+                     unsigned long desc);
 
 /* Support for virtually mapped pages */
 struct page *vmalloc_to_page(const void *addr);
@@ -904,20 +905,11 @@ static inline struct mem_cgroup *page_memcg(struct page *page)
 {
        return page->mem_cgroup;
 }
-
-static inline void set_page_memcg(struct page *page, struct mem_cgroup *memcg)
-{
-       page->mem_cgroup = memcg;
-}
 #else
 static inline struct mem_cgroup *page_memcg(struct page *page)
 {
        return NULL;
 }
-
-static inline void set_page_memcg(struct page *page, struct mem_cgroup *memcg)
-{
-}
 #endif
 
 /*
@@ -1299,10 +1291,9 @@ int __set_page_dirty_nobuffers(struct page *page);
 int __set_page_dirty_no_writeback(struct page *page);
 int redirty_page_for_writepage(struct writeback_control *wbc,
                                struct page *page);
-void account_page_dirtied(struct page *page, struct address_space *mapping,
-                         struct mem_cgroup *memcg);
+void account_page_dirtied(struct page *page, struct address_space *mapping);
 void account_page_cleaned(struct page *page, struct address_space *mapping,
-                         struct mem_cgroup *memcg, struct bdi_writeback *wb);
+                         struct bdi_writeback *wb);
 int set_page_dirty(struct page *page);
 int set_page_dirty_lock(struct page *page);
 void cancel_dirty_page(struct page *page);
@@ -2138,6 +2129,8 @@ int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
 int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
 int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
                        unsigned long pfn);
+int vm_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr,
+                       unsigned long pfn, pgprot_t pgprot);
 int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
                        pfn_t pfn);
 int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len);
@@ -2175,6 +2168,17 @@ extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
                               unsigned long size, pte_fn_t fn, void *data);
 
 
+#ifdef CONFIG_PAGE_POISONING
+extern bool page_poisoning_enabled(void);
+extern void kernel_poison_pages(struct page *page, int numpages, int enable);
+extern bool page_is_poisoned(struct page *page);
+#else
+static inline bool page_poisoning_enabled(void) { return false; }
+static inline void kernel_poison_pages(struct page *page, int numpages,
+                                       int enable) { }
+static inline bool page_is_poisoned(struct page *page) { return false; }
+#endif
+
 #ifdef CONFIG_DEBUG_PAGEALLOC
 extern bool _debug_pagealloc_enabled;
 extern void __kernel_map_pages(struct page *page, int numpages, int enable);
@@ -2194,14 +2198,18 @@ kernel_map_pages(struct page *page, int numpages, int enable)
 }
 #ifdef CONFIG_HIBERNATION
 extern bool kernel_page_present(struct page *page);
-#endif /* CONFIG_HIBERNATION */
-#else
+#endif /* CONFIG_HIBERNATION */
+#else  /* CONFIG_DEBUG_PAGEALLOC */
 static inline void
 kernel_map_pages(struct page *page, int numpages, int enable) {}
 #ifdef CONFIG_HIBERNATION
 static inline bool kernel_page_present(struct page *page) { return true; }
-#endif /* CONFIG_HIBERNATION */
-#endif
+#endif /* CONFIG_HIBERNATION */
+static inline bool debug_pagealloc_enabled(void)
+{
+       return false;
+}
+#endif /* CONFIG_DEBUG_PAGEALLOC */
 
 #ifdef __HAVE_ARCH_GATE_AREA
 extern struct vm_area_struct *get_gate_vma(struct mm_struct *mm);
index 624b78b848b89fae506faa1f4f48ce86297ceace..944b2b37313b49bffd581963a5f13380a7c6e520 100644 (file)
@@ -566,10 +566,26 @@ static inline void clear_tlb_flush_pending(struct mm_struct *mm)
 }
 #endif
 
-struct vm_special_mapping
-{
-       const char *name;
+struct vm_fault;
+
+struct vm_special_mapping {
+       const char *name;       /* The name, e.g. "[vdso]". */
+
+       /*
+        * If .fault is not provided, this points to a
+        * NULL-terminated array of pages that back the special mapping.
+        *
+        * This must not be NULL unless .fault is provided.
+        */
        struct page **pages;
+
+       /*
+        * If non-NULL, then this is called to resolve page faults
+        * on the special mapping.  If used, .pages is not checked.
+        */
+       int (*fault)(const struct vm_special_mapping *sm,
+                    struct vm_area_struct *vma,
+                    struct vm_fault *vmf);
 };
 
 enum tlb_flush_reason {
index 053824b0a412e0c2ca371e3844c1534b913fb6d0..de7be78c6f0ece43498ba1fd4f08bad266c06963 100644 (file)
@@ -9,8 +9,7 @@ struct vm_area_struct;
 struct mm_struct;
 
 extern void dump_page(struct page *page, const char *reason);
-extern void dump_page_badflags(struct page *page, const char *reason,
-                              unsigned long badflags);
+extern void __dump_page(struct page *page, const char *reason);
 void dump_vma(const struct vm_area_struct *vma);
 void dump_mm(const struct mm_struct *mm);
 
index 7b6c2cfee390e939e13b0f14c92224bcb3aafcf4..6de02ac378a0d2a9066a6068455e6775d668a3be 100644 (file)
@@ -63,6 +63,9 @@ enum {
        MIGRATE_TYPES
 };
 
+/* In mm/page_alloc.c; keep in sync also with show_migration_types() there */
+extern char * const migratetype_names[MIGRATE_TYPES];
+
 #ifdef CONFIG_CMA
 #  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
 #else
@@ -209,10 +212,12 @@ struct zone_reclaim_stat {
 };
 
 struct lruvec {
-       struct list_head lists[NR_LRU_LISTS];
-       struct zone_reclaim_stat reclaim_stat;
+       struct list_head                lists[NR_LRU_LISTS];
+       struct zone_reclaim_stat        reclaim_stat;
+       /* Evictions & activations on the inactive file list */
+       atomic_long_t                   inactive_age;
 #ifdef CONFIG_MEMCG
-       struct zone *zone;
+       struct zone                     *zone;
 #endif
 };
 
@@ -487,9 +492,6 @@ struct zone {
        spinlock_t              lru_lock;
        struct lruvec           lruvec;
 
-       /* Evictions & activations on the inactive file list */
-       atomic_long_t           inactive_age;
-
        /*
         * When free pages are below this point, additional steps are taken
         * when reading the number of free pages to avoid per-cpu counter
@@ -520,6 +522,8 @@ struct zone {
        bool                    compact_blockskip_flush;
 #endif
 
+       bool                    contiguous;
+
        ZONE_PADDING(_pad3_)
        /* Zone statistics */
        atomic_long_t           vm_stat[NR_VM_ZONE_STAT_ITEMS];
@@ -758,6 +762,8 @@ static inline struct zone *lruvec_zone(struct lruvec *lruvec)
 #endif
 }
 
+extern unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru);
+
 #ifdef CONFIG_HAVE_MEMORY_PRESENT
 void memory_present(int nid, unsigned long start, unsigned long end);
 #else
index d14a4c362465712857d1ea8fe39b974a5c05c4ce..4149868de4e6c82e8248544ff01ddfe801258be0 100644 (file)
@@ -47,6 +47,8 @@
  * runtime initialization.
  */
 
+struct notifier_block;
+
 typedef        int (*notifier_fn_t)(struct notifier_block *nb,
                        unsigned long action, void *data);
 
index 17f118a82854960701dac4de69dfc1af43713989..e1fe7cf5bddf0935a0c9eaab5273b230c4917d1b 100644 (file)
@@ -45,6 +45,7 @@ struct page_ext {
        unsigned int order;
        gfp_t gfp_mask;
        unsigned int nr_entries;
+       int last_migrate_reason;
        unsigned long trace_entries[8];
 #endif
 };
index cacaabea8a0950115138c956737c2bd9d7c04a90..46f1b939948c58df206e8c8740ba08bcd5f7f114 100644 (file)
@@ -1,38 +1,54 @@
 #ifndef __LINUX_PAGE_OWNER_H
 #define __LINUX_PAGE_OWNER_H
 
+#include <linux/jump_label.h>
+
 #ifdef CONFIG_PAGE_OWNER
-extern bool page_owner_inited;
+extern struct static_key_false page_owner_inited;
 extern struct page_ext_operations page_owner_ops;
 
 extern void __reset_page_owner(struct page *page, unsigned int order);
 extern void __set_page_owner(struct page *page,
                        unsigned int order, gfp_t gfp_mask);
 extern gfp_t __get_page_owner_gfp(struct page *page);
+extern void __copy_page_owner(struct page *oldpage, struct page *newpage);
+extern void __set_page_owner_migrate_reason(struct page *page, int reason);
+extern void __dump_page_owner(struct page *page);
 
 static inline void reset_page_owner(struct page *page, unsigned int order)
 {
-       if (likely(!page_owner_inited))
-               return;
-
-       __reset_page_owner(page, order);
+       if (static_branch_unlikely(&page_owner_inited))
+               __reset_page_owner(page, order);
 }
 
 static inline void set_page_owner(struct page *page,
                        unsigned int order, gfp_t gfp_mask)
 {
-       if (likely(!page_owner_inited))
-               return;
-
-       __set_page_owner(page, order, gfp_mask);
+       if (static_branch_unlikely(&page_owner_inited))
+               __set_page_owner(page, order, gfp_mask);
 }
 
 static inline gfp_t get_page_owner_gfp(struct page *page)
 {
-       if (likely(!page_owner_inited))
+       if (static_branch_unlikely(&page_owner_inited))
+               return __get_page_owner_gfp(page);
+       else
                return 0;
-
-       return __get_page_owner_gfp(page);
+}
+static inline void copy_page_owner(struct page *oldpage, struct page *newpage)
+{
+       if (static_branch_unlikely(&page_owner_inited))
+               __copy_page_owner(oldpage, newpage);
+}
+static inline void set_page_owner_migrate_reason(struct page *page, int reason)
+{
+       if (static_branch_unlikely(&page_owner_inited))
+               __set_page_owner_migrate_reason(page, reason);
+}
+static inline void dump_page_owner(struct page *page)
+{
+       if (static_branch_unlikely(&page_owner_inited))
+               __dump_page_owner(page);
 }
 #else
 static inline void reset_page_owner(struct page *page, unsigned int order)
@@ -46,6 +62,14 @@ static inline gfp_t get_page_owner_gfp(struct page *page)
 {
        return 0;
 }
-
+static inline void copy_page_owner(struct page *oldpage, struct page *newpage)
+{
+}
+static inline void set_page_owner_migrate_reason(struct page *page, int reason)
+{
+}
+static inline void dump_page_owner(struct page *page)
+{
+}
 #endif /* CONFIG_PAGE_OWNER */
 #endif /* __LINUX_PAGE_OWNER_H */
index 92395a0a7dc5c436cdd43317a798b6d15eba5a5e..183b15ea052ba1abe1ce8831c99efc323438e284 100644 (file)
@@ -663,8 +663,7 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
                                pgoff_t index, gfp_t gfp_mask);
 extern void delete_from_page_cache(struct page *page);
-extern void __delete_from_page_cache(struct page *page, void *shadow,
-                                    struct mem_cgroup *memcg);
+extern void __delete_from_page_cache(struct page *page, void *shadow);
 int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask);
 
 /*
diff --git a/include/linux/pci-dma-compat.h b/include/linux/pci-dma-compat.h
new file mode 100644 (file)
index 0000000..39726ca
--- /dev/null
@@ -0,0 +1,147 @@
+/* include this file if the platform implements the dma_ DMA Mapping API
+ * and wants to provide the pci_ DMA Mapping API in terms of it */
+
+#ifndef _ASM_GENERIC_PCI_DMA_COMPAT_H
+#define _ASM_GENERIC_PCI_DMA_COMPAT_H
+
+#include <linux/dma-mapping.h>
+
+/* This defines the direction arg to the DMA mapping routines. */
+#define PCI_DMA_BIDIRECTIONAL  0
+#define PCI_DMA_TODEVICE       1
+#define PCI_DMA_FROMDEVICE     2
+#define PCI_DMA_NONE           3
+
+static inline void *
+pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+                    dma_addr_t *dma_handle)
+{
+       return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle, GFP_ATOMIC);
+}
+
+static inline void *
+pci_zalloc_consistent(struct pci_dev *hwdev, size_t size,
+                     dma_addr_t *dma_handle)
+{
+       return dma_zalloc_coherent(hwdev == NULL ? NULL : &hwdev->dev,
+                                  size, dma_handle, GFP_ATOMIC);
+}
+
+static inline void
+pci_free_consistent(struct pci_dev *hwdev, size_t size,
+                   void *vaddr, dma_addr_t dma_handle)
+{
+       dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, vaddr, dma_handle);
+}
+
+static inline dma_addr_t
+pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+{
+       return dma_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+                size_t size, int direction)
+{
+       dma_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
+}
+
+static inline dma_addr_t
+pci_map_page(struct pci_dev *hwdev, struct page *page,
+            unsigned long offset, size_t size, int direction)
+{
+       return dma_map_page(hwdev == NULL ? NULL : &hwdev->dev, page, offset, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
+              size_t size, int direction)
+{
+       dma_unmap_page(hwdev == NULL ? NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction)direction);
+}
+
+static inline int
+pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+          int nents, int direction)
+{
+       return dma_map_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+            int nents, int direction)
+{
+       dma_unmap_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle,
+                   size_t size, int direction)
+{
+       dma_sync_single_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
+                   size_t size, int direction)
+{
+       dma_sync_single_for_device(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg,
+               int nelems, int direction)
+{
+       dma_sync_sg_for_cpu(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
+}
+
+static inline void
+pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
+               int nelems, int direction)
+{
+       dma_sync_sg_for_device(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
+}
+
+static inline int
+pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr)
+{
+       return dma_mapping_error(&pdev->dev, dma_addr);
+}
+
+#ifdef CONFIG_PCI
+static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{
+       return dma_set_mask(&dev->dev, mask);
+}
+
+static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{
+       return dma_set_coherent_mask(&dev->dev, mask);
+}
+
+static inline int pci_set_dma_max_seg_size(struct pci_dev *dev,
+                                          unsigned int size)
+{
+       return dma_set_max_seg_size(&dev->dev, size);
+}
+
+static inline int pci_set_dma_seg_boundary(struct pci_dev *dev,
+                                          unsigned long mask)
+{
+       return dma_set_seg_boundary(&dev->dev, mask);
+}
+#else
+static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
+{ return -EIO; }
+static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+{ return -EIO; }
+static inline int pci_set_dma_max_seg_size(struct pci_dev *dev,
+                                          unsigned int size)
+{ return -EIO; }
+static inline int pci_set_dma_seg_boundary(struct pci_dev *dev,
+                                          unsigned long mask)
+{ return -EIO; }
+#endif
+
+#endif
index 27df4a6585daedcc6a74865bf048cfd06a0593ba..17e17c2ee1e6fafabd5ce8ea9841d384434b321e 100644 (file)
@@ -70,12 +70,6 @@ enum pci_mmap_state {
        pci_mmap_mem
 };
 
-/* This defines the direction arg to the DMA mapping routines. */
-#define PCI_DMA_BIDIRECTIONAL  0
-#define PCI_DMA_TODEVICE       1
-#define PCI_DMA_FROMDEVICE     2
-#define PCI_DMA_NONE           3
-
 /*
  *  For PCI devices, the region numbers are assigned this way:
  */
@@ -359,6 +353,7 @@ struct pci_dev {
        unsigned int    io_window_1k:1; /* Intel P2P bridge 1K I/O windows */
        unsigned int    irq_managed:1;
        unsigned int    has_secondary_link:1;
+       unsigned int    non_compliant_bars:1;   /* broken BARs; ignore them */
        pci_dev_flags_t dev_flags;
        atomic_t        enable_cnt;     /* pci_enable_device has been called */
 
@@ -578,6 +573,8 @@ static inline int pcibios_err_to_errno(int err)
 /* Low-level architecture-dependent routines */
 
 struct pci_ops {
+       int (*add_bus)(struct pci_bus *bus);
+       void (*remove_bus)(struct pci_bus *bus);
        void __iomem *(*map_bus)(struct pci_bus *bus, unsigned int devfn, int where);
        int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
        int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
@@ -746,9 +743,26 @@ struct pci_driver {
        .vendor = PCI_VENDOR_ID_##vend, .device = (dev), \
        .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0
 
+enum {
+       PCI_REASSIGN_ALL_RSRC   = 0x00000001,   /* ignore firmware setup */
+       PCI_REASSIGN_ALL_BUS    = 0x00000002,   /* reassign all bus numbers */
+       PCI_PROBE_ONLY          = 0x00000004,   /* use existing setup */
+       PCI_CAN_SKIP_ISA_ALIGN  = 0x00000008,   /* don't do ISA alignment */
+       PCI_ENABLE_PROC_DOMAINS = 0x00000010,   /* enable domains in /proc */
+       PCI_COMPAT_DOMAIN_0     = 0x00000020,   /* ... except domain 0 */
+       PCI_SCAN_ALL_PCIE_DEVS  = 0x00000040,   /* scan all, not just dev 0 */
+};
+
 /* these external functions are only available when PCI support is enabled */
 #ifdef CONFIG_PCI
 
+extern unsigned int pci_flags;
+
+static inline void pci_set_flags(int flags) { pci_flags = flags; }
+static inline void pci_add_flags(int flags) { pci_flags |= flags; }
+static inline void pci_clear_flags(int flags) { pci_flags &= ~flags; }
+static inline int pci_has_flag(int flag) { return pci_flags & flag; }
+
 void pcie_bus_configure_settings(struct pci_bus *bus);
 
 enum pcie_bus_config_types {
@@ -988,23 +1002,6 @@ static inline int pci_is_managed(struct pci_dev *pdev)
        return pdev->is_managed;
 }
 
-static inline void pci_set_managed_irq(struct pci_dev *pdev, unsigned int irq)
-{
-       pdev->irq = irq;
-       pdev->irq_managed = 1;
-}
-
-static inline void pci_reset_managed_irq(struct pci_dev *pdev)
-{
-       pdev->irq = 0;
-       pdev->irq_managed = 0;
-}
-
-static inline bool pci_has_managed_irq(struct pci_dev *pdev)
-{
-       return pdev->irq_managed && pdev->irq > 0;
-}
-
 void pci_disable_device(struct pci_dev *dev);
 
 extern unsigned int pcibios_max_latency;
@@ -1021,8 +1018,6 @@ void pci_intx(struct pci_dev *dev, int enable);
 bool pci_intx_mask_supported(struct pci_dev *dev);
 bool pci_check_and_mask_intx(struct pci_dev *dev);
 bool pci_check_and_unmask_intx(struct pci_dev *dev);
-int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
-int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
 int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask);
 int pci_wait_for_pending_transaction(struct pci_dev *dev);
 int pcix_get_max_mmrbc(struct pci_dev *dev);
@@ -1238,6 +1233,7 @@ resource_size_t pcibios_iov_resource_alignment(struct pci_dev *dev, int resno);
 
 int pci_set_vga_state(struct pci_dev *pdev, bool decode,
                      unsigned int command_bits, u32 flags);
+
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 
 #include <linux/pci-dma.h>
@@ -1405,6 +1401,11 @@ void pci_register_set_vga_state(arch_set_vga_state_t func);
 
 #else /* CONFIG_PCI is not enabled */
 
+static inline void pci_set_flags(int flags) { }
+static inline void pci_add_flags(int flags) { }
+static inline void pci_clear_flags(int flags) { }
+static inline int pci_has_flag(int flag) { return 0; }
+
 /*
  *  If the system does not have PCI, clearly these return errors.  Define
  *  these as simple inline functions to avoid hair in drivers.
@@ -1444,16 +1445,6 @@ static inline struct pci_dev *pci_get_class(unsigned int class,
 static inline void pci_set_master(struct pci_dev *dev) { }
 static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; }
 static inline void pci_disable_device(struct pci_dev *dev) { }
-static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{ return -EIO; }
-static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{ return -EIO; }
-static inline int pci_set_dma_max_seg_size(struct pci_dev *dev,
-                                       unsigned int size)
-{ return -EIO; }
-static inline int pci_set_dma_seg_boundary(struct pci_dev *dev,
-                                       unsigned long mask)
-{ return -EIO; }
 static inline int pci_assign_resource(struct pci_dev *dev, int i)
 { return -EBUSY; }
 static inline int __pci_register_driver(struct pci_driver *drv,
@@ -1515,6 +1506,10 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
 
 #include <asm/pci.h>
 
+#ifndef pci_root_bus_fwnode
+#define pci_root_bus_fwnode(bus)       NULL
+#endif
+
 /* these helpers provide future and backwards compatibility
  * for accessing popular PCI BAR info */
 #define pci_resource_start(dev, bar)   ((dev)->resource[(bar)].start)
@@ -1834,12 +1829,13 @@ bool pci_acs_path_enabled(struct pci_dev *start,
 #define PCI_VPD_LRDT_RW_DATA           PCI_VPD_LRDT_ID(PCI_VPD_LTIN_RW_DATA)
 
 /* Small Resource Data Type Tag Item Names */
-#define PCI_VPD_STIN_END               0x78    /* End */
+#define PCI_VPD_STIN_END               0x0f    /* End */
 
-#define PCI_VPD_SRDT_END               PCI_VPD_STIN_END
+#define PCI_VPD_SRDT_END               (PCI_VPD_STIN_END << 3)
 
 #define PCI_VPD_SRDT_TIN_MASK          0x78
 #define PCI_VPD_SRDT_LEN_MASK          0x07
+#define PCI_VPD_LRDT_TIN_MASK          0x7f
 
 #define PCI_VPD_LRDT_TAG_SIZE          3
 #define PCI_VPD_SRDT_TAG_SIZE          1
@@ -1862,6 +1858,17 @@ static inline u16 pci_vpd_lrdt_size(const u8 *lrdt)
        return (u16)lrdt[1] + ((u16)lrdt[2] << 8);
 }
 
+/**
+ * pci_vpd_lrdt_tag - Extracts the Large Resource Data Type Tag Item
+ * @lrdt: Pointer to the beginning of the Large Resource Data Type tag
+ *
+ * Returns the extracted Large Resource Data Type Tag item.
+ */
+static inline u16 pci_vpd_lrdt_tag(const u8 *lrdt)
+{
+    return (u16)(lrdt[0] & PCI_VPD_LRDT_TIN_MASK);
+}
+
 /**
  * pci_vpd_srdt_size - Extracts the Small Resource Data Type length
  * @lrdt: Pointer to the beginning of the Small Resource Data Type tag
@@ -1873,6 +1880,17 @@ static inline u8 pci_vpd_srdt_size(const u8 *srdt)
        return (*srdt) & PCI_VPD_SRDT_LEN_MASK;
 }
 
+/**
+ * pci_vpd_srdt_tag - Extracts the Small Resource Data Type Tag Item
+ * @lrdt: Pointer to the beginning of the Small Resource Data Type tag
+ *
+ * Returns the extracted Small Resource Data Type Tag Item.
+ */
+static inline u8 pci_vpd_srdt_tag(const u8 *srdt)
+{
+       return ((*srdt) & PCI_VPD_SRDT_TIN_MASK) >> 3;
+}
+
 /**
  * pci_vpd_info_field_size - Extracts the information field length
  * @lrdt: Pointer to the beginning of an information field header
@@ -1989,4 +2007,8 @@ static inline bool pci_ari_enabled(struct pci_bus *bus)
 {
        return bus->self && bus->self->ari_enabled;
 }
+
+/* provide the legacy pci_dma_* API */
+#include <linux/pci-dma-compat.h>
+
 #endif /* LINUX_PCI_H */
index 37f05cb1dfd6d93cae1ceeffc8a3de1c0fcb0529..247da8c9586073d6759d333051909c5c4d050315 100644 (file)
 #define PCI_CLASS_SERIAL_USB_OHCI      0x0c0310
 #define PCI_CLASS_SERIAL_USB_EHCI      0x0c0320
 #define PCI_CLASS_SERIAL_USB_XHCI      0x0c0330
+#define PCI_CLASS_SERIAL_USB_DEVICE    0x0c03fe
 #define PCI_CLASS_SERIAL_FIBER         0x0c04
 #define PCI_CLASS_SERIAL_SMBUS         0x0c05
 
 
 #define PCI_VENDOR_ID_AZWAVE           0x1a3b
 
+#define PCI_VENDOR_ID_REDHAT_QUMRANET    0x1af4
+#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
+#define PCI_SUBDEVICE_ID_QEMU            0x1100
+
 #define PCI_VENDOR_ID_ASMEDIA          0x1b21
 
 #define PCI_VENDOR_ID_CIRCUITCO                0x1cc8
index b35a61a481fa0460b3b32591e6dd52f2fa9077e7..79ec7bbf01557e523aee3ed263425b6fc3360741 100644 (file)
@@ -397,6 +397,7 @@ struct pmu {
  * enum perf_event_active_state - the states of a event
  */
 enum perf_event_active_state {
+       PERF_EVENT_STATE_DEAD           = -4,
        PERF_EVENT_STATE_EXIT           = -3,
        PERF_EVENT_STATE_ERROR          = -2,
        PERF_EVENT_STATE_OFF            = -1,
@@ -467,6 +468,7 @@ struct perf_event {
        int                             group_flags;
        struct perf_event               *group_leader;
        struct pmu                      *pmu;
+       void                            *pmu_private;
 
        enum perf_event_active_state    state;
        unsigned int                    attach_state;
@@ -905,7 +907,7 @@ perf_sw_event_sched(u32 event_id, u64 nr, u64 addr)
        }
 }
 
-extern struct static_key_deferred perf_sched_events;
+extern struct static_key_false perf_sched_events;
 
 static __always_inline bool
 perf_sw_migrate_enabled(void)
@@ -924,7 +926,7 @@ static inline void perf_event_task_migrate(struct task_struct *task)
 static inline void perf_event_task_sched_in(struct task_struct *prev,
                                            struct task_struct *task)
 {
-       if (static_key_false(&perf_sched_events.key))
+       if (static_branch_unlikely(&perf_sched_events))
                __perf_event_task_sched_in(prev, task);
 
        if (perf_sw_migrate_enabled() && task->sched_migrated) {
@@ -941,7 +943,7 @@ static inline void perf_event_task_sched_out(struct task_struct *prev,
 {
        perf_sw_event_sched(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 0);
 
-       if (static_key_false(&perf_sched_events.key))
+       if (static_branch_unlikely(&perf_sched_events))
                __perf_event_task_sched_out(prev, next);
 }
 
@@ -1108,12 +1110,6 @@ static inline void perf_event_task_tick(void)                            { }
 static inline int perf_event_release_kernel(struct perf_event *event)  { return 0; }
 #endif
 
-#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_NO_HZ_FULL)
-extern bool perf_event_can_stop_tick(void);
-#else
-static inline bool perf_event_can_stop_tick(void)                      { return true; }
-#endif
-
 #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL)
 extern void perf_restore_debug_store(void);
 #else
index aed170588b747c05a50eedfda9cdb5e7ea48bc86..698d0d59db761b3cae1d75d5b88a67603dc2c187 100644 (file)
@@ -28,6 +28,7 @@ enum ntc_thermistor_type {
        TYPE_NCPXXWL333,
        TYPE_B57330V2103,
        TYPE_NCPXXWF104,
+       TYPE_NCPXXXH103,
 };
 
 struct ntc_thermistor_platform_data {
index db21d3995f7e339f7f7f7f1adf21536c7b9a4e8b..49cd8890b87348a7b0246a320ff80dd54d7232a7 100644 (file)
@@ -19,6 +19,8 @@
 /* Defines used for the flags field in the struct generic_pm_domain */
 #define GENPD_FLAG_PM_CLK      (1U << 0) /* PM domain uses PM clk */
 
+#define GENPD_MAX_NUM_STATES   8 /* Number of possible low power states */
+
 enum gpd_status {
        GPD_STATE_ACTIVE = 0,   /* PM domain is active */
        GPD_STATE_POWER_OFF,    /* PM domain is off */
@@ -37,6 +39,11 @@ struct gpd_dev_ops {
        bool (*active_wakeup)(struct device *dev);
 };
 
+struct genpd_power_state {
+       s64 power_off_latency_ns;
+       s64 power_on_latency_ns;
+};
+
 struct generic_pm_domain {
        struct dev_pm_domain domain;    /* PM domain operations */
        struct list_head gpd_list_node; /* Node in the global PM domains list */
@@ -54,9 +61,7 @@ struct generic_pm_domain {
        unsigned int prepared_count;    /* Suspend counter of prepared devices */
        bool suspend_power_off; /* Power status before system suspend */
        int (*power_off)(struct generic_pm_domain *domain);
-       s64 power_off_latency_ns;
        int (*power_on)(struct generic_pm_domain *domain);
-       s64 power_on_latency_ns;
        struct gpd_dev_ops dev_ops;
        s64 max_off_time_ns;    /* Maximum allowed "suspended" time. */
        bool max_off_time_changed;
@@ -66,6 +71,10 @@ struct generic_pm_domain {
        void (*detach_dev)(struct generic_pm_domain *domain,
                           struct device *dev);
        unsigned int flags;             /* Bit field of configs for genpd */
+       struct genpd_power_state states[GENPD_MAX_NUM_STATES];
+       unsigned int state_count; /* number of states */
+       unsigned int state_idx; /* state that genpd will go to when off */
+
 };
 
 static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
index 95403d2ccaf56b70207fa09e65c592d882fb30fd..cccaf4a29e9f02c9a60b65f73a523a69efa5af3a 100644 (file)
@@ -34,6 +34,8 @@ bool dev_pm_opp_is_turbo(struct dev_pm_opp *opp);
 
 int dev_pm_opp_get_opp_count(struct device *dev);
 unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev);
+unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev);
+unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev);
 struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev);
 
 struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
@@ -60,6 +62,9 @@ int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
 void dev_pm_opp_put_supported_hw(struct device *dev);
 int dev_pm_opp_set_prop_name(struct device *dev, const char *name);
 void dev_pm_opp_put_prop_name(struct device *dev);
+int dev_pm_opp_set_regulator(struct device *dev, const char *name);
+void dev_pm_opp_put_regulator(struct device *dev);
+int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq);
 #else
 static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
 {
@@ -86,6 +91,16 @@ static inline unsigned long dev_pm_opp_get_max_clock_latency(struct device *dev)
        return 0;
 }
 
+static inline unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
+{
+       return 0;
+}
+
+static inline unsigned long dev_pm_opp_get_max_transition_latency(struct device *dev)
+{
+       return 0;
+}
+
 static inline struct dev_pm_opp *dev_pm_opp_get_suspend_opp(struct device *dev)
 {
        return NULL;
@@ -151,6 +166,18 @@ static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
 
 static inline void dev_pm_opp_put_prop_name(struct device *dev) {}
 
+static inline int dev_pm_opp_set_regulator(struct device *dev, const char *name)
+{
+       return -EINVAL;
+}
+
+static inline void dev_pm_opp_put_regulator(struct device *dev) {}
+
+static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
+{
+       return -EINVAL;
+}
+
 #endif         /* CONFIG_PM_OPP */
 
 #if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
index 4a27153574e2839546fb40ee8e8afea483e33cef..51334edec506815a70868dd451d5c72944ed0a59 100644 (file)
 #define TIMER_ENTRY_STATIC     ((void *) 0x300 + POISON_POINTER_DELTA)
 
 /********** mm/debug-pagealloc.c **********/
+#ifdef CONFIG_PAGE_POISONING_ZERO
+#define PAGE_POISON 0x00
+#else
 #define PAGE_POISON 0xaa
+#endif
 
 /********** mm/page_alloc.c ************/
 
index 907f3fd191acaa1573445a0988e5161b8e408ec3..62d44c176071833ab644d46a95ec910fb1ee57e7 100644 (file)
@@ -128,9 +128,6 @@ void posix_cpu_timer_schedule(struct k_itimer *timer);
 void run_posix_cpu_timers(struct task_struct *task);
 void posix_cpu_timers_exit(struct task_struct *task);
 void posix_cpu_timers_exit_group(struct task_struct *task);
-
-bool posix_cpu_timers_can_stop_tick(struct task_struct *tsk);
-
 void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
                           cputime_t *newval, cputime_t *oldval);
 
index 998d8f1c3c9172037ef185963f415dbb0fad999f..b50c0492629dbfa9f902f214ad714f1c2df372bc 100644 (file)
@@ -49,6 +49,7 @@ struct bq27xxx_reg_cache {
 
 struct bq27xxx_device_info {
        struct device *dev;
+       int id;
        enum bq27xxx_chip chip;
        const char *name;
        struct bq27xxx_access_methods bus;
index 54bf1484d41f0333cc860c84307d23eda76477e5..35ac903956c7c0c282a9b0cfd74004212c8eb10d 100644 (file)
@@ -111,22 +111,17 @@ static inline void timespec_to_pps_ktime(struct pps_ktime *kt,
        kt->nsec = ts.tv_nsec;
 }
 
-#ifdef CONFIG_NTP_PPS
-
 static inline void pps_get_ts(struct pps_event_time *ts)
 {
-       ktime_get_raw_and_real_ts64(&ts->ts_raw, &ts->ts_real);
-}
+       struct system_time_snapshot snap;
 
-#else /* CONFIG_NTP_PPS */
-
-static inline void pps_get_ts(struct pps_event_time *ts)
-{
-       ktime_get_real_ts64(&ts->ts_real);
+       ktime_get_snapshot(&snap);
+       ts->ts_real = ktime_to_timespec64(snap.real);
+#ifdef CONFIG_NTP_PPS
+       ts->ts_raw = ktime_to_timespec64(snap.raw);
+#endif
 }
 
-#endif /* CONFIG_NTP_PPS */
-
 /* Subtract known time delay from PPS event time(s) */
 static inline void pps_sub_ts(struct pps_event_time *ts, struct timespec64 delta)
 {
index b8b73066d1379087f1ecd5bd40dbf719ad2af4ad..6b15e168148a3be73c52c35da6fc4a0f4a5b6ba6 100644 (file)
@@ -38,6 +38,7 @@ struct ptp_clock_request {
        };
 };
 
+struct system_device_crosststamp;
 /**
  * struct ptp_clock_info - decribes a PTP hardware clock
  *
@@ -67,6 +68,11 @@ struct ptp_clock_request {
  * @gettime64:  Reads the current time from the hardware clock.
  *              parameter ts: Holds the result.
  *
+ * @getcrosststamp:  Reads the current time from the hardware clock and
+ *                   system clock simultaneously.
+ *                   parameter cts: Contains timestamp (device,system) pair,
+ *                   where system time is realtime and monotonic.
+ *
  * @settime64:  Set the current time on the hardware clock.
  *              parameter ts: Time value to set.
  *
@@ -105,6 +111,8 @@ struct ptp_clock_info {
        int (*adjfreq)(struct ptp_clock_info *ptp, s32 delta);
        int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
        int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);
+       int (*getcrosststamp)(struct ptp_clock_info *ptp,
+                             struct system_device_crosststamp *cts);
        int (*settime64)(struct ptp_clock_info *p, const struct timespec64 *ts);
        int (*enable)(struct ptp_clock_info *ptp,
                      struct ptp_clock_request *request, int on);
index c2f2574ff61ceebbe4729df6d577722b391d0600..2a097d176ba964faae345a245f516c447701553c 100644 (file)
@@ -197,6 +197,7 @@ enum pxa_ssp_type {
        QUARK_X1000_SSP,
        LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */
        LPSS_BYT_SSP,
+       LPSS_BSW_SSP,
        LPSS_SPT_SSP,
        LPSS_BXT_SSP,
 };
index a75840c1aa71414acc43468da6cc8f83ec06c1b8..9c29122037f95283cc02b8af995975e80e059abd 100644 (file)
@@ -34,6 +34,7 @@ extern const struct file_operations random_fops, urandom_fops;
 #endif
 
 unsigned int get_random_int(void);
+unsigned long get_random_long(void);
 unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
 
 u32 prandom_u32(void);
index 14e6f47ee16fe49774894f7e9107d4357b2ce0a7..2657aff2725b4fdc8243e7beb836747bbd5817d6 100644 (file)
@@ -332,9 +332,7 @@ void rcu_init(void);
 void rcu_sched_qs(void);
 void rcu_bh_qs(void);
 void rcu_check_callbacks(int user);
-struct notifier_block;
-int rcu_cpu_notify(struct notifier_block *self,
-                  unsigned long action, void *hcpu);
+void rcu_report_dead(unsigned int cpu);
 
 #ifndef CONFIG_TINY_RCU
 void rcu_end_inkernel_boot(void);
@@ -360,8 +358,6 @@ void rcu_user_exit(void);
 #else
 static inline void rcu_user_enter(void) { }
 static inline void rcu_user_exit(void) { }
-static inline void rcu_user_hooks_switch(struct task_struct *prev,
-                                        struct task_struct *next) { }
 #endif /* CONFIG_NO_HZ_FULL */
 
 #ifdef CONFIG_RCU_NOCB_CPU
index 18394343f4891a42dc986e4a17e9c9ebb0b747ee..3dc08ce15426e67eff3cd1c785544c6877603e97 100644 (file)
@@ -65,6 +65,36 @@ struct reg_sequence {
        unsigned int delay_us;
 };
 
+#define        regmap_update_bits(map, reg, mask, val) \
+       regmap_update_bits_base(map, reg, mask, val, NULL, false, false)
+#define        regmap_update_bits_async(map, reg, mask, val)\
+       regmap_update_bits_base(map, reg, mask, val, NULL, true, false)
+#define        regmap_update_bits_check(map, reg, mask, val, change)\
+       regmap_update_bits_base(map, reg, mask, val, change, false, false)
+#define        regmap_update_bits_check_async(map, reg, mask, val, change)\
+       regmap_update_bits_base(map, reg, mask, val, change, true, false)
+
+#define        regmap_write_bits(map, reg, mask, val) \
+       regmap_update_bits_base(map, reg, mask, val, NULL, false, true)
+
+#define        regmap_field_write(field, val) \
+       regmap_field_update_bits_base(field, ~0, val, NULL, false, false)
+#define        regmap_field_force_write(field, val) \
+       regmap_field_update_bits_base(field, ~0, val, NULL, false, true)
+#define        regmap_field_update_bits(field, mask, val)\
+       regmap_field_update_bits_base(field, mask, val, NULL, false, false)
+#define        regmap_field_force_update_bits(field, mask, val) \
+       regmap_field_update_bits_base(field, mask, val, NULL, false, true)
+
+#define        regmap_fields_write(field, id, val) \
+       regmap_fields_update_bits_base(field, id, ~0, val, NULL, false, false)
+#define        regmap_fields_force_write(field, id, val) \
+       regmap_fields_update_bits_base(field, id, ~0, val, NULL, false, true)
+#define        regmap_fields_update_bits(field, id, mask, val)\
+       regmap_fields_update_bits_base(field, id, mask, val, NULL, false, false)
+#define        regmap_fields_force_update_bits(field, id, mask, val) \
+       regmap_fields_update_bits_base(field, id, mask, val, NULL, false, true)
+
 #ifdef CONFIG_REGMAP
 
 enum regmap_endian {
@@ -162,7 +192,7 @@ typedef void (*regmap_unlock)(void *);
  *               This field is a duplicate of a similar file in
  *               'struct regmap_bus' and serves exact same purpose.
  *                Use it only for "no-bus" cases.
- * @max_register: Optional, specifies the maximum valid register index.
+ * @max_register: Optional, specifies the maximum valid register address.
  * @wr_table:     Optional, points to a struct regmap_access_table specifying
  *                valid ranges for write access.
  * @rd_table:     As above, for read access.
@@ -691,18 +721,9 @@ int regmap_raw_read(struct regmap *map, unsigned int reg,
                    void *val, size_t val_len);
 int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
                     size_t val_count);
-int regmap_update_bits(struct regmap *map, unsigned int reg,
-                      unsigned int mask, unsigned int val);
-int regmap_write_bits(struct regmap *map, unsigned int reg,
-                      unsigned int mask, unsigned int val);
-int regmap_update_bits_async(struct regmap *map, unsigned int reg,
-                            unsigned int mask, unsigned int val);
-int regmap_update_bits_check(struct regmap *map, unsigned int reg,
-                            unsigned int mask, unsigned int val,
-                            bool *change);
-int regmap_update_bits_check_async(struct regmap *map, unsigned int reg,
-                                  unsigned int mask, unsigned int val,
-                                  bool *change);
+int regmap_update_bits_base(struct regmap *map, unsigned int reg,
+                           unsigned int mask, unsigned int val,
+                           bool *change, bool async, bool force);
 int regmap_get_val_bytes(struct regmap *map);
 int regmap_get_max_register(struct regmap *map);
 int regmap_get_reg_stride(struct regmap *map);
@@ -770,18 +791,14 @@ struct regmap_field *devm_regmap_field_alloc(struct device *dev,
 void devm_regmap_field_free(struct device *dev,        struct regmap_field *field);
 
 int regmap_field_read(struct regmap_field *field, unsigned int *val);
-int regmap_field_write(struct regmap_field *field, unsigned int val);
-int regmap_field_update_bits(struct regmap_field *field,
-                            unsigned int mask, unsigned int val);
-
-int regmap_fields_write(struct regmap_field *field, unsigned int id,
-                       unsigned int val);
-int regmap_fields_force_write(struct regmap_field *field, unsigned int id,
-                       unsigned int val);
+int regmap_field_update_bits_base(struct regmap_field *field,
+                                 unsigned int mask, unsigned int val,
+                                 bool *change, bool async, bool force);
 int regmap_fields_read(struct regmap_field *field, unsigned int id,
                       unsigned int *val);
-int regmap_fields_update_bits(struct regmap_field *field,  unsigned int id,
-                             unsigned int mask, unsigned int val);
+int regmap_fields_update_bits_base(struct regmap_field *field,  unsigned int id,
+                                  unsigned int mask, unsigned int val,
+                                  bool *change, bool async, bool force);
 
 /**
  * Description of an IRQ for the generic regmap irq_chip.
@@ -868,6 +885,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
                        int irq_base, const struct regmap_irq_chip *chip,
                        struct regmap_irq_chip_data **data);
 void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
+
+int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
+                            int irq_flags, int irq_base,
+                            const struct regmap_irq_chip *chip,
+                            struct regmap_irq_chip_data **data);
+void devm_regmap_del_irq_chip(struct device *dev, int irq,
+                             struct regmap_irq_chip_data *data);
+
 int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
 int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
 struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data);
@@ -937,42 +962,26 @@ static inline int regmap_bulk_read(struct regmap *map, unsigned int reg,
        return -EINVAL;
 }
 
-static inline int regmap_update_bits(struct regmap *map, unsigned int reg,
-                                    unsigned int mask, unsigned int val)
-{
-       WARN_ONCE(1, "regmap API is disabled");
-       return -EINVAL;
-}
-
-static inline int regmap_write_bits(struct regmap *map, unsigned int reg,
-                                    unsigned int mask, unsigned int val)
-{
-       WARN_ONCE(1, "regmap API is disabled");
-       return -EINVAL;
-}
-
-static inline int regmap_update_bits_async(struct regmap *map,
-                                          unsigned int reg,
-                                          unsigned int mask, unsigned int val)
+static inline int regmap_update_bits_base(struct regmap *map, unsigned int reg,
+                                         unsigned int mask, unsigned int val,
+                                         bool *change, bool async, bool force)
 {
        WARN_ONCE(1, "regmap API is disabled");
        return -EINVAL;
 }
 
-static inline int regmap_update_bits_check(struct regmap *map,
-                                          unsigned int reg,
-                                          unsigned int mask, unsigned int val,
-                                          bool *change)
+static inline int regmap_field_update_bits_base(struct regmap_field *field,
+                                       unsigned int mask, unsigned int val,
+                                       bool *change, bool async, bool force)
 {
        WARN_ONCE(1, "regmap API is disabled");
        return -EINVAL;
 }
 
-static inline int regmap_update_bits_check_async(struct regmap *map,
-                                                unsigned int reg,
-                                                unsigned int mask,
-                                                unsigned int val,
-                                                bool *change)
+static inline int regmap_fields_update_bits_base(struct regmap_field *field,
+                                  unsigned int id,
+                                  unsigned int mask, unsigned int val,
+                                  bool *change, bool async, bool force)
 {
        WARN_ONCE(1, "regmap API is disabled");
        return -EINVAL;
index 15fa8f2d35c9a58fc2e563418ee00981eb1da13f..2eb386017fa58fe5106c27b7bf76a27214690249 100644 (file)
@@ -68,12 +68,12 @@ enum {
  * act8865_regulator_data - regulator data
  * @id: regulator id
  * @name: regulator name
- * @platform_data: regulator init data
+ * @init_data: regulator init data
  */
 struct act8865_regulator_data {
        int id;
        const char *name;
-       struct regulator_init_data *platform_data;
+       struct regulator_init_data *init_data;
 };
 
 /**
index 16ac9e108806469728373dc6838305639c19dbb3..cd271e89a7e61a3a4271b536767ae5c001bd53a6 100644 (file)
@@ -93,6 +93,8 @@ struct regulator_linear_range {
  * @get_current_limit: Get the configured limit for a current-limited regulator.
  * @set_input_current_limit: Configure an input limit.
  *
+ * @set_active_discharge: Set active discharge enable/disable of regulators.
+ *
  * @set_mode: Set the configured operating mode for the regulator.
  * @get_mode: Get the configured operating mode for the regulator.
  * @get_status: Return actual (not as-configured) status of regulator, as a
@@ -149,6 +151,7 @@ struct regulator_ops {
 
        int (*set_input_current_limit) (struct regulator_dev *, int lim_uA);
        int (*set_over_current_protection) (struct regulator_dev *);
+       int (*set_active_discharge) (struct regulator_dev *, bool enable);
 
        /* enable/disable regulator */
        int (*enable) (struct regulator_dev *);
@@ -266,6 +269,14 @@ enum regulator_type {
  * @bypass_mask: Mask for control when using regmap set_bypass
  * @bypass_val_on: Enabling value for control when using regmap set_bypass
  * @bypass_val_off: Disabling value for control when using regmap set_bypass
+ * @active_discharge_off: Enabling value for control when using regmap
+ *                       set_active_discharge
+ * @active_discharge_on: Disabling value for control when using regmap
+ *                      set_active_discharge
+ * @active_discharge_mask: Mask for control when using regmap
+ *                        set_active_discharge
+ * @active_discharge_reg: Register for control when using regmap
+ *                       set_active_discharge
  *
  * @enable_time: Time taken for initial enable of regulator (in uS).
  * @off_on_delay: guard time (in uS), before re-enabling a regulator
@@ -315,6 +326,10 @@ struct regulator_desc {
        unsigned int bypass_mask;
        unsigned int bypass_val_on;
        unsigned int bypass_val_off;
+       unsigned int active_discharge_on;
+       unsigned int active_discharge_off;
+       unsigned int active_discharge_mask;
+       unsigned int active_discharge_reg;
 
        unsigned int enable_time;
 
@@ -447,6 +462,8 @@ int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
 int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable);
 int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable);
 
+int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
+                                         bool enable);
 void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
 
 #endif
index 132e05c466617b9336d7e0db49ef8455f48f171b..6029279f4eed990a74ce8d8bdc8718dcf35ca606 100644 (file)
@@ -18,6 +18,9 @@
 
 #define LP872X_MAX_REGULATORS          9
 
+#define LP8720_ENABLE_DELAY            200
+#define LP8725_ENABLE_DELAY            30000
+
 enum lp872x_regulator_id {
        LP8720_ID_BASE,
        LP8720_ID_LDO1 = LP8720_ID_BASE,
@@ -79,12 +82,14 @@ struct lp872x_regulator_data {
  * @update_config     : if LP872X_GENERAL_CFG register is updated, set true
  * @regulator_data    : platform regulator id and init data
  * @dvs               : dvs data for buck voltage control
+ * @enable_gpio       : gpio pin number for enable control
  */
 struct lp872x_platform_data {
        u8 general_config;
        bool update_config;
        struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS];
        struct lp872x_dvs *dvs;
+       int enable_gpio;
 };
 
 #endif
index a1067d0b39916b869eebc6a179c3696a115e3996..5d627c83a6300e4aca26469a6c8e326fc75172c6 100644 (file)
@@ -42,6 +42,13 @@ struct regulator;
 #define REGULATOR_CHANGE_DRMS          0x10
 #define REGULATOR_CHANGE_BYPASS                0x20
 
+/* Regulator active discharge flags */
+enum regulator_active_discharge {
+       REGULATOR_ACTIVE_DISCHARGE_DEFAULT,
+       REGULATOR_ACTIVE_DISCHARGE_DISABLE,
+       REGULATOR_ACTIVE_DISCHARGE_ENABLE,
+};
+
 /**
  * struct regulator_state - regulator state during low power system states
  *
@@ -100,6 +107,9 @@ struct regulator_state {
  * @initial_state: Suspend state to set by default.
  * @initial_mode: Mode to set at startup.
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @active_discharge: Enable/disable active discharge. The enum
+ *                   regulator_active_discharge values are used for
+ *                   initialisation.
  * @enable_time: Turn-on time of the rails (unit: microseconds)
  */
 struct regulation_constraints {
@@ -140,6 +150,8 @@ struct regulation_constraints {
        unsigned int ramp_delay;
        unsigned int enable_time;
 
+       unsigned int active_discharge;
+
        /* constraint flags */
        unsigned always_on:1;   /* regulator never off when system is on */
        unsigned boot_on:1;     /* bootloader/firmware enabled regulator */
index 3359f0422c6b5bcf7c9385ecff8a90ce28dc1eae..b693adac853b24e02046d3ce040ad03ea04e8208 100644 (file)
@@ -89,6 +89,8 @@ struct rtc_class_ops {
        int (*set_mmss)(struct device *, unsigned long secs);
        int (*read_callback)(struct device *, int data);
        int (*alarm_irq_enable)(struct device *, unsigned int enabled);
+       int (*read_offset)(struct device *, long *offset);
+       int (*set_offset)(struct device *, long offset);
 };
 
 #define RTC_DEVICE_NAME_SIZE 20
@@ -208,6 +210,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data);
 int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
                    ktime_t expires, ktime_t period);
 void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer);
+int rtc_read_offset(struct rtc_device *rtc, long *offset);
+int rtc_set_offset(struct rtc_device *rtc, long offset);
 void rtc_timer_do_work(struct work_struct *work);
 
 static inline bool is_leap_year(unsigned int year)
index a10494a94cc30f24d65ab866771833883c6f886d..eb7f2f84009b823fa751a6fe52a8b8db7fe7ff64 100644 (file)
@@ -182,8 +182,6 @@ extern void update_cpu_load_nohz(int active);
 static inline void update_cpu_load_nohz(int active) { }
 #endif
 
-extern unsigned long get_parent_ip(unsigned long addr);
-
 extern void dump_cpu_task(int cpu);
 
 struct seq_file;
@@ -719,6 +717,10 @@ struct signal_struct {
        /* Earliest-expiration cache. */
        struct task_cputime cputime_expires;
 
+#ifdef CONFIG_NO_HZ_FULL
+       unsigned long tick_dep_mask;
+#endif
+
        struct list_head cpu_timers[3];
 
        struct pid *tty_old_pgrp;
@@ -920,6 +922,10 @@ static inline int sched_info_on(void)
 #endif
 }
 
+#ifdef CONFIG_SCHEDSTATS
+void force_schedstat_enabled(void);
+#endif
+
 enum cpu_idle_type {
        CPU_IDLE,
        CPU_NOT_IDLE,
@@ -1289,6 +1295,8 @@ struct sched_rt_entity {
        unsigned long timeout;
        unsigned long watchdog_stamp;
        unsigned int time_slice;
+       unsigned short on_rq;
+       unsigned short on_list;
 
        struct sched_rt_entity *back;
 #ifdef CONFIG_RT_GROUP_SCHED
@@ -1329,10 +1337,6 @@ struct sched_dl_entity {
         * task has to wait for a replenishment to be performed at the
         * next firing of dl_timer.
         *
-        * @dl_new tells if a new instance arrived. If so we must
-        * start executing it with full runtime and reset its absolute
-        * deadline;
-        *
         * @dl_boosted tells if we are boosted due to DI. If so we are
         * outside bandwidth enforcement mechanism (but only until we
         * exit the critical section);
@@ -1340,7 +1344,7 @@ struct sched_dl_entity {
         * @dl_yielded tells if task gave up the cpu before consuming
         * all its available runtime during the last job.
         */
-       int dl_throttled, dl_new, dl_boosted, dl_yielded;
+       int dl_throttled, dl_boosted, dl_yielded;
 
        /*
         * Bandwidth enforcement timer. Each -deadline task has its
@@ -1542,6 +1546,10 @@ struct task_struct {
                VTIME_SYS,
        } vtime_snap_whence;
 #endif
+
+#ifdef CONFIG_NO_HZ_FULL
+       unsigned long tick_dep_mask;
+#endif
        unsigned long nvcsw, nivcsw; /* context switch counts */
        u64 start_time;         /* monotonic time in nsec */
        u64 real_start_time;    /* boot based time in nsec */
@@ -2356,10 +2364,7 @@ static inline void wake_up_nohz_cpu(int cpu) { }
 #endif
 
 #ifdef CONFIG_NO_HZ_FULL
-extern bool sched_can_stop_tick(void);
 extern u64 scheduler_tick_max_deferment(void);
-#else
-static inline bool sched_can_stop_tick(void) { return false; }
 #endif
 
 #ifdef CONFIG_SCHED_AUTOGROUP
@@ -3207,4 +3212,13 @@ static inline unsigned long rlimit_max(unsigned int limit)
        return task_rlimit_max(current, limit);
 }
 
+#ifdef CONFIG_CPU_FREQ
+struct update_util_data {
+       void (*func)(struct update_util_data *data,
+                    u64 time, unsigned long util, unsigned long max);
+};
+
+void cpufreq_set_update_util_data(int cpu, struct update_util_data *data);
+#endif /* CONFIG_CPU_FREQ */
+
 #endif
index c9e4731cf10b8e97956b160c503e447490991931..4f080ab4f2cd1199f3f5aee15e7b06fdebb61333 100644 (file)
@@ -95,4 +95,8 @@ extern int sysctl_numa_balancing(struct ctl_table *table, int write,
                                 void __user *buffer, size_t *lenp,
                                 loff_t *ppos);
 
+extern int sysctl_schedstats(struct ctl_table *table, int write,
+                                void __user *buffer, size_t *lenp,
+                                loff_t *ppos);
+
 #endif /* _SCHED_SYSCTL_H */
index 4ce9ff7086f4897a67f6037d88df21012cf28413..d3fcd4591ce4ac1312a35710c81a9ff51211c140 100644 (file)
@@ -1985,6 +1985,30 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
        skb->tail += len;
 }
 
+/**
+ *     skb_tailroom_reserve - adjust reserved_tailroom
+ *     @skb: buffer to alter
+ *     @mtu: maximum amount of headlen permitted
+ *     @needed_tailroom: minimum amount of reserved_tailroom
+ *
+ *     Set reserved_tailroom so that headlen can be as large as possible but
+ *     not larger than mtu and tailroom cannot be smaller than
+ *     needed_tailroom.
+ *     The required headroom should already have been reserved before using
+ *     this function.
+ */
+static inline void skb_tailroom_reserve(struct sk_buff *skb, unsigned int mtu,
+                                       unsigned int needed_tailroom)
+{
+       SKB_LINEAR_ASSERT(skb);
+       if (mtu < skb_tailroom(skb) - needed_tailroom)
+               /* use at most mtu */
+               skb->reserved_tailroom = skb_tailroom(skb) - mtu;
+       else
+               /* use up to all available space */
+               skb->reserved_tailroom = needed_tailroom;
+}
+
 #define ENCAP_TYPE_ETHER       0
 #define ENCAP_TYPE_IPPROTO     1
 
index 3627d5c1bc470d7b655416e9a941cd2b4e378e03..e4b568738ca39b6a9fef289fc26e39a242e1d6c4 100644 (file)
@@ -20,7 +20,7 @@
  * Flags to pass to kmem_cache_create().
  * The ones marked DEBUG are only valid if CONFIG_DEBUG_SLAB is set.
  */
-#define SLAB_DEBUG_FREE                0x00000100UL    /* DEBUG: Perform (expensive) checks on free */
+#define SLAB_CONSISTENCY_CHECKS        0x00000100UL    /* DEBUG: Perform (expensive) checks on alloc/free */
 #define SLAB_RED_ZONE          0x00000400UL    /* DEBUG: Red zone objs in a cache */
 #define SLAB_POISON            0x00000800UL    /* DEBUG: Poison objects */
 #define SLAB_HWCACHE_ALIGN     0x00002000UL    /* Align objs on cache lines */
@@ -314,7 +314,7 @@ void *kmem_cache_alloc(struct kmem_cache *, gfp_t flags) __assume_slab_alignment
 void kmem_cache_free(struct kmem_cache *, void *);
 
 /*
- * Bulk allocation and freeing operations. These are accellerated in an
+ * Bulk allocation and freeing operations. These are accelerated in an
  * allocator specific way to avoid taking locks repeatedly or building
  * metadata structures unnecessarily.
  *
@@ -323,6 +323,15 @@ void kmem_cache_free(struct kmem_cache *, void *);
 void kmem_cache_free_bulk(struct kmem_cache *, size_t, void **);
 int kmem_cache_alloc_bulk(struct kmem_cache *, gfp_t, size_t, void **);
 
+/*
+ * Caller must not use kfree_bulk() on memory not originally allocated
+ * by kmalloc(), because the SLOB allocator cannot handle this.
+ */
+static __always_inline void kfree_bulk(size_t size, void **p)
+{
+       kmem_cache_free_bulk(NULL, size, p);
+}
+
 #ifdef CONFIG_NUMA
 void *__kmalloc_node(size_t size, gfp_t flags, int node) __assume_kmalloc_alignment;
 void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node) __assume_slab_alignment;
index cf139d3fa51392caa1ab4b4aa8304e1ad26cde3a..e878ba35ae913a46a7115df170663f682d930280 100644 (file)
@@ -60,6 +60,9 @@ struct kmem_cache {
        atomic_t allocmiss;
        atomic_t freehit;
        atomic_t freemiss;
+#ifdef CONFIG_DEBUG_SLAB_LEAK
+       atomic_t store_user_clean;
+#endif
 
        /*
         * If debugging is enabled, then the allocator can add additional
index b7e57927f5218f57ee5c4fe35da90b5ce84d2854..ac5143f95ee665106a5aaccfad0447d36d44ed41 100644 (file)
@@ -81,6 +81,7 @@ struct kmem_cache {
        int reserved;           /* Reserved bytes at the end of slabs */
        const char *name;       /* Name (only for display!) */
        struct list_head list;  /* List of slab caches */
+       int red_left_pad;       /* Left redzone padding size */
 #ifdef CONFIG_SYSFS
        struct kobject kobj;    /* For sysfs */
 #endif
index 53be3a4c60cbe4d53388a18ef7ca96d3204b26cc..857a9a1d82b58ad3569c7daeb9fffb17f690926a 100644 (file)
@@ -25,6 +25,7 @@
 struct dma_chan;
 struct spi_master;
 struct spi_transfer;
+struct spi_flash_read_message;
 
 /*
  * INTERFACES between SPI master-side drivers and SPI infrastructure.
@@ -53,6 +54,10 @@ extern struct bus_type spi_bus_type;
  *
  * @transfer_bytes_histo:
  *                 transfer bytes histogramm
+ *
+ * @transfers_split_maxsize:
+ *                 number of transfers that have been split because of
+ *                 maxsize limit
  */
 struct spi_statistics {
        spinlock_t              lock; /* lock for the whole structure */
@@ -72,6 +77,8 @@ struct spi_statistics {
 
 #define SPI_STATISTICS_HISTO_SIZE 17
        unsigned long transfer_bytes_histo[SPI_STATISTICS_HISTO_SIZE];
+
+       unsigned long transfers_split_maxsize;
 };
 
 void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
@@ -303,6 +310,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @min_speed_hz: Lowest supported transfer speed
  * @max_speed_hz: Highest supported transfer speed
  * @flags: other constraints relevant to this driver
+ * @max_transfer_size: function that returns the max transfer size for
+ *     a &spi_device; may be %NULL, so the default %SIZE_MAX will be used.
  * @bus_lock_spinlock: spinlock for SPI bus locking
  * @bus_lock_mutex: mutex for SPI bus locking
  * @bus_lock_flag: indicates that the SPI bus is locked for exclusive use
@@ -361,6 +370,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @handle_err: the subsystem calls the driver to handle an error that occurs
  *             in the generic implementation of transfer_one_message().
  * @unprepare_message: undo any work done by prepare_message().
+ * @spi_flash_read: to support spi-controller hardwares that provide
+ *                  accelerated interface to read from flash devices.
  * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
  *     number. Any individual value may be -ENOENT for CS lines that
  *     are not GPIOs (driven by the SPI controller itself).
@@ -369,6 +380,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @dma_rx: DMA receive channel
  * @dummy_rx: dummy receive buffer for full-duplex devices
  * @dummy_tx: dummy transmit buffer for full-duplex devices
+ * @fw_translate_cs: If the boot firmware uses different numbering scheme
+ *     what Linux expects, this optional hook can be used to translate
+ *     between the two.
  *
  * Each SPI master controller can communicate with one or more @spi_device
  * children.  These make a small bus, sharing MOSI, MISO and SCK signals
@@ -513,6 +527,8 @@ struct spi_master {
                               struct spi_message *message);
        int (*unprepare_message)(struct spi_master *master,
                                 struct spi_message *message);
+       int (*spi_flash_read)(struct  spi_device *spi,
+                             struct spi_flash_read_message *msg);
 
        /*
         * These hooks are for drivers that use a generic implementation
@@ -537,6 +553,8 @@ struct spi_master {
        /* dummy data for full duplex devices */
        void                    *dummy_rx;
        void                    *dummy_tx;
+
+       int (*fw_translate_cs)(struct spi_master *master, unsigned cs);
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
@@ -582,6 +600,38 @@ extern void spi_unregister_master(struct spi_master *master);
 
 extern struct spi_master *spi_busnum_to_master(u16 busnum);
 
+/*
+ * SPI resource management while processing a SPI message
+ */
+
+typedef void (*spi_res_release_t)(struct spi_master *master,
+                                 struct spi_message *msg,
+                                 void *res);
+
+/**
+ * struct spi_res - spi resource management structure
+ * @entry:   list entry
+ * @release: release code called prior to freeing this resource
+ * @data:    extra data allocated for the specific use-case
+ *
+ * this is based on ideas from devres, but focused on life-cycle
+ * management during spi_message processing
+ */
+struct spi_res {
+       struct list_head        entry;
+       spi_res_release_t       release;
+       unsigned long long      data[]; /* guarantee ull alignment */
+};
+
+extern void *spi_res_alloc(struct spi_device *spi,
+                          spi_res_release_t release,
+                          size_t size, gfp_t gfp);
+extern void spi_res_add(struct spi_message *message, void *res);
+extern void spi_res_free(void *res);
+
+extern void spi_res_release(struct spi_master *master,
+                           struct spi_message *message);
+
 /*---------------------------------------------------------------------------*/
 
 /*
@@ -720,6 +770,7 @@ struct spi_transfer {
  * @status: zero for success, else negative errno
  * @queue: for use by whichever driver currently owns the message
  * @state: for use by whichever driver currently owns the message
+ * @resources: for resource management when the spi message is processed
  *
  * A @spi_message is used to execute an atomic sequence of data transfers,
  * each represented by a struct spi_transfer.  The sequence is "atomic"
@@ -766,11 +817,15 @@ struct spi_message {
         */
        struct list_head        queue;
        void                    *state;
+
+       /* list of spi_res reources when the spi message is processed */
+       struct list_head        resources;
 };
 
 static inline void spi_message_init_no_memset(struct spi_message *m)
 {
        INIT_LIST_HEAD(&m->transfers);
+       INIT_LIST_HEAD(&m->resources);
 }
 
 static inline void spi_message_init(struct spi_message *m)
@@ -854,6 +909,60 @@ spi_max_transfer_size(struct spi_device *spi)
 
 /*---------------------------------------------------------------------------*/
 
+/* SPI transfer replacement methods which make use of spi_res */
+
+struct spi_replaced_transfers;
+typedef void (*spi_replaced_release_t)(struct spi_master *master,
+                                      struct spi_message *msg,
+                                      struct spi_replaced_transfers *res);
+/**
+ * struct spi_replaced_transfers - structure describing the spi_transfer
+ *                                 replacements that have occurred
+ *                                 so that they can get reverted
+ * @release:            some extra release code to get executed prior to
+ *                      relasing this structure
+ * @extradata:          pointer to some extra data if requested or NULL
+ * @replaced_transfers: transfers that have been replaced and which need
+ *                      to get restored
+ * @replaced_after:     the transfer after which the @replaced_transfers
+ *                      are to get re-inserted
+ * @inserted:           number of transfers inserted
+ * @inserted_transfers: array of spi_transfers of array-size @inserted,
+ *                      that have been replacing replaced_transfers
+ *
+ * note: that @extradata will point to @inserted_transfers[@inserted]
+ * if some extra allocation is requested, so alignment will be the same
+ * as for spi_transfers
+ */
+struct spi_replaced_transfers {
+       spi_replaced_release_t release;
+       void *extradata;
+       struct list_head replaced_transfers;
+       struct list_head *replaced_after;
+       size_t inserted;
+       struct spi_transfer inserted_transfers[];
+};
+
+extern struct spi_replaced_transfers *spi_replace_transfers(
+       struct spi_message *msg,
+       struct spi_transfer *xfer_first,
+       size_t remove,
+       size_t insert,
+       spi_replaced_release_t release,
+       size_t extradatasize,
+       gfp_t gfp);
+
+/*---------------------------------------------------------------------------*/
+
+/* SPI transfer transformation methods */
+
+extern int spi_split_transfers_maxsize(struct spi_master *master,
+                                      struct spi_message *msg,
+                                      size_t maxsize,
+                                      gfp_t gfp);
+
+/*---------------------------------------------------------------------------*/
+
 /* All these synchronous SPI transfer routines are utilities layered
  * over the core async transfer primitive.  Here, "synchronous" means
  * they will sleep uninterruptibly until the async transfer completes.
@@ -1019,6 +1128,42 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd)
        return be16_to_cpu(result);
 }
 
+/**
+ * struct spi_flash_read_message - flash specific information for
+ * spi-masters that provide accelerated flash read interfaces
+ * @buf: buffer to read data
+ * @from: offset within the flash from where data is to be read
+ * @len: length of data to be read
+ * @retlen: actual length of data read
+ * @read_opcode: read_opcode to be used to communicate with flash
+ * @addr_width: number of address bytes
+ * @dummy_bytes: number of dummy bytes
+ * @opcode_nbits: number of lines to send opcode
+ * @addr_nbits: number of lines to send address
+ * @data_nbits: number of lines for data
+ */
+struct spi_flash_read_message {
+       void *buf;
+       loff_t from;
+       size_t len;
+       size_t retlen;
+       u8 read_opcode;
+       u8 addr_width;
+       u8 dummy_bytes;
+       u8 opcode_nbits;
+       u8 addr_nbits;
+       u8 data_nbits;
+};
+
+/* SPI core interface for flash read support */
+static inline bool spi_flash_read_supported(struct spi_device *spi)
+{
+       return spi->master->spi_flash_read ? true : false;
+}
+
+int spi_flash_read(struct spi_device *spi,
+                  struct spi_flash_read_message *msg);
+
 /*---------------------------------------------------------------------------*/
 
 /*
index f5f80c5643ac5669abbb1e3e736ded2f49b5f3a0..dc8eb63c6568a8b0d2b9a2d793f80f255f3fc570 100644 (file)
@@ -99,8 +99,23 @@ void process_srcu(struct work_struct *work);
        }
 
 /*
- * define and init a srcu struct at build time.
- * dont't call init_srcu_struct() nor cleanup_srcu_struct() on it.
+ * Define and initialize a srcu struct at build time.
+ * Do -not- call init_srcu_struct() nor cleanup_srcu_struct() on it.
+ *
+ * Note that although DEFINE_STATIC_SRCU() hides the name from other
+ * files, the per-CPU variable rules nevertheless require that the
+ * chosen name be globally unique.  These rules also prohibit use of
+ * DEFINE_STATIC_SRCU() within a function.  If these rules are too
+ * restrictive, declare the srcu_struct manually.  For example, in
+ * each file:
+ *
+ *     static struct srcu_struct my_srcu;
+ *
+ * Then, before the first use of each my_srcu, manually initialize it:
+ *
+ *     init_srcu_struct(&my_srcu);
+ *
+ * See include/linux/percpu-defs.h for the rules on per-CPU variables.
  */
 #define __DEFINE_SRCU(name, is_static)                                 \
        static DEFINE_PER_CPU(struct srcu_struct_array, name##_srcu_array);\
index eead8ab93c0a36e402741ee767d3c3bc70128964..881a79d524675d7411b8985fd4a91110f69fd8e5 100644 (file)
@@ -100,6 +100,7 @@ struct plat_stmmacenet_data {
        int interface;
        struct stmmac_mdio_bus_data *mdio_bus_data;
        struct device_node *phy_node;
+       struct device_node *mdio_node;
        struct stmmac_dma_cfg *dma_cfg;
        int clk_csr;
        int has_gmac;
diff --git a/include/linux/swait.h b/include/linux/swait.h
new file mode 100644 (file)
index 0000000..c1f9c62
--- /dev/null
@@ -0,0 +1,172 @@
+#ifndef _LINUX_SWAIT_H
+#define _LINUX_SWAIT_H
+
+#include <linux/list.h>
+#include <linux/stddef.h>
+#include <linux/spinlock.h>
+#include <asm/current.h>
+
+/*
+ * Simple wait queues
+ *
+ * While these are very similar to the other/complex wait queues (wait.h) the
+ * most important difference is that the simple waitqueue allows for
+ * deterministic behaviour -- IOW it has strictly bounded IRQ and lock hold
+ * times.
+ *
+ * In order to make this so, we had to drop a fair number of features of the
+ * other waitqueue code; notably:
+ *
+ *  - mixing INTERRUPTIBLE and UNINTERRUPTIBLE sleeps on the same waitqueue;
+ *    all wakeups are TASK_NORMAL in order to avoid O(n) lookups for the right
+ *    sleeper state.
+ *
+ *  - the exclusive mode; because this requires preserving the list order
+ *    and this is hard.
+ *
+ *  - custom wake functions; because you cannot give any guarantees about
+ *    random code.
+ *
+ * As a side effect of this; the data structures are slimmer.
+ *
+ * One would recommend using this wait queue where possible.
+ */
+
+struct task_struct;
+
+struct swait_queue_head {
+       raw_spinlock_t          lock;
+       struct list_head        task_list;
+};
+
+struct swait_queue {
+       struct task_struct      *task;
+       struct list_head        task_list;
+};
+
+#define __SWAITQUEUE_INITIALIZER(name) {                               \
+       .task           = current,                                      \
+       .task_list      = LIST_HEAD_INIT((name).task_list),             \
+}
+
+#define DECLARE_SWAITQUEUE(name)                                       \
+       struct swait_queue name = __SWAITQUEUE_INITIALIZER(name)
+
+#define __SWAIT_QUEUE_HEAD_INITIALIZER(name) {                         \
+       .lock           = __RAW_SPIN_LOCK_UNLOCKED(name.lock),          \
+       .task_list      = LIST_HEAD_INIT((name).task_list),             \
+}
+
+#define DECLARE_SWAIT_QUEUE_HEAD(name)                                 \
+       struct swait_queue_head name = __SWAIT_QUEUE_HEAD_INITIALIZER(name)
+
+extern void __init_swait_queue_head(struct swait_queue_head *q, const char *name,
+                                   struct lock_class_key *key);
+
+#define init_swait_queue_head(q)                               \
+       do {                                                    \
+               static struct lock_class_key __key;             \
+               __init_swait_queue_head((q), #q, &__key);       \
+       } while (0)
+
+#ifdef CONFIG_LOCKDEP
+# define __SWAIT_QUEUE_HEAD_INIT_ONSTACK(name)                 \
+       ({ init_swait_queue_head(&name); name; })
+# define DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(name)                        \
+       struct swait_queue_head name = __SWAIT_QUEUE_HEAD_INIT_ONSTACK(name)
+#else
+# define DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(name)                        \
+       DECLARE_SWAIT_QUEUE_HEAD(name)
+#endif
+
+static inline int swait_active(struct swait_queue_head *q)
+{
+       return !list_empty(&q->task_list);
+}
+
+extern void swake_up(struct swait_queue_head *q);
+extern void swake_up_all(struct swait_queue_head *q);
+extern void swake_up_locked(struct swait_queue_head *q);
+
+extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
+extern void prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait, int state);
+extern long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state);
+
+extern void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait);
+extern void finish_swait(struct swait_queue_head *q, struct swait_queue *wait);
+
+/* as per ___wait_event() but for swait, therefore "exclusive == 0" */
+#define ___swait_event(wq, condition, state, ret, cmd)                 \
+({                                                                     \
+       struct swait_queue __wait;                                      \
+       long __ret = ret;                                               \
+                                                                       \
+       INIT_LIST_HEAD(&__wait.task_list);                              \
+       for (;;) {                                                      \
+               long __int = prepare_to_swait_event(&wq, &__wait, state);\
+                                                                       \
+               if (condition)                                          \
+                       break;                                          \
+                                                                       \
+               if (___wait_is_interruptible(state) && __int) {         \
+                       __ret = __int;                                  \
+                       break;                                          \
+               }                                                       \
+                                                                       \
+               cmd;                                                    \
+       }                                                               \
+       finish_swait(&wq, &__wait);                                     \
+       __ret;                                                          \
+})
+
+#define __swait_event(wq, condition)                                   \
+       (void)___swait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0,    \
+                           schedule())
+
+#define swait_event(wq, condition)                                     \
+do {                                                                   \
+       if (condition)                                                  \
+               break;                                                  \
+       __swait_event(wq, condition);                                   \
+} while (0)
+
+#define __swait_event_timeout(wq, condition, timeout)                  \
+       ___swait_event(wq, ___wait_cond_timeout(condition),             \
+                     TASK_UNINTERRUPTIBLE, timeout,                    \
+                     __ret = schedule_timeout(__ret))
+
+#define swait_event_timeout(wq, condition, timeout)                    \
+({                                                                     \
+       long __ret = timeout;                                           \
+       if (!___wait_cond_timeout(condition))                           \
+               __ret = __swait_event_timeout(wq, condition, timeout);  \
+       __ret;                                                          \
+})
+
+#define __swait_event_interruptible(wq, condition)                     \
+       ___swait_event(wq, condition, TASK_INTERRUPTIBLE, 0,            \
+                     schedule())
+
+#define swait_event_interruptible(wq, condition)                       \
+({                                                                     \
+       int __ret = 0;                                                  \
+       if (!(condition))                                               \
+               __ret = __swait_event_interruptible(wq, condition);     \
+       __ret;                                                          \
+})
+
+#define __swait_event_interruptible_timeout(wq, condition, timeout)    \
+       ___swait_event(wq, ___wait_cond_timeout(condition),             \
+                     TASK_INTERRUPTIBLE, timeout,                      \
+                     __ret = schedule_timeout(__ret))
+
+#define swait_event_interruptible_timeout(wq, condition, timeout)      \
+({                                                                     \
+       long __ret = timeout;                                           \
+       if (!___wait_cond_timeout(condition))                           \
+               __ret = __swait_event_interruptible_timeout(wq,         \
+                                               condition, timeout);    \
+       __ret;                                                          \
+})
+
+#endif /* _LINUX_SWAIT_H */
index 97fd4e543846b5f4de1dc5e366f250cc26724098..21f73649a4dc501002356a95bd3e68f52a7be717 100644 (file)
@@ -97,6 +97,19 @@ static inline void tick_broadcast_exit(void)
        tick_broadcast_oneshot_control(TICK_BROADCAST_EXIT);
 }
 
+enum tick_dep_bits {
+       TICK_DEP_BIT_POSIX_TIMER        = 0,
+       TICK_DEP_BIT_PERF_EVENTS        = 1,
+       TICK_DEP_BIT_SCHED              = 2,
+       TICK_DEP_BIT_CLOCK_UNSTABLE     = 3
+};
+
+#define TICK_DEP_MASK_NONE             0
+#define TICK_DEP_MASK_POSIX_TIMER      (1 << TICK_DEP_BIT_POSIX_TIMER)
+#define TICK_DEP_MASK_PERF_EVENTS      (1 << TICK_DEP_BIT_PERF_EVENTS)
+#define TICK_DEP_MASK_SCHED            (1 << TICK_DEP_BIT_SCHED)
+#define TICK_DEP_MASK_CLOCK_UNSTABLE   (1 << TICK_DEP_BIT_CLOCK_UNSTABLE)
+
 #ifdef CONFIG_NO_HZ_COMMON
 extern int tick_nohz_enabled;
 extern int tick_nohz_tick_stopped(void);
@@ -154,9 +167,73 @@ static inline int housekeeping_any_cpu(void)
        return cpumask_any_and(housekeeping_mask, cpu_online_mask);
 }
 
-extern void tick_nohz_full_kick(void);
+extern void tick_nohz_dep_set(enum tick_dep_bits bit);
+extern void tick_nohz_dep_clear(enum tick_dep_bits bit);
+extern void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit);
+extern void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit);
+extern void tick_nohz_dep_set_task(struct task_struct *tsk,
+                                  enum tick_dep_bits bit);
+extern void tick_nohz_dep_clear_task(struct task_struct *tsk,
+                                    enum tick_dep_bits bit);
+extern void tick_nohz_dep_set_signal(struct signal_struct *signal,
+                                    enum tick_dep_bits bit);
+extern void tick_nohz_dep_clear_signal(struct signal_struct *signal,
+                                      enum tick_dep_bits bit);
+
+/*
+ * The below are tick_nohz_[set,clear]_dep() wrappers that optimize off-cases
+ * on top of static keys.
+ */
+static inline void tick_dep_set(enum tick_dep_bits bit)
+{
+       if (tick_nohz_full_enabled())
+               tick_nohz_dep_set(bit);
+}
+
+static inline void tick_dep_clear(enum tick_dep_bits bit)
+{
+       if (tick_nohz_full_enabled())
+               tick_nohz_dep_clear(bit);
+}
+
+static inline void tick_dep_set_cpu(int cpu, enum tick_dep_bits bit)
+{
+       if (tick_nohz_full_cpu(cpu))
+               tick_nohz_dep_set_cpu(cpu, bit);
+}
+
+static inline void tick_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
+{
+       if (tick_nohz_full_cpu(cpu))
+               tick_nohz_dep_clear_cpu(cpu, bit);
+}
+
+static inline void tick_dep_set_task(struct task_struct *tsk,
+                                    enum tick_dep_bits bit)
+{
+       if (tick_nohz_full_enabled())
+               tick_nohz_dep_set_task(tsk, bit);
+}
+static inline void tick_dep_clear_task(struct task_struct *tsk,
+                                      enum tick_dep_bits bit)
+{
+       if (tick_nohz_full_enabled())
+               tick_nohz_dep_clear_task(tsk, bit);
+}
+static inline void tick_dep_set_signal(struct signal_struct *signal,
+                                      enum tick_dep_bits bit)
+{
+       if (tick_nohz_full_enabled())
+               tick_nohz_dep_set_signal(signal, bit);
+}
+static inline void tick_dep_clear_signal(struct signal_struct *signal,
+                                        enum tick_dep_bits bit)
+{
+       if (tick_nohz_full_enabled())
+               tick_nohz_dep_clear_signal(signal, bit);
+}
+
 extern void tick_nohz_full_kick_cpu(int cpu);
-extern void tick_nohz_full_kick_all(void);
 extern void __tick_nohz_task_switch(void);
 #else
 static inline int housekeeping_any_cpu(void)
@@ -166,9 +243,21 @@ static inline int housekeeping_any_cpu(void)
 static inline bool tick_nohz_full_enabled(void) { return false; }
 static inline bool tick_nohz_full_cpu(int cpu) { return false; }
 static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { }
+
+static inline void tick_dep_set(enum tick_dep_bits bit) { }
+static inline void tick_dep_clear(enum tick_dep_bits bit) { }
+static inline void tick_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }
+static inline void tick_dep_clear_cpu(int cpu, enum tick_dep_bits bit) { }
+static inline void tick_dep_set_task(struct task_struct *tsk,
+                                    enum tick_dep_bits bit) { }
+static inline void tick_dep_clear_task(struct task_struct *tsk,
+                                      enum tick_dep_bits bit) { }
+static inline void tick_dep_set_signal(struct signal_struct *signal,
+                                      enum tick_dep_bits bit) { }
+static inline void tick_dep_clear_signal(struct signal_struct *signal,
+                                        enum tick_dep_bits bit) { }
+
 static inline void tick_nohz_full_kick_cpu(int cpu) { }
-static inline void tick_nohz_full_kick(void) { }
-static inline void tick_nohz_full_kick_all(void) { }
 static inline void __tick_nohz_task_switch(void) { }
 #endif
 
index 25247220b4b7ddf3f336077b105ab42271475a05..e88005459035e760cb2c3cf1dc8966a958191ef6 100644 (file)
@@ -50,6 +50,7 @@ struct tk_read_base {
  * @offs_tai:          Offset clock monotonic -> clock tai
  * @tai_offset:                The current UTC to TAI offset in seconds
  * @clock_was_set_seq: The sequence number of clock was set events
+ * @cs_was_changed_seq:        The sequence number of clocksource change events
  * @next_leap_ktime:   CLOCK_MONOTONIC time value of a pending leap-second
  * @raw_time:          Monotonic raw base time in timespec64 format
  * @cycle_interval:    Number of clock cycles in one NTP interval
@@ -91,6 +92,7 @@ struct timekeeper {
        ktime_t                 offs_tai;
        s32                     tai_offset;
        unsigned int            clock_was_set_seq;
+       u8                      cs_was_changed_seq;
        ktime_t                 next_leap_ktime;
        struct timespec64       raw_time;
 
index ec89d846324cac714807f7c002339636c497e4d8..96f37bee3bc13b96f3ddd9a27657e6d64340ceb3 100644 (file)
@@ -266,6 +266,64 @@ extern void timekeeping_inject_sleeptime64(struct timespec64 *delta);
 extern void ktime_get_raw_and_real_ts64(struct timespec64 *ts_raw,
                                        struct timespec64 *ts_real);
 
+/*
+ * struct system_time_snapshot - simultaneous raw/real time capture with
+ *     counter value
+ * @cycles:    Clocksource counter value to produce the system times
+ * @real:      Realtime system time
+ * @raw:       Monotonic raw system time
+ * @clock_was_set_seq: The sequence number of clock was set events
+ * @cs_was_changed_seq:        The sequence number of clocksource change events
+ */
+struct system_time_snapshot {
+       cycle_t         cycles;
+       ktime_t         real;
+       ktime_t         raw;
+       unsigned int    clock_was_set_seq;
+       u8              cs_was_changed_seq;
+};
+
+/*
+ * struct system_device_crosststamp - system/device cross-timestamp
+ *     (syncronized capture)
+ * @device:            Device time
+ * @sys_realtime:      Realtime simultaneous with device time
+ * @sys_monoraw:       Monotonic raw simultaneous with device time
+ */
+struct system_device_crosststamp {
+       ktime_t device;
+       ktime_t sys_realtime;
+       ktime_t sys_monoraw;
+};
+
+/*
+ * struct system_counterval_t - system counter value with the pointer to the
+ *     corresponding clocksource
+ * @cycles:    System counter value
+ * @cs:                Clocksource corresponding to system counter value. Used by
+ *     timekeeping code to verify comparibility of two cycle values
+ */
+struct system_counterval_t {
+       cycle_t                 cycles;
+       struct clocksource      *cs;
+};
+
+/*
+ * Get cross timestamp between system clock and device clock
+ */
+extern int get_device_system_crosststamp(
+                       int (*get_time_fn)(ktime_t *device_time,
+                               struct system_counterval_t *system_counterval,
+                               void *ctx),
+                       void *ctx,
+                       struct system_time_snapshot *history,
+                       struct system_device_crosststamp *xtstamp);
+
+/*
+ * Simultaneously snapshot realtime and monotonic raw clocks
+ */
+extern void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot);
+
 /*
  * Persistent clock related interfaces
  */
index 429fdfc3baf59e018d0e198062f894642af8a5bc..705df7db44821ed44dcb9e608667e706883c051f 100644 (file)
@@ -15,16 +15,6 @@ struct tracer;
 struct dentry;
 struct bpf_prog;
 
-struct trace_print_flags {
-       unsigned long           mask;
-       const char              *name;
-};
-
-struct trace_print_flags_u64 {
-       unsigned long long      mask;
-       const char              *name;
-};
-
 const char *trace_print_flags_seq(struct trace_seq *p, const char *delim,
                                  unsigned long flags,
                                  const struct trace_print_flags *flag_array);
@@ -568,6 +558,8 @@ enum {
        FILTER_DYN_STRING,
        FILTER_PTR_STRING,
        FILTER_TRACE_FN,
+       FILTER_COMM,
+       FILTER_CPU,
 };
 
 extern int trace_event_raw_init(struct trace_event_call *call);
index e1ee97c713bf23b433e85a881632215331269659..4ac89acb613687bd0899e7cbddadb79f4325349e 100644 (file)
@@ -3,13 +3,23 @@
 
 /*
  * File can be included directly by headers who only want to access
- * tracepoint->key to guard out of line trace calls. Otherwise
- * linux/tracepoint.h should be used.
+ * tracepoint->key to guard out of line trace calls, or the definition of
+ * trace_print_flags{_u64}. Otherwise linux/tracepoint.h should be used.
  */
 
 #include <linux/atomic.h>
 #include <linux/static_key.h>
 
+struct trace_print_flags {
+       unsigned long           mask;
+       const char              *name;
+};
+
+struct trace_print_flags_u64 {
+       unsigned long long      mask;
+       const char              *name;
+};
+
 struct tracepoint_func {
        void *func;
        void *data;
index acfdbf353a0b5bc7cfeb6ae58fa7e6a6acfa16ba..be586c632a0c04da3887ae6a0cf28357df98ef5c 100644 (file)
@@ -134,9 +134,6 @@ extern void syscall_unregfunc(void);
                void *it_func;                                          \
                void *__data;                                           \
                                                                        \
-               if (!cpu_online(raw_smp_processor_id()))                \
-                       return;                                         \
-                                                                       \
                if (!(cond))                                            \
                        return;                                         \
                prercu;                                                 \
@@ -343,15 +340,19 @@ extern void syscall_unregfunc(void);
  * "void *__data, proto" as the callback prototype.
  */
 #define DECLARE_TRACE_NOARGS(name)                                     \
-               __DECLARE_TRACE(name, void, , 1, void *__data, __data)
+       __DECLARE_TRACE(name, void, ,                                   \
+                       cpu_online(raw_smp_processor_id()),             \
+                       void *__data, __data)
 
 #define DECLARE_TRACE(name, proto, args)                               \
-               __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), 1,   \
-                               PARAMS(void *__data, proto),            \
-                               PARAMS(__data, args))
+       __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
+                       cpu_online(raw_smp_processor_id()),             \
+                       PARAMS(void *__data, proto),                    \
+                       PARAMS(__data, args))
 
 #define DECLARE_TRACE_CONDITION(name, proto, args, cond)               \
-       __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \
+       __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
+                       cpu_online(raw_smp_processor_id()) && (PARAMS(cond)), \
                        PARAMS(void *__data, proto),                    \
                        PARAMS(__data, args))
 
index ae71a769b89e3d9f706543a16cfd125120a52cb0..27d7a0ab5da3edf217e60d767c10c65d3e3c52a0 100644 (file)
@@ -338,7 +338,7 @@ do {                                                                        \
                            schedule(); try_to_freeze())
 
 /**
- * wait_event - sleep (or freeze) until a condition gets true
+ * wait_event_freezable - sleep (or freeze) until a condition gets true
  * @wq: the waitqueue to wait on
  * @condition: a C expression for the event to wait for
  *
index b333c945e57117aa3d80f6ec2df47f6513c82260..d0b5ca5d4e080346e8a657c6c6aee540e47776e7 100644 (file)
@@ -198,6 +198,7 @@ void wbc_attach_and_unlock_inode(struct writeback_control *wbc,
 void wbc_detach_inode(struct writeback_control *wbc);
 void wbc_account_io(struct writeback_control *wbc, struct page *page,
                    size_t bytes);
+void cgroup_writeback_umount(void);
 
 /**
  * inode_attach_wb - associate an inode with its wb
@@ -301,6 +302,10 @@ static inline void wbc_account_io(struct writeback_control *wbc,
 {
 }
 
+static inline void cgroup_writeback_umount(void)
+{
+}
+
 #endif /* CONFIG_CGROUP_WRITEBACK */
 
 /*
index 8f81bbbc38fc939070a5761e3af90da62faf8d68..e0f4109e64c6fca9ba87d768c2c7b1220a6557f4 100644 (file)
@@ -439,6 +439,12 @@ int dev_get_wireless_info(char *buffer, char **start, off_t offset, int length);
 /* Send a single event to user space */
 void wireless_send_event(struct net_device *dev, unsigned int cmd,
                         union iwreq_data *wrqu, const char *extra);
+#ifdef CONFIG_WEXT_CORE
+/* flush all previous wext events - if work is done from netdev notifiers */
+void wireless_nlevent_flush(void);
+#else
+static inline void wireless_nlevent_flush(void) {}
+#endif
 
 /* We may need a function to send a stream of events to user space.
  * More on that later... */
index e2b712c90d3f22d4bcbb75ded3a296304d23d7c6..c21c38ce74501dbdac327e9cac8b0b6d051a42b0 100644 (file)
@@ -343,7 +343,7 @@ void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
 void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
 
 void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
-void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
+int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
                                    void (*ack)(struct hdac_bus *,
                                                struct hdac_stream *));
 
index 317a1ed2f4acc7745c3e02955c60e8c1dc8eb7c3..9130dd5a184a25e7d6c6cf0b633d7d5c0c4fc0f6 100644 (file)
@@ -231,13 +231,13 @@ TRACE_EVENT(snd_soc_jack_report,
        TP_ARGS(jack, mask, val),
 
        TP_STRUCT__entry(
-               __string(       name,           jack->jack->name        )
+               __string(       name,           jack->jack->id          )
                __field(        int,            mask                    )
                __field(        int,            val                     )
        ),
 
        TP_fast_assign(
-               __assign_str(name, jack->jack->name);
+               __assign_str(name, jack->jack->id);
                __entry->mask = mask;
                __entry->val = val;
        ),
@@ -253,12 +253,12 @@ TRACE_EVENT(snd_soc_jack_notify,
        TP_ARGS(jack, val),
 
        TP_STRUCT__entry(
-               __string(       name,           jack->jack->name        )
+               __string(       name,           jack->jack->id          )
                __field(        int,            val                     )
        ),
 
        TP_fast_assign(
-               __assign_str(name, jack->jack->name);
+               __assign_str(name, jack->jack->id);
                __entry->val = val;
        ),
 
index d866f21efbbfd4722e6c23bde8320d7b54ecf2be..677807f29a1cd18ae142f0f6e95999b0b6e1125e 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <linux/writeback.h>
 #include <linux/tracepoint.h>
-#include <trace/events/gfpflags.h>
+#include <trace/events/mmflags.h>
 
 struct btrfs_root;
 struct btrfs_fs_info;
index c92d1e1cbad9171cdce14eaa7fc0a9400783388a..111e5666e5ebffb7c960d7fd3e024b084a466939 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/tracepoint.h>
-#include <trace/events/gfpflags.h>
+#include <trace/events/mmflags.h>
 
 #define COMPACTION_STATUS                                      \
        EM( COMPACT_DEFERRED,           "deferred")             \
diff --git a/include/trace/events/cpuhp.h b/include/trace/events/cpuhp.h
new file mode 100644 (file)
index 0000000..a72bd93
--- /dev/null
@@ -0,0 +1,66 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cpuhp
+
+#if !defined(_TRACE_CPUHP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_CPUHP_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(cpuhp_enter,
+
+       TP_PROTO(unsigned int cpu,
+                int target,
+                int idx,
+                int (*fun)(unsigned int)),
+
+       TP_ARGS(cpu, target, idx, fun),
+
+       TP_STRUCT__entry(
+               __field( unsigned int,  cpu             )
+               __field( int,           target          )
+               __field( int,           idx             )
+               __field( void *,        fun             )
+       ),
+
+       TP_fast_assign(
+               __entry->cpu    = cpu;
+               __entry->target = target;
+               __entry->idx    = idx;
+               __entry->fun    = fun;
+       ),
+
+       TP_printk("cpu: %04u target: %3d step: %3d (%pf)",
+                 __entry->cpu, __entry->target, __entry->idx, __entry->fun)
+);
+
+TRACE_EVENT(cpuhp_exit,
+
+       TP_PROTO(unsigned int cpu,
+                int state,
+                int idx,
+                int ret),
+
+       TP_ARGS(cpu, state, idx, ret),
+
+       TP_STRUCT__entry(
+               __field( unsigned int,  cpu             )
+               __field( int,           state           )
+               __field( int,           idx             )
+               __field( int,           ret             )
+       ),
+
+       TP_fast_assign(
+               __entry->cpu    = cpu;
+               __entry->state  = state;
+               __entry->idx    = idx;
+               __entry->ret    = ret;
+       ),
+
+       TP_printk(" cpu: %04u  state: %3d step: %3d ret: %d",
+                 __entry->cpu, __entry->state, __entry->idx,  __entry->ret)
+);
+
+#endif
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/gfpflags.h b/include/trace/events/gfpflags.h
deleted file mode 100644 (file)
index dde6bf0..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * The order of these masks is important. Matching masks will be seen
- * first and the left over flags will end up showing by themselves.
- *
- * For example, if we have GFP_KERNEL before GFP_USER we wil get:
- *
- *  GFP_KERNEL|GFP_HARDWALL
- *
- * Thus most bits set go first.
- */
-#define show_gfp_flags(flags)                                          \
-       (flags) ? __print_flags(flags, "|",                             \
-       {(unsigned long)GFP_TRANSHUGE,          "GFP_TRANSHUGE"},       \
-       {(unsigned long)GFP_HIGHUSER_MOVABLE,   "GFP_HIGHUSER_MOVABLE"}, \
-       {(unsigned long)GFP_HIGHUSER,           "GFP_HIGHUSER"},        \
-       {(unsigned long)GFP_USER,               "GFP_USER"},            \
-       {(unsigned long)GFP_TEMPORARY,          "GFP_TEMPORARY"},       \
-       {(unsigned long)GFP_KERNEL,             "GFP_KERNEL"},          \
-       {(unsigned long)GFP_NOFS,               "GFP_NOFS"},            \
-       {(unsigned long)GFP_ATOMIC,             "GFP_ATOMIC"},          \
-       {(unsigned long)GFP_NOIO,               "GFP_NOIO"},            \
-       {(unsigned long)__GFP_HIGH,             "GFP_HIGH"},            \
-       {(unsigned long)__GFP_ATOMIC,           "GFP_ATOMIC"},          \
-       {(unsigned long)__GFP_IO,               "GFP_IO"},              \
-       {(unsigned long)__GFP_COLD,             "GFP_COLD"},            \
-       {(unsigned long)__GFP_NOWARN,           "GFP_NOWARN"},          \
-       {(unsigned long)__GFP_REPEAT,           "GFP_REPEAT"},          \
-       {(unsigned long)__GFP_NOFAIL,           "GFP_NOFAIL"},          \
-       {(unsigned long)__GFP_NORETRY,          "GFP_NORETRY"},         \
-       {(unsigned long)__GFP_COMP,             "GFP_COMP"},            \
-       {(unsigned long)__GFP_ZERO,             "GFP_ZERO"},            \
-       {(unsigned long)__GFP_NOMEMALLOC,       "GFP_NOMEMALLOC"},      \
-       {(unsigned long)__GFP_MEMALLOC,         "GFP_MEMALLOC"},        \
-       {(unsigned long)__GFP_HARDWALL,         "GFP_HARDWALL"},        \
-       {(unsigned long)__GFP_THISNODE,         "GFP_THISNODE"},        \
-       {(unsigned long)__GFP_RECLAIMABLE,      "GFP_RECLAIMABLE"},     \
-       {(unsigned long)__GFP_MOVABLE,          "GFP_MOVABLE"},         \
-       {(unsigned long)__GFP_NOTRACK,          "GFP_NOTRACK"},         \
-       {(unsigned long)__GFP_DIRECT_RECLAIM,   "GFP_DIRECT_RECLAIM"},  \
-       {(unsigned long)__GFP_KSWAPD_RECLAIM,   "GFP_KSWAPD_RECLAIM"},  \
-       {(unsigned long)__GFP_OTHER_NODE,       "GFP_OTHER_NODE"}       \
-       ) : "GFP_NOWAIT"
-
index 47c6212d8f3cecb07d62cb9ea81f6ea65ae0c35f..551ba4acde4d89497aacb901b2ceba2a0fa2d6fc 100644 (file)
@@ -6,8 +6,6 @@
 
 #include  <linux/tracepoint.h>
 
-#include <trace/events/gfpflags.h>
-
 #define SCAN_STATUS                                                    \
        EM( SCAN_FAIL,                  "failed")                       \
        EM( SCAN_SUCCEED,               "succeeded")                    \
index f7554fd7fc62b92d6b1d73d7db6030599b552014..ca7217389067cbbdb752c05f6119bf3dc706a677 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <linux/types.h>
 #include <linux/tracepoint.h>
-#include <trace/events/gfpflags.h>
+#include <trace/events/mmflags.h>
 
 DECLARE_EVENT_CLASS(kmem_alloc,
 
index d6f83222a6a1671ec819d730801398ebb88f80ab..aa69253ecc7dd94df775361ac6c6f5b70c6e0dfc 100644 (file)
@@ -359,14 +359,15 @@ TRACE_EVENT(
 #endif
 
 TRACE_EVENT(kvm_halt_poll_ns,
-       TP_PROTO(bool grow, unsigned int vcpu_id, int new, int old),
+       TP_PROTO(bool grow, unsigned int vcpu_id, unsigned int new,
+                unsigned int old),
        TP_ARGS(grow, vcpu_id, new, old),
 
        TP_STRUCT__entry(
                __field(bool, grow)
                __field(unsigned int, vcpu_id)
-               __field(int, new)
-               __field(int, old)
+               __field(unsigned int, new)
+               __field(unsigned int, old)
        ),
 
        TP_fast_assign(
@@ -376,7 +377,7 @@ TRACE_EVENT(kvm_halt_poll_ns,
                __entry->old            = old;
        ),
 
-       TP_printk("vcpu %u: halt_poll_ns %d (%s %d)",
+       TP_printk("vcpu %u: halt_poll_ns %u (%s %u)",
                        __entry->vcpu_id,
                        __entry->new,
                        __entry->grow ? "grow" : "shrink",
diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
new file mode 100644 (file)
index 0000000..a849185
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * The order of these masks is important. Matching masks will be seen
+ * first and the left over flags will end up showing by themselves.
+ *
+ * For example, if we have GFP_KERNEL before GFP_USER we wil get:
+ *
+ *  GFP_KERNEL|GFP_HARDWALL
+ *
+ * Thus most bits set go first.
+ */
+
+#define __def_gfpflag_names                                            \
+       {(unsigned long)GFP_TRANSHUGE,          "GFP_TRANSHUGE"},       \
+       {(unsigned long)GFP_HIGHUSER_MOVABLE,   "GFP_HIGHUSER_MOVABLE"},\
+       {(unsigned long)GFP_HIGHUSER,           "GFP_HIGHUSER"},        \
+       {(unsigned long)GFP_USER,               "GFP_USER"},            \
+       {(unsigned long)GFP_TEMPORARY,          "GFP_TEMPORARY"},       \
+       {(unsigned long)GFP_KERNEL_ACCOUNT,     "GFP_KERNEL_ACCOUNT"},  \
+       {(unsigned long)GFP_KERNEL,             "GFP_KERNEL"},          \
+       {(unsigned long)GFP_NOFS,               "GFP_NOFS"},            \
+       {(unsigned long)GFP_ATOMIC,             "GFP_ATOMIC"},          \
+       {(unsigned long)GFP_NOIO,               "GFP_NOIO"},            \
+       {(unsigned long)GFP_NOWAIT,             "GFP_NOWAIT"},          \
+       {(unsigned long)GFP_DMA,                "GFP_DMA"},             \
+       {(unsigned long)__GFP_HIGHMEM,          "__GFP_HIGHMEM"},       \
+       {(unsigned long)GFP_DMA32,              "GFP_DMA32"},           \
+       {(unsigned long)__GFP_HIGH,             "__GFP_HIGH"},          \
+       {(unsigned long)__GFP_ATOMIC,           "__GFP_ATOMIC"},        \
+       {(unsigned long)__GFP_IO,               "__GFP_IO"},            \
+       {(unsigned long)__GFP_FS,               "__GFP_FS"},            \
+       {(unsigned long)__GFP_COLD,             "__GFP_COLD"},          \
+       {(unsigned long)__GFP_NOWARN,           "__GFP_NOWARN"},        \
+       {(unsigned long)__GFP_REPEAT,           "__GFP_REPEAT"},        \
+       {(unsigned long)__GFP_NOFAIL,           "__GFP_NOFAIL"},        \
+       {(unsigned long)__GFP_NORETRY,          "__GFP_NORETRY"},       \
+       {(unsigned long)__GFP_COMP,             "__GFP_COMP"},          \
+       {(unsigned long)__GFP_ZERO,             "__GFP_ZERO"},          \
+       {(unsigned long)__GFP_NOMEMALLOC,       "__GFP_NOMEMALLOC"},    \
+       {(unsigned long)__GFP_MEMALLOC,         "__GFP_MEMALLOC"},      \
+       {(unsigned long)__GFP_HARDWALL,         "__GFP_HARDWALL"},      \
+       {(unsigned long)__GFP_THISNODE,         "__GFP_THISNODE"},      \
+       {(unsigned long)__GFP_RECLAIMABLE,      "__GFP_RECLAIMABLE"},   \
+       {(unsigned long)__GFP_MOVABLE,          "__GFP_MOVABLE"},       \
+       {(unsigned long)__GFP_ACCOUNT,          "__GFP_ACCOUNT"},       \
+       {(unsigned long)__GFP_NOTRACK,          "__GFP_NOTRACK"},       \
+       {(unsigned long)__GFP_WRITE,            "__GFP_WRITE"},         \
+       {(unsigned long)__GFP_RECLAIM,          "__GFP_RECLAIM"},       \
+       {(unsigned long)__GFP_DIRECT_RECLAIM,   "__GFP_DIRECT_RECLAIM"},\
+       {(unsigned long)__GFP_KSWAPD_RECLAIM,   "__GFP_KSWAPD_RECLAIM"},\
+       {(unsigned long)__GFP_OTHER_NODE,       "__GFP_OTHER_NODE"}     \
+
+#define show_gfp_flags(flags)                                          \
+       (flags) ? __print_flags(flags, "|",                             \
+       __def_gfpflag_names                                             \
+       ) : "none"
+
+#ifdef CONFIG_MMU
+#define IF_HAVE_PG_MLOCK(flag,string) ,{1UL << flag, string}
+#else
+#define IF_HAVE_PG_MLOCK(flag,string)
+#endif
+
+#ifdef CONFIG_ARCH_USES_PG_UNCACHED
+#define IF_HAVE_PG_UNCACHED(flag,string) ,{1UL << flag, string}
+#else
+#define IF_HAVE_PG_UNCACHED(flag,string)
+#endif
+
+#ifdef CONFIG_MEMORY_FAILURE
+#define IF_HAVE_PG_HWPOISON(flag,string) ,{1UL << flag, string}
+#else
+#define IF_HAVE_PG_HWPOISON(flag,string)
+#endif
+
+#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT)
+#define IF_HAVE_PG_IDLE(flag,string) ,{1UL << flag, string}
+#else
+#define IF_HAVE_PG_IDLE(flag,string)
+#endif
+
+#define __def_pageflag_names                                           \
+       {1UL << PG_locked,              "locked"        },              \
+       {1UL << PG_error,               "error"         },              \
+       {1UL << PG_referenced,          "referenced"    },              \
+       {1UL << PG_uptodate,            "uptodate"      },              \
+       {1UL << PG_dirty,               "dirty"         },              \
+       {1UL << PG_lru,                 "lru"           },              \
+       {1UL << PG_active,              "active"        },              \
+       {1UL << PG_slab,                "slab"          },              \
+       {1UL << PG_owner_priv_1,        "owner_priv_1"  },              \
+       {1UL << PG_arch_1,              "arch_1"        },              \
+       {1UL << PG_reserved,            "reserved"      },              \
+       {1UL << PG_private,             "private"       },              \
+       {1UL << PG_private_2,           "private_2"     },              \
+       {1UL << PG_writeback,           "writeback"     },              \
+       {1UL << PG_head,                "head"          },              \
+       {1UL << PG_swapcache,           "swapcache"     },              \
+       {1UL << PG_mappedtodisk,        "mappedtodisk"  },              \
+       {1UL << PG_reclaim,             "reclaim"       },              \
+       {1UL << PG_swapbacked,          "swapbacked"    },              \
+       {1UL << PG_unevictable,         "unevictable"   }               \
+IF_HAVE_PG_MLOCK(PG_mlocked,           "mlocked"       )               \
+IF_HAVE_PG_UNCACHED(PG_uncached,       "uncached"      )               \
+IF_HAVE_PG_HWPOISON(PG_hwpoison,       "hwpoison"      )               \
+IF_HAVE_PG_IDLE(PG_young,              "young"         )               \
+IF_HAVE_PG_IDLE(PG_idle,               "idle"          )
+
+#define show_page_flags(flags)                                         \
+       (flags) ? __print_flags(flags, "|",                             \
+       __def_pageflag_names                                            \
+       ) : "none"
+
+#if defined(CONFIG_X86)
+#define __VM_ARCH_SPECIFIC {VM_PAT,     "pat"           }
+#elif defined(CONFIG_PPC)
+#define __VM_ARCH_SPECIFIC {VM_SAO,     "sao"           }
+#elif defined(CONFIG_PARISC) || defined(CONFIG_METAG) || defined(CONFIG_IA64)
+#define __VM_ARCH_SPECIFIC {VM_GROWSUP,        "growsup"       }
+#elif !defined(CONFIG_MMU)
+#define __VM_ARCH_SPECIFIC {VM_MAPPED_COPY,"mappedcopy"        }
+#else
+#define __VM_ARCH_SPECIFIC {VM_ARCH_1, "arch_1"        }
+#endif
+
+#ifdef CONFIG_MEM_SOFT_DIRTY
+#define IF_HAVE_VM_SOFTDIRTY(flag,name) {flag, name },
+#else
+#define IF_HAVE_VM_SOFTDIRTY(flag,name)
+#endif
+
+#define __def_vmaflag_names                                            \
+       {VM_READ,                       "read"          },              \
+       {VM_WRITE,                      "write"         },              \
+       {VM_EXEC,                       "exec"          },              \
+       {VM_SHARED,                     "shared"        },              \
+       {VM_MAYREAD,                    "mayread"       },              \
+       {VM_MAYWRITE,                   "maywrite"      },              \
+       {VM_MAYEXEC,                    "mayexec"       },              \
+       {VM_MAYSHARE,                   "mayshare"      },              \
+       {VM_GROWSDOWN,                  "growsdown"     },              \
+       {VM_PFNMAP,                     "pfnmap"        },              \
+       {VM_DENYWRITE,                  "denywrite"     },              \
+       {VM_LOCKONFAULT,                "lockonfault"   },              \
+       {VM_LOCKED,                     "locked"        },              \
+       {VM_IO,                         "io"            },              \
+       {VM_SEQ_READ,                   "seqread"       },              \
+       {VM_RAND_READ,                  "randread"      },              \
+       {VM_DONTCOPY,                   "dontcopy"      },              \
+       {VM_DONTEXPAND,                 "dontexpand"    },              \
+       {VM_ACCOUNT,                    "account"       },              \
+       {VM_NORESERVE,                  "noreserve"     },              \
+       {VM_HUGETLB,                    "hugetlb"       },              \
+       __VM_ARCH_SPECIFIC                              ,               \
+       {VM_DONTDUMP,                   "dontdump"      },              \
+IF_HAVE_VM_SOFTDIRTY(VM_SOFTDIRTY,     "softdirty"     )               \
+       {VM_MIXEDMAP,                   "mixedmap"      },              \
+       {VM_HUGEPAGE,                   "hugepage"      },              \
+       {VM_NOHUGEPAGE,                 "nohugepage"    },              \
+       {VM_MERGEABLE,                  "mergeable"     }               \
+
+#define show_vma_flags(flags)                                          \
+       (flags) ? __print_flags(flags, "|",                             \
+       __def_vmaflag_names                                             \
+       ) : "none"
index 284244ebfe8d2c3ef7036c3a7e9b55ea15b11078..19e50300ce7d63da516ef9ea365c156a4e77ad3c 100644 (file)
@@ -38,6 +38,28 @@ DEFINE_EVENT(cpu, cpu_idle,
        TP_ARGS(state, cpu_id)
 );
 
+TRACE_EVENT(powernv_throttle,
+
+       TP_PROTO(int chip_id, const char *reason, int pmax),
+
+       TP_ARGS(chip_id, reason, pmax),
+
+       TP_STRUCT__entry(
+               __field(int, chip_id)
+               __string(reason, reason)
+               __field(int, pmax)
+       ),
+
+       TP_fast_assign(
+               __entry->chip_id = chip_id;
+               __assign_str(reason, reason);
+               __entry->pmax = pmax;
+       ),
+
+       TP_printk("Chip %d Pmax %d %s", __entry->chip_id,
+                 __entry->pmax, __get_str(reason))
+);
+
 TRACE_EVENT(pstate_sample,
 
        TP_PROTO(u32 core_busy,
index 073b9ac245ba0315f31a51f5df9f21bcdf2e9115..51440131d3372feb1f09b7139362db66119f0e2a 100644 (file)
@@ -328,23 +328,49 @@ TRACE_EVENT(itimer_expire,
 );
 
 #ifdef CONFIG_NO_HZ_COMMON
+
+#define TICK_DEP_NAMES                                 \
+               tick_dep_name(NONE)                     \
+               tick_dep_name(POSIX_TIMER)              \
+               tick_dep_name(PERF_EVENTS)              \
+               tick_dep_name(SCHED)                    \
+               tick_dep_name_end(CLOCK_UNSTABLE)
+
+#undef tick_dep_name
+#undef tick_dep_name_end
+
+#define tick_dep_name(sdep) TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep);
+#define tick_dep_name_end(sdep)  TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep);
+
+TICK_DEP_NAMES
+
+#undef tick_dep_name
+#undef tick_dep_name_end
+
+#define tick_dep_name(sdep) { TICK_DEP_MASK_##sdep, #sdep },
+#define tick_dep_name_end(sdep) { TICK_DEP_MASK_##sdep, #sdep }
+
+#define show_tick_dep_name(val)                                \
+       __print_symbolic(val, TICK_DEP_NAMES)
+
 TRACE_EVENT(tick_stop,
 
-       TP_PROTO(int success, char *error_msg),
+       TP_PROTO(int success, int dependency),
 
-       TP_ARGS(success, error_msg),
+       TP_ARGS(success, dependency),
 
        TP_STRUCT__entry(
                __field( int ,          success )
-               __string( msg,          error_msg )
+               __field( int ,          dependency )
        ),
 
        TP_fast_assign(
                __entry->success        = success;
-               __assign_str(msg, error_msg);
+               __entry->dependency     = dependency;
        ),
 
-       TP_printk("success=%s msg=%s",  __entry->success ? "yes" : "no", __get_str(msg))
+       TP_printk("success=%d dependency=%s",  __entry->success, \
+                       show_tick_dep_name(__entry->dependency))
 );
 #endif
 
index 31763dd8db1cea9c4b7d5685c9996dfc73430562..0101ef37f1eed78a39ef095f3ced183cb4e3f7c8 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/tracepoint.h>
 #include <linux/mm.h>
 #include <linux/memcontrol.h>
-#include <trace/events/gfpflags.h>
+#include <trace/events/mmflags.h>
 
 #define RECLAIM_WB_ANON                0x0001u
 #define RECLAIM_WB_FILE                0x0002u
index bb991dfe134f03743a4e40c7024324289910b0e9..9175a1b4dc69a41301f0576939eeb78e75e02887 100644 (file)
@@ -1,7 +1,4 @@
-/* -*- linux-c -*- ------------------------------------------------------- *
- *   
- * linux/include/linux/auto_fs.h
- *
+/*
  *   Copyright 1997 Transmeta Corporation - All Rights Reserved
  *
  * This file is part of the Linux kernel and is made available under
@@ -51,7 +48,7 @@ struct autofs_packet_hdr {
 
 struct autofs_packet_missing {
        struct autofs_packet_hdr hdr;
-        autofs_wqt_t wait_queue_token;
+       autofs_wqt_t wait_queue_token;
        int len;
        char name[NAME_MAX+1];
 };     
@@ -63,12 +60,12 @@ struct autofs_packet_expire {
        char name[NAME_MAX+1];
 };
 
-#define AUTOFS_IOC_READY      _IO(0x93,0x60)
-#define AUTOFS_IOC_FAIL       _IO(0x93,0x61)
-#define AUTOFS_IOC_CATATONIC  _IO(0x93,0x62)
-#define AUTOFS_IOC_PROTOVER   _IOR(0x93,0x63,int)
-#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,compat_ulong_t)
-#define AUTOFS_IOC_SETTIMEOUT _IOWR(0x93,0x64,unsigned long)
-#define AUTOFS_IOC_EXPIRE     _IOR(0x93,0x65,struct autofs_packet_expire)
+#define AUTOFS_IOC_READY      _IO(0x93, 0x60)
+#define AUTOFS_IOC_FAIL       _IO(0x93, 0x61)
+#define AUTOFS_IOC_CATATONIC  _IO(0x93, 0x62)
+#define AUTOFS_IOC_PROTOVER   _IOR(0x93, 0x63, int)
+#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93, 0x64, compat_ulong_t)
+#define AUTOFS_IOC_SETTIMEOUT _IOWR(0x93, 0x64, unsigned long)
+#define AUTOFS_IOC_EXPIRE     _IOR(0x93, 0x65, struct autofs_packet_expire)
 
 #endif /* _UAPI_LINUX_AUTO_FS_H */
index e02982fa2953140719acc5968eed26e8f2058b8c..8f8f1bdcca8c07c8b237daf71525768d4685fc0f 100644 (file)
@@ -1,6 +1,4 @@
-/* -*- c -*-
- * linux/include/linux/auto_fs4.h
- *
+/*
  * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
  *
  * This file is part of the Linux kernel and is made available under
@@ -38,7 +36,6 @@
 static inline void set_autofs_type_indirect(unsigned int *type)
 {
        *type = AUTOFS_TYPE_INDIRECT;
-       return;
 }
 
 static inline unsigned int autofs_type_indirect(unsigned int type)
@@ -49,7 +46,6 @@ static inline unsigned int autofs_type_indirect(unsigned int type)
 static inline void set_autofs_type_direct(unsigned int *type)
 {
        *type = AUTOFS_TYPE_DIRECT;
-       return;
 }
 
 static inline unsigned int autofs_type_direct(unsigned int type)
@@ -60,7 +56,6 @@ static inline unsigned int autofs_type_direct(unsigned int type)
 static inline void set_autofs_type_offset(unsigned int *type)
 {
        *type = AUTOFS_TYPE_OFFSET;
-       return;
 }
 
 static inline unsigned int autofs_type_offset(unsigned int type)
@@ -81,7 +76,6 @@ static inline unsigned int autofs_type_trigger(unsigned int type)
 static inline void set_autofs_type_any(unsigned int *type)
 {
        *type = AUTOFS_TYPE_ANY;
-       return;
 }
 
 static inline unsigned int autofs_type_any(unsigned int type)
@@ -114,7 +108,7 @@ enum autofs_notify {
 /* v4 multi expire (via pipe) */
 struct autofs_packet_expire_multi {
        struct autofs_packet_hdr hdr;
-        autofs_wqt_t wait_queue_token;
+       autofs_wqt_t wait_queue_token;
        int len;
        char name[NAME_MAX+1];
 };
@@ -154,11 +148,10 @@ union autofs_v5_packet_union {
        autofs_packet_expire_direct_t expire_direct;
 };
 
-#define AUTOFS_IOC_EXPIRE_MULTI                _IOW(0x93,0x66,int)
+#define AUTOFS_IOC_EXPIRE_MULTI                _IOW(0x93, 0x66, int)
 #define AUTOFS_IOC_EXPIRE_INDIRECT     AUTOFS_IOC_EXPIRE_MULTI
 #define AUTOFS_IOC_EXPIRE_DIRECT       AUTOFS_IOC_EXPIRE_MULTI
-#define AUTOFS_IOC_PROTOSUBVER         _IOR(0x93,0x67,int)
-#define AUTOFS_IOC_ASKUMOUNT           _IOR(0x93,0x70,int)
-
+#define AUTOFS_IOC_PROTOSUBVER         _IOR(0x93, 0x67, int)
+#define AUTOFS_IOC_ASKUMOUNT           _IOR(0x93, 0x70, int)
 
 #endif /* _LINUX_AUTO_FS4_H */
index aa6f8571de136b74fba93996883bd69b3e28d412..5df4881dea7b5e8e42fc1274f967331a7d455600 100644 (file)
@@ -292,6 +292,9 @@ enum bpf_func_id {
 /* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
 #define BPF_F_TUNINFO_IPV6             (1ULL << 0)
 
+/* BPF_FUNC_skb_set_tunnel_key flags. */
+#define BPF_F_ZERO_CSUM_TX             (1ULL << 1)
+
 /* user accessible mirror of in-kernel sk_buff.
  * new fields can only be added to the end of this structure
  */
index 9da905157ceeebcb5afbd9e73b8ac56195954929..a7f1f8032ec1fbcb27bc452d818a71269af81a2e 100644 (file)
@@ -157,6 +157,7 @@ struct kvm_s390_skeys {
 
 struct kvm_hyperv_exit {
 #define KVM_EXIT_HYPERV_SYNIC          1
+#define KVM_EXIT_HYPERV_HCALL          2
        __u32 type;
        union {
                struct {
@@ -165,6 +166,11 @@ struct kvm_hyperv_exit {
                        __u64 evt_page;
                        __u64 msg_page;
                } synic;
+               struct {
+                       __u64 input;
+                       __u64 result;
+                       __u64 params[2];
+               } hcall;
        } u;
 };
 
@@ -541,7 +547,13 @@ struct kvm_s390_pgm_info {
        __u8 exc_access_id;
        __u8 per_access_id;
        __u8 op_access_id;
-       __u8 pad[3];
+#define KVM_S390_PGM_FLAGS_ILC_VALID   0x01
+#define KVM_S390_PGM_FLAGS_ILC_0       0x02
+#define KVM_S390_PGM_FLAGS_ILC_1       0x04
+#define KVM_S390_PGM_FLAGS_ILC_MASK    0x06
+#define KVM_S390_PGM_FLAGS_NO_REWIND   0x08
+       __u8 flags;
+       __u8 pad[2];
 };
 
 struct kvm_s390_prefix_info {
@@ -850,6 +862,9 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_IOEVENTFD_ANY_LENGTH 122
 #define KVM_CAP_HYPERV_SYNIC 123
 #define KVM_CAP_S390_RI 124
+#define KVM_CAP_SPAPR_TCE_64 125
+#define KVM_CAP_ARM_PMU_V3 126
+#define KVM_CAP_VCPU_ATTRIBUTES 127
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1142,6 +1157,8 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_PPC_ALLOC_HTAB */
 #define KVM_PPC_ALLOCATE_HTAB    _IOWR(KVMIO, 0xa7, __u32)
 #define KVM_CREATE_SPAPR_TCE     _IOW(KVMIO,  0xa8, struct kvm_create_spapr_tce)
+#define KVM_CREATE_SPAPR_TCE_64          _IOW(KVMIO,  0xa8, \
+                                      struct kvm_create_spapr_tce_64)
 /* Available with KVM_CAP_RMA */
 #define KVM_ALLOCATE_RMA         _IOR(KVMIO,  0xa9, struct kvm_allocate_rma)
 /* Available with KVM_CAP_PPC_HTAB_FD */
index 1e3c8cb43bd7ac61650da4b6e31ab854af4a7b89..a8e3a8c0d85a9173c7aa248b84e8e4e9fd01739f 100644 (file)
@@ -66,27 +66,33 @@ struct media_device_info {
 /*
  * DVB entities
  */
-#define MEDIA_ENT_F_DTV_DEMOD          (MEDIA_ENT_F_BASE + 1)
-#define MEDIA_ENT_F_TS_DEMUX           (MEDIA_ENT_F_BASE + 2)
-#define MEDIA_ENT_F_DTV_CA             (MEDIA_ENT_F_BASE + 3)
-#define MEDIA_ENT_F_DTV_NET_DECAP      (MEDIA_ENT_F_BASE + 4)
+#define MEDIA_ENT_F_DTV_DEMOD          (MEDIA_ENT_F_BASE + 0x00001)
+#define MEDIA_ENT_F_TS_DEMUX           (MEDIA_ENT_F_BASE + 0x00002)
+#define MEDIA_ENT_F_DTV_CA             (MEDIA_ENT_F_BASE + 0x00003)
+#define MEDIA_ENT_F_DTV_NET_DECAP      (MEDIA_ENT_F_BASE + 0x00004)
 
 /*
- * Connectors
+ * I/O entities
  */
-/* It is a responsibility of the entity drivers to add connectors and links */
-#define MEDIA_ENT_F_CONN_RF            (MEDIA_ENT_F_BASE + 21)
-#define MEDIA_ENT_F_CONN_SVIDEO                (MEDIA_ENT_F_BASE + 22)
-#define MEDIA_ENT_F_CONN_COMPOSITE     (MEDIA_ENT_F_BASE + 23)
-/* For internal test signal generators and other debug connectors */
-#define MEDIA_ENT_F_CONN_TEST          (MEDIA_ENT_F_BASE + 24)
+#define MEDIA_ENT_F_IO_DTV             (MEDIA_ENT_F_BASE + 0x01001)
+#define MEDIA_ENT_F_IO_VBI             (MEDIA_ENT_F_BASE + 0x01002)
+#define MEDIA_ENT_F_IO_SWRADIO         (MEDIA_ENT_F_BASE + 0x01003)
 
 /*
- * I/O entities
+ * Connectors
  */
-#define MEDIA_ENT_F_IO_DTV             (MEDIA_ENT_F_BASE + 31)
-#define MEDIA_ENT_F_IO_VBI             (MEDIA_ENT_F_BASE + 32)
-#define MEDIA_ENT_F_IO_SWRADIO         (MEDIA_ENT_F_BASE + 33)
+/* It is a responsibility of the entity drivers to add connectors and links */
+#ifdef __KERNEL__
+       /*
+        * For now, it should not be used in userspace, as some
+        * definitions may change
+        */
+
+#define MEDIA_ENT_F_CONN_RF            (MEDIA_ENT_F_BASE + 0x30001)
+#define MEDIA_ENT_F_CONN_SVIDEO                (MEDIA_ENT_F_BASE + 0x30002)
+#define MEDIA_ENT_F_CONN_COMPOSITE     (MEDIA_ENT_F_BASE + 0x30003)
+
+#endif
 
 /*
  * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and
@@ -114,7 +120,7 @@ struct media_device_info {
 
 #define MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN        MEDIA_ENT_F_OLD_SUBDEV_BASE
 
-#ifndef __KERNEL__
+#if !defined(__KERNEL__) || defined(__NEED_MEDIA_LEGACY_API)
 
 /*
  * Legacy symbols used to avoid userspace compilation breakages
@@ -127,6 +133,10 @@ struct media_device_info {
 #define MEDIA_ENT_TYPE_MASK            0x00ff0000
 #define MEDIA_ENT_SUBTYPE_MASK         0x0000ffff
 
+/* End of the old subdev reserved numberspace */
+#define MEDIA_ENT_T_DEVNODE_UNKNOWN    (MEDIA_ENT_T_DEVNODE | \
+                                        MEDIA_ENT_SUBTYPE_MASK)
+
 #define MEDIA_ENT_T_DEVNODE            MEDIA_ENT_F_OLD_BASE
 #define MEDIA_ENT_T_DEVNODE_V4L                MEDIA_ENT_F_IO_V4L
 #define MEDIA_ENT_T_DEVNODE_FB         (MEDIA_ENT_T_DEVNODE + 2)
@@ -291,14 +301,14 @@ struct media_v2_entity {
        __u32 id;
        char name[64];          /* FIXME: move to a property? (RFC says so) */
        __u32 function;         /* Main function of the entity */
-       __u16 reserved[12];
-};
+       __u32 reserved[6];
+} __attribute__ ((packed));
 
 /* Should match the specific fields at media_intf_devnode */
 struct media_v2_intf_devnode {
        __u32 major;
        __u32 minor;
-};
+} __attribute__ ((packed));
 
 struct media_v2_interface {
        __u32 id;
@@ -310,22 +320,22 @@ struct media_v2_interface {
                struct media_v2_intf_devnode devnode;
                __u32 raw[16];
        };
-};
+} __attribute__ ((packed));
 
 struct media_v2_pad {
        __u32 id;
        __u32 entity_id;
        __u32 flags;
-       __u16 reserved[9];
-};
+       __u32 reserved[5];
+} __attribute__ ((packed));
 
 struct media_v2_link {
        __u32 id;
        __u32 source_id;
        __u32 sink_id;
        __u32 flags;
-       __u32 reserved[5];
-};
+       __u32 reserved[6];
+} __attribute__ ((packed));
 
 struct media_v2_topology {
        __u64 topology_version;
@@ -345,7 +355,7 @@ struct media_v2_topology {
        __u32 num_links;
        __u32 reserved4;
        __u64 ptr_links;
-};
+} __attribute__ ((packed));
 
 static inline void __user *media_get_uptr(__u64 arg)
 {
index 5b4a4be06e2b9301699db8da20d8df8d10bc0a89..cc68b92124d46108d43241d2b4cc603c2771e5b0 100644 (file)
@@ -66,14 +66,18 @@ struct nd_cmd_ars_cap {
        __u64 length;
        __u32 status;
        __u32 max_ars_out;
+       __u32 clear_err_unit;
+       __u32 reserved;
 } __packed;
 
 struct nd_cmd_ars_start {
        __u64 address;
        __u64 length;
        __u16 type;
-       __u8 reserved[6];
+       __u8 flags;
+       __u8 reserved[5];
        __u32 status;
+       __u32 scrub_time;
 } __packed;
 
 struct nd_cmd_ars_status {
@@ -81,11 +85,14 @@ struct nd_cmd_ars_status {
        __u32 out_length;
        __u64 address;
        __u64 length;
+       __u64 restart_address;
+       __u64 restart_length;
        __u16 type;
+       __u16 flags;
        __u32 num_records;
        struct nd_ars_record {
                __u32 handle;
-               __u32 flags;
+               __u32 reserved;
                __u64 err_address;
                __u64 length;
        } __packed records[0];
index f0b7bfe5da920069a8acdca9dc018860495e0e59..ac6dded80ffa9282506eb8d26a50cb60646014f8 100644 (file)
@@ -51,7 +51,9 @@ struct ptp_clock_caps {
        int n_per_out; /* Number of programmable periodic signals. */
        int pps;       /* Whether the clock supports a PPS callback. */
        int n_pins;    /* Number of input/output pins. */
-       int rsv[14];   /* Reserved for future use. */
+       /* Whether the clock supports precise system-device cross timestamps */
+       int cross_timestamping;
+       int rsv[13];   /* Reserved for future use. */
 };
 
 struct ptp_extts_request {
@@ -81,6 +83,13 @@ struct ptp_sys_offset {
        struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
 };
 
+struct ptp_sys_offset_precise {
+       struct ptp_clock_time device;
+       struct ptp_clock_time sys_realtime;
+       struct ptp_clock_time sys_monoraw;
+       unsigned int rsv[4];    /* Reserved for future use. */
+};
+
 enum ptp_pin_function {
        PTP_PF_NONE,
        PTP_PF_EXTTS,
@@ -124,6 +133,8 @@ struct ptp_pin_desc {
 #define PTP_SYS_OFFSET     _IOW(PTP_CLK_MAGIC, 5, struct ptp_sys_offset)
 #define PTP_PIN_GETFUNC    _IOWR(PTP_CLK_MAGIC, 6, struct ptp_pin_desc)
 #define PTP_PIN_SETFUNC    _IOW(PTP_CLK_MAGIC, 7, struct ptp_pin_desc)
+#define PTP_SYS_OFFSET_PRECISE \
+       _IOWR(PTP_CLK_MAGIC, 8, struct ptp_sys_offset_precise)
 
 struct ptp_extts_event {
        struct ptp_clock_time t; /* Time event occured. */
index 22320804fbafdc57b7228b68392199657a7c2f49..fd664b3ab99ef79432643ab3e954943e759f81ca 100644 (file)
@@ -1420,6 +1420,28 @@ config KALLSYMS_ALL
 
           Say N unless you really need all symbols.
 
+config KALLSYMS_ABSOLUTE_PERCPU
+       bool
+       default X86_64 && SMP
+
+config KALLSYMS_BASE_RELATIVE
+       bool
+       depends on KALLSYMS
+       default !IA64 && !(TILE && 64BIT)
+       help
+         Instead of emitting them as absolute values in the native word size,
+         emit the symbol references in the kallsyms table as 32-bit entries,
+         each containing a relative value in the range [base, base + U32_MAX]
+         or, when KALLSYMS_ABSOLUTE_PERCPU is in effect, each containing either
+         an absolute value in the range [0, S32_MAX] or a relative value in the
+         range [base, base + S32_MAX], where base is the lowest relative symbol
+         address encountered in the image.
+
+         On 64-bit builds, this reduces the size of the address table by 50%,
+         but more importantly, it results in entries whose values are build
+         time constants, and no relocation pass is required at runtime to fix
+         up the entries based on the runtime load address of the kernel.
+
 config PRINTK
        default y
        bool "Enable support for printk" if EXPERT
index 58c9e374704bb20cfff41fa92afcf7cafe498c32..b3c6e363ae181b01fb5e530c2ae9b733c59c4ba4 100644 (file)
@@ -93,9 +93,6 @@ static int kernel_init(void *);
 extern void init_IRQ(void);
 extern void fork_init(void);
 extern void radix_tree_init(void);
-#ifndef CONFIG_DEBUG_RODATA
-static inline void mark_rodata_ro(void) { }
-#endif
 
 /*
  * Debug helper: via this flag we know that we are in 'early bootup code'
@@ -388,7 +385,6 @@ static noinline void __init_refok rest_init(void)
        int pid;
 
        rcu_scheduler_starting();
-       smpboot_thread_init();
        /*
         * We need to spawn init first so that it obtains pid 1, however
         * the init task will end up wanting to create kthreads, which, if
@@ -452,20 +448,6 @@ void __init parse_early_param(void)
        done = 1;
 }
 
-/*
- *     Activate the first processor.
- */
-
-static void __init boot_cpu_init(void)
-{
-       int cpu = smp_processor_id();
-       /* Mark the boot cpu "present", "online" etc for SMP and UP case */
-       set_cpu_online(cpu, true);
-       set_cpu_active(cpu, true);
-       set_cpu_present(cpu, true);
-       set_cpu_possible(cpu, true);
-}
-
 void __init __weak smp_setup_processor_id(void)
 {
 }
@@ -499,11 +481,6 @@ asmlinkage __visible void __init start_kernel(void)
        char *command_line;
        char *after_dashes;
 
-       /*
-        * Need to run as early as possible, to initialize the
-        * lockdep hash:
-        */
-       lockdep_init();
        set_task_stack_end_magic(&init_task);
        smp_setup_processor_id();
        debug_objects_early_init();
@@ -530,6 +507,7 @@ asmlinkage __visible void __init start_kernel(void)
        setup_command_line(command_line);
        setup_nr_cpu_ids();
        setup_per_cpu_areas();
+       boot_cpu_state_init();
        smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
 
        build_all_zonelists(NULL, NULL);
@@ -727,7 +705,6 @@ static int __init initcall_blacklist(char *str)
 
 static bool __init_or_module initcall_blacklisted(initcall_t fn)
 {
-       struct list_head *tmp;
        struct blacklist_entry *entry;
        char *fn_name;
 
@@ -735,8 +712,7 @@ static bool __init_or_module initcall_blacklisted(initcall_t fn)
        if (!fn_name)
                return false;
 
-       list_for_each(tmp, &blacklisted_initcalls) {
-               entry = list_entry(tmp, struct blacklist_entry, next);
+       list_for_each_entry(entry, &blacklisted_initcalls, next) {
                if (!strcmp(fn_name, entry->buf)) {
                        pr_debug("initcall %s blacklisted\n", fn_name);
                        kfree(fn_name);
@@ -929,6 +905,28 @@ static int try_to_run_init_process(const char *init_filename)
 
 static noinline void __init kernel_init_freeable(void);
 
+#ifdef CONFIG_DEBUG_RODATA
+static bool rodata_enabled = true;
+static int __init set_debug_rodata(char *str)
+{
+       return strtobool(str, &rodata_enabled);
+}
+__setup("rodata=", set_debug_rodata);
+
+static void mark_readonly(void)
+{
+       if (rodata_enabled)
+               mark_rodata_ro();
+       else
+               pr_info("Kernel memory protection disabled.\n");
+}
+#else
+static inline void mark_readonly(void)
+{
+       pr_warn("This architecture does not have kernel memory protection.\n");
+}
+#endif
+
 static int __ref kernel_init(void *unused)
 {
        int ret;
@@ -937,7 +935,7 @@ static int __ref kernel_init(void *unused)
        /* need to finish all async __init code before freeing the memory */
        async_synchronize_full();
        free_initmem();
-       mark_rodata_ro();
+       mark_readonly();
        system_state = SYSTEM_RUNNING;
        numa_default_policy();
 
index 5b9d39633ce9d9c01bac677f3575e9b301dcb394..6ea42e8da861b05077d01a23e15bb140afffa605 100644 (file)
 #include <linux/lockdep.h>
 #include <linux/tick.h>
 #include <linux/irq.h>
+#include <linux/smpboot.h>
+
 #include <trace/events/power.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/cpuhp.h>
 
 #include "smpboot.h"
 
+/**
+ * cpuhp_cpu_state - Per cpu hotplug state storage
+ * @state:     The current cpu state
+ * @target:    The target state
+ * @thread:    Pointer to the hotplug thread
+ * @should_run:        Thread should execute
+ * @cb_stat:   The state for a single callback (install/uninstall)
+ * @cb:                Single callback function (install/uninstall)
+ * @result:    Result of the operation
+ * @done:      Signal completion to the issuer of the task
+ */
+struct cpuhp_cpu_state {
+       enum cpuhp_state        state;
+       enum cpuhp_state        target;
+#ifdef CONFIG_SMP
+       struct task_struct      *thread;
+       bool                    should_run;
+       enum cpuhp_state        cb_state;
+       int                     (*cb)(unsigned int cpu);
+       int                     result;
+       struct completion       done;
+#endif
+};
+
+static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state);
+
+/**
+ * cpuhp_step - Hotplug state machine step
+ * @name:      Name of the step
+ * @startup:   Startup function of the step
+ * @teardown:  Teardown function of the step
+ * @skip_onerr:        Do not invoke the functions on error rollback
+ *             Will go away once the notifiers are gone
+ * @cant_stop: Bringup/teardown can't be stopped at this step
+ */
+struct cpuhp_step {
+       const char      *name;
+       int             (*startup)(unsigned int cpu);
+       int             (*teardown)(unsigned int cpu);
+       bool            skip_onerr;
+       bool            cant_stop;
+};
+
+static DEFINE_MUTEX(cpuhp_state_mutex);
+static struct cpuhp_step cpuhp_bp_states[];
+static struct cpuhp_step cpuhp_ap_states[];
+
+/**
+ * cpuhp_invoke_callback _ Invoke the callbacks for a given state
+ * @cpu:       The cpu for which the callback should be invoked
+ * @step:      The step in the state machine
+ * @cb:                The callback function to invoke
+ *
+ * Called from cpu hotplug and from the state register machinery
+ */
+static int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state step,
+                                int (*cb)(unsigned int))
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+       int ret = 0;
+
+       if (cb) {
+               trace_cpuhp_enter(cpu, st->target, step, cb);
+               ret = cb(cpu);
+               trace_cpuhp_exit(cpu, st->state, step, ret);
+       }
+       return ret;
+}
+
 #ifdef CONFIG_SMP
 /* Serializes the updates to cpu_online_mask, cpu_present_mask */
 static DEFINE_MUTEX(cpu_add_remove_lock);
+bool cpuhp_tasks_frozen;
+EXPORT_SYMBOL_GPL(cpuhp_tasks_frozen);
 
 /*
  * The following two APIs (cpu_maps_update_begin/done) must be used when
@@ -207,31 +282,281 @@ int __register_cpu_notifier(struct notifier_block *nb)
        return raw_notifier_chain_register(&cpu_chain, nb);
 }
 
-static int __cpu_notify(unsigned long val, void *v, int nr_to_call,
+static int __cpu_notify(unsigned long val, unsigned int cpu, int nr_to_call,
                        int *nr_calls)
 {
+       unsigned long mod = cpuhp_tasks_frozen ? CPU_TASKS_FROZEN : 0;
+       void *hcpu = (void *)(long)cpu;
+
        int ret;
 
-       ret = __raw_notifier_call_chain(&cpu_chain, val, v, nr_to_call,
+       ret = __raw_notifier_call_chain(&cpu_chain, val | mod, hcpu, nr_to_call,
                                        nr_calls);
 
        return notifier_to_errno(ret);
 }
 
-static int cpu_notify(unsigned long val, void *v)
+static int cpu_notify(unsigned long val, unsigned int cpu)
 {
-       return __cpu_notify(val, v, -1, NULL);
+       return __cpu_notify(val, cpu, -1, NULL);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
+/* Notifier wrappers for transitioning to state machine */
+static int notify_prepare(unsigned int cpu)
+{
+       int nr_calls = 0;
+       int ret;
+
+       ret = __cpu_notify(CPU_UP_PREPARE, cpu, -1, &nr_calls);
+       if (ret) {
+               nr_calls--;
+               printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n",
+                               __func__, cpu);
+               __cpu_notify(CPU_UP_CANCELED, cpu, nr_calls, NULL);
+       }
+       return ret;
+}
+
+static int notify_online(unsigned int cpu)
+{
+       cpu_notify(CPU_ONLINE, cpu);
+       return 0;
+}
+
+static int notify_starting(unsigned int cpu)
+{
+       cpu_notify(CPU_STARTING, cpu);
+       return 0;
+}
+
+static int bringup_wait_for_ap(unsigned int cpu)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+
+       wait_for_completion(&st->done);
+       return st->result;
+}
+
+static int bringup_cpu(unsigned int cpu)
+{
+       struct task_struct *idle = idle_thread_get(cpu);
+       int ret;
+
+       /* Arch-specific enabling code. */
+       ret = __cpu_up(cpu, idle);
+       if (ret) {
+               cpu_notify(CPU_UP_CANCELED, cpu);
+               return ret;
+       }
+       ret = bringup_wait_for_ap(cpu);
+       BUG_ON(!cpu_online(cpu));
+       return ret;
+}
+
+/*
+ * Hotplug state machine related functions
+ */
+static void undo_cpu_down(unsigned int cpu, struct cpuhp_cpu_state *st,
+                         struct cpuhp_step *steps)
+{
+       for (st->state++; st->state < st->target; st->state++) {
+               struct cpuhp_step *step = steps + st->state;
+
+               if (!step->skip_onerr)
+                       cpuhp_invoke_callback(cpu, st->state, step->startup);
+       }
+}
+
+static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
+                               struct cpuhp_step *steps, enum cpuhp_state target)
+{
+       enum cpuhp_state prev_state = st->state;
+       int ret = 0;
+
+       for (; st->state > target; st->state--) {
+               struct cpuhp_step *step = steps + st->state;
+
+               ret = cpuhp_invoke_callback(cpu, st->state, step->teardown);
+               if (ret) {
+                       st->target = prev_state;
+                       undo_cpu_down(cpu, st, steps);
+                       break;
+               }
+       }
+       return ret;
+}
+
+static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st,
+                       struct cpuhp_step *steps)
+{
+       for (st->state--; st->state > st->target; st->state--) {
+               struct cpuhp_step *step = steps + st->state;
+
+               if (!step->skip_onerr)
+                       cpuhp_invoke_callback(cpu, st->state, step->teardown);
+       }
+}
+
+static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
+                             struct cpuhp_step *steps, enum cpuhp_state target)
+{
+       enum cpuhp_state prev_state = st->state;
+       int ret = 0;
+
+       while (st->state < target) {
+               struct cpuhp_step *step;
+
+               st->state++;
+               step = steps + st->state;
+               ret = cpuhp_invoke_callback(cpu, st->state, step->startup);
+               if (ret) {
+                       st->target = prev_state;
+                       undo_cpu_up(cpu, st, steps);
+                       break;
+               }
+       }
+       return ret;
+}
+
+/*
+ * The cpu hotplug threads manage the bringup and teardown of the cpus
+ */
+static void cpuhp_create(unsigned int cpu)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+
+       init_completion(&st->done);
+}
+
+static int cpuhp_should_run(unsigned int cpu)
+{
+       struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
+
+       return st->should_run;
+}
+
+/* Execute the teardown callbacks. Used to be CPU_DOWN_PREPARE */
+static int cpuhp_ap_offline(unsigned int cpu, struct cpuhp_cpu_state *st)
+{
+       enum cpuhp_state target = max((int)st->target, CPUHP_TEARDOWN_CPU);
+
+       return cpuhp_down_callbacks(cpu, st, cpuhp_ap_states, target);
+}
+
+/* Execute the online startup callbacks. Used to be CPU_ONLINE */
+static int cpuhp_ap_online(unsigned int cpu, struct cpuhp_cpu_state *st)
+{
+       return cpuhp_up_callbacks(cpu, st, cpuhp_ap_states, st->target);
+}
+
+/*
+ * Execute teardown/startup callbacks on the plugged cpu. Also used to invoke
+ * callbacks when a state gets [un]installed at runtime.
+ */
+static void cpuhp_thread_fun(unsigned int cpu)
+{
+       struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
+       int ret = 0;
+
+       /*
+        * Paired with the mb() in cpuhp_kick_ap_work and
+        * cpuhp_invoke_ap_callback, so the work set is consistent visible.
+        */
+       smp_mb();
+       if (!st->should_run)
+               return;
+
+       st->should_run = false;
+
+       /* Single callback invocation for [un]install ? */
+       if (st->cb) {
+               if (st->cb_state < CPUHP_AP_ONLINE) {
+                       local_irq_disable();
+                       ret = cpuhp_invoke_callback(cpu, st->cb_state, st->cb);
+                       local_irq_enable();
+               } else {
+                       ret = cpuhp_invoke_callback(cpu, st->cb_state, st->cb);
+               }
+       } else {
+               /* Cannot happen .... */
+               BUG_ON(st->state < CPUHP_AP_ONLINE_IDLE);
+
+               /* Regular hotplug work */
+               if (st->state < st->target)
+                       ret = cpuhp_ap_online(cpu, st);
+               else if (st->state > st->target)
+                       ret = cpuhp_ap_offline(cpu, st);
+       }
+       st->result = ret;
+       complete(&st->done);
+}
 
-static void cpu_notify_nofail(unsigned long val, void *v)
+/* Invoke a single callback on a remote cpu */
+static int cpuhp_invoke_ap_callback(int cpu, enum cpuhp_state state,
+                                   int (*cb)(unsigned int))
 {
-       BUG_ON(cpu_notify(val, v));
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+
+       if (!cpu_online(cpu))
+               return 0;
+
+       st->cb_state = state;
+       st->cb = cb;
+       /*
+        * Make sure the above stores are visible before should_run becomes
+        * true. Paired with the mb() above in cpuhp_thread_fun()
+        */
+       smp_mb();
+       st->should_run = true;
+       wake_up_process(st->thread);
+       wait_for_completion(&st->done);
+       return st->result;
 }
+
+/* Regular hotplug invocation of the AP hotplug thread */
+static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st)
+{
+       st->result = 0;
+       st->cb = NULL;
+       /*
+        * Make sure the above stores are visible before should_run becomes
+        * true. Paired with the mb() above in cpuhp_thread_fun()
+        */
+       smp_mb();
+       st->should_run = true;
+       wake_up_process(st->thread);
+}
+
+static int cpuhp_kick_ap_work(unsigned int cpu)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+       enum cpuhp_state state = st->state;
+
+       trace_cpuhp_enter(cpu, st->target, state, cpuhp_kick_ap_work);
+       __cpuhp_kick_ap_work(st);
+       wait_for_completion(&st->done);
+       trace_cpuhp_exit(cpu, st->state, state, st->result);
+       return st->result;
+}
+
+static struct smp_hotplug_thread cpuhp_threads = {
+       .store                  = &cpuhp_state.thread,
+       .create                 = &cpuhp_create,
+       .thread_should_run      = cpuhp_should_run,
+       .thread_fn              = cpuhp_thread_fun,
+       .thread_comm            = "cpuhp/%u",
+       .selfparking            = true,
+};
+
+void __init cpuhp_threads_init(void)
+{
+       BUG_ON(smpboot_register_percpu_thread(&cpuhp_threads));
+       kthread_unpark(this_cpu_read(cpuhp_state.thread));
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
 EXPORT_SYMBOL(register_cpu_notifier);
 EXPORT_SYMBOL(__register_cpu_notifier);
-
 void unregister_cpu_notifier(struct notifier_block *nb)
 {
        cpu_maps_update_begin();
@@ -311,57 +636,60 @@ static inline void check_for_tasks(int dead_cpu)
        read_unlock(&tasklist_lock);
 }
 
-struct take_cpu_down_param {
-       unsigned long mod;
-       void *hcpu;
-};
+static void cpu_notify_nofail(unsigned long val, unsigned int cpu)
+{
+       BUG_ON(cpu_notify(val, cpu));
+}
+
+static int notify_down_prepare(unsigned int cpu)
+{
+       int err, nr_calls = 0;
+
+       err = __cpu_notify(CPU_DOWN_PREPARE, cpu, -1, &nr_calls);
+       if (err) {
+               nr_calls--;
+               __cpu_notify(CPU_DOWN_FAILED, cpu, nr_calls, NULL);
+               pr_warn("%s: attempt to take down CPU %u failed\n",
+                               __func__, cpu);
+       }
+       return err;
+}
+
+static int notify_dying(unsigned int cpu)
+{
+       cpu_notify(CPU_DYING, cpu);
+       return 0;
+}
 
 /* Take this CPU down. */
 static int take_cpu_down(void *_param)
 {
-       struct take_cpu_down_param *param = _param;
-       int err;
+       struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
+       enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE);
+       int err, cpu = smp_processor_id();
 
        /* Ensure this CPU doesn't handle any more interrupts. */
        err = __cpu_disable();
        if (err < 0)
                return err;
 
-       cpu_notify(CPU_DYING | param->mod, param->hcpu);
+       /* Invoke the former CPU_DYING callbacks */
+       for (; st->state > target; st->state--) {
+               struct cpuhp_step *step = cpuhp_ap_states + st->state;
+
+               cpuhp_invoke_callback(cpu, st->state, step->teardown);
+       }
        /* Give up timekeeping duties */
        tick_handover_do_timer();
        /* Park the stopper thread */
-       stop_machine_park((long)param->hcpu);
+       stop_machine_park(cpu);
        return 0;
 }
 
-/* Requires cpu_add_remove_lock to be held */
-static int _cpu_down(unsigned int cpu, int tasks_frozen)
+static int takedown_cpu(unsigned int cpu)
 {
-       int err, nr_calls = 0;
-       void *hcpu = (void *)(long)cpu;
-       unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
-       struct take_cpu_down_param tcd_param = {
-               .mod = mod,
-               .hcpu = hcpu,
-       };
-
-       if (num_online_cpus() == 1)
-               return -EBUSY;
-
-       if (!cpu_online(cpu))
-               return -EINVAL;
-
-       cpu_hotplug_begin();
-
-       err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls);
-       if (err) {
-               nr_calls--;
-               __cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL);
-               pr_warn("%s: attempt to take down CPU %u failed\n",
-                       __func__, cpu);
-               goto out_release;
-       }
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+       int err;
 
        /*
         * By now we've cleared cpu_active_mask, wait for all preempt-disabled
@@ -378,6 +706,8 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
        else
                synchronize_rcu();
 
+       /* Park the smpboot threads */
+       kthread_park(per_cpu_ptr(&cpuhp_state, cpu)->thread);
        smpboot_park_threads(cpu);
 
        /*
@@ -389,12 +719,12 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
        /*
         * So now all preempt/rcu users must observe !cpu_active().
         */
-       err = stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
+       err = stop_machine(take_cpu_down, NULL, cpumask_of(cpu));
        if (err) {
                /* CPU didn't die: tell everyone.  Can't complain. */
-               cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu);
+               cpu_notify_nofail(CPU_DOWN_FAILEDcpu);
                irq_unlock_sparse();
-               goto out_release;
+               return err;
        }
        BUG_ON(cpu_online(cpu));
 
@@ -405,10 +735,8 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
         *
         * Wait for the stop thread to go away.
         */
-       while (!per_cpu(cpu_dead_idle, cpu))
-               cpu_relax();
-       smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */
-       per_cpu(cpu_dead_idle, cpu) = false;
+       wait_for_completion(&st->done);
+       BUG_ON(st->state != CPUHP_AP_IDLE_DEAD);
 
        /* Interrupts are moved away from the dying cpu, reenable alloc/free */
        irq_unlock_sparse();
@@ -417,20 +745,104 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen)
        /* This actually kills the CPU. */
        __cpu_die(cpu);
 
-       /* CPU is completely dead: tell everyone.  Too late to complain. */
        tick_cleanup_dead_cpu(cpu);
-       cpu_notify_nofail(CPU_DEAD | mod, hcpu);
+       return 0;
+}
 
+static int notify_dead(unsigned int cpu)
+{
+       cpu_notify_nofail(CPU_DEAD, cpu);
        check_for_tasks(cpu);
+       return 0;
+}
 
-out_release:
+static void cpuhp_complete_idle_dead(void *arg)
+{
+       struct cpuhp_cpu_state *st = arg;
+
+       complete(&st->done);
+}
+
+void cpuhp_report_idle_dead(void)
+{
+       struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
+
+       BUG_ON(st->state != CPUHP_AP_OFFLINE);
+       rcu_report_dead(smp_processor_id());
+       st->state = CPUHP_AP_IDLE_DEAD;
+       /*
+        * We cannot call complete after rcu_report_dead() so we delegate it
+        * to an online cpu.
+        */
+       smp_call_function_single(cpumask_first(cpu_online_mask),
+                                cpuhp_complete_idle_dead, st, 0);
+}
+
+#else
+#define notify_down_prepare    NULL
+#define takedown_cpu           NULL
+#define notify_dead            NULL
+#define notify_dying           NULL
+#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+/* Requires cpu_add_remove_lock to be held */
+static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
+                          enum cpuhp_state target)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+       int prev_state, ret = 0;
+       bool hasdied = false;
+
+       if (num_online_cpus() == 1)
+               return -EBUSY;
+
+       if (!cpu_present(cpu))
+               return -EINVAL;
+
+       cpu_hotplug_begin();
+
+       cpuhp_tasks_frozen = tasks_frozen;
+
+       prev_state = st->state;
+       st->target = target;
+       /*
+        * If the current CPU state is in the range of the AP hotplug thread,
+        * then we need to kick the thread.
+        */
+       if (st->state > CPUHP_TEARDOWN_CPU) {
+               ret = cpuhp_kick_ap_work(cpu);
+               /*
+                * The AP side has done the error rollback already. Just
+                * return the error code..
+                */
+               if (ret)
+                       goto out;
+
+               /*
+                * We might have stopped still in the range of the AP hotplug
+                * thread. Nothing to do anymore.
+                */
+               if (st->state > CPUHP_TEARDOWN_CPU)
+                       goto out;
+       }
+       /*
+        * The AP brought itself down to CPUHP_TEARDOWN_CPU. So we need
+        * to do the further cleanups.
+        */
+       ret = cpuhp_down_callbacks(cpu, st, cpuhp_bp_states, target);
+
+       hasdied = prev_state != st->state && st->state == CPUHP_OFFLINE;
+out:
        cpu_hotplug_done();
-       if (!err)
-               cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);
-       return err;
+       /* This post dead nonsense must die */
+       if (!ret && hasdied)
+               cpu_notify_nofail(CPU_POST_DEAD, cpu);
+       return ret;
 }
 
-int cpu_down(unsigned int cpu)
+static int do_cpu_down(unsigned int cpu, enum cpuhp_state target)
 {
        int err;
 
@@ -441,100 +853,131 @@ int cpu_down(unsigned int cpu)
                goto out;
        }
 
-       err = _cpu_down(cpu, 0);
+       err = _cpu_down(cpu, 0, target);
 
 out:
        cpu_maps_update_done();
        return err;
 }
+int cpu_down(unsigned int cpu)
+{
+       return do_cpu_down(cpu, CPUHP_OFFLINE);
+}
 EXPORT_SYMBOL(cpu_down);
 #endif /*CONFIG_HOTPLUG_CPU*/
 
-/*
- * Unpark per-CPU smpboot kthreads at CPU-online time.
+/**
+ * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers
+ * @cpu: cpu that just started
+ *
+ * This function calls the cpu_chain notifiers with CPU_STARTING.
+ * It must be called by the arch code on the new cpu, before the new cpu
+ * enables interrupts and before the "boot" cpu returns from __cpu_up().
  */
-static int smpboot_thread_call(struct notifier_block *nfb,
-                              unsigned long action, void *hcpu)
+void notify_cpu_starting(unsigned int cpu)
 {
-       int cpu = (long)hcpu;
-
-       switch (action & ~CPU_TASKS_FROZEN) {
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+       enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE);
 
-       case CPU_DOWN_FAILED:
-       case CPU_ONLINE:
-               smpboot_unpark_threads(cpu);
-               break;
+       while (st->state < target) {
+               struct cpuhp_step *step;
 
-       default:
-               break;
+               st->state++;
+               step = cpuhp_ap_states + st->state;
+               cpuhp_invoke_callback(cpu, st->state, step->startup);
        }
-
-       return NOTIFY_OK;
 }
 
-static struct notifier_block smpboot_thread_notifier = {
-       .notifier_call = smpboot_thread_call,
-       .priority = CPU_PRI_SMPBOOT,
-};
-
-void smpboot_thread_init(void)
+/*
+ * Called from the idle task. We need to set active here, so we can kick off
+ * the stopper thread and unpark the smpboot threads. If the target state is
+ * beyond CPUHP_AP_ONLINE_IDLE we kick cpuhp thread and let it bring up the
+ * cpu further.
+ */
+void cpuhp_online_idle(enum cpuhp_state state)
 {
-       register_cpu_notifier(&smpboot_thread_notifier);
+       struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
+       unsigned int cpu = smp_processor_id();
+
+       /* Happens for the boot cpu */
+       if (state != CPUHP_AP_ONLINE_IDLE)
+               return;
+
+       st->state = CPUHP_AP_ONLINE_IDLE;
+
+       /* The cpu is marked online, set it active now */
+       set_cpu_active(cpu, true);
+       /* Unpark the stopper thread and the hotplug thread of this cpu */
+       stop_machine_unpark(cpu);
+       kthread_unpark(st->thread);
+
+       /* Should we go further up ? */
+       if (st->target > CPUHP_AP_ONLINE_IDLE)
+               __cpuhp_kick_ap_work(st);
+       else
+               complete(&st->done);
 }
 
 /* Requires cpu_add_remove_lock to be held */
-static int _cpu_up(unsigned int cpu, int tasks_frozen)
+static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
 {
-       int ret, nr_calls = 0;
-       void *hcpu = (void *)(long)cpu;
-       unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
        struct task_struct *idle;
+       int ret = 0;
 
        cpu_hotplug_begin();
 
-       if (cpu_online(cpu) || !cpu_present(cpu)) {
+       if (!cpu_present(cpu)) {
                ret = -EINVAL;
                goto out;
        }
 
-       idle = idle_thread_get(cpu);
-       if (IS_ERR(idle)) {
-               ret = PTR_ERR(idle);
-               goto out;
-       }
-
-       ret = smpboot_create_threads(cpu);
-       if (ret)
+       /*
+        * The caller of do_cpu_up might have raced with another
+        * caller. Ignore it for now.
+        */
+       if (st->state >= target)
                goto out;
 
-       ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls);
-       if (ret) {
-               nr_calls--;
-               pr_warn("%s: attempt to bring up CPU %u failed\n",
-                       __func__, cpu);
-               goto out_notify;
+       if (st->state == CPUHP_OFFLINE) {
+               /* Let it fail before we try to bring the cpu up */
+               idle = idle_thread_get(cpu);
+               if (IS_ERR(idle)) {
+                       ret = PTR_ERR(idle);
+                       goto out;
+               }
        }
 
-       /* Arch-specific enabling code. */
-       ret = __cpu_up(cpu, idle);
-
-       if (ret != 0)
-               goto out_notify;
-       BUG_ON(!cpu_online(cpu));
+       cpuhp_tasks_frozen = tasks_frozen;
 
-       /* Now call notifier in preparation. */
-       cpu_notify(CPU_ONLINE | mod, hcpu);
+       st->target = target;
+       /*
+        * If the current CPU state is in the range of the AP hotplug thread,
+        * then we need to kick the thread once more.
+        */
+       if (st->state > CPUHP_BRINGUP_CPU) {
+               ret = cpuhp_kick_ap_work(cpu);
+               /*
+                * The AP side has done the error rollback already. Just
+                * return the error code..
+                */
+               if (ret)
+                       goto out;
+       }
 
-out_notify:
-       if (ret != 0)
-               __cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);
+       /*
+        * Try to reach the target state. We max out on the BP at
+        * CPUHP_BRINGUP_CPU. After that the AP hotplug thread is
+        * responsible for bringing it up to the target state.
+        */
+       target = min((int)target, CPUHP_BRINGUP_CPU);
+       ret = cpuhp_up_callbacks(cpu, st, cpuhp_bp_states, target);
 out:
        cpu_hotplug_done();
-
        return ret;
 }
 
-int cpu_up(unsigned int cpu)
+static int do_cpu_up(unsigned int cpu, enum cpuhp_state target)
 {
        int err = 0;
 
@@ -558,12 +1001,16 @@ int cpu_up(unsigned int cpu)
                goto out;
        }
 
-       err = _cpu_up(cpu, 0);
-
+       err = _cpu_up(cpu, 0, target);
 out:
        cpu_maps_update_done();
        return err;
 }
+
+int cpu_up(unsigned int cpu)
+{
+       return do_cpu_up(cpu, CPUHP_ONLINE);
+}
 EXPORT_SYMBOL_GPL(cpu_up);
 
 #ifdef CONFIG_PM_SLEEP_SMP
@@ -586,7 +1033,7 @@ int disable_nonboot_cpus(void)
                if (cpu == first_cpu)
                        continue;
                trace_suspend_resume(TPS("CPU_OFF"), cpu, true);
-               error = _cpu_down(cpu, 1);
+               error = _cpu_down(cpu, 1, CPUHP_OFFLINE);
                trace_suspend_resume(TPS("CPU_OFF"), cpu, false);
                if (!error)
                        cpumask_set_cpu(cpu, frozen_cpus);
@@ -636,7 +1083,7 @@ void enable_nonboot_cpus(void)
 
        for_each_cpu(cpu, frozen_cpus) {
                trace_suspend_resume(TPS("CPU_ON"), cpu, true);
-               error = _cpu_up(cpu, 1);
+               error = _cpu_up(cpu, 1, CPUHP_ONLINE);
                trace_suspend_resume(TPS("CPU_ON"), cpu, false);
                if (!error) {
                        pr_info("CPU%d is up\n", cpu);
@@ -709,26 +1156,463 @@ core_initcall(cpu_hotplug_pm_sync_init);
 
 #endif /* CONFIG_PM_SLEEP_SMP */
 
+#endif /* CONFIG_SMP */
+
+/* Boot processor state steps */
+static struct cpuhp_step cpuhp_bp_states[] = {
+       [CPUHP_OFFLINE] = {
+               .name                   = "offline",
+               .startup                = NULL,
+               .teardown               = NULL,
+       },
+#ifdef CONFIG_SMP
+       [CPUHP_CREATE_THREADS]= {
+               .name                   = "threads:create",
+               .startup                = smpboot_create_threads,
+               .teardown               = NULL,
+               .cant_stop              = true,
+       },
+       /*
+        * Preparatory and dead notifiers. Will be replaced once the notifiers
+        * are converted to states.
+        */
+       [CPUHP_NOTIFY_PREPARE] = {
+               .name                   = "notify:prepare",
+               .startup                = notify_prepare,
+               .teardown               = notify_dead,
+               .skip_onerr             = true,
+               .cant_stop              = true,
+       },
+       /* Kicks the plugged cpu into life */
+       [CPUHP_BRINGUP_CPU] = {
+               .name                   = "cpu:bringup",
+               .startup                = bringup_cpu,
+               .teardown               = NULL,
+               .cant_stop              = true,
+       },
+       /*
+        * Handled on controll processor until the plugged processor manages
+        * this itself.
+        */
+       [CPUHP_TEARDOWN_CPU] = {
+               .name                   = "cpu:teardown",
+               .startup                = NULL,
+               .teardown               = takedown_cpu,
+               .cant_stop              = true,
+       },
+#endif
+};
+
+/* Application processor state steps */
+static struct cpuhp_step cpuhp_ap_states[] = {
+#ifdef CONFIG_SMP
+       /* Final state before CPU kills itself */
+       [CPUHP_AP_IDLE_DEAD] = {
+               .name                   = "idle:dead",
+       },
+       /*
+        * Last state before CPU enters the idle loop to die. Transient state
+        * for synchronization.
+        */
+       [CPUHP_AP_OFFLINE] = {
+               .name                   = "ap:offline",
+               .cant_stop              = true,
+       },
+       /*
+        * Low level startup/teardown notifiers. Run with interrupts
+        * disabled. Will be removed once the notifiers are converted to
+        * states.
+        */
+       [CPUHP_AP_NOTIFY_STARTING] = {
+               .name                   = "notify:starting",
+               .startup                = notify_starting,
+               .teardown               = notify_dying,
+               .skip_onerr             = true,
+               .cant_stop              = true,
+       },
+       /* Entry state on starting. Interrupts enabled from here on. Transient
+        * state for synchronsization */
+       [CPUHP_AP_ONLINE] = {
+               .name                   = "ap:online",
+       },
+       /* Handle smpboot threads park/unpark */
+       [CPUHP_AP_SMPBOOT_THREADS] = {
+               .name                   = "smpboot:threads",
+               .startup                = smpboot_unpark_threads,
+               .teardown               = NULL,
+       },
+       /*
+        * Online/down_prepare notifiers. Will be removed once the notifiers
+        * are converted to states.
+        */
+       [CPUHP_AP_NOTIFY_ONLINE] = {
+               .name                   = "notify:online",
+               .startup                = notify_online,
+               .teardown               = notify_down_prepare,
+       },
+#endif
+       /*
+        * The dynamically registered state space is here
+        */
+
+       /* CPU is fully up and running. */
+       [CPUHP_ONLINE] = {
+               .name                   = "online",
+               .startup                = NULL,
+               .teardown               = NULL,
+       },
+};
+
+/* Sanity check for callbacks */
+static int cpuhp_cb_check(enum cpuhp_state state)
+{
+       if (state <= CPUHP_OFFLINE || state >= CPUHP_ONLINE)
+               return -EINVAL;
+       return 0;
+}
+
+static bool cpuhp_is_ap_state(enum cpuhp_state state)
+{
+       /*
+        * The extra check for CPUHP_TEARDOWN_CPU is only for documentation
+        * purposes as that state is handled explicitely in cpu_down.
+        */
+       return state > CPUHP_BRINGUP_CPU && state != CPUHP_TEARDOWN_CPU;
+}
+
+static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state)
+{
+       struct cpuhp_step *sp;
+
+       sp = cpuhp_is_ap_state(state) ? cpuhp_ap_states : cpuhp_bp_states;
+       return sp + state;
+}
+
+static void cpuhp_store_callbacks(enum cpuhp_state state,
+                                 const char *name,
+                                 int (*startup)(unsigned int cpu),
+                                 int (*teardown)(unsigned int cpu))
+{
+       /* (Un)Install the callbacks for further cpu hotplug operations */
+       struct cpuhp_step *sp;
+
+       mutex_lock(&cpuhp_state_mutex);
+       sp = cpuhp_get_step(state);
+       sp->startup = startup;
+       sp->teardown = teardown;
+       sp->name = name;
+       mutex_unlock(&cpuhp_state_mutex);
+}
+
+static void *cpuhp_get_teardown_cb(enum cpuhp_state state)
+{
+       return cpuhp_get_step(state)->teardown;
+}
+
+/*
+ * Call the startup/teardown function for a step either on the AP or
+ * on the current CPU.
+ */
+static int cpuhp_issue_call(int cpu, enum cpuhp_state state,
+                           int (*cb)(unsigned int), bool bringup)
+{
+       int ret;
+
+       if (!cb)
+               return 0;
+       /*
+        * The non AP bound callbacks can fail on bringup. On teardown
+        * e.g. module removal we crash for now.
+        */
+#ifdef CONFIG_SMP
+       if (cpuhp_is_ap_state(state))
+               ret = cpuhp_invoke_ap_callback(cpu, state, cb);
+       else
+               ret = cpuhp_invoke_callback(cpu, state, cb);
+#else
+       ret = cpuhp_invoke_callback(cpu, state, cb);
+#endif
+       BUG_ON(ret && !bringup);
+       return ret;
+}
+
+/*
+ * Called from __cpuhp_setup_state on a recoverable failure.
+ *
+ * Note: The teardown callbacks for rollback are not allowed to fail!
+ */
+static void cpuhp_rollback_install(int failedcpu, enum cpuhp_state state,
+                                  int (*teardown)(unsigned int cpu))
+{
+       int cpu;
+
+       if (!teardown)
+               return;
+
+       /* Roll back the already executed steps on the other cpus */
+       for_each_present_cpu(cpu) {
+               struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+               int cpustate = st->state;
+
+               if (cpu >= failedcpu)
+                       break;
+
+               /* Did we invoke the startup call on that cpu ? */
+               if (cpustate >= state)
+                       cpuhp_issue_call(cpu, state, teardown, false);
+       }
+}
+
+/*
+ * Returns a free for dynamic slot assignment of the Online state. The states
+ * are protected by the cpuhp_slot_states mutex and an empty slot is identified
+ * by having no name assigned.
+ */
+static int cpuhp_reserve_state(enum cpuhp_state state)
+{
+       enum cpuhp_state i;
+
+       mutex_lock(&cpuhp_state_mutex);
+       for (i = CPUHP_AP_ONLINE_DYN; i <= CPUHP_AP_ONLINE_DYN_END; i++) {
+               if (cpuhp_ap_states[i].name)
+                       continue;
+
+               cpuhp_ap_states[i].name = "Reserved";
+               mutex_unlock(&cpuhp_state_mutex);
+               return i;
+       }
+       mutex_unlock(&cpuhp_state_mutex);
+       WARN(1, "No more dynamic states available for CPU hotplug\n");
+       return -ENOSPC;
+}
+
 /**
- * notify_cpu_starting(cpu) - call the CPU_STARTING notifiers
- * @cpu: cpu that just started
+ * __cpuhp_setup_state - Setup the callbacks for an hotplug machine state
+ * @state:     The state to setup
+ * @invoke:    If true, the startup function is invoked for cpus where
+ *             cpu state >= @state
+ * @startup:   startup callback function
+ * @teardown:  teardown callback function
  *
- * This function calls the cpu_chain notifiers with CPU_STARTING.
- * It must be called by the arch code on the new cpu, before the new cpu
- * enables interrupts and before the "boot" cpu returns from __cpu_up().
+ * Returns 0 if successful, otherwise a proper error code
  */
-void notify_cpu_starting(unsigned int cpu)
+int __cpuhp_setup_state(enum cpuhp_state state,
+                       const char *name, bool invoke,
+                       int (*startup)(unsigned int cpu),
+                       int (*teardown)(unsigned int cpu))
 {
-       unsigned long val = CPU_STARTING;
+       int cpu, ret = 0;
+       int dyn_state = 0;
 
-#ifdef CONFIG_PM_SLEEP_SMP
-       if (frozen_cpus != NULL && cpumask_test_cpu(cpu, frozen_cpus))
-               val = CPU_STARTING_FROZEN;
-#endif /* CONFIG_PM_SLEEP_SMP */
-       cpu_notify(val, (void *)(long)cpu);
+       if (cpuhp_cb_check(state) || !name)
+               return -EINVAL;
+
+       get_online_cpus();
+
+       /* currently assignments for the ONLINE state are possible */
+       if (state == CPUHP_AP_ONLINE_DYN) {
+               dyn_state = 1;
+               ret = cpuhp_reserve_state(state);
+               if (ret < 0)
+                       goto out;
+               state = ret;
+       }
+
+       cpuhp_store_callbacks(state, name, startup, teardown);
+
+       if (!invoke || !startup)
+               goto out;
+
+       /*
+        * Try to call the startup callback for each present cpu
+        * depending on the hotplug state of the cpu.
+        */
+       for_each_present_cpu(cpu) {
+               struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+               int cpustate = st->state;
+
+               if (cpustate < state)
+                       continue;
+
+               ret = cpuhp_issue_call(cpu, state, startup, true);
+               if (ret) {
+                       cpuhp_rollback_install(cpu, state, teardown);
+                       cpuhp_store_callbacks(state, NULL, NULL, NULL);
+                       goto out;
+               }
+       }
+out:
+       put_online_cpus();
+       if (!ret && dyn_state)
+               return state;
+       return ret;
 }
+EXPORT_SYMBOL(__cpuhp_setup_state);
 
-#endif /* CONFIG_SMP */
+/**
+ * __cpuhp_remove_state - Remove the callbacks for an hotplug machine state
+ * @state:     The state to remove
+ * @invoke:    If true, the teardown function is invoked for cpus where
+ *             cpu state >= @state
+ *
+ * The teardown callback is currently not allowed to fail. Think
+ * about module removal!
+ */
+void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
+{
+       int (*teardown)(unsigned int cpu) = cpuhp_get_teardown_cb(state);
+       int cpu;
+
+       BUG_ON(cpuhp_cb_check(state));
+
+       get_online_cpus();
+
+       if (!invoke || !teardown)
+               goto remove;
+
+       /*
+        * Call the teardown callback for each present cpu depending
+        * on the hotplug state of the cpu. This function is not
+        * allowed to fail currently!
+        */
+       for_each_present_cpu(cpu) {
+               struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+               int cpustate = st->state;
+
+               if (cpustate >= state)
+                       cpuhp_issue_call(cpu, state, teardown, false);
+       }
+remove:
+       cpuhp_store_callbacks(state, NULL, NULL, NULL);
+       put_online_cpus();
+}
+EXPORT_SYMBOL(__cpuhp_remove_state);
+
+#if defined(CONFIG_SYSFS) && defined(CONFIG_HOTPLUG_CPU)
+static ssize_t show_cpuhp_state(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, dev->id);
+
+       return sprintf(buf, "%d\n", st->state);
+}
+static DEVICE_ATTR(state, 0444, show_cpuhp_state, NULL);
+
+static ssize_t write_cpuhp_target(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, dev->id);
+       struct cpuhp_step *sp;
+       int target, ret;
+
+       ret = kstrtoint(buf, 10, &target);
+       if (ret)
+               return ret;
+
+#ifdef CONFIG_CPU_HOTPLUG_STATE_CONTROL
+       if (target < CPUHP_OFFLINE || target > CPUHP_ONLINE)
+               return -EINVAL;
+#else
+       if (target != CPUHP_OFFLINE && target != CPUHP_ONLINE)
+               return -EINVAL;
+#endif
+
+       ret = lock_device_hotplug_sysfs();
+       if (ret)
+               return ret;
+
+       mutex_lock(&cpuhp_state_mutex);
+       sp = cpuhp_get_step(target);
+       ret = !sp->name || sp->cant_stop ? -EINVAL : 0;
+       mutex_unlock(&cpuhp_state_mutex);
+       if (ret)
+               return ret;
+
+       if (st->state < target)
+               ret = do_cpu_up(dev->id, target);
+       else
+               ret = do_cpu_down(dev->id, target);
+
+       unlock_device_hotplug();
+       return ret ? ret : count;
+}
+
+static ssize_t show_cpuhp_target(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, dev->id);
+
+       return sprintf(buf, "%d\n", st->target);
+}
+static DEVICE_ATTR(target, 0644, show_cpuhp_target, write_cpuhp_target);
+
+static struct attribute *cpuhp_cpu_attrs[] = {
+       &dev_attr_state.attr,
+       &dev_attr_target.attr,
+       NULL
+};
+
+static struct attribute_group cpuhp_cpu_attr_group = {
+       .attrs = cpuhp_cpu_attrs,
+       .name = "hotplug",
+       NULL
+};
+
+static ssize_t show_cpuhp_states(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       ssize_t cur, res = 0;
+       int i;
+
+       mutex_lock(&cpuhp_state_mutex);
+       for (i = CPUHP_OFFLINE; i <= CPUHP_ONLINE; i++) {
+               struct cpuhp_step *sp = cpuhp_get_step(i);
+
+               if (sp->name) {
+                       cur = sprintf(buf, "%3d: %s\n", i, sp->name);
+                       buf += cur;
+                       res += cur;
+               }
+       }
+       mutex_unlock(&cpuhp_state_mutex);
+       return res;
+}
+static DEVICE_ATTR(states, 0444, show_cpuhp_states, NULL);
+
+static struct attribute *cpuhp_cpu_root_attrs[] = {
+       &dev_attr_states.attr,
+       NULL
+};
+
+static struct attribute_group cpuhp_cpu_root_attr_group = {
+       .attrs = cpuhp_cpu_root_attrs,
+       .name = "hotplug",
+       NULL
+};
+
+static int __init cpuhp_sysfs_init(void)
+{
+       int cpu, ret;
+
+       ret = sysfs_create_group(&cpu_subsys.dev_root->kobj,
+                                &cpuhp_cpu_root_attr_group);
+       if (ret)
+               return ret;
+
+       for_each_possible_cpu(cpu) {
+               struct device *dev = get_cpu_device(cpu);
+
+               if (!dev)
+                       continue;
+               ret = sysfs_create_group(&dev->kobj, &cpuhp_cpu_attr_group);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+device_initcall(cpuhp_sysfs_init);
+#endif
 
 /*
  * cpu_bit_bitmap[] is a special, "compressed" data structure that
@@ -789,3 +1673,25 @@ void init_cpu_online(const struct cpumask *src)
 {
        cpumask_copy(&__cpu_online_mask, src);
 }
+
+/*
+ * Activate the first processor.
+ */
+void __init boot_cpu_init(void)
+{
+       int cpu = smp_processor_id();
+
+       /* Mark the boot cpu "present", "online" etc for SMP and UP case */
+       set_cpu_online(cpu, true);
+       set_cpu_active(cpu, true);
+       set_cpu_present(cpu, true);
+       set_cpu_possible(cpu, true);
+}
+
+/*
+ * Must be called _AFTER_ setting up the per_cpu areas
+ */
+void __init boot_cpu_state_init(void)
+{
+       per_cpu_ptr(&cpuhp_state, smp_processor_id())->state = CPUHP_ONLINE;
+}
index e1dbf4a2c69e4ca9721c22184cb9f800325b9194..90ff129c88a27c50e33be234be695650e7210494 100644 (file)
@@ -153,13 +153,11 @@ static int _kdb_bp_install(struct pt_regs *regs, kdb_bp_t *bp)
        } else {
                kdb_printf("%s: failed to set breakpoint at 0x%lx\n",
                           __func__, bp->bp_addr);
-#ifdef CONFIG_DEBUG_RODATA
                if (!bp->bp_type) {
                        kdb_printf("Software breakpoints are unavailable.\n"
-                                  "  Change the kernel CONFIG_DEBUG_RODATA=n\n"
+                                  "  Boot the kernel with rodata=off\n"
                                   "  OR use hw breaks: help bph\n");
                }
-#endif
                return 1;
        }
        return 0;
index 0d58522103cd7e73d76a7935119077f33d68082b..712570dddacde345c481f86b8631df75b798a33b 100644 (file)
@@ -64,8 +64,17 @@ static void remote_function(void *data)
        struct task_struct *p = tfc->p;
 
        if (p) {
-               tfc->ret = -EAGAIN;
-               if (task_cpu(p) != smp_processor_id() || !task_curr(p))
+               /* -EAGAIN */
+               if (task_cpu(p) != smp_processor_id())
+                       return;
+
+               /*
+                * Now that we're on right CPU with IRQs disabled, we can test
+                * if we hit the right task without races.
+                */
+
+               tfc->ret = -ESRCH; /* No such (running) process */
+               if (p != current)
                        return;
        }
 
@@ -92,13 +101,17 @@ task_function_call(struct task_struct *p, remote_function_f func, void *info)
                .p      = p,
                .func   = func,
                .info   = info,
-               .ret    = -ESRCH, /* No such (running) process */
+               .ret    = -EAGAIN,
        };
+       int ret;
 
-       if (task_curr(p))
-               smp_call_function_single(task_cpu(p), remote_function, &data, 1);
+       do {
+               ret = smp_call_function_single(task_cpu(p), remote_function, &data, 1);
+               if (!ret)
+                       ret = data.ret;
+       } while (ret == -EAGAIN);
 
-       return data.ret;
+       return ret;
 }
 
 /**
@@ -169,19 +182,6 @@ static bool is_kernel_event(struct perf_event *event)
  *    rely on ctx->is_active and therefore cannot use event_function_call().
  *    See perf_install_in_context().
  *
- * This is because we need a ctx->lock serialized variable (ctx->is_active)
- * to reliably determine if a particular task/context is scheduled in. The
- * task_curr() use in task_function_call() is racy in that a remote context
- * switch is not a single atomic operation.
- *
- * As is, the situation is 'safe' because we set rq->curr before we do the
- * actual context switch. This means that task_curr() will fail early, but
- * we'll continue spinning on ctx->is_active until we've passed
- * perf_event_task_sched_out().
- *
- * Without this ctx->lock serialized variable we could have race where we find
- * the task (and hence the context) would not be active while in fact they are.
- *
  * If ctx->nr_events, then ctx->is_active and cpuctx->task_ctx are set.
  */
 
@@ -212,7 +212,7 @@ static int event_function(void *info)
         */
        if (ctx->task) {
                if (ctx->task != current) {
-                       ret = -EAGAIN;
+                       ret = -ESRCH;
                        goto unlock;
                }
 
@@ -276,10 +276,10 @@ static void event_function_call(struct perf_event *event, event_f func, void *da
                return;
        }
 
-again:
        if (task == TASK_TOMBSTONE)
                return;
 
+again:
        if (!task_function_call(task, event_function, &efs))
                return;
 
@@ -289,13 +289,15 @@ again:
         * a concurrent perf_event_context_sched_out().
         */
        task = ctx->task;
-       if (task != TASK_TOMBSTONE) {
-               if (ctx->is_active) {
-                       raw_spin_unlock_irq(&ctx->lock);
-                       goto again;
-               }
-               func(event, NULL, ctx, data);
+       if (task == TASK_TOMBSTONE) {
+               raw_spin_unlock_irq(&ctx->lock);
+               return;
        }
+       if (ctx->is_active) {
+               raw_spin_unlock_irq(&ctx->lock);
+               goto again;
+       }
+       func(event, NULL, ctx, data);
        raw_spin_unlock_irq(&ctx->lock);
 }
 
@@ -314,6 +316,7 @@ again:
 enum event_type_t {
        EVENT_FLEXIBLE = 0x1,
        EVENT_PINNED = 0x2,
+       EVENT_TIME = 0x4,
        EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
 };
 
@@ -321,7 +324,13 @@ enum event_type_t {
  * perf_sched_events : >0 events exist
  * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu
  */
-struct static_key_deferred perf_sched_events __read_mostly;
+
+static void perf_sched_delayed(struct work_struct *work);
+DEFINE_STATIC_KEY_FALSE(perf_sched_events);
+static DECLARE_DELAYED_WORK(perf_sched_work, perf_sched_delayed);
+static DEFINE_MUTEX(perf_sched_mutex);
+static atomic_t perf_sched_count;
+
 static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
 static DEFINE_PER_CPU(int, perf_sched_cb_usages);
 
@@ -1288,16 +1297,18 @@ static u64 perf_event_time(struct perf_event *event)
 
 /*
  * Update the total_time_enabled and total_time_running fields for a event.
- * The caller of this function needs to hold the ctx->lock.
  */
 static void update_event_times(struct perf_event *event)
 {
        struct perf_event_context *ctx = event->ctx;
        u64 run_end;
 
+       lockdep_assert_held(&ctx->lock);
+
        if (event->state < PERF_EVENT_STATE_INACTIVE ||
            event->group_leader->state < PERF_EVENT_STATE_INACTIVE)
                return;
+
        /*
         * in cgroup mode, time_enabled represents
         * the time the event was enabled AND active
@@ -1645,7 +1656,7 @@ out:
 
 static bool is_orphaned_event(struct perf_event *event)
 {
-       return event->state == PERF_EVENT_STATE_EXIT;
+       return event->state == PERF_EVENT_STATE_DEAD;
 }
 
 static inline int pmu_filter_match(struct perf_event *event)
@@ -1690,14 +1701,14 @@ event_sched_out(struct perf_event *event,
 
        perf_pmu_disable(event->pmu);
 
+       event->tstamp_stopped = tstamp;
+       event->pmu->del(event, 0);
+       event->oncpu = -1;
        event->state = PERF_EVENT_STATE_INACTIVE;
        if (event->pending_disable) {
                event->pending_disable = 0;
                event->state = PERF_EVENT_STATE_OFF;
        }
-       event->tstamp_stopped = tstamp;
-       event->pmu->del(event, 0);
-       event->oncpu = -1;
 
        if (!is_software_event(event))
                cpuctx->active_oncpu--;
@@ -1732,7 +1743,6 @@ group_sched_out(struct perf_event *group_event,
 }
 
 #define DETACH_GROUP   0x01UL
-#define DETACH_STATE   0x02UL
 
 /*
  * Cross CPU call to remove a performance event
@@ -1752,8 +1762,6 @@ __perf_remove_from_context(struct perf_event *event,
        if (flags & DETACH_GROUP)
                perf_group_detach(event);
        list_del_event(event, ctx);
-       if (flags & DETACH_STATE)
-               event->state = PERF_EVENT_STATE_EXIT;
 
        if (!ctx->nr_events && ctx->is_active) {
                ctx->is_active = 0;
@@ -2063,14 +2071,27 @@ static void add_event_to_ctx(struct perf_event *event,
        event->tstamp_stopped = tstamp;
 }
 
-static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
-                              struct perf_event_context *ctx);
+static void ctx_sched_out(struct perf_event_context *ctx,
+                         struct perf_cpu_context *cpuctx,
+                         enum event_type_t event_type);
 static void
 ctx_sched_in(struct perf_event_context *ctx,
             struct perf_cpu_context *cpuctx,
             enum event_type_t event_type,
             struct task_struct *task);
 
+static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
+                              struct perf_event_context *ctx)
+{
+       if (!cpuctx->task_ctx)
+               return;
+
+       if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
+               return;
+
+       ctx_sched_out(ctx, cpuctx, EVENT_ALL);
+}
+
 static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
                                struct perf_event_context *ctx,
                                struct task_struct *task)
@@ -2097,49 +2118,68 @@ static void ctx_resched(struct perf_cpu_context *cpuctx,
 /*
  * Cross CPU call to install and enable a performance event
  *
- * Must be called with ctx->mutex held
+ * Very similar to remote_function() + event_function() but cannot assume that
+ * things like ctx->is_active and cpuctx->task_ctx are set.
  */
 static int  __perf_install_in_context(void *info)
 {
-       struct perf_event_context *ctx = info;
+       struct perf_event *event = info;
+       struct perf_event_context *ctx = event->ctx;
        struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
        struct perf_event_context *task_ctx = cpuctx->task_ctx;
+       bool activate = true;
+       int ret = 0;
 
        raw_spin_lock(&cpuctx->ctx.lock);
        if (ctx->task) {
                raw_spin_lock(&ctx->lock);
-               /*
-                * If we hit the 'wrong' task, we've since scheduled and
-                * everything should be sorted, nothing to do!
-                */
                task_ctx = ctx;
-               if (ctx->task != current)
+
+               /* If we're on the wrong CPU, try again */
+               if (task_cpu(ctx->task) != smp_processor_id()) {
+                       ret = -ESRCH;
                        goto unlock;
+               }
 
                /*
-                * If task_ctx is set, it had better be to us.
+                * If we're on the right CPU, see if the task we target is
+                * current, if not we don't have to activate the ctx, a future
+                * context switch will do that for us.
                 */
-               WARN_ON_ONCE(cpuctx->task_ctx != ctx && cpuctx->task_ctx);
+               if (ctx->task != current)
+                       activate = false;
+               else
+                       WARN_ON_ONCE(cpuctx->task_ctx && cpuctx->task_ctx != ctx);
+
        } else if (task_ctx) {
                raw_spin_lock(&task_ctx->lock);
        }
 
-       ctx_resched(cpuctx, task_ctx);
+       if (activate) {
+               ctx_sched_out(ctx, cpuctx, EVENT_TIME);
+               add_event_to_ctx(event, ctx);
+               ctx_resched(cpuctx, task_ctx);
+       } else {
+               add_event_to_ctx(event, ctx);
+       }
+
 unlock:
        perf_ctx_unlock(cpuctx, task_ctx);
 
-       return 0;
+       return ret;
 }
 
 /*
- * Attach a performance event to a context
+ * Attach a performance event to a context.
+ *
+ * Very similar to event_function_call, see comment there.
  */
 static void
 perf_install_in_context(struct perf_event_context *ctx,
                        struct perf_event *event,
                        int cpu)
 {
-       struct task_struct *task = NULL;
+       struct task_struct *task = READ_ONCE(ctx->task);
 
        lockdep_assert_held(&ctx->mutex);
 
@@ -2147,40 +2187,46 @@ perf_install_in_context(struct perf_event_context *ctx,
        if (event->cpu != -1)
                event->cpu = cpu;
 
+       if (!task) {
+               cpu_function_call(cpu, __perf_install_in_context, event);
+               return;
+       }
+
+       /*
+        * Should not happen, we validate the ctx is still alive before calling.
+        */
+       if (WARN_ON_ONCE(task == TASK_TOMBSTONE))
+               return;
+
        /*
         * Installing events is tricky because we cannot rely on ctx->is_active
         * to be set in case this is the nr_events 0 -> 1 transition.
-        *
-        * So what we do is we add the event to the list here, which will allow
-        * a future context switch to DTRT and then send a racy IPI. If the IPI
-        * fails to hit the right task, this means a context switch must have
-        * happened and that will have taken care of business.
         */
-       raw_spin_lock_irq(&ctx->lock);
-       task = ctx->task;
+again:
        /*
-        * Worse, we cannot even rely on the ctx actually existing anymore. If
-        * between find_get_context() and perf_install_in_context() the task
-        * went through perf_event_exit_task() its dead and we should not be
-        * adding new events.
+        * Cannot use task_function_call() because we need to run on the task's
+        * CPU regardless of whether its current or not.
         */
-       if (task == TASK_TOMBSTONE) {
+       if (!cpu_function_call(task_cpu(task), __perf_install_in_context, event))
+               return;
+
+       raw_spin_lock_irq(&ctx->lock);
+       task = ctx->task;
+       if (WARN_ON_ONCE(task == TASK_TOMBSTONE)) {
+               /*
+                * Cannot happen because we already checked above (which also
+                * cannot happen), and we hold ctx->mutex, which serializes us
+                * against perf_event_exit_task_context().
+                */
                raw_spin_unlock_irq(&ctx->lock);
                return;
        }
-       update_context_time(ctx);
+       raw_spin_unlock_irq(&ctx->lock);
        /*
-        * Update cgrp time only if current cgrp matches event->cgrp.
-        * Must be done before calling add_event_to_ctx().
+        * Since !ctx->is_active doesn't mean anything, we must IPI
+        * unconditionally.
         */
-       update_cgrp_time_from_event(event);
-       add_event_to_ctx(event, ctx);
-       raw_spin_unlock_irq(&ctx->lock);
-
-       if (task)
-               task_function_call(task, __perf_install_in_context, ctx);
-       else
-               cpu_function_call(cpu, __perf_install_in_context, ctx);
+       goto again;
 }
 
 /*
@@ -2219,17 +2265,18 @@ static void __perf_event_enable(struct perf_event *event,
            event->state <= PERF_EVENT_STATE_ERROR)
                return;
 
-       update_context_time(ctx);
+       if (ctx->is_active)
+               ctx_sched_out(ctx, cpuctx, EVENT_TIME);
+
        __perf_event_mark_enabled(event);
 
        if (!ctx->is_active)
                return;
 
        if (!event_filter_match(event)) {
-               if (is_cgroup_event(event)) {
-                       perf_cgroup_set_timestamp(current, ctx); // XXX ?
+               if (is_cgroup_event(event))
                        perf_cgroup_defer_enabled(event);
-               }
+               ctx_sched_in(ctx, cpuctx, EVENT_TIME, current);
                return;
        }
 
@@ -2237,8 +2284,10 @@ static void __perf_event_enable(struct perf_event *event,
         * If the event is in a group and isn't the group leader,
         * then don't put it on unless the group is on.
         */
-       if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE)
+       if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE) {
+               ctx_sched_in(ctx, cpuctx, EVENT_TIME, current);
                return;
+       }
 
        task_ctx = cpuctx->task_ctx;
        if (ctx->task)
@@ -2344,24 +2393,33 @@ static void ctx_sched_out(struct perf_event_context *ctx,
        }
 
        ctx->is_active &= ~event_type;
+       if (!(ctx->is_active & EVENT_ALL))
+               ctx->is_active = 0;
+
        if (ctx->task) {
                WARN_ON_ONCE(cpuctx->task_ctx != ctx);
                if (!ctx->is_active)
                        cpuctx->task_ctx = NULL;
        }
 
-       update_context_time(ctx);
-       update_cgrp_time_from_cpuctx(cpuctx);
-       if (!ctx->nr_active)
+       is_active ^= ctx->is_active; /* changed bits */
+
+       if (is_active & EVENT_TIME) {
+               /* update (and stop) ctx time */
+               update_context_time(ctx);
+               update_cgrp_time_from_cpuctx(cpuctx);
+       }
+
+       if (!ctx->nr_active || !(is_active & EVENT_ALL))
                return;
 
        perf_pmu_disable(ctx->pmu);
-       if ((is_active & EVENT_PINNED) && (event_type & EVENT_PINNED)) {
+       if (is_active & EVENT_PINNED) {
                list_for_each_entry(event, &ctx->pinned_groups, group_entry)
                        group_sched_out(event, cpuctx, ctx);
        }
 
-       if ((is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE)) {
+       if (is_active & EVENT_FLEXIBLE) {
                list_for_each_entry(event, &ctx->flexible_groups, group_entry)
                        group_sched_out(event, cpuctx, ctx);
        }
@@ -2641,18 +2699,6 @@ void __perf_event_task_sched_out(struct task_struct *task,
                perf_cgroup_sched_out(task, next);
 }
 
-static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
-                              struct perf_event_context *ctx)
-{
-       if (!cpuctx->task_ctx)
-               return;
-
-       if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
-               return;
-
-       ctx_sched_out(ctx, cpuctx, EVENT_ALL);
-}
-
 /*
  * Called with IRQs disabled
  */
@@ -2735,7 +2781,7 @@ ctx_sched_in(struct perf_event_context *ctx,
        if (likely(!ctx->nr_events))
                return;
 
-       ctx->is_active |= event_type;
+       ctx->is_active |= (event_type | EVENT_TIME);
        if (ctx->task) {
                if (!is_active)
                        cpuctx->task_ctx = ctx;
@@ -2743,18 +2789,24 @@ ctx_sched_in(struct perf_event_context *ctx,
                        WARN_ON_ONCE(cpuctx->task_ctx != ctx);
        }
 
-       now = perf_clock();
-       ctx->timestamp = now;
-       perf_cgroup_set_timestamp(task, ctx);
+       is_active ^= ctx->is_active; /* changed bits */
+
+       if (is_active & EVENT_TIME) {
+               /* start ctx time */
+               now = perf_clock();
+               ctx->timestamp = now;
+               perf_cgroup_set_timestamp(task, ctx);
+       }
+
        /*
         * First go through the list and put on any pinned groups
         * in order to give them the best chance of going on.
         */
-       if (!(is_active & EVENT_PINNED) && (event_type & EVENT_PINNED))
+       if (is_active & EVENT_PINNED)
                ctx_pinned_sched_in(ctx, cpuctx);
 
        /* Then walk through the lower prio flexible groups */
-       if (!(is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE))
+       if (is_active & EVENT_FLEXIBLE)
                ctx_flexible_sched_in(ctx, cpuctx);
 }
 
@@ -3060,17 +3112,6 @@ done:
        return rotate;
 }
 
-#ifdef CONFIG_NO_HZ_FULL
-bool perf_event_can_stop_tick(void)
-{
-       if (atomic_read(&nr_freq_events) ||
-           __this_cpu_read(perf_throttled_count))
-               return false;
-       else
-               return true;
-}
-#endif
-
 void perf_event_task_tick(void)
 {
        struct list_head *head = this_cpu_ptr(&active_ctx_list);
@@ -3081,6 +3122,7 @@ void perf_event_task_tick(void)
 
        __this_cpu_inc(perf_throttled_seq);
        throttled = __this_cpu_xchg(perf_throttled_count, 0);
+       tick_dep_clear_cpu(smp_processor_id(), TICK_DEP_BIT_PERF_EVENTS);
 
        list_for_each_entry_safe(ctx, tmp, head, active_ctx_list)
                perf_adjust_freq_unthr_context(ctx, throttled);
@@ -3120,6 +3162,7 @@ static void perf_event_enable_on_exec(int ctxn)
 
        cpuctx = __get_cpu_context(ctx);
        perf_ctx_lock(cpuctx, ctx);
+       ctx_sched_out(ctx, cpuctx, EVENT_TIME);
        list_for_each_entry(event, &ctx->event_list, event_entry)
                enabled |= event_enable_on_exec(event, ctx);
 
@@ -3511,6 +3554,28 @@ static void unaccount_event_cpu(struct perf_event *event, int cpu)
                atomic_dec(&per_cpu(perf_cgroup_events, cpu));
 }
 
+#ifdef CONFIG_NO_HZ_FULL
+static DEFINE_SPINLOCK(nr_freq_lock);
+#endif
+
+static void unaccount_freq_event_nohz(void)
+{
+#ifdef CONFIG_NO_HZ_FULL
+       spin_lock(&nr_freq_lock);
+       if (atomic_dec_and_test(&nr_freq_events))
+               tick_nohz_dep_clear(TICK_DEP_BIT_PERF_EVENTS);
+       spin_unlock(&nr_freq_lock);
+#endif
+}
+
+static void unaccount_freq_event(void)
+{
+       if (tick_nohz_full_enabled())
+               unaccount_freq_event_nohz();
+       else
+               atomic_dec(&nr_freq_events);
+}
+
 static void unaccount_event(struct perf_event *event)
 {
        bool dec = false;
@@ -3527,7 +3592,7 @@ static void unaccount_event(struct perf_event *event)
        if (event->attr.task)
                atomic_dec(&nr_task_events);
        if (event->attr.freq)
-               atomic_dec(&nr_freq_events);
+               unaccount_freq_event();
        if (event->attr.context_switch) {
                dec = true;
                atomic_dec(&nr_switch_events);
@@ -3537,12 +3602,22 @@ static void unaccount_event(struct perf_event *event)
        if (has_branch_stack(event))
                dec = true;
 
-       if (dec)
-               static_key_slow_dec_deferred(&perf_sched_events);
+       if (dec) {
+               if (!atomic_add_unless(&perf_sched_count, -1, 1))
+                       schedule_delayed_work(&perf_sched_work, HZ);
+       }
 
        unaccount_event_cpu(event, event->cpu);
 }
 
+static void perf_sched_delayed(struct work_struct *work)
+{
+       mutex_lock(&perf_sched_mutex);
+       if (atomic_dec_and_test(&perf_sched_count))
+               static_branch_disable(&perf_sched_events);
+       mutex_unlock(&perf_sched_mutex);
+}
+
 /*
  * The following implement mutual exclusion of events on "exclusive" pmus
  * (PERF_PMU_CAP_EXCLUSIVE). Such pmus can only have one event scheduled
@@ -3752,30 +3827,42 @@ static void put_event(struct perf_event *event)
  */
 int perf_event_release_kernel(struct perf_event *event)
 {
-       struct perf_event_context *ctx;
+       struct perf_event_context *ctx = event->ctx;
        struct perf_event *child, *tmp;
 
+       /*
+        * If we got here through err_file: fput(event_file); we will not have
+        * attached to a context yet.
+        */
+       if (!ctx) {
+               WARN_ON_ONCE(event->attach_state &
+                               (PERF_ATTACH_CONTEXT|PERF_ATTACH_GROUP));
+               goto no_ctx;
+       }
+
        if (!is_kernel_event(event))
                perf_remove_from_owner(event);
 
        ctx = perf_event_ctx_lock(event);
        WARN_ON_ONCE(ctx->parent_ctx);
-       perf_remove_from_context(event, DETACH_GROUP | DETACH_STATE);
-       perf_event_ctx_unlock(event, ctx);
+       perf_remove_from_context(event, DETACH_GROUP);
 
+       raw_spin_lock_irq(&ctx->lock);
        /*
-        * At this point we must have event->state == PERF_EVENT_STATE_EXIT,
-        * either from the above perf_remove_from_context() or through
-        * perf_event_exit_event().
+        * Mark this even as STATE_DEAD, there is no external reference to it
+        * anymore.
         *
-        * Therefore, anybody acquiring event->child_mutex after the below
-        * loop _must_ also see this, most importantly inherit_event() which
-        * will avoid placing more children on the list.
+        * Anybody acquiring event->child_mutex after the below loop _must_
+        * also see this, most importantly inherit_event() which will avoid
+        * placing more children on the list.
         *
         * Thus this guarantees that we will in fact observe and kill _ALL_
         * child events.
         */
-       WARN_ON_ONCE(event->state != PERF_EVENT_STATE_EXIT);
+       event->state = PERF_EVENT_STATE_DEAD;
+       raw_spin_unlock_irq(&ctx->lock);
+
+       perf_event_ctx_unlock(event, ctx);
 
 again:
        mutex_lock(&event->child_mutex);
@@ -3830,8 +3917,8 @@ again:
        }
        mutex_unlock(&event->child_mutex);
 
-       /* Must be the last reference */
-       put_event(event);
+no_ctx:
+       put_event(event); /* Must be the 'last' reference */
        return 0;
 }
 EXPORT_SYMBOL_GPL(perf_event_release_kernel);
@@ -3988,7 +4075,7 @@ static bool is_event_hup(struct perf_event *event)
 {
        bool no_children;
 
-       if (event->state != PERF_EVENT_STATE_EXIT)
+       if (event->state > PERF_EVENT_STATE_EXIT)
                return false;
 
        mutex_lock(&event->child_mutex);
@@ -6349,9 +6436,9 @@ static int __perf_event_overflow(struct perf_event *event,
                if (unlikely(throttle
                             && hwc->interrupts >= max_samples_per_tick)) {
                        __this_cpu_inc(perf_throttled_count);
+                       tick_dep_set_cpu(smp_processor_id(), TICK_DEP_BIT_PERF_EVENTS);
                        hwc->interrupts = MAX_INTERRUPTS;
                        perf_log_throttle(event, 0);
-                       tick_nohz_full_kick();
                        ret = 1;
                }
        }
@@ -6710,7 +6797,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)
        kfree_rcu(hlist, rcu_head);
 }
 
-static void swevent_hlist_put_cpu(struct perf_event *event, int cpu)
+static void swevent_hlist_put_cpu(int cpu)
 {
        struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
@@ -6722,15 +6809,15 @@ static void swevent_hlist_put_cpu(struct perf_event *event, int cpu)
        mutex_unlock(&swhash->hlist_mutex);
 }
 
-static void swevent_hlist_put(struct perf_event *event)
+static void swevent_hlist_put(void)
 {
        int cpu;
 
        for_each_possible_cpu(cpu)
-               swevent_hlist_put_cpu(event, cpu);
+               swevent_hlist_put_cpu(cpu);
 }
 
-static int swevent_hlist_get_cpu(struct perf_event *event, int cpu)
+static int swevent_hlist_get_cpu(int cpu)
 {
        struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
        int err = 0;
@@ -6753,14 +6840,13 @@ exit:
        return err;
 }
 
-static int swevent_hlist_get(struct perf_event *event)
+static int swevent_hlist_get(void)
 {
-       int err;
-       int cpu, failed_cpu;
+       int err, cpu, failed_cpu;
 
        get_online_cpus();
        for_each_possible_cpu(cpu) {
-               err = swevent_hlist_get_cpu(event, cpu);
+               err = swevent_hlist_get_cpu(cpu);
                if (err) {
                        failed_cpu = cpu;
                        goto fail;
@@ -6773,7 +6859,7 @@ fail:
        for_each_possible_cpu(cpu) {
                if (cpu == failed_cpu)
                        break;
-               swevent_hlist_put_cpu(event, cpu);
+               swevent_hlist_put_cpu(cpu);
        }
 
        put_online_cpus();
@@ -6789,7 +6875,7 @@ static void sw_perf_event_destroy(struct perf_event *event)
        WARN_ON(event->parent);
 
        static_key_slow_dec(&perf_swevent_enabled[event_id]);
-       swevent_hlist_put(event);
+       swevent_hlist_put();
 }
 
 static int perf_swevent_init(struct perf_event *event)
@@ -6820,7 +6906,7 @@ static int perf_swevent_init(struct perf_event *event)
        if (!event->parent) {
                int err;
 
-               err = swevent_hlist_get(event);
+               err = swevent_hlist_get();
                if (err)
                        return err;
 
@@ -7741,6 +7827,27 @@ static void account_event_cpu(struct perf_event *event, int cpu)
                atomic_inc(&per_cpu(perf_cgroup_events, cpu));
 }
 
+/* Freq events need the tick to stay alive (see perf_event_task_tick). */
+static void account_freq_event_nohz(void)
+{
+#ifdef CONFIG_NO_HZ_FULL
+       /* Lock so we don't race with concurrent unaccount */
+       spin_lock(&nr_freq_lock);
+       if (atomic_inc_return(&nr_freq_events) == 1)
+               tick_nohz_dep_set(TICK_DEP_BIT_PERF_EVENTS);
+       spin_unlock(&nr_freq_lock);
+#endif
+}
+
+static void account_freq_event(void)
+{
+       if (tick_nohz_full_enabled())
+               account_freq_event_nohz();
+       else
+               atomic_inc(&nr_freq_events);
+}
+
+
 static void account_event(struct perf_event *event)
 {
        bool inc = false;
@@ -7756,10 +7863,8 @@ static void account_event(struct perf_event *event)
                atomic_inc(&nr_comm_events);
        if (event->attr.task)
                atomic_inc(&nr_task_events);
-       if (event->attr.freq) {
-               if (atomic_inc_return(&nr_freq_events) == 1)
-                       tick_nohz_full_kick_all();
-       }
+       if (event->attr.freq)
+               account_freq_event();
        if (event->attr.context_switch) {
                atomic_inc(&nr_switch_events);
                inc = true;
@@ -7769,8 +7874,28 @@ static void account_event(struct perf_event *event)
        if (is_cgroup_event(event))
                inc = true;
 
-       if (inc)
-               static_key_slow_inc(&perf_sched_events.key);
+       if (inc) {
+               if (atomic_inc_not_zero(&perf_sched_count))
+                       goto enabled;
+
+               mutex_lock(&perf_sched_mutex);
+               if (!atomic_read(&perf_sched_count)) {
+                       static_branch_enable(&perf_sched_events);
+                       /*
+                        * Guarantee that all CPUs observe they key change and
+                        * call the perf scheduling hooks before proceeding to
+                        * install events that need them.
+                        */
+                       synchronize_sched();
+               }
+               /*
+                * Now that we have waited for the sync_sched(), allow further
+                * increments to by-pass the mutex.
+                */
+               atomic_inc(&perf_sched_count);
+               mutex_unlock(&perf_sched_mutex);
+       }
+enabled:
 
        account_event_cpu(event, event->cpu);
 }
@@ -7906,6 +8031,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
                }
        }
 
+       /* symmetric to unaccount_event() in _free_event() */
+       account_event(event);
+
        return event;
 
 err_per_task:
@@ -8269,8 +8397,6 @@ SYSCALL_DEFINE5(perf_event_open,
                }
        }
 
-       account_event(event);
-
        /*
         * Special case software events and allow them to be part of
         * any hardware group.
@@ -8389,10 +8515,19 @@ SYSCALL_DEFINE5(perf_event_open,
        if (move_group) {
                gctx = group_leader->ctx;
                mutex_lock_double(&gctx->mutex, &ctx->mutex);
+               if (gctx->task == TASK_TOMBSTONE) {
+                       err = -ESRCH;
+                       goto err_locked;
+               }
        } else {
                mutex_lock(&ctx->mutex);
        }
 
+       if (ctx->task == TASK_TOMBSTONE) {
+               err = -ESRCH;
+               goto err_locked;
+       }
+
        if (!perf_event_validate_size(event)) {
                err = -E2BIG;
                goto err_locked;
@@ -8509,7 +8644,12 @@ err_context:
        perf_unpin_context(ctx);
        put_ctx(ctx);
 err_alloc:
-       free_event(event);
+       /*
+        * If event_file is set, the fput() above will have called ->release()
+        * and that will take care of freeing the event.
+        */
+       if (!event_file)
+               free_event(event);
 err_cpus:
        put_online_cpus();
 err_task:
@@ -8553,8 +8693,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
        /* Mark owner so we could distinguish it from user events. */
        event->owner = TASK_TOMBSTONE;
 
-       account_event(event);
-
        ctx = find_get_context(event->pmu, task, event);
        if (IS_ERR(ctx)) {
                err = PTR_ERR(ctx);
@@ -8563,12 +8701,14 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
+       if (ctx->task == TASK_TOMBSTONE) {
+               err = -ESRCH;
+               goto err_unlock;
+       }
+
        if (!exclusive_event_installable(event, ctx)) {
-               mutex_unlock(&ctx->mutex);
-               perf_unpin_context(ctx);
-               put_ctx(ctx);
                err = -EBUSY;
-               goto err_free;
+               goto err_unlock;
        }
 
        perf_install_in_context(ctx, event, cpu);
@@ -8577,6 +8717,10 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 
        return event;
 
+err_unlock:
+       mutex_unlock(&ctx->mutex);
+       perf_unpin_context(ctx);
+       put_ctx(ctx);
 err_free:
        free_event(event);
 err:
@@ -8695,7 +8839,7 @@ perf_event_exit_event(struct perf_event *child_event,
        if (parent_event)
                perf_group_detach(child_event);
        list_del_event(child_event, child_ctx);
-       child_event->state = PERF_EVENT_STATE_EXIT; /* see perf_event_release_kernel() */
+       child_event->state = PERF_EVENT_STATE_EXIT; /* is_event_hup() */
        raw_spin_unlock_irq(&child_ctx->lock);
 
        /*
@@ -9313,9 +9457,6 @@ void __init perf_event_init(void)
        ret = init_hw_breakpoint();
        WARN(ret, "hw_breakpoint initialization failed with: %d", ret);
 
-       /* do not patch jump label more than once per second */
-       jump_label_rate_limit(&perf_sched_events, HZ);
-
        /*
         * Build time assertion that we keep the data_head at the intended
         * location.  IOW, validation we got the __reserved[] size right.
@@ -9335,6 +9476,7 @@ ssize_t perf_event_sysfs_show(struct device *dev, struct device_attribute *attr,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(perf_event_sysfs_show);
 
 static int __init perf_event_sysfs_init(void)
 {
index 0167679182c08dae79cf54e0b3830fc626866ee2..5f6ce931f1eac3aace94813d0c13cca724ae53f9 100644 (file)
@@ -1178,6 +1178,7 @@ static struct xol_area *__create_xol_area(unsigned long vaddr)
                goto free_area;
 
        area->xol_mapping.name = "[uprobes]";
+       area->xol_mapping.fault = NULL;
        area->xol_mapping.pages = area->pages;
        area->pages[0] = alloc_page(GFP_HIGHUSER);
        if (!area->pages[0])
index 5d6ce6413ef1d227b32c99a4330bee1289f9f571..a5d2e74c89e0b217df98326e5febf3caf687687c 100644 (file)
  *   futex_wait(futex, val);
  *
  *   waiters++; (a)
- *   mb(); (A) <-- paired with -.
- *                              |
- *   lock(hash_bucket(futex));  |
- *                              |
- *   uval = *futex;             |
- *                              |        *futex = newval;
- *                              |        sys_futex(WAKE, futex);
- *                              |          futex_wake(futex);
- *                              |
- *                              `------->  mb(); (B)
+ *   smp_mb(); (A) <-- paired with -.
+ *                                  |
+ *   lock(hash_bucket(futex));      |
+ *                                  |
+ *   uval = *futex;                 |
+ *                                  |        *futex = newval;
+ *                                  |        sys_futex(WAKE, futex);
+ *                                  |          futex_wake(futex);
+ *                                  |
+ *                                  `--------> smp_mb(); (B)
  *   if (uval == val)
  *     queue();
  *     unlock(hash_bucket(futex));
@@ -334,7 +334,7 @@ static inline void futex_get_mm(union futex_key *key)
        /*
         * Ensure futex_get_mm() implies a full barrier such that
         * get_futex_key() implies a full barrier. This is relied upon
-        * as full barrier (B), see the ordering comment above.
+        * as smp_mb(); (B), see the ordering comment above.
         */
        smp_mb__after_atomic();
 }
@@ -407,10 +407,10 @@ static void get_futex_key_refs(union futex_key *key)
 
        switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
        case FUT_OFF_INODE:
-               ihold(key->shared.inode); /* implies MB (B) */
+               ihold(key->shared.inode); /* implies smp_mb(); (B) */
                break;
        case FUT_OFF_MMSHARED:
-               futex_get_mm(key); /* implies MB (B) */
+               futex_get_mm(key); /* implies smp_mb(); (B) */
                break;
        default:
                /*
@@ -418,7 +418,7 @@ static void get_futex_key_refs(union futex_key *key)
                 * mm, therefore the only purpose of calling get_futex_key_refs
                 * is because we need the barrier for the lockless waiter check.
                 */
-               smp_mb(); /* explicit MB (B) */
+               smp_mb(); /* explicit smp_mb(); (B) */
        }
 }
 
@@ -497,7 +497,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
        if (!fshared) {
                key->private.mm = mm;
                key->private.address = address;
-               get_futex_key_refs(key);  /* implies MB (B) */
+               get_futex_key_refs(key);  /* implies smp_mb(); (B) */
                return 0;
        }
 
@@ -520,7 +520,20 @@ again:
        else
                err = 0;
 
-       lock_page(page);
+       /*
+        * The treatment of mapping from this point on is critical. The page
+        * lock protects many things but in this context the page lock
+        * stabilizes mapping, prevents inode freeing in the shared
+        * file-backed region case and guards against movement to swap cache.
+        *
+        * Strictly speaking the page lock is not needed in all cases being
+        * considered here and page lock forces unnecessarily serialization
+        * From this point on, mapping will be re-verified if necessary and
+        * page lock will be acquired only if it is unavoidable
+        */
+       page = compound_head(page);
+       mapping = READ_ONCE(page->mapping);
+
        /*
         * If page->mapping is NULL, then it cannot be a PageAnon
         * page; but it might be the ZERO_PAGE or in the gate area or
@@ -536,19 +549,31 @@ again:
         * shmem_writepage move it from filecache to swapcache beneath us:
         * an unlikely race, but we do need to retry for page->mapping.
         */
-       mapping = compound_head(page)->mapping;
-       if (!mapping) {
-               int shmem_swizzled = PageSwapCache(page);
+       if (unlikely(!mapping)) {
+               int shmem_swizzled;
+
+               /*
+                * Page lock is required to identify which special case above
+                * applies. If this is really a shmem page then the page lock
+                * will prevent unexpected transitions.
+                */
+               lock_page(page);
+               shmem_swizzled = PageSwapCache(page) || page->mapping;
                unlock_page(page);
                put_page(page);
+
                if (shmem_swizzled)
                        goto again;
+
                return -EFAULT;
        }
 
        /*
         * Private mappings are handled in a simple way.
         *
+        * If the futex key is stored on an anonymous page, then the associated
+        * object is the mm which is implicitly pinned by the calling process.
+        *
         * NOTE: When userspace waits on a MAP_SHARED mapping, even if
         * it's a read-only handle, it's expected that futexes attach to
         * the object not the particular process.
@@ -566,16 +591,74 @@ again:
                key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
                key->private.mm = mm;
                key->private.address = address;
+
+               get_futex_key_refs(key); /* implies smp_mb(); (B) */
+
        } else {
+               struct inode *inode;
+
+               /*
+                * The associated futex object in this case is the inode and
+                * the page->mapping must be traversed. Ordinarily this should
+                * be stabilised under page lock but it's not strictly
+                * necessary in this case as we just want to pin the inode, not
+                * update the radix tree or anything like that.
+                *
+                * The RCU read lock is taken as the inode is finally freed
+                * under RCU. If the mapping still matches expectations then the
+                * mapping->host can be safely accessed as being a valid inode.
+                */
+               rcu_read_lock();
+
+               if (READ_ONCE(page->mapping) != mapping) {
+                       rcu_read_unlock();
+                       put_page(page);
+
+                       goto again;
+               }
+
+               inode = READ_ONCE(mapping->host);
+               if (!inode) {
+                       rcu_read_unlock();
+                       put_page(page);
+
+                       goto again;
+               }
+
+               /*
+                * Take a reference unless it is about to be freed. Previously
+                * this reference was taken by ihold under the page lock
+                * pinning the inode in place so i_lock was unnecessary. The
+                * only way for this check to fail is if the inode was
+                * truncated in parallel so warn for now if this happens.
+                *
+                * We are not calling into get_futex_key_refs() in file-backed
+                * cases, therefore a successful atomic_inc return below will
+                * guarantee that get_futex_key() will still imply smp_mb(); (B).
+                */
+               if (WARN_ON_ONCE(!atomic_inc_not_zero(&inode->i_count))) {
+                       rcu_read_unlock();
+                       put_page(page);
+
+                       goto again;
+               }
+
+               /* Should be impossible but lets be paranoid for now */
+               if (WARN_ON_ONCE(inode->i_mapping != mapping)) {
+                       err = -EFAULT;
+                       rcu_read_unlock();
+                       iput(inode);
+
+                       goto out;
+               }
+
                key->both.offset |= FUT_OFF_INODE; /* inode-based key */
-               key->shared.inode = mapping->host;
+               key->shared.inode = inode;
                key->shared.pgoff = basepage_index(page);
+               rcu_read_unlock();
        }
 
-       get_futex_key_refs(key); /* implies MB (B) */
-
 out:
-       unlock_page(page);
        put_page(page);
        return err;
 }
@@ -1864,7 +1947,7 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
 
        q->lock_ptr = &hb->lock;
 
-       spin_lock(&hb->lock); /* implies MB (A) */
+       spin_lock(&hb->lock); /* implies smp_mb(); (A) */
        return hb;
 }
 
@@ -1927,8 +2010,12 @@ static int unqueue_me(struct futex_q *q)
 
        /* In the common case we don't take the spinlock, which is nice. */
 retry:
-       lock_ptr = q->lock_ptr;
-       barrier();
+       /*
+        * q->lock_ptr can change between this read and the following spin_lock.
+        * Use READ_ONCE to forbid the compiler from reloading q->lock_ptr and
+        * optimizing lock_ptr out of the logic below.
+        */
+       lock_ptr = READ_ONCE(q->lock_ptr);
        if (lock_ptr != NULL) {
                spin_lock(lock_ptr);
                /*
index 3b48dab801648dc1b7ef9962b2dd8d8067d9adf8..3bbfd6a9c475610cef70ac32a928f79e50db60e8 100644 (file)
@@ -64,6 +64,10 @@ config IRQ_DOMAIN_HIERARCHY
        bool
        select IRQ_DOMAIN
 
+# Generic IRQ IPI support
+config GENERIC_IRQ_IPI
+       bool
+
 # Generic MSI interrupt support
 config GENERIC_MSI_IRQ
        bool
index 2fc9cbdf35b6221385ab1f8393098523cc4c43cd..2ee42e95a3ce182ce44bea1b1824e63b93436f37 100644 (file)
@@ -8,3 +8,4 @@ obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_GENERIC_IRQ_MIGRATION) += cpuhotplug.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
 obj-$(CONFIG_GENERIC_MSI_IRQ) += msi.o
+obj-$(CONFIG_GENERIC_IRQ_IPI) += ipi.o
index 5797909f4e5b1b52cc0b2ecc61b9c393dc7a8bee..2f9f2b0e79f2d9be7901546e8fc991d048d5fc0a 100644 (file)
@@ -961,6 +961,7 @@ void irq_chip_mask_parent(struct irq_data *data)
        data = data->parent_data;
        data->chip->irq_mask(data);
 }
+EXPORT_SYMBOL_GPL(irq_chip_mask_parent);
 
 /**
  * irq_chip_unmask_parent - Unmask the parent interrupt
@@ -971,6 +972,7 @@ void irq_chip_unmask_parent(struct irq_data *data)
        data = data->parent_data;
        data->chip->irq_unmask(data);
 }
+EXPORT_SYMBOL_GPL(irq_chip_unmask_parent);
 
 /**
  * irq_chip_eoi_parent - Invoke EOI on the parent interrupt
@@ -981,6 +983,7 @@ void irq_chip_eoi_parent(struct irq_data *data)
        data = data->parent_data;
        data->chip->irq_eoi(data);
 }
+EXPORT_SYMBOL_GPL(irq_chip_eoi_parent);
 
 /**
  * irq_chip_set_affinity_parent - Set affinity on the parent interrupt
@@ -1016,6 +1019,7 @@ int irq_chip_set_type_parent(struct irq_data *data, unsigned int type)
 
        return -ENOSYS;
 }
+EXPORT_SYMBOL_GPL(irq_chip_set_type_parent);
 
 /**
  * irq_chip_retrigger_hierarchy - Retrigger an interrupt in hardware
index 57bff7857e879bf2301a92723ade0a968870e637..a15b5485b446e8ff5575ba87e9a4cabb80aa7286 100644 (file)
@@ -136,10 +136,9 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
 {
        irqreturn_t retval = IRQ_NONE;
        unsigned int flags = 0, irq = desc->irq_data.irq;
-       struct irqaction *action = desc->action;
+       struct irqaction *action;
 
-       /* action might have become NULL since we dropped the lock */
-       while (action) {
+       for_each_action_of_desc(desc, action) {
                irqreturn_t res;
 
                trace_irq_handler_entry(irq, action);
@@ -173,7 +172,6 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
                }
 
                retval |= res;
-               action = action->next;
        }
 
        add_interrupt_randomness(irq, flags);
index fcab63c669059308d3cc27054742587b0627b23f..09be2c903c6d3fa0d622111f988b0211965ab662 100644 (file)
@@ -131,6 +131,9 @@ static inline void chip_bus_sync_unlock(struct irq_desc *desc)
 #define IRQ_GET_DESC_CHECK_GLOBAL      (_IRQ_DESC_CHECK)
 #define IRQ_GET_DESC_CHECK_PERCPU      (_IRQ_DESC_CHECK | _IRQ_DESC_PERCPU)
 
+#define for_each_action_of_desc(desc, act)                     \
+       for (act = desc->act; act; act = act->next)
+
 struct irq_desc *
 __irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,
                    unsigned int check);
@@ -160,6 +163,8 @@ irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags)
        __irq_put_desc_unlock(desc, flags, false);
 }
 
+#define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
+
 /*
  * Manipulation functions for irq_data.state
  */
@@ -188,6 +193,8 @@ static inline bool irqd_has_set(struct irq_data *d, unsigned int mask)
        return __irqd_to_state(d) & mask;
 }
 
+#undef __irqd_to_state
+
 static inline void kstat_incr_irqs_this_cpu(struct irq_desc *desc)
 {
        __this_cpu_inc(*desc->kstat_irqs);
diff --git a/kernel/irq/ipi.c b/kernel/irq/ipi.c
new file mode 100644 (file)
index 0000000..c37f34b
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * linux/kernel/irq/ipi.c
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd
+ * Author: Qais Yousef <qais.yousef@imgtec.com>
+ *
+ * This file contains driver APIs to the IPI subsystem.
+ */
+
+#define pr_fmt(fmt) "genirq/ipi: " fmt
+
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+
+/**
+ * irq_reserve_ipi() - Setup an IPI to destination cpumask
+ * @domain:    IPI domain
+ * @dest:      cpumask of cpus which can receive the IPI
+ *
+ * Allocate a virq that can be used to send IPI to any CPU in dest mask.
+ *
+ * On success it'll return linux irq number and 0 on failure
+ */
+unsigned int irq_reserve_ipi(struct irq_domain *domain,
+                            const struct cpumask *dest)
+{
+       unsigned int nr_irqs, offset;
+       struct irq_data *data;
+       int virq, i;
+
+       if (!domain ||!irq_domain_is_ipi(domain)) {
+               pr_warn("Reservation on a non IPI domain\n");
+               return 0;
+       }
+
+       if (!cpumask_subset(dest, cpu_possible_mask)) {
+               pr_warn("Reservation is not in possible_cpu_mask\n");
+               return 0;
+       }
+
+       nr_irqs = cpumask_weight(dest);
+       if (!nr_irqs) {
+               pr_warn("Reservation for empty destination mask\n");
+               return 0;
+       }
+
+       if (irq_domain_is_ipi_single(domain)) {
+               /*
+                * If the underlying implementation uses a single HW irq on
+                * all cpus then we only need a single Linux irq number for
+                * it. We have no restrictions vs. the destination mask. The
+                * underlying implementation can deal with holes nicely.
+                */
+               nr_irqs = 1;
+               offset = 0;
+       } else {
+               unsigned int next;
+
+               /*
+                * The IPI requires a seperate HW irq on each CPU. We require
+                * that the destination mask is consecutive. If an
+                * implementation needs to support holes, it can reserve
+                * several IPI ranges.
+                */
+               offset = cpumask_first(dest);
+               /*
+                * Find a hole and if found look for another set bit after the
+                * hole. For now we don't support this scenario.
+                */
+               next = cpumask_next_zero(offset, dest);
+               if (next < nr_cpu_ids)
+                       next = cpumask_next(next, dest);
+               if (next < nr_cpu_ids) {
+                       pr_warn("Destination mask has holes\n");
+                       return 0;
+               }
+       }
+
+       virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
+       if (virq <= 0) {
+               pr_warn("Can't reserve IPI, failed to alloc descs\n");
+               return 0;
+       }
+
+       virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
+                                      (void *) dest, true);
+
+       if (virq <= 0) {
+               pr_warn("Can't reserve IPI, failed to alloc hw irqs\n");
+               goto free_descs;
+       }
+
+       for (i = 0; i < nr_irqs; i++) {
+               data = irq_get_irq_data(virq + i);
+               cpumask_copy(data->common->affinity, dest);
+               data->common->ipi_offset = offset;
+       }
+       return virq;
+
+free_descs:
+       irq_free_descs(virq, nr_irqs);
+       return 0;
+}
+
+/**
+ * irq_destroy_ipi() - unreserve an IPI that was previously allocated
+ * @irq:       linux irq number to be destroyed
+ *
+ * Return the IPIs allocated with irq_reserve_ipi() to the system destroying
+ * all virqs associated with them.
+ */
+void irq_destroy_ipi(unsigned int irq)
+{
+       struct irq_data *data = irq_get_irq_data(irq);
+       struct cpumask *ipimask = data ? irq_data_get_affinity_mask(data) : NULL;
+       struct irq_domain *domain;
+       unsigned int nr_irqs;
+
+       if (!irq || !data || !ipimask)
+               return;
+
+       domain = data->domain;
+       if (WARN_ON(domain == NULL))
+               return;
+
+       if (!irq_domain_is_ipi(domain)) {
+               pr_warn("Trying to destroy a non IPI domain!\n");
+               return;
+       }
+
+       if (irq_domain_is_ipi_per_cpu(domain))
+               nr_irqs = cpumask_weight(ipimask);
+       else
+               nr_irqs = 1;
+
+       irq_domain_free_irqs(irq, nr_irqs);
+}
+
+/**
+ * ipi_get_hwirq - Get the hwirq associated with an IPI to a cpu
+ * @irq:       linux irq number
+ * @cpu:       the target cpu
+ *
+ * When dealing with coprocessors IPI, we need to inform the coprocessor of
+ * the hwirq it needs to use to receive and send IPIs.
+ *
+ * Returns hwirq value on success and INVALID_HWIRQ on failure.
+ */
+irq_hw_number_t ipi_get_hwirq(unsigned int irq, unsigned int cpu)
+{
+       struct irq_data *data = irq_get_irq_data(irq);
+       struct cpumask *ipimask = data ? irq_data_get_affinity_mask(data) : NULL;
+
+       if (!data || !ipimask || cpu > nr_cpu_ids)
+               return INVALID_HWIRQ;
+
+       if (!cpumask_test_cpu(cpu, ipimask))
+               return INVALID_HWIRQ;
+
+       /*
+        * Get the real hardware irq number if the underlying implementation
+        * uses a seperate irq per cpu. If the underlying implementation uses
+        * a single hardware irq for all cpus then the IPI send mechanism
+        * needs to take care of the cpu destinations.
+        */
+       if (irq_domain_is_ipi_per_cpu(data->domain))
+               data = irq_get_irq_data(irq + cpu - data->common->ipi_offset);
+
+       return data ? irqd_to_hwirq(data) : INVALID_HWIRQ;
+}
+EXPORT_SYMBOL_GPL(ipi_get_hwirq);
+
+static int ipi_send_verify(struct irq_chip *chip, struct irq_data *data,
+                          const struct cpumask *dest, unsigned int cpu)
+{
+       struct cpumask *ipimask = irq_data_get_affinity_mask(data);
+
+       if (!chip || !ipimask)
+               return -EINVAL;
+
+       if (!chip->ipi_send_single && !chip->ipi_send_mask)
+               return -EINVAL;
+
+       if (cpu > nr_cpu_ids)
+               return -EINVAL;
+
+       if (dest) {
+               if (!cpumask_subset(dest, ipimask))
+                       return -EINVAL;
+       } else {
+               if (!cpumask_test_cpu(cpu, ipimask))
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * __ipi_send_single - send an IPI to a target Linux SMP CPU
+ * @desc:      pointer to irq_desc of the IRQ
+ * @cpu:       destination CPU, must in the destination mask passed to
+ *             irq_reserve_ipi()
+ *
+ * This function is for architecture or core code to speed up IPI sending. Not
+ * usable from driver code.
+ *
+ * Returns zero on success and negative error number on failure.
+ */
+int __ipi_send_single(struct irq_desc *desc, unsigned int cpu)
+{
+       struct irq_data *data = irq_desc_get_irq_data(desc);
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
+
+#ifdef DEBUG
+       /*
+        * Minimise the overhead by omitting the checks for Linux SMP IPIs.
+        * Since the callers should be arch or core code which is generally
+        * trusted, only check for errors when debugging.
+        */
+       if (WARN_ON_ONCE(ipi_send_verify(chip, data, NULL, cpu)))
+               return -EINVAL;
+#endif
+       if (!chip->ipi_send_single) {
+               chip->ipi_send_mask(data, cpumask_of(cpu));
+               return 0;
+       }
+
+       /* FIXME: Store this information in irqdata flags */
+       if (irq_domain_is_ipi_per_cpu(data->domain) &&
+           cpu != data->common->ipi_offset) {
+               /* use the correct data for that cpu */
+               unsigned irq = data->irq + cpu - data->common->ipi_offset;
+
+               data = irq_get_irq_data(irq);
+       }
+       chip->ipi_send_single(data, cpu);
+       return 0;
+}
+
+/**
+ * ipi_send_mask - send an IPI to target Linux SMP CPU(s)
+ * @desc:      pointer to irq_desc of the IRQ
+ * @dest:      dest CPU(s), must be a subset of the mask passed to
+ *             irq_reserve_ipi()
+ *
+ * This function is for architecture or core code to speed up IPI sending. Not
+ * usable from driver code.
+ *
+ * Returns zero on success and negative error number on failure.
+ */
+int __ipi_send_mask(struct irq_desc *desc, const struct cpumask *dest)
+{
+       struct irq_data *data = irq_desc_get_irq_data(desc);
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
+       unsigned int cpu;
+
+#ifdef DEBUG
+       /*
+        * Minimise the overhead by omitting the checks for Linux SMP IPIs.
+        * Since the callers should be arch or core code which is generally
+        * trusted, only check for errors when debugging.
+        */
+       if (WARN_ON_ONCE(ipi_send_verify(chip, data, dest, 0)))
+               return -EINVAL;
+#endif
+       if (chip->ipi_send_mask) {
+               chip->ipi_send_mask(data, dest);
+               return 0;
+       }
+
+       if (irq_domain_is_ipi_per_cpu(data->domain)) {
+               unsigned int base = data->irq;
+
+               for_each_cpu(cpu, dest) {
+                       unsigned irq = base + cpu - data->common->ipi_offset;
+
+                       data = irq_get_irq_data(irq);
+                       chip->ipi_send_single(data, cpu);
+               }
+       } else {
+               for_each_cpu(cpu, dest)
+                       chip->ipi_send_single(data, cpu);
+       }
+       return 0;
+}
+
+/**
+ * ipi_send_single - Send an IPI to a single CPU
+ * @virq:      linux irq number from irq_reserve_ipi()
+ * @cpu:       destination CPU, must in the destination mask passed to
+ *             irq_reserve_ipi()
+ *
+ * Returns zero on success and negative error number on failure.
+ */
+int ipi_send_single(unsigned int virq, unsigned int cpu)
+{
+       struct irq_desc *desc = irq_to_desc(virq);
+       struct irq_data *data = desc ? irq_desc_get_irq_data(desc) : NULL;
+       struct irq_chip *chip = data ? irq_data_get_irq_chip(data) : NULL;
+
+       if (WARN_ON_ONCE(ipi_send_verify(chip, data, NULL, cpu)))
+               return -EINVAL;
+
+       return __ipi_send_single(desc, cpu);
+}
+EXPORT_SYMBOL_GPL(ipi_send_single);
+
+/**
+ * ipi_send_mask - Send an IPI to target CPU(s)
+ * @virq:      linux irq number from irq_reserve_ipi()
+ * @dest:      dest CPU(s), must be a subset of the mask passed to
+ *             irq_reserve_ipi()
+ *
+ * Returns zero on success and negative error number on failure.
+ */
+int ipi_send_mask(unsigned int virq, const struct cpumask *dest)
+{
+       struct irq_desc *desc = irq_to_desc(virq);
+       struct irq_data *data = desc ? irq_desc_get_irq_data(desc) : NULL;
+       struct irq_chip *chip = data ? irq_data_get_irq_chip(data) : NULL;
+
+       if (WARN_ON_ONCE(ipi_send_verify(chip, data, dest, 0)))
+               return -EINVAL;
+
+       return __ipi_send_mask(desc, dest);
+}
+EXPORT_SYMBOL_GPL(ipi_send_mask);
index 0409da0bcc3358b6b49ba6a79a339cf2176897ff..0ccd028817d7136ce7bd1faf10c6630690e2264e 100644 (file)
 static struct lock_class_key irq_desc_lock_class;
 
 #if defined(CONFIG_SMP)
+static int __init irq_affinity_setup(char *str)
+{
+       zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
+       cpulist_parse(str, irq_default_affinity);
+       /*
+        * Set at least the boot cpu. We don't want to end up with
+        * bugreports caused by random comandline masks
+        */
+       cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+       return 1;
+}
+__setup("irqaffinity=", irq_affinity_setup);
+
 static void __init init_irq_default_affinity(void)
 {
-       alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
-       cpumask_setall(irq_default_affinity);
+#ifdef CONFIG_CPUMASK_OFFSTACK
+       if (!irq_default_affinity)
+               zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
+#endif
+       if (cpumask_empty(irq_default_affinity))
+               cpumask_setall(irq_default_affinity);
 }
 #else
 static void __init init_irq_default_affinity(void)
index 3e56d2f03e24e6ee147e837727e6aac7a479f9aa..3a519a01118b0f68d071f8b0a0b368ea56327c20 100644 (file)
@@ -23,8 +23,6 @@ static DEFINE_MUTEX(irq_domain_mutex);
 static DEFINE_MUTEX(revmap_trees_mutex);
 static struct irq_domain *irq_default_domain;
 
-static int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
-                                 irq_hw_number_t hwirq, int node);
 static void irq_domain_check_hierarchy(struct irq_domain *domain);
 
 struct irqchip_fwid {
@@ -840,8 +838,8 @@ const struct irq_domain_ops irq_domain_simple_ops = {
 };
 EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
 
-static int irq_domain_alloc_descs(int virq, unsigned int cnt,
-                                 irq_hw_number_t hwirq, int node)
+int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
+                          int node)
 {
        unsigned int hint;
 
@@ -895,6 +893,7 @@ struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
 
        return domain;
 }
+EXPORT_SYMBOL_GPL(irq_domain_create_hierarchy);
 
 static void irq_domain_insert_irq(int virq)
 {
@@ -1045,6 +1044,7 @@ int irq_domain_set_hwirq_and_chip(struct irq_domain *domain, unsigned int virq,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(irq_domain_set_hwirq_and_chip);
 
 /**
  * irq_domain_set_info - Set the complete data for a @virq in @domain
@@ -1078,6 +1078,7 @@ void irq_domain_reset_irq_data(struct irq_data *irq_data)
        irq_data->chip = &no_irq_chip;
        irq_data->chip_data = NULL;
 }
+EXPORT_SYMBOL_GPL(irq_domain_reset_irq_data);
 
 /**
  * irq_domain_free_irqs_common - Clear irq_data and free the parent
@@ -1275,6 +1276,7 @@ int irq_domain_alloc_irqs_parent(struct irq_domain *domain,
                                                       nr_irqs, arg);
        return -ENOSYS;
 }
+EXPORT_SYMBOL_GPL(irq_domain_alloc_irqs_parent);
 
 /**
  * irq_domain_free_irqs_parent - Free interrupts from parent domain
@@ -1292,6 +1294,7 @@ void irq_domain_free_irqs_parent(struct irq_domain *domain,
                irq_domain_free_irqs_recursive(domain->parent, irq_base,
                                               nr_irqs);
 }
+EXPORT_SYMBOL_GPL(irq_domain_free_irqs_parent);
 
 /**
  * irq_domain_activate_irq - Call domain_ops->activate recursively to activate
index 841187239adc8e3bb0f72fb4ab0ca6a7fec2f618..64731e84c98242098733293ad37cdeee27baad7a 100644 (file)
@@ -144,13 +144,11 @@ int irq_can_set_affinity(unsigned int irq)
  */
 void irq_set_thread_affinity(struct irq_desc *desc)
 {
-       struct irqaction *action = desc->action;
+       struct irqaction *action;
 
-       while (action) {
+       for_each_action_of_desc(desc, action)
                if (action->thread)
                        set_bit(IRQTF_AFFINITY, &action->thread_flags);
-               action = action->next;
-       }
 }
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
@@ -994,7 +992,7 @@ void irq_wake_thread(unsigned int irq, void *dev_id)
                return;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       for (action = desc->action; action; action = action->next) {
+       for_each_action_of_desc(desc, action) {
                if (action->dev_id == dev_id) {
                        if (action->thread)
                                __irq_wake_thread(desc, action);
@@ -1609,6 +1607,9 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
        struct irq_desc *desc;
        int retval;
 
+       if (irq == IRQ_NOTCONNECTED)
+               return -ENOTCONN;
+
        /*
         * Sanity-check: shared interrupts must pass in a real dev-ID,
         * otherwise we'll have trouble later trying to figure out
@@ -1699,9 +1700,13 @@ EXPORT_SYMBOL(request_threaded_irq);
 int request_any_context_irq(unsigned int irq, irq_handler_t handler,
                            unsigned long flags, const char *name, void *dev_id)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
+       struct irq_desc *desc;
        int ret;
 
+       if (irq == IRQ_NOTCONNECTED)
+               return -ENOTCONN;
+
+       desc = irq_to_desc(irq);
        if (!desc)
                return -EINVAL;
 
index a2c02fd5d6d0f8c1ade72ab2680287f37321aa25..4e1b94726818001d7a165162b1ec954dc74880a9 100644 (file)
@@ -291,7 +291,7 @@ static int name_unique(unsigned int irq, struct irqaction *new_action)
        int ret = 1;
 
        raw_spin_lock_irqsave(&desc->lock, flags);
-       for (action = desc->action ; action; action = action->next) {
+       for_each_action_of_desc(desc, action) {
                if ((action != new_action) && action->name &&
                                !strcmp(new_action->name, action->name)) {
                        ret = 0;
index 32144175458d77d39dc65353770aa187818dfe6f..5707f97a3e6ac50954f8d407d5a4aadcaa2b96fc 100644 (file)
@@ -211,14 +211,12 @@ static void __report_bad_irq(struct irq_desc *desc, irqreturn_t action_ret)
         * desc->lock here. See synchronize_irq().
         */
        raw_spin_lock_irqsave(&desc->lock, flags);
-       action = desc->action;
-       while (action) {
+       for_each_action_of_desc(desc, action) {
                printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler);
                if (action->thread_fn)
                        printk(KERN_CONT " threaded [<%p>] %pf",
                                        action->thread_fn, action->thread_fn);
                printk(KERN_CONT "\n");
-               action = action->next;
        }
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
index 5c5987f1081964109f96cd6cc52b285b948f0a9e..fafd1a3ef0da56c6887fb5edd631e8e4a925a0e4 100644 (file)
@@ -38,6 +38,7 @@
  * during the second link stage.
  */
 extern const unsigned long kallsyms_addresses[] __weak;
+extern const int kallsyms_offsets[] __weak;
 extern const u8 kallsyms_names[] __weak;
 
 /*
@@ -47,6 +48,9 @@ extern const u8 kallsyms_names[] __weak;
 extern const unsigned long kallsyms_num_syms
 __attribute__((weak, section(".rodata")));
 
+extern const unsigned long kallsyms_relative_base
+__attribute__((weak, section(".rodata")));
+
 extern const u8 kallsyms_token_table[] __weak;
 extern const u16 kallsyms_token_index[] __weak;
 
@@ -176,6 +180,23 @@ static unsigned int get_symbol_offset(unsigned long pos)
        return name - kallsyms_names;
 }
 
+static unsigned long kallsyms_sym_address(int idx)
+{
+       if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
+               return kallsyms_addresses[idx];
+
+       /* values are unsigned offsets if --absolute-percpu is not in effect */
+       if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
+               return kallsyms_relative_base + (u32)kallsyms_offsets[idx];
+
+       /* ...otherwise, positive offsets are absolute values */
+       if (kallsyms_offsets[idx] >= 0)
+               return kallsyms_offsets[idx];
+
+       /* ...and negative offsets are relative to kallsyms_relative_base - 1 */
+       return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
+}
+
 /* Lookup the address for this symbol. Returns 0 if not found. */
 unsigned long kallsyms_lookup_name(const char *name)
 {
@@ -187,7 +208,7 @@ unsigned long kallsyms_lookup_name(const char *name)
                off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
 
                if (strcmp(namebuf, name) == 0)
-                       return kallsyms_addresses[i];
+                       return kallsyms_sym_address(i);
        }
        return module_kallsyms_lookup_name(name);
 }
@@ -204,7 +225,7 @@ int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
 
        for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
                off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
-               ret = fn(data, namebuf, NULL, kallsyms_addresses[i]);
+               ret = fn(data, namebuf, NULL, kallsyms_sym_address(i));
                if (ret != 0)
                        return ret;
        }
@@ -220,7 +241,10 @@ static unsigned long get_symbol_pos(unsigned long addr,
        unsigned long i, low, high, mid;
 
        /* This kernel should never had been booted. */
-       BUG_ON(!kallsyms_addresses);
+       if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
+               BUG_ON(!kallsyms_addresses);
+       else
+               BUG_ON(!kallsyms_offsets);
 
        /* Do a binary search on the sorted kallsyms_addresses array. */
        low = 0;
@@ -228,7 +252,7 @@ static unsigned long get_symbol_pos(unsigned long addr,
 
        while (high - low > 1) {
                mid = low + (high - low) / 2;
-               if (kallsyms_addresses[mid] <= addr)
+               if (kallsyms_sym_address(mid) <= addr)
                        low = mid;
                else
                        high = mid;
@@ -238,15 +262,15 @@ static unsigned long get_symbol_pos(unsigned long addr,
         * Search for the first aliased symbol. Aliased
         * symbols are symbols with the same address.
         */
-       while (low && kallsyms_addresses[low-1] == kallsyms_addresses[low])
+       while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
                --low;
 
-       symbol_start = kallsyms_addresses[low];
+       symbol_start = kallsyms_sym_address(low);
 
        /* Search for next non-aliased symbol. */
        for (i = low + 1; i < kallsyms_num_syms; i++) {
-               if (kallsyms_addresses[i] > symbol_start) {
-                       symbol_end = kallsyms_addresses[i];
+               if (kallsyms_sym_address(i) > symbol_start) {
+                       symbol_end = kallsyms_sym_address(i);
                        break;
                }
        }
@@ -470,7 +494,7 @@ static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
        unsigned off = iter->nameoff;
 
        iter->module_name[0] = '\0';
-       iter->value = kallsyms_addresses[iter->pos];
+       iter->value = kallsyms_sym_address(iter->pos);
 
        iter->type = kallsyms_get_symbol_type(off);
 
index 8dc65914486999f43caa9276dde914663919fbc6..8d34308ea449ad31bae472f0403c5f1b25324683 100644 (file)
@@ -66,13 +66,15 @@ struct resource crashk_res = {
        .name  = "Crash kernel",
        .start = 0,
        .end   = 0,
-       .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
+       .desc  = IORES_DESC_CRASH_KERNEL
 };
 struct resource crashk_low_res = {
        .name  = "Crash kernel",
        .start = 0,
        .end   = 0,
-       .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+       .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM,
+       .desc  = IORES_DESC_CRASH_KERNEL
 };
 
 int kexec_should_crash(struct task_struct *p)
@@ -959,7 +961,7 @@ int crash_shrink_memory(unsigned long new_size)
 
        ram_res->start = end;
        ram_res->end = crashk_res.end;
-       ram_res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+       ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
        ram_res->name = "System RAM";
 
        crashk_res.end = end - 1;
index 007b791f676d5605fb674b6db333d9dd1d0a23b4..56b18eb1f0013c9bc7e041a3dd2a8ecaeb580b95 100644 (file)
@@ -524,10 +524,10 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
 
        /* Walk the RAM ranges and allocate a suitable range for the buffer */
        if (image->type == KEXEC_TYPE_CRASH)
-               ret = walk_iomem_res("Crash kernel",
-                                    IORESOURCE_MEM | IORESOURCE_BUSY,
-                                    crashk_res.start, crashk_res.end, kbuf,
-                                    locate_mem_hole_callback);
+               ret = walk_iomem_res_desc(crashk_res.desc,
+                               IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
+                               crashk_res.start, crashk_res.end, kbuf,
+                               locate_mem_hole_callback);
        else
                ret = walk_system_ram_res(0, -1, kbuf,
                                          locate_mem_hole_callback);
index a02812743a7e63378a79cc768255f807a7fd469b..b5c30d9f46c5084acddbd34e533f91e9c98e8300 100644 (file)
  * of times)
  */
 
-#include <linux/latencytop.h>
 #include <linux/kallsyms.h>
 #include <linux/seq_file.h>
 #include <linux/notifier.h>
 #include <linux/spinlock.h>
 #include <linux/proc_fs.h>
+#include <linux/latencytop.h>
 #include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/list.h>
@@ -289,4 +289,16 @@ static int __init init_lstats_procfs(void)
        proc_create("latency_stats", 0644, NULL, &lstats_fops);
        return 0;
 }
+
+int sysctl_latencytop(struct ctl_table *table, int write,
+                       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int err;
+
+       err = proc_dointvec(table, write, buffer, lenp, ppos);
+       if (latencytop_enabled)
+               force_schedstat_enabled();
+
+       return err;
+}
 device_initcall(init_lstats_procfs);
index 716547fdb8731dcc395d70f2664ec6fb22378db6..53ab2f85d77e856942224b22980727c19e7dceae 100644 (file)
@@ -123,8 +123,6 @@ static inline int debug_locks_off_graph_unlock(void)
        return ret;
 }
 
-static int lockdep_initialized;
-
 unsigned long nr_list_entries;
 static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES];
 
@@ -150,8 +148,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
 }
 
 #ifdef CONFIG_LOCK_STAT
-static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS],
-                     cpu_lock_stats);
+static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
 
 static inline u64 lockstat_clock(void)
 {
@@ -433,19 +430,6 @@ unsigned int nr_process_chains;
 unsigned int max_lockdep_depth;
 
 #ifdef CONFIG_DEBUG_LOCKDEP
-/*
- * We cannot printk in early bootup code. Not even early_printk()
- * might work. So we mark any initialization errors and printk
- * about it later on, in lockdep_info().
- */
-static int lockdep_init_error;
-static const char *lock_init_error;
-static unsigned long lockdep_init_trace_data[20];
-static struct stack_trace lockdep_init_trace = {
-       .max_entries = ARRAY_SIZE(lockdep_init_trace_data),
-       .entries = lockdep_init_trace_data,
-};
-
 /*
  * Various lockdep statistics:
  */
@@ -669,20 +653,6 @@ look_up_lock_class(struct lockdep_map *lock, unsigned int subclass)
        struct hlist_head *hash_head;
        struct lock_class *class;
 
-#ifdef CONFIG_DEBUG_LOCKDEP
-       /*
-        * If the architecture calls into lockdep before initializing
-        * the hashes then we'll warn about it later. (we cannot printk
-        * right now)
-        */
-       if (unlikely(!lockdep_initialized)) {
-               lockdep_init();
-               lockdep_init_error = 1;
-               lock_init_error = lock->name;
-               save_stack_trace(&lockdep_init_trace);
-       }
-#endif
-
        if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) {
                debug_locks_off();
                printk(KERN_ERR
@@ -2010,6 +1980,53 @@ struct lock_class *lock_chain_get_class(struct lock_chain *chain, int i)
        return lock_classes + chain_hlocks[chain->base + i];
 }
 
+/*
+ * Returns the index of the first held_lock of the current chain
+ */
+static inline int get_first_held_lock(struct task_struct *curr,
+                                       struct held_lock *hlock)
+{
+       int i;
+       struct held_lock *hlock_curr;
+
+       for (i = curr->lockdep_depth - 1; i >= 0; i--) {
+               hlock_curr = curr->held_locks + i;
+               if (hlock_curr->irq_context != hlock->irq_context)
+                       break;
+
+       }
+
+       return ++i;
+}
+
+/*
+ * Checks whether the chain and the current held locks are consistent
+ * in depth and also in content. If they are not it most likely means
+ * that there was a collision during the calculation of the chain_key.
+ * Returns: 0 not passed, 1 passed
+ */
+static int check_no_collision(struct task_struct *curr,
+                       struct held_lock *hlock,
+                       struct lock_chain *chain)
+{
+#ifdef CONFIG_DEBUG_LOCKDEP
+       int i, j, id;
+
+       i = get_first_held_lock(curr, hlock);
+
+       if (DEBUG_LOCKS_WARN_ON(chain->depth != curr->lockdep_depth - (i - 1)))
+               return 0;
+
+       for (j = 0; j < chain->depth - 1; j++, i++) {
+               id = curr->held_locks[i].class_idx - 1;
+
+               if (DEBUG_LOCKS_WARN_ON(chain_hlocks[chain->base + j] != id))
+                       return 0;
+       }
+#endif
+       return 1;
+}
+
 /*
  * Look up a dependency chain. If the key is not present yet then
  * add it and return 1 - in this case the new dependency chain is
@@ -2023,7 +2040,6 @@ static inline int lookup_chain_cache(struct task_struct *curr,
        struct lock_class *class = hlock_class(hlock);
        struct hlist_head *hash_head = chainhashentry(chain_key);
        struct lock_chain *chain;
-       struct held_lock *hlock_curr;
        int i, j;
 
        /*
@@ -2041,6 +2057,9 @@ static inline int lookup_chain_cache(struct task_struct *curr,
                if (chain->chain_key == chain_key) {
 cache_hit:
                        debug_atomic_inc(chain_lookup_hits);
+                       if (!check_no_collision(curr, hlock, chain))
+                               return 0;
+
                        if (very_verbose(class))
                                printk("\nhash chain already cached, key: "
                                        "%016Lx tail class: [%p] %s\n",
@@ -2078,13 +2097,7 @@ cache_hit:
        chain = lock_chains + nr_lock_chains++;
        chain->chain_key = chain_key;
        chain->irq_context = hlock->irq_context;
-       /* Find the first held_lock of current chain */
-       for (i = curr->lockdep_depth - 1; i >= 0; i--) {
-               hlock_curr = curr->held_locks + i;
-               if (hlock_curr->irq_context != hlock->irq_context)
-                       break;
-       }
-       i++;
+       i = get_first_held_lock(curr, hlock);
        chain->depth = curr->lockdep_depth + 1 - i;
        if (likely(nr_chain_hlocks + chain->depth <= MAX_LOCKDEP_CHAIN_HLOCKS)) {
                chain->base = nr_chain_hlocks;
@@ -2172,7 +2185,7 @@ static void check_chain_key(struct task_struct *curr)
 {
 #ifdef CONFIG_DEBUG_LOCKDEP
        struct held_lock *hlock, *prev_hlock = NULL;
-       unsigned int i, id;
+       unsigned int i;
        u64 chain_key = 0;
 
        for (i = 0; i < curr->lockdep_depth; i++) {
@@ -2189,17 +2202,16 @@ static void check_chain_key(struct task_struct *curr)
                                (unsigned long long)hlock->prev_chain_key);
                        return;
                }
-               id = hlock->class_idx - 1;
                /*
                 * Whoops ran out of static storage again?
                 */
-               if (DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS))
+               if (DEBUG_LOCKS_WARN_ON(hlock->class_idx > MAX_LOCKDEP_KEYS))
                        return;
 
                if (prev_hlock && (prev_hlock->irq_context !=
                                                        hlock->irq_context))
                        chain_key = 0;
-               chain_key = iterate_chain_key(chain_key, id);
+               chain_key = iterate_chain_key(chain_key, hlock->class_idx);
                prev_hlock = hlock;
        }
        if (chain_key != curr->curr_chain_key) {
@@ -3077,7 +3089,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        struct task_struct *curr = current;
        struct lock_class *class = NULL;
        struct held_lock *hlock;
-       unsigned int depth, id;
+       unsigned int depth;
        int chain_head = 0;
        int class_idx;
        u64 chain_key;
@@ -3180,11 +3192,10 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
         * The 'key ID' is what is the most compact key value to drive
         * the hash, not class->key.
         */
-       id = class - lock_classes;
        /*
         * Whoops, we did it again.. ran straight out of our static allocation.
         */
-       if (DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS))
+       if (DEBUG_LOCKS_WARN_ON(class_idx > MAX_LOCKDEP_KEYS))
                return 0;
 
        chain_key = curr->curr_chain_key;
@@ -3202,7 +3213,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
                chain_key = 0;
                chain_head = 1;
        }
-       chain_key = iterate_chain_key(chain_key, id);
+       chain_key = iterate_chain_key(chain_key, class_idx);
 
        if (nest_lock && !__lock_is_held(nest_lock))
                return print_lock_nested_lock_not_held(curr, hlock, ip);
@@ -4013,28 +4024,6 @@ out_restore:
        raw_local_irq_restore(flags);
 }
 
-void lockdep_init(void)
-{
-       int i;
-
-       /*
-        * Some architectures have their own start_kernel()
-        * code which calls lockdep_init(), while we also
-        * call lockdep_init() from the start_kernel() itself,
-        * and we want to initialize the hashes only once:
-        */
-       if (lockdep_initialized)
-               return;
-
-       for (i = 0; i < CLASSHASH_SIZE; i++)
-               INIT_HLIST_HEAD(classhash_table + i);
-
-       for (i = 0; i < CHAINHASH_SIZE; i++)
-               INIT_HLIST_HEAD(chainhash_table + i);
-
-       lockdep_initialized = 1;
-}
-
 void __init lockdep_info(void)
 {
        printk("Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar\n");
@@ -4061,14 +4050,6 @@ void __init lockdep_info(void)
 
        printk(" per task-struct memory footprint: %lu bytes\n",
                sizeof(struct held_lock) * MAX_LOCK_DEPTH);
-
-#ifdef CONFIG_DEBUG_LOCKDEP
-       if (lockdep_init_error) {
-               printk("WARNING: lockdep init error: lock '%s' was acquired before lockdep_init().\n", lock_init_error);
-               printk("Call stack leading to lockdep invocation was:\n");
-               print_stack_trace(&lockdep_init_trace, 0);
-       }
-#endif
 }
 
 static void
index 5b9102a47ea5209dd887b6dfbca16215b2bad922..c835270f0c2f93c24f623e9ea2ba2e94eebb006a 100644 (file)
@@ -67,7 +67,13 @@ void mcs_spin_lock(struct mcs_spinlock **lock, struct mcs_spinlock *node)
        node->locked = 0;
        node->next   = NULL;
 
-       prev = xchg_acquire(lock, node);
+       /*
+        * We rely on the full barrier with global transitivity implied by the
+        * below xchg() to order the initialization stores above against any
+        * observation of @node. And to provide the ACQUIRE ordering associated
+        * with a LOCK primitive.
+        */
+       prev = xchg(lock, node);
        if (likely(prev == NULL)) {
                /*
                 * Lock acquired, don't need to set node->locked to 1. Threads
index 0551c219c40e5bb8f8f87bfb0445100fe1b31cc9..e364b424b019ff51de0bde17fe2611444b5c1efb 100644 (file)
@@ -716,6 +716,7 @@ static inline void
 __mutex_unlock_common_slowpath(struct mutex *lock, int nested)
 {
        unsigned long flags;
+       WAKE_Q(wake_q);
 
        /*
         * As a performance measurement, release the lock before doing other
@@ -743,11 +744,11 @@ __mutex_unlock_common_slowpath(struct mutex *lock, int nested)
                                           struct mutex_waiter, list);
 
                debug_mutex_wake_waiter(lock, waiter);
-
-               wake_up_process(waiter->task);
+               wake_q_add(&wake_q, waiter->task);
        }
 
        spin_unlock_mutex(&lock->wait_lock, flags);
+       wake_up_q(&wake_q);
 }
 
 /*
index 393d1874b9e0c81d44ef9d0447ded22a03bccd81..ce2f75e32ae155b30cfe324c56f9bc526771b66a 100644 (file)
@@ -358,8 +358,7 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
         * sequentiality; this is because not all clear_pending_set_locked()
         * implementations imply full barriers.
         */
-       while ((val = smp_load_acquire(&lock->val.counter)) & _Q_LOCKED_MASK)
-               cpu_relax();
+       smp_cond_acquire(!(atomic_read(&lock->val) & _Q_LOCKED_MASK));
 
        /*
         * take ownership and clear the pending bit.
@@ -435,7 +434,7 @@ queue:
         *
         * The PV pv_wait_head_or_lock function, if active, will acquire
         * the lock and return a non-zero value. So we have to skip the
-        * smp_load_acquire() call. As the next PV queue head hasn't been
+        * smp_cond_acquire() call. As the next PV queue head hasn't been
         * designated yet, there is no way for the locked value to become
         * _Q_SLOW_VAL. So both the set_locked() and the
         * atomic_cmpxchg_relaxed() calls will be safe.
@@ -466,7 +465,7 @@ locked:
                        break;
                }
                /*
-                * The smp_load_acquire() call above has provided the necessary
+                * The smp_cond_acquire() call above has provided the necessary
                 * acquire semantics required for locking. At most two
                 * iterations of this loop may be ran.
                 */
index 87bb235c3448054d63923d0f9549cbc7718a49ca..21ede57f68b320594f874e4ff0a1b60974fc67f0 100644 (file)
@@ -54,6 +54,11 @@ struct pv_node {
        u8                      state;
 };
 
+/*
+ * Include queued spinlock statistics code
+ */
+#include "qspinlock_stat.h"
+
 /*
  * By replacing the regular queued_spin_trylock() with the function below,
  * it will be called once when a lock waiter enter the PV slowpath before
@@ -65,9 +70,11 @@ struct pv_node {
 static inline bool pv_queued_spin_steal_lock(struct qspinlock *lock)
 {
        struct __qspinlock *l = (void *)lock;
+       int ret = !(atomic_read(&lock->val) & _Q_LOCKED_PENDING_MASK) &&
+                  (cmpxchg(&l->locked, 0, _Q_LOCKED_VAL) == 0);
 
-       return !(atomic_read(&lock->val) & _Q_LOCKED_PENDING_MASK) &&
-               (cmpxchg(&l->locked, 0, _Q_LOCKED_VAL) == 0);
+       qstat_inc(qstat_pv_lock_stealing, ret);
+       return ret;
 }
 
 /*
@@ -137,11 +144,6 @@ static __always_inline int trylock_clear_pending(struct qspinlock *lock)
 }
 #endif /* _Q_PENDING_BITS == 8 */
 
-/*
- * Include queued spinlock statistics code
- */
-#include "qspinlock_stat.h"
-
 /*
  * Lock and MCS node addresses hash table for fast lookup
  *
@@ -398,6 +400,11 @@ pv_wait_head_or_lock(struct qspinlock *lock, struct mcs_spinlock *node)
        if (READ_ONCE(pn->state) == vcpu_hashed)
                lp = (struct qspinlock **)1;
 
+       /*
+        * Tracking # of slowpath locking operations
+        */
+       qstat_inc(qstat_pv_lock_slowpath, true);
+
        for (;; waitcnt++) {
                /*
                 * Set correct vCPU state to be used by queue node wait-early
index 640dcecdd1df7a5ac5c8167fbd9e70e71b2e8f21..eb2a2c9bc3fc15d181c9e5981648974dc7aec65c 100644 (file)
@@ -22,6 +22,7 @@
  *   pv_kick_wake      - # of vCPU kicks used for computing pv_latency_wake
  *   pv_latency_kick   - average latency (ns) of vCPU kick operation
  *   pv_latency_wake   - average latency (ns) from vCPU kick to wakeup
+ *   pv_lock_slowpath  - # of locking operations via the slowpath
  *   pv_lock_stealing  - # of lock stealing operations
  *   pv_spurious_wakeup        - # of spurious wakeups
  *   pv_wait_again     - # of vCPU wait's that happened after a vCPU kick
@@ -45,6 +46,7 @@ enum qlock_stats {
        qstat_pv_kick_wake,
        qstat_pv_latency_kick,
        qstat_pv_latency_wake,
+       qstat_pv_lock_slowpath,
        qstat_pv_lock_stealing,
        qstat_pv_spurious_wakeup,
        qstat_pv_wait_again,
@@ -70,6 +72,7 @@ static const char * const qstat_names[qstat_num + 1] = {
        [qstat_pv_spurious_wakeup] = "pv_spurious_wakeup",
        [qstat_pv_latency_kick]    = "pv_latency_kick",
        [qstat_pv_latency_wake]    = "pv_latency_wake",
+       [qstat_pv_lock_slowpath]   = "pv_lock_slowpath",
        [qstat_pv_lock_stealing]   = "pv_lock_stealing",
        [qstat_pv_wait_again]      = "pv_wait_again",
        [qstat_pv_wait_early]      = "pv_wait_early",
@@ -279,19 +282,6 @@ static inline void __pv_wait(u8 *ptr, u8 val)
 #define pv_kick(c)     __pv_kick(c)
 #define pv_wait(p, v)  __pv_wait(p, v)
 
-/*
- * PV unfair trylock count tracking function
- */
-static inline int qstat_spin_steal_lock(struct qspinlock *lock)
-{
-       int ret = pv_queued_spin_steal_lock(lock);
-
-       qstat_inc(qstat_pv_lock_stealing, ret);
-       return ret;
-}
-#undef  queued_spin_trylock
-#define queued_spin_trylock(l) qstat_spin_steal_lock(l)
-
 #else /* CONFIG_QUEUED_LOCK_STAT */
 
 static inline void qstat_inc(enum qlock_stats stat, bool cond) { }
index 7a1b5c3ef14e9301966f724c873b1edee864f910..584febd13e2e3864a336c66998c69f85480d4211 100644 (file)
@@ -29,10 +29,10 @@ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
 
 static void *try_ram_remap(resource_size_t offset, size_t size)
 {
-       struct page *page = pfn_to_page(offset >> PAGE_SHIFT);
+       unsigned long pfn = PHYS_PFN(offset);
 
        /* In the simple case just return the existing linear address */
-       if (!PageHighMem(page))
+       if (pfn_valid(pfn) && !PageHighMem(pfn_to_page(pfn)))
                return __va(offset);
        return NULL; /* fallback to ioremap_cache */
 }
@@ -47,7 +47,7 @@ static void *try_ram_remap(resource_size_t offset, size_t size)
  * being mapped does not have i/o side effects and the __iomem
  * annotation is not applicable.
  *
- * MEMREMAP_WB - matches the default mapping for "System RAM" on
+ * MEMREMAP_WB - matches the default mapping for System RAM on
  * the architecture.  This is usually a read-allocate write-back cache.
  * Morever, if MEMREMAP_WB is specified and the requested remap region is RAM
  * memremap() will bypass establishing a new mapping and instead return
@@ -56,11 +56,12 @@ static void *try_ram_remap(resource_size_t offset, size_t size)
  * MEMREMAP_WT - establish a mapping whereby writes either bypass the
  * cache or are written through to memory and never exist in a
  * cache-dirty state with respect to program visibility.  Attempts to
- * map "System RAM" with this mapping type will fail.
+ * map System RAM with this mapping type will fail.
  */
 void *memremap(resource_size_t offset, size_t size, unsigned long flags)
 {
-       int is_ram = region_intersects(offset, size, "System RAM");
+       int is_ram = region_intersects(offset, size,
+                                      IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
        void *addr = NULL;
 
        if (is_ram == REGION_MIXED) {
@@ -76,7 +77,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
                 * MEMREMAP_WB is special in that it can be satisifed
                 * from the direct map.  Some archs depend on the
                 * capability of memremap() to autodetect cases where
-                * the requested range is potentially in "System RAM"
+                * the requested range is potentially in System RAM.
                 */
                if (is_ram == REGION_INTERSECTS)
                        addr = try_ram_remap(offset, size);
@@ -88,7 +89,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
         * If we don't have a mapping yet and more request flags are
         * pending then we will be attempting to establish a new virtual
         * address mapping.  Enforce that this mapping is not aliasing
-        * "System RAM"
+        * System RAM.
         */
        if (!addr && is_ram == REGION_INTERSECTS && flags) {
                WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n",
@@ -136,8 +137,10 @@ void *devm_memremap(struct device *dev, resource_size_t offset,
        if (addr) {
                *ptr = addr;
                devres_add(dev, ptr);
-       } else
+       } else {
                devres_free(ptr);
+               return ERR_PTR(-ENXIO);
+       }
 
        return addr;
 }
@@ -268,13 +271,17 @@ struct dev_pagemap *find_dev_pagemap(resource_size_t phys)
 void *devm_memremap_pages(struct device *dev, struct resource *res,
                struct percpu_ref *ref, struct vmem_altmap *altmap)
 {
-       int is_ram = region_intersects(res->start, resource_size(res),
-                       "System RAM");
        resource_size_t key, align_start, align_size, align_end;
        struct dev_pagemap *pgmap;
        struct page_map *page_map;
+       int error, nid, is_ram;
        unsigned long pfn;
-       int error, nid;
+
+       align_start = res->start & ~(SECTION_SIZE - 1);
+       align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
+               - align_start;
+       is_ram = region_intersects(align_start, align_size,
+               IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
 
        if (is_ram == REGION_MIXED) {
                WARN_ONCE(1, "%s attempted on mixed region %pr\n",
@@ -312,8 +319,6 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
 
        mutex_lock(&pgmap_lock);
        error = 0;
-       align_start = res->start & ~(SECTION_SIZE - 1);
-       align_size = ALIGN(resource_size(res), SECTION_SIZE);
        align_end = align_start + align_size - 1;
        for (key = align_start; key <= align_end; key += SECTION_SIZE) {
                struct dev_pagemap *dup;
@@ -349,8 +354,13 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
        for_each_device_pfn(pfn, page_map) {
                struct page *page = pfn_to_page(pfn);
 
-               /* ZONE_DEVICE pages must never appear on a slab lru */
-               list_force_poison(&page->lru);
+               /*
+                * ZONE_DEVICE pages union ->lru with a ->pgmap back
+                * pointer.  It is a bug if a ZONE_DEVICE page is ever
+                * freed or placed on a driver-private list.  Seed the
+                * storage with LIST_POISON* values.
+                */
+               list_del(&page->lru);
                page->pgmap = pgmap;
        }
        devres_add(dev, page_map);
@@ -381,7 +391,7 @@ struct vmem_altmap *to_vmem_altmap(unsigned long memmap_start)
        /*
         * 'memmap_start' is the virtual address for the first "struct
         * page" in this range of the vmemmap array.  In the case of
-        * CONFIG_SPARSE_VMEMMAP a page_to_pfn conversion is simple
+        * CONFIG_SPARSEMEM_VMEMMAP a page_to_pfn conversion is simple
         * pointer arithmetic, so we can perform this to_vmem_altmap()
         * conversion without concern for the initialization state of
         * the struct page fields.
@@ -390,7 +400,7 @@ struct vmem_altmap *to_vmem_altmap(unsigned long memmap_start)
        struct dev_pagemap *pgmap;
 
        /*
-        * Uncoditionally retrieve a dev_pagemap associated with the
+        * Unconditionally retrieve a dev_pagemap associated with the
         * given physical address, this is only for use in the
         * arch_{add|remove}_memory() for setting up and tearing down
         * the memmap.
index b7342a24f559211934fb90db21a4a06d5479b21a..aa0f26b5842659a5c12b794ed8535e77edd44f15 100644 (file)
@@ -1158,6 +1158,22 @@ static int __init kaslr_nohibernate_setup(char *str)
        return nohibernate_setup(str);
 }
 
+static int __init page_poison_nohibernate_setup(char *str)
+{
+#ifdef CONFIG_PAGE_POISONING_ZERO
+       /*
+        * The zeroing option for page poison skips the checks on alloc.
+        * since hibernation doesn't save free pages there's no way to
+        * guarantee the pages will still be zeroed.
+        */
+       if (!strcmp(str, "on")) {
+               pr_info("Disabling hibernation due to page poisoning\n");
+               return nohibernate_setup(str);
+       }
+#endif
+       return 1;
+}
+
 __setup("noresume", noresume_setup);
 __setup("resume_offset=", resume_offset_setup);
 __setup("resume=", resume_setup);
@@ -1166,3 +1182,4 @@ __setup("resumewait", resumewait_setup);
 __setup("resumedelay=", resumedelay_setup);
 __setup("nohibernate", nohibernate_setup);
 __setup("kaslr", kaslr_nohibernate_setup);
+__setup("page_poison=", page_poison_nohibernate_setup);
index 564f786df4701a82a8de89821304cfb0f0b7a337..df058bed53cebea8172fceaa1a97041d29a78fa6 100644 (file)
@@ -30,13 +30,12 @@ static int try_to_freeze_tasks(bool user_only)
        unsigned long end_time;
        unsigned int todo;
        bool wq_busy = false;
-       struct timeval start, end;
-       u64 elapsed_msecs64;
+       ktime_t start, end, elapsed;
        unsigned int elapsed_msecs;
        bool wakeup = false;
        int sleep_usecs = USEC_PER_MSEC;
 
-       do_gettimeofday(&start);
+       start = ktime_get_boottime();
 
        end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs);
 
@@ -78,10 +77,9 @@ static int try_to_freeze_tasks(bool user_only)
                        sleep_usecs *= 2;
        }
 
-       do_gettimeofday(&end);
-       elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
-       do_div(elapsed_msecs64, NSEC_PER_MSEC);
-       elapsed_msecs = elapsed_msecs64;
+       end = ktime_get_boottime();
+       elapsed = ktime_sub(end, start);
+       elapsed_msecs = ktime_to_ms(elapsed);
 
        if (todo) {
                pr_cont("\n");
index f9fe133c13e24de8e91f4ea81abebe6c58a3fd23..230a77225e2e8d5bd0cb16807c810ec5f18f2f60 100644 (file)
@@ -248,7 +248,7 @@ static int suspend_test(int level)
 {
 #ifdef CONFIG_PM_DEBUG
        if (pm_test_level == level) {
-               printk(KERN_INFO "suspend debug: Waiting for %d second(s).\n",
+               pr_info("suspend debug: Waiting for %d second(s).\n",
                                pm_test_delay);
                mdelay(pm_test_delay * 1000);
                return 1;
@@ -320,7 +320,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 
        error = dpm_suspend_late(PMSG_SUSPEND);
        if (error) {
-               printk(KERN_ERR "PM: late suspend of devices failed\n");
+               pr_err("PM: late suspend of devices failed\n");
                goto Platform_finish;
        }
        error = platform_suspend_prepare_late(state);
@@ -329,7 +329,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
 
        error = dpm_suspend_noirq(PMSG_SUSPEND);
        if (error) {
-               printk(KERN_ERR "PM: noirq suspend of devices failed\n");
+               pr_err("PM: noirq suspend of devices failed\n");
                goto Platform_early_resume;
        }
        error = platform_suspend_prepare_noirq(state);
index 99513e1160e518d322f6d0ce0f346e6da9fcbbf0..51369697466e36ba52af710863376d4847d43e36 100644 (file)
@@ -59,6 +59,7 @@ int profile_setup(char *str)
 
        if (!strncmp(str, sleepstr, strlen(sleepstr))) {
 #ifdef CONFIG_SCHEDSTATS
+               force_schedstat_enabled();
                prof_on = SLEEP_PROFILING;
                if (str[strlen(sleepstr)] == ',')
                        str += strlen(sleepstr) + 1;
index d2988d047d668d1d280c894beef56befdab65e65..250ea67c1615bf1022056e7a01ef088414cc0c39 100644 (file)
@@ -130,10 +130,8 @@ static struct rcu_torture __rcu *rcu_torture_current;
 static unsigned long rcu_torture_current_version;
 static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
 static DEFINE_SPINLOCK(rcu_torture_lock);
-static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1],
-                     rcu_torture_count) = { 0 };
-static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1],
-                     rcu_torture_batch) = { 0 };
+static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) = { 0 };
+static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_batch) = { 0 };
 static atomic_t rcu_torture_wcount[RCU_TORTURE_PIPE_LEN + 1];
 static atomic_t n_rcu_torture_alloc;
 static atomic_t n_rcu_torture_alloc_fail;
@@ -932,12 +930,14 @@ rcu_torture_writer(void *arg)
        int nsynctypes = 0;
 
        VERBOSE_TOROUT_STRING("rcu_torture_writer task started");
-       pr_alert("%s" TORTURE_FLAG
-                " Grace periods expedited from boot/sysfs for %s,\n",
-                torture_type, cur_ops->name);
-       pr_alert("%s" TORTURE_FLAG
-                " Testing of dynamic grace-period expediting diabled.\n",
-                torture_type);
+       if (!can_expedite) {
+               pr_alert("%s" TORTURE_FLAG
+                        " Grace periods expedited from boot/sysfs for %s,\n",
+                        torture_type, cur_ops->name);
+               pr_alert("%s" TORTURE_FLAG
+                        " Disabled dynamic grace-period expediting.\n",
+                        torture_type);
+       }
 
        /* Initialize synctype[] array.  If none set, take default. */
        if (!gp_cond1 && !gp_exp1 && !gp_normal1 && !gp_sync1)
index e492a5253e0f10c94da7056efd8f42ba2c1a394c..196f0302e2f4320ebd25dedc31d0ea8a4ab026c1 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 #include <linux/kthread.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
@@ -122,18 +122,7 @@ free_out:
        debugfs_remove_recursive(rcudir);
        return 1;
 }
-
-static void __exit rcutiny_trace_cleanup(void)
-{
-       debugfs_remove_recursive(rcudir);
-}
-
-module_init(rcutiny_trace_init);
-module_exit(rcutiny_trace_cleanup);
-
-MODULE_AUTHOR("Paul E. McKenney");
-MODULE_DESCRIPTION("Read-Copy Update tracing for tiny implementation");
-MODULE_LICENSE("GPL");
+device_initcall(rcutiny_trace_init);
 
 static void check_cpu_stall(struct rcu_ctrlblk *rcp)
 {
index e41dd4131f7a141976e771653e3169f2955f6f33..9a535a86e7326b21dce28a002607370df4de4de4 100644 (file)
@@ -108,7 +108,6 @@ RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched);
 RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh);
 
 static struct rcu_state *const rcu_state_p;
-static struct rcu_data __percpu *const rcu_data_p;
 LIST_HEAD(rcu_struct_flavors);
 
 /* Dump rcu_node combining tree at boot to verify correct setup. */
@@ -1083,13 +1082,12 @@ static int dyntick_save_progress_counter(struct rcu_data *rdp,
        rcu_sysidle_check_cpu(rdp, isidle, maxj);
        if ((rdp->dynticks_snap & 0x1) == 0) {
                trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, TPS("dti"));
-               return 1;
-       } else {
                if (ULONG_CMP_LT(READ_ONCE(rdp->gpnum) + ULONG_MAX / 4,
                                 rdp->mynode->gpnum))
                        WRITE_ONCE(rdp->gpwrap, true);
-               return 0;
+               return 1;
        }
+       return 0;
 }
 
 /*
@@ -1173,15 +1171,16 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
                        smp_mb(); /* ->cond_resched_completed before *rcrmp. */
                        WRITE_ONCE(*rcrmp,
                                   READ_ONCE(*rcrmp) + rdp->rsp->flavor_mask);
-                       resched_cpu(rdp->cpu);  /* Force CPU into scheduler. */
-                       rdp->rsp->jiffies_resched += 5; /* Enable beating. */
-               } else if (ULONG_CMP_GE(jiffies, rdp->rsp->jiffies_resched)) {
-                       /* Time to beat on that CPU again! */
-                       resched_cpu(rdp->cpu);  /* Force CPU into scheduler. */
-                       rdp->rsp->jiffies_resched += 5; /* Re-enable beating. */
                }
+               rdp->rsp->jiffies_resched += 5; /* Re-enable beating. */
        }
 
+       /* And if it has been a really long time, kick the CPU as well. */
+       if (ULONG_CMP_GE(jiffies,
+                        rdp->rsp->gp_start + 2 * jiffies_till_sched_qs) ||
+           ULONG_CMP_GE(jiffies, rdp->rsp->gp_start + jiffies_till_sched_qs))
+               resched_cpu(rdp->cpu);  /* Force CPU into scheduler. */
+
        return 0;
 }
 
@@ -1246,7 +1245,7 @@ static void rcu_dump_cpu_stacks(struct rcu_state *rsp)
                                if (rnp->qsmask & (1UL << cpu))
                                        dump_cpu_task(rnp->grplo + cpu);
                }
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        }
 }
 
@@ -1266,12 +1265,12 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
        raw_spin_lock_irqsave_rcu_node(rnp, flags);
        delta = jiffies - READ_ONCE(rsp->jiffies_stall);
        if (delta < RCU_STALL_RAT_DELAY || !rcu_gp_in_progress(rsp)) {
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                return;
        }
        WRITE_ONCE(rsp->jiffies_stall,
                   jiffies + 3 * rcu_jiffies_till_stall_check() + 3);
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 
        /*
         * OK, time to rat on our buddy...
@@ -1292,7 +1291,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
                                        ndetected++;
                                }
                }
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        }
 
        print_cpu_stall_info_end();
@@ -1357,7 +1356,7 @@ static void print_cpu_stall(struct rcu_state *rsp)
        if (ULONG_CMP_GE(jiffies, READ_ONCE(rsp->jiffies_stall)))
                WRITE_ONCE(rsp->jiffies_stall,
                           jiffies + 3 * rcu_jiffies_till_stall_check() + 3);
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 
        /*
         * Attempt to revive the RCU machinery by forcing a context switch.
@@ -1595,7 +1594,7 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp,
        }
 unlock_out:
        if (rnp != rnp_root)
-               raw_spin_unlock(&rnp_root->lock);
+               raw_spin_unlock_rcu_node(rnp_root);
 out:
        if (c_out != NULL)
                *c_out = c;
@@ -1614,7 +1613,6 @@ static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
        int needmore;
        struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
 
-       rcu_nocb_gp_cleanup(rsp, rnp);
        rnp->need_future_gp[c & 0x1] = 0;
        needmore = rnp->need_future_gp[(c + 1) & 0x1];
        trace_rcu_future_gp(rnp, rdp, c,
@@ -1635,7 +1633,7 @@ static void rcu_gp_kthread_wake(struct rcu_state *rsp)
            !READ_ONCE(rsp->gp_flags) ||
            !rsp->gp_kthread)
                return;
-       wake_up(&rsp->gp_wq);
+       swake_up(&rsp->gp_wq);
 }
 
 /*
@@ -1815,7 +1813,7 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp)
                return;
        }
        needwake = __note_gp_changes(rsp, rnp, rdp);
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        if (needwake)
                rcu_gp_kthread_wake(rsp);
 }
@@ -1840,7 +1838,7 @@ static bool rcu_gp_init(struct rcu_state *rsp)
        raw_spin_lock_irq_rcu_node(rnp);
        if (!READ_ONCE(rsp->gp_flags)) {
                /* Spurious wakeup, tell caller to go back to sleep.  */
-               raw_spin_unlock_irq(&rnp->lock);
+               raw_spin_unlock_irq_rcu_node(rnp);
                return false;
        }
        WRITE_ONCE(rsp->gp_flags, 0); /* Clear all flags: New grace period. */
@@ -1850,7 +1848,7 @@ static bool rcu_gp_init(struct rcu_state *rsp)
                 * Grace period already in progress, don't start another.
                 * Not supposed to be able to happen.
                 */
-               raw_spin_unlock_irq(&rnp->lock);
+               raw_spin_unlock_irq_rcu_node(rnp);
                return false;
        }
 
@@ -1859,7 +1857,7 @@ static bool rcu_gp_init(struct rcu_state *rsp)
        /* Record GP times before starting GP, hence smp_store_release(). */
        smp_store_release(&rsp->gpnum, rsp->gpnum + 1);
        trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start"));
-       raw_spin_unlock_irq(&rnp->lock);
+       raw_spin_unlock_irq_rcu_node(rnp);
 
        /*
         * Apply per-leaf buffered online and offline operations to the
@@ -1873,7 +1871,7 @@ static bool rcu_gp_init(struct rcu_state *rsp)
                if (rnp->qsmaskinit == rnp->qsmaskinitnext &&
                    !rnp->wait_blkd_tasks) {
                        /* Nothing to do on this leaf rcu_node structure. */
-                       raw_spin_unlock_irq(&rnp->lock);
+                       raw_spin_unlock_irq_rcu_node(rnp);
                        continue;
                }
 
@@ -1907,7 +1905,7 @@ static bool rcu_gp_init(struct rcu_state *rsp)
                        rcu_cleanup_dead_rnp(rnp);
                }
 
-               raw_spin_unlock_irq(&rnp->lock);
+               raw_spin_unlock_irq_rcu_node(rnp);
        }
 
        /*
@@ -1938,7 +1936,7 @@ static bool rcu_gp_init(struct rcu_state *rsp)
                trace_rcu_grace_period_init(rsp->name, rnp->gpnum,
                                            rnp->level, rnp->grplo,
                                            rnp->grphi, rnp->qsmask);
-               raw_spin_unlock_irq(&rnp->lock);
+               raw_spin_unlock_irq_rcu_node(rnp);
                cond_resched_rcu_qs();
                WRITE_ONCE(rsp->gp_activity, jiffies);
        }
@@ -1996,7 +1994,7 @@ static void rcu_gp_fqs(struct rcu_state *rsp, bool first_time)
                raw_spin_lock_irq_rcu_node(rnp);
                WRITE_ONCE(rsp->gp_flags,
                           READ_ONCE(rsp->gp_flags) & ~RCU_GP_FLAG_FQS);
-               raw_spin_unlock_irq(&rnp->lock);
+               raw_spin_unlock_irq_rcu_node(rnp);
        }
 }
 
@@ -2010,6 +2008,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
        int nocb = 0;
        struct rcu_data *rdp;
        struct rcu_node *rnp = rcu_get_root(rsp);
+       struct swait_queue_head *sq;
 
        WRITE_ONCE(rsp->gp_activity, jiffies);
        raw_spin_lock_irq_rcu_node(rnp);
@@ -2025,7 +2024,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
         * safe for us to drop the lock in order to mark the grace
         * period as completed in all of the rcu_node structures.
         */
-       raw_spin_unlock_irq(&rnp->lock);
+       raw_spin_unlock_irq_rcu_node(rnp);
 
        /*
         * Propagate new ->completed value to rcu_node structures so
@@ -2046,7 +2045,9 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
                        needgp = __note_gp_changes(rsp, rnp, rdp) || needgp;
                /* smp_mb() provided by prior unlock-lock pair. */
                nocb += rcu_future_gp_cleanup(rsp, rnp);
-               raw_spin_unlock_irq(&rnp->lock);
+               sq = rcu_nocb_gp_get(rnp);
+               raw_spin_unlock_irq_rcu_node(rnp);
+               rcu_nocb_gp_cleanup(sq);
                cond_resched_rcu_qs();
                WRITE_ONCE(rsp->gp_activity, jiffies);
                rcu_gp_slow(rsp, gp_cleanup_delay);
@@ -2068,7 +2069,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
                                       READ_ONCE(rsp->gpnum),
                                       TPS("newreq"));
        }
-       raw_spin_unlock_irq(&rnp->lock);
+       raw_spin_unlock_irq_rcu_node(rnp);
 }
 
 /*
@@ -2092,7 +2093,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
                                               READ_ONCE(rsp->gpnum),
                                               TPS("reqwait"));
                        rsp->gp_state = RCU_GP_WAIT_GPS;
-                       wait_event_interruptible(rsp->gp_wq,
+                       swait_event_interruptible(rsp->gp_wq,
                                                 READ_ONCE(rsp->gp_flags) &
                                                 RCU_GP_FLAG_INIT);
                        rsp->gp_state = RCU_GP_DONE_GPS;
@@ -2122,7 +2123,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
                                               READ_ONCE(rsp->gpnum),
                                               TPS("fqswait"));
                        rsp->gp_state = RCU_GP_WAIT_FQS;
-                       ret = wait_event_interruptible_timeout(rsp->gp_wq,
+                       ret = swait_event_interruptible_timeout(rsp->gp_wq,
                                        rcu_gp_fqs_check_wake(rsp, &gf), j);
                        rsp->gp_state = RCU_GP_DOING_FQS;
                        /* Locking provides needed memory barriers. */
@@ -2234,19 +2235,21 @@ static bool rcu_start_gp(struct rcu_state *rsp)
 }
 
 /*
- * Report a full set of quiescent states to the specified rcu_state
- * data structure.  This involves cleaning up after the prior grace
- * period and letting rcu_start_gp() start up the next grace period
- * if one is needed.  Note that the caller must hold rnp->lock, which
- * is released before return.
+ * Report a full set of quiescent states to the specified rcu_state data
+ * structure.  Invoke rcu_gp_kthread_wake() to awaken the grace-period
+ * kthread if another grace period is required.  Whether we wake
+ * the grace-period kthread or it awakens itself for the next round
+ * of quiescent-state forcing, that kthread will clean up after the
+ * just-completed grace period.  Note that the caller must hold rnp->lock,
+ * which is released before return.
  */
 static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)
        __releases(rcu_get_root(rsp)->lock)
 {
        WARN_ON_ONCE(!rcu_gp_in_progress(rsp));
        WRITE_ONCE(rsp->gp_flags, READ_ONCE(rsp->gp_flags) | RCU_GP_FLAG_FQS);
-       raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags);
-       rcu_gp_kthread_wake(rsp);
+       raw_spin_unlock_irqrestore_rcu_node(rcu_get_root(rsp), flags);
+       swake_up(&rsp->gp_wq);  /* Memory barrier implied by swake_up() path. */
 }
 
 /*
@@ -2275,7 +2278,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
                         * Our bit has already been cleared, or the
                         * relevant grace period is already over, so done.
                         */
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                        return;
                }
                WARN_ON_ONCE(oldmask); /* Any child must be all zeroed! */
@@ -2287,7 +2290,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
                if (rnp->qsmask != 0 || rcu_preempt_blocked_readers_cgp(rnp)) {
 
                        /* Other bits still set at this level, so done. */
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                        return;
                }
                mask = rnp->grpmask;
@@ -2297,7 +2300,7 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,
 
                        break;
                }
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                rnp_c = rnp;
                rnp = rnp->parent;
                raw_spin_lock_irqsave_rcu_node(rnp, flags);
@@ -2329,7 +2332,7 @@ static void rcu_report_unblock_qs_rnp(struct rcu_state *rsp,
 
        if (rcu_state_p == &rcu_sched_state || rsp != rcu_state_p ||
            rnp->qsmask != 0 || rcu_preempt_blocked_readers_cgp(rnp)) {
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                return;  /* Still need more quiescent states! */
        }
 
@@ -2346,19 +2349,14 @@ static void rcu_report_unblock_qs_rnp(struct rcu_state *rsp,
        /* Report up the rest of the hierarchy, tracking current ->gpnum. */
        gps = rnp->gpnum;
        mask = rnp->grpmask;
-       raw_spin_unlock(&rnp->lock);    /* irqs remain disabled. */
+       raw_spin_unlock_rcu_node(rnp);  /* irqs remain disabled. */
        raw_spin_lock_rcu_node(rnp_p);  /* irqs already disabled. */
        rcu_report_qs_rnp(mask, rsp, rnp_p, gps, flags);
 }
 
 /*
  * Record a quiescent state for the specified CPU to that CPU's rcu_data
- * structure.  This must be either called from the specified CPU, or
- * called when the specified CPU is known to be offline (and when it is
- * also known that no other CPU is concurrently trying to help the offline
- * CPU).  The lastcomp argument is used to make sure we are still in the
- * grace period of interest.  We don't want to end the current grace period
- * based on quiescent states detected in an earlier grace period!
+ * structure.  This must be called from the specified CPU.
  */
 static void
 rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)
@@ -2383,14 +2381,14 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)
                 */
                rdp->cpu_no_qs.b.norm = true;   /* need qs for new gp. */
                rdp->rcu_qs_ctr_snap = __this_cpu_read(rcu_qs_ctr);
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                return;
        }
        mask = rdp->grpmask;
        if ((rnp->qsmask & mask) == 0) {
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        } else {
-               rdp->core_needs_qs = 0;
+               rdp->core_needs_qs = false;
 
                /*
                 * This GP can't end until cpu checks in, so all of our
@@ -2599,35 +2597,14 @@ static void rcu_cleanup_dead_rnp(struct rcu_node *rnp_leaf)
                rnp->qsmaskinit &= ~mask;
                rnp->qsmask &= ~mask;
                if (rnp->qsmaskinit) {
-                       raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
+                       raw_spin_unlock_rcu_node(rnp);
+                       /* irqs remain disabled. */
                        return;
                }
-               raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
+               raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */
        }
 }
 
-/*
- * The CPU is exiting the idle loop into the arch_cpu_idle_dead()
- * function.  We now remove it from the rcu_node tree's ->qsmaskinit
- * bit masks.
- */
-static void rcu_cleanup_dying_idle_cpu(int cpu, struct rcu_state *rsp)
-{
-       unsigned long flags;
-       unsigned long mask;
-       struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
-       struct rcu_node *rnp = rdp->mynode;  /* Outgoing CPU's rdp & rnp. */
-
-       if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
-               return;
-
-       /* Remove outgoing CPU from mask in the leaf rcu_node structure. */
-       mask = rdp->grpmask;
-       raw_spin_lock_irqsave_rcu_node(rnp, flags); /* Enforce GP memory-order guarantee. */
-       rnp->qsmaskinitnext &= ~mask;
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
-}
-
 /*
  * The CPU has been completely removed, and some other CPU is reporting
  * this fact from process context.  Do the remainder of the cleanup,
@@ -2859,7 +2836,7 @@ static void force_qs_rnp(struct rcu_state *rsp,
                        rcu_report_qs_rnp(mask, rsp, rnp, rnp->gpnum, flags);
                } else {
                        /* Nothing to do here, so just drop the lock. */
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                }
        }
 }
@@ -2895,12 +2872,12 @@ static void force_quiescent_state(struct rcu_state *rsp)
        raw_spin_unlock(&rnp_old->fqslock);
        if (READ_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {
                rsp->n_force_qs_lh++;
-               raw_spin_unlock_irqrestore(&rnp_old->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp_old, flags);
                return;  /* Someone beat us to it. */
        }
        WRITE_ONCE(rsp->gp_flags, READ_ONCE(rsp->gp_flags) | RCU_GP_FLAG_FQS);
-       raw_spin_unlock_irqrestore(&rnp_old->lock, flags);
-       rcu_gp_kthread_wake(rsp);
+       raw_spin_unlock_irqrestore_rcu_node(rnp_old, flags);
+       swake_up(&rsp->gp_wq); /* Memory barrier implied by swake_up() path. */
 }
 
 /*
@@ -2925,7 +2902,7 @@ __rcu_process_callbacks(struct rcu_state *rsp)
        if (cpu_needs_another_gp(rsp, rdp)) {
                raw_spin_lock_rcu_node(rcu_get_root(rsp)); /* irqs disabled. */
                needwake = rcu_start_gp(rsp);
-               raw_spin_unlock_irqrestore(&rcu_get_root(rsp)->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rcu_get_root(rsp), flags);
                if (needwake)
                        rcu_gp_kthread_wake(rsp);
        } else {
@@ -3016,7 +2993,7 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
 
                        raw_spin_lock_rcu_node(rnp_root);
                        needwake = rcu_start_gp(rsp);
-                       raw_spin_unlock(&rnp_root->lock);
+                       raw_spin_unlock_rcu_node(rnp_root);
                        if (needwake)
                                rcu_gp_kthread_wake(rsp);
                } else {
@@ -3436,14 +3413,14 @@ static void sync_exp_reset_tree_hotplug(struct rcu_state *rsp)
        rcu_for_each_leaf_node(rsp, rnp) {
                raw_spin_lock_irqsave_rcu_node(rnp, flags);
                if (rnp->expmaskinit == rnp->expmaskinitnext) {
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                        continue;  /* No new CPUs, nothing to do. */
                }
 
                /* Update this node's mask, track old value for propagation. */
                oldmask = rnp->expmaskinit;
                rnp->expmaskinit = rnp->expmaskinitnext;
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 
                /* If was already nonzero, nothing to propagate. */
                if (oldmask)
@@ -3458,7 +3435,7 @@ static void sync_exp_reset_tree_hotplug(struct rcu_state *rsp)
                        if (rnp_up->expmaskinit)
                                done = true;
                        rnp_up->expmaskinit |= mask;
-                       raw_spin_unlock_irqrestore(&rnp_up->lock, flags);
+                       raw_spin_unlock_irqrestore_rcu_node(rnp_up, flags);
                        if (done)
                                break;
                        mask = rnp_up->grpmask;
@@ -3481,7 +3458,7 @@ static void __maybe_unused sync_exp_reset_tree(struct rcu_state *rsp)
                raw_spin_lock_irqsave_rcu_node(rnp, flags);
                WARN_ON_ONCE(rnp->expmask);
                rnp->expmask = rnp->expmaskinit;
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        }
 }
 
@@ -3522,19 +3499,19 @@ static void __rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
                        if (!rnp->expmask)
                                rcu_initiate_boost(rnp, flags);
                        else
-                               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                        break;
                }
                if (rnp->parent == NULL) {
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                        if (wake) {
                                smp_mb(); /* EGP done before wake_up(). */
-                               wake_up(&rsp->expedited_wq);
+                               swake_up(&rsp->expedited_wq);
                        }
                        break;
                }
                mask = rnp->grpmask;
-               raw_spin_unlock(&rnp->lock); /* irqs remain disabled */
+               raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled */
                rnp = rnp->parent;
                raw_spin_lock_rcu_node(rnp); /* irqs already disabled */
                WARN_ON_ONCE(!(rnp->expmask & mask));
@@ -3569,7 +3546,7 @@ static void rcu_report_exp_cpu_mult(struct rcu_state *rsp, struct rcu_node *rnp,
 
        raw_spin_lock_irqsave_rcu_node(rnp, flags);
        if (!(rnp->expmask & mask)) {
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                return;
        }
        rnp->expmask &= ~mask;
@@ -3730,7 +3707,7 @@ static void sync_rcu_exp_select_cpus(struct rcu_state *rsp,
                 */
                if (rcu_preempt_has_tasks(rnp))
                        rnp->exp_tasks = rnp->blkd_tasks.next;
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 
                /* IPI the remaining CPUs for expedited quiescent state. */
                mask = 1;
@@ -3747,7 +3724,7 @@ retry_ipi:
                        raw_spin_lock_irqsave_rcu_node(rnp, flags);
                        if (cpu_online(cpu) &&
                            (rnp->expmask & mask)) {
-                               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                                schedule_timeout_uninterruptible(1);
                                if (cpu_online(cpu) &&
                                    (rnp->expmask & mask))
@@ -3756,7 +3733,7 @@ retry_ipi:
                        }
                        if (!(rnp->expmask & mask))
                                mask_ofl_ipi &= ~mask;
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                }
                /* Report quiescent states for those that went offline. */
                mask_ofl_test |= mask_ofl_ipi;
@@ -3780,7 +3757,7 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp)
        jiffies_start = jiffies;
 
        for (;;) {
-               ret = wait_event_interruptible_timeout(
+               ret = swait_event_timeout(
                                rsp->expedited_wq,
                                sync_rcu_preempt_exp_done(rnp_root),
                                jiffies_stall);
@@ -3788,7 +3765,7 @@ static void synchronize_sched_expedited_wait(struct rcu_state *rsp)
                        return;
                if (ret < 0) {
                        /* Hit a signal, disable CPU stall warnings. */
-                       wait_event(rsp->expedited_wq,
+                       swait_event(rsp->expedited_wq,
                                   sync_rcu_preempt_exp_done(rnp_root));
                        return;
                }
@@ -4163,7 +4140,7 @@ static void rcu_init_new_rnp(struct rcu_node *rnp_leaf)
                        return;
                raw_spin_lock_rcu_node(rnp); /* Interrupts already disabled. */
                rnp->qsmaskinit |= mask;
-               raw_spin_unlock(&rnp->lock); /* Interrupts remain disabled. */
+               raw_spin_unlock_rcu_node(rnp); /* Interrupts remain disabled. */
        }
 }
 
@@ -4187,7 +4164,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
        rdp->rsp = rsp;
        mutex_init(&rdp->exp_funnel_mutex);
        rcu_boot_init_nocb_percpu_data(rdp);
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 }
 
 /*
@@ -4215,7 +4192,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
        rcu_sysidle_init_percpu_data(rdp->dynticks);
        atomic_set(&rdp->dynticks->dynticks,
                   (atomic_read(&rdp->dynticks->dynticks) & ~0x1) + 1);
-       raw_spin_unlock(&rnp->lock);            /* irqs remain disabled. */
+       raw_spin_unlock_rcu_node(rnp);          /* irqs remain disabled. */
 
        /*
         * Add CPU to leaf rcu_node pending-online bitmask.  Any needed
@@ -4236,7 +4213,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
        rdp->rcu_qs_ctr_snap = per_cpu(rcu_qs_ctr, cpu);
        rdp->core_needs_qs = false;
        trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpuonl"));
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 }
 
 static void rcu_prepare_cpu(int cpu)
@@ -4247,6 +4224,46 @@ static void rcu_prepare_cpu(int cpu)
                rcu_init_percpu_data(cpu, rsp);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * The CPU is exiting the idle loop into the arch_cpu_idle_dead()
+ * function.  We now remove it from the rcu_node tree's ->qsmaskinit
+ * bit masks.
+ * The CPU is exiting the idle loop into the arch_cpu_idle_dead()
+ * function.  We now remove it from the rcu_node tree's ->qsmaskinit
+ * bit masks.
+ */
+static void rcu_cleanup_dying_idle_cpu(int cpu, struct rcu_state *rsp)
+{
+       unsigned long flags;
+       unsigned long mask;
+       struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
+       struct rcu_node *rnp = rdp->mynode;  /* Outgoing CPU's rdp & rnp. */
+
+       if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+               return;
+
+       /* Remove outgoing CPU from mask in the leaf rcu_node structure. */
+       mask = rdp->grpmask;
+       raw_spin_lock_irqsave_rcu_node(rnp, flags); /* Enforce GP memory-order guarantee. */
+       rnp->qsmaskinitnext &= ~mask;
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+}
+
+void rcu_report_dead(unsigned int cpu)
+{
+       struct rcu_state *rsp;
+
+       /* QS for any half-done expedited RCU-sched GP. */
+       preempt_disable();
+       rcu_report_exp_rdp(&rcu_sched_state,
+                          this_cpu_ptr(rcu_sched_state.rda), true);
+       preempt_enable();
+       for_each_rcu_flavor(rsp)
+               rcu_cleanup_dying_idle_cpu(cpu, rsp);
+}
+#endif
+
 /*
  * Handle CPU online/offline notification events.
  */
@@ -4278,17 +4295,6 @@ int rcu_cpu_notify(struct notifier_block *self,
                for_each_rcu_flavor(rsp)
                        rcu_cleanup_dying_cpu(rsp);
                break;
-       case CPU_DYING_IDLE:
-               /* QS for any half-done expedited RCU-sched GP. */
-               preempt_disable();
-               rcu_report_exp_rdp(&rcu_sched_state,
-                                  this_cpu_ptr(rcu_sched_state.rda), true);
-               preempt_enable();
-
-               for_each_rcu_flavor(rsp) {
-                       rcu_cleanup_dying_idle_cpu(cpu, rsp);
-               }
-               break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
        case CPU_UP_CANCELED:
@@ -4358,7 +4364,7 @@ static int __init rcu_spawn_gp_kthread(void)
                        sp.sched_priority = kthread_prio;
                        sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
                }
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                wake_up_process(t);
        }
        rcu_spawn_nocb_kthreads();
@@ -4449,8 +4455,8 @@ static void __init rcu_init_one(struct rcu_state *rsp)
                cpustride *= levelspread[i];
                rnp = rsp->level[i];
                for (j = 0; j < levelcnt[i]; j++, rnp++) {
-                       raw_spin_lock_init(&rnp->lock);
-                       lockdep_set_class_and_name(&rnp->lock,
+                       raw_spin_lock_init(&ACCESS_PRIVATE(rnp, lock));
+                       lockdep_set_class_and_name(&ACCESS_PRIVATE(rnp, lock),
                                                   &rcu_node_class[i], buf[i]);
                        raw_spin_lock_init(&rnp->fqslock);
                        lockdep_set_class_and_name(&rnp->fqslock,
@@ -4482,8 +4488,8 @@ static void __init rcu_init_one(struct rcu_state *rsp)
                }
        }
 
-       init_waitqueue_head(&rsp->gp_wq);
-       init_waitqueue_head(&rsp->expedited_wq);
+       init_swait_queue_head(&rsp->gp_wq);
+       init_swait_queue_head(&rsp->expedited_wq);
        rnp = rsp->level[rcu_num_lvls - 1];
        for_each_possible_cpu(i) {
                while (i > rnp->grphi)
index 83360b4f4352786b0129d5ac64046102d73933db..df668c0f9e64991346dd94a872ee67e16e97d735 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/seqlock.h>
+#include <linux/swait.h>
 #include <linux/stop_machine.h>
 
 /*
@@ -149,8 +150,9 @@ struct rcu_dynticks {
  * Definition for node within the RCU grace-period-detection hierarchy.
  */
 struct rcu_node {
-       raw_spinlock_t lock;    /* Root rcu_node's lock protects some */
-                               /*  rcu_state fields as well as following. */
+       raw_spinlock_t __private lock;  /* Root rcu_node's lock protects */
+                                       /*  some rcu_state fields as well as */
+                                       /*  following. */
        unsigned long gpnum;    /* Current grace period for this node. */
                                /*  This will either be equal to or one */
                                /*  behind the root rcu_node's gpnum. */
@@ -243,7 +245,7 @@ struct rcu_node {
                                /* Refused to boost: not sure why, though. */
                                /*  This can happen due to race conditions. */
 #ifdef CONFIG_RCU_NOCB_CPU
-       wait_queue_head_t nocb_gp_wq[2];
+       struct swait_queue_head nocb_gp_wq[2];
                                /* Place for rcu_nocb_kthread() to wait GP. */
 #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
        int need_future_gp[2];
@@ -399,7 +401,7 @@ struct rcu_data {
        atomic_long_t nocb_q_count_lazy; /*  invocation (all stages). */
        struct rcu_head *nocb_follower_head; /* CBs ready to invoke. */
        struct rcu_head **nocb_follower_tail;
-       wait_queue_head_t nocb_wq;      /* For nocb kthreads to sleep on. */
+       struct swait_queue_head nocb_wq; /* For nocb kthreads to sleep on. */
        struct task_struct *nocb_kthread;
        int nocb_defer_wakeup;          /* Defer wakeup of nocb_kthread. */
 
@@ -478,7 +480,7 @@ struct rcu_state {
        unsigned long gpnum;                    /* Current gp number. */
        unsigned long completed;                /* # of last completed gp. */
        struct task_struct *gp_kthread;         /* Task for grace periods. */
-       wait_queue_head_t gp_wq;                /* Where GP task waits. */
+       struct swait_queue_head gp_wq;          /* Where GP task waits. */
        short gp_flags;                         /* Commands for GP task. */
        short gp_state;                         /* GP kthread sleep state. */
 
@@ -506,7 +508,7 @@ struct rcu_state {
        unsigned long expedited_sequence;       /* Take a ticket. */
        atomic_long_t expedited_normal;         /* # fallbacks to normal. */
        atomic_t expedited_need_qs;             /* # CPUs left to check in. */
-       wait_queue_head_t expedited_wq;         /* Wait for check-ins. */
+       struct swait_queue_head expedited_wq;   /* Wait for check-ins. */
        int ncpus_snap;                         /* # CPUs seen last time. */
 
        unsigned long jiffies_force_qs;         /* Time at which to invoke */
@@ -621,7 +623,8 @@ static void zero_cpu_stall_ticks(struct rcu_data *rdp);
 static void increment_cpu_stall_ticks(void);
 static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu);
 static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq);
-static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp);
+static struct swait_queue_head *rcu_nocb_gp_get(struct rcu_node *rnp);
+static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq);
 static void rcu_init_one_nocb(struct rcu_node *rnp);
 static bool __call_rcu_nocb(struct rcu_data *rdp, struct rcu_head *rhp,
                            bool lazy, unsigned long flags);
@@ -680,7 +683,7 @@ static inline void rcu_nocb_q_lengths(struct rcu_data *rdp, long *ql, long *qll)
 #endif /* #else #ifdef CONFIG_PPC */
 
 /*
- * Wrappers for the rcu_node::lock acquire.
+ * Wrappers for the rcu_node::lock acquire and release.
  *
  * Because the rcu_nodes form a tree, the tree traversal locking will observe
  * different lock values, this in turn means that an UNLOCK of one level
@@ -689,29 +692,48 @@ static inline void rcu_nocb_q_lengths(struct rcu_data *rdp, long *ql, long *qll)
  *
  * In order to restore full ordering between tree levels, augment the regular
  * lock acquire functions with smp_mb__after_unlock_lock().
+ *
+ * As ->lock of struct rcu_node is a __private field, therefore one should use
+ * these wrappers rather than directly call raw_spin_{lock,unlock}* on ->lock.
  */
 static inline void raw_spin_lock_rcu_node(struct rcu_node *rnp)
 {
-       raw_spin_lock(&rnp->lock);
+       raw_spin_lock(&ACCESS_PRIVATE(rnp, lock));
        smp_mb__after_unlock_lock();
 }
 
+static inline void raw_spin_unlock_rcu_node(struct rcu_node *rnp)
+{
+       raw_spin_unlock(&ACCESS_PRIVATE(rnp, lock));
+}
+
 static inline void raw_spin_lock_irq_rcu_node(struct rcu_node *rnp)
 {
-       raw_spin_lock_irq(&rnp->lock);
+       raw_spin_lock_irq(&ACCESS_PRIVATE(rnp, lock));
        smp_mb__after_unlock_lock();
 }
 
-#define raw_spin_lock_irqsave_rcu_node(rnp, flags)     \
-do {                                                   \
-       typecheck(unsigned long, flags);                \
-       raw_spin_lock_irqsave(&(rnp)->lock, flags);     \
-       smp_mb__after_unlock_lock();                    \
+static inline void raw_spin_unlock_irq_rcu_node(struct rcu_node *rnp)
+{
+       raw_spin_unlock_irq(&ACCESS_PRIVATE(rnp, lock));
+}
+
+#define raw_spin_lock_irqsave_rcu_node(rnp, flags)                     \
+do {                                                                   \
+       typecheck(unsigned long, flags);                                \
+       raw_spin_lock_irqsave(&ACCESS_PRIVATE(rnp, lock), flags);       \
+       smp_mb__after_unlock_lock();                                    \
+} while (0)
+
+#define raw_spin_unlock_irqrestore_rcu_node(rnp, flags)                        \
+do {                                                                   \
+       typecheck(unsigned long, flags);                                \
+       raw_spin_unlock_irqrestore(&ACCESS_PRIVATE(rnp, lock), flags);  \
 } while (0)
 
 static inline bool raw_spin_trylock_rcu_node(struct rcu_node *rnp)
 {
-       bool locked = raw_spin_trylock(&rnp->lock);
+       bool locked = raw_spin_trylock(&ACCESS_PRIVATE(rnp, lock));
 
        if (locked)
                smp_mb__after_unlock_lock();
index 9467a8b7e756173bc9a94cc5b9828066a9f50e16..efdf7b61ce120d6acccbb725db87e74fed097b91 100644 (file)
@@ -235,7 +235,7 @@ static void rcu_preempt_ctxt_queue(struct rcu_node *rnp, struct rcu_data *rdp)
                rnp->gp_tasks = &t->rcu_node_entry;
        if (!rnp->exp_tasks && (blkd_state & RCU_EXP_BLKD))
                rnp->exp_tasks = &t->rcu_node_entry;
-       raw_spin_unlock(&rnp->lock); /* rrupts remain disabled. */
+       raw_spin_unlock_rcu_node(rnp); /* interrupts remain disabled. */
 
        /*
         * Report the quiescent state for the expedited GP.  This expedited
@@ -489,7 +489,7 @@ void rcu_read_unlock_special(struct task_struct *t)
                                                         !!rnp->gp_tasks);
                        rcu_report_unblock_qs_rnp(rcu_state_p, rnp, flags);
                } else {
-                       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                }
 
                /* Unboost if we were boosted. */
@@ -518,14 +518,14 @@ static void rcu_print_detail_task_stall_rnp(struct rcu_node *rnp)
 
        raw_spin_lock_irqsave_rcu_node(rnp, flags);
        if (!rcu_preempt_blocked_readers_cgp(rnp)) {
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                return;
        }
        t = list_entry(rnp->gp_tasks->prev,
                       struct task_struct, rcu_node_entry);
        list_for_each_entry_continue(t, &rnp->blkd_tasks, rcu_node_entry)
                sched_show_task(t);
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 }
 
 /*
@@ -807,7 +807,6 @@ void exit_rcu(void)
 #else /* #ifdef CONFIG_PREEMPT_RCU */
 
 static struct rcu_state *const rcu_state_p = &rcu_sched_state;
-static struct rcu_data __percpu *const rcu_data_p = &rcu_sched_data;
 
 /*
  * Tell them what RCU they are running.
@@ -991,7 +990,7 @@ static int rcu_boost(struct rcu_node *rnp)
         * might exit their RCU read-side critical sections on their own.
         */
        if (rnp->exp_tasks == NULL && rnp->boost_tasks == NULL) {
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                return 0;
        }
 
@@ -1028,7 +1027,7 @@ static int rcu_boost(struct rcu_node *rnp)
         */
        t = container_of(tb, struct task_struct, rcu_node_entry);
        rt_mutex_init_proxy_locked(&rnp->boost_mtx, t);
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        /* Lock only for side effect: boosts task t's priority. */
        rt_mutex_lock(&rnp->boost_mtx);
        rt_mutex_unlock(&rnp->boost_mtx);  /* Then keep lockdep happy. */
@@ -1088,7 +1087,7 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
 
        if (!rcu_preempt_blocked_readers_cgp(rnp) && rnp->exp_tasks == NULL) {
                rnp->n_balk_exp_gp_tasks++;
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                return;
        }
        if (rnp->exp_tasks != NULL ||
@@ -1098,13 +1097,13 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
             ULONG_CMP_GE(jiffies, rnp->boost_time))) {
                if (rnp->exp_tasks == NULL)
                        rnp->boost_tasks = rnp->gp_tasks;
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                t = rnp->boost_kthread_task;
                if (t)
                        rcu_wake_cond(t, rnp->boost_kthread_status);
        } else {
                rcu_initiate_boost_trace(rnp);
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        }
 }
 
@@ -1172,7 +1171,7 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
                return PTR_ERR(t);
        raw_spin_lock_irqsave_rcu_node(rnp, flags);
        rnp->boost_kthread_task = t;
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        sp.sched_priority = kthread_prio;
        sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
        wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */
@@ -1308,7 +1307,7 @@ static void rcu_prepare_kthreads(int cpu)
 static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
        __releases(rnp->lock)
 {
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 }
 
 static void invoke_rcu_callbacks_kthread(void)
@@ -1559,7 +1558,7 @@ static void rcu_prepare_for_idle(void)
                rnp = rdp->mynode;
                raw_spin_lock_rcu_node(rnp); /* irqs already disabled. */
                needwake = rcu_accelerate_cbs(rsp, rnp, rdp);
-               raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */
+               raw_spin_unlock_rcu_node(rnp); /* irqs remain disabled. */
                if (needwake)
                        rcu_gp_kthread_wake(rsp);
        }
@@ -1811,9 +1810,9 @@ early_param("rcu_nocb_poll", parse_rcu_nocb_poll);
  * Wake up any no-CBs CPUs' kthreads that were waiting on the just-ended
  * grace period.
  */
-static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
+static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq)
 {
-       wake_up_all(&rnp->nocb_gp_wq[rnp->completed & 0x1]);
+       swake_up_all(sq);
 }
 
 /*
@@ -1829,10 +1828,15 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq)
        rnp->need_future_gp[(rnp->completed + 1) & 0x1] += nrq;
 }
 
+static struct swait_queue_head *rcu_nocb_gp_get(struct rcu_node *rnp)
+{
+       return &rnp->nocb_gp_wq[rnp->completed & 0x1];
+}
+
 static void rcu_init_one_nocb(struct rcu_node *rnp)
 {
-       init_waitqueue_head(&rnp->nocb_gp_wq[0]);
-       init_waitqueue_head(&rnp->nocb_gp_wq[1]);
+       init_swait_queue_head(&rnp->nocb_gp_wq[0]);
+       init_swait_queue_head(&rnp->nocb_gp_wq[1]);
 }
 
 #ifndef CONFIG_RCU_NOCB_CPU_ALL
@@ -1857,7 +1861,7 @@ static void wake_nocb_leader(struct rcu_data *rdp, bool force)
        if (READ_ONCE(rdp_leader->nocb_leader_sleep) || force) {
                /* Prior smp_mb__after_atomic() orders against prior enqueue. */
                WRITE_ONCE(rdp_leader->nocb_leader_sleep, false);
-               wake_up(&rdp_leader->nocb_wq);
+               swake_up(&rdp_leader->nocb_wq);
        }
 }
 
@@ -2059,7 +2063,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp)
 
        raw_spin_lock_irqsave_rcu_node(rnp, flags);
        needwake = rcu_start_future_gp(rnp, rdp, &c);
-       raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        if (needwake)
                rcu_gp_kthread_wake(rdp->rsp);
 
@@ -2069,7 +2073,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp)
         */
        trace_rcu_future_gp(rnp, rdp, c, TPS("StartWait"));
        for (;;) {
-               wait_event_interruptible(
+               swait_event_interruptible(
                        rnp->nocb_gp_wq[c & 0x1],
                        (d = ULONG_CMP_GE(READ_ONCE(rnp->completed), c)));
                if (likely(d))
@@ -2097,7 +2101,7 @@ wait_again:
        /* Wait for callbacks to appear. */
        if (!rcu_nocb_poll) {
                trace_rcu_nocb_wake(my_rdp->rsp->name, my_rdp->cpu, "Sleep");
-               wait_event_interruptible(my_rdp->nocb_wq,
+               swait_event_interruptible(my_rdp->nocb_wq,
                                !READ_ONCE(my_rdp->nocb_leader_sleep));
                /* Memory barrier handled by smp_mb() calls below and repoll. */
        } else if (firsttime) {
@@ -2172,7 +2176,7 @@ wait_again:
                         * List was empty, wake up the follower.
                         * Memory barriers supplied by atomic_long_add().
                         */
-                       wake_up(&rdp->nocb_wq);
+                       swake_up(&rdp->nocb_wq);
                }
        }
 
@@ -2193,7 +2197,7 @@ static void nocb_follower_wait(struct rcu_data *rdp)
                if (!rcu_nocb_poll) {
                        trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
                                            "FollowerSleep");
-                       wait_event_interruptible(rdp->nocb_wq,
+                       swait_event_interruptible(rdp->nocb_wq,
                                                 READ_ONCE(rdp->nocb_follower_head));
                } else if (firsttime) {
                        /* Don't drown trace log with "Poll"! */
@@ -2352,7 +2356,7 @@ void __init rcu_init_nohz(void)
 static void __init rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp)
 {
        rdp->nocb_tail = &rdp->nocb_head;
-       init_waitqueue_head(&rdp->nocb_wq);
+       init_swait_queue_head(&rdp->nocb_wq);
        rdp->nocb_follower_tail = &rdp->nocb_follower_head;
 }
 
@@ -2502,7 +2506,7 @@ static bool rcu_nocb_cpu_needs_barrier(struct rcu_state *rsp, int cpu)
        return false;
 }
 
-static void rcu_nocb_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
+static void rcu_nocb_gp_cleanup(struct swait_queue_head *sq)
 {
 }
 
@@ -2510,6 +2514,11 @@ static void rcu_nocb_gp_set(struct rcu_node *rnp, int nrq)
 {
 }
 
+static struct swait_queue_head *rcu_nocb_gp_get(struct rcu_node *rnp)
+{
+       return NULL;
+}
+
 static void rcu_init_one_nocb(struct rcu_node *rnp)
 {
 }
index 76b94e19430b21b8f4615b70dbb89282445ca149..ca828b41c938b24e5b11b33e421ea4b4e2366f1f 100644 (file)
@@ -128,6 +128,7 @@ bool rcu_gp_is_normal(void)
 {
        return READ_ONCE(rcu_normal);
 }
+EXPORT_SYMBOL_GPL(rcu_gp_is_normal);
 
 static atomic_t rcu_expedited_nesting =
        ATOMIC_INIT(IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT) ? 1 : 0);
index 3669d1bfc4254213e0e42dacab374624d74cdd5c..4d466052426b3e993e7e3c3550e948308e377c51 100644 (file)
@@ -333,13 +333,13 @@ int release_resource(struct resource *old)
 EXPORT_SYMBOL(release_resource);
 
 /*
- * Finds the lowest iomem reosurce exists with-in [res->start.res->end)
- * the caller must specify res->start, res->end, res->flags and "name".
- * If found, returns 0, res is overwritten, if not found, returns -1.
- * This walks through whole tree and not just first level children
- * until and unless first_level_children_only is true.
+ * Finds the lowest iomem resource existing within [res->start.res->end).
+ * The caller must specify res->start, res->end, res->flags, and optionally
+ * desc.  If found, returns 0, res is overwritten, if not found, returns -1.
+ * This function walks the whole tree and not just first level children until
+ * and unless first_level_children_only is true.
  */
-static int find_next_iomem_res(struct resource *res, char *name,
+static int find_next_iomem_res(struct resource *res, unsigned long desc,
                               bool first_level_children_only)
 {
        resource_size_t start, end;
@@ -358,9 +358,9 @@ static int find_next_iomem_res(struct resource *res, char *name,
        read_lock(&resource_lock);
 
        for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) {
-               if (p->flags != res->flags)
+               if ((p->flags & res->flags) != res->flags)
                        continue;
-               if (name && strcmp(p->name, name))
+               if ((desc != IORES_DESC_NONE) && (desc != p->desc))
                        continue;
                if (p->start > end) {
                        p = NULL;
@@ -385,15 +385,18 @@ static int find_next_iomem_res(struct resource *res, char *name,
  * Walks through iomem resources and calls func() with matching resource
  * ranges. This walks through whole tree and not just first level children.
  * All the memory ranges which overlap start,end and also match flags and
- * name are valid candidates.
+ * desc are valid candidates.
  *
- * @name: name of resource
- * @flags: resource flags
+ * @desc: I/O resource descriptor. Use IORES_DESC_NONE to skip @desc check.
+ * @flags: I/O resource flags
  * @start: start addr
  * @end: end addr
+ *
+ * NOTE: For a new descriptor search, define a new IORES_DESC in
+ * <linux/ioport.h> and set it in 'desc' of a target resource entry.
  */
-int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end,
-               void *arg, int (*func)(u64, u64, void *))
+int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start,
+               u64 end, void *arg, int (*func)(u64, u64, void *))
 {
        struct resource res;
        u64 orig_end;
@@ -403,23 +406,27 @@ int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end,
        res.end = end;
        res.flags = flags;
        orig_end = res.end;
+
        while ((res.start < res.end) &&
-               (!find_next_iomem_res(&res, name, false))) {
+               (!find_next_iomem_res(&res, desc, false))) {
+
                ret = (*func)(res.start, res.end, arg);
                if (ret)
                        break;
+
                res.start = res.end + 1;
                res.end = orig_end;
        }
+
        return ret;
 }
 
 /*
- * This function calls callback against all memory range of "System RAM"
- * which are marked as IORESOURCE_MEM and IORESOUCE_BUSY.
- * Now, this function is only for "System RAM". This function deals with
- * full ranges and not pfn. If resources are not pfn aligned, dealing
- * with pfn can truncate ranges.
+ * This function calls the @func callback against all memory ranges of type
+ * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
+ * Now, this function is only for System RAM, it deals with full ranges and
+ * not PFNs. If resources are not PFN-aligned, dealing with PFNs can truncate
+ * ranges.
  */
 int walk_system_ram_res(u64 start, u64 end, void *arg,
                                int (*func)(u64, u64, void *))
@@ -430,10 +437,10 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
 
        res.start = start;
        res.end = end;
-       res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
        orig_end = res.end;
        while ((res.start < res.end) &&
-               (!find_next_iomem_res(&res, "System RAM", true))) {
+               (!find_next_iomem_res(&res, IORES_DESC_NONE, true))) {
                ret = (*func)(res.start, res.end, arg);
                if (ret)
                        break;
@@ -446,9 +453,9 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
 #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY)
 
 /*
- * This function calls callback against all memory range of "System RAM"
- * which are marked as IORESOURCE_MEM and IORESOUCE_BUSY.
- * Now, this function is only for "System RAM".
+ * This function calls the @func callback against all memory ranges of type
+ * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
+ * It is to be used only for System RAM.
  */
 int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
                void *arg, int (*func)(unsigned long, unsigned long, void *))
@@ -460,10 +467,10 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
 
        res.start = (u64) start_pfn << PAGE_SHIFT;
        res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
-       res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
        orig_end = res.end;
        while ((res.start < res.end) &&
-               (find_next_iomem_res(&res, "System RAM", true) >= 0)) {
+               (find_next_iomem_res(&res, IORES_DESC_NONE, true) >= 0)) {
                pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT;
                end_pfn = (res.end + 1) >> PAGE_SHIFT;
                if (end_pfn > pfn)
@@ -484,7 +491,7 @@ static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg)
 }
 /*
  * This generic page_is_ram() returns true if specified address is
- * registered as "System RAM" in iomem_resource list.
+ * registered as System RAM in iomem_resource list.
  */
 int __weak page_is_ram(unsigned long pfn)
 {
@@ -496,30 +503,34 @@ EXPORT_SYMBOL_GPL(page_is_ram);
  * region_intersects() - determine intersection of region with known resources
  * @start: region start address
  * @size: size of region
- * @name: name of resource (in iomem_resource)
+ * @flags: flags of resource (in iomem_resource)
+ * @desc: descriptor of resource (in iomem_resource) or IORES_DESC_NONE
  *
  * Check if the specified region partially overlaps or fully eclipses a
- * resource identified by @name.  Return REGION_DISJOINT if the region
- * does not overlap @name, return REGION_MIXED if the region overlaps
- * @type and another resource, and return REGION_INTERSECTS if the
- * region overlaps @type and no other defined resource. Note, that
- * REGION_INTERSECTS is also returned in the case when the specified
- * region overlaps RAM and undefined memory holes.
+ * resource identified by @flags and @desc (optional with IORES_DESC_NONE).
+ * Return REGION_DISJOINT if the region does not overlap @flags/@desc,
+ * return REGION_MIXED if the region overlaps @flags/@desc and another
+ * resource, and return REGION_INTERSECTS if the region overlaps @flags/@desc
+ * and no other defined resource. Note that REGION_INTERSECTS is also
+ * returned in the case when the specified region overlaps RAM and undefined
+ * memory holes.
  *
  * region_intersect() is used by memory remapping functions to ensure
  * the user is not remapping RAM and is a vast speed up over walking
  * through the resource table page by page.
  */
-int region_intersects(resource_size_t start, size_t size, const char *name)
+int region_intersects(resource_size_t start, size_t size, unsigned long flags,
+                     unsigned long desc)
 {
-       unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY;
        resource_size_t end = start + size - 1;
        int type = 0; int other = 0;
        struct resource *p;
 
        read_lock(&resource_lock);
        for (p = iomem_resource.child; p ; p = p->sibling) {
-               bool is_type = strcmp(p->name, name) == 0 && p->flags == flags;
+               bool is_type = (((p->flags & flags) == flags) &&
+                               ((desc == IORES_DESC_NONE) ||
+                                (desc == p->desc)));
 
                if (start >= p->start && start <= p->end)
                        is_type ? type++ : other++;
@@ -538,6 +549,7 @@ int region_intersects(resource_size_t start, size_t size, const char *name)
 
        return REGION_DISJOINT;
 }
+EXPORT_SYMBOL_GPL(region_intersects);
 
 void __weak arch_remove_reservations(struct resource *avail)
 {
@@ -948,6 +960,7 @@ static void __init __reserve_region_with_split(struct resource *root,
        res->start = start;
        res->end = end;
        res->flags = IORESOURCE_BUSY;
+       res->desc = IORES_DESC_NONE;
 
        while (1) {
 
@@ -982,6 +995,7 @@ static void __init __reserve_region_with_split(struct resource *root,
                                next_res->start = conflict->end + 1;
                                next_res->end = end;
                                next_res->flags = IORESOURCE_BUSY;
+                               next_res->desc = IORES_DESC_NONE;
                        }
                } else {
                        res->start = conflict->end + 1;
@@ -1071,8 +1085,9 @@ struct resource * __request_region(struct resource *parent,
        res->name = name;
        res->start = start;
        res->end = start + n - 1;
-       res->flags = resource_type(parent);
+       res->flags = resource_type(parent) | resource_ext_type(parent);
        res->flags |= IORESOURCE_BUSY | flags;
+       res->desc = IORES_DESC_NONE;
 
        write_lock(&resource_lock);
 
@@ -1238,6 +1253,7 @@ int release_mem_region_adjustable(struct resource *parent,
                        new_res->start = end + 1;
                        new_res->end = res->end;
                        new_res->flags = res->flags;
+                       new_res->desc = res->desc;
                        new_res->parent = res->parent;
                        new_res->sibling = res->sibling;
                        new_res->child = NULL;
@@ -1413,6 +1429,7 @@ static int __init reserve_setup(char *str)
                        res->start = io_start;
                        res->end = io_start + io_num - 1;
                        res->flags = IORESOURCE_BUSY;
+                       res->desc = IORES_DESC_NONE;
                        res->child = NULL;
                        if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)
                                reserved = x+1;
index 67687973ce80d63d3f52698fb4b738b76964b896..302d6ebd64f7943be9189b4e6fa55fba56e5d403 100644 (file)
@@ -13,9 +13,10 @@ endif
 
 obj-y += core.o loadavg.o clock.o cputime.o
 obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o
-obj-y += wait.o completion.o idle.o
+obj-y += wait.o swait.o completion.o idle.o
 obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o
 obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
 obj-$(CONFIG_SCHEDSTATS) += stats.o
 obj-$(CONFIG_SCHED_DEBUG) += debug.o
 obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o
+obj-$(CONFIG_CPU_FREQ) += cpufreq.o
index bc54e84675da0d50bd9a60a82f2da5df8590b080..fedb967a98419c14348e8d79becdcb7abf62bfa2 100644 (file)
@@ -61,6 +61,7 @@
 #include <linux/static_key.h>
 #include <linux/workqueue.h>
 #include <linux/compiler.h>
+#include <linux/tick.h>
 
 /*
  * Scheduler clock - returns current time in nanosec units.
@@ -89,6 +90,8 @@ static void __set_sched_clock_stable(void)
 {
        if (!sched_clock_stable())
                static_key_slow_inc(&__sched_clock_stable);
+
+       tick_dep_clear(TICK_DEP_BIT_CLOCK_UNSTABLE);
 }
 
 void set_sched_clock_stable(void)
@@ -108,6 +111,8 @@ static void __clear_sched_clock_stable(struct work_struct *work)
        /* XXX worry about clock continuity */
        if (sched_clock_stable())
                static_key_slow_dec(&__sched_clock_stable);
+
+       tick_dep_set(TICK_DEP_BIT_CLOCK_UNSTABLE);
 }
 
 static DECLARE_WORK(sched_clock_work, __clear_sched_clock_stable);
index 9503d590e5ef5b81537947b9925ecfe689f72a91..ea8f49ae00626771a6497f50e5670b7f129f8a8c 100644 (file)
@@ -26,6 +26,7 @@
  *              Thomas Gleixner, Mike Kravetz
  */
 
+#include <linux/kasan.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/nmi.h>
 #include <linux/pagemap.h>
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
-#include <linux/debugfs.h>
 #include <linux/ctype.h>
 #include <linux/ftrace.h>
 #include <linux/slab.h>
 #include <linux/init_task.h>
-#include <linux/binfmts.h>
 #include <linux/context_tracking.h>
 #include <linux/compiler.h>
 
@@ -124,138 +123,6 @@ const_debug unsigned int sysctl_sched_features =
 
 #undef SCHED_FEAT
 
-#ifdef CONFIG_SCHED_DEBUG
-#define SCHED_FEAT(name, enabled)      \
-       #name ,
-
-static const char * const sched_feat_names[] = {
-#include "features.h"
-};
-
-#undef SCHED_FEAT
-
-static int sched_feat_show(struct seq_file *m, void *v)
-{
-       int i;
-
-       for (i = 0; i < __SCHED_FEAT_NR; i++) {
-               if (!(sysctl_sched_features & (1UL << i)))
-                       seq_puts(m, "NO_");
-               seq_printf(m, "%s ", sched_feat_names[i]);
-       }
-       seq_puts(m, "\n");
-
-       return 0;
-}
-
-#ifdef HAVE_JUMP_LABEL
-
-#define jump_label_key__true  STATIC_KEY_INIT_TRUE
-#define jump_label_key__false STATIC_KEY_INIT_FALSE
-
-#define SCHED_FEAT(name, enabled)      \
-       jump_label_key__##enabled ,
-
-struct static_key sched_feat_keys[__SCHED_FEAT_NR] = {
-#include "features.h"
-};
-
-#undef SCHED_FEAT
-
-static void sched_feat_disable(int i)
-{
-       static_key_disable(&sched_feat_keys[i]);
-}
-
-static void sched_feat_enable(int i)
-{
-       static_key_enable(&sched_feat_keys[i]);
-}
-#else
-static void sched_feat_disable(int i) { };
-static void sched_feat_enable(int i) { };
-#endif /* HAVE_JUMP_LABEL */
-
-static int sched_feat_set(char *cmp)
-{
-       int i;
-       int neg = 0;
-
-       if (strncmp(cmp, "NO_", 3) == 0) {
-               neg = 1;
-               cmp += 3;
-       }
-
-       for (i = 0; i < __SCHED_FEAT_NR; i++) {
-               if (strcmp(cmp, sched_feat_names[i]) == 0) {
-                       if (neg) {
-                               sysctl_sched_features &= ~(1UL << i);
-                               sched_feat_disable(i);
-                       } else {
-                               sysctl_sched_features |= (1UL << i);
-                               sched_feat_enable(i);
-                       }
-                       break;
-               }
-       }
-
-       return i;
-}
-
-static ssize_t
-sched_feat_write(struct file *filp, const char __user *ubuf,
-               size_t cnt, loff_t *ppos)
-{
-       char buf[64];
-       char *cmp;
-       int i;
-       struct inode *inode;
-
-       if (cnt > 63)
-               cnt = 63;
-
-       if (copy_from_user(&buf, ubuf, cnt))
-               return -EFAULT;
-
-       buf[cnt] = 0;
-       cmp = strstrip(buf);
-
-       /* Ensure the static_key remains in a consistent state */
-       inode = file_inode(filp);
-       inode_lock(inode);
-       i = sched_feat_set(cmp);
-       inode_unlock(inode);
-       if (i == __SCHED_FEAT_NR)
-               return -EINVAL;
-
-       *ppos += cnt;
-
-       return cnt;
-}
-
-static int sched_feat_open(struct inode *inode, struct file *filp)
-{
-       return single_open(filp, sched_feat_show, NULL);
-}
-
-static const struct file_operations sched_feat_fops = {
-       .open           = sched_feat_open,
-       .write          = sched_feat_write,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static __init int sched_init_debug(void)
-{
-       debugfs_create_file("sched_features", 0644, NULL, NULL,
-                       &sched_feat_fops);
-
-       return 0;
-}
-late_initcall(sched_init_debug);
-#endif /* CONFIG_SCHED_DEBUG */
-
 /*
  * Number of tasks to iterate in a single balance run.
  * Limited because this is done with IRQs disabled.
@@ -453,20 +320,6 @@ static inline void init_hrtick(void)
 }
 #endif /* CONFIG_SCHED_HRTICK */
 
-/*
- * cmpxchg based fetch_or, macro so it works for different integer types
- */
-#define fetch_or(ptr, val)                                             \
-({     typeof(*(ptr)) __old, __val = *(ptr);                           \
-       for (;;) {                                                      \
-               __old = cmpxchg((ptr), __val, __val | (val));           \
-               if (__old == __val)                                     \
-                       break;                                          \
-               __val = __old;                                          \
-       }                                                               \
-       __old;                                                          \
-})
-
 #if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
 /*
  * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG,
@@ -715,31 +568,36 @@ static inline bool got_nohz_idle_kick(void)
 #endif /* CONFIG_NO_HZ_COMMON */
 
 #ifdef CONFIG_NO_HZ_FULL
-bool sched_can_stop_tick(void)
+bool sched_can_stop_tick(struct rq *rq)
 {
+       int fifo_nr_running;
+
+       /* Deadline tasks, even if single, need the tick */
+       if (rq->dl.dl_nr_running)
+               return false;
+
        /*
-        * FIFO realtime policy runs the highest priority task. Other runnable
-        * tasks are of a lower priority. The scheduler tick does nothing.
+        * FIFO realtime policy runs the highest priority task (after DEADLINE).
+        * Other runnable tasks are of a lower priority. The scheduler tick
+        * isn't needed.
         */
-       if (current->policy == SCHED_FIFO)
+       fifo_nr_running = rq->rt.rt_nr_running - rq->rt.rr_nr_running;
+       if (fifo_nr_running)
                return true;
 
        /*
         * Round-robin realtime tasks time slice with other tasks at the same
-        * realtime priority. Is this task the only one at this priority?
+        * realtime priority.
         */
-       if (current->policy == SCHED_RR) {
-               struct sched_rt_entity *rt_se = &current->rt;
-
-               return list_is_singular(&rt_se->run_list);
+       if (rq->rt.rr_nr_running) {
+               if (rq->rt.rr_nr_running == 1)
+                       return true;
+               else
+                       return false;
        }
 
-       /*
-        * More than one running task need preemption.
-        * nr_running update is assumed to be visible
-        * after IPI is sent from wakers.
-        */
-       if (this_rq()->nr_running > 1)
+       /* Normal multitasking need periodic preemption checks */
+       if (rq->cfs.nr_running > 1)
                return false;
 
        return true;
@@ -2093,7 +1951,8 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
 
        ttwu_queue(p, cpu);
 stat:
-       ttwu_stat(p, cpu, wake_flags);
+       if (schedstat_enabled())
+               ttwu_stat(p, cpu, wake_flags);
 out:
        raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
@@ -2141,7 +2000,8 @@ static void try_to_wake_up_local(struct task_struct *p)
                ttwu_activate(rq, p, ENQUEUE_WAKEUP);
 
        ttwu_do_wakeup(rq, p, 0);
-       ttwu_stat(p, smp_processor_id(), 0);
+       if (schedstat_enabled())
+               ttwu_stat(p, smp_processor_id(), 0);
 out:
        raw_spin_unlock(&p->pi_lock);
 }
@@ -2183,7 +2043,6 @@ void __dl_clear_params(struct task_struct *p)
        dl_se->dl_bw = 0;
 
        dl_se->dl_throttled = 0;
-       dl_se->dl_new = 1;
        dl_se->dl_yielded = 0;
 }
 
@@ -2210,6 +2069,7 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
 #endif
 
 #ifdef CONFIG_SCHEDSTATS
+       /* Even if schedstat is disabled, there should not be garbage */
        memset(&p->se.statistics, 0, sizeof(p->se.statistics));
 #endif
 
@@ -2218,6 +2078,10 @@ static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
        __dl_clear_params(p);
 
        INIT_LIST_HEAD(&p->rt.run_list);
+       p->rt.timeout           = 0;
+       p->rt.time_slice        = sched_rr_timeslice;
+       p->rt.on_rq             = 0;
+       p->rt.on_list           = 0;
 
 #ifdef CONFIG_PREEMPT_NOTIFIERS
        INIT_HLIST_HEAD(&p->preempt_notifiers);
@@ -2281,6 +2145,69 @@ int sysctl_numa_balancing(struct ctl_table *table, int write,
 #endif
 #endif
 
+DEFINE_STATIC_KEY_FALSE(sched_schedstats);
+
+#ifdef CONFIG_SCHEDSTATS
+static void set_schedstats(bool enabled)
+{
+       if (enabled)
+               static_branch_enable(&sched_schedstats);
+       else
+               static_branch_disable(&sched_schedstats);
+}
+
+void force_schedstat_enabled(void)
+{
+       if (!schedstat_enabled()) {
+               pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n");
+               static_branch_enable(&sched_schedstats);
+       }
+}
+
+static int __init setup_schedstats(char *str)
+{
+       int ret = 0;
+       if (!str)
+               goto out;
+
+       if (!strcmp(str, "enable")) {
+               set_schedstats(true);
+               ret = 1;
+       } else if (!strcmp(str, "disable")) {
+               set_schedstats(false);
+               ret = 1;
+       }
+out:
+       if (!ret)
+               pr_warn("Unable to parse schedstats=\n");
+
+       return ret;
+}
+__setup("schedstats=", setup_schedstats);
+
+#ifdef CONFIG_PROC_SYSCTL
+int sysctl_schedstats(struct ctl_table *table, int write,
+                        void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       struct ctl_table t;
+       int err;
+       int state = static_branch_likely(&sched_schedstats);
+
+       if (write && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       t = *table;
+       t.data = &state;
+       err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
+       if (err < 0)
+               return err;
+       if (write)
+               set_schedstats(state);
+       return err;
+}
+#endif
+#endif
+
 /*
  * fork()/clone()-time setup:
  */
@@ -3010,16 +2937,6 @@ u64 scheduler_tick_max_deferment(void)
 }
 #endif
 
-notrace unsigned long get_parent_ip(unsigned long addr)
-{
-       if (in_lock_functions(addr)) {
-               addr = CALLER_ADDR2;
-               if (in_lock_functions(addr))
-                       addr = CALLER_ADDR3;
-       }
-       return addr;
-}
-
 #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
                                defined(CONFIG_PREEMPT_TRACER))
 
@@ -3041,7 +2958,7 @@ void preempt_count_add(int val)
                                PREEMPT_MASK - 10);
 #endif
        if (preempt_count() == val) {
-               unsigned long ip = get_parent_ip(CALLER_ADDR1);
+               unsigned long ip = get_lock_parent_ip();
 #ifdef CONFIG_DEBUG_PREEMPT
                current->preempt_disable_ip = ip;
 #endif
@@ -3068,7 +2985,7 @@ void preempt_count_sub(int val)
 #endif
 
        if (preempt_count() == val)
-               trace_preempt_on(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
+               trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
        __preempt_count_sub(val);
 }
 EXPORT_SYMBOL(preempt_count_sub);
@@ -3280,7 +3197,6 @@ static void __sched notrace __schedule(bool preempt)
 
                trace_sched_switch(preempt, prev, next);
                rq = context_switch(rq, prev, next); /* unlocks the rq */
-               cpu = cpu_of(rq);
        } else {
                lockdep_unpin_lock(&rq->lock);
                raw_spin_unlock_irq(&rq->lock);
@@ -3466,7 +3382,7 @@ EXPORT_SYMBOL(default_wake_function);
  */
 void rt_mutex_setprio(struct task_struct *p, int prio)
 {
-       int oldprio, queued, running, enqueue_flag = ENQUEUE_RESTORE;
+       int oldprio, queued, running, queue_flag = DEQUEUE_SAVE | DEQUEUE_MOVE;
        struct rq *rq;
        const struct sched_class *prev_class;
 
@@ -3494,11 +3410,15 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
 
        trace_sched_pi_setprio(p, prio);
        oldprio = p->prio;
+
+       if (oldprio == prio)
+               queue_flag &= ~DEQUEUE_MOVE;
+
        prev_class = p->sched_class;
        queued = task_on_rq_queued(p);
        running = task_current(rq, p);
        if (queued)
-               dequeue_task(rq, p, DEQUEUE_SAVE);
+               dequeue_task(rq, p, queue_flag);
        if (running)
                put_prev_task(rq, p);
 
@@ -3516,7 +3436,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
                if (!dl_prio(p->normal_prio) ||
                    (pi_task && dl_entity_preempt(&pi_task->dl, &p->dl))) {
                        p->dl.dl_boosted = 1;
-                       enqueue_flag |= ENQUEUE_REPLENISH;
+                       queue_flag |= ENQUEUE_REPLENISH;
                } else
                        p->dl.dl_boosted = 0;
                p->sched_class = &dl_sched_class;
@@ -3524,7 +3444,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
                if (dl_prio(oldprio))
                        p->dl.dl_boosted = 0;
                if (oldprio < prio)
-                       enqueue_flag |= ENQUEUE_HEAD;
+                       queue_flag |= ENQUEUE_HEAD;
                p->sched_class = &rt_sched_class;
        } else {
                if (dl_prio(oldprio))
@@ -3539,7 +3459,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
        if (running)
                p->sched_class->set_curr_task(rq);
        if (queued)
-               enqueue_task(rq, p, enqueue_flag);
+               enqueue_task(rq, p, queue_flag);
 
        check_class_changed(rq, p, prev_class, oldprio);
 out_unlock:
@@ -3895,6 +3815,7 @@ static int __sched_setscheduler(struct task_struct *p,
        const struct sched_class *prev_class;
        struct rq *rq;
        int reset_on_fork;
+       int queue_flags = DEQUEUE_SAVE | DEQUEUE_MOVE;
 
        /* may grab non-irq protected spin_locks */
        BUG_ON(in_interrupt());
@@ -4077,17 +3998,14 @@ change:
                 * itself.
                 */
                new_effective_prio = rt_mutex_get_effective_prio(p, newprio);
-               if (new_effective_prio == oldprio) {
-                       __setscheduler_params(p, attr);
-                       task_rq_unlock(rq, p, &flags);
-                       return 0;
-               }
+               if (new_effective_prio == oldprio)
+                       queue_flags &= ~DEQUEUE_MOVE;
        }
 
        queued = task_on_rq_queued(p);
        running = task_current(rq, p);
        if (queued)
-               dequeue_task(rq, p, DEQUEUE_SAVE);
+               dequeue_task(rq, p, queue_flags);
        if (running)
                put_prev_task(rq, p);
 
@@ -4097,15 +4015,14 @@ change:
        if (running)
                p->sched_class->set_curr_task(rq);
        if (queued) {
-               int enqueue_flags = ENQUEUE_RESTORE;
                /*
                 * We enqueue to tail when the priority of a task is
                 * increased (user space view).
                 */
-               if (oldprio <= p->prio)
-                       enqueue_flags |= ENQUEUE_HEAD;
+               if (oldprio < p->prio)
+                       queue_flags |= ENQUEUE_HEAD;
 
-               enqueue_task(rq, p, enqueue_flags);
+               enqueue_task(rq, p, queue_flags);
        }
 
        check_class_changed(rq, p, prev_class, oldprio);
@@ -5096,6 +5013,8 @@ void init_idle(struct task_struct *idle, int cpu)
        idle->state = TASK_RUNNING;
        idle->se.exec_start = sched_clock();
 
+       kasan_unpoison_task_stack(idle);
+
 #ifdef CONFIG_SMP
        /*
         * Its possible that init_idle() gets called multiple times on a task,
@@ -5405,183 +5324,6 @@ static void migrate_tasks(struct rq *dead_rq)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL)
-
-static struct ctl_table sd_ctl_dir[] = {
-       {
-               .procname       = "sched_domain",
-               .mode           = 0555,
-       },
-       {}
-};
-
-static struct ctl_table sd_ctl_root[] = {
-       {
-               .procname       = "kernel",
-               .mode           = 0555,
-               .child          = sd_ctl_dir,
-       },
-       {}
-};
-
-static struct ctl_table *sd_alloc_ctl_entry(int n)
-{
-       struct ctl_table *entry =
-               kcalloc(n, sizeof(struct ctl_table), GFP_KERNEL);
-
-       return entry;
-}
-
-static void sd_free_ctl_entry(struct ctl_table **tablep)
-{
-       struct ctl_table *entry;
-
-       /*
-        * In the intermediate directories, both the child directory and
-        * procname are dynamically allocated and could fail but the mode
-        * will always be set. In the lowest directory the names are
-        * static strings and all have proc handlers.
-        */
-       for (entry = *tablep; entry->mode; entry++) {
-               if (entry->child)
-                       sd_free_ctl_entry(&entry->child);
-               if (entry->proc_handler == NULL)
-                       kfree(entry->procname);
-       }
-
-       kfree(*tablep);
-       *tablep = NULL;
-}
-
-static int min_load_idx = 0;
-static int max_load_idx = CPU_LOAD_IDX_MAX-1;
-
-static void
-set_table_entry(struct ctl_table *entry,
-               const char *procname, void *data, int maxlen,
-               umode_t mode, proc_handler *proc_handler,
-               bool load_idx)
-{
-       entry->procname = procname;
-       entry->data = data;
-       entry->maxlen = maxlen;
-       entry->mode = mode;
-       entry->proc_handler = proc_handler;
-
-       if (load_idx) {
-               entry->extra1 = &min_load_idx;
-               entry->extra2 = &max_load_idx;
-       }
-}
-
-static struct ctl_table *
-sd_alloc_ctl_domain_table(struct sched_domain *sd)
-{
-       struct ctl_table *table = sd_alloc_ctl_entry(14);
-
-       if (table == NULL)
-               return NULL;
-
-       set_table_entry(&table[0], "min_interval", &sd->min_interval,
-               sizeof(long), 0644, proc_doulongvec_minmax, false);
-       set_table_entry(&table[1], "max_interval", &sd->max_interval,
-               sizeof(long), 0644, proc_doulongvec_minmax, false);
-       set_table_entry(&table[2], "busy_idx", &sd->busy_idx,
-               sizeof(int), 0644, proc_dointvec_minmax, true);
-       set_table_entry(&table[3], "idle_idx", &sd->idle_idx,
-               sizeof(int), 0644, proc_dointvec_minmax, true);
-       set_table_entry(&table[4], "newidle_idx", &sd->newidle_idx,
-               sizeof(int), 0644, proc_dointvec_minmax, true);
-       set_table_entry(&table[5], "wake_idx", &sd->wake_idx,
-               sizeof(int), 0644, proc_dointvec_minmax, true);
-       set_table_entry(&table[6], "forkexec_idx", &sd->forkexec_idx,
-               sizeof(int), 0644, proc_dointvec_minmax, true);
-       set_table_entry(&table[7], "busy_factor", &sd->busy_factor,
-               sizeof(int), 0644, proc_dointvec_minmax, false);
-       set_table_entry(&table[8], "imbalance_pct", &sd->imbalance_pct,
-               sizeof(int), 0644, proc_dointvec_minmax, false);
-       set_table_entry(&table[9], "cache_nice_tries",
-               &sd->cache_nice_tries,
-               sizeof(int), 0644, proc_dointvec_minmax, false);
-       set_table_entry(&table[10], "flags", &sd->flags,
-               sizeof(int), 0644, proc_dointvec_minmax, false);
-       set_table_entry(&table[11], "max_newidle_lb_cost",
-               &sd->max_newidle_lb_cost,
-               sizeof(long), 0644, proc_doulongvec_minmax, false);
-       set_table_entry(&table[12], "name", sd->name,
-               CORENAME_MAX_SIZE, 0444, proc_dostring, false);
-       /* &table[13] is terminator */
-
-       return table;
-}
-
-static struct ctl_table *sd_alloc_ctl_cpu_table(int cpu)
-{
-       struct ctl_table *entry, *table;
-       struct sched_domain *sd;
-       int domain_num = 0, i;
-       char buf[32];
-
-       for_each_domain(cpu, sd)
-               domain_num++;
-       entry = table = sd_alloc_ctl_entry(domain_num + 1);
-       if (table == NULL)
-               return NULL;
-
-       i = 0;
-       for_each_domain(cpu, sd) {
-               snprintf(buf, 32, "domain%d", i);
-               entry->procname = kstrdup(buf, GFP_KERNEL);
-               entry->mode = 0555;
-               entry->child = sd_alloc_ctl_domain_table(sd);
-               entry++;
-               i++;
-       }
-       return table;
-}
-
-static struct ctl_table_header *sd_sysctl_header;
-static void register_sched_domain_sysctl(void)
-{
-       int i, cpu_num = num_possible_cpus();
-       struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1);
-       char buf[32];
-
-       WARN_ON(sd_ctl_dir[0].child);
-       sd_ctl_dir[0].child = entry;
-
-       if (entry == NULL)
-               return;
-
-       for_each_possible_cpu(i) {
-               snprintf(buf, 32, "cpu%d", i);
-               entry->procname = kstrdup(buf, GFP_KERNEL);
-               entry->mode = 0555;
-               entry->child = sd_alloc_ctl_cpu_table(i);
-               entry++;
-       }
-
-       WARN_ON(sd_sysctl_header);
-       sd_sysctl_header = register_sysctl_table(sd_ctl_root);
-}
-
-/* may be called multiple times per register */
-static void unregister_sched_domain_sysctl(void)
-{
-       unregister_sysctl_table(sd_sysctl_header);
-       sd_sysctl_header = NULL;
-       if (sd_ctl_dir[0].child)
-               sd_free_ctl_entry(&sd_ctl_dir[0].child);
-}
-#else
-static void register_sched_domain_sysctl(void)
-{
-}
-static void unregister_sched_domain_sysctl(void)
-{
-}
-#endif /* CONFIG_SCHED_DEBUG && CONFIG_SYSCTL */
-
 static void set_rq_online(struct rq *rq)
 {
        if (!rq->online) {
@@ -5692,16 +5434,6 @@ static int sched_cpu_active(struct notifier_block *nfb,
                set_cpu_rq_start_time();
                return NOTIFY_OK;
 
-       case CPU_ONLINE:
-               /*
-                * At this point a starting CPU has marked itself as online via
-                * set_cpu_online(). But it might not yet have marked itself
-                * as active, which is essential from here on.
-                */
-               set_cpu_active(cpu, true);
-               stop_machine_unpark(cpu);
-               return NOTIFY_OK;
-
        case CPU_DOWN_FAILED:
                set_cpu_active(cpu, true);
                return NOTIFY_OK;
@@ -6173,11 +5905,16 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
 /* Setup the mask of cpus configured for isolated domains */
 static int __init isolated_cpu_setup(char *str)
 {
+       int ret;
+
        alloc_bootmem_cpumask_var(&cpu_isolated_map);
-       cpulist_parse(str, cpu_isolated_map);
+       ret = cpulist_parse(str, cpu_isolated_map);
+       if (ret) {
+               pr_err("sched: Error, all isolcpus= values must be between 0 and %d\n", nr_cpu_ids);
+               return 0;
+       }
        return 1;
 }
-
 __setup("isolcpus=", isolated_cpu_setup);
 
 struct s_data {
@@ -7860,11 +7597,9 @@ void sched_destroy_group(struct task_group *tg)
 void sched_offline_group(struct task_group *tg)
 {
        unsigned long flags;
-       int i;
 
        /* end participation in shares distribution */
-       for_each_possible_cpu(i)
-               unregister_fair_sched_group(tg, i);
+       unregister_fair_sched_group(tg);
 
        spin_lock_irqsave(&task_group_lock, flags);
        list_del_rcu(&tg->list);
@@ -7890,7 +7625,7 @@ void sched_move_task(struct task_struct *tsk)
        queued = task_on_rq_queued(tsk);
 
        if (queued)
-               dequeue_task(rq, tsk, DEQUEUE_SAVE);
+               dequeue_task(rq, tsk, DEQUEUE_SAVE | DEQUEUE_MOVE);
        if (unlikely(running))
                put_prev_task(rq, tsk);
 
@@ -7914,7 +7649,7 @@ void sched_move_task(struct task_struct *tsk)
        if (unlikely(running))
                tsk->sched_class->set_curr_task(rq);
        if (queued)
-               enqueue_task(rq, tsk, ENQUEUE_RESTORE);
+               enqueue_task(rq, tsk, ENQUEUE_RESTORE | ENQUEUE_MOVE);
 
        task_rq_unlock(rq, tsk, &flags);
 }
diff --git a/kernel/sched/cpufreq.c b/kernel/sched/cpufreq.c
new file mode 100644 (file)
index 0000000..928c4ba
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Scheduler code and data structures related to cpufreq.
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.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.
+ */
+
+#include "sched.h"
+
+DEFINE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
+
+/**
+ * cpufreq_set_update_util_data - Populate the CPU's update_util_data pointer.
+ * @cpu: The CPU to set the pointer for.
+ * @data: New pointer value.
+ *
+ * Set and publish the update_util_data pointer for the given CPU.  That pointer
+ * points to a struct update_util_data object containing a callback function
+ * to call from cpufreq_update_util().  That function will be called from an RCU
+ * read-side critical section, so it must not sleep.
+ *
+ * Callers must use RCU-sched callbacks to free any memory that might be
+ * accessed via the old update_util_data pointer or invoke synchronize_sched()
+ * right after this function to avoid use-after-free.
+ */
+void cpufreq_set_update_util_data(int cpu, struct update_util_data *data)
+{
+       if (WARN_ON(data && !data->func))
+               return;
+
+       rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), data);
+}
+EXPORT_SYMBOL_GPL(cpufreq_set_update_util_data);
index b2ab2ffb1adc021de289d3e3c857de60ad2428b6..75f98c5498d55d38b0a36bba2719907742166fe1 100644 (file)
@@ -262,21 +262,21 @@ static __always_inline bool steal_account_process_tick(void)
 #ifdef CONFIG_PARAVIRT
        if (static_key_false(&paravirt_steal_enabled)) {
                u64 steal;
-               cputime_t steal_ct;
+               unsigned long steal_jiffies;
 
                steal = paravirt_steal_clock(smp_processor_id());
                steal -= this_rq()->prev_steal_time;
 
                /*
-                * cputime_t may be less precise than nsecs (eg: if it's
-                * based on jiffies). Lets cast the result to cputime
+                * steal is in nsecs but our caller is expecting steal
+                * time in jiffies. Lets cast the result to jiffies
                 * granularity and account the rest on the next rounds.
                 */
-               steal_ct = nsecs_to_cputime(steal);
-               this_rq()->prev_steal_time += cputime_to_nsecs(steal_ct);
+               steal_jiffies = nsecs_to_jiffies(steal);
+               this_rq()->prev_steal_time += jiffies_to_nsecs(steal_jiffies);
 
-               account_steal_time(steal_ct);
-               return steal_ct;
+               account_steal_time(jiffies_to_cputime(steal_jiffies));
+               return steal_jiffies;
        }
 #endif
        return false;
@@ -668,26 +668,25 @@ void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, cputime
 #endif /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
-static unsigned long long vtime_delta(struct task_struct *tsk)
+static cputime_t vtime_delta(struct task_struct *tsk)
 {
-       unsigned long long clock;
+       unsigned long now = READ_ONCE(jiffies);
 
-       clock = local_clock();
-       if (clock < tsk->vtime_snap)
+       if (time_before(now, (unsigned long)tsk->vtime_snap))
                return 0;
 
-       return clock - tsk->vtime_snap;
+       return jiffies_to_cputime(now - tsk->vtime_snap);
 }
 
 static cputime_t get_vtime_delta(struct task_struct *tsk)
 {
-       unsigned long long delta = vtime_delta(tsk);
+       unsigned long now = READ_ONCE(jiffies);
+       unsigned long delta = now - tsk->vtime_snap;
 
        WARN_ON_ONCE(tsk->vtime_snap_whence == VTIME_INACTIVE);
-       tsk->vtime_snap += delta;
+       tsk->vtime_snap = now;
 
-       /* CHECKME: always safe to convert nsecs to cputime? */
-       return nsecs_to_cputime(delta);
+       return jiffies_to_cputime(delta);
 }
 
 static void __vtime_account_system(struct task_struct *tsk)
@@ -699,6 +698,9 @@ static void __vtime_account_system(struct task_struct *tsk)
 
 void vtime_account_system(struct task_struct *tsk)
 {
+       if (!vtime_delta(tsk))
+               return;
+
        write_seqcount_begin(&tsk->vtime_seqcount);
        __vtime_account_system(tsk);
        write_seqcount_end(&tsk->vtime_seqcount);
@@ -707,7 +709,8 @@ void vtime_account_system(struct task_struct *tsk)
 void vtime_gen_account_irq_exit(struct task_struct *tsk)
 {
        write_seqcount_begin(&tsk->vtime_seqcount);
-       __vtime_account_system(tsk);
+       if (vtime_delta(tsk))
+               __vtime_account_system(tsk);
        if (context_tracking_in_user())
                tsk->vtime_snap_whence = VTIME_USER;
        write_seqcount_end(&tsk->vtime_seqcount);
@@ -718,16 +721,19 @@ void vtime_account_user(struct task_struct *tsk)
        cputime_t delta_cpu;
 
        write_seqcount_begin(&tsk->vtime_seqcount);
-       delta_cpu = get_vtime_delta(tsk);
        tsk->vtime_snap_whence = VTIME_SYS;
-       account_user_time(tsk, delta_cpu, cputime_to_scaled(delta_cpu));
+       if (vtime_delta(tsk)) {
+               delta_cpu = get_vtime_delta(tsk);
+               account_user_time(tsk, delta_cpu, cputime_to_scaled(delta_cpu));
+       }
        write_seqcount_end(&tsk->vtime_seqcount);
 }
 
 void vtime_user_enter(struct task_struct *tsk)
 {
        write_seqcount_begin(&tsk->vtime_seqcount);
-       __vtime_account_system(tsk);
+       if (vtime_delta(tsk))
+               __vtime_account_system(tsk);
        tsk->vtime_snap_whence = VTIME_USER;
        write_seqcount_end(&tsk->vtime_seqcount);
 }
@@ -742,7 +748,8 @@ void vtime_guest_enter(struct task_struct *tsk)
         * that can thus safely catch up with a tickless delta.
         */
        write_seqcount_begin(&tsk->vtime_seqcount);
-       __vtime_account_system(tsk);
+       if (vtime_delta(tsk))
+               __vtime_account_system(tsk);
        current->flags |= PF_VCPU;
        write_seqcount_end(&tsk->vtime_seqcount);
 }
@@ -772,7 +779,7 @@ void arch_vtime_task_switch(struct task_struct *prev)
 
        write_seqcount_begin(&current->vtime_seqcount);
        current->vtime_snap_whence = VTIME_SYS;
-       current->vtime_snap = sched_clock_cpu(smp_processor_id());
+       current->vtime_snap = jiffies;
        write_seqcount_end(&current->vtime_seqcount);
 }
 
@@ -783,7 +790,7 @@ void vtime_init_idle(struct task_struct *t, int cpu)
        local_irq_save(flags);
        write_seqcount_begin(&t->vtime_seqcount);
        t->vtime_snap_whence = VTIME_SYS;
-       t->vtime_snap = sched_clock_cpu(cpu);
+       t->vtime_snap = jiffies;
        write_seqcount_end(&t->vtime_seqcount);
        local_irq_restore(flags);
 }
index cd64c979d0e1857aceb8f9f4383c507ad5fa6809..affd97ec9f65a0c1b9751ee9f1d39cf77757b0aa 100644 (file)
@@ -352,7 +352,15 @@ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se,
        struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
        struct rq *rq = rq_of_dl_rq(dl_rq);
 
-       WARN_ON(!dl_se->dl_new || dl_se->dl_throttled);
+       WARN_ON(dl_time_before(rq_clock(rq), dl_se->deadline));
+
+       /*
+        * We are racing with the deadline timer. So, do nothing because
+        * the deadline timer handler will take care of properly recharging
+        * the runtime and postponing the deadline
+        */
+       if (dl_se->dl_throttled)
+               return;
 
        /*
         * We use the regular wall clock time to set deadlines in the
@@ -361,7 +369,6 @@ static inline void setup_new_dl_entity(struct sched_dl_entity *dl_se,
         */
        dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
        dl_se->runtime = pi_se->dl_runtime;
-       dl_se->dl_new = 0;
 }
 
 /*
@@ -399,6 +406,9 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
                dl_se->runtime = pi_se->dl_runtime;
        }
 
+       if (dl_se->dl_yielded && dl_se->runtime > 0)
+               dl_se->runtime = 0;
+
        /*
         * We keep moving the deadline away until we get some
         * available runtime for the entity. This ensures correct
@@ -420,7 +430,7 @@ static void replenish_dl_entity(struct sched_dl_entity *dl_se,
         * entity.
         */
        if (dl_time_before(dl_se->deadline, rq_clock(rq))) {
-               printk_deferred_once("sched: DL replenish lagged to much\n");
+               printk_deferred_once("sched: DL replenish lagged too much\n");
                dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
                dl_se->runtime = pi_se->dl_runtime;
        }
@@ -500,15 +510,6 @@ static void update_dl_entity(struct sched_dl_entity *dl_se,
        struct dl_rq *dl_rq = dl_rq_of_se(dl_se);
        struct rq *rq = rq_of_dl_rq(dl_rq);
 
-       /*
-        * The arrival of a new instance needs special treatment, i.e.,
-        * the actual scheduling parameters have to be "renewed".
-        */
-       if (dl_se->dl_new) {
-               setup_new_dl_entity(dl_se, pi_se);
-               return;
-       }
-
        if (dl_time_before(dl_se->deadline, rq_clock(rq)) ||
            dl_entity_overflow(dl_se, pi_se, rq_clock(rq))) {
                dl_se->deadline = rq_clock(rq) + pi_se->dl_deadline;
@@ -604,16 +605,6 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
                goto unlock;
        }
 
-       /*
-        * This is possible if switched_from_dl() raced against a running
-        * callback that took the above !dl_task() path and we've since then
-        * switched back into SCHED_DEADLINE.
-        *
-        * There's nothing to do except drop our task reference.
-        */
-       if (dl_se->dl_new)
-               goto unlock;
-
        /*
         * The task might have been boosted by someone else and might be in the
         * boosting/deboosting path, its not throttled.
@@ -726,6 +717,10 @@ static void update_curr_dl(struct rq *rq)
        if (!dl_task(curr) || !on_dl_rq(dl_se))
                return;
 
+       /* Kick cpufreq (see the comment in linux/cpufreq.h). */
+       if (cpu_of(rq) == smp_processor_id())
+               cpufreq_trigger_update(rq_clock(rq));
+
        /*
         * Consumed budget is computed considering the time as
         * observed by schedulable tasks (excluding time spent
@@ -735,8 +730,11 @@ static void update_curr_dl(struct rq *rq)
         * approach need further study.
         */
        delta_exec = rq_clock_task(rq) - curr->se.exec_start;
-       if (unlikely((s64)delta_exec <= 0))
+       if (unlikely((s64)delta_exec <= 0)) {
+               if (unlikely(dl_se->dl_yielded))
+                       goto throttle;
                return;
+       }
 
        schedstat_set(curr->se.statistics.exec_max,
                      max(curr->se.statistics.exec_max, delta_exec));
@@ -749,8 +747,10 @@ static void update_curr_dl(struct rq *rq)
 
        sched_rt_avg_update(rq, delta_exec);
 
-       dl_se->runtime -= dl_se->dl_yielded ? 0 : delta_exec;
-       if (dl_runtime_exceeded(dl_se)) {
+       dl_se->runtime -= delta_exec;
+
+throttle:
+       if (dl_runtime_exceeded(dl_se) || dl_se->dl_yielded) {
                dl_se->dl_throttled = 1;
                __dequeue_task_dl(rq, curr, 0);
                if (unlikely(dl_se->dl_boosted || !start_dl_timer(curr)))
@@ -917,7 +917,7 @@ enqueue_dl_entity(struct sched_dl_entity *dl_se,
         * parameters of the task might need updating. Otherwise,
         * we want a replenishment of its runtime.
         */
-       if (dl_se->dl_new || flags & ENQUEUE_WAKEUP)
+       if (flags & ENQUEUE_WAKEUP)
                update_dl_entity(dl_se, pi_se);
        else if (flags & ENQUEUE_REPLENISH)
                replenish_dl_entity(dl_se, pi_se);
@@ -994,18 +994,14 @@ static void dequeue_task_dl(struct rq *rq, struct task_struct *p, int flags)
  */
 static void yield_task_dl(struct rq *rq)
 {
-       struct task_struct *p = rq->curr;
-
        /*
         * We make the task go to sleep until its current deadline by
         * forcing its runtime to zero. This way, update_curr_dl() stops
         * it and the bandwidth timer will wake it up and will give it
         * new scheduling parameters (thanks to dl_yielded=1).
         */
-       if (p->dl.runtime > 0) {
-               rq->curr->dl.dl_yielded = 1;
-               p->dl.runtime = 0;
-       }
+       rq->curr->dl.dl_yielded = 1;
+
        update_rq_clock(rq);
        update_curr_dl(rq);
        /*
@@ -1722,6 +1718,9 @@ static void switched_from_dl(struct rq *rq, struct task_struct *p)
  */
 static void switched_to_dl(struct rq *rq, struct task_struct *p)
 {
+       if (dl_time_before(p->dl.deadline, rq_clock(rq)))
+               setup_new_dl_entity(&p->dl, &p->dl);
+
        if (task_on_rq_queued(p) && rq->curr != p) {
 #ifdef CONFIG_SMP
                if (p->nr_cpus_allowed > 1 && rq->dl.overloaded)
@@ -1768,8 +1767,7 @@ static void prio_changed_dl(struct rq *rq, struct task_struct *p,
                 */
                resched_curr(rq);
 #endif /* CONFIG_SMP */
-       } else
-               switched_to_dl(rq, p);
+       }
 }
 
 const struct sched_class dl_sched_class = {
index 641511771ae6a696271f77532ac9e40e28175749..4fbc3bd5ff6067dfe184295fc262987c912b669e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kallsyms.h>
 #include <linux/utsname.h>
 #include <linux/mempolicy.h>
+#include <linux/debugfs.h>
 
 #include "sched.h"
 
@@ -58,6 +59,309 @@ static unsigned long nsec_low(unsigned long long nsec)
 
 #define SPLIT_NS(x) nsec_high(x), nsec_low(x)
 
+#define SCHED_FEAT(name, enabled)      \
+       #name ,
+
+static const char * const sched_feat_names[] = {
+#include "features.h"
+};
+
+#undef SCHED_FEAT
+
+static int sched_feat_show(struct seq_file *m, void *v)
+{
+       int i;
+
+       for (i = 0; i < __SCHED_FEAT_NR; i++) {
+               if (!(sysctl_sched_features & (1UL << i)))
+                       seq_puts(m, "NO_");
+               seq_printf(m, "%s ", sched_feat_names[i]);
+       }
+       seq_puts(m, "\n");
+
+       return 0;
+}
+
+#ifdef HAVE_JUMP_LABEL
+
+#define jump_label_key__true  STATIC_KEY_INIT_TRUE
+#define jump_label_key__false STATIC_KEY_INIT_FALSE
+
+#define SCHED_FEAT(name, enabled)      \
+       jump_label_key__##enabled ,
+
+struct static_key sched_feat_keys[__SCHED_FEAT_NR] = {
+#include "features.h"
+};
+
+#undef SCHED_FEAT
+
+static void sched_feat_disable(int i)
+{
+       static_key_disable(&sched_feat_keys[i]);
+}
+
+static void sched_feat_enable(int i)
+{
+       static_key_enable(&sched_feat_keys[i]);
+}
+#else
+static void sched_feat_disable(int i) { };
+static void sched_feat_enable(int i) { };
+#endif /* HAVE_JUMP_LABEL */
+
+static int sched_feat_set(char *cmp)
+{
+       int i;
+       int neg = 0;
+
+       if (strncmp(cmp, "NO_", 3) == 0) {
+               neg = 1;
+               cmp += 3;
+       }
+
+       for (i = 0; i < __SCHED_FEAT_NR; i++) {
+               if (strcmp(cmp, sched_feat_names[i]) == 0) {
+                       if (neg) {
+                               sysctl_sched_features &= ~(1UL << i);
+                               sched_feat_disable(i);
+                       } else {
+                               sysctl_sched_features |= (1UL << i);
+                               sched_feat_enable(i);
+                       }
+                       break;
+               }
+       }
+
+       return i;
+}
+
+static ssize_t
+sched_feat_write(struct file *filp, const char __user *ubuf,
+               size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       char *cmp;
+       int i;
+       struct inode *inode;
+
+       if (cnt > 63)
+               cnt = 63;
+
+       if (copy_from_user(&buf, ubuf, cnt))
+               return -EFAULT;
+
+       buf[cnt] = 0;
+       cmp = strstrip(buf);
+
+       /* Ensure the static_key remains in a consistent state */
+       inode = file_inode(filp);
+       inode_lock(inode);
+       i = sched_feat_set(cmp);
+       inode_unlock(inode);
+       if (i == __SCHED_FEAT_NR)
+               return -EINVAL;
+
+       *ppos += cnt;
+
+       return cnt;
+}
+
+static int sched_feat_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, sched_feat_show, NULL);
+}
+
+static const struct file_operations sched_feat_fops = {
+       .open           = sched_feat_open,
+       .write          = sched_feat_write,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static __init int sched_init_debug(void)
+{
+       debugfs_create_file("sched_features", 0644, NULL, NULL,
+                       &sched_feat_fops);
+
+       return 0;
+}
+late_initcall(sched_init_debug);
+
+#ifdef CONFIG_SMP
+
+#ifdef CONFIG_SYSCTL
+
+static struct ctl_table sd_ctl_dir[] = {
+       {
+               .procname       = "sched_domain",
+               .mode           = 0555,
+       },
+       {}
+};
+
+static struct ctl_table sd_ctl_root[] = {
+       {
+               .procname       = "kernel",
+               .mode           = 0555,
+               .child          = sd_ctl_dir,
+       },
+       {}
+};
+
+static struct ctl_table *sd_alloc_ctl_entry(int n)
+{
+       struct ctl_table *entry =
+               kcalloc(n, sizeof(struct ctl_table), GFP_KERNEL);
+
+       return entry;
+}
+
+static void sd_free_ctl_entry(struct ctl_table **tablep)
+{
+       struct ctl_table *entry;
+
+       /*
+        * In the intermediate directories, both the child directory and
+        * procname are dynamically allocated and could fail but the mode
+        * will always be set. In the lowest directory the names are
+        * static strings and all have proc handlers.
+        */
+       for (entry = *tablep; entry->mode; entry++) {
+               if (entry->child)
+                       sd_free_ctl_entry(&entry->child);
+               if (entry->proc_handler == NULL)
+                       kfree(entry->procname);
+       }
+
+       kfree(*tablep);
+       *tablep = NULL;
+}
+
+static int min_load_idx = 0;
+static int max_load_idx = CPU_LOAD_IDX_MAX-1;
+
+static void
+set_table_entry(struct ctl_table *entry,
+               const char *procname, void *data, int maxlen,
+               umode_t mode, proc_handler *proc_handler,
+               bool load_idx)
+{
+       entry->procname = procname;
+       entry->data = data;
+       entry->maxlen = maxlen;
+       entry->mode = mode;
+       entry->proc_handler = proc_handler;
+
+       if (load_idx) {
+               entry->extra1 = &min_load_idx;
+               entry->extra2 = &max_load_idx;
+       }
+}
+
+static struct ctl_table *
+sd_alloc_ctl_domain_table(struct sched_domain *sd)
+{
+       struct ctl_table *table = sd_alloc_ctl_entry(14);
+
+       if (table == NULL)
+               return NULL;
+
+       set_table_entry(&table[0], "min_interval", &sd->min_interval,
+               sizeof(long), 0644, proc_doulongvec_minmax, false);
+       set_table_entry(&table[1], "max_interval", &sd->max_interval,
+               sizeof(long), 0644, proc_doulongvec_minmax, false);
+       set_table_entry(&table[2], "busy_idx", &sd->busy_idx,
+               sizeof(int), 0644, proc_dointvec_minmax, true);
+       set_table_entry(&table[3], "idle_idx", &sd->idle_idx,
+               sizeof(int), 0644, proc_dointvec_minmax, true);
+       set_table_entry(&table[4], "newidle_idx", &sd->newidle_idx,
+               sizeof(int), 0644, proc_dointvec_minmax, true);
+       set_table_entry(&table[5], "wake_idx", &sd->wake_idx,
+               sizeof(int), 0644, proc_dointvec_minmax, true);
+       set_table_entry(&table[6], "forkexec_idx", &sd->forkexec_idx,
+               sizeof(int), 0644, proc_dointvec_minmax, true);
+       set_table_entry(&table[7], "busy_factor", &sd->busy_factor,
+               sizeof(int), 0644, proc_dointvec_minmax, false);
+       set_table_entry(&table[8], "imbalance_pct", &sd->imbalance_pct,
+               sizeof(int), 0644, proc_dointvec_minmax, false);
+       set_table_entry(&table[9], "cache_nice_tries",
+               &sd->cache_nice_tries,
+               sizeof(int), 0644, proc_dointvec_minmax, false);
+       set_table_entry(&table[10], "flags", &sd->flags,
+               sizeof(int), 0644, proc_dointvec_minmax, false);
+       set_table_entry(&table[11], "max_newidle_lb_cost",
+               &sd->max_newidle_lb_cost,
+               sizeof(long), 0644, proc_doulongvec_minmax, false);
+       set_table_entry(&table[12], "name", sd->name,
+               CORENAME_MAX_SIZE, 0444, proc_dostring, false);
+       /* &table[13] is terminator */
+
+       return table;
+}
+
+static struct ctl_table *sd_alloc_ctl_cpu_table(int cpu)
+{
+       struct ctl_table *entry, *table;
+       struct sched_domain *sd;
+       int domain_num = 0, i;
+       char buf[32];
+
+       for_each_domain(cpu, sd)
+               domain_num++;
+       entry = table = sd_alloc_ctl_entry(domain_num + 1);
+       if (table == NULL)
+               return NULL;
+
+       i = 0;
+       for_each_domain(cpu, sd) {
+               snprintf(buf, 32, "domain%d", i);
+               entry->procname = kstrdup(buf, GFP_KERNEL);
+               entry->mode = 0555;
+               entry->child = sd_alloc_ctl_domain_table(sd);
+               entry++;
+               i++;
+       }
+       return table;
+}
+
+static struct ctl_table_header *sd_sysctl_header;
+void register_sched_domain_sysctl(void)
+{
+       int i, cpu_num = num_possible_cpus();
+       struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1);
+       char buf[32];
+
+       WARN_ON(sd_ctl_dir[0].child);
+       sd_ctl_dir[0].child = entry;
+
+       if (entry == NULL)
+               return;
+
+       for_each_possible_cpu(i) {
+               snprintf(buf, 32, "cpu%d", i);
+               entry->procname = kstrdup(buf, GFP_KERNEL);
+               entry->mode = 0555;
+               entry->child = sd_alloc_ctl_cpu_table(i);
+               entry++;
+       }
+
+       WARN_ON(sd_sysctl_header);
+       sd_sysctl_header = register_sysctl_table(sd_ctl_root);
+}
+
+/* may be called multiple times per register */
+void unregister_sched_domain_sysctl(void)
+{
+       unregister_sysctl_table(sd_sysctl_header);
+       sd_sysctl_header = NULL;
+       if (sd_ctl_dir[0].child)
+               sd_free_ctl_entry(&sd_ctl_dir[0].child);
+}
+#endif /* CONFIG_SYSCTL */
+#endif /* CONFIG_SMP */
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group *tg)
 {
@@ -75,16 +379,18 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu, struct task_group
        PN(se->vruntime);
        PN(se->sum_exec_runtime);
 #ifdef CONFIG_SCHEDSTATS
-       PN(se->statistics.wait_start);
-       PN(se->statistics.sleep_start);
-       PN(se->statistics.block_start);
-       PN(se->statistics.sleep_max);
-       PN(se->statistics.block_max);
-       PN(se->statistics.exec_max);
-       PN(se->statistics.slice_max);
-       PN(se->statistics.wait_max);
-       PN(se->statistics.wait_sum);
-       P(se->statistics.wait_count);
+       if (schedstat_enabled()) {
+               PN(se->statistics.wait_start);
+               PN(se->statistics.sleep_start);
+               PN(se->statistics.block_start);
+               PN(se->statistics.sleep_max);
+               PN(se->statistics.block_max);
+               PN(se->statistics.exec_max);
+               PN(se->statistics.slice_max);
+               PN(se->statistics.wait_max);
+               PN(se->statistics.wait_sum);
+               P(se->statistics.wait_count);
+       }
 #endif
        P(se->load.weight);
 #ifdef CONFIG_SMP
@@ -122,10 +428,12 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
                (long long)(p->nvcsw + p->nivcsw),
                p->prio);
 #ifdef CONFIG_SCHEDSTATS
-       SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld",
-               SPLIT_NS(p->se.statistics.wait_sum),
-               SPLIT_NS(p->se.sum_exec_runtime),
-               SPLIT_NS(p->se.statistics.sum_sleep_runtime));
+       if (schedstat_enabled()) {
+               SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld",
+                       SPLIT_NS(p->se.statistics.wait_sum),
+                       SPLIT_NS(p->se.sum_exec_runtime),
+                       SPLIT_NS(p->se.statistics.sum_sleep_runtime));
+       }
 #else
        SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld",
                0LL, 0L,
@@ -258,8 +566,17 @@ void print_rt_rq(struct seq_file *m, int cpu, struct rt_rq *rt_rq)
 
 void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq)
 {
+       struct dl_bw *dl_bw;
+
        SEQ_printf(m, "\ndl_rq[%d]:\n", cpu);
        SEQ_printf(m, "  .%-30s: %ld\n", "dl_nr_running", dl_rq->dl_nr_running);
+#ifdef CONFIG_SMP
+       dl_bw = &cpu_rq(cpu)->rd->dl_bw;
+#else
+       dl_bw = &dl_rq->dl_bw;
+#endif
+       SEQ_printf(m, "  .%-30s: %lld\n", "dl_bw->bw", dl_bw->bw);
+       SEQ_printf(m, "  .%-30s: %lld\n", "dl_bw->total_bw", dl_bw->total_bw);
 }
 
 extern __read_mostly int sched_clock_running;
@@ -313,17 +630,18 @@ do {                                                                      \
 #define P(n) SEQ_printf(m, "  .%-30s: %d\n", #n, rq->n);
 #define P64(n) SEQ_printf(m, "  .%-30s: %Ld\n", #n, rq->n);
 
-       P(yld_count);
-
-       P(sched_count);
-       P(sched_goidle);
 #ifdef CONFIG_SMP
        P64(avg_idle);
        P64(max_idle_balance_cost);
 #endif
 
-       P(ttwu_count);
-       P(ttwu_local);
+       if (schedstat_enabled()) {
+               P(yld_count);
+               P(sched_count);
+               P(sched_goidle);
+               P(ttwu_count);
+               P(ttwu_local);
+       }
 
 #undef P
 #undef P64
@@ -569,38 +887,39 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
        nr_switches = p->nvcsw + p->nivcsw;
 
 #ifdef CONFIG_SCHEDSTATS
-       PN(se.statistics.sum_sleep_runtime);
-       PN(se.statistics.wait_start);
-       PN(se.statistics.sleep_start);
-       PN(se.statistics.block_start);
-       PN(se.statistics.sleep_max);
-       PN(se.statistics.block_max);
-       PN(se.statistics.exec_max);
-       PN(se.statistics.slice_max);
-       PN(se.statistics.wait_max);
-       PN(se.statistics.wait_sum);
-       P(se.statistics.wait_count);
-       PN(se.statistics.iowait_sum);
-       P(se.statistics.iowait_count);
        P(se.nr_migrations);
-       P(se.statistics.nr_migrations_cold);
-       P(se.statistics.nr_failed_migrations_affine);
-       P(se.statistics.nr_failed_migrations_running);
-       P(se.statistics.nr_failed_migrations_hot);
-       P(se.statistics.nr_forced_migrations);
-       P(se.statistics.nr_wakeups);
-       P(se.statistics.nr_wakeups_sync);
-       P(se.statistics.nr_wakeups_migrate);
-       P(se.statistics.nr_wakeups_local);
-       P(se.statistics.nr_wakeups_remote);
-       P(se.statistics.nr_wakeups_affine);
-       P(se.statistics.nr_wakeups_affine_attempts);
-       P(se.statistics.nr_wakeups_passive);
-       P(se.statistics.nr_wakeups_idle);
 
-       {
+       if (schedstat_enabled()) {
                u64 avg_atom, avg_per_cpu;
 
+               PN(se.statistics.sum_sleep_runtime);
+               PN(se.statistics.wait_start);
+               PN(se.statistics.sleep_start);
+               PN(se.statistics.block_start);
+               PN(se.statistics.sleep_max);
+               PN(se.statistics.block_max);
+               PN(se.statistics.exec_max);
+               PN(se.statistics.slice_max);
+               PN(se.statistics.wait_max);
+               PN(se.statistics.wait_sum);
+               P(se.statistics.wait_count);
+               PN(se.statistics.iowait_sum);
+               P(se.statistics.iowait_count);
+               P(se.statistics.nr_migrations_cold);
+               P(se.statistics.nr_failed_migrations_affine);
+               P(se.statistics.nr_failed_migrations_running);
+               P(se.statistics.nr_failed_migrations_hot);
+               P(se.statistics.nr_forced_migrations);
+               P(se.statistics.nr_wakeups);
+               P(se.statistics.nr_wakeups_sync);
+               P(se.statistics.nr_wakeups_migrate);
+               P(se.statistics.nr_wakeups_local);
+               P(se.statistics.nr_wakeups_remote);
+               P(se.statistics.nr_wakeups_affine);
+               P(se.statistics.nr_wakeups_affine_attempts);
+               P(se.statistics.nr_wakeups_passive);
+               P(se.statistics.nr_wakeups_idle);
+
                avg_atom = p->se.sum_exec_runtime;
                if (nr_switches)
                        avg_atom = div64_ul(avg_atom, nr_switches);
index 56b7d4b839476b6ed1692e786abe9ed6cda64a5f..46d64e4ccfde8ad99014761c93ef3ceca1e122b2 100644 (file)
@@ -20,8 +20,8 @@
  *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  */
 
-#include <linux/latencytop.h>
 #include <linux/sched.h>
+#include <linux/latencytop.h>
 #include <linux/cpumask.h>
 #include <linux/cpuidle.h>
 #include <linux/slab.h>
@@ -755,7 +755,9 @@ static void
 update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
        struct task_struct *p;
-       u64 delta = rq_clock(rq_of(cfs_rq)) - se->statistics.wait_start;
+       u64 delta;
+
+       delta = rq_clock(rq_of(cfs_rq)) - se->statistics.wait_start;
 
        if (entity_is_task(se)) {
                p = task_of(se);
@@ -776,22 +778,12 @@ update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se)
        se->statistics.wait_sum += delta;
        se->statistics.wait_start = 0;
 }
-#else
-static inline void
-update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
-{
-}
-
-static inline void
-update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se)
-{
-}
-#endif
 
 /*
  * Task is being enqueued - update stats:
  */
-static void update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+static inline void
+update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
        /*
         * Are we enqueueing a waiting task? (for current tasks
@@ -802,7 +794,7 @@ static void update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
 }
 
 static inline void
-update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 {
        /*
         * Mark the end of the wait period if dequeueing a
@@ -810,8 +802,41 @@ update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
         */
        if (se != cfs_rq->curr)
                update_stats_wait_end(cfs_rq, se);
+
+       if (flags & DEQUEUE_SLEEP) {
+               if (entity_is_task(se)) {
+                       struct task_struct *tsk = task_of(se);
+
+                       if (tsk->state & TASK_INTERRUPTIBLE)
+                               se->statistics.sleep_start = rq_clock(rq_of(cfs_rq));
+                       if (tsk->state & TASK_UNINTERRUPTIBLE)
+                               se->statistics.block_start = rq_clock(rq_of(cfs_rq));
+               }
+       }
+
+}
+#else
+static inline void
+update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+}
+
+static inline void
+update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
 }
 
+static inline void
+update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+}
+
+static inline void
+update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
+{
+}
+#endif
+
 /*
  * We are picking a new current task - update its stats:
  */
@@ -907,10 +932,11 @@ struct numa_group {
        spinlock_t lock; /* nr_tasks, tasks */
        int nr_tasks;
        pid_t gid;
+       int active_nodes;
 
        struct rcu_head rcu;
-       nodemask_t active_nodes;
        unsigned long total_faults;
+       unsigned long max_faults_cpu;
        /*
         * Faults_cpu is used to decide whether memory should move
         * towards the CPU. As a consequence, these stats are weighted
@@ -969,6 +995,18 @@ static inline unsigned long group_faults_cpu(struct numa_group *group, int nid)
                group->faults_cpu[task_faults_idx(NUMA_MEM, nid, 1)];
 }
 
+/*
+ * A node triggering more than 1/3 as many NUMA faults as the maximum is
+ * considered part of a numa group's pseudo-interleaving set. Migrations
+ * between these nodes are slowed down, to allow things to settle down.
+ */
+#define ACTIVE_NODE_FRACTION 3
+
+static bool numa_is_active_node(int nid, struct numa_group *ng)
+{
+       return group_faults_cpu(ng, nid) * ACTIVE_NODE_FRACTION > ng->max_faults_cpu;
+}
+
 /* Handle placement on systems where not all nodes are directly connected. */
 static unsigned long score_nearby_nodes(struct task_struct *p, int nid,
                                        int maxdist, bool task)
@@ -1118,27 +1156,23 @@ bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
                return true;
 
        /*
-        * Do not migrate if the destination is not a node that
-        * is actively used by this numa group.
-        */
-       if (!node_isset(dst_nid, ng->active_nodes))
-               return false;
-
-       /*
-        * Source is a node that is not actively used by this
-        * numa group, while the destination is. Migrate.
+        * Destination node is much more heavily used than the source
+        * node? Allow migration.
         */
-       if (!node_isset(src_nid, ng->active_nodes))
+       if (group_faults_cpu(ng, dst_nid) > group_faults_cpu(ng, src_nid) *
+                                       ACTIVE_NODE_FRACTION)
                return true;
 
        /*
-        * Both source and destination are nodes in active
-        * use by this numa group. Maximize memory bandwidth
-        * by migrating from more heavily used groups, to less
-        * heavily used ones, spreading the load around.
-        * Use a 1/4 hysteresis to avoid spurious page movement.
+        * Distribute memory according to CPU & memory use on each node,
+        * with 3/4 hysteresis to avoid unnecessary memory migrations:
+        *
+        * faults_cpu(dst)   3   faults_cpu(src)
+        * --------------- * - > ---------------
+        * faults_mem(dst)   4   faults_mem(src)
         */
-       return group_faults(p, dst_nid) < (group_faults(p, src_nid) * 3 / 4);
+       return group_faults_cpu(ng, dst_nid) * group_faults(p, src_nid) * 3 >
+              group_faults_cpu(ng, src_nid) * group_faults(p, dst_nid) * 4;
 }
 
 static unsigned long weighted_cpuload(const int cpu);
@@ -1484,7 +1518,7 @@ static int task_numa_migrate(struct task_struct *p)
 
                .best_task = NULL,
                .best_imp = 0,
-               .best_cpu = -1
+               .best_cpu = -1,
        };
        struct sched_domain *sd;
        unsigned long taskweight, groupweight;
@@ -1536,8 +1570,7 @@ static int task_numa_migrate(struct task_struct *p)
         *   multiple NUMA nodes; in order to better consolidate the group,
         *   we need to check other locations.
         */
-       if (env.best_cpu == -1 || (p->numa_group &&
-                       nodes_weight(p->numa_group->active_nodes) > 1)) {
+       if (env.best_cpu == -1 || (p->numa_group && p->numa_group->active_nodes > 1)) {
                for_each_online_node(nid) {
                        if (nid == env.src_nid || nid == p->numa_preferred_nid)
                                continue;
@@ -1572,12 +1605,14 @@ static int task_numa_migrate(struct task_struct *p)
         * trying for a better one later. Do not set the preferred node here.
         */
        if (p->numa_group) {
+               struct numa_group *ng = p->numa_group;
+
                if (env.best_cpu == -1)
                        nid = env.src_nid;
                else
                        nid = env.dst_nid;
 
-               if (node_isset(nid, p->numa_group->active_nodes))
+               if (ng->active_nodes > 1 && numa_is_active_node(env.dst_nid, ng))
                        sched_setnuma(p, env.dst_nid);
        }
 
@@ -1627,20 +1662,15 @@ static void numa_migrate_preferred(struct task_struct *p)
 }
 
 /*
- * Find the nodes on which the workload is actively running. We do this by
+ * Find out how many nodes on the workload is actively running on. Do this by
  * tracking the nodes from which NUMA hinting faults are triggered. This can
  * be different from the set of nodes where the workload's memory is currently
  * located.
- *
- * The bitmask is used to make smarter decisions on when to do NUMA page
- * migrations, To prevent flip-flopping, and excessive page migrations, nodes
- * are added when they cause over 6/16 of the maximum number of faults, but
- * only removed when they drop below 3/16.
  */
-static void update_numa_active_node_mask(struct numa_group *numa_group)
+static void numa_group_count_active_nodes(struct numa_group *numa_group)
 {
        unsigned long faults, max_faults = 0;
-       int nid;
+       int nid, active_nodes = 0;
 
        for_each_online_node(nid) {
                faults = group_faults_cpu(numa_group, nid);
@@ -1650,12 +1680,12 @@ static void update_numa_active_node_mask(struct numa_group *numa_group)
 
        for_each_online_node(nid) {
                faults = group_faults_cpu(numa_group, nid);
-               if (!node_isset(nid, numa_group->active_nodes)) {
-                       if (faults > max_faults * 6 / 16)
-                               node_set(nid, numa_group->active_nodes);
-               } else if (faults < max_faults * 3 / 16)
-                       node_clear(nid, numa_group->active_nodes);
+               if (faults * ACTIVE_NODE_FRACTION > max_faults)
+                       active_nodes++;
        }
+
+       numa_group->max_faults_cpu = max_faults;
+       numa_group->active_nodes = active_nodes;
 }
 
 /*
@@ -1946,7 +1976,7 @@ static void task_numa_placement(struct task_struct *p)
        update_task_scan_period(p, fault_types[0], fault_types[1]);
 
        if (p->numa_group) {
-               update_numa_active_node_mask(p->numa_group);
+               numa_group_count_active_nodes(p->numa_group);
                spin_unlock_irq(group_lock);
                max_nid = preferred_group_nid(p, max_group_nid);
        }
@@ -1990,14 +2020,14 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
                        return;
 
                atomic_set(&grp->refcount, 1);
+               grp->active_nodes = 1;
+               grp->max_faults_cpu = 0;
                spin_lock_init(&grp->lock);
                grp->gid = p->pid;
                /* Second half of the array tracks nids where faults happen */
                grp->faults_cpu = grp->faults + NR_NUMA_HINT_FAULT_TYPES *
                                                nr_node_ids;
 
-               node_set(task_node(current), grp->active_nodes);
-
                for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
                        grp->faults[i] = p->numa_faults[i];
 
@@ -2111,6 +2141,7 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
        bool migrated = flags & TNF_MIGRATED;
        int cpu_node = task_node(current);
        int local = !!(flags & TNF_FAULT_LOCAL);
+       struct numa_group *ng;
        int priv;
 
        if (!static_branch_likely(&sched_numa_balancing))
@@ -2151,9 +2182,10 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
         * actively using should be counted as local. This allows the
         * scan rate to slow down when a workload has settled down.
         */
-       if (!priv && !local && p->numa_group &&
-                       node_isset(cpu_node, p->numa_group->active_nodes) &&
-                       node_isset(mem_node, p->numa_group->active_nodes))
+       ng = p->numa_group;
+       if (!priv && !local && ng && ng->active_nodes > 1 &&
+                               numa_is_active_node(cpu_node, ng) &&
+                               numa_is_active_node(mem_node, ng))
                local = 1;
 
        task_numa_placement(p);
@@ -2824,7 +2856,8 @@ static inline void update_load_avg(struct sched_entity *se, int update_tg)
 {
        struct cfs_rq *cfs_rq = cfs_rq_of(se);
        u64 now = cfs_rq_clock_task(cfs_rq);
-       int cpu = cpu_of(rq_of(cfs_rq));
+       struct rq *rq = rq_of(cfs_rq);
+       int cpu = cpu_of(rq);
 
        /*
         * Track task load average for carrying it to new CPU after migrated, and
@@ -2836,6 +2869,29 @@ static inline void update_load_avg(struct sched_entity *se, int update_tg)
 
        if (update_cfs_rq_load_avg(now, cfs_rq) && update_tg)
                update_tg_load_avg(cfs_rq, 0);
+
+       if (cpu == smp_processor_id() && &rq->cfs == cfs_rq) {
+               unsigned long max = rq->cpu_capacity_orig;
+
+               /*
+                * There are a few boundary cases this might miss but it should
+                * get called often enough that that should (hopefully) not be
+                * a real problem -- added to that it only calls on the local
+                * CPU, so if we enqueue remotely we'll miss an update, but
+                * the next tick/schedule should update.
+                *
+                * It will not get called when we go idle, because the idle
+                * thread is a different class (!fair), nor will the utilization
+                * number include things like RT tasks.
+                *
+                * As is, the util number is not freq-invariant (we'd have to
+                * implement arch_scale_freq_capacity() for that).
+                *
+                * See cpu_util().
+                */
+               cpufreq_update_util(rq_clock(rq),
+                                   min(cfs_rq->avg.util_avg, max), max);
+       }
 }
 
 static void attach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se)
@@ -3102,6 +3158,26 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
 
 static void check_enqueue_throttle(struct cfs_rq *cfs_rq);
 
+static inline void check_schedstat_required(void)
+{
+#ifdef CONFIG_SCHEDSTATS
+       if (schedstat_enabled())
+               return;
+
+       /* Force schedstat enabled if a dependent tracepoint is active */
+       if (trace_sched_stat_wait_enabled()    ||
+                       trace_sched_stat_sleep_enabled()   ||
+                       trace_sched_stat_iowait_enabled()  ||
+                       trace_sched_stat_blocked_enabled() ||
+                       trace_sched_stat_runtime_enabled())  {
+               pr_warn_once("Scheduler tracepoints stat_sleep, stat_iowait, "
+                            "stat_blocked and stat_runtime require the "
+                            "kernel parameter schedstats=enabled or "
+                            "kernel.sched_schedstats=1\n");
+       }
+#endif
+}
+
 static void
 enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 {
@@ -3122,11 +3198,15 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 
        if (flags & ENQUEUE_WAKEUP) {
                place_entity(cfs_rq, se, 0);
-               enqueue_sleeper(cfs_rq, se);
+               if (schedstat_enabled())
+                       enqueue_sleeper(cfs_rq, se);
        }
 
-       update_stats_enqueue(cfs_rq, se);
-       check_spread(cfs_rq, se);
+       check_schedstat_required();
+       if (schedstat_enabled()) {
+               update_stats_enqueue(cfs_rq, se);
+               check_spread(cfs_rq, se);
+       }
        if (se != cfs_rq->curr)
                __enqueue_entity(cfs_rq, se);
        se->on_rq = 1;
@@ -3193,19 +3273,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
        update_curr(cfs_rq);
        dequeue_entity_load_avg(cfs_rq, se);
 
-       update_stats_dequeue(cfs_rq, se);
-       if (flags & DEQUEUE_SLEEP) {
-#ifdef CONFIG_SCHEDSTATS
-               if (entity_is_task(se)) {
-                       struct task_struct *tsk = task_of(se);
-
-                       if (tsk->state & TASK_INTERRUPTIBLE)
-                               se->statistics.sleep_start = rq_clock(rq_of(cfs_rq));
-                       if (tsk->state & TASK_UNINTERRUPTIBLE)
-                               se->statistics.block_start = rq_clock(rq_of(cfs_rq));
-               }
-#endif
-       }
+       if (schedstat_enabled())
+               update_stats_dequeue(cfs_rq, se, flags);
 
        clear_buddies(cfs_rq, se);
 
@@ -3279,7 +3348,8 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
                 * a CPU. So account for the time it spent waiting on the
                 * runqueue.
                 */
-               update_stats_wait_end(cfs_rq, se);
+               if (schedstat_enabled())
+                       update_stats_wait_end(cfs_rq, se);
                __dequeue_entity(cfs_rq, se);
                update_load_avg(se, 1);
        }
@@ -3292,7 +3362,7 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
         * least twice that of our own weight (i.e. dont track it
         * when there are only lesser-weight tasks around):
         */
-       if (rq_of(cfs_rq)->load.weight >= 2*se->load.weight) {
+       if (schedstat_enabled() && rq_of(cfs_rq)->load.weight >= 2*se->load.weight) {
                se->statistics.slice_max = max(se->statistics.slice_max,
                        se->sum_exec_runtime - se->prev_sum_exec_runtime);
        }
@@ -3375,9 +3445,13 @@ static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev)
        /* throttle cfs_rqs exceeding runtime */
        check_cfs_rq_runtime(cfs_rq);
 
-       check_spread(cfs_rq, prev);
+       if (schedstat_enabled()) {
+               check_spread(cfs_rq, prev);
+               if (prev->on_rq)
+                       update_stats_wait_start(cfs_rq, prev);
+       }
+
        if (prev->on_rq) {
-               update_stats_wait_start(cfs_rq, prev);
                /* Put 'current' back into the tree. */
                __enqueue_entity(cfs_rq, prev);
                /* in !on_rq case, update occurred at dequeue */
@@ -4459,9 +4533,17 @@ static void __update_cpu_load(struct rq *this_rq, unsigned long this_load,
 
                /* scale is effectively 1 << i now, and >> i divides by scale */
 
-               old_load = this_rq->cpu_load[i] - tickless_load;
+               old_load = this_rq->cpu_load[i];
                old_load = decay_load_missed(old_load, pending_updates - 1, i);
-               old_load += tickless_load;
+               if (tickless_load) {
+                       old_load -= decay_load_missed(tickless_load, pending_updates - 1, i);
+                       /*
+                        * old_load can never be a negative value because a
+                        * decayed tickless_load cannot be greater than the
+                        * original tickless_load.
+                        */
+                       old_load += tickless_load;
+               }
                new_load = this_load;
                /*
                 * Round up the averaging division if load is increasing. This
@@ -4484,6 +4566,25 @@ static unsigned long weighted_cpuload(const int cpu)
 }
 
 #ifdef CONFIG_NO_HZ_COMMON
+static void __update_cpu_load_nohz(struct rq *this_rq,
+                                  unsigned long curr_jiffies,
+                                  unsigned long load,
+                                  int active)
+{
+       unsigned long pending_updates;
+
+       pending_updates = curr_jiffies - this_rq->last_load_update_tick;
+       if (pending_updates) {
+               this_rq->last_load_update_tick = curr_jiffies;
+               /*
+                * In the regular NOHZ case, we were idle, this means load 0.
+                * In the NOHZ_FULL case, we were non-idle, we should consider
+                * its weighted load.
+                */
+               __update_cpu_load(this_rq, load, pending_updates, active);
+       }
+}
+
 /*
  * There is no sane way to deal with nohz on smp when using jiffies because the
  * cpu doing the jiffies update might drift wrt the cpu doing the jiffy reading
@@ -4501,22 +4602,15 @@ static unsigned long weighted_cpuload(const int cpu)
  * Called from nohz_idle_balance() to update the load ratings before doing the
  * idle balance.
  */
-static void update_idle_cpu_load(struct rq *this_rq)
+static void update_cpu_load_idle(struct rq *this_rq)
 {
-       unsigned long curr_jiffies = READ_ONCE(jiffies);
-       unsigned long load = weighted_cpuload(cpu_of(this_rq));
-       unsigned long pending_updates;
-
        /*
         * bail if there's load or we're actually up-to-date.
         */
-       if (load || curr_jiffies == this_rq->last_load_update_tick)
+       if (weighted_cpuload(cpu_of(this_rq)))
                return;
 
-       pending_updates = curr_jiffies - this_rq->last_load_update_tick;
-       this_rq->last_load_update_tick = curr_jiffies;
-
-       __update_cpu_load(this_rq, load, pending_updates, 0);
+       __update_cpu_load_nohz(this_rq, READ_ONCE(jiffies), 0, 0);
 }
 
 /*
@@ -4527,22 +4621,12 @@ void update_cpu_load_nohz(int active)
        struct rq *this_rq = this_rq();
        unsigned long curr_jiffies = READ_ONCE(jiffies);
        unsigned long load = active ? weighted_cpuload(cpu_of(this_rq)) : 0;
-       unsigned long pending_updates;
 
        if (curr_jiffies == this_rq->last_load_update_tick)
                return;
 
        raw_spin_lock(&this_rq->lock);
-       pending_updates = curr_jiffies - this_rq->last_load_update_tick;
-       if (pending_updates) {
-               this_rq->last_load_update_tick = curr_jiffies;
-               /*
-                * In the regular NOHZ case, we were idle, this means load 0.
-                * In the NOHZ_FULL case, we were non-idle, we should consider
-                * its weighted load.
-                */
-               __update_cpu_load(this_rq, load, pending_updates, active);
-       }
+       __update_cpu_load_nohz(this_rq, curr_jiffies, load, active);
        raw_spin_unlock(&this_rq->lock);
 }
 #endif /* CONFIG_NO_HZ */
@@ -4554,7 +4638,7 @@ void update_cpu_load_active(struct rq *this_rq)
 {
        unsigned long load = weighted_cpuload(cpu_of(this_rq));
        /*
-        * See the mess around update_idle_cpu_load() / update_cpu_load_nohz().
+        * See the mess around update_cpu_load_idle() / update_cpu_load_nohz().
         */
        this_rq->last_load_update_tick = jiffies;
        __update_cpu_load(this_rq, load, 1, 1);
@@ -7848,7 +7932,7 @@ static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle)
                if (time_after_eq(jiffies, rq->next_balance)) {
                        raw_spin_lock_irq(&rq->lock);
                        update_rq_clock(rq);
-                       update_idle_cpu_load(rq);
+                       update_cpu_load_idle(rq);
                        raw_spin_unlock_irq(&rq->lock);
                        rebalance_domains(rq, CPU_IDLE);
                }
@@ -8234,11 +8318,8 @@ void free_fair_sched_group(struct task_group *tg)
        for_each_possible_cpu(i) {
                if (tg->cfs_rq)
                        kfree(tg->cfs_rq[i]);
-               if (tg->se) {
-                       if (tg->se[i])
-                               remove_entity_load_avg(tg->se[i]);
+               if (tg->se)
                        kfree(tg->se[i]);
-               }
        }
 
        kfree(tg->cfs_rq);
@@ -8286,21 +8367,29 @@ err:
        return 0;
 }
 
-void unregister_fair_sched_group(struct task_group *tg, int cpu)
+void unregister_fair_sched_group(struct task_group *tg)
 {
-       struct rq *rq = cpu_rq(cpu);
        unsigned long flags;
+       struct rq *rq;
+       int cpu;
 
-       /*
-       * Only empty task groups can be destroyed; so we can speculatively
-       * check on_list without danger of it being re-added.
-       */
-       if (!tg->cfs_rq[cpu]->on_list)
-               return;
+       for_each_possible_cpu(cpu) {
+               if (tg->se[cpu])
+                       remove_entity_load_avg(tg->se[cpu]);
 
-       raw_spin_lock_irqsave(&rq->lock, flags);
-       list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
-       raw_spin_unlock_irqrestore(&rq->lock, flags);
+               /*
+                * Only empty task groups can be destroyed; so we can speculatively
+                * check on_list without danger of it being re-added.
+                */
+               if (!tg->cfs_rq[cpu]->on_list)
+                       continue;
+
+               rq = cpu_rq(cpu);
+
+               raw_spin_lock_irqsave(&rq->lock, flags);
+               list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
+               raw_spin_unlock_irqrestore(&rq->lock, flags);
+       }
 }
 
 void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
@@ -8382,7 +8471,7 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
        return 1;
 }
 
-void unregister_fair_sched_group(struct task_group *tg, int cpu) { }
+void unregister_fair_sched_group(struct task_group *tg) { }
 
 #endif /* CONFIG_FAIR_GROUP_SCHED */
 
index 544a7133cbd1df2a6ee4369231148fc0309eae11..bd12c6c714ecea0718565df4539304e3bf9d9e57 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/sched.h>
 #include <linux/cpu.h>
 #include <linux/cpuidle.h>
+#include <linux/cpuhotplug.h>
 #include <linux/tick.h>
 #include <linux/mm.h>
 #include <linux/stackprotector.h>
@@ -193,8 +194,6 @@ exit_idle:
        rcu_idle_exit();
 }
 
-DEFINE_PER_CPU(bool, cpu_dead_idle);
-
 /*
  * Generic idle loop implementation
  *
@@ -221,10 +220,7 @@ static void cpu_idle_loop(void)
                        rmb();
 
                        if (cpu_is_offline(smp_processor_id())) {
-                               rcu_cpu_notify(NULL, CPU_DYING_IDLE,
-                                              (void *)(long)smp_processor_id());
-                               smp_mb(); /* all activity before dead. */
-                               this_cpu_write(cpu_dead_idle, true);
+                               cpuhp_report_idle_dead();
                                arch_cpu_idle_dead();
                        }
 
@@ -291,5 +287,6 @@ void cpu_startup_entry(enum cpuhp_state state)
        boot_init_stack_canary();
 #endif
        arch_cpu_idle_prepare();
+       cpuhp_online_idle(state);
        cpu_idle_loop();
 }
index 8ec86abe0ea188369ee4e7efd21789d8cb127c14..c41ea7ac1764b831fd015531c3d8f40d445bf8ae 100644 (file)
@@ -58,7 +58,15 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
        raw_spin_lock(&rt_b->rt_runtime_lock);
        if (!rt_b->rt_period_active) {
                rt_b->rt_period_active = 1;
-               hrtimer_forward_now(&rt_b->rt_period_timer, rt_b->rt_period);
+               /*
+                * SCHED_DEADLINE updates the bandwidth, as a run away
+                * RT task with a DL task could hog a CPU. But DL does
+                * not reset the period. If a deadline task was running
+                * without an RT task running, it can cause RT tasks to
+                * throttle when they start up. Kick the timer right away
+                * to update the period.
+                */
+               hrtimer_forward_now(&rt_b->rt_period_timer, ns_to_ktime(0));
                hrtimer_start_expires(&rt_b->rt_period_timer, HRTIMER_MODE_ABS_PINNED);
        }
        raw_spin_unlock(&rt_b->rt_runtime_lock);
@@ -436,7 +444,7 @@ static void dequeue_top_rt_rq(struct rt_rq *rt_rq);
 
 static inline int on_rt_rq(struct sched_rt_entity *rt_se)
 {
-       return !list_empty(&rt_se->run_list);
+       return rt_se->on_rq;
 }
 
 #ifdef CONFIG_RT_GROUP_SCHED
@@ -482,8 +490,8 @@ static inline struct rt_rq *group_rt_rq(struct sched_rt_entity *rt_se)
        return rt_se->my_q;
 }
 
-static void enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head);
-static void dequeue_rt_entity(struct sched_rt_entity *rt_se);
+static void enqueue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flags);
+static void dequeue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flags);
 
 static void sched_rt_rq_enqueue(struct rt_rq *rt_rq)
 {
@@ -499,7 +507,7 @@ static void sched_rt_rq_enqueue(struct rt_rq *rt_rq)
                if (!rt_se)
                        enqueue_top_rt_rq(rt_rq);
                else if (!on_rt_rq(rt_se))
-                       enqueue_rt_entity(rt_se, false);
+                       enqueue_rt_entity(rt_se, 0);
 
                if (rt_rq->highest_prio.curr < curr->prio)
                        resched_curr(rq);
@@ -516,7 +524,7 @@ static void sched_rt_rq_dequeue(struct rt_rq *rt_rq)
        if (!rt_se)
                dequeue_top_rt_rq(rt_rq);
        else if (on_rt_rq(rt_se))
-               dequeue_rt_entity(rt_se);
+               dequeue_rt_entity(rt_se, 0);
 }
 
 static inline int rt_rq_throttled(struct rt_rq *rt_rq)
@@ -945,6 +953,10 @@ static void update_curr_rt(struct rq *rq)
        if (curr->sched_class != &rt_sched_class)
                return;
 
+       /* Kick cpufreq (see the comment in linux/cpufreq.h). */
+       if (cpu_of(rq) == smp_processor_id())
+               cpufreq_trigger_update(rq_clock(rq));
+
        delta_exec = rq_clock_task(rq) - curr->se.exec_start;
        if (unlikely((s64)delta_exec <= 0))
                return;
@@ -1141,6 +1153,20 @@ unsigned int rt_se_nr_running(struct sched_rt_entity *rt_se)
                return 1;
 }
 
+static inline
+unsigned int rt_se_rr_nr_running(struct sched_rt_entity *rt_se)
+{
+       struct rt_rq *group_rq = group_rt_rq(rt_se);
+       struct task_struct *tsk;
+
+       if (group_rq)
+               return group_rq->rr_nr_running;
+
+       tsk = rt_task_of(rt_se);
+
+       return (tsk->policy == SCHED_RR) ? 1 : 0;
+}
+
 static inline
 void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 {
@@ -1148,6 +1174,7 @@ void inc_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 
        WARN_ON(!rt_prio(prio));
        rt_rq->rt_nr_running += rt_se_nr_running(rt_se);
+       rt_rq->rr_nr_running += rt_se_rr_nr_running(rt_se);
 
        inc_rt_prio(rt_rq, prio);
        inc_rt_migration(rt_se, rt_rq);
@@ -1160,13 +1187,37 @@ void dec_rt_tasks(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
        WARN_ON(!rt_prio(rt_se_prio(rt_se)));
        WARN_ON(!rt_rq->rt_nr_running);
        rt_rq->rt_nr_running -= rt_se_nr_running(rt_se);
+       rt_rq->rr_nr_running -= rt_se_rr_nr_running(rt_se);
 
        dec_rt_prio(rt_rq, rt_se_prio(rt_se));
        dec_rt_migration(rt_se, rt_rq);
        dec_rt_group(rt_se, rt_rq);
 }
 
-static void __enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head)
+/*
+ * Change rt_se->run_list location unless SAVE && !MOVE
+ *
+ * assumes ENQUEUE/DEQUEUE flags match
+ */
+static inline bool move_entity(unsigned int flags)
+{
+       if ((flags & (DEQUEUE_SAVE | DEQUEUE_MOVE)) == DEQUEUE_SAVE)
+               return false;
+
+       return true;
+}
+
+static void __delist_rt_entity(struct sched_rt_entity *rt_se, struct rt_prio_array *array)
+{
+       list_del_init(&rt_se->run_list);
+
+       if (list_empty(array->queue + rt_se_prio(rt_se)))
+               __clear_bit(rt_se_prio(rt_se), array->bitmap);
+
+       rt_se->on_list = 0;
+}
+
+static void __enqueue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flags)
 {
        struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
        struct rt_prio_array *array = &rt_rq->active;
@@ -1179,26 +1230,37 @@ static void __enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head)
         * get throttled and the current group doesn't have any other
         * active members.
         */
-       if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running))
+       if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running)) {
+               if (rt_se->on_list)
+                       __delist_rt_entity(rt_se, array);
                return;
+       }
 
-       if (head)
-               list_add(&rt_se->run_list, queue);
-       else
-               list_add_tail(&rt_se->run_list, queue);
-       __set_bit(rt_se_prio(rt_se), array->bitmap);
+       if (move_entity(flags)) {
+               WARN_ON_ONCE(rt_se->on_list);
+               if (flags & ENQUEUE_HEAD)
+                       list_add(&rt_se->run_list, queue);
+               else
+                       list_add_tail(&rt_se->run_list, queue);
+
+               __set_bit(rt_se_prio(rt_se), array->bitmap);
+               rt_se->on_list = 1;
+       }
+       rt_se->on_rq = 1;
 
        inc_rt_tasks(rt_se, rt_rq);
 }
 
-static void __dequeue_rt_entity(struct sched_rt_entity *rt_se)
+static void __dequeue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flags)
 {
        struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
        struct rt_prio_array *array = &rt_rq->active;
 
-       list_del_init(&rt_se->run_list);
-       if (list_empty(array->queue + rt_se_prio(rt_se)))
-               __clear_bit(rt_se_prio(rt_se), array->bitmap);
+       if (move_entity(flags)) {
+               WARN_ON_ONCE(!rt_se->on_list);
+               __delist_rt_entity(rt_se, array);
+       }
+       rt_se->on_rq = 0;
 
        dec_rt_tasks(rt_se, rt_rq);
 }
@@ -1207,7 +1269,7 @@ static void __dequeue_rt_entity(struct sched_rt_entity *rt_se)
  * Because the prio of an upper entry depends on the lower
  * entries, we must remove entries top - down.
  */
-static void dequeue_rt_stack(struct sched_rt_entity *rt_se)
+static void dequeue_rt_stack(struct sched_rt_entity *rt_se, unsigned int flags)
 {
        struct sched_rt_entity *back = NULL;
 
@@ -1220,31 +1282,31 @@ static void dequeue_rt_stack(struct sched_rt_entity *rt_se)
 
        for (rt_se = back; rt_se; rt_se = rt_se->back) {
                if (on_rt_rq(rt_se))
-                       __dequeue_rt_entity(rt_se);
+                       __dequeue_rt_entity(rt_se, flags);
        }
 }
 
-static void enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head)
+static void enqueue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flags)
 {
        struct rq *rq = rq_of_rt_se(rt_se);
 
-       dequeue_rt_stack(rt_se);
+       dequeue_rt_stack(rt_se, flags);
        for_each_sched_rt_entity(rt_se)
-               __enqueue_rt_entity(rt_se, head);
+               __enqueue_rt_entity(rt_se, flags);
        enqueue_top_rt_rq(&rq->rt);
 }
 
-static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
+static void dequeue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flags)
 {
        struct rq *rq = rq_of_rt_se(rt_se);
 
-       dequeue_rt_stack(rt_se);
+       dequeue_rt_stack(rt_se, flags);
 
        for_each_sched_rt_entity(rt_se) {
                struct rt_rq *rt_rq = group_rt_rq(rt_se);
 
                if (rt_rq && rt_rq->rt_nr_running)
-                       __enqueue_rt_entity(rt_se, false);
+                       __enqueue_rt_entity(rt_se, flags);
        }
        enqueue_top_rt_rq(&rq->rt);
 }
@@ -1260,7 +1322,7 @@ enqueue_task_rt(struct rq *rq, struct task_struct *p, int flags)
        if (flags & ENQUEUE_WAKEUP)
                rt_se->timeout = 0;
 
-       enqueue_rt_entity(rt_se, flags & ENQUEUE_HEAD);
+       enqueue_rt_entity(rt_se, flags);
 
        if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
                enqueue_pushable_task(rq, p);
@@ -1271,7 +1333,7 @@ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int flags)
        struct sched_rt_entity *rt_se = &p->rt;
 
        update_curr_rt(rq);
-       dequeue_rt_entity(rt_se);
+       dequeue_rt_entity(rt_se, flags);
 
        dequeue_pushable_task(rq, p);
 }
index 10f16374df7f3a3f0f3dc0eb281559cacd223311..382848a24ed92beefdf2d49b6f72b16f0a279ade 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/sched/sysctl.h>
 #include <linux/sched/rt.h>
 #include <linux/sched/deadline.h>
+#include <linux/binfmts.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/stop_machine.h>
@@ -313,12 +314,11 @@ extern int tg_nop(struct task_group *tg, void *data);
 
 extern void free_fair_sched_group(struct task_group *tg);
 extern int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent);
-extern void unregister_fair_sched_group(struct task_group *tg, int cpu);
+extern void unregister_fair_sched_group(struct task_group *tg);
 extern void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
                        struct sched_entity *se, int cpu,
                        struct sched_entity *parent);
 extern void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b);
-extern int sched_group_set_shares(struct task_group *tg, unsigned long shares);
 
 extern void __refill_cfs_bandwidth_runtime(struct cfs_bandwidth *cfs_b);
 extern void start_cfs_bandwidth(struct cfs_bandwidth *cfs_b);
@@ -450,6 +450,7 @@ static inline int rt_bandwidth_enabled(void)
 struct rt_rq {
        struct rt_prio_array active;
        unsigned int rt_nr_running;
+       unsigned int rr_nr_running;
 #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED
        struct {
                int curr; /* highest queued rt task prio */
@@ -909,6 +910,18 @@ static inline unsigned int group_first_cpu(struct sched_group *group)
 
 extern int group_balance_cpu(struct sched_group *sg);
 
+#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL)
+void register_sched_domain_sysctl(void);
+void unregister_sched_domain_sysctl(void);
+#else
+static inline void register_sched_domain_sysctl(void)
+{
+}
+static inline void unregister_sched_domain_sysctl(void)
+{
+}
+#endif
+
 #else
 
 static inline void sched_ttwu_pending(void) { }
@@ -1022,6 +1035,7 @@ extern struct static_key sched_feat_keys[__SCHED_FEAT_NR];
 #endif /* SCHED_DEBUG && HAVE_JUMP_LABEL */
 
 extern struct static_key_false sched_numa_balancing;
+extern struct static_key_false sched_schedstats;
 
 static inline u64 global_rt_period(void)
 {
@@ -1130,18 +1144,40 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
 extern const int sched_prio_to_weight[40];
 extern const u32 sched_prio_to_wmult[40];
 
+/*
+ * {de,en}queue flags:
+ *
+ * DEQUEUE_SLEEP  - task is no longer runnable
+ * ENQUEUE_WAKEUP - task just became runnable
+ *
+ * SAVE/RESTORE - an otherwise spurious dequeue/enqueue, done to ensure tasks
+ *                are in a known state which allows modification. Such pairs
+ *                should preserve as much state as possible.
+ *
+ * MOVE - paired with SAVE/RESTORE, explicitly does not preserve the location
+ *        in the runqueue.
+ *
+ * ENQUEUE_HEAD      - place at front of runqueue (tail if not specified)
+ * ENQUEUE_REPLENISH - CBS (replenish runtime and postpone deadline)
+ * ENQUEUE_WAKING    - sched_class::task_waking was called
+ *
+ */
+
+#define DEQUEUE_SLEEP          0x01
+#define DEQUEUE_SAVE           0x02 /* matches ENQUEUE_RESTORE */
+#define DEQUEUE_MOVE           0x04 /* matches ENQUEUE_MOVE */
+
 #define ENQUEUE_WAKEUP         0x01
-#define ENQUEUE_HEAD           0x02
+#define ENQUEUE_RESTORE                0x02
+#define ENQUEUE_MOVE           0x04
+
+#define ENQUEUE_HEAD           0x08
+#define ENQUEUE_REPLENISH      0x10
 #ifdef CONFIG_SMP
-#define ENQUEUE_WAKING         0x04    /* sched_class::task_waking was called */
+#define ENQUEUE_WAKING         0x20
 #else
 #define ENQUEUE_WAKING         0x00
 #endif
-#define ENQUEUE_REPLENISH      0x08
-#define ENQUEUE_RESTORE        0x10
-
-#define DEQUEUE_SLEEP          0x01
-#define DEQUEUE_SAVE           0x02
 
 #define RETRY_TASK             ((void *)-1UL)
 
@@ -1278,6 +1314,35 @@ unsigned long to_ratio(u64 period, u64 runtime);
 
 extern void init_entity_runnable_average(struct sched_entity *se);
 
+#ifdef CONFIG_NO_HZ_FULL
+extern bool sched_can_stop_tick(struct rq *rq);
+
+/*
+ * Tick may be needed by tasks in the runqueue depending on their policy and
+ * requirements. If tick is needed, lets send the target an IPI to kick it out of
+ * nohz mode if necessary.
+ */
+static inline void sched_update_tick_dependency(struct rq *rq)
+{
+       int cpu;
+
+       if (!tick_nohz_full_enabled())
+               return;
+
+       cpu = cpu_of(rq);
+
+       if (!tick_nohz_full_cpu(cpu))
+               return;
+
+       if (sched_can_stop_tick(rq))
+               tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED);
+       else
+               tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED);
+}
+#else
+static inline void sched_update_tick_dependency(struct rq *rq) { }
+#endif
+
 static inline void add_nr_running(struct rq *rq, unsigned count)
 {
        unsigned prev_nr = rq->nr_running;
@@ -1289,26 +1354,16 @@ static inline void add_nr_running(struct rq *rq, unsigned count)
                if (!rq->rd->overload)
                        rq->rd->overload = true;
 #endif
-
-#ifdef CONFIG_NO_HZ_FULL
-               if (tick_nohz_full_cpu(rq->cpu)) {
-                       /*
-                        * Tick is needed if more than one task runs on a CPU.
-                        * Send the target an IPI to kick it out of nohz mode.
-                        *
-                        * We assume that IPI implies full memory barrier and the
-                        * new value of rq->nr_running is visible on reception
-                        * from the target.
-                        */
-                       tick_nohz_full_kick_cpu(rq->cpu);
-               }
-#endif
        }
+
+       sched_update_tick_dependency(rq);
 }
 
 static inline void sub_nr_running(struct rq *rq, unsigned count)
 {
        rq->nr_running -= count;
+       /* Check if we still need preemption */
+       sched_update_tick_dependency(rq);
 }
 
 static inline void rq_last_tick_reset(struct rq *rq)
@@ -1738,3 +1793,51 @@ static inline u64 irq_time_read(int cpu)
 }
 #endif /* CONFIG_64BIT */
 #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
+
+#ifdef CONFIG_CPU_FREQ
+DECLARE_PER_CPU(struct update_util_data *, cpufreq_update_util_data);
+
+/**
+ * cpufreq_update_util - Take a note about CPU utilization changes.
+ * @time: Current time.
+ * @util: Current utilization.
+ * @max: Utilization ceiling.
+ *
+ * This function is called by the scheduler on every invocation of
+ * update_load_avg() on the CPU whose utilization is being updated.
+ *
+ * It can only be called from RCU-sched read-side critical sections.
+ */
+static inline void cpufreq_update_util(u64 time, unsigned long util, unsigned long max)
+{
+       struct update_util_data *data;
+
+       data = rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data));
+       if (data)
+               data->func(data, time, util, max);
+}
+
+/**
+ * cpufreq_trigger_update - Trigger CPU performance state evaluation if needed.
+ * @time: Current time.
+ *
+ * The way cpufreq is currently arranged requires it to evaluate the CPU
+ * performance state (frequency/voltage) on a regular basis to prevent it from
+ * being stuck in a completely inadequate performance level for too long.
+ * That is not guaranteed to happen if the updates are only triggered from CFS,
+ * though, because they may not be coming in if RT or deadline tasks are active
+ * all the time (or there are RT and DL tasks only).
+ *
+ * As a workaround for that issue, this function is called by the RT and DL
+ * sched classes to trigger extra cpufreq updates to prevent it from stalling,
+ * but that really is a band-aid.  Going forward it should be replaced with
+ * solutions targeted more specifically at RT and DL tasks.
+ */
+static inline void cpufreq_trigger_update(u64 time)
+{
+       cpufreq_update_util(time, ULONG_MAX, 0);
+}
+#else
+static inline void cpufreq_update_util(u64 time, unsigned long util, unsigned long max) {}
+static inline void cpufreq_trigger_update(u64 time) {}
+#endif /* CONFIG_CPU_FREQ */
index b0fbc7632de5f9b13d8ccd2c42d73560c347669a..70b3b6a20fb0e362f4c816fe0f069c7c8576c7f4 100644 (file)
@@ -29,9 +29,10 @@ rq_sched_info_dequeued(struct rq *rq, unsigned long long delta)
        if (rq)
                rq->rq_sched_info.run_delay += delta;
 }
-# define schedstat_inc(rq, field)      do { (rq)->field++; } while (0)
-# define schedstat_add(rq, field, amt) do { (rq)->field += (amt); } while (0)
-# define schedstat_set(var, val)       do { var = (val); } while (0)
+# define schedstat_enabled()           static_branch_unlikely(&sched_schedstats)
+# define schedstat_inc(rq, field)      do { if (schedstat_enabled()) { (rq)->field++; } } while (0)
+# define schedstat_add(rq, field, amt) do { if (schedstat_enabled()) { (rq)->field += (amt); } } while (0)
+# define schedstat_set(var, val)       do { if (schedstat_enabled()) { var = (val); } } while (0)
 #else /* !CONFIG_SCHEDSTATS */
 static inline void
 rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
@@ -42,6 +43,7 @@ rq_sched_info_dequeued(struct rq *rq, unsigned long long delta)
 static inline void
 rq_sched_info_depart(struct rq *rq, unsigned long long delta)
 {}
+# define schedstat_enabled()           0
 # define schedstat_inc(rq, field)      do { } while (0)
 # define schedstat_add(rq, field, amt) do { } while (0)
 # define schedstat_set(var, val)       do { } while (0)
diff --git a/kernel/sched/swait.c b/kernel/sched/swait.c
new file mode 100644 (file)
index 0000000..82f0dff
--- /dev/null
@@ -0,0 +1,123 @@
+#include <linux/sched.h>
+#include <linux/swait.h>
+
+void __init_swait_queue_head(struct swait_queue_head *q, const char *name,
+                            struct lock_class_key *key)
+{
+       raw_spin_lock_init(&q->lock);
+       lockdep_set_class_and_name(&q->lock, key, name);
+       INIT_LIST_HEAD(&q->task_list);
+}
+EXPORT_SYMBOL(__init_swait_queue_head);
+
+/*
+ * The thing about the wake_up_state() return value; I think we can ignore it.
+ *
+ * If for some reason it would return 0, that means the previously waiting
+ * task is already running, so it will observe condition true (or has already).
+ */
+void swake_up_locked(struct swait_queue_head *q)
+{
+       struct swait_queue *curr;
+
+       if (list_empty(&q->task_list))
+               return;
+
+       curr = list_first_entry(&q->task_list, typeof(*curr), task_list);
+       wake_up_process(curr->task);
+       list_del_init(&curr->task_list);
+}
+EXPORT_SYMBOL(swake_up_locked);
+
+void swake_up(struct swait_queue_head *q)
+{
+       unsigned long flags;
+
+       if (!swait_active(q))
+               return;
+
+       raw_spin_lock_irqsave(&q->lock, flags);
+       swake_up_locked(q);
+       raw_spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL(swake_up);
+
+/*
+ * Does not allow usage from IRQ disabled, since we must be able to
+ * release IRQs to guarantee bounded hold time.
+ */
+void swake_up_all(struct swait_queue_head *q)
+{
+       struct swait_queue *curr;
+       LIST_HEAD(tmp);
+
+       if (!swait_active(q))
+               return;
+
+       raw_spin_lock_irq(&q->lock);
+       list_splice_init(&q->task_list, &tmp);
+       while (!list_empty(&tmp)) {
+               curr = list_first_entry(&tmp, typeof(*curr), task_list);
+
+               wake_up_state(curr->task, TASK_NORMAL);
+               list_del_init(&curr->task_list);
+
+               if (list_empty(&tmp))
+                       break;
+
+               raw_spin_unlock_irq(&q->lock);
+               raw_spin_lock_irq(&q->lock);
+       }
+       raw_spin_unlock_irq(&q->lock);
+}
+EXPORT_SYMBOL(swake_up_all);
+
+void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)
+{
+       wait->task = current;
+       if (list_empty(&wait->task_list))
+               list_add(&wait->task_list, &q->task_list);
+}
+
+void prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait, int state)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&q->lock, flags);
+       __prepare_to_swait(q, wait);
+       set_current_state(state);
+       raw_spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL(prepare_to_swait);
+
+long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state)
+{
+       if (signal_pending_state(state, current))
+               return -ERESTARTSYS;
+
+       prepare_to_swait(q, wait, state);
+
+       return 0;
+}
+EXPORT_SYMBOL(prepare_to_swait_event);
+
+void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait)
+{
+       __set_current_state(TASK_RUNNING);
+       if (!list_empty(&wait->task_list))
+               list_del_init(&wait->task_list);
+}
+
+void finish_swait(struct swait_queue_head *q, struct swait_queue *wait)
+{
+       unsigned long flags;
+
+       __set_current_state(TASK_RUNNING);
+
+       if (!list_empty_careful(&wait->task_list)) {
+               raw_spin_lock_irqsave(&q->lock, flags);
+               list_del_init(&wait->task_list);
+               raw_spin_unlock_irqrestore(&q->lock, flags);
+       }
+}
+EXPORT_SYMBOL(finish_swait);
index d903c02223afbaa2776b2610f00ae3def7de442e..74165443c240147cd701489298d2b552c8f46adf 100644 (file)
@@ -105,13 +105,12 @@ void __init call_function_init(void)
  * previous function call. For multi-cpu calls its even more interesting
  * as we'll have to ensure no other cpu is observing our csd.
  */
-static void csd_lock_wait(struct call_single_data *csd)
+static __always_inline void csd_lock_wait(struct call_single_data *csd)
 {
-       while (smp_load_acquire(&csd->flags) & CSD_FLAG_LOCK)
-               cpu_relax();
+       smp_cond_acquire(!(csd->flags & CSD_FLAG_LOCK));
 }
 
-static void csd_lock(struct call_single_data *csd)
+static __always_inline void csd_lock(struct call_single_data *csd)
 {
        csd_lock_wait(csd);
        csd->flags |= CSD_FLAG_LOCK;
@@ -124,7 +123,7 @@ static void csd_lock(struct call_single_data *csd)
        smp_wmb();
 }
 
-static void csd_unlock(struct call_single_data *csd)
+static __always_inline void csd_unlock(struct call_single_data *csd)
 {
        WARN_ON(!(csd->flags & CSD_FLAG_LOCK));
 
@@ -569,6 +568,7 @@ void __init smp_init(void)
        unsigned int cpu;
 
        idle_threads_init();
+       cpuhp_threads_init();
 
        /* FIXME: This should be done in userspace --RR */
        for_each_present_cpu(cpu) {
index d264f59bff56cb128edc68c5746280a2499752d5..13bc43d1fb227f8ee0c55a411460200a2ac3b067 100644 (file)
@@ -226,7 +226,7 @@ static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cp
                kthread_unpark(tsk);
 }
 
-void smpboot_unpark_threads(unsigned int cpu)
+int smpboot_unpark_threads(unsigned int cpu)
 {
        struct smp_hotplug_thread *cur;
 
@@ -235,6 +235,7 @@ void smpboot_unpark_threads(unsigned int cpu)
                if (cpumask_test_cpu(cpu, cur->cpumask))
                        smpboot_unpark_thread(cur, cpu);
        mutex_unlock(&smpboot_threads_lock);
+       return 0;
 }
 
 static void smpboot_park_thread(struct smp_hotplug_thread *ht, unsigned int cpu)
@@ -245,7 +246,7 @@ static void smpboot_park_thread(struct smp_hotplug_thread *ht, unsigned int cpu)
                kthread_park(tsk);
 }
 
-void smpboot_park_threads(unsigned int cpu)
+int smpboot_park_threads(unsigned int cpu)
 {
        struct smp_hotplug_thread *cur;
 
@@ -253,6 +254,7 @@ void smpboot_park_threads(unsigned int cpu)
        list_for_each_entry_reverse(cur, &hotplug_threads, list)
                smpboot_park_thread(cur, cpu);
        mutex_unlock(&smpboot_threads_lock);
+       return 0;
 }
 
 static void smpboot_destroy_threads(struct smp_hotplug_thread *ht)
index 72415a0eb955cd84130d2753c7704e8af7f30960..485b81cfab34fd2189203df091fe494a9d10efbd 100644 (file)
@@ -14,7 +14,9 @@ static inline void idle_threads_init(void) { }
 #endif
 
 int smpboot_create_threads(unsigned int cpu);
-void smpboot_park_threads(unsigned int cpu);
-void smpboot_unpark_threads(unsigned int cpu);
+int smpboot_park_threads(unsigned int cpu);
+int smpboot_unpark_threads(unsigned int cpu);
+
+void __init cpuhp_threads_init(void);
 
 #endif
index 479e4436f787646c92c42e0dbe2d940b366fbf60..8aae49dd7da862955f9ec49c65b0d80ad8effcd6 100644 (file)
@@ -116,9 +116,9 @@ void __local_bh_disable_ip(unsigned long ip, unsigned int cnt)
 
        if (preempt_count() == cnt) {
 #ifdef CONFIG_DEBUG_PREEMPT
-               current->preempt_disable_ip = get_parent_ip(CALLER_ADDR1);
+               current->preempt_disable_ip = get_lock_parent_ip();
 #endif
-               trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
+               trace_preempt_off(CALLER_ADDR0, get_lock_parent_ip());
        }
 }
 EXPORT_SYMBOL(__local_bh_disable_ip);
index 97715fd9e790ade5d7cd7731107de2dafb8272e3..f5102fabef7f525f6c79d66756336c262e465caa 100644 (file)
@@ -350,6 +350,17 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+#ifdef CONFIG_SCHEDSTATS
+       {
+               .procname       = "sched_schedstats",
+               .data           = NULL,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = sysctl_schedstats,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
+#endif /* CONFIG_SCHEDSTATS */
 #endif /* CONFIG_SMP */
 #ifdef CONFIG_NUMA_BALANCING
        {
@@ -505,7 +516,7 @@ static struct ctl_table kern_table[] = {
                .data           = &latencytop_enabled,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = sysctl_latencytop,
        },
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
index 664de539299b6ec3c8eb9a1565f02c14ae839379..56ece145a814a87ce172d96f32c17bf9d119b2f8 100644 (file)
@@ -323,13 +323,42 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs)
                /* cs is a watchdog. */
                if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
                        cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
+       }
+       spin_unlock_irqrestore(&watchdog_lock, flags);
+}
+
+static void clocksource_select_watchdog(bool fallback)
+{
+       struct clocksource *cs, *old_wd;
+       unsigned long flags;
+
+       spin_lock_irqsave(&watchdog_lock, flags);
+       /* save current watchdog */
+       old_wd = watchdog;
+       if (fallback)
+               watchdog = NULL;
+
+       list_for_each_entry(cs, &clocksource_list, list) {
+               /* cs is a clocksource to be watched. */
+               if (cs->flags & CLOCK_SOURCE_MUST_VERIFY)
+                       continue;
+
+               /* Skip current if we were requested for a fallback. */
+               if (fallback && cs == old_wd)
+                       continue;
+
                /* Pick the best watchdog. */
-               if (!watchdog || cs->rating > watchdog->rating) {
+               if (!watchdog || cs->rating > watchdog->rating)
                        watchdog = cs;
-                       /* Reset watchdog cycles */
-                       clocksource_reset_watchdog();
-               }
        }
+       /* If we failed to find a fallback restore the old one. */
+       if (!watchdog)
+               watchdog = old_wd;
+
+       /* If we changed the watchdog we need to reset cycles. */
+       if (watchdog != old_wd)
+               clocksource_reset_watchdog();
+
        /* Check if the watchdog timer needs to be started. */
        clocksource_start_watchdog();
        spin_unlock_irqrestore(&watchdog_lock, flags);
@@ -404,6 +433,7 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs)
                cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
 }
 
+static void clocksource_select_watchdog(bool fallback) { }
 static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { }
 static inline void clocksource_resume_watchdog(void) { }
 static inline int __clocksource_watchdog_kthread(void) { return 0; }
@@ -736,6 +766,7 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
        clocksource_enqueue(cs);
        clocksource_enqueue_watchdog(cs);
        clocksource_select();
+       clocksource_select_watchdog(false);
        mutex_unlock(&clocksource_mutex);
        return 0;
 }
@@ -758,6 +789,7 @@ void clocksource_change_rating(struct clocksource *cs, int rating)
        mutex_lock(&clocksource_mutex);
        __clocksource_change_rating(cs, rating);
        clocksource_select();
+       clocksource_select_watchdog(false);
        mutex_unlock(&clocksource_mutex);
 }
 EXPORT_SYMBOL(clocksource_change_rating);
@@ -767,12 +799,12 @@ EXPORT_SYMBOL(clocksource_change_rating);
  */
 static int clocksource_unbind(struct clocksource *cs)
 {
-       /*
-        * I really can't convince myself to support this on hardware
-        * designed by lobotomized monkeys.
-        */
-       if (clocksource_is_watchdog(cs))
-               return -EBUSY;
+       if (clocksource_is_watchdog(cs)) {
+               /* Select and try to install a replacement watchdog. */
+               clocksource_select_watchdog(true);
+               if (clocksource_is_watchdog(cs))
+                       return -EBUSY;
+       }
 
        if (cs == curr_clocksource) {
                /* Select and try to install a replacement clock source */
index 347fecf86a3fb2242e0a88b63975424f0293dde7..555e21f7b966c789f48ee4aa5fece85cc7db6768 100644 (file)
@@ -68,7 +68,7 @@ static struct clocksource clocksource_jiffies = {
        .name           = "jiffies",
        .rating         = 1, /* lowest valid rating*/
        .read           = jiffies_read,
-       .mask           = 0xffffffff, /*32bits*/
+       .mask           = CLOCKSOURCE_MASK(32),
        .mult           = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
        .shift          = JIFFIES_SHIFT,
        .max_cycles     = 10,
index f5e86d282d520a7881557de76096c1cf46f58fa7..1cafba860b08ceb6030fa2a1f237e3950a4e0aa7 100644 (file)
@@ -333,7 +333,6 @@ static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
        return err;
 }
 
-
 /*
  * Validate the clockid_t for a new CPU-clock timer, and initialize the timer.
  * This is called from sys_timer_create() and do_cpu_nanosleep() with the
@@ -517,6 +516,10 @@ static void arm_timer(struct k_itimer *timer)
                                cputime_expires->sched_exp = exp;
                        break;
                }
+               if (CPUCLOCK_PERTHREAD(timer->it_clock))
+                       tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
+               else
+                       tick_dep_set_signal(p->signal, TICK_DEP_BIT_POSIX_TIMER);
        }
 }
 
@@ -582,39 +585,6 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
        return 0;
 }
 
-#ifdef CONFIG_NO_HZ_FULL
-static void nohz_kick_work_fn(struct work_struct *work)
-{
-       tick_nohz_full_kick_all();
-}
-
-static DECLARE_WORK(nohz_kick_work, nohz_kick_work_fn);
-
-/*
- * We need the IPIs to be sent from sane process context.
- * The posix cpu timers are always set with irqs disabled.
- */
-static void posix_cpu_timer_kick_nohz(void)
-{
-       if (context_tracking_is_enabled())
-               schedule_work(&nohz_kick_work);
-}
-
-bool posix_cpu_timers_can_stop_tick(struct task_struct *tsk)
-{
-       if (!task_cputime_zero(&tsk->cputime_expires))
-               return false;
-
-       /* Check if cputimer is running. This is accessed without locking. */
-       if (READ_ONCE(tsk->signal->cputimer.running))
-               return false;
-
-       return true;
-}
-#else
-static inline void posix_cpu_timer_kick_nohz(void) { }
-#endif
-
 /*
  * Guts of sys_timer_settime for CPU timers.
  * This is called with the timer locked and interrupts disabled.
@@ -761,8 +731,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
                sample_to_timespec(timer->it_clock,
                                   old_incr, &old->it_interval);
        }
-       if (!ret)
-               posix_cpu_timer_kick_nohz();
+
        return ret;
 }
 
@@ -911,6 +880,8 @@ static void check_thread_timers(struct task_struct *tsk,
                        __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
                }
        }
+       if (task_cputime_zero(tsk_expires))
+               tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
 static inline void stop_process_timers(struct signal_struct *sig)
@@ -919,6 +890,7 @@ static inline void stop_process_timers(struct signal_struct *sig)
 
        /* Turn off cputimer->running. This is done without locking. */
        WRITE_ONCE(cputimer->running, false);
+       tick_dep_clear_signal(sig, TICK_DEP_BIT_POSIX_TIMER);
 }
 
 static u32 onecputick;
@@ -1095,8 +1067,6 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
        arm_timer(timer);
        unlock_task_sighand(p, &flags);
 
-       /* Kick full dynticks CPUs in case they need to tick on the new timer */
-       posix_cpu_timer_kick_nohz();
 out:
        timer->it_overrun_last = timer->it_overrun;
        timer->it_overrun = -1;
@@ -1270,7 +1240,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
                }
 
                if (!*newval)
-                       goto out;
+                       return;
                *newval += now;
        }
 
@@ -1288,8 +1258,8 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
                        tsk->signal->cputime_expires.virt_exp = *newval;
                break;
        }
-out:
-       posix_cpu_timer_kick_nohz();
+
+       tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);
 }
 
 static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
index 0b17424349eb4dafd76a2cf588748988ce51a295..969e6704c3c9a24754d0da31e0dd028257425ddd 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/module.h>
 #include <linux/irq_work.h>
 #include <linux/posix-timers.h>
-#include <linux/perf_event.h>
 #include <linux/context_tracking.h>
 
 #include <asm/irq_regs.h>
@@ -158,54 +157,63 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs)
 cpumask_var_t tick_nohz_full_mask;
 cpumask_var_t housekeeping_mask;
 bool tick_nohz_full_running;
+static unsigned long tick_dep_mask;
 
-static bool can_stop_full_tick(void)
+static void trace_tick_dependency(unsigned long dep)
+{
+       if (dep & TICK_DEP_MASK_POSIX_TIMER) {
+               trace_tick_stop(0, TICK_DEP_MASK_POSIX_TIMER);
+               return;
+       }
+
+       if (dep & TICK_DEP_MASK_PERF_EVENTS) {
+               trace_tick_stop(0, TICK_DEP_MASK_PERF_EVENTS);
+               return;
+       }
+
+       if (dep & TICK_DEP_MASK_SCHED) {
+               trace_tick_stop(0, TICK_DEP_MASK_SCHED);
+               return;
+       }
+
+       if (dep & TICK_DEP_MASK_CLOCK_UNSTABLE)
+               trace_tick_stop(0, TICK_DEP_MASK_CLOCK_UNSTABLE);
+}
+
+static bool can_stop_full_tick(struct tick_sched *ts)
 {
        WARN_ON_ONCE(!irqs_disabled());
 
-       if (!sched_can_stop_tick()) {
-               trace_tick_stop(0, "more than 1 task in runqueue\n");
+       if (tick_dep_mask) {
+               trace_tick_dependency(tick_dep_mask);
                return false;
        }
 
-       if (!posix_cpu_timers_can_stop_tick(current)) {
-               trace_tick_stop(0, "posix timers running\n");
+       if (ts->tick_dep_mask) {
+               trace_tick_dependency(ts->tick_dep_mask);
                return false;
        }
 
-       if (!perf_event_can_stop_tick()) {
-               trace_tick_stop(0, "perf events running\n");
+       if (current->tick_dep_mask) {
+               trace_tick_dependency(current->tick_dep_mask);
                return false;
        }
 
-       /* sched_clock_tick() needs us? */
-#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
-       /*
-        * TODO: kick full dynticks CPUs when
-        * sched_clock_stable is set.
-        */
-       if (!sched_clock_stable()) {
-               trace_tick_stop(0, "unstable sched clock\n");
-               /*
-                * Don't allow the user to think they can get
-                * full NO_HZ with this machine.
-                */
-               WARN_ONCE(tick_nohz_full_running,
-                         "NO_HZ FULL will not work with unstable sched clock");
+       if (current->signal->tick_dep_mask) {
+               trace_tick_dependency(current->signal->tick_dep_mask);
                return false;
        }
-#endif
 
        return true;
 }
 
-static void nohz_full_kick_work_func(struct irq_work *work)
+static void nohz_full_kick_func(struct irq_work *work)
 {
        /* Empty, the tick restart happens on tick_nohz_irq_exit() */
 }
 
 static DEFINE_PER_CPU(struct irq_work, nohz_full_kick_work) = {
-       .func = nohz_full_kick_work_func,
+       .func = nohz_full_kick_func,
 };
 
 /*
@@ -214,7 +222,7 @@ static DEFINE_PER_CPU(struct irq_work, nohz_full_kick_work) = {
  * This kick, unlike tick_nohz_full_kick_cpu() and tick_nohz_full_kick_all(),
  * is NMI safe.
  */
-void tick_nohz_full_kick(void)
+static void tick_nohz_full_kick(void)
 {
        if (!tick_nohz_full_cpu(smp_processor_id()))
                return;
@@ -234,27 +242,112 @@ void tick_nohz_full_kick_cpu(int cpu)
        irq_work_queue_on(&per_cpu(nohz_full_kick_work, cpu), cpu);
 }
 
-static void nohz_full_kick_ipi(void *info)
-{
-       /* Empty, the tick restart happens on tick_nohz_irq_exit() */
-}
-
 /*
  * Kick all full dynticks CPUs in order to force these to re-evaluate
  * their dependency on the tick and restart it if necessary.
  */
-void tick_nohz_full_kick_all(void)
+static void tick_nohz_full_kick_all(void)
 {
+       int cpu;
+
        if (!tick_nohz_full_running)
                return;
 
        preempt_disable();
-       smp_call_function_many(tick_nohz_full_mask,
-                              nohz_full_kick_ipi, NULL, false);
-       tick_nohz_full_kick();
+       for_each_cpu_and(cpu, tick_nohz_full_mask, cpu_online_mask)
+               tick_nohz_full_kick_cpu(cpu);
        preempt_enable();
 }
 
+static void tick_nohz_dep_set_all(unsigned long *dep,
+                                 enum tick_dep_bits bit)
+{
+       unsigned long prev;
+
+       prev = fetch_or(dep, BIT_MASK(bit));
+       if (!prev)
+               tick_nohz_full_kick_all();
+}
+
+/*
+ * Set a global tick dependency. Used by perf events that rely on freq and
+ * by unstable clock.
+ */
+void tick_nohz_dep_set(enum tick_dep_bits bit)
+{
+       tick_nohz_dep_set_all(&tick_dep_mask, bit);
+}
+
+void tick_nohz_dep_clear(enum tick_dep_bits bit)
+{
+       clear_bit(bit, &tick_dep_mask);
+}
+
+/*
+ * Set per-CPU tick dependency. Used by scheduler and perf events in order to
+ * manage events throttling.
+ */
+void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit)
+{
+       unsigned long prev;
+       struct tick_sched *ts;
+
+       ts = per_cpu_ptr(&tick_cpu_sched, cpu);
+
+       prev = fetch_or(&ts->tick_dep_mask, BIT_MASK(bit));
+       if (!prev) {
+               preempt_disable();
+               /* Perf needs local kick that is NMI safe */
+               if (cpu == smp_processor_id()) {
+                       tick_nohz_full_kick();
+               } else {
+                       /* Remote irq work not NMI-safe */
+                       if (!WARN_ON_ONCE(in_nmi()))
+                               tick_nohz_full_kick_cpu(cpu);
+               }
+               preempt_enable();
+       }
+}
+
+void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit)
+{
+       struct tick_sched *ts = per_cpu_ptr(&tick_cpu_sched, cpu);
+
+       clear_bit(bit, &ts->tick_dep_mask);
+}
+
+/*
+ * Set a per-task tick dependency. Posix CPU timers need this in order to elapse
+ * per task timers.
+ */
+void tick_nohz_dep_set_task(struct task_struct *tsk, enum tick_dep_bits bit)
+{
+       /*
+        * We could optimize this with just kicking the target running the task
+        * if that noise matters for nohz full users.
+        */
+       tick_nohz_dep_set_all(&tsk->tick_dep_mask, bit);
+}
+
+void tick_nohz_dep_clear_task(struct task_struct *tsk, enum tick_dep_bits bit)
+{
+       clear_bit(bit, &tsk->tick_dep_mask);
+}
+
+/*
+ * Set a per-taskgroup tick dependency. Posix CPU timers need this in order to elapse
+ * per process timers.
+ */
+void tick_nohz_dep_set_signal(struct signal_struct *sig, enum tick_dep_bits bit)
+{
+       tick_nohz_dep_set_all(&sig->tick_dep_mask, bit);
+}
+
+void tick_nohz_dep_clear_signal(struct signal_struct *sig, enum tick_dep_bits bit)
+{
+       clear_bit(bit, &sig->tick_dep_mask);
+}
+
 /*
  * Re-evaluate the need for the tick as we switch the current task.
  * It might need the tick due to per task/process properties:
@@ -263,15 +356,19 @@ void tick_nohz_full_kick_all(void)
 void __tick_nohz_task_switch(void)
 {
        unsigned long flags;
+       struct tick_sched *ts;
 
        local_irq_save(flags);
 
        if (!tick_nohz_full_cpu(smp_processor_id()))
                goto out;
 
-       if (tick_nohz_tick_stopped() && !can_stop_full_tick())
-               tick_nohz_full_kick();
+       ts = this_cpu_ptr(&tick_cpu_sched);
 
+       if (ts->tick_stopped) {
+               if (current->tick_dep_mask || current->signal->tick_dep_mask)
+                       tick_nohz_full_kick();
+       }
 out:
        local_irq_restore(flags);
 }
@@ -689,7 +786,7 @@ static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
 
                ts->last_tick = hrtimer_get_expires(&ts->sched_timer);
                ts->tick_stopped = 1;
-               trace_tick_stop(1, " ");
+               trace_tick_stop(1, TICK_DEP_MASK_NONE);
        }
 
        /*
@@ -740,7 +837,7 @@ static void tick_nohz_full_update_tick(struct tick_sched *ts)
        if (!ts->tick_stopped && ts->nohz_mode == NOHZ_MODE_INACTIVE)
                return;
 
-       if (can_stop_full_tick())
+       if (can_stop_full_tick(ts))
                tick_nohz_stop_sched_tick(ts, ktime_get(), cpu);
        else if (ts->tick_stopped)
                tick_nohz_restart_sched_tick(ts, ktime_get(), 1);
index a4a8d4e9baa13f37cbdceff5ffedc3bfc5fd8e4c..eb4e32566a832c27afc6f388121521abab5c5d9b 100644 (file)
@@ -60,6 +60,7 @@ struct tick_sched {
        u64                             next_timer;
        ktime_t                         idle_expires;
        int                             do_timer_last;
+       unsigned long                   tick_dep_mask;
 };
 
 extern struct tick_sched *tick_get_tick_sched(int cpu);
index 34b4cedfa80da0de969c12d1551620513f93d02c..9c629bbed572b0cbe6710a936af5fbc52440cb03 100644 (file)
@@ -233,6 +233,7 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
        u64 tmp, ntpinterval;
        struct clocksource *old_clock;
 
+       ++tk->cs_was_changed_seq;
        old_clock = tk->tkr_mono.clock;
        tk->tkr_mono.clock = clock;
        tk->tkr_mono.read = clock->read;
@@ -298,17 +299,34 @@ u32 (*arch_gettimeoffset)(void) = default_arch_gettimeoffset;
 static inline u32 arch_gettimeoffset(void) { return 0; }
 #endif
 
+static inline s64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
+                                         cycle_t delta)
+{
+       s64 nsec;
+
+       nsec = delta * tkr->mult + tkr->xtime_nsec;
+       nsec >>= tkr->shift;
+
+       /* If arch requires, add in get_arch_timeoffset() */
+       return nsec + arch_gettimeoffset();
+}
+
 static inline s64 timekeeping_get_ns(struct tk_read_base *tkr)
 {
        cycle_t delta;
-       s64 nsec;
 
        delta = timekeeping_get_delta(tkr);
+       return timekeeping_delta_to_ns(tkr, delta);
+}
 
-       nsec = (delta * tkr->mult + tkr->xtime_nsec) >> tkr->shift;
+static inline s64 timekeeping_cycles_to_ns(struct tk_read_base *tkr,
+                                           cycle_t cycles)
+{
+       cycle_t delta;
 
-       /* If arch requires, add in get_arch_timeoffset() */
-       return nsec + arch_gettimeoffset();
+       /* calculate the delta since the last update_wall_time */
+       delta = clocksource_delta(cycles, tkr->cycle_last, tkr->mask);
+       return timekeeping_delta_to_ns(tkr, delta);
 }
 
 /**
@@ -857,44 +875,262 @@ time64_t __ktime_get_real_seconds(void)
        return tk->xtime_sec;
 }
 
+/**
+ * ktime_get_snapshot - snapshots the realtime/monotonic raw clocks with counter
+ * @systime_snapshot:  pointer to struct receiving the system time snapshot
+ */
+void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot)
+{
+       struct timekeeper *tk = &tk_core.timekeeper;
+       unsigned long seq;
+       ktime_t base_raw;
+       ktime_t base_real;
+       s64 nsec_raw;
+       s64 nsec_real;
+       cycle_t now;
 
-#ifdef CONFIG_NTP_PPS
+       WARN_ON_ONCE(timekeeping_suspended);
+
+       do {
+               seq = read_seqcount_begin(&tk_core.seq);
+
+               now = tk->tkr_mono.read(tk->tkr_mono.clock);
+               systime_snapshot->cs_was_changed_seq = tk->cs_was_changed_seq;
+               systime_snapshot->clock_was_set_seq = tk->clock_was_set_seq;
+               base_real = ktime_add(tk->tkr_mono.base,
+                                     tk_core.timekeeper.offs_real);
+               base_raw = tk->tkr_raw.base;
+               nsec_real = timekeeping_cycles_to_ns(&tk->tkr_mono, now);
+               nsec_raw  = timekeeping_cycles_to_ns(&tk->tkr_raw, now);
+       } while (read_seqcount_retry(&tk_core.seq, seq));
+
+       systime_snapshot->cycles = now;
+       systime_snapshot->real = ktime_add_ns(base_real, nsec_real);
+       systime_snapshot->raw = ktime_add_ns(base_raw, nsec_raw);
+}
+EXPORT_SYMBOL_GPL(ktime_get_snapshot);
+
+/* Scale base by mult/div checking for overflow */
+static int scale64_check_overflow(u64 mult, u64 div, u64 *base)
+{
+       u64 tmp, rem;
+
+       tmp = div64_u64_rem(*base, div, &rem);
+
+       if (((int)sizeof(u64)*8 - fls64(mult) < fls64(tmp)) ||
+           ((int)sizeof(u64)*8 - fls64(mult) < fls64(rem)))
+               return -EOVERFLOW;
+       tmp *= mult;
+       rem *= mult;
+
+       do_div(rem, div);
+       *base = tmp + rem;
+       return 0;
+}
 
 /**
- * ktime_get_raw_and_real_ts64 - get day and raw monotonic time in timespec format
- * @ts_raw:    pointer to the timespec to be set to raw monotonic time
- * @ts_real:   pointer to the timespec to be set to the time of day
+ * adjust_historical_crosststamp - adjust crosstimestamp previous to current interval
+ * @history:                   Snapshot representing start of history
+ * @partial_history_cycles:    Cycle offset into history (fractional part)
+ * @total_history_cycles:      Total history length in cycles
+ * @discontinuity:             True indicates clock was set on history period
+ * @ts:                                Cross timestamp that should be adjusted using
+ *     partial/total ratio
  *
- * This function reads both the time of day and raw monotonic time at the
- * same time atomically and stores the resulting timestamps in timespec
- * format.
+ * Helper function used by get_device_system_crosststamp() to correct the
+ * crosstimestamp corresponding to the start of the current interval to the
+ * system counter value (timestamp point) provided by the driver. The
+ * total_history_* quantities are the total history starting at the provided
+ * reference point and ending at the start of the current interval. The cycle
+ * count between the driver timestamp point and the start of the current
+ * interval is partial_history_cycles.
  */
-void ktime_get_raw_and_real_ts64(struct timespec64 *ts_raw, struct timespec64 *ts_real)
+static int adjust_historical_crosststamp(struct system_time_snapshot *history,
+                                        cycle_t partial_history_cycles,
+                                        cycle_t total_history_cycles,
+                                        bool discontinuity,
+                                        struct system_device_crosststamp *ts)
 {
        struct timekeeper *tk = &tk_core.timekeeper;
-       unsigned long seq;
-       s64 nsecs_raw, nsecs_real;
+       u64 corr_raw, corr_real;
+       bool interp_forward;
+       int ret;
 
-       WARN_ON_ONCE(timekeeping_suspended);
+       if (total_history_cycles == 0 || partial_history_cycles == 0)
+               return 0;
+
+       /* Interpolate shortest distance from beginning or end of history */
+       interp_forward = partial_history_cycles > total_history_cycles/2 ?
+               true : false;
+       partial_history_cycles = interp_forward ?
+               total_history_cycles - partial_history_cycles :
+               partial_history_cycles;
+
+       /*
+        * Scale the monotonic raw time delta by:
+        *      partial_history_cycles / total_history_cycles
+        */
+       corr_raw = (u64)ktime_to_ns(
+               ktime_sub(ts->sys_monoraw, history->raw));
+       ret = scale64_check_overflow(partial_history_cycles,
+                                    total_history_cycles, &corr_raw);
+       if (ret)
+               return ret;
+
+       /*
+        * If there is a discontinuity in the history, scale monotonic raw
+        *      correction by:
+        *      mult(real)/mult(raw) yielding the realtime correction
+        * Otherwise, calculate the realtime correction similar to monotonic
+        *      raw calculation
+        */
+       if (discontinuity) {
+               corr_real = mul_u64_u32_div
+                       (corr_raw, tk->tkr_mono.mult, tk->tkr_raw.mult);
+       } else {
+               corr_real = (u64)ktime_to_ns(
+                       ktime_sub(ts->sys_realtime, history->real));
+               ret = scale64_check_overflow(partial_history_cycles,
+                                            total_history_cycles, &corr_real);
+               if (ret)
+                       return ret;
+       }
+
+       /* Fixup monotonic raw and real time time values */
+       if (interp_forward) {
+               ts->sys_monoraw = ktime_add_ns(history->raw, corr_raw);
+               ts->sys_realtime = ktime_add_ns(history->real, corr_real);
+       } else {
+               ts->sys_monoraw = ktime_sub_ns(ts->sys_monoraw, corr_raw);
+               ts->sys_realtime = ktime_sub_ns(ts->sys_realtime, corr_real);
+       }
+
+       return 0;
+}
+
+/*
+ * cycle_between - true if test occurs chronologically between before and after
+ */
+static bool cycle_between(cycle_t before, cycle_t test, cycle_t after)
+{
+       if (test > before && test < after)
+               return true;
+       if (test < before && before > after)
+               return true;
+       return false;
+}
+
+/**
+ * get_device_system_crosststamp - Synchronously capture system/device timestamp
+ * @get_time_fn:       Callback to get simultaneous device time and
+ *     system counter from the device driver
+ * @ctx:               Context passed to get_time_fn()
+ * @history_begin:     Historical reference point used to interpolate system
+ *     time when counter provided by the driver is before the current interval
+ * @xtstamp:           Receives simultaneously captured system and device time
+ *
+ * Reads a timestamp from a device and correlates it to system time
+ */
+int get_device_system_crosststamp(int (*get_time_fn)
+                                 (ktime_t *device_time,
+                                  struct system_counterval_t *sys_counterval,
+                                  void *ctx),
+                                 void *ctx,
+                                 struct system_time_snapshot *history_begin,
+                                 struct system_device_crosststamp *xtstamp)
+{
+       struct system_counterval_t system_counterval;
+       struct timekeeper *tk = &tk_core.timekeeper;
+       cycle_t cycles, now, interval_start;
+       unsigned int clock_was_set_seq = 0;
+       ktime_t base_real, base_raw;
+       s64 nsec_real, nsec_raw;
+       u8 cs_was_changed_seq;
+       unsigned long seq;
+       bool do_interp;
+       int ret;
 
        do {
                seq = read_seqcount_begin(&tk_core.seq);
+               /*
+                * Try to synchronously capture device time and a system
+                * counter value calling back into the device driver
+                */
+               ret = get_time_fn(&xtstamp->device, &system_counterval, ctx);
+               if (ret)
+                       return ret;
+
+               /*
+                * Verify that the clocksource associated with the captured
+                * system counter value is the same as the currently installed
+                * timekeeper clocksource
+                */
+               if (tk->tkr_mono.clock != system_counterval.cs)
+                       return -ENODEV;
+               cycles = system_counterval.cycles;
 
-               *ts_raw = tk->raw_time;
-               ts_real->tv_sec = tk->xtime_sec;
-               ts_real->tv_nsec = 0;
+               /*
+                * Check whether the system counter value provided by the
+                * device driver is on the current timekeeping interval.
+                */
+               now = tk->tkr_mono.read(tk->tkr_mono.clock);
+               interval_start = tk->tkr_mono.cycle_last;
+               if (!cycle_between(interval_start, cycles, now)) {
+                       clock_was_set_seq = tk->clock_was_set_seq;
+                       cs_was_changed_seq = tk->cs_was_changed_seq;
+                       cycles = interval_start;
+                       do_interp = true;
+               } else {
+                       do_interp = false;
+               }
 
-               nsecs_raw  = timekeeping_get_ns(&tk->tkr_raw);
-               nsecs_real = timekeeping_get_ns(&tk->tkr_mono);
+               base_real = ktime_add(tk->tkr_mono.base,
+                                     tk_core.timekeeper.offs_real);
+               base_raw = tk->tkr_raw.base;
 
+               nsec_real = timekeeping_cycles_to_ns(&tk->tkr_mono,
+                                                    system_counterval.cycles);
+               nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw,
+                                                   system_counterval.cycles);
        } while (read_seqcount_retry(&tk_core.seq, seq));
 
-       timespec64_add_ns(ts_raw, nsecs_raw);
-       timespec64_add_ns(ts_real, nsecs_real);
-}
-EXPORT_SYMBOL(ktime_get_raw_and_real_ts64);
+       xtstamp->sys_realtime = ktime_add_ns(base_real, nsec_real);
+       xtstamp->sys_monoraw = ktime_add_ns(base_raw, nsec_raw);
 
-#endif /* CONFIG_NTP_PPS */
+       /*
+        * Interpolate if necessary, adjusting back from the start of the
+        * current interval
+        */
+       if (do_interp) {
+               cycle_t partial_history_cycles, total_history_cycles;
+               bool discontinuity;
+
+               /*
+                * Check that the counter value occurs after the provided
+                * history reference and that the history doesn't cross a
+                * clocksource change
+                */
+               if (!history_begin ||
+                   !cycle_between(history_begin->cycles,
+                                  system_counterval.cycles, cycles) ||
+                   history_begin->cs_was_changed_seq != cs_was_changed_seq)
+                       return -EINVAL;
+               partial_history_cycles = cycles - system_counterval.cycles;
+               total_history_cycles = cycles - history_begin->cycles;
+               discontinuity =
+                       history_begin->clock_was_set_seq != clock_was_set_seq;
+
+               ret = adjust_historical_crosststamp(history_begin,
+                                                   partial_history_cycles,
+                                                   total_history_cycles,
+                                                   discontinuity, xtstamp);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(get_device_system_crosststamp);
 
 /**
  * do_gettimeofday - Returns the time of day in a timeval
index eb4220a132ecd1be9002cf35edf82870969d6c82..81b87451c0ea145f93ba41e47dacc6a2acec8189 100644 (file)
@@ -15,4 +15,5 @@
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(suspend_resume);
 EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_idle);
+EXPORT_TRACEPOINT_SYMBOL_GPL(powernv_throttle);
 
index f333e57c4614a2a6aaac04061003f73cd3a6d844..05ddc0820771eb7bc456aab9e2f0e5167ce7f023 100644 (file)
@@ -97,16 +97,16 @@ trace_find_event_field(struct trace_event_call *call, char *name)
        struct ftrace_event_field *field;
        struct list_head *head;
 
-       field = __find_event_field(&ftrace_generic_fields, name);
+       head = trace_get_fields(call);
+       field = __find_event_field(head, name);
        if (field)
                return field;
 
-       field = __find_event_field(&ftrace_common_fields, name);
+       field = __find_event_field(&ftrace_generic_fields, name);
        if (field)
                return field;
 
-       head = trace_get_fields(call);
-       return __find_event_field(head, name);
+       return __find_event_field(&ftrace_common_fields, name);
 }
 
 static int __trace_define_field(struct list_head *head, const char *type,
@@ -171,8 +171,10 @@ static int trace_define_generic_fields(void)
 {
        int ret;
 
-       __generic_field(int, cpu, FILTER_OTHER);
-       __generic_field(char *, comm, FILTER_PTR_STRING);
+       __generic_field(int, CPU, FILTER_CPU);
+       __generic_field(int, cpu, FILTER_CPU);
+       __generic_field(char *, COMM, FILTER_COMM);
+       __generic_field(char *, comm, FILTER_COMM);
 
        return ret;
 }
@@ -869,7 +871,8 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
                 * The ftrace subsystem is for showing formats only.
                 * They can not be enabled or disabled via the event files.
                 */
-               if (call->class && call->class->reg)
+               if (call->class && call->class->reg &&
+                   !(call->flags & TRACE_EVENT_FL_IGNORE_ENABLE))
                        return file;
        }
 
index f93a219b18daaa92ed314ad7ac4ba8e0ed3c4c09..6816302542b28158a4756373f5b3a57ed1a907fa 100644 (file)
@@ -1043,13 +1043,14 @@ static int init_pred(struct filter_parse_state *ps,
                return -EINVAL;
        }
 
-       if (is_string_field(field)) {
+       if (field->filter_type == FILTER_COMM) {
+               filter_build_regex(pred);
+               fn = filter_pred_comm;
+               pred->regex.field_len = TASK_COMM_LEN;
+       } else if (is_string_field(field)) {
                filter_build_regex(pred);
 
-               if (!strcmp(field->name, "comm")) {
-                       fn = filter_pred_comm;
-                       pred->regex.field_len = TASK_COMM_LEN;
-               } else if (field->filter_type == FILTER_STATIC_STRING) {
+               if (field->filter_type == FILTER_STATIC_STRING) {
                        fn = filter_pred_string;
                        pred->regex.field_len = field->size;
                } else if (field->filter_type == FILTER_DYN_STRING)
@@ -1072,7 +1073,7 @@ static int init_pred(struct filter_parse_state *ps,
                }
                pred->val = val;
 
-               if (!strcmp(field->name, "cpu"))
+               if (field->filter_type == FILTER_CPU)
                        fn = filter_pred_cpu;
                else
                        fn = select_comparison_fn(pred->op, field->size,
index c9956440d0e609c51e2032f6f625c4061ba764a4..21b81a41dae572a3263c7b731efa97a2d25872e9 100644 (file)
@@ -30,7 +30,7 @@
 struct trace_kprobe {
        struct list_head        list;
        struct kretprobe        rp;     /* Use rp.kp for kprobe use */
-       unsigned long           nhit;
+       unsigned long __percpu *nhit;
        const char              *symbol;        /* symbol name */
        struct trace_probe      tp;
 };
@@ -274,6 +274,10 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
        if (!tk)
                return ERR_PTR(ret);
 
+       tk->nhit = alloc_percpu(unsigned long);
+       if (!tk->nhit)
+               goto error;
+
        if (symbol) {
                tk->symbol = kstrdup(symbol, GFP_KERNEL);
                if (!tk->symbol)
@@ -313,6 +317,7 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
 error:
        kfree(tk->tp.call.name);
        kfree(tk->symbol);
+       free_percpu(tk->nhit);
        kfree(tk);
        return ERR_PTR(ret);
 }
@@ -327,6 +332,7 @@ static void free_trace_kprobe(struct trace_kprobe *tk)
        kfree(tk->tp.call.class->system);
        kfree(tk->tp.call.name);
        kfree(tk->symbol);
+       free_percpu(tk->nhit);
        kfree(tk);
 }
 
@@ -874,9 +880,14 @@ static const struct file_operations kprobe_events_ops = {
 static int probes_profile_seq_show(struct seq_file *m, void *v)
 {
        struct trace_kprobe *tk = v;
+       unsigned long nhit = 0;
+       int cpu;
+
+       for_each_possible_cpu(cpu)
+               nhit += *per_cpu_ptr(tk->nhit, cpu);
 
        seq_printf(m, "  %-44s %15lu %15lu\n",
-                  trace_event_name(&tk->tp.call), tk->nhit,
+                  trace_event_name(&tk->tp.call), nhit,
                   tk->rp.kp.nmissed);
 
        return 0;
@@ -1225,7 +1236,7 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
 {
        struct trace_kprobe *tk = container_of(kp, struct trace_kprobe, rp.kp);
 
-       tk->nhit++;
+       raw_cpu_inc(*tk->nhit);
 
        if (tk->tp.flags & TP_FLAG_TRACE)
                kprobe_trace_func(tk, regs);
@@ -1242,7 +1253,7 @@ kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
        struct trace_kprobe *tk = container_of(ri->rp, struct trace_kprobe, rp);
 
-       tk->nhit++;
+       raw_cpu_inc(*tk->nhit);
 
        if (tk->tp.flags & TP_FLAG_TRACE)
                kretprobe_trace_func(tk, ri, regs);
index 0655afbea83f596ded953d6017e0f25a640bc073..d1663083d903aaad3ce4b359cfdb20068004b237 100644 (file)
@@ -186,11 +186,11 @@ print_syscall_exit(struct trace_iterator *iter, int flags,
 
 extern char *__bad_type_size(void);
 
-#define SYSCALL_FIELD(type, name)                                      \
-       sizeof(type) != sizeof(trace.name) ?                            \
+#define SYSCALL_FIELD(type, field, name)                               \
+       sizeof(type) != sizeof(trace.field) ?                           \
                __bad_type_size() :                                     \
-               #type, #name, offsetof(typeof(trace), name),            \
-               sizeof(trace.name), is_signed_type(type)
+               #type, #name, offsetof(typeof(trace), field),           \
+               sizeof(trace.field), is_signed_type(type)
 
 static int __init
 __set_enter_print_fmt(struct syscall_metadata *entry, char *buf, int len)
@@ -261,7 +261,8 @@ static int __init syscall_enter_define_fields(struct trace_event_call *call)
        int i;
        int offset = offsetof(typeof(trace), args);
 
-       ret = trace_define_field(call, SYSCALL_FIELD(int, nr), FILTER_OTHER);
+       ret = trace_define_field(call, SYSCALL_FIELD(int, nr, __syscall_nr),
+                                FILTER_OTHER);
        if (ret)
                return ret;
 
@@ -281,11 +282,12 @@ static int __init syscall_exit_define_fields(struct trace_event_call *call)
        struct syscall_trace_exit trace;
        int ret;
 
-       ret = trace_define_field(call, SYSCALL_FIELD(int, nr), FILTER_OTHER);
+       ret = trace_define_field(call, SYSCALL_FIELD(int, nr, __syscall_nr),
+                                FILTER_OTHER);
        if (ret)
                return ret;
 
-       ret = trace_define_field(call, SYSCALL_FIELD(long, ret),
+       ret = trace_define_field(call, SYSCALL_FIELD(long, ret, ret),
                                 FILTER_OTHER);
 
        return ret;
index 975cb49e32bf8b1e5dc3085d27c37c312d4ce6bd..f8e26ab963ed2fc057db395bee59d6f25307b5d5 100644 (file)
@@ -93,9 +93,11 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
 {
        struct mm_struct *mm;
 
-       /* convert pages-usec to Mbyte-usec */
-       stats->coremem = p->acct_rss_mem1 * PAGE_SIZE / MB;
-       stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE / MB;
+       /* convert pages-nsec/1024 to Mbyte-usec, see __acct_update_integrals */
+       stats->coremem = p->acct_rss_mem1 * PAGE_SIZE;
+       do_div(stats->coremem, 1000 * KB);
+       stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE;
+       do_div(stats->virtmem, 1000 * KB);
        mm = get_task_mm(p);
        if (mm) {
                /* adjust to KB unit */
@@ -123,27 +125,28 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
 static void __acct_update_integrals(struct task_struct *tsk,
                                    cputime_t utime, cputime_t stime)
 {
-       if (likely(tsk->mm)) {
-               cputime_t time, dtime;
-               struct timeval value;
-               unsigned long flags;
-               u64 delta;
-
-               local_irq_save(flags);
-               time = stime + utime;
-               dtime = time - tsk->acct_timexpd;
-               jiffies_to_timeval(cputime_to_jiffies(dtime), &value);
-               delta = value.tv_sec;
-               delta = delta * USEC_PER_SEC + value.tv_usec;
-
-               if (delta == 0)
-                       goto out;
-               tsk->acct_timexpd = time;
-               tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
-               tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
-       out:
-               local_irq_restore(flags);
-       }
+       cputime_t time, dtime;
+       u64 delta;
+
+       if (!likely(tsk->mm))
+               return;
+
+       time = stime + utime;
+       dtime = time - tsk->acct_timexpd;
+       /* Avoid division: cputime_t is often in nanoseconds already. */
+       delta = cputime_to_nsecs(dtime);
+
+       if (delta < TICK_NSEC)
+               return;
+
+       tsk->acct_timexpd = time;
+       /*
+        * Divide by 1024 to avoid overflow, and to avoid division.
+        * The final unit reported to userspace is Mbyte-usecs,
+        * the rest of the math is done in xacct_add_tsk.
+        */
+       tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm) >> 10;
+       tsk->acct_vm_mem1 += delta * tsk->mm->total_vm >> 10;
 }
 
 /**
@@ -153,9 +156,12 @@ static void __acct_update_integrals(struct task_struct *tsk,
 void acct_update_integrals(struct task_struct *tsk)
 {
        cputime_t utime, stime;
+       unsigned long flags;
 
+       local_irq_save(flags);
        task_cputime(tsk, &utime, &stime);
        __acct_update_integrals(tsk, utime, stime);
+       local_irq_restore(flags);
 }
 
 /**
index 7ff5dc7d2ac5f47395bc3be8484c642c5d577b6b..16e13d8628a301c61e2178df18756ba7483d4941 100644 (file)
@@ -320,8 +320,7 @@ static bool wq_debug_force_rr_cpu = false;
 module_param_named(debug_force_rr_cpu, wq_debug_force_rr_cpu, bool, 0644);
 
 /* the per-cpu worker pools */
-static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS],
-                                    cpu_worker_pools);
+static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS], cpu_worker_pools);
 
 static DEFINE_IDR(worker_pool_idr);    /* PR: idr of all pools */
 
index 8bfd1aca7a3d01a9887700b3f90d1d5697a9dab4..f28f7fad452fe462b324761898a4a686581ef90c 100644 (file)
@@ -1442,6 +1442,19 @@ config DEBUG_BLOCK_EXT_DEVT
 
          Say N if you are unsure.
 
+config CPU_HOTPLUG_STATE_CONTROL
+       bool "Enable CPU hotplug state control"
+       depends on DEBUG_KERNEL
+       depends on HOTPLUG_CPU
+       default n
+       help
+         Allows to write steps between "offline" and "online" to the CPUs
+         sysfs target file so states can be stepped granular. This is a debug
+         option for now as the hotplug machinery cannot be stopped and
+         restarted at arbitrary points yet.
+
+         Say N if your are unsure.
+
 config NOTIFIER_ERROR_INJECTION
        tristate "Notifier error injection"
        depends on DEBUG_KERNEL
index d62de8bf022d2534182fa2bcbdf31b4eb142a8a3..1234818143204a754ec6df5ae8073107c5171dc5 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/atomic.h>
 
 #ifdef CONFIG_X86
-#include <asm/processor.h>     /* for boot_cpu_has below */
+#include <asm/cpufeature.h>    /* for boot_cpu_has below */
 #endif
 
 #define TEST(bit, op, c_op, val)                               \
index 5a70f6196f577a071ae0a31e9da7fa0e1dd1bc68..81dedaab36ccfed3150281a0f915a4070f667bfd 100644 (file)
@@ -41,6 +41,7 @@ int cpumask_any_but(const struct cpumask *mask, unsigned int cpu)
                        break;
        return i;
 }
+EXPORT_SYMBOL(cpumask_any_but);
 
 /* These are not inline because of header tangles. */
 #ifdef CONFIG_CPUMASK_OFFSTACK
index 3345a089ef7b954d475d67965b8ce891c1b16ab0..3859bf63561c63936947b007fe3ee20e822509a1 100644 (file)
 #include <linux/kernel.h>
 #include <linux/rculist.h>
 
-static struct list_head force_poison;
-void list_force_poison(struct list_head *entry)
-{
-       entry->next = &force_poison;
-       entry->prev = &force_poison;
-}
-
 /*
  * Insert a new entry between two known consecutive entries.
  *
@@ -30,8 +23,6 @@ void __list_add(struct list_head *new,
                              struct list_head *prev,
                              struct list_head *next)
 {
-       WARN(new->next == &force_poison || new->prev == &force_poison,
-               "list_add attempted on force-poisoned entry\n");
        WARN(next->prev != prev,
                "list_add corruption. next->prev should be "
                "prev (%p), but was %p. (next=%p).\n",
index 4f6ae60433bc5d1e1d6df9b7c8d5d359512ad82a..563f10e6876aecf6e3932e0a2e955305f271b249 100644 (file)
@@ -17,6 +17,9 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 
+#include <linux/gfp.h>
+#include <linux/mm.h>
+
 #define BUF_SIZE 256
 #define PAD_SIZE 16
 #define FILL_CHAR '$'
@@ -410,6 +413,55 @@ netdev_features(void)
 {
 }
 
+static void __init
+flags(void)
+{
+       unsigned long flags;
+       gfp_t gfp;
+       char *cmp_buffer;
+
+       flags = 0;
+       test("", "%pGp", &flags);
+
+       /* Page flags should filter the zone id */
+       flags = 1UL << NR_PAGEFLAGS;
+       test("", "%pGp", &flags);
+
+       flags |= 1UL << PG_uptodate | 1UL << PG_dirty | 1UL << PG_lru
+               | 1UL << PG_active | 1UL << PG_swapbacked;
+       test("uptodate|dirty|lru|active|swapbacked", "%pGp", &flags);
+
+
+       flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC
+                       | VM_DENYWRITE;
+       test("read|exec|mayread|maywrite|mayexec|denywrite", "%pGv", &flags);
+
+       gfp = GFP_TRANSHUGE;
+       test("GFP_TRANSHUGE", "%pGg", &gfp);
+
+       gfp = GFP_ATOMIC|__GFP_DMA;
+       test("GFP_ATOMIC|GFP_DMA", "%pGg", &gfp);
+
+       gfp = __GFP_ATOMIC;
+       test("__GFP_ATOMIC", "%pGg", &gfp);
+
+       cmp_buffer = kmalloc(BUF_SIZE, GFP_KERNEL);
+       if (!cmp_buffer)
+               return;
+
+       /* Any flags not translated by the table should remain numeric */
+       gfp = ~__GFP_BITS_MASK;
+       snprintf(cmp_buffer, BUF_SIZE, "%#lx", (unsigned long) gfp);
+       test(cmp_buffer, "%pGg", &gfp);
+
+       snprintf(cmp_buffer, BUF_SIZE, "__GFP_ATOMIC|%#lx",
+                                                       (unsigned long) gfp);
+       gfp |= __GFP_ATOMIC;
+       test(cmp_buffer, "%pGg", &gfp);
+
+       kfree(cmp_buffer);
+}
+
 static void __init
 test_pointer(void)
 {
@@ -428,6 +480,7 @@ test_pointer(void)
        struct_clk();
        bitmap();
        netdev_features();
+       flags();
 }
 
 static int __init
index c61b299e367ffac86450ac59c123d0925285b96c..915d75df20864d07428376750c1bd148c216a585 100644 (file)
@@ -46,8 +46,11 @@ struct test_key {
        bool                    (*test_key)(void);
 };
 
-#define test_key_func(key, branch) \
-       ({bool func(void) { return branch(key); } func; })
+#define test_key_func(key, branch)     \
+static bool key ## _ ## branch(void)   \
+{                                      \
+       return branch(&key);            \
+}
 
 static void invert_key(struct static_key *key)
 {
@@ -92,6 +95,25 @@ static int verify_keys(struct test_key *keys, int size, bool invert)
        return 0;
 }
 
+test_key_func(old_true_key, static_key_true)
+test_key_func(old_false_key, static_key_false)
+test_key_func(true_key, static_branch_likely)
+test_key_func(true_key, static_branch_unlikely)
+test_key_func(false_key, static_branch_likely)
+test_key_func(false_key, static_branch_unlikely)
+test_key_func(base_old_true_key, static_key_true)
+test_key_func(base_inv_old_true_key, static_key_true)
+test_key_func(base_old_false_key, static_key_false)
+test_key_func(base_inv_old_false_key, static_key_false)
+test_key_func(base_true_key, static_branch_likely)
+test_key_func(base_true_key, static_branch_unlikely)
+test_key_func(base_inv_true_key, static_branch_likely)
+test_key_func(base_inv_true_key, static_branch_unlikely)
+test_key_func(base_false_key, static_branch_likely)
+test_key_func(base_false_key, static_branch_unlikely)
+test_key_func(base_inv_false_key, static_branch_likely)
+test_key_func(base_inv_false_key, static_branch_unlikely)
+
 static int __init test_static_key_init(void)
 {
        int ret;
@@ -102,95 +124,95 @@ static int __init test_static_key_init(void)
                {
                        .init_state     = true,
                        .key            = &old_true_key,
-                       .test_key       = test_key_func(&old_true_key, static_key_true),
+                       .test_key       = &old_true_key_static_key_true,
                },
                {
                        .init_state     = false,
                        .key            = &old_false_key,
-                       .test_key       = test_key_func(&old_false_key, static_key_false),
+                       .test_key       = &old_false_key_static_key_false,
                },
                /* internal keys - new keys */
                {
                        .init_state     = true,
                        .key            = &true_key.key,
-                       .test_key       = test_key_func(&true_key, static_branch_likely),
+                       .test_key       = &true_key_static_branch_likely,
                },
                {
                        .init_state     = true,
                        .key            = &true_key.key,
-                       .test_key       = test_key_func(&true_key, static_branch_unlikely),
+                       .test_key       = &true_key_static_branch_unlikely,
                },
                {
                        .init_state     = false,
                        .key            = &false_key.key,
-                       .test_key       = test_key_func(&false_key, static_branch_likely),
+                       .test_key       = &false_key_static_branch_likely,
                },
                {
                        .init_state     = false,
                        .key            = &false_key.key,
-                       .test_key       = test_key_func(&false_key, static_branch_unlikely),
+                       .test_key       = &false_key_static_branch_unlikely,
                },
                /* external keys - old keys */
                {
                        .init_state     = true,
                        .key            = &base_old_true_key,
-                       .test_key       = test_key_func(&base_old_true_key, static_key_true),
+                       .test_key       = &base_old_true_key_static_key_true,
                },
                {
                        .init_state     = false,
                        .key            = &base_inv_old_true_key,
-                       .test_key       = test_key_func(&base_inv_old_true_key, static_key_true),
+                       .test_key       = &base_inv_old_true_key_static_key_true,
                },
                {
                        .init_state     = false,
                        .key            = &base_old_false_key,
-                       .test_key       = test_key_func(&base_old_false_key, static_key_false),
+                       .test_key       = &base_old_false_key_static_key_false,
                },
                {
                        .init_state     = true,
                        .key            = &base_inv_old_false_key,
-                       .test_key       = test_key_func(&base_inv_old_false_key, static_key_false),
+                       .test_key       = &base_inv_old_false_key_static_key_false,
                },
                /* external keys - new keys */
                {
                        .init_state     = true,
                        .key            = &base_true_key.key,
-                       .test_key       = test_key_func(&base_true_key, static_branch_likely),
+                       .test_key       = &base_true_key_static_branch_likely,
                },
                {
                        .init_state     = true,
                        .key            = &base_true_key.key,
-                       .test_key       = test_key_func(&base_true_key, static_branch_unlikely),
+                       .test_key       = &base_true_key_static_branch_unlikely,
                },
                {
                        .init_state     = false,
                        .key            = &base_inv_true_key.key,
-                       .test_key       = test_key_func(&base_inv_true_key, static_branch_likely),
+                       .test_key       = &base_inv_true_key_static_branch_likely,
                },
                {
                        .init_state     = false,
                        .key            = &base_inv_true_key.key,
-                       .test_key       = test_key_func(&base_inv_true_key, static_branch_unlikely),
+                       .test_key       = &base_inv_true_key_static_branch_unlikely,
                },
                {
                        .init_state     = false,
                        .key            = &base_false_key.key,
-                       .test_key       = test_key_func(&base_false_key, static_branch_likely),
+                       .test_key       = &base_false_key_static_branch_likely,
                },
                {
                        .init_state     = false,
                        .key            = &base_false_key.key,
-                       .test_key       = test_key_func(&base_false_key, static_branch_unlikely),
+                       .test_key       = &base_false_key_static_branch_unlikely,
                },
                {
                        .init_state     = true,
                        .key            = &base_inv_false_key.key,
-                       .test_key       = test_key_func(&base_inv_false_key, static_branch_likely),
+                       .test_key       = &base_inv_false_key_static_branch_likely,
                },
                {
                        .init_state     = true,
                        .key            = &base_inv_false_key.key,
-                       .test_key       = test_key_func(&base_inv_false_key, static_branch_unlikely),
+                       .test_key       = &base_inv_false_key_static_branch_unlikely,
                },
        };
 
index f44e178e6edec22e2f7c405f8cb433b2be935f83..525c8e19bda2b8a4e7398d7fc19064b2abc84b45 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/blkdev.h>
 #endif
 
+#include "../mm/internal.h"    /* For the trace_print_flags arrays */
+
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/sections.h>      /* for dereference_function_descriptor() */
 #include <asm/byteorder.h>     /* cpu_to_le16 */
@@ -1407,6 +1409,72 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec,
        }
 }
 
+static
+char *format_flags(char *buf, char *end, unsigned long flags,
+                                       const struct trace_print_flags *names)
+{
+       unsigned long mask;
+       const struct printf_spec strspec = {
+               .field_width = -1,
+               .precision = -1,
+       };
+       const struct printf_spec numspec = {
+               .flags = SPECIAL|SMALL,
+               .field_width = -1,
+               .precision = -1,
+               .base = 16,
+       };
+
+       for ( ; flags && names->name; names++) {
+               mask = names->mask;
+               if ((flags & mask) != mask)
+                       continue;
+
+               buf = string(buf, end, names->name, strspec);
+
+               flags &= ~mask;
+               if (flags) {
+                       if (buf < end)
+                               *buf = '|';
+                       buf++;
+               }
+       }
+
+       if (flags)
+               buf = number(buf, end, flags, numspec);
+
+       return buf;
+}
+
+static noinline_for_stack
+char *flags_string(char *buf, char *end, void *flags_ptr, const char *fmt)
+{
+       unsigned long flags;
+       const struct trace_print_flags *names;
+
+       switch (fmt[1]) {
+       case 'p':
+               flags = *(unsigned long *)flags_ptr;
+               /* Remove zone id */
+               flags &= (1UL << NR_PAGEFLAGS) - 1;
+               names = pageflag_names;
+               break;
+       case 'v':
+               flags = *(unsigned long *)flags_ptr;
+               names = vmaflag_names;
+               break;
+       case 'g':
+               flags = *(gfp_t *)flags_ptr;
+               names = gfpflag_names;
+               break;
+       default:
+               WARN_ONCE(1, "Unsupported flags modifier: %c\n", fmt[1]);
+               return buf;
+       }
+
+       return format_flags(buf, end, flags, names);
+}
+
 int kptr_restrict __read_mostly;
 
 /*
@@ -1495,6 +1563,11 @@ int kptr_restrict __read_mostly;
  * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address
  *        (legacy clock framework) of the clock
  * - 'Cr' For a clock, it prints the current rate of the clock
+ * - 'G' For flags to be printed as a collection of symbolic strings that would
+ *       construct the specific value. Supported flags given by option:
+ *       p page flags (see struct page) given as pointer to unsigned long
+ *       g gfp flags (GFP_* and __GFP_*) given as pointer to gfp_t
+ *       v vma flags (VM_*) given as pointer to unsigned long
  *
  * ** Please update also Documentation/printk-formats.txt when making changes **
  *
@@ -1648,6 +1721,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                return bdev_name(buf, end, ptr, spec, fmt);
 #endif
 
+       case 'G':
+               return flags_string(buf, end, ptr, fmt);
        }
        spec.flags |= SMALL;
        if (spec.field_width == -1) {
index 957d3da53dddcd53b72da82e39f77d951db57a66..5c50b238b7705a5a4e2ce9a1845e11fc76ec4503 100644 (file)
@@ -16,8 +16,8 @@ config DEBUG_PAGEALLOC
        select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC
        ---help---
          Unmap pages from the kernel linear mapping after free_pages().
-         This results in a large slowdown, but helps to find certain types
-         of memory corruption.
+         Depending on runtime enablement, this results in a small or large
+         slowdown, but helps to find certain types of memory corruption.
 
          For architectures which don't enable ARCH_SUPPORTS_DEBUG_PAGEALLOC,
          fill the pages with poison patterns after free_pages() and verify
@@ -26,5 +26,56 @@ config DEBUG_PAGEALLOC
          that would result in incorrect warnings of memory corruption after
          a resume because free pages are not saved to the suspend image.
 
+         By default this option will have a small overhead, e.g. by not
+         allowing the kernel mapping to be backed by large pages on some
+         architectures. Even bigger overhead comes when the debugging is
+         enabled by DEBUG_PAGEALLOC_ENABLE_DEFAULT or the debug_pagealloc
+         command line parameter.
+
+config DEBUG_PAGEALLOC_ENABLE_DEFAULT
+       bool "Enable debug page memory allocations by default?"
+       default n
+       depends on DEBUG_PAGEALLOC
+       ---help---
+         Enable debug page memory allocations by default? This value
+         can be overridden by debug_pagealloc=off|on.
+
 config PAGE_POISONING
-       bool
+       bool "Poison pages after freeing"
+       select PAGE_EXTENSION
+       select PAGE_POISONING_NO_SANITY if HIBERNATION
+       ---help---
+         Fill the pages with poison patterns after free_pages() and verify
+         the patterns before alloc_pages. The filling of the memory helps
+         reduce the risk of information leaks from freed data. This does
+         have a potential performance impact.
+
+         Note that "poison" here is not the same thing as the "HWPoison"
+         for CONFIG_MEMORY_FAILURE. This is software poisoning only.
+
+         If unsure, say N
+
+config PAGE_POISONING_NO_SANITY
+       depends on PAGE_POISONING
+       bool "Only poison, don't sanity check"
+       ---help---
+          Skip the sanity checking on alloc, only fill the pages with
+          poison on free. This reduces some of the overhead of the
+          poisoning feature.
+
+          If you are only interested in sanitization, say Y. Otherwise
+          say N.
+
+config PAGE_POISONING_ZERO
+       bool "Use zero for poisoning instead of random data"
+       depends on PAGE_POISONING
+       ---help---
+          Instead of using the existing poison value, fill the pages with
+          zeros. This makes it harder to detect when errors are occurring
+          due to sanitization but the zeroing at free means that it is
+          no longer necessary to write zeros when GFP_ZERO is used on
+          allocation.
+
+          Enabling page poisoning with this option will disable hibernation
+
+          If unsure, say N
index 2ed43191fc3bf78f46f111e88fa9d5a01b8c661a..cfdd481d27a5d7344b1eeb706174b0ec393acade 100644 (file)
@@ -48,7 +48,7 @@ obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
 obj-$(CONFIG_SLOB) += slob.o
 obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
 obj-$(CONFIG_KSM) += ksm.o
-obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o
+obj-$(CONFIG_PAGE_POISONING) += page_poison.o
 obj-$(CONFIG_SLAB) += slab.o
 obj-$(CONFIG_SLUB) += slub.o
 obj-$(CONFIG_KMEMCHECK) += kmemcheck.o
index 585de54dbe8ccef06543b547eadfe8e4fe8e3117..93f71d968098ce6f2ff907bf5036f6a57e2028e0 100644 (file)
@@ -71,49 +71,6 @@ static inline bool migrate_async_suitable(int migratetype)
        return is_migrate_cma(migratetype) || migratetype == MIGRATE_MOVABLE;
 }
 
-/*
- * Check that the whole (or subset of) a pageblock given by the interval of
- * [start_pfn, end_pfn) is valid and within the same zone, before scanning it
- * with the migration of free compaction scanner. The scanners then need to
- * use only pfn_valid_within() check for arches that allow holes within
- * pageblocks.
- *
- * Return struct page pointer of start_pfn, or NULL if checks were not passed.
- *
- * It's possible on some configurations to have a setup like node0 node1 node0
- * i.e. it's possible that all pages within a zones range of pages do not
- * belong to a single zone. We assume that a border between node0 and node1
- * can occur within a single pageblock, but not a node0 node1 node0
- * interleaving within a single pageblock. It is therefore sufficient to check
- * the first and last page of a pageblock and avoid checking each individual
- * page in a pageblock.
- */
-static struct page *pageblock_pfn_to_page(unsigned long start_pfn,
-                               unsigned long end_pfn, struct zone *zone)
-{
-       struct page *start_page;
-       struct page *end_page;
-
-       /* end_pfn is one past the range we are checking */
-       end_pfn--;
-
-       if (!pfn_valid(start_pfn) || !pfn_valid(end_pfn))
-               return NULL;
-
-       start_page = pfn_to_page(start_pfn);
-
-       if (page_zone(start_page) != zone)
-               return NULL;
-
-       end_page = pfn_to_page(end_pfn);
-
-       /* This gives a shorter code than deriving page_zone(end_page) */
-       if (page_zone_id(start_page) != page_zone_id(end_page))
-               return NULL;
-
-       return start_page;
-}
-
 #ifdef CONFIG_COMPACTION
 
 /* Do not skip compaction more than 64 times */
@@ -200,7 +157,8 @@ static void reset_cached_positions(struct zone *zone)
 {
        zone->compact_cached_migrate_pfn[0] = zone->zone_start_pfn;
        zone->compact_cached_migrate_pfn[1] = zone->zone_start_pfn;
-       zone->compact_cached_free_pfn = zone_end_pfn(zone);
+       zone->compact_cached_free_pfn =
+                       round_down(zone_end_pfn(zone) - 1, pageblock_nr_pages);
 }
 
 /*
@@ -554,13 +512,17 @@ unsigned long
 isolate_freepages_range(struct compact_control *cc,
                        unsigned long start_pfn, unsigned long end_pfn)
 {
-       unsigned long isolated, pfn, block_end_pfn;
+       unsigned long isolated, pfn, block_start_pfn, block_end_pfn;
        LIST_HEAD(freelist);
 
        pfn = start_pfn;
+       block_start_pfn = pfn & ~(pageblock_nr_pages - 1);
+       if (block_start_pfn < cc->zone->zone_start_pfn)
+               block_start_pfn = cc->zone->zone_start_pfn;
        block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
 
        for (; pfn < end_pfn; pfn += isolated,
+                               block_start_pfn = block_end_pfn,
                                block_end_pfn += pageblock_nr_pages) {
                /* Protect pfn from changing by isolate_freepages_block */
                unsigned long isolate_start_pfn = pfn;
@@ -573,11 +535,13 @@ isolate_freepages_range(struct compact_control *cc,
                 * scanning range to right one.
                 */
                if (pfn >= block_end_pfn) {
+                       block_start_pfn = pfn & ~(pageblock_nr_pages - 1);
                        block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
                        block_end_pfn = min(block_end_pfn, end_pfn);
                }
 
-               if (!pageblock_pfn_to_page(pfn, block_end_pfn, cc->zone))
+               if (!pageblock_pfn_to_page(block_start_pfn,
+                                       block_end_pfn, cc->zone))
                        break;
 
                isolated = isolate_freepages_block(cc, &isolate_start_pfn,
@@ -863,18 +827,23 @@ unsigned long
 isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
                                                        unsigned long end_pfn)
 {
-       unsigned long pfn, block_end_pfn;
+       unsigned long pfn, block_start_pfn, block_end_pfn;
 
        /* Scan block by block. First and last block may be incomplete */
        pfn = start_pfn;
+       block_start_pfn = pfn & ~(pageblock_nr_pages - 1);
+       if (block_start_pfn < cc->zone->zone_start_pfn)
+               block_start_pfn = cc->zone->zone_start_pfn;
        block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
 
        for (; pfn < end_pfn; pfn = block_end_pfn,
+                               block_start_pfn = block_end_pfn,
                                block_end_pfn += pageblock_nr_pages) {
 
                block_end_pfn = min(block_end_pfn, end_pfn);
 
-               if (!pageblock_pfn_to_page(pfn, block_end_pfn, cc->zone))
+               if (!pageblock_pfn_to_page(block_start_pfn,
+                                       block_end_pfn, cc->zone))
                        continue;
 
                pfn = isolate_migratepages_block(cc, pfn, block_end_pfn,
@@ -1103,7 +1072,9 @@ int sysctl_compact_unevictable_allowed __read_mostly = 1;
 static isolate_migrate_t isolate_migratepages(struct zone *zone,
                                        struct compact_control *cc)
 {
-       unsigned long low_pfn, end_pfn;
+       unsigned long block_start_pfn;
+       unsigned long block_end_pfn;
+       unsigned long low_pfn;
        unsigned long isolate_start_pfn;
        struct page *page;
        const isolate_mode_t isolate_mode =
@@ -1115,16 +1086,21 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
         * initialized by compact_zone()
         */
        low_pfn = cc->migrate_pfn;
+       block_start_pfn = cc->migrate_pfn & ~(pageblock_nr_pages - 1);
+       if (block_start_pfn < zone->zone_start_pfn)
+               block_start_pfn = zone->zone_start_pfn;
 
        /* Only scan within a pageblock boundary */
-       end_pfn = ALIGN(low_pfn + 1, pageblock_nr_pages);
+       block_end_pfn = ALIGN(low_pfn + 1, pageblock_nr_pages);
 
        /*
         * Iterate over whole pageblocks until we find the first suitable.
         * Do not cross the free scanner.
         */
-       for (; end_pfn <= cc->free_pfn;
-                       low_pfn = end_pfn, end_pfn += pageblock_nr_pages) {
+       for (; block_end_pfn <= cc->free_pfn;
+                       low_pfn = block_end_pfn,
+                       block_start_pfn = block_end_pfn,
+                       block_end_pfn += pageblock_nr_pages) {
 
                /*
                 * This can potentially iterate a massively long zone with
@@ -1135,7 +1111,8 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
                                                && compact_should_abort(cc))
                        break;
 
-               page = pageblock_pfn_to_page(low_pfn, end_pfn, zone);
+               page = pageblock_pfn_to_page(block_start_pfn, block_end_pfn,
+                                                                       zone);
                if (!page)
                        continue;
 
@@ -1154,8 +1131,8 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
 
                /* Perform the isolation */
                isolate_start_pfn = low_pfn;
-               low_pfn = isolate_migratepages_block(cc, low_pfn, end_pfn,
-                                                               isolate_mode);
+               low_pfn = isolate_migratepages_block(cc, low_pfn,
+                                               block_end_pfn, isolate_mode);
 
                if (!low_pfn || cc->contended) {
                        acct_isolated(zone, cc);
@@ -1371,11 +1348,11 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
         */
        cc->migrate_pfn = zone->compact_cached_migrate_pfn[sync];
        cc->free_pfn = zone->compact_cached_free_pfn;
-       if (cc->free_pfn < start_pfn || cc->free_pfn > end_pfn) {
-               cc->free_pfn = end_pfn & ~(pageblock_nr_pages-1);
+       if (cc->free_pfn < start_pfn || cc->free_pfn >= end_pfn) {
+               cc->free_pfn = round_down(end_pfn - 1, pageblock_nr_pages);
                zone->compact_cached_free_pfn = cc->free_pfn;
        }
-       if (cc->migrate_pfn < start_pfn || cc->migrate_pfn > end_pfn) {
+       if (cc->migrate_pfn < start_pfn || cc->migrate_pfn >= end_pfn) {
                cc->migrate_pfn = start_pfn;
                zone->compact_cached_migrate_pfn[0] = cc->migrate_pfn;
                zone->compact_cached_migrate_pfn[1] = cc->migrate_pfn;
diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c
deleted file mode 100644 (file)
index 5bf5906..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/page_ext.h>
-#include <linux/poison.h>
-#include <linux/ratelimit.h>
-
-static bool page_poisoning_enabled __read_mostly;
-
-static bool need_page_poisoning(void)
-{
-       if (!debug_pagealloc_enabled())
-               return false;
-
-       return true;
-}
-
-static void init_page_poisoning(void)
-{
-       if (!debug_pagealloc_enabled())
-               return;
-
-       page_poisoning_enabled = true;
-}
-
-struct page_ext_operations page_poisoning_ops = {
-       .need = need_page_poisoning,
-       .init = init_page_poisoning,
-};
-
-static inline void set_page_poison(struct page *page)
-{
-       struct page_ext *page_ext;
-
-       page_ext = lookup_page_ext(page);
-       __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
-}
-
-static inline void clear_page_poison(struct page *page)
-{
-       struct page_ext *page_ext;
-
-       page_ext = lookup_page_ext(page);
-       __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
-}
-
-static inline bool page_poison(struct page *page)
-{
-       struct page_ext *page_ext;
-
-       page_ext = lookup_page_ext(page);
-       return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
-}
-
-static void poison_page(struct page *page)
-{
-       void *addr = kmap_atomic(page);
-
-       set_page_poison(page);
-       memset(addr, PAGE_POISON, PAGE_SIZE);
-       kunmap_atomic(addr);
-}
-
-static void poison_pages(struct page *page, int n)
-{
-       int i;
-
-       for (i = 0; i < n; i++)
-               poison_page(page + i);
-}
-
-static bool single_bit_flip(unsigned char a, unsigned char b)
-{
-       unsigned char error = a ^ b;
-
-       return error && !(error & (error - 1));
-}
-
-static void check_poison_mem(unsigned char *mem, size_t bytes)
-{
-       static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10);
-       unsigned char *start;
-       unsigned char *end;
-
-       start = memchr_inv(mem, PAGE_POISON, bytes);
-       if (!start)
-               return;
-
-       for (end = mem + bytes - 1; end > start; end--) {
-               if (*end != PAGE_POISON)
-                       break;
-       }
-
-       if (!__ratelimit(&ratelimit))
-               return;
-       else if (start == end && single_bit_flip(*start, PAGE_POISON))
-               printk(KERN_ERR "pagealloc: single bit error\n");
-       else
-               printk(KERN_ERR "pagealloc: memory corruption\n");
-
-       print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start,
-                       end - start + 1, 1);
-       dump_stack();
-}
-
-static void unpoison_page(struct page *page)
-{
-       void *addr;
-
-       if (!page_poison(page))
-               return;
-
-       addr = kmap_atomic(page);
-       check_poison_mem(addr, PAGE_SIZE);
-       clear_page_poison(page);
-       kunmap_atomic(addr);
-}
-
-static void unpoison_pages(struct page *page, int n)
-{
-       int i;
-
-       for (i = 0; i < n; i++)
-               unpoison_page(page + i);
-}
-
-void __kernel_map_pages(struct page *page, int numpages, int enable)
-{
-       if (!page_poisoning_enabled)
-               return;
-
-       if (enable)
-               unpoison_pages(page, numpages);
-       else
-               poison_pages(page, numpages);
-}
index f05b2d5d6481f64913500c1ad01857d53a5de0de..df7247b0b5326a6a9251d89bce3b2ffb0e90a34b 100644 (file)
@@ -9,75 +9,38 @@
 #include <linux/mm.h>
 #include <linux/trace_events.h>
 #include <linux/memcontrol.h>
-
-static const struct trace_print_flags pageflag_names[] = {
-       {1UL << PG_locked,              "locked"        },
-       {1UL << PG_error,               "error"         },
-       {1UL << PG_referenced,          "referenced"    },
-       {1UL << PG_uptodate,            "uptodate"      },
-       {1UL << PG_dirty,               "dirty"         },
-       {1UL << PG_lru,                 "lru"           },
-       {1UL << PG_active,              "active"        },
-       {1UL << PG_slab,                "slab"          },
-       {1UL << PG_owner_priv_1,        "owner_priv_1"  },
-       {1UL << PG_arch_1,              "arch_1"        },
-       {1UL << PG_reserved,            "reserved"      },
-       {1UL << PG_private,             "private"       },
-       {1UL << PG_private_2,           "private_2"     },
-       {1UL << PG_writeback,           "writeback"     },
-       {1UL << PG_head,                "head"          },
-       {1UL << PG_swapcache,           "swapcache"     },
-       {1UL << PG_mappedtodisk,        "mappedtodisk"  },
-       {1UL << PG_reclaim,             "reclaim"       },
-       {1UL << PG_swapbacked,          "swapbacked"    },
-       {1UL << PG_unevictable,         "unevictable"   },
-#ifdef CONFIG_MMU
-       {1UL << PG_mlocked,             "mlocked"       },
-#endif
-#ifdef CONFIG_ARCH_USES_PG_UNCACHED
-       {1UL << PG_uncached,            "uncached"      },
-#endif
-#ifdef CONFIG_MEMORY_FAILURE
-       {1UL << PG_hwpoison,            "hwpoison"      },
-#endif
-#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT)
-       {1UL << PG_young,               "young"         },
-       {1UL << PG_idle,                "idle"          },
-#endif
+#include <trace/events/mmflags.h>
+#include <linux/migrate.h>
+#include <linux/page_owner.h>
+
+#include "internal.h"
+
+char *migrate_reason_names[MR_TYPES] = {
+       "compaction",
+       "memory_failure",
+       "memory_hotplug",
+       "syscall_or_cpuset",
+       "mempolicy_mbind",
+       "numa_misplaced",
+       "cma",
 };
 
-static void dump_flags(unsigned long flags,
-                       const struct trace_print_flags *names, int count)
-{
-       const char *delim = "";
-       unsigned long mask;
-       int i;
-
-       pr_emerg("flags: %#lx(", flags);
-
-       /* remove zone id */
-       flags &= (1UL << NR_PAGEFLAGS) - 1;
-
-       for (i = 0; i < count && flags; i++) {
-
-               mask = names[i].mask;
-               if ((flags & mask) != mask)
-                       continue;
-
-               flags &= ~mask;
-               pr_cont("%s%s", delim, names[i].name);
-               delim = "|";
-       }
+const struct trace_print_flags pageflag_names[] = {
+       __def_pageflag_names,
+       {0, NULL}
+};
 
-       /* check for left over flags */
-       if (flags)
-               pr_cont("%s%#lx", delim, flags);
+const struct trace_print_flags gfpflag_names[] = {
+       __def_gfpflag_names,
+       {0, NULL}
+};
 
-       pr_cont(")\n");
-}
+const struct trace_print_flags vmaflag_names[] = {
+       __def_vmaflag_names,
+       {0, NULL}
+};
 
-void dump_page_badflags(struct page *page, const char *reason,
-               unsigned long badflags)
+void __dump_page(struct page *page, const char *reason)
 {
        pr_emerg("page:%p count:%d mapcount:%d mapping:%p index:%#lx",
                  page, atomic_read(&page->_count), page_mapcount(page),
@@ -85,15 +48,13 @@ void dump_page_badflags(struct page *page, const char *reason,
        if (PageCompound(page))
                pr_cont(" compound_mapcount: %d", compound_mapcount(page));
        pr_cont("\n");
-       BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS);
-       dump_flags(page->flags, pageflag_names, ARRAY_SIZE(pageflag_names));
+       BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS + 1);
+
+       pr_emerg("flags: %#lx(%pGp)\n", page->flags, &page->flags);
+
        if (reason)
                pr_alert("page dumped because: %s\n", reason);
-       if (page->flags & badflags) {
-               pr_alert("bad because of flags:\n");
-               dump_flags(page->flags & badflags,
-                               pageflag_names, ARRAY_SIZE(pageflag_names));
-       }
+
 #ifdef CONFIG_MEMCG
        if (page->mem_cgroup)
                pr_alert("page->mem_cgroup:%p\n", page->mem_cgroup);
@@ -102,67 +63,26 @@ void dump_page_badflags(struct page *page, const char *reason,
 
 void dump_page(struct page *page, const char *reason)
 {
-       dump_page_badflags(page, reason, 0);
+       __dump_page(page, reason);
+       dump_page_owner(page);
 }
 EXPORT_SYMBOL(dump_page);
 
 #ifdef CONFIG_DEBUG_VM
 
-static const struct trace_print_flags vmaflags_names[] = {
-       {VM_READ,                       "read"          },
-       {VM_WRITE,                      "write"         },
-       {VM_EXEC,                       "exec"          },
-       {VM_SHARED,                     "shared"        },
-       {VM_MAYREAD,                    "mayread"       },
-       {VM_MAYWRITE,                   "maywrite"      },
-       {VM_MAYEXEC,                    "mayexec"       },
-       {VM_MAYSHARE,                   "mayshare"      },
-       {VM_GROWSDOWN,                  "growsdown"     },
-       {VM_PFNMAP,                     "pfnmap"        },
-       {VM_DENYWRITE,                  "denywrite"     },
-       {VM_LOCKONFAULT,                "lockonfault"   },
-       {VM_LOCKED,                     "locked"        },
-       {VM_IO,                         "io"            },
-       {VM_SEQ_READ,                   "seqread"       },
-       {VM_RAND_READ,                  "randread"      },
-       {VM_DONTCOPY,                   "dontcopy"      },
-       {VM_DONTEXPAND,                 "dontexpand"    },
-       {VM_ACCOUNT,                    "account"       },
-       {VM_NORESERVE,                  "noreserve"     },
-       {VM_HUGETLB,                    "hugetlb"       },
-#if defined(CONFIG_X86)
-       {VM_PAT,                        "pat"           },
-#elif defined(CONFIG_PPC)
-       {VM_SAO,                        "sao"           },
-#elif defined(CONFIG_PARISC) || defined(CONFIG_METAG) || defined(CONFIG_IA64)
-       {VM_GROWSUP,                    "growsup"       },
-#elif !defined(CONFIG_MMU)
-       {VM_MAPPED_COPY,                "mappedcopy"    },
-#else
-       {VM_ARCH_1,                     "arch_1"        },
-#endif
-       {VM_DONTDUMP,                   "dontdump"      },
-#ifdef CONFIG_MEM_SOFT_DIRTY
-       {VM_SOFTDIRTY,                  "softdirty"     },
-#endif
-       {VM_MIXEDMAP,                   "mixedmap"      },
-       {VM_HUGEPAGE,                   "hugepage"      },
-       {VM_NOHUGEPAGE,                 "nohugepage"    },
-       {VM_MERGEABLE,                  "mergeable"     },
-};
-
 void dump_vma(const struct vm_area_struct *vma)
 {
        pr_emerg("vma %p start %p end %p\n"
                "next %p prev %p mm %p\n"
                "prot %lx anon_vma %p vm_ops %p\n"
-               "pgoff %lx file %p private_data %p\n",
+               "pgoff %lx file %p private_data %p\n"
+               "flags: %#lx(%pGv)\n",
                vma, (void *)vma->vm_start, (void *)vma->vm_end, vma->vm_next,
                vma->vm_prev, vma->vm_mm,
                (unsigned long)pgprot_val(vma->vm_page_prot),
                vma->anon_vma, vma->vm_ops, vma->vm_pgoff,
-               vma->vm_file, vma->vm_private_data);
-       dump_flags(vma->vm_flags, vmaflags_names, ARRAY_SIZE(vmaflags_names));
+               vma->vm_file, vma->vm_private_data,
+               vma->vm_flags, &vma->vm_flags);
 }
 EXPORT_SYMBOL(dump_vma);
 
@@ -196,7 +116,7 @@ void dump_mm(const struct mm_struct *mm)
 #if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
                "tlb_flush_pending %d\n"
 #endif
-               "%s",   /* This is here to hold the comma */
+               "def_flags: %#lx(%pGv)\n",
 
                mm, mm->mmap, mm->vmacache_seqnum, mm->task_size,
 #ifdef CONFIG_MMU
@@ -230,11 +150,8 @@ void dump_mm(const struct mm_struct *mm)
 #if defined(CONFIG_NUMA_BALANCING) || defined(CONFIG_COMPACTION)
                mm->tlb_flush_pending,
 #endif
-               ""              /* This is here to not have a comma! */
-               );
-
-               dump_flags(mm->def_flags, vmaflags_names,
-                               ARRAY_SIZE(vmaflags_names));
+               mm->def_flags, &mm->def_flags
+       );
 }
 
 #endif         /* CONFIG_DEBUG_VM */
index 79171b4a58269986491198403a322d6c2a7dc814..b0fac98cd9388941db02a3985d98b32d37b307dd 100644 (file)
@@ -1,5 +1,7 @@
 #include <linux/fault-inject.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
+#include "slab.h"
 
 static struct {
        struct fault_attr attr;
@@ -11,18 +13,22 @@ static struct {
        .cache_filter = false,
 };
 
-bool should_failslab(size_t size, gfp_t gfpflags, unsigned long cache_flags)
+bool should_failslab(struct kmem_cache *s, gfp_t gfpflags)
 {
+       /* No fault-injection for bootstrap cache */
+       if (unlikely(s == kmem_cache))
+               return false;
+
        if (gfpflags & __GFP_NOFAIL)
                return false;
 
        if (failslab.ignore_gfp_reclaim && (gfpflags & __GFP_RECLAIM))
                return false;
 
-       if (failslab.cache_filter && !(cache_flags & SLAB_FAILSLAB))
+       if (failslab.cache_filter && !(s->flags & SLAB_FAILSLAB))
                return false;
 
-       return should_fail(&failslab.attr, size);
+       return should_fail(&failslab.attr, s->object_size);
 }
 
 static int __init setup_failslab(char *str)
index 23edccecadb076700580b81ec40b9db713334960..61b441b191adc5bcae5e7b98558b7705a75240a9 100644 (file)
  *    ->tree_lock              (page_remove_rmap->set_page_dirty)
  *    bdi.wb->list_lock                (page_remove_rmap->set_page_dirty)
  *    ->inode->i_lock          (page_remove_rmap->set_page_dirty)
- *    ->memcg->move_lock       (page_remove_rmap->mem_cgroup_begin_page_stat)
+ *    ->memcg->move_lock       (page_remove_rmap->lock_page_memcg)
  *    bdi.wb->list_lock                (zap_pte_range->set_page_dirty)
  *    ->inode->i_lock          (zap_pte_range->set_page_dirty)
  *    ->private_lock           (zap_pte_range->__set_page_dirty_buffers)
@@ -176,11 +176,9 @@ static void page_cache_tree_delete(struct address_space *mapping,
 /*
  * Delete a page from the page cache and free it. Caller has to make
  * sure the page is locked and that nobody else uses it - or that usage
- * is safe.  The caller must hold the mapping's tree_lock and
- * mem_cgroup_begin_page_stat().
+ * is safe.  The caller must hold the mapping's tree_lock.
  */
-void __delete_from_page_cache(struct page *page, void *shadow,
-                             struct mem_cgroup *memcg)
+void __delete_from_page_cache(struct page *page, void *shadow)
 {
        struct address_space *mapping = page->mapping;
 
@@ -195,6 +193,30 @@ void __delete_from_page_cache(struct page *page, void *shadow,
        else
                cleancache_invalidate_page(mapping, page);
 
+       VM_BUG_ON_PAGE(page_mapped(page), page);
+       if (!IS_ENABLED(CONFIG_DEBUG_VM) && unlikely(page_mapped(page))) {
+               int mapcount;
+
+               pr_alert("BUG: Bad page cache in process %s  pfn:%05lx\n",
+                        current->comm, page_to_pfn(page));
+               dump_page(page, "still mapped when deleted");
+               dump_stack();
+               add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
+
+               mapcount = page_mapcount(page);
+               if (mapping_exiting(mapping) &&
+                   page_count(page) >= mapcount + 2) {
+                       /*
+                        * All vmas have already been torn down, so it's
+                        * a good bet that actually the page is unmapped,
+                        * and we'd prefer not to leak it: if we're wrong,
+                        * some other bad page check should catch it later.
+                        */
+                       page_mapcount_reset(page);
+                       atomic_sub(mapcount, &page->_count);
+               }
+       }
+
        page_cache_tree_delete(mapping, page, shadow);
 
        page->mapping = NULL;
@@ -205,7 +227,6 @@ void __delete_from_page_cache(struct page *page, void *shadow,
                __dec_zone_page_state(page, NR_FILE_PAGES);
        if (PageSwapBacked(page))
                __dec_zone_page_state(page, NR_SHMEM);
-       VM_BUG_ON_PAGE(page_mapped(page), page);
 
        /*
         * At this point page must be either written or cleaned by truncate.
@@ -216,8 +237,7 @@ void __delete_from_page_cache(struct page *page, void *shadow,
         * anyway will be cleared before returning page into buddy allocator.
         */
        if (WARN_ON_ONCE(PageDirty(page)))
-               account_page_cleaned(page, mapping, memcg,
-                                    inode_to_wb(mapping->host));
+               account_page_cleaned(page, mapping, inode_to_wb(mapping->host));
 }
 
 /**
@@ -231,7 +251,6 @@ void __delete_from_page_cache(struct page *page, void *shadow,
 void delete_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
-       struct mem_cgroup *memcg;
        unsigned long flags;
 
        void (*freepage)(struct page *);
@@ -240,11 +259,9 @@ void delete_from_page_cache(struct page *page)
 
        freepage = mapping->a_ops->freepage;
 
-       memcg = mem_cgroup_begin_page_stat(page);
        spin_lock_irqsave(&mapping->tree_lock, flags);
-       __delete_from_page_cache(page, NULL, memcg);
+       __delete_from_page_cache(page, NULL);
        spin_unlock_irqrestore(&mapping->tree_lock, flags);
-       mem_cgroup_end_page_stat(memcg);
 
        if (freepage)
                freepage(page);
@@ -446,7 +463,8 @@ int filemap_write_and_wait(struct address_space *mapping)
 {
        int err = 0;
 
-       if (mapping->nrpages) {
+       if ((!dax_mapping(mapping) && mapping->nrpages) ||
+           (dax_mapping(mapping) && mapping->nrexceptional)) {
                err = filemap_fdatawrite(mapping);
                /*
                 * Even if the above returned error, the pages may be
@@ -482,13 +500,8 @@ int filemap_write_and_wait_range(struct address_space *mapping,
 {
        int err = 0;
 
-       if (dax_mapping(mapping) && mapping->nrexceptional) {
-               err = dax_writeback_mapping_range(mapping, lstart, lend);
-               if (err)
-                       return err;
-       }
-
-       if (mapping->nrpages) {
+       if ((!dax_mapping(mapping) && mapping->nrpages) ||
+           (dax_mapping(mapping) && mapping->nrexceptional)) {
                err = __filemap_fdatawrite_range(mapping, lstart, lend,
                                                 WB_SYNC_ALL);
                /* See comment of filemap_write_and_wait() */
@@ -532,7 +545,6 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask)
        if (!error) {
                struct address_space *mapping = old->mapping;
                void (*freepage)(struct page *);
-               struct mem_cgroup *memcg;
                unsigned long flags;
 
                pgoff_t offset = old->index;
@@ -542,9 +554,8 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask)
                new->mapping = mapping;
                new->index = offset;
 
-               memcg = mem_cgroup_begin_page_stat(old);
                spin_lock_irqsave(&mapping->tree_lock, flags);
-               __delete_from_page_cache(old, NULL, memcg);
+               __delete_from_page_cache(old, NULL);
                error = radix_tree_insert(&mapping->page_tree, offset, new);
                BUG_ON(error);
                mapping->nrpages++;
@@ -557,8 +568,7 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask)
                if (PageSwapBacked(new))
                        __inc_zone_page_state(new, NR_SHMEM);
                spin_unlock_irqrestore(&mapping->tree_lock, flags);
-               mem_cgroup_end_page_stat(memcg);
-               mem_cgroup_replace_page(old, new);
+               mem_cgroup_migrate(old, new);
                radix_tree_preload_end();
                if (freepage)
                        freepage(old);
@@ -1649,6 +1659,15 @@ find_page:
                                        index, last_index - index);
                }
                if (!PageUptodate(page)) {
+                       /*
+                        * See comment in do_read_cache_page on why
+                        * wait_on_page_locked is used to avoid unnecessarily
+                        * serialisations and why it's safe.
+                        */
+                       wait_on_page_locked_killable(page);
+                       if (PageUptodate(page))
+                               goto page_ok;
+
                        if (inode->i_blkbits == PAGE_CACHE_SHIFT ||
                                        !mapping->a_ops->is_partially_uptodate)
                                goto page_not_up_to_date;
@@ -2284,7 +2303,7 @@ static struct page *wait_on_page_read(struct page *page)
        return page;
 }
 
-static struct page *__read_cache_page(struct address_space *mapping,
+static struct page *do_read_cache_page(struct address_space *mapping,
                                pgoff_t index,
                                int (*filler)(void *, struct page *),
                                void *data,
@@ -2306,53 +2325,74 @@ repeat:
                        /* Presumably ENOMEM for radix tree node */
                        return ERR_PTR(err);
                }
+
+filler:
                err = filler(data, page);
                if (err < 0) {
                        page_cache_release(page);
-                       page = ERR_PTR(err);
-               } else {
-                       page = wait_on_page_read(page);
+                       return ERR_PTR(err);
                }
-       }
-       return page;
-}
 
-static struct page *do_read_cache_page(struct address_space *mapping,
-                               pgoff_t index,
-                               int (*filler)(void *, struct page *),
-                               void *data,
-                               gfp_t gfp)
-
-{
-       struct page *page;
-       int err;
+               page = wait_on_page_read(page);
+               if (IS_ERR(page))
+                       return page;
+               goto out;
+       }
+       if (PageUptodate(page))
+               goto out;
 
-retry:
-       page = __read_cache_page(mapping, index, filler, data, gfp);
-       if (IS_ERR(page))
-               return page;
+       /*
+        * Page is not up to date and may be locked due one of the following
+        * case a: Page is being filled and the page lock is held
+        * case b: Read/write error clearing the page uptodate status
+        * case c: Truncation in progress (page locked)
+        * case d: Reclaim in progress
+        *
+        * Case a, the page will be up to date when the page is unlocked.
+        *    There is no need to serialise on the page lock here as the page
+        *    is pinned so the lock gives no additional protection. Even if the
+        *    the page is truncated, the data is still valid if PageUptodate as
+        *    it's a race vs truncate race.
+        * Case b, the page will not be up to date
+        * Case c, the page may be truncated but in itself, the data may still
+        *    be valid after IO completes as it's a read vs truncate race. The
+        *    operation must restart if the page is not uptodate on unlock but
+        *    otherwise serialising on page lock to stabilise the mapping gives
+        *    no additional guarantees to the caller as the page lock is
+        *    released before return.
+        * Case d, similar to truncation. If reclaim holds the page lock, it
+        *    will be a race with remove_mapping that determines if the mapping
+        *    is valid on unlock but otherwise the data is valid and there is
+        *    no need to serialise with page lock.
+        *
+        * As the page lock gives no additional guarantee, we optimistically
+        * wait on the page to be unlocked and check if it's up to date and
+        * use the page if it is. Otherwise, the page lock is required to
+        * distinguish between the different cases. The motivation is that we
+        * avoid spurious serialisations and wakeups when multiple processes
+        * wait on the same page for IO to complete.
+        */
+       wait_on_page_locked(page);
        if (PageUptodate(page))
                goto out;
 
+       /* Distinguish between all the cases under the safety of the lock */
        lock_page(page);
+
+       /* Case c or d, restart the operation */
        if (!page->mapping) {
                unlock_page(page);
                page_cache_release(page);
-               goto retry;
+               goto repeat;
        }
+
+       /* Someone else locked and filled the page in a very small window */
        if (PageUptodate(page)) {
                unlock_page(page);
                goto out;
        }
-       err = filler(data, page);
-       if (err < 0) {
-               page_cache_release(page);
-               return ERR_PTR(err);
-       } else {
-               page = wait_on_page_read(page);
-               if (IS_ERR(page))
-                       return page;
-       }
+       goto filler;
+
 out:
        mark_page_accessed(page);
        return page;
index 1c317b85ea7d70e56418e978b5ad72aed058ca2f..1ea21e203a700114587dedca262f9267bb5a005a 100644 (file)
@@ -2836,6 +2836,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
        pgtable_t pgtable;
        pmd_t _pmd;
        bool young, write, dirty;
+       unsigned long addr;
        int i;
 
        VM_BUG_ON(haddr & ~HPAGE_PMD_MASK);
@@ -2865,7 +2866,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
        pgtable = pgtable_trans_huge_withdraw(mm, pmd);
        pmd_populate(mm, &_pmd, pgtable);
 
-       for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+       for (i = 0, addr = haddr; i < HPAGE_PMD_NR; i++, addr += PAGE_SIZE) {
                pte_t entry, *pte;
                /*
                 * Note that NUMA hinting access restrictions are not
@@ -2886,9 +2887,9 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
                }
                if (dirty)
                        SetPageDirty(page + i);
-               pte = pte_offset_map(&_pmd, haddr);
+               pte = pte_offset_map(&_pmd, addr);
                BUG_ON(!pte_none(*pte));
-               set_pte_at(mm, haddr, pte, entry);
+               set_pte_at(mm, addr, pte, entry);
                atomic_inc(&page[i]._mapcount);
                pte_unmap(pte);
        }
@@ -2938,7 +2939,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
        pmd_populate(mm, pmd, pgtable);
 
        if (freeze) {
-               for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
+               for (i = 0; i < HPAGE_PMD_NR; i++) {
                        page_remove_rmap(page + i, false);
                        put_page(page + i);
                }
@@ -3219,28 +3220,26 @@ static void unfreeze_page(struct anon_vma *anon_vma, struct page *page)
        }
 }
 
-static int __split_huge_page_tail(struct page *head, int tail,
+static void __split_huge_page_tail(struct page *head, int tail,
                struct lruvec *lruvec, struct list_head *list)
 {
-       int mapcount;
        struct page *page_tail = head + tail;
 
-       mapcount = atomic_read(&page_tail->_mapcount) + 1;
+       VM_BUG_ON_PAGE(atomic_read(&page_tail->_mapcount) != -1, page_tail);
        VM_BUG_ON_PAGE(atomic_read(&page_tail->_count) != 0, page_tail);
 
        /*
         * tail_page->_count is zero and not changing from under us. But
         * get_page_unless_zero() may be running from under us on the
-        * tail_page. If we used atomic_set() below instead of atomic_add(), we
+        * tail_page. If we used atomic_set() below instead of atomic_inc(), we
         * would then run atomic_set() concurrently with
         * get_page_unless_zero(), and atomic_set() is implemented in C not
         * using locked ops. spin_unlock on x86 sometime uses locked ops
         * because of PPro errata 66, 92, so unless somebody can guarantee
         * atomic_set() here would be safe on all archs (and not only on x86),
-        * it's safer to use atomic_add().
+        * it's safer to use atomic_inc().
         */
-       atomic_add(mapcount + 1, &page_tail->_count);
-
+       atomic_inc(&page_tail->_count);
 
        page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
        page_tail->flags |= (head->flags &
@@ -3274,8 +3273,6 @@ static int __split_huge_page_tail(struct page *head, int tail,
        page_tail->index = head->index + tail;
        page_cpupid_xchg_last(page_tail, page_cpupid_last(head));
        lru_add_page_tail(head, page_tail, lruvec, list);
-
-       return mapcount;
 }
 
 static void __split_huge_page(struct page *page, struct list_head *list)
@@ -3283,7 +3280,7 @@ static void __split_huge_page(struct page *page, struct list_head *list)
        struct page *head = compound_head(page);
        struct zone *zone = page_zone(head);
        struct lruvec *lruvec;
-       int i, tail_mapcount;
+       int i;
 
        /* prevent PageLRU to go away from under us, and freeze lru stats */
        spin_lock_irq(&zone->lru_lock);
@@ -3292,10 +3289,8 @@ static void __split_huge_page(struct page *page, struct list_head *list)
        /* complete memcg works before add pages to LRU */
        mem_cgroup_split_huge_fixup(head);
 
-       tail_mapcount = 0;
        for (i = HPAGE_PMD_NR - 1; i >= 1; i--)
-               tail_mapcount += __split_huge_page_tail(head, i, lruvec, list);
-       atomic_sub(tail_mapcount, &head->_count);
+               __split_huge_page_tail(head, i, lruvec, list);
 
        ClearPageCompound(head);
        spin_unlock_irq(&zone->lru_lock);
index 01f2b48c8618a9f973eeb11f2162b75bb8cf67d4..aefba5a9cc47f74880dbbb3491a8927fcf999b06 100644 (file)
@@ -2751,7 +2751,7 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
        int ret;
 
        if (!hugepages_supported())
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        table->data = &tmp;
        table->maxlen = sizeof(unsigned long);
@@ -2792,7 +2792,7 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
        int ret;
 
        if (!hugepages_supported())
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 
        tmp = h->nr_overcommit_huge_pages;
 
@@ -3502,7 +3502,7 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
         * COW. Warn that such a situation has occurred as it may not be obvious
         */
        if (is_vma_resv_set(vma, HPAGE_RESV_UNMAPPED)) {
-               pr_warning("PID %d killed due to inadequate hugepage pool\n",
+               pr_warn_ratelimited("PID %d killed due to inadequate hugepage pool\n",
                           current->pid);
                return ret;
        }
index a38a21ebddb454540fc1dcae83be516ffc7cdf26..ad9400d759c8a64300657a395317dd3ac771cf0c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
+#include <linux/tracepoint-defs.h>
 
 /*
  * The set of flags that only affect watermark checking and reclaim
@@ -131,6 +132,18 @@ __find_buddy_index(unsigned long page_idx, unsigned int order)
        return page_idx ^ (1 << order);
 }
 
+extern struct page *__pageblock_pfn_to_page(unsigned long start_pfn,
+                               unsigned long end_pfn, struct zone *zone);
+
+static inline struct page *pageblock_pfn_to_page(unsigned long start_pfn,
+                               unsigned long end_pfn, struct zone *zone)
+{
+       if (zone->contiguous)
+               return pfn_to_page(start_pfn);
+
+       return __pageblock_pfn_to_page(start_pfn, end_pfn, zone);
+}
+
 extern int __isolate_free_page(struct page *page, unsigned int order);
 extern void __free_pages_bootmem(struct page *page, unsigned long pfn,
                                        unsigned int order);
@@ -466,4 +479,9 @@ static inline void try_to_unmap_flush_dirty(void)
 }
 
 #endif /* CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH */
+
+extern const struct trace_print_flags pageflag_names[];
+extern const struct trace_print_flags vmaflag_names[];
+extern const struct trace_print_flags gfpflag_names[];
+
 #endif /* __MM_INTERNAL_H */
index bc0a8d8b8f42faf7bca01501425ba73e156ee293..1ad20ade8c91328d2f47e8c116f9aca6bc2fb57f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/kmemleak.h>
+#include <linux/linkage.h>
 #include <linux/memblock.h>
 #include <linux/memory.h>
 #include <linux/mm.h>
@@ -60,6 +61,25 @@ void kasan_unpoison_shadow(const void *address, size_t size)
        }
 }
 
+static void __kasan_unpoison_stack(struct task_struct *task, void *sp)
+{
+       void *base = task_stack_page(task);
+       size_t size = sp - base;
+
+       kasan_unpoison_shadow(base, size);
+}
+
+/* Unpoison the entire stack for a task. */
+void kasan_unpoison_task_stack(struct task_struct *task)
+{
+       __kasan_unpoison_stack(task, task_stack_page(task) + THREAD_SIZE);
+}
+
+/* Unpoison the stack for the current task beyond a watermark sp value. */
+asmlinkage void kasan_unpoison_remaining_stack(void *sp)
+{
+       __kasan_unpoison_stack(current, sp);
+}
 
 /*
  * All functions below always inlined so compiler could
index cab58bb592d8fa881dccfcddf0dcc7612f05128b..6f4f424037c0dafd4b034fb33d90d9f038733810 100644 (file)
@@ -60,6 +60,9 @@ void kmemcheck_free_shadow(struct page *page, int order)
 void kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
                          size_t size)
 {
+       if (unlikely(!object)) /* Skip object if allocation failed */
+               return;
+
        /*
         * Has already been memset(), which initializes the shadow for us
         * as well.
index f56825b6d2e103c920d2b21cfb56e316dcea9418..a01147359f3bb71c9c34b9c14f97ad0a730d33e5 100644 (file)
@@ -555,8 +555,9 @@ static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end)
                }
                pr_info("Injecting memory failure for page %#lx at %#lx\n",
                       page_to_pfn(p), start);
-               /* Ignore return value for now */
-               memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED);
+               ret = memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED);
+               if (ret)
+                       return ret;
        }
        return 0;
 }
@@ -638,14 +639,28 @@ madvise_behavior_valid(int behavior)
  *             some pages ahead.
  *  MADV_DONTNEED - the application is finished with the given range,
  *             so the kernel can free resources associated with it.
+ *  MADV_FREE - the application marks pages in the given range as lazy free,
+ *             where actual purges are postponed until memory pressure happens.
  *  MADV_REMOVE - the application wants to free up the given range of
  *             pages and associated backing store.
  *  MADV_DONTFORK - omit this area from child's address space when forking:
  *             typically, to avoid COWing pages pinned by get_user_pages().
  *  MADV_DOFORK - cancel MADV_DONTFORK: no longer omit this area when forking.
+ *  MADV_HWPOISON - trigger memory error handler as if the given memory range
+ *             were corrupted by unrecoverable hardware memory failure.
+ *  MADV_SOFT_OFFLINE - try to soft-offline the given range of memory.
  *  MADV_MERGEABLE - the application recommends that KSM try to merge pages in
  *             this area with pages of identical content from other such areas.
  *  MADV_UNMERGEABLE- cancel MADV_MERGEABLE: no longer merge pages with others.
+ *  MADV_HUGEPAGE - the application wants to back the given range by transparent
+ *             huge pages in the future. Existing pages might be coalesced and
+ *             new pages might be allocated as THP.
+ *  MADV_NOHUGEPAGE - mark the given range as not worth being backed by
+ *             transparent huge pages so the existing pages will not be
+ *             coalesced into THP and new pages will not be allocated as THP.
+ *  MADV_DONTDUMP - the application wants to prevent pages in the given range
+ *             from being included in its core dump.
+ *  MADV_DODUMP - cancel MADV_DONTDUMP: no longer exclude from core dump.
  *
  * return values:
  *  zero    - success
index dd7989929f13ae16e265bff30fd958f1f13993cb..fc7824fa1b422f044c37dfa3d899a0df7eaeb26a 100644 (file)
@@ -612,14 +612,12 @@ static int __init_memblock memblock_add_region(phys_addr_t base,
                                                int nid,
                                                unsigned long flags)
 {
-       struct memblock_type *type = &memblock.memory;
-
        memblock_dbg("memblock_add: [%#016llx-%#016llx] flags %#02lx %pF\n",
                     (unsigned long long)base,
                     (unsigned long long)base + size - 1,
                     flags, (void *)_RET_IP_);
 
-       return memblock_add_range(type, base, size, nid, flags);
+       return memblock_add_range(&memblock.memory, base, size, nid, flags);
 }
 
 int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
@@ -740,14 +738,12 @@ static int __init_memblock memblock_reserve_region(phys_addr_t base,
                                                   int nid,
                                                   unsigned long flags)
 {
-       struct memblock_type *type = &memblock.reserved;
-
        memblock_dbg("memblock_reserve: [%#016llx-%#016llx] flags %#02lx %pF\n",
                     (unsigned long long)base,
                     (unsigned long long)base + size - 1,
                     flags, (void *)_RET_IP_);
 
-       return memblock_add_range(type, base, size, nid, flags);
+       return memblock_add_range(&memblock.reserved, base, size, nid, flags);
 }
 
 int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
index d06cae2de783acf462162e27f8770ff7bf60f4ad..42882c1e7fcea1a5896a77d58af2e6e87aabc898 100644 (file)
@@ -268,31 +268,6 @@ static inline bool mem_cgroup_is_root(struct mem_cgroup *memcg)
        return (memcg == root_mem_cgroup);
 }
 
-/*
- * We restrict the id in the range of [1, 65535], so it can fit into
- * an unsigned short.
- */
-#define MEM_CGROUP_ID_MAX      USHRT_MAX
-
-static inline unsigned short mem_cgroup_id(struct mem_cgroup *memcg)
-{
-       return memcg->css.id;
-}
-
-/*
- * A helper function to get mem_cgroup from ID. must be called under
- * rcu_read_lock().  The caller is responsible for calling
- * css_tryget_online() if the mem_cgroup is used for charging. (dropping
- * refcnt from swap can be called against removed memcg.)
- */
-static inline struct mem_cgroup *mem_cgroup_from_id(unsigned short id)
-{
-       struct cgroup_subsys_state *css;
-
-       css = css_from_id(id, &memory_cgrp_subsys);
-       return mem_cgroup_from_css(css);
-}
-
 #ifndef CONFIG_SLOB
 /*
  * This will be the memcg's index in each cache's ->memcg_params.memcg_caches.
@@ -1709,19 +1684,13 @@ cleanup:
 }
 
 /**
- * mem_cgroup_begin_page_stat - begin a page state statistics transaction
- * @page: page that is going to change accounted state
- *
- * This function must mark the beginning of an accounted page state
- * change to prevent double accounting when the page is concurrently
- * being moved to another memcg:
+ * lock_page_memcg - lock a page->mem_cgroup binding
+ * @page: the page
  *
- *   memcg = mem_cgroup_begin_page_stat(page);
- *   if (TestClearPageState(page))
- *     mem_cgroup_update_page_stat(memcg, state, -1);
- *   mem_cgroup_end_page_stat(memcg);
+ * This function protects unlocked LRU pages from being moved to
+ * another cgroup and stabilizes their page->mem_cgroup binding.
  */
-struct mem_cgroup *mem_cgroup_begin_page_stat(struct page *page)
+void lock_page_memcg(struct page *page)
 {
        struct mem_cgroup *memcg;
        unsigned long flags;
@@ -1730,25 +1699,18 @@ struct mem_cgroup *mem_cgroup_begin_page_stat(struct page *page)
         * The RCU lock is held throughout the transaction.  The fast
         * path can get away without acquiring the memcg->move_lock
         * because page moving starts with an RCU grace period.
-        *
-        * The RCU lock also protects the memcg from being freed when
-        * the page state that is going to change is the only thing
-        * preventing the page from being uncharged.
-        * E.g. end-writeback clearing PageWriteback(), which allows
-        * migration to go ahead and uncharge the page before the
-        * account transaction might be complete.
         */
        rcu_read_lock();
 
        if (mem_cgroup_disabled())
-               return NULL;
+               return;
 again:
        memcg = page->mem_cgroup;
        if (unlikely(!memcg))
-               return NULL;
+               return;
 
        if (atomic_read(&memcg->moving_account) <= 0)
-               return memcg;
+               return;
 
        spin_lock_irqsave(&memcg->move_lock, flags);
        if (memcg != page->mem_cgroup) {
@@ -1759,21 +1721,23 @@ again:
        /*
         * When charge migration first begins, we can have locked and
         * unlocked page stat updates happening concurrently.  Track
-        * the task who has the lock for mem_cgroup_end_page_stat().
+        * the task who has the lock for unlock_page_memcg().
         */
        memcg->move_lock_task = current;
        memcg->move_lock_flags = flags;
 
-       return memcg;
+       return;
 }
-EXPORT_SYMBOL(mem_cgroup_begin_page_stat);
+EXPORT_SYMBOL(lock_page_memcg);
 
 /**
- * mem_cgroup_end_page_stat - finish a page state statistics transaction
- * @memcg: the memcg that was accounted against
+ * unlock_page_memcg - unlock a page->mem_cgroup binding
+ * @page: the page
  */
-void mem_cgroup_end_page_stat(struct mem_cgroup *memcg)
+void unlock_page_memcg(struct page *page)
 {
+       struct mem_cgroup *memcg = page->mem_cgroup;
+
        if (memcg && memcg->move_lock_task == current) {
                unsigned long flags = memcg->move_lock_flags;
 
@@ -1785,7 +1749,7 @@ void mem_cgroup_end_page_stat(struct mem_cgroup *memcg)
 
        rcu_read_unlock();
 }
-EXPORT_SYMBOL(mem_cgroup_end_page_stat);
+EXPORT_SYMBOL(unlock_page_memcg);
 
 /*
  * size of first charge trial. "32" comes from vmscan.c's magic value.
@@ -4488,7 +4452,7 @@ static int mem_cgroup_move_account(struct page *page,
        VM_BUG_ON(compound && !PageTransHuge(page));
 
        /*
-        * Prevent mem_cgroup_replace_page() from looking at
+        * Prevent mem_cgroup_migrate() from looking at
         * page->mem_cgroup of its source page while we change it.
         */
        ret = -EBUSY;
@@ -4923,9 +4887,9 @@ static void mem_cgroup_move_charge(struct mm_struct *mm)
 
        lru_add_drain_all();
        /*
-        * Signal mem_cgroup_begin_page_stat() to take the memcg's
-        * move_lock while we're moving its pages to another memcg.
-        * Then wait for already started RCU-only updates to finish.
+        * Signal lock_page_memcg() to take the memcg's move_lock
+        * while we're moving its pages to another memcg. Then wait
+        * for already started RCU-only updates to finish.
         */
        atomic_inc(&mc.from->moving_account);
        synchronize_rcu();
@@ -5517,16 +5481,16 @@ void mem_cgroup_uncharge_list(struct list_head *page_list)
 }
 
 /**
- * mem_cgroup_replace_page - migrate a charge to another page
- * @oldpage: currently charged page
- * @newpage: page to transfer the charge to
+ * mem_cgroup_migrate - charge a page's replacement
+ * @oldpage: currently circulating page
+ * @newpage: replacement page
  *
- * Migrate the charge from @oldpage to @newpage.
+ * Charge @newpage as a replacement page for @oldpage. @oldpage will
+ * be uncharged upon free.
  *
  * Both pages must be locked, @newpage->mapping must be set up.
- * Either or both pages might be on the LRU already.
  */
-void mem_cgroup_replace_page(struct page *oldpage, struct page *newpage)
+void mem_cgroup_migrate(struct page *oldpage, struct page *newpage)
 {
        struct mem_cgroup *memcg;
        unsigned int nr_pages;
@@ -5559,7 +5523,7 @@ void mem_cgroup_replace_page(struct page *oldpage, struct page *newpage)
                page_counter_charge(&memcg->memsw, nr_pages);
        css_get_many(&memcg->css, nr_pages);
 
-       commit_charge(newpage, memcg, true);
+       commit_charge(newpage, memcg, false);
 
        local_irq_disable();
        mem_cgroup_charge_statistics(memcg, newpage, compound, nr_pages);
index ac595e7a3a955d457e8ff3b6934e8728e8db6d5d..67c30eb993f0e73c33a4565bde7565e4f5202b51 100644 (file)
@@ -826,8 +826,6 @@ static struct page_state {
 #undef lru
 #undef swapbacked
 #undef head
-#undef tail
-#undef compound
 #undef slab
 #undef reserved
 
index 635451abc8f7c9b84663535678a26a9b0848c89d..0e247642ed5b7567ebbf97259df003580bfffb4d 100644 (file)
@@ -1550,9 +1550,30 @@ out:
  */
 int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
                        unsigned long pfn)
+{
+       return vm_insert_pfn_prot(vma, addr, pfn, vma->vm_page_prot);
+}
+EXPORT_SYMBOL(vm_insert_pfn);
+
+/**
+ * vm_insert_pfn_prot - insert single pfn into user vma with specified pgprot
+ * @vma: user vma to map to
+ * @addr: target user address of this page
+ * @pfn: source kernel pfn
+ * @pgprot: pgprot flags for the inserted page
+ *
+ * This is exactly like vm_insert_pfn, except that it allows drivers to
+ * to override pgprot on a per-page basis.
+ *
+ * This only makes sense for IO mappings, and it makes no sense for
+ * cow mappings.  In general, using multiple vmas is preferable;
+ * vm_insert_pfn_prot should only be used if using multiple VMAs is
+ * impractical.
+ */
+int vm_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr,
+                       unsigned long pfn, pgprot_t pgprot)
 {
        int ret;
-       pgprot_t pgprot = vma->vm_page_prot;
        /*
         * Technically, architectures with pte_special can avoid all these
         * restrictions (same for remap_pfn_range).  However we would like
@@ -1574,7 +1595,7 @@ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
 
        return ret;
 }
-EXPORT_SYMBOL(vm_insert_pfn);
+EXPORT_SYMBOL(vm_insert_pfn_prot);
 
 int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
                        pfn_t pfn)
@@ -1876,7 +1897,9 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
        unsigned long end = addr + size;
        int err;
 
-       BUG_ON(addr >= end);
+       if (WARN_ON(addr >= end))
+               return -EINVAL;
+
        pgd = pgd_offset(mm, addr);
        do {
                next = pgd_addr_end(addr, end);
@@ -3122,8 +3145,7 @@ static int do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                unsigned long address, pte_t *page_table, pmd_t *pmd,
                unsigned int flags, pte_t orig_pte)
 {
-       pgoff_t pgoff = (((address & PAGE_MASK)
-                       - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+       pgoff_t pgoff = linear_page_index(vma, address);
 
        pte_unmap(page_table);
        /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */
@@ -3404,8 +3426,18 @@ static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        if (unlikely(pmd_none(*pmd)) &&
            unlikely(__pte_alloc(mm, vma, pmd, address)))
                return VM_FAULT_OOM;
-       /* if an huge pmd materialized from under us just retry later */
-       if (unlikely(pmd_trans_huge(*pmd) || pmd_devmap(*pmd)))
+       /*
+        * If a huge pmd materialized under us just retry later.  Use
+        * pmd_trans_unstable() instead of pmd_trans_huge() to ensure the pmd
+        * didn't become pmd_trans_huge under us and then back to pmd_none, as
+        * a result of MADV_DONTNEED running immediately after a huge pmd fault
+        * in a different thread of this mm, in turn leading to a misleading
+        * pmd_trans_huge() retval.  All we have to ensure is that it is a
+        * regular pmd that we can walk with pte_offset_map() and we can do that
+        * through an atomic read in C, which is what pmd_trans_unstable()
+        * provides.
+        */
+       if (unlikely(pmd_trans_unstable(pmd) || pmd_devmap(*pmd)))
                return 0;
        /*
         * A regular pmd is established and it can't morph into a huge pmd
index 4af58a3a8ffa345c16fe190be76ba9f9e83113d4..24ea06393816c58b43a857bb5e1cc05dbdfc4712 100644 (file)
@@ -77,6 +77,9 @@ static struct {
 #define memhp_lock_acquire()      lock_map_acquire(&mem_hotplug.dep_map)
 #define memhp_lock_release()      lock_map_release(&mem_hotplug.dep_map)
 
+bool memhp_auto_online;
+EXPORT_SYMBOL_GPL(memhp_auto_online);
+
 void get_online_mems(void)
 {
        might_sleep();
@@ -138,7 +141,7 @@ static struct resource *register_memory_resource(u64 start, u64 size)
        res->name = "System RAM";
        res->start = start;
        res->end = start + size - 1;
-       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
        if (request_resource(&iomem_resource, res) < 0) {
                pr_debug("System RAM resource %pR cannot be added\n", res);
                kfree(res);
@@ -509,6 +512,8 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
        int start_sec, end_sec;
        struct vmem_altmap *altmap;
 
+       clear_zone_contiguous(zone);
+
        /* during initialize mem_map, align hot-added range to section */
        start_sec = pfn_to_section_nr(phys_start_pfn);
        end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1);
@@ -521,7 +526,8 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
                if (altmap->base_pfn != phys_start_pfn
                                || vmem_altmap_offset(altmap) > nr_pages) {
                        pr_warn_once("memory add fail, invalid altmap\n");
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto out;
                }
                altmap->alloc = 0;
        }
@@ -539,7 +545,8 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
                err = 0;
        }
        vmemmap_populate_print_last();
-
+out:
+       set_zone_contiguous(zone);
        return err;
 }
 EXPORT_SYMBOL_GPL(__add_pages);
@@ -811,6 +818,8 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
                }
        }
 
+       clear_zone_contiguous(zone);
+
        /*
         * We can only remove entire sections
         */
@@ -826,6 +835,9 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
                if (ret)
                        break;
        }
+
+       set_zone_contiguous(zone);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(__remove_pages);
@@ -1261,8 +1273,13 @@ int zone_for_memory(int nid, u64 start, u64 size, int zone_default,
        return zone_default;
 }
 
+static int online_memory_block(struct memory_block *mem, void *arg)
+{
+       return memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
+}
+
 /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
-int __ref add_memory_resource(int nid, struct resource *res)
+int __ref add_memory_resource(int nid, struct resource *res, bool online)
 {
        u64 start, size;
        pg_data_t *pgdat = NULL;
@@ -1322,6 +1339,11 @@ int __ref add_memory_resource(int nid, struct resource *res)
        /* create new memmap entry */
        firmware_map_add_hotplug(start, start + size, "System RAM");
 
+       /* online pages if requested */
+       if (online)
+               walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1),
+                                 NULL, online_memory_block);
+
        goto out;
 
 error:
@@ -1345,7 +1367,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
        if (IS_ERR(res))
                return PTR_ERR(res);
 
-       ret = add_memory_resource(nid, res);
+       ret = add_memory_resource(nid, res, memhp_auto_online);
        if (ret < 0)
                release_memory_resource(res);
        return ret;
index 4c4187c0e1deeb25bdbf5eb383132d27feb9be90..8cbc74387df38c5572001bd2e06bd8da1af5ab70 100644 (file)
@@ -532,7 +532,7 @@ retry:
                nid = page_to_nid(page);
                if (node_isset(nid, *qp->nmask) == !!(flags & MPOL_MF_INVERT))
                        continue;
-               if (PageTail(page) && PageAnon(page)) {
+               if (PageTransCompound(page) && PageAnon(page)) {
                        get_page(page);
                        pte_unmap_unlock(pte, ptl);
                        lock_page(page);
@@ -643,7 +643,9 @@ static int queue_pages_test_walk(unsigned long start, unsigned long end,
 
        if (flags & MPOL_MF_LAZY) {
                /* Similar to task_numa_work, skip inaccessible VMAs */
-               if (vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))
+               if (!is_vm_hugetlb_page(vma) &&
+                       (vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)) &&
+                       !(vma->vm_flags & VM_MIXEDMAP))
                        change_prot_numa(vma, start, endvma);
                return 1;
        }
index 004d42b1dfaf928ab174e057696afa580447f3d9..7924f4f58a6d48ae5335fdedb1c2e2dd93a56d88 100644 (file)
@@ -135,8 +135,8 @@ static void *remove_element(mempool_t *pool)
        void *element = pool->elements[--pool->curr_nr];
 
        BUG_ON(pool->curr_nr < 0);
-       check_element(pool, element);
        kasan_unpoison_element(pool, element);
+       check_element(pool, element);
        return element;
 }
 
index b1034f9c77e7d5a9bdbe60692396e5584c6991fc..568284ec75d419863866f43065003883b8d81939 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/balloon_compaction.h>
 #include <linux/mmu_notifier.h>
 #include <linux/page_idle.h>
+#include <linux/page_owner.h>
 
 #include <asm/tlbflush.h>
 
@@ -325,7 +326,6 @@ int migrate_page_move_mapping(struct address_space *mapping,
                        return -EAGAIN;
 
                /* No turning back from here */
-               set_page_memcg(newpage, page_memcg(page));
                newpage->index = page->index;
                newpage->mapping = page->mapping;
                if (PageSwapBacked(page))
@@ -372,7 +372,6 @@ int migrate_page_move_mapping(struct address_space *mapping,
         * Now we know that no one else is looking at the page:
         * no turning back from here.
         */
-       set_page_memcg(newpage, page_memcg(page));
        newpage->index = page->index;
        newpage->mapping = page->mapping;
        if (PageSwapBacked(page))
@@ -457,9 +456,9 @@ int migrate_huge_page_move_mapping(struct address_space *mapping,
                return -EAGAIN;
        }
 
-       set_page_memcg(newpage, page_memcg(page));
        newpage->index = page->index;
        newpage->mapping = page->mapping;
+
        get_page(newpage);
 
        radix_tree_replace_slot(pslot, newpage);
@@ -467,6 +466,7 @@ int migrate_huge_page_move_mapping(struct address_space *mapping,
        page_unfreeze_refs(page, expected_count - 1);
 
        spin_unlock_irq(&mapping->tree_lock);
+
        return MIGRATEPAGE_SUCCESS;
 }
 
@@ -578,6 +578,10 @@ void migrate_page_copy(struct page *newpage, struct page *page)
         */
        if (PageWriteback(newpage))
                end_page_writeback(newpage);
+
+       copy_page_owner(page, newpage);
+
+       mem_cgroup_migrate(page, newpage);
 }
 
 /************************************************************
@@ -772,7 +776,6 @@ static int move_to_new_page(struct page *newpage, struct page *page,
         * page is freed; but stats require that PageAnon be left as PageAnon.
         */
        if (rc == MIGRATEPAGE_SUCCESS) {
-               set_page_memcg(page, NULL);
                if (!PageAnon(page))
                        page->mapping = NULL;
        }
@@ -952,8 +955,10 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page,
        }
 
        rc = __unmap_and_move(page, newpage, force, mode);
-       if (rc == MIGRATEPAGE_SUCCESS)
+       if (rc == MIGRATEPAGE_SUCCESS) {
                put_new_page = NULL;
+               set_page_owner_migrate_reason(newpage, reason);
+       }
 
 out:
        if (rc != -EAGAIN) {
@@ -1018,7 +1023,7 @@ out:
 static int unmap_and_move_huge_page(new_page_t get_new_page,
                                free_page_t put_new_page, unsigned long private,
                                struct page *hpage, int force,
-                               enum migrate_mode mode)
+                               enum migrate_mode mode, int reason)
 {
        int rc = -EAGAIN;
        int *result = NULL;
@@ -1076,6 +1081,7 @@ put_anon:
        if (rc == MIGRATEPAGE_SUCCESS) {
                hugetlb_cgroup_migrate(hpage, new_hpage);
                put_new_page = NULL;
+               set_page_owner_migrate_reason(new_hpage, reason);
        }
 
        unlock_page(hpage);
@@ -1148,7 +1154,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
                        if (PageHuge(page))
                                rc = unmap_and_move_huge_page(get_new_page,
                                                put_new_page, private, page,
-                                               pass > 2, mode);
+                                               pass > 2, mode, reason);
                        else
                                rc = unmap_and_move(get_new_page, put_new_page,
                                                private, page, pass > 2, mode,
@@ -1582,7 +1588,7 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
                                         (GFP_HIGHUSER_MOVABLE |
                                          __GFP_THISNODE | __GFP_NOMEMALLOC |
                                          __GFP_NORETRY | __GFP_NOWARN) &
-                                        ~(__GFP_IO | __GFP_FS), 0);
+                                        ~__GFP_RECLAIM, 0);
 
        return newpage;
 }
@@ -1836,9 +1842,8 @@ fail_putback:
        }
 
        mlock_migrate_page(new_page, page);
-       set_page_memcg(new_page, page_memcg(page));
-       set_page_memcg(page, NULL);
        page_remove_rmap(page, true);
+       set_page_owner_migrate_reason(new_page, MR_NUMA_MISPLACED);
 
        spin_unlock(ptl);
        mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
index 76d1ec29149bf25f5e6ffe3e56e86467efccc641..90e3b869a8b9daed1ed426dd8d2bec0ee950c785 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -3066,11 +3066,16 @@ static int special_mapping_fault(struct vm_area_struct *vma,
        pgoff_t pgoff;
        struct page **pages;
 
-       if (vma->vm_ops == &legacy_special_mapping_vmops)
+       if (vma->vm_ops == &legacy_special_mapping_vmops) {
                pages = vma->vm_private_data;
-       else
-               pages = ((struct vm_special_mapping *)vma->vm_private_data)->
-                       pages;
+       } else {
+               struct vm_special_mapping *sm = vma->vm_private_data;
+
+               if (sm->fault)
+                       return sm->fault(sm, vma, vmf);
+
+               pages = sm->pages;
+       }
 
        for (pgoff = vmf->pgoff; pgoff && *pages; ++pages)
                pgoff--;
index dc490c06941b2a6be5170c0d9ca73418b7fe8619..e97a05d9621f47425a25f88fb9c0ae8fbd50004b 100644 (file)
@@ -386,10 +386,11 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask)
 static void dump_header(struct oom_control *oc, struct task_struct *p,
                        struct mem_cgroup *memcg)
 {
-       pr_warning("%s invoked oom-killer: gfp_mask=0x%x, order=%d, "
-               "oom_score_adj=%hd\n",
-               current->comm, oc->gfp_mask, oc->order,
+       pr_warn("%s invoked oom-killer: gfp_mask=%#x(%pGg), order=%d, "
+                       "oom_score_adj=%hd\n",
+               current->comm, oc->gfp_mask, &oc->gfp_mask, oc->order,
                current->signal->oom_score_adj);
+
        cpuset_print_current_mems_allowed();
        dump_stack();
        if (memcg)
index 6fe7d15bd1f7804e87f192c6b06b681ac6c51896..11ff8f75863105b773ee279fee5d6853e4680abb 100644 (file)
@@ -1169,6 +1169,7 @@ static void wb_update_dirty_ratelimit(struct dirty_throttle_control *dtc,
        unsigned long balanced_dirty_ratelimit;
        unsigned long step;
        unsigned long x;
+       unsigned long shift;
 
        /*
         * The dirty rate will match the writeout rate in long term, except
@@ -1293,11 +1294,11 @@ static void wb_update_dirty_ratelimit(struct dirty_throttle_control *dtc,
         * rate itself is constantly fluctuating. So decrease the track speed
         * when it gets close to the target. Helps eliminate pointless tremors.
         */
-       step >>= dirty_ratelimit / (2 * step + 1);
-       /*
-        * Limit the tracking speed to avoid overshooting.
-        */
-       step = (step + 7) / 8;
+       shift = dirty_ratelimit / (2 * step + 1);
+       if (shift < BITS_PER_LONG)
+               step = DIV_ROUND_UP(step >> shift, 8);
+       else
+               step = 0;
 
        if (dirty_ratelimit < balanced_dirty_ratelimit)
                dirty_ratelimit += step;
@@ -2409,12 +2410,11 @@ int __set_page_dirty_no_writeback(struct page *page)
 /*
  * Helper function for set_page_dirty family.
  *
- * Caller must hold mem_cgroup_begin_page_stat().
+ * Caller must hold lock_page_memcg().
  *
  * NOTE: This relies on being atomic wrt interrupts.
  */
-void account_page_dirtied(struct page *page, struct address_space *mapping,
-                         struct mem_cgroup *memcg)
+void account_page_dirtied(struct page *page, struct address_space *mapping)
 {
        struct inode *inode = mapping->host;
 
@@ -2426,7 +2426,7 @@ void account_page_dirtied(struct page *page, struct address_space *mapping,
                inode_attach_wb(inode, page);
                wb = inode_to_wb(inode);
 
-               mem_cgroup_inc_page_stat(memcg, MEM_CGROUP_STAT_DIRTY);
+               mem_cgroup_inc_page_stat(page, MEM_CGROUP_STAT_DIRTY);
                __inc_zone_page_state(page, NR_FILE_DIRTY);
                __inc_zone_page_state(page, NR_DIRTIED);
                __inc_wb_stat(wb, WB_RECLAIMABLE);
@@ -2441,13 +2441,13 @@ EXPORT_SYMBOL(account_page_dirtied);
 /*
  * Helper function for deaccounting dirty page without writeback.
  *
- * Caller must hold mem_cgroup_begin_page_stat().
+ * Caller must hold lock_page_memcg().
  */
 void account_page_cleaned(struct page *page, struct address_space *mapping,
-                         struct mem_cgroup *memcg, struct bdi_writeback *wb)
+                         struct bdi_writeback *wb)
 {
        if (mapping_cap_account_dirty(mapping)) {
-               mem_cgroup_dec_page_stat(memcg, MEM_CGROUP_STAT_DIRTY);
+               mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_DIRTY);
                dec_zone_page_state(page, NR_FILE_DIRTY);
                dec_wb_stat(wb, WB_RECLAIMABLE);
                task_io_account_cancelled_write(PAGE_CACHE_SIZE);
@@ -2468,26 +2468,24 @@ void account_page_cleaned(struct page *page, struct address_space *mapping,
  */
 int __set_page_dirty_nobuffers(struct page *page)
 {
-       struct mem_cgroup *memcg;
-
-       memcg = mem_cgroup_begin_page_stat(page);
+       lock_page_memcg(page);
        if (!TestSetPageDirty(page)) {
                struct address_space *mapping = page_mapping(page);
                unsigned long flags;
 
                if (!mapping) {
-                       mem_cgroup_end_page_stat(memcg);
+                       unlock_page_memcg(page);
                        return 1;
                }
 
                spin_lock_irqsave(&mapping->tree_lock, flags);
                BUG_ON(page_mapping(page) != mapping);
                WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page));
-               account_page_dirtied(page, mapping, memcg);
+               account_page_dirtied(page, mapping);
                radix_tree_tag_set(&mapping->page_tree, page_index(page),
                                   PAGECACHE_TAG_DIRTY);
                spin_unlock_irqrestore(&mapping->tree_lock, flags);
-               mem_cgroup_end_page_stat(memcg);
+               unlock_page_memcg(page);
 
                if (mapping->host) {
                        /* !PageAnon && !swapper_space */
@@ -2495,7 +2493,7 @@ int __set_page_dirty_nobuffers(struct page *page)
                }
                return 1;
        }
-       mem_cgroup_end_page_stat(memcg);
+       unlock_page_memcg(page);
        return 0;
 }
 EXPORT_SYMBOL(__set_page_dirty_nobuffers);
@@ -2625,17 +2623,16 @@ void cancel_dirty_page(struct page *page)
        if (mapping_cap_account_dirty(mapping)) {
                struct inode *inode = mapping->host;
                struct bdi_writeback *wb;
-               struct mem_cgroup *memcg;
                bool locked;
 
-               memcg = mem_cgroup_begin_page_stat(page);
+               lock_page_memcg(page);
                wb = unlocked_inode_to_wb_begin(inode, &locked);
 
                if (TestClearPageDirty(page))
-                       account_page_cleaned(page, mapping, memcg, wb);
+                       account_page_cleaned(page, mapping, wb);
 
                unlocked_inode_to_wb_end(inode, locked);
-               mem_cgroup_end_page_stat(memcg);
+               unlock_page_memcg(page);
        } else {
                ClearPageDirty(page);
        }
@@ -2666,7 +2663,6 @@ int clear_page_dirty_for_io(struct page *page)
        if (mapping && mapping_cap_account_dirty(mapping)) {
                struct inode *inode = mapping->host;
                struct bdi_writeback *wb;
-               struct mem_cgroup *memcg;
                bool locked;
 
                /*
@@ -2704,16 +2700,14 @@ int clear_page_dirty_for_io(struct page *page)
                 * always locked coming in here, so we get the desired
                 * exclusion.
                 */
-               memcg = mem_cgroup_begin_page_stat(page);
                wb = unlocked_inode_to_wb_begin(inode, &locked);
                if (TestClearPageDirty(page)) {
-                       mem_cgroup_dec_page_stat(memcg, MEM_CGROUP_STAT_DIRTY);
+                       mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_DIRTY);
                        dec_zone_page_state(page, NR_FILE_DIRTY);
                        dec_wb_stat(wb, WB_RECLAIMABLE);
                        ret = 1;
                }
                unlocked_inode_to_wb_end(inode, locked);
-               mem_cgroup_end_page_stat(memcg);
                return ret;
        }
        return TestClearPageDirty(page);
@@ -2723,10 +2717,9 @@ EXPORT_SYMBOL(clear_page_dirty_for_io);
 int test_clear_page_writeback(struct page *page)
 {
        struct address_space *mapping = page_mapping(page);
-       struct mem_cgroup *memcg;
        int ret;
 
-       memcg = mem_cgroup_begin_page_stat(page);
+       lock_page_memcg(page);
        if (mapping) {
                struct inode *inode = mapping->host;
                struct backing_dev_info *bdi = inode_to_bdi(inode);
@@ -2750,21 +2743,20 @@ int test_clear_page_writeback(struct page *page)
                ret = TestClearPageWriteback(page);
        }
        if (ret) {
-               mem_cgroup_dec_page_stat(memcg, MEM_CGROUP_STAT_WRITEBACK);
+               mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_WRITEBACK);
                dec_zone_page_state(page, NR_WRITEBACK);
                inc_zone_page_state(page, NR_WRITTEN);
        }
-       mem_cgroup_end_page_stat(memcg);
+       unlock_page_memcg(page);
        return ret;
 }
 
 int __test_set_page_writeback(struct page *page, bool keep_write)
 {
        struct address_space *mapping = page_mapping(page);
-       struct mem_cgroup *memcg;
        int ret;
 
-       memcg = mem_cgroup_begin_page_stat(page);
+       lock_page_memcg(page);
        if (mapping) {
                struct inode *inode = mapping->host;
                struct backing_dev_info *bdi = inode_to_bdi(inode);
@@ -2792,10 +2784,10 @@ int __test_set_page_writeback(struct page *page, bool keep_write)
                ret = TestSetPageWriteback(page);
        }
        if (!ret) {
-               mem_cgroup_inc_page_stat(memcg, MEM_CGROUP_STAT_WRITEBACK);
+               mem_cgroup_inc_page_stat(page, MEM_CGROUP_STAT_WRITEBACK);
                inc_zone_page_state(page, NR_WRITEBACK);
        }
-       mem_cgroup_end_page_stat(memcg);
+       unlock_page_memcg(page);
        return ret;
 
 }
index 838ca8bb64f7376062fc6670c759a27d7f59c7e3..c46b75d14b6f8732b513065f1bd79d124d703579 100644 (file)
@@ -223,6 +223,19 @@ static char * const zone_names[MAX_NR_ZONES] = {
 #endif
 };
 
+char * const migratetype_names[MIGRATE_TYPES] = {
+       "Unmovable",
+       "Movable",
+       "Reclaimable",
+       "HighAtomic",
+#ifdef CONFIG_CMA
+       "CMA",
+#endif
+#ifdef CONFIG_MEMORY_ISOLATION
+       "Isolate",
+#endif
+};
+
 compound_page_dtor * const compound_page_dtors[] = {
        NULL,
        free_compound_page,
@@ -247,6 +260,7 @@ static unsigned long __meminitdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
 static unsigned long __initdata required_kernelcore;
 static unsigned long __initdata required_movablecore;
 static unsigned long __meminitdata zone_movable_pfn[MAX_NUMNODES];
+static bool mirrored_kernelcore;
 
 /* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */
 int movable_zone;
@@ -416,7 +430,7 @@ static void bad_page(struct page *page, const char *reason,
                        goto out;
                }
                if (nr_unshown) {
-                       printk(KERN_ALERT
+                       pr_alert(
                              "BUG: Bad page state: %lu messages suppressed\n",
                                nr_unshown);
                        nr_unshown = 0;
@@ -426,9 +440,14 @@ static void bad_page(struct page *page, const char *reason,
        if (nr_shown++ == 0)
                resume = jiffies + 60 * HZ;
 
-       printk(KERN_ALERT "BUG: Bad page state in process %s  pfn:%05lx\n",
+       pr_alert("BUG: Bad page state in process %s  pfn:%05lx\n",
                current->comm, page_to_pfn(page));
-       dump_page_badflags(page, reason, bad_flags);
+       __dump_page(page, reason);
+       bad_flags &= page->flags;
+       if (bad_flags)
+               pr_alert("bad because of flags: %#lx(%pGp)\n",
+                                               bad_flags, &bad_flags);
+       dump_page_owner(page);
 
        print_modules();
        dump_stack();
@@ -477,7 +496,8 @@ void prep_compound_page(struct page *page, unsigned int order)
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
 unsigned int _debug_guardpage_minorder;
-bool _debug_pagealloc_enabled __read_mostly;
+bool _debug_pagealloc_enabled __read_mostly
+                       = IS_ENABLED(CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT);
 bool _debug_guardpage_enabled __read_mostly;
 
 static int __init early_debug_pagealloc(char *buf)
@@ -488,6 +508,9 @@ static int __init early_debug_pagealloc(char *buf)
        if (strcmp(buf, "on") == 0)
                _debug_pagealloc_enabled = true;
 
+       if (strcmp(buf, "off") == 0)
+               _debug_pagealloc_enabled = false;
+
        return 0;
 }
 early_param("debug_pagealloc", early_debug_pagealloc);
@@ -1002,6 +1025,7 @@ static bool free_pages_prepare(struct page *page, unsigned int order)
                                           PAGE_SIZE << order);
        }
        arch_free_page(page, order);
+       kernel_poison_pages(page, 1 << order, 0);
        kernel_map_pages(page, 1 << order, 0);
 
        return true;
@@ -1104,6 +1128,75 @@ void __init __free_pages_bootmem(struct page *page, unsigned long pfn,
        return __free_pages_boot_core(page, pfn, order);
 }
 
+/*
+ * Check that the whole (or subset of) a pageblock given by the interval of
+ * [start_pfn, end_pfn) is valid and within the same zone, before scanning it
+ * with the migration of free compaction scanner. The scanners then need to
+ * use only pfn_valid_within() check for arches that allow holes within
+ * pageblocks.
+ *
+ * Return struct page pointer of start_pfn, or NULL if checks were not passed.
+ *
+ * It's possible on some configurations to have a setup like node0 node1 node0
+ * i.e. it's possible that all pages within a zones range of pages do not
+ * belong to a single zone. We assume that a border between node0 and node1
+ * can occur within a single pageblock, but not a node0 node1 node0
+ * interleaving within a single pageblock. It is therefore sufficient to check
+ * the first and last page of a pageblock and avoid checking each individual
+ * page in a pageblock.
+ */
+struct page *__pageblock_pfn_to_page(unsigned long start_pfn,
+                                    unsigned long end_pfn, struct zone *zone)
+{
+       struct page *start_page;
+       struct page *end_page;
+
+       /* end_pfn is one past the range we are checking */
+       end_pfn--;
+
+       if (!pfn_valid(start_pfn) || !pfn_valid(end_pfn))
+               return NULL;
+
+       start_page = pfn_to_page(start_pfn);
+
+       if (page_zone(start_page) != zone)
+               return NULL;
+
+       end_page = pfn_to_page(end_pfn);
+
+       /* This gives a shorter code than deriving page_zone(end_page) */
+       if (page_zone_id(start_page) != page_zone_id(end_page))
+               return NULL;
+
+       return start_page;
+}
+
+void set_zone_contiguous(struct zone *zone)
+{
+       unsigned long block_start_pfn = zone->zone_start_pfn;
+       unsigned long block_end_pfn;
+
+       block_end_pfn = ALIGN(block_start_pfn + 1, pageblock_nr_pages);
+       for (; block_start_pfn < zone_end_pfn(zone);
+                       block_start_pfn = block_end_pfn,
+                        block_end_pfn += pageblock_nr_pages) {
+
+               block_end_pfn = min(block_end_pfn, zone_end_pfn(zone));
+
+               if (!__pageblock_pfn_to_page(block_start_pfn,
+                                            block_end_pfn, zone))
+                       return;
+       }
+
+       /* We confirm that there is no hole */
+       zone->contiguous = true;
+}
+
+void clear_zone_contiguous(struct zone *zone)
+{
+       zone->contiguous = false;
+}
+
 #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
 static void __init deferred_free_range(struct page *page,
                                        unsigned long pfn, int nr_pages)
@@ -1254,9 +1347,13 @@ free_range:
        pgdat_init_report_one_done();
        return 0;
 }
+#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 
 void __init page_alloc_init_late(void)
 {
+       struct zone *zone;
+
+#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
        int nid;
 
        /* There will be num_node_state(N_MEMORY) threads */
@@ -1270,8 +1367,11 @@ void __init page_alloc_init_late(void)
 
        /* Reinit limits that are based on free pages after the kernel is up */
        files_maxfiles_init();
+#endif
+
+       for_each_populated_zone(zone)
+               set_zone_contiguous(zone);
 }
-#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
 
 #ifdef CONFIG_CMA
 /* Free whole pageblock and set its migration type to MIGRATE_CMA. */
@@ -1381,15 +1481,24 @@ static inline int check_new_page(struct page *page)
        return 0;
 }
 
+static inline bool free_pages_prezeroed(bool poisoned)
+{
+       return IS_ENABLED(CONFIG_PAGE_POISONING_ZERO) &&
+               page_poisoning_enabled() && poisoned;
+}
+
 static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
                                                                int alloc_flags)
 {
        int i;
+       bool poisoned = true;
 
        for (i = 0; i < (1 << order); i++) {
                struct page *p = page + i;
                if (unlikely(check_new_page(p)))
                        return 1;
+               if (poisoned)
+                       poisoned &= page_is_poisoned(p);
        }
 
        set_page_private(page, 0);
@@ -1397,9 +1506,10 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
 
        arch_alloc_page(page, order);
        kernel_map_pages(page, 1 << order, 1);
+       kernel_poison_pages(page, 1 << order, 1);
        kasan_alloc_pages(page, order);
 
-       if (gfp_flags & __GFP_ZERO)
+       if (!free_pages_prezeroed(poisoned) && (gfp_flags & __GFP_ZERO))
                for (i = 0; i < (1 << order); i++)
                        clear_highpage(page + i);
 
@@ -2690,9 +2800,8 @@ void warn_alloc_failed(gfp_t gfp_mask, unsigned int order, const char *fmt, ...)
                va_end(args);
        }
 
-       pr_warn("%s: page allocation failure: order:%u, mode:0x%x\n",
-               current->comm, order, gfp_mask);
-
+       pr_warn("%s: page allocation failure: order:%u, mode:%#x(%pGg)\n",
+               current->comm, order, gfp_mask, &gfp_mask);
        dump_stack();
        if (!should_suppress_show_mem())
                show_mem(filter);
@@ -4491,6 +4600,9 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
        pg_data_t *pgdat = NODE_DATA(nid);
        unsigned long pfn;
        unsigned long nr_initialised = 0;
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+       struct memblock_region *r = NULL, *tmp;
+#endif
 
        if (highest_memmap_pfn < end_pfn - 1)
                highest_memmap_pfn = end_pfn - 1;
@@ -4504,20 +4616,51 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 
        for (pfn = start_pfn; pfn < end_pfn; pfn++) {
                /*
-                * There can be holes in boot-time mem_map[]s
-                * handed to this function.  They do not
-                * exist on hotplugged memory.
+                * There can be holes in boot-time mem_map[]s handed to this
+                * function.  They do not exist on hotplugged memory.
                 */
-               if (context == MEMMAP_EARLY) {
-                       if (!early_pfn_valid(pfn))
+               if (context != MEMMAP_EARLY)
+                       goto not_early;
+
+               if (!early_pfn_valid(pfn))
+                       continue;
+               if (!early_pfn_in_nid(pfn, nid))
+                       continue;
+               if (!update_defer_init(pgdat, pfn, end_pfn, &nr_initialised))
+                       break;
+
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+               /*
+                * If not mirrored_kernelcore and ZONE_MOVABLE exists, range
+                * from zone_movable_pfn[nid] to end of each node should be
+                * ZONE_MOVABLE not ZONE_NORMAL. skip it.
+                */
+               if (!mirrored_kernelcore && zone_movable_pfn[nid])
+                       if (zone == ZONE_NORMAL && pfn >= zone_movable_pfn[nid])
                                continue;
-                       if (!early_pfn_in_nid(pfn, nid))
+
+               /*
+                * Check given memblock attribute by firmware which can affect
+                * kernel memory layout.  If zone==ZONE_MOVABLE but memory is
+                * mirrored, it's an overlapped memmap init. skip it.
+                */
+               if (mirrored_kernelcore && zone == ZONE_MOVABLE) {
+                       if (!r || pfn >= memblock_region_memory_end_pfn(r)) {
+                               for_each_memblock(memory, tmp)
+                                       if (pfn < memblock_region_memory_end_pfn(tmp))
+                                               break;
+                               r = tmp;
+                       }
+                       if (pfn >= memblock_region_memory_base_pfn(r) &&
+                           memblock_is_mirror(r)) {
+                               /* already initialized as NORMAL */
+                               pfn = memblock_region_memory_end_pfn(r);
                                continue;
-                       if (!update_defer_init(pgdat, pfn, end_pfn,
-                                               &nr_initialised))
-                               break;
+                       }
                }
+#endif
 
+not_early:
                /*
                 * Mark the block movable so that blocks are reserved for
                 * movable at startup. This will force kernel allocations
@@ -4934,11 +5077,6 @@ static void __meminit adjust_zone_range_for_zone_movable(int nid,
                        *zone_end_pfn = min(node_end_pfn,
                                arch_zone_highest_possible_pfn[movable_zone]);
 
-               /* Adjust for ZONE_MOVABLE starting within this range */
-               } else if (*zone_start_pfn < zone_movable_pfn[nid] &&
-                               *zone_end_pfn > zone_movable_pfn[nid]) {
-                       *zone_end_pfn = zone_movable_pfn[nid];
-
                /* Check if this whole range is within ZONE_MOVABLE */
                } else if (*zone_start_pfn >= zone_movable_pfn[nid])
                        *zone_start_pfn = *zone_end_pfn;
@@ -4953,31 +5091,31 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
                                        unsigned long zone_type,
                                        unsigned long node_start_pfn,
                                        unsigned long node_end_pfn,
+                                       unsigned long *zone_start_pfn,
+                                       unsigned long *zone_end_pfn,
                                        unsigned long *ignored)
 {
-       unsigned long zone_start_pfn, zone_end_pfn;
-
        /* When hotadd a new node from cpu_up(), the node should be empty */
        if (!node_start_pfn && !node_end_pfn)
                return 0;
 
        /* Get the start and end of the zone */
-       zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
-       zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
+       *zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
+       *zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
        adjust_zone_range_for_zone_movable(nid, zone_type,
                                node_start_pfn, node_end_pfn,
-                               &zone_start_pfn, &zone_end_pfn);
+                               zone_start_pfn, zone_end_pfn);
 
        /* Check that this node has pages within the zone's required range */
-       if (zone_end_pfn < node_start_pfn || zone_start_pfn > node_end_pfn)
+       if (*zone_end_pfn < node_start_pfn || *zone_start_pfn > node_end_pfn)
                return 0;
 
        /* Move the zone boundaries inside the node if necessary */
-       zone_end_pfn = min(zone_end_pfn, node_end_pfn);
-       zone_start_pfn = max(zone_start_pfn, node_start_pfn);
+       *zone_end_pfn = min(*zone_end_pfn, node_end_pfn);
+       *zone_start_pfn = max(*zone_start_pfn, node_start_pfn);
 
        /* Return the spanned pages */
-       return zone_end_pfn - zone_start_pfn;
+       return *zone_end_pfn - *zone_start_pfn;
 }
 
 /*
@@ -5023,6 +5161,7 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid,
        unsigned long zone_low = arch_zone_lowest_possible_pfn[zone_type];
        unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type];
        unsigned long zone_start_pfn, zone_end_pfn;
+       unsigned long nr_absent;
 
        /* When hotadd a new node from cpu_up(), the node should be empty */
        if (!node_start_pfn && !node_end_pfn)
@@ -5034,7 +5173,39 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid,
        adjust_zone_range_for_zone_movable(nid, zone_type,
                        node_start_pfn, node_end_pfn,
                        &zone_start_pfn, &zone_end_pfn);
-       return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
+       nr_absent = __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
+
+       /*
+        * ZONE_MOVABLE handling.
+        * Treat pages to be ZONE_MOVABLE in ZONE_NORMAL as absent pages
+        * and vice versa.
+        */
+       if (zone_movable_pfn[nid]) {
+               if (mirrored_kernelcore) {
+                       unsigned long start_pfn, end_pfn;
+                       struct memblock_region *r;
+
+                       for_each_memblock(memory, r) {
+                               start_pfn = clamp(memblock_region_memory_base_pfn(r),
+                                                 zone_start_pfn, zone_end_pfn);
+                               end_pfn = clamp(memblock_region_memory_end_pfn(r),
+                                               zone_start_pfn, zone_end_pfn);
+
+                               if (zone_type == ZONE_MOVABLE &&
+                                   memblock_is_mirror(r))
+                                       nr_absent += end_pfn - start_pfn;
+
+                               if (zone_type == ZONE_NORMAL &&
+                                   !memblock_is_mirror(r))
+                                       nr_absent += end_pfn - start_pfn;
+                       }
+               } else {
+                       if (zone_type == ZONE_NORMAL)
+                               nr_absent += node_end_pfn - zone_movable_pfn[nid];
+               }
+       }
+
+       return nr_absent;
 }
 
 #else /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
@@ -5042,8 +5213,18 @@ static inline unsigned long __meminit zone_spanned_pages_in_node(int nid,
                                        unsigned long zone_type,
                                        unsigned long node_start_pfn,
                                        unsigned long node_end_pfn,
+                                       unsigned long *zone_start_pfn,
+                                       unsigned long *zone_end_pfn,
                                        unsigned long *zones_size)
 {
+       unsigned int zone;
+
+       *zone_start_pfn = node_start_pfn;
+       for (zone = 0; zone < zone_type; zone++)
+               *zone_start_pfn += zones_size[zone];
+
+       *zone_end_pfn = *zone_start_pfn + zones_size[zone_type];
+
        return zones_size[zone_type];
 }
 
@@ -5072,15 +5253,22 @@ static void __meminit calculate_node_totalpages(struct pglist_data *pgdat,
 
        for (i = 0; i < MAX_NR_ZONES; i++) {
                struct zone *zone = pgdat->node_zones + i;
+               unsigned long zone_start_pfn, zone_end_pfn;
                unsigned long size, real_size;
 
                size = zone_spanned_pages_in_node(pgdat->node_id, i,
                                                  node_start_pfn,
                                                  node_end_pfn,
+                                                 &zone_start_pfn,
+                                                 &zone_end_pfn,
                                                  zones_size);
                real_size = size - zone_absent_pages_in_node(pgdat->node_id, i,
                                                  node_start_pfn, node_end_pfn,
                                                  zholes_size);
+               if (size)
+                       zone->zone_start_pfn = zone_start_pfn;
+               else
+                       zone->zone_start_pfn = 0;
                zone->spanned_pages = size;
                zone->present_pages = real_size;
 
@@ -5201,7 +5389,6 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
 {
        enum zone_type j;
        int nid = pgdat->node_id;
-       unsigned long zone_start_pfn = pgdat->node_start_pfn;
        int ret;
 
        pgdat_resize_init(pgdat);
@@ -5222,6 +5409,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
        for (j = 0; j < MAX_NR_ZONES; j++) {
                struct zone *zone = pgdat->node_zones + j;
                unsigned long size, realsize, freesize, memmap_pages;
+               unsigned long zone_start_pfn = zone->zone_start_pfn;
 
                size = zone->spanned_pages;
                realsize = freesize = zone->present_pages;
@@ -5290,7 +5478,6 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
                ret = init_currently_empty_zone(zone, zone_start_pfn, size);
                BUG_ON(ret);
                memmap_init(size, nid, j, zone_start_pfn);
-               zone_start_pfn += size;
        }
 }
 
@@ -5358,6 +5545,8 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
        pr_info("Initmem setup node %d [mem %#018Lx-%#018Lx]\n", nid,
                (u64)start_pfn << PAGE_SHIFT,
                end_pfn ? ((u64)end_pfn << PAGE_SHIFT) - 1 : 0);
+#else
+       start_pfn = node_start_pfn;
 #endif
        calculate_node_totalpages(pgdat, start_pfn, end_pfn,
                                  zones_size, zholes_size);
@@ -5528,6 +5717,36 @@ static void __init find_zone_movable_pfns_for_nodes(void)
                goto out2;
        }
 
+       /*
+        * If kernelcore=mirror is specified, ignore movablecore option
+        */
+       if (mirrored_kernelcore) {
+               bool mem_below_4gb_not_mirrored = false;
+
+               for_each_memblock(memory, r) {
+                       if (memblock_is_mirror(r))
+                               continue;
+
+                       nid = r->nid;
+
+                       usable_startpfn = memblock_region_memory_base_pfn(r);
+
+                       if (usable_startpfn < 0x100000) {
+                               mem_below_4gb_not_mirrored = true;
+                               continue;
+                       }
+
+                       zone_movable_pfn[nid] = zone_movable_pfn[nid] ?
+                               min(usable_startpfn, zone_movable_pfn[nid]) :
+                               usable_startpfn;
+               }
+
+               if (mem_below_4gb_not_mirrored)
+                       pr_warn("This configuration results in unmirrored kernel memory.");
+
+               goto out2;
+       }
+
        /*
         * If movablecore=nn[KMG] was specified, calculate what size of
         * kernelcore that corresponds so that memory usable for
@@ -5788,6 +6007,12 @@ static int __init cmdline_parse_core(char *p, unsigned long *core)
  */
 static int __init cmdline_parse_kernelcore(char *p)
 {
+       /* parse kernelcore=mirror */
+       if (parse_option_str(p, "mirror")) {
+               mirrored_kernelcore = true;
+               return 0;
+       }
+
        return cmdline_parse_core(p, &required_kernelcore);
 }
 
index 292ca7b8debd2c27c87d056e1ea4872d3094c756..2d864e64f7fe3d4128e4cf043a3d0b93374bcfea 100644 (file)
@@ -106,12 +106,15 @@ struct page_ext *lookup_page_ext(struct page *page)
        struct page_ext *base;
 
        base = NODE_DATA(page_to_nid(page))->node_page_ext;
-#ifdef CONFIG_DEBUG_VM
+#if defined(CONFIG_DEBUG_VM) || defined(CONFIG_PAGE_POISONING)
        /*
         * The sanity checks the page allocator does upon freeing a
         * page can reach here before the page_ext arrays are
         * allocated when feeding a range of pages to the allocator
         * for the first time during bootup or memory hotplug.
+        *
+        * This check is also necessary for ensuring page poisoning
+        * works as expected when enabled
         */
        if (unlikely(!base))
                return NULL;
@@ -180,12 +183,15 @@ struct page_ext *lookup_page_ext(struct page *page)
 {
        unsigned long pfn = page_to_pfn(page);
        struct mem_section *section = __pfn_to_section(pfn);
-#ifdef CONFIG_DEBUG_VM
+#if defined(CONFIG_DEBUG_VM) || defined(CONFIG_PAGE_POISONING)
        /*
         * The sanity checks the page allocator does upon freeing a
         * page can reach here before the page_ext arrays are
         * allocated when feeding a range of pages to the allocator
         * for the first time during bootup or memory hotplug.
+        *
+        * This check is also necessary for ensuring page poisoning
+        * works as expected when enabled
         */
        if (!section->page_ext)
                return NULL;
index 983c3a10fa07058df249c64d5c89b9578661f672..44ad1f00c4e1ce8e356c94bbc751fc544f7c7229 100644 (file)
@@ -5,10 +5,12 @@
 #include <linux/bootmem.h>
 #include <linux/stacktrace.h>
 #include <linux/page_owner.h>
+#include <linux/jump_label.h>
+#include <linux/migrate.h>
 #include "internal.h"
 
 static bool page_owner_disabled = true;
-bool page_owner_inited __read_mostly;
+DEFINE_STATIC_KEY_FALSE(page_owner_inited);
 
 static void init_early_allocated_pages(void);
 
@@ -37,7 +39,7 @@ static void init_page_owner(void)
        if (page_owner_disabled)
                return;
 
-       page_owner_inited = true;
+       static_branch_enable(&page_owner_inited);
        init_early_allocated_pages();
 }
 
@@ -72,10 +74,18 @@ void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask)
        page_ext->order = order;
        page_ext->gfp_mask = gfp_mask;
        page_ext->nr_entries = trace.nr_entries;
+       page_ext->last_migrate_reason = -1;
 
        __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
 }
 
+void __set_page_owner_migrate_reason(struct page *page, int reason)
+{
+       struct page_ext *page_ext = lookup_page_ext(page);
+
+       page_ext->last_migrate_reason = reason;
+}
+
 gfp_t __get_page_owner_gfp(struct page *page)
 {
        struct page_ext *page_ext = lookup_page_ext(page);
@@ -83,6 +93,31 @@ gfp_t __get_page_owner_gfp(struct page *page)
        return page_ext->gfp_mask;
 }
 
+void __copy_page_owner(struct page *oldpage, struct page *newpage)
+{
+       struct page_ext *old_ext = lookup_page_ext(oldpage);
+       struct page_ext *new_ext = lookup_page_ext(newpage);
+       int i;
+
+       new_ext->order = old_ext->order;
+       new_ext->gfp_mask = old_ext->gfp_mask;
+       new_ext->nr_entries = old_ext->nr_entries;
+
+       for (i = 0; i < ARRAY_SIZE(new_ext->trace_entries); i++)
+               new_ext->trace_entries[i] = old_ext->trace_entries[i];
+
+       /*
+        * We don't clear the bit on the oldpage as it's going to be freed
+        * after migration. Until then, the info can be useful in case of
+        * a bug, and the overal stats will be off a bit only temporarily.
+        * Also, migrate_misplaced_transhuge_page() can still fail the
+        * migration and then we want the oldpage to retain the info. But
+        * in that case we also don't need to explicitly clear the info from
+        * the new page, which will be freed.
+        */
+       __set_bit(PAGE_EXT_OWNER, &new_ext->flags);
+}
+
 static ssize_t
 print_page_owner(char __user *buf, size_t count, unsigned long pfn,
                struct page *page, struct page_ext *page_ext)
@@ -100,8 +135,9 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
                return -ENOMEM;
 
        ret = snprintf(kbuf, count,
-                       "Page allocated via order %u, mask 0x%x\n",
-                       page_ext->order, page_ext->gfp_mask);
+                       "Page allocated via order %u, mask %#x(%pGg)\n",
+                       page_ext->order, page_ext->gfp_mask,
+                       &page_ext->gfp_mask);
 
        if (ret >= count)
                goto err;
@@ -110,23 +146,12 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
        pageblock_mt = get_pfnblock_migratetype(page, pfn);
        page_mt  = gfpflags_to_migratetype(page_ext->gfp_mask);
        ret += snprintf(kbuf + ret, count - ret,
-                       "PFN %lu Block %lu type %d %s Flags %s%s%s%s%s%s%s%s%s%s%s%s\n",
+                       "PFN %lu type %s Block %lu type %s Flags %#lx(%pGp)\n",
                        pfn,
+                       migratetype_names[page_mt],
                        pfn >> pageblock_order,
-                       pageblock_mt,
-                       pageblock_mt != page_mt ? "Fallback" : "        ",
-                       PageLocked(page)        ? "K" : " ",
-                       PageError(page)         ? "E" : " ",
-                       PageReferenced(page)    ? "R" : " ",
-                       PageUptodate(page)      ? "U" : " ",
-                       PageDirty(page)         ? "D" : " ",
-                       PageLRU(page)           ? "L" : " ",
-                       PageActive(page)        ? "A" : " ",
-                       PageSlab(page)          ? "S" : " ",
-                       PageWriteback(page)     ? "W" : " ",
-                       PageCompound(page)      ? "C" : " ",
-                       PageSwapCache(page)     ? "B" : " ",
-                       PageMappedToDisk(page)  ? "M" : " ");
+                       migratetype_names[pageblock_mt],
+                       page->flags, &page->flags);
 
        if (ret >= count)
                goto err;
@@ -135,6 +160,14 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
        if (ret >= count)
                goto err;
 
+       if (page_ext->last_migrate_reason != -1) {
+               ret += snprintf(kbuf + ret, count - ret,
+                       "Page has been migrated, last migrate reason: %s\n",
+                       migrate_reason_names[page_ext->last_migrate_reason]);
+               if (ret >= count)
+                       goto err;
+       }
+
        ret += snprintf(kbuf + ret, count - ret, "\n");
        if (ret >= count)
                goto err;
@@ -150,6 +183,31 @@ err:
        return -ENOMEM;
 }
 
+void __dump_page_owner(struct page *page)
+{
+       struct page_ext *page_ext = lookup_page_ext(page);
+       struct stack_trace trace = {
+               .nr_entries = page_ext->nr_entries,
+               .entries = &page_ext->trace_entries[0],
+       };
+       gfp_t gfp_mask = page_ext->gfp_mask;
+       int mt = gfpflags_to_migratetype(gfp_mask);
+
+       if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) {
+               pr_alert("page_owner info is not active (free page?)\n");
+               return;
+       }
+
+       pr_alert("page allocated via order %u, migratetype %s, "
+                       "gfp_mask %#x(%pGg)\n", page_ext->order,
+                       migratetype_names[mt], gfp_mask, &gfp_mask);
+       print_stack_trace(&trace, 0);
+
+       if (page_ext->last_migrate_reason != -1)
+               pr_alert("page has been migrated, last migrate reason: %s\n",
+                       migrate_reason_names[page_ext->last_migrate_reason]);
+}
+
 static ssize_t
 read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
@@ -157,7 +215,7 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
        struct page *page;
        struct page_ext *page_ext;
 
-       if (!page_owner_inited)
+       if (!static_branch_unlikely(&page_owner_inited))
                return -EINVAL;
 
        page = NULL;
@@ -305,7 +363,7 @@ static int __init pageowner_init(void)
 {
        struct dentry *dentry;
 
-       if (!page_owner_inited) {
+       if (!static_branch_unlikely(&page_owner_inited)) {
                pr_info("page_owner is disabled\n");
                return 0;
        }
diff --git a/mm/page_poison.c b/mm/page_poison.c
new file mode 100644 (file)
index 0000000..479e7ea
--- /dev/null
@@ -0,0 +1,176 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/page_ext.h>
+#include <linux/poison.h>
+#include <linux/ratelimit.h>
+
+static bool __page_poisoning_enabled __read_mostly;
+static bool want_page_poisoning __read_mostly;
+
+static int early_page_poison_param(char *buf)
+{
+       if (!buf)
+               return -EINVAL;
+
+       if (strcmp(buf, "on") == 0)
+               want_page_poisoning = true;
+       else if (strcmp(buf, "off") == 0)
+               want_page_poisoning = false;
+
+       return 0;
+}
+early_param("page_poison", early_page_poison_param);
+
+bool page_poisoning_enabled(void)
+{
+       return __page_poisoning_enabled;
+}
+
+static bool need_page_poisoning(void)
+{
+       return want_page_poisoning;
+}
+
+static void init_page_poisoning(void)
+{
+       /*
+        * page poisoning is debug page alloc for some arches. If either
+        * of those options are enabled, enable poisoning
+        */
+       if (!IS_ENABLED(CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC)) {
+               if (!want_page_poisoning && !debug_pagealloc_enabled())
+                       return;
+       } else {
+               if (!want_page_poisoning)
+                       return;
+       }
+
+       __page_poisoning_enabled = true;
+}
+
+struct page_ext_operations page_poisoning_ops = {
+       .need = need_page_poisoning,
+       .init = init_page_poisoning,
+};
+
+static inline void set_page_poison(struct page *page)
+{
+       struct page_ext *page_ext;
+
+       page_ext = lookup_page_ext(page);
+       __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
+}
+
+static inline void clear_page_poison(struct page *page)
+{
+       struct page_ext *page_ext;
+
+       page_ext = lookup_page_ext(page);
+       __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
+}
+
+bool page_is_poisoned(struct page *page)
+{
+       struct page_ext *page_ext;
+
+       page_ext = lookup_page_ext(page);
+       if (!page_ext)
+               return false;
+
+       return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
+}
+
+static void poison_page(struct page *page)
+{
+       void *addr = kmap_atomic(page);
+
+       set_page_poison(page);
+       memset(addr, PAGE_POISON, PAGE_SIZE);
+       kunmap_atomic(addr);
+}
+
+static void poison_pages(struct page *page, int n)
+{
+       int i;
+
+       for (i = 0; i < n; i++)
+               poison_page(page + i);
+}
+
+static bool single_bit_flip(unsigned char a, unsigned char b)
+{
+       unsigned char error = a ^ b;
+
+       return error && !(error & (error - 1));
+}
+
+static void check_poison_mem(unsigned char *mem, size_t bytes)
+{
+       static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10);
+       unsigned char *start;
+       unsigned char *end;
+
+       if (IS_ENABLED(CONFIG_PAGE_POISONING_NO_SANITY))
+               return;
+
+       start = memchr_inv(mem, PAGE_POISON, bytes);
+       if (!start)
+               return;
+
+       for (end = mem + bytes - 1; end > start; end--) {
+               if (*end != PAGE_POISON)
+                       break;
+       }
+
+       if (!__ratelimit(&ratelimit))
+               return;
+       else if (start == end && single_bit_flip(*start, PAGE_POISON))
+               pr_err("pagealloc: single bit error\n");
+       else
+               pr_err("pagealloc: memory corruption\n");
+
+       print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start,
+                       end - start + 1, 1);
+       dump_stack();
+}
+
+static void unpoison_page(struct page *page)
+{
+       void *addr;
+
+       if (!page_is_poisoned(page))
+               return;
+
+       addr = kmap_atomic(page);
+       check_poison_mem(addr, PAGE_SIZE);
+       clear_page_poison(page);
+       kunmap_atomic(addr);
+}
+
+static void unpoison_pages(struct page *page, int n)
+{
+       int i;
+
+       for (i = 0; i < n; i++)
+               unpoison_page(page + i);
+}
+
+void kernel_poison_pages(struct page *page, int numpages, int enable)
+{
+       if (!page_poisoning_enabled())
+               return;
+
+       if (enable)
+               unpoison_pages(page, numpages);
+       else
+               poison_pages(page, numpages);
+}
+
+#ifndef CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC
+void __kernel_map_pages(struct page *page, int numpages, int enable)
+{
+       /* This function does nothing, all work is done via poison pages */
+}
+#endif
index 79f3bf047f38497bdcdae741c2941370353a3ea7..02f0bfc3c80af93edb82b31307e44dc21a622ec1 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1287,21 +1287,17 @@ void page_add_new_anon_rmap(struct page *page,
  */
 void page_add_file_rmap(struct page *page)
 {
-       struct mem_cgroup *memcg;
-
-       memcg = mem_cgroup_begin_page_stat(page);
+       lock_page_memcg(page);
        if (atomic_inc_and_test(&page->_mapcount)) {
                __inc_zone_page_state(page, NR_FILE_MAPPED);
-               mem_cgroup_inc_page_stat(memcg, MEM_CGROUP_STAT_FILE_MAPPED);
+               mem_cgroup_inc_page_stat(page, MEM_CGROUP_STAT_FILE_MAPPED);
        }
-       mem_cgroup_end_page_stat(memcg);
+       unlock_page_memcg(page);
 }
 
 static void page_remove_file_rmap(struct page *page)
 {
-       struct mem_cgroup *memcg;
-
-       memcg = mem_cgroup_begin_page_stat(page);
+       lock_page_memcg(page);
 
        /* Hugepages are not counted in NR_FILE_MAPPED for now. */
        if (unlikely(PageHuge(page))) {
@@ -1320,12 +1316,12 @@ static void page_remove_file_rmap(struct page *page)
         * pte lock(a spinlock) is held, which implies preemption disabled.
         */
        __dec_zone_page_state(page, NR_FILE_MAPPED);
-       mem_cgroup_dec_page_stat(memcg, MEM_CGROUP_STAT_FILE_MAPPED);
+       mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_FILE_MAPPED);
 
        if (unlikely(PageMlocked(page)))
                clear_page_mlock(page);
 out:
-       mem_cgroup_end_page_stat(memcg);
+       unlock_page_memcg(page);
 }
 
 static void page_remove_anon_compound_rmap(struct page *page)
index 440e2a7e6c1c2ca706376eb72d719fb8b83af05a..1acfdbc4bd9e306e31a8759aeb46f9d43dfd0113 100644 (file)
@@ -1116,7 +1116,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
                 */
                oldpage = newpage;
        } else {
-               mem_cgroup_replace_page(oldpage, newpage);
+               mem_cgroup_migrate(oldpage, newpage);
                lru_cache_add_anon(newpage);
                *pagep = newpage;
        }
index 621fbcb35a366abf0d979cf48c5476cff1e609f5..852fc5c79829b04a2b673e3e2e41de19d8ff55e5 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -168,12 +168,6 @@ typedef unsigned short freelist_idx_t;
 
 #define SLAB_OBJ_MAX_NUM ((1 << sizeof(freelist_idx_t) * BITS_PER_BYTE) - 1)
 
-/*
- * true if a page was allocated from pfmemalloc reserves for network-based
- * swap
- */
-static bool pfmemalloc_active __read_mostly;
-
 /*
  * struct array_cache
  *
@@ -195,10 +189,6 @@ struct array_cache {
                         * Must have this definition in here for the proper
                         * alignment of array_cache. Also simplifies accessing
                         * the entries.
-                        *
-                        * Entries should not be directly dereferenced as
-                        * entries belonging to slabs marked pfmemalloc will
-                        * have the lower bits set SLAB_OBJ_PFMEMALLOC
                         */
 };
 
@@ -207,33 +197,6 @@ struct alien_cache {
        struct array_cache ac;
 };
 
-#define SLAB_OBJ_PFMEMALLOC    1
-static inline bool is_obj_pfmemalloc(void *objp)
-{
-       return (unsigned long)objp & SLAB_OBJ_PFMEMALLOC;
-}
-
-static inline void set_obj_pfmemalloc(void **objp)
-{
-       *objp = (void *)((unsigned long)*objp | SLAB_OBJ_PFMEMALLOC);
-       return;
-}
-
-static inline void clear_obj_pfmemalloc(void **objp)
-{
-       *objp = (void *)((unsigned long)*objp & ~SLAB_OBJ_PFMEMALLOC);
-}
-
-/*
- * bootstrap: The caches do not work without cpuarrays anymore, but the
- * cpuarrays are allocated from the generic caches...
- */
-#define BOOT_CPUCACHE_ENTRIES  1
-struct arraycache_init {
-       struct array_cache cache;
-       void *entries[BOOT_CPUCACHE_ENTRIES];
-};
-
 /*
  * Need this for bootstrapping a per node allocator.
  */
@@ -280,9 +243,10 @@ static void kmem_cache_node_init(struct kmem_cache_node *parent)
        MAKE_LIST((cachep), (&(ptr)->slabs_free), slabs_free, nodeid);  \
        } while (0)
 
+#define CFLGS_OBJFREELIST_SLAB (0x40000000UL)
 #define CFLGS_OFF_SLAB         (0x80000000UL)
+#define        OBJFREELIST_SLAB(x)     ((x)->flags & CFLGS_OBJFREELIST_SLAB)
 #define        OFF_SLAB(x)     ((x)->flags & CFLGS_OFF_SLAB)
-#define OFF_SLAB_MIN_SIZE (max_t(size_t, PAGE_SIZE >> 5, KMALLOC_MIN_SIZE + 1))
 
 #define BATCHREFILL_LIMIT      16
 /*
@@ -390,36 +354,26 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp)
 
 #endif
 
-#define OBJECT_FREE (0)
-#define OBJECT_ACTIVE (1)
-
 #ifdef CONFIG_DEBUG_SLAB_LEAK
 
-static void set_obj_status(struct page *page, int idx, int val)
+static inline bool is_store_user_clean(struct kmem_cache *cachep)
 {
-       int freelist_size;
-       char *status;
-       struct kmem_cache *cachep = page->slab_cache;
-
-       freelist_size = cachep->num * sizeof(freelist_idx_t);
-       status = (char *)page->freelist + freelist_size;
-       status[idx] = val;
+       return atomic_read(&cachep->store_user_clean) == 1;
 }
 
-static inline unsigned int get_obj_status(struct page *page, int idx)
+static inline void set_store_user_clean(struct kmem_cache *cachep)
 {
-       int freelist_size;
-       char *status;
-       struct kmem_cache *cachep = page->slab_cache;
-
-       freelist_size = cachep->num * sizeof(freelist_idx_t);
-       status = (char *)page->freelist + freelist_size;
+       atomic_set(&cachep->store_user_clean, 1);
+}
 
-       return status[idx];
+static inline void set_store_user_dirty(struct kmem_cache *cachep)
+{
+       if (is_store_user_clean(cachep))
+               atomic_set(&cachep->store_user_clean, 0);
 }
 
 #else
-static inline void set_obj_status(struct page *page, int idx, int val) {}
+static inline void set_store_user_dirty(struct kmem_cache *cachep) {}
 
 #endif
 
@@ -457,6 +411,7 @@ static inline unsigned int obj_to_index(const struct kmem_cache *cache,
        return reciprocal_divide(offset, cache->reciprocal_buffer_size);
 }
 
+#define BOOT_CPUCACHE_ENTRIES  1
 /* internal cache of cache description objs */
 static struct kmem_cache kmem_cache_boot = {
        .batchcount = 1,
@@ -475,61 +430,13 @@ static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep)
        return this_cpu_ptr(cachep->cpu_cache);
 }
 
-static size_t calculate_freelist_size(int nr_objs, size_t align)
-{
-       size_t freelist_size;
-
-       freelist_size = nr_objs * sizeof(freelist_idx_t);
-       if (IS_ENABLED(CONFIG_DEBUG_SLAB_LEAK))
-               freelist_size += nr_objs * sizeof(char);
-
-       if (align)
-               freelist_size = ALIGN(freelist_size, align);
-
-       return freelist_size;
-}
-
-static int calculate_nr_objs(size_t slab_size, size_t buffer_size,
-                               size_t idx_size, size_t align)
-{
-       int nr_objs;
-       size_t remained_size;
-       size_t freelist_size;
-       int extra_space = 0;
-
-       if (IS_ENABLED(CONFIG_DEBUG_SLAB_LEAK))
-               extra_space = sizeof(char);
-       /*
-        * Ignore padding for the initial guess. The padding
-        * is at most @align-1 bytes, and @buffer_size is at
-        * least @align. In the worst case, this result will
-        * be one greater than the number of objects that fit
-        * into the memory allocation when taking the padding
-        * into account.
-        */
-       nr_objs = slab_size / (buffer_size + idx_size + extra_space);
-
-       /*
-        * This calculated number will be either the right
-        * amount, or one greater than what we want.
-        */
-       remained_size = slab_size - nr_objs * buffer_size;
-       freelist_size = calculate_freelist_size(nr_objs, align);
-       if (remained_size < freelist_size)
-               nr_objs--;
-
-       return nr_objs;
-}
-
 /*
  * Calculate the number of objects and left-over bytes for a given buffer size.
  */
-static void cache_estimate(unsigned long gfporder, size_t buffer_size,
-                          size_t align, int flags, size_t *left_over,
-                          unsigned int *num)
+static unsigned int cache_estimate(unsigned long gfporder, size_t buffer_size,
+               unsigned long flags, size_t *left_over)
 {
-       int nr_objs;
-       size_t mgmt_size;
+       unsigned int num;
        size_t slab_size = PAGE_SIZE << gfporder;
 
        /*
@@ -537,26 +444,28 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size,
         * on it. For the latter case, the memory allocated for a
         * slab is used for:
         *
-        * - One unsigned int for each object
-        * - Padding to respect alignment of @align
         * - @buffer_size bytes for each object
+        * - One freelist_idx_t for each object
+        *
+        * We don't need to consider alignment of freelist because
+        * freelist will be at the end of slab page. The objects will be
+        * at the correct alignment.
         *
         * If the slab management structure is off the slab, then the
         * alignment will already be calculated into the size. Because
         * the slabs are all pages aligned, the objects will be at the
         * correct alignment when allocated.
         */
-       if (flags & CFLGS_OFF_SLAB) {
-               mgmt_size = 0;
-               nr_objs = slab_size / buffer_size;
-
+       if (flags & (CFLGS_OBJFREELIST_SLAB | CFLGS_OFF_SLAB)) {
+               num = slab_size / buffer_size;
+               *left_over = slab_size % buffer_size;
        } else {
-               nr_objs = calculate_nr_objs(slab_size, buffer_size,
-                                       sizeof(freelist_idx_t), align);
-               mgmt_size = calculate_freelist_size(nr_objs, align);
+               num = slab_size / (buffer_size + sizeof(freelist_idx_t));
+               *left_over = slab_size %
+                       (buffer_size + sizeof(freelist_idx_t));
        }
-       *num = nr_objs;
-       *left_over = slab_size - nr_objs*buffer_size - mgmt_size;
+
+       return num;
 }
 
 #if DEBUG
@@ -687,120 +596,21 @@ static struct array_cache *alloc_arraycache(int node, int entries,
        return ac;
 }
 
-static inline bool is_slab_pfmemalloc(struct page *page)
-{
-       return PageSlabPfmemalloc(page);
-}
-
-/* Clears pfmemalloc_active if no slabs have pfmalloc set */
-static void recheck_pfmemalloc_active(struct kmem_cache *cachep,
-                                               struct array_cache *ac)
-{
-       struct kmem_cache_node *n = get_node(cachep, numa_mem_id());
-       struct page *page;
-       unsigned long flags;
-
-       if (!pfmemalloc_active)
-               return;
-
-       spin_lock_irqsave(&n->list_lock, flags);
-       list_for_each_entry(page, &n->slabs_full, lru)
-               if (is_slab_pfmemalloc(page))
-                       goto out;
-
-       list_for_each_entry(page, &n->slabs_partial, lru)
-               if (is_slab_pfmemalloc(page))
-                       goto out;
-
-       list_for_each_entry(page, &n->slabs_free, lru)
-               if (is_slab_pfmemalloc(page))
-                       goto out;
-
-       pfmemalloc_active = false;
-out:
-       spin_unlock_irqrestore(&n->list_lock, flags);
-}
-
-static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
-                                               gfp_t flags, bool force_refill)
+static noinline void cache_free_pfmemalloc(struct kmem_cache *cachep,
+                                       struct page *page, void *objp)
 {
-       int i;
-       void *objp = ac->entry[--ac->avail];
-
-       /* Ensure the caller is allowed to use objects from PFMEMALLOC slab */
-       if (unlikely(is_obj_pfmemalloc(objp))) {
-               struct kmem_cache_node *n;
-
-               if (gfp_pfmemalloc_allowed(flags)) {
-                       clear_obj_pfmemalloc(&objp);
-                       return objp;
-               }
-
-               /* The caller cannot use PFMEMALLOC objects, find another one */
-               for (i = 0; i < ac->avail; i++) {
-                       /* If a !PFMEMALLOC object is found, swap them */
-                       if (!is_obj_pfmemalloc(ac->entry[i])) {
-                               objp = ac->entry[i];
-                               ac->entry[i] = ac->entry[ac->avail];
-                               ac->entry[ac->avail] = objp;
-                               return objp;
-                       }
-               }
-
-               /*
-                * If there are empty slabs on the slabs_free list and we are
-                * being forced to refill the cache, mark this one !pfmemalloc.
-                */
-               n = get_node(cachep, numa_mem_id());
-               if (!list_empty(&n->slabs_free) && force_refill) {
-                       struct page *page = virt_to_head_page(objp);
-                       ClearPageSlabPfmemalloc(page);
-                       clear_obj_pfmemalloc(&objp);
-                       recheck_pfmemalloc_active(cachep, ac);
-                       return objp;
-               }
-
-               /* No !PFMEMALLOC objects available */
-               ac->avail++;
-               objp = NULL;
-       }
-
-       return objp;
-}
-
-static inline void *ac_get_obj(struct kmem_cache *cachep,
-                       struct array_cache *ac, gfp_t flags, bool force_refill)
-{
-       void *objp;
-
-       if (unlikely(sk_memalloc_socks()))
-               objp = __ac_get_obj(cachep, ac, flags, force_refill);
-       else
-               objp = ac->entry[--ac->avail];
-
-       return objp;
-}
-
-static noinline void *__ac_put_obj(struct kmem_cache *cachep,
-                       struct array_cache *ac, void *objp)
-{
-       if (unlikely(pfmemalloc_active)) {
-               /* Some pfmemalloc slabs exist, check if this is one */
-               struct page *page = virt_to_head_page(objp);
-               if (PageSlabPfmemalloc(page))
-                       set_obj_pfmemalloc(&objp);
-       }
+       struct kmem_cache_node *n;
+       int page_node;
+       LIST_HEAD(list);
 
-       return objp;
-}
+       page_node = page_to_nid(page);
+       n = get_node(cachep, page_node);
 
-static inline void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac,
-                                                               void *objp)
-{
-       if (unlikely(sk_memalloc_socks()))
-               objp = __ac_put_obj(cachep, ac, objp);
+       spin_lock(&n->list_lock);
+       free_block(cachep, &objp, 1, page_node, &list);
+       spin_unlock(&n->list_lock);
 
-       ac->entry[ac->avail++] = objp;
+       slabs_destroy(cachep, &list);
 }
 
 /*
@@ -1003,7 +813,7 @@ static int __cache_free_alien(struct kmem_cache *cachep, void *objp,
                        STATS_INC_ACOVERFLOW(cachep);
                        __drain_alien_cache(cachep, ac, page_node, &list);
                }
-               ac_put_obj(cachep, ac, objp);
+               ac->entry[ac->avail++] = objp;
                spin_unlock(&alien->lock);
                slabs_destroy(cachep, &list);
        } else {
@@ -1540,10 +1350,9 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
        if ((gfpflags & __GFP_NOWARN) || !__ratelimit(&slab_oom_rs))
                return;
 
-       printk(KERN_WARNING
-               "SLAB: Unable to allocate memory on node %d (gfp=0x%x)\n",
-               nodeid, gfpflags);
-       printk(KERN_WARNING "  cache: %s, object size: %d, order: %d\n",
+       pr_warn("SLAB: Unable to allocate memory on node %d, gfp=%#x(%pGg)\n",
+               nodeid, gfpflags, &gfpflags);
+       pr_warn("  cache: %s, object size: %d, order: %d\n",
                cachep->name, cachep->size, cachep->gfporder);
 
        for_each_kmem_cache_node(cachep, node, n) {
@@ -1567,8 +1376,7 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid)
 
                num_slabs += active_slabs;
                num_objs = num_slabs * cachep->num;
-               printk(KERN_WARNING
-                       "  node %d: slabs: %ld/%ld, objs: %ld/%ld, free: %ld\n",
+               pr_warn("  node %d: slabs: %ld/%ld, objs: %ld/%ld, free: %ld\n",
                        node, active_slabs, num_slabs, active_objs, num_objs,
                        free_objects);
        }
@@ -1604,10 +1412,6 @@ static struct page *kmem_getpages(struct kmem_cache *cachep, gfp_t flags,
                return NULL;
        }
 
-       /* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */
-       if (page_is_pfmemalloc(page))
-               pfmemalloc_active = true;
-
        nr_pages = (1 << cachep->gfporder);
        if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
                add_zone_page_state(page_zone(page),
@@ -1615,8 +1419,10 @@ static struct page *kmem_getpages(struct kmem_cache *cachep, gfp_t flags,
        else
                add_zone_page_state(page_zone(page),
                        NR_SLAB_UNRECLAIMABLE, nr_pages);
+
        __SetPageSlab(page);
-       if (page_is_pfmemalloc(page))
+       /* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */
+       if (sk_memalloc_socks() && page_is_pfmemalloc(page))
                SetPageSlabPfmemalloc(page);
 
        if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) {
@@ -1670,6 +1476,14 @@ static void kmem_rcu_free(struct rcu_head *head)
 }
 
 #if DEBUG
+static bool is_debug_pagealloc_cache(struct kmem_cache *cachep)
+{
+       if (debug_pagealloc_enabled() && OFF_SLAB(cachep) &&
+               (cachep->size % PAGE_SIZE) == 0)
+               return true;
+
+       return false;
+}
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
 static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr,
@@ -1703,6 +1517,23 @@ static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr,
        }
        *addr++ = 0x87654321;
 }
+
+static void slab_kernel_map(struct kmem_cache *cachep, void *objp,
+                               int map, unsigned long caller)
+{
+       if (!is_debug_pagealloc_cache(cachep))
+               return;
+
+       if (caller)
+               store_stackinfo(cachep, objp, caller);
+
+       kernel_map_pages(virt_to_page(objp), cachep->size / PAGE_SIZE, map);
+}
+
+#else
+static inline void slab_kernel_map(struct kmem_cache *cachep, void *objp,
+                               int map, unsigned long caller) {}
+
 #endif
 
 static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val)
@@ -1781,6 +1612,9 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp)
        int size, i;
        int lines = 0;
 
+       if (is_debug_pagealloc_cache(cachep))
+               return;
+
        realobj = (char *)objp + obj_offset(cachep);
        size = cachep->object_size;
 
@@ -1842,20 +1676,18 @@ static void slab_destroy_debugcheck(struct kmem_cache *cachep,
                                                struct page *page)
 {
        int i;
+
+       if (OBJFREELIST_SLAB(cachep) && cachep->flags & SLAB_POISON) {
+               poison_obj(cachep, page->freelist - obj_offset(cachep),
+                       POISON_FREE);
+       }
+
        for (i = 0; i < cachep->num; i++) {
                void *objp = index_to_obj(cachep, page, i);
 
                if (cachep->flags & SLAB_POISON) {
-#ifdef CONFIG_DEBUG_PAGEALLOC
-                       if (cachep->size % PAGE_SIZE == 0 &&
-                                       OFF_SLAB(cachep))
-                               kernel_map_pages(virt_to_page(objp),
-                                       cachep->size / PAGE_SIZE, 1);
-                       else
-                               check_poison_obj(cachep, objp);
-#else
                        check_poison_obj(cachep, objp);
-#endif
+                       slab_kernel_map(cachep, objp, 1, 0);
                }
                if (cachep->flags & SLAB_RED_ZONE) {
                        if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)
@@ -1916,7 +1748,6 @@ static void slabs_destroy(struct kmem_cache *cachep, struct list_head *list)
  * calculate_slab_order - calculate size (page order) of slabs
  * @cachep: pointer to the cache that is being created
  * @size: size of objects to be created in this cache.
- * @align: required alignment for the objects.
  * @flags: slab allocation flags
  *
  * Also calculates the number of objects per slab.
@@ -1926,9 +1757,8 @@ static void slabs_destroy(struct kmem_cache *cachep, struct list_head *list)
  * towards high-order requests, this should be changed.
  */
 static size_t calculate_slab_order(struct kmem_cache *cachep,
-                       size_t size, size_t align, unsigned long flags)
+                               size_t size, unsigned long flags)
 {
-       unsigned long offslab_limit;
        size_t left_over = 0;
        int gfporder;
 
@@ -1936,7 +1766,7 @@ static size_t calculate_slab_order(struct kmem_cache *cachep,
                unsigned int num;
                size_t remainder;
 
-               cache_estimate(gfporder, size, align, flags, &remainder, &num);
+               num = cache_estimate(gfporder, size, flags, &remainder);
                if (!num)
                        continue;
 
@@ -1945,19 +1775,24 @@ static size_t calculate_slab_order(struct kmem_cache *cachep,
                        break;
 
                if (flags & CFLGS_OFF_SLAB) {
-                       size_t freelist_size_per_obj = sizeof(freelist_idx_t);
+                       struct kmem_cache *freelist_cache;
+                       size_t freelist_size;
+
+                       freelist_size = num * sizeof(freelist_idx_t);
+                       freelist_cache = kmalloc_slab(freelist_size, 0u);
+                       if (!freelist_cache)
+                               continue;
+
                        /*
-                        * Max number of objs-per-slab for caches which
-                        * use off-slab slabs. Needed to avoid a possible
-                        * looping condition in cache_grow().
+                        * Needed to avoid possible looping condition
+                        * in cache_grow()
                         */
-                       if (IS_ENABLED(CONFIG_DEBUG_SLAB_LEAK))
-                               freelist_size_per_obj += sizeof(char);
-                       offslab_limit = size;
-                       offslab_limit /= freelist_size_per_obj;
+                       if (OFF_SLAB(freelist_cache))
+                               continue;
 
-                       if (num > offslab_limit)
-                               break;
+                       /* check if off slab has enough benefit */
+                       if (freelist_cache->size > cachep->size / 2)
+                               continue;
                }
 
                /* Found something acceptable - save it away */
@@ -2075,6 +1910,79 @@ __kmem_cache_alias(const char *name, size_t size, size_t align,
        return cachep;
 }
 
+static bool set_objfreelist_slab_cache(struct kmem_cache *cachep,
+                       size_t size, unsigned long flags)
+{
+       size_t left;
+
+       cachep->num = 0;
+
+       if (cachep->ctor || flags & SLAB_DESTROY_BY_RCU)
+               return false;
+
+       left = calculate_slab_order(cachep, size,
+                       flags | CFLGS_OBJFREELIST_SLAB);
+       if (!cachep->num)
+               return false;
+
+       if (cachep->num * sizeof(freelist_idx_t) > cachep->object_size)
+               return false;
+
+       cachep->colour = left / cachep->colour_off;
+
+       return true;
+}
+
+static bool set_off_slab_cache(struct kmem_cache *cachep,
+                       size_t size, unsigned long flags)
+{
+       size_t left;
+
+       cachep->num = 0;
+
+       /*
+        * Always use on-slab management when SLAB_NOLEAKTRACE
+        * to avoid recursive calls into kmemleak.
+        */
+       if (flags & SLAB_NOLEAKTRACE)
+               return false;
+
+       /*
+        * Size is large, assume best to place the slab management obj
+        * off-slab (should allow better packing of objs).
+        */
+       left = calculate_slab_order(cachep, size, flags | CFLGS_OFF_SLAB);
+       if (!cachep->num)
+               return false;
+
+       /*
+        * If the slab has been placed off-slab, and we have enough space then
+        * move it on-slab. This is at the expense of any extra colouring.
+        */
+       if (left >= cachep->num * sizeof(freelist_idx_t))
+               return false;
+
+       cachep->colour = left / cachep->colour_off;
+
+       return true;
+}
+
+static bool set_on_slab_cache(struct kmem_cache *cachep,
+                       size_t size, unsigned long flags)
+{
+       size_t left;
+
+       cachep->num = 0;
+
+       left = calculate_slab_order(cachep, size, flags);
+       if (!cachep->num)
+               return false;
+
+       cachep->colour = left / cachep->colour_off;
+
+       return true;
+}
+
 /**
  * __kmem_cache_create - Create a cache.
  * @cachep: cache management descriptor
@@ -2099,7 +2007,6 @@ __kmem_cache_alias(const char *name, size_t size, size_t align,
 int
 __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
 {
-       size_t left_over, freelist_size;
        size_t ralign = BYTES_PER_WORD;
        gfp_t gfp;
        int err;
@@ -2119,8 +2026,6 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
        if (!(flags & SLAB_DESTROY_BY_RCU))
                flags |= SLAB_POISON;
 #endif
-       if (flags & SLAB_DESTROY_BY_RCU)
-               BUG_ON(flags & SLAB_POISON);
 #endif
 
        /*
@@ -2152,6 +2057,10 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
         * 4) Store it.
         */
        cachep->align = ralign;
+       cachep->colour_off = cache_line_size();
+       /* Offset must be a multiple of the alignment. */
+       if (cachep->colour_off < cachep->align)
+               cachep->colour_off = cachep->align;
 
        if (slab_is_available())
                gfp = GFP_KERNEL;
@@ -2179,37 +2088,8 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
                else
                        size += BYTES_PER_WORD;
        }
-#if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
-       /*
-        * To activate debug pagealloc, off-slab management is necessary
-        * requirement. In early phase of initialization, small sized slab
-        * doesn't get initialized so it would not be possible. So, we need
-        * to check size >= 256. It guarantees that all necessary small
-        * sized slab is initialized in current slab initialization sequence.
-        */
-       if (!slab_early_init && size >= kmalloc_size(INDEX_NODE) &&
-               size >= 256 && cachep->object_size > cache_line_size() &&
-               ALIGN(size, cachep->align) < PAGE_SIZE) {
-               cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align);
-               size = PAGE_SIZE;
-       }
-#endif
 #endif
 
-       /*
-        * Determine if the slab management is 'on' or 'off' slab.
-        * (bootstrapping cannot cope with offslab caches so don't do
-        * it too early on. Always use on-slab management when
-        * SLAB_NOLEAKTRACE to avoid recursive calls into kmemleak)
-        */
-       if (size >= OFF_SLAB_MIN_SIZE && !slab_early_init &&
-           !(flags & SLAB_NOLEAKTRACE))
-               /*
-                * Size is large, assume best to place the slab management obj
-                * off-slab (should allow better packing of objs).
-                */
-               flags |= CFLGS_OFF_SLAB;
-
        size = ALIGN(size, cachep->align);
        /*
         * We should restrict the number of objects in a slab to implement
@@ -2218,42 +2098,46 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
        if (FREELIST_BYTE_INDEX && size < SLAB_OBJ_MIN_SIZE)
                size = ALIGN(SLAB_OBJ_MIN_SIZE, cachep->align);
 
-       left_over = calculate_slab_order(cachep, size, cachep->align, flags);
-
-       if (!cachep->num)
-               return -E2BIG;
-
-       freelist_size = calculate_freelist_size(cachep->num, cachep->align);
-
+#if DEBUG
        /*
-        * If the slab has been placed off-slab, and we have enough space then
-        * move it on-slab. This is at the expense of any extra colouring.
+        * To activate debug pagealloc, off-slab management is necessary
+        * requirement. In early phase of initialization, small sized slab
+        * doesn't get initialized so it would not be possible. So, we need
+        * to check size >= 256. It guarantees that all necessary small
+        * sized slab is initialized in current slab initialization sequence.
         */
-       if (flags & CFLGS_OFF_SLAB && left_over >= freelist_size) {
-               flags &= ~CFLGS_OFF_SLAB;
-               left_over -= freelist_size;
+       if (debug_pagealloc_enabled() && (flags & SLAB_POISON) &&
+               size >= 256 && cachep->object_size > cache_line_size()) {
+               if (size < PAGE_SIZE || size % PAGE_SIZE == 0) {
+                       size_t tmp_size = ALIGN(size, PAGE_SIZE);
+
+                       if (set_off_slab_cache(cachep, tmp_size, flags)) {
+                               flags |= CFLGS_OFF_SLAB;
+                               cachep->obj_offset += tmp_size - size;
+                               size = tmp_size;
+                               goto done;
+                       }
+               }
        }
+#endif
 
-       if (flags & CFLGS_OFF_SLAB) {
-               /* really off slab. No need for manual alignment */
-               freelist_size = calculate_freelist_size(cachep->num, 0);
+       if (set_objfreelist_slab_cache(cachep, size, flags)) {
+               flags |= CFLGS_OBJFREELIST_SLAB;
+               goto done;
+       }
 
-#ifdef CONFIG_PAGE_POISONING
-               /* If we're going to use the generic kernel_map_pages()
-                * poisoning, then it's going to smash the contents of
-                * the redzone and userword anyhow, so switch them off.
-                */
-               if (size % PAGE_SIZE == 0 && flags & SLAB_POISON)
-                       flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
-#endif
+       if (set_off_slab_cache(cachep, size, flags)) {
+               flags |= CFLGS_OFF_SLAB;
+               goto done;
        }
 
-       cachep->colour_off = cache_line_size();
-       /* Offset must be a multiple of the alignment. */
-       if (cachep->colour_off < cachep->align)
-               cachep->colour_off = cachep->align;
-       cachep->colour = left_over / cachep->colour_off;
-       cachep->freelist_size = freelist_size;
+       if (set_on_slab_cache(cachep, size, flags))
+               goto done;
+
+       return -E2BIG;
+
+done:
+       cachep->freelist_size = cachep->num * sizeof(freelist_idx_t);
        cachep->flags = flags;
        cachep->allocflags = __GFP_COMP;
        if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA))
@@ -2261,16 +2145,21 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
        cachep->size = size;
        cachep->reciprocal_buffer_size = reciprocal_value(size);
 
-       if (flags & CFLGS_OFF_SLAB) {
-               cachep->freelist_cache = kmalloc_slab(freelist_size, 0u);
-               /*
-                * This is a possibility for one of the kmalloc_{dma,}_caches.
-                * But since we go off slab only for object size greater than
-                * OFF_SLAB_MIN_SIZE, and kmalloc_{dma,}_caches get created
-                * in ascending order,this should not happen at all.
-                * But leave a BUG_ON for some lucky dude.
-                */
-               BUG_ON(ZERO_OR_NULL_PTR(cachep->freelist_cache));
+#if DEBUG
+       /*
+        * If we're going to use the generic kernel_map_pages()
+        * poisoning, then it's going to smash the contents of
+        * the redzone and userword anyhow, so switch them off.
+        */
+       if (IS_ENABLED(CONFIG_PAGE_POISONING) &&
+               (cachep->flags & SLAB_POISON) &&
+               is_debug_pagealloc_cache(cachep))
+               cachep->flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
+#endif
+
+       if (OFF_SLAB(cachep)) {
+               cachep->freelist_cache =
+                       kmalloc_slab(cachep->freelist_size, 0u);
        }
 
        err = setup_cpu_cache(cachep, gfp);
@@ -2377,9 +2266,6 @@ static int drain_freelist(struct kmem_cache *cache,
                }
 
                page = list_entry(p, struct page, lru);
-#if DEBUG
-               BUG_ON(page->active);
-#endif
                list_del(&page->lru);
                /*
                 * Safe to drop the lock. The slab is no longer linked
@@ -2454,18 +2340,23 @@ static void *alloc_slabmgmt(struct kmem_cache *cachep,
        void *freelist;
        void *addr = page_address(page);
 
-       if (OFF_SLAB(cachep)) {
+       page->s_mem = addr + colour_off;
+       page->active = 0;
+
+       if (OBJFREELIST_SLAB(cachep))
+               freelist = NULL;
+       else if (OFF_SLAB(cachep)) {
                /* Slab management obj is off-slab. */
                freelist = kmem_cache_alloc_node(cachep->freelist_cache,
                                              local_flags, nodeid);
                if (!freelist)
                        return NULL;
        } else {
-               freelist = addr + colour_off;
-               colour_off += cachep->freelist_size;
+               /* We will use last bytes at the slab for freelist */
+               freelist = addr + (PAGE_SIZE << cachep->gfporder) -
+                               cachep->freelist_size;
        }
-       page->active = 0;
-       page->s_mem = addr + colour_off;
+
        return freelist;
 }
 
@@ -2480,17 +2371,14 @@ static inline void set_free_obj(struct page *page,
        ((freelist_idx_t *)(page->freelist))[idx] = val;
 }
 
-static void cache_init_objs(struct kmem_cache *cachep,
-                           struct page *page)
+static void cache_init_objs_debug(struct kmem_cache *cachep, struct page *page)
 {
+#if DEBUG
        int i;
 
        for (i = 0; i < cachep->num; i++) {
                void *objp = index_to_obj(cachep, page, i);
-#if DEBUG
-               /* need to poison the objs? */
-               if (cachep->flags & SLAB_POISON)
-                       poison_obj(cachep, objp, POISON_FREE);
+
                if (cachep->flags & SLAB_STORE_USER)
                        *dbg_userword(cachep, objp) = NULL;
 
@@ -2514,15 +2402,32 @@ static void cache_init_objs(struct kmem_cache *cachep,
                                slab_error(cachep, "constructor overwrote the"
                                           " start of an object");
                }
-               if ((cachep->size % PAGE_SIZE) == 0 &&
-                           OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
-                       kernel_map_pages(virt_to_page(objp),
-                                        cachep->size / PAGE_SIZE, 0);
-#else
-               if (cachep->ctor)
-                       cachep->ctor(objp);
+               /* need to poison the objs? */
+               if (cachep->flags & SLAB_POISON) {
+                       poison_obj(cachep, objp, POISON_FREE);
+                       slab_kernel_map(cachep, objp, 0, 0);
+               }
+       }
 #endif
-               set_obj_status(page, i, OBJECT_FREE);
+}
+
+static void cache_init_objs(struct kmem_cache *cachep,
+                           struct page *page)
+{
+       int i;
+
+       cache_init_objs_debug(cachep, page);
+
+       if (OBJFREELIST_SLAB(cachep)) {
+               page->freelist = index_to_obj(cachep, page, cachep->num - 1) +
+                                               obj_offset(cachep);
+       }
+
+       for (i = 0; i < cachep->num; i++) {
+               /* constructor could break poison info */
+               if (DEBUG == 0 && cachep->ctor)
+                       cachep->ctor(index_to_obj(cachep, page, i));
+
                set_free_obj(page, i, i);
        }
 }
@@ -2537,30 +2442,28 @@ static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags)
        }
 }
 
-static void *slab_get_obj(struct kmem_cache *cachep, struct page *page,
-                               int nodeid)
+static void *slab_get_obj(struct kmem_cache *cachep, struct page *page)
 {
        void *objp;
 
        objp = index_to_obj(cachep, page, get_free_obj(page, page->active));
        page->active++;
+
 #if DEBUG
-       WARN_ON(page_to_nid(virt_to_page(objp)) != nodeid);
+       if (cachep->flags & SLAB_STORE_USER)
+               set_store_user_dirty(cachep);
 #endif
 
        return objp;
 }
 
-static void slab_put_obj(struct kmem_cache *cachep, struct page *page,
-                               void *objp, int nodeid)
+static void slab_put_obj(struct kmem_cache *cachep,
+                       struct page *page, void *objp)
 {
        unsigned int objnr = obj_to_index(cachep, page, objp);
 #if DEBUG
        unsigned int i;
 
-       /* Verify that the slab belongs to the intended node */
-       WARN_ON(page_to_nid(virt_to_page(objp)) != nodeid);
-
        /* Verify double free bug */
        for (i = page->active; i < cachep->num; i++) {
                if (get_free_obj(page, i) == objnr) {
@@ -2571,6 +2474,9 @@ static void slab_put_obj(struct kmem_cache *cachep, struct page *page,
        }
 #endif
        page->active--;
+       if (!page->freelist)
+               page->freelist = objp + obj_offset(cachep);
+
        set_free_obj(page, page->active, objnr);
 }
 
@@ -2645,7 +2551,7 @@ static int cache_grow(struct kmem_cache *cachep,
        /* Get slab management. */
        freelist = alloc_slabmgmt(cachep, page, offset,
                        local_flags & ~GFP_CONSTRAINT_MASK, nodeid);
-       if (!freelist)
+       if (OFF_SLAB(cachep) && !freelist)
                goto opps1;
 
        slab_map_pages(cachep, page, freelist);
@@ -2726,27 +2632,19 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
                *dbg_redzone1(cachep, objp) = RED_INACTIVE;
                *dbg_redzone2(cachep, objp) = RED_INACTIVE;
        }
-       if (cachep->flags & SLAB_STORE_USER)
+       if (cachep->flags & SLAB_STORE_USER) {
+               set_store_user_dirty(cachep);
                *dbg_userword(cachep, objp) = (void *)caller;
+       }
 
        objnr = obj_to_index(cachep, page, objp);
 
        BUG_ON(objnr >= cachep->num);
        BUG_ON(objp != index_to_obj(cachep, page, objnr));
 
-       set_obj_status(page, objnr, OBJECT_FREE);
        if (cachep->flags & SLAB_POISON) {
-#ifdef CONFIG_DEBUG_PAGEALLOC
-               if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) {
-                       store_stackinfo(cachep, objp, caller);
-                       kernel_map_pages(virt_to_page(objp),
-                                        cachep->size / PAGE_SIZE, 0);
-               } else {
-                       poison_obj(cachep, objp, POISON_FREE);
-               }
-#else
                poison_obj(cachep, objp, POISON_FREE);
-#endif
+               slab_kernel_map(cachep, objp, 0, caller);
        }
        return objp;
 }
@@ -2756,7 +2654,85 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
 #define cache_free_debugcheck(x,objp,z) (objp)
 #endif
 
-static struct page *get_first_slab(struct kmem_cache_node *n)
+static inline void fixup_objfreelist_debug(struct kmem_cache *cachep,
+                                               void **list)
+{
+#if DEBUG
+       void *next = *list;
+       void *objp;
+
+       while (next) {
+               objp = next - obj_offset(cachep);
+               next = *(void **)next;
+               poison_obj(cachep, objp, POISON_FREE);
+       }
+#endif
+}
+
+static inline void fixup_slab_list(struct kmem_cache *cachep,
+                               struct kmem_cache_node *n, struct page *page,
+                               void **list)
+{
+       /* move slabp to correct slabp list: */
+       list_del(&page->lru);
+       if (page->active == cachep->num) {
+               list_add(&page->lru, &n->slabs_full);
+               if (OBJFREELIST_SLAB(cachep)) {
+#if DEBUG
+                       /* Poisoning will be done without holding the lock */
+                       if (cachep->flags & SLAB_POISON) {
+                               void **objp = page->freelist;
+
+                               *objp = *list;
+                               *list = objp;
+                       }
+#endif
+                       page->freelist = NULL;
+               }
+       } else
+               list_add(&page->lru, &n->slabs_partial);
+}
+
+/* Try to find non-pfmemalloc slab if needed */
+static noinline struct page *get_valid_first_slab(struct kmem_cache_node *n,
+                                       struct page *page, bool pfmemalloc)
+{
+       if (!page)
+               return NULL;
+
+       if (pfmemalloc)
+               return page;
+
+       if (!PageSlabPfmemalloc(page))
+               return page;
+
+       /* No need to keep pfmemalloc slab if we have enough free objects */
+       if (n->free_objects > n->free_limit) {
+               ClearPageSlabPfmemalloc(page);
+               return page;
+       }
+
+       /* Move pfmemalloc slab to the end of list to speed up next search */
+       list_del(&page->lru);
+       if (!page->active)
+               list_add_tail(&page->lru, &n->slabs_free);
+       else
+               list_add_tail(&page->lru, &n->slabs_partial);
+
+       list_for_each_entry(page, &n->slabs_partial, lru) {
+               if (!PageSlabPfmemalloc(page))
+                       return page;
+       }
+
+       list_for_each_entry(page, &n->slabs_free, lru) {
+               if (!PageSlabPfmemalloc(page))
+                       return page;
+       }
+
+       return NULL;
+}
+
+static struct page *get_first_slab(struct kmem_cache_node *n, bool pfmemalloc)
 {
        struct page *page;
 
@@ -2768,21 +2744,51 @@ static struct page *get_first_slab(struct kmem_cache_node *n)
                                struct page, lru);
        }
 
+       if (sk_memalloc_socks())
+               return get_valid_first_slab(n, page, pfmemalloc);
+
        return page;
 }
 
-static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags,
-                                                       bool force_refill)
+static noinline void *cache_alloc_pfmemalloc(struct kmem_cache *cachep,
+                               struct kmem_cache_node *n, gfp_t flags)
+{
+       struct page *page;
+       void *obj;
+       void *list = NULL;
+
+       if (!gfp_pfmemalloc_allowed(flags))
+               return NULL;
+
+       spin_lock(&n->list_lock);
+       page = get_first_slab(n, true);
+       if (!page) {
+               spin_unlock(&n->list_lock);
+               return NULL;
+       }
+
+       obj = slab_get_obj(cachep, page);
+       n->free_objects--;
+
+       fixup_slab_list(cachep, n, page, &list);
+
+       spin_unlock(&n->list_lock);
+       fixup_objfreelist_debug(cachep, &list);
+
+       return obj;
+}
+
+static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
 {
        int batchcount;
        struct kmem_cache_node *n;
        struct array_cache *ac;
        int node;
+       void *list = NULL;
 
        check_irq_off();
        node = numa_mem_id();
-       if (unlikely(force_refill))
-               goto force_grow;
+
 retry:
        ac = cpu_cache_get(cachep);
        batchcount = ac->batchcount;
@@ -2808,7 +2814,7 @@ retry:
        while (batchcount > 0) {
                struct page *page;
                /* Get slab alloc is to come from. */
-               page = get_first_slab(n);
+               page = get_first_slab(n, false);
                if (!page)
                        goto must_grow;
 
@@ -2826,26 +2832,29 @@ retry:
                        STATS_INC_ACTIVE(cachep);
                        STATS_SET_HIGH(cachep);
 
-                       ac_put_obj(cachep, ac, slab_get_obj(cachep, page,
-                                                                       node));
+                       ac->entry[ac->avail++] = slab_get_obj(cachep, page);
                }
 
-               /* move slabp to correct slabp list: */
-               list_del(&page->lru);
-               if (page->active == cachep->num)
-                       list_add(&page->lru, &n->slabs_full);
-               else
-                       list_add(&page->lru, &n->slabs_partial);
+               fixup_slab_list(cachep, n, page, &list);
        }
 
 must_grow:
        n->free_objects -= ac->avail;
 alloc_done:
        spin_unlock(&n->list_lock);
+       fixup_objfreelist_debug(cachep, &list);
 
        if (unlikely(!ac->avail)) {
                int x;
-force_grow:
+
+               /* Check if we can use obj in pfmemalloc slab */
+               if (sk_memalloc_socks()) {
+                       void *obj = cache_alloc_pfmemalloc(cachep, n, flags);
+
+                       if (obj)
+                               return obj;
+               }
+
                x = cache_grow(cachep, gfp_exact_node(flags), node, NULL);
 
                /* cache_grow can reenable interrupts, then ac could change. */
@@ -2853,7 +2862,7 @@ force_grow:
                node = numa_mem_id();
 
                /* no objects in sight? abort */
-               if (!x && (ac->avail == 0 || force_refill))
+               if (!x && ac->avail == 0)
                        return NULL;
 
                if (!ac->avail)         /* objects refilled by interrupt? */
@@ -2861,7 +2870,7 @@ force_grow:
        }
        ac->touched = 1;
 
-       return ac_get_obj(cachep, ac, flags, force_refill);
+       return ac->entry[--ac->avail];
 }
 
 static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep,
@@ -2877,20 +2886,11 @@ static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep,
 static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
                                gfp_t flags, void *objp, unsigned long caller)
 {
-       struct page *page;
-
        if (!objp)
                return objp;
        if (cachep->flags & SLAB_POISON) {
-#ifdef CONFIG_DEBUG_PAGEALLOC
-               if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
-                       kernel_map_pages(virt_to_page(objp),
-                                        cachep->size / PAGE_SIZE, 1);
-               else
-                       check_poison_obj(cachep, objp);
-#else
                check_poison_obj(cachep, objp);
-#endif
+               slab_kernel_map(cachep, objp, 1, 0);
                poison_obj(cachep, objp, POISON_INUSE);
        }
        if (cachep->flags & SLAB_STORE_USER)
@@ -2910,8 +2910,6 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
                *dbg_redzone2(cachep, objp) = RED_ACTIVE;
        }
 
-       page = virt_to_head_page(objp);
-       set_obj_status(page, obj_to_index(cachep, page, objp), OBJECT_ACTIVE);
        objp += obj_offset(cachep);
        if (cachep->ctor && cachep->flags & SLAB_POISON)
                cachep->ctor(objp);
@@ -2926,40 +2924,24 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep,
 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
 #endif
 
-static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags)
-{
-       if (unlikely(cachep == kmem_cache))
-               return false;
-
-       return should_failslab(cachep->object_size, flags, cachep->flags);
-}
-
 static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
        void *objp;
        struct array_cache *ac;
-       bool force_refill = false;
 
        check_irq_off();
 
        ac = cpu_cache_get(cachep);
        if (likely(ac->avail)) {
                ac->touched = 1;
-               objp = ac_get_obj(cachep, ac, flags, false);
+               objp = ac->entry[--ac->avail];
 
-               /*
-                * Allow for the possibility all avail objects are not allowed
-                * by the current flags
-                */
-               if (objp) {
-                       STATS_INC_ALLOCHIT(cachep);
-                       goto out;
-               }
-               force_refill = true;
+               STATS_INC_ALLOCHIT(cachep);
+               goto out;
        }
 
        STATS_INC_ALLOCMISS(cachep);
-       objp = cache_alloc_refill(cachep, flags, force_refill);
+       objp = cache_alloc_refill(cachep, flags);
        /*
         * the 'ac' may be updated by cache_alloc_refill(),
         * and kmemleak_erase() requires its correct value.
@@ -3097,6 +3079,7 @@ static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
        struct page *page;
        struct kmem_cache_node *n;
        void *obj;
+       void *list = NULL;
        int x;
 
        VM_BUG_ON(nodeid < 0 || nodeid >= MAX_NUMNODES);
@@ -3106,7 +3089,7 @@ static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags,
 retry:
        check_irq_off();
        spin_lock(&n->list_lock);
-       page = get_first_slab(n);
+       page = get_first_slab(n, false);
        if (!page)
                goto must_grow;
 
@@ -3118,17 +3101,13 @@ retry:
 
        BUG_ON(page->active == cachep->num);
 
-       obj = slab_get_obj(cachep, page, nodeid);
+       obj = slab_get_obj(cachep, page);
        n->free_objects--;
-       /* move slabp to correct slabp list: */
-       list_del(&page->lru);
 
-       if (page->active == cachep->num)
-               list_add(&page->lru, &n->slabs_full);
-       else
-               list_add(&page->lru, &n->slabs_partial);
+       fixup_slab_list(cachep, n, page, &list);
 
        spin_unlock(&n->list_lock);
+       fixup_objfreelist_debug(cachep, &list);
        goto done;
 
 must_grow:
@@ -3152,14 +3131,10 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
        int slab_node = numa_mem_id();
 
        flags &= gfp_allowed_mask;
-
-       lockdep_trace_alloc(flags);
-
-       if (slab_should_failslab(cachep, flags))
+       cachep = slab_pre_alloc_hook(cachep, flags);
+       if (unlikely(!cachep))
                return NULL;
 
-       cachep = memcg_kmem_get_cache(cachep, flags);
-
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
 
@@ -3188,16 +3163,11 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid,
   out:
        local_irq_restore(save_flags);
        ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
-       kmemleak_alloc_recursive(ptr, cachep->object_size, 1, cachep->flags,
-                                flags);
 
-       if (likely(ptr)) {
-               kmemcheck_slab_alloc(cachep, flags, ptr, cachep->object_size);
-               if (unlikely(flags & __GFP_ZERO))
-                       memset(ptr, 0, cachep->object_size);
-       }
+       if (unlikely(flags & __GFP_ZERO) && ptr)
+               memset(ptr, 0, cachep->object_size);
 
-       memcg_kmem_put_cache(cachep);
+       slab_post_alloc_hook(cachep, flags, 1, &ptr);
        return ptr;
 }
 
@@ -3240,30 +3210,21 @@ slab_alloc(struct kmem_cache *cachep, gfp_t flags, unsigned long caller)
        void *objp;
 
        flags &= gfp_allowed_mask;
-
-       lockdep_trace_alloc(flags);
-
-       if (slab_should_failslab(cachep, flags))
+       cachep = slab_pre_alloc_hook(cachep, flags);
+       if (unlikely(!cachep))
                return NULL;
 
-       cachep = memcg_kmem_get_cache(cachep, flags);
-
        cache_alloc_debugcheck_before(cachep, flags);
        local_irq_save(save_flags);
        objp = __do_cache_alloc(cachep, flags);
        local_irq_restore(save_flags);
        objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
-       kmemleak_alloc_recursive(objp, cachep->object_size, 1, cachep->flags,
-                                flags);
        prefetchw(objp);
 
-       if (likely(objp)) {
-               kmemcheck_slab_alloc(cachep, flags, objp, cachep->object_size);
-               if (unlikely(flags & __GFP_ZERO))
-                       memset(objp, 0, cachep->object_size);
-       }
+       if (unlikely(flags & __GFP_ZERO) && objp)
+               memset(objp, 0, cachep->object_size);
 
-       memcg_kmem_put_cache(cachep);
+       slab_post_alloc_hook(cachep, flags, 1, &objp);
        return objp;
 }
 
@@ -3281,13 +3242,12 @@ static void free_block(struct kmem_cache *cachep, void **objpp,
                void *objp;
                struct page *page;
 
-               clear_obj_pfmemalloc(&objpp[i]);
                objp = objpp[i];
 
                page = virt_to_head_page(objp);
                list_del(&page->lru);
                check_spinlock_acquired_node(cachep, node);
-               slab_put_obj(cachep, page, objp, node);
+               slab_put_obj(cachep, page, objp);
                STATS_DEC_ACTIVE(cachep);
                n->free_objects++;
 
@@ -3317,9 +3277,7 @@ static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac)
        LIST_HEAD(list);
 
        batchcount = ac->batchcount;
-#if DEBUG
-       BUG_ON(!batchcount || batchcount > ac->avail);
-#endif
+
        check_irq_off();
        n = get_node(cachep, node);
        spin_lock(&n->list_lock);
@@ -3389,7 +3347,16 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp,
                cache_flusharray(cachep, ac);
        }
 
-       ac_put_obj(cachep, ac, objp);
+       if (sk_memalloc_socks()) {
+               struct page *page = virt_to_head_page(objp);
+
+               if (unlikely(PageSlabPfmemalloc(page))) {
+                       cache_free_pfmemalloc(cachep, page, objp);
+                       return;
+               }
+       }
+
+       ac->entry[ac->avail++] = objp;
 }
 
 /**
@@ -3411,16 +3378,53 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 }
 EXPORT_SYMBOL(kmem_cache_alloc);
 
-void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
+static __always_inline void
+cache_alloc_debugcheck_after_bulk(struct kmem_cache *s, gfp_t flags,
+                                 size_t size, void **p, unsigned long caller)
 {
-       __kmem_cache_free_bulk(s, size, p);
+       size_t i;
+
+       for (i = 0; i < size; i++)
+               p[i] = cache_alloc_debugcheck_after(s, flags, p[i], caller);
 }
-EXPORT_SYMBOL(kmem_cache_free_bulk);
 
 int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
-                                                               void **p)
+                         void **p)
 {
-       return __kmem_cache_alloc_bulk(s, flags, size, p);
+       size_t i;
+
+       s = slab_pre_alloc_hook(s, flags);
+       if (!s)
+               return 0;
+
+       cache_alloc_debugcheck_before(s, flags);
+
+       local_irq_disable();
+       for (i = 0; i < size; i++) {
+               void *objp = __do_cache_alloc(s, flags);
+
+               if (unlikely(!objp))
+                       goto error;
+               p[i] = objp;
+       }
+       local_irq_enable();
+
+       cache_alloc_debugcheck_after_bulk(s, flags, size, p, _RET_IP_);
+
+       /* Clear memory outside IRQ disabled section */
+       if (unlikely(flags & __GFP_ZERO))
+               for (i = 0; i < size; i++)
+                       memset(p[i], 0, s->object_size);
+
+       slab_post_alloc_hook(s, flags, size, p);
+       /* FIXME: Trace call missing. Christoph would like a bulk variant */
+       return size;
+error:
+       local_irq_enable();
+       cache_alloc_debugcheck_after_bulk(s, flags, i, p, _RET_IP_);
+       slab_post_alloc_hook(s, flags, i, p);
+       __kmem_cache_free_bulk(s, i, p);
+       return 0;
 }
 EXPORT_SYMBOL(kmem_cache_alloc_bulk);
 
@@ -3567,6 +3571,32 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp)
 }
 EXPORT_SYMBOL(kmem_cache_free);
 
+void kmem_cache_free_bulk(struct kmem_cache *orig_s, size_t size, void **p)
+{
+       struct kmem_cache *s;
+       size_t i;
+
+       local_irq_disable();
+       for (i = 0; i < size; i++) {
+               void *objp = p[i];
+
+               if (!orig_s) /* called via kfree_bulk */
+                       s = virt_to_cache(objp);
+               else
+                       s = cache_from_obj(orig_s, objp);
+
+               debug_check_no_locks_freed(objp, s->object_size);
+               if (!(s->flags & SLAB_DEBUG_OBJECTS))
+                       debug_check_no_obj_freed(objp, s->object_size);
+
+               __cache_free(s, objp, _RET_IP_);
+       }
+       local_irq_enable();
+
+       /* FIXME: add tracing */
+}
+EXPORT_SYMBOL(kmem_cache_free_bulk);
+
 /**
  * kfree - free previously allocated memory
  * @objp: pointer returned by kmalloc.
@@ -4102,15 +4132,34 @@ static void handle_slab(unsigned long *n, struct kmem_cache *c,
                                                struct page *page)
 {
        void *p;
-       int i;
+       int i, j;
+       unsigned long v;
 
        if (n[0] == n[1])
                return;
        for (i = 0, p = page->s_mem; i < c->num; i++, p += c->size) {
-               if (get_obj_status(page, i) != OBJECT_ACTIVE)
+               bool active = true;
+
+               for (j = page->active; j < c->num; j++) {
+                       if (get_free_obj(page, j) == i) {
+                               active = false;
+                               break;
+                       }
+               }
+
+               if (!active)
+                       continue;
+
+               /*
+                * probe_kernel_read() is used for DEBUG_PAGEALLOC. page table
+                * mapping is established when actual object allocation and
+                * we could mistakenly access the unmapped object in the cpu
+                * cache.
+                */
+               if (probe_kernel_read(&v, dbg_userword(c, p), sizeof(v)))
                        continue;
 
-               if (!add_caller(n, (unsigned long)*dbg_userword(c, p)))
+               if (!add_caller(n, v))
                        return;
        }
 }
@@ -4146,21 +4195,31 @@ static int leaks_show(struct seq_file *m, void *p)
        if (!(cachep->flags & SLAB_RED_ZONE))
                return 0;
 
-       /* OK, we can do it */
+       /*
+        * Set store_user_clean and start to grab stored user information
+        * for all objects on this cache. If some alloc/free requests comes
+        * during the processing, information would be wrong so restart
+        * whole processing.
+        */
+       do {
+               set_store_user_clean(cachep);
+               drain_cpu_caches(cachep);
 
-       x[1] = 0;
+               x[1] = 0;
 
-       for_each_kmem_cache_node(cachep, node, n) {
+               for_each_kmem_cache_node(cachep, node, n) {
 
-               check_irq_on();
-               spin_lock_irq(&n->list_lock);
+                       check_irq_on();
+                       spin_lock_irq(&n->list_lock);
+
+                       list_for_each_entry(page, &n->slabs_full, lru)
+                               handle_slab(x, cachep, page);
+                       list_for_each_entry(page, &n->slabs_partial, lru)
+                               handle_slab(x, cachep, page);
+                       spin_unlock_irq(&n->list_lock);
+               }
+       } while (!is_store_user_clean(cachep));
 
-               list_for_each_entry(page, &n->slabs_full, lru)
-                       handle_slab(x, cachep, page);
-               list_for_each_entry(page, &n->slabs_partial, lru)
-                       handle_slab(x, cachep, page);
-               spin_unlock_irq(&n->list_lock);
-       }
        name = cachep->name;
        if (x[0] == x[1]) {
                /* Increase the buffer size */
index 2eedacea439de698bdf2103f54ae936fe40de48d..b7934361f0263dd8fa95cebd73702468eadb1ad3 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -38,6 +38,10 @@ struct kmem_cache {
 #endif
 
 #include <linux/memcontrol.h>
+#include <linux/fault-inject.h>
+#include <linux/kmemcheck.h>
+#include <linux/kasan.h>
+#include <linux/kmemleak.h>
 
 /*
  * State of the slab allocator.
@@ -121,7 +125,7 @@ static inline unsigned long kmem_cache_flags(unsigned long object_size,
 #define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER)
 #elif defined(CONFIG_SLUB_DEBUG)
 #define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
-                         SLAB_TRACE | SLAB_DEBUG_FREE)
+                         SLAB_TRACE | SLAB_CONSISTENCY_CHECKS)
 #else
 #define SLAB_DEBUG_FLAGS (0)
 #endif
@@ -168,7 +172,7 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer,
 /*
  * Generic implementation of bulk operations
  * These are useful for situations in which the allocator cannot
- * perform optimizations. In that case segments of the objecct listed
+ * perform optimizations. In that case segments of the object listed
  * may be allocated or freed using these operations.
  */
 void __kmem_cache_free_bulk(struct kmem_cache *, size_t, void **);
@@ -307,7 +311,8 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
         * to not do even the assignment. In that case, slab_equal_or_root
         * will also be a constant.
         */
-       if (!memcg_kmem_enabled() && !unlikely(s->flags & SLAB_DEBUG_FREE))
+       if (!memcg_kmem_enabled() &&
+           !unlikely(s->flags & SLAB_CONSISTENCY_CHECKS))
                return s;
 
        page = virt_to_head_page(x);
@@ -321,6 +326,64 @@ static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x)
        return s;
 }
 
+static inline size_t slab_ksize(const struct kmem_cache *s)
+{
+#ifndef CONFIG_SLUB
+       return s->object_size;
+
+#else /* CONFIG_SLUB */
+# ifdef CONFIG_SLUB_DEBUG
+       /*
+        * Debugging requires use of the padding between object
+        * and whatever may come after it.
+        */
+       if (s->flags & (SLAB_RED_ZONE | SLAB_POISON))
+               return s->object_size;
+# endif
+       /*
+        * If we have the need to store the freelist pointer
+        * back there or track user information then we can
+        * only use the space before that information.
+        */
+       if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER))
+               return s->inuse;
+       /*
+        * Else we can use all the padding etc for the allocation
+        */
+       return s->size;
+#endif
+}
+
+static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
+                                                    gfp_t flags)
+{
+       flags &= gfp_allowed_mask;
+       lockdep_trace_alloc(flags);
+       might_sleep_if(gfpflags_allow_blocking(flags));
+
+       if (should_failslab(s, flags))
+               return NULL;
+
+       return memcg_kmem_get_cache(s, flags);
+}
+
+static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
+                                       size_t size, void **p)
+{
+       size_t i;
+
+       flags &= gfp_allowed_mask;
+       for (i = 0; i < size; i++) {
+               void *object = p[i];
+
+               kmemcheck_slab_alloc(s, flags, object, slab_ksize(s));
+               kmemleak_alloc_recursive(object, s->object_size, 1,
+                                        s->flags, flags);
+               kasan_slab_alloc(s, object);
+       }
+       memcg_kmem_put_cache(s);
+}
+
 #ifndef CONFIG_SLOB
 /*
  * The slab lists for all objects.
index 065b7bdabdc30c5b763b368d84e2057fcde3eb5a..6afb2263a5c5f0dd6066831e0d70701227b78894 100644 (file)
@@ -109,8 +109,12 @@ void __kmem_cache_free_bulk(struct kmem_cache *s, size_t nr, void **p)
 {
        size_t i;
 
-       for (i = 0; i < nr; i++)
-               kmem_cache_free(s, p[i]);
+       for (i = 0; i < nr; i++) {
+               if (s)
+                       kmem_cache_free(s, p[i]);
+               else
+                       kfree(p[i]);
+       }
 }
 
 int __kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t nr,
index d8fbd4a6ed599882489143665ca750eb7613fd65..6c91324f9370663749877fa2e8ea8d9c87c1df73 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -124,6 +124,14 @@ static inline int kmem_cache_debug(struct kmem_cache *s)
 #endif
 }
 
+static inline void *fixup_red_left(struct kmem_cache *s, void *p)
+{
+       if (kmem_cache_debug(s) && s->flags & SLAB_RED_ZONE)
+               p += s->red_left_pad;
+
+       return p;
+}
+
 static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s)
 {
 #ifdef CONFIG_SLUB_CPU_PARTIAL
@@ -160,9 +168,17 @@ static inline bool kmem_cache_has_cpu_partial(struct kmem_cache *s)
  */
 #define MAX_PARTIAL 10
 
-#define DEBUG_DEFAULT_FLAGS (SLAB_DEBUG_FREE | SLAB_RED_ZONE | \
+#define DEBUG_DEFAULT_FLAGS (SLAB_CONSISTENCY_CHECKS | SLAB_RED_ZONE | \
                                SLAB_POISON | SLAB_STORE_USER)
 
+/*
+ * These debug flags cannot use CMPXCHG because there might be consistency
+ * issues when checking or reading debug information
+ */
+#define SLAB_NO_CMPXCHG (SLAB_CONSISTENCY_CHECKS | SLAB_STORE_USER | \
+                               SLAB_TRACE)
+
+
 /*
  * Debugging flags that require metadata to be stored in the slab.  These get
  * disabled when slub_debug=O is used and a cache's min order increases with
@@ -224,24 +240,6 @@ static inline void stat(const struct kmem_cache *s, enum stat_item si)
  *                     Core slab cache functions
  *******************************************************************/
 
-/* Verify that a pointer has an address that is valid within a slab page */
-static inline int check_valid_pointer(struct kmem_cache *s,
-                               struct page *page, const void *object)
-{
-       void *base;
-
-       if (!object)
-               return 1;
-
-       base = page_address(page);
-       if (object < base || object >= base + page->objects * s->size ||
-               (object - base) % s->size) {
-               return 0;
-       }
-
-       return 1;
-}
-
 static inline void *get_freepointer(struct kmem_cache *s, void *object)
 {
        return *(void **)(object + s->offset);
@@ -271,12 +269,14 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
 
 /* Loop over all objects in a slab */
 #define for_each_object(__p, __s, __addr, __objects) \
-       for (__p = (__addr); __p < (__addr) + (__objects) * (__s)->size;\
-                       __p += (__s)->size)
+       for (__p = fixup_red_left(__s, __addr); \
+               __p < (__addr) + (__objects) * (__s)->size; \
+               __p += (__s)->size)
 
 #define for_each_object_idx(__p, __idx, __s, __addr, __objects) \
-       for (__p = (__addr), __idx = 1; __idx <= __objects;\
-                       __p += (__s)->size, __idx++)
+       for (__p = fixup_red_left(__s, __addr), __idx = 1; \
+               __idx <= __objects; \
+               __p += (__s)->size, __idx++)
 
 /* Determine object index from a given position */
 static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
@@ -284,30 +284,6 @@ static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
        return (p - addr) / s->size;
 }
 
-static inline size_t slab_ksize(const struct kmem_cache *s)
-{
-#ifdef CONFIG_SLUB_DEBUG
-       /*
-        * Debugging requires use of the padding between object
-        * and whatever may come after it.
-        */
-       if (s->flags & (SLAB_RED_ZONE | SLAB_POISON))
-               return s->object_size;
-
-#endif
-       /*
-        * If we have the need to store the freelist pointer
-        * back there or track user information then we can
-        * only use the space before that information.
-        */
-       if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER))
-               return s->inuse;
-       /*
-        * Else we can use all the padding etc for the allocation
-        */
-       return s->size;
-}
-
 static inline int order_objects(int order, unsigned long size, int reserved)
 {
        return ((PAGE_SIZE << order) - reserved) / size;
@@ -458,6 +434,22 @@ static void get_map(struct kmem_cache *s, struct page *page, unsigned long *map)
                set_bit(slab_index(p, s, addr), map);
 }
 
+static inline int size_from_object(struct kmem_cache *s)
+{
+       if (s->flags & SLAB_RED_ZONE)
+               return s->size - s->red_left_pad;
+
+       return s->size;
+}
+
+static inline void *restore_red_left(struct kmem_cache *s, void *p)
+{
+       if (s->flags & SLAB_RED_ZONE)
+               p -= s->red_left_pad;
+
+       return p;
+}
+
 /*
  * Debug settings:
  */
@@ -491,6 +483,26 @@ static inline void metadata_access_disable(void)
 /*
  * Object debugging
  */
+
+/* Verify that a pointer has an address that is valid within a slab page */
+static inline int check_valid_pointer(struct kmem_cache *s,
+                               struct page *page, void *object)
+{
+       void *base;
+
+       if (!object)
+               return 1;
+
+       base = page_address(page);
+       object = restore_red_left(s, object);
+       if (object < base || object >= base + page->objects * s->size ||
+               (object - base) % s->size) {
+               return 0;
+       }
+
+       return 1;
+}
+
 static void print_section(char *text, u8 *addr, unsigned int length)
 {
        metadata_access_enable();
@@ -630,7 +642,9 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
        pr_err("INFO: Object 0x%p @offset=%tu fp=0x%p\n\n",
               p, p - addr, get_freepointer(s, p));
 
-       if (p > addr + 16)
+       if (s->flags & SLAB_RED_ZONE)
+               print_section("Redzone ", p - s->red_left_pad, s->red_left_pad);
+       else if (p > addr + 16)
                print_section("Bytes b4 ", p - 16, 16);
 
        print_section("Object ", p, min_t(unsigned long, s->object_size,
@@ -647,9 +661,9 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
        if (s->flags & SLAB_STORE_USER)
                off += 2 * sizeof(struct track);
 
-       if (off != s->size)
+       if (off != size_from_object(s))
                /* Beginning of the filler is the free pointer */
-               print_section("Padding ", p + off, s->size - off);
+               print_section("Padding ", p + off, size_from_object(s) - off);
 
        dump_stack();
 }
@@ -679,6 +693,9 @@ static void init_object(struct kmem_cache *s, void *object, u8 val)
 {
        u8 *p = object;
 
+       if (s->flags & SLAB_RED_ZONE)
+               memset(p - s->red_left_pad, val, s->red_left_pad);
+
        if (s->flags & __OBJECT_POISON) {
                memset(p, POISON_FREE, s->object_size - 1);
                p[s->object_size - 1] = POISON_END;
@@ -771,11 +788,11 @@ static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p)
                /* We also have user information there */
                off += 2 * sizeof(struct track);
 
-       if (s->size == off)
+       if (size_from_object(s) == off)
                return 1;
 
        return check_bytes_and_report(s, page, p, "Object padding",
-                               p + off, POISON_INUSE, s->size - off);
+                       p + off, POISON_INUSE, size_from_object(s) - off);
 }
 
 /* Check the pad bytes at the end of a slab page */
@@ -819,6 +836,10 @@ static int check_object(struct kmem_cache *s, struct page *page,
        u8 *endobject = object + s->object_size;
 
        if (s->flags & SLAB_RED_ZONE) {
+               if (!check_bytes_and_report(s, page, object, "Redzone",
+                       object - s->red_left_pad, val, s->red_left_pad))
+                       return 0;
+
                if (!check_bytes_and_report(s, page, object, "Redzone",
                        endobject, val, s->inuse - s->object_size))
                        return 0;
@@ -1031,20 +1052,32 @@ static void setup_object_debug(struct kmem_cache *s, struct page *page,
        init_tracking(s, object);
 }
 
-static noinline int alloc_debug_processing(struct kmem_cache *s,
+static inline int alloc_consistency_checks(struct kmem_cache *s,
                                        struct page *page,
                                        void *object, unsigned long addr)
 {
        if (!check_slab(s, page))
-               goto bad;
+               return 0;
 
        if (!check_valid_pointer(s, page, object)) {
                object_err(s, page, object, "Freelist Pointer check fails");
-               goto bad;
+               return 0;
        }
 
        if (!check_object(s, page, object, SLUB_RED_INACTIVE))
-               goto bad;
+               return 0;
+
+       return 1;
+}
+
+static noinline int alloc_debug_processing(struct kmem_cache *s,
+                                       struct page *page,
+                                       void *object, unsigned long addr)
+{
+       if (s->flags & SLAB_CONSISTENCY_CHECKS) {
+               if (!alloc_consistency_checks(s, page, object, addr))
+                       goto bad;
+       }
 
        /* Success perform special debug activities for allocs */
        if (s->flags & SLAB_STORE_USER)
@@ -1067,37 +1100,21 @@ bad:
        return 0;
 }
 
-/* Supports checking bulk free of a constructed freelist */
-static noinline struct kmem_cache_node *free_debug_processing(
-       struct kmem_cache *s, struct page *page,
-       void *head, void *tail, int bulk_cnt,
-       unsigned long addr, unsigned long *flags)
+static inline int free_consistency_checks(struct kmem_cache *s,
+               struct page *page, void *object, unsigned long addr)
 {
-       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
-       void *object = head;
-       int cnt = 0;
-
-       spin_lock_irqsave(&n->list_lock, *flags);
-       slab_lock(page);
-
-       if (!check_slab(s, page))
-               goto fail;
-
-next_object:
-       cnt++;
-
        if (!check_valid_pointer(s, page, object)) {
                slab_err(s, page, "Invalid object pointer 0x%p", object);
-               goto fail;
+               return 0;
        }
 
        if (on_freelist(s, page, object)) {
                object_err(s, page, object, "Object already free");
-               goto fail;
+               return 0;
        }
 
        if (!check_object(s, page, object, SLUB_RED_ACTIVE))
-               goto out;
+               return 0;
 
        if (unlikely(s != page->slab_cache)) {
                if (!PageSlab(page)) {
@@ -1110,7 +1127,37 @@ next_object:
                } else
                        object_err(s, page, object,
                                        "page slab pointer corrupt.");
-               goto fail;
+               return 0;
+       }
+       return 1;
+}
+
+/* Supports checking bulk free of a constructed freelist */
+static noinline int free_debug_processing(
+       struct kmem_cache *s, struct page *page,
+       void *head, void *tail, int bulk_cnt,
+       unsigned long addr)
+{
+       struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+       void *object = head;
+       int cnt = 0;
+       unsigned long uninitialized_var(flags);
+       int ret = 0;
+
+       spin_lock_irqsave(&n->list_lock, flags);
+       slab_lock(page);
+
+       if (s->flags & SLAB_CONSISTENCY_CHECKS) {
+               if (!check_slab(s, page))
+                       goto out;
+       }
+
+next_object:
+       cnt++;
+
+       if (s->flags & SLAB_CONSISTENCY_CHECKS) {
+               if (!free_consistency_checks(s, page, object, addr))
+                       goto out;
        }
 
        if (s->flags & SLAB_STORE_USER)
@@ -1124,23 +1171,18 @@ next_object:
                object = get_freepointer(s, object);
                goto next_object;
        }
+       ret = 1;
+
 out:
        if (cnt != bulk_cnt)
                slab_err(s, page, "Bulk freelist count(%d) invalid(%d)\n",
                         bulk_cnt, cnt);
 
        slab_unlock(page);
-       /*
-        * Keep node_lock to preserve integrity
-        * until the object is actually freed
-        */
-       return n;
-
-fail:
-       slab_unlock(page);
-       spin_unlock_irqrestore(&n->list_lock, *flags);
-       slab_fix(s, "Object at 0x%p not freed", object);
-       return NULL;
+       spin_unlock_irqrestore(&n->list_lock, flags);
+       if (!ret)
+               slab_fix(s, "Object at 0x%p not freed", object);
+       return ret;
 }
 
 static int __init setup_slub_debug(char *str)
@@ -1172,7 +1214,7 @@ static int __init setup_slub_debug(char *str)
        for (; *str && *str != ','; str++) {
                switch (tolower(*str)) {
                case 'f':
-                       slub_debug |= SLAB_DEBUG_FREE;
+                       slub_debug |= SLAB_CONSISTENCY_CHECKS;
                        break;
                case 'z':
                        slub_debug |= SLAB_RED_ZONE;
@@ -1231,10 +1273,10 @@ static inline void setup_object_debug(struct kmem_cache *s,
 static inline int alloc_debug_processing(struct kmem_cache *s,
        struct page *page, void *object, unsigned long addr) { return 0; }
 
-static inline struct kmem_cache_node *free_debug_processing(
+static inline int free_debug_processing(
        struct kmem_cache *s, struct page *page,
        void *head, void *tail, int bulk_cnt,
-       unsigned long addr, unsigned long *flags) { return NULL; }
+       unsigned long addr) { return 0; }
 
 static inline int slab_pad_check(struct kmem_cache *s, struct page *page)
                        { return 1; }
@@ -1281,36 +1323,6 @@ static inline void kfree_hook(const void *x)
        kasan_kfree_large(x);
 }
 
-static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
-                                                    gfp_t flags)
-{
-       flags &= gfp_allowed_mask;
-       lockdep_trace_alloc(flags);
-       might_sleep_if(gfpflags_allow_blocking(flags));
-
-       if (should_failslab(s->object_size, flags, s->flags))
-               return NULL;
-
-       return memcg_kmem_get_cache(s, flags);
-}
-
-static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
-                                       size_t size, void **p)
-{
-       size_t i;
-
-       flags &= gfp_allowed_mask;
-       for (i = 0; i < size; i++) {
-               void *object = p[i];
-
-               kmemcheck_slab_alloc(s, flags, object, slab_ksize(s));
-               kmemleak_alloc_recursive(object, s->object_size, 1,
-                                        s->flags, flags);
-               kasan_slab_alloc(s, object);
-       }
-       memcg_kmem_put_cache(s);
-}
-
 static inline void slab_free_hook(struct kmem_cache *s, void *x)
 {
        kmemleak_free_recursive(x, s->flags);
@@ -1470,7 +1482,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
                        set_freepointer(s, p, NULL);
        }
 
-       page->freelist = start;
+       page->freelist = fixup_red_left(s, start);
        page->inuse = page->objects;
        page->frozen = 1;
 
@@ -1506,7 +1518,7 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
        int order = compound_order(page);
        int pages = 1 << order;
 
-       if (kmem_cache_debug(s)) {
+       if (s->flags & SLAB_CONSISTENCY_CHECKS) {
                void *p;
 
                slab_pad_check(s, page);
@@ -2224,8 +2236,8 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid)
        if ((gfpflags & __GFP_NOWARN) || !__ratelimit(&slub_oom_rs))
                return;
 
-       pr_warn("SLUB: Unable to allocate memory on node %d (gfp=0x%x)\n",
-               nid, gfpflags);
+       pr_warn("SLUB: Unable to allocate memory on node %d, gfp=%#x(%pGg)\n",
+               nid, gfpflags, &gfpflags);
        pr_warn("  cache: %s, object size: %d, buffer size: %d, default order: %d, min order: %d\n",
                s->name, s->object_size, s->size, oo_order(s->oo),
                oo_order(s->min));
@@ -2642,8 +2654,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
        stat(s, FREE_SLOWPATH);
 
        if (kmem_cache_debug(s) &&
-           !(n = free_debug_processing(s, page, head, tail, cnt,
-                                       addr, &flags)))
+           !free_debug_processing(s, page, head, tail, cnt, addr))
                return;
 
        do {
@@ -2815,6 +2826,7 @@ struct detached_freelist {
        void *tail;
        void *freelist;
        int cnt;
+       struct kmem_cache *s;
 };
 
 /*
@@ -2829,26 +2841,45 @@ struct detached_freelist {
  * synchronization primitive.  Look ahead in the array is limited due
  * to performance reasons.
  */
-static int build_detached_freelist(struct kmem_cache *s, size_t size,
-                                  void **p, struct detached_freelist *df)
+static inline
+int build_detached_freelist(struct kmem_cache *s, size_t size,
+                           void **p, struct detached_freelist *df)
 {
        size_t first_skipped_index = 0;
        int lookahead = 3;
        void *object;
+       struct page *page;
 
        /* Always re-init detached_freelist */
        df->page = NULL;
 
        do {
                object = p[--size];
+               /* Do we need !ZERO_OR_NULL_PTR(object) here? (for kfree) */
        } while (!object && size);
 
        if (!object)
                return 0;
 
+       page = virt_to_head_page(object);
+       if (!s) {
+               /* Handle kalloc'ed objects */
+               if (unlikely(!PageSlab(page))) {
+                       BUG_ON(!PageCompound(page));
+                       kfree_hook(object);
+                       __free_kmem_pages(page, compound_order(page));
+                       p[size] = NULL; /* mark object processed */
+                       return size;
+               }
+               /* Derive kmem_cache from object */
+               df->s = page->slab_cache;
+       } else {
+               df->s = cache_from_obj(s, object); /* Support for memcg */
+       }
+
        /* Start new detached freelist */
-       set_freepointer(s, object, NULL);
-       df->page = virt_to_head_page(object);
+       df->page = page;
+       set_freepointer(df->s, object, NULL);
        df->tail = object;
        df->freelist = object;
        p[size] = NULL; /* mark object processed */
@@ -2862,7 +2893,7 @@ static int build_detached_freelist(struct kmem_cache *s, size_t size,
                /* df->page is always set at this point */
                if (df->page == virt_to_head_page(object)) {
                        /* Opportunity build freelist */
-                       set_freepointer(s, object, df->freelist);
+                       set_freepointer(df->s, object, df->freelist);
                        df->freelist = object;
                        df->cnt++;
                        p[size] = NULL; /* mark object processed */
@@ -2881,25 +2912,20 @@ static int build_detached_freelist(struct kmem_cache *s, size_t size,
        return first_skipped_index;
 }
 
-
 /* Note that interrupts must be enabled when calling this function. */
-void kmem_cache_free_bulk(struct kmem_cache *orig_s, size_t size, void **p)
+void kmem_cache_free_bulk(struct kmem_cache *s, size_t size, void **p)
 {
        if (WARN_ON(!size))
                return;
 
        do {
                struct detached_freelist df;
-               struct kmem_cache *s;
-
-               /* Support for memcg */
-               s = cache_from_obj(orig_s, p[size - 1]);
 
                size = build_detached_freelist(s, size, p, &df);
                if (unlikely(!df.page))
                        continue;
 
-               slab_free(s, df.page, df.freelist, df.tail, df.cnt, _RET_IP_);
+               slab_free(df.s, df.page, df.freelist, df.tail, df.cnt,_RET_IP_);
        } while (likely(size));
 }
 EXPORT_SYMBOL(kmem_cache_free_bulk);
@@ -3285,7 +3311,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
                 */
                size += 2 * sizeof(struct track);
 
-       if (flags & SLAB_RED_ZONE)
+       if (flags & SLAB_RED_ZONE) {
                /*
                 * Add some empty padding so that we can catch
                 * overwrites from earlier objects rather than let
@@ -3294,6 +3320,11 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
                 * of the object.
                 */
                size += sizeof(void *);
+
+               s->red_left_pad = sizeof(void *);
+               s->red_left_pad = ALIGN(s->red_left_pad, s->align);
+               size += s->red_left_pad;
+       }
 #endif
 
        /*
@@ -3357,7 +3388,7 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags)
 
 #if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && \
     defined(CONFIG_HAVE_ALIGNED_STRUCT_PAGE)
-       if (system_has_cmpxchg_double() && (s->flags & SLAB_DEBUG_FLAGS) == 0)
+       if (system_has_cmpxchg_double() && (s->flags & SLAB_NO_CMPXCHG) == 0)
                /* Enable fast mode */
                s->flags |= __CMPXCHG_DOUBLE;
 #endif
@@ -4812,16 +4843,16 @@ SLAB_ATTR_RO(total_objects);
 
 static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE));
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_CONSISTENCY_CHECKS));
 }
 
 static ssize_t sanity_checks_store(struct kmem_cache *s,
                                const char *buf, size_t length)
 {
-       s->flags &= ~SLAB_DEBUG_FREE;
+       s->flags &= ~SLAB_CONSISTENCY_CHECKS;
        if (buf[0] == '1') {
                s->flags &= ~__CMPXCHG_DOUBLE;
-               s->flags |= SLAB_DEBUG_FREE;
+               s->flags |= SLAB_CONSISTENCY_CHECKS;
        }
        return length;
 }
@@ -4865,7 +4896,6 @@ static ssize_t red_zone_store(struct kmem_cache *s,
 
        s->flags &= ~SLAB_RED_ZONE;
        if (buf[0] == '1') {
-               s->flags &= ~__CMPXCHG_DOUBLE;
                s->flags |= SLAB_RED_ZONE;
        }
        calculate_sizes(s, -1);
@@ -4886,7 +4916,6 @@ static ssize_t poison_store(struct kmem_cache *s,
 
        s->flags &= ~SLAB_POISON;
        if (buf[0] == '1') {
-               s->flags &= ~__CMPXCHG_DOUBLE;
                s->flags |= SLAB_POISON;
        }
        calculate_sizes(s, -1);
@@ -5356,7 +5385,7 @@ static char *create_unique_id(struct kmem_cache *s)
                *p++ = 'd';
        if (s->flags & SLAB_RECLAIM_ACCOUNT)
                *p++ = 'a';
-       if (s->flags & SLAB_DEBUG_FREE)
+       if (s->flags & SLAB_CONSISTENCY_CHECKS)
                *p++ = 'F';
        if (!(s->flags & SLAB_NOTRACK))
                *p++ = 't';
index e3ee0e27cd17f20d1d35f1acdeab18136ccc1e29..7598b552ae0310c6490121422fcc58aae7ff010f 100644 (file)
@@ -519,7 +519,6 @@ EXPORT_SYMBOL(invalidate_mapping_pages);
 static int
 invalidate_complete_page2(struct address_space *mapping, struct page *page)
 {
-       struct mem_cgroup *memcg;
        unsigned long flags;
 
        if (page->mapping != mapping)
@@ -528,15 +527,13 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
        if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL))
                return 0;
 
-       memcg = mem_cgroup_begin_page_stat(page);
        spin_lock_irqsave(&mapping->tree_lock, flags);
        if (PageDirty(page))
                goto failed;
 
        BUG_ON(page_has_private(page));
-       __delete_from_page_cache(page, NULL, memcg);
+       __delete_from_page_cache(page, NULL);
        spin_unlock_irqrestore(&mapping->tree_lock, flags);
-       mem_cgroup_end_page_stat(memcg);
 
        if (mapping->a_ops->freepage)
                mapping->a_ops->freepage(page);
@@ -545,7 +542,6 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
        return 1;
 failed:
        spin_unlock_irqrestore(&mapping->tree_lock, flags);
-       mem_cgroup_end_page_stat(memcg);
        return 0;
 }
 
index 71b1c29948dba30aab0a894ddc7c84eb62acde2b..dd984470248fe3a137d211be0789f8aa8446f95a 100644 (file)
@@ -195,25 +195,25 @@ static unsigned long zone_reclaimable_pages(struct zone *zone)
 {
        unsigned long nr;
 
-       nr = zone_page_state(zone, NR_ACTIVE_FILE) +
-            zone_page_state(zone, NR_INACTIVE_FILE) +
-            zone_page_state(zone, NR_ISOLATED_FILE);
+       nr = zone_page_state_snapshot(zone, NR_ACTIVE_FILE) +
+            zone_page_state_snapshot(zone, NR_INACTIVE_FILE) +
+            zone_page_state_snapshot(zone, NR_ISOLATED_FILE);
 
        if (get_nr_swap_pages() > 0)
-               nr += zone_page_state(zone, NR_ACTIVE_ANON) +
-                     zone_page_state(zone, NR_INACTIVE_ANON) +
-                     zone_page_state(zone, NR_ISOLATED_ANON);
+               nr += zone_page_state_snapshot(zone, NR_ACTIVE_ANON) +
+                     zone_page_state_snapshot(zone, NR_INACTIVE_ANON) +
+                     zone_page_state_snapshot(zone, NR_ISOLATED_ANON);
 
        return nr;
 }
 
 bool zone_reclaimable(struct zone *zone)
 {
-       return zone_page_state(zone, NR_PAGES_SCANNED) <
+       return zone_page_state_snapshot(zone, NR_PAGES_SCANNED) <
                zone_reclaimable_pages(zone) * 6;
 }
 
-static unsigned long get_lru_size(struct lruvec *lruvec, enum lru_list lru)
+unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru)
 {
        if (!mem_cgroup_disabled())
                return mem_cgroup_get_lru_size(lruvec, lru);
@@ -228,14 +228,6 @@ int register_shrinker(struct shrinker *shrinker)
 {
        size_t size = sizeof(*shrinker->nr_deferred);
 
-       /*
-        * If we only have one possible node in the system anyway, save
-        * ourselves the trouble and disable NUMA aware behavior. This way we
-        * will save memory and some small loop time later.
-        */
-       if (nr_node_ids == 1)
-               shrinker->flags &= ~SHRINKER_NUMA_AWARE;
-
        if (shrinker->flags & SHRINKER_NUMA_AWARE)
                size *= nr_node_ids;
 
@@ -611,12 +603,10 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
                            bool reclaimed)
 {
        unsigned long flags;
-       struct mem_cgroup *memcg;
 
        BUG_ON(!PageLocked(page));
        BUG_ON(mapping != page_mapping(page));
 
-       memcg = mem_cgroup_begin_page_stat(page);
        spin_lock_irqsave(&mapping->tree_lock, flags);
        /*
         * The non racy check for a busy page.
@@ -656,7 +646,6 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
                mem_cgroup_swapout(page, swap);
                __delete_from_swap_cache(page);
                spin_unlock_irqrestore(&mapping->tree_lock, flags);
-               mem_cgroup_end_page_stat(memcg);
                swapcache_free(swap);
        } else {
                void (*freepage)(struct page *);
@@ -682,9 +671,8 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
                if (reclaimed && page_is_file_cache(page) &&
                    !mapping_exiting(mapping) && !dax_mapping(mapping))
                        shadow = workingset_eviction(mapping, page);
-               __delete_from_page_cache(page, shadow, memcg);
+               __delete_from_page_cache(page, shadow);
                spin_unlock_irqrestore(&mapping->tree_lock, flags);
-               mem_cgroup_end_page_stat(memcg);
 
                if (freepage != NULL)
                        freepage(page);
@@ -694,7 +682,6 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
 
 cannot_free:
        spin_unlock_irqrestore(&mapping->tree_lock, flags);
-       mem_cgroup_end_page_stat(memcg);
        return 0;
 }
 
@@ -1931,8 +1918,8 @@ static bool inactive_file_is_low(struct lruvec *lruvec)
        unsigned long inactive;
        unsigned long active;
 
-       inactive = get_lru_size(lruvec, LRU_INACTIVE_FILE);
-       active = get_lru_size(lruvec, LRU_ACTIVE_FILE);
+       inactive = lruvec_lru_size(lruvec, LRU_INACTIVE_FILE);
+       active = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE);
 
        return active > inactive;
 }
@@ -2071,7 +2058,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
         * system is under heavy pressure.
         */
        if (!inactive_file_is_low(lruvec) &&
-           get_lru_size(lruvec, LRU_INACTIVE_FILE) >> sc->priority) {
+           lruvec_lru_size(lruvec, LRU_INACTIVE_FILE) >> sc->priority) {
                scan_balance = SCAN_FILE;
                goto out;
        }
@@ -2097,10 +2084,10 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
         * anon in [0], file in [1]
         */
 
-       anon  = get_lru_size(lruvec, LRU_ACTIVE_ANON) +
-               get_lru_size(lruvec, LRU_INACTIVE_ANON);
-       file  = get_lru_size(lruvec, LRU_ACTIVE_FILE) +
-               get_lru_size(lruvec, LRU_INACTIVE_FILE);
+       anon  = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON) +
+               lruvec_lru_size(lruvec, LRU_INACTIVE_ANON);
+       file  = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE) +
+               lruvec_lru_size(lruvec, LRU_INACTIVE_FILE);
 
        spin_lock_irq(&zone->lru_lock);
        if (unlikely(reclaim_stat->recent_scanned[0] > anon / 4)) {
@@ -2138,7 +2125,7 @@ out:
                        unsigned long size;
                        unsigned long scan;
 
-                       size = get_lru_size(lruvec, lru);
+                       size = lruvec_lru_size(lruvec, lru);
                        scan = size >> sc->priority;
 
                        if (!scan && pass && force_scan)
index 084c6725b3734430483e7ea4fcf74e2ab67f7bfa..69ce64f7b8d76de74991638730f825855f7a26d2 100644 (file)
@@ -924,19 +924,6 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
 #endif
 
 #ifdef CONFIG_PROC_FS
-static char * const migratetype_names[MIGRATE_TYPES] = {
-       "Unmovable",
-       "Movable",
-       "Reclaimable",
-       "HighAtomic",
-#ifdef CONFIG_CMA
-       "CMA",
-#endif
-#ifdef CONFIG_MEMORY_ISOLATION
-       "Isolate",
-#endif
-};
-
 static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
                                                struct zone *zone)
 {
@@ -1133,7 +1120,7 @@ static void pagetypeinfo_showmixedcount(struct seq_file *m, pg_data_t *pgdat)
 #ifdef CONFIG_PAGE_OWNER
        int mtype;
 
-       if (!page_owner_inited)
+       if (!static_branch_unlikely(&page_owner_inited))
                return;
 
        drain_all_pages(NULL);
index 61ead9e5549df171f43fa53936a4b8cbd86a21a5..6130ba0b26415353e09c977a0f3d13cf94b76178 100644 (file)
  * refault distance will immediately activate the refaulting page.
  */
 
-static void *pack_shadow(unsigned long eviction, struct zone *zone)
+#define EVICTION_SHIFT (RADIX_TREE_EXCEPTIONAL_ENTRY + \
+                        ZONES_SHIFT + NODES_SHIFT +    \
+                        MEM_CGROUP_ID_SHIFT)
+#define EVICTION_MASK  (~0UL >> EVICTION_SHIFT)
+
+/*
+ * Eviction timestamps need to be able to cover the full range of
+ * actionable refaults. However, bits are tight in the radix tree
+ * entry, and after storing the identifier for the lruvec there might
+ * not be enough left to represent every single actionable refault. In
+ * that case, we have to sacrifice granularity for distance, and group
+ * evictions into coarser buckets by shaving off lower timestamp bits.
+ */
+static unsigned int bucket_order __read_mostly;
+
+static void *pack_shadow(int memcgid, struct zone *zone, unsigned long eviction)
 {
+       eviction >>= bucket_order;
+       eviction = (eviction << MEM_CGROUP_ID_SHIFT) | memcgid;
        eviction = (eviction << NODES_SHIFT) | zone_to_nid(zone);
        eviction = (eviction << ZONES_SHIFT) | zone_idx(zone);
        eviction = (eviction << RADIX_TREE_EXCEPTIONAL_SHIFT);
@@ -161,45 +178,23 @@ static void *pack_shadow(unsigned long eviction, struct zone *zone)
        return (void *)(eviction | RADIX_TREE_EXCEPTIONAL_ENTRY);
 }
 
-static void unpack_shadow(void *shadow,
-                         struct zone **zone,
-                         unsigned long *distance)
+static void unpack_shadow(void *shadow, int *memcgidp, struct zone **zonep,
+                         unsigned long *evictionp)
 {
        unsigned long entry = (unsigned long)shadow;
-       unsigned long eviction;
-       unsigned long refault;
-       unsigned long mask;
-       int zid, nid;
+       int memcgid, nid, zid;
 
        entry >>= RADIX_TREE_EXCEPTIONAL_SHIFT;
        zid = entry & ((1UL << ZONES_SHIFT) - 1);
        entry >>= ZONES_SHIFT;
        nid = entry & ((1UL << NODES_SHIFT) - 1);
        entry >>= NODES_SHIFT;
-       eviction = entry;
+       memcgid = entry & ((1UL << MEM_CGROUP_ID_SHIFT) - 1);
+       entry >>= MEM_CGROUP_ID_SHIFT;
 
-       *zone = NODE_DATA(nid)->node_zones + zid;
-
-       refault = atomic_long_read(&(*zone)->inactive_age);
-       mask = ~0UL >> (NODES_SHIFT + ZONES_SHIFT +
-                       RADIX_TREE_EXCEPTIONAL_SHIFT);
-       /*
-        * The unsigned subtraction here gives an accurate distance
-        * across inactive_age overflows in most cases.
-        *
-        * There is a special case: usually, shadow entries have a
-        * short lifetime and are either refaulted or reclaimed along
-        * with the inode before they get too old.  But it is not
-        * impossible for the inactive_age to lap a shadow entry in
-        * the field, which can then can result in a false small
-        * refault distance, leading to a false activation should this
-        * old entry actually refault again.  However, earlier kernels
-        * used to deactivate unconditionally with *every* reclaim
-        * invocation for the longest time, so the occasional
-        * inappropriate activation leading to pressure on the active
-        * list is not a problem.
-        */
-       *distance = (refault - eviction) & mask;
+       *memcgidp = memcgid;
+       *zonep = NODE_DATA(nid)->node_zones + zid;
+       *evictionp = entry << bucket_order;
 }
 
 /**
@@ -212,11 +207,20 @@ static void unpack_shadow(void *shadow,
  */
 void *workingset_eviction(struct address_space *mapping, struct page *page)
 {
+       struct mem_cgroup *memcg = page_memcg(page);
        struct zone *zone = page_zone(page);
+       int memcgid = mem_cgroup_id(memcg);
        unsigned long eviction;
+       struct lruvec *lruvec;
 
-       eviction = atomic_long_inc_return(&zone->inactive_age);
-       return pack_shadow(eviction, zone);
+       /* Page is fully exclusive and pins page->mem_cgroup */
+       VM_BUG_ON_PAGE(PageLRU(page), page);
+       VM_BUG_ON_PAGE(page_count(page), page);
+       VM_BUG_ON_PAGE(!PageLocked(page), page);
+
+       lruvec = mem_cgroup_zone_lruvec(zone, memcg);
+       eviction = atomic_long_inc_return(&lruvec->inactive_age);
+       return pack_shadow(memcgid, zone, eviction);
 }
 
 /**
@@ -231,12 +235,64 @@ void *workingset_eviction(struct address_space *mapping, struct page *page)
 bool workingset_refault(void *shadow)
 {
        unsigned long refault_distance;
+       unsigned long active_file;
+       struct mem_cgroup *memcg;
+       unsigned long eviction;
+       struct lruvec *lruvec;
+       unsigned long refault;
        struct zone *zone;
+       int memcgid;
+
+       unpack_shadow(shadow, &memcgid, &zone, &eviction);
+
+       rcu_read_lock();
+       /*
+        * Look up the memcg associated with the stored ID. It might
+        * have been deleted since the page's eviction.
+        *
+        * Note that in rare events the ID could have been recycled
+        * for a new cgroup that refaults a shared page. This is
+        * impossible to tell from the available data. However, this
+        * should be a rare and limited disturbance, and activations
+        * are always speculative anyway. Ultimately, it's the aging
+        * algorithm's job to shake out the minimum access frequency
+        * for the active cache.
+        *
+        * XXX: On !CONFIG_MEMCG, this will always return NULL; it
+        * would be better if the root_mem_cgroup existed in all
+        * configurations instead.
+        */
+       memcg = mem_cgroup_from_id(memcgid);
+       if (!mem_cgroup_disabled() && !memcg) {
+               rcu_read_unlock();
+               return false;
+       }
+       lruvec = mem_cgroup_zone_lruvec(zone, memcg);
+       refault = atomic_long_read(&lruvec->inactive_age);
+       active_file = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE);
+       rcu_read_unlock();
+
+       /*
+        * The unsigned subtraction here gives an accurate distance
+        * across inactive_age overflows in most cases.
+        *
+        * There is a special case: usually, shadow entries have a
+        * short lifetime and are either refaulted or reclaimed along
+        * with the inode before they get too old.  But it is not
+        * impossible for the inactive_age to lap a shadow entry in
+        * the field, which can then can result in a false small
+        * refault distance, leading to a false activation should this
+        * old entry actually refault again.  However, earlier kernels
+        * used to deactivate unconditionally with *every* reclaim
+        * invocation for the longest time, so the occasional
+        * inappropriate activation leading to pressure on the active
+        * list is not a problem.
+        */
+       refault_distance = (refault - eviction) & EVICTION_MASK;
 
-       unpack_shadow(shadow, &zone, &refault_distance);
        inc_zone_state(zone, WORKINGSET_REFAULT);
 
-       if (refault_distance <= zone_page_state(zone, NR_ACTIVE_FILE)) {
+       if (refault_distance <= active_file) {
                inc_zone_state(zone, WORKINGSET_ACTIVATE);
                return true;
        }
@@ -249,7 +305,22 @@ bool workingset_refault(void *shadow)
  */
 void workingset_activation(struct page *page)
 {
-       atomic_long_inc(&page_zone(page)->inactive_age);
+       struct lruvec *lruvec;
+
+       lock_page_memcg(page);
+       /*
+        * Filter non-memcg pages here, e.g. unmap can call
+        * mark_page_accessed() on VDSO pages.
+        *
+        * XXX: See workingset_refault() - this should return
+        * root_mem_cgroup even for !CONFIG_MEMCG.
+        */
+       if (!mem_cgroup_disabled() && !page_memcg(page))
+               goto out;
+       lruvec = mem_cgroup_zone_lruvec(page_zone(page), page_memcg(page));
+       atomic_long_inc(&lruvec->inactive_age);
+out:
+       unlock_page_memcg(page);
 }
 
 /*
@@ -398,8 +469,25 @@ static struct lock_class_key shadow_nodes_key;
 
 static int __init workingset_init(void)
 {
+       unsigned int timestamp_bits;
+       unsigned int max_order;
        int ret;
 
+       BUILD_BUG_ON(BITS_PER_LONG < EVICTION_SHIFT);
+       /*
+        * Calculate the eviction bucket size to cover the longest
+        * actionable refault distance, which is currently half of
+        * memory (totalram_pages/2). However, memory hotplug may add
+        * some more pages at runtime, so keep working with up to
+        * double the initial memory by using totalram_pages as-is.
+        */
+       timestamp_bits = BITS_PER_LONG - EVICTION_SHIFT;
+       max_order = fls_long(totalram_pages - 1);
+       if (max_order > timestamp_bits)
+               bucket_order = max_order - timestamp_bits;
+       printk("workingset: timestamp_bits=%d max_order=%d bucket_order=%u\n",
+              timestamp_bits, max_order, bucket_order);
+
        ret = list_lru_init_key(&workingset_shadow_nodes, &shadow_nodes_key);
        if (ret)
                goto err;
index 82e3e97050173542b5d6094ebc4db81324198b18..dcea4f4c62b3b43d701fb68a74a6aa1a1e0aa8cf 100644 (file)
@@ -723,6 +723,8 @@ int br_fdb_dump(struct sk_buff *skb,
                struct net_bridge_fdb_entry *f;
 
                hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
+                       int err;
+
                        if (idx < cb->args[0])
                                goto skip;
 
@@ -741,12 +743,15 @@ int br_fdb_dump(struct sk_buff *skb,
                        if (!filter_dev && f->dst)
                                goto skip;
 
-                       if (fdb_fill_info(skb, br, f,
-                                         NETLINK_CB(cb->skb).portid,
-                                         cb->nlh->nlmsg_seq,
-                                         RTM_NEWNEIGH,
-                                         NLM_F_MULTI) < 0)
+                       err = fdb_fill_info(skb, br, f,
+                                           NETLINK_CB(cb->skb).portid,
+                                           cb->nlh->nlmsg_seq,
+                                           RTM_NEWNEIGH,
+                                           NLM_F_MULTI);
+                       if (err < 0) {
+                               cb->args[1] = err;
                                break;
+                       }
 skip:
                        ++idx;
                }
index 9cfedf565f5b236b5ede7974466cf62af6ad995c..9382619a405b8da854c82b041a137a670399567f 100644 (file)
@@ -1197,6 +1197,13 @@ static bool ceph_msg_data_advance(struct ceph_msg_data_cursor *cursor,
        return new_piece;
 }
 
+static size_t sizeof_footer(struct ceph_connection *con)
+{
+       return (con->peer_features & CEPH_FEATURE_MSG_AUTH) ?
+           sizeof(struct ceph_msg_footer) :
+           sizeof(struct ceph_msg_footer_old);
+}
+
 static void prepare_message_data(struct ceph_msg *msg, u32 data_len)
 {
        BUG_ON(!msg);
@@ -2335,9 +2342,9 @@ static int read_partial_message(struct ceph_connection *con)
                        ceph_pr_addr(&con->peer_addr.in_addr),
                        seq, con->in_seq + 1);
                con->in_base_pos = -front_len - middle_len - data_len -
-                       sizeof(m->footer);
+                       sizeof_footer(con);
                con->in_tag = CEPH_MSGR_TAG_READY;
-               return 0;
+               return 1;
        } else if ((s64)seq - (s64)con->in_seq > 1) {
                pr_err("read_partial_message bad seq %lld expected %lld\n",
                       seq, con->in_seq + 1);
@@ -2360,10 +2367,10 @@ static int read_partial_message(struct ceph_connection *con)
                        /* skip this message */
                        dout("alloc_msg said skip message\n");
                        con->in_base_pos = -front_len - middle_len - data_len -
-                               sizeof(m->footer);
+                               sizeof_footer(con);
                        con->in_tag = CEPH_MSGR_TAG_READY;
                        con->in_seq++;
-                       return 0;
+                       return 1;
                }
 
                BUG_ON(!con->in_msg);
index 3534e12683d3b2b6efa9988faff9e9b3249e6fa6..5bc053778feddd0e35fe73480317be25345da61c 100644 (file)
@@ -2853,8 +2853,8 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
        mutex_lock(&osdc->request_mutex);
        req = __lookup_request(osdc, tid);
        if (!req) {
-               pr_warn("%s osd%d tid %llu unknown, skipping\n",
-                       __func__, osd->o_osd, tid);
+               dout("%s osd%d tid %llu unknown, skipping\n", __func__,
+                    osd->o_osd, tid);
                m = NULL;
                *skip = 1;
                goto out;
index 94d26201080d6671080f63865994bb41d7d3d8bc..bba502f7cd575692a9ed795f83d2fdedf2428ed6 100644 (file)
@@ -1752,7 +1752,7 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)
        u8 compat[sizeof(struct bpf_tunnel_key)];
        struct ip_tunnel_info *info;
 
-       if (unlikely(flags & ~(BPF_F_TUNINFO_IPV6)))
+       if (unlikely(flags & ~(BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX)))
                return -EINVAL;
        if (unlikely(size != sizeof(struct bpf_tunnel_key))) {
                switch (size) {
@@ -1776,7 +1776,7 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)
        info = &md->u.tun_info;
        info->mode = IP_TUNNEL_INFO_TX;
 
-       info->key.tun_flags = TUNNEL_KEY;
+       info->key.tun_flags = TUNNEL_KEY | TUNNEL_CSUM;
        info->key.tun_id = cpu_to_be64(from->tunnel_id);
        info->key.tos = from->tunnel_tos;
        info->key.ttl = from->tunnel_ttl;
@@ -1787,6 +1787,8 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)
                       sizeof(from->remote_ipv6));
        } else {
                info->key.u.ipv4.dst = cpu_to_be32(from->remote_ipv4);
+               if (flags & BPF_F_ZERO_CSUM_TX)
+                       info->key.tun_flags &= ~TUNNEL_CSUM;
        }
 
        return 0;
index d735e854f916040912fb12930cbc6a7950ace942..8261d95dd846647798c7dba8f1dbfa4cf61a0eef 100644 (file)
@@ -2911,6 +2911,7 @@ int ndo_dflt_fdb_dump(struct sk_buff *skb,
        nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc);
 out:
        netif_addr_unlock_bh(dev);
+       cb->args[1] = err;
        return idx;
 }
 EXPORT_SYMBOL(ndo_dflt_fdb_dump);
@@ -2944,6 +2945,7 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
                ops = br_dev->netdev_ops;
        }
 
+       cb->args[1] = 0;
        for_each_netdev(net, dev) {
                if (brport_idx && (dev->ifindex != brport_idx))
                        continue;
@@ -2971,12 +2973,16 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
                                idx = cops->ndo_fdb_dump(skb, cb, br_dev, dev,
                                                         idx);
                }
+               if (cb->args[1] == -EMSGSIZE)
+                       break;
 
                if (dev->netdev_ops->ndo_fdb_dump)
                        idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL,
                                                            idx);
                else
                        idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx);
+               if (cb->args[1] == -EMSGSIZE)
+                       break;
 
                cops = NULL;
        }
index 5bf88f58bee7405ff65f80487a64339b92a91bcb..8616d1147c938808da752734b6cecea260b149b9 100644 (file)
@@ -2947,6 +2947,24 @@ int skb_append_pagefrags(struct sk_buff *skb, struct page *page,
 }
 EXPORT_SYMBOL_GPL(skb_append_pagefrags);
 
+/**
+ *     skb_push_rcsum - push skb and update receive checksum
+ *     @skb: buffer to update
+ *     @len: length of data pulled
+ *
+ *     This function performs an skb_push on the packet and updates
+ *     the CHECKSUM_COMPLETE checksum.  It should be used on
+ *     receive path processing instead of skb_push unless you know
+ *     that the checksum difference is zero (e.g., a valid IP header)
+ *     or you are setting ip_summed to CHECKSUM_NONE.
+ */
+static unsigned char *skb_push_rcsum(struct sk_buff *skb, unsigned len)
+{
+       skb_push(skb, len);
+       skb_postpush_rcsum(skb, skb->data, len);
+       return skb->data;
+}
+
 /**
  *     skb_pull_rcsum - pull skb and update receive checksum
  *     @skb: buffer to update
@@ -4084,9 +4102,9 @@ struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,
        if (!pskb_may_pull(skb_chk, offset))
                goto err;
 
-       __skb_pull(skb_chk, offset);
+       skb_pull_rcsum(skb_chk, offset);
        ret = skb_chkf(skb_chk);
-       __skb_push(skb_chk, offset);
+       skb_push_rcsum(skb_chk, offset);
 
        if (ret)
                goto err;
index 05e4cba14162f3583ec588657af7e8b68546b111..b3086cf2702759d1077cb6a014afbd130d8206db 100644 (file)
@@ -356,9 +356,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, unsigned int mtu)
        skb_dst_set(skb, &rt->dst);
        skb->dev = dev;
 
-       skb->reserved_tailroom = skb_end_offset(skb) -
-                                min(mtu, skb_end_offset(skb));
        skb_reserve(skb, hlen);
+       skb_tailroom_reserve(skb, mtu, tlen);
 
        skb_reset_network_header(skb);
        pip = ip_hdr(skb);
index 64878efa045c132d1ce511c326c2da04fc77a895..565bf64b2b7d6047a29e69df00fb3b85ec84f06a 100644 (file)
@@ -1236,13 +1236,16 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
        if (!skb)
                return -EINVAL;
 
-       cork->length += size;
        if ((size + skb->len > mtu) &&
            (sk->sk_protocol == IPPROTO_UDP) &&
            (rt->dst.dev->features & NETIF_F_UFO)) {
+               if (skb->ip_summed != CHECKSUM_PARTIAL)
+                       return -EOPNOTSUPP;
+
                skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
        }
+       cork->length += size;
 
        while (size > 0) {
                if (skb_is_gso(skb)) {
index 89e8861e05fcb1d371c371c1784b89499b69d9df..336e6892a93ce99aabf1794133c9567ee0effde7 100644 (file)
@@ -661,6 +661,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
        connected = (tunnel->parms.iph.daddr != 0);
 
+       memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+
        dst = tnl_params->daddr;
        if (dst == 0) {
                /* NBMA tunnel */
@@ -758,7 +760,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                                tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
                        tunnel->err_count--;
 
-                       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
                        dst_link_failure(skb);
                } else
                        tunnel->err_count = 0;
index 643a86c490208cad3fa1e4098e5bc7c30d03eab8..2d5589b61e9faa0fc53c7ddfa198e593a02ddea5 100644 (file)
@@ -50,8 +50,7 @@ static u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS] __read_mostly;
 #define TSBITS 6
 #define TSMASK (((__u32)1 << TSBITS) - 1)
 
-static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS],
-                     ipv4_cookie_scratch);
+static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], ipv4_cookie_scratch);
 
 static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
                       u32 count, int c)
index c8cbc2b4b7921fb4f70681e4ac6d945f5499654c..a726d7853ce53fe03b48b199ca909c02393cabcf 100644 (file)
@@ -550,7 +550,7 @@ reset:
         */
        if (crtt > tp->srtt_us) {
                /* Set RTO like tcp_rtt_estimator(), but from cached RTT. */
-               crtt /= 8 * USEC_PER_MSEC;
+               crtt /= 8 * USEC_PER_SEC / HZ;
                inet_csk(sk)->icsk_rto = crtt + max(2 * crtt, tcp_rto_min(sk));
        } else if (tp->srtt_us == 0) {
                /* RFC6298: 5.7 We've failed to get a valid RTT sample from
index 75632a92582425db63f1078c223cbd54a91fa0c3..9b02af2139d3d3245ea952f643fc52e0ee92a9ab 100644 (file)
@@ -455,7 +455,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
 
                newtp->rcv_wup = newtp->copied_seq =
                newtp->rcv_nxt = treq->rcv_isn + 1;
-               newtp->segs_in = 0;
+               newtp->segs_in = 1;
 
                newtp->snd_sml = newtp->snd_una =
                newtp->snd_nxt = newtp->snd_up = treq->snt_isn + 1;
@@ -815,6 +815,7 @@ int tcp_child_process(struct sock *parent, struct sock *child,
        int ret = 0;
        int state = child->sk_state;
 
+       tcp_sk(child)->segs_in += max_t(u16, 1, skb_shinfo(skb)->gso_segs);
        if (!sock_owned_by_user(child)) {
                ret = tcp_rcv_state_process(child, skb);
                /* Wakeup parent, send SIGIO */
index 0ec08814f37d9e904b5f85bbd86cd2fa607c4307..96599d1a13184d4ef6d34ae9bff7833420d0ad93 100644 (file)
@@ -89,6 +89,8 @@ void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb
        uh->source = src_port;
        uh->len = htons(skb->len);
 
+       memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+
        udp_set_csum(nocheck, skb, src, dst, skb->len);
 
        iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, xnet);
index 5c5d23e59da598995ff962d069d1e7b6886e31d6..9508a20fbf61432f561202edbe40b59e63c3489e 100644 (file)
@@ -257,7 +257,11 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
                                                *fragoff = _frag_off;
                                        return hp->nexthdr;
                                }
-                               return -ENOENT;
+                               if (!found)
+                                       return -ENOENT;
+                               if (fragoff)
+                                       *fragoff = _frag_off;
+                               break;
                        }
                        hdrlen = 8;
                } else if (nexthdr == NEXTHDR_AUTH) {
index a69aad1e29d1ebb2429650cc083f0e4dd2bcaf86..c0d4dc1c5ea4c31d8ebb4512bb55fcd177ce9f4e 100644 (file)
@@ -777,6 +777,8 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
        __u32 mtu;
        int err;
 
+       memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+
        if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
                encap_limit = t->parms.encap_limit;
 
index 137fca42aaa6bb809d46e7809b240d8810d89a04..6c5dfec7a3779601eb760eeeb975ae5e6db00bb7 100644 (file)
@@ -1180,6 +1180,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        u8 tproto;
        int err;
 
+       memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+
        tproto = ACCESS_ONCE(t->parms.proto);
        if (tproto != IPPROTO_IPIP && tproto != 0)
                return -1;
index 5ee56d0a8699e22434d5ad8b4380f890fa8d2126..d64ee7e8366492a439ab70ea7487bd3669800097 100644 (file)
@@ -1574,9 +1574,8 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
                return NULL;
 
        skb->priority = TC_PRIO_CONTROL;
-       skb->reserved_tailroom = skb_end_offset(skb) -
-                                min(mtu, skb_end_offset(skb));
        skb_reserve(skb, hlen);
+       skb_tailroom_reserve(skb, mtu, tlen);
 
        if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
                /* <draft-ietf-magma-mld-source-05.txt>:
index 2906ef20795e4ce2365011128c5eb9bfbcc9bdca..aae3e5ca63ea9a9a7b7822d3905330562a5d8a3c 100644 (file)
@@ -41,8 +41,7 @@ static __u16 const msstab[] = {
        9000 - 60,
 };
 
-static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS],
-                     ipv6_cookie_scratch);
+static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], ipv6_cookie_scratch);
 
 static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr,
                       __be16 sport, __be16 dport, u32 count, int c)
index 22e28a44e3c88c6e52ff59ea1c7dd8a3e964e701..422dd014aa2ce9b27263eed4612ff156271d982f 100644 (file)
@@ -962,11 +962,9 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
                ret = udpv6_queue_rcv_skb(sk, skb);
                sock_put(sk);
 
-               /* a return value > 0 means to resubmit the input, but
-                * it wants the return to be -protocol, or 0
-                */
+               /* a return value > 0 means to resubmit the input */
                if (ret > 0)
-                       return -ret;
+                       return ret;
 
                return 0;
        }
index 10ad4ac1fa0ba8ebd04e793595fab47d326194ce..367784be5df20f26fd3940c4608f1ea715bfddd6 100644 (file)
@@ -291,7 +291,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta,
        }
 
        /* prepare A-MPDU MLME for Rx aggregation */
-       tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
+       tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
        if (!tid_agg_rx)
                goto end;
 
index b84f6aa32c0831ce200f286af2ecd947ef0fefde..f006f4a44c0e6fbcdec025dcaa5450d194403bd9 100644 (file)
@@ -92,7 +92,7 @@ struct ieee80211_fragment_entry {
        u16 extra_len;
        u16 last_frag;
        u8 rx_queue;
-       bool ccmp; /* Whether fragments were encrypted with CCMP */
+       bool check_sequential_pn; /* needed for CCMP/GCMP */
        u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
 };
 
index 3ece7d1034c81ae8749cada074fbebecbe06d57f..b54f398cda5d0e2d561f2383f1d049a5410fcf68 100644 (file)
@@ -711,7 +711,7 @@ static u32 minstrel_get_expected_throughput(void *priv_sta)
         * computing cur_tp
         */
        tmp_mrs = &mi->r[idx].stats;
-       tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma);
+       tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10;
        tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024;
 
        return tmp_cur_tp;
index 3928dbd24e257e68627aa977cc54a19aaa996339..370d677b547b2aa2591bea4302e4994bddfe2649 100644 (file)
@@ -414,15 +414,16 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
            (max_tp_group != MINSTREL_CCK_GROUP))
                return;
 
+       max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
+       max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
+       max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma;
+
        if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) {
                cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx,
                                                    mrs->prob_ewma);
                if (cur_tp_avg > tmp_tp_avg)
                        mi->max_prob_rate = index;
 
-               max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES;
-               max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES;
-               max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma;
                max_gpr_tp_avg = minstrel_ht_get_tp_avg(mi, max_gpr_group,
                                                        max_gpr_idx,
                                                        max_gpr_prob);
@@ -431,7 +432,7 @@ minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
        } else {
                if (mrs->prob_ewma > tmp_prob)
                        mi->max_prob_rate = index;
-               if (mrs->prob_ewma > mg->rates[mg->max_group_prob_rate].prob_ewma)
+               if (mrs->prob_ewma > max_gpr_prob)
                        mg->max_group_prob_rate = index;
        }
 }
@@ -691,7 +692,7 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb)
        if (likely(sta->ampdu_mlme.tid_tx[tid]))
                return;
 
-       ieee80211_start_tx_ba_session(pubsta, tid, 5000);
+       ieee80211_start_tx_ba_session(pubsta, tid, 0);
 }
 
 static void
@@ -871,7 +872,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
         *  - if station is in dynamic SMPS (and streams > 1)
         *  - for fallback rates, to increase chances of getting through
         */
-       if (offset > 0 &&
+       if (offset > 0 ||
            (mi->sta->smps_mode == IEEE80211_SMPS_DYNAMIC &&
             group->streams > 1)) {
                ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
@@ -1334,7 +1335,8 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
        prob = mi->groups[i].rates[j].prob_ewma;
 
        /* convert tp_avg from pkt per second in kbps */
-       tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * AVG_PKT_SIZE * 8 / 1024;
+       tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10;
+       tp_avg = tp_avg * AVG_PKT_SIZE * 8 / 1024;
 
        return tp_avg;
 }
index bc081850ac0e5538241bd1cab37b65aeefd2c244..60d093f40f1d16de32b1bb962b25ddb12f9a1b72 100644 (file)
@@ -1753,7 +1753,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
        entry->seq = seq;
        entry->rx_queue = rx_queue;
        entry->last_frag = frag;
-       entry->ccmp = 0;
+       entry->check_sequential_pn = false;
        entry->extra_len = 0;
 
        return entry;
@@ -1849,15 +1849,27 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                                                 rx->seqno_idx, &(rx->skb));
                if (rx->key &&
                    (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
-                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) &&
+                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
+                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
+                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
                    ieee80211_has_protected(fc)) {
                        int queue = rx->security_idx;
-                       /* Store CCMP PN so that we can verify that the next
-                        * fragment has a sequential PN value. */
-                       entry->ccmp = 1;
+
+                       /* Store CCMP/GCMP PN so that we can verify that the
+                        * next fragment has a sequential PN value.
+                        */
+                       entry->check_sequential_pn = true;
                        memcpy(entry->last_pn,
                               rx->key->u.ccmp.rx_pn[queue],
                               IEEE80211_CCMP_PN_LEN);
+                       BUILD_BUG_ON(offsetof(struct ieee80211_key,
+                                             u.ccmp.rx_pn) !=
+                                    offsetof(struct ieee80211_key,
+                                             u.gcmp.rx_pn));
+                       BUILD_BUG_ON(sizeof(rx->key->u.ccmp.rx_pn[queue]) !=
+                                    sizeof(rx->key->u.gcmp.rx_pn[queue]));
+                       BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
+                                    IEEE80211_GCMP_PN_LEN);
                }
                return RX_QUEUED;
        }
@@ -1872,15 +1884,21 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                return RX_DROP_MONITOR;
        }
 
-       /* Verify that MPDUs within one MSDU have sequential PN values.
-        * (IEEE 802.11i, 8.3.3.4.5) */
-       if (entry->ccmp) {
+       /* "The receiver shall discard MSDUs and MMPDUs whose constituent
+        *  MPDU PN values are not incrementing in steps of 1."
+        * see IEEE P802.11-REVmc/D5.0, 12.5.3.4.4, item d (for CCMP)
+        * and IEEE P802.11-REVmc/D5.0, 12.5.5.4.4, item d (for GCMP)
+        */
+       if (entry->check_sequential_pn) {
                int i;
                u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
                int queue;
+
                if (!rx->key ||
                    (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
-                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256))
+                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
+                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
+                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
                        return RX_DROP_UNUSABLE;
                memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
                for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
@@ -3366,6 +3384,7 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
                                return false;
                        /* ignore action frames to TDLS-peers */
                        if (ieee80211_is_action(hdr->frame_control) &&
+                           !is_broadcast_ether_addr(bssid) &&
                            !ether_addr_equal(bssid, hdr->addr1))
                                return false;
                }
index 5a14e6d6a926a76a98ca71b1fae5ed6c59b5cbdb..616f21f4e7d7c9f9987c1a0206bab68e589040d7 100644 (file)
@@ -42,8 +42,8 @@ struct rds_page_remainder {
        unsigned long   r_offset;
 };
 
-static DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_page_remainder,
-                                    rds_page_remainders);
+static
+DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_page_remainder, rds_page_remainders);
 
 /*
  * returns 0 on success or -errno on failure.
index d05869646515dbabeb352361c9d58b9ccfc687d5..6b70399ab78121e723efc439b27122f18b52a206 100644 (file)
@@ -62,6 +62,7 @@ static void ipt_destroy_target(struct xt_entry_target *t)
        struct xt_tgdtor_param par = {
                .target   = t->u.kernel.target,
                .targinfo = t->data,
+               .family   = NFPROTO_IPV4,
        };
        if (par.target->destroy != NULL)
                par.target->destroy(&par);
@@ -195,6 +196,7 @@ static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
        par.hooknum  = ipt->tcfi_hook;
        par.target   = ipt->tcfi_t->u.kernel.target;
        par.targinfo = ipt->tcfi_t->data;
+       par.family   = NFPROTO_IPV4;
        ret = par.target->target(skb, &par);
 
        switch (ret) {
index ec529121f38a03c4b3e2317249cd0694fd619d3f..ce46f1c7f133ad5b114e4c2cd571d26c2b9ee901 100644 (file)
@@ -526,6 +526,8 @@ static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
                }
                return 0;
        }
+       if (addr1->v6.sin6_port != addr2->v6.sin6_port)
+               return 0;
        if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr))
                return 0;
        /* If this is a linklocal address, compare the scope_id. */
index ded7d931a6a5b218c7bbd4481acdea1d2bc29325..963dffcc2618b0fa5d186460bf12960c21f9babe 100644 (file)
@@ -482,7 +482,7 @@ static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
 static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
 {
        struct sctp_association *assoc;
-       struct sctp_transport *tsp;
+       struct sctp_transport *transport, *tsp;
 
        if (v == SEQ_START_TOKEN) {
                seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
@@ -490,10 +490,10 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
                return 0;
        }
 
-       tsp = (struct sctp_transport *)v;
-       if (!sctp_transport_hold(tsp))
+       transport = (struct sctp_transport *)v;
+       if (!sctp_transport_hold(transport))
                return 0;
-       assoc = tsp->asoc;
+       assoc = transport->asoc;
 
        list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
                                transports) {
@@ -546,7 +546,7 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
                seq_printf(seq, "\n");
        }
 
-       sctp_transport_put(tsp);
+       sctp_transport_put(transport);
 
        return 0;
 }
index 2b32fd602669f1fbc1aa96d61ad076fe688713e1..273bc3a35425ba99351eedb3f99244f0f9c07ab7 100644 (file)
@@ -1225,7 +1225,7 @@ int qword_get(char **bpp, char *dest, int bufsize)
        if (bp[0] == '\\' && bp[1] == 'x') {
                /* HEX STRING */
                bp += 2;
-               while (len < bufsize) {
+               while (len < bufsize - 1) {
                        int h, l;
 
                        h = hex_to_bin(bp[0]);
index 47f7da58a7f0e93e3ffd632396a5a8db65c7f7c3..8b5833c1ff2e8695030587749c8c72d86d334323 100644 (file)
@@ -1093,8 +1093,11 @@ int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
                .cb = cb,
                .idx = idx,
        };
+       int err;
 
-       switchdev_port_obj_dump(dev, &dump.fdb.obj, switchdev_port_fdb_dump_cb);
+       err = switchdev_port_obj_dump(dev, &dump.fdb.obj,
+                                     switchdev_port_fdb_dump_cb);
+       cb->args[1] = err;
        return dump.idx;
 }
 EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump);
index 69c29050f14abe8c926db671dfa05c96f2ddc3bc..4d420bb273960cd6eac206753f25435970f2724d 100644 (file)
@@ -673,7 +673,7 @@ static int tipc_sendmcast(struct  socket *sock, struct tipc_name_seq *seq,
        struct tipc_sock *tsk = tipc_sk(sk);
        struct net *net = sock_net(sk);
        struct tipc_msg *mhdr = &tsk->phdr;
-       struct sk_buff_head *pktchain = &sk->sk_write_queue;
+       struct sk_buff_head pktchain;
        struct iov_iter save = msg->msg_iter;
        uint mtu;
        int rc;
@@ -687,14 +687,16 @@ static int tipc_sendmcast(struct  socket *sock, struct tipc_name_seq *seq,
        msg_set_nameupper(mhdr, seq->upper);
        msg_set_hdr_sz(mhdr, MCAST_H_SIZE);
 
+       skb_queue_head_init(&pktchain);
+
 new_mtu:
        mtu = tipc_bcast_get_mtu(net);
-       rc = tipc_msg_build(mhdr, msg, 0, dsz, mtu, pktchain);
+       rc = tipc_msg_build(mhdr, msg, 0, dsz, mtu, &pktchain);
        if (unlikely(rc < 0))
                return rc;
 
        do {
-               rc = tipc_bcast_xmit(net, pktchain);
+               rc = tipc_bcast_xmit(net, &pktchain);
                if (likely(!rc))
                        return dsz;
 
@@ -704,7 +706,7 @@ new_mtu:
                        if (!rc)
                                continue;
                }
-               __skb_queue_purge(pktchain);
+               __skb_queue_purge(&pktchain);
                if (rc == -EMSGSIZE) {
                        msg->msg_iter = save;
                        goto new_mtu;
@@ -863,7 +865,7 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz)
        struct net *net = sock_net(sk);
        struct tipc_msg *mhdr = &tsk->phdr;
        u32 dnode, dport;
-       struct sk_buff_head *pktchain = &sk->sk_write_queue;
+       struct sk_buff_head pktchain;
        struct sk_buff *skb;
        struct tipc_name_seq *seq;
        struct iov_iter save;
@@ -924,17 +926,18 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz)
                msg_set_hdr_sz(mhdr, BASIC_H_SIZE);
        }
 
+       skb_queue_head_init(&pktchain);
        save = m->msg_iter;
 new_mtu:
        mtu = tipc_node_get_mtu(net, dnode, tsk->portid);
-       rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, pktchain);
+       rc = tipc_msg_build(mhdr, m, 0, dsz, mtu, &pktchain);
        if (rc < 0)
                return rc;
 
        do {
-               skb = skb_peek(pktchain);
+               skb = skb_peek(&pktchain);
                TIPC_SKB_CB(skb)->wakeup_pending = tsk->link_cong;
-               rc = tipc_node_xmit(net, pktchain, dnode, tsk->portid);
+               rc = tipc_node_xmit(net, &pktchain, dnode, tsk->portid);
                if (likely(!rc)) {
                        if (sock->state != SS_READY)
                                sock->state = SS_CONNECTING;
@@ -946,7 +949,7 @@ new_mtu:
                        if (!rc)
                                continue;
                }
-               __skb_queue_purge(pktchain);
+               __skb_queue_purge(&pktchain);
                if (rc == -EMSGSIZE) {
                        m->msg_iter = save;
                        goto new_mtu;
@@ -1016,7 +1019,7 @@ static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
        struct net *net = sock_net(sk);
        struct tipc_sock *tsk = tipc_sk(sk);
        struct tipc_msg *mhdr = &tsk->phdr;
-       struct sk_buff_head *pktchain = &sk->sk_write_queue;
+       struct sk_buff_head pktchain;
        DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name);
        u32 portid = tsk->portid;
        int rc = -EINVAL;
@@ -1044,17 +1047,19 @@ static int __tipc_send_stream(struct socket *sock, struct msghdr *m, size_t dsz)
 
        timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
        dnode = tsk_peer_node(tsk);
+       skb_queue_head_init(&pktchain);
 
 next:
        save = m->msg_iter;
        mtu = tsk->max_pkt;
        send = min_t(uint, dsz - sent, TIPC_MAX_USER_MSG_SIZE);
-       rc = tipc_msg_build(mhdr, m, sent, send, mtu, pktchain);
+       rc = tipc_msg_build(mhdr, m, sent, send, mtu, &pktchain);
        if (unlikely(rc < 0))
                return rc;
+
        do {
                if (likely(!tsk_conn_cong(tsk))) {
-                       rc = tipc_node_xmit(net, pktchain, dnode, portid);
+                       rc = tipc_node_xmit(net, &pktchain, dnode, portid);
                        if (likely(!rc)) {
                                tsk->sent_unacked++;
                                sent += send;
@@ -1063,7 +1068,7 @@ next:
                                goto next;
                        }
                        if (rc == -EMSGSIZE) {
-                               __skb_queue_purge(pktchain);
+                               __skb_queue_purge(&pktchain);
                                tsk->max_pkt = tipc_node_get_mtu(net, dnode,
                                                                 portid);
                                m->msg_iter = save;
@@ -1077,7 +1082,7 @@ next:
                rc = tipc_wait_for_sndpkt(sock, &timeo);
        } while (!rc);
 
-       __skb_queue_purge(pktchain);
+       __skb_queue_purge(&pktchain);
        return sent ? sent : rc;
 }
 
index 69ee2eeef968851192035cb166410f1f37e7722f..f9ff73a8d8154ff0a52f8c33a64077f5d8c57ae5 100644 (file)
@@ -296,7 +296,8 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid,
        if (tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscrb, &sub))
                return tipc_conn_terminate(tn->topsrv, subscrb->conid);
 
-       tipc_nametbl_subscribe(sub);
+       if (sub)
+               tipc_nametbl_subscribe(sub);
 }
 
 /* Handle one request to establish a new subscriber */
index b0915515640efed1ff4795103c0572aba48c38f4..8f0bac7e03c406466e0b5ca2b01b3ca2574ab79f 100644 (file)
@@ -1147,6 +1147,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                return NOTIFY_DONE;
        }
 
+       wireless_nlevent_flush();
+
        return NOTIFY_OK;
 }
 
index d4786f2802aa3c94f0a9bfcba846c98ec5b2b249..711cb7ad6ae011132b868d928ebe23037040db82 100644 (file)
@@ -7547,7 +7547,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 
                if ((ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) &&
                    no_ht) {
-                       kfree(connkeys);
+                       kzfree(connkeys);
                        return -EINVAL;
                }
        }
index 8020b5b094d4c8fba0c0f2431f8af7d8ecc40dca..d49ed7666d4cb3e5a20641ebc0acfd3ccda80ff9 100644 (file)
@@ -917,6 +917,12 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
 
        nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
 
+       /* stop critical protocol if supported */
+       if (rdev->ops->crit_proto_stop && rdev->crit_proto_nlportid) {
+               rdev->crit_proto_nlportid = 0;
+               rdev_crit_proto_stop(rdev, wdev);
+       }
+
        /*
         * Delete all the keys ... pairwise keys can't really
         * exist any more anyway, but default keys might.
index c8717c1d082e702f9b071c480e873b408b400daf..b50ee5d622e14d4fb486ce0c533757e958702f54 100644 (file)
@@ -342,6 +342,40 @@ static const int compat_event_type_size[] = {
 
 /* IW event code */
 
+void wireless_nlevent_flush(void)
+{
+       struct sk_buff *skb;
+       struct net *net;
+
+       ASSERT_RTNL();
+
+       for_each_net(net) {
+               while ((skb = skb_dequeue(&net->wext_nlevents)))
+                       rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
+                                   GFP_KERNEL);
+       }
+}
+EXPORT_SYMBOL_GPL(wireless_nlevent_flush);
+
+static int wext_netdev_notifier_call(struct notifier_block *nb,
+                                    unsigned long state, void *ptr)
+{
+       /*
+        * When a netdev changes state in any way, flush all pending messages
+        * to avoid them going out in a strange order, e.g. RTM_NEWLINK after
+        * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close()
+        * or similar - all of which could otherwise happen due to delays from
+        * schedule_work().
+        */
+       wireless_nlevent_flush();
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block wext_netdev_notifier = {
+       .notifier_call = wext_netdev_notifier_call,
+};
+
 static int __net_init wext_pernet_init(struct net *net)
 {
        skb_queue_head_init(&net->wext_nlevents);
@@ -360,7 +394,12 @@ static struct pernet_operations wext_pernet_ops = {
 
 static int __init wireless_nlevent_init(void)
 {
-       return register_pernet_subsys(&wext_pernet_ops);
+       int err = register_pernet_subsys(&wext_pernet_ops);
+
+       if (err)
+               return err;
+
+       return register_netdevice_notifier(&wext_netdev_notifier);
 }
 
 subsys_initcall(wireless_nlevent_init);
@@ -368,17 +407,8 @@ subsys_initcall(wireless_nlevent_init);
 /* Process events generated by the wireless layer or the driver. */
 static void wireless_nlevent_process(struct work_struct *work)
 {
-       struct sk_buff *skb;
-       struct net *net;
-
        rtnl_lock();
-
-       for_each_net(net) {
-               while ((skb = skb_dequeue(&net->wext_nlevents)))
-                       rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
-                                   GFP_KERNEL);
-       }
-
+       wireless_nlevent_flush();
        rtnl_unlock();
 }
 
index 0147c91fa549e6ab46b68c47b46425b272c37571..d574d13ba96395ffa0c3a73b9ce669ba42e6a5a3 100755 (executable)
@@ -269,7 +269,8 @@ our $Sparse = qr{
                        __init_refok|
                        __kprobes|
                        __ref|
-                       __rcu
+                       __rcu|
+                       __private
                }x;
 our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
 our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
@@ -3239,6 +3240,30 @@ sub process {
 #ignore lines not being added
                next if ($line =~ /^[^\+]/);
 
+# check for declarations of signed or unsigned without int
+               while ($line =~ m{($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) {
+                       my $type = $1;
+                       my $var = $2;
+                       $var = "" if (!defined $var);
+                       if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) {
+                               my $sign = $1;
+                               my $pointer = $2;
+
+                               $pointer = "" if (!defined $pointer);
+
+                               if (WARN("UNSPECIFIED_INT",
+                                        "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) &&
+                                   $fix) {
+                                       my $decl = trim($sign) . " int ";
+                                       my $comp_pointer = $pointer;
+                                       $comp_pointer =~ s/\s//g;
+                                       $decl .= $comp_pointer;
+                                       $decl = rtrim($decl) if ($var eq "");
+                                       $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@;
+                               }
+                       }
+               }
+
 # TEST: allow direct testing of the type matcher.
                if ($dbg_type) {
                        if ($line =~ /^.\s*$Declare\s*$/) {
@@ -4108,7 +4133,7 @@ sub process {
 ##             }
 
 #need space before brace following if, while, etc
-               if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\){/) ||
+               if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
                    $line =~ /do\{/) {
                        if (ERROR("SPACING",
                                  "space required before the open brace '{'\n" . $herecurr) &&
@@ -4560,6 +4585,9 @@ sub process {
                        {
                        }
 
+                       # Make asm volatile uses seem like a generic function
+                       $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g;
+
                        my $exceptions = qr{
                                $Declare|
                                module_param_named|
index 8fa81e84e29510c053e5e52cefc5eb9e1da16887..638b143ee60f4246cc16d67936bc62095a66c646 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <limits.h>
 
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
@@ -34,6 +35,7 @@ struct sym_entry {
        unsigned int len;
        unsigned int start_pos;
        unsigned char *sym;
+       unsigned int percpu_absolute;
 };
 
 struct addr_range {
@@ -42,6 +44,7 @@ struct addr_range {
 };
 
 static unsigned long long _text;
+static unsigned long long relative_base;
 static struct addr_range text_ranges[] = {
        { "_stext",     "_etext"     },
        { "_sinittext", "_einittext" },
@@ -61,6 +64,7 @@ static int all_symbols = 0;
 static int absolute_percpu = 0;
 static char symbol_prefix_char = '\0';
 static unsigned long long kernel_start_addr = 0;
+static int base_relative = 0;
 
 int token_profit[0x10000];
 
@@ -74,7 +78,7 @@ static void usage(void)
        fprintf(stderr, "Usage: kallsyms [--all-symbols] "
                        "[--symbol-prefix=<prefix char>] "
                        "[--page-offset=<CONFIG_PAGE_OFFSET>] "
-                       "< in.map > out.S\n");
+                       "[--base-relative] < in.map > out.S\n");
        exit(1);
 }
 
@@ -171,6 +175,8 @@ static int read_symbol(FILE *in, struct sym_entry *s)
        strcpy((char *)s->sym + 1, str);
        s->sym[0] = stype;
 
+       s->percpu_absolute = 0;
+
        /* Record if we've found __per_cpu_start/end. */
        check_symbol_range(sym, s->addr, &percpu_range, 1);
 
@@ -202,6 +208,8 @@ static int symbol_valid(struct sym_entry *s)
         */
        static char *special_symbols[] = {
                "kallsyms_addresses",
+               "kallsyms_offsets",
+               "kallsyms_relative_base",
                "kallsyms_num_syms",
                "kallsyms_names",
                "kallsyms_markers",
@@ -325,7 +333,7 @@ static int expand_symbol(unsigned char *data, int len, char *result)
 
 static int symbol_absolute(struct sym_entry *s)
 {
-       return toupper(s->sym[0]) == 'A';
+       return s->percpu_absolute;
 }
 
 static void write_src(void)
@@ -346,16 +354,48 @@ static void write_src(void)
 
        printf("\t.section .rodata, \"a\"\n");
 
-       /* Provide proper symbols relocatability by their '_text'
-        * relativeness.  The symbol names cannot be used to construct
-        * normal symbol references as the list of symbols contains
-        * symbols that are declared static and are private to their
-        * .o files.  This prevents .tmp_kallsyms.o or any other
-        * object from referencing them.
+       /* Provide proper symbols relocatability by their relativeness
+        * to a fixed anchor point in the runtime image, either '_text'
+        * for absolute address tables, in which case the linker will
+        * emit the final addresses at build time. Otherwise, use the
+        * offset relative to the lowest value encountered of all relative
+        * symbols, and emit non-relocatable fixed offsets that will be fixed
+        * up at runtime.
+        *
+        * The symbol names cannot be used to construct normal symbol
+        * references as the list of symbols contains symbols that are
+        * declared static and are private to their .o files.  This prevents
+        * .tmp_kallsyms.o or any other object from referencing them.
         */
-       output_label("kallsyms_addresses");
+       if (!base_relative)
+               output_label("kallsyms_addresses");
+       else
+               output_label("kallsyms_offsets");
+
        for (i = 0; i < table_cnt; i++) {
-               if (!symbol_absolute(&table[i])) {
+               if (base_relative) {
+                       long long offset;
+                       int overflow;
+
+                       if (!absolute_percpu) {
+                               offset = table[i].addr - relative_base;
+                               overflow = (offset < 0 || offset > UINT_MAX);
+                       } else if (symbol_absolute(&table[i])) {
+                               offset = table[i].addr;
+                               overflow = (offset < 0 || offset > INT_MAX);
+                       } else {
+                               offset = relative_base - table[i].addr - 1;
+                               overflow = (offset < INT_MIN || offset >= 0);
+                       }
+                       if (overflow) {
+                               fprintf(stderr, "kallsyms failure: "
+                                       "%s symbol value %#llx out of range in relative mode\n",
+                                       symbol_absolute(&table[i]) ? "absolute" : "relative",
+                                       table[i].addr);
+                               exit(EXIT_FAILURE);
+                       }
+                       printf("\t.long\t%#x\n", (int)offset);
+               } else if (!symbol_absolute(&table[i])) {
                        if (_text <= table[i].addr)
                                printf("\tPTR\t_text + %#llx\n",
                                        table[i].addr - _text);
@@ -368,6 +408,12 @@ static void write_src(void)
        }
        printf("\n");
 
+       if (base_relative) {
+               output_label("kallsyms_relative_base");
+               printf("\tPTR\t_text - %#llx\n", _text - relative_base);
+               printf("\n");
+       }
+
        output_label("kallsyms_num_syms");
        printf("\tPTR\t%d\n", table_cnt);
        printf("\n");
@@ -681,8 +727,27 @@ static void make_percpus_absolute(void)
        unsigned int i;
 
        for (i = 0; i < table_cnt; i++)
-               if (symbol_in_range(&table[i], &percpu_range, 1))
+               if (symbol_in_range(&table[i], &percpu_range, 1)) {
+                       /*
+                        * Keep the 'A' override for percpu symbols to
+                        * ensure consistent behavior compared to older
+                        * versions of this tool.
+                        */
                        table[i].sym[0] = 'A';
+                       table[i].percpu_absolute = 1;
+               }
+}
+
+/* find the minimum non-absolute symbol address */
+static void record_relative_base(void)
+{
+       unsigned int i;
+
+       relative_base = -1ULL;
+       for (i = 0; i < table_cnt; i++)
+               if (!symbol_absolute(&table[i]) &&
+                   table[i].addr < relative_base)
+                       relative_base = table[i].addr;
 }
 
 int main(int argc, char **argv)
@@ -703,7 +768,9 @@ int main(int argc, char **argv)
                        } else if (strncmp(argv[i], "--page-offset=", 14) == 0) {
                                const char *p = &argv[i][14];
                                kernel_start_addr = strtoull(p, NULL, 16);
-                       } else
+                       } else if (strcmp(argv[i], "--base-relative") == 0)
+                               base_relative = 1;
+                       else
                                usage();
                }
        } else if (argc != 1)
@@ -712,6 +779,8 @@ int main(int argc, char **argv)
        read_map(stdin);
        if (absolute_percpu)
                make_percpus_absolute();
+       if (base_relative)
+               record_relative_base();
        sort_symbols();
        optimize_token_table();
        write_src();
index d154f0877fd806a93d234e6d4288da27d6c5d09f..7bfe9fa1c8dc6db8d6c4415fbf0d26e66477e42e 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/awk -f
 # extract linker version number from stdin and turn into single number
        {
-       gsub(".*)", "");
+       gsub(".*\\)", "");
        gsub(".*version ", "");
        gsub("-.*", "");
        split($1,a, ".");
index ba6c34ea5429535cd303b1aa1d6ebd6ae30dd912..453ede9d2f3db672e9f36f62c7edbf1bc58f9e3b 100755 (executable)
@@ -86,10 +86,14 @@ kallsyms()
                kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
        fi
 
-       if [ -n "${CONFIG_X86_64}" ]; then
+       if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then
                kallsymopt="${kallsymopt} --absolute-percpu"
        fi
 
+       if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then
+               kallsymopt="${kallsymopt} --base-relative"
+       fi
+
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
                      ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}"
 
index a71be6b7cdec5b11a8644132f75819941dd2d3c7..9f3c9d47a4a5d89c4e95de825f67d84b0258f0df 100755 (executable)
@@ -117,6 +117,8 @@ my %nameexception = (
     'kallsyms_names'   => 1,
     'kallsyms_num_syms'        => 1,
     'kallsyms_addresses'=> 1,
+    'kallsyms_offsets' => 1,
+    'kallsyms_relative_base'=> 1,
     '__this_module'    => 1,
     '_etext'           => 1,
     '_edata'           => 1,
index c2423d913b46bd0e659ea4d4c057a3af6119c2d4..7b29fb14f870283ae4174e34643640150f7e098b 100644 (file)
@@ -209,6 +209,35 @@ static int compare_relative_table(const void *a, const void *b)
        return 0;
 }
 
+static void x86_sort_relative_table(char *extab_image, int image_size)
+{
+       int i;
+
+       i = 0;
+       while (i < image_size) {
+               uint32_t *loc = (uint32_t *)(extab_image + i);
+
+               w(r(loc) + i, loc);
+               w(r(loc + 1) + i + 4, loc + 1);
+               w(r(loc + 2) + i + 8, loc + 2);
+
+               i += sizeof(uint32_t) * 3;
+       }
+
+       qsort(extab_image, image_size / 12, 12, compare_relative_table);
+
+       i = 0;
+       while (i < image_size) {
+               uint32_t *loc = (uint32_t *)(extab_image + i);
+
+               w(r(loc) - i, loc);
+               w(r(loc + 1) - (i + 4), loc + 1);
+               w(r(loc + 2) - (i + 8), loc + 2);
+
+               i += sizeof(uint32_t) * 3;
+       }
+}
+
 static void sort_relative_table(char *extab_image, int image_size)
 {
        int i;
@@ -281,6 +310,9 @@ do_file(char const *const fname)
                break;
        case EM_386:
        case EM_X86_64:
+               custom_sort = x86_sort_relative_table;
+               break;
+
        case EM_S390:
                custom_sort = sort_relative_table;
                break;
index f8110cfd80ff64bf05ef428f03dff935e6d704c4..f1ab71504e1d59e1c6aaa7c0d22870e371ec85b3 100644 (file)
@@ -3249,7 +3249,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
 
 static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
 {
-       struct inode_security_struct *isec = inode_security(inode);
+       struct inode_security_struct *isec = inode_security_novalidate(inode);
        *secid = isec->sid;
 }
 
index e9b98af6b52c83faecccd4cc1011286a75560849..e8da3b8ee7213352426023029fcff04e87659d50 100644 (file)
@@ -141,10 +141,8 @@ int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
        struct vm_area_struct *vma)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
-       return dma_mmap_writecombine(substream->pcm->card->dev, vma,
-                                    runtime->dma_area,
-                                    runtime->dma_addr,
-                                    runtime->dma_bytes);
+       return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
+                          runtime->dma_addr, runtime->dma_bytes);
 }
 EXPORT_SYMBOL(pxa2xx_pcm_mmap);
 
@@ -156,8 +154,7 @@ int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
        buf->dev.type = SNDRV_DMA_TYPE_DEV;
        buf->dev.dev = pcm->card->dev;
        buf->private_data = NULL;
-       buf->area = dma_alloc_writecombine(pcm->card->dev, size,
-                                          &buf->addr, GFP_KERNEL);
+       buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
        if (!buf->area)
                return -ENOMEM;
        buf->bytes = size;
@@ -178,8 +175,7 @@ void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
                buf = &substream->dma_buffer;
                if (!buf->area)
                        continue;
-               dma_free_writecombine(pcm->card->dev, buf->bytes,
-                                     buf->area, buf->addr);
+               dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
                buf->area = NULL;
        }
 }
index b9c0910fb8c4ead97559c7f9c1737e76b2d5cf7f..0608f216f3592fc597c85c2c92594b891e499647 100644 (file)
@@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 {
         unsigned char reserved[128];
 };
 
+#ifdef CONFIG_X86_X32
+/* x32 has a different alignment for 64bit values from ia32 */
+struct snd_ctl_elem_value_x32 {
+       struct snd_ctl_elem_id id;
+       unsigned int indirect;  /* bit-field causes misalignment */
+       union {
+               s32 integer[128];
+               unsigned char data[512];
+               s64 integer64[64];
+       } value;
+       unsigned char reserved[128];
+};
+#endif /* CONFIG_X86_X32 */
 
 /* get the value type and count of the control */
 static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
@@ -219,9 +232,11 @@ static int get_elem_size(int type, int count)
 
 static int copy_ctl_value_from_user(struct snd_card *card,
                                    struct snd_ctl_elem_value *data,
-                                   struct snd_ctl_elem_value32 __user *data32,
+                                   void __user *userdata,
+                                   void __user *valuep,
                                    int *typep, int *countp)
 {
+       struct snd_ctl_elem_value32 __user *data32 = userdata;
        int i, type, size;
        int uninitialized_var(count);
        unsigned int indirect;
@@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card,
        if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
            type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                for (i = 0; i < count; i++) {
+                       s32 __user *intp = valuep;
                        int val;
-                       if (get_user(val, &data32->value.integer[i]))
+                       if (get_user(val, &intp[i]))
                                return -EFAULT;
                        data->value.integer.value[i] = val;
                }
@@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card,
                        dev_err(card->dev, "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
                        return -EINVAL;
                }
-               if (copy_from_user(data->value.bytes.data,
-                                  data32->value.data, size))
+               if (copy_from_user(data->value.bytes.data, valuep, size))
                        return -EFAULT;
        }
 
@@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card,
 }
 
 /* restore the value to 32bit */
-static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
+static int copy_ctl_value_to_user(void __user *userdata,
+                                 void __user *valuep,
                                  struct snd_ctl_elem_value *data,
                                  int type, int count)
 {
@@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
        if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
            type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
                for (i = 0; i < count; i++) {
+                       s32 __user *intp = valuep;
                        int val;
                        val = data->value.integer.value[i];
-                       if (put_user(val, &data32->value.integer[i]))
+                       if (put_user(val, &intp[i]))
                                return -EFAULT;
                }
        } else {
                size = get_elem_size(type, count);
-               if (copy_to_user(data32->value.data,
-                                data->value.bytes.data, size))
+               if (copy_to_user(valuep, data->value.bytes.data, size))
                        return -EFAULT;
        }
        return 0;
 }
 
-static int snd_ctl_elem_read_user_compat(struct snd_card *card, 
-                                        struct snd_ctl_elem_value32 __user *data32)
+static int ctl_elem_read_user(struct snd_card *card,
+                             void __user *userdata, void __user *valuep)
 {
        struct snd_ctl_elem_value *data;
        int err, type, count;
@@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
        if (data == NULL)
                return -ENOMEM;
 
-       if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
+       err = copy_ctl_value_from_user(card, data, userdata, valuep,
+                                      &type, &count);
+       if (err < 0)
                goto error;
 
        snd_power_lock(card);
@@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card *card,
                err = snd_ctl_elem_read(card, data);
        snd_power_unlock(card);
        if (err >= 0)
-               err = copy_ctl_value_to_user(data32, data, type, count);
+               err = copy_ctl_value_to_user(userdata, valuep, data,
+                                            type, count);
  error:
        kfree(data);
        return err;
 }
 
-static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
-                                         struct snd_ctl_elem_value32 __user *data32)
+static int ctl_elem_write_user(struct snd_ctl_file *file,
+                              void __user *userdata, void __user *valuep)
 {
        struct snd_ctl_elem_value *data;
        struct snd_card *card = file->card;
@@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
        if (data == NULL)
                return -ENOMEM;
 
-       if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
+       err = copy_ctl_value_from_user(card, data, userdata, valuep,
+                                      &type, &count);
+       if (err < 0)
                goto error;
 
        snd_power_lock(card);
@@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
                err = snd_ctl_elem_write(card, file, data);
        snd_power_unlock(card);
        if (err >= 0)
-               err = copy_ctl_value_to_user(data32, data, type, count);
+               err = copy_ctl_value_to_user(userdata, valuep, data,
+                                            type, count);
  error:
        kfree(data);
        return err;
 }
 
+static int snd_ctl_elem_read_user_compat(struct snd_card *card,
+                                        struct snd_ctl_elem_value32 __user *data32)
+{
+       return ctl_elem_read_user(card, data32, &data32->value);
+}
+
+static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
+                                         struct snd_ctl_elem_value32 __user *data32)
+{
+       return ctl_elem_write_user(file, data32, &data32->value);
+}
+
+#ifdef CONFIG_X86_X32
+static int snd_ctl_elem_read_user_x32(struct snd_card *card,
+                                     struct snd_ctl_elem_value_x32 __user *data32)
+{
+       return ctl_elem_read_user(card, data32, &data32->value);
+}
+
+static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file,
+                                      struct snd_ctl_elem_value_x32 __user *data32)
+{
+       return ctl_elem_write_user(file, data32, &data32->value);
+}
+#endif /* CONFIG_X86_X32 */
+
 /* add or replace a user control */
 static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
                                   struct snd_ctl_elem_info32 __user *data32,
@@ -393,6 +441,10 @@ enum {
        SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct snd_ctl_elem_value32),
        SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct snd_ctl_elem_info32),
        SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct snd_ctl_elem_info32),
+#ifdef CONFIG_X86_X32
+       SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct snd_ctl_elem_value_x32),
+       SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct snd_ctl_elem_value_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns
                return snd_ctl_elem_add_compat(ctl, argp, 0);
        case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
                return snd_ctl_elem_add_compat(ctl, argp, 1);
+#ifdef CONFIG_X86_X32
+       case SNDRV_CTL_IOCTL_ELEM_READ_X32:
+               return snd_ctl_elem_read_user_x32(ctl->card, argp);
+       case SNDRV_CTL_IOCTL_ELEM_WRITE_X32:
+               return snd_ctl_elem_write_user_x32(ctl, argp);
+#endif /* CONFIG_X86_X32 */
        }
 
        down_read(&snd_ioctl_rwsem);
index 9630e9f72b7ba2ad77f50a516ecc559c0c200975..1f64ab0c2a95a291638406e62daa15ad6a172db3 100644 (file)
@@ -183,6 +183,14 @@ static int snd_pcm_ioctl_channel_info_compat(struct snd_pcm_substream *substream
        return err;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has the same struct as x86-64 for snd_pcm_channel_info */
+static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
+                                    struct snd_pcm_channel_info __user *src);
+#define snd_pcm_ioctl_channel_info_x32(s, p)   \
+       snd_pcm_channel_info_user(s, p)
+#endif /* CONFIG_X86_X32 */
+
 struct snd_pcm_status32 {
        s32 state;
        struct compat_timespec trigger_tstamp;
@@ -243,6 +251,71 @@ static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
        return err;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_pcm_status_x32 {
+       s32 state;
+       u32 rsvd; /* alignment */
+       struct timespec trigger_tstamp;
+       struct timespec tstamp;
+       u32 appl_ptr;
+       u32 hw_ptr;
+       s32 delay;
+       u32 avail;
+       u32 avail_max;
+       u32 overrange;
+       s32 suspended_state;
+       u32 audio_tstamp_data;
+       struct timespec audio_tstamp;
+       struct timespec driver_tstamp;
+       u32 audio_tstamp_accuracy;
+       unsigned char reserved[52-2*sizeof(struct timespec)];
+} __packed;
+
+#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
+
+static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream,
+                                  struct snd_pcm_status_x32 __user *src,
+                                  bool ext)
+{
+       struct snd_pcm_status status;
+       int err;
+
+       memset(&status, 0, sizeof(status));
+       /*
+        * with extension, parameters are read/write,
+        * get audio_tstamp_data from user,
+        * ignore rest of status structure
+        */
+       if (ext && get_user(status.audio_tstamp_data,
+                               (u32 __user *)(&src->audio_tstamp_data)))
+               return -EFAULT;
+       err = snd_pcm_status(substream, &status);
+       if (err < 0)
+               return err;
+
+       if (clear_user(src, sizeof(*src)))
+               return -EFAULT;
+       if (put_user(status.state, &src->state) ||
+           put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
+           put_timespec(&status.tstamp, &src->tstamp) ||
+           put_user(status.appl_ptr, &src->appl_ptr) ||
+           put_user(status.hw_ptr, &src->hw_ptr) ||
+           put_user(status.delay, &src->delay) ||
+           put_user(status.avail, &src->avail) ||
+           put_user(status.avail_max, &src->avail_max) ||
+           put_user(status.overrange, &src->overrange) ||
+           put_user(status.suspended_state, &src->suspended_state) ||
+           put_user(status.audio_tstamp_data, &src->audio_tstamp_data) ||
+           put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
+           put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
+           put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
+               return -EFAULT;
+
+       return err;
+}
+#endif /* CONFIG_X86_X32 */
+
 /* both for HW_PARAMS and HW_REFINE */
 static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
                                          int refine, 
@@ -469,6 +542,93 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
        return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_pcm_mmap_status_x32 {
+       s32 state;
+       s32 pad1;
+       u32 hw_ptr;
+       u32 pad2; /* alignment */
+       struct timespec tstamp;
+       s32 suspended_state;
+       struct timespec audio_tstamp;
+} __packed;
+
+struct snd_pcm_mmap_control_x32 {
+       u32 appl_ptr;
+       u32 avail_min;
+};
+
+struct snd_pcm_sync_ptr_x32 {
+       u32 flags;
+       u32 rsvd; /* alignment */
+       union {
+               struct snd_pcm_mmap_status_x32 status;
+               unsigned char reserved[64];
+       } s;
+       union {
+               struct snd_pcm_mmap_control_x32 control;
+               unsigned char reserved[64];
+       } c;
+} __packed;
+
+static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
+                                     struct snd_pcm_sync_ptr_x32 __user *src)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       volatile struct snd_pcm_mmap_status *status;
+       volatile struct snd_pcm_mmap_control *control;
+       u32 sflags;
+       struct snd_pcm_mmap_control scontrol;
+       struct snd_pcm_mmap_status sstatus;
+       snd_pcm_uframes_t boundary;
+       int err;
+
+       if (snd_BUG_ON(!runtime))
+               return -EINVAL;
+
+       if (get_user(sflags, &src->flags) ||
+           get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+           get_user(scontrol.avail_min, &src->c.control.avail_min))
+               return -EFAULT;
+       if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
+               err = snd_pcm_hwsync(substream);
+               if (err < 0)
+                       return err;
+       }
+       status = runtime->status;
+       control = runtime->control;
+       boundary = recalculate_boundary(runtime);
+       if (!boundary)
+               boundary = 0x7fffffff;
+       snd_pcm_stream_lock_irq(substream);
+       /* FIXME: we should consider the boundary for the sync from app */
+       if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
+               control->appl_ptr = scontrol.appl_ptr;
+       else
+               scontrol.appl_ptr = control->appl_ptr % boundary;
+       if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+               control->avail_min = scontrol.avail_min;
+       else
+               scontrol.avail_min = control->avail_min;
+       sstatus.state = status->state;
+       sstatus.hw_ptr = status->hw_ptr % boundary;
+       sstatus.tstamp = status->tstamp;
+       sstatus.suspended_state = status->suspended_state;
+       sstatus.audio_tstamp = status->audio_tstamp;
+       snd_pcm_stream_unlock_irq(substream);
+       if (put_user(sstatus.state, &src->s.status.state) ||
+           put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
+           put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
+           put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+           put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) ||
+           put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+           put_user(scontrol.avail_min, &src->c.control.avail_min))
+               return -EFAULT;
+
+       return 0;
+}
+#endif /* CONFIG_X86_X32 */
 
 /*
  */
@@ -487,7 +647,12 @@ enum {
        SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct snd_xfern32),
        SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct snd_xfern32),
        SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr32),
-
+#ifdef CONFIG_X86_X32
+       SNDRV_PCM_IOCTL_CHANNEL_INFO_X32 = _IOR('A', 0x32, struct snd_pcm_channel_info),
+       SNDRV_PCM_IOCTL_STATUS_X32 = _IOR('A', 0x20, struct snd_pcm_status_x32),
+       SNDRV_PCM_IOCTL_STATUS_EXT_X32 = _IOWR('A', 0x24, struct snd_pcm_status_x32),
+       SNDRV_PCM_IOCTL_SYNC_PTR_X32 = _IOWR('A', 0x23, struct snd_pcm_sync_ptr_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -559,6 +724,16 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
                return snd_pcm_ioctl_rewind_compat(substream, argp);
        case SNDRV_PCM_IOCTL_FORWARD32:
                return snd_pcm_ioctl_forward_compat(substream, argp);
+#ifdef CONFIG_X86_X32
+       case SNDRV_PCM_IOCTL_STATUS_X32:
+               return snd_pcm_status_user_x32(substream, argp, false);
+       case SNDRV_PCM_IOCTL_STATUS_EXT_X32:
+               return snd_pcm_status_user_x32(substream, argp, true);
+       case SNDRV_PCM_IOCTL_SYNC_PTR_X32:
+               return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
+       case SNDRV_PCM_IOCTL_CHANNEL_INFO_X32:
+               return snd_pcm_ioctl_channel_info_x32(substream, argp);
+#endif /* CONFIG_X86_X32 */
        }
 
        return -ENOIOCTLCMD;
index 5268c1f58c25b7e143b5713a45dac36220558cc5..f69764d7cdd7025d3935143883c162372e3c0c7c 100644 (file)
@@ -85,8 +85,7 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
        if (err < 0)
                return err;
 
-       if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
-           put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+       if (compat_put_timespec(&status.tstamp, &src->tstamp) ||
            put_user(status.avail, &src->avail) ||
            put_user(status.xruns, &src->xruns))
                return -EFAULT;
@@ -94,9 +93,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
        return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has 64bit timespec and 64bit alignment */
+struct snd_rawmidi_status_x32 {
+       s32 stream;
+       u32 rsvd; /* alignment */
+       struct timespec tstamp;
+       u32 avail;
+       u32 xruns;
+       unsigned char reserved[16];
+} __attribute__((packed));
+
+#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
+
+static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile,
+                                       struct snd_rawmidi_status_x32 __user *src)
+{
+       int err;
+       struct snd_rawmidi_status status;
+
+       if (rfile->output == NULL)
+               return -EINVAL;
+       if (get_user(status.stream, &src->stream))
+               return -EFAULT;
+
+       switch (status.stream) {
+       case SNDRV_RAWMIDI_STREAM_OUTPUT:
+               err = snd_rawmidi_output_status(rfile->output, &status);
+               break;
+       case SNDRV_RAWMIDI_STREAM_INPUT:
+               err = snd_rawmidi_input_status(rfile->input, &status);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (err < 0)
+               return err;
+
+       if (put_timespec(&status.tstamp, &src->tstamp) ||
+           put_user(status.avail, &src->avail) ||
+           put_user(status.xruns, &src->xruns))
+               return -EFAULT;
+
+       return 0;
+}
+#endif /* CONFIG_X86_X32 */
+
 enum {
        SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32),
        SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
+#ifdef CONFIG_X86_X32
+       SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -115,6 +163,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign
                return snd_rawmidi_ioctl_params_compat(rfile, argp);
        case SNDRV_RAWMIDI_IOCTL_STATUS32:
                return snd_rawmidi_ioctl_status_compat(rfile, argp);
+#ifdef CONFIG_X86_X32
+       case SNDRV_RAWMIDI_IOCTL_STATUS_X32:
+               return snd_rawmidi_ioctl_status_x32(rfile, argp);
+#endif /* CONFIG_X86_X32 */
        }
        return -ENOIOCTLCMD;
 }
index 8db156b207f187dfc821160cf39d92a8a5521085..8cdf489df80e03ee2cd5652aec627ffa73e9fcc3 100644 (file)
@@ -149,8 +149,6 @@ odev_release(struct inode *inode, struct file *file)
        if ((dp = file->private_data) == NULL)
                return 0;
 
-       snd_seq_oss_drain_write(dp);
-
        mutex_lock(&register_mutex);
        snd_seq_oss_release(dp);
        mutex_unlock(&register_mutex);
index b43924325249c01b0cdd11fc1164572a50369f98..d7b4d016b547584ed337c6d0e29502ad1b12c5bf 100644 (file)
@@ -127,7 +127,6 @@ int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int co
 unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, poll_table * wait);
 
 void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
-void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp);
 
 /* */
 void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
index 6779e82b46dd7060bd982137ca75cfcdbbfa989e..92c96a95a903abd82ace8256b77c2c3bb99ff620 100644 (file)
@@ -435,22 +435,6 @@ snd_seq_oss_release(struct seq_oss_devinfo *dp)
 }
 
 
-/*
- * Wait until the queue is empty (if we don't have nonblock)
- */
-void
-snd_seq_oss_drain_write(struct seq_oss_devinfo *dp)
-{
-       if (! dp->timer->running)
-               return;
-       if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) &&
-           dp->writeq) {
-               while (snd_seq_oss_writeq_sync(dp->writeq))
-                       ;
-       }
-}
-
-
 /*
  * reset sequencer devices
  */
index e05802ae6e1b1e240a187a43c9f5308fcf7145c0..2e908225d754cfd4f4d23aa40abab01785351456 100644 (file)
@@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file,
                                        struct snd_timer_status32 __user *_status)
 {
        struct snd_timer_user *tu;
-       struct snd_timer_status status;
+       struct snd_timer_status32 status;
        
        tu = file->private_data;
        if (snd_BUG_ON(!tu->timeri))
                return -ENXIO;
        memset(&status, 0, sizeof(status));
-       status.tstamp = tu->tstamp;
+       status.tstamp.tv_sec = tu->tstamp.tv_sec;
+       status.tstamp.tv_nsec = tu->tstamp.tv_nsec;
        status.resolution = snd_timer_resolution(tu->timeri);
        status.lost = tu->timeri->lost;
        status.overrun = tu->overrun;
@@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file,
        return 0;
 }
 
+#ifdef CONFIG_X86_X32
+/* X32 ABI has the same struct as x86-64 */
+#define snd_timer_user_status_x32(file, s) \
+       snd_timer_user_status(file, s)
+#endif /* CONFIG_X86_X32 */
+
 /*
  */
 
 enum {
        SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
        SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
+#ifdef CONFIG_X86_X32
+       SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status),
+#endif /* CONFIG_X86_X32 */
 };
 
 static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
                return snd_timer_user_info_compat(file, argp);
        case SNDRV_TIMER_IOCTL_STATUS32:
                return snd_timer_user_status_compat(file, argp);
+#ifdef CONFIG_X86_X32
+       case SNDRV_TIMER_IOCTL_STATUS_X32:
+               return snd_timer_user_status_x32(file, argp);
+#endif /* CONFIG_X86_X32 */
        }
        return -ENOIOCTLCMD;
 }
index b5a17cb510a0b4ee71115973a7d73309e9061b03..8c486235c905253ea0609183d813362a294e42f9 100644 (file)
@@ -426,18 +426,22 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip);
  * @bus: HD-audio core bus
  * @status: INTSTS register value
  * @ask: callback to be called for woken streams
+ *
+ * Returns the bits of handled streams, or zero if no stream is handled.
  */
-void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
+int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
                                    void (*ack)(struct hdac_bus *,
                                                struct hdac_stream *))
 {
        struct hdac_stream *azx_dev;
        u8 sd_status;
+       int handled = 0;
 
        list_for_each_entry(azx_dev, &bus->stream_list, list) {
                if (status & azx_dev->sd_int_sta_mask) {
                        sd_status = snd_hdac_stream_readb(azx_dev, SD_STS);
                        snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
+                       handled |= 1 << azx_dev->index;
                        if (!azx_dev->substream || !azx_dev->running ||
                            !(sd_status & SD_INT_COMPLETE))
                                continue;
@@ -445,6 +449,7 @@ void snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
                                ack(bus, azx_dev);
                }
        }
+       return handled;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_bus_handle_stream_irq);
 
index 37cf9cee983555ad1a47e4bb43ff2e9db6de39e9..27de8015717d95fdf45ac512a77c60eb32202d67 100644 (file)
@@ -930,6 +930,8 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
        struct azx *chip = dev_id;
        struct hdac_bus *bus = azx_bus(chip);
        u32 status;
+       bool active, handled = false;
+       int repeat = 0; /* count for avoiding endless loop */
 
 #ifdef CONFIG_PM
        if (azx_has_pm_runtime(chip))
@@ -939,33 +941,36 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
 
        spin_lock(&bus->reg_lock);
 
-       if (chip->disabled) {
-               spin_unlock(&bus->reg_lock);
-               return IRQ_NONE;
-       }
-
-       status = azx_readl(chip, INTSTS);
-       if (status == 0 || status == 0xffffffff) {
-               spin_unlock(&bus->reg_lock);
-               return IRQ_NONE;
-       }
+       if (chip->disabled)
+               goto unlock;
 
-       snd_hdac_bus_handle_stream_irq(bus, status, stream_update);
+       do {
+               status = azx_readl(chip, INTSTS);
+               if (status == 0 || status == 0xffffffff)
+                       break;
 
-       /* clear rirb int */
-       status = azx_readb(chip, RIRBSTS);
-       if (status & RIRB_INT_MASK) {
-               if (status & RIRB_INT_RESPONSE) {
-                       if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
-                               udelay(80);
-                       snd_hdac_bus_update_rirb(bus);
+               handled = true;
+               active = false;
+               if (snd_hdac_bus_handle_stream_irq(bus, status, stream_update))
+                       active = true;
+
+               /* clear rirb int */
+               status = azx_readb(chip, RIRBSTS);
+               if (status & RIRB_INT_MASK) {
+                       active = true;
+                       if (status & RIRB_INT_RESPONSE) {
+                               if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
+                                       udelay(80);
+                               snd_hdac_bus_update_rirb(bus);
+                       }
+                       azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
                }
-               azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
-       }
+       } while (active && ++repeat < 10);
 
+ unlock:
        spin_unlock(&bus->reg_lock);
 
-       return IRQ_HANDLED;
+       return IRQ_RETVAL(handled);
 }
 EXPORT_SYMBOL_GPL(azx_interrupt);
 
index ce6b97f313900494a3895eef47dc0e1924f66a1e..e5240cb3749f4186e79f70dfc9e2c6536eaaed1d 100644 (file)
@@ -363,7 +363,10 @@ enum {
                                        ((pci)->device == 0x0d0c) || \
                                        ((pci)->device == 0x160c))
 
-#define IS_BROXTON(pci)        ((pci)->device == 0x5a98)
+#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
+#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
+#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
 
 static char *driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
@@ -540,13 +543,13 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset)
 
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
                snd_hdac_set_codec_wakeup(bus, true);
-       if (IS_BROXTON(pci)) {
+       if (IS_SKL_PLUS(pci)) {
                pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
                val = val & ~INTEL_HDA_CGCTL_MISCBDCGE;
                pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
        }
        azx_init_chip(chip, full_reset);
-       if (IS_BROXTON(pci)) {
+       if (IS_SKL_PLUS(pci)) {
                pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
                val = val | INTEL_HDA_CGCTL_MISCBDCGE;
                pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
@@ -555,7 +558,7 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset)
                snd_hdac_set_codec_wakeup(bus, false);
 
        /* reduce dma latency to avoid noise */
-       if (IS_BROXTON(pci))
+       if (IS_BXT(pci))
                bxt_reduce_dma_latency(chip);
 }
 
@@ -977,11 +980,6 @@ static int azx_resume(struct device *dev)
 /* put codec down to D3 at hibernation for Intel SKL+;
  * otherwise BIOS may still access the codec and screw up the driver
  */
-#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
-#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
-#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
-
 static int azx_freeze_noirq(struct device *dev)
 {
        struct pci_dev *pci = to_pci_dev(dev);
index 8ee78dbd4c6054065186501b59ecd957c25285a8..bcbc4ee10130a5ee86de2c23815eb85ec8684459 100644 (file)
@@ -2477,13 +2477,6 @@ static int patch_generic_hdmi(struct hda_codec *codec)
                        is_broxton(codec))
                codec->core.link_power_control = 1;
 
-       if (codec_has_acomp(codec)) {
-               codec->depop_delay = 0;
-               spec->i915_audio_ops.audio_ptr = codec;
-               spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
-               snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
-       }
-
        if (hdmi_parse_codec(codec) < 0) {
                if (spec->i915_bound)
                        snd_hdac_i915_exit(&codec->bus->core);
@@ -2505,6 +2498,18 @@ static int patch_generic_hdmi(struct hda_codec *codec)
 
        init_channel_allocations();
 
+       if (codec_has_acomp(codec)) {
+               codec->depop_delay = 0;
+               spec->i915_audio_ops.audio_ptr = codec;
+               /* intel_audio_codec_enable() or intel_audio_codec_disable()
+                * will call pin_eld_notify with using audio_ptr pointer
+                * We need make sure audio_ptr is really setup
+                */
+               wmb();
+               spec->i915_audio_ops.pin_eld_notify = intel_pin_eld_notify;
+               snd_hdac_i915_register_notifier(&spec->i915_audio_ops);
+       }
+
        return 0;
 }
 
index efd4980cffb8a0273228ac7570315f0f1aa1dbf9..93d2156b62410935f3c0f945f0d5d8a2fe182eba 100644 (file)
@@ -3801,6 +3801,10 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
 
 static void alc_headset_mode_default(struct hda_codec *codec)
 {
+       static struct coef_fw coef0225[] = {
+               UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
+               {}
+       };
        static struct coef_fw coef0255[] = {
                WRITE_COEF(0x45, 0xc089),
                WRITE_COEF(0x45, 0xc489),
@@ -3842,6 +3846,9 @@ static void alc_headset_mode_default(struct hda_codec *codec)
        };
 
        switch (codec->core.vendor_id) {
+       case 0x10ec0225:
+               alc_process_coef_fw(codec, coef0225);
+               break;
        case 0x10ec0255:
        case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
@@ -4749,6 +4756,9 @@ enum {
        ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
        ALC293_FIXUP_LENOVO_SPK_NOISE,
        ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
+       ALC255_FIXUP_DELL_SPK_NOISE,
+       ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
+       ALC280_FIXUP_HP_HEADSET_MIC,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5368,6 +5378,29 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc233_fixup_lenovo_line2_mic_hotkey,
        },
+       [ALC255_FIXUP_DELL_SPK_NOISE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_aamix,
+               .chained = true,
+               .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
+       [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* Disable pass-through path for FRONT 14h */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x36 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 },
+                       {}
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
+       [ALC280_FIXUP_HP_HEADSET_MIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_aamix,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MIC,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5379,6 +5412,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
+       SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
        SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
@@ -5410,6 +5444,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
        SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
        SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+       SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -5470,6 +5505,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+       SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -5638,10 +5674,10 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {0x21, 0x03211020}
 
 static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
-       SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+       SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC225_STANDARD_PINS,
                {0x14, 0x901701a0}),
-       SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+       SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC225_STANDARD_PINS,
                {0x14, 0x901701b0}),
        SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
index 42bcbac801a322d0f7cf8df6961e9c6129ae0093..12c2c180e4072755ba17a4826070093669b45723 100644 (file)
@@ -2980,8 +2980,8 @@ static int snd_intel8x0_inside_vm(struct pci_dev *pci)
                goto fini;
 
        /* check for known (emulated) devices */
-       if (pci->subsystem_vendor == 0x1af4 &&
-           pci->subsystem_device == 0x1100) {
+       if (pci->subsystem_vendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
+           pci->subsystem_device == PCI_SUBDEVICE_ID_QEMU) {
                /* KVM emulated sound, PCI SSID: 1af4:1100 */
                msg = "enable KVM";
        } else if (pci->subsystem_vendor == 0x1ab8) {
index 2875b4f6d8c9e6a792638547d4b6850fa620a857..7c8941b8b2defd9b21b8159f1cef333659ce423d 100644 (file)
@@ -2879,7 +2879,7 @@ static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl
 {
        struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
 
-       ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
+       ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp);
        return 0;
 }
 
@@ -2891,7 +2891,7 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl
 
        if (!snd_hdsp_use_is_exclusive(hdsp))
                return -EBUSY;
-       val = ucontrol->value.enumerated.item[0];
+       val = ucontrol->value.integer.value[0];
        spin_lock_irq(&hdsp->lock);
        if (val != hdsp_dds_offset(hdsp))
                change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
index 8bc8016c173d6a6005e33222df1381272bb7819e..a4a999a0317eaefc30eeb2265fd38b784c4afd8a 100644 (file)
@@ -1601,6 +1601,9 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
 {
        u64 n;
 
+       if (snd_BUG_ON(rate <= 0))
+               return;
+
        if (rate >= 112000)
                rate /= 4;
        else if (rate >= 56000)
@@ -2215,6 +2218,8 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
                } else {
                        /* slave mode, return external sample rate */
                        rate = hdspm_external_sample_rate(hdspm);
+                       if (!rate)
+                               rate = hdspm->system_sample_rate;
                }
        }
 
@@ -2260,8 +2265,11 @@ static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
                                            ucontrol)
 {
        struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+       int rate = ucontrol->value.integer.value[0];
 
-       hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
+       if (rate < 27000 || rate > 207000)
+               return -EINVAL;
+       hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
        return 0;
 }
 
@@ -4449,7 +4457,7 @@ static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
 {
        struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-       ucontrol->value.enumerated.item[0] = hdspm->tco->term;
+       ucontrol->value.integer.value[0] = hdspm->tco->term;
 
        return 0;
 }
@@ -4460,8 +4468,8 @@ static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
 {
        struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-       if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
-               hdspm->tco->term = ucontrol->value.enumerated.item[0];
+       if (hdspm->tco->term != ucontrol->value.integer.value[0]) {
+               hdspm->tco->term = ucontrol->value.integer.value[0];
 
                hdspm_tco_write(hdspm);
 
index 0095a80a997fc157e97b70d3c12051d65d0ee4ab..a5843fc5ff204ee6efb32becd35e671927903f59 100644 (file)
@@ -34,7 +34,6 @@
 #include "pmac.h"
 #include <sound/pcm_params.h>
 #include <asm/pmac_feature.h>
-#include <asm/pci-bridge.h>
 
 
 /* fixed frequency table for awacs, screamer, burgundy, DACA (44100 max) */
index affb192238a403b88dc38f3e76e0c54440779ea0..faae6936bae4f55851e4f0a7062f03fdebf674ee 100644 (file)
@@ -1130,7 +1130,7 @@ static int sid_status_control_get(struct snd_kcontrol *kcontrol,
        struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
 
        mutex_lock(&drvdata->ctrl_lock);
-       ucontrol->value.integer.value[0] = drvdata->sid_status;
+       ucontrol->value.enumerated.item[0] = drvdata->sid_status;
        mutex_unlock(&drvdata->ctrl_lock);
 
        return 0;
@@ -1147,7 +1147,7 @@ static int sid_status_control_put(struct snd_kcontrol *kcontrol,
 
        dev_dbg(codec->dev, "%s: Enter\n", __func__);
 
-       if (ucontrol->value.integer.value[0] != SID_APPLY_FIR) {
+       if (ucontrol->value.enumerated.item[0] != SID_APPLY_FIR) {
                dev_err(codec->dev,
                        "%s: ERROR: This control supports '%s' only!\n",
                        __func__, enum_sid_state[SID_APPLY_FIR]);
@@ -1199,7 +1199,7 @@ static int anc_status_control_get(struct snd_kcontrol *kcontrol,
        struct ab8500_codec_drvdata *drvdata = dev_get_drvdata(codec->dev);
 
        mutex_lock(&drvdata->ctrl_lock);
-       ucontrol->value.integer.value[0] = drvdata->anc_status;
+       ucontrol->value.enumerated.item[0] = drvdata->anc_status;
        mutex_unlock(&drvdata->ctrl_lock);
 
        return 0;
@@ -1220,7 +1220,7 @@ static int anc_status_control_put(struct snd_kcontrol *kcontrol,
 
        mutex_lock(&drvdata->ctrl_lock);
 
-       req = ucontrol->value.integer.value[0];
+       req = ucontrol->value.enumerated.item[0];
        if (req >= ARRAY_SIZE(enum_anc_state)) {
                status = -EINVAL;
                goto cleanup;
index e13583e6ff56aa5d69a163ca7a447acdaa18cbd6..5ae87a084d97e24a6aa243ba6cb1afc45290ac43 100644 (file)
@@ -103,9 +103,9 @@ bool adau17x1_has_dsp(struct adau *adau);
 #define ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL BIT(3)
 #define ADAU17X1_CLOCK_CONTROL_SYSCLK_EN       BIT(0)
 
-#define ADAU17X1_SERIAL_PORT1_BCLK32           (0x0 << 5)
-#define ADAU17X1_SERIAL_PORT1_BCLK48           (0x1 << 5)
-#define ADAU17X1_SERIAL_PORT1_BCLK64           (0x2 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK64           (0x0 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK32           (0x1 << 5)
+#define ADAU17X1_SERIAL_PORT1_BCLK48           (0x2 << 5)
 #define ADAU17X1_SERIAL_PORT1_BCLK128          (0x3 << 5)
 #define ADAU17X1_SERIAL_PORT1_BCLK256          (0x4 << 5)
 #define ADAU17X1_SERIAL_PORT1_BCLK_MASK                (0x7 << 5)
index e770ee6f36da1eab0c0952a2f968f3b780db6755..0c0010b254213f11ff19783b0ebafbd3bd37b491 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
@@ -157,6 +158,10 @@ static bool cs4271_volatile_reg(struct device *dev, unsigned int reg)
        return reg == CS4271_CHIPID;
 }
 
+static const char * const supply_names[] = {
+       "vd", "vl", "va"
+};
+
 struct cs4271_private {
        unsigned int                    mclk;
        bool                            master;
@@ -170,6 +175,7 @@ struct cs4271_private {
        int                             gpio_disable;
        /* enable soft reset workaround */
        bool                            enable_soft_reset;
+       struct regulator_bulk_data      supplies[ARRAY_SIZE(supply_names)];
 };
 
 static const struct snd_soc_dapm_widget cs4271_dapm_widgets[] = {
@@ -487,6 +493,20 @@ static struct snd_soc_dai_driver cs4271_dai = {
        .symmetric_rates = 1,
 };
 
+static int cs4271_reset(struct snd_soc_codec *codec)
+{
+       struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+
+       if (gpio_is_valid(cs4271->gpio_nreset)) {
+               gpio_set_value(cs4271->gpio_nreset, 0);
+               mdelay(1);
+               gpio_set_value(cs4271->gpio_nreset, 1);
+               mdelay(1);
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_PM
 static int cs4271_soc_suspend(struct snd_soc_codec *codec)
 {
@@ -499,6 +519,9 @@ static int cs4271_soc_suspend(struct snd_soc_codec *codec)
        if (ret < 0)
                return ret;
 
+       regcache_mark_dirty(cs4271->regmap);
+       regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies);
+
        return 0;
 }
 
@@ -507,6 +530,16 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec)
        int ret;
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
 
+       ret = regulator_bulk_enable(ARRAY_SIZE(cs4271->supplies),
+                                   cs4271->supplies);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
+               return ret;
+       }
+
+       /* Do a proper reset after power up */
+       cs4271_reset(codec);
+
        /* Restore codec state */
        ret = regcache_sync(cs4271->regmap);
        if (ret < 0)
@@ -553,19 +586,24 @@ static int cs4271_codec_probe(struct snd_soc_codec *codec)
        }
 #endif
 
+       ret = regulator_bulk_enable(ARRAY_SIZE(cs4271->supplies),
+                                   cs4271->supplies);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
+               return ret;
+       }
+
        if (cs4271plat) {
                amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
                cs4271->enable_soft_reset = cs4271plat->enable_soft_reset;
        }
 
-       if (gpio_is_valid(cs4271->gpio_nreset)) {
-               /* Reset codec */
-               gpio_direction_output(cs4271->gpio_nreset, 0);
-               mdelay(1);
-               gpio_set_value(cs4271->gpio_nreset, 1);
-               /* Give the codec time to wake up */
-               mdelay(1);
-       }
+       /* Reset codec */
+       cs4271_reset(codec);
+
+       ret = regcache_sync(cs4271->regmap);
+       if (ret < 0)
+               return ret;
 
        ret = regmap_update_bits(cs4271->regmap, CS4271_MODE2,
                                 CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
@@ -595,6 +633,9 @@ static int cs4271_codec_remove(struct snd_soc_codec *codec)
                /* Set codec to the reset state */
                gpio_set_value(cs4271->gpio_nreset, 0);
 
+       regcache_mark_dirty(cs4271->regmap);
+       regulator_bulk_disable(ARRAY_SIZE(cs4271->supplies), cs4271->supplies);
+
        return 0;
 };
 
@@ -617,6 +658,7 @@ static int cs4271_common_probe(struct device *dev,
 {
        struct cs4271_platform_data *cs4271plat = dev->platform_data;
        struct cs4271_private *cs4271;
+       int i, ret;
 
        cs4271 = devm_kzalloc(dev, sizeof(*cs4271), GFP_KERNEL);
        if (!cs4271)
@@ -638,6 +680,17 @@ static int cs4271_common_probe(struct device *dev,
                        return ret;
        }
 
+       for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+               cs4271->supplies[i].supply = supply_names[i];
+
+       ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs4271->supplies),
+                                       cs4271->supplies);
+
+       if (ret < 0) {
+               dev_err(dev, "Failed to get regulators: %d\n", ret);
+               return ret;
+       }
+
        *c = cs4271;
        return 0;
 }
index b3951524339f90cdf8f90dbc23cbadd46a874af9..35488f14e2378ada271328a97504a9558b746836 100644 (file)
@@ -60,15 +60,15 @@ static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
        switch (value) {
        default:
        case 0:
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.enumerated.item[0] = 0;
                break;
        /* same value : (L+R)/2 and (R+L)/2 */
        case 1:
        case 2:
-               ucontrol->value.integer.value[0] = 1;
+               ucontrol->value.enumerated.item[0] = 1;
                break;
        case 3:
-               ucontrol->value.integer.value[0] = 2;
+               ucontrol->value.enumerated.item[0] = 2;
                break;
        }
 
@@ -85,7 +85,7 @@ static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        unsigned char val;
 
-       switch (ucontrol->value.integer.value[0]) {
+       switch (ucontrol->value.enumerated.item[0]) {
        default:
        case 0:
                val = CHAN_MIX_NORMAL;
index 1d5a89c5164b85686f652dc8f5e13af6c1eb49e6..461506a4ca6a2ddb790b1646f27bce2d7abf25ba 100644 (file)
@@ -334,7 +334,7 @@ static int da732x_hpf_set(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct soc_enum *enum_ctrl = (struct soc_enum *)kcontrol->private_value;
        unsigned int reg = enum_ctrl->reg;
-       unsigned int sel = ucontrol->value.integer.value[0];
+       unsigned int sel = ucontrol->value.enumerated.item[0];
        unsigned int bits;
 
        switch (sel) {
@@ -368,13 +368,13 @@ static int da732x_hpf_get(struct snd_kcontrol *kcontrol,
 
        switch (val) {
        case DA732X_HPF_VOICE_EN:
-               ucontrol->value.integer.value[0] = DA732X_HPF_VOICE;
+               ucontrol->value.enumerated.item[0] = DA732X_HPF_VOICE;
                break;
        case DA732X_HPF_MUSIC_EN:
-               ucontrol->value.integer.value[0] = DA732X_HPF_MUSIC;
+               ucontrol->value.enumerated.item[0] = DA732X_HPF_MUSIC;
                break;
        default:
-               ucontrol->value.integer.value[0] = DA732X_HPF_DISABLED;
+               ucontrol->value.enumerated.item[0] = DA732X_HPF_DISABLED;
                break;
        }
 
index 20dcc496d39c9d8ac01e4d49004f92823fdd37a6..fc22804cabc5942acca6921c034fa98f234041dc 100644 (file)
@@ -1496,7 +1496,7 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
        struct max98088_pdata *pdata = max98088->pdata;
        int channel = max98088_get_channel(codec, kcontrol->id.name);
        struct max98088_cdata *cdata;
-       int sel = ucontrol->value.integer.value[0];
+       int sel = ucontrol->value.enumerated.item[0];
 
        if (channel < 0)
               return channel;
index 1fedac50355e954790a15b84ed6aab49b2bb98e3..3577003f39cf8feaba0d97bb313e277b3b763ce7 100644 (file)
@@ -1499,7 +1499,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol,
        struct max98095_pdata *pdata = max98095->pdata;
        int channel = max98095_get_eq_channel(kcontrol->id.name);
        struct max98095_cdata *cdata;
-       unsigned int sel = ucontrol->value.integer.value[0];
+       unsigned int sel = ucontrol->value.enumerated.item[0];
        struct max98095_eq_cfg *coef_set;
        int fs, best, best_val, i;
        int regmask, regsave;
@@ -1653,7 +1653,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
        struct max98095_pdata *pdata = max98095->pdata;
        int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
        struct max98095_cdata *cdata;
-       unsigned int sel = ucontrol->value.integer.value[0];
+       unsigned int sel = ucontrol->value.enumerated.item[0];
        struct max98095_biquad_cfg *coef_set;
        int fs, best, best_val, i;
        int regmask, regsave;
index 781398fb2841565f20d2f7e7a4f893d840e3e7ae..f7a6ce7e5fb12b7ab183428b28d6c69409676d08 100644 (file)
@@ -446,7 +446,7 @@ static int dac33_get_fifo_mode(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.integer.value[0] = dac33->fifo_mode;
+       ucontrol->value.enumerated.item[0] = dac33->fifo_mode;
 
        return 0;
 }
@@ -458,17 +458,16 @@ static int dac33_set_fifo_mode(struct snd_kcontrol *kcontrol,
        struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
-       if (dac33->fifo_mode == ucontrol->value.integer.value[0])
+       if (dac33->fifo_mode == ucontrol->value.enumerated.item[0])
                return 0;
        /* Do not allow changes while stream is running*/
        if (snd_soc_codec_is_active(codec))
                return -EPERM;
 
-       if (ucontrol->value.integer.value[0] < 0 ||
-           ucontrol->value.integer.value[0] >= DAC33_FIFO_LAST_MODE)
+       if (ucontrol->value.enumerated.item[0] >= DAC33_FIFO_LAST_MODE)
                ret = -EINVAL;
        else
-               dac33->fifo_mode = ucontrol->value.integer.value[0];
+               dac33->fifo_mode = ucontrol->value.enumerated.item[0];
 
        return ret;
 }
index 7693c1129babf0e42c58b5ca93832052374cb426..1b79778098d29ffbb377efc24576825cdfe8038c 100644 (file)
@@ -175,7 +175,7 @@ static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.integer.value[0] = wl1273->mode;
+       ucontrol->value.enumerated.item[0] = wl1273->mode;
 
        return 0;
 }
@@ -193,18 +193,17 @@ static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
 
-       if (wl1273->mode == ucontrol->value.integer.value[0])
+       if (wl1273->mode == ucontrol->value.enumerated.item[0])
                return 0;
 
        /* Do not allow changes while stream is running */
        if (snd_soc_codec_is_active(codec))
                return -EPERM;
 
-       if (ucontrol->value.integer.value[0] < 0 ||
-           ucontrol->value.integer.value[0] >=  ARRAY_SIZE(wl1273_audio_route))
+       if (ucontrol->value.enumerated.item[0] >=  ARRAY_SIZE(wl1273_audio_route))
                return -EINVAL;
 
-       wl1273->mode = ucontrol->value.integer.value[0];
+       wl1273->mode = ucontrol->value.enumerated.item[0];
 
        return 1;
 }
@@ -219,7 +218,7 @@ static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
 
        dev_dbg(codec->dev, "%s: enter.\n", __func__);
 
-       ucontrol->value.integer.value[0] = wl1273->core->audio_mode;
+       ucontrol->value.enumerated.item[0] = wl1273->core->audio_mode;
 
        return 0;
 }
@@ -233,7 +232,7 @@ static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
 
        dev_dbg(codec->dev, "%s: enter.\n", __func__);
 
-       val = ucontrol->value.integer.value[0];
+       val = ucontrol->value.enumerated.item[0];
        if (wl1273->core->audio_mode == val)
                return 0;
 
index 61299ca372ffc1fc3f83dd88fe823151da7b09b8..6f1024f48b193bc7d3127cc8b12d56d14124413b 100644 (file)
@@ -233,7 +233,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.integer.value[0] = wm8753->dai_func;
+       ucontrol->value.enumerated.item[0] = wm8753->dai_func;
        return 0;
 }
 
@@ -244,7 +244,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
        u16 ioctl;
 
-       if (wm8753->dai_func == ucontrol->value.integer.value[0])
+       if (wm8753->dai_func == ucontrol->value.enumerated.item[0])
                return 0;
 
        if (snd_soc_codec_is_active(codec))
@@ -252,7 +252,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
 
        ioctl = snd_soc_read(codec, WM8753_IOCTL);
 
-       wm8753->dai_func = ucontrol->value.integer.value[0];
+       wm8753->dai_func = ucontrol->value.enumerated.item[0];
 
        if (((ioctl >> 2) & 0x3) == wm8753->dai_func)
                return 1;
index 8172e499e6ed18f33e6f94b2bec1a1647d1c1788..edd7a77091942cd7b873e9c193baed54dd6186c6 100644 (file)
@@ -396,7 +396,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (value >= pdata->num_drc_cfgs)
                return -EINVAL;
@@ -467,7 +467,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (value >= pdata->num_retune_mobile_cfgs)
                return -EINVAL;
index c799cca5abeb704645687b863ccedfc6749e9ac2..6b864c0fc2b676cc83f9d03d2218815e7e805919 100644 (file)
@@ -459,7 +459,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
        int reg;
 
        /* Don't allow on the fly reconfiguration */
@@ -549,7 +549,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
        int reg;
 
        /* Don't allow on the fly reconfiguration */
@@ -582,7 +582,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
        int reg;
 
        /* Don't allow on the fly reconfiguration */
@@ -749,7 +749,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = wm8994->wm8994;
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
        int reg;
 
        /* Don't allow on the fly reconfiguration */
index 7350ff654bbf37fe660e2b7a75cc5a15b5d63c68..0c002a5712cb4f261cd84454f38e24a89836519a 100644 (file)
@@ -497,9 +497,9 @@ static int eqmode_get(struct snd_kcontrol *kcontrol,
 
        reg = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF);
        if (reg & WM8983_EQ3DMODE)
-               ucontrol->value.integer.value[0] = 1;
+               ucontrol->value.enumerated.item[0] = 1;
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.enumerated.item[0] = 0;
 
        return 0;
 }
@@ -511,18 +511,18 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        unsigned int regpwr2, regpwr3;
        unsigned int reg_eq;
 
-       if (ucontrol->value.integer.value[0] != 0
-           && ucontrol->value.integer.value[0] != 1)
+       if (ucontrol->value.enumerated.item[0] != 0
+           && ucontrol->value.enumerated.item[0] != 1)
                return -EINVAL;
 
        reg_eq = snd_soc_read(codec, WM8983_EQ1_LOW_SHELF);
        switch ((reg_eq & WM8983_EQ3DMODE) >> WM8983_EQ3DMODE_SHIFT) {
        case 0:
-               if (!ucontrol->value.integer.value[0])
+               if (!ucontrol->value.enumerated.item[0])
                        return 0;
                break;
        case 1:
-               if (ucontrol->value.integer.value[0])
+               if (ucontrol->value.enumerated.item[0])
                        return 0;
                break;
        }
@@ -537,7 +537,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        /* set the desired eqmode */
        snd_soc_update_bits(codec, WM8983_EQ1_LOW_SHELF,
                            WM8983_EQ3DMODE_MASK,
-                           ucontrol->value.integer.value[0]
+                           ucontrol->value.enumerated.item[0]
                            << WM8983_EQ3DMODE_SHIFT);
        /* restore DAC/ADC configuration */
        snd_soc_write(codec, WM8983_POWER_MANAGEMENT_2, regpwr2);
index 9918152a03c7518e5c0c2e299a35145abd808a14..6ac76fe116b028db34c8cdbf3691babeb2a68844 100644 (file)
@@ -531,9 +531,9 @@ static int eqmode_get(struct snd_kcontrol *kcontrol,
 
        reg = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
        if (reg & WM8985_EQ3DMODE)
-               ucontrol->value.integer.value[0] = 1;
+               ucontrol->value.enumerated.item[0] = 1;
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.enumerated.item[0] = 0;
 
        return 0;
 }
@@ -545,18 +545,18 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        unsigned int regpwr2, regpwr3;
        unsigned int reg_eq;
 
-       if (ucontrol->value.integer.value[0] != 0
-                       && ucontrol->value.integer.value[0] != 1)
+       if (ucontrol->value.enumerated.item[0] != 0
+                       && ucontrol->value.enumerated.item[0] != 1)
                return -EINVAL;
 
        reg_eq = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
        switch ((reg_eq & WM8985_EQ3DMODE) >> WM8985_EQ3DMODE_SHIFT) {
        case 0:
-               if (!ucontrol->value.integer.value[0])
+               if (!ucontrol->value.enumerated.item[0])
                        return 0;
                break;
        case 1:
-               if (ucontrol->value.integer.value[0])
+               if (ucontrol->value.enumerated.item[0])
                        return 0;
                break;
        }
@@ -573,7 +573,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
        /* set the desired eqmode */
        snd_soc_update_bits(codec, WM8985_EQ1_LOW_SHELF,
                            WM8985_EQ3DMODE_MASK,
-                           ucontrol->value.integer.value[0]
+                           ucontrol->value.enumerated.item[0]
                            << WM8985_EQ3DMODE_SHIFT);
        /* restore DAC/ADC configuration */
        snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, regpwr2);
index 2ccbb322df775b803d40fe765958f439d855d41f..a18aecb4993590e6a7bd936b238fee544462a6bc 100644 (file)
@@ -362,7 +362,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
        struct wm8994 *control = wm8994->wm8994;
        struct wm8994_pdata *pdata = &control->pdata;
        int drc = wm8994_get_drc(kcontrol->id.name);
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (drc < 0)
                return drc;
@@ -469,7 +469,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
        struct wm8994 *control = wm8994->wm8994;
        struct wm8994_pdata *pdata = &control->pdata;
        int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (block < 0)
                return block;
index 8d7d6c01a2f7264905e7a8e29888a417f44fb515..f99b34f7647b092a657fbbc3a70fd01219837351 100644 (file)
@@ -416,7 +416,7 @@ static int wm8996_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
        struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
        struct wm8996_pdata *pdata = &wm8996->pdata;
        int block = wm8996_get_retune_mobile_block(kcontrol->id.name);
-       int value = ucontrol->value.integer.value[0];
+       int value = ucontrol->value.enumerated.item[0];
 
        if (block < 0)
                return block;
index ccb3b15139ad9dacd41ad801201471d1ed696997..363b3b6676163e8c0b110efd165c5eccd7ec9e1a 100644 (file)
@@ -344,9 +344,9 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol,
 
        reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
        if (reg & WM9081_SPK_MODE)
-               ucontrol->value.integer.value[0] = 1;
+               ucontrol->value.enumerated.item[0] = 1;
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.enumerated.item[0] = 0;
 
        return 0;
 }
@@ -365,7 +365,7 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol,
        unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
 
        /* Are we changing anything? */
-       if (ucontrol->value.integer.value[0] ==
+       if (ucontrol->value.enumerated.item[0] ==
            ((reg2 & WM9081_SPK_MODE) != 0))
                return 0;
 
@@ -373,7 +373,7 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol,
        if (reg_pwr & WM9081_SPK_ENA)
                return -EINVAL;
 
-       if (ucontrol->value.integer.value[0]) {
+       if (ucontrol->value.enumerated.item[0]) {
                /* Class AB */
                reg2 &= ~(WM9081_SPK_INV_MUTE | WM9081_OUT_SPK_CTRL);
                reg2 |= WM9081_SPK_MODE;
index 79e143625ac3d9c14ca72f96dc11acb6a970efdb..9849643ef8099c7f3340a719cf160c8ce633f9c5 100644 (file)
@@ -1212,7 +1212,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
        if (IS_ERR(wm9713->ac97))
                return PTR_ERR(wm9713->ac97);
 
-       regmap = devm_regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
+       regmap = regmap_init_ac97(wm9713->ac97, &wm9713_regmap_config);
        if (IS_ERR(regmap)) {
                snd_soc_free_ac97_codec(wm9713->ac97);
                return PTR_ERR(regmap);
index 33806d487b8ae00711dddd4ec400393dbff59b1f..b9195b9c2b05175278d4e779f7db87aad20d9f63 100644 (file)
@@ -586,7 +586,7 @@ static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
        struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
 
-       ucontrol->value.integer.value[0] = dsp[e->shift_l].fw;
+       ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw;
 
        return 0;
 }
@@ -599,10 +599,10 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
        struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
 
-       if (ucontrol->value.integer.value[0] == dsp[e->shift_l].fw)
+       if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
                return 0;
 
-       if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW)
+       if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW)
                return -EINVAL;
 
        mutex_lock(&dsp[e->shift_l].pwr_lock);
@@ -610,7 +610,7 @@ static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
        if (dsp[e->shift_l].running || dsp[e->shift_l].compr)
                ret = -EBUSY;
        else
-               dsp[e->shift_l].fw = ucontrol->value.integer.value[0];
+               dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
 
        mutex_unlock(&dsp[e->shift_l].pwr_lock);
 
index ed8de1035cda159d0d186f2cded0fb7a97fbceb4..40dfd8a3648408a2cc76bb6e4c4c3872c8e28ac3 100644 (file)
@@ -112,6 +112,20 @@ struct fsl_ssi_rxtx_reg_val {
        struct fsl_ssi_reg_val tx;
 };
 
+static const struct reg_default fsl_ssi_reg_defaults[] = {
+       {CCSR_SSI_SCR,     0x00000000},
+       {CCSR_SSI_SIER,    0x00003003},
+       {CCSR_SSI_STCR,    0x00000200},
+       {CCSR_SSI_SRCR,    0x00000200},
+       {CCSR_SSI_STCCR,   0x00040000},
+       {CCSR_SSI_SRCCR,   0x00040000},
+       {CCSR_SSI_SACNT,   0x00000000},
+       {CCSR_SSI_STMSK,   0x00000000},
+       {CCSR_SSI_SRMSK,   0x00000000},
+       {CCSR_SSI_SACCEN,  0x00000000},
+       {CCSR_SSI_SACCDIS, 0x00000000},
+};
+
 static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
@@ -176,7 +190,8 @@ static const struct regmap_config fsl_ssi_regconfig = {
        .val_bits = 32,
        .reg_stride = 4,
        .val_format_endian = REGMAP_ENDIAN_NATIVE,
-       .num_reg_defaults_raw = CCSR_SSI_SACCDIS / sizeof(uint32_t) + 1,
+       .reg_defaults = fsl_ssi_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(fsl_ssi_reg_defaults),
        .readable_reg = fsl_ssi_readable_reg,
        .volatile_reg = fsl_ssi_volatile_reg,
        .precious_reg = fsl_ssi_precious_reg,
@@ -186,7 +201,6 @@ static const struct regmap_config fsl_ssi_regconfig = {
 
 struct fsl_ssi_soc_data {
        bool imx;
-       bool imx21regs; /* imx21-class SSI - no SACC{ST,EN,DIS} regs */
        bool offline_config;
        u32 sisr_write_mask;
 };
@@ -289,7 +303,6 @@ static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
 
 static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
        .imx = true,
-       .imx21regs = true,
        .offline_config = true,
        .sisr_write_mask = 0,
 };
@@ -573,12 +586,8 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
         */
        regmap_write(regs, CCSR_SSI_SACNT,
                        CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV);
-
-       /* no SACC{ST,EN,DIS} regs on imx21-class SSI */
-       if (!ssi_private->soc->imx21regs) {
-               regmap_write(regs, CCSR_SSI_SACCDIS, 0xff);
-               regmap_write(regs, CCSR_SSI_SACCEN, 0x300);
-       }
+       regmap_write(regs, CCSR_SSI_SACCDIS, 0xff);
+       regmap_write(regs, CCSR_SSI_SACCEN, 0x300);
 
        /*
         * Enable SSI, Transmit and Receive. AC97 has to communicate with the
@@ -1388,7 +1397,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
        struct resource *res;
        void __iomem *iomem;
        char name[64];
-       struct regmap_config regconfig = fsl_ssi_regconfig;
 
        of_id = of_match_device(fsl_ssi_ids, &pdev->dev);
        if (!of_id || !of_id->data)
@@ -1436,25 +1444,15 @@ static int fsl_ssi_probe(struct platform_device *pdev)
                return PTR_ERR(iomem);
        ssi_private->ssi_phys = res->start;
 
-       if (ssi_private->soc->imx21regs) {
-               /*
-                * According to datasheet imx21-class SSI
-                * don't have SACC{ST,EN,DIS} regs.
-                */
-               regconfig.max_register = CCSR_SSI_SRMSK;
-               regconfig.num_reg_defaults_raw =
-                       CCSR_SSI_SRMSK / sizeof(uint32_t) + 1;
-       }
-
        ret = of_property_match_string(np, "clock-names", "ipg");
        if (ret < 0) {
                ssi_private->has_ipg_clk_name = false;
                ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem,
-                       &regconfig);
+                       &fsl_ssi_regconfig);
        } else {
                ssi_private->has_ipg_clk_name = true;
                ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev,
-                       "ipg", iomem, &regconfig);
+                       "ipg", iomem, &fsl_ssi_regconfig);
        }
        if (IS_ERR(ssi_private->regs)) {
                dev_err(&pdev->dev, "Failed to init register map\n");
index 49d7513f429e5424ee3ea081178e087368e74896..e63cd5ecfd8feacd396f835756af90107fd2e2a6 100644 (file)
@@ -217,8 +217,8 @@ static int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
        struct snd_pcm_runtime *runtime = substream->runtime;
        int ret;
 
-       ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
-               runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+       ret = dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
+                         runtime->dma_addr, runtime->dma_bytes);
 
        pr_debug("%s: ret: %d %p %pad 0x%08x\n", __func__, ret,
                        runtime->dma_area,
@@ -247,8 +247,7 @@ static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
        buf->dev.type = SNDRV_DMA_TYPE_DEV;
        buf->dev.dev = pcm->card->dev;
        buf->private_data = NULL;
-       buf->area = dma_alloc_writecombine(pcm->card->dev, size,
-                                          &buf->addr, GFP_KERNEL);
+       buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
        if (!buf->area)
                return -ENOMEM;
        buf->bytes = size;
@@ -330,8 +329,7 @@ static void imx_pcm_free(struct snd_pcm *pcm)
                if (!buf->area)
                        continue;
 
-               dma_free_writecombine(pcm->card->dev, buf->bytes,
-                                     buf->area, buf->addr);
+               dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
                buf->area = NULL;
        }
 }
index 2d3afddb0a2e8c83fef54b36eed42d7ff6b69878..a7b96a9a4e0ecb57876413c848cfa91359d42a92 100644 (file)
@@ -367,8 +367,12 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
        }
        card->dev = &pdev->dev;
        sprintf(codec_name, "i2c-%s:00", drv->acpi_card->codec_id);
+
        /* set correct codec name */
-       strcpy((char *)card->dai_link[2].codec_name, codec_name);
+       for (i = 0; i < ARRAY_SIZE(cht_dailink); i++)
+               if (!strcmp(card->dai_link[i].codec_name, "i2c-10EC5645:00"))
+                       card->dai_link[i].codec_name = kstrdup(codec_name, GFP_KERNEL);
+
        snd_soc_card_set_drvdata(card, drv);
        ret_val = devm_snd_soc_register_card(&pdev->dev, card);
        if (ret_val) {
index 49c09a0add797ff95101bee1923b62254e3928a0..34f46c72a0e27cff8cd37108d27b71029cd088c6 100644 (file)
@@ -94,7 +94,7 @@ static const struct soc_enum lo_enum =
 static int headset_get_switch(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = hs_switch;
+       ucontrol->value.enumerated.item[0] = hs_switch;
        return 0;
 }
 
@@ -104,12 +104,12 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol,
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
        struct snd_soc_dapm_context *dapm = &card->dapm;
 
-       if (ucontrol->value.integer.value[0] == hs_switch)
+       if (ucontrol->value.enumerated.item[0] == hs_switch)
                return 0;
 
        snd_soc_dapm_mutex_lock(dapm);
 
-       if (ucontrol->value.integer.value[0]) {
+       if (ucontrol->value.enumerated.item[0]) {
                pr_debug("hs_set HS path\n");
                snd_soc_dapm_enable_pin_unlocked(dapm, "Headphones");
                snd_soc_dapm_disable_pin_unlocked(dapm, "EPOUT");
@@ -123,7 +123,7 @@ static int headset_set_switch(struct snd_kcontrol *kcontrol,
 
        snd_soc_dapm_mutex_unlock(dapm);
 
-       hs_switch = ucontrol->value.integer.value[0];
+       hs_switch = ucontrol->value.enumerated.item[0];
 
        return 0;
 }
@@ -148,7 +148,7 @@ static void lo_enable_out_pins(struct snd_soc_dapm_context *dapm)
 static int lo_get_switch(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = lo_dac;
+       ucontrol->value.enumerated.item[0] = lo_dac;
        return 0;
 }
 
@@ -158,7 +158,7 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol,
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
        struct snd_soc_dapm_context *dapm = &card->dapm;
 
-       if (ucontrol->value.integer.value[0] == lo_dac)
+       if (ucontrol->value.enumerated.item[0] == lo_dac)
                return 0;
 
        snd_soc_dapm_mutex_lock(dapm);
@@ -168,7 +168,7 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol,
         */
        lo_enable_out_pins(dapm);
 
-       switch (ucontrol->value.integer.value[0]) {
+       switch (ucontrol->value.enumerated.item[0]) {
        case 0:
                pr_debug("set vibra path\n");
                snd_soc_dapm_disable_pin_unlocked(dapm, "VIB1OUT");
@@ -202,7 +202,7 @@ static int lo_set_switch(struct snd_kcontrol *kcontrol,
 
        snd_soc_dapm_mutex_unlock(dapm);
 
-       lo_dac = ucontrol->value.integer.value[0];
+       lo_dac = ucontrol->value.enumerated.item[0];
        return 0;
 }
 
index a294fee431f07363f965a81b4c9ef42eb3a42f58..5a4837dcfce3e615eedf47049ac3923332c8a9bf 100644 (file)
@@ -978,7 +978,7 @@ static int skl_tplg_tlv_control_set(struct snd_kcontrol *kcontrol,
                                return -EFAULT;
                } else {
                        if (copy_from_user(ac->params,
-                                          data + 2 * sizeof(u32), size))
+                                          data + 2, size))
                                return -EFAULT;
                }
 
index e09326158bc2dd0be61ea69f375f37dc6f0cdbe5..2cca055fd806cdb80e7226557af943533680c2f8 100644 (file)
@@ -267,10 +267,8 @@ static int nuc900_dma_mmap(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
 
-       return dma_mmap_writecombine(substream->pcm->card->dev, vma,
-                                       runtime->dma_area,
-                                       runtime->dma_addr,
-                                       runtime->dma_bytes);
+       return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
+                          runtime->dma_addr, runtime->dma_bytes);
 }
 
 static struct snd_pcm_ops nuc900_dma_ops = {
index 190f868e78b24af37d8442d378c06aeb8ec6aaf2..fdecb70431745bf23c7113bf7abcede1cd5306ef 100644 (file)
@@ -133,7 +133,7 @@ static struct snd_soc_ops n810_ops = {
 static int n810_get_spk(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = n810_spk_func;
+       ucontrol->value.enumerated.item[0] = n810_spk_func;
 
        return 0;
 }
@@ -143,10 +143,10 @@ static int n810_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (n810_spk_func == ucontrol->value.integer.value[0])
+       if (n810_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       n810_spk_func = ucontrol->value.integer.value[0];
+       n810_spk_func = ucontrol->value.enumerated.item[0];
        n810_ext_control(&card->dapm);
 
        return 1;
@@ -155,7 +155,7 @@ static int n810_set_spk(struct snd_kcontrol *kcontrol,
 static int n810_get_jack(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = n810_jack_func;
+       ucontrol->value.enumerated.item[0] = n810_jack_func;
 
        return 0;
 }
@@ -165,10 +165,10 @@ static int n810_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (n810_jack_func == ucontrol->value.integer.value[0])
+       if (n810_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       n810_jack_func = ucontrol->value.integer.value[0];
+       n810_jack_func = ucontrol->value.enumerated.item[0];
        n810_ext_control(&card->dapm);
 
        return 1;
@@ -177,7 +177,7 @@ static int n810_set_jack(struct snd_kcontrol *kcontrol,
 static int n810_get_input(struct snd_kcontrol *kcontrol,
                          struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = n810_dmic_func;
+       ucontrol->value.enumerated.item[0] = n810_dmic_func;
 
        return 0;
 }
@@ -187,10 +187,10 @@ static int n810_set_input(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (n810_dmic_func == ucontrol->value.integer.value[0])
+       if (n810_dmic_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       n810_dmic_func = ucontrol->value.integer.value[0];
+       n810_dmic_func = ucontrol->value.enumerated.item[0];
        n810_ext_control(&card->dapm);
 
        return 1;
index 6bb623a2a4dfcfa3cda744ca8bef18575baec2d9..99381a27295bbbd9452f0d0050c1509651373bff 100644 (file)
@@ -156,10 +156,8 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
 
-       return dma_mmap_writecombine(substream->pcm->card->dev, vma,
-                                    runtime->dma_area,
-                                    runtime->dma_addr,
-                                    runtime->dma_bytes);
+       return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area,
+                          runtime->dma_addr, runtime->dma_bytes);
 }
 
 static struct snd_pcm_ops omap_pcm_ops = {
@@ -183,8 +181,7 @@ static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
        buf->dev.type = SNDRV_DMA_TYPE_DEV;
        buf->dev.dev = pcm->card->dev;
        buf->private_data = NULL;
-       buf->area = dma_alloc_writecombine(pcm->card->dev, size,
-                                          &buf->addr, GFP_KERNEL);
+       buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL);
        if (!buf->area)
                return -ENOMEM;
 
@@ -207,8 +204,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
                if (!buf->area)
                        continue;
 
-               dma_free_writecombine(pcm->card->dev, buf->bytes,
-                                     buf->area, buf->addr);
+               dma_free_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr);
                buf->area = NULL;
        }
 }
index 5e21f08579d804c5f7895a22e87de6cdff8b79ef..54949242bc7075587e6a73a7235049db2e108734 100644 (file)
@@ -132,7 +132,7 @@ static struct snd_soc_ops rx51_ops = {
 static int rx51_get_spk(struct snd_kcontrol *kcontrol,
                        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = rx51_spk_func;
+       ucontrol->value.enumerated.item[0] = rx51_spk_func;
 
        return 0;
 }
@@ -142,10 +142,10 @@ static int rx51_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (rx51_spk_func == ucontrol->value.integer.value[0])
+       if (rx51_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       rx51_spk_func = ucontrol->value.integer.value[0];
+       rx51_spk_func = ucontrol->value.enumerated.item[0];
        rx51_ext_control(&card->dapm);
 
        return 1;
@@ -180,7 +180,7 @@ static int rx51_hp_event(struct snd_soc_dapm_widget *w,
 static int rx51_get_input(struct snd_kcontrol *kcontrol,
                          struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = rx51_dmic_func;
+       ucontrol->value.enumerated.item[0] = rx51_dmic_func;
 
        return 0;
 }
@@ -190,10 +190,10 @@ static int rx51_set_input(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (rx51_dmic_func == ucontrol->value.integer.value[0])
+       if (rx51_dmic_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       rx51_dmic_func = ucontrol->value.integer.value[0];
+       rx51_dmic_func = ucontrol->value.enumerated.item[0];
        rx51_ext_control(&card->dapm);
 
        return 1;
@@ -202,7 +202,7 @@ static int rx51_set_input(struct snd_kcontrol *kcontrol,
 static int rx51_get_jack(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = rx51_jack_func;
+       ucontrol->value.enumerated.item[0] = rx51_jack_func;
 
        return 0;
 }
@@ -212,10 +212,10 @@ static int rx51_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (rx51_jack_func == ucontrol->value.integer.value[0])
+       if (rx51_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       rx51_jack_func = ucontrol->value.integer.value[0];
+       rx51_jack_func = ucontrol->value.enumerated.item[0];
        rx51_ext_control(&card->dapm);
 
        return 1;
index c97dc13d36087628433de516a1b2217df02b492b..dcbb7aa9830c0347af6f7bd2c198639e52d9e24e 100644 (file)
@@ -163,7 +163,7 @@ static struct snd_soc_ops corgi_ops = {
 static int corgi_get_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = corgi_jack_func;
+       ucontrol->value.enumerated.item[0] = corgi_jack_func;
        return 0;
 }
 
@@ -172,10 +172,10 @@ static int corgi_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (corgi_jack_func == ucontrol->value.integer.value[0])
+       if (corgi_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       corgi_jack_func = ucontrol->value.integer.value[0];
+       corgi_jack_func = ucontrol->value.enumerated.item[0];
        corgi_ext_control(&card->dapm);
        return 1;
 }
@@ -183,7 +183,7 @@ static int corgi_set_jack(struct snd_kcontrol *kcontrol,
 static int corgi_get_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = corgi_spk_func;
+       ucontrol->value.enumerated.item[0] = corgi_spk_func;
        return 0;
 }
 
@@ -192,10 +192,10 @@ static int corgi_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (corgi_spk_func == ucontrol->value.integer.value[0])
+       if (corgi_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       corgi_spk_func = ucontrol->value.integer.value[0];
+       corgi_spk_func = ucontrol->value.enumerated.item[0];
        corgi_ext_control(&card->dapm);
        return 1;
 }
index 241d0be42d7a0c6779bb6459c5165728cbedb302..62b8377a9d2b93c81f06a8df4c0b5ed2cd7a567f 100644 (file)
@@ -308,17 +308,17 @@ static int magician_set_spk(struct snd_kcontrol *kcontrol,
 static int magician_get_input(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = magician_in_sel;
+       ucontrol->value.enumerated.item[0] = magician_in_sel;
        return 0;
 }
 
 static int magician_set_input(struct snd_kcontrol *kcontrol,
                              struct snd_ctl_elem_value *ucontrol)
 {
-       if (magician_in_sel == ucontrol->value.integer.value[0])
+       if (magician_in_sel == ucontrol->value.enumerated.item[0])
                return 0;
 
-       magician_in_sel = ucontrol->value.integer.value[0];
+       magician_in_sel = ucontrol->value.enumerated.item[0];
 
        switch (magician_in_sel) {
        case MAGICIAN_MIC:
index 84d0e2e508088a260b54911bca03236a50046203..4b3b714f5ee7a67e5538b191a9da99bac86e56f8 100644 (file)
@@ -138,7 +138,7 @@ static struct snd_soc_ops poodle_ops = {
 static int poodle_get_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = poodle_jack_func;
+       ucontrol->value.enumerated.item[0] = poodle_jack_func;
        return 0;
 }
 
@@ -147,10 +147,10 @@ static int poodle_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (poodle_jack_func == ucontrol->value.integer.value[0])
+       if (poodle_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       poodle_jack_func = ucontrol->value.integer.value[0];
+       poodle_jack_func = ucontrol->value.enumerated.item[0];
        poodle_ext_control(&card->dapm);
        return 1;
 }
@@ -158,7 +158,7 @@ static int poodle_set_jack(struct snd_kcontrol *kcontrol,
 static int poodle_get_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = poodle_spk_func;
+       ucontrol->value.enumerated.item[0] = poodle_spk_func;
        return 0;
 }
 
@@ -167,10 +167,10 @@ static int poodle_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card =  snd_kcontrol_chip(kcontrol);
 
-       if (poodle_spk_func == ucontrol->value.integer.value[0])
+       if (poodle_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       poodle_spk_func = ucontrol->value.integer.value[0];
+       poodle_spk_func = ucontrol->value.enumerated.item[0];
        poodle_ext_control(&card->dapm);
        return 1;
 }
index b00222620fd01be5cf00d4118d44f18832ad3bdc..0e02634c8b7f6f41764b75344ae850ff7ce586d7 100644 (file)
@@ -164,7 +164,7 @@ static struct snd_soc_ops spitz_ops = {
 static int spitz_get_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = spitz_jack_func;
+       ucontrol->value.enumerated.item[0] = spitz_jack_func;
        return 0;
 }
 
@@ -173,10 +173,10 @@ static int spitz_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (spitz_jack_func == ucontrol->value.integer.value[0])
+       if (spitz_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       spitz_jack_func = ucontrol->value.integer.value[0];
+       spitz_jack_func = ucontrol->value.enumerated.item[0];
        spitz_ext_control(&card->dapm);
        return 1;
 }
@@ -184,7 +184,7 @@ static int spitz_set_jack(struct snd_kcontrol *kcontrol,
 static int spitz_get_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = spitz_spk_func;
+       ucontrol->value.enumerated.item[0] = spitz_spk_func;
        return 0;
 }
 
@@ -193,10 +193,10 @@ static int spitz_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (spitz_spk_func == ucontrol->value.integer.value[0])
+       if (spitz_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       spitz_spk_func = ucontrol->value.integer.value[0];
+       spitz_spk_func = ucontrol->value.enumerated.item[0];
        spitz_ext_control(&card->dapm);
        return 1;
 }
index 49518dd642aa18ffd3f0004fe2f425210e820b54..c508f024ecfbc206887aeb9f91943311a279aed7 100644 (file)
@@ -95,7 +95,7 @@ static struct snd_soc_ops tosa_ops = {
 static int tosa_get_jack(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = tosa_jack_func;
+       ucontrol->value.enumerated.item[0] = tosa_jack_func;
        return 0;
 }
 
@@ -104,10 +104,10 @@ static int tosa_set_jack(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (tosa_jack_func == ucontrol->value.integer.value[0])
+       if (tosa_jack_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       tosa_jack_func = ucontrol->value.integer.value[0];
+       tosa_jack_func = ucontrol->value.enumerated.item[0];
        tosa_ext_control(&card->dapm);
        return 1;
 }
@@ -115,7 +115,7 @@ static int tosa_set_jack(struct snd_kcontrol *kcontrol,
 static int tosa_get_spk(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.integer.value[0] = tosa_spk_func;
+       ucontrol->value.enumerated.item[0] = tosa_spk_func;
        return 0;
 }
 
@@ -124,10 +124,10 @@ static int tosa_set_spk(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
 
-       if (tosa_spk_func == ucontrol->value.integer.value[0])
+       if (tosa_spk_func == ucontrol->value.enumerated.item[0])
                return 0;
 
-       tosa_spk_func = ucontrol->value.integer.value[0];
+       tosa_spk_func = ucontrol->value.enumerated.item[0];
        tosa_ext_control(&card->dapm);
        return 1;
 }
index 00b6c9d039cfada651dad6e917be9318dc4ce762..e5101e0d2d372262f8ecf7d0498240cba971b86f 100644 (file)
@@ -355,7 +355,6 @@ static struct regmap_config lpass_cpu_regmap_config = {
        .readable_reg = lpass_cpu_regmap_readable,
        .volatile_reg = lpass_cpu_regmap_volatile,
        .cache_type = REGCACHE_FLAT,
-       .val_format_endian = REGMAP_ENDIAN_LITTLE,
 };
 
 int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
index 84d9e77c0fbe1e8d5e737d26beb492c3ce85883b..70a2559b63f9050bcbb86049717518d022463e2f 100644 (file)
@@ -481,10 +481,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
        unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off;
        unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;
        u32 mod, mask, val = 0;
+       unsigned long flags;
 
-       spin_lock(i2s->lock);
+       spin_lock_irqsave(i2s->lock, flags);
        mod = readl(i2s->addr + I2SMOD);
-       spin_unlock(i2s->lock);
+       spin_unlock_irqrestore(i2s->lock, flags);
 
        switch (clk_id) {
        case SAMSUNG_I2S_OPCLK:
@@ -575,11 +576,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       spin_lock(i2s->lock);
+       spin_lock_irqsave(i2s->lock, flags);
        mod = readl(i2s->addr + I2SMOD);
        mod = (mod & ~mask) | val;
        writel(mod, i2s->addr + I2SMOD);
-       spin_unlock(i2s->lock);
+       spin_unlock_irqrestore(i2s->lock, flags);
 
        return 0;
 }
@@ -590,6 +591,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
        struct i2s_dai *i2s = to_info(dai);
        int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave;
        u32 mod, tmp = 0;
+       unsigned long flags;
 
        lrp_shift = i2s->variant_regs->lrp_off;
        sdf_shift = i2s->variant_regs->sdf_off;
@@ -649,7 +651,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       spin_lock(i2s->lock);
+       spin_lock_irqsave(i2s->lock, flags);
        mod = readl(i2s->addr + I2SMOD);
        /*
         * Don't change the I2S mode if any controller is active on this
@@ -657,7 +659,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
         */
        if (any_active(i2s) &&
                ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) {
-               spin_unlock(i2s->lock);
+               spin_unlock_irqrestore(i2s->lock, flags);
                dev_err(&i2s->pdev->dev,
                                "%s:%d Other DAI busy\n", __func__, __LINE__);
                return -EAGAIN;
@@ -666,7 +668,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
        mod &= ~(sdf_mask | lrp_rlow | mod_slave);
        mod |= tmp;
        writel(mod, i2s->addr + I2SMOD);
-       spin_unlock(i2s->lock);
+       spin_unlock_irqrestore(i2s->lock, flags);
 
        return 0;
 }
@@ -676,6 +678,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 {
        struct i2s_dai *i2s = to_info(dai);
        u32 mod, mask = 0, val = 0;
+       unsigned long flags;
 
        if (!is_secondary(i2s))
                mask |= (MOD_DC2_EN | MOD_DC1_EN);
@@ -744,11 +747,11 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       spin_lock(i2s->lock);
+       spin_lock_irqsave(i2s->lock, flags);
        mod = readl(i2s->addr + I2SMOD);
        mod = (mod & ~mask) | val;
        writel(mod, i2s->addr + I2SMOD);
-       spin_unlock(i2s->lock);
+       spin_unlock_irqrestore(i2s->lock, flags);
 
        samsung_asoc_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
 
index 0d37079879002d472c538b69ccc3321c0d7772ad..581175a51ecf730bb8c6a2271d137f049c2a445d 100644 (file)
@@ -3573,7 +3573,7 @@ static int snd_soc_dapm_dai_link_get(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_dapm_widget *w = snd_kcontrol_chip(kcontrol);
 
-       ucontrol->value.integer.value[0] = w->params_select;
+       ucontrol->value.enumerated.item[0] = w->params_select;
 
        return 0;
 }
@@ -3587,13 +3587,13 @@ static int snd_soc_dapm_dai_link_put(struct snd_kcontrol *kcontrol,
        if (w->power)
                return -EBUSY;
 
-       if (ucontrol->value.integer.value[0] == w->params_select)
+       if (ucontrol->value.enumerated.item[0] == w->params_select)
                return 0;
 
-       if (ucontrol->value.integer.value[0] >= w->num_params)
+       if (ucontrol->value.enumerated.item[0] >= w->num_params)
                return -EINVAL;
 
-       w->params_select = ucontrol->value.integer.value[0];
+       w->params_select = ucontrol->value.enumerated.item[0];
 
        return 0;
 }
index 4f6ce1cac8e20ef8b504073a6dfcc6236c0cf90c..c458d60d50300823e03e39109b715c94bf44cbbf 100644 (file)
@@ -1124,6 +1124,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
        case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
        case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
        case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
+       case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
        case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
        case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
        case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
index 4a96473b180f938b038d5e698f3578876eb7c70c..ee566e8bd1cff56efde9200bf4a76caa840669f1 100644 (file)
@@ -85,7 +85,7 @@ $(OUTPUT)%.i: %.c FORCE
        $(call rule_mkdir)
        $(call if_changed_dep,cc_i_c)
 
-$(OUTPUT)%.i: %.S FORCE
+$(OUTPUT)%.s: %.S FORCE
        $(call rule_mkdir)
        $(call if_changed_dep,cc_i_c)
 
index 02db3cdff20ff7653c8ca0db21d28ef7b508a9eb..6b7707270aa3b19791c8b6248f90ecddeabc1fdd 100644 (file)
@@ -27,7 +27,7 @@ endef
 #   the rule that uses them - an example for that is the 'bionic'
 #   feature check. ]
 #
-FEATURE_TESTS ?=                       \
+FEATURE_TESTS_BASIC :=                 \
        backtrace                       \
        dwarf                           \
        fortify-source                  \
@@ -46,6 +46,7 @@ FEATURE_TESTS ?=                      \
        libpython                       \
        libpython-version               \
        libslang                        \
+       libcrypto                       \
        libunwind                       \
        pthread-attr-setaffinity-np     \
        stackprotector-all              \
@@ -56,6 +57,25 @@ FEATURE_TESTS ?=                     \
        get_cpuid                       \
        bpf
 
+# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
+# of all feature tests
+FEATURE_TESTS_EXTRA :=                 \
+       bionic                          \
+       compile-32                      \
+       compile-x32                     \
+       cplus-demangle                  \
+       hello                           \
+       libbabeltrace                   \
+       liberty                         \
+       liberty-z                       \
+       libunwind-debug-frame
+
+FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
+
+ifeq ($(FEATURE_TESTS),all)
+  FEATURE_TESTS := $(FEATURE_TESTS_BASIC) $(FEATURE_TESTS_EXTRA)
+endif
+
 FEATURE_DISPLAY ?=                     \
        dwarf                           \
        glibc                           \
@@ -68,6 +88,7 @@ FEATURE_DISPLAY ?=                    \
        libperl                         \
        libpython                       \
        libslang                        \
+       libcrypto                       \
        libunwind                       \
        libdw-dwarf-unwind              \
        zlib                            \
@@ -100,6 +121,14 @@ ifeq ($(feature-all), 1)
   # test-all.c passed - just set all the core feature flags to 1:
   #
   $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat)))
+  #
+  # test-all.c does not comprise these tests, so we need to
+  # for this case to get features proper values
+  #
+  $(call feature_check,compile-32)
+  $(call feature_check,compile-x32)
+  $(call feature_check,bionic)
+  $(call feature_check,libbabeltrace)
 else
   $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))
 endif
index bf8f0352264dcc8a5a1286bc4add2ca9de481357..c5f4c417428d7099fbe4f487a179b0663f478611 100644 (file)
@@ -23,6 +23,7 @@ FILES=                                        \
        test-libpython.bin              \
        test-libpython-version.bin      \
        test-libslang.bin               \
+       test-libcrypto.bin              \
        test-libunwind.bin              \
        test-libunwind-debug-frame.bin  \
        test-pthread-attr-setaffinity-np.bin    \
@@ -105,6 +106,9 @@ $(OUTPUT)test-libaudit.bin:
 $(OUTPUT)test-libslang.bin:
        $(BUILD) -I/usr/include/slang -lslang
 
+$(OUTPUT)test-libcrypto.bin:
+       $(BUILD) -lcrypto
+
 $(OUTPUT)test-gtk2.bin:
        $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
 
index 81025cade45fa9a3fcc6f8f0aacc8f403e6d9211..e499a36c1e4a9e21e9c355309b53a7dc5901664a 100644 (file)
 # include "test-bpf.c"
 #undef main
 
+#define main main_test_libcrypto
+# include "test-libcrypto.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
        main_test_libpython();
@@ -158,6 +162,7 @@ int main(int argc, char *argv[])
        main_test_lzma();
        main_test_get_cpuid();
        main_test_bpf();
+       main_test_libcrypto();
 
        return 0;
 }
index 31dbf45bf99c5996ca0ee62cba186d912b08e666..c54e6551ae4c54cd6e9f418e6e8ff97280444efd 100644 (file)
@@ -1,4 +1,6 @@
+#include <stdio.h>
 int main(void)
 {
+       printf("Hello World!\n");
        return 0;
 }
diff --git a/tools/build/feature/test-libcrypto.c b/tools/build/feature/test-libcrypto.c
new file mode 100644 (file)
index 0000000..bd79dc7
--- /dev/null
@@ -0,0 +1,17 @@
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+
+int main(void)
+{
+       MD5_CTX context;
+       unsigned char md[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH];
+       unsigned char dat[] = "12345";
+
+       MD5_Init(&context);
+       MD5_Update(&context, &dat[0], sizeof(dat));
+       MD5_Final(&md[0], &context);
+
+       SHA1(&dat[0], sizeof(dat), &md[0]);
+
+       return 0;
+}
index e8b8a23b9bf4cdac8ccfcf95690f8dfd93e1d6e6..954c644f7ad9e5ee0f54bdf16cf2b68766f1e2a5 100644 (file)
@@ -1,3 +1,4 @@
 libapi-y += fd/
 libapi-y += fs/
 libapi-y += cpu.o
+libapi-y += debug.o
index d85904dc9b38747dc0feda60f819cf93ceabbdcf..bbc82c614bee62eec8563c5b1dd9fd222eafa5de 100644 (file)
@@ -18,6 +18,7 @@ LIBFILE = $(OUTPUT)libapi.a
 CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
 CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+CFLAGS += -I$(srctree)/tools/lib/api
 
 RM = rm -f
 
diff --git a/tools/lib/api/debug-internal.h b/tools/lib/api/debug-internal.h
new file mode 100644 (file)
index 0000000..188f788
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __API_DEBUG_INTERNAL_H__
+#define __API_DEBUG_INTERNAL_H__
+
+#include "debug.h"
+
+#define __pr(func, fmt, ...)   \
+do {                           \
+       if ((func))             \
+               (func)("libapi: " fmt, ##__VA_ARGS__); \
+} while (0)
+
+extern libapi_print_fn_t __pr_warning;
+extern libapi_print_fn_t __pr_info;
+extern libapi_print_fn_t __pr_debug;
+
+#define pr_warning(fmt, ...)   __pr(__pr_warning, fmt, ##__VA_ARGS__)
+#define pr_info(fmt, ...)      __pr(__pr_info, fmt, ##__VA_ARGS__)
+#define pr_debug(fmt, ...)     __pr(__pr_debug, fmt, ##__VA_ARGS__)
+
+#endif /* __API_DEBUG_INTERNAL_H__ */
diff --git a/tools/lib/api/debug.c b/tools/lib/api/debug.c
new file mode 100644 (file)
index 0000000..5fa5cf5
--- /dev/null
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include "debug.h"
+#include "debug-internal.h"
+
+static int __base_pr(const char *format, ...)
+{
+       va_list args;
+       int err;
+
+       va_start(args, format);
+       err = vfprintf(stderr, format, args);
+       va_end(args);
+       return err;
+}
+
+libapi_print_fn_t __pr_warning = __base_pr;
+libapi_print_fn_t __pr_info    = __base_pr;
+libapi_print_fn_t __pr_debug;
+
+void libapi_set_print(libapi_print_fn_t warn,
+                     libapi_print_fn_t info,
+                     libapi_print_fn_t debug)
+{
+       __pr_warning = warn;
+       __pr_info    = info;
+       __pr_debug   = debug;
+}
diff --git a/tools/lib/api/debug.h b/tools/lib/api/debug.h
new file mode 100644 (file)
index 0000000..a0872f6
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __API_DEBUG_H__
+#define __API_DEBUG_H__
+
+typedef int (*libapi_print_fn_t)(const char *, ...);
+
+void libapi_set_print(libapi_print_fn_t warn,
+                     libapi_print_fn_t info,
+                     libapi_print_fn_t debug);
+
+#endif /* __API_DEBUG_H__ */
index 459599d1b6c410b7b41333c13f248ee685c2dd4a..ef78c22ff44d4142f01a1f5aea3bbe4e15fd0101 100644 (file)
@@ -13,6 +13,7 @@
 #include <sys/mount.h>
 
 #include "fs.h"
+#include "debug-internal.h"
 
 #define _STR(x) #x
 #define STR(x) _STR(x)
@@ -300,6 +301,56 @@ int filename__read_ull(const char *filename, unsigned long long *value)
        return err;
 }
 
+#define STRERR_BUFSIZE  128     /* For the buffer size of strerror_r */
+
+int filename__read_str(const char *filename, char **buf, size_t *sizep)
+{
+       size_t size = 0, alloc_size = 0;
+       void *bf = NULL, *nbf;
+       int fd, n, err = 0;
+       char sbuf[STRERR_BUFSIZE];
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0)
+               return -errno;
+
+       do {
+               if (size == alloc_size) {
+                       alloc_size += BUFSIZ;
+                       nbf = realloc(bf, alloc_size);
+                       if (!nbf) {
+                               err = -ENOMEM;
+                               break;
+                       }
+
+                       bf = nbf;
+               }
+
+               n = read(fd, bf + size, alloc_size - size);
+               if (n < 0) {
+                       if (size) {
+                               pr_warning("read failed %d: %s\n", errno,
+                                        strerror_r(errno, sbuf, sizeof(sbuf)));
+                               err = 0;
+                       } else
+                               err = -errno;
+
+                       break;
+               }
+
+               size += n;
+       } while (n > 0);
+
+       if (!err) {
+               *sizep = size;
+               *buf   = bf;
+       } else
+               free(bf);
+
+       close(fd);
+       return err;
+}
+
 int sysfs__read_ull(const char *entry, unsigned long long *value)
 {
        char path[PATH_MAX];
@@ -326,6 +377,19 @@ int sysfs__read_int(const char *entry, int *value)
        return filename__read_int(path, value);
 }
 
+int sysfs__read_str(const char *entry, char **buf, size_t *sizep)
+{
+       char path[PATH_MAX];
+       const char *sysfs = sysfs__mountpoint();
+
+       if (!sysfs)
+               return -1;
+
+       snprintf(path, sizeof(path), "%s/%s", sysfs, entry);
+
+       return filename__read_str(path, buf, sizep);
+}
+
 int sysctl__read_int(const char *sysctl, int *value)
 {
        char path[PATH_MAX];
index d024a7f682f69b27a4bba1aed7b8f1894d07b50f..9f6598098dc5804a5bf660013ad5b07c499b6169 100644 (file)
@@ -2,6 +2,7 @@
 #define __API_FS__
 
 #include <stdbool.h>
+#include <unistd.h>
 
 /*
  * On most systems <limits.h> would have given us this, but  not on some systems
@@ -26,8 +27,10 @@ FS(tracefs)
 
 int filename__read_int(const char *filename, int *value);
 int filename__read_ull(const char *filename, unsigned long long *value);
+int filename__read_str(const char *filename, char **buf, size_t *sizep);
 
 int sysctl__read_int(const char *sysctl, int *value);
 int sysfs__read_int(const char *entry, int *value);
 int sysfs__read_ull(const char *entry, unsigned long long *value);
+int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
 #endif /* __API_FS__ */
index 8334a5a9d5d7f55e97144e1d7462c52deec02e02..7e543c3102d4118a09717bb6fb4c0f779532ae91 100644 (file)
@@ -201,6 +201,7 @@ struct bpf_object {
                        Elf_Data *data;
                } *reloc;
                int nr_reloc;
+               int maps_shndx;
        } efile;
        /*
         * All loaded bpf_object is linked in a list, which is
@@ -350,6 +351,7 @@ static struct bpf_object *bpf_object__new(const char *path,
         */
        obj->efile.obj_buf = obj_buf;
        obj->efile.obj_buf_sz = obj_buf_sz;
+       obj->efile.maps_shndx = -1;
 
        obj->loaded = false;
 
@@ -529,12 +531,12 @@ bpf_object__init_maps(struct bpf_object *obj, void *data,
 }
 
 static int
-bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
+bpf_object__init_maps_name(struct bpf_object *obj)
 {
        int i;
        Elf_Data *symbols = obj->efile.symbols;
 
-       if (!symbols || maps_shndx < 0)
+       if (!symbols || obj->efile.maps_shndx < 0)
                return -EINVAL;
 
        for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) {
@@ -544,7 +546,7 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx)
 
                if (!gelf_getsym(symbols, i, &sym))
                        continue;
-               if (sym.st_shndx != maps_shndx)
+               if (sym.st_shndx != obj->efile.maps_shndx)
                        continue;
 
                map_name = elf_strptr(obj->efile.elf,
@@ -572,7 +574,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
        Elf *elf = obj->efile.elf;
        GElf_Ehdr *ep = &obj->efile.ehdr;
        Elf_Scn *scn = NULL;
-       int idx = 0, err = 0, maps_shndx = -1;
+       int idx = 0, err = 0;
 
        /* Elf is corrupted/truncated, avoid calling elf_strptr. */
        if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) {
@@ -625,7 +627,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
                else if (strcmp(name, "maps") == 0) {
                        err = bpf_object__init_maps(obj, data->d_buf,
                                                    data->d_size);
-                       maps_shndx = idx;
+                       obj->efile.maps_shndx = idx;
                } else if (sh.sh_type == SHT_SYMTAB) {
                        if (obj->efile.symbols) {
                                pr_warning("bpf: multiple SYMTAB in %s\n",
@@ -674,8 +676,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
                pr_warning("Corrupted ELF file: index of strtab invalid\n");
                return LIBBPF_ERRNO__FORMAT;
        }
-       if (maps_shndx >= 0)
-               err = bpf_object__init_maps_name(obj, maps_shndx);
+       if (obj->efile.maps_shndx >= 0)
+               err = bpf_object__init_maps_name(obj);
 out:
        return err;
 }
@@ -697,7 +699,8 @@ bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx)
 static int
 bpf_program__collect_reloc(struct bpf_program *prog,
                           size_t nr_maps, GElf_Shdr *shdr,
-                          Elf_Data *data, Elf_Data *symbols)
+                          Elf_Data *data, Elf_Data *symbols,
+                          int maps_shndx)
 {
        int i, nrels;
 
@@ -724,9 +727,6 @@ bpf_program__collect_reloc(struct bpf_program *prog,
                        return -LIBBPF_ERRNO__FORMAT;
                }
 
-               insn_idx = rel.r_offset / sizeof(struct bpf_insn);
-               pr_debug("relocation: insn_idx=%u\n", insn_idx);
-
                if (!gelf_getsym(symbols,
                                 GELF_R_SYM(rel.r_info),
                                 &sym)) {
@@ -735,6 +735,15 @@ bpf_program__collect_reloc(struct bpf_program *prog,
                        return -LIBBPF_ERRNO__FORMAT;
                }
 
+               if (sym.st_shndx != maps_shndx) {
+                       pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n",
+                                  prog->section_name, sym.st_shndx);
+                       return -LIBBPF_ERRNO__RELOC;
+               }
+
+               insn_idx = rel.r_offset / sizeof(struct bpf_insn);
+               pr_debug("relocation: insn_idx=%u\n", insn_idx);
+
                if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
                        pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n",
                                   insn_idx, insns[insn_idx].code);
@@ -863,7 +872,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 
                err = bpf_program__collect_reloc(prog, nr_maps,
                                                 shdr, data,
-                                                obj->efile.symbols);
+                                                obj->efile.symbols,
+                                                obj->efile.maps_shndx);
                if (err)
                        return err;
        }
index 90d2baeb621a5265f703ecc0e3bc0cbde60ac1f4..1d57af56814b8671c10d9619202f042ad5c031d4 100644 (file)
@@ -100,7 +100,7 @@ include $(srctree)/tools/build/Makefile.include
 
 do_compile_shared_library =                    \
        ($(print_shared_lib_compile)            \
-       $(CC) --shared $^ -o $@ -lpthread -ldl -Wl,-soname='"$@"';$(shell ln -s $@ liblockdep.so))
+       $(CC) --shared $^ -o $@ -lpthread -ldl -Wl,-soname='"$@"';$(shell ln -sf $@ liblockdep.so))
 
 do_build_static_lib =                          \
        ($(print_static_lib_build)              \
index 9be663340f0a4c48e9ec51c996b13c3a8b596fdc..d1c89cc06f5f6710471c42dc5b2a475a54ee7658 100644 (file)
@@ -11,11 +11,6 @@ static __thread struct task_struct current_obj;
 bool debug_locks = true;
 bool debug_locks_silent;
 
-__attribute__((constructor)) static void liblockdep_init(void)
-{
-       lockdep_init();
-}
-
 __attribute__((destructor)) static void liblockdep_exit(void)
 {
        debug_check_no_locks_held();
index a60c14b9662aefd6f17b47dec534bce2f53d9f03..6e66277ec4375c84693b25756fdf8336faf79fcf 100644 (file)
@@ -44,7 +44,6 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 void lock_release(struct lockdep_map *lock, int nested,
                        unsigned long ip);
 extern void debug_check_no_locks_freed(const void *from, unsigned long len);
-extern void lockdep_init(void);
 
 #define STATIC_LOCKDEP_MAP_INIT(_name, _key) \
        { .name = (_name), .key = (void *)(_key), }
index f42b7e9aa48f2661fb94fced614db8f443eca9c4..a0a2e3a266af8122fed3d66b3f5a537ab3c1c773 100644 (file)
@@ -1,2 +1,8 @@
 #include <linux/lockdep.h>
+
+/* Trivial API wrappers, we don't (yet) have RCU in user-space: */
+#define hlist_for_each_entry_rcu       hlist_for_each_entry
+#define hlist_add_head_rcu             hlist_add_head
+#define hlist_del_rcu                  hlist_del
+
 #include "../../../kernel/locking/lockdep.c"
index 21cdf869a01b8b7facc084c4dc66cf73afa163bb..52844847569c99b878c031da8f25a13d1c0b5838 100644 (file)
@@ -439,7 +439,5 @@ __attribute__((constructor)) static void init_preload(void)
        ll_pthread_rwlock_unlock = dlsym(RTLD_NEXT, "pthread_rwlock_unlock");
 #endif
 
-       lockdep_init();
-
        __init_state = done;
 }
index 0f782ff404ac65999c8689555967eabb9c6f0e52..18211a5f354fe53e2a0650fe1ca9150956fd5b7a 100644 (file)
@@ -1,13 +1,13 @@
 #include <liblockdep/mutex.h>
 
-void main(void)
+int main(void)
 {
-       pthread_mutex_t a, b;
+       pthread_mutex_t a;
 
        pthread_mutex_init(&a, NULL);
-       pthread_mutex_init(&b, NULL);
 
        pthread_mutex_lock(&a);
-       pthread_mutex_lock(&b);
        pthread_mutex_lock(&a);
+
+       return 0;
 }
diff --git a/tools/lib/lockdep/tests/ABA.c b/tools/lib/lockdep/tests/ABA.c
new file mode 100644 (file)
index 0000000..0f782ff
--- /dev/null
@@ -0,0 +1,13 @@
+#include <liblockdep/mutex.h>
+
+void main(void)
+{
+       pthread_mutex_t a, b;
+
+       pthread_mutex_init(&a, NULL);
+       pthread_mutex_init(&b, NULL);
+
+       pthread_mutex_lock(&a);
+       pthread_mutex_lock(&b);
+       pthread_mutex_lock(&a);
+}
diff --git a/tools/lib/lockdep/tests/ABBA_2threads.c b/tools/lib/lockdep/tests/ABBA_2threads.c
new file mode 100644 (file)
index 0000000..cd807d7
--- /dev/null
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <pthread.h>
+
+pthread_mutex_t a = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t b = PTHREAD_MUTEX_INITIALIZER;
+pthread_barrier_t bar;
+
+void *ba_lock(void *arg)
+{
+       int ret, i;
+
+       pthread_mutex_lock(&b);
+
+       if (pthread_barrier_wait(&bar) == PTHREAD_BARRIER_SERIAL_THREAD)
+               pthread_barrier_destroy(&bar);
+
+       pthread_mutex_lock(&a);
+
+       pthread_mutex_unlock(&a);
+       pthread_mutex_unlock(&b);
+}
+
+int main(void)
+{
+       pthread_t t;
+
+       pthread_barrier_init(&bar, NULL, 2);
+
+       if (pthread_create(&t, NULL, ba_lock, NULL)) {
+               fprintf(stderr, "pthread_create() failed\n");
+               return 1;
+       }
+       pthread_mutex_lock(&a);
+
+       if (pthread_barrier_wait(&bar) == PTHREAD_BARRIER_SERIAL_THREAD)
+               pthread_barrier_destroy(&bar);
+
+       pthread_mutex_lock(&b);
+
+       pthread_mutex_unlock(&b);
+       pthread_mutex_unlock(&a);
+
+       pthread_join(t, NULL);
+
+       return 0;
+}
index 6386dc3182a0985a40551d0af980e53102e04c2a..fd3e56a83fc27025a9016cae2eaf1882c751cc01 100644 (file)
@@ -3,6 +3,7 @@
 
 #define __used         __attribute__((__unused__))
 #define unlikely
+#define READ_ONCE(x) (x)
 #define WRITE_ONCE(x, val) x=(val)
 #define RCU_INIT_POINTER(p, v) p=(v)
 
index c3bd294a63d1f7e4a75b2a950bbe398f33703cd6..190cc886ab9105ea6be58ad58caf8e940274c4a9 100644 (file)
@@ -1951,6 +1951,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
                   strcmp(token, "*") == 0 ||
                   strcmp(token, "^") == 0 ||
                   strcmp(token, "/") == 0 ||
+                  strcmp(token, "%") == 0 ||
                   strcmp(token, "<") == 0 ||
                   strcmp(token, ">") == 0 ||
                   strcmp(token, "<=") == 0 ||
@@ -2397,6 +2398,12 @@ static int arg_num_eval(struct print_arg *arg, long long *val)
                                break;
                        *val = left + right;
                        break;
+               case '~':
+                       ret = arg_num_eval(arg->op.right, &right);
+                       if (!ret)
+                               break;
+                       *val = ~right;
+                       break;
                default:
                        do_warning("unknown op '%s'", arg->op.op);
                        ret = 0;
@@ -2634,6 +2641,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok)
 
 free_field:
        free_arg(arg->hex.field);
+       arg->hex.field = NULL;
 out:
        *tok = NULL;
        return EVENT_ERROR;
@@ -2658,8 +2666,10 @@ process_int_array(struct event_format *event, struct print_arg *arg, char **tok)
 
 free_size:
        free_arg(arg->int_array.count);
+       arg->int_array.count = NULL;
 free_field:
        free_arg(arg->int_array.field);
+       arg->int_array.field = NULL;
 out:
        *tok = NULL;
        return EVENT_ERROR;
@@ -3689,6 +3699,9 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                case '/':
                        val = left / right;
                        break;
+               case '%':
+                       val = left % right;
+                       break;
                case '*':
                        val = left * right;
                        break;
@@ -4971,7 +4984,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
                                                break;
                                        }
                                }
-                               if (pevent->long_size == 8 && ls &&
+                               if (pevent->long_size == 8 && ls == 1 &&
                                    sizeof(long) != 8) {
                                        char *p;
 
@@ -5335,41 +5348,45 @@ static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
        return false;
 }
 
-void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
-                       struct pevent_record *record, bool use_trace_clock)
+/**
+ * pevent_find_event_by_record - return the event from a given record
+ * @pevent: a handle to the pevent
+ * @record: The record to get the event from
+ *
+ * Returns the associated event for a given record, or NULL if non is
+ * is found.
+ */
+struct event_format *
+pevent_find_event_by_record(struct pevent *pevent, struct pevent_record *record)
 {
-       static const char *spaces = "                    "; /* 20 spaces */
-       struct event_format *event;
-       unsigned long secs;
-       unsigned long usecs;
-       unsigned long nsecs;
-       const char *comm;
-       void *data = record->data;
        int type;
-       int pid;
-       int len;
-       int p;
-       bool use_usec_format;
-
-       use_usec_format = is_timestamp_in_us(pevent->trace_clock,
-                                                       use_trace_clock);
-       if (use_usec_format) {
-               secs = record->ts / NSECS_PER_SEC;
-               nsecs = record->ts - secs * NSECS_PER_SEC;
-       }
 
        if (record->size < 0) {
                do_warning("ug! negative record size %d", record->size);
-               return;
+               return NULL;
        }
 
-       type = trace_parse_common_type(pevent, data);
+       type = trace_parse_common_type(pevent, record->data);
 
-       event = pevent_find_event(pevent, type);
-       if (!event) {
-               do_warning("ug! no event found for type %d", type);
-               return;
-       }
+       return pevent_find_event(pevent, type);
+}
+
+/**
+ * pevent_print_event_task - Write the event task comm, pid and CPU
+ * @pevent: a handle to the pevent
+ * @s: the trace_seq to write to
+ * @event: the handle to the record's event
+ * @record: The record to get the event from
+ *
+ * Writes the tasks comm, pid and CPU to @s.
+ */
+void pevent_print_event_task(struct pevent *pevent, struct trace_seq *s,
+                            struct event_format *event,
+                            struct pevent_record *record)
+{
+       void *data = record->data;
+       const char *comm;
+       int pid;
 
        pid = parse_common_pid(pevent, data);
        comm = find_cmdline(pevent, pid);
@@ -5377,9 +5394,43 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
        if (pevent->latency_format) {
                trace_seq_printf(s, "%8.8s-%-5d %3d",
                       comm, pid, record->cpu);
-               pevent_data_lat_fmt(pevent, s, record);
        } else
                trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
+}
+
+/**
+ * pevent_print_event_time - Write the event timestamp
+ * @pevent: a handle to the pevent
+ * @s: the trace_seq to write to
+ * @event: the handle to the record's event
+ * @record: The record to get the event from
+ * @use_trace_clock: Set to parse according to the @pevent->trace_clock
+ *
+ * Writes the timestamp of the record into @s.
+ */
+void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
+                            struct event_format *event,
+                            struct pevent_record *record,
+                            bool use_trace_clock)
+{
+       unsigned long secs;
+       unsigned long usecs;
+       unsigned long nsecs;
+       int p;
+       bool use_usec_format;
+
+       use_usec_format = is_timestamp_in_us(pevent->trace_clock,
+                                                       use_trace_clock);
+       if (use_usec_format) {
+               secs = record->ts / NSECS_PER_SEC;
+               nsecs = record->ts - secs * NSECS_PER_SEC;
+       }
+
+       if (pevent->latency_format) {
+               trace_seq_printf(s, " %3d", record->cpu);
+               pevent_data_lat_fmt(pevent, s, record);
+       } else
+               trace_seq_printf(s, " [%03d]", record->cpu);
 
        if (use_usec_format) {
                if (pevent->flags & PEVENT_NSEC_OUTPUT) {
@@ -5387,14 +5438,36 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
                        p = 9;
                } else {
                        usecs = (nsecs + 500) / NSECS_PER_USEC;
+                       /* To avoid usecs larger than 1 sec */
+                       if (usecs >= 1000000) {
+                               usecs -= 1000000;
+                               secs++;
+                       }
                        p = 6;
                }
 
-               trace_seq_printf(s, " %5lu.%0*lu: %s: ",
-                                       secs, p, usecs, event->name);
+               trace_seq_printf(s, " %5lu.%0*lu:", secs, p, usecs);
        } else
-               trace_seq_printf(s, " %12llu: %s: ",
-                                       record->ts, event->name);
+               trace_seq_printf(s, " %12llu:", record->ts);
+}
+
+/**
+ * pevent_print_event_data - Write the event data section
+ * @pevent: a handle to the pevent
+ * @s: the trace_seq to write to
+ * @event: the handle to the record's event
+ * @record: The record to get the event from
+ *
+ * Writes the parsing of the record's data to @s.
+ */
+void pevent_print_event_data(struct pevent *pevent, struct trace_seq *s,
+                            struct event_format *event,
+                            struct pevent_record *record)
+{
+       static const char *spaces = "                    "; /* 20 spaces */
+       int len;
+
+       trace_seq_printf(s, " %s: ", event->name);
 
        /* Space out the event names evenly. */
        len = strlen(event->name);
@@ -5404,6 +5477,23 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
        pevent_event_info(s, event, record);
 }
 
+void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
+                       struct pevent_record *record, bool use_trace_clock)
+{
+       struct event_format *event;
+
+       event = pevent_find_event_by_record(pevent, record);
+       if (!event) {
+               do_warning("ug! no event found for type %d",
+                          trace_parse_common_type(pevent, record->data));
+               return;
+       }
+
+       pevent_print_event_task(pevent, s, event, record);
+       pevent_print_event_time(pevent, s, event, record, use_trace_clock);
+       pevent_print_event_data(pevent, s, event, record);
+}
+
 static int events_id_cmp(const void *a, const void *b)
 {
        struct event_format * const * ea = a;
index 706d9bc24066cf308ba17d718eafd95c4ff5550c..9ffde377e89d912ffb2127fe454872346759738b 100644 (file)
@@ -628,6 +628,16 @@ int pevent_register_print_string(struct pevent *pevent, const char *fmt,
                                 unsigned long long addr);
 int pevent_pid_is_registered(struct pevent *pevent, int pid);
 
+void pevent_print_event_task(struct pevent *pevent, struct trace_seq *s,
+                            struct event_format *event,
+                            struct pevent_record *record);
+void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
+                            struct event_format *event,
+                            struct pevent_record *record,
+                            bool use_trace_clock);
+void pevent_print_event_data(struct pevent *pevent, struct trace_seq *s,
+                            struct event_format *event,
+                            struct pevent_record *record);
 void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
                        struct pevent_record *record, bool use_trace_clock);
 
@@ -694,6 +704,9 @@ struct event_format *pevent_find_event(struct pevent *pevent, int id);
 struct event_format *
 pevent_find_event_by_name(struct pevent *pevent, const char *sys, const char *name);
 
+struct event_format *
+pevent_find_event_by_record(struct pevent *pevent, struct pevent_record *record);
+
 void pevent_data_lat_fmt(struct pevent *pevent,
                         struct trace_seq *s, struct pevent_record *record);
 int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
index b9ca1e304158da86f36dafad33e7de0a52e01567..15949e2a7805cc6e7d848ddbf2f99b249e332f3b 100644 (file)
@@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file.
 SYNOPSIS
 --------
 [verse]
-'perf config' -l | --list
+'perf config' [<file-option>] -l | --list
 
 DESCRIPTION
 -----------
@@ -21,6 +21,14 @@ OPTIONS
 --list::
        Show current config variables, name and value, for all sections.
 
+--user::
+       For writing and reading options: write to user
+       '$HOME/.perfconfig' file or read it.
+
+--system::
+       For writing and reading options: write to system-wide
+       '$(sysconfdir)/perfconfig' or read it.
+
 CONFIGURATION FILE
 ------------------
 
@@ -30,6 +38,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration.
 The file '$(sysconfdir)/perfconfig' can be used to
 store a system-wide default configuration.
 
+When reading or writing, the values are read from the system and user
+configuration files by default, and options '--system' and '--user'
+can be used to tell the command to read from or write to only that location.
+
 Syntax
 ~~~~~~
 
@@ -62,7 +74,7 @@ Given a $HOME/.perfconfig like this:
                medium = green, default
                normal = lightgray, default
                selected = white, lightgray
-               code = blue, default
+               jump_arrows = blue, default
                addr = magenta, default
                root = white, blue
 
@@ -98,6 +110,347 @@ Given a $HOME/.perfconfig like this:
                order = caller
                sort-key = function
 
+Variables
+~~~~~~~~~
+
+colors.*::
+       The variables for customizing the colors used in the output for the
+       'report', 'top' and 'annotate' in the TUI. They should specify the
+       foreground and background colors, separated by a comma, for example:
+
+               medium = green, lightgray
+
+       If you want to use the color configured for you terminal, just leave it
+       as 'default', for example:
+
+               medium = default, lightgray
+
+       Available colors:
+       red, yellow, green, cyan, gray, black, blue,
+       white, default, magenta, lightgray
+
+       colors.top::
+               'top' means a overhead percentage which is more than 5%.
+               And values of this variable specify percentage colors.
+               Basic key values are foreground-color 'red' and
+               background-color 'default'.
+       colors.medium::
+               'medium' means a overhead percentage which has more than 0.5%.
+               Default values are 'green' and 'default'.
+       colors.normal::
+               'normal' means the rest of overhead percentages
+               except 'top', 'medium', 'selected'.
+               Default values are 'lightgray' and 'default'.
+       colors.selected::
+               This selects the colors for the current entry in a list of entries
+               from sub-commands (top, report, annotate).
+               Default values are 'black' and 'lightgray'.
+       colors.jump_arrows::
+               Colors for jump arrows on assembly code listings
+               such as 'jns', 'jmp', 'jane', etc.
+               Default values are 'blue', 'default'.
+       colors.addr::
+               This selects colors for addresses from 'annotate'.
+               Default values are 'magenta', 'default'.
+       colors.root::
+               Colors for headers in the output of a sub-commands (top, report).
+               Default values are 'white', 'blue'.
+
+tui.*, gtk.*::
+       Subcommands that can be configured here are 'top', 'report' and 'annotate'.
+       These values are booleans, for example:
+
+       [tui]
+               top = true
+
+       will make the TUI be the default for the 'top' subcommand. Those will be
+       available if the required libs were detected at tool build time.
+
+buildid.*::
+       buildid.dir::
+               Each executable and shared library in modern distributions comes with a
+               content based identifier that, if available, will be inserted in a
+               'perf.data' file header to, at analysis time find what is needed to do
+               symbol resolution, code annotation, etc.
+
+               The recording tools also stores a hard link or copy in a per-user
+               directory, $HOME/.debug/, of binaries, shared libraries, /proc/kallsyms
+               and /proc/kcore files to be used at analysis time.
+
+               The buildid.dir variable can be used to either change this directory
+               cache location, or to disable it altogether. If you want to disable it,
+               set buildid.dir to /dev/null. The default is $HOME/.debug
+
+annotate.*::
+       These options work only for TUI.
+       These are in control of addresses, jump function, source code
+       in lines of assembly code from a specific program.
+
+       annotate.hide_src_code::
+               If a program which is analyzed has source code,
+               this option lets 'annotate' print a list of assembly code with the source code.
+               For example, let's see a part of a program. There're four lines.
+               If this option is 'true', they can be printed
+               without source code from a program as below.
+
+               â”‚        push   %rbp
+               â”‚        mov    %rsp,%rbp
+               â”‚        sub    $0x10,%rsp
+               â”‚        mov    (%rdi),%rdx
+
+               But if this option is 'false', source code of the part
+               can be also printed as below. Default is 'false'.
+
+               â”‚      struct rb_node *rb_next(const struct rb_node *node)
+               â”‚      {
+               â”‚        push   %rbp
+               â”‚        mov    %rsp,%rbp
+               â”‚        sub    $0x10,%rsp
+               â”‚              struct rb_node *parent;
+               â”‚
+               â”‚              if (RB_EMPTY_NODE(node))
+               â”‚        mov    (%rdi),%rdx
+               â”‚              return n;
+
+        annotate.use_offset::
+               Basing on a first address of a loaded function, offset can be used.
+               Instead of using original addresses of assembly code,
+               addresses subtracted from a base address can be printed.
+               Let's illustrate an example.
+               If a base address is 0XFFFFFFFF81624d50 as below,
+
+               ffffffff81624d50 <load0>
+
+               an address on assembly code has a specific absolute address as below
+
+               ffffffff816250b8:│  mov    0x8(%r14),%rdi
+
+               but if use_offset is 'true', an address subtracted from a base address is printed.
+               Default is true. This option is only applied to TUI.
+
+                            368:│  mov    0x8(%r14),%rdi
+
+       annotate.jump_arrows::
+               There can be jump instruction among assembly code.
+               Depending on a boolean value of jump_arrows,
+               arrows can be printed or not which represent
+               where do the instruction jump into as below.
+
+               â”‚     â”Œâ”€â”€jmp    1333
+               â”‚     â”‚  xchg   %ax,%ax
+               â”‚1330:│  mov    %r15,%r10
+               â”‚1333:└─→cmp    %r15,%r14
+
+               If jump_arrow is 'false', the arrows isn't printed as below.
+               Default is 'false'.
+
+               â”‚      â†“ jmp    1333
+               â”‚        xchg   %ax,%ax
+               â”‚1330:   mov    %r15,%r10
+               â”‚1333:   cmp    %r15,%r14
+
+        annotate.show_linenr::
+               When showing source code if this option is 'true',
+               line numbers are printed as below.
+
+               â”‚1628         if (type & PERF_SAMPLE_IDENTIFIER) {
+               â”‚     â†“ jne    508
+               â”‚1628                 data->id = *array;
+               â”‚1629                 array++;
+               â”‚1630         }
+
+               However if this option is 'false', they aren't printed as below.
+               Default is 'false'.
+
+               â”‚             if (type & PERF_SAMPLE_IDENTIFIER) {
+               â”‚     â†“ jne    508
+               â”‚                     data->id = *array;
+               â”‚                     array++;
+               â”‚             }
+
+        annotate.show_nr_jumps::
+               Let's see a part of assembly code.
+
+               â”‚1382:   movb   $0x1,-0x270(%rbp)
+
+               If use this, the number of branches jumping to that address can be printed as below.
+               Default is 'false'.
+
+               â”‚1 1382:   movb   $0x1,-0x270(%rbp)
+
+        annotate.show_total_period::
+               To compare two records on an instruction base, with this option
+               provided, display total number of samples that belong to a line
+               in assembly code. If this option is 'true', total periods are printed
+               instead of percent values as below.
+
+                 302 â”‚      mov    %eax,%eax
+
+               But if this option is 'false', percent values for overhead are printed i.e.
+               Default is 'false'.
+
+               99.93 â”‚      mov    %eax,%eax
+
+hist.*::
+       hist.percentage::
+               This option control the way to calculate overhead of filtered entries -
+               that means the value of this option is effective only if there's a
+               filter (by comm, dso or symbol name). Suppose a following example:
+
+                      Overhead  Symbols
+                      ........  .......
+                       33.33%     foo
+                       33.33%     bar
+                       33.33%     baz
+
+              This is an original overhead and we'll filter out the first 'foo'
+              entry. The value of 'relative' would increase the overhead of 'bar'
+              and 'baz' to 50.00% for each, while 'absolute' would show their
+              current overhead (33.33%).
+
+ui.*::
+       ui.show-headers::
+               This option controls display of column headers (like 'Overhead' and 'Symbol')
+               in 'report' and 'top'. If this option is false, they are hidden.
+               This option is only applied to TUI.
+
+call-graph.*::
+       When sub-commands 'top' and 'report' work with -g/—-children
+       there're options in control of call-graph.
+
+       call-graph.record-mode::
+               The record-mode can be 'fp' (frame pointer), 'dwarf' and 'lbr'.
+               The value of 'dwarf' is effective only if perf detect needed library
+               (libunwind or a recent version of libdw).
+               'lbr' only work for cpus that support it.
+
+       call-graph.dump-size::
+               The size of stack to dump in order to do post-unwinding. Default is 8192 (byte).
+               When using dwarf into record-mode, the default size will be used if omitted.
+
+       call-graph.print-type::
+               The print-types can be graph (graph absolute), fractal (graph relative),
+               flat and folded. This option controls a way to show overhead for each callchain
+               entry. Suppose a following example.
+
+                Overhead  Symbols
+                ........  .......
+                  40.00%  foo
+                          |
+                          ---foo
+                             |
+                             |--50.00%--bar
+                             |          main
+                             |
+                              --50.00%--baz
+                                        main
+
+               This output is a 'fractal' format. The 'foo' came from 'bar' and 'baz' exactly
+               half and half so 'fractal' shows 50.00% for each
+               (meaning that it assumes 100% total overhead of 'foo').
+
+               The 'graph' uses absolute overhead value of 'foo' as total so each of
+               'bar' and 'baz' callchain will have 20.00% of overhead.
+               If 'flat' is used, single column and linear exposure of call chains.
+               'folded' mean call chains are displayed in a line, separated by semicolons.
+
+       call-graph.order::
+               This option controls print order of callchains. The default is
+               'callee' which means callee is printed at top and then followed by its
+               caller and so on. The 'caller' prints it in reverse order.
+
+               If this option is not set and report.children or top.children is
+               set to true (or the equivalent command line option is given),
+               the default value of this option is changed to 'caller' for the
+               execution of 'perf report' or 'perf top'. Other commands will
+               still default to 'callee'.
+
+       call-graph.sort-key::
+               The callchains are merged if they contain same information.
+               The sort-key option determines a way to compare the callchains.
+               A value of 'sort-key' can be 'function' or 'address'.
+               The default is 'function'.
+
+       call-graph.threshold::
+               When there're many callchains it'd print tons of lines. So perf omits
+               small callchains under a certain overhead (threshold) and this option
+               control the threshold. Default is 0.5 (%). The overhead is calculated
+               by value depends on call-graph.print-type.
+
+       call-graph.print-limit::
+               This is a maximum number of lines of callchain printed for a single
+               histogram entry. Default is 0 which means no limitation.
+
+report.*::
+       report.percent-limit::
+               This one is mostly the same as call-graph.threshold but works for
+               histogram entries. Entries having an overhead lower than this
+               percentage will not be printed. Default is '0'. If percent-limit
+               is '10', only entries which have more than 10% of overhead will be
+               printed.
+
+       report.queue-size::
+               This option sets up the maximum allocation size of the internal
+               event queue for ordering events. Default is 0, meaning no limit.
+
+       report.children::
+               'Children' means functions called from another function.
+               If this option is true, 'perf report' cumulates callchains of children
+               and show (accumulated) total overhead as well as 'Self' overhead.
+               Please refer to the 'perf report' manual. The default is 'true'.
+
+       report.group::
+               This option is to show event group information together.
+               Example output with this turned on, notice that there is one column
+               per event in the group, ref-cycles and cycles:
+
+               # group: {ref-cycles,cycles}
+               # ========
+               #
+               # Samples: 7K of event 'anon group { ref-cycles, cycles }'
+               # Event count (approx.): 6876107743
+               #
+               #         Overhead  Command      Shared Object               Symbol
+               # ................  .......  .................  ...................
+               #
+                   99.84%  99.76%  noploop  noploop            [.] main
+                    0.07%   0.00%  noploop  ld-2.15.so         [.] strcmp
+                    0.03%   0.00%  noploop  [kernel.kallsyms]  [k] timerqueue_del
+
+top.*::
+       top.children::
+               Same as 'report.children'. So if it is enabled, the output of 'top'
+               command will have 'Children' overhead column as well as 'Self' overhead
+               column by default.
+               The default is 'true'.
+
+man.*::
+       man.viewer::
+               This option can assign a tool to view manual pages when 'help'
+               subcommand was invoked. Supported tools are 'man', 'woman'
+               (with emacs client) and 'konqueror'. Default is 'man'.
+
+               New man viewer tool can be also added using 'man.<tool>.cmd'
+               or use different path using 'man.<tool>.path' config option.
+
+pager.*::
+       pager.<subcommand>::
+               When the subcommand is run on stdio, determine whether it uses
+               pager or not based on this value. Default is 'unspecified'.
+
+kmem.*::
+       kmem.default::
+               This option decides which allocator is to be analyzed if neither
+               '--slab' nor '--page' option is used. Default is 'slab'.
+
+record.*::
+       record.build-id::
+               This option can be 'cache', 'no-cache' or 'skip'.
+               'cache' is to post-process data and save/update the binaries into
+               the build-id cache (in ~/.debug). This is the default.
+               But if this option is 'no-cache', it will not update the build-id cache.
+               'skip' skips post-processing and does not update the cache.
+
 SEE ALSO
 --------
 linkperf:perf[1]
index 0b1cedeef895369c9c60aa0a1e6cbb718c65c509..87b2588d1cbdee6060a304be4f79015cb5889171 100644 (file)
@@ -53,6 +53,13 @@ include::itrace.txt[]
 --strip::
        Use with --itrace to strip out non-synthesized events.
 
+-j::
+--jit::
+       Process jitdump files by injecting the mmap records corresponding to jitted
+       functions. This option also generates the ELF images for each jitted function
+       found in the jitdumps files captured in the input perf.data file. Use this option
+       if you are monitoring environment using JIT runtimes, such as Java, DART or V8.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
index fbceb631387c31c44002080130b7ff6e282229d3..19aa17532a16709646dc52487c5f686675c2b658 100644 (file)
@@ -341,6 +341,12 @@ Specify vmlinux path which has debuginfo.
 --buildid-all::
 Record build-id of all DSOs regardless whether it's actually hit or not.
 
+--all-kernel::
+Configure all used events to run in kernel space.
+
+--all-user::
+Configure all used events to run in user space.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
index 8a301f6afb37ad855351fcd5fba1644d12dc2529..12113992ac9d0f5ceca0b003cec568717c4208e5 100644 (file)
@@ -117,6 +117,22 @@ OPTIONS
        And default sort keys are changed to comm, dso_from, symbol_from, dso_to
        and symbol_to, see '--branch-stack'.
 
+       If the --mem-mode option is used, the following sort keys are also available
+       (incompatible with --branch-stack):
+       symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline.
+
+       - symbol_daddr: name of data symbol being executed on at the time of sample
+       - dso_daddr: name of library or module containing the data being executed
+       on at the time of the sample
+       - locked: whether the bus was locked at the time of the sample
+       - tlb: type of tlb access for the data at the time of the sample
+       - mem: type of memory access for the data at the time of the sample
+       - snoop: type of snoop (if any) for the data at the time of the sample
+       - dcacheline: the cacheline the data address is on at the time of the sample
+
+       And the default sort keys are changed to local_weight, mem, sym, dso,
+       symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
+
        If the data file has tracepoint event(s), following (dynamic) sort keys
        are also available:
        trace, trace_fields, [<event>.]<field>[/raw]
@@ -151,22 +167,6 @@ OPTIONS
        By default, every sort keys not specified in -F will be appended
        automatically.
 
-       If --mem-mode option is used, following sort keys are also available
-       (incompatible with --branch-stack):
-       symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline.
-
-       - symbol_daddr: name of data symbol being executed on at the time of sample
-       - dso_daddr: name of library or module containing the data being executed
-       on at the time of sample
-       - locked: whether the bus was locked at the time of sample
-       - tlb: type of tlb access for the data at the time of sample
-       - mem: type of memory access for the data at the time of sample
-       - snoop: type of snoop (if any) for the data at the time of sample
-       - dcacheline: the cacheline the data address is on at the time of sample
-
-       And default sort keys are changed to local_weight, mem, sym, dso,
-       symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'.
-
 -p::
 --parent=<regex>::
         A regex filter to identify parent. The parent is a caller of this
@@ -351,7 +351,10 @@ OPTIONS
 
 --percent-limit::
        Do not show entries which have an overhead under that percent.
-       (Default: 0).
+       (Default: 0).  Note that this option also sets the percent limit (threshold)
+       of callchains.  However the default value of callchain threshold is
+       different than the default value of hist entries.  Please see the
+       --call-graph option for details.
 
 --percentage::
        Determine how to display the overhead percentage of filtered entries.
@@ -398,6 +401,9 @@ include::itrace.txt[]
 --raw-trace::
        When displaying traceevent output, do not use print fmt or plugins.
 
+--hierarchy::
+       Enable hierarchical output.
+
 include::callchain-overhead-calculation.txt[]
 
 SEE ALSO
index 52ef7a9d50aacbc3d3fbb0366852457d39718cdf..04f23b404bbc5a7bd4b5bcdfb7e833d79ba1234e 100644 (file)
@@ -69,6 +69,14 @@ report::
 --scale::
        scale/normalize counter values
 
+-d::
+--detailed::
+       print more detailed statistics, can be specified up to 3 times
+
+          -d:          detailed events, L1 and LLC data cache
+        -d -d:     more detailed events, dTLB and iTLB events
+     -d -d -d:     very detailed events, adding prefetch events
+
 -r::
 --repeat=<n>::
        repeat command and print average + stddev (max: 100). 0 means forever.
@@ -139,6 +147,10 @@ Print count deltas every N milliseconds (minimum: 10ms)
 The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals.  Use with caution.
        example: 'perf stat -I 1000 -e cycles -a sleep 5'
 
+--metric-only::
+Only print computed metrics. Print them in a single line.
+Don't show any raw values. Not supported with --per-thread.
+
 --per-socket::
 Aggregate counts per processor socket for system-wide mode measurements.  This
 is a useful mode to detect imbalance between sockets.  To enable this mode,
@@ -211,6 +223,29 @@ $ perf stat -- make -j
 
  Wall-clock time elapsed:   719.554352 msecs
 
+CSV FORMAT
+----------
+
+With -x, perf stat is able to output a not-quite-CSV format output
+Commas in the output are not put into "". To make it easy to parse
+it is recommended to use a different character like -x \;
+
+The fields are in this order:
+
+       - optional usec time stamp in fractions of second (with -I xxx)
+       - optional CPU, core, or socket identifier
+       - optional number of logical CPUs aggregated
+       - counter value
+       - unit of the counter value or empty
+       - event name
+       - run time of counter
+       - percentage of measurement time the counter was running
+       - optional variance if multiple values are collected with -r
+       - optional metric value
+       - optional unit of metric
+
+Additional metrics may be printed with all earlier fields being empty.
+
 SEE ALSO
 --------
 linkperf:perf-top[1], linkperf:perf-list[1]
index b0e60e17db389d89efafa7025cd47fd44fe625c3..19f046f027cd81e42c5696ab3172539baaeb745d 100644 (file)
@@ -233,6 +233,9 @@ Default is to monitor all CPUS.
 --raw-trace::
        When displaying traceevent output, do not use print fmt or plugins.
 
+--hierarchy::
+       Enable hierarchy output.
+
 INTERACTIVE PROMPTING KEYS
 --------------------------
 
index 767ea2436e1cd841a762ee8cdb039ba80a7120b3..1d8d5bc4cd2de6601f926696d5c172b30fa735d4 100644 (file)
@@ -5,7 +5,7 @@
        medium = green, lightgray
        normal = black, lightgray
        selected = lightgray, magenta
-       code = blue, lightgray
+       jump_arrows = blue, lightgray
        addr = magenta, lightgray
 
 [tui]
index e0ce9573b79bd26ddfe8cb4aee6eade061a09a12..5950b5a24efdf6024ca58a2da084d9cd43295c12 100644 (file)
@@ -27,3 +27,4 @@ Skip collecing build-id when recording: perf record -B
 To change sampling frequency to 100 Hz: perf record -F 100
 See assembly instructions with percentage: perf annotate <symbol>
 If you prefer Intel style assembly, try: perf annotate -M intel
+For hierarchical output, try: perf report --hierarchy
index dcd9a70c7193b43b5791058b01a3773da6e0d870..32a64e6190288e5110cfa6de78138aceb955e7af 100644 (file)
@@ -68,6 +68,20 @@ all tags TAGS:
        $(print_msg)
        $(make)
 
+ifdef MAKECMDGOALS
+has_clean := 0
+ifneq ($(filter clean,$(MAKECMDGOALS)),)
+  has_clean := 1
+endif # clean
+
+ifeq ($(has_clean),1)
+  rest := $(filter-out clean,$(MAKECMDGOALS))
+  ifneq ($(rest),)
+$(rest): clean
+  endif # rest
+endif # has_clean
+endif # MAKECMDGOALS
+
 #
 # The clean target is not really parallel, don't print the jobs info:
 #
@@ -75,10 +89,17 @@ clean:
        $(make)
 
 #
-# The build-test target is not really parallel, don't print the jobs info:
+# The build-test target is not really parallel, don't print the jobs info,
+# it also uses only the tests/make targets that don't pollute the source
+# repository, i.e. that uses O= or builds the tarpkg outside the source
+# repo directories.
+#
+# For a full test, use:
+#
+# make -C tools/perf -f tests/make
 #
 build-test:
-       @$(MAKE) SHUF=1 -f tests/make --no-print-directory
+       @$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory tarpkg out
 
 #
 # All other targets get passed through:
index 5d34815c7ccb8e02ac6d4db0d82d4712af73f343..4a4fad4182f534f23550ca5ac1ed5d42000f9b08 100644 (file)
@@ -58,6 +58,9 @@ include config/utilities.mak
 #
 # Define NO_LIBBIONIC if you do not want bionic support
 #
+# Define NO_LIBCRYPTO if you do not want libcrypto (openssl) support
+# used for generating build-ids for ELFs generated by jitdump.
+#
 # Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support
 # for dwarf backtrace post unwind.
 #
@@ -136,6 +139,8 @@ $(call allow-override,CC,$(CROSS_COMPILE)gcc)
 $(call allow-override,AR,$(CROSS_COMPILE)ar)
 $(call allow-override,LD,$(CROSS_COMPILE)ld)
 
+LD += $(EXTRA_LDFLAGS)
+
 PKG_CONFIG = $(CROSS_COMPILE)pkg-config
 
 RM      = rm -f
@@ -165,7 +170,16 @@ ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
 endif
 endif
 
+# Set FEATURE_TESTS to 'all' so all possible feature checkers are executed.
+# Without this setting the output feature dump file misses some features, for
+# example, liberty. Select all checkers so we won't get an incomplete feature
+# dump file.
 ifeq ($(config),1)
+ifdef MAKECMDGOALS
+ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
+FEATURE_TESTS := all
+endif
+endif
 include config/Makefile
 endif
 
@@ -618,7 +632,7 @@ clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean
        $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
        $(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
                $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \
-               $(OUTPUT)tests/llvm-src-{base,kbuild,prologue}.c
+               $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c
        $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
        $(python-clean)
 
index 7fbca175099ec917ad69b8025c8249ee6c52a6a4..18b13518d8d8701137d489a65f7dd752bdc7f43f 100644 (file)
@@ -1,3 +1,4 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
 endif
+PERF_HAVE_JITDUMP := 1
index 7fbca175099ec917ad69b8025c8249ee6c52a6a4..18b13518d8d8701137d489a65f7dd752bdc7f43f 100644 (file)
@@ -1,3 +1,4 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
 endif
+PERF_HAVE_JITDUMP := 1
index 7fbca175099ec917ad69b8025c8249ee6c52a6a4..56e05f126ad8793d25bb1a70ce3dac5f100d3b3a 100644 (file)
@@ -1,3 +1,6 @@
 ifndef NO_DWARF
 PERF_HAVE_DWARF_REGS := 1
 endif
+
+HAVE_KVM_STAT_SUPPORT := 1
+PERF_HAVE_JITDUMP := 1
index 7b8b0d1a1b626065e0b414f42a7a998723e0e57f..c8fe2074d2177f0709f0e1d54f63cd77f84f2233 100644 (file)
@@ -1,5 +1,6 @@
 libperf-y += header.o
 libperf-y += sym-handling.o
+libperf-y += kvm-stat.o
 
 libperf-$(CONFIG_DWARF) += dwarf-regs.o
 libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/book3s_hcalls.h b/tools/perf/arch/powerpc/util/book3s_hcalls.h
new file mode 100644 (file)
index 0000000..0dd6b7f
--- /dev/null
@@ -0,0 +1,123 @@
+#ifndef ARCH_PERF_BOOK3S_HV_HCALLS_H
+#define ARCH_PERF_BOOK3S_HV_HCALLS_H
+
+/*
+ * PowerPC HCALL codes : hcall code to name mapping
+ */
+#define kvm_trace_symbol_hcall \
+       {0x4, "H_REMOVE"},                                      \
+       {0x8, "H_ENTER"},                                       \
+       {0xc, "H_READ"},                                        \
+       {0x10, "H_CLEAR_MOD"},                                  \
+       {0x14, "H_CLEAR_REF"},                                  \
+       {0x18, "H_PROTECT"},                                    \
+       {0x1c, "H_GET_TCE"},                                    \
+       {0x20, "H_PUT_TCE"},                                    \
+       {0x24, "H_SET_SPRG0"},                                  \
+       {0x28, "H_SET_DABR"},                                   \
+       {0x2c, "H_PAGE_INIT"},                                  \
+       {0x30, "H_SET_ASR"},                                    \
+       {0x34, "H_ASR_ON"},                                     \
+       {0x38, "H_ASR_OFF"},                                    \
+       {0x3c, "H_LOGICAL_CI_LOAD"},                            \
+       {0x40, "H_LOGICAL_CI_STORE"},                           \
+       {0x44, "H_LOGICAL_CACHE_LOAD"},                         \
+       {0x48, "H_LOGICAL_CACHE_STORE"},                        \
+       {0x4c, "H_LOGICAL_ICBI"},                               \
+       {0x50, "H_LOGICAL_DCBF"},                               \
+       {0x54, "H_GET_TERM_CHAR"},                              \
+       {0x58, "H_PUT_TERM_CHAR"},                              \
+       {0x5c, "H_REAL_TO_LOGICAL"},                            \
+       {0x60, "H_HYPERVISOR_DATA"},                            \
+       {0x64, "H_EOI"},                                        \
+       {0x68, "H_CPPR"},                                       \
+       {0x6c, "H_IPI"},                                        \
+       {0x70, "H_IPOLL"},                                      \
+       {0x74, "H_XIRR"},                                       \
+       {0x78, "H_MIGRATE_DMA"},                                \
+       {0x7c, "H_PERFMON"},                                    \
+       {0xdc, "H_REGISTER_VPA"},                               \
+       {0xe0, "H_CEDE"},                                       \
+       {0xe4, "H_CONFER"},                                     \
+       {0xe8, "H_PROD"},                                       \
+       {0xec, "H_GET_PPP"},                                    \
+       {0xf0, "H_SET_PPP"},                                    \
+       {0xf4, "H_PURR"},                                       \
+       {0xf8, "H_PIC"},                                        \
+       {0xfc, "H_REG_CRQ"},                                    \
+       {0x100, "H_FREE_CRQ"},                                  \
+       {0x104, "H_VIO_SIGNAL"},                                \
+       {0x108, "H_SEND_CRQ"},                                  \
+       {0x110, "H_COPY_RDMA"},                                 \
+       {0x114, "H_REGISTER_LOGICAL_LAN"},                      \
+       {0x118, "H_FREE_LOGICAL_LAN"},                          \
+       {0x11c, "H_ADD_LOGICAL_LAN_BUFFER"},                    \
+       {0x120, "H_SEND_LOGICAL_LAN"},                          \
+       {0x124, "H_BULK_REMOVE"},                               \
+       {0x130, "H_MULTICAST_CTRL"},                            \
+       {0x134, "H_SET_XDABR"},                                 \
+       {0x138, "H_STUFF_TCE"},                                 \
+       {0x13c, "H_PUT_TCE_INDIRECT"},                          \
+       {0x14c, "H_CHANGE_LOGICAL_LAN_MAC"},                    \
+       {0x150, "H_VTERM_PARTNER_INFO"},                        \
+       {0x154, "H_REGISTER_VTERM"},                            \
+       {0x158, "H_FREE_VTERM"},                                \
+       {0x15c, "H_RESET_EVENTS"},                              \
+       {0x160, "H_ALLOC_RESOURCE"},                            \
+       {0x164, "H_FREE_RESOURCE"},                             \
+       {0x168, "H_MODIFY_QP"},                                 \
+       {0x16c, "H_QUERY_QP"},                                  \
+       {0x170, "H_REREGISTER_PMR"},                            \
+       {0x174, "H_REGISTER_SMR"},                              \
+       {0x178, "H_QUERY_MR"},                                  \
+       {0x17c, "H_QUERY_MW"},                                  \
+       {0x180, "H_QUERY_HCA"},                                 \
+       {0x184, "H_QUERY_PORT"},                                \
+       {0x188, "H_MODIFY_PORT"},                               \
+       {0x18c, "H_DEFINE_AQP1"},                               \
+       {0x190, "H_GET_TRACE_BUFFER"},                          \
+       {0x194, "H_DEFINE_AQP0"},                               \
+       {0x198, "H_RESIZE_MR"},                                 \
+       {0x19c, "H_ATTACH_MCQP"},                               \
+       {0x1a0, "H_DETACH_MCQP"},                               \
+       {0x1a4, "H_CREATE_RPT"},                                \
+       {0x1a8, "H_REMOVE_RPT"},                                \
+       {0x1ac, "H_REGISTER_RPAGES"},                           \
+       {0x1b0, "H_DISABLE_AND_GETC"},                          \
+       {0x1b4, "H_ERROR_DATA"},                                \
+       {0x1b8, "H_GET_HCA_INFO"},                              \
+       {0x1bc, "H_GET_PERF_COUNT"},                            \
+       {0x1c0, "H_MANAGE_TRACE"},                              \
+       {0x1d4, "H_FREE_LOGICAL_LAN_BUFFER"},                   \
+       {0x1d8, "H_POLL_PENDING"},                              \
+       {0x1e4, "H_QUERY_INT_STATE"},                           \
+       {0x244, "H_ILLAN_ATTRIBUTES"},                          \
+       {0x250, "H_MODIFY_HEA_QP"},                             \
+       {0x254, "H_QUERY_HEA_QP"},                              \
+       {0x258, "H_QUERY_HEA"},                                 \
+       {0x25c, "H_QUERY_HEA_PORT"},                            \
+       {0x260, "H_MODIFY_HEA_PORT"},                           \
+       {0x264, "H_REG_BCMC"},                                  \
+       {0x268, "H_DEREG_BCMC"},                                \
+       {0x26c, "H_REGISTER_HEA_RPAGES"},                       \
+       {0x270, "H_DISABLE_AND_GET_HEA"},                       \
+       {0x274, "H_GET_HEA_INFO"},                              \
+       {0x278, "H_ALLOC_HEA_RESOURCE"},                        \
+       {0x284, "H_ADD_CONN"},                                  \
+       {0x288, "H_DEL_CONN"},                                  \
+       {0x298, "H_JOIN"},                                      \
+       {0x2a4, "H_VASI_STATE"},                                \
+       {0x2b0, "H_ENABLE_CRQ"},                                \
+       {0x2b8, "H_GET_EM_PARMS"},                              \
+       {0x2d0, "H_SET_MPP"},                                   \
+       {0x2d4, "H_GET_MPP"},                                   \
+       {0x2ec, "H_HOME_NODE_ASSOCIATIVITY"},                   \
+       {0x2f4, "H_BEST_ENERGY"},                               \
+       {0x2fc, "H_XIRR_X"},                                    \
+       {0x300, "H_RANDOM"},                                    \
+       {0x304, "H_COP"},                                       \
+       {0x314, "H_GET_MPP_X"},                                 \
+       {0x31c, "H_SET_MODE"},                                  \
+       {0xf000, "H_RTAS"}                                      \
+
+#endif
diff --git a/tools/perf/arch/powerpc/util/book3s_hv_exits.h b/tools/perf/arch/powerpc/util/book3s_hv_exits.h
new file mode 100644 (file)
index 0000000..e68ba2d
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef ARCH_PERF_BOOK3S_HV_EXITS_H
+#define ARCH_PERF_BOOK3S_HV_EXITS_H
+
+/*
+ * PowerPC Interrupt vectors : exit code to name mapping
+ */
+
+#define kvm_trace_symbol_exit \
+       {0x0,   "RETURN_TO_HOST"}, \
+       {0x100, "SYSTEM_RESET"}, \
+       {0x200, "MACHINE_CHECK"}, \
+       {0x300, "DATA_STORAGE"}, \
+       {0x380, "DATA_SEGMENT"}, \
+       {0x400, "INST_STORAGE"}, \
+       {0x480, "INST_SEGMENT"}, \
+       {0x500, "EXTERNAL"}, \
+       {0x501, "EXTERNAL_LEVEL"}, \
+       {0x502, "EXTERNAL_HV"}, \
+       {0x600, "ALIGNMENT"}, \
+       {0x700, "PROGRAM"}, \
+       {0x800, "FP_UNAVAIL"}, \
+       {0x900, "DECREMENTER"}, \
+       {0x980, "HV_DECREMENTER"}, \
+       {0xc00, "SYSCALL"}, \
+       {0xd00, "TRACE"}, \
+       {0xe00, "H_DATA_STORAGE"}, \
+       {0xe20, "H_INST_STORAGE"}, \
+       {0xe40, "H_EMUL_ASSIST"}, \
+       {0xf00, "PERFMON"}, \
+       {0xf20, "ALTIVEC"}, \
+       {0xf40, "VSX"}
+
+#endif
diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c
new file mode 100644 (file)
index 0000000..74eee30
--- /dev/null
@@ -0,0 +1,170 @@
+#include "util/kvm-stat.h"
+#include "util/parse-events.h"
+#include "util/debug.h"
+
+#include "book3s_hv_exits.h"
+#include "book3s_hcalls.h"
+
+#define NR_TPS 4
+
+const char *vcpu_id_str = "vcpu_id";
+const int decode_str_len = 40;
+const char *kvm_entry_trace = "kvm_hv:kvm_guest_enter";
+const char *kvm_exit_trace = "kvm_hv:kvm_guest_exit";
+
+define_exit_reasons_table(hv_exit_reasons, kvm_trace_symbol_exit);
+define_exit_reasons_table(hcall_reasons, kvm_trace_symbol_hcall);
+
+/* Tracepoints specific to ppc_book3s_hv */
+const char *ppc_book3s_hv_kvm_tp[] = {
+       "kvm_hv:kvm_guest_enter",
+       "kvm_hv:kvm_guest_exit",
+       "kvm_hv:kvm_hcall_enter",
+       "kvm_hv:kvm_hcall_exit",
+       NULL,
+};
+
+/* 1 extra placeholder for NULL */
+const char *kvm_events_tp[NR_TPS + 1];
+const char *kvm_exit_reason;
+
+static void hcall_event_get_key(struct perf_evsel *evsel,
+                               struct perf_sample *sample,
+                               struct event_key *key)
+{
+       key->info = 0;
+       key->key = perf_evsel__intval(evsel, sample, "req");
+}
+
+static const char *get_hcall_exit_reason(u64 exit_code)
+{
+       struct exit_reasons_table *tbl = hcall_reasons;
+
+       while (tbl->reason != NULL) {
+               if (tbl->exit_code == exit_code)
+                       return tbl->reason;
+               tbl++;
+       }
+
+       pr_debug("Unknown hcall code: %lld\n",
+              (unsigned long long)exit_code);
+       return "UNKNOWN";
+}
+
+static bool hcall_event_end(struct perf_evsel *evsel,
+                           struct perf_sample *sample __maybe_unused,
+                           struct event_key *key __maybe_unused)
+{
+       return (!strcmp(evsel->name, kvm_events_tp[3]));
+}
+
+static bool hcall_event_begin(struct perf_evsel *evsel,
+                             struct perf_sample *sample, struct event_key *key)
+{
+       if (!strcmp(evsel->name, kvm_events_tp[2])) {
+               hcall_event_get_key(evsel, sample, key);
+               return true;
+       }
+
+       return false;
+}
+static void hcall_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
+                                  struct event_key *key,
+                                  char *decode)
+{
+       const char *hcall_reason = get_hcall_exit_reason(key->key);
+
+       scnprintf(decode, decode_str_len, "%s", hcall_reason);
+}
+
+static struct kvm_events_ops hcall_events = {
+       .is_begin_event = hcall_event_begin,
+       .is_end_event = hcall_event_end,
+       .decode_key = hcall_event_decode_key,
+       .name = "HCALL-EVENT",
+};
+
+static struct kvm_events_ops exit_events = {
+       .is_begin_event = exit_event_begin,
+       .is_end_event = exit_event_end,
+       .decode_key = exit_event_decode_key,
+       .name = "VM-EXIT"
+};
+
+struct kvm_reg_events_ops kvm_reg_events_ops[] = {
+       { .name = "vmexit", .ops = &exit_events },
+       { .name = "hcall", .ops = &hcall_events },
+       { NULL, NULL },
+};
+
+const char * const kvm_skip_events[] = {
+       NULL,
+};
+
+
+static int is_tracepoint_available(const char *str, struct perf_evlist *evlist)
+{
+       struct parse_events_error err;
+       int ret;
+
+       err.str = NULL;
+       ret = parse_events(evlist, str, &err);
+       if (err.str)
+               pr_err("%s : %s\n", str, err.str);
+       return ret;
+}
+
+static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm,
+                               struct perf_evlist *evlist)
+{
+       const char **events_ptr;
+       int i, nr_tp = 0, err = -1;
+
+       /* Check for book3s_hv tracepoints */
+       for (events_ptr = ppc_book3s_hv_kvm_tp; *events_ptr; events_ptr++) {
+               err = is_tracepoint_available(*events_ptr, evlist);
+               if (err)
+                       return -1;
+               nr_tp++;
+       }
+
+       for (i = 0; i < nr_tp; i++)
+               kvm_events_tp[i] = ppc_book3s_hv_kvm_tp[i];
+
+       kvm_events_tp[i] = NULL;
+       kvm_exit_reason = "trap";
+       kvm->exit_reasons = hv_exit_reasons;
+       kvm->exit_reasons_isa = "HV";
+
+       return 0;
+}
+
+/* Wrapper to setup kvm tracepoints */
+static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm)
+{
+       struct perf_evlist *evlist = perf_evlist__new();
+
+       if (evlist == NULL)
+               return -ENOMEM;
+
+       /* Right now, only supported on book3s_hv */
+       return ppc__setup_book3s_hv(kvm, evlist);
+}
+
+int setup_kvm_events_tp(struct perf_kvm_stat *kvm)
+{
+       return ppc__setup_kvm_tp(kvm);
+}
+
+int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
+{
+       int ret;
+
+       ret = ppc__setup_kvm_tp(kvm);
+       if (ret) {
+               kvm->exit_reasons = NULL;
+               kvm->exit_reasons_isa = NULL;
+       }
+
+       return ret;
+}
index a5dbc07ec9dc70900ed4a593f5979d419061fd35..ed57df2e6d687d89ccf95d9aa03c263411de7fe9 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include "../../util/kvm-stat.h"
-#include <asm/kvm_perf.h>
+#include <asm/sie.h>
 
 define_exit_reasons_table(sie_exit_reasons, sie_intercept_code);
 define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes);
@@ -18,6 +18,12 @@ define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes);
 define_exit_reasons_table(sie_diagnose_codes, diagnose_codes);
 define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes);
 
+const char *vcpu_id_str = "id";
+const int decode_str_len = 40;
+const char *kvm_exit_reason = "icptcode";
+const char *kvm_entry_trace = "kvm:kvm_s390_sie_enter";
+const char *kvm_exit_trace = "kvm:kvm_s390_sie_exit";
+
 static void event_icpt_insn_get_key(struct perf_evsel *evsel,
                                    struct perf_sample *sample,
                                    struct event_key *key)
@@ -73,7 +79,7 @@ static struct kvm_events_ops exit_events = {
        .name = "VM-EXIT"
 };
 
-const char * const kvm_events_tp[] = {
+const char *kvm_events_tp[] = {
        "kvm:kvm_s390_sie_enter",
        "kvm:kvm_s390_sie_exit",
        "kvm:kvm_s390_intercept_instruction",
index 09ba923debe86810f8380f7df54504dee4232ec8..269af21437353b2fb886383ede1e3f9a2f586f25 100644 (file)
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1
 endif
 HAVE_KVM_STAT_SUPPORT := 1
 PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
+PERF_HAVE_JITDUMP := 1
index 7bb0d13c235f70326afc28d726f38f1d95499055..72193f19d6d75d3c32e19b424a0f1910ebbc24a6 100644 (file)
@@ -59,7 +59,7 @@ static u64 mmap_read_self(void *addr)
                u64 quot, rem;
 
                quot = (cyc >> time_shift);
-               rem = cyc & ((1 << time_shift) - 1);
+               rem = cyc & (((u64)1 << time_shift) - 1);
                delta = time_offset + quot * time_mult +
                        ((rem * time_mult) >> time_shift);
 
@@ -103,6 +103,7 @@ static int __test__rdpmc(void)
 
        sigfillset(&sa.sa_mask);
        sa.sa_sigaction = segfault_handler;
+       sa.sa_flags = 0;
        sigaction(SIGSEGV, &sa, NULL);
 
        fd = sys_perf_event_open(&attr, 0, -1, -1,
index 8d8150f1cf9bcf426b4c29a19170221db680a980..d66f9ad4df2ea5da6eca22cae351a842d1143508 100644 (file)
@@ -60,7 +60,9 @@ struct branch {
        u64 misc;
 };
 
-static size_t intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused)
+static size_t
+intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+                        struct perf_evlist *evlist __maybe_unused)
 {
        return INTEL_BTS_AUXTRACE_PRIV_SIZE;
 }
index f05daacc9e7810117cfe25415a75990b3aa89f63..a3395179c9eebd5fcd39aa4796a0dc3d495f4b5d 100644 (file)
@@ -89,7 +89,7 @@ static int intel_pt_parse_terms_with_default(struct list_head *formats,
 
        *config = attr.config;
 out_free:
-       parse_events__free_terms(terms);
+       parse_events_terms__delete(terms);
        return err;
 }
 
@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
        return attr;
 }
 
-static size_t intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused)
+static size_t
+intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+                       struct perf_evlist *evlist __maybe_unused)
 {
        return INTEL_PT_AUXTRACE_PRIV_SIZE;
 }
index 14e4e668fad733c1802908047ae524318aa586de..b63d4be655a24a678f69d6deea3b4ee87283b938 100644 (file)
@@ -1,5 +1,7 @@
 #include "../../util/kvm-stat.h"
-#include <asm/kvm_perf.h>
+#include <asm/svm.h>
+#include <asm/vmx.h>
+#include <asm/kvm.h>
 
 define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS);
 define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);
@@ -11,6 +13,12 @@ static struct kvm_events_ops exit_events = {
        .name = "VM-EXIT"
 };
 
+const char *vcpu_id_str = "vcpu_id";
+const int decode_str_len = 20;
+const char *kvm_exit_reason = "exit_reason";
+const char *kvm_entry_trace = "kvm:kvm_entry";
+const char *kvm_exit_trace = "kvm:kvm_exit";
+
 /*
  * For the mmio events, we treat:
  * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
@@ -65,7 +73,7 @@ static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
                                  struct event_key *key,
                                  char *decode)
 {
-       scnprintf(decode, DECODE_STR_LEN, "%#lx:%s",
+       scnprintf(decode, decode_str_len, "%#lx:%s",
                  (unsigned long)key->key,
                  key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
 }
@@ -109,7 +117,7 @@ static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
                                    struct event_key *key,
                                    char *decode)
 {
-       scnprintf(decode, DECODE_STR_LEN, "%#llx:%s",
+       scnprintf(decode, decode_str_len, "%#llx:%s",
                  (unsigned long long)key->key,
                  key->info ? "POUT" : "PIN");
 }
@@ -121,7 +129,7 @@ static struct kvm_events_ops ioport_events = {
        .name = "IO Port Access"
 };
 
-const char * const kvm_events_tp[] = {
+const char *kvm_events_tp[] = {
        "kvm:kvm_entry",
        "kvm:kvm_exit",
        "kvm:kvm_mmio",
index e4c2c30143b95133913a2bc3569b2871b79aa75c..5c3cce082cb88c5cab984bdb1ae6944274861ad4 100644 (file)
@@ -1,6 +1,11 @@
+
+/* Various wrappers to make the kernel .S file build in user-space: */
+
 #define memcpy MEMCPY /* don't hide glibc's memcpy() */
 #define altinstr_replacement text
 #define globl p2align 4; .globl
+#define _ASM_EXTABLE_FAULT(x, y)
+
 #include "../../../arch/x86/lib/memcpy_64.S"
 /*
  * We need to provide note.GNU-stack section, saying that we want
index cc5c1267c738da038cfb6b824f79854fab41a629..cfe366375c4b89bb3642f5531d04b418a8d76e56 100644 (file)
@@ -245,7 +245,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
                        hists__collapse_resort(hists, NULL);
                        /* Don't sort callchain */
                        perf_evsel__reset_sample_bit(pos, CALLCHAIN);
-                       hists__output_resort(hists, NULL);
+                       perf_evsel__output_resort(pos, NULL);
 
                        if (symbol_conf.event_group &&
                            !perf_evsel__is_group_leader(pos))
index d93bff7fc0e407d6518a6ce0e2ee0dd4b65bf910..632efc6b79a07e20c4b25f9757bcd9c089050270 100644 (file)
@@ -38,19 +38,7 @@ static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
 
 static int build_id_cache__kcore_dir(char *dir, size_t sz)
 {
-       struct timeval tv;
-       struct tm tm;
-       char dt[32];
-
-       if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
-               return -1;
-
-       if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
-               return -1;
-
-       scnprintf(dir, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
-
-       return 0;
+       return fetch_current_timestamp(dir, sz);
 }
 
 static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
index f04e804a9fadc6807a7bc74810fac5ddaad912b2..c42448ed5dfe20a74af9c671669aa23a25cadb5b 100644 (file)
 #include "util/util.h"
 #include "util/debug.h"
 
+static bool use_system_config, use_user_config;
+
 static const char * const config_usage[] = {
-       "perf config [options]",
+       "perf config [<file-option>] [options]",
        NULL
 };
 
@@ -25,6 +27,8 @@ enum actions {
 static struct option config_options[] = {
        OPT_SET_UINT('l', "list", &actions,
                     "show current config variables", ACTION_LIST),
+       OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
+       OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
        OPT_END()
 };
 
@@ -42,10 +46,23 @@ static int show_config(const char *key, const char *value,
 int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        int ret = 0;
+       char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
 
        argc = parse_options(argc, argv, config_options, config_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
 
+       if (use_system_config && use_user_config) {
+               pr_err("Error: only one config file at a time\n");
+               parse_options_usage(config_usage, config_options, "user", 0);
+               parse_options_usage(NULL, config_options, "system", 0);
+               return -1;
+       }
+
+       if (use_system_config)
+               config_exclusive_filename = perf_etc_perfconfig();
+       else if (use_user_config)
+               config_exclusive_filename = user_config;
+
        switch (actions) {
        case ACTION_LIST:
                if (argc) {
@@ -53,9 +70,13 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
                        parse_options_usage(config_usage, config_options, "l", 1);
                } else {
                        ret = perf_config(show_config, NULL);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               const char * config_filename = config_exclusive_filename;
+                               if (!config_exclusive_filename)
+                                       config_filename = user_config;
                                pr_err("Nothing configured, "
-                                      "please check your ~/.perfconfig file\n");
+                                      "please check your %s \n", config_filename);
+                       }
                }
                break;
        default:
index 36ccc2b8827fdd239b657e79b396ae013c318462..4d72359fd15ad00ca7397bb033e84b4f899546c2 100644 (file)
@@ -1264,8 +1264,6 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
        if (ret < 0)
                return ret;
 
-       perf_config(perf_default_config, NULL);
-
        argc = parse_options(argc, argv, options, diff_usage, 0);
 
        if (symbol__init(NULL) < 0)
index 96c1a4cfbbbf6b1f639d91d562c55b09da5c7e6f..49d55e21b1b06dbecd9c6935a2e0f33550585514 100644 (file)
@@ -86,8 +86,7 @@ static int check_emacsclient_version(void)
                return -1;
        }
 
-       strbuf_remove(&buffer, 0, strlen("emacsclient"));
-       version = atoi(buffer.buf);
+       version = atoi(buffer.buf + strlen("emacsclient"));
 
        if (version < 22) {
                fprintf(stderr,
@@ -273,7 +272,7 @@ static int perf_help_config(const char *var, const char *value, void *cb)
        if (!prefixcmp(var, "man."))
                return add_man_viewer_info(var, value);
 
-       return perf_default_config(var, value, cb);
+       return 0;
 }
 
 static struct cmdnames main_cmds, other_cmds;
index 0022e02ed31a7034b9286884ab87c4c131e41fa3..7fa68663ed7287f63adad2342db987941ba0c1b4 100644 (file)
@@ -17,6 +17,7 @@
 #include "util/build-id.h"
 #include "util/data.h"
 #include "util/auxtrace.h"
+#include "util/jit.h"
 
 #include <subcmd/parse-options.h>
 
@@ -29,6 +30,7 @@ struct perf_inject {
        bool                    sched_stat;
        bool                    have_auxtrace;
        bool                    strip;
+       bool                    jit_mode;
        const char              *input_name;
        struct perf_data_file   output;
        u64                     bytes_written;
@@ -71,6 +73,15 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool,
        return perf_event__repipe_synth(tool, event);
 }
 
+#ifdef HAVE_JITDUMP
+static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused,
+                              union perf_event *event __maybe_unused,
+                              struct ordered_events *oe __maybe_unused)
+{
+       return 0;
+}
+#endif
+
 static int perf_event__repipe_op2_synth(struct perf_tool *tool,
                                        union perf_event *event,
                                        struct perf_session *session
@@ -234,6 +245,31 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
        return err;
 }
 
+#ifdef HAVE_JITDUMP
+static int perf_event__jit_repipe_mmap(struct perf_tool *tool,
+                                      union perf_event *event,
+                                      struct perf_sample *sample,
+                                      struct machine *machine)
+{
+       struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
+       u64 n = 0;
+       int ret;
+
+       /*
+        * if jit marker, then inject jit mmaps and generate ELF images
+        */
+       ret = jit_process(inject->session, &inject->output, machine,
+                         event->mmap.filename, sample->pid, &n);
+       if (ret < 0)
+               return ret;
+       if (ret) {
+               inject->bytes_written += n;
+               return 0;
+       }
+       return perf_event__repipe_mmap(tool, event, sample, machine);
+}
+#endif
+
 static int perf_event__repipe_mmap2(struct perf_tool *tool,
                                   union perf_event *event,
                                   struct perf_sample *sample,
@@ -247,6 +283,31 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool,
        return err;
 }
 
+#ifdef HAVE_JITDUMP
+static int perf_event__jit_repipe_mmap2(struct perf_tool *tool,
+                                       union perf_event *event,
+                                       struct perf_sample *sample,
+                                       struct machine *machine)
+{
+       struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
+       u64 n = 0;
+       int ret;
+
+       /*
+        * if jit marker, then inject jit mmaps and generate ELF images
+        */
+       ret = jit_process(inject->session, &inject->output, machine,
+                         event->mmap2.filename, sample->pid, &n);
+       if (ret < 0)
+               return ret;
+       if (ret) {
+               inject->bytes_written += n;
+               return 0;
+       }
+       return perf_event__repipe_mmap2(tool, event, sample, machine);
+}
+#endif
+
 static int perf_event__repipe_fork(struct perf_tool *tool,
                                   union perf_event *event,
                                   struct perf_sample *sample,
@@ -626,12 +687,16 @@ static int __cmd_inject(struct perf_inject *inject)
        ret = perf_session__process_events(session);
 
        if (!file_out->is_pipe) {
-               if (inject->build_ids) {
+               if (inject->build_ids)
                        perf_header__set_feat(&session->header,
                                              HEADER_BUILD_ID);
-                       if (inject->have_auxtrace)
-                               dsos__hit_all(session);
-               }
+               /*
+                * Keep all buildids when there is unprocessed AUX data because
+                * it is not known which ones the AUX trace hits.
+                */
+               if (perf_header__has_feat(&session->header, HEADER_BUILD_ID) &&
+                   inject->have_auxtrace && !inject->itrace_synth_opts.set)
+                       dsos__hit_all(session);
                /*
                 * The AUX areas have been removed and replaced with
                 * synthesized hardware events, so clear the feature flag and
@@ -703,7 +768,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
        };
        int ret;
 
-       const struct option options[] = {
+       struct option options[] = {
                OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
                            "Inject build-ids into the output stream"),
                OPT_STRING('i', "input", &inject.input_name, "file",
@@ -713,6 +778,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
                OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
                            "Merge sched-stat and sched-switch for getting events "
                            "where and how long tasks slept"),
+#ifdef HAVE_JITDUMP
+               OPT_BOOLEAN('j', "jit", &inject.jit_mode, "merge jitdump files into perf.data file"),
+#endif
                OPT_INCR('v', "verbose", &verbose,
                         "be more verbose (show build ids, etc)"),
                OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
@@ -729,7 +797,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
                "perf inject [<options>]",
                NULL
        };
-
+#ifndef HAVE_JITDUMP
+       set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true);
+#endif
        argc = parse_options(argc, argv, options, inject_usage, 0);
 
        /*
@@ -755,6 +825,29 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
        if (inject.session == NULL)
                return -1;
 
+       if (inject.build_ids) {
+               /*
+                * to make sure the mmap records are ordered correctly
+                * and so that the correct especially due to jitted code
+                * mmaps. We cannot generate the buildid hit list and
+                * inject the jit mmaps at the same time for now.
+                */
+               inject.tool.ordered_events = true;
+               inject.tool.ordering_requires_timestamps = true;
+       }
+#ifdef HAVE_JITDUMP
+       if (inject.jit_mode) {
+               inject.tool.mmap2          = perf_event__jit_repipe_mmap2;
+               inject.tool.mmap           = perf_event__jit_repipe_mmap;
+               inject.tool.ordered_events = true;
+               inject.tool.ordering_requires_timestamps = true;
+               /*
+                * JIT MMAP injection injects all MMAP events in one go, so it
+                * does not obey finished_round semantics.
+                */
+               inject.tool.finished_round = perf_event__drop_oe;
+       }
+#endif
        ret = symbol__init(&inject.session->header.env);
        if (ret < 0)
                goto out_delete;
index 118010553d0cf0dca9de6f493a5c8e267b0fff48..c9cb3be47cff4801d105d8c5091768a4646ccdc5 100644 (file)
@@ -602,7 +602,7 @@ static int gfpcmp(const void *a, const void *b)
        return fa->flags - fb->flags;
 }
 
-/* see include/trace/events/gfpflags.h */
+/* see include/trace/events/mmflags.h */
 static const struct {
        const char *original;
        const char *compact;
@@ -612,30 +612,39 @@ static const struct {
        { "GFP_HIGHUSER",               "HU" },
        { "GFP_USER",                   "U" },
        { "GFP_TEMPORARY",              "TMP" },
+       { "GFP_KERNEL_ACCOUNT",         "KAC" },
        { "GFP_KERNEL",                 "K" },
        { "GFP_NOFS",                   "NF" },
        { "GFP_ATOMIC",                 "A" },
        { "GFP_NOIO",                   "NI" },
-       { "GFP_HIGH",                   "H" },
-       { "GFP_WAIT",                   "W" },
-       { "GFP_IO",                     "I" },
-       { "GFP_COLD",                   "CO" },
-       { "GFP_NOWARN",                 "NWR" },
-       { "GFP_REPEAT",                 "R" },
-       { "GFP_NOFAIL",                 "NF" },
-       { "GFP_NORETRY",                "NR" },
-       { "GFP_COMP",                   "C" },
-       { "GFP_ZERO",                   "Z" },
-       { "GFP_NOMEMALLOC",             "NMA" },
-       { "GFP_MEMALLOC",               "MA" },
-       { "GFP_HARDWALL",               "HW" },
-       { "GFP_THISNODE",               "TN" },
-       { "GFP_RECLAIMABLE",            "RC" },
-       { "GFP_MOVABLE",                "M" },
-       { "GFP_NOTRACK",                "NT" },
-       { "GFP_NO_KSWAPD",              "NK" },
-       { "GFP_OTHER_NODE",             "ON" },
        { "GFP_NOWAIT",                 "NW" },
+       { "GFP_DMA",                    "D" },
+       { "__GFP_HIGHMEM",              "HM" },
+       { "GFP_DMA32",                  "D32" },
+       { "__GFP_HIGH",                 "H" },
+       { "__GFP_ATOMIC",               "_A" },
+       { "__GFP_IO",                   "I" },
+       { "__GFP_FS",                   "F" },
+       { "__GFP_COLD",                 "CO" },
+       { "__GFP_NOWARN",               "NWR" },
+       { "__GFP_REPEAT",               "R" },
+       { "__GFP_NOFAIL",               "NF" },
+       { "__GFP_NORETRY",              "NR" },
+       { "__GFP_COMP",                 "C" },
+       { "__GFP_ZERO",                 "Z" },
+       { "__GFP_NOMEMALLOC",           "NMA" },
+       { "__GFP_MEMALLOC",             "MA" },
+       { "__GFP_HARDWALL",             "HW" },
+       { "__GFP_THISNODE",             "TN" },
+       { "__GFP_RECLAIMABLE",          "RC" },
+       { "__GFP_MOVABLE",              "M" },
+       { "__GFP_ACCOUNT",              "AC" },
+       { "__GFP_NOTRACK",              "NT" },
+       { "__GFP_WRITE",                "WR" },
+       { "__GFP_RECLAIM",              "R" },
+       { "__GFP_DIRECT_RECLAIM",       "DR" },
+       { "__GFP_KSWAPD_RECLAIM",       "KR" },
+       { "__GFP_OTHER_NODE",           "ON" },
 };
 
 static size_t max_gfp_len;
@@ -1834,7 +1843,7 @@ static int __cmd_record(int argc, const char **argv)
        return cmd_record(i, rec_argv, NULL);
 }
 
-static int kmem_config(const char *var, const char *value, void *cb)
+static int kmem_config(const char *var, const char *value, void *cb __maybe_unused)
 {
        if (!strcmp(var, "kmem.default")) {
                if (!strcmp(value, "slab"))
@@ -1847,7 +1856,7 @@ static int kmem_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return perf_default_config(var, value, cb);
+       return 0;
 }
 
 int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
index 4418d9214872150648a719dd07fc14a29c913e9b..bff666458b28e24dccac682d0f28b6708a1a7c83 100644 (file)
@@ -30,7 +30,6 @@
 #include <math.h>
 
 #ifdef HAVE_KVM_STAT_SUPPORT
-#include <asm/kvm_perf.h>
 #include "util/kvm-stat.h"
 
 void exit_event_get_key(struct perf_evsel *evsel,
@@ -38,12 +37,12 @@ void exit_event_get_key(struct perf_evsel *evsel,
                        struct event_key *key)
 {
        key->info = 0;
-       key->key = perf_evsel__intval(evsel, sample, KVM_EXIT_REASON);
+       key->key = perf_evsel__intval(evsel, sample, kvm_exit_reason);
 }
 
 bool kvm_exit_event(struct perf_evsel *evsel)
 {
-       return !strcmp(evsel->name, KVM_EXIT_TRACE);
+       return !strcmp(evsel->name, kvm_exit_trace);
 }
 
 bool exit_event_begin(struct perf_evsel *evsel,
@@ -59,7 +58,7 @@ bool exit_event_begin(struct perf_evsel *evsel,
 
 bool kvm_entry_event(struct perf_evsel *evsel)
 {
-       return !strcmp(evsel->name, KVM_ENTRY_TRACE);
+       return !strcmp(evsel->name, kvm_entry_trace);
 }
 
 bool exit_event_end(struct perf_evsel *evsel,
@@ -91,7 +90,7 @@ void exit_event_decode_key(struct perf_kvm_stat *kvm,
        const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
                                                  key->key);
 
-       scnprintf(decode, DECODE_STR_LEN, "%s", exit_reason);
+       scnprintf(decode, decode_str_len, "%s", exit_reason);
 }
 
 static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
@@ -357,7 +356,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
        time_diff = sample->time - time_begin;
 
        if (kvm->duration && time_diff > kvm->duration) {
-               char decode[DECODE_STR_LEN];
+               char decode[decode_str_len];
 
                kvm->events_ops->decode_key(kvm, &event->key, decode);
                if (!skip_event(decode)) {
@@ -385,7 +384,8 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
                        return NULL;
                }
 
-               vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID);
+               vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample,
+                                                         vcpu_id_str);
                thread__set_priv(thread, vcpu_record);
        }
 
@@ -574,7 +574,7 @@ static void show_timeofday(void)
 
 static void print_result(struct perf_kvm_stat *kvm)
 {
-       char decode[DECODE_STR_LEN];
+       char decode[decode_str_len];
        struct kvm_event *event;
        int vcpu = kvm->trace_vcpu;
 
@@ -585,7 +585,7 @@ static void print_result(struct perf_kvm_stat *kvm)
 
        pr_info("\n\n");
        print_vcpu_info(kvm);
-       pr_info("%*s ", DECODE_STR_LEN, kvm->events_ops->name);
+       pr_info("%*s ", decode_str_len, kvm->events_ops->name);
        pr_info("%10s ", "Samples");
        pr_info("%9s ", "Samples%");
 
@@ -604,7 +604,7 @@ static void print_result(struct perf_kvm_stat *kvm)
                min = get_event_min(event, vcpu);
 
                kvm->events_ops->decode_key(kvm, &event->key, decode);
-               pr_info("%*s ", DECODE_STR_LEN, decode);
+               pr_info("%*s ", decode_str_len, decode);
                pr_info("%10llu ", (unsigned long long)ecount);
                pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
                pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
@@ -1132,6 +1132,11 @@ exit:
                _p;                     \
        })
 
+int __weak setup_kvm_events_tp(struct perf_kvm_stat *kvm __maybe_unused)
+{
+       return 0;
+}
+
 static int
 kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
 {
@@ -1148,7 +1153,14 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
                NULL
        };
        const char * const *events_tp;
+       int ret;
+
        events_tp_size = 0;
+       ret = setup_kvm_events_tp(kvm);
+       if (ret < 0) {
+               pr_err("Unable to setup the kvm tracepoints\n");
+               return ret;
+       }
 
        for (events_tp = kvm_events_tp; *events_tp; events_tp++)
                events_tp_size++;
@@ -1377,6 +1389,12 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
        /*
         * generate the event list
         */
+       err = setup_kvm_events_tp(kvm);
+       if (err < 0) {
+               pr_err("Unable to setup the kvm tracepoints\n");
+               return err;
+       }
+
        kvm->evlist = kvm_live_event_list();
        if (kvm->evlist == NULL) {
                err = -1;
index 39017004169665ec4a2ebd59aa0bc43e58412874..88aeac9aa1da12c664ec64ee419d6ce48c5ad8ec 100644 (file)
@@ -6,6 +6,8 @@
 #include "util/tool.h"
 #include "util/session.h"
 #include "util/data.h"
+#include "util/mem-events.h"
+#include "util/debug.h"
 
 #define MEM_OPERATION_LOAD     0x1
 #define MEM_OPERATION_STORE    0x2
@@ -21,11 +23,56 @@ struct perf_mem {
        DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
 
+static int parse_record_events(const struct option *opt,
+                              const char *str, int unset __maybe_unused)
+{
+       struct perf_mem *mem = *(struct perf_mem **)opt->value;
+       int j;
+
+       if (strcmp(str, "list")) {
+               if (!perf_mem_events__parse(str)) {
+                       mem->operation = 0;
+                       return 0;
+               }
+               exit(-1);
+       }
+
+       for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
+               struct perf_mem_event *e = &perf_mem_events[j];
+
+               fprintf(stderr, "%-13s%-*s%s\n",
+                       e->tag,
+                       verbose ? 25 : 0,
+                       verbose ? perf_mem_events__name(j) : "",
+                       e->supported ? ": available" : "");
+       }
+       exit(0);
+}
+
+static const char * const __usage[] = {
+       "perf mem record [<options>] [<command>]",
+       "perf mem record [<options>] -- <command> [<options>]",
+       NULL
+};
+
+static const char * const *record_mem_usage = __usage;
+
 static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
 {
        int rec_argc, i = 0, j;
        const char **rec_argv;
        int ret;
+       struct option options[] = {
+       OPT_CALLBACK('e', "event", &mem, "event",
+                    "event selector. use 'perf mem record -e list' to list available events",
+                    parse_record_events),
+       OPT_INCR('v', "verbose", &verbose,
+                "be more verbose (show counter open errors, etc)"),
+       OPT_END()
+       };
+
+       argc = parse_options(argc, argv, options, record_mem_usage,
+                            PARSE_OPT_STOP_AT_NON_OPTION);
 
        rec_argc = argc + 7; /* max number of arguments */
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
@@ -35,23 +82,40 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
        rec_argv[i++] = "record";
 
        if (mem->operation & MEM_OPERATION_LOAD)
+               perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
+
+       if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
                rec_argv[i++] = "-W";
 
        rec_argv[i++] = "-d";
 
-       if (mem->operation & MEM_OPERATION_LOAD) {
-               rec_argv[i++] = "-e";
-               rec_argv[i++] = "cpu/mem-loads/pp";
-       }
+       for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
+               if (!perf_mem_events[j].record)
+                       continue;
+
+               if (!perf_mem_events[j].supported) {
+                       pr_err("failed: event '%s' not supported\n",
+                              perf_mem_events__name(j));
+                       return -1;
+               }
 
-       if (mem->operation & MEM_OPERATION_STORE) {
                rec_argv[i++] = "-e";
-               rec_argv[i++] = "cpu/mem-stores/pp";
-       }
+               rec_argv[i++] = perf_mem_events__name(j);
+       };
 
-       for (j = 1; j < argc; j++, i++)
+       for (j = 0; j < argc; j++, i++)
                rec_argv[i] = argv[j];
 
+       if (verbose > 0) {
+               pr_debug("calling: record ");
+
+               while (rec_argv[j]) {
+                       pr_debug("%s ", rec_argv[j]);
+                       j++;
+               }
+               pr_debug("\n");
+       }
+
        ret = cmd_record(i, rec_argv, NULL);
        free(rec_argv);
        return ret;
@@ -298,6 +362,10 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
                NULL
        };
 
+       if (perf_mem_events__init()) {
+               pr_err("failed: memory events not supported\n");
+               return -1;
+       }
 
        argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
                                        mem_usage, PARSE_OPT_STOP_AT_NON_OPTION);
index 319712a4e02b73de7359fc2ed772bed1d9cd424f..515510ecc76a43391e2ac58f830557b51810b466 100644 (file)
@@ -32,6 +32,8 @@
 #include "util/parse-branch-options.h"
 #include "util/parse-regs-options.h"
 #include "util/llvm-utils.h"
+#include "util/bpf-loader.h"
+#include "asm/bug.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -49,7 +51,9 @@ struct record {
        const char              *progname;
        int                     realtime_prio;
        bool                    no_buildid;
+       bool                    no_buildid_set;
        bool                    no_buildid_cache;
+       bool                    no_buildid_cache_set;
        bool                    buildid_all;
        unsigned long long      samples;
 };
@@ -320,7 +324,10 @@ try_again:
                } else {
                        pr_err("failed to mmap with %d (%s)\n", errno,
                                strerror_r(errno, msg, sizeof(msg)));
-                       rc = -errno;
+                       if (errno)
+                               rc = -errno;
+                       else
+                               rc = -EINVAL;
                }
                goto out;
        }
@@ -464,6 +471,29 @@ static void record__init_features(struct record *rec)
        perf_header__clear_feat(&session->header, HEADER_STAT);
 }
 
+static void
+record__finish_output(struct record *rec)
+{
+       struct perf_data_file *file = &rec->file;
+       int fd = perf_data_file__fd(file);
+
+       if (file->is_pipe)
+               return;
+
+       rec->session->header.data_size += rec->bytes_written;
+       file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
+
+       if (!rec->no_buildid) {
+               process_buildids(rec);
+
+               if (rec->buildid_all)
+                       dsos__hit_all(rec->session);
+       }
+       perf_session__write_header(rec->session, rec->evlist, fd, true);
+
+       return;
+}
+
 static volatile int workload_exec_errno;
 
 /*
@@ -482,6 +512,74 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
 
 static void snapshot_sig_handler(int sig);
 
+static int record__synthesize(struct record *rec)
+{
+       struct perf_session *session = rec->session;
+       struct machine *machine = &session->machines.host;
+       struct perf_data_file *file = &rec->file;
+       struct record_opts *opts = &rec->opts;
+       struct perf_tool *tool = &rec->tool;
+       int fd = perf_data_file__fd(file);
+       int err = 0;
+
+       if (file->is_pipe) {
+               err = perf_event__synthesize_attrs(tool, session,
+                                                  process_synthesized_event);
+               if (err < 0) {
+                       pr_err("Couldn't synthesize attrs.\n");
+                       goto out;
+               }
+
+               if (have_tracepoints(&rec->evlist->entries)) {
+                       /*
+                        * FIXME err <= 0 here actually means that
+                        * there were no tracepoints so its not really
+                        * an error, just that we don't need to
+                        * synthesize anything.  We really have to
+                        * return this more properly and also
+                        * propagate errors that now are calling die()
+                        */
+                       err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist,
+                                                                 process_synthesized_event);
+                       if (err <= 0) {
+                               pr_err("Couldn't record tracing data.\n");
+                               goto out;
+                       }
+                       rec->bytes_written += err;
+               }
+       }
+
+       if (rec->opts.full_auxtrace) {
+               err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
+                                       session, process_synthesized_event);
+               if (err)
+                       goto out;
+       }
+
+       err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
+                                                machine);
+       WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
+                          "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
+                          "Check /proc/kallsyms permission or run as root.\n");
+
+       err = perf_event__synthesize_modules(tool, process_synthesized_event,
+                                            machine);
+       WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
+                          "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
+                          "Check /proc/modules permission or run as root.\n");
+
+       if (perf_guest) {
+               machines__process_guests(&session->machines,
+                                        perf_event__synthesize_guest_os, tool);
+       }
+
+       err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
+                                           process_synthesized_event, opts->sample_address,
+                                           opts->proc_map_timeout);
+out:
+       return err;
+}
+
 static int __cmd_record(struct record *rec, int argc, const char **argv)
 {
        int err;
@@ -534,6 +632,16 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
                goto out_child;
        }
 
+       err = bpf__apply_obj_config();
+       if (err) {
+               char errbuf[BUFSIZ];
+
+               bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
+               pr_err("ERROR: Apply config to BPF failed: %s\n",
+                        errbuf);
+               goto out_child;
+       }
+
        /*
         * Normally perf_session__new would do this, but it doesn't have the
         * evlist.
@@ -566,63 +674,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
        machine = &session->machines.host;
 
-       if (file->is_pipe) {
-               err = perf_event__synthesize_attrs(tool, session,
-                                                  process_synthesized_event);
-               if (err < 0) {
-                       pr_err("Couldn't synthesize attrs.\n");
-                       goto out_child;
-               }
-
-               if (have_tracepoints(&rec->evlist->entries)) {
-                       /*
-                        * FIXME err <= 0 here actually means that
-                        * there were no tracepoints so its not really
-                        * an error, just that we don't need to
-                        * synthesize anything.  We really have to
-                        * return this more properly and also
-                        * propagate errors that now are calling die()
-                        */
-                       err = perf_event__synthesize_tracing_data(tool, fd, rec->evlist,
-                                                                 process_synthesized_event);
-                       if (err <= 0) {
-                               pr_err("Couldn't record tracing data.\n");
-                               goto out_child;
-                       }
-                       rec->bytes_written += err;
-               }
-       }
-
-       if (rec->opts.full_auxtrace) {
-               err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
-                                       session, process_synthesized_event);
-               if (err)
-                       goto out_delete_session;
-       }
-
-       err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
-                                                machine);
-       if (err < 0)
-               pr_err("Couldn't record kernel reference relocation symbol\n"
-                      "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
-                      "Check /proc/kallsyms permission or run as root.\n");
-
-       err = perf_event__synthesize_modules(tool, process_synthesized_event,
-                                            machine);
+       err = record__synthesize(rec);
        if (err < 0)
-               pr_err("Couldn't record kernel module information.\n"
-                      "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
-                      "Check /proc/modules permission or run as root.\n");
-
-       if (perf_guest) {
-               machines__process_guests(&session->machines,
-                                        perf_event__synthesize_guest_os, tool);
-       }
-
-       err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
-                                           process_synthesized_event, opts->sample_address,
-                                           opts->proc_map_timeout);
-       if (err != 0)
                goto out_child;
 
        if (rec->realtime_prio) {
@@ -758,18 +811,8 @@ out_child:
        /* this will be recalculated during process_buildids() */
        rec->samples = 0;
 
-       if (!err && !file->is_pipe) {
-               rec->session->header.data_size += rec->bytes_written;
-               file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR);
-
-               if (!rec->no_buildid) {
-                       process_buildids(rec);
-
-                       if (rec->buildid_all)
-                               dsos__hit_all(rec->session);
-               }
-               perf_session__write_header(rec->session, rec->evlist, fd, true);
-       }
+       if (!err)
+               record__finish_output(rec);
 
        if (!err && !quiet) {
                char samples[128];
@@ -1097,10 +1140,12 @@ struct option __record_options[] = {
        OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
        OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
                    "don't sample"),
-       OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
-                   "do not update the buildid cache"),
-       OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
-                   "do not collect buildids in perf.data"),
+       OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
+                       &record.no_buildid_cache_set,
+                       "do not update the buildid cache"),
+       OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
+                       &record.no_buildid_set,
+                       "do not collect buildids in perf.data"),
        OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
                     "monitor event in cgroup name only",
                     parse_cgroups),
@@ -1136,6 +1181,12 @@ struct option __record_options[] = {
                        "per thread proc mmap processing timeout in ms"),
        OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
                    "Record context switch events"),
+       OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
+                        "Configure all used events to run in kernel space.",
+                        PARSE_OPT_EXCLUSIVE),
+       OPT_BOOLEAN_FLAG(0, "all-user", &record.opts.all_user,
+                        "Configure all used events to run in user space.",
+                        PARSE_OPT_EXCLUSIVE),
        OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
                   "clang binary to use for compiling BPF scriptlets"),
        OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
index 2bf537f190a026952bd63126e9c37def827e9914..7eea49f9ed46b520bdce56972379b76c14302c4b 100644 (file)
@@ -75,7 +75,10 @@ static int report__config(const char *var, const char *value, void *cb)
                return 0;
        }
        if (!strcmp(var, "report.percent-limit")) {
-               rep->min_percent = strtof(value, NULL);
+               double pcnt = strtof(value, NULL);
+
+               rep->min_percent = pcnt;
+               callchain_param.min_percent = pcnt;
                return 0;
        }
        if (!strcmp(var, "report.children")) {
@@ -87,7 +90,7 @@ static int report__config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return perf_default_config(var, value, cb);
+       return 0;
 }
 
 static int hist_iter__report_callback(struct hist_entry_iter *iter,
@@ -466,10 +469,11 @@ static int report__browse_hists(struct report *rep)
        return ret;
 }
 
-static void report__collapse_hists(struct report *rep)
+static int report__collapse_hists(struct report *rep)
 {
        struct ui_progress prog;
        struct perf_evsel *pos;
+       int ret = 0;
 
        ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
 
@@ -481,7 +485,9 @@ static void report__collapse_hists(struct report *rep)
 
                hists->socket_filter = rep->socket_filter;
 
-               hists__collapse_resort(hists, &prog);
+               ret = hists__collapse_resort(hists, &prog);
+               if (ret < 0)
+                       break;
 
                /* Non-group events are considered as leader */
                if (symbol_conf.event_group &&
@@ -494,6 +500,7 @@ static void report__collapse_hists(struct report *rep)
        }
 
        ui_progress__finish();
+       return ret;
 }
 
 static void report__output_resort(struct report *rep)
@@ -504,7 +511,7 @@ static void report__output_resort(struct report *rep)
        ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
 
        evlist__for_each(rep->session->evlist, pos)
-               hists__output_resort(evsel__hists(pos), &prog);
+               perf_evsel__output_resort(pos, &prog);
 
        ui_progress__finish();
 }
@@ -561,7 +568,11 @@ static int __cmd_report(struct report *rep)
                }
        }
 
-       report__collapse_hists(rep);
+       ret = report__collapse_hists(rep);
+       if (ret) {
+               ui__error("failed to process hist entry\n");
+               return ret;
+       }
 
        if (session_done())
                return 0;
@@ -633,8 +644,10 @@ parse_percent_limit(const struct option *opt, const char *str,
                    int unset __maybe_unused)
 {
        struct report *rep = opt->value;
+       double pcnt = strtof(str, NULL);
 
-       rep->min_percent = strtof(str, NULL);
+       rep->min_percent = pcnt;
+       callchain_param.min_percent = pcnt;
        return 0;
 }
 
@@ -798,6 +811,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                    "only show processor socket that match with this filter"),
        OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
                    "Show raw trace event output (do not use print fmt or plugins)"),
+       OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
+                   "Show entries in a hierarchy"),
        OPT_END()
        };
        struct perf_data_file file = {
@@ -907,13 +922,19 @@ repeat:
                symbol_conf.cumulate_callchain = false;
        }
 
-       if (setup_sorting(session->evlist) < 0) {
-               if (sort_order)
-                       parse_options_usage(report_usage, options, "s", 1);
-               if (field_order)
-                       parse_options_usage(sort_order ? NULL : report_usage,
-                                           options, "F", 1);
-               goto error;
+       if (symbol_conf.report_hierarchy) {
+               /* disable incompatible options */
+               symbol_conf.event_group = false;
+               symbol_conf.cumulate_callchain = false;
+
+               if (field_order) {
+                       pr_err("Error: --hierarchy and --fields options cannot be used together\n");
+                       parse_options_usage(report_usage, options, "F", 1);
+                       parse_options_usage(NULL, options, "hierarchy", 0);
+                       goto error;
+               }
+
+               sort__need_collapse = true;
        }
 
        /* Force tty output for header output and per-thread stat. */
@@ -925,6 +946,15 @@ repeat:
        else
                use_browser = 0;
 
+       if (setup_sorting(session->evlist) < 0) {
+               if (sort_order)
+                       parse_options_usage(report_usage, options, "s", 1);
+               if (field_order)
+                       parse_options_usage(sort_order ? NULL : report_usage,
+                                           options, "F", 1);
+               goto error;
+       }
+
        if (report.header || report.header_only) {
                perf_session__fprintf_info(session, stdout,
                                           report.show_full_info);
index c691214d820f0050c39e9d376d69cd5891132a47..57f9a7e7f7d3e948a29a92018140902c7f5c840f 100644 (file)
@@ -23,6 +23,7 @@
 #include "util/stat.h"
 #include <linux/bitmap.h>
 #include "asm/bug.h"
+#include "util/mem-events.h"
 
 static char const              *script_name;
 static char const              *generate_script_lang;
@@ -58,6 +59,9 @@ enum perf_output_field {
        PERF_OUTPUT_IREGS           = 1U << 14,
        PERF_OUTPUT_BRSTACK         = 1U << 15,
        PERF_OUTPUT_BRSTACKSYM      = 1U << 16,
+       PERF_OUTPUT_DATA_SRC        = 1U << 17,
+       PERF_OUTPUT_WEIGHT          = 1U << 18,
+       PERF_OUTPUT_BPF_OUTPUT      = 1U << 19,
 };
 
 struct output_option {
@@ -81,6 +85,9 @@ struct output_option {
        {.str = "iregs", .field = PERF_OUTPUT_IREGS},
        {.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
        {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
+       {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
+       {.str = "weight",   .field = PERF_OUTPUT_WEIGHT},
+       {.str = "bpf-output",   .field = PERF_OUTPUT_BPF_OUTPUT},
 };
 
 /* default set to maintain compatibility with current format */
@@ -101,7 +108,7 @@ static struct {
                              PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
                              PERF_OUTPUT_PERIOD,
 
-               .invalid_fields = PERF_OUTPUT_TRACE,
+               .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
        },
 
        [PERF_TYPE_SOFTWARE] = {
@@ -111,7 +118,7 @@ static struct {
                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
                              PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
                              PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
-                             PERF_OUTPUT_PERIOD,
+                             PERF_OUTPUT_PERIOD | PERF_OUTPUT_BPF_OUTPUT,
 
                .invalid_fields = PERF_OUTPUT_TRACE,
        },
@@ -121,7 +128,7 @@ static struct {
 
                .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
                                  PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
-                                 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
+                                 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE
        },
 
        [PERF_TYPE_RAW] = {
@@ -131,9 +138,10 @@ static struct {
                              PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
                              PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
                              PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
-                             PERF_OUTPUT_PERIOD,
+                             PERF_OUTPUT_PERIOD |  PERF_OUTPUT_ADDR |
+                             PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT,
 
-               .invalid_fields = PERF_OUTPUT_TRACE,
+               .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
        },
 
        [PERF_TYPE_BREAKPOINT] = {
@@ -145,7 +153,7 @@ static struct {
                              PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
                              PERF_OUTPUT_PERIOD,
 
-               .invalid_fields = PERF_OUTPUT_TRACE,
+               .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
        },
 };
 
@@ -242,6 +250,16 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
                                           PERF_OUTPUT_ADDR, allow_user_set))
                return -EINVAL;
 
+       if (PRINT_FIELD(DATA_SRC) &&
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_DATA_SRC, "DATA_SRC",
+                                       PERF_OUTPUT_DATA_SRC))
+               return -EINVAL;
+
+       if (PRINT_FIELD(WEIGHT) &&
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_WEIGHT, "WEIGHT",
+                                       PERF_OUTPUT_WEIGHT))
+               return -EINVAL;
+
        if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
                pr_err("Display of symbols requested but neither sample IP nor "
                           "sample address\nis selected. Hence, no addresses to convert "
@@ -608,6 +626,84 @@ static void print_sample_flags(u32 flags)
        printf("  %-4s ", str);
 }
 
+struct printer_data {
+       int line_no;
+       bool hit_nul;
+       bool is_printable;
+};
+
+static void
+print_sample_bpf_output_printer(enum binary_printer_ops op,
+                               unsigned int val,
+                               void *extra)
+{
+       unsigned char ch = (unsigned char)val;
+       struct printer_data *printer_data = extra;
+
+       switch (op) {
+       case BINARY_PRINT_DATA_BEGIN:
+               printf("\n");
+               break;
+       case BINARY_PRINT_LINE_BEGIN:
+               printf("%17s", !printer_data->line_no ? "BPF output:" :
+                                                       "           ");
+               break;
+       case BINARY_PRINT_ADDR:
+               printf(" %04x:", val);
+               break;
+       case BINARY_PRINT_NUM_DATA:
+               printf(" %02x", val);
+               break;
+       case BINARY_PRINT_NUM_PAD:
+               printf("   ");
+               break;
+       case BINARY_PRINT_SEP:
+               printf("  ");
+               break;
+       case BINARY_PRINT_CHAR_DATA:
+               if (printer_data->hit_nul && ch)
+                       printer_data->is_printable = false;
+
+               if (!isprint(ch)) {
+                       printf("%c", '.');
+
+                       if (!printer_data->is_printable)
+                               break;
+
+                       if (ch == '\0')
+                               printer_data->hit_nul = true;
+                       else
+                               printer_data->is_printable = false;
+               } else {
+                       printf("%c", ch);
+               }
+               break;
+       case BINARY_PRINT_CHAR_PAD:
+               printf(" ");
+               break;
+       case BINARY_PRINT_LINE_END:
+               printf("\n");
+               printer_data->line_no++;
+               break;
+       case BINARY_PRINT_DATA_END:
+       default:
+               break;
+       }
+}
+
+static void print_sample_bpf_output(struct perf_sample *sample)
+{
+       unsigned int nr_bytes = sample->raw_size;
+       struct printer_data printer_data = {0, false, true};
+
+       print_binary(sample->raw_data, nr_bytes, 8,
+                    print_sample_bpf_output_printer, &printer_data);
+
+       if (printer_data.is_printable && printer_data.hit_nul)
+               printf("%17s \"%s\"\n", "BPF string:",
+                      (char *)(sample->raw_data));
+}
+
 struct perf_script {
        struct perf_tool        tool;
        struct perf_session     *session;
@@ -634,6 +730,23 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist)
        return max;
 }
 
+static size_t data_src__printf(u64 data_src)
+{
+       struct mem_info mi = { .data_src.val = data_src };
+       char decode[100];
+       char out[100];
+       static int maxlen;
+       int len;
+
+       perf_script__meminfo_scnprintf(decode, 100, &mi);
+
+       len = scnprintf(out, 100, "%16" PRIx64 " %s", data_src, decode);
+       if (maxlen < len)
+               maxlen = len;
+
+       return printf("%-*s", maxlen, out);
+}
+
 static void process_event(struct perf_script *script, union perf_event *event,
                          struct perf_sample *sample, struct perf_evsel *evsel,
                          struct addr_location *al)
@@ -673,6 +786,12 @@ static void process_event(struct perf_script *script, union perf_event *event,
        if (PRINT_FIELD(ADDR))
                print_sample_addr(event, sample, thread, attr);
 
+       if (PRINT_FIELD(DATA_SRC))
+               data_src__printf(sample->data_src);
+
+       if (PRINT_FIELD(WEIGHT))
+               printf("%16" PRIu64, sample->weight);
+
        if (PRINT_FIELD(IP)) {
                if (!symbol_conf.use_callchain)
                        printf(" ");
@@ -692,6 +811,9 @@ static void process_event(struct perf_script *script, union perf_event *event,
        else if (PRINT_FIELD(BRSTACKSYM))
                print_sample_brstacksym(event, sample, thread, attr);
 
+       if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
+               print_sample_bpf_output(sample);
+
        printf("\n");
 }
 
@@ -1090,23 +1212,6 @@ static struct script_spec *script_spec__find(const char *spec)
        return NULL;
 }
 
-static struct script_spec *script_spec__findnew(const char *spec,
-                                               struct scripting_ops *ops)
-{
-       struct script_spec *s = script_spec__find(spec);
-
-       if (s)
-               return s;
-
-       s = script_spec__new(spec, ops);
-       if (!s)
-               return NULL;
-
-       script_spec__add(s);
-
-       return s;
-}
-
 int script_spec_register(const char *spec, struct scripting_ops *ops)
 {
        struct script_spec *s;
@@ -1115,9 +1220,11 @@ int script_spec_register(const char *spec, struct scripting_ops *ops)
        if (s)
                return -1;
 
-       s = script_spec__findnew(spec, ops);
+       s = script_spec__new(spec, ops);
        if (!s)
                return -1;
+       else
+               script_spec__add(s);
 
        return 0;
 }
index 038e877081b682dd8d9ba052a0be66c8ac2786c6..1f19f2f999c841b9da140e10bcaf5e6e0f41ee6b 100644 (file)
@@ -122,6 +122,7 @@ static bool                 sync_run                        = false;
 static unsigned int            initial_delay                   = 0;
 static unsigned int            unit_width                      = 4; /* strlen("unit") */
 static bool                    forever                         = false;
+static bool                    metric_only                     = false;
 static struct timespec         ref_time;
 static struct cpu_map          *aggr_map;
 static aggr_get_id_t           aggr_get_id;
@@ -735,6 +736,191 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
        }
 }
 
+struct outstate {
+       FILE *fh;
+       bool newline;
+       const char *prefix;
+       int  nfields;
+       int  id, nr;
+       struct perf_evsel *evsel;
+};
+
+#define METRIC_LEN  35
+
+static void new_line_std(void *ctx)
+{
+       struct outstate *os = ctx;
+
+       os->newline = true;
+}
+
+static void do_new_line_std(struct outstate *os)
+{
+       fputc('\n', os->fh);
+       fputs(os->prefix, os->fh);
+       aggr_printout(os->evsel, os->id, os->nr);
+       if (stat_config.aggr_mode == AGGR_NONE)
+               fprintf(os->fh, "        ");
+       fprintf(os->fh, "                                                 ");
+}
+
+static void print_metric_std(void *ctx, const char *color, const char *fmt,
+                            const char *unit, double val)
+{
+       struct outstate *os = ctx;
+       FILE *out = os->fh;
+       int n;
+       bool newline = os->newline;
+
+       os->newline = false;
+
+       if (unit == NULL || fmt == NULL) {
+               fprintf(out, "%-*s", METRIC_LEN, "");
+               return;
+       }
+
+       if (newline)
+               do_new_line_std(os);
+
+       n = fprintf(out, " # ");
+       if (color)
+               n += color_fprintf(out, color, fmt, val);
+       else
+               n += fprintf(out, fmt, val);
+       fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
+}
+
+static void new_line_csv(void *ctx)
+{
+       struct outstate *os = ctx;
+       int i;
+
+       fputc('\n', os->fh);
+       if (os->prefix)
+               fprintf(os->fh, "%s%s", os->prefix, csv_sep);
+       aggr_printout(os->evsel, os->id, os->nr);
+       for (i = 0; i < os->nfields; i++)
+               fputs(csv_sep, os->fh);
+}
+
+static void print_metric_csv(void *ctx,
+                            const char *color __maybe_unused,
+                            const char *fmt, const char *unit, double val)
+{
+       struct outstate *os = ctx;
+       FILE *out = os->fh;
+       char buf[64], *vals, *ends;
+
+       if (unit == NULL || fmt == NULL) {
+               fprintf(out, "%s%s%s%s", csv_sep, csv_sep, csv_sep, csv_sep);
+               return;
+       }
+       snprintf(buf, sizeof(buf), fmt, val);
+       vals = buf;
+       while (isspace(*vals))
+               vals++;
+       ends = vals;
+       while (isdigit(*ends) || *ends == '.')
+               ends++;
+       *ends = 0;
+       while (isspace(*unit))
+               unit++;
+       fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit);
+}
+
+#define METRIC_ONLY_LEN 20
+
+/* Filter out some columns that don't work well in metrics only mode */
+
+static bool valid_only_metric(const char *unit)
+{
+       if (!unit)
+               return false;
+       if (strstr(unit, "/sec") ||
+           strstr(unit, "hz") ||
+           strstr(unit, "Hz") ||
+           strstr(unit, "CPUs utilized"))
+               return false;
+       return true;
+}
+
+static const char *fixunit(char *buf, struct perf_evsel *evsel,
+                          const char *unit)
+{
+       if (!strncmp(unit, "of all", 6)) {
+               snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel),
+                        unit);
+               return buf;
+       }
+       return unit;
+}
+
+static void print_metric_only(void *ctx, const char *color, const char *fmt,
+                             const char *unit, double val)
+{
+       struct outstate *os = ctx;
+       FILE *out = os->fh;
+       int n;
+       char buf[1024];
+       unsigned mlen = METRIC_ONLY_LEN;
+
+       if (!valid_only_metric(unit))
+               return;
+       unit = fixunit(buf, os->evsel, unit);
+       if (color)
+               n = color_fprintf(out, color, fmt, val);
+       else
+               n = fprintf(out, fmt, val);
+       if (n > METRIC_ONLY_LEN)
+               n = METRIC_ONLY_LEN;
+       if (mlen < strlen(unit))
+               mlen = strlen(unit) + 1;
+       fprintf(out, "%*s", mlen - n, "");
+}
+
+static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
+                                 const char *fmt,
+                                 const char *unit, double val)
+{
+       struct outstate *os = ctx;
+       FILE *out = os->fh;
+       char buf[64], *vals, *ends;
+       char tbuf[1024];
+
+       if (!valid_only_metric(unit))
+               return;
+       unit = fixunit(tbuf, os->evsel, unit);
+       snprintf(buf, sizeof buf, fmt, val);
+       vals = buf;
+       while (isspace(*vals))
+               vals++;
+       ends = vals;
+       while (isdigit(*ends) || *ends == '.')
+               ends++;
+       *ends = 0;
+       fprintf(out, "%s%s", vals, csv_sep);
+}
+
+static void new_line_metric(void *ctx __maybe_unused)
+{
+}
+
+static void print_metric_header(void *ctx, const char *color __maybe_unused,
+                               const char *fmt __maybe_unused,
+                               const char *unit, double val __maybe_unused)
+{
+       struct outstate *os = ctx;
+       char tbuf[1024];
+
+       if (!valid_only_metric(unit))
+               return;
+       unit = fixunit(tbuf, os->evsel, unit);
+       if (csv_output)
+               fprintf(os->fh, "%s%s", unit, csv_sep);
+       else
+               fprintf(os->fh, "%-*s ", METRIC_ONLY_LEN, unit);
+}
+
 static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 {
        FILE *output = stat_config.output;
@@ -763,6 +949,28 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
 }
 
+static int first_shadow_cpu(struct perf_evsel *evsel, int id)
+{
+       int i;
+
+       if (!aggr_get_id)
+               return 0;
+
+       if (stat_config.aggr_mode == AGGR_NONE)
+               return id;
+
+       if (stat_config.aggr_mode == AGGR_GLOBAL)
+               return 0;
+
+       for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) {
+               int cpu2 = perf_evsel__cpus(evsel)->map[i];
+
+               if (aggr_get_id(evsel_list->cpus, cpu2) == id)
+                       return cpu2;
+       }
+       return 0;
+}
+
 static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 {
        FILE *output = stat_config.output;
@@ -793,22 +1001,124 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
 }
 
-static void printout(int id, int nr, struct perf_evsel *counter, double uval)
+static void printout(int id, int nr, struct perf_evsel *counter, double uval,
+                    char *prefix, u64 run, u64 ena, double noise)
 {
-       int cpu = cpu_map__id_to_cpu(id);
+       struct perf_stat_output_ctx out;
+       struct outstate os = {
+               .fh = stat_config.output,
+               .prefix = prefix ? prefix : "",
+               .id = id,
+               .nr = nr,
+               .evsel = counter,
+       };
+       print_metric_t pm = print_metric_std;
+       void (*nl)(void *);
 
-       if (stat_config.aggr_mode == AGGR_GLOBAL)
-               cpu = 0;
+       if (metric_only) {
+               nl = new_line_metric;
+               if (csv_output)
+                       pm = print_metric_only_csv;
+               else
+                       pm = print_metric_only;
+       } else
+               nl = new_line_std;
+
+       if (csv_output && !metric_only) {
+               static int aggr_fields[] = {
+                       [AGGR_GLOBAL] = 0,
+                       [AGGR_THREAD] = 1,
+                       [AGGR_NONE] = 1,
+                       [AGGR_SOCKET] = 2,
+                       [AGGR_CORE] = 2,
+               };
+
+               pm = print_metric_csv;
+               nl = new_line_csv;
+               os.nfields = 3;
+               os.nfields += aggr_fields[stat_config.aggr_mode];
+               if (counter->cgrp)
+                       os.nfields++;
+       }
+       if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
+               if (metric_only) {
+                       pm(&os, NULL, "", "", 0);
+                       return;
+               }
+               aggr_printout(counter, id, nr);
+
+               fprintf(stat_config.output, "%*s%s",
+                       csv_output ? 0 : 18,
+                       counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
+                       csv_sep);
+
+               fprintf(stat_config.output, "%-*s%s",
+                       csv_output ? 0 : unit_width,
+                       counter->unit, csv_sep);
+
+               fprintf(stat_config.output, "%*s",
+                       csv_output ? 0 : -25,
+                       perf_evsel__name(counter));
+
+               if (counter->cgrp)
+                       fprintf(stat_config.output, "%s%s",
+                               csv_sep, counter->cgrp->name);
 
-       if (nsec_counter(counter))
+               if (!csv_output)
+                       pm(&os, NULL, NULL, "", 0);
+               print_noise(counter, noise);
+               print_running(run, ena);
+               if (csv_output)
+                       pm(&os, NULL, NULL, "", 0);
+               return;
+       }
+
+       if (metric_only)
+               /* nothing */;
+       else if (nsec_counter(counter))
                nsec_printout(id, nr, counter, uval);
        else
                abs_printout(id, nr, counter, uval);
 
-       if (!csv_output && !stat_config.interval)
-               perf_stat__print_shadow_stats(stat_config.output, counter,
-                                             uval, cpu,
-                                             stat_config.aggr_mode);
+       out.print_metric = pm;
+       out.new_line = nl;
+       out.ctx = &os;
+
+       if (csv_output && !metric_only) {
+               print_noise(counter, noise);
+               print_running(run, ena);
+       }
+
+       perf_stat__print_shadow_stats(counter, uval,
+                               first_shadow_cpu(counter, id),
+                               &out);
+       if (!csv_output && !metric_only) {
+               print_noise(counter, noise);
+               print_running(run, ena);
+       }
+}
+
+static void aggr_update_shadow(void)
+{
+       int cpu, s2, id, s;
+       u64 val;
+       struct perf_evsel *counter;
+
+       for (s = 0; s < aggr_map->nr; s++) {
+               id = aggr_map->map[s];
+               evlist__for_each(evsel_list, counter) {
+                       val = 0;
+                       for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+                               s2 = aggr_get_id(evsel_list->cpus, cpu);
+                               if (s2 != id)
+                                       continue;
+                               val += perf_counts(counter->counts, cpu, 0)->val;
+                       }
+                       val = val * counter->scale;
+                       perf_stat__update_shadow_stats(counter, &val,
+                                                      first_shadow_cpu(counter, id));
+               }
+       }
 }
 
 static void print_aggr(char *prefix)
@@ -818,12 +1128,23 @@ static void print_aggr(char *prefix)
        int cpu, s, s2, id, nr;
        double uval;
        u64 ena, run, val;
+       bool first;
 
        if (!(aggr_map || aggr_get_id))
                return;
 
+       aggr_update_shadow();
+
+       /*
+        * With metric_only everything is on a single line.
+        * Without each counter has its own line.
+        */
        for (s = 0; s < aggr_map->nr; s++) {
+               if (prefix && metric_only)
+                       fprintf(output, "%s", prefix);
+
                id = aggr_map->map[s];
+               first = true;
                evlist__for_each(evsel_list, counter) {
                        val = ena = run = 0;
                        nr = 0;
@@ -836,41 +1157,20 @@ static void print_aggr(char *prefix)
                                run += perf_counts(counter->counts, cpu, 0)->run;
                                nr++;
                        }
-                       if (prefix)
-                               fprintf(output, "%s", prefix);
-
-                       if (run == 0 || ena == 0) {
+                       if (first && metric_only) {
+                               first = false;
                                aggr_printout(counter, id, nr);
-
-                               fprintf(output, "%*s%s",
-                                       csv_output ? 0 : 18,
-                                       counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                                       csv_sep);
-
-                               fprintf(output, "%-*s%s",
-                                       csv_output ? 0 : unit_width,
-                                       counter->unit, csv_sep);
-
-                               fprintf(output, "%*s",
-                                       csv_output ? 0 : -25,
-                                       perf_evsel__name(counter));
-
-                               if (counter->cgrp)
-                                       fprintf(output, "%s%s",
-                                               csv_sep, counter->cgrp->name);
-
-                               print_running(run, ena);
-                               fputc('\n', output);
-                               continue;
                        }
-                       uval = val * counter->scale;
-                       printout(id, nr, counter, uval);
-                       if (!csv_output)
-                               print_noise(counter, 1.0);
+                       if (prefix && !metric_only)
+                               fprintf(output, "%s", prefix);
 
-                       print_running(run, ena);
-                       fputc('\n', output);
+                       uval = val * counter->scale;
+                       printout(id, nr, counter, uval, prefix, run, ena, 1.0);
+                       if (!metric_only)
+                               fputc('\n', output);
                }
+               if (metric_only)
+                       fputc('\n', output);
        }
 }
 
@@ -895,12 +1195,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
                        fprintf(output, "%s", prefix);
 
                uval = val * counter->scale;
-               printout(thread, 0, counter, uval);
-
-               if (!csv_output)
-                       print_noise(counter, 1.0);
-
-               print_running(run, ena);
+               printout(thread, 0, counter, uval, prefix, run, ena, 1.0);
                fputc('\n', output);
        }
 }
@@ -914,43 +1209,19 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
        FILE *output = stat_config.output;
        struct perf_stat_evsel *ps = counter->priv;
        double avg = avg_stats(&ps->res_stats[0]);
-       int scaled = counter->counts->scaled;
        double uval;
        double avg_enabled, avg_running;
 
        avg_enabled = avg_stats(&ps->res_stats[1]);
        avg_running = avg_stats(&ps->res_stats[2]);
 
-       if (prefix)
+       if (prefix && !metric_only)
                fprintf(output, "%s", prefix);
 
-       if (scaled == -1 || !counter->supported) {
-               fprintf(output, "%*s%s",
-                       csv_output ? 0 : 18,
-                       counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                       csv_sep);
-               fprintf(output, "%-*s%s",
-                       csv_output ? 0 : unit_width,
-                       counter->unit, csv_sep);
-               fprintf(output, "%*s",
-                       csv_output ? 0 : -25,
-                       perf_evsel__name(counter));
-
-               if (counter->cgrp)
-                       fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
-
-               print_running(avg_running, avg_enabled);
-               fputc('\n', output);
-               return;
-       }
-
        uval = avg * counter->scale;
-       printout(-1, 0, counter, uval);
-
-       print_noise(counter, avg);
-
-       print_running(avg_running, avg_enabled);
-       fprintf(output, "\n");
+       printout(-1, 0, counter, uval, prefix, avg_running, avg_enabled, avg);
+       if (!metric_only)
+               fprintf(output, "\n");
 }
 
 /*
@@ -972,39 +1243,78 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
                if (prefix)
                        fprintf(output, "%s", prefix);
 
-               if (run == 0 || ena == 0) {
-                       fprintf(output, "CPU%*d%s%*s%s",
-                               csv_output ? 0 : -4,
-                               perf_evsel__cpus(counter)->map[cpu], csv_sep,
-                               csv_output ? 0 : 18,
-                               counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
-                               csv_sep);
+               uval = val * counter->scale;
+               printout(cpu, 0, counter, uval, prefix, run, ena, 1.0);
 
-                               fprintf(output, "%-*s%s",
-                                       csv_output ? 0 : unit_width,
-                                       counter->unit, csv_sep);
+               fputc('\n', output);
+       }
+}
 
-                               fprintf(output, "%*s",
-                                       csv_output ? 0 : -25,
-                                       perf_evsel__name(counter));
+static void print_no_aggr_metric(char *prefix)
+{
+       int cpu;
+       int nrcpus = 0;
+       struct perf_evsel *counter;
+       u64 ena, run, val;
+       double uval;
 
-                       if (counter->cgrp)
-                               fprintf(output, "%s%s",
-                                       csv_sep, counter->cgrp->name);
+       nrcpus = evsel_list->cpus->nr;
+       for (cpu = 0; cpu < nrcpus; cpu++) {
+               bool first = true;
 
-                       print_running(run, ena);
-                       fputc('\n', output);
-                       continue;
+               if (prefix)
+                       fputs(prefix, stat_config.output);
+               evlist__for_each(evsel_list, counter) {
+                       if (first) {
+                               aggr_printout(counter, cpu, 0);
+                               first = false;
+                       }
+                       val = perf_counts(counter->counts, cpu, 0)->val;
+                       ena = perf_counts(counter->counts, cpu, 0)->ena;
+                       run = perf_counts(counter->counts, cpu, 0)->run;
+
+                       uval = val * counter->scale;
+                       printout(cpu, 0, counter, uval, prefix, run, ena, 1.0);
                }
+               fputc('\n', stat_config.output);
+       }
+}
 
-               uval = val * counter->scale;
-               printout(cpu, 0, counter, uval);
-               if (!csv_output)
-                       print_noise(counter, 1.0);
-               print_running(run, ena);
+static int aggr_header_lens[] = {
+       [AGGR_CORE] = 18,
+       [AGGR_SOCKET] = 12,
+       [AGGR_NONE] = 6,
+       [AGGR_THREAD] = 24,
+       [AGGR_GLOBAL] = 0,
+};
 
-               fputc('\n', output);
+static void print_metric_headers(char *prefix)
+{
+       struct perf_stat_output_ctx out;
+       struct perf_evsel *counter;
+       struct outstate os = {
+               .fh = stat_config.output
+       };
+
+       if (prefix)
+               fprintf(stat_config.output, "%s", prefix);
+
+       if (!csv_output)
+               fprintf(stat_config.output, "%*s",
+                       aggr_header_lens[stat_config.aggr_mode], "");
+
+       /* Print metrics headers only */
+       evlist__for_each(evsel_list, counter) {
+               os.evsel = counter;
+               out.ctx = &os;
+               out.print_metric = print_metric_header;
+               out.new_line = new_line_metric;
+               os.evsel = counter;
+               perf_stat__print_shadow_stats(counter, 0,
+                                             0,
+                                             &out);
        }
+       fputc('\n', stat_config.output);
 }
 
 static void print_interval(char *prefix, struct timespec *ts)
@@ -1014,7 +1324,7 @@ static void print_interval(char *prefix, struct timespec *ts)
 
        sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
 
-       if (num_print_interval == 0 && !csv_output) {
+       if (num_print_interval == 0 && !csv_output && !metric_only) {
                switch (stat_config.aggr_mode) {
                case AGGR_SOCKET:
                        fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
@@ -1101,6 +1411,17 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
        else
                print_header(argc, argv);
 
+       if (metric_only) {
+               static int num_print_iv;
+
+               if (num_print_iv == 0)
+                       print_metric_headers(prefix);
+               if (num_print_iv++ == 25)
+                       num_print_iv = 0;
+               if (stat_config.aggr_mode == AGGR_GLOBAL && prefix)
+                       fprintf(stat_config.output, "%s", prefix);
+       }
+
        switch (stat_config.aggr_mode) {
        case AGGR_CORE:
        case AGGR_SOCKET:
@@ -1113,10 +1434,16 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
        case AGGR_GLOBAL:
                evlist__for_each(evsel_list, counter)
                        print_counter_aggr(counter, prefix);
+               if (metric_only)
+                       fputc('\n', stat_config.output);
                break;
        case AGGR_NONE:
-               evlist__for_each(evsel_list, counter)
-                       print_counter(counter, prefix);
+               if (metric_only)
+                       print_no_aggr_metric(prefix);
+               else {
+                       evlist__for_each(evsel_list, counter)
+                               print_counter(counter, prefix);
+               }
                break;
        case AGGR_UNSET:
        default:
@@ -1237,6 +1564,8 @@ static const struct option stat_options[] = {
                     "aggregate counts per thread", AGGR_THREAD),
        OPT_UINTEGER('D', "delay", &initial_delay,
                     "ms to wait before starting measurement after program start"),
+       OPT_BOOLEAN(0, "metric-only", &metric_only,
+                       "Only print computed metrics. No raw values"),
        OPT_END()
 };
 
@@ -1435,7 +1764,7 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
  */
 static int add_default_attributes(void)
 {
-       struct perf_event_attr default_attrs[] = {
+       struct perf_event_attr default_attrs0[] = {
 
   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK             },
   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES       },
@@ -1443,8 +1772,14 @@ static int add_default_attributes(void)
   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS            },
 
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES             },
+};
+       struct perf_event_attr frontend_attrs[] = {
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND        },
+};
+       struct perf_event_attr backend_attrs[] = {
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
+};
+       struct perf_event_attr default_attrs1[] = {
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS           },
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS    },
   { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES          },
@@ -1561,7 +1896,19 @@ static int add_default_attributes(void)
        }
 
        if (!evsel_list->nr_entries) {
-               if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0)
+               if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0)
+                       return -1;
+               if (pmu_have_event("cpu", "stalled-cycles-frontend")) {
+                       if (perf_evlist__add_default_attrs(evsel_list,
+                                               frontend_attrs) < 0)
+                               return -1;
+               }
+               if (pmu_have_event("cpu", "stalled-cycles-backend")) {
+                       if (perf_evlist__add_default_attrs(evsel_list,
+                                               backend_attrs) < 0)
+                               return -1;
+               }
+               if (perf_evlist__add_default_attrs(evsel_list, default_attrs1) < 0)
                        return -1;
        }
 
@@ -1825,9 +2172,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
        if (evsel_list == NULL)
                return -ENOMEM;
 
+       parse_events__shrink_config_terms();
        argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,
                                        (const char **) stat_usage,
                                        PARSE_OPT_STOP_AT_NON_OPTION);
+       perf_stat__init_shadow_stats();
 
        if (csv_sep) {
                csv_output = true;
@@ -1858,6 +2207,16 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
                goto out;
        }
 
+       if (metric_only && stat_config.aggr_mode == AGGR_THREAD) {
+               fprintf(stderr, "--metric-only is not supported with --per-thread\n");
+               goto out;
+       }
+
+       if (metric_only && run_count > 1) {
+               fprintf(stderr, "--metric-only is not supported with -r\n");
+               goto out;
+       }
+
        if (output_fd < 0) {
                fprintf(stderr, "argument to --log-fd must be a > 0\n");
                parse_options_usage(stat_usage, stat_options, "log-fd", 0);
index bf01cbb0ef2369f2fc904809b86b70a823bdb604..94af190f6843d2c92e68b2dfef8dc51017c42079 100644 (file)
@@ -252,7 +252,8 @@ static void perf_top__print_sym_table(struct perf_top *top)
        char bf[160];
        int printed = 0;
        const int win_width = top->winsize.ws_col - 1;
-       struct hists *hists = evsel__hists(top->sym_evsel);
+       struct perf_evsel *evsel = top->sym_evsel;
+       struct hists *hists = evsel__hists(evsel);
 
        puts(CONSOLE_CLEAR);
 
@@ -288,7 +289,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
        }
 
        hists__collapse_resort(hists, NULL);
-       hists__output_resort(hists, NULL);
+       perf_evsel__output_resort(evsel, NULL);
 
        hists__output_recalc_col_len(hists, top->print_entries - printed);
        putchar('\n');
@@ -540,6 +541,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
 static void perf_top__sort_new_samples(void *arg)
 {
        struct perf_top *t = arg;
+       struct perf_evsel *evsel = t->sym_evsel;
        struct hists *hists;
 
        perf_top__reset_sample_counters(t);
@@ -547,7 +549,7 @@ static void perf_top__sort_new_samples(void *arg)
        if (t->evlist->selected != NULL)
                t->sym_evsel = t->evlist->selected;
 
-       hists = evsel__hists(t->sym_evsel);
+       hists = evsel__hists(evsel);
 
        if (t->evlist->enabled) {
                if (t->zero) {
@@ -559,7 +561,7 @@ static void perf_top__sort_new_samples(void *arg)
        }
 
        hists__collapse_resort(hists, NULL);
-       hists__output_resort(hists, NULL);
+       perf_evsel__output_resort(evsel, NULL);
 }
 
 static void *display_thread_tui(void *arg)
@@ -1063,7 +1065,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
        return parse_callchain_top_opt(arg);
 }
 
-static int perf_top_config(const char *var, const char *value, void *cb)
+static int perf_top_config(const char *var, const char *value, void *cb __maybe_unused)
 {
        if (!strcmp(var, "top.call-graph"))
                var = "call-graph.record-mode"; /* fall-through */
@@ -1072,7 +1074,7 @@ static int perf_top_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return perf_default_config(var, value, cb);
+       return 0;
 }
 
 static int
@@ -1212,6 +1214,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                     parse_branch_stack),
        OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
                    "Show raw trace event output (do not use print fmt or plugins)"),
+       OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
+                   "Show entries in a hierarchy"),
        OPT_END()
        };
        const char * const top_usage[] = {
@@ -1239,10 +1243,30 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                goto out_delete_evlist;
        }
 
+       if (symbol_conf.report_hierarchy) {
+               /* disable incompatible options */
+               symbol_conf.event_group = false;
+               symbol_conf.cumulate_callchain = false;
+
+               if (field_order) {
+                       pr_err("Error: --hierarchy and --fields options cannot be used together\n");
+                       parse_options_usage(top_usage, options, "fields", 0);
+                       parse_options_usage(NULL, options, "hierarchy", 0);
+                       goto out_delete_evlist;
+               }
+       }
+
        sort__mode = SORT_MODE__TOP;
        /* display thread wants entries to be collapsed in a different tree */
        sort__need_collapse = 1;
 
+       if (top.use_stdio)
+               use_browser = 0;
+       else if (top.use_tui)
+               use_browser = 1;
+
+       setup_browser(false);
+
        if (setup_sorting(top.evlist) < 0) {
                if (sort_order)
                        parse_options_usage(top_usage, options, "s", 1);
@@ -1252,13 +1276,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
                goto out_delete_evlist;
        }
 
-       if (top.use_stdio)
-               use_browser = 0;
-       else if (top.use_tui)
-               use_browser = 1;
-
-       setup_browser(false);
-
        status = target__validate(target);
        if (status) {
                target__strerror(target, status, errbuf, BUFSIZ);
index 20916dd77aac24847bffbaa5d1c0fb56580d6e39..8dc98c598b1aed734ab6a6695c7308f3c16e0910 100644 (file)
@@ -33,6 +33,7 @@
 #include "util/stat.h"
 #include "trace-event.h"
 #include "util/parse-events.h"
+#include "util/bpf-loader.h"
 
 #include <libaudit.h>
 #include <stdlib.h>
@@ -1724,8 +1725,12 @@ static int trace__read_syscall_info(struct trace *trace, int id)
 
        sc->args = sc->tp_format->format.fields;
        sc->nr_args = sc->tp_format->format.nr_fields;
-       /* drop nr field - not relevant here; does not exist on older kernels */
-       if (sc->args && strcmp(sc->args->name, "nr") == 0) {
+       /*
+        * We need to check and discard the first variable '__syscall_nr'
+        * or 'nr' that mean the syscall number. It is needless here.
+        * So drop '__syscall_nr' or 'nr' field but does not exist on older kernels.
+        */
+       if (sc->args && (!strcmp(sc->args->name, "__syscall_nr") || !strcmp(sc->args->name, "nr"))) {
                sc->args = sc->args->next;
                --sc->nr_args;
        }
@@ -2177,6 +2182,37 @@ out_dump:
        return 0;
 }
 
+static void bpf_output__printer(enum binary_printer_ops op,
+                               unsigned int val, void *extra)
+{
+       FILE *output = extra;
+       unsigned char ch = (unsigned char)val;
+
+       switch (op) {
+       case BINARY_PRINT_CHAR_DATA:
+               fprintf(output, "%c", isprint(ch) ? ch : '.');
+               break;
+       case BINARY_PRINT_DATA_BEGIN:
+       case BINARY_PRINT_LINE_BEGIN:
+       case BINARY_PRINT_ADDR:
+       case BINARY_PRINT_NUM_DATA:
+       case BINARY_PRINT_NUM_PAD:
+       case BINARY_PRINT_SEP:
+       case BINARY_PRINT_CHAR_PAD:
+       case BINARY_PRINT_LINE_END:
+       case BINARY_PRINT_DATA_END:
+       default:
+               break;
+       }
+}
+
+static void bpf_output__fprintf(struct trace *trace,
+                               struct perf_sample *sample)
+{
+       print_binary(sample->raw_data, sample->raw_size, 8,
+                    bpf_output__printer, trace->output);
+}
+
 static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
                                union perf_event *event __maybe_unused,
                                struct perf_sample *sample)
@@ -2189,7 +2225,9 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
 
        fprintf(trace->output, "%s:", evsel->name);
 
-       if (evsel->tp_format) {
+       if (perf_evsel__is_bpf_output(evsel)) {
+               bpf_output__fprintf(trace, sample);
+       } else if (evsel->tp_format) {
                event_format__fprintf(evsel->tp_format, sample->cpu,
                                      sample->raw_data, sample->raw_size,
                                      trace->output);
@@ -2586,6 +2624,16 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
        if (err < 0)
                goto out_error_open;
 
+       err = bpf__apply_obj_config();
+       if (err) {
+               char errbuf[BUFSIZ];
+
+               bpf__strerror_apply_obj_config(err, errbuf, sizeof(errbuf));
+               pr_err("ERROR: Apply config to BPF failed: %s\n",
+                        errbuf);
+               goto out_error_open;
+       }
+
        /*
         * Better not use !target__has_task() here because we need to cover the
         * case where no threads were specified in the command line, but a
index 511141b102e8464fe3e102007f792220306ad3b9..eca6a912e8c22b0df342a7d955c6bad2db5ddf47 100644 (file)
@@ -61,50 +61,45 @@ endif
 
 ifeq ($(LIBUNWIND_LIBS),)
   NO_LIBUNWIND := 1
-else
-  #
-  # For linking with debug library, run like:
-  #
-  #   make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
-  #
-  ifdef LIBUNWIND_DIR
-    LIBUNWIND_CFLAGS  = -I$(LIBUNWIND_DIR)/include
-    LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
-  endif
-  LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
-
-  # Set per-feature check compilation flags
-  FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
-  FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS)
-  FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
-  FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS)
 endif
+#
+# For linking with debug library, run like:
+#
+#   make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
+#
+ifdef LIBUNWIND_DIR
+  LIBUNWIND_CFLAGS  = -I$(LIBUNWIND_DIR)/include
+  LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
+endif
+LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
+
+# Set per-feature check compilation flags
+FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
+FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS)
+FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
+FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS)
 
 ifeq ($(NO_PERF_REGS),0)
   CFLAGS += -DHAVE_PERF_REGS_SUPPORT
 endif
 
-ifndef NO_LIBELF
-  # for linking with debug library, run like:
-  # make DEBUG=1 LIBDW_DIR=/opt/libdw/
-  ifdef LIBDW_DIR
-    LIBDW_CFLAGS  := -I$(LIBDW_DIR)/include
-    LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
-  endif
-  FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
-  FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
+# for linking with debug library, run like:
+# make DEBUG=1 LIBDW_DIR=/opt/libdw/
+ifdef LIBDW_DIR
+  LIBDW_CFLAGS  := -I$(LIBDW_DIR)/include
+  LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
 endif
+FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
+FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
 
-ifdef LIBBABELTRACE
-  # for linking with debug library, run like:
-  # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
-  ifdef LIBBABELTRACE_DIR
-    LIBBABELTRACE_CFLAGS  := -I$(LIBBABELTRACE_DIR)/include
-    LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib
-  endif
-  FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
-  FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
+# for linking with debug library, run like:
+# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
+ifdef LIBBABELTRACE_DIR
+  LIBBABELTRACE_CFLAGS  := -I$(LIBBABELTRACE_DIR)/include
+  LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib
 endif
+FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
+FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
 
 FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi
 # include ARCH specific config
@@ -145,28 +140,26 @@ ifdef PARSER_DEBUG
   $(call detected_var,PARSER_DEBUG_FLEX)
 endif
 
-ifndef NO_LIBPYTHON
-  # Try different combinations to accommodate systems that only have
-  # python[2][-config] in weird combinations but always preferring
-  # python2 and python2-config as per pep-0394. If we catch a
-  # python[-config] in version 3, the version check will kill it.
-  PYTHON2 := $(if $(call get-executable,python2),python2,python)
-  override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2))
-  PYTHON2_CONFIG := \
-    $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config)
-  override PYTHON_CONFIG := \
-    $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
+# Try different combinations to accommodate systems that only have
+# python[2][-config] in weird combinations but always preferring
+# python2 and python2-config as per pep-0394. If we catch a
+# python[-config] in version 3, the version check will kill it.
+PYTHON2 := $(if $(call get-executable,python2),python2,python)
+override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2))
+PYTHON2_CONFIG := \
+  $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config)
+override PYTHON_CONFIG := \
+  $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
 
-  PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
+PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
 
-  PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
-  PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
+PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
+PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
 
-  FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
-  FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
-  FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
-  FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
-endif
+FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
+FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
+FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
+FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
 
 CFLAGS += -fno-omit-frame-pointer
 CFLAGS += -ggdb3
@@ -335,6 +328,13 @@ ifndef NO_LIBELF
   endif # NO_LIBBPF
 endif # NO_LIBELF
 
+ifdef PERF_HAVE_JITDUMP
+  ifndef NO_DWARF
+    $(call detected,CONFIG_JITDUMP)
+    CFLAGS += -DHAVE_JITDUMP
+  endif
+endif
+
 ifeq ($(ARCH),powerpc)
   ifndef NO_DWARF
     CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
@@ -411,6 +411,17 @@ ifndef NO_LIBAUDIT
   endif
 endif
 
+ifndef NO_LIBCRYPTO
+  ifneq ($(feature-libcrypto), 1)
+    msg := $(warning No libcrypto.h found, disables jitted code injection, please install libssl-devel or libssl-dev);
+    NO_LIBCRYPTO := 1
+  else
+    CFLAGS += -DHAVE_LIBCRYPTO_SUPPORT
+    EXTLIBS += -lcrypto
+    $(call detected,CONFIG_CRYPTO)
+  endif
+endif
+
 ifdef NO_NEWT
   NO_SLANG=1
 endif
diff --git a/tools/perf/jvmti/Makefile b/tools/perf/jvmti/Makefile
new file mode 100644 (file)
index 0000000..5ce61a1
--- /dev/null
@@ -0,0 +1,89 @@
+ARCH=$(shell uname -m)
+
+ifeq ($(ARCH), x86_64)
+JARCH=amd64
+endif
+ifeq ($(ARCH), armv7l)
+JARCH=armhf
+endif
+ifeq ($(ARCH), armv6l)
+JARCH=armhf
+endif
+ifeq ($(ARCH), aarch64)
+JARCH=aarch64
+endif
+ifeq ($(ARCH), ppc64)
+JARCH=powerpc
+endif
+ifeq ($(ARCH), ppc64le)
+JARCH=powerpc
+endif
+
+DESTDIR=/usr/local
+
+VERSION=1
+REVISION=0
+AGE=0
+
+LN=ln -sf
+RM=rm
+
+SLIBJVMTI=libjvmti.so.$(VERSION).$(REVISION).$(AGE)
+VLIBJVMTI=libjvmti.so.$(VERSION)
+SLDFLAGS=-shared -Wl,-soname -Wl,$(VLIBJVMTI)
+SOLIBEXT=so
+
+# The following works at least on fedora 23, you may need the next
+# line for other distros.
+ifneq (,$(wildcard /usr/sbin/update-java-alternatives))
+JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | cut -d ' ' -f 3)
+else
+  ifneq (,$(wildcard /usr/sbin/alternatives))
+    JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g')
+  endif
+endif
+ifndef JDIR
+$(error Could not find alternatives command, you need to set JDIR= to point to the root of your Java directory)
+else
+  ifeq (,$(wildcard $(JDIR)/include/jvmti.h))
+  $(error the openjdk development package appears to me missing, install and try again)
+  endif
+endif
+$(info Using Java from $(JDIR))
+# -lrt required in 32-bit mode for clock_gettime()
+LIBS=-lelf -lrt
+INCDIR=-I $(JDIR)/include -I $(JDIR)/include/linux
+
+TARGETS=$(SLIBJVMTI)
+
+SRCS=libjvmti.c jvmti_agent.c
+OBJS=$(SRCS:.c=.o)
+SOBJS=$(OBJS:.o=.lo)
+OPT=-O2 -g -Werror -Wall
+
+CFLAGS=$(INCDIR) $(OPT)
+
+all: $(TARGETS)
+
+.c.o:
+       $(CC) $(CFLAGS) -c $*.c
+.c.lo:
+       $(CC) -fPIC -DPIC $(CFLAGS) -c $*.c -o $*.lo
+
+$(OBJS) $(SOBJS): Makefile jvmti_agent.h ../util/jitdump.h
+
+$(SLIBJVMTI):  $(SOBJS)
+       $(CC) $(CFLAGS) $(SLDFLAGS)  -o $@ $(SOBJS) $(LIBS)
+       $(LN) $@ libjvmti.$(SOLIBEXT)
+
+clean:
+       $(RM) -f *.o *.so.* *.so *.lo
+
+install:
+       -mkdir -p $(DESTDIR)/lib
+       install -m 755 $(SLIBJVMTI) $(DESTDIR)/lib/
+       (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) $(VLIBJVMTI))
+       (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) libjvmti.$(SOLIBEXT))
+       ldconfig
+
+.SUFFIXES: .c .S .o .lo
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
new file mode 100644 (file)
index 0000000..6461e02
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ * jvmti_agent.c: JVMTI agent interface
+ *
+ * Adapted from the Oprofile code in opagent.c:
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Copyright 2007 OProfile authors
+ * Jens Wilke
+ * Daniel Hansel
+ * Copyright IBM Corporation 2007
+ */
+#include <sys/types.h>
+#include <sys/stat.h> /* for mkdir() */
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/mman.h>
+#include <syscall.h> /* for gettid() */
+#include <err.h>
+
+#include "jvmti_agent.h"
+#include "../util/jitdump.h"
+
+#define JIT_LANG "java"
+
+static char jit_path[PATH_MAX];
+static void *marker_addr;
+
+/*
+ * padding buffer
+ */
+static const char pad_bytes[7];
+
+static inline pid_t gettid(void)
+{
+       return (pid_t)syscall(__NR_gettid);
+}
+
+static int get_e_machine(struct jitheader *hdr)
+{
+       ssize_t sret;
+       char id[16];
+       int fd, ret = -1;
+       int m = -1;
+       struct {
+               uint16_t e_type;
+               uint16_t e_machine;
+       } info;
+
+       fd = open("/proc/self/exe", O_RDONLY);
+       if (fd == -1)
+               return -1;
+
+       sret = read(fd, id, sizeof(id));
+       if (sret != sizeof(id))
+               goto error;
+
+       /* check ELF signature */
+       if (id[0] != 0x7f || id[1] != 'E' || id[2] != 'L' || id[3] != 'F')
+               goto error;
+
+       sret = read(fd, &info, sizeof(info));
+       if (sret != sizeof(info))
+               goto error;
+
+       m = info.e_machine;
+       if (m < 0)
+               m = 0; /* ELF EM_NONE */
+
+       hdr->elf_mach = m;
+       ret = 0;
+error:
+       close(fd);
+       return ret;
+}
+
+#define NSEC_PER_SEC   1000000000
+static int perf_clk_id = CLOCK_MONOTONIC;
+
+static inline uint64_t
+timespec_to_ns(const struct timespec *ts)
+{
+        return ((uint64_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
+}
+
+static inline uint64_t
+perf_get_timestamp(void)
+{
+       struct timespec ts;
+       int ret;
+
+       ret = clock_gettime(perf_clk_id, &ts);
+       if (ret)
+               return 0;
+
+       return timespec_to_ns(&ts);
+}
+
+static int
+debug_cache_init(void)
+{
+       char str[32];
+       char *base, *p;
+       struct tm tm;
+       time_t t;
+       int ret;
+
+       time(&t);
+       localtime_r(&t, &tm);
+
+       base = getenv("JITDUMPDIR");
+       if (!base)
+               base = getenv("HOME");
+       if (!base)
+               base = ".";
+
+       strftime(str, sizeof(str), JIT_LANG"-jit-%Y%m%d", &tm);
+
+       snprintf(jit_path, PATH_MAX - 1, "%s/.debug/", base);
+
+       ret = mkdir(jit_path, 0755);
+       if (ret == -1) {
+               if (errno != EEXIST) {
+                       warn("jvmti: cannot create jit cache dir %s", jit_path);
+                       return -1;
+               }
+       }
+
+       snprintf(jit_path, PATH_MAX - 1, "%s/.debug/jit", base);
+       ret = mkdir(jit_path, 0755);
+       if (ret == -1) {
+               if (errno != EEXIST) {
+                       warn("cannot create jit cache dir %s", jit_path);
+                       return -1;
+               }
+       }
+
+       snprintf(jit_path, PATH_MAX - 1, "%s/.debug/jit/%s.XXXXXXXX", base, str);
+
+       p = mkdtemp(jit_path);
+       if (p != jit_path) {
+               warn("cannot create jit cache dir %s", jit_path);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
+perf_open_marker_file(int fd)
+{
+       long pgsz;
+
+       pgsz = sysconf(_SC_PAGESIZE);
+       if (pgsz == -1)
+               return -1;
+
+       /*
+        * we mmap the jitdump to create an MMAP RECORD in perf.data file.
+        * The mmap is captured either live (perf record running when we mmap)
+        * or  in deferred mode, via /proc/PID/maps
+        * the MMAP record is used as a marker of a jitdump file for more meta
+        * data info about the jitted code. Perf report/annotate detect this
+        * special filename and process the jitdump file.
+        *
+        * mapping must be PROT_EXEC to ensure it is captured by perf record
+        * even when not using -d option
+        */
+       marker_addr = mmap(NULL, pgsz, PROT_READ|PROT_EXEC, MAP_PRIVATE, fd, 0);
+       return (marker_addr == MAP_FAILED) ? -1 : 0;
+}
+
+static void
+perf_close_marker_file(void)
+{
+       long pgsz;
+
+       if (!marker_addr)
+               return;
+
+       pgsz = sysconf(_SC_PAGESIZE);
+       if (pgsz == -1)
+               return;
+
+       munmap(marker_addr, pgsz);
+}
+
+void *jvmti_open(void)
+{
+       int pad_cnt;
+       char dump_path[PATH_MAX];
+       struct jitheader header;
+       int fd;
+       FILE *fp;
+
+       /*
+        * check if clockid is supported
+        */
+       if (!perf_get_timestamp())
+               warnx("jvmti: kernel does not support %d clock id", perf_clk_id);
+
+       memset(&header, 0, sizeof(header));
+
+       debug_cache_init();
+
+       /*
+        * jitdump file name
+        */
+       snprintf(dump_path, PATH_MAX, "%s/jit-%i.dump", jit_path, getpid());
+
+       fd = open(dump_path, O_CREAT|O_TRUNC|O_RDWR, 0666);
+       if (fd == -1)
+               return NULL;
+
+       /*
+        * create perf.data maker for the jitdump file
+        */
+       if (perf_open_marker_file(fd)) {
+               warnx("jvmti: failed to create marker file");
+               return NULL;
+       }
+
+       fp = fdopen(fd, "w+");
+       if (!fp) {
+               warn("jvmti: cannot create %s", dump_path);
+               close(fd);
+               goto error;
+       }
+
+       warnx("jvmti: jitdump in %s", dump_path);
+
+       if (get_e_machine(&header)) {
+               warn("get_e_machine failed\n");
+               goto error;
+       }
+
+       header.magic      = JITHEADER_MAGIC;
+       header.version    = JITHEADER_VERSION;
+       header.total_size = sizeof(header);
+       header.pid        = getpid();
+
+       /* calculate amount of padding '\0' */
+       pad_cnt = PADDING_8ALIGNED(header.total_size);
+       header.total_size += pad_cnt;
+
+       header.timestamp = perf_get_timestamp();
+
+       if (!fwrite(&header, sizeof(header), 1, fp)) {
+               warn("jvmti: cannot write dumpfile header");
+               goto error;
+       }
+
+       /* write padding '\0' if necessary */
+       if (pad_cnt && !fwrite(pad_bytes, pad_cnt, 1, fp)) {
+               warn("jvmti: cannot write dumpfile header padding");
+               goto error;
+       }
+
+       return fp;
+error:
+       fclose(fp);
+       return NULL;
+}
+
+int
+jvmti_close(void *agent)
+{
+       struct jr_code_close rec;
+       FILE *fp = agent;
+
+       if (!fp) {
+               warnx("jvmti: incalid fd in close_agent");
+               return -1;
+       }
+
+       rec.p.id = JIT_CODE_CLOSE;
+       rec.p.total_size = sizeof(rec);
+
+       rec.p.timestamp = perf_get_timestamp();
+
+       if (!fwrite(&rec, sizeof(rec), 1, fp))
+               return -1;
+
+       fclose(fp);
+
+       fp = NULL;
+
+       perf_close_marker_file();
+
+       return 0;
+}
+
+int
+jvmti_write_code(void *agent, char const *sym,
+       uint64_t vma, void const *code, unsigned int const size)
+{
+       static int code_generation = 1;
+       struct jr_code_load rec;
+       size_t sym_len;
+       size_t padding_count;
+       FILE *fp = agent;
+       int ret = -1;
+
+       /* don't care about 0 length function, no samples */
+       if (size == 0)
+               return 0;
+
+       if (!fp) {
+               warnx("jvmti: invalid fd in write_native_code");
+               return -1;
+       }
+
+       sym_len = strlen(sym) + 1;
+
+       rec.p.id           = JIT_CODE_LOAD;
+       rec.p.total_size   = sizeof(rec) + sym_len;
+       padding_count      = PADDING_8ALIGNED(rec.p.total_size);
+       rec.p. total_size += padding_count;
+       rec.p.timestamp    = perf_get_timestamp();
+
+       rec.code_size  = size;
+       rec.vma        = vma;
+       rec.code_addr  = vma;
+       rec.pid        = getpid();
+       rec.tid        = gettid();
+
+       if (code)
+               rec.p.total_size += size;
+
+       /*
+        * If JVM is multi-threaded, nultiple concurrent calls to agent
+        * may be possible, so protect file writes
+        */
+       flockfile(fp);
+
+       /*
+        * get code index inside lock to avoid race condition
+        */
+       rec.code_index = code_generation++;
+
+       ret = fwrite_unlocked(&rec, sizeof(rec), 1, fp);
+       fwrite_unlocked(sym, sym_len, 1, fp);
+
+       if (padding_count)
+               fwrite_unlocked(pad_bytes, padding_count, 1, fp);
+
+       if (code)
+               fwrite_unlocked(code, size, 1, fp);
+
+       funlockfile(fp);
+
+       ret = 0;
+
+       return ret;
+}
+
+int
+jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
+                      jvmti_line_info_t *li, int nr_lines)
+{
+       struct jr_code_debug_info rec;
+       size_t sret, len, size, flen;
+       size_t padding_count;
+       uint64_t addr;
+       const char *fn = file;
+       FILE *fp = agent;
+       int i;
+
+       /*
+        * no entry to write
+        */
+       if (!nr_lines)
+               return 0;
+
+       if (!fp) {
+               warnx("jvmti: invalid fd in write_debug_info");
+               return -1;
+       }
+
+       flen = strlen(file) + 1;
+
+       rec.p.id        = JIT_CODE_DEBUG_INFO;
+       size            = sizeof(rec);
+       rec.p.timestamp = perf_get_timestamp();
+       rec.code_addr   = (uint64_t)(uintptr_t)code;
+       rec.nr_entry    = nr_lines;
+
+       /*
+        * on disk source line info layout:
+        * uint64_t : addr
+        * int      : line number
+        * int      : column discriminator
+        * file[]   : source file name
+        * padding  : pad to multiple of 8 bytes
+        */
+       size += nr_lines * sizeof(struct debug_entry);
+       size += flen * nr_lines;
+       /*
+        * pad to 8 bytes
+        */
+       padding_count = PADDING_8ALIGNED(size);
+
+       rec.p.total_size = size + padding_count;
+
+       /*
+        * If JVM is multi-threaded, nultiple concurrent calls to agent
+        * may be possible, so protect file writes
+        */
+       flockfile(fp);
+
+       sret = fwrite_unlocked(&rec, sizeof(rec), 1, fp);
+       if (sret != 1)
+               goto error;
+
+       for (i = 0; i < nr_lines; i++) {
+
+               addr = (uint64_t)li[i].pc;
+               len  = sizeof(addr);
+               sret = fwrite_unlocked(&addr, len, 1, fp);
+               if (sret != 1)
+                       goto error;
+
+               len  = sizeof(li[0].line_number);
+               sret = fwrite_unlocked(&li[i].line_number, len, 1, fp);
+               if (sret != 1)
+                       goto error;
+
+               len  = sizeof(li[0].discrim);
+               sret = fwrite_unlocked(&li[i].discrim, len, 1, fp);
+               if (sret != 1)
+                       goto error;
+
+               sret = fwrite_unlocked(fn, flen, 1, fp);
+               if (sret != 1)
+                       goto error;
+       }
+       if (padding_count)
+               sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp);
+               if (sret != 1)
+                       goto error;
+
+       funlockfile(fp);
+       return 0;
+error:
+       funlockfile(fp);
+       return -1;
+}
diff --git a/tools/perf/jvmti/jvmti_agent.h b/tools/perf/jvmti/jvmti_agent.h
new file mode 100644 (file)
index 0000000..bedf5d0
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __JVMTI_AGENT_H__
+#define __JVMTI_AGENT_H__
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <jvmti.h>
+
+#define __unused __attribute__((unused))
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct {
+       unsigned long   pc;
+       int             line_number;
+       int             discrim; /* discriminator -- 0 for now */
+} jvmti_line_info_t;
+
+void *jvmti_open(void);
+int   jvmti_close(void *agent);
+int   jvmti_write_code(void *agent, char const *symbol_name,
+                      uint64_t vma, void const *code,
+                      const unsigned int code_size);
+
+int   jvmti_write_debug_info(void *agent,
+                            uint64_t code,
+                            const char *file,
+                            jvmti_line_info_t *li,
+                            int nr_lines);
+
+#if defined(__cplusplus)
+}
+
+#endif
+#endif /* __JVMTI_H__ */
diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c
new file mode 100644 (file)
index 0000000..ac12e4b
--- /dev/null
@@ -0,0 +1,304 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <err.h>
+#include <jvmti.h>
+#include <jvmticmlr.h>
+#include <limits.h>
+
+#include "jvmti_agent.h"
+
+static int has_line_numbers;
+void *jvmti_agent;
+
+static jvmtiError
+do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci,
+                   jvmti_line_info_t *tab, jint *nr)
+{
+       jint i, lines = 0;
+       jint nr_lines = 0;
+       jvmtiLineNumberEntry *loc_tab = NULL;
+       jvmtiError ret;
+
+       ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab);
+       if (ret != JVMTI_ERROR_NONE)
+               return ret;
+
+       for (i = 0; i < nr_lines; i++) {
+               if (loc_tab[i].start_location < bci) {
+                       tab[lines].pc = (unsigned long)pc;
+                       tab[lines].line_number = loc_tab[i].line_number;
+                       tab[lines].discrim = 0; /* not yet used */
+                       lines++;
+               } else {
+                       break;
+               }
+       }
+       (*jvmti)->Deallocate(jvmti, (unsigned char *)loc_tab);
+       *nr = lines;
+       return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError
+get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **tab, int *nr_lines)
+{
+       const jvmtiCompiledMethodLoadRecordHeader *hdr;
+       jvmtiCompiledMethodLoadInlineRecord *rec;
+       jvmtiLineNumberEntry *lne = NULL;
+       PCStackInfo *c;
+       jint nr, ret;
+       int nr_total = 0;
+       int i, lines_total = 0;
+
+       if (!(tab && nr_lines))
+               return JVMTI_ERROR_NULL_POINTER;
+
+       /*
+        * Phase 1 -- get the number of lines necessary
+        */
+       for (hdr = compile_info; hdr != NULL; hdr = hdr->next) {
+               if (hdr->kind == JVMTI_CMLR_INLINE_INFO) {
+                       rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr;
+                       for (i = 0; i < rec->numpcs; i++) {
+                               c = rec->pcinfo + i;
+                               nr = 0;
+                               /*
+                                * unfortunately, need a tab to get the number of lines!
+                                */
+                               ret = (*jvmti)->GetLineNumberTable(jvmti, c->methods[0], &nr, &lne);
+                               if (ret == JVMTI_ERROR_NONE) {
+                                       /* free what was allocated for nothing */
+                                       (*jvmti)->Deallocate(jvmti, (unsigned char *)lne);
+                                       nr_total += (int)nr;
+                               }
+                       }
+               }
+       }
+
+       if (nr_total == 0)
+               return JVMTI_ERROR_NOT_FOUND;
+
+       /*
+        * Phase 2 -- allocate big enough line table
+        */
+       *tab = malloc(nr_total * sizeof(**tab));
+       if (!*tab)
+               return JVMTI_ERROR_OUT_OF_MEMORY;
+
+       for (hdr = compile_info; hdr != NULL; hdr = hdr->next) {
+               if (hdr->kind == JVMTI_CMLR_INLINE_INFO) {
+                       rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr;
+                       for (i = 0; i < rec->numpcs; i++) {
+                               c = rec->pcinfo + i;
+                               nr = 0;
+                               ret = do_get_line_numbers(jvmti, c->pc,
+                                                         c->methods[0],
+                                                         c->bcis[0],
+                                                         *tab + lines_total,
+                                                         &nr);
+                               if (ret == JVMTI_ERROR_NONE)
+                                       lines_total += nr;
+                       }
+               }
+       }
+       *nr_lines = lines_total;
+       return JVMTI_ERROR_NONE;
+}
+
+static void JNICALL
+compiled_method_load_cb(jvmtiEnv *jvmti,
+                       jmethodID method,
+                       jint code_size,
+                       void const *code_addr,
+                       jint map_length,
+                       jvmtiAddrLocationMap const *map,
+                       const void *compile_info)
+{
+       jvmti_line_info_t *line_tab = NULL;
+       jclass decl_class;
+       char *class_sign = NULL;
+       char *func_name = NULL;
+       char *func_sign = NULL;
+       char *file_name= NULL;
+       char fn[PATH_MAX];
+       uint64_t addr = (uint64_t)(uintptr_t)code_addr;
+       jvmtiError ret;
+       int nr_lines = 0; /* in line_tab[] */
+       size_t len;
+
+       ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method,
+                                               &decl_class);
+       if (ret != JVMTI_ERROR_NONE) {
+               warnx("jvmti: cannot get declaring class");
+               return;
+       }
+
+       if (has_line_numbers && map && map_length) {
+               ret = get_line_numbers(jvmti, compile_info, &line_tab, &nr_lines);
+               if (ret != JVMTI_ERROR_NONE) {
+                       warnx("jvmti: cannot get line table for method");
+                       nr_lines = 0;
+               }
+       }
+
+       ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name);
+       if (ret != JVMTI_ERROR_NONE) {
+               warnx("jvmti: cannot get source filename ret=%d", ret);
+               goto error;
+       }
+
+       ret = (*jvmti)->GetClassSignature(jvmti, decl_class,
+                                         &class_sign, NULL);
+       if (ret != JVMTI_ERROR_NONE) {
+               warnx("jvmti: getclassignature failed");
+               goto error;
+       }
+
+       ret = (*jvmti)->GetMethodName(jvmti, method, &func_name,
+                                     &func_sign, NULL);
+       if (ret != JVMTI_ERROR_NONE) {
+               warnx("jvmti: failed getmethodname");
+               goto error;
+       }
+
+       /*
+        * Assume path name is class hierarchy, this is a common practice with Java programs
+        */
+       if (*class_sign == 'L') {
+               int j, i = 0;
+               char *p = strrchr(class_sign, '/');
+               if (p) {
+                       /* drop the 'L' prefix and copy up to the final '/' */
+                       for (i = 0; i < (p - class_sign); i++)
+                               fn[i] = class_sign[i+1];
+               }
+               /*
+                * append file name, we use loops and not string ops to avoid modifying
+                * class_sign which is used later for the symbol name
+                */
+               for (j = 0; i < (PATH_MAX - 1) && file_name && j < strlen(file_name); j++, i++)
+                       fn[i] = file_name[j];
+               fn[i] = '\0';
+       } else {
+               /* fallback case */
+               strcpy(fn, file_name);
+       }
+       /*
+        * write source line info record if we have it
+        */
+       if (jvmti_write_debug_info(jvmti_agent, addr, fn, line_tab, nr_lines))
+               warnx("jvmti: write_debug_info() failed");
+
+       len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2;
+       {
+               char str[len];
+               snprintf(str, len, "%s%s%s", class_sign, func_name, func_sign);
+
+               if (jvmti_write_code(jvmti_agent, str, addr, code_addr, code_size))
+                       warnx("jvmti: write_code() failed");
+       }
+error:
+       (*jvmti)->Deallocate(jvmti, (unsigned char *)func_name);
+       (*jvmti)->Deallocate(jvmti, (unsigned char *)func_sign);
+       (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign);
+       (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name);
+       free(line_tab);
+}
+
+static void JNICALL
+code_generated_cb(jvmtiEnv *jvmti,
+                 char const *name,
+                 void const *code_addr,
+                 jint code_size)
+{
+       uint64_t addr = (uint64_t)(unsigned long)code_addr;
+       int ret;
+
+       ret = jvmti_write_code(jvmti_agent, name, addr, code_addr, code_size);
+       if (ret)
+               warnx("jvmti: write_code() failed for code_generated");
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused)
+{
+       jvmtiEventCallbacks cb;
+       jvmtiCapabilities caps1;
+       jvmtiJlocationFormat format;
+       jvmtiEnv *jvmti = NULL;
+       jint ret;
+
+       jvmti_agent = jvmti_open();
+       if (!jvmti_agent) {
+               warnx("jvmti: open_agent failed");
+               return -1;
+       }
+
+       /*
+        * Request a JVMTI interface version 1 environment
+        */
+       ret = (*jvm)->GetEnv(jvm, (void *)&jvmti, JVMTI_VERSION_1);
+       if (ret != JNI_OK) {
+               warnx("jvmti: jvmti version 1 not supported");
+               return -1;
+       }
+
+       /*
+        * acquire method_load capability, we require it
+        * request line numbers (optional)
+        */
+       memset(&caps1, 0, sizeof(caps1));
+       caps1.can_generate_compiled_method_load_events = 1;
+
+       ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
+       if (ret != JVMTI_ERROR_NONE) {
+               warnx("jvmti: acquire compiled_method capability failed");
+               return -1;
+       }
+       ret = (*jvmti)->GetJLocationFormat(jvmti, &format);
+        if (ret == JVMTI_ERROR_NONE && format == JVMTI_JLOCATION_JVMBCI) {
+                memset(&caps1, 0, sizeof(caps1));
+                caps1.can_get_line_numbers = 1;
+                caps1.can_get_source_file_name = 1;
+               ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
+                if (ret == JVMTI_ERROR_NONE)
+                        has_line_numbers = 1;
+        }
+
+       memset(&cb, 0, sizeof(cb));
+
+       cb.CompiledMethodLoad   = compiled_method_load_cb;
+       cb.DynamicCodeGenerated = code_generated_cb;
+
+       ret = (*jvmti)->SetEventCallbacks(jvmti, &cb, sizeof(cb));
+       if (ret != JVMTI_ERROR_NONE) {
+               warnx("jvmti: cannot set event callbacks");
+               return -1;
+       }
+
+       ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
+                       JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
+       if (ret != JVMTI_ERROR_NONE) {
+               warnx("jvmti: setnotification failed for method_load");
+               return -1;
+       }
+
+       ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
+                       JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);
+       if (ret != JVMTI_ERROR_NONE) {
+               warnx("jvmti: setnotification failed on code_generated");
+               return -1;
+       }
+       return 0;
+}
+
+JNIEXPORT void JNICALL
+Agent_OnUnload(JavaVM *jvm __unused)
+{
+       int ret;
+
+       ret = jvmti_close(jvmti_agent);
+       if (ret)
+               errx(1, "Error: op_close_agent()");
+}
index a929618b8eb616f90c9bb8e26bad5416a0fdbc19..aaee0a7827477810c5c0d2d82753545592d7f22f 100644 (file)
@@ -454,11 +454,12 @@ static void handle_internal_command(int argc, const char **argv)
 
 static void execv_dashed_external(const char **argv)
 {
-       struct strbuf cmd = STRBUF_INIT;
+       char *cmd;
        const char *tmp;
        int status;
 
-       strbuf_addf(&cmd, "perf-%s", argv[0]);
+       if (asprintf(&cmd, "perf-%s", argv[0]) < 0)
+               goto do_die;
 
        /*
         * argv[0] must be the perf command, but the argv array
@@ -467,7 +468,7 @@ static void execv_dashed_external(const char **argv)
         * restore it on error.
         */
        tmp = argv[0];
-       argv[0] = cmd.buf;
+       argv[0] = cmd;
 
        /*
         * if we fail because the command is not found, it is
@@ -475,15 +476,16 @@ static void execv_dashed_external(const char **argv)
         */
        status = run_command_v_opt(argv, 0);
        if (status != -ERR_RUN_COMMAND_EXEC) {
-               if (IS_RUN_COMMAND_ERR(status))
+               if (IS_RUN_COMMAND_ERR(status)) {
+do_die:
                        die("unable to run '%s'", argv[0]);
+               }
                exit(-status);
        }
        errno = ENOENT; /* as if we called execvp */
 
        argv[0] = tmp;
-
-       strbuf_release(&cmd);
+       zfree(&cmd);
 }
 
 static int run_argv(int *argcp, const char ***argv)
@@ -546,6 +548,8 @@ int main(int argc, const char **argv)
 
        srandom(time(NULL));
 
+       perf_config(perf_default_config, NULL);
+
        /* get debugfs/tracefs mount point from /proc/mounts */
        tracing_path_mount();
 
@@ -613,6 +617,8 @@ int main(int argc, const char **argv)
         */
        pthread__block_sigwinch();
 
+       perf_debug_setup();
+
        while (1) {
                static int done_help;
                int was_alias = run_argv(&argc, &argv);
index 90129accffbe824e37d9831ba3b323011295f78a..5381a01c0610c0e61f079140ed5cdc2df3f87b0d 100644 (file)
@@ -58,6 +58,8 @@ struct record_opts {
        bool         full_auxtrace;
        bool         auxtrace_snapshot_mode;
        bool         record_switch_events;
+       bool         all_kernel;
+       bool         all_user;
        unsigned int freq;
        unsigned int mmap_pages;
        unsigned int auxtrace_mmap_pages;
index 15c8400240fd9029ae34fca077304337d9c75ca6..1d95009592eb3a8a8d053e1340a3e42dd412a68c 100644 (file)
@@ -71,7 +71,10 @@ try:
 except:
        if not audit_package_warned:
                audit_package_warned = True
-               print "Install the audit-libs-python package to get syscall names"
+               print "Install the audit-libs-python package to get syscall names.\n" \
+                    "For example:\n  # apt-get install python-audit (Ubuntu)" \
+                    "\n  # yum install audit-libs-python (Fedora)" \
+                    "\n  etc.\n"
 
 def syscall_name(id):
        try:
index bf016c439fbd10a3cada60253c98d60ce441aa98..8cc30e731c739495f3eb61a0da9a76246ad35600 100644 (file)
@@ -1,3 +1,4 @@
 llvm-src-base.c
 llvm-src-kbuild.c
 llvm-src-prologue.c
+llvm-src-relocation.c
index 614899b88b377e07f9615d618ba7045f66051bea..1ba628ed049adbafc27c7b8900ecb838165a2aa7 100644 (file)
@@ -31,7 +31,7 @@ perf-y += sample-parsing.o
 perf-y += parse-no-sample-id-all.o
 perf-y += kmod-path.o
 perf-y += thread-map.o
-perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o
+perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o llvm-src-relocation.o
 perf-y += bpf.o
 perf-y += topology.o
 perf-y += cpumap.o
@@ -59,6 +59,13 @@ $(OUTPUT)tests/llvm-src-prologue.c: tests/bpf-script-test-prologue.c tests/Build
        $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
        $(Q)echo ';' >> $@
 
+$(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/Build
+       $(call rule_mkdir)
+       $(Q)echo '#include <tests/llvm.h>' > $@
+       $(Q)echo 'const char test_llvm__bpf_test_relocation[] =' >> $@
+       $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
+       $(Q)echo ';' >> $@
+
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
 perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 endif
index fb80c9eb6a95b67947b23adaeca69b5e57bac704..e7664fe3bd33739fd92be2579c30102e481e8f03 100644 (file)
 
 static int fd1;
 static int fd2;
+static int fd3;
 static int overflows;
+static int overflows_2;
+
+volatile long the_var;
+
+
+/*
+ * Use ASM to ensure watchpoint and breakpoint can be triggered
+ * at one instruction.
+ */
+#if defined (__x86_64__)
+extern void __test_function(volatile long *ptr);
+asm (
+       ".globl __test_function\n"
+       "__test_function:\n"
+       "incq (%rdi)\n"
+       "ret\n");
+#elif defined (__aarch64__)
+extern void __test_function(volatile long *ptr);
+asm (
+       ".globl __test_function\n"
+       "__test_function:\n"
+       "str x30, [x0]\n"
+       "ret\n");
+
+#else
+static void __test_function(volatile long *ptr)
+{
+       *ptr = 0x1234;
+}
+#endif
 
 __attribute__ ((noinline))
 static int test_function(void)
 {
+       __test_function(&the_var);
+       the_var++;
        return time(NULL);
 }
 
+static void sig_handler_2(int signum __maybe_unused,
+                         siginfo_t *oh __maybe_unused,
+                         void *uc __maybe_unused)
+{
+       overflows_2++;
+       if (overflows_2 > 10) {
+               ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
+               ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
+               ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
+       }
+}
+
 static void sig_handler(int signum __maybe_unused,
                        siginfo_t *oh __maybe_unused,
                        void *uc __maybe_unused)
@@ -54,10 +99,11 @@ static void sig_handler(int signum __maybe_unused,
                 */
                ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
                ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
+               ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
        }
 }
 
-static int bp_event(void *fn, int setup_signal)
+static int __event(bool is_x, void *addr, int sig)
 {
        struct perf_event_attr pe;
        int fd;
@@ -67,8 +113,8 @@ static int bp_event(void *fn, int setup_signal)
        pe.size = sizeof(struct perf_event_attr);
 
        pe.config = 0;
-       pe.bp_type = HW_BREAKPOINT_X;
-       pe.bp_addr = (unsigned long) fn;
+       pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
+       pe.bp_addr = (unsigned long) addr;
        pe.bp_len = sizeof(long);
 
        pe.sample_period = 1;
@@ -86,17 +132,25 @@ static int bp_event(void *fn, int setup_signal)
                return TEST_FAIL;
        }
 
-       if (setup_signal) {
-               fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
-               fcntl(fd, F_SETSIG, SIGIO);
-               fcntl(fd, F_SETOWN, getpid());
-       }
+       fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
+       fcntl(fd, F_SETSIG, sig);
+       fcntl(fd, F_SETOWN, getpid());
 
        ioctl(fd, PERF_EVENT_IOC_RESET, 0);
 
        return fd;
 }
 
+static int bp_event(void *addr, int sig)
+{
+       return __event(true, addr, sig);
+}
+
+static int wp_event(void *addr, int sig)
+{
+       return __event(false, addr, sig);
+}
+
 static long long bp_count(int fd)
 {
        long long count;
@@ -114,7 +168,7 @@ static long long bp_count(int fd)
 int test__bp_signal(int subtest __maybe_unused)
 {
        struct sigaction sa;
-       long long count1, count2;
+       long long count1, count2, count3;
 
        /* setup SIGIO signal handler */
        memset(&sa, 0, sizeof(struct sigaction));
@@ -126,21 +180,52 @@ int test__bp_signal(int subtest __maybe_unused)
                return TEST_FAIL;
        }
 
+       sa.sa_sigaction = (void *) sig_handler_2;
+       if (sigaction(SIGUSR1, &sa, NULL) < 0) {
+               pr_debug("failed setting up signal handler 2\n");
+               return TEST_FAIL;
+       }
+
        /*
         * We create following events:
         *
-        * fd1 - breakpoint event on test_function with SIGIO
+        * fd1 - breakpoint event on __test_function with SIGIO
         *       signal configured. We should get signal
         *       notification each time the breakpoint is hit
         *
-        * fd2 - breakpoint event on sig_handler without SIGIO
+        * fd2 - breakpoint event on sig_handler with SIGUSR1
+        *       configured. We should get SIGUSR1 each time when
+        *       breakpoint is hit
+        *
+        * fd3 - watchpoint event on __test_function with SIGIO
         *       configured.
         *
         * Following processing should happen:
-        *   - execute test_function
-        *   - fd1 event breakpoint hit -> count1 == 1
-        *   - SIGIO is delivered       -> overflows == 1
-        *   - fd2 event breakpoint hit -> count2 == 1
+        *   Exec:               Action:                       Result:
+        *   incq (%rdi)       - fd1 event breakpoint hit   -> count1 == 1
+        *                     - SIGIO is delivered
+        *   sig_handler       - fd2 event breakpoint hit   -> count2 == 1
+        *                     - SIGUSR1 is delivered
+        *   sig_handler_2                                  -> overflows_2 == 1  (nested signal)
+        *   sys_rt_sigreturn  - return from sig_handler_2
+        *   overflows++                                    -> overflows = 1
+        *   sys_rt_sigreturn  - return from sig_handler
+        *   incq (%rdi)       - fd3 event watchpoint hit   -> count3 == 1       (wp and bp in one insn)
+        *                     - SIGIO is delivered
+        *   sig_handler       - fd2 event breakpoint hit   -> count2 == 2
+        *                     - SIGUSR1 is delivered
+        *   sig_handler_2                                  -> overflows_2 == 2  (nested signal)
+        *   sys_rt_sigreturn  - return from sig_handler_2
+        *   overflows++                                    -> overflows = 2
+        *   sys_rt_sigreturn  - return from sig_handler
+        *   the_var++         - fd3 event watchpoint hit   -> count3 == 2       (standalone watchpoint)
+        *                     - SIGIO is delivered
+        *   sig_handler       - fd2 event breakpoint hit   -> count2 == 3
+        *                     - SIGUSR1 is delivered
+        *   sig_handler_2                                  -> overflows_2 == 3  (nested signal)
+        *   sys_rt_sigreturn  - return from sig_handler_2
+        *   overflows++                                    -> overflows == 3
+        *   sys_rt_sigreturn  - return from sig_handler
         *
         * The test case check following error conditions:
         * - we get stuck in signal handler because of debug
@@ -152,11 +237,13 @@ int test__bp_signal(int subtest __maybe_unused)
         *
         */
 
-       fd1 = bp_event(test_function, 1);
-       fd2 = bp_event(sig_handler, 0);
+       fd1 = bp_event(__test_function, SIGIO);
+       fd2 = bp_event(sig_handler, SIGUSR1);
+       fd3 = wp_event((void *)&the_var, SIGIO);
 
        ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
        ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
+       ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
 
        /*
         * Kick off the test by trigering 'fd1'
@@ -166,15 +253,18 @@ int test__bp_signal(int subtest __maybe_unused)
 
        ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
        ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
+       ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
 
        count1 = bp_count(fd1);
        count2 = bp_count(fd2);
+       count3 = bp_count(fd3);
 
        close(fd1);
        close(fd2);
+       close(fd3);
 
-       pr_debug("count1 %lld, count2 %lld, overflow %d\n",
-                count1, count2, overflows);
+       pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n",
+                count1, count2, count3, overflows, overflows_2);
 
        if (count1 != 1) {
                if (count1 == 11)
@@ -183,12 +273,18 @@ int test__bp_signal(int subtest __maybe_unused)
                        pr_debug("failed: wrong count for bp1%lld\n", count1);
        }
 
-       if (overflows != 1)
+       if (overflows != 3)
                pr_debug("failed: wrong overflow hit\n");
 
-       if (count2 != 1)
+       if (overflows_2 != 3)
+               pr_debug("failed: wrong overflow_2 hit\n");
+
+       if (count2 != 3)
                pr_debug("failed: wrong count for bp2\n");
 
-       return count1 == 1 && overflows == 1 && count2 == 1 ?
+       if (count3 != 2)
+               pr_debug("failed: wrong count for bp3\n");
+
+       return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
                TEST_OK : TEST_FAIL;
 }
diff --git a/tools/perf/tests/bpf-script-test-relocation.c b/tools/perf/tests/bpf-script-test-relocation.c
new file mode 100644 (file)
index 0000000..93af774
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * bpf-script-test-relocation.c
+ * Test BPF loader checking relocation
+ */
+#ifndef LINUX_VERSION_CODE
+# error Need LINUX_VERSION_CODE
+# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
+#endif
+#define BPF_ANY 0
+#define BPF_MAP_TYPE_ARRAY 2
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+       (void *) BPF_FUNC_map_lookup_elem;
+static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
+       (void *) BPF_FUNC_map_update_elem;
+
+struct bpf_map_def {
+       unsigned int type;
+       unsigned int key_size;
+       unsigned int value_size;
+       unsigned int max_entries;
+};
+
+#define SEC(NAME) __attribute__((section(NAME), used))
+struct bpf_map_def SEC("maps") my_table = {
+       .type = BPF_MAP_TYPE_ARRAY,
+       .key_size = sizeof(int),
+       .value_size = sizeof(int),
+       .max_entries = 1,
+};
+
+int this_is_a_global_val;
+
+SEC("func=sys_write")
+int bpf_func__sys_write(void *ctx)
+{
+       int key = 0;
+       int value = 0;
+
+       /*
+        * Incorrect relocation. Should not allow this program be
+        * loaded into kernel.
+        */
+       bpf_map_update_elem(&this_is_a_global_val, &key, &value, 0);
+       return 0;
+}
+char _license[] SEC("license") = "GPL";
+int _version SEC("version") = LINUX_VERSION_CODE;
index 33689a0cf821e5b9608e54b981e3280ee580890c..199501c71e272491850065910aae5003603ab10e 100644 (file)
@@ -1,7 +1,11 @@
 #include <stdio.h>
 #include <sys/epoll.h>
+#include <util/util.h>
 #include <util/bpf-loader.h>
 #include <util/evlist.h>
+#include <linux/bpf.h>
+#include <linux/filter.h>
+#include <bpf/bpf.h>
 #include "tests.h"
 #include "llvm.h"
 #include "debug.h"
@@ -71,6 +75,15 @@ static struct {
                (NR_ITERS + 1) / 4,
        },
 #endif
+       {
+               LLVM_TESTCASE_BPF_RELOCATION,
+               "Test BPF relocation checker",
+               "[bpf_relocation_test]",
+               "fix 'perf test LLVM' first",
+               "libbpf error when dealing with relocation",
+               NULL,
+               0,
+       },
 };
 
 static int do_test(struct bpf_object *obj, int (*func)(void),
@@ -99,7 +112,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
        parse_evlist.error = &parse_error;
        INIT_LIST_HEAD(&parse_evlist.list);
 
-       err = parse_events_load_bpf_obj(&parse_evlist, &parse_evlist.list, obj);
+       err = parse_events_load_bpf_obj(&parse_evlist, &parse_evlist.list, obj, NULL);
        if (err || list_empty(&parse_evlist.list)) {
                pr_debug("Failed to add events selected by BPF\n");
                return TEST_FAIL;
@@ -190,7 +203,7 @@ static int __test__bpf(int idx)
 
        ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
                                       bpf_testcase_table[idx].prog_id,
-                                      true);
+                                      true, NULL);
        if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
                pr_debug("Unable to get BPF object, %s\n",
                         bpf_testcase_table[idx].msg_compile_fail);
@@ -202,14 +215,21 @@ static int __test__bpf(int idx)
 
        obj = prepare_bpf(obj_buf, obj_buf_sz,
                          bpf_testcase_table[idx].name);
-       if (!obj) {
+       if ((!!bpf_testcase_table[idx].target_func) != (!!obj)) {
+               if (!obj)
+                       pr_debug("Fail to load BPF object: %s\n",
+                                bpf_testcase_table[idx].msg_load_fail);
+               else
+                       pr_debug("Success unexpectedly: %s\n",
+                                bpf_testcase_table[idx].msg_load_fail);
                ret = TEST_FAIL;
                goto out;
        }
 
-       ret = do_test(obj,
-                     bpf_testcase_table[idx].target_func,
-                     bpf_testcase_table[idx].expect_result);
+       if (obj)
+               ret = do_test(obj,
+                             bpf_testcase_table[idx].target_func,
+                             bpf_testcase_table[idx].expect_result);
 out:
        bpf__clear();
        return ret;
@@ -227,6 +247,36 @@ const char *test__bpf_subtest_get_desc(int i)
        return bpf_testcase_table[i].desc;
 }
 
+static int check_env(void)
+{
+       int err;
+       unsigned int kver_int;
+       char license[] = "GPL";
+
+       struct bpf_insn insns[] = {
+               BPF_MOV64_IMM(BPF_REG_0, 1),
+               BPF_EXIT_INSN(),
+       };
+
+       err = fetch_kernel_version(&kver_int, NULL, 0);
+       if (err) {
+               pr_debug("Unable to get kernel version\n");
+               return err;
+       }
+
+       err = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
+                              sizeof(insns) / sizeof(insns[0]),
+                              license, kver_int, NULL, 0);
+       if (err < 0) {
+               pr_err("Missing basic BPF support, skip this test: %s\n",
+                      strerror(errno));
+               return err;
+       }
+       close(err);
+
+       return 0;
+}
+
 int test__bpf(int i)
 {
        int err;
@@ -239,6 +289,9 @@ int test__bpf(int i)
                return TEST_SKIP;
        }
 
+       if (check_env())
+               return TEST_SKIP;
+
        err = __test__bpf(i);
        return err;
 }
index 313a48c6b2bc8e111e113e79c4a72fdc2d720ac5..afc9ad0a0515c5db77745d0d0c6964d950fa3bfc 100644 (file)
@@ -439,7 +439,7 @@ static int do_test_code_reading(bool try_kcore)
                .mmap_pages          = UINT_MAX,
                .user_freq           = UINT_MAX,
                .user_interval       = ULLONG_MAX,
-               .freq                = 4000,
+               .freq                = 500,
                .target              = {
                        .uses_mmap   = true,
                },
@@ -559,7 +559,13 @@ static int do_test_code_reading(bool try_kcore)
                                evlist = NULL;
                                continue;
                        }
-                       pr_debug("perf_evlist__open failed\n");
+
+                       if (verbose) {
+                               char errbuf[512];
+                               perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
+                               pr_debug("perf_evlist__open() failed!\n%s\n", errbuf);
+                       }
+
                        goto out_put;
                }
                break;
index 5e6a86e50fb97aae648c16ce627157e8377ebb02..ecf136c385d5ff2f21111e813a9ce1e30c03365a 100644 (file)
@@ -191,7 +191,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec
         * function since TEST_ASSERT_VAL() returns in case of failure.
         */
        hists__collapse_resort(hists, NULL);
-       hists__output_resort(hists, NULL);
+       perf_evsel__output_resort(hists_to_evsel(hists), NULL);
 
        if (verbose > 2) {
                pr_info("use callchain: %d, cumulate callchain: %d\n",
index 351a42463444a3df9f80daea3848499b8d39659a..34b945a55d4d2864cc561f36275191f57f84210a 100644 (file)
@@ -145,7 +145,7 @@ int test__hists_filter(int subtest __maybe_unused)
                struct hists *hists = evsel__hists(evsel);
 
                hists__collapse_resort(hists, NULL);
-               hists__output_resort(hists, NULL);
+               perf_evsel__output_resort(evsel, NULL);
 
                if (verbose > 2) {
                        pr_info("Normal histogram\n");
index b231265148d89a28e39387d423711c643351eb70..23cce67c7e48902b86c00cc6e56df22ef16386e4 100644 (file)
@@ -156,7 +156,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
                goto out;
 
        hists__collapse_resort(hists, NULL);
-       hists__output_resort(hists, NULL);
+       perf_evsel__output_resort(evsel, NULL);
 
        if (verbose > 2) {
                pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
@@ -256,7 +256,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
                goto out;
 
        hists__collapse_resort(hists, NULL);
-       hists__output_resort(hists, NULL);
+       perf_evsel__output_resort(evsel, NULL);
 
        if (verbose > 2) {
                pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
@@ -310,7 +310,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
                goto out;
 
        hists__collapse_resort(hists, NULL);
-       hists__output_resort(hists, NULL);
+       perf_evsel__output_resort(evsel, NULL);
 
        if (verbose > 2) {
                pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
@@ -388,7 +388,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
                goto out;
 
        hists__collapse_resort(hists, NULL);
-       hists__output_resort(hists, NULL);
+       perf_evsel__output_resort(evsel, NULL);
 
        if (verbose > 2) {
                pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
@@ -491,7 +491,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)
                goto out;
 
        hists__collapse_resort(hists, NULL);
-       hists__output_resort(hists, NULL);
+       perf_evsel__output_resort(evsel, NULL);
 
        if (verbose > 2) {
                pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
index 06f45c1d42561df030e35d55078d70d910e79998..cff564fb4b66761f7f7fdcd5ee10727ad3b08726 100644 (file)
@@ -6,12 +6,6 @@
 #include "tests.h"
 #include "debug.h"
 
-static int perf_config_cb(const char *var, const char *val,
-                         void *arg __maybe_unused)
-{
-       return perf_default_config(var, val, arg);
-}
-
 #ifdef HAVE_LIBBPF_SUPPORT
 static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
 {
@@ -35,6 +29,7 @@ static int test__bpf_parsing(void *obj_buf __maybe_unused,
 static struct {
        const char *source;
        const char *desc;
+       bool should_load_fail;
 } bpf_source_table[__LLVM_TESTCASE_MAX] = {
        [LLVM_TESTCASE_BASE] = {
                .source = test_llvm__bpf_base_prog,
@@ -48,14 +43,19 @@ static struct {
                .source = test_llvm__bpf_test_prologue_prog,
                .desc = "Compile source for BPF prologue generation test",
        },
+       [LLVM_TESTCASE_BPF_RELOCATION] = {
+               .source = test_llvm__bpf_test_relocation,
+               .desc = "Compile source for BPF relocation test",
+               .should_load_fail = true,
+       },
 };
 
-
 int
 test_llvm__fetch_bpf_obj(void **p_obj_buf,
                         size_t *p_obj_buf_sz,
                         enum test_llvm__testcase idx,
-                        bool force)
+                        bool force,
+                        bool *should_load_fail)
 {
        const char *source;
        const char *desc;
@@ -68,8 +68,8 @@ test_llvm__fetch_bpf_obj(void **p_obj_buf,
 
        source = bpf_source_table[idx].source;
        desc = bpf_source_table[idx].desc;
-
-       perf_config(perf_config_cb, NULL);
+       if (should_load_fail)
+               *should_load_fail = bpf_source_table[idx].should_load_fail;
 
        /*
         * Skip this test if user's .perfconfig doesn't set [llvm] section
@@ -136,14 +136,15 @@ int test__llvm(int subtest)
        int ret;
        void *obj_buf = NULL;
        size_t obj_buf_sz = 0;
+       bool should_load_fail = false;
 
        if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
                return TEST_FAIL;
 
        ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
-                                      subtest, false);
+                                      subtest, false, &should_load_fail);
 
-       if (ret == TEST_OK) {
+       if (ret == TEST_OK && !should_load_fail) {
                ret = test__bpf_parsing(obj_buf, obj_buf_sz);
                if (ret != TEST_OK) {
                        pr_debug("Failed to parse test case '%s'\n",
index 5150b4d6ef50afe357f5f86300f4d39d28bec658..0eaa604be99defec6dcf3b09ee9a75eb348096fb 100644 (file)
@@ -7,14 +7,17 @@
 extern const char test_llvm__bpf_base_prog[];
 extern const char test_llvm__bpf_test_kbuild_prog[];
 extern const char test_llvm__bpf_test_prologue_prog[];
+extern const char test_llvm__bpf_test_relocation[];
 
 enum test_llvm__testcase {
        LLVM_TESTCASE_BASE,
        LLVM_TESTCASE_KBUILD,
        LLVM_TESTCASE_BPF_PROLOGUE,
+       LLVM_TESTCASE_BPF_RELOCATION,
        __LLVM_TESTCASE_MAX,
 };
 
 int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
-                            enum test_llvm__testcase index, bool force);
+                            enum test_llvm__testcase index, bool force,
+                            bool *should_load_fail);
 #endif
index f918015512af96d1173891dac2e8f460ff65ca85..cac15d93aea656f96ad449cba1f9529e42afcbec 100644 (file)
@@ -15,6 +15,7 @@ else
 PERF := .
 PERF_O := $(PERF)
 O_OPT :=
+FULL_O := $(shell readlink -f $(PERF_O) || echo $(PERF_O))
 
 ifneq ($(O),)
   FULL_O := $(shell readlink -f $(O) || echo $(O))
@@ -79,6 +80,7 @@ make_no_libaudit    := NO_LIBAUDIT=1
 make_no_libbionic   := NO_LIBBIONIC=1
 make_no_auxtrace    := NO_AUXTRACE=1
 make_no_libbpf     := NO_LIBBPF=1
+make_no_libcrypto   := NO_LIBCRYPTO=1
 make_tags           := tags
 make_cscope         := cscope
 make_help           := help
@@ -102,6 +104,7 @@ make_minimal        := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
 make_minimal        += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
 make_minimal        += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
 make_minimal        += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
+make_minimal        += NO_LIBCRYPTO=1
 
 # $(run) contains all available tests
 run := make_pure
@@ -110,6 +113,9 @@ run := make_pure
 # disable features detection
 ifeq ($(MK),Makefile)
 run += make_clean_all
+MAKE_F := $(MAKE)
+else
+MAKE_F := $(MAKE) -f $(MK)
 endif
 run += make_python_perf_so
 run += make_debug
@@ -260,6 +266,8 @@ run := $(shell shuf -e $(run))
 run_O := $(shell shuf -e $(run_O))
 endif
 
+max_width := $(shell echo $(run_O) | sed 's/ /\n/g' | wc -L)
+
 ifdef DEBUG
 d := $(info run   $(run))
 d := $(info run_O $(run_O))
@@ -267,13 +275,13 @@ endif
 
 MAKEFLAGS := --no-print-directory
 
-clean := @(cd $(PERF); make -s -f $(MK) $(O_OPT) clean >/dev/null)
+clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null)
 
 $(run):
        $(call clean)
        @TMP_DEST=$$(mktemp -d); \
-       cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST $($@)"; \
-       echo "- $@: $$cmd" && echo $$cmd > $@ && \
+       cmd="cd $(PERF) && $(MAKE_F) $($@) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST"; \
+       printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \
        ( eval $$cmd ) >> $@ 2>&1; \
        echo "  test: $(call test,$@)" >> $@ 2>&1; \
        $(call test,$@) && \
@@ -283,8 +291,8 @@ $(run_O):
        $(call clean)
        @TMP_O=$$(mktemp -d); \
        TMP_DEST=$$(mktemp -d); \
-       cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \
-       echo "- $@: $$cmd" && echo $$cmd > $@ && \
+       cmd="cd $(PERF) && $(MAKE_F) $($(patsubst %_O,%,$@)) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST"; \
+       printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \
        ( eval $$cmd ) >> $@ 2>&1 && \
        echo "  test: $(call test_O,$@)" >> $@ 2>&1; \
        $(call test_O,$@) && \
@@ -313,11 +321,43 @@ make_kernelsrc_tools:
        (make -C ../../tools $(PARALLEL_OPT) $(K_O_OPT) perf) > $@ 2>&1 && \
        test -x $(KERNEL_O)/tools/perf/perf && rm -f $@ || (cat $@ ; false)
 
+FEATURES_DUMP_FILE := $(FULL_O)/BUILD_TEST_FEATURE_DUMP
+FEATURES_DUMP_FILE_STATIC := $(FULL_O)/BUILD_TEST_FEATURE_DUMP_STATIC
+
 all: $(run) $(run_O) tarpkg make_kernelsrc make_kernelsrc_tools
        @echo OK
+       @rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC)
 
 out: $(run_O)
        @echo OK
+       @rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC)
+
+ifeq ($(REUSE_FEATURES_DUMP),1)
+$(FEATURES_DUMP_FILE):
+       $(call clean)
+       @cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) feature-dump"; \
+       echo "- $@: $$cmd" && echo $$cmd && \
+       ( eval $$cmd ) > /dev/null 2>&1
+
+$(FEATURES_DUMP_FILE_STATIC):
+       $(call clean)
+       @cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) LDFLAGS='-static' feature-dump"; \
+       echo "- $@: $$cmd" && echo $$cmd && \
+       ( eval $$cmd ) > /dev/null 2>&1
+
+# Add feature dump dependency for run/run_O targets
+$(foreach t,$(run) $(run_O),$(eval \
+       $(t): $(if $(findstring make_static,$(t)),\
+               $(FEATURES_DUMP_FILE_STATIC),\
+               $(FEATURES_DUMP_FILE))))
+
+# Append 'FEATURES_DUMP=' option to all test cases. For example:
+# make_no_libbpf: NO_LIBBPF=1  --> NO_LIBBPF=1 FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP
+# make_static: LDFLAGS=-static --> LDFLAGS=-static FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP_STATIC
+$(foreach t,$(run),$(if $(findstring make_static,$(t)),\
+                       $(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE_STATIC)),\
+                       $(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE))))
+endif
 
 .PHONY: all $(run) $(run_O) tarpkg clean make_kernelsrc make_kernelsrc_tools
 endif # ifndef MK
index abe8849d1d7030bda2ae65f770424e3c9ad84330..7865f68dc0d82bea12c960c61792e9fd28857305 100644 (file)
@@ -1271,6 +1271,38 @@ static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist)
        return 0;
 }
 
+static int test__checkevent_config_symbol(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = perf_evlist__first(evlist);
+
+       TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "insn") == 0);
+       return 0;
+}
+
+static int test__checkevent_config_raw(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = perf_evlist__first(evlist);
+
+       TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "rawpmu") == 0);
+       return 0;
+}
+
+static int test__checkevent_config_num(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = perf_evlist__first(evlist);
+
+       TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "numpmu") == 0);
+       return 0;
+}
+
+static int test__checkevent_config_cache(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = perf_evlist__first(evlist);
+
+       TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "cachepmu") == 0);
+       return 0;
+}
+
 static int count_tracepoints(void)
 {
        struct dirent *events_ent;
@@ -1579,6 +1611,26 @@ static struct evlist_test test__events[] = {
                .check = test__checkevent_precise_max_modifier,
                .id    = 47,
        },
+       {
+               .name  = "instructions/name=insn/",
+               .check = test__checkevent_config_symbol,
+               .id    = 48,
+       },
+       {
+               .name  = "r1234/name=rawpmu/",
+               .check = test__checkevent_config_raw,
+               .id    = 49,
+       },
+       {
+               .name  = "4:0x6530160/name=numpmu/",
+               .check = test__checkevent_config_num,
+               .id    = 50,
+       },
+       {
+               .name  = "L1-dcache-misses/name=cachepmu/",
+               .check = test__checkevent_config_cache,
+               .id    = 51,
+       },
 };
 
 static struct evlist_test test__events_pmu[] = {
@@ -1666,7 +1718,7 @@ static int test_term(struct terms_test *t)
        }
 
        ret = t->check(&terms);
-       parse_events__free_terms(&terms);
+       parse_events_terms__purge(&terms);
 
        return ret;
 }
index f0bfc9e8fd9f617d69c0b3cb36fe6c210ebbd6d5..630b0b409b973f87ba00312e5e4e3d8fdf829f32 100644 (file)
@@ -110,7 +110,6 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
         */
        for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
                struct symbol *pair, *first_pair;
-               bool backwards = true;
 
                sym  = rb_entry(nd, struct symbol, rb_node);
 
@@ -151,27 +150,14 @@ next_pair:
                                continue;
 
                        } else {
-                               struct rb_node *nnd;
-detour:
-                               nnd = backwards ? rb_prev(&pair->rb_node) :
-                                                 rb_next(&pair->rb_node);
-                               if (nnd) {
-                                       struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
-
-                                       if (UM(next->start) == mem_start) {
-                                               pair = next;
+                               pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL, NULL);
+                               if (pair) {
+                                       if (UM(pair->start) == mem_start)
                                                goto next_pair;
-                                       }
-                               }
 
-                               if (backwards) {
-                                       backwards = false;
-                                       pair = first_pair;
-                                       goto detour;
+                                       pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
+                                                mem_start, sym->name, pair->name);
                                }
-
-                               pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
-                                        mem_start, sym->name, pair->name);
                        }
                } else
                        pr_debug("%#" PRIx64 ": %s not on kallsyms\n",
index d37202121689a017b0790d552e088d695716c527..af68a9d488bfce964c84e67cf5394e7e13daab29 100644 (file)
@@ -531,8 +531,8 @@ static struct ui_browser_colorset {
                .bg       = "yellow",
        },
        {
-               .colorset = HE_COLORSET_CODE,
-               .name     = "code",
+               .colorset = HE_COLORSET_JUMP_ARROWS,
+               .name     = "jump_arrows",
                .fg       = "blue",
                .bg       = "default",
        },
index 01781de59532ce9c9fd1ff7f8c7fdf97d45fa105..be3b70eb5fca6e402830570c4111f10258702c04 100644 (file)
@@ -7,7 +7,7 @@
 #define HE_COLORSET_MEDIUM     51
 #define HE_COLORSET_NORMAL     52
 #define HE_COLORSET_SELECTED   53
-#define HE_COLORSET_CODE       54
+#define HE_COLORSET_JUMP_ARROWS        54
 #define HE_COLORSET_ADDR       55
 #define HE_COLORSET_ROOT       56
 
index 718bd46d47fa7bc88674a192dd1a8e8ab1fb7ca9..4fc208e82c6fc7b28d99af147d1c75738bc338e6 100644 (file)
@@ -284,7 +284,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
                to = (u64)btarget->idx;
        }
 
-       ui_browser__set_color(browser, HE_COLORSET_CODE);
+       ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS);
        __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width,
                                 from, to);
 }
index 08c09ad755d2d2f8dd55be06b258e16fb2c8335f..4b98165559462025ded4db4a41fe8b5e66a9f151 100644 (file)
@@ -32,6 +32,7 @@ struct hist_browser {
        bool                 show_headers;
        float                min_pcnt;
        u64                  nr_non_filtered_entries;
+       u64                  nr_hierarchy_entries;
        u64                  nr_callchain_rows;
 };
 
@@ -58,11 +59,11 @@ static int hist_browser__get_folding(struct hist_browser *browser)
 
        for (nd = rb_first(&hists->entries);
             (nd = hists__filter_entries(nd, browser->min_pcnt)) != NULL;
-            nd = rb_next(nd)) {
+            nd = rb_hierarchy_next(nd)) {
                struct hist_entry *he =
                        rb_entry(nd, struct hist_entry, rb_node);
 
-               if (he->unfolded)
+               if (he->leaf && he->unfolded)
                        unfolded_rows += he->nr_rows;
        }
        return unfolded_rows;
@@ -72,7 +73,9 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb)
 {
        u32 nr_entries;
 
-       if (hist_browser__has_filter(hb))
+       if (symbol_conf.report_hierarchy)
+               nr_entries = hb->nr_hierarchy_entries;
+       else if (hist_browser__has_filter(hb))
                nr_entries = hb->nr_non_filtered_entries;
        else
                nr_entries = hb->hists->nr_entries;
@@ -247,6 +250,38 @@ static int callchain__count_rows(struct rb_root *chain)
        return n;
 }
 
+static int hierarchy_count_rows(struct hist_browser *hb, struct hist_entry *he,
+                               bool include_children)
+{
+       int count = 0;
+       struct rb_node *node;
+       struct hist_entry *child;
+
+       if (he->leaf)
+               return callchain__count_rows(&he->sorted_chain);
+
+       if (he->has_no_entry)
+               return 1;
+
+       node = rb_first(&he->hroot_out);
+       while (node) {
+               float percent;
+
+               child = rb_entry(node, struct hist_entry, rb_node);
+               percent = hist_entry__get_percent_limit(child);
+
+               if (!child->filtered && percent >= hb->min_pcnt) {
+                       count++;
+
+                       if (include_children && child->unfolded)
+                               count += hierarchy_count_rows(hb, child, true);
+               }
+
+               node = rb_next(node);
+       }
+       return count;
+}
+
 static bool hist_entry__toggle_fold(struct hist_entry *he)
 {
        if (!he)
@@ -326,11 +361,17 @@ static void callchain__init_have_children(struct rb_root *root)
 
 static void hist_entry__init_have_children(struct hist_entry *he)
 {
-       if (!he->init_have_children) {
+       if (he->init_have_children)
+               return;
+
+       if (he->leaf) {
                he->has_children = !RB_EMPTY_ROOT(&he->sorted_chain);
                callchain__init_have_children(&he->sorted_chain);
-               he->init_have_children = true;
+       } else {
+               he->has_children = !RB_EMPTY_ROOT(&he->hroot_out);
        }
+
+       he->init_have_children = true;
 }
 
 static bool hist_browser__toggle_fold(struct hist_browser *browser)
@@ -349,17 +390,49 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser)
                has_children = callchain_list__toggle_fold(cl);
 
        if (has_children) {
+               int child_rows = 0;
+
                hist_entry__init_have_children(he);
                browser->b.nr_entries -= he->nr_rows;
-               browser->nr_callchain_rows -= he->nr_rows;
 
-               if (he->unfolded)
-                       he->nr_rows = callchain__count_rows(&he->sorted_chain);
+               if (he->leaf)
+                       browser->nr_callchain_rows -= he->nr_rows;
                else
+                       browser->nr_hierarchy_entries -= he->nr_rows;
+
+               if (symbol_conf.report_hierarchy)
+                       child_rows = hierarchy_count_rows(browser, he, true);
+
+               if (he->unfolded) {
+                       if (he->leaf)
+                               he->nr_rows = callchain__count_rows(&he->sorted_chain);
+                       else
+                               he->nr_rows = hierarchy_count_rows(browser, he, false);
+
+                       /* account grand children */
+                       if (symbol_conf.report_hierarchy)
+                               browser->b.nr_entries += child_rows - he->nr_rows;
+
+                       if (!he->leaf && he->nr_rows == 0) {
+                               he->has_no_entry = true;
+                               he->nr_rows = 1;
+                       }
+               } else {
+                       if (symbol_conf.report_hierarchy)
+                               browser->b.nr_entries -= child_rows - he->nr_rows;
+
+                       if (he->has_no_entry)
+                               he->has_no_entry = false;
+
                        he->nr_rows = 0;
+               }
 
                browser->b.nr_entries += he->nr_rows;
-               browser->nr_callchain_rows += he->nr_rows;
+
+               if (he->leaf)
+                       browser->nr_callchain_rows += he->nr_rows;
+               else
+                       browser->nr_hierarchy_entries += he->nr_rows;
 
                return true;
        }
@@ -422,13 +495,38 @@ static int callchain__set_folding(struct rb_root *chain, bool unfold)
        return n;
 }
 
-static void hist_entry__set_folding(struct hist_entry *he, bool unfold)
+static int hierarchy_set_folding(struct hist_browser *hb, struct hist_entry *he,
+                                bool unfold __maybe_unused)
+{
+       float percent;
+       struct rb_node *nd;
+       struct hist_entry *child;
+       int n = 0;
+
+       for (nd = rb_first(&he->hroot_out); nd; nd = rb_next(nd)) {
+               child = rb_entry(nd, struct hist_entry, rb_node);
+               percent = hist_entry__get_percent_limit(child);
+               if (!child->filtered && percent >= hb->min_pcnt)
+                       n++;
+       }
+
+       return n;
+}
+
+static void hist_entry__set_folding(struct hist_entry *he,
+                                   struct hist_browser *hb, bool unfold)
 {
        hist_entry__init_have_children(he);
        he->unfolded = unfold ? he->has_children : false;
 
        if (he->has_children) {
-               int n = callchain__set_folding(&he->sorted_chain, unfold);
+               int n;
+
+               if (he->leaf)
+                       n = callchain__set_folding(&he->sorted_chain, unfold);
+               else
+                       n = hierarchy_set_folding(hb, he, unfold);
+
                he->nr_rows = unfold ? n : 0;
        } else
                he->nr_rows = 0;
@@ -438,19 +536,38 @@ static void
 __hist_browser__set_folding(struct hist_browser *browser, bool unfold)
 {
        struct rb_node *nd;
-       struct hists *hists = browser->hists;
+       struct hist_entry *he;
+       double percent;
 
-       for (nd = rb_first(&hists->entries);
-            (nd = hists__filter_entries(nd, browser->min_pcnt)) != NULL;
-            nd = rb_next(nd)) {
-               struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
-               hist_entry__set_folding(he, unfold);
-               browser->nr_callchain_rows += he->nr_rows;
+       nd = rb_first(&browser->hists->entries);
+       while (nd) {
+               he = rb_entry(nd, struct hist_entry, rb_node);
+
+               /* set folding state even if it's currently folded */
+               nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD);
+
+               hist_entry__set_folding(he, browser, unfold);
+
+               percent = hist_entry__get_percent_limit(he);
+               if (he->filtered || percent < browser->min_pcnt)
+                       continue;
+
+               if (!he->depth || unfold)
+                       browser->nr_hierarchy_entries++;
+               if (he->leaf)
+                       browser->nr_callchain_rows += he->nr_rows;
+               else if (unfold && !hist_entry__has_hierarchy_children(he, browser->min_pcnt)) {
+                       browser->nr_hierarchy_entries++;
+                       he->has_no_entry = true;
+                       he->nr_rows = 1;
+               } else
+                       he->has_no_entry = false;
        }
 }
 
 static void hist_browser__set_folding(struct hist_browser *browser, bool unfold)
 {
+       browser->nr_hierarchy_entries = 0;
        browser->nr_callchain_rows = 0;
        __hist_browser__set_folding(browser, unfold);
 
@@ -657,9 +774,24 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
        return 1;
 }
 
+static bool check_percent_display(struct rb_node *node, u64 parent_total)
+{
+       struct callchain_node *child;
+
+       if (node == NULL)
+               return false;
+
+       if (rb_next(node))
+               return true;
+
+       child = rb_entry(node, struct callchain_node, rb_node);
+       return callchain_cumul_hits(child) != parent_total;
+}
+
 static int hist_browser__show_callchain_flat(struct hist_browser *browser,
                                             struct rb_root *root,
                                             unsigned short row, u64 total,
+                                            u64 parent_total,
                                             print_callchain_entry_fn print,
                                             struct callchain_print_arg *arg,
                                             check_output_full_fn is_output_full)
@@ -669,7 +801,7 @@ static int hist_browser__show_callchain_flat(struct hist_browser *browser,
        bool need_percent;
 
        node = rb_first(root);
-       need_percent = node && rb_next(node);
+       need_percent = check_percent_display(node, parent_total);
 
        while (node) {
                struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
@@ -763,6 +895,7 @@ static char *hist_browser__folded_callchain_str(struct hist_browser *browser,
 static int hist_browser__show_callchain_folded(struct hist_browser *browser,
                                               struct rb_root *root,
                                               unsigned short row, u64 total,
+                                              u64 parent_total,
                                               print_callchain_entry_fn print,
                                               struct callchain_print_arg *arg,
                                               check_output_full_fn is_output_full)
@@ -772,7 +905,7 @@ static int hist_browser__show_callchain_folded(struct hist_browser *browser,
        bool need_percent;
 
        node = rb_first(root);
-       need_percent = node && rb_next(node);
+       need_percent = check_percent_display(node, parent_total);
 
        while (node) {
                struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
@@ -844,20 +977,24 @@ next:
        return row - first_row;
 }
 
-static int hist_browser__show_callchain(struct hist_browser *browser,
+static int hist_browser__show_callchain_graph(struct hist_browser *browser,
                                        struct rb_root *root, int level,
                                        unsigned short row, u64 total,
+                                       u64 parent_total,
                                        print_callchain_entry_fn print,
                                        struct callchain_print_arg *arg,
                                        check_output_full_fn is_output_full)
 {
        struct rb_node *node;
        int first_row = row, offset = level * LEVEL_OFFSET_STEP;
-       u64 new_total;
        bool need_percent;
+       u64 percent_total = total;
+
+       if (callchain_param.mode == CHAIN_GRAPH_REL)
+               percent_total = parent_total;
 
        node = rb_first(root);
-       need_percent = node && rb_next(node);
+       need_percent = check_percent_display(node, parent_total);
 
        while (node) {
                struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
@@ -878,7 +1015,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
                        folded_sign = callchain_list__folded(chain);
 
                        row += hist_browser__show_callchain_list(browser, child,
-                                                       chain, row, total,
+                                                       chain, row, percent_total,
                                                        was_first && need_percent,
                                                        offset + extra_offset,
                                                        print, arg);
@@ -893,13 +1030,9 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
                if (folded_sign == '-') {
                        const int new_level = level + (extra_offset ? 2 : 1);
 
-                       if (callchain_param.mode == CHAIN_GRAPH_REL)
-                               new_total = child->children_hit;
-                       else
-                               new_total = total;
-
-                       row += hist_browser__show_callchain(browser, &child->rb_root,
-                                                           new_level, row, new_total,
+                       row += hist_browser__show_callchain_graph(browser, &child->rb_root,
+                                                           new_level, row, total,
+                                                           child->children_hit,
                                                            print, arg, is_output_full);
                }
                if (is_output_full(browser, row))
@@ -910,6 +1043,45 @@ out:
        return row - first_row;
 }
 
+static int hist_browser__show_callchain(struct hist_browser *browser,
+                                       struct hist_entry *entry, int level,
+                                       unsigned short row,
+                                       print_callchain_entry_fn print,
+                                       struct callchain_print_arg *arg,
+                                       check_output_full_fn is_output_full)
+{
+       u64 total = hists__total_period(entry->hists);
+       u64 parent_total;
+       int printed;
+
+       if (symbol_conf.cumulate_callchain)
+               parent_total = entry->stat_acc->period;
+       else
+               parent_total = entry->stat.period;
+
+       if (callchain_param.mode == CHAIN_FLAT) {
+               printed = hist_browser__show_callchain_flat(browser,
+                                               &entry->sorted_chain, row,
+                                               total, parent_total, print, arg,
+                                               is_output_full);
+       } else if (callchain_param.mode == CHAIN_FOLDED) {
+               printed = hist_browser__show_callchain_folded(browser,
+                                               &entry->sorted_chain, row,
+                                               total, parent_total, print, arg,
+                                               is_output_full);
+       } else {
+               printed = hist_browser__show_callchain_graph(browser,
+                                               &entry->sorted_chain, level, row,
+                                               total, parent_total, print, arg,
+                                               is_output_full);
+       }
+
+       if (arg->is_current_entry)
+               browser->he_selection = entry;
+
+       return printed;
+}
+
 struct hpp_arg {
        struct ui_browser *b;
        char folded_sign;
@@ -1006,7 +1178,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                                    struct hist_entry *entry,
                                    unsigned short row)
 {
-       char s[256];
        int printed = 0;
        int width = browser->b.width;
        char folded_sign = ' ';
@@ -1031,16 +1202,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                        .folded_sign    = folded_sign,
                        .current_entry  = current_entry,
                };
-               struct perf_hpp hpp = {
-                       .buf            = s,
-                       .size           = sizeof(s),
-                       .ptr            = &arg,
-               };
                int column = 0;
 
                hist_browser__gotorc(browser, row, 0);
 
-               perf_hpp__for_each_format(fmt) {
+               hists__for_each_format(browser->hists, fmt) {
+                       char s[2048];
+                       struct perf_hpp hpp = {
+                               .buf    = s,
+                               .size   = sizeof(s),
+                               .ptr    = &arg,
+                       };
+
                        if (perf_hpp__should_skip(fmt, entry->hists) ||
                            column++ < browser->b.horiz_scroll)
                                continue;
@@ -1065,11 +1238,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                        }
 
                        if (fmt->color) {
-                               width -= fmt->color(fmt, &hpp, entry);
+                               int ret = fmt->color(fmt, &hpp, entry);
+                               hist_entry__snprintf_alignment(entry, &hpp, fmt, ret);
+                               /*
+                                * fmt->color() already used ui_browser to
+                                * print the non alignment bits, skip it (+ret):
+                                */
+                               ui_browser__printf(&browser->b, "%s", s + ret);
                        } else {
-                               width -= fmt->entry(fmt, &hpp, entry);
+                               hist_entry__snprintf_alignment(entry, &hpp, fmt, fmt->entry(fmt, &hpp, entry));
                                ui_browser__printf(&browser->b, "%s", s);
                        }
+                       width -= hpp.buf - s;
                }
 
                /* The scroll bar isn't being used */
@@ -1084,43 +1264,246 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                --row_offset;
 
        if (folded_sign == '-' && row != browser->b.rows) {
-               u64 total = hists__total_period(entry->hists);
                struct callchain_print_arg arg = {
                        .row_offset = row_offset,
                        .is_current_entry = current_entry,
                };
 
-               if (callchain_param.mode == CHAIN_GRAPH_REL) {
-                       if (symbol_conf.cumulate_callchain)
-                               total = entry->stat_acc->period;
-                       else
-                               total = entry->stat.period;
-               }
-
-               if (callchain_param.mode == CHAIN_FLAT) {
-                       printed += hist_browser__show_callchain_flat(browser,
-                                       &entry->sorted_chain, row, total,
-                                       hist_browser__show_callchain_entry, &arg,
-                                       hist_browser__check_output_full);
-               } else if (callchain_param.mode == CHAIN_FOLDED) {
-                       printed += hist_browser__show_callchain_folded(browser,
-                                       &entry->sorted_chain, row, total,
+               printed += hist_browser__show_callchain(browser, entry, 1, row,
                                        hist_browser__show_callchain_entry, &arg,
                                        hist_browser__check_output_full);
+       }
+
+       return printed;
+}
+
+static int hist_browser__show_hierarchy_entry(struct hist_browser *browser,
+                                             struct hist_entry *entry,
+                                             unsigned short row,
+                                             int level)
+{
+       int printed = 0;
+       int width = browser->b.width;
+       char folded_sign = ' ';
+       bool current_entry = ui_browser__is_current_entry(&browser->b, row);
+       off_t row_offset = entry->row_offset;
+       bool first = true;
+       struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *fmt_node;
+       struct hpp_arg arg = {
+               .b              = &browser->b,
+               .current_entry  = current_entry,
+       };
+       int column = 0;
+       int hierarchy_indent = (entry->hists->nr_hpp_node - 2) * HIERARCHY_INDENT;
+
+       if (current_entry) {
+               browser->he_selection = entry;
+               browser->selection = &entry->ms;
+       }
+
+       hist_entry__init_have_children(entry);
+       folded_sign = hist_entry__folded(entry);
+       arg.folded_sign = folded_sign;
+
+       if (entry->leaf && row_offset) {
+               row_offset--;
+               goto show_callchain;
+       }
+
+       hist_browser__gotorc(browser, row, 0);
+
+       if (current_entry && browser->b.navkeypressed)
+               ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED);
+       else
+               ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL);
+
+       ui_browser__write_nstring(&browser->b, "", level * HIERARCHY_INDENT);
+       width -= level * HIERARCHY_INDENT;
+
+       /* the first hpp_list_node is for overhead columns */
+       fmt_node = list_first_entry(&entry->hists->hpp_formats,
+                                   struct perf_hpp_list_node, list);
+       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+               char s[2048];
+               struct perf_hpp hpp = {
+                       .buf            = s,
+                       .size           = sizeof(s),
+                       .ptr            = &arg,
+               };
+
+               if (perf_hpp__should_skip(fmt, entry->hists) ||
+                   column++ < browser->b.horiz_scroll)
+                       continue;
+
+               if (current_entry && browser->b.navkeypressed) {
+                       ui_browser__set_color(&browser->b,
+                                             HE_COLORSET_SELECTED);
                } else {
-                       printed += hist_browser__show_callchain(browser,
-                                       &entry->sorted_chain, 1, row, total,
-                                       hist_browser__show_callchain_entry, &arg,
-                                       hist_browser__check_output_full);
+                       ui_browser__set_color(&browser->b,
+                                             HE_COLORSET_NORMAL);
+               }
+
+               if (first) {
+                       ui_browser__printf(&browser->b, "%c", folded_sign);
+                       width--;
+                       first = false;
+               } else {
+                       ui_browser__printf(&browser->b, "  ");
+                       width -= 2;
+               }
+
+               if (fmt->color) {
+                       int ret = fmt->color(fmt, &hpp, entry);
+                       hist_entry__snprintf_alignment(entry, &hpp, fmt, ret);
+                       /*
+                        * fmt->color() already used ui_browser to
+                        * print the non alignment bits, skip it (+ret):
+                        */
+                       ui_browser__printf(&browser->b, "%s", s + ret);
+               } else {
+                       int ret = fmt->entry(fmt, &hpp, entry);
+                       hist_entry__snprintf_alignment(entry, &hpp, fmt, ret);
+                       ui_browser__printf(&browser->b, "%s", s);
+               }
+               width -= hpp.buf - s;
+       }
+
+       ui_browser__write_nstring(&browser->b, "", hierarchy_indent);
+       width -= hierarchy_indent;
+
+       if (column >= browser->b.horiz_scroll) {
+               char s[2048];
+               struct perf_hpp hpp = {
+                       .buf            = s,
+                       .size           = sizeof(s),
+                       .ptr            = &arg,
+               };
+
+               if (current_entry && browser->b.navkeypressed) {
+                       ui_browser__set_color(&browser->b,
+                                             HE_COLORSET_SELECTED);
+               } else {
+                       ui_browser__set_color(&browser->b,
+                                             HE_COLORSET_NORMAL);
                }
 
-               if (arg.is_current_entry)
-                       browser->he_selection = entry;
+               perf_hpp_list__for_each_format(entry->hpp_list, fmt) {
+                       ui_browser__write_nstring(&browser->b, "", 2);
+                       width -= 2;
+
+                       /*
+                        * No need to call hist_entry__snprintf_alignment()
+                        * since this fmt is always the last column in the
+                        * hierarchy mode.
+                        */
+                       if (fmt->color) {
+                               width -= fmt->color(fmt, &hpp, entry);
+                       } else {
+                               int i = 0;
+
+                               width -= fmt->entry(fmt, &hpp, entry);
+                               ui_browser__printf(&browser->b, "%s", ltrim(s));
+
+                               while (isspace(s[i++]))
+                                       width++;
+                       }
+               }
+       }
+
+       /* The scroll bar isn't being used */
+       if (!browser->b.navkeypressed)
+               width += 1;
+
+       ui_browser__write_nstring(&browser->b, "", width);
+
+       ++row;
+       ++printed;
+
+show_callchain:
+       if (entry->leaf && folded_sign == '-' && row != browser->b.rows) {
+               struct callchain_print_arg carg = {
+                       .row_offset = row_offset,
+               };
+
+               printed += hist_browser__show_callchain(browser, entry,
+                                       level + 1, row,
+                                       hist_browser__show_callchain_entry, &carg,
+                                       hist_browser__check_output_full);
        }
 
        return printed;
 }
 
+static int hist_browser__show_no_entry(struct hist_browser *browser,
+                                      unsigned short row, int level)
+{
+       int width = browser->b.width;
+       bool current_entry = ui_browser__is_current_entry(&browser->b, row);
+       bool first = true;
+       int column = 0;
+       int ret;
+       struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *fmt_node;
+       int indent = browser->hists->nr_hpp_node - 2;
+
+       if (current_entry) {
+               browser->he_selection = NULL;
+               browser->selection = NULL;
+       }
+
+       hist_browser__gotorc(browser, row, 0);
+
+       if (current_entry && browser->b.navkeypressed)
+               ui_browser__set_color(&browser->b, HE_COLORSET_SELECTED);
+       else
+               ui_browser__set_color(&browser->b, HE_COLORSET_NORMAL);
+
+       ui_browser__write_nstring(&browser->b, "", level * HIERARCHY_INDENT);
+       width -= level * HIERARCHY_INDENT;
+
+       /* the first hpp_list_node is for overhead columns */
+       fmt_node = list_first_entry(&browser->hists->hpp_formats,
+                                   struct perf_hpp_list_node, list);
+       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+               if (perf_hpp__should_skip(fmt, browser->hists) ||
+                   column++ < browser->b.horiz_scroll)
+                       continue;
+
+               ret = fmt->width(fmt, NULL, hists_to_evsel(browser->hists));
+
+               if (first) {
+                       /* for folded sign */
+                       first = false;
+                       ret++;
+               } else {
+                       /* space between columns */
+                       ret += 2;
+               }
+
+               ui_browser__write_nstring(&browser->b, "", ret);
+               width -= ret;
+       }
+
+       ui_browser__write_nstring(&browser->b, "", indent * HIERARCHY_INDENT);
+       width -= indent * HIERARCHY_INDENT;
+
+       if (column >= browser->b.horiz_scroll) {
+               char buf[32];
+
+               ret = snprintf(buf, sizeof(buf), "no entry >= %.2f%%", browser->min_pcnt);
+               ui_browser__printf(&browser->b, "  %s", buf);
+               width -= ret + 2;
+       }
+
+       /* The scroll bar isn't being used */
+       if (!browser->b.navkeypressed)
+               width += 1;
+
+       ui_browser__write_nstring(&browser->b, "", width);
+       return 1;
+}
+
 static int advance_hpp_check(struct perf_hpp *hpp, int inc)
 {
        advance_hpp(hpp, inc);
@@ -1144,7 +1527,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
                        return ret;
        }
 
-       perf_hpp__for_each_format(fmt) {
+       hists__for_each_format(browser->hists, fmt) {
                if (perf_hpp__should_skip(fmt, hists)  || column++ < browser->b.horiz_scroll)
                        continue;
 
@@ -1160,11 +1543,96 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
        return ret;
 }
 
+static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *browser, char *buf, size_t size)
+{
+       struct hists *hists = browser->hists;
+       struct perf_hpp dummy_hpp = {
+               .buf    = buf,
+               .size   = size,
+       };
+       struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *fmt_node;
+       size_t ret = 0;
+       int column = 0;
+       int indent = hists->nr_hpp_node - 2;
+       bool first_node, first_col;
+
+       ret = scnprintf(buf, size, " ");
+       if (advance_hpp_check(&dummy_hpp, ret))
+               return ret;
+
+       /* the first hpp_list_node is for overhead columns */
+       fmt_node = list_first_entry(&hists->hpp_formats,
+                                   struct perf_hpp_list_node, list);
+       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+               if (column++ < browser->b.horiz_scroll)
+                       continue;
+
+               ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
+               if (advance_hpp_check(&dummy_hpp, ret))
+                       break;
+
+               ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, "  ");
+               if (advance_hpp_check(&dummy_hpp, ret))
+                       break;
+       }
+
+       ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, "%*s",
+                       indent * HIERARCHY_INDENT, "");
+       if (advance_hpp_check(&dummy_hpp, ret))
+               return ret;
+
+       first_node = true;
+       list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) {
+               if (!first_node) {
+                       ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " / ");
+                       if (advance_hpp_check(&dummy_hpp, ret))
+                               break;
+               }
+               first_node = false;
+
+               first_col = true;
+               perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+                       char *start;
+
+                       if (perf_hpp__should_skip(fmt, hists))
+                               continue;
+
+                       if (!first_col) {
+                               ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, "+");
+                               if (advance_hpp_check(&dummy_hpp, ret))
+                                       break;
+                       }
+                       first_col = false;
+
+                       ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
+                       dummy_hpp.buf[ret] = '\0';
+                       rtrim(dummy_hpp.buf);
+
+                       start = ltrim(dummy_hpp.buf);
+                       ret = strlen(start);
+
+                       if (start != dummy_hpp.buf)
+                               memmove(dummy_hpp.buf, start, ret + 1);
+
+                       if (advance_hpp_check(&dummy_hpp, ret))
+                               break;
+               }
+       }
+
+       return ret;
+}
+
 static void hist_browser__show_headers(struct hist_browser *browser)
 {
        char headers[1024];
 
-       hists_browser__scnprintf_headers(browser, headers, sizeof(headers));
+       if (symbol_conf.report_hierarchy)
+               hists_browser__scnprintf_hierarchy_headers(browser, headers,
+                                                          sizeof(headers));
+       else
+               hists_browser__scnprintf_headers(browser, headers,
+                                                sizeof(headers));
        ui_browser__gotorc(&browser->b, 0, 0);
        ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
        ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
@@ -1196,18 +1664,34 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
        hb->he_selection = NULL;
        hb->selection = NULL;
 
-       for (nd = browser->top; nd; nd = rb_next(nd)) {
+       for (nd = browser->top; nd; nd = rb_hierarchy_next(nd)) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
                float percent;
 
-               if (h->filtered)
+               if (h->filtered) {
+                       /* let it move to sibling */
+                       h->unfolded = false;
                        continue;
+               }
 
                percent = hist_entry__get_percent_limit(h);
                if (percent < hb->min_pcnt)
                        continue;
 
-               row += hist_browser__show_entry(hb, h, row);
+               if (symbol_conf.report_hierarchy) {
+                       row += hist_browser__show_hierarchy_entry(hb, h, row,
+                                                                 h->depth);
+                       if (row == browser->rows)
+                               break;
+
+                       if (h->has_no_entry) {
+                               hist_browser__show_no_entry(hb, row, h->depth + 1);
+                               row++;
+                       }
+               } else {
+                       row += hist_browser__show_entry(hb, h, row);
+               }
+
                if (row == browser->rows)
                        break;
        }
@@ -1225,7 +1709,14 @@ static struct rb_node *hists__filter_entries(struct rb_node *nd,
                if (!h->filtered && percent >= min_pcnt)
                        return nd;
 
-               nd = rb_next(nd);
+               /*
+                * If it's filtered, its all children also were filtered.
+                * So move to sibling node.
+                */
+               if (rb_next(nd))
+                       nd = rb_next(nd);
+               else
+                       nd = rb_hierarchy_next(nd);
        }
 
        return NULL;
@@ -1241,7 +1732,7 @@ static struct rb_node *hists__filter_prev_entries(struct rb_node *nd,
                if (!h->filtered && percent >= min_pcnt)
                        return nd;
 
-               nd = rb_prev(nd);
+               nd = rb_hierarchy_prev(nd);
        }
 
        return NULL;
@@ -1271,8 +1762,8 @@ static void ui_browser__hists_seek(struct ui_browser *browser,
                nd = browser->top;
                goto do_offset;
        case SEEK_END:
-               nd = hists__filter_prev_entries(rb_last(browser->entries),
-                                               hb->min_pcnt);
+               nd = rb_hierarchy_last(rb_last(browser->entries));
+               nd = hists__filter_prev_entries(nd, hb->min_pcnt);
                first = false;
                break;
        default:
@@ -1306,7 +1797,7 @@ do_offset:
        if (offset > 0) {
                do {
                        h = rb_entry(nd, struct hist_entry, rb_node);
-                       if (h->unfolded) {
+                       if (h->unfolded && h->leaf) {
                                u16 remaining = h->nr_rows - h->row_offset;
                                if (offset > remaining) {
                                        offset -= remaining;
@@ -1318,7 +1809,8 @@ do_offset:
                                        break;
                                }
                        }
-                       nd = hists__filter_entries(rb_next(nd), hb->min_pcnt);
+                       nd = hists__filter_entries(rb_hierarchy_next(nd),
+                                                  hb->min_pcnt);
                        if (nd == NULL)
                                break;
                        --offset;
@@ -1327,7 +1819,7 @@ do_offset:
        } else if (offset < 0) {
                while (1) {
                        h = rb_entry(nd, struct hist_entry, rb_node);
-                       if (h->unfolded) {
+                       if (h->unfolded && h->leaf) {
                                if (first) {
                                        if (-offset > h->row_offset) {
                                                offset += h->row_offset;
@@ -1351,7 +1843,7 @@ do_offset:
                                }
                        }
 
-                       nd = hists__filter_prev_entries(rb_prev(nd),
+                       nd = hists__filter_prev_entries(rb_hierarchy_prev(nd),
                                                        hb->min_pcnt);
                        if (nd == NULL)
                                break;
@@ -1364,7 +1856,7 @@ do_offset:
                                 * row_offset at its last entry.
                                 */
                                h = rb_entry(nd, struct hist_entry, rb_node);
-                               if (h->unfolded)
+                               if (h->unfolded && h->leaf)
                                        h->row_offset = h->nr_rows;
                                break;
                        }
@@ -1378,17 +1870,14 @@ do_offset:
 }
 
 static int hist_browser__fprintf_callchain(struct hist_browser *browser,
-                                          struct hist_entry *he, FILE *fp)
+                                          struct hist_entry *he, FILE *fp,
+                                          int level)
 {
-       u64 total = hists__total_period(he->hists);
        struct callchain_print_arg arg  = {
                .fp = fp,
        };
 
-       if (symbol_conf.cumulate_callchain)
-               total = he->stat_acc->period;
-
-       hist_browser__show_callchain(browser, &he->sorted_chain, 1, 0, total,
+       hist_browser__show_callchain(browser, he, level, 0,
                                     hist_browser__fprintf_callchain_entry, &arg,
                                     hist_browser__check_dump_full);
        return arg.printed;
@@ -1414,7 +1903,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
        if (symbol_conf.use_callchain)
                printed += fprintf(fp, "%c ", folded_sign);
 
-       perf_hpp__for_each_format(fmt) {
+       hists__for_each_format(browser->hists, fmt) {
                if (perf_hpp__should_skip(fmt, he->hists))
                        continue;
 
@@ -1425,12 +1914,71 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
                        first = false;
 
                ret = fmt->entry(fmt, &hpp, he);
+               ret = hist_entry__snprintf_alignment(he, &hpp, fmt, ret);
                advance_hpp(&hpp, ret);
        }
-       printed += fprintf(fp, "%s\n", rtrim(s));
+       printed += fprintf(fp, "%s\n", s);
 
        if (folded_sign == '-')
-               printed += hist_browser__fprintf_callchain(browser, he, fp);
+               printed += hist_browser__fprintf_callchain(browser, he, fp, 1);
+
+       return printed;
+}
+
+
+static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser,
+                                                struct hist_entry *he,
+                                                FILE *fp, int level)
+{
+       char s[8192];
+       int printed = 0;
+       char folded_sign = ' ';
+       struct perf_hpp hpp = {
+               .buf = s,
+               .size = sizeof(s),
+       };
+       struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *fmt_node;
+       bool first = true;
+       int ret;
+       int hierarchy_indent = (he->hists->nr_hpp_node - 2) * HIERARCHY_INDENT;
+
+       printed = fprintf(fp, "%*s", level * HIERARCHY_INDENT, "");
+
+       folded_sign = hist_entry__folded(he);
+       printed += fprintf(fp, "%c", folded_sign);
+
+       /* the first hpp_list_node is for overhead columns */
+       fmt_node = list_first_entry(&he->hists->hpp_formats,
+                                   struct perf_hpp_list_node, list);
+       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+               if (!first) {
+                       ret = scnprintf(hpp.buf, hpp.size, "  ");
+                       advance_hpp(&hpp, ret);
+               } else
+                       first = false;
+
+               ret = fmt->entry(fmt, &hpp, he);
+               advance_hpp(&hpp, ret);
+       }
+
+       ret = scnprintf(hpp.buf, hpp.size, "%*s", hierarchy_indent, "");
+       advance_hpp(&hpp, ret);
+
+       perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+               ret = scnprintf(hpp.buf, hpp.size, "  ");
+               advance_hpp(&hpp, ret);
+
+               ret = fmt->entry(fmt, &hpp, he);
+               advance_hpp(&hpp, ret);
+       }
+
+       printed += fprintf(fp, "%s\n", rtrim(s));
+
+       if (he->leaf && folded_sign == '-') {
+               printed += hist_browser__fprintf_callchain(browser, he, fp,
+                                                          he->depth + 1);
+       }
 
        return printed;
 }
@@ -1444,8 +1992,16 @@ static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp)
        while (nd) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
 
-               printed += hist_browser__fprintf_entry(browser, h, fp);
-               nd = hists__filter_entries(rb_next(nd), browser->min_pcnt);
+               if (symbol_conf.report_hierarchy) {
+                       printed += hist_browser__fprintf_hierarchy_entry(browser,
+                                                                        h, fp,
+                                                                        h->depth);
+               } else {
+                       printed += hist_browser__fprintf_entry(browser, h, fp);
+               }
+
+               nd = hists__filter_entries(rb_hierarchy_next(nd),
+                                          browser->min_pcnt);
        }
 
        return printed;
@@ -1580,11 +2136,18 @@ static int hists__browser_title(struct hists *hists,
        if (hists->uid_filter_str)
                printed += snprintf(bf + printed, size - printed,
                                    ", UID: %s", hists->uid_filter_str);
-       if (thread)
-               printed += scnprintf(bf + printed, size - printed,
+       if (thread) {
+               if (sort__has_thread) {
+                       printed += scnprintf(bf + printed, size - printed,
                                    ", Thread: %s(%d)",
                                     (thread->comm_set ? thread__comm_str(thread) : ""),
                                    thread->tid);
+               } else {
+                       printed += scnprintf(bf + printed, size - printed,
+                                   ", Thread: %s",
+                                    (thread->comm_set ? thread__comm_str(thread) : ""));
+               }
+       }
        if (dso)
                printed += scnprintf(bf + printed, size - printed,
                                    ", DSO: %s", dso->short_name);
@@ -1759,15 +2322,24 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act)
 {
        struct thread *thread = act->thread;
 
+       if ((!sort__has_thread && !sort__has_comm) || thread == NULL)
+               return 0;
+
        if (browser->hists->thread_filter) {
                pstack__remove(browser->pstack, &browser->hists->thread_filter);
                perf_hpp__set_elide(HISTC_THREAD, false);
                thread__zput(browser->hists->thread_filter);
                ui_helpline__pop();
        } else {
-               ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"",
-                                  thread->comm_set ? thread__comm_str(thread) : "",
-                                  thread->tid);
+               if (sort__has_thread) {
+                       ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"",
+                                          thread->comm_set ? thread__comm_str(thread) : "",
+                                          thread->tid);
+               } else {
+                       ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s thread\"",
+                                          thread->comm_set ? thread__comm_str(thread) : "");
+               }
+
                browser->hists->thread_filter = thread__get(thread);
                perf_hpp__set_elide(HISTC_THREAD, false);
                pstack__push(browser->pstack, &browser->hists->thread_filter);
@@ -1782,13 +2354,22 @@ static int
 add_thread_opt(struct hist_browser *browser, struct popup_action *act,
               char **optstr, struct thread *thread)
 {
-       if (thread == NULL)
+       int ret;
+
+       if ((!sort__has_thread && !sort__has_comm) || thread == NULL)
                return 0;
 
-       if (asprintf(optstr, "Zoom %s %s(%d) thread",
-                    browser->hists->thread_filter ? "out of" : "into",
-                    thread->comm_set ? thread__comm_str(thread) : "",
-                    thread->tid) < 0)
+       if (sort__has_thread) {
+               ret = asprintf(optstr, "Zoom %s %s(%d) thread",
+                              browser->hists->thread_filter ? "out of" : "into",
+                              thread->comm_set ? thread__comm_str(thread) : "",
+                              thread->tid);
+       } else {
+               ret = asprintf(optstr, "Zoom %s %s thread",
+                              browser->hists->thread_filter ? "out of" : "into",
+                              thread->comm_set ? thread__comm_str(thread) : "");
+       }
+       if (ret < 0)
                return 0;
 
        act->thread = thread;
@@ -1801,6 +2382,9 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
 {
        struct map *map = act->ms.map;
 
+       if (!sort__has_dso || map == NULL)
+               return 0;
+
        if (browser->hists->dso_filter) {
                pstack__remove(browser->pstack, &browser->hists->dso_filter);
                perf_hpp__set_elide(HISTC_DSO, false);
@@ -1825,7 +2409,7 @@ static int
 add_dso_opt(struct hist_browser *browser, struct popup_action *act,
            char **optstr, struct map *map)
 {
-       if (map == NULL)
+       if (!sort__has_dso || map == NULL)
                return 0;
 
        if (asprintf(optstr, "Zoom %s %s DSO",
@@ -1850,7 +2434,7 @@ static int
 add_map_opt(struct hist_browser *browser __maybe_unused,
            struct popup_action *act, char **optstr, struct map *map)
 {
-       if (map == NULL)
+       if (!sort__has_dso || map == NULL)
                return 0;
 
        if (asprintf(optstr, "Browse map details") < 0)
@@ -1952,6 +2536,9 @@ add_exit_opt(struct hist_browser *browser __maybe_unused,
 static int
 do_zoom_socket(struct hist_browser *browser, struct popup_action *act)
 {
+       if (!sort__has_socket || act->socket < 0)
+               return 0;
+
        if (browser->hists->socket_filter > -1) {
                pstack__remove(browser->pstack, &browser->hists->socket_filter);
                browser->hists->socket_filter = -1;
@@ -1971,7 +2558,7 @@ static int
 add_socket_opt(struct hist_browser *browser, struct popup_action *act,
               char **optstr, int socket_id)
 {
-       if (socket_id < 0)
+       if (!sort__has_socket || socket_id < 0)
                return 0;
 
        if (asprintf(optstr, "Zoom %s Processor Socket %d",
@@ -1989,17 +2576,60 @@ static void hist_browser__update_nr_entries(struct hist_browser *hb)
        u64 nr_entries = 0;
        struct rb_node *nd = rb_first(&hb->hists->entries);
 
-       if (hb->min_pcnt == 0) {
+       if (hb->min_pcnt == 0 && !symbol_conf.report_hierarchy) {
                hb->nr_non_filtered_entries = hb->hists->nr_non_filtered_entries;
                return;
        }
 
        while ((nd = hists__filter_entries(nd, hb->min_pcnt)) != NULL) {
                nr_entries++;
-               nd = rb_next(nd);
+               nd = rb_hierarchy_next(nd);
        }
 
        hb->nr_non_filtered_entries = nr_entries;
+       hb->nr_hierarchy_entries = nr_entries;
+}
+
+static void hist_browser__update_percent_limit(struct hist_browser *hb,
+                                              double percent)
+{
+       struct hist_entry *he;
+       struct rb_node *nd = rb_first(&hb->hists->entries);
+       u64 total = hists__total_period(hb->hists);
+       u64 min_callchain_hits = total * (percent / 100);
+
+       hb->min_pcnt = callchain_param.min_percent = percent;
+
+       while ((nd = hists__filter_entries(nd, hb->min_pcnt)) != NULL) {
+               he = rb_entry(nd, struct hist_entry, rb_node);
+
+               if (he->has_no_entry) {
+                       he->has_no_entry = false;
+                       he->nr_rows = 0;
+               }
+
+               if (!he->leaf || !symbol_conf.use_callchain)
+                       goto next;
+
+               if (callchain_param.mode == CHAIN_GRAPH_REL) {
+                       total = he->stat.period;
+
+                       if (symbol_conf.cumulate_callchain)
+                               total = he->stat_acc->period;
+
+                       min_callchain_hits = total * (percent / 100);
+               }
+
+               callchain_param.sort(&he->sorted_chain, he->callchain,
+                                    min_callchain_hits, &callchain_param);
+
+next:
+               nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD);
+
+               /* force to re-evaluate folding state of callchains */
+               he->init_have_children = false;
+               hist_entry__set_folding(he, hb, false);
+       }
 }
 
 static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
@@ -2037,6 +2667,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
        "E             Expand all callchains\n"                         \
        "F             Toggle percentage of filtered entries\n"         \
        "H             Display column headers\n"                        \
+       "L             Change percent limit\n"                          \
        "m             Display context menu\n"                          \
        "S             Zoom into current Processor Socket\n"            \
 
@@ -2077,7 +2708,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
        memset(options, 0, sizeof(options));
        memset(actions, 0, sizeof(actions));
 
-       perf_hpp__for_each_format(fmt) {
+       hists__for_each_format(browser->hists, fmt) {
                perf_hpp__reset_width(fmt, hists);
                /*
                 * This is done just once, and activates the horizontal scrolling
@@ -2192,6 +2823,24 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                                top->zero = !top->zero;
                        }
                        continue;
+               case 'L':
+                       if (ui_browser__input_window("Percent Limit",
+                                       "Please enter the value you want to hide entries under that percent.",
+                                       buf, "ENTER: OK, ESC: Cancel",
+                                       delay_secs * 2) == K_ENTER) {
+                               char *end;
+                               double new_percent = strtod(buf, &end);
+
+                               if (new_percent < 0 || new_percent > 100) {
+                                       ui_browser__warning(&browser->b, delay_secs * 2,
+                                               "Invalid percent: %.2f", new_percent);
+                                       continue;
+                               }
+
+                               hist_browser__update_percent_limit(browser, new_percent);
+                               hist_browser__reset(browser);
+                       }
+                       continue;
                case K_F1:
                case 'h':
                case '?':
@@ -2263,10 +2912,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                        continue;
                }
 
-               if (!sort__has_sym)
-                       goto add_exit_option;
-
-               if (browser->selection == NULL)
+               if (!sort__has_sym || browser->selection == NULL)
                        goto skip_annotation;
 
                if (sort__mode == SORT_MODE__BRANCH) {
@@ -2306,11 +2952,16 @@ skip_annotation:
                                             &options[nr_options],
                                             socked_id);
                /* perf script support */
+               if (!is_report_browser(hbt))
+                       goto skip_scripting;
+
                if (browser->he_selection) {
-                       nr_options += add_script_opt(browser,
-                                                    &actions[nr_options],
-                                                    &options[nr_options],
-                                                    thread, NULL);
+                       if (sort__has_thread && thread) {
+                               nr_options += add_script_opt(browser,
+                                                            &actions[nr_options],
+                                                            &options[nr_options],
+                                                            thread, NULL);
+                       }
                        /*
                         * Note that browser->selection != NULL
                         * when browser->he_selection is not NULL,
@@ -2320,16 +2971,18 @@ skip_annotation:
                         *
                         * See hist_browser__show_entry.
                         */
-                       nr_options += add_script_opt(browser,
-                                                    &actions[nr_options],
-                                                    &options[nr_options],
-                                                    NULL, browser->selection->sym);
+                       if (sort__has_sym && browser->selection->sym) {
+                               nr_options += add_script_opt(browser,
+                                                            &actions[nr_options],
+                                                            &options[nr_options],
+                                                            NULL, browser->selection->sym);
+                       }
                }
                nr_options += add_script_opt(browser, &actions[nr_options],
                                             &options[nr_options], NULL, NULL);
                nr_options += add_switch_opt(browser, &actions[nr_options],
                                             &options[nr_options]);
-add_exit_option:
+skip_scripting:
                nr_options += add_exit_opt(browser, &actions[nr_options],
                                           &options[nr_options]);
 
index 0f8dcfdfb10f3856abefc7f252631e8937bacf6b..bd9bf7e343b1e310d20587d0b0f7b75c6b10a574 100644 (file)
@@ -306,7 +306,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 
        nr_cols = 0;
 
-       perf_hpp__for_each_format(fmt)
+       hists__for_each_format(hists, fmt)
                col_types[nr_cols++] = G_TYPE_STRING;
 
        store = gtk_tree_store_newv(nr_cols, col_types);
@@ -317,7 +317,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 
        col_idx = 0;
 
-       perf_hpp__for_each_format(fmt) {
+       hists__for_each_format(hists, fmt) {
                if (perf_hpp__should_skip(fmt, hists))
                        continue;
 
@@ -367,7 +367,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 
                col_idx = 0;
 
-               perf_hpp__for_each_format(fmt) {
+               hists__for_each_format(hists, fmt) {
                        if (perf_hpp__should_skip(fmt, h->hists))
                                continue;
 
@@ -396,6 +396,194 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
        gtk_container_add(GTK_CONTAINER(window), view);
 }
 
+static void perf_gtk__add_hierarchy_entries(struct hists *hists,
+                                           struct rb_root *root,
+                                           GtkTreeStore *store,
+                                           GtkTreeIter *parent,
+                                           struct perf_hpp *hpp,
+                                           float min_pcnt)
+{
+       int col_idx = 0;
+       struct rb_node *node;
+       struct hist_entry *he;
+       struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *fmt_node;
+       u64 total = hists__total_period(hists);
+       int size;
+
+       for (node = rb_first(root); node; node = rb_next(node)) {
+               GtkTreeIter iter;
+               float percent;
+               char *bf;
+
+               he = rb_entry(node, struct hist_entry, rb_node);
+               if (he->filtered)
+                       continue;
+
+               percent = hist_entry__get_percent_limit(he);
+               if (percent < min_pcnt)
+                       continue;
+
+               gtk_tree_store_append(store, &iter, parent);
+
+               col_idx = 0;
+
+               /* the first hpp_list_node is for overhead columns */
+               fmt_node = list_first_entry(&hists->hpp_formats,
+                                           struct perf_hpp_list_node, list);
+               perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+                       if (fmt->color)
+                               fmt->color(fmt, hpp, he);
+                       else
+                               fmt->entry(fmt, hpp, he);
+
+                       gtk_tree_store_set(store, &iter, col_idx++, hpp->buf, -1);
+               }
+
+               bf = hpp->buf;
+               size = hpp->size;
+               perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+                       int ret;
+
+                       if (fmt->color)
+                               ret = fmt->color(fmt, hpp, he);
+                       else
+                               ret = fmt->entry(fmt, hpp, he);
+
+                       snprintf(hpp->buf + ret, hpp->size - ret, "  ");
+                       advance_hpp(hpp, ret + 2);
+               }
+
+               gtk_tree_store_set(store, &iter, col_idx, ltrim(rtrim(bf)), -1);
+
+               if (!he->leaf) {
+                       hpp->buf = bf;
+                       hpp->size = size;
+
+                       perf_gtk__add_hierarchy_entries(hists, &he->hroot_out,
+                                                       store, &iter, hpp,
+                                                       min_pcnt);
+
+                       if (!hist_entry__has_hierarchy_children(he, min_pcnt)) {
+                               char buf[32];
+                               GtkTreeIter child;
+
+                               snprintf(buf, sizeof(buf), "no entry >= %.2f%%",
+                                        min_pcnt);
+
+                               gtk_tree_store_append(store, &child, &iter);
+                               gtk_tree_store_set(store, &child, col_idx, buf, -1);
+                       }
+               }
+
+               if (symbol_conf.use_callchain && he->leaf) {
+                       if (callchain_param.mode == CHAIN_GRAPH_REL)
+                               total = symbol_conf.cumulate_callchain ?
+                                       he->stat_acc->period : he->stat.period;
+
+                       perf_gtk__add_callchain(&he->sorted_chain, store, &iter,
+                                               col_idx, total);
+               }
+       }
+
+}
+
+static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
+                                    float min_pcnt)
+{
+       struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *fmt_node;
+       GType col_types[MAX_COLUMNS];
+       GtkCellRenderer *renderer;
+       GtkTreeStore *store;
+       GtkWidget *view;
+       int col_idx;
+       int nr_cols = 0;
+       char s[512];
+       char buf[512];
+       bool first_node, first_col;
+       struct perf_hpp hpp = {
+               .buf            = s,
+               .size           = sizeof(s),
+       };
+
+       hists__for_each_format(hists, fmt) {
+               if (perf_hpp__is_sort_entry(fmt) ||
+                   perf_hpp__is_dynamic_entry(fmt))
+                       break;
+
+               col_types[nr_cols++] = G_TYPE_STRING;
+       }
+       col_types[nr_cols++] = G_TYPE_STRING;
+
+       store = gtk_tree_store_newv(nr_cols, col_types);
+       view = gtk_tree_view_new();
+       renderer = gtk_cell_renderer_text_new();
+
+       col_idx = 0;
+
+       /* the first hpp_list_node is for overhead columns */
+       fmt_node = list_first_entry(&hists->hpp_formats,
+                                   struct perf_hpp_list_node, list);
+       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+               gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+                                                           -1, fmt->name,
+                                                           renderer, "markup",
+                                                           col_idx++, NULL);
+       }
+
+       /* construct merged column header since sort keys share single column */
+       buf[0] = '\0';
+       first_node = true;
+       list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) {
+               if (!first_node)
+                       strcat(buf, " / ");
+               first_node = false;
+
+               first_col = true;
+               perf_hpp_list__for_each_format(&fmt_node->hpp ,fmt) {
+                       if (perf_hpp__should_skip(fmt, hists))
+                               continue;
+
+                       if (!first_col)
+                               strcat(buf, "+");
+                       first_col = false;
+
+                       fmt->header(fmt, &hpp, hists_to_evsel(hists));
+                       strcat(buf, ltrim(rtrim(hpp.buf)));
+               }
+       }
+
+       gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
+                                                   -1, buf,
+                                                   renderer, "markup",
+                                                   col_idx++, NULL);
+
+       for (col_idx = 0; col_idx < nr_cols; col_idx++) {
+               GtkTreeViewColumn *column;
+
+               column = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_idx);
+               gtk_tree_view_column_set_resizable(column, TRUE);
+
+               if (col_idx == 0) {
+                       gtk_tree_view_set_expander_column(GTK_TREE_VIEW(view),
+                                                         column);
+               }
+       }
+
+       gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
+       g_object_unref(GTK_TREE_MODEL(store));
+
+       perf_gtk__add_hierarchy_entries(hists, &hists->entries, store,
+                                       NULL, &hpp, min_pcnt);
+
+       gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
+
+       g_signal_connect(view, "row-activated",
+                        G_CALLBACK(on_row_activated), NULL);
+       gtk_container_add(GTK_CONTAINER(window), view);
+}
+
 int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
                                  const char *help,
                                  struct hist_browser_timer *hbt __maybe_unused,
@@ -463,7 +651,10 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
                                                        GTK_POLICY_AUTOMATIC,
                                                        GTK_POLICY_AUTOMATIC);
 
-               perf_gtk__show_hists(scrolled_window, hists, min_pcnt);
+               if (symbol_conf.report_hierarchy)
+                       perf_gtk__show_hierarchy(scrolled_window, hists, min_pcnt);
+               else
+                       perf_gtk__show_hists(scrolled_window, hists, min_pcnt);
 
                tab_label = gtk_label_new(evname);
 
index bf2a66e254eac35c63a0dd44e83628f34e4dc2f9..3baeaa6e71b5a51e113b8b485df97b7c8ae003a2 100644 (file)
@@ -5,6 +5,7 @@
 #include "../util/util.h"
 #include "../util/sort.h"
 #include "../util/evsel.h"
+#include "../util/evlist.h"
 
 /* hist period print (hpp) functions */
 
@@ -371,7 +372,20 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
        return 0;
 }
 
-#define HPP__COLOR_PRINT_FNS(_name, _fn)               \
+static bool perf_hpp__is_hpp_entry(struct perf_hpp_fmt *a)
+{
+       return a->header == hpp__header_fn;
+}
+
+static bool hpp__equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
+{
+       if (!perf_hpp__is_hpp_entry(a) || !perf_hpp__is_hpp_entry(b))
+               return false;
+
+       return a->idx == b->idx;
+}
+
+#define HPP__COLOR_PRINT_FNS(_name, _fn, _idx)         \
        {                                               \
                .name   = _name,                        \
                .header = hpp__header_fn,               \
@@ -381,9 +395,11 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
                .cmp    = hpp__nop_cmp,                 \
                .collapse = hpp__nop_cmp,               \
                .sort   = hpp__sort_ ## _fn,            \
+               .idx    = PERF_HPP__ ## _idx,           \
+               .equal  = hpp__equal,                   \
        }
 
-#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn)           \
+#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn, _idx)     \
        {                                               \
                .name   = _name,                        \
                .header = hpp__header_fn,               \
@@ -393,9 +409,11 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
                .cmp    = hpp__nop_cmp,                 \
                .collapse = hpp__nop_cmp,               \
                .sort   = hpp__sort_ ## _fn,            \
+               .idx    = PERF_HPP__ ## _idx,           \
+               .equal  = hpp__equal,                   \
        }
 
-#define HPP__PRINT_FNS(_name, _fn)                     \
+#define HPP__PRINT_FNS(_name, _fn, _idx)               \
        {                                               \
                .name   = _name,                        \
                .header = hpp__header_fn,               \
@@ -404,22 +422,25 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
                .cmp    = hpp__nop_cmp,                 \
                .collapse = hpp__nop_cmp,               \
                .sort   = hpp__sort_ ## _fn,            \
+               .idx    = PERF_HPP__ ## _idx,           \
+               .equal  = hpp__equal,                   \
        }
 
 struct perf_hpp_fmt perf_hpp__format[] = {
-       HPP__COLOR_PRINT_FNS("Overhead", overhead),
-       HPP__COLOR_PRINT_FNS("sys", overhead_sys),
-       HPP__COLOR_PRINT_FNS("usr", overhead_us),
-       HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys),
-       HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us),
-       HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc),
-       HPP__PRINT_FNS("Samples", samples),
-       HPP__PRINT_FNS("Period", period)
+       HPP__COLOR_PRINT_FNS("Overhead", overhead, OVERHEAD),
+       HPP__COLOR_PRINT_FNS("sys", overhead_sys, OVERHEAD_SYS),
+       HPP__COLOR_PRINT_FNS("usr", overhead_us, OVERHEAD_US),
+       HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys, OVERHEAD_GUEST_SYS),
+       HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us, OVERHEAD_GUEST_US),
+       HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc, OVERHEAD_ACC),
+       HPP__PRINT_FNS("Samples", samples, SAMPLES),
+       HPP__PRINT_FNS("Period", period, PERIOD)
 };
 
-LIST_HEAD(perf_hpp__list);
-LIST_HEAD(perf_hpp__sort_list);
-
+struct perf_hpp_list perf_hpp_list = {
+       .fields = LIST_HEAD_INIT(perf_hpp_list.fields),
+       .sorts  = LIST_HEAD_INIT(perf_hpp_list.sorts),
+};
 
 #undef HPP__COLOR_PRINT_FNS
 #undef HPP__COLOR_ACC_PRINT_FNS
@@ -485,63 +506,60 @@ void perf_hpp__init(void)
                hpp_dimension__add_output(PERF_HPP__PERIOD);
 }
 
-void perf_hpp__column_register(struct perf_hpp_fmt *format)
+void perf_hpp_list__column_register(struct perf_hpp_list *list,
+                                   struct perf_hpp_fmt *format)
 {
-       list_add_tail(&format->list, &perf_hpp__list);
+       list_add_tail(&format->list, &list->fields);
 }
 
-void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
+void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
+                                       struct perf_hpp_fmt *format)
 {
-       list_del(&format->list);
+       list_add_tail(&format->sort_list, &list->sorts);
 }
 
-void perf_hpp__register_sort_field(struct perf_hpp_fmt *format)
-{
-       list_add_tail(&format->sort_list, &perf_hpp__sort_list);
-}
-
-void perf_hpp__column_enable(unsigned col)
-{
-       BUG_ON(col >= PERF_HPP__MAX_INDEX);
-       perf_hpp__column_register(&perf_hpp__format[col]);
-}
-
-void perf_hpp__column_disable(unsigned col)
+void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
 {
-       BUG_ON(col >= PERF_HPP__MAX_INDEX);
-       perf_hpp__column_unregister(&perf_hpp__format[col]);
+       list_del(&format->list);
 }
 
 void perf_hpp__cancel_cumulate(void)
 {
+       struct perf_hpp_fmt *fmt, *acc, *ovh, *tmp;
+
        if (is_strict_order(field_order))
                return;
 
-       perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC);
-       perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead";
+       ovh = &perf_hpp__format[PERF_HPP__OVERHEAD];
+       acc = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC];
+
+       perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) {
+               if (acc->equal(acc, fmt)) {
+                       perf_hpp__column_unregister(fmt);
+                       continue;
+               }
+
+               if (ovh->equal(ovh, fmt))
+                       fmt->name = "Overhead";
+       }
 }
 
-void perf_hpp__setup_output_field(void)
+static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
+{
+       return a->equal && a->equal(a, b);
+}
+
+void perf_hpp__setup_output_field(struct perf_hpp_list *list)
 {
        struct perf_hpp_fmt *fmt;
 
        /* append sort keys to output field */
-       perf_hpp__for_each_sort_list(fmt) {
-               if (!list_empty(&fmt->list))
-                       continue;
-
-               /*
-                * sort entry fields are dynamically created,
-                * so they can share a same sort key even though
-                * the list is empty.
-                */
-               if (perf_hpp__is_sort_entry(fmt)) {
-                       struct perf_hpp_fmt *pos;
+       perf_hpp_list__for_each_sort_list(list, fmt) {
+               struct perf_hpp_fmt *pos;
 
-                       perf_hpp__for_each_format(pos) {
-                               if (perf_hpp__same_sort_entry(pos, fmt))
-                                       goto next;
-                       }
+               perf_hpp_list__for_each_format(list, pos) {
+                       if (fmt_equal(fmt, pos))
+                               goto next;
                }
 
                perf_hpp__column_register(fmt);
@@ -550,27 +568,17 @@ next:
        }
 }
 
-void perf_hpp__append_sort_keys(void)
+void perf_hpp__append_sort_keys(struct perf_hpp_list *list)
 {
        struct perf_hpp_fmt *fmt;
 
        /* append output fields to sort keys */
-       perf_hpp__for_each_format(fmt) {
-               if (!list_empty(&fmt->sort_list))
-                       continue;
-
-               /*
-                * sort entry fields are dynamically created,
-                * so they can share a same sort key even though
-                * the list is empty.
-                */
-               if (perf_hpp__is_sort_entry(fmt)) {
-                       struct perf_hpp_fmt *pos;
+       perf_hpp_list__for_each_format(list, fmt) {
+               struct perf_hpp_fmt *pos;
 
-                       perf_hpp__for_each_sort_list(pos) {
-                               if (perf_hpp__same_sort_entry(pos, fmt))
-                                       goto next;
-                       }
+               perf_hpp_list__for_each_sort_list(list, pos) {
+                       if (fmt_equal(fmt, pos))
+                               goto next;
                }
 
                perf_hpp__register_sort_field(fmt);
@@ -579,20 +587,29 @@ next:
        }
 }
 
-void perf_hpp__reset_output_field(void)
+
+static void fmt_free(struct perf_hpp_fmt *fmt)
+{
+       if (fmt->free)
+               fmt->free(fmt);
+}
+
+void perf_hpp__reset_output_field(struct perf_hpp_list *list)
 {
        struct perf_hpp_fmt *fmt, *tmp;
 
        /* reset output fields */
-       perf_hpp__for_each_format_safe(fmt, tmp) {
+       perf_hpp_list__for_each_format_safe(list, fmt, tmp) {
                list_del_init(&fmt->list);
                list_del_init(&fmt->sort_list);
+               fmt_free(fmt);
        }
 
        /* reset sort keys */
-       perf_hpp__for_each_sort_list_safe(fmt, tmp) {
+       perf_hpp_list__for_each_sort_list_safe(list, fmt, tmp) {
                list_del_init(&fmt->list);
                list_del_init(&fmt->sort_list);
+               fmt_free(fmt);
        }
 }
 
@@ -606,7 +623,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
        bool first = true;
        struct perf_hpp dummy_hpp;
 
-       perf_hpp__for_each_format(fmt) {
+       hists__for_each_format(hists, fmt) {
                if (perf_hpp__should_skip(fmt, hists))
                        continue;
 
@@ -624,22 +641,39 @@ unsigned int hists__sort_list_width(struct hists *hists)
        return ret;
 }
 
-void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
+unsigned int hists__overhead_width(struct hists *hists)
 {
-       int idx;
-
-       if (perf_hpp__is_sort_entry(fmt))
-               return perf_hpp__reset_sort_width(fmt, hists);
+       struct perf_hpp_fmt *fmt;
+       int ret = 0;
+       bool first = true;
+       struct perf_hpp dummy_hpp;
 
-       for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
-               if (fmt == &perf_hpp__format[idx])
+       hists__for_each_format(hists, fmt) {
+               if (perf_hpp__is_sort_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
                        break;
+
+               if (first)
+                       first = false;
+               else
+                       ret += 2;
+
+               ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));
        }
 
-       if (idx == PERF_HPP__MAX_INDEX)
+       return ret;
+}
+
+void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
+{
+       if (perf_hpp__is_sort_entry(fmt))
+               return perf_hpp__reset_sort_width(fmt, hists);
+
+       if (perf_hpp__is_dynamic_entry(fmt))
                return;
 
-       switch (idx) {
+       BUG_ON(fmt->idx >= PERF_HPP__MAX_INDEX);
+
+       switch (fmt->idx) {
        case PERF_HPP__OVERHEAD:
        case PERF_HPP__OVERHEAD_SYS:
        case PERF_HPP__OVERHEAD_US:
@@ -667,7 +701,7 @@ void perf_hpp__set_user_width(const char *width_list_str)
        struct perf_hpp_fmt *fmt;
        const char *ptr = width_list_str;
 
-       perf_hpp__for_each_format(fmt) {
+       perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
                char *p;
 
                int len = strtol(ptr, &p, 10);
@@ -679,3 +713,71 @@ void perf_hpp__set_user_width(const char *width_list_str)
                        break;
        }
 }
+
+static int add_hierarchy_fmt(struct hists *hists, struct perf_hpp_fmt *fmt)
+{
+       struct perf_hpp_list_node *node = NULL;
+       struct perf_hpp_fmt *fmt_copy;
+       bool found = false;
+       bool skip = perf_hpp__should_skip(fmt, hists);
+
+       list_for_each_entry(node, &hists->hpp_formats, list) {
+               if (node->level == fmt->level) {
+                       found = true;
+                       break;
+               }
+       }
+
+       if (!found) {
+               node = malloc(sizeof(*node));
+               if (node == NULL)
+                       return -1;
+
+               node->skip = skip;
+               node->level = fmt->level;
+               perf_hpp_list__init(&node->hpp);
+
+               hists->nr_hpp_node++;
+               list_add_tail(&node->list, &hists->hpp_formats);
+       }
+
+       fmt_copy = perf_hpp_fmt__dup(fmt);
+       if (fmt_copy == NULL)
+               return -1;
+
+       if (!skip)
+               node->skip = false;
+
+       list_add_tail(&fmt_copy->list, &node->hpp.fields);
+       list_add_tail(&fmt_copy->sort_list, &node->hpp.sorts);
+
+       return 0;
+}
+
+int perf_hpp__setup_hists_formats(struct perf_hpp_list *list,
+                                 struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel;
+       struct perf_hpp_fmt *fmt;
+       struct hists *hists;
+       int ret;
+
+       if (!symbol_conf.report_hierarchy)
+               return 0;
+
+       evlist__for_each(evlist, evsel) {
+               hists = evsel__hists(evsel);
+
+               perf_hpp_list__for_each_sort_list(list, fmt) {
+                       if (perf_hpp__is_dynamic_entry(fmt) &&
+                           !perf_hpp__defined_dynamic_entry(fmt, hists))
+                               continue;
+
+                       ret = add_hierarchy_fmt(hists, fmt);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
index 387110d50b002557d99e723605407c3db990d71a..7aff5acf3265782e03254de2d8bc1dfafb56e03a 100644 (file)
@@ -165,8 +165,28 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root,
        return ret;
 }
 
+/*
+ * If have one single callchain root, don't bother printing
+ * its percentage (100 % in fractal mode and the same percentage
+ * than the hist in graph mode). This also avoid one level of column.
+ *
+ * However when percent-limit applied, it's possible that single callchain
+ * node have different (non-100% in fractal mode) percentage.
+ */
+static bool need_percent_display(struct rb_node *node, u64 parent_samples)
+{
+       struct callchain_node *cnode;
+
+       if (rb_next(node))
+               return true;
+
+       cnode = rb_entry(node, struct callchain_node, rb_node);
+       return callchain_cumul_hits(cnode) != parent_samples;
+}
+
 static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
-                                      u64 total_samples, int left_margin)
+                                      u64 total_samples, u64 parent_samples,
+                                      int left_margin)
 {
        struct callchain_node *cnode;
        struct callchain_list *chain;
@@ -177,13 +197,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
        int ret = 0;
        char bf[1024];
 
-       /*
-        * If have one single callchain root, don't bother printing
-        * its percentage (100 % in fractal mode and the same percentage
-        * than the hist in graph mode). This also avoid one level of column.
-        */
        node = rb_first(root);
-       if (node && !rb_next(node)) {
+       if (node && !need_percent_display(node, parent_samples)) {
                cnode = rb_entry(node, struct callchain_node, rb_node);
                list_for_each_entry(chain, &cnode->val, list) {
                        /*
@@ -213,9 +228,15 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
                root = &cnode->rb_root;
        }
 
+       if (callchain_param.mode == CHAIN_GRAPH_REL)
+               total_samples = parent_samples;
+
        ret += __callchain__fprintf_graph(fp, root, total_samples,
                                          1, 1, left_margin);
-       ret += fprintf(fp, "\n");
+       if (ret) {
+               /* do not add a blank line if it printed nothing */
+               ret += fprintf(fp, "\n");
+       }
 
        return ret;
 }
@@ -323,16 +344,19 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
                                            u64 total_samples, int left_margin,
                                            FILE *fp)
 {
+       u64 parent_samples = he->stat.period;
+
+       if (symbol_conf.cumulate_callchain)
+               parent_samples = he->stat_acc->period;
+
        switch (callchain_param.mode) {
        case CHAIN_GRAPH_REL:
-               return callchain__fprintf_graph(fp, &he->sorted_chain,
-                                               symbol_conf.cumulate_callchain ?
-                                               he->stat_acc->period : he->stat.period,
-                                               left_margin);
+               return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples,
+                                               parent_samples, left_margin);
                break;
        case CHAIN_GRAPH_ABS:
                return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples,
-                                               left_margin);
+                                               parent_samples, left_margin);
                break;
        case CHAIN_FLAT:
                return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples);
@@ -349,45 +373,66 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
        return 0;
 }
 
-static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
-                                           struct hists *hists,
-                                           FILE *fp)
+static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
 {
-       int left_margin = 0;
-       u64 total_period = hists->stats.total_period;
+       const char *sep = symbol_conf.field_sep;
+       struct perf_hpp_fmt *fmt;
+       char *start = hpp->buf;
+       int ret;
+       bool first = true;
 
-       if (field_order == NULL && (sort_order == NULL ||
-                                   !prefixcmp(sort_order, "comm"))) {
-               struct perf_hpp_fmt *fmt;
+       if (symbol_conf.exclude_other && !he->parent)
+               return 0;
 
-               perf_hpp__for_each_format(fmt) {
-                       if (!perf_hpp__is_sort_entry(fmt))
-                               continue;
+       hists__for_each_format(he->hists, fmt) {
+               if (perf_hpp__should_skip(fmt, he->hists))
+                       continue;
 
-                       /* must be 'comm' sort entry */
-                       left_margin = fmt->width(fmt, NULL, hists_to_evsel(hists));
-                       left_margin -= thread__comm_len(he->thread);
-                       break;
-               }
+               /*
+                * If there's no field_sep, we still need
+                * to display initial '  '.
+                */
+               if (!sep || !first) {
+                       ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: "  ");
+                       advance_hpp(hpp, ret);
+               } else
+                       first = false;
+
+               if (perf_hpp__use_color() && fmt->color)
+                       ret = fmt->color(fmt, hpp, he);
+               else
+                       ret = fmt->entry(fmt, hpp, he);
+
+               ret = hist_entry__snprintf_alignment(he, hpp, fmt, ret);
+               advance_hpp(hpp, ret);
        }
-       return hist_entry_callchain__fprintf(he, total_period, left_margin, fp);
+
+       return hpp->buf - start;
 }
 
-static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
+static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
+                                        struct perf_hpp *hpp,
+                                        struct hists *hists,
+                                        FILE *fp)
 {
        const char *sep = symbol_conf.field_sep;
        struct perf_hpp_fmt *fmt;
-       char *start = hpp->buf;
-       int ret;
+       struct perf_hpp_list_node *fmt_node;
+       char *buf = hpp->buf;
+       size_t size = hpp->size;
+       int ret, printed = 0;
        bool first = true;
 
        if (symbol_conf.exclude_other && !he->parent)
                return 0;
 
-       perf_hpp__for_each_format(fmt) {
-               if (perf_hpp__should_skip(fmt, he->hists))
-                       continue;
+       ret = scnprintf(hpp->buf, hpp->size, "%*s", he->depth * HIERARCHY_INDENT, "");
+       advance_hpp(hpp, ret);
 
+       /* the first hpp_list_node is for overhead columns */
+       fmt_node = list_first_entry(&hists->hpp_formats,
+                                   struct perf_hpp_list_node, list);
+       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
                /*
                 * If there's no field_sep, we still need
                 * to display initial '  '.
@@ -403,10 +448,47 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
                else
                        ret = fmt->entry(fmt, hpp, he);
 
+               ret = hist_entry__snprintf_alignment(he, hpp, fmt, ret);
                advance_hpp(hpp, ret);
        }
 
-       return hpp->buf - start;
+       if (!sep)
+               ret = scnprintf(hpp->buf, hpp->size, "%*s",
+                               (hists->nr_hpp_node - 2) * HIERARCHY_INDENT, "");
+       advance_hpp(hpp, ret);
+
+       printed += fprintf(fp, "%s", buf);
+
+       perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+               hpp->buf  = buf;
+               hpp->size = size;
+
+               /*
+                * No need to call hist_entry__snprintf_alignment() since this
+                * fmt is always the last column in the hierarchy mode.
+                */
+               if (perf_hpp__use_color() && fmt->color)
+                       fmt->color(fmt, hpp, he);
+               else
+                       fmt->entry(fmt, hpp, he);
+
+               /*
+                * dynamic entries are right-aligned but we want left-aligned
+                * in the hierarchy mode
+                */
+               printed += fprintf(fp, "%s%s", sep ?: "  ", ltrim(buf));
+       }
+       printed += putc('\n', fp);
+
+       if (symbol_conf.use_callchain && he->leaf) {
+               u64 total = hists__total_period(hists);
+
+               printed += hist_entry_callchain__fprintf(he, total, 0, fp);
+               goto out;
+       }
+
+out:
+       return printed;
 }
 
 static int hist_entry__fprintf(struct hist_entry *he, size_t size,
@@ -418,24 +500,134 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
                .buf            = bf,
                .size           = size,
        };
+       u64 total_period = hists->stats.total_period;
 
        if (size == 0 || size > bfsz)
                size = hpp.size = bfsz;
 
+       if (symbol_conf.report_hierarchy)
+               return hist_entry__hierarchy_fprintf(he, &hpp, hists, fp);
+
        hist_entry__snprintf(he, &hpp);
 
        ret = fprintf(fp, "%s\n", bf);
 
        if (symbol_conf.use_callchain)
-               ret += hist_entry__callchain_fprintf(he, hists, fp);
+               ret += hist_entry_callchain__fprintf(he, total_period, 0, fp);
 
        return ret;
 }
 
+static int print_hierarchy_indent(const char *sep, int indent,
+                                 const char *line, FILE *fp)
+{
+       if (sep != NULL || indent < 2)
+               return 0;
+
+       return fprintf(fp, "%-.*s", (indent - 2) * HIERARCHY_INDENT, line);
+}
+
+static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
+                                 const char *sep, FILE *fp)
+{
+       bool first_node, first_col;
+       int indent;
+       int depth;
+       unsigned width = 0;
+       unsigned header_width = 0;
+       struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *fmt_node;
+
+       indent = hists->nr_hpp_node;
+
+       /* preserve max indent depth for column headers */
+       print_hierarchy_indent(sep, indent, spaces, fp);
+
+       /* the first hpp_list_node is for overhead columns */
+       fmt_node = list_first_entry(&hists->hpp_formats,
+                                   struct perf_hpp_list_node, list);
+
+       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+               fmt->header(fmt, hpp, hists_to_evsel(hists));
+               fprintf(fp, "%s%s", hpp->buf, sep ?: "  ");
+       }
+
+       /* combine sort headers with ' / ' */
+       first_node = true;
+       list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) {
+               if (!first_node)
+                       header_width += fprintf(fp, " / ");
+               first_node = false;
+
+               first_col = true;
+               perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+                       if (perf_hpp__should_skip(fmt, hists))
+                               continue;
+
+                       if (!first_col)
+                               header_width += fprintf(fp, "+");
+                       first_col = false;
+
+                       fmt->header(fmt, hpp, hists_to_evsel(hists));
+                       rtrim(hpp->buf);
+
+                       header_width += fprintf(fp, "%s", ltrim(hpp->buf));
+               }
+       }
+
+       fprintf(fp, "\n# ");
+
+       /* preserve max indent depth for initial dots */
+       print_hierarchy_indent(sep, indent, dots, fp);
+
+       /* the first hpp_list_node is for overhead columns */
+       fmt_node = list_first_entry(&hists->hpp_formats,
+                                   struct perf_hpp_list_node, list);
+
+       first_col = true;
+       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+               if (!first_col)
+                       fprintf(fp, "%s", sep ?: "..");
+               first_col = false;
+
+               width = fmt->width(fmt, hpp, hists_to_evsel(hists));
+               fprintf(fp, "%.*s", width, dots);
+       }
+
+       depth = 0;
+       list_for_each_entry_continue(fmt_node, &hists->hpp_formats, list) {
+               first_col = true;
+               width = depth * HIERARCHY_INDENT;
+
+               perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
+                       if (perf_hpp__should_skip(fmt, hists))
+                               continue;
+
+                       if (!first_col)
+                               width++;  /* for '+' sign between column header */
+                       first_col = false;
+
+                       width += fmt->width(fmt, hpp, hists_to_evsel(hists));
+               }
+
+               if (width > header_width)
+                       header_width = width;
+
+               depth++;
+       }
+
+       fprintf(fp, "%s%-.*s", sep ?: "  ", header_width, dots);
+
+       fprintf(fp, "\n#\n");
+
+       return 2;
+}
+
 size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
                      int max_cols, float min_pcnt, FILE *fp)
 {
        struct perf_hpp_fmt *fmt;
+       struct perf_hpp_list_node *fmt_node;
        struct rb_node *nd;
        size_t ret = 0;
        unsigned int width;
@@ -449,10 +641,11 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
        bool first = true;
        size_t linesz;
        char *line = NULL;
+       unsigned indent;
 
        init_rem_hits();
 
-       perf_hpp__for_each_format(fmt)
+       hists__for_each_format(hists, fmt)
                perf_hpp__reset_width(fmt, hists);
 
        if (symbol_conf.col_width_list_str)
@@ -463,7 +656,16 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 
        fprintf(fp, "# ");
 
-       perf_hpp__for_each_format(fmt) {
+       if (symbol_conf.report_hierarchy) {
+               list_for_each_entry(fmt_node, &hists->hpp_formats, list) {
+                       perf_hpp_list__for_each_format(&fmt_node->hpp, fmt)
+                               perf_hpp__reset_width(fmt, hists);
+               }
+               nr_rows += print_hierarchy_header(hists, &dummy_hpp, sep, fp);
+               goto print_entries;
+       }
+
+       hists__for_each_format(hists, fmt) {
                if (perf_hpp__should_skip(fmt, hists))
                        continue;
 
@@ -487,7 +689,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
 
        fprintf(fp, "# ");
 
-       perf_hpp__for_each_format(fmt) {
+       hists__for_each_format(hists, fmt) {
                unsigned int i;
 
                if (perf_hpp__should_skip(fmt, hists))
@@ -520,7 +722,9 @@ print_entries:
                goto out;
        }
 
-       for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
+       indent = hists__overhead_width(hists) + 4;
+
+       for (nd = rb_first(&hists->entries); nd; nd = __rb_hierarchy_next(nd, HMD_FORCE_CHILD)) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
                float percent;
 
@@ -536,6 +740,20 @@ print_entries:
                if (max_rows && ++nr_rows >= max_rows)
                        break;
 
+               /*
+                * If all children are filtered out or percent-limited,
+                * display "no entry >= x.xx%" message.
+                */
+               if (!h->leaf && !hist_entry__has_hierarchy_children(h, min_pcnt)) {
+                       int depth = hists->nr_hpp_node + h->depth + 1;
+
+                       print_hierarchy_indent(sep, depth, spaces, fp);
+                       fprintf(fp, "%*sno entry >= %.2f%%\n", indent, "", min_pcnt);
+
+                       if (max_rows && ++nr_rows >= max_rows)
+                               break;
+               }
+
                if (h->ms.map == NULL && verbose > 1) {
                        __map_groups__fprintf_maps(h->thread->mg,
                                                   MAP__FUNCTION, fp);
index 5eec53a3f4ac7dbedb54776f746705acfa4fa2b4..eea25e2424e99172715c681a05ffc68b3c58e78a 100644 (file)
@@ -82,6 +82,7 @@ libperf-y += parse-branch-options.o
 libperf-y += parse-regs-options.o
 libperf-y += term.o
 libperf-y += help-unknown-cmd.o
+libperf-y += mem-events.o
 
 libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -105,8 +106,17 @@ libperf-y += scripting-engines/
 
 libperf-$(CONFIG_ZLIB) += zlib.o
 libperf-$(CONFIG_LZMA) += lzma.o
+libperf-y += demangle-java.o
+
+ifdef CONFIG_JITDUMP
+libperf-$(CONFIG_LIBELF) += jitdump.o
+libperf-$(CONFIG_LIBELF) += genelf.o
+libperf-$(CONFIG_LIBELF) += genelf_debug.o
+endif
 
 CFLAGS_config.o   += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
+# avoid compiler warnings in 32-bit mode
+CFLAGS_genelf_debug.o  += -Wno-packed
 
 $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
        $(call rule_mkdir)
index 360fda01f3b0d17369254d03fe16daf24f30c698..ec164fe70718df1480b02733d8701c7ab2b74297 100644 (file)
@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap)
                         heap_array[last].ordinal);
 }
 
-size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr)
+size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
+                                      struct perf_evlist *evlist)
 {
        if (itr)
-               return itr->info_priv_size(itr);
+               return itr->info_priv_size(itr, evlist);
        return 0;
 }
 
@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
        int err;
 
        pr_debug2("Synthesizing auxtrace information\n");
-       priv_size = auxtrace_record__info_priv_size(itr);
+       priv_size = auxtrace_record__info_priv_size(itr, session->evlist);
        ev = zalloc(sizeof(struct auxtrace_info_event) + priv_size);
        if (!ev)
                return -ENOMEM;
index b86f90db1352a6c8635e3ea5d02aa3c21bccc323..e5a8e2d4f2af4e9b717be7ce27c587f569983027 100644 (file)
@@ -293,7 +293,8 @@ struct auxtrace_record {
        int (*recording_options)(struct auxtrace_record *itr,
                                 struct perf_evlist *evlist,
                                 struct record_opts *opts);
-       size_t (*info_priv_size)(struct auxtrace_record *itr);
+       size_t (*info_priv_size)(struct auxtrace_record *itr,
+                                struct perf_evlist *evlist);
        int (*info_fill)(struct auxtrace_record *itr,
                         struct perf_session *session,
                         struct auxtrace_info_event *auxtrace_info,
@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
 int auxtrace_record__options(struct auxtrace_record *itr,
                             struct perf_evlist *evlist,
                             struct record_opts *opts);
-size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr);
+size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
+                                      struct perf_evlist *evlist);
 int auxtrace_record__info_fill(struct auxtrace_record *itr,
                               struct perf_session *session,
                               struct auxtrace_info_event *auxtrace_info,
index 540a7efa657ea8668eeddf1b476bbcb3c0490bbc..0967ce601931685ed294827e8aef7c30c47736c6 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/bpf.h>
 #include <bpf/libbpf.h>
+#include <bpf/bpf.h>
 #include <linux/err.h>
 #include <linux/string.h>
 #include "perf.h"
@@ -16,6 +17,7 @@
 #include "llvm-utils.h"
 #include "probe-event.h"
 #include "probe-finder.h" // for MAX_PROBES
+#include "parse-events.h"
 #include "llvm-utils.h"
 
 #define DEFINE_PRINT_FN(name, level) \
@@ -108,8 +110,8 @@ void bpf__clear(void)
 }
 
 static void
-bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused,
-                    void *_priv)
+clear_prog_priv(struct bpf_program *prog __maybe_unused,
+               void *_priv)
 {
        struct bpf_prog_priv *priv = _priv;
 
@@ -337,7 +339,7 @@ config_bpf_program(struct bpf_program *prog)
        }
        pr_debug("bpf: config '%s' is ok\n", config_str);
 
-       err = bpf_program__set_private(prog, priv, bpf_prog_priv__clear);
+       err = bpf_program__set_private(prog, priv, clear_prog_priv);
        if (err) {
                pr_debug("Failed to set priv for program '%s'\n", config_str);
                goto errout;
@@ -739,6 +741,682 @@ int bpf__foreach_tev(struct bpf_object *obj,
        return 0;
 }
 
+enum bpf_map_op_type {
+       BPF_MAP_OP_SET_VALUE,
+       BPF_MAP_OP_SET_EVSEL,
+};
+
+enum bpf_map_key_type {
+       BPF_MAP_KEY_ALL,
+       BPF_MAP_KEY_RANGES,
+};
+
+struct bpf_map_op {
+       struct list_head list;
+       enum bpf_map_op_type op_type;
+       enum bpf_map_key_type key_type;
+       union {
+               struct parse_events_array array;
+       } k;
+       union {
+               u64 value;
+               struct perf_evsel *evsel;
+       } v;
+};
+
+struct bpf_map_priv {
+       struct list_head ops_list;
+};
+
+static void
+bpf_map_op__delete(struct bpf_map_op *op)
+{
+       if (!list_empty(&op->list))
+               list_del(&op->list);
+       if (op->key_type == BPF_MAP_KEY_RANGES)
+               parse_events__clear_array(&op->k.array);
+       free(op);
+}
+
+static void
+bpf_map_priv__purge(struct bpf_map_priv *priv)
+{
+       struct bpf_map_op *pos, *n;
+
+       list_for_each_entry_safe(pos, n, &priv->ops_list, list) {
+               list_del_init(&pos->list);
+               bpf_map_op__delete(pos);
+       }
+}
+
+static void
+bpf_map_priv__clear(struct bpf_map *map __maybe_unused,
+                   void *_priv)
+{
+       struct bpf_map_priv *priv = _priv;
+
+       bpf_map_priv__purge(priv);
+       free(priv);
+}
+
+static int
+bpf_map_op_setkey(struct bpf_map_op *op, struct parse_events_term *term)
+{
+       op->key_type = BPF_MAP_KEY_ALL;
+       if (!term)
+               return 0;
+
+       if (term->array.nr_ranges) {
+               size_t memsz = term->array.nr_ranges *
+                               sizeof(op->k.array.ranges[0]);
+
+               op->k.array.ranges = memdup(term->array.ranges, memsz);
+               if (!op->k.array.ranges) {
+                       pr_debug("No enough memory to alloc indices for map\n");
+                       return -ENOMEM;
+               }
+               op->key_type = BPF_MAP_KEY_RANGES;
+               op->k.array.nr_ranges = term->array.nr_ranges;
+       }
+       return 0;
+}
+
+static struct bpf_map_op *
+bpf_map_op__new(struct parse_events_term *term)
+{
+       struct bpf_map_op *op;
+       int err;
+
+       op = zalloc(sizeof(*op));
+       if (!op) {
+               pr_debug("Failed to alloc bpf_map_op\n");
+               return ERR_PTR(-ENOMEM);
+       }
+       INIT_LIST_HEAD(&op->list);
+
+       err = bpf_map_op_setkey(op, term);
+       if (err) {
+               free(op);
+               return ERR_PTR(err);
+       }
+       return op;
+}
+
+static int
+bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
+{
+       struct bpf_map_priv *priv;
+       const char *map_name;
+       int err;
+
+       map_name = bpf_map__get_name(map);
+       err = bpf_map__get_private(map, (void **)&priv);
+       if (err) {
+               pr_debug("Failed to get private from map %s\n", map_name);
+               return err;
+       }
+
+       if (!priv) {
+               priv = zalloc(sizeof(*priv));
+               if (!priv) {
+                       pr_debug("No enough memory to alloc map private\n");
+                       return -ENOMEM;
+               }
+               INIT_LIST_HEAD(&priv->ops_list);
+
+               if (bpf_map__set_private(map, priv, bpf_map_priv__clear)) {
+                       free(priv);
+                       return -BPF_LOADER_ERRNO__INTERNAL;
+               }
+       }
+
+       list_add_tail(&op->list, &priv->ops_list);
+       return 0;
+}
+
+static struct bpf_map_op *
+bpf_map__add_newop(struct bpf_map *map, struct parse_events_term *term)
+{
+       struct bpf_map_op *op;
+       int err;
+
+       op = bpf_map_op__new(term);
+       if (IS_ERR(op))
+               return op;
+
+       err = bpf_map__add_op(map, op);
+       if (err) {
+               bpf_map_op__delete(op);
+               return ERR_PTR(err);
+       }
+       return op;
+}
+
+static int
+__bpf_map__config_value(struct bpf_map *map,
+                       struct parse_events_term *term)
+{
+       struct bpf_map_def def;
+       struct bpf_map_op *op;
+       const char *map_name;
+       int err;
+
+       map_name = bpf_map__get_name(map);
+
+       err = bpf_map__get_def(map, &def);
+       if (err) {
+               pr_debug("Unable to get map definition from '%s'\n",
+                        map_name);
+               return -BPF_LOADER_ERRNO__INTERNAL;
+       }
+
+       if (def.type != BPF_MAP_TYPE_ARRAY) {
+               pr_debug("Map %s type is not BPF_MAP_TYPE_ARRAY\n",
+                        map_name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
+       }
+       if (def.key_size < sizeof(unsigned int)) {
+               pr_debug("Map %s has incorrect key size\n", map_name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE;
+       }
+       switch (def.value_size) {
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+               break;
+       default:
+               pr_debug("Map %s has incorrect value size\n", map_name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE;
+       }
+
+       op = bpf_map__add_newop(map, term);
+       if (IS_ERR(op))
+               return PTR_ERR(op);
+       op->op_type = BPF_MAP_OP_SET_VALUE;
+       op->v.value = term->val.num;
+       return 0;
+}
+
+static int
+bpf_map__config_value(struct bpf_map *map,
+                     struct parse_events_term *term,
+                     struct perf_evlist *evlist __maybe_unused)
+{
+       if (!term->err_val) {
+               pr_debug("Config value not set\n");
+               return -BPF_LOADER_ERRNO__OBJCONF_CONF;
+       }
+
+       if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) {
+               pr_debug("ERROR: wrong value type for 'value'\n");
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE;
+       }
+
+       return __bpf_map__config_value(map, term);
+}
+
+static int
+__bpf_map__config_event(struct bpf_map *map,
+                       struct parse_events_term *term,
+                       struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel;
+       struct bpf_map_def def;
+       struct bpf_map_op *op;
+       const char *map_name;
+       int err;
+
+       map_name = bpf_map__get_name(map);
+       evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str);
+       if (!evsel) {
+               pr_debug("Event (for '%s') '%s' doesn't exist\n",
+                        map_name, term->val.str);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT;
+       }
+
+       err = bpf_map__get_def(map, &def);
+       if (err) {
+               pr_debug("Unable to get map definition from '%s'\n",
+                        map_name);
+               return err;
+       }
+
+       /*
+        * No need to check key_size and value_size:
+        * kernel has already checked them.
+        */
+       if (def.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
+               pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n",
+                        map_name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
+       }
+
+       op = bpf_map__add_newop(map, term);
+       if (IS_ERR(op))
+               return PTR_ERR(op);
+       op->op_type = BPF_MAP_OP_SET_EVSEL;
+       op->v.evsel = evsel;
+       return 0;
+}
+
+static int
+bpf_map__config_event(struct bpf_map *map,
+                     struct parse_events_term *term,
+                     struct perf_evlist *evlist)
+{
+       if (!term->err_val) {
+               pr_debug("Config value not set\n");
+               return -BPF_LOADER_ERRNO__OBJCONF_CONF;
+       }
+
+       if (term->type_val != PARSE_EVENTS__TERM_TYPE_STR) {
+               pr_debug("ERROR: wrong value type for 'event'\n");
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE;
+       }
+
+       return __bpf_map__config_event(map, term, evlist);
+}
+
+struct bpf_obj_config__map_func {
+       const char *config_opt;
+       int (*config_func)(struct bpf_map *, struct parse_events_term *,
+                          struct perf_evlist *);
+};
+
+struct bpf_obj_config__map_func bpf_obj_config__map_funcs[] = {
+       {"value", bpf_map__config_value},
+       {"event", bpf_map__config_event},
+};
+
+static int
+config_map_indices_range_check(struct parse_events_term *term,
+                              struct bpf_map *map,
+                              const char *map_name)
+{
+       struct parse_events_array *array = &term->array;
+       struct bpf_map_def def;
+       unsigned int i;
+       int err;
+
+       if (!array->nr_ranges)
+               return 0;
+       if (!array->ranges) {
+               pr_debug("ERROR: map %s: array->nr_ranges is %d but range array is NULL\n",
+                        map_name, (int)array->nr_ranges);
+               return -BPF_LOADER_ERRNO__INTERNAL;
+       }
+
+       err = bpf_map__get_def(map, &def);
+       if (err) {
+               pr_debug("ERROR: Unable to get map definition from '%s'\n",
+                        map_name);
+               return -BPF_LOADER_ERRNO__INTERNAL;
+       }
+
+       for (i = 0; i < array->nr_ranges; i++) {
+               unsigned int start = array->ranges[i].start;
+               size_t length = array->ranges[i].length;
+               unsigned int idx = start + length - 1;
+
+               if (idx >= def.max_entries) {
+                       pr_debug("ERROR: index %d too large\n", idx);
+                       return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG;
+               }
+       }
+       return 0;
+}
+
+static int
+bpf__obj_config_map(struct bpf_object *obj,
+                   struct parse_events_term *term,
+                   struct perf_evlist *evlist,
+                   int *key_scan_pos)
+{
+       /* key is "map:<mapname>.<config opt>" */
+       char *map_name = strdup(term->config + sizeof("map:") - 1);
+       struct bpf_map *map;
+       int err = -BPF_LOADER_ERRNO__OBJCONF_OPT;
+       char *map_opt;
+       size_t i;
+
+       if (!map_name)
+               return -ENOMEM;
+
+       map_opt = strchr(map_name, '.');
+       if (!map_opt) {
+               pr_debug("ERROR: Invalid map config: %s\n", map_name);
+               goto out;
+       }
+
+       *map_opt++ = '\0';
+       if (*map_opt == '\0') {
+               pr_debug("ERROR: Invalid map option: %s\n", term->config);
+               goto out;
+       }
+
+       map = bpf_object__get_map_by_name(obj, map_name);
+       if (!map) {
+               pr_debug("ERROR: Map %s doesn't exist\n", map_name);
+               err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST;
+               goto out;
+       }
+
+       *key_scan_pos += strlen(map_opt);
+       err = config_map_indices_range_check(term, map, map_name);
+       if (err)
+               goto out;
+       *key_scan_pos -= strlen(map_opt);
+
+       for (i = 0; i < ARRAY_SIZE(bpf_obj_config__map_funcs); i++) {
+               struct bpf_obj_config__map_func *func =
+                               &bpf_obj_config__map_funcs[i];
+
+               if (strcmp(map_opt, func->config_opt) == 0) {
+                       err = func->config_func(map, term, evlist);
+                       goto out;
+               }
+       }
+
+       pr_debug("ERROR: Invalid map config option '%s'\n", map_opt);
+       err = -BPF_LOADER_ERRNO__OBJCONF_MAP_OPT;
+out:
+       free(map_name);
+       if (!err)
+               key_scan_pos += strlen(map_opt);
+       return err;
+}
+
+int bpf__config_obj(struct bpf_object *obj,
+                   struct parse_events_term *term,
+                   struct perf_evlist *evlist,
+                   int *error_pos)
+{
+       int key_scan_pos = 0;
+       int err;
+
+       if (!obj || !term || !term->config)
+               return -EINVAL;
+
+       if (!prefixcmp(term->config, "map:")) {
+               key_scan_pos = sizeof("map:") - 1;
+               err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos);
+               goto out;
+       }
+       err = -BPF_LOADER_ERRNO__OBJCONF_OPT;
+out:
+       if (error_pos)
+               *error_pos = key_scan_pos;
+       return err;
+
+}
+
+typedef int (*map_config_func_t)(const char *name, int map_fd,
+                                struct bpf_map_def *pdef,
+                                struct bpf_map_op *op,
+                                void *pkey, void *arg);
+
+static int
+foreach_key_array_all(map_config_func_t func,
+                     void *arg, const char *name,
+                     int map_fd, struct bpf_map_def *pdef,
+                     struct bpf_map_op *op)
+{
+       unsigned int i;
+       int err;
+
+       for (i = 0; i < pdef->max_entries; i++) {
+               err = func(name, map_fd, pdef, op, &i, arg);
+               if (err) {
+                       pr_debug("ERROR: failed to insert value to %s[%u]\n",
+                                name, i);
+                       return err;
+               }
+       }
+       return 0;
+}
+
+static int
+foreach_key_array_ranges(map_config_func_t func, void *arg,
+                        const char *name, int map_fd,
+                        struct bpf_map_def *pdef,
+                        struct bpf_map_op *op)
+{
+       unsigned int i, j;
+       int err;
+
+       for (i = 0; i < op->k.array.nr_ranges; i++) {
+               unsigned int start = op->k.array.ranges[i].start;
+               size_t length = op->k.array.ranges[i].length;
+
+               for (j = 0; j < length; j++) {
+                       unsigned int idx = start + j;
+
+                       err = func(name, map_fd, pdef, op, &idx, arg);
+                       if (err) {
+                               pr_debug("ERROR: failed to insert value to %s[%u]\n",
+                                        name, idx);
+                               return err;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int
+bpf_map_config_foreach_key(struct bpf_map *map,
+                          map_config_func_t func,
+                          void *arg)
+{
+       int err, map_fd;
+       const char *name;
+       struct bpf_map_op *op;
+       struct bpf_map_def def;
+       struct bpf_map_priv *priv;
+
+       name = bpf_map__get_name(map);
+
+       err = bpf_map__get_private(map, (void **)&priv);
+       if (err) {
+               pr_debug("ERROR: failed to get private from map %s\n", name);
+               return -BPF_LOADER_ERRNO__INTERNAL;
+       }
+       if (!priv || list_empty(&priv->ops_list)) {
+               pr_debug("INFO: nothing to config for map %s\n", name);
+               return 0;
+       }
+
+       err = bpf_map__get_def(map, &def);
+       if (err) {
+               pr_debug("ERROR: failed to get definition from map %s\n", name);
+               return -BPF_LOADER_ERRNO__INTERNAL;
+       }
+       map_fd = bpf_map__get_fd(map);
+       if (map_fd < 0) {
+               pr_debug("ERROR: failed to get fd from map %s\n", name);
+               return map_fd;
+       }
+
+       list_for_each_entry(op, &priv->ops_list, list) {
+               switch (def.type) {
+               case BPF_MAP_TYPE_ARRAY:
+               case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
+                       switch (op->key_type) {
+                       case BPF_MAP_KEY_ALL:
+                               err = foreach_key_array_all(func, arg, name,
+                                                           map_fd, &def, op);
+                               break;
+                       case BPF_MAP_KEY_RANGES:
+                               err = foreach_key_array_ranges(func, arg, name,
+                                                              map_fd, &def,
+                                                              op);
+                               break;
+                       default:
+                               pr_debug("ERROR: keytype for map '%s' invalid\n",
+                                        name);
+                               return -BPF_LOADER_ERRNO__INTERNAL;
+                       }
+                       if (err)
+                               return err;
+                       break;
+               default:
+                       pr_debug("ERROR: type of '%s' incorrect\n", name);
+                       return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
+               }
+       }
+
+       return 0;
+}
+
+static int
+apply_config_value_for_key(int map_fd, void *pkey,
+                          size_t val_size, u64 val)
+{
+       int err = 0;
+
+       switch (val_size) {
+       case 1: {
+               u8 _val = (u8)(val);
+               err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY);
+               break;
+       }
+       case 2: {
+               u16 _val = (u16)(val);
+               err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY);
+               break;
+       }
+       case 4: {
+               u32 _val = (u32)(val);
+               err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY);
+               break;
+       }
+       case 8: {
+               err = bpf_map_update_elem(map_fd, pkey, &val, BPF_ANY);
+               break;
+       }
+       default:
+               pr_debug("ERROR: invalid value size\n");
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE;
+       }
+       if (err && errno)
+               err = -errno;
+       return err;
+}
+
+static int
+apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
+                          struct perf_evsel *evsel)
+{
+       struct xyarray *xy = evsel->fd;
+       struct perf_event_attr *attr;
+       unsigned int key, events;
+       bool check_pass = false;
+       int *evt_fd;
+       int err;
+
+       if (!xy) {
+               pr_debug("ERROR: evsel not ready for map %s\n", name);
+               return -BPF_LOADER_ERRNO__INTERNAL;
+       }
+
+       if (xy->row_size / xy->entry_size != 1) {
+               pr_debug("ERROR: Dimension of target event is incorrect for map %s\n",
+                        name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM;
+       }
+
+       attr = &evsel->attr;
+       if (attr->inherit) {
+               pr_debug("ERROR: Can't put inherit event into map %s\n", name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH;
+       }
+
+       if (perf_evsel__is_bpf_output(evsel))
+               check_pass = true;
+       if (attr->type == PERF_TYPE_RAW)
+               check_pass = true;
+       if (attr->type == PERF_TYPE_HARDWARE)
+               check_pass = true;
+       if (!check_pass) {
+               pr_debug("ERROR: Event type is wrong for map %s\n", name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE;
+       }
+
+       events = xy->entries / (xy->row_size / xy->entry_size);
+       key = *((unsigned int *)pkey);
+       if (key >= events) {
+               pr_debug("ERROR: there is no event %d for map %s\n",
+                        key, name);
+               return -BPF_LOADER_ERRNO__OBJCONF_MAP_MAPSIZE;
+       }
+       evt_fd = xyarray__entry(xy, key, 0);
+       err = bpf_map_update_elem(map_fd, pkey, evt_fd, BPF_ANY);
+       if (err && errno)
+               err = -errno;
+       return err;
+}
+
+static int
+apply_obj_config_map_for_key(const char *name, int map_fd,
+                            struct bpf_map_def *pdef __maybe_unused,
+                            struct bpf_map_op *op,
+                            void *pkey, void *arg __maybe_unused)
+{
+       int err;
+
+       switch (op->op_type) {
+       case BPF_MAP_OP_SET_VALUE:
+               err = apply_config_value_for_key(map_fd, pkey,
+                                                pdef->value_size,
+                                                op->v.value);
+               break;
+       case BPF_MAP_OP_SET_EVSEL:
+               err = apply_config_evsel_for_key(name, map_fd, pkey,
+                                                op->v.evsel);
+               break;
+       default:
+               pr_debug("ERROR: unknown value type for '%s'\n", name);
+               err = -BPF_LOADER_ERRNO__INTERNAL;
+       }
+       return err;
+}
+
+static int
+apply_obj_config_map(struct bpf_map *map)
+{
+       return bpf_map_config_foreach_key(map,
+                                         apply_obj_config_map_for_key,
+                                         NULL);
+}
+
+static int
+apply_obj_config_object(struct bpf_object *obj)
+{
+       struct bpf_map *map;
+       int err;
+
+       bpf_map__for_each(map, obj) {
+               err = apply_obj_config_map(map);
+               if (err)
+                       return err;
+       }
+       return 0;
+}
+
+int bpf__apply_obj_config(void)
+{
+       struct bpf_object *obj, *tmp;
+       int err;
+
+       bpf_object__for_each_safe(obj, tmp) {
+               err = apply_obj_config_object(obj);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 #define ERRNO_OFFSET(e)                ((e) - __BPF_LOADER_ERRNO__START)
 #define ERRCODE_OFFSET(c)      ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
 #define NR_ERRNO       (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
@@ -753,6 +1431,20 @@ static const char *bpf_loader_strerror_table[NR_ERRNO] = {
        [ERRCODE_OFFSET(PROLOGUE)]      = "Failed to generate prologue",
        [ERRCODE_OFFSET(PROLOGUE2BIG)]  = "Prologue too big for program",
        [ERRCODE_OFFSET(PROLOGUEOOB)]   = "Offset out of bound for prologue",
+       [ERRCODE_OFFSET(OBJCONF_OPT)]   = "Invalid object config option",
+       [ERRCODE_OFFSET(OBJCONF_CONF)]  = "Config value not set (missing '=')",
+       [ERRCODE_OFFSET(OBJCONF_MAP_OPT)]       = "Invalid object map config option",
+       [ERRCODE_OFFSET(OBJCONF_MAP_NOTEXIST)]  = "Target map doesn't exist",
+       [ERRCODE_OFFSET(OBJCONF_MAP_VALUE)]     = "Incorrect value type for map",
+       [ERRCODE_OFFSET(OBJCONF_MAP_TYPE)]      = "Incorrect map type",
+       [ERRCODE_OFFSET(OBJCONF_MAP_KEYSIZE)]   = "Incorrect map key size",
+       [ERRCODE_OFFSET(OBJCONF_MAP_VALUESIZE)] = "Incorrect map value size",
+       [ERRCODE_OFFSET(OBJCONF_MAP_NOEVT)]     = "Event not found for map setting",
+       [ERRCODE_OFFSET(OBJCONF_MAP_MAPSIZE)]   = "Invalid map size for event setting",
+       [ERRCODE_OFFSET(OBJCONF_MAP_EVTDIM)]    = "Event dimension too large",
+       [ERRCODE_OFFSET(OBJCONF_MAP_EVTINH)]    = "Doesn't support inherit event",
+       [ERRCODE_OFFSET(OBJCONF_MAP_EVTTYPE)]   = "Wrong event type for map",
+       [ERRCODE_OFFSET(OBJCONF_MAP_IDX2BIG)]   = "Index too large",
 };
 
 static int
@@ -872,3 +1564,29 @@ int bpf__strerror_load(struct bpf_object *obj,
        bpf__strerror_end(buf, size);
        return 0;
 }
+
+int bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
+                            struct parse_events_term *term __maybe_unused,
+                            struct perf_evlist *evlist __maybe_unused,
+                            int *error_pos __maybe_unused, int err,
+                            char *buf, size_t size)
+{
+       bpf__strerror_head(err, buf, size);
+       bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE,
+                           "Can't use this config term with this map type");
+       bpf__strerror_end(buf, size);
+       return 0;
+}
+
+int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
+{
+       bpf__strerror_head(err, buf, size);
+       bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM,
+                           "Cannot set event to BPF map in multi-thread tracing");
+       bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH,
+                           "%s (Hint: use -i to turn off inherit)", emsg);
+       bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE,
+                           "Can only put raw, hardware and BPF output event into a BPF map");
+       bpf__strerror_end(buf, size);
+       return 0;
+}
index 6fdc0457e2b66ea3fedd8e26c4a0e8f6a4bcc6e2..be4311944e3daa2abc87cdd54be72ed7bce70682 100644 (file)
@@ -10,6 +10,7 @@
 #include <string.h>
 #include <bpf/libbpf.h>
 #include "probe-event.h"
+#include "evlist.h"
 #include "debug.h"
 
 enum bpf_loader_errno {
@@ -24,10 +25,25 @@ enum bpf_loader_errno {
        BPF_LOADER_ERRNO__PROLOGUE,     /* Failed to generate prologue */
        BPF_LOADER_ERRNO__PROLOGUE2BIG, /* Prologue too big for program */
        BPF_LOADER_ERRNO__PROLOGUEOOB,  /* Offset out of bound for prologue */
+       BPF_LOADER_ERRNO__OBJCONF_OPT,  /* Invalid object config option */
+       BPF_LOADER_ERRNO__OBJCONF_CONF, /* Config value not set (lost '=')) */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_OPT,      /* Invalid object map config option */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST, /* Target map not exist */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE,    /* Incorrect value type for map */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE,     /* Incorrect map type */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE,  /* Incorrect map key size */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE,/* Incorrect map value size */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT,    /* Event not found for map setting */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_MAPSIZE,  /* Invalid map size for event setting */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM,   /* Event dimension too large */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH,   /* Doesn't support inherit event */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE,  /* Wrong event type for map */
+       BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG,  /* Index too large */
        __BPF_LOADER_ERRNO__END,
 };
 
 struct bpf_object;
+struct parse_events_term;
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
 
 typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
@@ -53,6 +69,16 @@ int bpf__strerror_load(struct bpf_object *obj, int err,
                       char *buf, size_t size);
 int bpf__foreach_tev(struct bpf_object *obj,
                     bpf_prog_iter_callback_t func, void *arg);
+
+int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term,
+                   struct perf_evlist *evlist, int *error_pos);
+int bpf__strerror_config_obj(struct bpf_object *obj,
+                            struct parse_events_term *term,
+                            struct perf_evlist *evlist,
+                            int *error_pos, int err, char *buf,
+                            size_t size);
+int bpf__apply_obj_config(void);
+int bpf__strerror_apply_obj_config(int err, char *buf, size_t size);
 #else
 static inline struct bpf_object *
 bpf__prepare_load(const char *filename __maybe_unused,
@@ -83,6 +109,21 @@ bpf__foreach_tev(struct bpf_object *obj __maybe_unused,
        return 0;
 }
 
+static inline int
+bpf__config_obj(struct bpf_object *obj __maybe_unused,
+               struct parse_events_term *term __maybe_unused,
+               struct perf_evlist *evlist __maybe_unused,
+               int *error_pos __maybe_unused)
+{
+       return 0;
+}
+
+static inline int
+bpf__apply_obj_config(void)
+{
+       return 0;
+}
+
 static inline int
 __bpf_strerror(char *buf, size_t size)
 {
@@ -118,5 +159,23 @@ static inline int bpf__strerror_load(struct bpf_object *obj __maybe_unused,
 {
        return __bpf_strerror(buf, size);
 }
+
+static inline int
+bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
+                        struct parse_events_term *term __maybe_unused,
+                        struct perf_evlist *evlist __maybe_unused,
+                        int *error_pos __maybe_unused,
+                        int err __maybe_unused,
+                        char *buf, size_t size)
+{
+       return __bpf_strerror(buf, size);
+}
+
+static inline int
+bpf__strerror_apply_obj_config(int err __maybe_unused,
+                              char *buf, size_t size)
+{
+       return __bpf_strerror(buf, size);
+}
 #endif
 #endif
index 6a7e273a514a642b30a477c3119696dc7fa09975..f1479eeef7daf9ae2c386abcef7d079a0370c836 100644 (file)
@@ -166,6 +166,50 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
        return build_id__filename(build_id_hex, bf, size);
 }
 
+bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
+{
+       char *id_name, *ch;
+       struct stat sb;
+
+       id_name = dso__build_id_filename(dso, bf, size);
+       if (!id_name)
+               goto err;
+       if (access(id_name, F_OK))
+               goto err;
+       if (lstat(id_name, &sb) == -1)
+               goto err;
+       if ((size_t)sb.st_size > size - 1)
+               goto err;
+       if (readlink(id_name, bf, size - 1) < 0)
+               goto err;
+
+       bf[sb.st_size] = '\0';
+
+       /*
+        * link should be:
+        * ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92
+        */
+       ch = strrchr(bf, '/');
+       if (!ch)
+               goto err;
+       if (ch - 3 < bf)
+               goto err;
+
+       return strncmp(".ko", ch - 3, 3) == 0;
+err:
+       /*
+        * If dso__build_id_filename work, get id_name again,
+        * because id_name points to bf and is broken.
+        */
+       if (id_name)
+               id_name = dso__build_id_filename(dso, bf, size);
+       pr_err("Invalid build id: %s\n", id_name ? :
+                                        dso->long_name ? :
+                                        dso->short_name ? :
+                                        "[unknown]");
+       return false;
+}
+
 #define dsos__for_each_with_build_id(pos, head)        \
        list_for_each_entry(pos, head, node)    \
                if (!pos->has_build_id)         \
@@ -211,6 +255,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
        dsos__for_each_with_build_id(pos, &machine->dsos.head) {
                const char *name;
                size_t name_len;
+               bool in_kernel = false;
 
                if (!pos->hit)
                        continue;
@@ -227,8 +272,11 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
                        name_len = pos->long_name_len + 1;
                }
 
+               in_kernel = pos->kernel ||
+                               is_kernel_module(name,
+                                       PERF_RECORD_MISC_CPUMODE_UNKNOWN);
                err = write_buildid(name, name_len, pos->build_id, machine->pid,
-                                   pos->kernel ? kmisc : umisc, fd);
+                                   in_kernel ? kmisc : umisc, fd);
                if (err)
                        break;
        }
index 27a14a8a945beb8eec9cc389ca7d6545b44a2ac4..64af3e20610d7718ecacfad3810fc4bff4ee882d 100644 (file)
@@ -16,6 +16,7 @@ int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
 int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
 
 char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
+bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size);
 
 int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
                           struct perf_sample *sample, struct perf_evsel *evsel,
index 07b5d63947b11ec5f70029c6e41266e56b2bd8aa..3ca453f0c51f6f5b269f84270e78132e45f9768c 100644 (file)
@@ -23,6 +23,8 @@
 #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
 #define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
 
+extern const char *config_exclusive_filename;
+
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int perf_default_config(const char *, const char *, void *);
 extern int perf_config(config_fn_t fn, void *);
@@ -31,6 +33,7 @@ extern u64 perf_config_u64(const char *, const char *);
 extern int perf_config_bool(const char *, const char *);
 extern int config_error_nonbool(const char *);
 extern const char *perf_config_dirname(const char *, const char *);
+extern const char *perf_etc_perfconfig(void);
 
 char *alias_lookup(const char *alias);
 int split_cmdline(char *cmdline, const char ***argv);
index 53c43eb9489e4ba4a4e56a795bc05c2b85fb4cbc..24b4bd0d77545e7bb9f95e83222eb103c92f5151 100644 (file)
@@ -416,7 +416,7 @@ create_child(struct callchain_node *parent, bool inherit_children)
 /*
  * Fill the node with callchain values
  */
-static void
+static int
 fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
 {
        struct callchain_cursor_node *cursor_node;
@@ -433,7 +433,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
                call = zalloc(sizeof(*call));
                if (!call) {
                        perror("not enough memory for the code path tree");
-                       return;
+                       return -1;
                }
                call->ip = cursor_node->ip;
                call->ms.sym = cursor_node->sym;
@@ -443,6 +443,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
                callchain_cursor_advance(cursor);
                cursor_node = callchain_cursor_current(cursor);
        }
+       return 0;
 }
 
 static struct callchain_node *
@@ -453,7 +454,19 @@ add_child(struct callchain_node *parent,
        struct callchain_node *new;
 
        new = create_child(parent, false);
-       fill_node(new, cursor);
+       if (new == NULL)
+               return NULL;
+
+       if (fill_node(new, cursor) < 0) {
+               struct callchain_list *call, *tmp;
+
+               list_for_each_entry_safe(call, tmp, &new->val, list) {
+                       list_del(&call->list);
+                       free(call);
+               }
+               free(new);
+               return NULL;
+       }
 
        new->children_hit = 0;
        new->hit = period;
@@ -462,16 +475,32 @@ add_child(struct callchain_node *parent,
        return new;
 }
 
-static s64 match_chain(struct callchain_cursor_node *node,
-                     struct callchain_list *cnode)
+enum match_result {
+       MATCH_ERROR  = -1,
+       MATCH_EQ,
+       MATCH_LT,
+       MATCH_GT,
+};
+
+static enum match_result match_chain(struct callchain_cursor_node *node,
+                                    struct callchain_list *cnode)
 {
        struct symbol *sym = node->sym;
+       u64 left, right;
 
        if (cnode->ms.sym && sym &&
-           callchain_param.key == CCKEY_FUNCTION)
-               return cnode->ms.sym->start - sym->start;
-       else
-               return cnode->ip - node->ip;
+           callchain_param.key == CCKEY_FUNCTION) {
+               left = cnode->ms.sym->start;
+               right = sym->start;
+       } else {
+               left = cnode->ip;
+               right = node->ip;
+       }
+
+       if (left == right)
+               return MATCH_EQ;
+
+       return left > right ? MATCH_GT : MATCH_LT;
 }
 
 /*
@@ -479,7 +508,7 @@ static s64 match_chain(struct callchain_cursor_node *node,
  * give a part of its callchain to the created child.
  * Then create another child to host the given callchain of new branch
  */
-static void
+static int
 split_add_child(struct callchain_node *parent,
                struct callchain_cursor *cursor,
                struct callchain_list *to_split,
@@ -491,6 +520,8 @@ split_add_child(struct callchain_node *parent,
 
        /* split */
        new = create_child(parent, true);
+       if (new == NULL)
+               return -1;
 
        /* split the callchain and move a part to the new child */
        old_tail = parent->val.prev;
@@ -524,6 +555,8 @@ split_add_child(struct callchain_node *parent,
 
                node = callchain_cursor_current(cursor);
                new = add_child(parent, cursor, period);
+               if (new == NULL)
+                       return -1;
 
                /*
                 * This is second child since we moved parent's children
@@ -534,7 +567,7 @@ split_add_child(struct callchain_node *parent,
                cnode = list_first_entry(&first->val, struct callchain_list,
                                         list);
 
-               if (match_chain(node, cnode) < 0)
+               if (match_chain(node, cnode) == MATCH_LT)
                        pp = &p->rb_left;
                else
                        pp = &p->rb_right;
@@ -545,14 +578,15 @@ split_add_child(struct callchain_node *parent,
                parent->hit = period;
                parent->count = 1;
        }
+       return 0;
 }
 
-static int
+static enum match_result
 append_chain(struct callchain_node *root,
             struct callchain_cursor *cursor,
             u64 period);
 
-static void
+static int
 append_chain_children(struct callchain_node *root,
                      struct callchain_cursor *cursor,
                      u64 period)
@@ -564,36 +598,42 @@ append_chain_children(struct callchain_node *root,
 
        node = callchain_cursor_current(cursor);
        if (!node)
-               return;
+               return -1;
 
        /* lookup in childrens */
        while (*p) {
-               s64 ret;
+               enum match_result ret;
 
                parent = *p;
                rnode = rb_entry(parent, struct callchain_node, rb_node_in);
 
                /* If at least first entry matches, rely to children */
                ret = append_chain(rnode, cursor, period);
-               if (ret == 0)
+               if (ret == MATCH_EQ)
                        goto inc_children_hit;
+               if (ret == MATCH_ERROR)
+                       return -1;
 
-               if (ret < 0)
+               if (ret == MATCH_LT)
                        p = &parent->rb_left;
                else
                        p = &parent->rb_right;
        }
        /* nothing in children, add to the current node */
        rnode = add_child(root, cursor, period);
+       if (rnode == NULL)
+               return -1;
+
        rb_link_node(&rnode->rb_node_in, parent, p);
        rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
 
 inc_children_hit:
        root->children_hit += period;
        root->children_count++;
+       return 0;
 }
 
-static int
+static enum match_result
 append_chain(struct callchain_node *root,
             struct callchain_cursor *cursor,
             u64 period)
@@ -602,7 +642,7 @@ append_chain(struct callchain_node *root,
        u64 start = cursor->pos;
        bool found = false;
        u64 matches;
-       int cmp = 0;
+       enum match_result cmp = MATCH_ERROR;
 
        /*
         * Lookup in the current node
@@ -618,7 +658,7 @@ append_chain(struct callchain_node *root,
                        break;
 
                cmp = match_chain(node, cnode);
-               if (cmp)
+               if (cmp != MATCH_EQ)
                        break;
 
                found = true;
@@ -628,7 +668,7 @@ append_chain(struct callchain_node *root,
 
        /* matches not, relay no the parent */
        if (!found) {
-               WARN_ONCE(!cmp, "Chain comparison error\n");
+               WARN_ONCE(cmp == MATCH_ERROR, "Chain comparison error\n");
                return cmp;
        }
 
@@ -636,21 +676,25 @@ append_chain(struct callchain_node *root,
 
        /* we match only a part of the node. Split it and add the new chain */
        if (matches < root->val_nr) {
-               split_add_child(root, cursor, cnode, start, matches, period);
-               return 0;
+               if (split_add_child(root, cursor, cnode, start, matches,
+                                   period) < 0)
+                       return MATCH_ERROR;
+
+               return MATCH_EQ;
        }
 
        /* we match 100% of the path, increment the hit */
        if (matches == root->val_nr && cursor->pos == cursor->nr) {
                root->hit += period;
                root->count++;
-               return 0;
+               return MATCH_EQ;
        }
 
        /* We match the node and still have a part remaining */
-       append_chain_children(root, cursor, period);
+       if (append_chain_children(root, cursor, period) < 0)
+               return MATCH_ERROR;
 
-       return 0;
+       return MATCH_EQ;
 }
 
 int callchain_append(struct callchain_root *root,
@@ -662,7 +706,8 @@ int callchain_append(struct callchain_root *root,
 
        callchain_cursor_commit(cursor);
 
-       append_chain_children(&root->node, cursor, period);
+       if (append_chain_children(&root->node, cursor, period) < 0)
+               return -1;
 
        if (cursor->nr > root->max_depth)
                root->max_depth = cursor->nr;
@@ -690,7 +735,8 @@ merge_chain_branch(struct callchain_cursor *cursor,
 
        if (src->hit) {
                callchain_cursor_commit(cursor);
-               append_chain_children(dst, cursor, src->hit);
+               if (append_chain_children(dst, cursor, src->hit) < 0)
+                       return -1;
        }
 
        n = rb_first(&src->rb_root_in);
index e5fb88bab9e1c416a3c53fe5036f8eb57f64a55d..43e84aa27e4a6489eafdebc3636d8bfb33334e3f 100644 (file)
@@ -32,14 +32,15 @@ int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty)
        return 0;
 }
 
-int perf_color_default_config(const char *var, const char *value, void *cb)
+int perf_color_default_config(const char *var, const char *value,
+                             void *cb __maybe_unused)
 {
        if (!strcmp(var, "color.ui")) {
                perf_use_color_default = perf_config_colorbool(var, value, -1);
                return 0;
        }
 
-       return perf_default_config(var, value, cb);
+       return 0;
 }
 
 static int __color_vsnprintf(char *bf, size_t size, const char *color,
index d3e12e30e1d520f8073d1f01d17e1eaf4ac30254..4e727635476eadf5b105a7be4620f86a4bf46499 100644 (file)
@@ -26,7 +26,7 @@ static const char *config_file_name;
 static int config_linenr;
 static int config_file_eof;
 
-static const char *config_exclusive_filename;
+const char *config_exclusive_filename;
 
 static int get_next_char(void)
 {
@@ -434,7 +434,7 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat
        return ret;
 }
 
-static const char *perf_etc_perfconfig(void)
+const char *perf_etc_perfconfig(void)
 {
        static const char *system_wide;
        if (!system_wide)
index fa935093a599429011fa214c24645fd0230e3b3a..9bcf2bed3a6d1b7369ee4deee7f38e9c4abab06d 100644 (file)
@@ -8,6 +8,10 @@
 #include <linux/bitmap.h>
 #include "asm/bug.h"
 
+static int max_cpu_num;
+static int max_node_num;
+static int *cpunode_map;
+
 static struct cpu_map *cpu_map__default_new(void)
 {
        struct cpu_map *cpus;
@@ -486,6 +490,32 @@ out:
                pr_err("Failed to read max nodes, using default of %d\n", max_node_num);
 }
 
+int cpu__max_node(void)
+{
+       if (unlikely(!max_node_num))
+               set_max_node_num();
+
+       return max_node_num;
+}
+
+int cpu__max_cpu(void)
+{
+       if (unlikely(!max_cpu_num))
+               set_max_cpu_num();
+
+       return max_cpu_num;
+}
+
+int cpu__get_node(int cpu)
+{
+       if (unlikely(cpunode_map == NULL)) {
+               pr_debug("cpu_map not initialized\n");
+               return -1;
+       }
+
+       return cpunode_map[cpu];
+}
+
 static int init_cpunode_map(void)
 {
        int i;
index 71c41b9efabb3b38dd17a7374413985dfd944f77..81a2562aaa2b02261b88c960997238dc9e0925ab 100644 (file)
@@ -57,37 +57,11 @@ static inline bool cpu_map__empty(const struct cpu_map *map)
        return map ? map->map[0] == -1 : true;
 }
 
-int max_cpu_num;
-int max_node_num;
-int *cpunode_map;
-
 int cpu__setup_cpunode_map(void);
 
-static inline int cpu__max_node(void)
-{
-       if (unlikely(!max_node_num))
-               pr_debug("cpu_map not initialized\n");
-
-       return max_node_num;
-}
-
-static inline int cpu__max_cpu(void)
-{
-       if (unlikely(!max_cpu_num))
-               pr_debug("cpu_map not initialized\n");
-
-       return max_cpu_num;
-}
-
-static inline int cpu__get_node(int cpu)
-{
-       if (unlikely(cpunode_map == NULL)) {
-               pr_debug("cpu_map not initialized\n");
-               return -1;
-       }
-
-       return cpunode_map[cpu];
-}
+int cpu__max_node(void);
+int cpu__max_cpu(void);
+int cpu__get_node(int cpu);
 
 int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
                       int (*f)(struct cpu_map *map, int cpu, void *data),
index aada3ac5e891f85be1f4d25791d4ee17dd859077..d4a5a21c2a7e2e47596444665b5f5828874da337 100644 (file)
@@ -31,9 +31,18 @@ unsigned char sane_ctype[256] = {
 };
 
 const char *graph_line =
+       "_____________________________________________________________________"
        "_____________________________________________________________________"
        "_____________________________________________________________________";
 const char *graph_dotted_line =
        "---------------------------------------------------------------------"
        "---------------------------------------------------------------------"
        "---------------------------------------------------------------------";
+const char *spaces =
+       "                                                                     "
+       "                                                                     "
+       "                                                                     ";
+const char *dots =
+       "....................................................................."
+       "....................................................................."
+       ".....................................................................";
index 34cd1e4039d35e05be0460ff0a259e7d8b2bb80a..811af89ce0bb8f37b99898dc8b2a2d5f6e183d26 100644 (file)
@@ -352,6 +352,84 @@ static int add_tracepoint_values(struct ctf_writer *cw,
        return ret;
 }
 
+static int
+add_bpf_output_values(struct bt_ctf_event_class *event_class,
+                     struct bt_ctf_event *event,
+                     struct perf_sample *sample)
+{
+       struct bt_ctf_field_type *len_type, *seq_type;
+       struct bt_ctf_field *len_field, *seq_field;
+       unsigned int raw_size = sample->raw_size;
+       unsigned int nr_elements = raw_size / sizeof(u32);
+       unsigned int i;
+       int ret;
+
+       if (nr_elements * sizeof(u32) != raw_size)
+               pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n",
+                          raw_size, nr_elements * sizeof(u32) - raw_size);
+
+       len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
+       len_field = bt_ctf_field_create(len_type);
+       if (!len_field) {
+               pr_err("failed to create 'raw_len' for bpf output event\n");
+               ret = -1;
+               goto put_len_type;
+       }
+
+       ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
+       if (ret) {
+               pr_err("failed to set field value for raw_len\n");
+               goto put_len_field;
+       }
+       ret = bt_ctf_event_set_payload(event, "raw_len", len_field);
+       if (ret) {
+               pr_err("failed to set payload to raw_len\n");
+               goto put_len_field;
+       }
+
+       seq_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_data");
+       seq_field = bt_ctf_field_create(seq_type);
+       if (!seq_field) {
+               pr_err("failed to create 'raw_data' for bpf output event\n");
+               ret = -1;
+               goto put_seq_type;
+       }
+
+       ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
+       if (ret) {
+               pr_err("failed to set length of 'raw_data'\n");
+               goto put_seq_field;
+       }
+
+       for (i = 0; i < nr_elements; i++) {
+               struct bt_ctf_field *elem_field =
+                       bt_ctf_field_sequence_get_field(seq_field, i);
+
+               ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
+                               ((u32 *)(sample->raw_data))[i]);
+
+               bt_ctf_field_put(elem_field);
+               if (ret) {
+                       pr_err("failed to set raw_data[%d]\n", i);
+                       goto put_seq_field;
+               }
+       }
+
+       ret = bt_ctf_event_set_payload(event, "raw_data", seq_field);
+       if (ret)
+               pr_err("failed to set payload for raw_data\n");
+
+put_seq_field:
+       bt_ctf_field_put(seq_field);
+put_seq_type:
+       bt_ctf_field_type_put(seq_type);
+put_len_field:
+       bt_ctf_field_put(len_field);
+put_len_type:
+       bt_ctf_field_type_put(len_type);
+       return ret;
+}
+
 static int add_generic_values(struct ctf_writer *cw,
                              struct bt_ctf_event *event,
                              struct perf_evsel *evsel,
@@ -597,6 +675,12 @@ static int process_sample_event(struct perf_tool *tool,
                        return -1;
        }
 
+       if (perf_evsel__is_bpf_output(evsel)) {
+               ret = add_bpf_output_values(event_class, event, sample);
+               if (ret)
+                       return -1;
+       }
+
        cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
        if (cs) {
                if (is_flush_needed(cs))
@@ -744,6 +828,25 @@ static int add_tracepoint_types(struct ctf_writer *cw,
        return ret;
 }
 
+static int add_bpf_output_types(struct ctf_writer *cw,
+                               struct bt_ctf_event_class *class)
+{
+       struct bt_ctf_field_type *len_type = cw->data.u32;
+       struct bt_ctf_field_type *seq_base_type = cw->data.u32_hex;
+       struct bt_ctf_field_type *seq_type;
+       int ret;
+
+       ret = bt_ctf_event_class_add_field(class, len_type, "raw_len");
+       if (ret)
+               return ret;
+
+       seq_type = bt_ctf_field_type_sequence_create(seq_base_type, "raw_len");
+       if (!seq_type)
+               return -1;
+
+       return bt_ctf_event_class_add_field(class, seq_type, "raw_data");
+}
+
 static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
                             struct bt_ctf_event_class *event_class)
 {
@@ -755,7 +858,8 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
         *                              ctf event header
         *   PERF_SAMPLE_READ         - TODO
         *   PERF_SAMPLE_CALLCHAIN    - TODO
-        *   PERF_SAMPLE_RAW          - tracepoint fields are handled separately
+        *   PERF_SAMPLE_RAW          - tracepoint fields and BPF output
+        *                              are handled separately
         *   PERF_SAMPLE_BRANCH_STACK - TODO
         *   PERF_SAMPLE_REGS_USER    - TODO
         *   PERF_SAMPLE_STACK_USER   - TODO
@@ -824,6 +928,12 @@ static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
                        goto err;
        }
 
+       if (perf_evsel__is_bpf_output(evsel)) {
+               ret = add_bpf_output_types(cw, event_class);
+               if (ret)
+                       goto err;
+       }
+
        ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
        if (ret) {
                pr("Failed to add event class into stream.\n");
@@ -858,6 +968,23 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
        return 0;
 }
 
+static void cleanup_events(struct perf_session *session)
+{
+       struct perf_evlist *evlist = session->evlist;
+       struct perf_evsel *evsel;
+
+       evlist__for_each(evlist, evsel) {
+               struct evsel_priv *priv;
+
+               priv = evsel->priv;
+               bt_ctf_event_class_put(priv->event_class);
+               zfree(&evsel->priv);
+       }
+
+       perf_evlist__delete(evlist);
+       session->evlist = NULL;
+}
+
 static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
 {
        struct ctf_stream **stream;
@@ -953,6 +1080,12 @@ static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
            bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
                goto err;
 
+#if __BYTE_ORDER == __BIG_ENDIAN
+       bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_BIG_ENDIAN);
+#else
+       bt_ctf_field_type_set_byte_order(type, BT_CTF_BYTE_ORDER_LITTLE_ENDIAN);
+#endif
+
        pr2("Created type: INTEGER %d-bit %ssigned %s\n",
            size, sign ? "un" : "", hex ? "hex" : "");
        return type;
@@ -1100,7 +1233,7 @@ static int convert__config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       return perf_default_config(var, value, cb);
+       return 0;
 }
 
 int bt_convert__perf2ctf(const char *input, const char *path, bool force)
@@ -1171,6 +1304,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
                (double) c.events_size / 1024.0 / 1024.0,
                c.events_count);
 
+       cleanup_events(session);
        perf_session__delete(session);
        ctf_writer__cleanup(cw);
 
index 86d9c73025983d0132a4dddc8607161d713bfbf2..8c4212abd19b48b9e84ca1f9978f06561c05576a 100644 (file)
@@ -5,6 +5,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <api/debug.h>
 
 #include "cache.h"
 #include "color.h"
@@ -22,7 +23,7 @@ int debug_ordered_events;
 static int redirect_to_stderr;
 int debug_data_convert;
 
-static int _eprintf(int level, int var, const char *fmt, va_list args)
+int veprintf(int level, int var, const char *fmt, va_list args)
 {
        int ret = 0;
 
@@ -36,24 +37,19 @@ static int _eprintf(int level, int var, const char *fmt, va_list args)
        return ret;
 }
 
-int veprintf(int level, int var, const char *fmt, va_list args)
-{
-       return _eprintf(level, var, fmt, args);
-}
-
 int eprintf(int level, int var, const char *fmt, ...)
 {
        va_list args;
        int ret;
 
        va_start(args, fmt);
-       ret = _eprintf(level, var, fmt, args);
+       ret = veprintf(level, var, fmt, args);
        va_end(args);
 
        return ret;
 }
 
-static int __eprintf_time(u64 t, const char *fmt, va_list args)
+static int veprintf_time(u64 t, const char *fmt, va_list args)
 {
        int ret = 0;
        u64 secs, usecs, nsecs = t;
@@ -75,7 +71,7 @@ int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
 
        if (var >= level) {
                va_start(args, fmt);
-               ret = __eprintf_time(t, fmt, args);
+               ret = veprintf_time(t, fmt, args);
                va_end(args);
        }
 
@@ -91,7 +87,7 @@ void pr_stat(const char *fmt, ...)
        va_list args;
 
        va_start(args, fmt);
-       _eprintf(1, verbose, fmt, args);
+       veprintf(1, verbose, fmt, args);
        va_end(args);
        eprintf(1, verbose, "\n");
 }
@@ -110,40 +106,61 @@ int dump_printf(const char *fmt, ...)
        return ret;
 }
 
+static void trace_event_printer(enum binary_printer_ops op,
+                               unsigned int val, void *extra)
+{
+       const char *color = PERF_COLOR_BLUE;
+       union perf_event *event = (union perf_event *)extra;
+       unsigned char ch = (unsigned char)val;
+
+       switch (op) {
+       case BINARY_PRINT_DATA_BEGIN:
+               printf(".");
+               color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n",
+                               event->header.size);
+               break;
+       case BINARY_PRINT_LINE_BEGIN:
+               printf(".");
+               break;
+       case BINARY_PRINT_ADDR:
+               color_fprintf(stdout, color, "  %04x: ", val);
+               break;
+       case BINARY_PRINT_NUM_DATA:
+               color_fprintf(stdout, color, " %02x", val);
+               break;
+       case BINARY_PRINT_NUM_PAD:
+               color_fprintf(stdout, color, "   ");
+               break;
+       case BINARY_PRINT_SEP:
+               color_fprintf(stdout, color, "  ");
+               break;
+       case BINARY_PRINT_CHAR_DATA:
+               color_fprintf(stdout, color, "%c",
+                             isprint(ch) ? ch : '.');
+               break;
+       case BINARY_PRINT_CHAR_PAD:
+               color_fprintf(stdout, color, " ");
+               break;
+       case BINARY_PRINT_LINE_END:
+               color_fprintf(stdout, color, "\n");
+               break;
+       case BINARY_PRINT_DATA_END:
+               printf("\n");
+               break;
+       default:
+               break;
+       }
+}
+
 void trace_event(union perf_event *event)
 {
        unsigned char *raw_event = (void *)event;
-       const char *color = PERF_COLOR_BLUE;
-       int i, j;
 
        if (!dump_trace)
                return;
 
-       printf(".");
-       color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n",
-                     event->header.size);
-
-       for (i = 0; i < event->header.size; i++) {
-               if ((i & 15) == 0) {
-                       printf(".");
-                       color_fprintf(stdout, color, "  %04x: ", i);
-               }
-
-               color_fprintf(stdout, color, " %02x", raw_event[i]);
-
-               if (((i & 15) == 15) || i == event->header.size-1) {
-                       color_fprintf(stdout, color, "  ");
-                       for (j = 0; j < 15-(i & 15); j++)
-                               color_fprintf(stdout, color, "   ");
-                       for (j = i & ~15; j <= i; j++) {
-                               color_fprintf(stdout, color, "%c",
-                                             isprint(raw_event[j]) ?
-                                             raw_event[j] : '.');
-                       }
-                       color_fprintf(stdout, color, "\n");
-               }
-       }
-       printf(".\n");
+       print_binary(raw_event, event->header.size, 16,
+                    trace_event_printer, event);
 }
 
 static struct debug_variable {
@@ -192,3 +209,23 @@ int perf_debug_option(const char *str)
        free(s);
        return 0;
 }
+
+#define DEBUG_WRAPPER(__n, __l)                                \
+static int pr_ ## __n ## _wrapper(const char *fmt, ...)        \
+{                                                      \
+       va_list args;                                   \
+       int ret;                                        \
+                                                       \
+       va_start(args, fmt);                            \
+       ret = veprintf(__l, verbose, fmt, args);        \
+       va_end(args);                                   \
+       return ret;                                     \
+}
+
+DEBUG_WRAPPER(warning, 0);
+DEBUG_WRAPPER(debug, 1);
+
+void perf_debug_setup(void)
+{
+       libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
+}
index 8b9a088c32ab4e330ece47ae91397bdd87bdd0ee..14bafda79edaeba1bbd3e007b5faa8607d0570bf 100644 (file)
@@ -53,5 +53,6 @@ int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__(
 int veprintf(int level, int var, const char *fmt, va_list args);
 
 int perf_debug_option(const char *str);
+void perf_debug_setup(void);
 
 #endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/demangle-java.c b/tools/perf/util/demangle-java.c
new file mode 100644 (file)
index 0000000..3e6062a
--- /dev/null
@@ -0,0 +1,199 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include "util.h"
+#include "debug.h"
+#include "symbol.h"
+
+#include "demangle-java.h"
+
+enum {
+       MODE_PREFIX = 0,
+       MODE_CLASS  = 1,
+       MODE_FUNC   = 2,
+       MODE_TYPE   = 3,
+       MODE_CTYPE  = 3, /* class arg */
+};
+
+#define BASE_ENT(c, n) [c - 'A']=n
+static const char *base_types['Z' - 'A' + 1] = {
+       BASE_ENT('B', "byte" ),
+       BASE_ENT('C', "char" ),
+       BASE_ENT('D', "double" ),
+       BASE_ENT('F', "float" ),
+       BASE_ENT('I', "int" ),
+       BASE_ENT('J', "long" ),
+       BASE_ENT('S', "short" ),
+       BASE_ENT('Z', "bool" ),
+};
+
+/*
+ * demangle Java symbol between str and end positions and stores
+ * up to maxlen characters into buf. The parser starts in mode.
+ *
+ * Use MODE_PREFIX to process entire prototype till end position
+ * Use MODE_TYPE to process return type if str starts on return type char
+ *
+ *  Return:
+ *     success: buf
+ *     error  : NULL
+ */
+static char *
+__demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int mode)
+{
+       int rlen = 0;
+       int array = 0;
+       int narg = 0;
+       const char *q;
+
+       if (!end)
+               end = str + strlen(str);
+
+       for (q = str; q != end; q++) {
+
+               if (rlen == (maxlen - 1))
+                       break;
+
+               switch (*q) {
+               case 'L':
+                       if (mode == MODE_PREFIX || mode == MODE_CTYPE) {
+                               if (mode == MODE_CTYPE) {
+                                       if (narg)
+                                               rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
+                                       narg++;
+                               }
+                               rlen += scnprintf(buf + rlen, maxlen - rlen, "class ");
+                               if (mode == MODE_PREFIX)
+                                       mode = MODE_CLASS;
+                       } else
+                               buf[rlen++] = *q;
+                       break;
+               case 'B':
+               case 'C':
+               case 'D':
+               case 'F':
+               case 'I':
+               case 'J':
+               case 'S':
+               case 'Z':
+                       if (mode == MODE_TYPE) {
+                               if (narg)
+                                       rlen += scnprintf(buf + rlen, maxlen - rlen, ", ");
+                               rlen += scnprintf(buf + rlen, maxlen - rlen, "%s", base_types[*q - 'A']);
+                               while (array--)
+                                       rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
+                               array = 0;
+                               narg++;
+                       } else
+                               buf[rlen++] = *q;
+                       break;
+               case 'V':
+                       if (mode == MODE_TYPE) {
+                               rlen += scnprintf(buf + rlen, maxlen - rlen, "void");
+                               while (array--)
+                                       rlen += scnprintf(buf + rlen, maxlen - rlen, "[]");
+                               array = 0;
+                       } else
+                               buf[rlen++] = *q;
+                       break;
+               case '[':
+                       if (mode != MODE_TYPE)
+                               goto error;
+                       array++;
+                       break;
+               case '(':
+                       if (mode != MODE_FUNC)
+                               goto error;
+                       buf[rlen++] = *q;
+                       mode = MODE_TYPE;
+                       break;
+               case ')':
+                       if (mode != MODE_TYPE)
+                               goto error;
+                       buf[rlen++] = *q;
+                       narg = 0;
+                       break;
+               case ';':
+                       if (mode != MODE_CLASS && mode != MODE_CTYPE)
+                               goto error;
+                       /* safe because at least one other char to process */
+                       if (isalpha(*(q + 1)))
+                               rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
+                       if (mode == MODE_CLASS)
+                               mode = MODE_FUNC;
+                       else if (mode == MODE_CTYPE)
+                               mode = MODE_TYPE;
+                       break;
+               case '/':
+                       if (mode != MODE_CLASS && mode != MODE_CTYPE)
+                               goto error;
+                       rlen += scnprintf(buf + rlen, maxlen - rlen, ".");
+                       break;
+               default :
+                       buf[rlen++] = *q;
+               }
+       }
+       buf[rlen] = '\0';
+       return buf;
+error:
+       return NULL;
+}
+
+/*
+ * Demangle Java function signature (openJDK, not GCJ)
+ * input:
+ *     str: string to parse. String is not modified
+ *    flags: comobination of JAVA_DEMANGLE_* flags to modify demangling
+ * return:
+ *     if input can be demangled, then a newly allocated string is returned.
+ *     if input cannot be demangled, then NULL is returned
+ *
+ * Note: caller is responsible for freeing demangled string
+ */
+char *
+java_demangle_sym(const char *str, int flags)
+{
+       char *buf, *ptr;
+       char *p;
+       size_t len, l1 = 0;
+
+       if (!str)
+               return NULL;
+
+       /* find start of retunr type */
+       p = strrchr(str, ')');
+       if (!p)
+               return NULL;
+
+       /*
+        * expansion factor estimated to 3x
+        */
+       len = strlen(str) * 3 + 1;
+       buf = malloc(len);
+       if (!buf)
+               return NULL;
+
+       buf[0] = '\0';
+       if (!(flags & JAVA_DEMANGLE_NORET)) {
+               /*
+                * get return type first
+                */
+               ptr = __demangle_java_sym(p + 1, NULL, buf, len, MODE_TYPE);
+               if (!ptr)
+                       goto error;
+
+               /* add space between return type and function prototype */
+               l1 = strlen(buf);
+               buf[l1++] = ' ';
+       }
+
+       /* process function up to return type */
+       ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX);
+       if (!ptr)
+               goto error;
+
+       return buf;
+error:
+       free(buf);
+       return NULL;
+}
diff --git a/tools/perf/util/demangle-java.h b/tools/perf/util/demangle-java.h
new file mode 100644 (file)
index 0000000..a981c1f
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __PERF_DEMANGLE_JAVA
+#define __PERF_DEMANGLE_JAVA 1
+/*
+ * demangle function flags
+ */
+#define JAVA_DEMANGLE_NORET    0x1 /* do not process return type */
+
+char * java_demangle_sym(const char *str, int flags);
+
+#endif /* __PERF_DEMANGLE_JAVA */
index e8e9a9dbf5e395a20d589c80b253c2d869b927c1..8e6395439ca0830cefaaa5b6dbe905ae2af93011 100644 (file)
@@ -52,6 +52,11 @@ int dso__read_binary_type_filename(const struct dso *dso,
                        debuglink--;
                if (*debuglink == '/')
                        debuglink++;
+
+               ret = -1;
+               if (!is_regular_file(filename))
+                       break;
+
                ret = filename__read_debuglink(filename, debuglink,
                                               size - (debuglink - filename));
                }
index 7dd5939dea2e58385bd374a3e59aecf766e799c1..49a11d9d8b8f050efa48715cfba9e54731f63eef 100644 (file)
@@ -6,6 +6,8 @@ struct perf_env perf_env;
 
 void perf_env__exit(struct perf_env *env)
 {
+       int i;
+
        zfree(&env->hostname);
        zfree(&env->os_release);
        zfree(&env->version);
@@ -19,6 +21,10 @@ void perf_env__exit(struct perf_env *env)
        zfree(&env->numa_nodes);
        zfree(&env->pmu_mappings);
        zfree(&env->cpu);
+
+       for (i = 0; i < env->caches_cnt; i++)
+               cpu_cache_level__free(&env->caches[i]);
+       zfree(&env->caches);
 }
 
 int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
@@ -75,3 +81,10 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)
        env->nr_cpus_avail = nr_cpus;
        return 0;
 }
+
+void cpu_cache_level__free(struct cpu_cache_level *cache)
+{
+       free(cache->type);
+       free(cache->map);
+       free(cache->size);
+}
index 0132b9557c02b56f7f31e3e51981d55b0d1027bd..56cffb60a0b42e456a11fb2bd489d74a69893b0c 100644 (file)
@@ -1,11 +1,23 @@
 #ifndef __PERF_ENV_H
 #define __PERF_ENV_H
 
+#include <linux/types.h>
+
 struct cpu_topology_map {
        int     socket_id;
        int     core_id;
 };
 
+struct cpu_cache_level {
+       u32     level;
+       u32     line_size;
+       u32     sets;
+       u32     ways;
+       char    *type;
+       char    *size;
+       char    *map;
+};
+
 struct perf_env {
        char                    *hostname;
        char                    *os_release;
@@ -31,6 +43,8 @@ struct perf_env {
        char                    *numa_nodes;
        char                    *pmu_mappings;
        struct cpu_topology_map *cpu;
+       struct cpu_cache_level  *caches;
+       int                      caches_cnt;
 };
 
 extern struct perf_env perf_env;
@@ -41,4 +55,5 @@ int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]);
 
 int perf_env__read_cpu_topology_map(struct perf_env *env);
 
+void cpu_cache_level__free(struct cpu_cache_level *cache);
 #endif /* __PERF_ENV_H */
index 85155e91b61ba9b70feaf867b109270df498b9b8..7bad5c3fa7b7175862f5e3bdf38ffca0e1b14ee1 100644 (file)
@@ -282,7 +282,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
                strcpy(execname, "");
 
                /* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
-               n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
+               n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %[^\n]\n",
                       &event->mmap2.start, &event->mmap2.len, prot,
                       &event->mmap2.pgoff, &event->mmap2.maj,
                       &event->mmap2.min,
index d81f13de24769963f6c32c3f809a714e6868dc5e..86a03836a83fc3f8ee8648d83317b8d91e3f48d8 100644 (file)
@@ -1181,12 +1181,12 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
         */
        if (cpus != evlist->cpus) {
                cpu_map__put(evlist->cpus);
-               evlist->cpus = cpus;
+               evlist->cpus = cpu_map__get(cpus);
        }
 
        if (threads != evlist->threads) {
                thread_map__put(evlist->threads);
-               evlist->threads = threads;
+               evlist->threads = thread_map__get(threads);
        }
 
        perf_evlist__propagate_maps(evlist);
@@ -1223,6 +1223,9 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
        int err = 0;
 
        evlist__for_each(evlist, evsel) {
+               if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+                       continue;
+
                err = perf_evsel__set_filter(evsel, filter);
                if (err)
                        break;
@@ -1624,7 +1627,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
        return printed + fprintf(fp, "\n");
 }
 
-int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
+int perf_evlist__strerror_open(struct perf_evlist *evlist,
                               int err, char *buf, size_t size)
 {
        int printed, value;
@@ -1652,7 +1655,25 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
                                    "Hint:\tTry: 'sudo sh -c \"echo -1 > /proc/sys/kernel/perf_event_paranoid\"'\n"
                                    "Hint:\tThe current value is %d.", value);
                break;
+       case EINVAL: {
+               struct perf_evsel *first = perf_evlist__first(evlist);
+               int max_freq;
+
+               if (sysctl__read_int("kernel/perf_event_max_sample_rate", &max_freq) < 0)
+                       goto out_default;
+
+               if (first->attr.sample_freq < (u64)max_freq)
+                       goto out_default;
+
+               printed = scnprintf(buf, size,
+                                   "Error:\t%s.\n"
+                                   "Hint:\tCheck /proc/sys/kernel/perf_event_max_sample_rate.\n"
+                                   "Hint:\tThe current value is %d and %" PRIu64 " is being requested.",
+                                   emsg, max_freq, first->attr.sample_freq);
+               break;
+       }
        default:
+out_default:
                scnprintf(buf, size, "%s", emsg);
                break;
        }
@@ -1723,3 +1744,19 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
 
        tracking_evsel->tracking = true;
 }
+
+struct perf_evsel *
+perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
+                              const char *str)
+{
+       struct perf_evsel *evsel;
+
+       evlist__for_each(evlist, evsel) {
+               if (!evsel->name)
+                       continue;
+               if (strcmp(str, evsel->name) == 0)
+                       return evsel;
+       }
+
+       return NULL;
+}
index 7c4d9a2067769b0e3de2d96a11e6f7dd7d62106a..a0d15221db6e878412126f1ec5de08cb030f132f 100644 (file)
@@ -294,4 +294,7 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
                                     struct perf_evsel *tracking_evsel);
 
 void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr);
+
+struct perf_evsel *
+perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str);
 #endif /* __PERF_EVLIST_H */
index cdbaf9b51e428ad4537a38ded24ee07bec54e90c..0902fe418754ec0c3149d3daeafc122fee65e243 100644 (file)
@@ -225,6 +225,11 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
        if (evsel != NULL)
                perf_evsel__init(evsel, attr, idx);
 
+       if (perf_evsel__is_bpf_output(evsel)) {
+               evsel->attr.sample_type |= PERF_SAMPLE_RAW;
+               evsel->attr.sample_period = 1;
+       }
+
        return evsel;
 }
 
@@ -898,6 +903,16 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
        if (evsel->precise_max)
                perf_event_attr__set_max_precise_ip(attr);
 
+       if (opts->all_user) {
+               attr->exclude_kernel = 1;
+               attr->exclude_user   = 0;
+       }
+
+       if (opts->all_kernel) {
+               attr->exclude_kernel = 0;
+               attr->exclude_user   = 1;
+       }
+
        /*
         * Apply event specific term settings,
         * it overloads any global configuration.
@@ -2362,12 +2377,15 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
        case EPERM:
        case EACCES:
                return scnprintf(msg, size,
-                "You may not have permission to collect %sstats.\n"
-                "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
-                " -1 - Not paranoid at all\n"
-                "  0 - Disallow raw tracepoint access for unpriv\n"
-                "  1 - Disallow cpu events for unpriv\n"
-                "  2 - Disallow kernel profiling for unpriv",
+                "You may not have permission to collect %sstats.\n\n"
+                "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n"
+                "which controls use of the performance events system by\n"
+                "unprivileged users (without CAP_SYS_ADMIN).\n\n"
+                "The default value is 1:\n\n"
+                "  -1: Allow use of (almost) all events by all users\n"
+                ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n"
+                ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n"
+                ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN",
                                 target->system_wide ? "system-wide " : "");
        case ENOENT:
                return scnprintf(msg, size, "The %s event is not supported.",
index 8e75434bd01c671a8ed2e0c0b03a139212d7001c..501ea6e565f13a4a4817947957c79f15d805d130 100644 (file)
@@ -93,10 +93,8 @@ struct perf_evsel {
        const char              *unit;
        struct event_format     *tp_format;
        off_t                   id_offset;
-       union {
-               void            *priv;
-               u64             db_id;
-       };
+       void                    *priv;
+       u64                     db_id;
        struct cgroup_sel       *cgrp;
        void                    *handler;
        struct cpu_map          *cpus;
@@ -364,6 +362,14 @@ static inline bool perf_evsel__is_function_event(struct perf_evsel *evsel)
 #undef FUNCTION_EVENT
 }
 
+static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel)
+{
+       struct perf_event_attr *attr = &evsel->attr;
+
+       return (attr->config == PERF_COUNT_SW_BPF_OUTPUT) &&
+               (attr->type == PERF_TYPE_SOFTWARE);
+}
+
 struct perf_attr_details {
        bool freq;
        bool verbose;
diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c
new file mode 100644 (file)
index 0000000..c1ef805
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * genelf.c
+ * Copyright (C) 2014, Google, Inc
+ *
+ * Contributed by:
+ *     Stephane Eranian <eranian@gmail.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stddef.h>
+#include <libelf.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <err.h>
+#include <dwarf.h>
+
+#include "perf.h"
+#include "genelf.h"
+#include "../util/jitdump.h"
+
+#define JVMTI
+
+#define BUILD_ID_URANDOM /* different uuid for each run */
+
+#ifdef HAVE_LIBCRYPTO
+
+#define BUILD_ID_MD5
+#undef BUILD_ID_SHA    /* does not seem to work well when linked with Java */
+#undef BUILD_ID_URANDOM /* different uuid for each run */
+
+#ifdef BUILD_ID_SHA
+#include <openssl/sha.h>
+#endif
+
+#ifdef BUILD_ID_MD5
+#include <openssl/md5.h>
+#endif
+#endif
+
+
+typedef struct {
+  unsigned int namesz;  /* Size of entry's owner string */
+  unsigned int descsz;  /* Size of the note descriptor */
+  unsigned int type;    /* Interpretation of the descriptor */
+  char         name[0]; /* Start of the name+desc data */
+} Elf_Note;
+
+struct options {
+       char *output;
+       int fd;
+};
+
+static char shd_string_table[] = {
+       0,
+       '.', 't', 'e', 'x', 't', 0,                     /*  1 */
+       '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0, /*  7 */
+       '.', 's', 'y', 'm', 't', 'a', 'b', 0,           /* 17 */
+       '.', 's', 't', 'r', 't', 'a', 'b', 0,           /* 25 */
+       '.', 'n', 'o', 't', 'e', '.', 'g', 'n', 'u', '.', 'b', 'u', 'i', 'l', 'd', '-', 'i', 'd', 0, /* 33 */
+       '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */
+       '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */
+       '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */
+};
+
+static struct buildid_note {
+       Elf_Note desc;          /* descsz: size of build-id, must be multiple of 4 */
+       char     name[4];       /* GNU\0 */
+       char     build_id[20];
+} bnote;
+
+static Elf_Sym symtab[]={
+       /* symbol 0 MUST be the undefined symbol */
+       { .st_name  = 0, /* index in sym_string table */
+         .st_info  = ELF_ST_TYPE(STT_NOTYPE),
+         .st_shndx = 0, /* for now */
+         .st_value = 0x0,
+         .st_other = ELF_ST_VIS(STV_DEFAULT),
+         .st_size  = 0,
+       },
+       { .st_name  = 1, /* index in sym_string table */
+         .st_info  = ELF_ST_BIND(STB_LOCAL) | ELF_ST_TYPE(STT_FUNC),
+         .st_shndx = 1,
+         .st_value = 0, /* for now */
+         .st_other = ELF_ST_VIS(STV_DEFAULT),
+         .st_size  = 0, /* for now */
+       }
+};
+
+#ifdef BUILD_ID_URANDOM
+static void
+gen_build_id(struct buildid_note *note,
+            unsigned long load_addr __maybe_unused,
+            const void *code __maybe_unused,
+            size_t csize __maybe_unused)
+{
+       int fd;
+       size_t sz = sizeof(note->build_id);
+       ssize_t sret;
+
+       fd = open("/dev/urandom", O_RDONLY);
+       if (fd == -1)
+               err(1, "cannot access /dev/urandom for builid");
+
+       sret = read(fd, note->build_id, sz);
+
+       close(fd);
+
+       if (sret != (ssize_t)sz)
+               memset(note->build_id, 0, sz);
+}
+#endif
+
+#ifdef BUILD_ID_SHA
+static void
+gen_build_id(struct buildid_note *note,
+            unsigned long load_addr __maybe_unused,
+            const void *code,
+            size_t csize)
+{
+       if (sizeof(note->build_id) < SHA_DIGEST_LENGTH)
+               errx(1, "build_id too small for SHA1");
+
+       SHA1(code, csize, (unsigned char *)note->build_id);
+}
+#endif
+
+#ifdef BUILD_ID_MD5
+static void
+gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *code, size_t csize)
+{
+       MD5_CTX context;
+
+       if (sizeof(note->build_id) < 16)
+               errx(1, "build_id too small for MD5");
+
+       MD5_Init(&context);
+       MD5_Update(&context, &load_addr, sizeof(load_addr));
+       MD5_Update(&context, code, csize);
+       MD5_Final((unsigned char *)note->build_id, &context);
+}
+#endif
+
+/*
+ * fd: file descriptor open for writing for the output file
+ * load_addr: code load address (could be zero, just used for buildid)
+ * sym: function name (for native code - used as the symbol)
+ * code: the native code
+ * csize: the code size in bytes
+ */
+int
+jit_write_elf(int fd, uint64_t load_addr, const char *sym,
+             const void *code, int csize,
+             void *debug, int nr_debug_entries)
+{
+       Elf *e;
+       Elf_Data *d;
+       Elf_Scn *scn;
+       Elf_Ehdr *ehdr;
+       Elf_Shdr *shdr;
+       char *strsym = NULL;
+       int symlen;
+       int retval = -1;
+
+       if (elf_version(EV_CURRENT) == EV_NONE) {
+               warnx("ELF initialization failed");
+               return -1;
+       }
+
+       e = elf_begin(fd, ELF_C_WRITE, NULL);
+       if (!e) {
+               warnx("elf_begin failed");
+               goto error;
+       }
+
+       /*
+        * setup ELF header
+        */
+       ehdr = elf_newehdr(e);
+       if (!ehdr) {
+               warnx("cannot get ehdr");
+               goto error;
+       }
+
+       ehdr->e_ident[EI_DATA] = GEN_ELF_ENDIAN;
+       ehdr->e_ident[EI_CLASS] = GEN_ELF_CLASS;
+       ehdr->e_machine = GEN_ELF_ARCH;
+       ehdr->e_type = ET_DYN;
+       ehdr->e_entry = GEN_ELF_TEXT_OFFSET;
+       ehdr->e_version = EV_CURRENT;
+       ehdr->e_shstrndx= 2; /* shdr index for section name */
+
+       /*
+        * setup text section
+        */
+       scn = elf_newscn(e);
+       if (!scn) {
+               warnx("cannot create section");
+               goto error;
+       }
+
+       d = elf_newdata(scn);
+       if (!d) {
+               warnx("cannot get new data");
+               goto error;
+       }
+
+       d->d_align = 16;
+       d->d_off = 0LL;
+       d->d_buf = (void *)code;
+       d->d_type = ELF_T_BYTE;
+       d->d_size = csize;
+       d->d_version = EV_CURRENT;
+
+       shdr = elf_getshdr(scn);
+       if (!shdr) {
+               warnx("cannot get section header");
+               goto error;
+       }
+
+       shdr->sh_name = 1;
+       shdr->sh_type = SHT_PROGBITS;
+       shdr->sh_addr = GEN_ELF_TEXT_OFFSET;
+       shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
+       shdr->sh_entsize = 0;
+
+       /*
+        * setup section headers string table
+        */
+       scn = elf_newscn(e);
+       if (!scn) {
+               warnx("cannot create section");
+               goto error;
+       }
+
+       d = elf_newdata(scn);
+       if (!d) {
+               warnx("cannot get new data");
+               goto error;
+       }
+
+       d->d_align = 1;
+       d->d_off = 0LL;
+       d->d_buf = shd_string_table;
+       d->d_type = ELF_T_BYTE;
+       d->d_size = sizeof(shd_string_table);
+       d->d_version = EV_CURRENT;
+
+       shdr = elf_getshdr(scn);
+       if (!shdr) {
+               warnx("cannot get section header");
+               goto error;
+       }
+
+       shdr->sh_name = 7; /* offset of '.shstrtab' in shd_string_table */
+       shdr->sh_type = SHT_STRTAB;
+       shdr->sh_flags = 0;
+       shdr->sh_entsize = 0;
+
+       /*
+        * setup symtab section
+        */
+       symtab[1].st_size  = csize;
+       symtab[1].st_value = GEN_ELF_TEXT_OFFSET;
+
+       scn = elf_newscn(e);
+       if (!scn) {
+               warnx("cannot create section");
+               goto error;
+       }
+
+       d = elf_newdata(scn);
+       if (!d) {
+               warnx("cannot get new data");
+               goto error;
+       }
+
+       d->d_align = 8;
+       d->d_off = 0LL;
+       d->d_buf = symtab;
+       d->d_type = ELF_T_SYM;
+       d->d_size = sizeof(symtab);
+       d->d_version = EV_CURRENT;
+
+       shdr = elf_getshdr(scn);
+       if (!shdr) {
+               warnx("cannot get section header");
+               goto error;
+       }
+
+       shdr->sh_name = 17; /* offset of '.symtab' in shd_string_table */
+       shdr->sh_type = SHT_SYMTAB;
+       shdr->sh_flags = 0;
+       shdr->sh_entsize = sizeof(Elf_Sym);
+       shdr->sh_link = 4; /* index of .strtab section */
+
+       /*
+        * setup symbols string table
+        * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry
+        */
+       symlen = 2 + strlen(sym);
+       strsym = calloc(1, symlen);
+       if (!strsym) {
+               warnx("cannot allocate strsym");
+               goto error;
+       }
+       strcpy(strsym + 1, sym);
+
+       scn = elf_newscn(e);
+       if (!scn) {
+               warnx("cannot create section");
+               goto error;
+       }
+
+       d = elf_newdata(scn);
+       if (!d) {
+               warnx("cannot get new data");
+               goto error;
+       }
+
+       d->d_align = 1;
+       d->d_off = 0LL;
+       d->d_buf = strsym;
+       d->d_type = ELF_T_BYTE;
+       d->d_size = symlen;
+       d->d_version = EV_CURRENT;
+
+       shdr = elf_getshdr(scn);
+       if (!shdr) {
+               warnx("cannot get section header");
+               goto error;
+       }
+
+       shdr->sh_name = 25; /* offset in shd_string_table */
+       shdr->sh_type = SHT_STRTAB;
+       shdr->sh_flags = 0;
+       shdr->sh_entsize = 0;
+
+       /*
+        * setup build-id section
+        */
+       scn = elf_newscn(e);
+       if (!scn) {
+               warnx("cannot create section");
+               goto error;
+       }
+
+       d = elf_newdata(scn);
+       if (!d) {
+               warnx("cannot get new data");
+               goto error;
+       }
+
+       /*
+        * build-id generation
+        */
+       gen_build_id(&bnote, load_addr, code, csize);
+       bnote.desc.namesz = sizeof(bnote.name); /* must include 0 termination */
+       bnote.desc.descsz = sizeof(bnote.build_id);
+       bnote.desc.type   = NT_GNU_BUILD_ID;
+       strcpy(bnote.name, "GNU");
+
+       d->d_align = 4;
+       d->d_off = 0LL;
+       d->d_buf = &bnote;
+       d->d_type = ELF_T_BYTE;
+       d->d_size = sizeof(bnote);
+       d->d_version = EV_CURRENT;
+
+       shdr = elf_getshdr(scn);
+       if (!shdr) {
+               warnx("cannot get section header");
+               goto error;
+       }
+
+       shdr->sh_name = 33; /* offset in shd_string_table */
+       shdr->sh_type = SHT_NOTE;
+       shdr->sh_addr = 0x0;
+       shdr->sh_flags = SHF_ALLOC;
+       shdr->sh_size = sizeof(bnote);
+       shdr->sh_entsize = 0;
+
+       if (debug && nr_debug_entries) {
+               retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries);
+               if (retval)
+                       goto error;
+       } else {
+               if (elf_update(e, ELF_C_WRITE) < 0) {
+                       warnx("elf_update 4 failed");
+                       goto error;
+               }
+       }
+
+       retval = 0;
+error:
+       (void)elf_end(e);
+
+       free(strsym);
+
+
+       return retval;
+}
+
+#ifndef JVMTI
+
+static unsigned char x86_code[] = {
+    0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
+    0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
+    0xCD, 0x80            /* int $0x80 */
+};
+
+static struct options options;
+
+int main(int argc, char **argv)
+{
+       int c, fd, ret;
+
+       while ((c = getopt(argc, argv, "o:h")) != -1) {
+               switch (c) {
+               case 'o':
+                       options.output = optarg;
+                       break;
+               case 'h':
+                       printf("Usage: genelf -o output_file [-h]\n");
+                       return 0;
+               default:
+                       errx(1, "unknown option");
+               }
+       }
+
+       fd = open(options.output, O_CREAT|O_TRUNC|O_RDWR, 0666);
+       if (fd == -1)
+               err(1, "cannot create file %s", options.output);
+
+       ret = jit_write_elf(fd, "main", x86_code, sizeof(x86_code));
+       close(fd);
+
+       if (ret != 0)
+               unlink(options.output);
+
+       return ret;
+}
+#endif
diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h
new file mode 100644 (file)
index 0000000..45bf9c6
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __GENELF_H__
+#define __GENELF_H__
+
+/* genelf.c */
+extern int jit_write_elf(int fd, uint64_t code_addr, const char *sym,
+                        const void *code, int csize,
+                        void *debug, int nr_debug_entries);
+/* genelf_debug.c */
+extern int jit_add_debug_info(Elf *e, uint64_t code_addr,
+                             void *debug, int nr_debug_entries);
+
+#if   defined(__arm__)
+#define GEN_ELF_ARCH   EM_ARM
+#define GEN_ELF_ENDIAN ELFDATA2LSB
+#define GEN_ELF_CLASS  ELFCLASS32
+#elif defined(__aarch64__)
+#define GEN_ELF_ARCH   EM_AARCH64
+#define GEN_ELF_ENDIAN ELFDATA2LSB
+#define GEN_ELF_CLASS  ELFCLASS64
+#elif defined(__x86_64__)
+#define GEN_ELF_ARCH   EM_X86_64
+#define GEN_ELF_ENDIAN ELFDATA2LSB
+#define GEN_ELF_CLASS  ELFCLASS64
+#elif defined(__i386__)
+#define GEN_ELF_ARCH   EM_386
+#define GEN_ELF_ENDIAN ELFDATA2LSB
+#define GEN_ELF_CLASS  ELFCLASS32
+#elif defined(__ppcle__)
+#define GEN_ELF_ARCH   EM_PPC
+#define GEN_ELF_ENDIAN ELFDATA2LSB
+#define GEN_ELF_CLASS  ELFCLASS64
+#elif defined(__powerpc__)
+#define GEN_ELF_ARCH   EM_PPC64
+#define GEN_ELF_ENDIAN ELFDATA2MSB
+#define GEN_ELF_CLASS  ELFCLASS64
+#elif defined(__powerpcle__)
+#define GEN_ELF_ARCH   EM_PPC64
+#define GEN_ELF_ENDIAN ELFDATA2LSB
+#define GEN_ELF_CLASS  ELFCLASS64
+#else
+#error "unsupported architecture"
+#endif
+
+#if GEN_ELF_CLASS == ELFCLASS64
+#define elf_newehdr    elf64_newehdr
+#define elf_getshdr    elf64_getshdr
+#define Elf_Ehdr       Elf64_Ehdr
+#define Elf_Shdr       Elf64_Shdr
+#define Elf_Sym                Elf64_Sym
+#define ELF_ST_TYPE(a) ELF64_ST_TYPE(a)
+#define ELF_ST_BIND(a) ELF64_ST_BIND(a)
+#define ELF_ST_VIS(a)  ELF64_ST_VISIBILITY(a)
+#else
+#define elf_newehdr    elf32_newehdr
+#define elf_getshdr    elf32_getshdr
+#define Elf_Ehdr       Elf32_Ehdr
+#define Elf_Shdr       Elf32_Shdr
+#define Elf_Sym                Elf32_Sym
+#define ELF_ST_TYPE(a) ELF32_ST_TYPE(a)
+#define ELF_ST_BIND(a) ELF32_ST_BIND(a)
+#define ELF_ST_VIS(a)  ELF32_ST_VISIBILITY(a)
+#endif
+
+/* The .text section is directly after the ELF header */
+#define GEN_ELF_TEXT_OFFSET sizeof(Elf_Ehdr)
+
+#endif
diff --git a/tools/perf/util/genelf_debug.c b/tools/perf/util/genelf_debug.c
new file mode 100644 (file)
index 0000000..5980f7d
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ * genelf_debug.c
+ * Copyright (C) 2015, Google, Inc
+ *
+ * Contributed by:
+ *     Stephane Eranian <eranian@google.com>
+ *
+ * Released under the GPL v2.
+ *
+ * based on GPLv2 source code from Oprofile
+ * @remark Copyright 2007 OProfile authors
+ * @author Philippe Elie
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stddef.h>
+#include <libelf.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <err.h>
+#include <dwarf.h>
+
+#include "perf.h"
+#include "genelf.h"
+#include "../util/jitdump.h"
+
+#define BUFFER_EXT_DFL_SIZE    (4 * 1024)
+
+typedef uint32_t uword;
+typedef uint16_t uhalf;
+typedef int32_t  sword;
+typedef int16_t  shalf;
+typedef uint8_t  ubyte;
+typedef int8_t   sbyte;
+
+struct buffer_ext {
+       size_t cur_pos;
+       size_t max_sz;
+       void *data;
+};
+
+static void
+buffer_ext_dump(struct buffer_ext *be, const char *msg)
+{
+       size_t i;
+       warnx("DUMP for %s", msg);
+       for (i = 0 ; i < be->cur_pos; i++)
+               warnx("%4zu 0x%02x", i, (((char *)be->data)[i]) & 0xff);
+}
+
+static inline int
+buffer_ext_add(struct buffer_ext *be, void *addr, size_t sz)
+{
+       void *tmp;
+       size_t be_sz = be->max_sz;
+
+retry:
+       if ((be->cur_pos + sz) < be_sz) {
+               memcpy(be->data + be->cur_pos, addr, sz);
+               be->cur_pos += sz;
+               return 0;
+       }
+
+       if (!be_sz)
+               be_sz = BUFFER_EXT_DFL_SIZE;
+       else
+               be_sz <<= 1;
+
+       tmp = realloc(be->data, be_sz);
+       if (!tmp)
+               return -1;
+
+       be->data   = tmp;
+       be->max_sz = be_sz;
+
+       goto retry;
+}
+
+static void
+buffer_ext_init(struct buffer_ext *be)
+{
+       be->data = NULL;
+       be->cur_pos = 0;
+       be->max_sz = 0;
+}
+
+static inline size_t
+buffer_ext_size(struct buffer_ext *be)
+{
+       return be->cur_pos;
+}
+
+static inline void *
+buffer_ext_addr(struct buffer_ext *be)
+{
+       return be->data;
+}
+
+struct debug_line_header {
+       // Not counting this field
+       uword total_length;
+       // version number (2 currently)
+       uhalf version;
+       // relative offset from next field to
+       // program statement
+       uword prolog_length;
+       ubyte minimum_instruction_length;
+       ubyte default_is_stmt;
+       // line_base - see DWARF 2 specs
+       sbyte line_base;
+       // line_range - see DWARF 2 specs
+       ubyte line_range;
+       // number of opcode + 1
+       ubyte opcode_base;
+       /* follow the array of opcode args nr: ubytes [nr_opcode_base] */
+       /* follow the search directories index, zero terminated string
+        * terminated by an empty string.
+        */
+       /* follow an array of { filename, LEB128, LEB128, LEB128 }, first is
+        * the directory index entry, 0 means current directory, then mtime
+        * and filesize, last entry is followed by en empty string.
+        */
+       /* follow the first program statement */
+} __attribute__((packed));
+
+/* DWARF 2 spec talk only about one possible compilation unit header while
+ * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not
+ * related to the used arch, an ELF 32 can hold more than 4 Go of debug
+ * information. For now we handle only DWARF 2 32 bits comp unit. It'll only
+ * become a problem if we generate more than 4GB of debug information.
+ */
+struct compilation_unit_header {
+       uword total_length;
+       uhalf version;
+       uword debug_abbrev_offset;
+       ubyte pointer_size;
+} __attribute__((packed));
+
+#define DW_LNS_num_opcode (DW_LNS_set_isa + 1)
+
+/* field filled at run time are marked with -1 */
+static struct debug_line_header const default_debug_line_header = {
+       .total_length = -1,
+       .version = 2,
+       .prolog_length = -1,
+       .minimum_instruction_length = 1,        /* could be better when min instruction size != 1 */
+       .default_is_stmt = 1,   /* we don't take care about basic block */
+       .line_base = -5,        /* sensible value for line base ... */
+       .line_range = -14,     /* ... and line range are guessed statically */
+       .opcode_base = DW_LNS_num_opcode
+};
+
+static ubyte standard_opcode_length[] =
+{
+       0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1
+};
+#if 0
+{
+       [DW_LNS_advance_pc]   = 1,
+       [DW_LNS_advance_line] = 1,
+       [DW_LNS_set_file] =  1,
+       [DW_LNS_set_column] = 1,
+       [DW_LNS_fixed_advance_pc] = 1,
+       [DW_LNS_set_isa] = 1,
+};
+#endif
+
+/* field filled at run time are marked with -1 */
+static struct compilation_unit_header default_comp_unit_header = {
+       .total_length = -1,
+       .version = 2,
+       .debug_abbrev_offset = 0,     /* we reuse the same abbrev entries for all comp unit */
+       .pointer_size = sizeof(void *)
+};
+
+static void emit_uword(struct buffer_ext *be, uword data)
+{
+       buffer_ext_add(be, &data, sizeof(uword));
+}
+
+static void emit_string(struct buffer_ext *be, const char *s)
+{
+       buffer_ext_add(be, (void *)s, strlen(s) + 1);
+}
+
+static void emit_unsigned_LEB128(struct buffer_ext *be,
+                                unsigned long data)
+{
+       do {
+               ubyte cur = data & 0x7F;
+               data >>= 7;
+               if (data)
+                       cur |= 0x80;
+               buffer_ext_add(be, &cur, 1);
+       } while (data);
+}
+
+static void emit_signed_LEB128(struct buffer_ext *be, long data)
+{
+       int more = 1;
+       int negative = data < 0;
+       int size = sizeof(long) * CHAR_BIT;
+       while (more) {
+               ubyte cur = data & 0x7F;
+               data >>= 7;
+               if (negative)
+                       data |= - (1 << (size - 7));
+               if ((data == 0 && !(cur & 0x40)) ||
+                   (data == -1l && (cur & 0x40)))
+                       more = 0;
+               else
+                       cur |= 0x80;
+               buffer_ext_add(be, &cur, 1);
+       }
+}
+
+static void emit_extended_opcode(struct buffer_ext *be, ubyte opcode,
+                                void *data, size_t data_len)
+{
+       buffer_ext_add(be, (char *)"", 1);
+
+       emit_unsigned_LEB128(be, data_len + 1);
+
+       buffer_ext_add(be, &opcode, 1);
+       buffer_ext_add(be, data, data_len);
+}
+
+static void emit_opcode(struct buffer_ext *be, ubyte opcode)
+{
+       buffer_ext_add(be, &opcode, 1);
+}
+
+static void emit_opcode_signed(struct buffer_ext  *be,
+                              ubyte opcode, long data)
+{
+       buffer_ext_add(be, &opcode, 1);
+       emit_signed_LEB128(be, data);
+}
+
+static void emit_opcode_unsigned(struct buffer_ext *be, ubyte opcode,
+                                unsigned long data)
+{
+       buffer_ext_add(be, &opcode, 1);
+       emit_unsigned_LEB128(be, data);
+}
+
+static void emit_advance_pc(struct buffer_ext *be, unsigned long delta_pc)
+{
+       emit_opcode_unsigned(be, DW_LNS_advance_pc, delta_pc);
+}
+
+static void emit_advance_lineno(struct buffer_ext  *be, long delta_lineno)
+{
+       emit_opcode_signed(be, DW_LNS_advance_line, delta_lineno);
+}
+
+static void emit_lne_end_of_sequence(struct buffer_ext *be)
+{
+       emit_extended_opcode(be, DW_LNE_end_sequence, NULL, 0);
+}
+
+static void emit_set_file(struct buffer_ext *be, unsigned long idx)
+{
+       emit_opcode_unsigned(be, DW_LNS_set_file, idx);
+}
+
+static void emit_lne_define_filename(struct buffer_ext *be,
+                                    const char *filename)
+{
+       buffer_ext_add(be, (void *)"", 1);
+
+       /* LNE field, strlen(filename) + zero termination, 3 bytes for: the dir entry, timestamp, filesize */
+       emit_unsigned_LEB128(be, strlen(filename) + 5);
+       emit_opcode(be, DW_LNE_define_file);
+       emit_string(be, filename);
+       /* directory index 0=do not know */
+        emit_unsigned_LEB128(be, 0);
+       /* last modification date on file 0=do not know */
+        emit_unsigned_LEB128(be, 0);
+       /* filesize 0=do not know */
+        emit_unsigned_LEB128(be, 0);
+}
+
+static void emit_lne_set_address(struct buffer_ext *be,
+                                void *address)
+{
+       emit_extended_opcode(be, DW_LNE_set_address, &address, sizeof(unsigned long));
+}
+
+static ubyte get_special_opcode(struct debug_entry *ent,
+                               unsigned int last_line,
+                               unsigned long last_vma)
+{
+       unsigned int temp;
+       unsigned long delta_addr;
+
+       /*
+        * delta from line_base
+        */
+       temp = (ent->lineno - last_line) - default_debug_line_header.line_base;
+
+       if (temp >= default_debug_line_header.line_range)
+               return 0;
+
+       /*
+        * delta of addresses
+        */
+       delta_addr = (ent->addr - last_vma) / default_debug_line_header.minimum_instruction_length;
+
+       /* This is not sufficient to ensure opcode will be in [0-256] but
+        * sufficient to ensure when summing with the delta lineno we will
+        * not overflow the unsigned long opcode */
+
+       if (delta_addr <= 256 / default_debug_line_header.line_range) {
+               unsigned long opcode = temp +
+                       (delta_addr * default_debug_line_header.line_range) +
+                       default_debug_line_header.opcode_base;
+
+               return opcode <= 255 ? opcode : 0;
+       }
+       return 0;
+}
+
+static void emit_lineno_info(struct buffer_ext *be,
+                            struct debug_entry *ent, size_t nr_entry,
+                            unsigned long code_addr)
+{
+       size_t i;
+
+       /*
+        * Machine state at start of a statement program
+        * address = 0
+        * file    = 1
+        * line    = 1
+        * column  = 0
+        * is_stmt = default_is_stmt as given in the debug_line_header
+        * basic block = 0
+        * end sequence = 0
+        */
+
+       /* start state of the state machine we take care of */
+       unsigned long last_vma = code_addr;
+       char const  *cur_filename = NULL;
+       unsigned long cur_file_idx = 0;
+       int last_line = 1;
+
+       emit_lne_set_address(be, (void *)code_addr);
+
+       for (i = 0; i < nr_entry; i++, ent = debug_entry_next(ent)) {
+               int need_copy = 0;
+               ubyte special_opcode;
+
+               /*
+                * check if filename changed, if so add it
+                */
+               if (!cur_filename || strcmp(cur_filename, ent->name)) {
+                       emit_lne_define_filename(be, ent->name);
+                       cur_filename = ent->name;
+                       emit_set_file(be, ++cur_file_idx);
+                       need_copy = 1;
+               }
+
+               special_opcode = get_special_opcode(ent, last_line, last_vma);
+               if (special_opcode != 0) {
+                       last_line = ent->lineno;
+                       last_vma  = ent->addr;
+                       emit_opcode(be, special_opcode);
+               } else {
+                       /*
+                        * lines differ, emit line delta
+                        */
+                       if (last_line != ent->lineno) {
+                               emit_advance_lineno(be, ent->lineno - last_line);
+                               last_line = ent->lineno;
+                               need_copy = 1;
+                       }
+                       /*
+                        * addresses differ, emit address delta
+                        */
+                       if (last_vma != ent->addr) {
+                               emit_advance_pc(be, ent->addr - last_vma);
+                               last_vma = ent->addr;
+                               need_copy = 1;
+                       }
+                       /*
+                        * add new row to matrix
+                        */
+                       if (need_copy)
+                               emit_opcode(be, DW_LNS_copy);
+               }
+       }
+}
+
+static void add_debug_line(struct buffer_ext *be,
+       struct debug_entry *ent, size_t nr_entry,
+       unsigned long code_addr)
+{
+       struct debug_line_header * dbg_header;
+       size_t old_size;
+
+       old_size = buffer_ext_size(be);
+
+       buffer_ext_add(be, (void *)&default_debug_line_header,
+                sizeof(default_debug_line_header));
+
+       buffer_ext_add(be, &standard_opcode_length,  sizeof(standard_opcode_length));
+
+       // empty directory entry
+       buffer_ext_add(be, (void *)"", 1);
+
+       // empty filename directory
+       buffer_ext_add(be, (void *)"", 1);
+
+       dbg_header = buffer_ext_addr(be) + old_size;
+       dbg_header->prolog_length = (buffer_ext_size(be) - old_size) -
+               offsetof(struct debug_line_header, minimum_instruction_length);
+
+       emit_lineno_info(be, ent, nr_entry, code_addr);
+
+       emit_lne_end_of_sequence(be);
+
+       dbg_header = buffer_ext_addr(be) + old_size;
+       dbg_header->total_length = (buffer_ext_size(be) - old_size) -
+               offsetof(struct debug_line_header, version);
+}
+
+static void
+add_debug_abbrev(struct buffer_ext *be)
+{
+        emit_unsigned_LEB128(be, 1);
+        emit_unsigned_LEB128(be, DW_TAG_compile_unit);
+        emit_unsigned_LEB128(be, DW_CHILDREN_yes);
+        emit_unsigned_LEB128(be, DW_AT_stmt_list);
+        emit_unsigned_LEB128(be, DW_FORM_data4);
+        emit_unsigned_LEB128(be, 0);
+        emit_unsigned_LEB128(be, 0);
+        emit_unsigned_LEB128(be, 0);
+}
+
+static void
+add_compilation_unit(struct buffer_ext *be,
+                    size_t offset_debug_line)
+{
+       struct compilation_unit_header *comp_unit_header;
+       size_t old_size = buffer_ext_size(be);
+
+       buffer_ext_add(be, &default_comp_unit_header,
+                      sizeof(default_comp_unit_header));
+
+       emit_unsigned_LEB128(be, 1);
+       emit_uword(be, offset_debug_line);
+
+       comp_unit_header = buffer_ext_addr(be) + old_size;
+       comp_unit_header->total_length = (buffer_ext_size(be) - old_size) -
+               offsetof(struct compilation_unit_header, version);
+}
+
+static int
+jit_process_debug_info(uint64_t code_addr,
+                      void *debug, int nr_debug_entries,
+                      struct buffer_ext *dl,
+                      struct buffer_ext *da,
+                      struct buffer_ext *di)
+{
+       struct debug_entry *ent = debug;
+       int i;
+
+       for (i = 0; i < nr_debug_entries; i++) {
+               ent->addr = ent->addr - code_addr;
+               ent = debug_entry_next(ent);
+       }
+       add_compilation_unit(di, buffer_ext_size(dl));
+       add_debug_line(dl, debug, nr_debug_entries, 0);
+       add_debug_abbrev(da);
+       if (0) buffer_ext_dump(da, "abbrev");
+
+       return 0;
+}
+
+int
+jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries)
+{
+       Elf_Data *d;
+       Elf_Scn *scn;
+       Elf_Shdr *shdr;
+       struct buffer_ext dl, di, da;
+       int ret;
+
+       buffer_ext_init(&dl);
+       buffer_ext_init(&di);
+       buffer_ext_init(&da);
+
+       ret = jit_process_debug_info(code_addr, debug, nr_debug_entries, &dl, &da, &di);
+       if (ret)
+               return -1;
+       /*
+        * setup .debug_line section
+        */
+       scn = elf_newscn(e);
+       if (!scn) {
+               warnx("cannot create section");
+               return -1;
+       }
+
+       d = elf_newdata(scn);
+       if (!d) {
+               warnx("cannot get new data");
+               return -1;
+       }
+
+       d->d_align = 1;
+       d->d_off = 0LL;
+       d->d_buf = buffer_ext_addr(&dl);
+       d->d_type = ELF_T_BYTE;
+       d->d_size = buffer_ext_size(&dl);
+       d->d_version = EV_CURRENT;
+
+       shdr = elf_getshdr(scn);
+       if (!shdr) {
+               warnx("cannot get section header");
+               return -1;
+       }
+
+       shdr->sh_name = 52; /* .debug_line */
+       shdr->sh_type = SHT_PROGBITS;
+       shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
+       shdr->sh_flags = 0;
+       shdr->sh_entsize = 0;
+
+       /*
+        * setup .debug_info section
+        */
+       scn = elf_newscn(e);
+       if (!scn) {
+               warnx("cannot create section");
+               return -1;
+       }
+
+       d = elf_newdata(scn);
+       if (!d) {
+               warnx("cannot get new data");
+               return -1;
+       }
+
+       d->d_align = 1;
+       d->d_off = 0LL;
+       d->d_buf = buffer_ext_addr(&di);
+       d->d_type = ELF_T_BYTE;
+       d->d_size = buffer_ext_size(&di);
+       d->d_version = EV_CURRENT;
+
+       shdr = elf_getshdr(scn);
+       if (!shdr) {
+               warnx("cannot get section header");
+               return -1;
+       }
+
+       shdr->sh_name = 64; /* .debug_info */
+       shdr->sh_type = SHT_PROGBITS;
+       shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
+       shdr->sh_flags = 0;
+       shdr->sh_entsize = 0;
+
+       /*
+        * setup .debug_abbrev section
+        */
+       scn = elf_newscn(e);
+       if (!scn) {
+               warnx("cannot create section");
+               return -1;
+       }
+
+       d = elf_newdata(scn);
+       if (!d) {
+               warnx("cannot get new data");
+               return -1;
+       }
+
+       d->d_align = 1;
+       d->d_off = 0LL;
+       d->d_buf = buffer_ext_addr(&da);
+       d->d_type = ELF_T_BYTE;
+       d->d_size = buffer_ext_size(&da);
+       d->d_version = EV_CURRENT;
+
+       shdr = elf_getshdr(scn);
+       if (!shdr) {
+               warnx("cannot get section header");
+               return -1;
+       }
+
+       shdr->sh_name = 76; /* .debug_info */
+       shdr->sh_type = SHT_PROGBITS;
+       shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */
+       shdr->sh_flags = 0;
+       shdr->sh_entsize = 0;
+
+       /*
+        * now we update the ELF image with all the sections
+        */
+       if (elf_update(e, ELF_C_WRITE) < 0) {
+               warnx("elf_update debug failed");
+               return -1;
+       }
+       return 0;
+}
index f50b7235ecb6558d167a475bf4199e8b05f52143..73e38e472ecd7771695b7ac2d91829a35529f419 100644 (file)
@@ -23,6 +23,8 @@
 #include "strbuf.h"
 #include "build-id.h"
 #include "data.h"
+#include <api/fs/fs.h>
+#include "asm/bug.h"
 
 /*
  * magic2 = "PERFILE2"
@@ -868,6 +870,199 @@ static int write_auxtrace(int fd, struct perf_header *h,
        return err;
 }
 
+static int cpu_cache_level__sort(const void *a, const void *b)
+{
+       struct cpu_cache_level *cache_a = (struct cpu_cache_level *)a;
+       struct cpu_cache_level *cache_b = (struct cpu_cache_level *)b;
+
+       return cache_a->level - cache_b->level;
+}
+
+static bool cpu_cache_level__cmp(struct cpu_cache_level *a, struct cpu_cache_level *b)
+{
+       if (a->level != b->level)
+               return false;
+
+       if (a->line_size != b->line_size)
+               return false;
+
+       if (a->sets != b->sets)
+               return false;
+
+       if (a->ways != b->ways)
+               return false;
+
+       if (strcmp(a->type, b->type))
+               return false;
+
+       if (strcmp(a->size, b->size))
+               return false;
+
+       if (strcmp(a->map, b->map))
+               return false;
+
+       return true;
+}
+
+static int cpu_cache_level__read(struct cpu_cache_level *cache, u32 cpu, u16 level)
+{
+       char path[PATH_MAX], file[PATH_MAX];
+       struct stat st;
+       size_t len;
+
+       scnprintf(path, PATH_MAX, "devices/system/cpu/cpu%d/cache/index%d/", cpu, level);
+       scnprintf(file, PATH_MAX, "%s/%s", sysfs__mountpoint(), path);
+
+       if (stat(file, &st))
+               return 1;
+
+       scnprintf(file, PATH_MAX, "%s/level", path);
+       if (sysfs__read_int(file, (int *) &cache->level))
+               return -1;
+
+       scnprintf(file, PATH_MAX, "%s/coherency_line_size", path);
+       if (sysfs__read_int(file, (int *) &cache->line_size))
+               return -1;
+
+       scnprintf(file, PATH_MAX, "%s/number_of_sets", path);
+       if (sysfs__read_int(file, (int *) &cache->sets))
+               return -1;
+
+       scnprintf(file, PATH_MAX, "%s/ways_of_associativity", path);
+       if (sysfs__read_int(file, (int *) &cache->ways))
+               return -1;
+
+       scnprintf(file, PATH_MAX, "%s/type", path);
+       if (sysfs__read_str(file, &cache->type, &len))
+               return -1;
+
+       cache->type[len] = 0;
+       cache->type = rtrim(cache->type);
+
+       scnprintf(file, PATH_MAX, "%s/size", path);
+       if (sysfs__read_str(file, &cache->size, &len)) {
+               free(cache->type);
+               return -1;
+       }
+
+       cache->size[len] = 0;
+       cache->size = rtrim(cache->size);
+
+       scnprintf(file, PATH_MAX, "%s/shared_cpu_list", path);
+       if (sysfs__read_str(file, &cache->map, &len)) {
+               free(cache->map);
+               free(cache->type);
+               return -1;
+       }
+
+       cache->map[len] = 0;
+       cache->map = rtrim(cache->map);
+       return 0;
+}
+
+static void cpu_cache_level__fprintf(FILE *out, struct cpu_cache_level *c)
+{
+       fprintf(out, "L%d %-15s %8s [%s]\n", c->level, c->type, c->size, c->map);
+}
+
+static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
+{
+       u32 i, cnt = 0;
+       long ncpus;
+       u32 nr, cpu;
+       u16 level;
+
+       ncpus = sysconf(_SC_NPROCESSORS_CONF);
+       if (ncpus < 0)
+               return -1;
+
+       nr = (u32)(ncpus & UINT_MAX);
+
+       for (cpu = 0; cpu < nr; cpu++) {
+               for (level = 0; level < 10; level++) {
+                       struct cpu_cache_level c;
+                       int err;
+
+                       err = cpu_cache_level__read(&c, cpu, level);
+                       if (err < 0)
+                               return err;
+
+                       if (err == 1)
+                               break;
+
+                       for (i = 0; i < cnt; i++) {
+                               if (cpu_cache_level__cmp(&c, &caches[i]))
+                                       break;
+                       }
+
+                       if (i == cnt)
+                               caches[cnt++] = c;
+                       else
+                               cpu_cache_level__free(&c);
+
+                       if (WARN_ONCE(cnt == size, "way too many cpu caches.."))
+                               goto out;
+               }
+       }
+ out:
+       *cntp = cnt;
+       return 0;
+}
+
+#define MAX_CACHES 2000
+
+static int write_cache(int fd, struct perf_header *h __maybe_unused,
+                         struct perf_evlist *evlist __maybe_unused)
+{
+       struct cpu_cache_level caches[MAX_CACHES];
+       u32 cnt = 0, i, version = 1;
+       int ret;
+
+       ret = build_caches(caches, MAX_CACHES, &cnt);
+       if (ret)
+               goto out;
+
+       qsort(&caches, cnt, sizeof(struct cpu_cache_level), cpu_cache_level__sort);
+
+       ret = do_write(fd, &version, sizeof(u32));
+       if (ret < 0)
+               goto out;
+
+       ret = do_write(fd, &cnt, sizeof(u32));
+       if (ret < 0)
+               goto out;
+
+       for (i = 0; i < cnt; i++) {
+               struct cpu_cache_level *c = &caches[i];
+
+               #define _W(v)                                   \
+                       ret = do_write(fd, &c->v, sizeof(u32)); \
+                       if (ret < 0)                            \
+                               goto out;
+
+               _W(level)
+               _W(line_size)
+               _W(sets)
+               _W(ways)
+               #undef _W
+
+               #define _W(v)                                           \
+                       ret = do_write_string(fd, (const char *) c->v); \
+                       if (ret < 0)                                    \
+                               goto out;
+
+               _W(type)
+               _W(size)
+               _W(map)
+               #undef _W
+       }
+
+out:
+       for (i = 0; i < cnt; i++)
+               cpu_cache_level__free(&caches[i]);
+       return ret;
+}
+
 static int write_stat(int fd __maybe_unused,
                      struct perf_header *h __maybe_unused,
                      struct perf_evlist *evlist __maybe_unused)
@@ -1172,6 +1367,18 @@ static void print_stat(struct perf_header *ph __maybe_unused,
        fprintf(fp, "# contains stat data\n");
 }
 
+static void print_cache(struct perf_header *ph __maybe_unused,
+                       int fd __maybe_unused, FILE *fp __maybe_unused)
+{
+       int i;
+
+       fprintf(fp, "# CPU cache info:\n");
+       for (i = 0; i < ph->env.caches_cnt; i++) {
+               fprintf(fp, "#  ");
+               cpu_cache_level__fprintf(fp, &ph->env.caches[i]);
+       }
+}
+
 static void print_pmu_mappings(struct perf_header *ph, int fd __maybe_unused,
                               FILE *fp)
 {
@@ -1920,6 +2127,68 @@ static int process_auxtrace(struct perf_file_section *section,
        return err;
 }
 
+static int process_cache(struct perf_file_section *section __maybe_unused,
+                        struct perf_header *ph __maybe_unused, int fd __maybe_unused,
+                        void *data __maybe_unused)
+{
+       struct cpu_cache_level *caches;
+       u32 cnt, i, version;
+
+       if (readn(fd, &version, sizeof(version)) != sizeof(version))
+               return -1;
+
+       if (ph->needs_swap)
+               version = bswap_32(version);
+
+       if (version != 1)
+               return -1;
+
+       if (readn(fd, &cnt, sizeof(cnt)) != sizeof(cnt))
+               return -1;
+
+       if (ph->needs_swap)
+               cnt = bswap_32(cnt);
+
+       caches = zalloc(sizeof(*caches) * cnt);
+       if (!caches)
+               return -1;
+
+       for (i = 0; i < cnt; i++) {
+               struct cpu_cache_level c;
+
+               #define _R(v)                                           \
+                       if (readn(fd, &c.v, sizeof(u32)) != sizeof(u32))\
+                               goto out_free_caches;                   \
+                       if (ph->needs_swap)                             \
+                               c.v = bswap_32(c.v);                    \
+
+               _R(level)
+               _R(line_size)
+               _R(sets)
+               _R(ways)
+               #undef _R
+
+               #define _R(v)                           \
+                       c.v = do_read_string(fd, ph);   \
+                       if (!c.v)                       \
+                               goto out_free_caches;
+
+               _R(type)
+               _R(size)
+               _R(map)
+               #undef _R
+
+               caches[i] = c;
+       }
+
+       ph->env.caches = caches;
+       ph->env.caches_cnt = cnt;
+       return 0;
+out_free_caches:
+       free(caches);
+       return -1;
+}
+
 struct feature_ops {
        int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
        void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1962,6 +2231,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
        FEAT_OPP(HEADER_GROUP_DESC,     group_desc),
        FEAT_OPP(HEADER_AUXTRACE,       auxtrace),
        FEAT_OPA(HEADER_STAT,           stat),
+       FEAT_OPF(HEADER_CACHE,          cache),
 };
 
 struct header_print_data {
index cff9892452ee393764726a12895ad95d36f766fe..3d87ca823c0ae55591e753f6f928802e831c0e3c 100644 (file)
@@ -32,6 +32,7 @@ enum {
        HEADER_GROUP_DESC,
        HEADER_AUXTRACE,
        HEADER_STAT,
+       HEADER_CACHE,
        HEADER_LAST_FEATURE,
        HEADER_FEAT_BITS        = 256,
 };
index dc1e41c9b054b186c0d9349d97e9d0f467099ac0..43a98a4dc1e1e90c7079fba26929022ec0959a31 100644 (file)
@@ -6,7 +6,8 @@
 static int autocorrect;
 static struct cmdnames aliases;
 
-static int perf_unknown_cmd_config(const char *var, const char *value, void *cb)
+static int perf_unknown_cmd_config(const char *var, const char *value,
+                                  void *cb __maybe_unused)
 {
        if (!strcmp(var, "help.autocorrect"))
                autocorrect = perf_config_int(var,value);
@@ -14,7 +15,7 @@ static int perf_unknown_cmd_config(const char *var, const char *value, void *cb)
        if (!prefixcmp(var, "alias."))
                add_cmdname(&aliases, var + 6, strlen(var + 6));
 
-       return perf_default_config(var, value, cb);
+       return 0;
 }
 
 static int levenshtein_compare(const void *p1, const void *p2)
index 68a7612019dc3c3be315604693b68170183044d6..290b3cbf68772de883bff4fee5c2294234dbefd3 100644 (file)
@@ -179,6 +179,9 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
        if (h->transaction)
                hists__new_col_len(hists, HISTC_TRANSACTION,
                                   hist_entry__transaction_len());
+
+       if (h->trace_output)
+               hists__new_col_len(hists, HISTC_TRACE, strlen(h->trace_output));
 }
 
 void hists__output_recalc_col_len(struct hists *hists, int max_rows)
@@ -245,6 +248,8 @@ static void he_stat__decay(struct he_stat *he_stat)
        /* XXX need decay for weight too? */
 }
 
+static void hists__delete_entry(struct hists *hists, struct hist_entry *he);
+
 static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
 {
        u64 prev_period = he->stat.period;
@@ -260,21 +265,45 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
 
        diff = prev_period - he->stat.period;
 
-       hists->stats.total_period -= diff;
-       if (!he->filtered)
-               hists->stats.total_non_filtered_period -= diff;
+       if (!he->depth) {
+               hists->stats.total_period -= diff;
+               if (!he->filtered)
+                       hists->stats.total_non_filtered_period -= diff;
+       }
+
+       if (!he->leaf) {
+               struct hist_entry *child;
+               struct rb_node *node = rb_first(&he->hroot_out);
+               while (node) {
+                       child = rb_entry(node, struct hist_entry, rb_node);
+                       node = rb_next(node);
+
+                       if (hists__decay_entry(hists, child))
+                               hists__delete_entry(hists, child);
+               }
+       }
 
        return he->stat.period == 0;
 }
 
 static void hists__delete_entry(struct hists *hists, struct hist_entry *he)
 {
-       rb_erase(&he->rb_node, &hists->entries);
+       struct rb_root *root_in;
+       struct rb_root *root_out;
 
-       if (sort__need_collapse)
-               rb_erase(&he->rb_node_in, &hists->entries_collapsed);
-       else
-               rb_erase(&he->rb_node_in, hists->entries_in);
+       if (he->parent_he) {
+               root_in  = &he->parent_he->hroot_in;
+               root_out = &he->parent_he->hroot_out;
+       } else {
+               if (sort__need_collapse)
+                       root_in = &hists->entries_collapsed;
+               else
+                       root_in = hists->entries_in;
+               root_out = &hists->entries;
+       }
+
+       rb_erase(&he->rb_node_in, root_in);
+       rb_erase(&he->rb_node, root_out);
 
        --hists->nr_entries;
        if (!he->filtered)
@@ -393,6 +422,9 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
                }
                INIT_LIST_HEAD(&he->pairs.node);
                thread__get(he->thread);
+
+               if (!symbol_conf.report_hierarchy)
+                       he->leaf = true;
        }
 
        return he;
@@ -405,6 +437,16 @@ static u8 symbol__parent_filter(const struct symbol *parent)
        return 0;
 }
 
+static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period)
+{
+       if (!symbol_conf.use_callchain)
+               return;
+
+       he->hists->callchain_period += period;
+       if (!he->filtered)
+               he->hists->callchain_non_filtered_period += period;
+}
+
 static struct hist_entry *hists__findnew_entry(struct hists *hists,
                                               struct hist_entry *entry,
                                               struct addr_location *al,
@@ -432,8 +474,10 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
                cmp = hist_entry__cmp(he, entry);
 
                if (!cmp) {
-                       if (sample_self)
+                       if (sample_self) {
                                he_stat__add_period(&he->stat, period, weight);
+                               hist_entry__add_callchain_period(he, period);
+                       }
                        if (symbol_conf.cumulate_callchain)
                                he_stat__add_period(he->stat_acc, period, weight);
 
@@ -466,6 +510,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
        if (!he)
                return NULL;
 
+       if (sample_self)
+               hist_entry__add_callchain_period(he, period);
        hists->nr_entries++;
 
        rb_link_node(&he->rb_node_in, parent, p);
@@ -951,10 +997,15 @@ out:
 int64_t
 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
 {
+       struct hists *hists = left->hists;
        struct perf_hpp_fmt *fmt;
        int64_t cmp = 0;
 
-       perf_hpp__for_each_sort_list(fmt) {
+       hists__for_each_sort_list(hists, fmt) {
+               if (perf_hpp__is_dynamic_entry(fmt) &&
+                   !perf_hpp__defined_dynamic_entry(fmt, hists))
+                       continue;
+
                cmp = fmt->cmp(fmt, left, right);
                if (cmp)
                        break;
@@ -966,10 +1017,15 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
 int64_t
 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
 {
+       struct hists *hists = left->hists;
        struct perf_hpp_fmt *fmt;
        int64_t cmp = 0;
 
-       perf_hpp__for_each_sort_list(fmt) {
+       hists__for_each_sort_list(hists, fmt) {
+               if (perf_hpp__is_dynamic_entry(fmt) &&
+                   !perf_hpp__defined_dynamic_entry(fmt, hists))
+                       continue;
+
                cmp = fmt->collapse(fmt, left, right);
                if (cmp)
                        break;
@@ -1005,18 +1061,251 @@ void hist_entry__delete(struct hist_entry *he)
        free(he);
 }
 
+/*
+ * If this is not the last column, then we need to pad it according to the
+ * pre-calculated max lenght for this column, otherwise don't bother adding
+ * spaces because that would break viewing this with, for instance, 'less',
+ * that would show tons of trailing spaces when a long C++ demangled method
+ * names is sampled.
+*/
+int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
+                                  struct perf_hpp_fmt *fmt, int printed)
+{
+       if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) {
+               const int width = fmt->width(fmt, hpp, hists_to_evsel(he->hists));
+               if (printed < width) {
+                       advance_hpp(hpp, printed);
+                       printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " ");
+               }
+       }
+
+       return printed;
+}
+
 /*
  * collapse the histogram
  */
 
-bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
-                                 struct rb_root *root, struct hist_entry *he)
+static void hists__apply_filters(struct hists *hists, struct hist_entry *he);
+static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *he,
+                                      enum hist_filter type);
+
+typedef bool (*fmt_chk_fn)(struct perf_hpp_fmt *fmt);
+
+static bool check_thread_entry(struct perf_hpp_fmt *fmt)
+{
+       return perf_hpp__is_thread_entry(fmt) || perf_hpp__is_comm_entry(fmt);
+}
+
+static void hist_entry__check_and_remove_filter(struct hist_entry *he,
+                                               enum hist_filter type,
+                                               fmt_chk_fn check)
+{
+       struct perf_hpp_fmt *fmt;
+       bool type_match = false;
+       struct hist_entry *parent = he->parent_he;
+
+       switch (type) {
+       case HIST_FILTER__THREAD:
+               if (symbol_conf.comm_list == NULL &&
+                   symbol_conf.pid_list == NULL &&
+                   symbol_conf.tid_list == NULL)
+                       return;
+               break;
+       case HIST_FILTER__DSO:
+               if (symbol_conf.dso_list == NULL)
+                       return;
+               break;
+       case HIST_FILTER__SYMBOL:
+               if (symbol_conf.sym_list == NULL)
+                       return;
+               break;
+       case HIST_FILTER__PARENT:
+       case HIST_FILTER__GUEST:
+       case HIST_FILTER__HOST:
+       case HIST_FILTER__SOCKET:
+       default:
+               return;
+       }
+
+       /* if it's filtered by own fmt, it has to have filter bits */
+       perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+               if (check(fmt)) {
+                       type_match = true;
+                       break;
+               }
+       }
+
+       if (type_match) {
+               /*
+                * If the filter is for current level entry, propagate
+                * filter marker to parents.  The marker bit was
+                * already set by default so it only needs to clear
+                * non-filtered entries.
+                */
+               if (!(he->filtered & (1 << type))) {
+                       while (parent) {
+                               parent->filtered &= ~(1 << type);
+                               parent = parent->parent_he;
+                       }
+               }
+       } else {
+               /*
+                * If current entry doesn't have matching formats, set
+                * filter marker for upper level entries.  it will be
+                * cleared if its lower level entries is not filtered.
+                *
+                * For lower-level entries, it inherits parent's
+                * filter bit so that lower level entries of a
+                * non-filtered entry won't set the filter marker.
+                */
+               if (parent == NULL)
+                       he->filtered |= (1 << type);
+               else
+                       he->filtered |= (parent->filtered & (1 << type));
+       }
+}
+
+static void hist_entry__apply_hierarchy_filters(struct hist_entry *he)
+{
+       hist_entry__check_and_remove_filter(he, HIST_FILTER__THREAD,
+                                           check_thread_entry);
+
+       hist_entry__check_and_remove_filter(he, HIST_FILTER__DSO,
+                                           perf_hpp__is_dso_entry);
+
+       hist_entry__check_and_remove_filter(he, HIST_FILTER__SYMBOL,
+                                           perf_hpp__is_sym_entry);
+
+       hists__apply_filters(he->hists, he);
+}
+
+static struct hist_entry *hierarchy_insert_entry(struct hists *hists,
+                                                struct rb_root *root,
+                                                struct hist_entry *he,
+                                                struct hist_entry *parent_he,
+                                                struct perf_hpp_list *hpp_list)
+{
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
+       struct hist_entry *iter, *new;
+       struct perf_hpp_fmt *fmt;
+       int64_t cmp;
+
+       while (*p != NULL) {
+               parent = *p;
+               iter = rb_entry(parent, struct hist_entry, rb_node_in);
+
+               cmp = 0;
+               perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
+                       cmp = fmt->collapse(fmt, iter, he);
+                       if (cmp)
+                               break;
+               }
+
+               if (!cmp) {
+                       he_stat__add_stat(&iter->stat, &he->stat);
+                       return iter;
+               }
+
+               if (cmp < 0)
+                       p = &parent->rb_left;
+               else
+                       p = &parent->rb_right;
+       }
+
+       new = hist_entry__new(he, true);
+       if (new == NULL)
+               return NULL;
+
+       hists->nr_entries++;
+
+       /* save related format list for output */
+       new->hpp_list = hpp_list;
+       new->parent_he = parent_he;
+
+       hist_entry__apply_hierarchy_filters(new);
+
+       /* some fields are now passed to 'new' */
+       perf_hpp_list__for_each_sort_list(hpp_list, fmt) {
+               if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt))
+                       he->trace_output = NULL;
+               else
+                       new->trace_output = NULL;
+
+               if (perf_hpp__is_srcline_entry(fmt))
+                       he->srcline = NULL;
+               else
+                       new->srcline = NULL;
+
+               if (perf_hpp__is_srcfile_entry(fmt))
+                       he->srcfile = NULL;
+               else
+                       new->srcfile = NULL;
+       }
+
+       rb_link_node(&new->rb_node_in, parent, p);
+       rb_insert_color(&new->rb_node_in, root);
+       return new;
+}
+
+static int hists__hierarchy_insert_entry(struct hists *hists,
+                                        struct rb_root *root,
+                                        struct hist_entry *he)
+{
+       struct perf_hpp_list_node *node;
+       struct hist_entry *new_he = NULL;
+       struct hist_entry *parent = NULL;
+       int depth = 0;
+       int ret = 0;
+
+       list_for_each_entry(node, &hists->hpp_formats, list) {
+               /* skip period (overhead) and elided columns */
+               if (node->level == 0 || node->skip)
+                       continue;
+
+               /* insert copy of 'he' for each fmt into the hierarchy */
+               new_he = hierarchy_insert_entry(hists, root, he, parent, &node->hpp);
+               if (new_he == NULL) {
+                       ret = -1;
+                       break;
+               }
+
+               root = &new_he->hroot_in;
+               new_he->depth = depth++;
+               parent = new_he;
+       }
+
+       if (new_he) {
+               new_he->leaf = true;
+
+               if (symbol_conf.use_callchain) {
+                       callchain_cursor_reset(&callchain_cursor);
+                       if (callchain_merge(&callchain_cursor,
+                                           new_he->callchain,
+                                           he->callchain) < 0)
+                               ret = -1;
+               }
+       }
+
+       /* 'he' is no longer used */
+       hist_entry__delete(he);
+
+       /* return 0 (or -1) since it already applied filters */
+       return ret;
+}
+
+int hists__collapse_insert_entry(struct hists *hists, struct rb_root *root,
+                                struct hist_entry *he)
 {
        struct rb_node **p = &root->rb_node;
        struct rb_node *parent = NULL;
        struct hist_entry *iter;
        int64_t cmp;
 
+       if (symbol_conf.report_hierarchy)
+               return hists__hierarchy_insert_entry(hists, root, he);
+
        while (*p != NULL) {
                parent = *p;
                iter = rb_entry(parent, struct hist_entry, rb_node_in);
@@ -1024,18 +1313,21 @@ bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
                cmp = hist_entry__collapse(iter, he);
 
                if (!cmp) {
+                       int ret = 0;
+
                        he_stat__add_stat(&iter->stat, &he->stat);
                        if (symbol_conf.cumulate_callchain)
                                he_stat__add_stat(iter->stat_acc, he->stat_acc);
 
                        if (symbol_conf.use_callchain) {
                                callchain_cursor_reset(&callchain_cursor);
-                               callchain_merge(&callchain_cursor,
-                                               iter->callchain,
-                                               he->callchain);
+                               if (callchain_merge(&callchain_cursor,
+                                                   iter->callchain,
+                                                   he->callchain) < 0)
+                                       ret = -1;
                        }
                        hist_entry__delete(he);
-                       return false;
+                       return ret;
                }
 
                if (cmp < 0)
@@ -1047,7 +1339,7 @@ bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
 
        rb_link_node(&he->rb_node_in, parent, p);
        rb_insert_color(&he->rb_node_in, root);
-       return true;
+       return 1;
 }
 
 struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
@@ -1073,14 +1365,15 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
        hists__filter_entry_by_socket(hists, he);
 }
 
-void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
+int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
 {
        struct rb_root *root;
        struct rb_node *next;
        struct hist_entry *n;
+       int ret;
 
        if (!sort__need_collapse)
-               return;
+               return 0;
 
        hists->nr_entries = 0;
 
@@ -1095,7 +1388,11 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
                next = rb_next(&n->rb_node_in);
 
                rb_erase(&n->rb_node_in, root);
-               if (hists__collapse_insert_entry(hists, &hists->entries_collapsed, n)) {
+               ret = hists__collapse_insert_entry(hists, &hists->entries_collapsed, n);
+               if (ret < 0)
+                       return -1;
+
+               if (ret) {
                        /*
                         * If it wasn't combined with one of the entries already
                         * collapsed, we need to apply the filters that may have
@@ -1106,14 +1403,16 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
                if (prog)
                        ui_progress__update(prog, 1);
        }
+       return 0;
 }
 
 static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
 {
+       struct hists *hists = a->hists;
        struct perf_hpp_fmt *fmt;
        int64_t cmp = 0;
 
-       perf_hpp__for_each_sort_list(fmt) {
+       hists__for_each_sort_list(hists, fmt) {
                if (perf_hpp__should_skip(fmt, a->hists))
                        continue;
 
@@ -1154,6 +1453,113 @@ void hists__inc_stats(struct hists *hists, struct hist_entry *h)
        hists->stats.total_period += h->stat.period;
 }
 
+static void hierarchy_recalc_total_periods(struct hists *hists)
+{
+       struct rb_node *node;
+       struct hist_entry *he;
+
+       node = rb_first(&hists->entries);
+
+       hists->stats.total_period = 0;
+       hists->stats.total_non_filtered_period = 0;
+
+       /*
+        * recalculate total period using top-level entries only
+        * since lower level entries only see non-filtered entries
+        * but upper level entries have sum of both entries.
+        */
+       while (node) {
+               he = rb_entry(node, struct hist_entry, rb_node);
+               node = rb_next(node);
+
+               hists->stats.total_period += he->stat.period;
+               if (!he->filtered)
+                       hists->stats.total_non_filtered_period += he->stat.period;
+       }
+}
+
+static void hierarchy_insert_output_entry(struct rb_root *root,
+                                         struct hist_entry *he)
+{
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
+       struct hist_entry *iter;
+       struct perf_hpp_fmt *fmt;
+
+       while (*p != NULL) {
+               parent = *p;
+               iter = rb_entry(parent, struct hist_entry, rb_node);
+
+               if (hist_entry__sort(he, iter) > 0)
+                       p = &parent->rb_left;
+               else
+                       p = &parent->rb_right;
+       }
+
+       rb_link_node(&he->rb_node, parent, p);
+       rb_insert_color(&he->rb_node, root);
+
+       /* update column width of dynamic entry */
+       perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
+               if (perf_hpp__is_dynamic_entry(fmt))
+                       fmt->sort(fmt, he, NULL);
+       }
+}
+
+static void hists__hierarchy_output_resort(struct hists *hists,
+                                          struct ui_progress *prog,
+                                          struct rb_root *root_in,
+                                          struct rb_root *root_out,
+                                          u64 min_callchain_hits,
+                                          bool use_callchain)
+{
+       struct rb_node *node;
+       struct hist_entry *he;
+
+       *root_out = RB_ROOT;
+       node = rb_first(root_in);
+
+       while (node) {
+               he = rb_entry(node, struct hist_entry, rb_node_in);
+               node = rb_next(node);
+
+               hierarchy_insert_output_entry(root_out, he);
+
+               if (prog)
+                       ui_progress__update(prog, 1);
+
+               if (!he->leaf) {
+                       hists__hierarchy_output_resort(hists, prog,
+                                                      &he->hroot_in,
+                                                      &he->hroot_out,
+                                                      min_callchain_hits,
+                                                      use_callchain);
+                       hists->nr_entries++;
+                       if (!he->filtered) {
+                               hists->nr_non_filtered_entries++;
+                               hists__calc_col_len(hists, he);
+                       }
+
+                       continue;
+               }
+
+               if (!use_callchain)
+                       continue;
+
+               if (callchain_param.mode == CHAIN_GRAPH_REL) {
+                       u64 total = he->stat.period;
+
+                       if (symbol_conf.cumulate_callchain)
+                               total = he->stat_acc->period;
+
+                       min_callchain_hits = total * (callchain_param.min_percent / 100);
+               }
+
+               callchain_param.sort(&he->sorted_chain, he->callchain,
+                                    min_callchain_hits, &callchain_param);
+       }
+}
+
 static void __hists__insert_output_entry(struct rb_root *entries,
                                         struct hist_entry *he,
                                         u64 min_callchain_hits,
@@ -1162,10 +1568,20 @@ static void __hists__insert_output_entry(struct rb_root *entries,
        struct rb_node **p = &entries->rb_node;
        struct rb_node *parent = NULL;
        struct hist_entry *iter;
+       struct perf_hpp_fmt *fmt;
+
+       if (use_callchain) {
+               if (callchain_param.mode == CHAIN_GRAPH_REL) {
+                       u64 total = he->stat.period;
+
+                       if (symbol_conf.cumulate_callchain)
+                               total = he->stat_acc->period;
 
-       if (use_callchain)
+                       min_callchain_hits = total * (callchain_param.min_percent / 100);
+               }
                callchain_param.sort(&he->sorted_chain, he->callchain,
                                      min_callchain_hits, &callchain_param);
+       }
 
        while (*p != NULL) {
                parent = *p;
@@ -1179,23 +1595,41 @@ static void __hists__insert_output_entry(struct rb_root *entries,
 
        rb_link_node(&he->rb_node, parent, p);
        rb_insert_color(&he->rb_node, entries);
+
+       perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) {
+               if (perf_hpp__is_dynamic_entry(fmt) &&
+                   perf_hpp__defined_dynamic_entry(fmt, he->hists))
+                       fmt->sort(fmt, he, NULL);  /* update column width */
+       }
 }
 
-void hists__output_resort(struct hists *hists, struct ui_progress *prog)
+static void output_resort(struct hists *hists, struct ui_progress *prog,
+                         bool use_callchain)
 {
        struct rb_root *root;
        struct rb_node *next;
        struct hist_entry *n;
+       u64 callchain_total;
        u64 min_callchain_hits;
-       struct perf_evsel *evsel = hists_to_evsel(hists);
-       bool use_callchain;
 
-       if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph)
-               use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN;
-       else
-               use_callchain = symbol_conf.use_callchain;
+       callchain_total = hists->callchain_period;
+       if (symbol_conf.filter_relative)
+               callchain_total = hists->callchain_non_filtered_period;
 
-       min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
+       min_callchain_hits = callchain_total * (callchain_param.min_percent / 100);
+
+       hists__reset_stats(hists);
+       hists__reset_col_len(hists);
+
+       if (symbol_conf.report_hierarchy) {
+               hists__hierarchy_output_resort(hists, prog,
+                                              &hists->entries_collapsed,
+                                              &hists->entries,
+                                              min_callchain_hits,
+                                              use_callchain);
+               hierarchy_recalc_total_periods(hists);
+               return;
+       }
 
        if (sort__need_collapse)
                root = &hists->entries_collapsed;
@@ -1205,9 +1639,6 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog)
        next = rb_first(root);
        hists->entries = RB_ROOT;
 
-       hists__reset_stats(hists);
-       hists__reset_col_len(hists);
-
        while (next) {
                n = rb_entry(next, struct hist_entry, rb_node_in);
                next = rb_next(&n->rb_node_in);
@@ -1223,15 +1654,136 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog)
        }
 }
 
+void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog)
+{
+       bool use_callchain;
+
+       if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph)
+               use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN;
+       else
+               use_callchain = symbol_conf.use_callchain;
+
+       output_resort(evsel__hists(evsel), prog, use_callchain);
+}
+
+void hists__output_resort(struct hists *hists, struct ui_progress *prog)
+{
+       output_resort(hists, prog, symbol_conf.use_callchain);
+}
+
+static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd)
+{
+       if (he->leaf || hmd == HMD_FORCE_SIBLING)
+               return false;
+
+       if (he->unfolded || hmd == HMD_FORCE_CHILD)
+               return true;
+
+       return false;
+}
+
+struct rb_node *rb_hierarchy_last(struct rb_node *node)
+{
+       struct hist_entry *he = rb_entry(node, struct hist_entry, rb_node);
+
+       while (can_goto_child(he, HMD_NORMAL)) {
+               node = rb_last(&he->hroot_out);
+               he = rb_entry(node, struct hist_entry, rb_node);
+       }
+       return node;
+}
+
+struct rb_node *__rb_hierarchy_next(struct rb_node *node, enum hierarchy_move_dir hmd)
+{
+       struct hist_entry *he = rb_entry(node, struct hist_entry, rb_node);
+
+       if (can_goto_child(he, hmd))
+               node = rb_first(&he->hroot_out);
+       else
+               node = rb_next(node);
+
+       while (node == NULL) {
+               he = he->parent_he;
+               if (he == NULL)
+                       break;
+
+               node = rb_next(&he->rb_node);
+       }
+       return node;
+}
+
+struct rb_node *rb_hierarchy_prev(struct rb_node *node)
+{
+       struct hist_entry *he = rb_entry(node, struct hist_entry, rb_node);
+
+       node = rb_prev(node);
+       if (node)
+               return rb_hierarchy_last(node);
+
+       he = he->parent_he;
+       if (he == NULL)
+               return NULL;
+
+       return &he->rb_node;
+}
+
+bool hist_entry__has_hierarchy_children(struct hist_entry *he, float limit)
+{
+       struct rb_node *node;
+       struct hist_entry *child;
+       float percent;
+
+       if (he->leaf)
+               return false;
+
+       node = rb_first(&he->hroot_out);
+       child = rb_entry(node, struct hist_entry, rb_node);
+
+       while (node && child->filtered) {
+               node = rb_next(node);
+               child = rb_entry(node, struct hist_entry, rb_node);
+       }
+
+       if (node)
+               percent = hist_entry__get_percent_limit(child);
+       else
+               percent = 0;
+
+       return node && percent >= limit;
+}
+
 static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
                                       enum hist_filter filter)
 {
        h->filtered &= ~(1 << filter);
+
+       if (symbol_conf.report_hierarchy) {
+               struct hist_entry *parent = h->parent_he;
+
+               while (parent) {
+                       he_stat__add_stat(&parent->stat, &h->stat);
+
+                       parent->filtered &= ~(1 << filter);
+
+                       if (parent->filtered)
+                               goto next;
+
+                       /* force fold unfiltered entry for simplicity */
+                       parent->unfolded = false;
+                       parent->has_no_entry = false;
+                       parent->row_offset = 0;
+                       parent->nr_rows = 0;
+next:
+                       parent = parent->parent_he;
+               }
+       }
+
        if (h->filtered)
                return;
 
        /* force fold unfiltered entry for simplicity */
        h->unfolded = false;
+       h->has_no_entry = false;
        h->row_offset = 0;
        h->nr_rows = 0;
 
@@ -1254,28 +1806,6 @@ static bool hists__filter_entry_by_dso(struct hists *hists,
        return false;
 }
 
-void hists__filter_by_dso(struct hists *hists)
-{
-       struct rb_node *nd;
-
-       hists->stats.nr_non_filtered_samples = 0;
-
-       hists__reset_filter_stats(hists);
-       hists__reset_col_len(hists);
-
-       for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
-               struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
-
-               if (symbol_conf.exclude_other && !h->parent)
-                       continue;
-
-               if (hists__filter_entry_by_dso(hists, h))
-                       continue;
-
-               hists__remove_entry_filter(hists, h, HIST_FILTER__DSO);
-       }
-}
-
 static bool hists__filter_entry_by_thread(struct hists *hists,
                                          struct hist_entry *he)
 {
@@ -1288,25 +1818,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
        return false;
 }
 
-void hists__filter_by_thread(struct hists *hists)
-{
-       struct rb_node *nd;
-
-       hists->stats.nr_non_filtered_samples = 0;
-
-       hists__reset_filter_stats(hists);
-       hists__reset_col_len(hists);
-
-       for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
-               struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
-
-               if (hists__filter_entry_by_thread(hists, h))
-                       continue;
-
-               hists__remove_entry_filter(hists, h, HIST_FILTER__THREAD);
-       }
-}
-
 static bool hists__filter_entry_by_symbol(struct hists *hists,
                                          struct hist_entry *he)
 {
@@ -1320,7 +1831,21 @@ static bool hists__filter_entry_by_symbol(struct hists *hists,
        return false;
 }
 
-void hists__filter_by_symbol(struct hists *hists)
+static bool hists__filter_entry_by_socket(struct hists *hists,
+                                         struct hist_entry *he)
+{
+       if ((hists->socket_filter > -1) &&
+           (he->socket != hists->socket_filter)) {
+               he->filtered |= (1 << HIST_FILTER__SOCKET);
+               return true;
+       }
+
+       return false;
+}
+
+typedef bool (*filter_fn_t)(struct hists *hists, struct hist_entry *he);
+
+static void hists__filter_by_type(struct hists *hists, int type, filter_fn_t filter)
 {
        struct rb_node *nd;
 
@@ -1332,42 +1857,155 @@ void hists__filter_by_symbol(struct hists *hists)
        for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
 
-               if (hists__filter_entry_by_symbol(hists, h))
+               if (filter(hists, h))
                        continue;
 
-               hists__remove_entry_filter(hists, h, HIST_FILTER__SYMBOL);
+               hists__remove_entry_filter(hists, h, type);
        }
 }
 
-static bool hists__filter_entry_by_socket(struct hists *hists,
-                                         struct hist_entry *he)
+static void resort_filtered_entry(struct rb_root *root, struct hist_entry *he)
 {
-       if ((hists->socket_filter > -1) &&
-           (he->socket != hists->socket_filter)) {
-               he->filtered |= (1 << HIST_FILTER__SOCKET);
-               return true;
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
+       struct hist_entry *iter;
+       struct rb_root new_root = RB_ROOT;
+       struct rb_node *nd;
+
+       while (*p != NULL) {
+               parent = *p;
+               iter = rb_entry(parent, struct hist_entry, rb_node);
+
+               if (hist_entry__sort(he, iter) > 0)
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
        }
 
-       return false;
+       rb_link_node(&he->rb_node, parent, p);
+       rb_insert_color(&he->rb_node, root);
+
+       if (he->leaf || he->filtered)
+               return;
+
+       nd = rb_first(&he->hroot_out);
+       while (nd) {
+               struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+
+               nd = rb_next(nd);
+               rb_erase(&h->rb_node, &he->hroot_out);
+
+               resort_filtered_entry(&new_root, h);
+       }
+
+       he->hroot_out = new_root;
 }
 
-void hists__filter_by_socket(struct hists *hists)
+static void hists__filter_hierarchy(struct hists *hists, int type, const void *arg)
 {
        struct rb_node *nd;
+       struct rb_root new_root = RB_ROOT;
 
        hists->stats.nr_non_filtered_samples = 0;
 
        hists__reset_filter_stats(hists);
        hists__reset_col_len(hists);
 
-       for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
+       nd = rb_first(&hists->entries);
+       while (nd) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+               int ret;
 
-               if (hists__filter_entry_by_socket(hists, h))
-                       continue;
+               ret = hist_entry__filter(h, type, arg);
 
-               hists__remove_entry_filter(hists, h, HIST_FILTER__SOCKET);
+               /*
+                * case 1. non-matching type
+                * zero out the period, set filter marker and move to child
+                */
+               if (ret < 0) {
+                       memset(&h->stat, 0, sizeof(h->stat));
+                       h->filtered |= (1 << type);
+
+                       nd = __rb_hierarchy_next(&h->rb_node, HMD_FORCE_CHILD);
+               }
+               /*
+                * case 2. matched type (filter out)
+                * set filter marker and move to next
+                */
+               else if (ret == 1) {
+                       h->filtered |= (1 << type);
+
+                       nd = __rb_hierarchy_next(&h->rb_node, HMD_FORCE_SIBLING);
+               }
+               /*
+                * case 3. ok (not filtered)
+                * add period to hists and parents, erase the filter marker
+                * and move to next sibling
+                */
+               else {
+                       hists__remove_entry_filter(hists, h, type);
+
+                       nd = __rb_hierarchy_next(&h->rb_node, HMD_FORCE_SIBLING);
+               }
+       }
+
+       hierarchy_recalc_total_periods(hists);
+
+       /*
+        * resort output after applying a new filter since filter in a lower
+        * hierarchy can change periods in a upper hierarchy.
+        */
+       nd = rb_first(&hists->entries);
+       while (nd) {
+               struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+
+               nd = rb_next(nd);
+               rb_erase(&h->rb_node, &hists->entries);
+
+               resort_filtered_entry(&new_root, h);
        }
+
+       hists->entries = new_root;
+}
+
+void hists__filter_by_thread(struct hists *hists)
+{
+       if (symbol_conf.report_hierarchy)
+               hists__filter_hierarchy(hists, HIST_FILTER__THREAD,
+                                       hists->thread_filter);
+       else
+               hists__filter_by_type(hists, HIST_FILTER__THREAD,
+                                     hists__filter_entry_by_thread);
+}
+
+void hists__filter_by_dso(struct hists *hists)
+{
+       if (symbol_conf.report_hierarchy)
+               hists__filter_hierarchy(hists, HIST_FILTER__DSO,
+                                       hists->dso_filter);
+       else
+               hists__filter_by_type(hists, HIST_FILTER__DSO,
+                                     hists__filter_entry_by_dso);
+}
+
+void hists__filter_by_symbol(struct hists *hists)
+{
+       if (symbol_conf.report_hierarchy)
+               hists__filter_hierarchy(hists, HIST_FILTER__SYMBOL,
+                                       hists->symbol_filter_str);
+       else
+               hists__filter_by_type(hists, HIST_FILTER__SYMBOL,
+                                     hists__filter_entry_by_symbol);
+}
+
+void hists__filter_by_socket(struct hists *hists)
+{
+       if (symbol_conf.report_hierarchy)
+               hists__filter_hierarchy(hists, HIST_FILTER__SOCKET,
+                                       &hists->socket_filter);
+       else
+               hists__filter_by_type(hists, HIST_FILTER__SOCKET,
+                                     hists__filter_entry_by_socket);
 }
 
 void events_stats__inc(struct events_stats *stats, u32 type)
@@ -1585,7 +2223,7 @@ int perf_hist_config(const char *var, const char *value)
        return 0;
 }
 
-int __hists__init(struct hists *hists)
+int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list)
 {
        memset(hists, 0, sizeof(*hists));
        hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
@@ -1594,6 +2232,8 @@ int __hists__init(struct hists *hists)
        hists->entries = RB_ROOT;
        pthread_mutex_init(&hists->lock, NULL);
        hists->socket_filter = -1;
+       hists->hpp_list = hpp_list;
+       INIT_LIST_HEAD(&hists->hpp_formats);
        return 0;
 }
 
@@ -1622,15 +2262,26 @@ static void hists__delete_all_entries(struct hists *hists)
 static void hists_evsel__exit(struct perf_evsel *evsel)
 {
        struct hists *hists = evsel__hists(evsel);
+       struct perf_hpp_fmt *fmt, *pos;
+       struct perf_hpp_list_node *node, *tmp;
 
        hists__delete_all_entries(hists);
+
+       list_for_each_entry_safe(node, tmp, &hists->hpp_formats, list) {
+               perf_hpp_list__for_each_format_safe(&node->hpp, fmt, pos) {
+                       list_del(&fmt->list);
+                       free(fmt);
+               }
+               list_del(&node->list);
+               free(node);
+       }
 }
 
 static int hists_evsel__init(struct perf_evsel *evsel)
 {
        struct hists *hists = evsel__hists(evsel);
 
-       __hists__init(hists);
+       __hists__init(hists, &perf_hpp_list);
        return 0;
 }
 
@@ -1649,3 +2300,9 @@ int hists__init(void)
 
        return err;
 }
+
+void perf_hpp_list__init(struct perf_hpp_list *list)
+{
+       INIT_LIST_HEAD(&list->fields);
+       INIT_LIST_HEAD(&list->sorts);
+}
index d4ec4822a1038611a7269aa0df2eb37171a647a6..ead18c82294faf881f1d4bc89be653e27ff5c708 100644 (file)
@@ -66,6 +66,8 @@ struct hists {
        struct rb_root          entries_collapsed;
        u64                     nr_entries;
        u64                     nr_non_filtered_entries;
+       u64                     callchain_period;
+       u64                     callchain_non_filtered_period;
        struct thread           *thread_filter;
        const struct dso        *dso_filter;
        const char              *uid_filter_str;
@@ -75,6 +77,9 @@ struct hists {
        u64                     event_stream;
        u16                     col_len[HISTC_NR_COLS];
        int                     socket_filter;
+       struct perf_hpp_list    *hpp_list;
+       struct list_head        hpp_formats;
+       int                     nr_hpp_node;
 };
 
 struct hist_entry_iter;
@@ -121,15 +126,21 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
 int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
                         int max_stack_depth, void *arg);
 
+struct perf_hpp;
+struct perf_hpp_fmt;
+
 int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
 int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
 int hist_entry__transaction_len(void);
 int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
                              struct hists *hists);
+int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
+                                  struct perf_hpp_fmt *fmt, int printed);
 void hist_entry__delete(struct hist_entry *he);
 
+void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog);
 void hists__output_resort(struct hists *hists, struct ui_progress *prog);
-void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
+int hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
 
 void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
 void hists__delete_entries(struct hists *hists);
@@ -185,10 +196,10 @@ static inline struct hists *evsel__hists(struct perf_evsel *evsel)
 }
 
 int hists__init(void);
-int __hists__init(struct hists *hists);
+int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list);
 
 struct rb_root *hists__get_rotate_entries_in(struct hists *hists);
-bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
+int hists__collapse_insert_entry(struct hists *hists,
                                  struct rb_root *root, struct hist_entry *he);
 
 struct perf_hpp {
@@ -214,28 +225,64 @@ struct perf_hpp_fmt {
                            struct hist_entry *a, struct hist_entry *b);
        int64_t (*sort)(struct perf_hpp_fmt *fmt,
                        struct hist_entry *a, struct hist_entry *b);
+       bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b);
+       void (*free)(struct perf_hpp_fmt *fmt);
 
        struct list_head list;
        struct list_head sort_list;
        bool elide;
        int len;
        int user_len;
+       int idx;
+       int level;
+};
+
+struct perf_hpp_list {
+       struct list_head fields;
+       struct list_head sorts;
 };
 
-extern struct list_head perf_hpp__list;
-extern struct list_head perf_hpp__sort_list;
+extern struct perf_hpp_list perf_hpp_list;
+
+struct perf_hpp_list_node {
+       struct list_head        list;
+       struct perf_hpp_list    hpp;
+       int                     level;
+       bool                    skip;
+};
+
+void perf_hpp_list__column_register(struct perf_hpp_list *list,
+                                   struct perf_hpp_fmt *format);
+void perf_hpp_list__register_sort_field(struct perf_hpp_list *list,
+                                       struct perf_hpp_fmt *format);
+
+static inline void perf_hpp__column_register(struct perf_hpp_fmt *format)
+{
+       perf_hpp_list__column_register(&perf_hpp_list, format);
+}
+
+static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format)
+{
+       perf_hpp_list__register_sort_field(&perf_hpp_list, format);
+}
+
+#define perf_hpp_list__for_each_format(_list, format) \
+       list_for_each_entry(format, &(_list)->fields, list)
 
-#define perf_hpp__for_each_format(format) \
-       list_for_each_entry(format, &perf_hpp__list, list)
+#define perf_hpp_list__for_each_format_safe(_list, format, tmp)        \
+       list_for_each_entry_safe(format, tmp, &(_list)->fields, list)
 
-#define perf_hpp__for_each_format_safe(format, tmp)    \
-       list_for_each_entry_safe(format, tmp, &perf_hpp__list, list)
+#define perf_hpp_list__for_each_sort_list(_list, format) \
+       list_for_each_entry(format, &(_list)->sorts, sort_list)
 
-#define perf_hpp__for_each_sort_list(format) \
-       list_for_each_entry(format, &perf_hpp__sort_list, sort_list)
+#define perf_hpp_list__for_each_sort_list_safe(_list, format, tmp)     \
+       list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list)
 
-#define perf_hpp__for_each_sort_list_safe(format, tmp) \
-       list_for_each_entry_safe(format, tmp, &perf_hpp__sort_list, sort_list)
+#define hists__for_each_format(hists, format) \
+       perf_hpp_list__for_each_format((hists)->hpp_list, fmt)
+
+#define hists__for_each_sort_list(hists, format) \
+       perf_hpp_list__for_each_sort_list((hists)->hpp_list, fmt)
 
 extern struct perf_hpp_fmt perf_hpp__format[];
 
@@ -254,21 +301,29 @@ enum {
 };
 
 void perf_hpp__init(void);
-void perf_hpp__column_register(struct perf_hpp_fmt *format);
 void perf_hpp__column_unregister(struct perf_hpp_fmt *format);
-void perf_hpp__column_enable(unsigned col);
-void perf_hpp__column_disable(unsigned col);
 void perf_hpp__cancel_cumulate(void);
+void perf_hpp__setup_output_field(struct perf_hpp_list *list);
+void perf_hpp__reset_output_field(struct perf_hpp_list *list);
+void perf_hpp__append_sort_keys(struct perf_hpp_list *list);
+int perf_hpp__setup_hists_formats(struct perf_hpp_list *list,
+                                 struct perf_evlist *evlist);
 
-void perf_hpp__register_sort_field(struct perf_hpp_fmt *format);
-void perf_hpp__setup_output_field(void);
-void perf_hpp__reset_output_field(void);
-void perf_hpp__append_sort_keys(void);
 
 bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format);
-bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b);
 bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format);
 bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists);
+bool perf_hpp__is_trace_entry(struct perf_hpp_fmt *fmt);
+bool perf_hpp__is_srcline_entry(struct perf_hpp_fmt *fmt);
+bool perf_hpp__is_srcfile_entry(struct perf_hpp_fmt *fmt);
+bool perf_hpp__is_thread_entry(struct perf_hpp_fmt *fmt);
+bool perf_hpp__is_comm_entry(struct perf_hpp_fmt *fmt);
+bool perf_hpp__is_dso_entry(struct perf_hpp_fmt *fmt);
+bool perf_hpp__is_sym_entry(struct perf_hpp_fmt *fmt);
+
+struct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt);
+
+int hist_entry__filter(struct hist_entry *he, int type, const void *arg);
 
 static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format,
                                         struct hists *hists)
@@ -372,6 +427,7 @@ static inline int script_browse(const char *script_opt __maybe_unused)
 #endif
 
 unsigned int hists__sort_list_width(struct hists *hists);
+unsigned int hists__overhead_width(struct hists *hists);
 
 void hist__account_cycles(struct branch_stack *bs, struct addr_location *al,
                          struct perf_sample *sample, bool nonany_branch_mode);
@@ -381,4 +437,26 @@ int parse_filter_percentage(const struct option *opt __maybe_unused,
                            const char *arg, int unset __maybe_unused);
 int perf_hist_config(const char *var, const char *value);
 
+void perf_hpp_list__init(struct perf_hpp_list *list);
+
+enum hierarchy_move_dir {
+       HMD_NORMAL,
+       HMD_FORCE_SIBLING,
+       HMD_FORCE_CHILD,
+};
+
+struct rb_node *rb_hierarchy_last(struct rb_node *node);
+struct rb_node *__rb_hierarchy_next(struct rb_node *node,
+                                   enum hierarchy_move_dir hmd);
+struct rb_node *rb_hierarchy_prev(struct rb_node *node);
+
+static inline struct rb_node *rb_hierarchy_next(struct rb_node *node)
+{
+       return __rb_hierarchy_next(node, HMD_NORMAL);
+}
+
+#define HIERARCHY_INDENT  3
+
+bool hist_entry__has_hierarchy_children(struct hist_entry *he, float limit);
+
 #endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/jit.h b/tools/perf/util/jit.h
new file mode 100644 (file)
index 0000000..a1e99da
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __JIT_H__
+#define __JIT_H__
+
+#include <data.h>
+
+extern int jit_process(struct perf_session *session,
+                      struct perf_data_file *output,
+                      struct machine *machine,
+                      char *filename,
+                      pid_t pid,
+                      u64 *nbytes);
+
+extern int jit_inject_record(const char *filename);
+
+#endif /* __JIT_H__ */
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
new file mode 100644 (file)
index 0000000..cd272cc
--- /dev/null
@@ -0,0 +1,697 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <byteswap.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "util.h"
+#include "event.h"
+#include "debug.h"
+#include "evlist.h"
+#include "symbol.h"
+#include "strlist.h"
+#include <elf.h>
+
+#include "session.h"
+#include "jit.h"
+#include "jitdump.h"
+#include "genelf.h"
+#include "../builtin.h"
+
+struct jit_buf_desc {
+       struct perf_data_file *output;
+       struct perf_session *session;
+       struct machine *machine;
+       union jr_entry   *entry;
+       void             *buf;
+       uint64_t         sample_type;
+       size_t           bufsize;
+       FILE             *in;
+       bool             needs_bswap; /* handles cross-endianess */
+       void             *debug_data;
+       size_t           nr_debug_entries;
+       uint32_t         code_load_count;
+       u64              bytes_written;
+       struct rb_root   code_root;
+       char             dir[PATH_MAX];
+};
+
+struct debug_line_info {
+       unsigned long vma;
+       unsigned int lineno;
+       /* The filename format is unspecified, absolute path, relative etc. */
+       char const filename[0];
+};
+
+struct jit_tool {
+       struct perf_tool tool;
+       struct perf_data_file   output;
+       struct perf_data_file   input;
+       u64 bytes_written;
+};
+
+#define hmax(a, b) ((a) > (b) ? (a) : (b))
+#define get_jit_tool(t) (container_of(tool, struct jit_tool, tool))
+
+static int
+jit_emit_elf(char *filename,
+            const char *sym,
+            uint64_t code_addr,
+            const void *code,
+            int csize,
+            void *debug,
+            int nr_debug_entries)
+{
+       int ret, fd;
+
+       if (verbose > 0)
+               fprintf(stderr, "write ELF image %s\n", filename);
+
+       fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
+       if (fd == -1) {
+               pr_warning("cannot create jit ELF %s: %s\n", filename, strerror(errno));
+               return -1;
+       }
+
+        ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries);
+
+        close(fd);
+
+        if (ret)
+                unlink(filename);
+
+       return ret;
+}
+
+static void
+jit_close(struct jit_buf_desc *jd)
+{
+       if (!(jd && jd->in))
+               return;
+       funlockfile(jd->in);
+       fclose(jd->in);
+       jd->in = NULL;
+}
+
+static int
+jit_validate_events(struct perf_session *session)
+{
+       struct perf_evsel *evsel;
+
+       /*
+        * check that all events use CLOCK_MONOTONIC
+        */
+       evlist__for_each(session->evlist, evsel) {
+               if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC)
+                       return -1;
+       }
+       return 0;
+}
+
+static int
+jit_open(struct jit_buf_desc *jd, const char *name)
+{
+       struct jitheader header;
+       struct jr_prefix *prefix;
+       ssize_t bs, bsz = 0;
+       void *n, *buf = NULL;
+       int ret, retval = -1;
+
+       jd->in = fopen(name, "r");
+       if (!jd->in)
+               return -1;
+
+       bsz = hmax(sizeof(header), sizeof(*prefix));
+
+       buf = malloc(bsz);
+       if (!buf)
+               goto error;
+
+       /*
+        * protect from writer modifying the file while we are reading it
+        */
+       flockfile(jd->in);
+
+       ret = fread(buf, sizeof(header), 1, jd->in);
+       if (ret != 1)
+               goto error;
+
+       memcpy(&header, buf, sizeof(header));
+
+       if (header.magic != JITHEADER_MAGIC) {
+               if (header.magic != JITHEADER_MAGIC_SW)
+                       goto error;
+               jd->needs_bswap = true;
+       }
+
+       if (jd->needs_bswap) {
+               header.version    = bswap_32(header.version);
+               header.total_size = bswap_32(header.total_size);
+               header.pid        = bswap_32(header.pid);
+               header.elf_mach   = bswap_32(header.elf_mach);
+               header.timestamp  = bswap_64(header.timestamp);
+               header.flags      = bswap_64(header.flags);
+       }
+
+       if (verbose > 2)
+               pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n",
+                       header.version,
+                       header.total_size,
+                       (unsigned long long)header.timestamp,
+                       header.pid,
+                       header.elf_mach);
+
+       if (header.flags & JITDUMP_FLAGS_RESERVED) {
+               pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
+                      (unsigned long long)header.flags & JITDUMP_FLAGS_RESERVED);
+               goto error;
+       }
+
+       /*
+        * validate event is using the correct clockid
+        */
+       if (jit_validate_events(jd->session)) {
+               pr_err("error, jitted code must be sampled with perf record -k 1\n");
+               goto error;
+       }
+
+       bs = header.total_size - sizeof(header);
+
+       if (bs > bsz) {
+               n = realloc(buf, bs);
+               if (!n)
+                       goto error;
+               bsz = bs;
+               buf = n;
+               /* read extra we do not know about */
+               ret = fread(buf, bs - bsz, 1, jd->in);
+               if (ret != 1)
+                       goto error;
+       }
+       /*
+        * keep dirname for generating files and mmap records
+        */
+       strcpy(jd->dir, name);
+       dirname(jd->dir);
+
+       return 0;
+error:
+       funlockfile(jd->in);
+       fclose(jd->in);
+       return retval;
+}
+
+static union jr_entry *
+jit_get_next_entry(struct jit_buf_desc *jd)
+{
+       struct jr_prefix *prefix;
+       union jr_entry *jr;
+       void *addr;
+       size_t bs, size;
+       int id, ret;
+
+       if (!(jd && jd->in))
+               return NULL;
+
+       if (jd->buf == NULL) {
+               size_t sz = getpagesize();
+               if (sz < sizeof(*prefix))
+                       sz = sizeof(*prefix);
+
+               jd->buf = malloc(sz);
+               if (jd->buf == NULL)
+                       return NULL;
+
+               jd->bufsize = sz;
+       }
+
+       prefix = jd->buf;
+
+       /*
+        * file is still locked at this point
+        */
+       ret = fread(prefix, sizeof(*prefix), 1, jd->in);
+       if (ret  != 1)
+               return NULL;
+
+       if (jd->needs_bswap) {
+               prefix->id         = bswap_32(prefix->id);
+               prefix->total_size = bswap_32(prefix->total_size);
+               prefix->timestamp  = bswap_64(prefix->timestamp);
+       }
+       id   = prefix->id;
+       size = prefix->total_size;
+
+       bs = (size_t)size;
+       if (bs < sizeof(*prefix))
+               return NULL;
+
+       if (id >= JIT_CODE_MAX) {
+               pr_warning("next_entry: unknown prefix %d, skipping\n", id);
+               return NULL;
+       }
+       if (bs > jd->bufsize) {
+               void *n;
+               n = realloc(jd->buf, bs);
+               if (!n)
+                       return NULL;
+               jd->buf = n;
+               jd->bufsize = bs;
+       }
+
+       addr = ((void *)jd->buf) + sizeof(*prefix);
+
+       ret = fread(addr, bs - sizeof(*prefix), 1, jd->in);
+       if (ret != 1)
+               return NULL;
+
+       jr = (union jr_entry *)jd->buf;
+
+       switch(id) {
+       case JIT_CODE_DEBUG_INFO:
+               if (jd->needs_bswap) {
+                       uint64_t n;
+                       jr->info.code_addr = bswap_64(jr->info.code_addr);
+                       jr->info.nr_entry  = bswap_64(jr->info.nr_entry);
+                       for (n = 0 ; n < jr->info.nr_entry; n++) {
+                               jr->info.entries[n].addr    = bswap_64(jr->info.entries[n].addr);
+                               jr->info.entries[n].lineno  = bswap_32(jr->info.entries[n].lineno);
+                               jr->info.entries[n].discrim = bswap_32(jr->info.entries[n].discrim);
+                       }
+               }
+               break;
+       case JIT_CODE_CLOSE:
+               break;
+       case JIT_CODE_LOAD:
+               if (jd->needs_bswap) {
+                       jr->load.pid       = bswap_32(jr->load.pid);
+                       jr->load.tid       = bswap_32(jr->load.tid);
+                       jr->load.vma       = bswap_64(jr->load.vma);
+                       jr->load.code_addr = bswap_64(jr->load.code_addr);
+                       jr->load.code_size = bswap_64(jr->load.code_size);
+                       jr->load.code_index= bswap_64(jr->load.code_index);
+               }
+               jd->code_load_count++;
+               break;
+       case JIT_CODE_MOVE:
+               if (jd->needs_bswap) {
+                       jr->move.pid           = bswap_32(jr->move.pid);
+                       jr->move.tid           = bswap_32(jr->move.tid);
+                       jr->move.vma           = bswap_64(jr->move.vma);
+                       jr->move.old_code_addr = bswap_64(jr->move.old_code_addr);
+                       jr->move.new_code_addr = bswap_64(jr->move.new_code_addr);
+                       jr->move.code_size     = bswap_64(jr->move.code_size);
+                       jr->move.code_index    = bswap_64(jr->move.code_index);
+               }
+               break;
+       case JIT_CODE_MAX:
+       default:
+               return NULL;
+       }
+       return jr;
+}
+
+static int
+jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
+{
+       ssize_t size;
+
+       size = perf_data_file__write(jd->output, event, event->header.size);
+       if (size < 0)
+               return -1;
+
+       jd->bytes_written += size;
+       return 0;
+}
+
+static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
+{
+       struct perf_sample sample;
+       union perf_event *event;
+       struct perf_tool *tool = jd->session->tool;
+       uint64_t code, addr;
+       uintptr_t uaddr;
+       char *filename;
+       struct stat st;
+       size_t size;
+       u16 idr_size;
+       const char *sym;
+       uint32_t count;
+       int ret, csize;
+       pid_t pid, tid;
+       struct {
+               u32 pid, tid;
+               u64 time;
+       } *id;
+
+       pid   = jr->load.pid;
+       tid   = jr->load.tid;
+       csize = jr->load.code_size;
+       addr  = jr->load.code_addr;
+       sym   = (void *)((unsigned long)jr + sizeof(jr->load));
+       code  = (unsigned long)jr + jr->load.p.total_size - csize;
+       count = jr->load.code_index;
+       idr_size = jd->machine->id_hdr_size;
+
+       event = calloc(1, sizeof(*event) + idr_size);
+       if (!event)
+               return -1;
+
+       filename = event->mmap2.filename;
+       size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%u.so",
+                       jd->dir,
+                       pid,
+                       count);
+
+       size++; /* for \0 */
+
+       size = PERF_ALIGN(size, sizeof(u64));
+       uaddr = (uintptr_t)code;
+       ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries);
+
+       if (jd->debug_data && jd->nr_debug_entries) {
+               free(jd->debug_data);
+               jd->debug_data = NULL;
+               jd->nr_debug_entries = 0;
+       }
+
+       if (ret) {
+               free(event);
+               return -1;
+       }
+       if (stat(filename, &st))
+               memset(&st, 0, sizeof(stat));
+
+       event->mmap2.header.type = PERF_RECORD_MMAP2;
+       event->mmap2.header.misc = PERF_RECORD_MISC_USER;
+       event->mmap2.header.size = (sizeof(event->mmap2) -
+                       (sizeof(event->mmap2.filename) - size) + idr_size);
+
+       event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;
+       event->mmap2.start = addr;
+       event->mmap2.len   = csize;
+       event->mmap2.pid   = pid;
+       event->mmap2.tid   = tid;
+       event->mmap2.ino   = st.st_ino;
+       event->mmap2.maj   = major(st.st_dev);
+       event->mmap2.min   = minor(st.st_dev);
+       event->mmap2.prot  = st.st_mode;
+       event->mmap2.flags = MAP_SHARED;
+       event->mmap2.ino_generation = 1;
+
+       id = (void *)((unsigned long)event + event->mmap.header.size - idr_size);
+       if (jd->sample_type & PERF_SAMPLE_TID) {
+               id->pid  = pid;
+               id->tid  = tid;
+       }
+       if (jd->sample_type & PERF_SAMPLE_TIME)
+               id->time = jr->load.p.timestamp;
+
+       /*
+        * create pseudo sample to induce dso hit increment
+        * use first address as sample address
+        */
+       memset(&sample, 0, sizeof(sample));
+       sample.pid  = pid;
+       sample.tid  = tid;
+       sample.time = id->time;
+       sample.ip   = addr;
+
+       ret = perf_event__process_mmap2(tool, event, &sample, jd->machine);
+       if (ret)
+               return ret;
+
+       ret = jit_inject_event(jd, event);
+       /*
+        * mark dso as use to generate buildid in the header
+        */
+       if (!ret)
+               build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine);
+
+       return ret;
+}
+
+static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
+{
+       struct perf_sample sample;
+       union perf_event *event;
+       struct perf_tool *tool = jd->session->tool;
+       char *filename;
+       size_t size;
+       struct stat st;
+       u16 idr_size;
+       int ret;
+       pid_t pid, tid;
+       struct {
+               u32 pid, tid;
+               u64 time;
+       } *id;
+
+       pid = jr->move.pid;
+       tid =  jr->move.tid;
+       idr_size = jd->machine->id_hdr_size;
+
+       /*
+        * +16 to account for sample_id_all (hack)
+        */
+       event = calloc(1, sizeof(*event) + 16);
+       if (!event)
+               return -1;
+
+       filename = event->mmap2.filename;
+       size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%"PRIu64,
+                jd->dir,
+                pid,
+                jr->move.code_index);
+
+       size++; /* for \0 */
+
+       if (stat(filename, &st))
+               memset(&st, 0, sizeof(stat));
+
+       size = PERF_ALIGN(size, sizeof(u64));
+
+       event->mmap2.header.type = PERF_RECORD_MMAP2;
+       event->mmap2.header.misc = PERF_RECORD_MISC_USER;
+       event->mmap2.header.size = (sizeof(event->mmap2) -
+                       (sizeof(event->mmap2.filename) - size) + idr_size);
+       event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;
+       event->mmap2.start = jr->move.new_code_addr;
+       event->mmap2.len   = jr->move.code_size;
+       event->mmap2.pid   = pid;
+       event->mmap2.tid   = tid;
+       event->mmap2.ino   = st.st_ino;
+       event->mmap2.maj   = major(st.st_dev);
+       event->mmap2.min   = minor(st.st_dev);
+       event->mmap2.prot  = st.st_mode;
+       event->mmap2.flags = MAP_SHARED;
+       event->mmap2.ino_generation = 1;
+
+       id = (void *)((unsigned long)event + event->mmap.header.size - idr_size);
+       if (jd->sample_type & PERF_SAMPLE_TID) {
+               id->pid  = pid;
+               id->tid  = tid;
+       }
+       if (jd->sample_type & PERF_SAMPLE_TIME)
+               id->time = jr->load.p.timestamp;
+
+       /*
+        * create pseudo sample to induce dso hit increment
+        * use first address as sample address
+        */
+       memset(&sample, 0, sizeof(sample));
+       sample.pid  = pid;
+       sample.tid  = tid;
+       sample.time = id->time;
+       sample.ip   = jr->move.new_code_addr;
+
+       ret = perf_event__process_mmap2(tool, event, &sample, jd->machine);
+       if (ret)
+               return ret;
+
+       ret = jit_inject_event(jd, event);
+       if (!ret)
+               build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine);
+
+       return ret;
+}
+
+static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr)
+{
+       void *data;
+       size_t sz;
+
+       if (!(jd && jr))
+               return -1;
+
+       sz  = jr->prefix.total_size - sizeof(jr->info);
+       data = malloc(sz);
+       if (!data)
+               return -1;
+
+       memcpy(data, &jr->info.entries, sz);
+
+       jd->debug_data       = data;
+
+       /*
+        * we must use nr_entry instead of size here because
+        * we cannot distinguish actual entry from padding otherwise
+        */
+       jd->nr_debug_entries = jr->info.nr_entry;
+
+       return 0;
+}
+
+static int
+jit_process_dump(struct jit_buf_desc *jd)
+{
+       union jr_entry *jr;
+       int ret;
+
+       while ((jr = jit_get_next_entry(jd))) {
+               switch(jr->prefix.id) {
+               case JIT_CODE_LOAD:
+                       ret = jit_repipe_code_load(jd, jr);
+                       break;
+               case JIT_CODE_MOVE:
+                       ret = jit_repipe_code_move(jd, jr);
+                       break;
+               case JIT_CODE_DEBUG_INFO:
+                       ret = jit_repipe_debug_info(jd, jr);
+                       break;
+               default:
+                       ret = 0;
+                       continue;
+               }
+       }
+       return ret;
+}
+
+static int
+jit_inject(struct jit_buf_desc *jd, char *path)
+{
+       int ret;
+
+       if (verbose > 0)
+               fprintf(stderr, "injecting: %s\n", path);
+
+       ret = jit_open(jd, path);
+       if (ret)
+               return -1;
+
+       ret = jit_process_dump(jd);
+
+       jit_close(jd);
+
+       if (verbose > 0)
+               fprintf(stderr, "injected: %s (%d)\n", path, ret);
+
+       return 0;
+}
+
+/*
+ * File must be with pattern .../jit-XXXX.dump
+ * where XXXX is the PID of the process which did the mmap()
+ * as captured in the RECORD_MMAP record
+ */
+static int
+jit_detect(char *mmap_name, pid_t pid)
+ {
+       char *p;
+       char *end = NULL;
+       pid_t pid2;
+
+       if (verbose > 2)
+               fprintf(stderr, "jit marker trying : %s\n", mmap_name);
+       /*
+        * get file name
+        */
+       p = strrchr(mmap_name, '/');
+       if (!p)
+               return -1;
+
+       /*
+        * match prefix
+        */
+       if (strncmp(p, "/jit-", 5))
+               return -1;
+
+       /*
+        * skip prefix
+        */
+       p += 5;
+
+       /*
+        * must be followed by a pid
+        */
+       if (!isdigit(*p))
+               return -1;
+
+       pid2 = (int)strtol(p, &end, 10);
+       if (!end)
+               return -1;
+
+       /*
+        * pid does not match mmap pid
+        * pid==0 in system-wide mode (synthesized)
+        */
+       if (pid && pid2 != pid)
+               return -1;
+       /*
+        * validate suffix
+        */
+       if (strcmp(end, ".dump"))
+               return -1;
+
+       if (verbose > 0)
+               fprintf(stderr, "jit marker found: %s\n", mmap_name);
+
+       return 0;
+}
+
+int
+jit_process(struct perf_session *session,
+           struct perf_data_file *output,
+           struct machine *machine,
+           char *filename,
+           pid_t pid,
+           u64 *nbytes)
+{
+       struct perf_evsel *first;
+       struct jit_buf_desc jd;
+       int ret;
+
+       /*
+        * first, detect marker mmap (i.e., the jitdump mmap)
+        */
+       if (jit_detect(filename, pid))
+               return 0;
+
+       memset(&jd, 0, sizeof(jd));
+
+       jd.session = session;
+       jd.output  = output;
+       jd.machine = machine;
+
+       /*
+        * track sample_type to compute id_all layout
+        * perf sets the same sample type to all events as of now
+        */
+       first = perf_evlist__first(session->evlist);
+       jd.sample_type = first->attr.sample_type;
+
+       *nbytes = 0;
+
+       ret = jit_inject(&jd, filename);
+       if (!ret) {
+               *nbytes = jd.bytes_written;
+               ret = 1;
+       }
+
+       return ret;
+}
diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h
new file mode 100644 (file)
index 0000000..b66c1f5
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * jitdump.h: jitted code info encapsulation file format
+ *
+ * Adapted from OProfile GPLv2 support jidump.h:
+ * Copyright 2007 OProfile authors
+ * Jens Wilke
+ * Daniel Hansel
+ * Copyright IBM Corporation 2007
+ */
+#ifndef JITDUMP_H
+#define JITDUMP_H
+
+#include <sys/time.h>
+#include <time.h>
+#include <stdint.h>
+
+/* JiTD */
+#define JITHEADER_MAGIC                0x4A695444
+#define JITHEADER_MAGIC_SW     0x4454694A
+
+#define PADDING_8ALIGNED(x) ((((x) + 7) & 7) ^ 7)
+
+#define JITHEADER_VERSION 1
+
+enum jitdump_flags_bits {
+       JITDUMP_FLAGS_MAX_BIT,
+};
+
+#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \
+                               (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0)
+
+struct jitheader {
+       uint32_t magic;         /* characters "jItD" */
+       uint32_t version;       /* header version */
+       uint32_t total_size;    /* total size of header */
+       uint32_t elf_mach;      /* elf mach target */
+       uint32_t pad1;          /* reserved */
+       uint32_t pid;           /* JIT process id */
+       uint64_t timestamp;     /* timestamp */
+       uint64_t flags;         /* flags */
+};
+
+enum jit_record_type {
+       JIT_CODE_LOAD           = 0,
+        JIT_CODE_MOVE           = 1,
+       JIT_CODE_DEBUG_INFO     = 2,
+       JIT_CODE_CLOSE          = 3,
+
+       JIT_CODE_MAX,
+};
+
+/* record prefix (mandatory in each record) */
+struct jr_prefix {
+       uint32_t id;
+       uint32_t total_size;
+       uint64_t timestamp;
+};
+
+struct jr_code_load {
+       struct jr_prefix p;
+
+       uint32_t pid;
+       uint32_t tid;
+       uint64_t vma;
+       uint64_t code_addr;
+       uint64_t code_size;
+       uint64_t code_index;
+};
+
+struct jr_code_close {
+       struct jr_prefix p;
+};
+
+struct jr_code_move {
+       struct jr_prefix p;
+
+       uint32_t pid;
+       uint32_t tid;
+       uint64_t vma;
+       uint64_t old_code_addr;
+       uint64_t new_code_addr;
+       uint64_t code_size;
+       uint64_t code_index;
+};
+
+struct debug_entry {
+       uint64_t addr;
+       int lineno;         /* source line number starting at 1 */
+       int discrim;        /* column discriminator, 0 is default */
+       const char name[0]; /* null terminated filename, \xff\0 if same as previous entry */
+};
+
+struct jr_code_debug_info {
+       struct jr_prefix p;
+
+       uint64_t code_addr;
+       uint64_t nr_entry;
+       struct debug_entry entries[0];
+};
+
+union jr_entry {
+        struct jr_code_debug_info info;
+        struct jr_code_close close;
+        struct jr_code_load load;
+        struct jr_code_move move;
+        struct jr_prefix prefix;
+};
+
+static inline struct debug_entry *
+debug_entry_next(struct debug_entry *ent)
+{
+       void *a = ent + 1;
+       size_t l = strlen(ent->name) + 1;
+       return a + l;
+}
+
+static inline char *
+debug_entry_file(struct debug_entry *ent)
+{
+       void *a = ent + 1;
+       return a;
+}
+
+#endif /* !JITDUMP_H */
index ae825d4ec110fcfe6a06ef5e4daf50b03a214a87..d01e73592f6e34347f0c26531b58aa6ce1d57d52 100644 (file)
@@ -122,6 +122,7 @@ void exit_event_decode_key(struct perf_kvm_stat *kvm,
 
 bool kvm_exit_event(struct perf_evsel *evsel);
 bool kvm_entry_event(struct perf_evsel *evsel);
+int setup_kvm_events_tp(struct perf_kvm_stat *kvm);
 
 #define define_exit_reasons_table(name, symbols)       \
        static struct exit_reasons_table name[] = {     \
@@ -133,8 +134,13 @@ bool kvm_entry_event(struct perf_evsel *evsel);
  */
 int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid);
 
-extern const char * const kvm_events_tp[];
+extern const char *kvm_events_tp[];
 extern struct kvm_reg_events_ops kvm_reg_events_ops[];
 extern const char * const kvm_skip_events[];
+extern const char *vcpu_id_str;
+extern const int decode_str_len;
+extern const char *kvm_exit_reason;
+extern const char *kvm_entry_trace;
+extern const char *kvm_exit_trace;
 
 #endif /* __PERF_KVM_STAT_H */
index 2c2b443df5ba796c43ee12c6c0f2061b5d7c7b80..1a3e45baf97fb575c02afe49707727aff0f628ec 100644 (file)
@@ -179,6 +179,16 @@ struct symbol *machine__find_kernel_symbol(struct machine *machine,
                                       mapp, filter);
 }
 
+static inline
+struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
+                                                  enum map_type type, const char *name,
+                                                  struct map **mapp,
+                                                  symbol_filter_t filter)
+{
+       return map_groups__find_symbol_by_name(&machine->kmaps, type, name,
+                                              mapp, filter);
+}
+
 static inline
 struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr,
                                             struct map **mapp,
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
new file mode 100644 (file)
index 0000000..75465f8
--- /dev/null
@@ -0,0 +1,255 @@
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <api/fs/fs.h>
+#include "mem-events.h"
+#include "debug.h"
+#include "symbol.h"
+
+#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
+
+struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
+       E("ldlat-loads",        "cpu/mem-loads,ldlat=30/P",     "mem-loads"),
+       E("ldlat-stores",       "cpu/mem-stores/P",             "mem-stores"),
+};
+#undef E
+
+#undef E
+
+char *perf_mem_events__name(int i)
+{
+       return (char *)perf_mem_events[i].name;
+}
+
+int perf_mem_events__parse(const char *str)
+{
+       char *tok, *saveptr = NULL;
+       bool found = false;
+       char *buf;
+       int j;
+
+       /* We need buffer that we know we can write to. */
+       buf = malloc(strlen(str) + 1);
+       if (!buf)
+               return -ENOMEM;
+
+       strcpy(buf, str);
+
+       tok = strtok_r((char *)buf, ",", &saveptr);
+
+       while (tok) {
+               for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
+                       struct perf_mem_event *e = &perf_mem_events[j];
+
+                       if (strstr(e->tag, tok))
+                               e->record = found = true;
+               }
+
+               tok = strtok_r(NULL, ",", &saveptr);
+       }
+
+       free(buf);
+
+       if (found)
+               return 0;
+
+       pr_err("failed: event '%s' not found, use '-e list' to get list of available events\n", str);
+       return -1;
+}
+
+int perf_mem_events__init(void)
+{
+       const char *mnt = sysfs__mount();
+       bool found = false;
+       int j;
+
+       if (!mnt)
+               return -ENOENT;
+
+       for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
+               char path[PATH_MAX];
+               struct perf_mem_event *e = &perf_mem_events[j];
+               struct stat st;
+
+               scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
+                         mnt, e->sysfs_name);
+
+               if (!stat(path, &st))
+                       e->supported = found = true;
+       }
+
+       return found ? 0 : -ENOENT;
+}
+
+static const char * const tlb_access[] = {
+       "N/A",
+       "HIT",
+       "MISS",
+       "L1",
+       "L2",
+       "Walker",
+       "Fault",
+};
+
+int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
+{
+       size_t l = 0, i;
+       u64 m = PERF_MEM_TLB_NA;
+       u64 hit, miss;
+
+       sz -= 1; /* -1 for null termination */
+       out[0] = '\0';
+
+       if (mem_info)
+               m = mem_info->data_src.mem_dtlb;
+
+       hit = m & PERF_MEM_TLB_HIT;
+       miss = m & PERF_MEM_TLB_MISS;
+
+       /* already taken care of */
+       m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
+
+       for (i = 0; m && i < ARRAY_SIZE(tlb_access); i++, m >>= 1) {
+               if (!(m & 0x1))
+                       continue;
+               if (l) {
+                       strcat(out, " or ");
+                       l += 4;
+               }
+               l += scnprintf(out + l, sz - l, tlb_access[i]);
+       }
+       if (*out == '\0')
+               l += scnprintf(out, sz - l, "N/A");
+       if (hit)
+               l += scnprintf(out + l, sz - l, " hit");
+       if (miss)
+               l += scnprintf(out + l, sz - l, " miss");
+
+       return l;
+}
+
+static const char * const mem_lvl[] = {
+       "N/A",
+       "HIT",
+       "MISS",
+       "L1",
+       "LFB",
+       "L2",
+       "L3",
+       "Local RAM",
+       "Remote RAM (1 hop)",
+       "Remote RAM (2 hops)",
+       "Remote Cache (1 hop)",
+       "Remote Cache (2 hops)",
+       "I/O",
+       "Uncached",
+};
+
+int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
+{
+       size_t i, l = 0;
+       u64 m =  PERF_MEM_LVL_NA;
+       u64 hit, miss;
+
+       if (mem_info)
+               m  = mem_info->data_src.mem_lvl;
+
+       sz -= 1; /* -1 for null termination */
+       out[0] = '\0';
+
+       hit = m & PERF_MEM_LVL_HIT;
+       miss = m & PERF_MEM_LVL_MISS;
+
+       /* already taken care of */
+       m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
+
+       for (i = 0; m && i < ARRAY_SIZE(mem_lvl); i++, m >>= 1) {
+               if (!(m & 0x1))
+                       continue;
+               if (l) {
+                       strcat(out, " or ");
+                       l += 4;
+               }
+               l += scnprintf(out + l, sz - l, mem_lvl[i]);
+       }
+       if (*out == '\0')
+               l += scnprintf(out, sz - l, "N/A");
+       if (hit)
+               l += scnprintf(out + l, sz - l, " hit");
+       if (miss)
+               l += scnprintf(out + l, sz - l, " miss");
+
+       return l;
+}
+
+static const char * const snoop_access[] = {
+       "N/A",
+       "None",
+       "Miss",
+       "Hit",
+       "HitM",
+};
+
+int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
+{
+       size_t i, l = 0;
+       u64 m = PERF_MEM_SNOOP_NA;
+
+       sz -= 1; /* -1 for null termination */
+       out[0] = '\0';
+
+       if (mem_info)
+               m = mem_info->data_src.mem_snoop;
+
+       for (i = 0; m && i < ARRAY_SIZE(snoop_access); i++, m >>= 1) {
+               if (!(m & 0x1))
+                       continue;
+               if (l) {
+                       strcat(out, " or ");
+                       l += 4;
+               }
+               l += scnprintf(out + l, sz - l, snoop_access[i]);
+       }
+
+       if (*out == '\0')
+               l += scnprintf(out, sz - l, "N/A");
+
+       return l;
+}
+
+int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
+{
+       u64 mask = PERF_MEM_LOCK_NA;
+       int l;
+
+       if (mem_info)
+               mask = mem_info->data_src.mem_lock;
+
+       if (mask & PERF_MEM_LOCK_NA)
+               l = scnprintf(out, sz, "N/A");
+       else if (mask & PERF_MEM_LOCK_LOCKED)
+               l = scnprintf(out, sz, "Yes");
+       else
+               l = scnprintf(out, sz, "No");
+
+       return l;
+}
+
+int perf_script__meminfo_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
+{
+       int i = 0;
+
+       i += perf_mem__lvl_scnprintf(out, sz, mem_info);
+       i += scnprintf(out + i, sz - i, "|SNP ");
+       i += perf_mem__snp_scnprintf(out + i, sz - i, mem_info);
+       i += scnprintf(out + i, sz - i, "|TLB ");
+       i += perf_mem__tlb_scnprintf(out + i, sz - i, mem_info);
+       i += scnprintf(out + i, sz - i, "|LCK ");
+       i += perf_mem__lck_scnprintf(out + i, sz - i, mem_info);
+
+       return i;
+}
diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h
new file mode 100644 (file)
index 0000000..5d6d930
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __PERF_MEM_EVENTS_H
+#define __PERF_MEM_EVENTS_H
+
+#include <stdbool.h>
+
+struct perf_mem_event {
+       bool            record;
+       bool            supported;
+       const char      *tag;
+       const char      *name;
+       const char      *sysfs_name;
+};
+
+enum {
+       PERF_MEM_EVENTS__LOAD,
+       PERF_MEM_EVENTS__STORE,
+       PERF_MEM_EVENTS__MAX,
+};
+
+extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX];
+
+int perf_mem_events__parse(const char *str);
+int perf_mem_events__init(void);
+
+char *perf_mem_events__name(int i);
+
+struct mem_info;
+int perf_mem__tlb_scnprintf(char *out, size_t sz, struct mem_info *mem_info);
+int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info);
+int perf_mem__snp_scnprintf(char *out, size_t sz, struct mem_info *mem_info);
+int perf_mem__lck_scnprintf(char *out, size_t sz, struct mem_info *mem_info);
+
+int perf_script__meminfo_scnprintf(char *bf, size_t size, struct mem_info *mem_info);
+
+#endif /* __PERF_MEM_EVENTS_H */
index 813d9b272c813b0dd749470f6209aa3a0a0607b4..4c19d5e79d8c4d626eb3fa91486cc1d83447aeeb 100644 (file)
@@ -279,7 +279,24 @@ const char *event_type(int type)
        return "unknown";
 }
 
+static int parse_events__is_name_term(struct parse_events_term *term)
+{
+       return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
+}
 
+static char *get_config_name(struct list_head *head_terms)
+{
+       struct parse_events_term *term;
+
+       if (!head_terms)
+               return NULL;
+
+       list_for_each_entry(term, head_terms, list)
+               if (parse_events__is_name_term(term))
+                       return term->val.str;
+
+       return NULL;
+}
 
 static struct perf_evsel *
 __add_event(struct list_head *list, int *idx,
@@ -333,11 +350,25 @@ static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES]
        return -1;
 }
 
+typedef int config_term_func_t(struct perf_event_attr *attr,
+                              struct parse_events_term *term,
+                              struct parse_events_error *err);
+static int config_term_common(struct perf_event_attr *attr,
+                             struct parse_events_term *term,
+                             struct parse_events_error *err);
+static int config_attr(struct perf_event_attr *attr,
+                      struct list_head *head,
+                      struct parse_events_error *err,
+                      config_term_func_t config_term);
+
 int parse_events_add_cache(struct list_head *list, int *idx,
-                          char *type, char *op_result1, char *op_result2)
+                          char *type, char *op_result1, char *op_result2,
+                          struct parse_events_error *err,
+                          struct list_head *head_config)
 {
        struct perf_event_attr attr;
-       char name[MAX_NAME_LEN];
+       LIST_HEAD(config_terms);
+       char name[MAX_NAME_LEN], *config_name;
        int cache_type = -1, cache_op = -1, cache_result = -1;
        char *op_result[2] = { op_result1, op_result2 };
        int i, n;
@@ -351,6 +382,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
        if (cache_type == -1)
                return -EINVAL;
 
+       config_name = get_config_name(head_config);
        n = snprintf(name, MAX_NAME_LEN, "%s", type);
 
        for (i = 0; (i < 2) && (op_result[i]); i++) {
@@ -391,7 +423,16 @@ int parse_events_add_cache(struct list_head *list, int *idx,
        memset(&attr, 0, sizeof(attr));
        attr.config = cache_type | (cache_op << 8) | (cache_result << 16);
        attr.type = PERF_TYPE_HW_CACHE;
-       return add_event(list, idx, &attr, name, NULL);
+
+       if (head_config) {
+               if (config_attr(&attr, head_config, err,
+                               config_term_common))
+                       return -EINVAL;
+
+               if (get_config_terms(head_config, &config_terms))
+                       return -ENOMEM;
+       }
+       return add_event(list, idx, &attr, config_name ? : name, &config_terms);
 }
 
 static void tracepoint_error(struct parse_events_error *e, int err,
@@ -540,6 +581,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
 struct __add_bpf_event_param {
        struct parse_events_evlist *data;
        struct list_head *list;
+       struct list_head *head_config;
 };
 
 static int add_bpf_event(struct probe_trace_event *tev, int fd,
@@ -556,7 +598,8 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
                 tev->group, tev->event, fd);
 
        err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group,
-                                         tev->event, evlist->error, NULL);
+                                         tev->event, evlist->error,
+                                         param->head_config);
        if (err) {
                struct perf_evsel *evsel, *tmp;
 
@@ -581,11 +624,12 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
 
 int parse_events_load_bpf_obj(struct parse_events_evlist *data,
                              struct list_head *list,
-                             struct bpf_object *obj)
+                             struct bpf_object *obj,
+                             struct list_head *head_config)
 {
        int err;
        char errbuf[BUFSIZ];
-       struct __add_bpf_event_param param = {data, list};
+       struct __add_bpf_event_param param = {data, list, head_config};
        static bool registered_unprobe_atexit = false;
 
        if (IS_ERR(obj) || !obj) {
@@ -631,17 +675,99 @@ errout:
        return err;
 }
 
+static int
+parse_events_config_bpf(struct parse_events_evlist *data,
+                       struct bpf_object *obj,
+                       struct list_head *head_config)
+{
+       struct parse_events_term *term;
+       int error_pos;
+
+       if (!head_config || list_empty(head_config))
+               return 0;
+
+       list_for_each_entry(term, head_config, list) {
+               char errbuf[BUFSIZ];
+               int err;
+
+               if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) {
+                       snprintf(errbuf, sizeof(errbuf),
+                                "Invalid config term for BPF object");
+                       errbuf[BUFSIZ - 1] = '\0';
+
+                       data->error->idx = term->err_term;
+                       data->error->str = strdup(errbuf);
+                       return -EINVAL;
+               }
+
+               err = bpf__config_obj(obj, term, data->evlist, &error_pos);
+               if (err) {
+                       bpf__strerror_config_obj(obj, term, data->evlist,
+                                                &error_pos, err, errbuf,
+                                                sizeof(errbuf));
+                       data->error->help = strdup(
+"Hint:\tValid config terms:\n"
+"     \tmap:[<arraymap>].value<indices>=[value]\n"
+"     \tmap:[<eventmap>].event<indices>=[event]\n"
+"\n"
+"     \twhere <indices> is something like [0,3...5] or [all]\n"
+"     \t(add -v to see detail)");
+                       data->error->str = strdup(errbuf);
+                       if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
+                               data->error->idx = term->err_val;
+                       else
+                               data->error->idx = term->err_term + error_pos;
+                       return err;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Split config terms:
+ * perf record -e bpf.c/call-graph=fp,map:array.value[0]=1/ ...
+ *  'call-graph=fp' is 'evt config', should be applied to each
+ *  events in bpf.c.
+ * 'map:array.value[0]=1' is 'obj config', should be processed
+ * with parse_events_config_bpf.
+ *
+ * Move object config terms from the first list to obj_head_config.
+ */
+static void
+split_bpf_config_terms(struct list_head *evt_head_config,
+                      struct list_head *obj_head_config)
+{
+       struct parse_events_term *term, *temp;
+
+       /*
+        * Currectly, all possible user config term
+        * belong to bpf object. parse_events__is_hardcoded_term()
+        * happends to be a good flag.
+        *
+        * See parse_events_config_bpf() and
+        * config_term_tracepoint().
+        */
+       list_for_each_entry_safe(term, temp, evt_head_config, list)
+               if (!parse_events__is_hardcoded_term(term))
+                       list_move_tail(&term->list, obj_head_config);
+}
+
 int parse_events_load_bpf(struct parse_events_evlist *data,
                          struct list_head *list,
                          char *bpf_file_name,
-                         bool source)
+                         bool source,
+                         struct list_head *head_config)
 {
+       int err;
        struct bpf_object *obj;
+       LIST_HEAD(obj_head_config);
+
+       if (head_config)
+               split_bpf_config_terms(head_config, &obj_head_config);
 
        obj = bpf__prepare_load(bpf_file_name, source);
        if (IS_ERR(obj)) {
                char errbuf[BUFSIZ];
-               int err;
 
                err = PTR_ERR(obj);
 
@@ -659,7 +785,18 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
                return err;
        }
 
-       return parse_events_load_bpf_obj(data, list, obj);
+       err = parse_events_load_bpf_obj(data, list, obj, head_config);
+       if (err)
+               return err;
+       err = parse_events_config_bpf(data, obj, &obj_head_config);
+
+       /*
+        * Caller doesn't know anything about obj_head_config,
+        * so combine them together again before returnning.
+        */
+       if (head_config)
+               list_splice_tail(&obj_head_config, head_config);
+       return err;
 }
 
 static int
@@ -746,9 +883,59 @@ static int check_type_val(struct parse_events_term *term,
        return -EINVAL;
 }
 
-typedef int config_term_func_t(struct perf_event_attr *attr,
-                              struct parse_events_term *term,
-                              struct parse_events_error *err);
+/*
+ * Update according to parse-events.l
+ */
+static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
+       [PARSE_EVENTS__TERM_TYPE_USER]                  = "<sysfs term>",
+       [PARSE_EVENTS__TERM_TYPE_CONFIG]                = "config",
+       [PARSE_EVENTS__TERM_TYPE_CONFIG1]               = "config1",
+       [PARSE_EVENTS__TERM_TYPE_CONFIG2]               = "config2",
+       [PARSE_EVENTS__TERM_TYPE_NAME]                  = "name",
+       [PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD]         = "period",
+       [PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ]           = "freq",
+       [PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE]    = "branch_type",
+       [PARSE_EVENTS__TERM_TYPE_TIME]                  = "time",
+       [PARSE_EVENTS__TERM_TYPE_CALLGRAPH]             = "call-graph",
+       [PARSE_EVENTS__TERM_TYPE_STACKSIZE]             = "stack-size",
+       [PARSE_EVENTS__TERM_TYPE_NOINHERIT]             = "no-inherit",
+       [PARSE_EVENTS__TERM_TYPE_INHERIT]               = "inherit",
+};
+
+static bool config_term_shrinked;
+
+static bool
+config_term_avail(int term_type, struct parse_events_error *err)
+{
+       if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) {
+               err->str = strdup("Invalid term_type");
+               return false;
+       }
+       if (!config_term_shrinked)
+               return true;
+
+       switch (term_type) {
+       case PARSE_EVENTS__TERM_TYPE_CONFIG:
+       case PARSE_EVENTS__TERM_TYPE_CONFIG1:
+       case PARSE_EVENTS__TERM_TYPE_CONFIG2:
+       case PARSE_EVENTS__TERM_TYPE_NAME:
+               return true;
+       default:
+               if (!err)
+                       return false;
+
+               /* term_type is validated so indexing is safe */
+               if (asprintf(&err->str, "'%s' is not usable in 'perf stat'",
+                            config_term_names[term_type]) < 0)
+                       err->str = NULL;
+               return false;
+       }
+}
+
+void parse_events__shrink_config_terms(void)
+{
+       config_term_shrinked = true;
+}
 
 static int config_term_common(struct perf_event_attr *attr,
                              struct parse_events_term *term,
@@ -815,6 +1002,17 @@ do {                                                                         \
                return -EINVAL;
        }
 
+       /*
+        * Check term availbility after basic checking so
+        * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered.
+        *
+        * If check availbility at the entry of this function,
+        * user will see "'<sysfs term>' is not usable in 'perf stat'"
+        * if an invalid config term is provided for legacy events
+        * (for example, instructions/badterm/...), which is confusing.
+        */
+       if (!config_term_avail(term->type_term, err))
+               return -EINVAL;
        return 0;
 #undef CHECK_TYPE_VAL
 }
@@ -961,23 +1159,8 @@ int parse_events_add_numeric(struct parse_events_evlist *data,
                        return -ENOMEM;
        }
 
-       return add_event(list, &data->idx, &attr, NULL, &config_terms);
-}
-
-static int parse_events__is_name_term(struct parse_events_term *term)
-{
-       return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
-}
-
-static char *pmu_event_name(struct list_head *head_terms)
-{
-       struct parse_events_term *term;
-
-       list_for_each_entry(term, head_terms, list)
-               if (parse_events__is_name_term(term))
-                       return term->val.str;
-
-       return NULL;
+       return add_event(list, &data->idx, &attr,
+                        get_config_name(head_config), &config_terms);
 }
 
 int parse_events_add_pmu(struct parse_events_evlist *data,
@@ -1024,7 +1207,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
                return -EINVAL;
 
        evsel = __add_event(list, &data->idx, &attr,
-                           pmu_event_name(head_config), pmu->cpus,
+                           get_config_name(head_config), pmu->cpus,
                            &config_terms);
        if (evsel) {
                evsel->unit = info.unit;
@@ -1386,8 +1569,7 @@ int parse_events_terms(struct list_head *terms, const char *str)
                return 0;
        }
 
-       if (data.terms)
-               parse_events__free_terms(data.terms);
+       parse_events_terms__delete(data.terms);
        return ret;
 }
 
@@ -1395,9 +1577,10 @@ int parse_events(struct perf_evlist *evlist, const char *str,
                 struct parse_events_error *err)
 {
        struct parse_events_evlist data = {
-               .list  = LIST_HEAD_INIT(data.list),
-               .idx   = evlist->nr_entries,
-               .error = err,
+               .list   = LIST_HEAD_INIT(data.list),
+               .idx    = evlist->nr_entries,
+               .error  = err,
+               .evlist = evlist,
        };
        int ret;
 
@@ -2068,12 +2251,29 @@ int parse_events_term__clone(struct parse_events_term **new,
                        term->err_term, term->err_val);
 }
 
-void parse_events__free_terms(struct list_head *terms)
+void parse_events_terms__purge(struct list_head *terms)
 {
        struct parse_events_term *term, *h;
 
-       list_for_each_entry_safe(term, h, terms, list)
+       list_for_each_entry_safe(term, h, terms, list) {
+               if (term->array.nr_ranges)
+                       free(term->array.ranges);
+               list_del_init(&term->list);
                free(term);
+       }
+}
+
+void parse_events_terms__delete(struct list_head *terms)
+{
+       if (!terms)
+               return;
+       parse_events_terms__purge(terms);
+       free(terms);
+}
+
+void parse_events__clear_array(struct parse_events_array *a)
+{
+       free(a->ranges);
 }
 
 void parse_events_evlist_error(struct parse_events_evlist *data,
@@ -2088,6 +2288,33 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
        WARN_ONCE(!err->str, "WARNING: failed to allocate error string");
 }
 
+static void config_terms_list(char *buf, size_t buf_sz)
+{
+       int i;
+       bool first = true;
+
+       buf[0] = '\0';
+       for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) {
+               const char *name = config_term_names[i];
+
+               if (!config_term_avail(i, NULL))
+                       continue;
+               if (!name)
+                       continue;
+               if (name[0] == '<')
+                       continue;
+
+               if (strlen(buf) + strlen(name) + 2 >= buf_sz)
+                       return;
+
+               if (!first)
+                       strcat(buf, ",");
+               else
+                       first = false;
+               strcat(buf, name);
+       }
+}
+
 /*
  * Return string contains valid config terms of an event.
  * @additional_terms: For terms such as PMU sysfs terms.
@@ -2095,17 +2322,18 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
 char *parse_events_formats_error_string(char *additional_terms)
 {
        char *str;
-       static const char *static_terms = "config,config1,config2,name,"
-                                         "period,freq,branch_type,time,"
-                                         "call-graph,stack-size\n";
+       /* "branch_type" is the longest name */
+       char static_terms[__PARSE_EVENTS__TERM_TYPE_NR *
+                         (sizeof("branch_type") - 1)];
 
+       config_terms_list(static_terms, sizeof(static_terms));
        /* valid terms */
        if (additional_terms) {
-               if (!asprintf(&str, "valid terms: %s,%s",
-                             additional_terms, static_terms))
+               if (asprintf(&str, "valid terms: %s,%s",
+                            additional_terms, static_terms) < 0)
                        goto fail;
        } else {
-               if (!asprintf(&str, "valid terms: %s", static_terms))
+               if (asprintf(&str, "valid terms: %s", static_terms) < 0)
                        goto fail;
        }
        return str;
index f1a6db107241b1c8ffaf03a3514ba1549df6fd1b..67e493088e81c29c17819e94b37da4f83fae073f 100644 (file)
@@ -68,11 +68,21 @@ enum {
        PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
        PARSE_EVENTS__TERM_TYPE_STACKSIZE,
        PARSE_EVENTS__TERM_TYPE_NOINHERIT,
-       PARSE_EVENTS__TERM_TYPE_INHERIT
+       PARSE_EVENTS__TERM_TYPE_INHERIT,
+       __PARSE_EVENTS__TERM_TYPE_NR,
+};
+
+struct parse_events_array {
+       size_t nr_ranges;
+       struct {
+               unsigned int start;
+               size_t length;
+       } *ranges;
 };
 
 struct parse_events_term {
        char *config;
+       struct parse_events_array array;
        union {
                char *str;
                u64  num;
@@ -98,12 +108,14 @@ struct parse_events_evlist {
        int                        idx;
        int                        nr_groups;
        struct parse_events_error *error;
+       struct perf_evlist        *evlist;
 };
 
 struct parse_events_terms {
        struct list_head *terms;
 };
 
+void parse_events__shrink_config_terms(void);
 int parse_events__is_hardcoded_term(struct parse_events_term *term);
 int parse_events_term__num(struct parse_events_term **term,
                           int type_term, char *config, u64 num,
@@ -115,7 +127,9 @@ int parse_events_term__sym_hw(struct parse_events_term **term,
                              char *config, unsigned idx);
 int parse_events_term__clone(struct parse_events_term **new,
                             struct parse_events_term *term);
-void parse_events__free_terms(struct list_head *terms);
+void parse_events_terms__delete(struct list_head *terms);
+void parse_events_terms__purge(struct list_head *terms);
+void parse_events__clear_array(struct parse_events_array *a);
 int parse_events__modifier_event(struct list_head *list, char *str, bool add);
 int parse_events__modifier_group(struct list_head *list, char *event_mod);
 int parse_events_name(struct list_head *list, char *name);
@@ -126,18 +140,22 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
 int parse_events_load_bpf(struct parse_events_evlist *data,
                          struct list_head *list,
                          char *bpf_file_name,
-                         bool source);
+                         bool source,
+                         struct list_head *head_config);
 /* Provide this function for perf test */
 struct bpf_object;
 int parse_events_load_bpf_obj(struct parse_events_evlist *data,
                              struct list_head *list,
-                             struct bpf_object *obj);
+                             struct bpf_object *obj,
+                             struct list_head *head_config);
 int parse_events_add_numeric(struct parse_events_evlist *data,
                             struct list_head *list,
                             u32 type, u64 config,
                             struct list_head *head_config);
 int parse_events_add_cache(struct list_head *list, int *idx,
-                          char *type, char *op_result1, char *op_result2);
+                          char *type, char *op_result1, char *op_result2,
+                          struct parse_events_error *error,
+                          struct list_head *head_config);
 int parse_events_add_breakpoint(struct list_head *list, int *idx,
                                void *ptr, char *type, u64 len);
 int parse_events_add_pmu(struct parse_events_evlist *data,
index 58c5831ffd5c22133f48a4c1a3a07721c71362fa..1477fbc78993c7b31d7bb1531f630cca8587d93f 100644 (file)
@@ -9,8 +9,8 @@
 %{
 #include <errno.h>
 #include "../perf.h"
-#include "parse-events-bison.h"
 #include "parse-events.h"
+#include "parse-events-bison.h"
 
 char *parse_events_get_text(yyscan_t yyscanner);
 YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
@@ -111,6 +111,7 @@ do {                                                        \
 %x mem
 %s config
 %x event
+%x array
 
 group          [^,{}/]*[{][^}]*[}][^,{}/]*
 event_pmu      [^,{}/]+[/][^/]*[/][^,{}/]*
@@ -122,7 +123,7 @@ num_dec             [0-9]+
 num_hex                0x[a-fA-F0-9]+
 num_raw_hex    [a-fA-F0-9]+
 name           [a-zA-Z_*?][a-zA-Z0-9_*?.]*
-name_minus     [a-zA-Z_*?][a-zA-Z0-9\-_*?.]*
+name_minus     [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
 /* If you add a modifier you need to update check_modifier() */
 modifier_event [ukhpPGHSDI]+
 modifier_bp    [rwx]{1,3}
@@ -176,10 +177,17 @@ modifier_bp       [rwx]{1,3}
 
 }
 
+<array>{
+"]"                    { BEGIN(config); return ']'; }
+{num_dec}              { return value(yyscanner, 10); }
+{num_hex}              { return value(yyscanner, 16); }
+,                      { return ','; }
+"\.\.\."               { return PE_ARRAY_RANGE; }
+}
+
 <config>{
        /*
-        * Please update parse_events_formats_error_string any time
-        * new static term is added.
+        * Please update config_term_names when new static term is added.
         */
 config                 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
 config1                        { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
@@ -196,6 +204,8 @@ no-inherit          { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
 ,                      { return ','; }
 "/"                    { BEGIN(INITIAL); return '/'; }
 {name_minus}           { return str(yyscanner, PE_NAME); }
+\[all\]                        { return PE_ARRAY_ALL; }
+"["                    { BEGIN(array); return '['; }
 }
 
 <mem>{
@@ -238,6 +248,7 @@ cpu-migrations|migrations                   { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COU
 alignment-faults                               { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
 emulation-faults                               { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
 dummy                                          { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
+bpf-output                                     { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
 
        /*
         * We have to handle the kernel PMU event cycles-ct/cycles-t/mem-loads/mem-stores separately.
index ad379968d4c10c0fb7bb2ddc3bacce3dc1166f43..5be4a5f216d6d23889e07e225810fec40df67c30 100644 (file)
@@ -28,7 +28,7 @@ do { \
        INIT_LIST_HEAD(list);         \
 } while (0)
 
-static inc_group_count(struct list_head *list,
+static void inc_group_count(struct list_head *list,
                       struct parse_events_evlist *data)
 {
        /* Count groups only have more than 1 members */
@@ -48,6 +48,7 @@ static inc_group_count(struct list_head *list,
 %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
 %token PE_ERROR
 %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
+%token PE_ARRAY_ALL PE_ARRAY_RANGE
 %type <num> PE_VALUE
 %type <num> PE_VALUE_SYM_HW
 %type <num> PE_VALUE_SYM_SW
@@ -64,6 +65,7 @@ static inc_group_count(struct list_head *list,
 %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
 %type <num> value_sym
 %type <head> event_config
+%type <head> opt_event_config
 %type <term> event_term
 %type <head> event_pmu
 %type <head> event_legacy_symbol
@@ -82,6 +84,9 @@ static inc_group_count(struct list_head *list,
 %type <head> group_def
 %type <head> group
 %type <head> groups
+%type <array> array
+%type <array> array_term
+%type <array> array_terms
 
 %union
 {
@@ -93,6 +98,7 @@ static inc_group_count(struct list_head *list,
                char *sys;
                char *event;
        } tracepoint_name;
+       struct parse_events_array array;
 }
 %%
 
@@ -211,24 +217,14 @@ event_def: event_pmu |
           event_bpf_file
 
 event_pmu:
-PE_NAME '/' event_config '/'
+PE_NAME opt_event_config
 {
        struct parse_events_evlist *data = _data;
        struct list_head *list;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_pmu(data, list, $1, $3));
-       parse_events__free_terms($3);
-       $$ = list;
-}
-|
-PE_NAME '/' '/'
-{
-       struct parse_events_evlist *data = _data;
-       struct list_head *list;
-
-       ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_pmu(data, list, $1, NULL));
+       ABORT_ON(parse_events_add_pmu(data, list, $1, $2));
+       parse_events_terms__delete($2);
        $$ = list;
 }
 |
@@ -246,7 +242,7 @@ PE_KERNEL_PMU_EVENT sep_dc
 
        ALLOC_LIST(list);
        ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
-       parse_events__free_terms(head);
+       parse_events_terms__delete(head);
        $$ = list;
 }
 |
@@ -266,7 +262,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
 
        ALLOC_LIST(list);
        ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
-       parse_events__free_terms(head);
+       parse_events_terms__delete(head);
        $$ = list;
 }
 
@@ -285,7 +281,7 @@ value_sym '/' event_config '/'
 
        ALLOC_LIST(list);
        ABORT_ON(parse_events_add_numeric(data, list, type, config, $3));
-       parse_events__free_terms($3);
+       parse_events_terms__delete($3);
        $$ = list;
 }
 |
@@ -302,33 +298,39 @@ value_sym sep_slash_dc
 }
 
 event_legacy_cache:
-PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
+PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_event_config
 {
        struct parse_events_evlist *data = _data;
+       struct parse_events_error *error = data->error;
        struct list_head *list;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5));
+       ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5, error, $6));
+       parse_events_terms__delete($6);
        $$ = list;
 }
 |
-PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
+PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config
 {
        struct parse_events_evlist *data = _data;
+       struct parse_events_error *error = data->error;
        struct list_head *list;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL));
+       ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL, error, $4));
+       parse_events_terms__delete($4);
        $$ = list;
 }
 |
-PE_NAME_CACHE_TYPE
+PE_NAME_CACHE_TYPE opt_event_config
 {
        struct parse_events_evlist *data = _data;
+       struct parse_events_error *error = data->error;
        struct list_head *list;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL));
+       ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL, error, $2));
+       parse_events_terms__delete($2);
        $$ = list;
 }
 
@@ -378,24 +380,7 @@ PE_PREFIX_MEM PE_VALUE sep_dc
 }
 
 event_legacy_tracepoint:
-tracepoint_name
-{
-       struct parse_events_evlist *data = _data;
-       struct parse_events_error *error = data->error;
-       struct list_head *list;
-
-       ALLOC_LIST(list);
-       if (error)
-               error->idx = @1.first_column;
-
-       if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
-                                       error, NULL))
-               return -1;
-
-       $$ = list;
-}
-|
-tracepoint_name '/' event_config '/'
+tracepoint_name opt_event_config
 {
        struct parse_events_evlist *data = _data;
        struct parse_events_error *error = data->error;
@@ -406,7 +391,7 @@ tracepoint_name '/' event_config '/'
                error->idx = @1.first_column;
 
        if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
-                                       error, $3))
+                                       error, $2))
                return -1;
 
        $$ = list;
@@ -433,49 +418,68 @@ PE_NAME ':' PE_NAME
 }
 
 event_legacy_numeric:
-PE_VALUE ':' PE_VALUE
+PE_VALUE ':' PE_VALUE opt_event_config
 {
        struct parse_events_evlist *data = _data;
        struct list_head *list;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, NULL));
+       ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, $4));
+       parse_events_terms__delete($4);
        $$ = list;
 }
 
 event_legacy_raw:
-PE_RAW
+PE_RAW opt_event_config
 {
        struct parse_events_evlist *data = _data;
        struct list_head *list;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, NULL));
+       ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, $2));
+       parse_events_terms__delete($2);
        $$ = list;
 }
 
 event_bpf_file:
-PE_BPF_OBJECT
+PE_BPF_OBJECT opt_event_config
 {
        struct parse_events_evlist *data = _data;
        struct parse_events_error *error = data->error;
        struct list_head *list;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_load_bpf(data, list, $1, false));
+       ABORT_ON(parse_events_load_bpf(data, list, $1, false, $2));
+       parse_events_terms__delete($2);
        $$ = list;
 }
 |
-PE_BPF_SOURCE
+PE_BPF_SOURCE opt_event_config
 {
        struct parse_events_evlist *data = _data;
        struct list_head *list;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_load_bpf(data, list, $1, true));
+       ABORT_ON(parse_events_load_bpf(data, list, $1, true, $2));
+       parse_events_terms__delete($2);
        $$ = list;
 }
 
+opt_event_config:
+'/' event_config '/'
+{
+       $$ = $2;
+}
+|
+'/' '/'
+{
+       $$ = NULL;
+}
+|
+{
+       $$ = NULL;
+}
+
 start_terms: event_config
 {
        struct parse_events_terms *data = _data;
@@ -573,6 +577,86 @@ PE_TERM
        ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
        $$ = term;
 }
+|
+PE_NAME array '=' PE_NAME
+{
+       struct parse_events_term *term;
+       int i;
+
+       ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
+                                       $1, $4, &@1, &@4));
+
+       term->array = $2;
+       $$ = term;
+}
+|
+PE_NAME array '=' PE_VALUE
+{
+       struct parse_events_term *term;
+
+       ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+                                       $1, $4, &@1, &@4));
+       term->array = $2;
+       $$ = term;
+}
+
+array:
+'[' array_terms ']'
+{
+       $$ = $2;
+}
+|
+PE_ARRAY_ALL
+{
+       $$.nr_ranges = 0;
+       $$.ranges = NULL;
+}
+
+array_terms:
+array_terms ',' array_term
+{
+       struct parse_events_array new_array;
+
+       new_array.nr_ranges = $1.nr_ranges + $3.nr_ranges;
+       new_array.ranges = malloc(sizeof(new_array.ranges[0]) *
+                                 new_array.nr_ranges);
+       ABORT_ON(!new_array.ranges);
+       memcpy(&new_array.ranges[0], $1.ranges,
+              $1.nr_ranges * sizeof(new_array.ranges[0]));
+       memcpy(&new_array.ranges[$1.nr_ranges], $3.ranges,
+              $3.nr_ranges * sizeof(new_array.ranges[0]));
+       free($1.ranges);
+       free($3.ranges);
+       $$ = new_array;
+}
+|
+array_term
+
+array_term:
+PE_VALUE
+{
+       struct parse_events_array array;
+
+       array.nr_ranges = 1;
+       array.ranges = malloc(sizeof(array.ranges[0]));
+       ABORT_ON(!array.ranges);
+       array.ranges[0].start = $1;
+       array.ranges[0].length = 1;
+       $$ = array;
+}
+|
+PE_VALUE PE_ARRAY_RANGE PE_VALUE
+{
+       struct parse_events_array array;
+
+       ABORT_ON($3 < $1);
+       array.nr_ranges = 1;
+       array.ranges = malloc(sizeof(array.ranges[0]));
+       ABORT_ON(!array.ranges);
+       array.ranges[0].start = $1;
+       array.ranges[0].length = $3 - $1 + 1;
+       $$ = array;
+}
 
 sep_dc: ':' |
 
index b597bcc8fc781f4fa2c631044bddaab447b756e9..adef23b1352e836fec9f0f9a5290c578bb25cc43 100644 (file)
@@ -98,7 +98,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
        char scale[128];
        int fd, ret = -1;
        char path[PATH_MAX];
-       const char *lc;
+       char *lc;
 
        snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
 
@@ -123,6 +123,17 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
         */
        lc = setlocale(LC_NUMERIC, NULL);
 
+       /*
+        * The lc string may be allocated in static storage,
+        * so get a dynamic copy to make it survive setlocale
+        * call below.
+        */
+       lc = strdup(lc);
+       if (!lc) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
        /*
         * force to C locale to ensure kernel
         * scale string is converted correctly.
@@ -135,6 +146,8 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *
        /* restore locale */
        setlocale(LC_NUMERIC, lc);
 
+       free(lc);
+
        ret = 0;
 error:
        close(fd);
@@ -153,7 +166,7 @@ static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *n
        if (fd == -1)
                return -1;
 
-               sret = read(fd, alias->unit, UNIT_MAX_LEN);
+       sret = read(fd, alias->unit, UNIT_MAX_LEN);
        if (sret < 0)
                goto error;
 
@@ -284,13 +297,12 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
 {
        struct dirent *evt_ent;
        DIR *event_dir;
-       int ret = 0;
 
        event_dir = opendir(dir);
        if (!event_dir)
                return -EINVAL;
 
-       while (!ret && (evt_ent = readdir(event_dir))) {
+       while ((evt_ent = readdir(event_dir))) {
                char path[PATH_MAX];
                char *name = evt_ent->d_name;
                FILE *file;
@@ -306,17 +318,19 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
 
                snprintf(path, PATH_MAX, "%s/%s", dir, name);
 
-               ret = -EINVAL;
                file = fopen(path, "r");
-               if (!file)
-                       break;
+               if (!file) {
+                       pr_debug("Cannot open %s\n", path);
+                       continue;
+               }
 
-               ret = perf_pmu__new_alias(head, dir, name, file);
+               if (perf_pmu__new_alias(head, dir, name, file) < 0)
+                       pr_debug("Cannot set up %s\n", name);
                fclose(file);
        }
 
        closedir(event_dir);
-       return ret;
+       return 0;
 }
 
 /*
@@ -354,7 +368,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias,
        list_for_each_entry(term, &alias->terms, list) {
                ret = parse_events_term__clone(&cloned, term);
                if (ret) {
-                       parse_events__free_terms(&list);
+                       parse_events_terms__purge(&list);
                        return ret;
                }
                list_add_tail(&cloned->list, &list);
index 544509c159cec4111e5865007b513e1197c576c4..b3aabc0d4eb0096fff41fb078a09d77988f103ff 100644 (file)
@@ -187,6 +187,9 @@ static void define_event_symbols(struct event_format *event,
                                 const char *ev_name,
                                 struct print_arg *args)
 {
+       if (args == NULL)
+               return;
+
        switch (args->type) {
        case PRINT_NULL:
                break;
index d72fafc1c800db1a699ac37e4ecb4acd0f1e3326..fbd05242b4e59786ca0e081a52729248d780f5a0 100644 (file)
@@ -205,6 +205,9 @@ static void define_event_symbols(struct event_format *event,
                                 const char *ev_name,
                                 struct print_arg *args)
 {
+       if (args == NULL)
+               return;
+
        switch (args->type) {
        case PRINT_NULL:
                break;
@@ -1091,8 +1094,6 @@ static int python_start_script(const char *script, int argc, const char **argv)
                goto error;
        }
 
-       free(command_line);
-
        set_table_handlers(tables);
 
        if (tables->db_export_mode) {
@@ -1101,6 +1102,8 @@ static int python_start_script(const char *script, int argc, const char **argv)
                        goto error;
        }
 
+       free(command_line);
+
        return err;
 error:
        Py_Finalize();
index 40b7a0d0905b8d7f01972c6e38e225f108b15133..60b3593d210dbc3b52997a693bcc8f9645687f08 100644 (file)
@@ -240,14 +240,6 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,
        return 0;
 }
 
-static int process_build_id_stub(struct perf_tool *tool __maybe_unused,
-                                union perf_event *event __maybe_unused,
-                                struct perf_session *session __maybe_unused)
-{
-       dump_printf(": unhandled!\n");
-       return 0;
-}
-
 static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
                                       union perf_event *event __maybe_unused,
                                       struct ordered_events *oe __maybe_unused)
@@ -260,23 +252,6 @@ static int process_finished_round(struct perf_tool *tool,
                                  union perf_event *event,
                                  struct ordered_events *oe);
 
-static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
-                                union perf_event *event __maybe_unused,
-                                struct perf_session *perf_session
-                                __maybe_unused)
-{
-       dump_printf(": unhandled!\n");
-       return 0;
-}
-
-static int process_event_auxtrace_info_stub(struct perf_tool *tool __maybe_unused,
-                               union perf_event *event __maybe_unused,
-                               struct perf_session *session __maybe_unused)
-{
-       dump_printf(": unhandled!\n");
-       return 0;
-}
-
 static int skipn(int fd, off_t n)
 {
        char buf[4096];
@@ -303,10 +278,9 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
        return event->auxtrace.size;
 }
 
-static
-int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
-                                     union perf_event *event __maybe_unused,
-                                     struct perf_session *session __maybe_unused)
+static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
+                                 union perf_event *event __maybe_unused,
+                                 struct perf_session *session __maybe_unused)
 {
        dump_printf(": unhandled!\n");
        return 0;
@@ -410,7 +384,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
        if (tool->tracing_data == NULL)
                tool->tracing_data = process_event_synth_tracing_data_stub;
        if (tool->build_id == NULL)
-               tool->build_id = process_build_id_stub;
+               tool->build_id = process_event_op2_stub;
        if (tool->finished_round == NULL) {
                if (tool->ordered_events)
                        tool->finished_round = process_finished_round;
@@ -418,13 +392,13 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
                        tool->finished_round = process_finished_round_stub;
        }
        if (tool->id_index == NULL)
-               tool->id_index = process_id_index_stub;
+               tool->id_index = process_event_op2_stub;
        if (tool->auxtrace_info == NULL)
-               tool->auxtrace_info = process_event_auxtrace_info_stub;
+               tool->auxtrace_info = process_event_op2_stub;
        if (tool->auxtrace == NULL)
                tool->auxtrace = process_event_auxtrace_stub;
        if (tool->auxtrace_error == NULL)
-               tool->auxtrace_error = process_event_auxtrace_error_stub;
+               tool->auxtrace_error = process_event_op2_stub;
        if (tool->thread_map == NULL)
                tool->thread_map = process_event_thread_map_stub;
        if (tool->cpu_map == NULL)
index 1833103768cb99fbdbb92ea8910b08488fd2aac3..c8680984d2d6680f56a974a1b54056a5e74263e1 100644 (file)
@@ -22,6 +22,7 @@ cflags = getenv('CFLAGS', '').split()
 # switch off several checks (need to be at the end of cflags list)
 cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ]
 
+src_perf  = getenv('srctree') + '/tools/perf'
 build_lib = getenv('PYTHON_EXTBUILD_LIB')
 build_tmp = getenv('PYTHON_EXTBUILD_TMP')
 libtraceevent = getenv('LIBTRACEEVENT')
@@ -30,6 +31,9 @@ libapikfs = getenv('LIBAPI')
 ext_sources = [f.strip() for f in file('util/python-ext-sources')
                                if len(f.strip()) > 0 and f[0] != '#']
 
+# use full paths with source files
+ext_sources = map(lambda x: '%s/%s' % (src_perf, x) , ext_sources)
+
 perf = Extension('perf',
                  sources = ext_sources,
                  include_dirs = ['util/include'],
index ec722346e6ffb8dd6531e94576bb15b548a1487b..93fa136b0025c02e1e4383be523fcf37c092f36e 100644 (file)
@@ -6,6 +6,7 @@
 #include "evsel.h"
 #include "evlist.h"
 #include <traceevent/event-parse.h>
+#include "mem-events.h"
 
 regex_t                parent_regex;
 const char     default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -25,9 +26,19 @@ int          sort__has_parent = 0;
 int            sort__has_sym = 0;
 int            sort__has_dso = 0;
 int            sort__has_socket = 0;
+int            sort__has_thread = 0;
+int            sort__has_comm = 0;
 enum sort_mode sort__mode = SORT_MODE__NORMAL;
 
-
+/*
+ * Replaces all occurrences of a char used with the:
+ *
+ * -t, --field-separator
+ *
+ * option, that uses a special separator character and don't pad with spaces,
+ * replacing all occurances of this separator in symbol names (and other
+ * output) with a '.' character, that thus it's the only non valid separator.
+*/
 static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
 {
        int n;
@@ -80,10 +91,21 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
                               width, width, comm ?: "");
 }
 
+static int hist_entry__thread_filter(struct hist_entry *he, int type, const void *arg)
+{
+       const struct thread *th = arg;
+
+       if (type != HIST_FILTER__THREAD)
+               return -1;
+
+       return th && he->thread != th;
+}
+
 struct sort_entry sort_thread = {
        .se_header      = "  Pid:Command",
        .se_cmp         = sort__thread_cmp,
        .se_snprintf    = hist_entry__thread_snprintf,
+       .se_filter      = hist_entry__thread_filter,
        .se_width_idx   = HISTC_THREAD,
 };
 
@@ -121,6 +143,7 @@ struct sort_entry sort_comm = {
        .se_collapse    = sort__comm_collapse,
        .se_sort        = sort__comm_sort,
        .se_snprintf    = hist_entry__comm_snprintf,
+       .se_filter      = hist_entry__thread_filter,
        .se_width_idx   = HISTC_COMM,
 };
 
@@ -170,10 +193,21 @@ static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
        return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
 }
 
+static int hist_entry__dso_filter(struct hist_entry *he, int type, const void *arg)
+{
+       const struct dso *dso = arg;
+
+       if (type != HIST_FILTER__DSO)
+               return -1;
+
+       return dso && (!he->ms.map || he->ms.map->dso != dso);
+}
+
 struct sort_entry sort_dso = {
        .se_header      = "Shared Object",
        .se_cmp         = sort__dso_cmp,
        .se_snprintf    = hist_entry__dso_snprintf,
+       .se_filter      = hist_entry__dso_filter,
        .se_width_idx   = HISTC_DSO,
 };
 
@@ -246,10 +280,8 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
                        ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
                        ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
                                        ip - map->unmap_ip(map, sym->start));
-                       ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
-                                      width - ret, "");
                } else {
-                       ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
+                       ret += repsep_snprintf(bf + ret, size - ret, "%.*s",
                                               width - ret,
                                               sym->name);
                }
@@ -257,14 +289,9 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
                size_t len = BITS_PER_LONG / 4;
                ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
                                       len, ip);
-               ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
-                                      width - ret, "");
        }
 
-       if (ret > width)
-               bf[width] = '\0';
-
-       return width;
+       return ret;
 }
 
 static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
@@ -274,46 +301,56 @@ static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
                                         he->level, bf, size, width);
 }
 
+static int hist_entry__sym_filter(struct hist_entry *he, int type, const void *arg)
+{
+       const char *sym = arg;
+
+       if (type != HIST_FILTER__SYMBOL)
+               return -1;
+
+       return sym && (!he->ms.sym || !strstr(he->ms.sym->name, sym));
+}
+
 struct sort_entry sort_sym = {
        .se_header      = "Symbol",
        .se_cmp         = sort__sym_cmp,
        .se_sort        = sort__sym_sort,
        .se_snprintf    = hist_entry__sym_snprintf,
+       .se_filter      = hist_entry__sym_filter,
        .se_width_idx   = HISTC_SYMBOL,
 };
 
 /* --sort srcline */
 
+static char *hist_entry__get_srcline(struct hist_entry *he)
+{
+       struct map *map = he->ms.map;
+
+       if (!map)
+               return SRCLINE_UNKNOWN;
+
+       return get_srcline(map->dso, map__rip_2objdump(map, he->ip),
+                          he->ms.sym, true);
+}
+
 static int64_t
 sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-       if (!left->srcline) {
-               if (!left->ms.map)
-                       left->srcline = SRCLINE_UNKNOWN;
-               else {
-                       struct map *map = left->ms.map;
-                       left->srcline = get_srcline(map->dso,
-                                          map__rip_2objdump(map, left->ip),
-                                                   left->ms.sym, true);
-               }
-       }
-       if (!right->srcline) {
-               if (!right->ms.map)
-                       right->srcline = SRCLINE_UNKNOWN;
-               else {
-                       struct map *map = right->ms.map;
-                       right->srcline = get_srcline(map->dso,
-                                            map__rip_2objdump(map, right->ip),
-                                                    right->ms.sym, true);
-               }
-       }
+       if (!left->srcline)
+               left->srcline = hist_entry__get_srcline(left);
+       if (!right->srcline)
+               right->srcline = hist_entry__get_srcline(right);
+
        return strcmp(right->srcline, left->srcline);
 }
 
 static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
                                        size_t size, unsigned int width)
 {
-       return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
+       if (!he->srcline)
+               he->srcline = hist_entry__get_srcline(he);
+
+       return repsep_snprintf(bf, size, "%-.*s", width, he->srcline);
 }
 
 struct sort_entry sort_srcline = {
@@ -327,11 +364,14 @@ struct sort_entry sort_srcline = {
 
 static char no_srcfile[1];
 
-static char *get_srcfile(struct hist_entry *e)
+static char *hist_entry__get_srcfile(struct hist_entry *e)
 {
        char *sf, *p;
        struct map *map = e->ms.map;
 
+       if (!map)
+               return no_srcfile;
+
        sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
                         e->ms.sym, false, true);
        if (!strcmp(sf, SRCLINE_UNKNOWN))
@@ -348,25 +388,21 @@ static char *get_srcfile(struct hist_entry *e)
 static int64_t
 sort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right)
 {
-       if (!left->srcfile) {
-               if (!left->ms.map)
-                       left->srcfile = no_srcfile;
-               else
-                       left->srcfile = get_srcfile(left);
-       }
-       if (!right->srcfile) {
-               if (!right->ms.map)
-                       right->srcfile = no_srcfile;
-               else
-                       right->srcfile = get_srcfile(right);
-       }
+       if (!left->srcfile)
+               left->srcfile = hist_entry__get_srcfile(left);
+       if (!right->srcfile)
+               right->srcfile = hist_entry__get_srcfile(right);
+
        return strcmp(right->srcfile, left->srcfile);
 }
 
 static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf,
                                        size_t size, unsigned int width)
 {
-       return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcfile);
+       if (!he->srcfile)
+               he->srcfile = hist_entry__get_srcfile(he);
+
+       return repsep_snprintf(bf, size, "%-.*s", width, he->srcfile);
 }
 
 struct sort_entry sort_srcfile = {
@@ -439,10 +475,21 @@ static int hist_entry__socket_snprintf(struct hist_entry *he, char *bf,
        return repsep_snprintf(bf, size, "%*.*d", width, width-3, he->socket);
 }
 
+static int hist_entry__socket_filter(struct hist_entry *he, int type, const void *arg)
+{
+       int sk = *(const int *)arg;
+
+       if (type != HIST_FILTER__SOCKET)
+               return -1;
+
+       return sk >= 0 && he->socket != sk;
+}
+
 struct sort_entry sort_socket = {
        .se_header      = "Socket",
        .se_cmp         = sort__socket_cmp,
        .se_snprintf    = hist_entry__socket_snprintf,
+       .se_filter      = hist_entry__socket_filter,
        .se_width_idx   = HISTC_SOCKET,
 };
 
@@ -483,9 +530,6 @@ sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
        if (right->trace_output == NULL)
                right->trace_output = get_trace_output(right);
 
-       hists__new_col_len(left->hists, HISTC_TRACE, strlen(left->trace_output));
-       hists__new_col_len(right->hists, HISTC_TRACE, strlen(right->trace_output));
-
        return strcmp(right->trace_output, left->trace_output);
 }
 
@@ -496,11 +540,11 @@ static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf,
 
        evsel = hists_to_evsel(he->hists);
        if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
-               return scnprintf(bf, size, "%-*.*s", width, width, "N/A");
+               return scnprintf(bf, size, "%-.*s", width, "N/A");
 
        if (he->trace_output == NULL)
                he->trace_output = get_trace_output(he);
-       return repsep_snprintf(bf, size, "%-*.*s", width, width, he->trace_output);
+       return repsep_snprintf(bf, size, "%-.*s", width, he->trace_output);
 }
 
 struct sort_entry sort_trace = {
@@ -532,6 +576,18 @@ static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
                return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
 }
 
+static int hist_entry__dso_from_filter(struct hist_entry *he, int type,
+                                      const void *arg)
+{
+       const struct dso *dso = arg;
+
+       if (type != HIST_FILTER__DSO)
+               return -1;
+
+       return dso && (!he->branch_info || !he->branch_info->from.map ||
+                      he->branch_info->from.map->dso != dso);
+}
+
 static int64_t
 sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -552,6 +608,18 @@ static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
                return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
 }
 
+static int hist_entry__dso_to_filter(struct hist_entry *he, int type,
+                                    const void *arg)
+{
+       const struct dso *dso = arg;
+
+       if (type != HIST_FILTER__DSO)
+               return -1;
+
+       return dso && (!he->branch_info || !he->branch_info->to.map ||
+                      he->branch_info->to.map->dso != dso);
+}
+
 static int64_t
 sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -613,10 +681,35 @@ static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
        return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
 }
 
+static int hist_entry__sym_from_filter(struct hist_entry *he, int type,
+                                      const void *arg)
+{
+       const char *sym = arg;
+
+       if (type != HIST_FILTER__SYMBOL)
+               return -1;
+
+       return sym && !(he->branch_info && he->branch_info->from.sym &&
+                       strstr(he->branch_info->from.sym->name, sym));
+}
+
+static int hist_entry__sym_to_filter(struct hist_entry *he, int type,
+                                      const void *arg)
+{
+       const char *sym = arg;
+
+       if (type != HIST_FILTER__SYMBOL)
+               return -1;
+
+       return sym && !(he->branch_info && he->branch_info->to.sym &&
+                       strstr(he->branch_info->to.sym->name, sym));
+}
+
 struct sort_entry sort_dso_from = {
        .se_header      = "Source Shared Object",
        .se_cmp         = sort__dso_from_cmp,
        .se_snprintf    = hist_entry__dso_from_snprintf,
+       .se_filter      = hist_entry__dso_from_filter,
        .se_width_idx   = HISTC_DSO_FROM,
 };
 
@@ -624,6 +717,7 @@ struct sort_entry sort_dso_to = {
        .se_header      = "Target Shared Object",
        .se_cmp         = sort__dso_to_cmp,
        .se_snprintf    = hist_entry__dso_to_snprintf,
+       .se_filter      = hist_entry__dso_to_filter,
        .se_width_idx   = HISTC_DSO_TO,
 };
 
@@ -631,6 +725,7 @@ struct sort_entry sort_sym_from = {
        .se_header      = "Source Symbol",
        .se_cmp         = sort__sym_from_cmp,
        .se_snprintf    = hist_entry__sym_from_snprintf,
+       .se_filter      = hist_entry__sym_from_filter,
        .se_width_idx   = HISTC_SYMBOL_FROM,
 };
 
@@ -638,6 +733,7 @@ struct sort_entry sort_sym_to = {
        .se_header      = "Target Symbol",
        .se_cmp         = sort__sym_to_cmp,
        .se_snprintf    = hist_entry__sym_to_snprintf,
+       .se_filter      = hist_entry__sym_to_filter,
        .se_width_idx   = HISTC_SYMBOL_TO,
 };
 
@@ -797,20 +893,10 @@ sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
-       const char *out;
-       u64 mask = PERF_MEM_LOCK_NA;
+       char out[10];
 
-       if (he->mem_info)
-               mask = he->mem_info->data_src.mem_lock;
-
-       if (mask & PERF_MEM_LOCK_NA)
-               out = "N/A";
-       else if (mask & PERF_MEM_LOCK_LOCKED)
-               out = "Yes";
-       else
-               out = "No";
-
-       return repsep_snprintf(bf, size, "%-*s", width, out);
+       perf_mem__lck_scnprintf(out, sizeof(out), he->mem_info);
+       return repsep_snprintf(bf, size, "%.*s", width, out);
 }
 
 static int64_t
@@ -832,54 +918,12 @@ sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
        return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
 }
 
-static const char * const tlb_access[] = {
-       "N/A",
-       "HIT",
-       "MISS",
-       "L1",
-       "L2",
-       "Walker",
-       "Fault",
-};
-#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
-
 static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
        char out[64];
-       size_t sz = sizeof(out) - 1; /* -1 for null termination */
-       size_t l = 0, i;
-       u64 m = PERF_MEM_TLB_NA;
-       u64 hit, miss;
-
-       out[0] = '\0';
-
-       if (he->mem_info)
-               m = he->mem_info->data_src.mem_dtlb;
-
-       hit = m & PERF_MEM_TLB_HIT;
-       miss = m & PERF_MEM_TLB_MISS;
-
-       /* already taken care of */
-       m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
-
-       for (i = 0; m && i < NUM_TLB_ACCESS; i++, m >>= 1) {
-               if (!(m & 0x1))
-                       continue;
-               if (l) {
-                       strcat(out, " or ");
-                       l += 4;
-               }
-               strncat(out, tlb_access[i], sz - l);
-               l += strlen(tlb_access[i]);
-       }
-       if (*out == '\0')
-               strcpy(out, "N/A");
-       if (hit)
-               strncat(out, " hit", sz - l);
-       if (miss)
-               strncat(out, " miss", sz - l);
 
+       perf_mem__tlb_scnprintf(out, sizeof(out), he->mem_info);
        return repsep_snprintf(bf, size, "%-*s", width, out);
 }
 
@@ -902,61 +946,12 @@ sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
        return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
 }
 
-static const char * const mem_lvl[] = {
-       "N/A",
-       "HIT",
-       "MISS",
-       "L1",
-       "LFB",
-       "L2",
-       "L3",
-       "Local RAM",
-       "Remote RAM (1 hop)",
-       "Remote RAM (2 hops)",
-       "Remote Cache (1 hop)",
-       "Remote Cache (2 hops)",
-       "I/O",
-       "Uncached",
-};
-#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
-
 static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
        char out[64];
-       size_t sz = sizeof(out) - 1; /* -1 for null termination */
-       size_t i, l = 0;
-       u64 m =  PERF_MEM_LVL_NA;
-       u64 hit, miss;
-
-       if (he->mem_info)
-               m  = he->mem_info->data_src.mem_lvl;
-
-       out[0] = '\0';
-
-       hit = m & PERF_MEM_LVL_HIT;
-       miss = m & PERF_MEM_LVL_MISS;
-
-       /* already taken care of */
-       m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
-
-       for (i = 0; m && i < NUM_MEM_LVL; i++, m >>= 1) {
-               if (!(m & 0x1))
-                       continue;
-               if (l) {
-                       strcat(out, " or ");
-                       l += 4;
-               }
-               strncat(out, mem_lvl[i], sz - l);
-               l += strlen(mem_lvl[i]);
-       }
-       if (*out == '\0')
-               strcpy(out, "N/A");
-       if (hit)
-               strncat(out, " hit", sz - l);
-       if (miss)
-               strncat(out, " miss", sz - l);
 
+       perf_mem__lvl_scnprintf(out, sizeof(out), he->mem_info);
        return repsep_snprintf(bf, size, "%-*s", width, out);
 }
 
@@ -979,51 +974,15 @@ sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
        return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
 }
 
-static const char * const snoop_access[] = {
-       "N/A",
-       "None",
-       "Miss",
-       "Hit",
-       "HitM",
-};
-#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
-
 static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
        char out[64];
-       size_t sz = sizeof(out) - 1; /* -1 for null termination */
-       size_t i, l = 0;
-       u64 m = PERF_MEM_SNOOP_NA;
-
-       out[0] = '\0';
-
-       if (he->mem_info)
-               m = he->mem_info->data_src.mem_snoop;
-
-       for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
-               if (!(m & 0x1))
-                       continue;
-               if (l) {
-                       strcat(out, " or ");
-                       l += 4;
-               }
-               strncat(out, snoop_access[i], sz - l);
-               l += strlen(snoop_access[i]);
-       }
-
-       if (*out == '\0')
-               strcpy(out, "N/A");
 
+       perf_mem__snp_scnprintf(out, sizeof(out), he->mem_info);
        return repsep_snprintf(bf, size, "%-*s", width, out);
 }
 
-static inline  u64 cl_address(u64 address)
-{
-       /* return the cacheline of the address */
-       return (address & ~(cacheline_size - 1));
-}
-
 static int64_t
 sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
 {
@@ -1440,20 +1399,6 @@ struct hpp_sort_entry {
        struct sort_entry *se;
 };
 
-bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
-{
-       struct hpp_sort_entry *hse_a;
-       struct hpp_sort_entry *hse_b;
-
-       if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b))
-               return false;
-
-       hse_a = container_of(a, struct hpp_sort_entry, hpp);
-       hse_b = container_of(b, struct hpp_sort_entry, hpp);
-
-       return hse_a->se == hse_b->se;
-}
-
 void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
 {
        struct hpp_sort_entry *hse;
@@ -1539,8 +1484,56 @@ static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt,
        return sort_fn(a, b);
 }
 
+bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format)
+{
+       return format->header == __sort__hpp_header;
+}
+
+#define MK_SORT_ENTRY_CHK(key)                                 \
+bool perf_hpp__is_ ## key ## _entry(struct perf_hpp_fmt *fmt)  \
+{                                                              \
+       struct hpp_sort_entry *hse;                             \
+                                                               \
+       if (!perf_hpp__is_sort_entry(fmt))                      \
+               return false;                                   \
+                                                               \
+       hse = container_of(fmt, struct hpp_sort_entry, hpp);    \
+       return hse->se == &sort_ ## key ;                       \
+}
+
+MK_SORT_ENTRY_CHK(trace)
+MK_SORT_ENTRY_CHK(srcline)
+MK_SORT_ENTRY_CHK(srcfile)
+MK_SORT_ENTRY_CHK(thread)
+MK_SORT_ENTRY_CHK(comm)
+MK_SORT_ENTRY_CHK(dso)
+MK_SORT_ENTRY_CHK(sym)
+
+
+static bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
+{
+       struct hpp_sort_entry *hse_a;
+       struct hpp_sort_entry *hse_b;
+
+       if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b))
+               return false;
+
+       hse_a = container_of(a, struct hpp_sort_entry, hpp);
+       hse_b = container_of(b, struct hpp_sort_entry, hpp);
+
+       return hse_a->se == hse_b->se;
+}
+
+static void hse_free(struct perf_hpp_fmt *fmt)
+{
+       struct hpp_sort_entry *hse;
+
+       hse = container_of(fmt, struct hpp_sort_entry, hpp);
+       free(hse);
+}
+
 static struct hpp_sort_entry *
-__sort_dimension__alloc_hpp(struct sort_dimension *sd)
+__sort_dimension__alloc_hpp(struct sort_dimension *sd, int level)
 {
        struct hpp_sort_entry *hse;
 
@@ -1560,40 +1553,92 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
        hse->hpp.cmp = __sort__hpp_cmp;
        hse->hpp.collapse = __sort__hpp_collapse;
        hse->hpp.sort = __sort__hpp_sort;
+       hse->hpp.equal = __sort__hpp_equal;
+       hse->hpp.free = hse_free;
 
        INIT_LIST_HEAD(&hse->hpp.list);
        INIT_LIST_HEAD(&hse->hpp.sort_list);
        hse->hpp.elide = false;
        hse->hpp.len = 0;
        hse->hpp.user_len = 0;
+       hse->hpp.level = level;
 
        return hse;
 }
 
-bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format)
+static void hpp_free(struct perf_hpp_fmt *fmt)
 {
-       return format->header == __sort__hpp_header;
+       free(fmt);
+}
+
+static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd,
+                                                      int level)
+{
+       struct perf_hpp_fmt *fmt;
+
+       fmt = memdup(hd->fmt, sizeof(*fmt));
+       if (fmt) {
+               INIT_LIST_HEAD(&fmt->list);
+               INIT_LIST_HEAD(&fmt->sort_list);
+               fmt->free = hpp_free;
+               fmt->level = level;
+       }
+
+       return fmt;
+}
+
+int hist_entry__filter(struct hist_entry *he, int type, const void *arg)
+{
+       struct perf_hpp_fmt *fmt;
+       struct hpp_sort_entry *hse;
+       int ret = -1;
+       int r;
+
+       perf_hpp_list__for_each_format(he->hpp_list, fmt) {
+               if (!perf_hpp__is_sort_entry(fmt))
+                       continue;
+
+               hse = container_of(fmt, struct hpp_sort_entry, hpp);
+               if (hse->se->se_filter == NULL)
+                       continue;
+
+               /*
+                * hist entry is filtered if any of sort key in the hpp list
+                * is applied.  But it should skip non-matched filter types.
+                */
+               r = hse->se->se_filter(he, type, arg);
+               if (r >= 0) {
+                       if (ret < 0)
+                               ret = 0;
+                       ret |= r;
+               }
+       }
+
+       return ret;
 }
 
-static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd)
+static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd,
+                                         struct perf_hpp_list *list,
+                                         int level)
 {
-       struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
+       struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, level);
 
        if (hse == NULL)
                return -1;
 
-       perf_hpp__register_sort_field(&hse->hpp);
+       perf_hpp_list__register_sort_field(list, &hse->hpp);
        return 0;
 }
 
-static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
+static int __sort_dimension__add_hpp_output(struct sort_dimension *sd,
+                                           struct perf_hpp_list *list)
 {
-       struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
+       struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, 0);
 
        if (hse == NULL)
                return -1;
 
-       perf_hpp__column_register(&hse->hpp);
+       perf_hpp_list__column_register(list, &hse->hpp);
        return 0;
 }
 
@@ -1727,6 +1772,9 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
        if (hde->raw_trace)
                goto raw_field;
 
+       if (!he->trace_output)
+               he->trace_output = get_trace_output(he);
+
        field = hde->field;
        namelen = strlen(field->name);
        str = he->trace_output;
@@ -1776,6 +1824,11 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
 
        hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
 
+       if (b == NULL) {
+               update_dynamic_len(hde, a);
+               return 0;
+       }
+
        field = hde->field;
        if (field->flags & FIELD_IS_DYNAMIC) {
                unsigned long long dyn;
@@ -1790,9 +1843,6 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
        } else {
                offset = field->offset;
                size = field->size;
-
-               update_dynamic_len(hde, a);
-               update_dynamic_len(hde, b);
        }
 
        return memcmp(a->raw_data + offset, b->raw_data + offset, size);
@@ -1803,8 +1853,31 @@ bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt)
        return fmt->cmp == __sort__hde_cmp;
 }
 
+static bool __sort__hde_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
+{
+       struct hpp_dynamic_entry *hde_a;
+       struct hpp_dynamic_entry *hde_b;
+
+       if (!perf_hpp__is_dynamic_entry(a) || !perf_hpp__is_dynamic_entry(b))
+               return false;
+
+       hde_a = container_of(a, struct hpp_dynamic_entry, hpp);
+       hde_b = container_of(b, struct hpp_dynamic_entry, hpp);
+
+       return hde_a->field == hde_b->field;
+}
+
+static void hde_free(struct perf_hpp_fmt *fmt)
+{
+       struct hpp_dynamic_entry *hde;
+
+       hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+       free(hde);
+}
+
 static struct hpp_dynamic_entry *
-__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
+__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field,
+                     int level)
 {
        struct hpp_dynamic_entry *hde;
 
@@ -1827,16 +1900,47 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
        hde->hpp.cmp = __sort__hde_cmp;
        hde->hpp.collapse = __sort__hde_cmp;
        hde->hpp.sort = __sort__hde_cmp;
+       hde->hpp.equal = __sort__hde_equal;
+       hde->hpp.free = hde_free;
 
        INIT_LIST_HEAD(&hde->hpp.list);
        INIT_LIST_HEAD(&hde->hpp.sort_list);
        hde->hpp.elide = false;
        hde->hpp.len = 0;
        hde->hpp.user_len = 0;
+       hde->hpp.level = level;
 
        return hde;
 }
 
+struct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt)
+{
+       struct perf_hpp_fmt *new_fmt = NULL;
+
+       if (perf_hpp__is_sort_entry(fmt)) {
+               struct hpp_sort_entry *hse, *new_hse;
+
+               hse = container_of(fmt, struct hpp_sort_entry, hpp);
+               new_hse = memdup(hse, sizeof(*hse));
+               if (new_hse)
+                       new_fmt = &new_hse->hpp;
+       } else if (perf_hpp__is_dynamic_entry(fmt)) {
+               struct hpp_dynamic_entry *hde, *new_hde;
+
+               hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
+               new_hde = memdup(hde, sizeof(*hde));
+               if (new_hde)
+                       new_fmt = &new_hde->hpp;
+       } else {
+               new_fmt = memdup(fmt, sizeof(*fmt));
+       }
+
+       INIT_LIST_HEAD(&new_fmt->list);
+       INIT_LIST_HEAD(&new_fmt->sort_list);
+
+       return new_fmt;
+}
+
 static int parse_field_name(char *str, char **event, char **field, char **opt)
 {
        char *event_name, *field_name, *opt_name;
@@ -1908,11 +2012,11 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
 
 static int __dynamic_dimension__add(struct perf_evsel *evsel,
                                    struct format_field *field,
-                                   bool raw_trace)
+                                   bool raw_trace, int level)
 {
        struct hpp_dynamic_entry *hde;
 
-       hde = __alloc_dynamic_entry(evsel, field);
+       hde = __alloc_dynamic_entry(evsel, field, level);
        if (hde == NULL)
                return -ENOMEM;
 
@@ -1922,14 +2026,14 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel,
        return 0;
 }
 
-static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
+static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level)
 {
        int ret;
        struct format_field *field;
 
        field = evsel->tp_format->format.fields;
        while (field) {
-               ret = __dynamic_dimension__add(evsel, field, raw_trace);
+               ret = __dynamic_dimension__add(evsel, field, raw_trace, level);
                if (ret < 0)
                        return ret;
 
@@ -1938,7 +2042,8 @@ static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
        return 0;
 }
 
-static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
+static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
+                                 int level)
 {
        int ret;
        struct perf_evsel *evsel;
@@ -1947,7 +2052,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
                if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
                        continue;
 
-               ret = add_evsel_fields(evsel, raw_trace);
+               ret = add_evsel_fields(evsel, raw_trace, level);
                if (ret < 0)
                        return ret;
        }
@@ -1955,7 +2060,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
 }
 
 static int add_all_matching_fields(struct perf_evlist *evlist,
-                                  char *field_name, bool raw_trace)
+                                  char *field_name, bool raw_trace, int level)
 {
        int ret = -ESRCH;
        struct perf_evsel *evsel;
@@ -1969,14 +2074,15 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
                if (field == NULL)
                        continue;
 
-               ret = __dynamic_dimension__add(evsel, field, raw_trace);
+               ret = __dynamic_dimension__add(evsel, field, raw_trace, level);
                if (ret < 0)
                        break;
        }
        return ret;
 }
 
-static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
+static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
+                            int level)
 {
        char *str, *event_name, *field_name, *opt_name;
        struct perf_evsel *evsel;
@@ -2006,12 +2112,12 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
        }
 
        if (!strcmp(field_name, "trace_fields")) {
-               ret = add_all_dynamic_fields(evlist, raw_trace);
+               ret = add_all_dynamic_fields(evlist, raw_trace, level);
                goto out;
        }
 
        if (event_name == NULL) {
-               ret = add_all_matching_fields(evlist, field_name, raw_trace);
+               ret = add_all_matching_fields(evlist, field_name, raw_trace, level);
                goto out;
        }
 
@@ -2029,7 +2135,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
        }
 
        if (!strcmp(field_name, "*")) {
-               ret = add_evsel_fields(evsel, raw_trace);
+               ret = add_evsel_fields(evsel, raw_trace, level);
        } else {
                field = pevent_find_any_field(evsel->tp_format, field_name);
                if (field == NULL) {
@@ -2038,7 +2144,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
                        return -ENOENT;
                }
 
-               ret = __dynamic_dimension__add(evsel, field, raw_trace);
+               ret = __dynamic_dimension__add(evsel, field, raw_trace, level);
        }
 
 out:
@@ -2046,12 +2152,14 @@ out:
        return ret;
 }
 
-static int __sort_dimension__add(struct sort_dimension *sd)
+static int __sort_dimension__add(struct sort_dimension *sd,
+                                struct perf_hpp_list *list,
+                                int level)
 {
        if (sd->taken)
                return 0;
 
-       if (__sort_dimension__add_hpp_sort(sd) < 0)
+       if (__sort_dimension__add_hpp_sort(sd, list, level) < 0)
                return -1;
 
        if (sd->entry->se_collapse)
@@ -2062,46 +2170,63 @@ static int __sort_dimension__add(struct sort_dimension *sd)
        return 0;
 }
 
-static int __hpp_dimension__add(struct hpp_dimension *hd)
+static int __hpp_dimension__add(struct hpp_dimension *hd,
+                               struct perf_hpp_list *list,
+                               int level)
 {
-       if (!hd->taken) {
-               hd->taken = 1;
+       struct perf_hpp_fmt *fmt;
 
-               perf_hpp__register_sort_field(hd->fmt);
-       }
+       if (hd->taken)
+               return 0;
+
+       fmt = __hpp_dimension__alloc_hpp(hd, level);
+       if (!fmt)
+               return -1;
+
+       hd->taken = 1;
+       perf_hpp_list__register_sort_field(list, fmt);
        return 0;
 }
 
-static int __sort_dimension__add_output(struct sort_dimension *sd)
+static int __sort_dimension__add_output(struct perf_hpp_list *list,
+                                       struct sort_dimension *sd)
 {
        if (sd->taken)
                return 0;
 
-       if (__sort_dimension__add_hpp_output(sd) < 0)
+       if (__sort_dimension__add_hpp_output(sd, list) < 0)
                return -1;
 
        sd->taken = 1;
        return 0;
 }
 
-static int __hpp_dimension__add_output(struct hpp_dimension *hd)
+static int __hpp_dimension__add_output(struct perf_hpp_list *list,
+                                      struct hpp_dimension *hd)
 {
-       if (!hd->taken) {
-               hd->taken = 1;
+       struct perf_hpp_fmt *fmt;
 
-               perf_hpp__column_register(hd->fmt);
-       }
+       if (hd->taken)
+               return 0;
+
+       fmt = __hpp_dimension__alloc_hpp(hd, 0);
+       if (!fmt)
+               return -1;
+
+       hd->taken = 1;
+       perf_hpp_list__column_register(list, fmt);
        return 0;
 }
 
 int hpp_dimension__add_output(unsigned col)
 {
        BUG_ON(col >= PERF_HPP__MAX_INDEX);
-       return __hpp_dimension__add_output(&hpp_sort_dimensions[col]);
+       return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]);
 }
 
-static int sort_dimension__add(const char *tok,
-                              struct perf_evlist *evlist __maybe_unused)
+static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
+                              struct perf_evlist *evlist __maybe_unused,
+                              int level)
 {
        unsigned int i;
 
@@ -2136,9 +2261,13 @@ static int sort_dimension__add(const char *tok,
                        sort__has_dso = 1;
                } else if (sd->entry == &sort_socket) {
                        sort__has_socket = 1;
+               } else if (sd->entry == &sort_thread) {
+                       sort__has_thread = 1;
+               } else if (sd->entry == &sort_comm) {
+                       sort__has_comm = 1;
                }
 
-               return __sort_dimension__add(sd);
+               return __sort_dimension__add(sd, list, level);
        }
 
        for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
@@ -2147,7 +2276,7 @@ static int sort_dimension__add(const char *tok,
                if (strncasecmp(tok, hd->name, strlen(tok)))
                        continue;
 
-               return __hpp_dimension__add(hd);
+               return __hpp_dimension__add(hd, list, level);
        }
 
        for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
@@ -2162,7 +2291,7 @@ static int sort_dimension__add(const char *tok,
                if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
                        sort__has_sym = 1;
 
-               __sort_dimension__add(sd);
+               __sort_dimension__add(sd, list, level);
                return 0;
        }
 
@@ -2178,16 +2307,60 @@ static int sort_dimension__add(const char *tok,
                if (sd->entry == &sort_mem_daddr_sym)
                        sort__has_sym = 1;
 
-               __sort_dimension__add(sd);
+               __sort_dimension__add(sd, list, level);
                return 0;
        }
 
-       if (!add_dynamic_entry(evlist, tok))
+       if (!add_dynamic_entry(evlist, tok, level))
                return 0;
 
        return -ESRCH;
 }
 
+static int setup_sort_list(struct perf_hpp_list *list, char *str,
+                          struct perf_evlist *evlist)
+{
+       char *tmp, *tok;
+       int ret = 0;
+       int level = 0;
+       int next_level = 1;
+       bool in_group = false;
+
+       do {
+               tok = str;
+               tmp = strpbrk(str, "{}, ");
+               if (tmp) {
+                       if (in_group)
+                               next_level = level;
+                       else
+                               next_level = level + 1;
+
+                       if (*tmp == '{')
+                               in_group = true;
+                       else if (*tmp == '}')
+                               in_group = false;
+
+                       *tmp = '\0';
+                       str = tmp + 1;
+               }
+
+               if (*tok) {
+                       ret = sort_dimension__add(list, tok, evlist, level);
+                       if (ret == -EINVAL) {
+                               error("Invalid --sort key: `%s'", tok);
+                               break;
+                       } else if (ret == -ESRCH) {
+                               error("Unknown --sort key: `%s'", tok);
+                               break;
+                       }
+               }
+
+               level = next_level;
+       } while (tmp);
+
+       return ret;
+}
+
 static const char *get_default_sort_order(struct perf_evlist *evlist)
 {
        const char *default_sort_orders[] = {
@@ -2282,7 +2455,7 @@ static char *setup_overhead(char *keys)
 
 static int __setup_sorting(struct perf_evlist *evlist)
 {
-       char *tmp, *tok, *str;
+       char *str;
        const char *sort_keys;
        int ret = 0;
 
@@ -2320,17 +2493,7 @@ static int __setup_sorting(struct perf_evlist *evlist)
                }
        }
 
-       for (tok = strtok_r(str, ", ", &tmp);
-                       tok; tok = strtok_r(NULL, ", ", &tmp)) {
-               ret = sort_dimension__add(tok, evlist);
-               if (ret == -EINVAL) {
-                       error("Invalid --sort key: `%s'", tok);
-                       break;
-               } else if (ret == -ESRCH) {
-                       error("Unknown --sort key: `%s'", tok);
-                       break;
-               }
-       }
+       ret = setup_sort_list(&perf_hpp_list, str, evlist);
 
        free(str);
        return ret;
@@ -2341,7 +2504,7 @@ void perf_hpp__set_elide(int idx, bool elide)
        struct perf_hpp_fmt *fmt;
        struct hpp_sort_entry *hse;
 
-       perf_hpp__for_each_format(fmt) {
+       perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
                if (!perf_hpp__is_sort_entry(fmt))
                        continue;
 
@@ -2401,7 +2564,7 @@ void sort__setup_elide(FILE *output)
        struct perf_hpp_fmt *fmt;
        struct hpp_sort_entry *hse;
 
-       perf_hpp__for_each_format(fmt) {
+       perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
                if (!perf_hpp__is_sort_entry(fmt))
                        continue;
 
@@ -2413,7 +2576,7 @@ void sort__setup_elide(FILE *output)
         * It makes no sense to elide all of sort entries.
         * Just revert them to show up again.
         */
-       perf_hpp__for_each_format(fmt) {
+       perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
                if (!perf_hpp__is_sort_entry(fmt))
                        continue;
 
@@ -2421,7 +2584,7 @@ void sort__setup_elide(FILE *output)
                        return;
        }
 
-       perf_hpp__for_each_format(fmt) {
+       perf_hpp_list__for_each_format(&perf_hpp_list, fmt) {
                if (!perf_hpp__is_sort_entry(fmt))
                        continue;
 
@@ -2429,7 +2592,7 @@ void sort__setup_elide(FILE *output)
        }
 }
 
-static int output_field_add(char *tok)
+static int output_field_add(struct perf_hpp_list *list, char *tok)
 {
        unsigned int i;
 
@@ -2439,7 +2602,7 @@ static int output_field_add(char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
-               return __sort_dimension__add_output(sd);
+               return __sort_dimension__add_output(list, sd);
        }
 
        for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
@@ -2448,7 +2611,7 @@ static int output_field_add(char *tok)
                if (strncasecmp(tok, hd->name, strlen(tok)))
                        continue;
 
-               return __hpp_dimension__add_output(hd);
+               return __hpp_dimension__add_output(list, hd);
        }
 
        for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
@@ -2457,7 +2620,7 @@ static int output_field_add(char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
-               return __sort_dimension__add_output(sd);
+               return __sort_dimension__add_output(list, sd);
        }
 
        for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
@@ -2466,12 +2629,32 @@ static int output_field_add(char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
-               return __sort_dimension__add_output(sd);
+               return __sort_dimension__add_output(list, sd);
        }
 
        return -ESRCH;
 }
 
+static int setup_output_list(struct perf_hpp_list *list, char *str)
+{
+       char *tmp, *tok;
+       int ret = 0;
+
+       for (tok = strtok_r(str, ", ", &tmp);
+                       tok; tok = strtok_r(NULL, ", ", &tmp)) {
+               ret = output_field_add(list, tok);
+               if (ret == -EINVAL) {
+                       error("Invalid --fields key: `%s'", tok);
+                       break;
+               } else if (ret == -ESRCH) {
+                       error("Unknown --fields key: `%s'", tok);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
 static void reset_dimensions(void)
 {
        unsigned int i;
@@ -2496,7 +2679,7 @@ bool is_strict_order(const char *order)
 
 static int __setup_output_field(void)
 {
-       char *tmp, *tok, *str, *strp;
+       char *str, *strp;
        int ret = -EINVAL;
 
        if (field_order == NULL)
@@ -2516,17 +2699,7 @@ static int __setup_output_field(void)
                goto out;
        }
 
-       for (tok = strtok_r(strp, ", ", &tmp);
-                       tok; tok = strtok_r(NULL, ", ", &tmp)) {
-               ret = output_field_add(tok);
-               if (ret == -EINVAL) {
-                       error("Invalid --fields key: `%s'", tok);
-                       break;
-               } else if (ret == -ESRCH) {
-                       error("Unknown --fields key: `%s'", tok);
-                       break;
-               }
-       }
+       ret = setup_output_list(&perf_hpp_list, strp);
 
 out:
        free(str);
@@ -2542,7 +2715,7 @@ int setup_sorting(struct perf_evlist *evlist)
                return err;
 
        if (parent_pattern != default_parent_pattern) {
-               err = sort_dimension__add("parent", evlist);
+               err = sort_dimension__add(&perf_hpp_list, "parent", evlist, -1);
                if (err < 0)
                        return err;
        }
@@ -2560,9 +2733,13 @@ int setup_sorting(struct perf_evlist *evlist)
                return err;
 
        /* copy sort keys to output fields */
-       perf_hpp__setup_output_field();
+       perf_hpp__setup_output_field(&perf_hpp_list);
        /* and then copy output fields to sort keys */
-       perf_hpp__append_sort_keys();
+       perf_hpp__append_sort_keys(&perf_hpp_list);
+
+       /* setup hists-specific output fields */
+       if (perf_hpp__setup_hists_formats(&perf_hpp_list, evlist) < 0)
+               return -1;
 
        return 0;
 }
@@ -2578,5 +2755,5 @@ void reset_output_field(void)
        sort_order = NULL;
 
        reset_dimensions();
-       perf_hpp__reset_output_field();
+       perf_hpp__reset_output_field(&perf_hpp_list);
 }
index 687bbb1244281ba65a99c3cb78f5bcb8a1eaa41b..3f4e359981192ac50b56e770aa472749666e1f98 100644 (file)
@@ -32,9 +32,12 @@ extern const char default_sort_order[];
 extern regex_t ignore_callees_regex;
 extern int have_ignore_callees;
 extern int sort__need_collapse;
+extern int sort__has_dso;
 extern int sort__has_parent;
 extern int sort__has_sym;
 extern int sort__has_socket;
+extern int sort__has_thread;
+extern int sort__has_comm;
 extern enum sort_mode sort__mode;
 extern struct sort_entry sort_comm;
 extern struct sort_entry sort_dso;
@@ -94,9 +97,11 @@ struct hist_entry {
        s32                     socket;
        s32                     cpu;
        u8                      cpumode;
+       u8                      depth;
 
        /* We are added by hists__add_dummy_entry. */
        bool                    dummy;
+       bool                    leaf;
 
        char                    level;
        u8                      filtered;
@@ -113,18 +118,28 @@ struct hist_entry {
                        bool    init_have_children;
                        bool    unfolded;
                        bool    has_children;
+                       bool    has_no_entry;
                };
        };
        char                    *srcline;
        char                    *srcfile;
        struct symbol           *parent;
-       struct rb_root          sorted_chain;
        struct branch_info      *branch_info;
        struct hists            *hists;
        struct mem_info         *mem_info;
        void                    *raw_data;
        u32                     raw_size;
        void                    *trace_output;
+       struct perf_hpp_list    *hpp_list;
+       struct hist_entry       *parent_he;
+       union {
+               /* this is for hierarchical entry structure */
+               struct {
+                       struct rb_root  hroot_in;
+                       struct rb_root  hroot_out;
+               };                              /* non-leaf entries */
+               struct rb_root  sorted_chain;   /* leaf entry has callchains */
+       };
        struct callchain_root   callchain[0]; /* must be last member */
 };
 
@@ -160,6 +175,17 @@ static inline float hist_entry__get_percent_limit(struct hist_entry *he)
        return period * 100.0 / total_period;
 }
 
+static inline u64 cl_address(u64 address)
+{
+       /* return the cacheline of the address */
+       return (address & ~(cacheline_size - 1));
+}
+
+static inline u64 cl_offset(u64 address)
+{
+       /* return the cacheline of the address */
+       return (address & (cacheline_size - 1));
+}
 
 enum sort_mode {
        SORT_MODE__NORMAL,
@@ -221,6 +247,7 @@ struct sort_entry {
        int64_t (*se_sort)(struct hist_entry *, struct hist_entry *);
        int     (*se_snprintf)(struct hist_entry *he, char *bf, size_t size,
                               unsigned int width);
+       int     (*se_filter)(struct hist_entry *he, int type, const void *arg);
        u8      se_width_idx;
 };
 
index 6ac03146889d29be60707efd6e04c27c919f64de..b33ffb2af2cf5900378fb9fb8ef60e9eddaaf9db 100644 (file)
@@ -2,6 +2,7 @@
 #include "evsel.h"
 #include "stat.h"
 #include "color.h"
+#include "pmu.h"
 
 enum {
        CTX_BIT_USER    = 1 << 0,
@@ -14,6 +15,13 @@ enum {
 
 #define NUM_CTX CTX_BIT_MAX
 
+/*
+ * AGGR_GLOBAL: Use CPU 0
+ * AGGR_SOCKET: Use first CPU of socket
+ * AGGR_CORE: Use first CPU of core
+ * AGGR_NONE: Use matching CPU
+ * AGGR_THREAD: Not supported?
+ */
 static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
 static struct stats runtime_cycles_stats[NUM_CTX][MAX_NR_CPUS];
 static struct stats runtime_stalled_cycles_front_stats[NUM_CTX][MAX_NR_CPUS];
@@ -28,9 +36,15 @@ static struct stats runtime_dtlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
 static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS];
 static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS];
 static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS];
+static bool have_frontend_stalled;
 
 struct stats walltime_nsecs_stats;
 
+void perf_stat__init_shadow_stats(void)
+{
+       have_frontend_stalled = pmu_have_event("cpu", "stalled-cycles-frontend");
+}
+
 static int evsel_context(struct perf_evsel *evsel)
 {
        int ctx = 0;
@@ -137,9 +151,10 @@ static const char *get_ratio_color(enum grc_type type, double ratio)
        return color;
 }
 
-static void print_stalled_cycles_frontend(FILE *out, int cpu,
+static void print_stalled_cycles_frontend(int cpu,
                                          struct perf_evsel *evsel
-                                         __maybe_unused, double avg)
+                                         __maybe_unused, double avg,
+                                         struct perf_stat_output_ctx *out)
 {
        double total, ratio = 0.0;
        const char *color;
@@ -152,14 +167,17 @@ static void print_stalled_cycles_frontend(FILE *out, int cpu,
 
        color = get_ratio_color(GRC_STALLED_CYCLES_FE, ratio);
 
-       fprintf(out, " #  ");
-       color_fprintf(out, color, "%6.2f%%", ratio);
-       fprintf(out, " frontend cycles idle   ");
+       if (ratio)
+               out->print_metric(out->ctx, color, "%7.2f%%", "frontend cycles idle",
+                                 ratio);
+       else
+               out->print_metric(out->ctx, NULL, NULL, "frontend cycles idle", 0);
 }
 
-static void print_stalled_cycles_backend(FILE *out, int cpu,
+static void print_stalled_cycles_backend(int cpu,
                                         struct perf_evsel *evsel
-                                        __maybe_unused, double avg)
+                                        __maybe_unused, double avg,
+                                        struct perf_stat_output_ctx *out)
 {
        double total, ratio = 0.0;
        const char *color;
@@ -172,14 +190,13 @@ static void print_stalled_cycles_backend(FILE *out, int cpu,
 
        color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
 
-       fprintf(out, " #  ");
-       color_fprintf(out, color, "%6.2f%%", ratio);
-       fprintf(out, " backend  cycles idle   ");
+       out->print_metric(out->ctx, color, "%6.2f%%", "backend cycles idle", ratio);
 }
 
-static void print_branch_misses(FILE *out, int cpu,
+static void print_branch_misses(int cpu,
                                struct perf_evsel *evsel __maybe_unused,
-                               double avg)
+                               double avg,
+                               struct perf_stat_output_ctx *out)
 {
        double total, ratio = 0.0;
        const char *color;
@@ -192,14 +209,13 @@ static void print_branch_misses(FILE *out, int cpu,
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
-       fprintf(out, " #  ");
-       color_fprintf(out, color, "%6.2f%%", ratio);
-       fprintf(out, " of all branches        ");
+       out->print_metric(out->ctx, color, "%7.2f%%", "of all branches", ratio);
 }
 
-static void print_l1_dcache_misses(FILE *out, int cpu,
+static void print_l1_dcache_misses(int cpu,
                                   struct perf_evsel *evsel __maybe_unused,
-                                  double avg)
+                                  double avg,
+                                  struct perf_stat_output_ctx *out)
 {
        double total, ratio = 0.0;
        const char *color;
@@ -212,14 +228,13 @@ static void print_l1_dcache_misses(FILE *out, int cpu,
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
 
-       fprintf(out, " #  ");
-       color_fprintf(out, color, "%6.2f%%", ratio);
-       fprintf(out, " of all L1-dcache hits  ");
+       out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio);
 }
 
-static void print_l1_icache_misses(FILE *out, int cpu,
+static void print_l1_icache_misses(int cpu,
                                   struct perf_evsel *evsel __maybe_unused,
-                                  double avg)
+                                  double avg,
+                                  struct perf_stat_output_ctx *out)
 {
        double total, ratio = 0.0;
        const char *color;
@@ -231,15 +246,13 @@ static void print_l1_icache_misses(FILE *out, int cpu,
                ratio = avg / total * 100.0;
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-
-       fprintf(out, " #  ");
-       color_fprintf(out, color, "%6.2f%%", ratio);
-       fprintf(out, " of all L1-icache hits  ");
+       out->print_metric(out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio);
 }
 
-static void print_dtlb_cache_misses(FILE *out, int cpu,
+static void print_dtlb_cache_misses(int cpu,
                                    struct perf_evsel *evsel __maybe_unused,
-                                   double avg)
+                                   double avg,
+                                   struct perf_stat_output_ctx *out)
 {
        double total, ratio = 0.0;
        const char *color;
@@ -251,15 +264,13 @@ static void print_dtlb_cache_misses(FILE *out, int cpu,
                ratio = avg / total * 100.0;
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-
-       fprintf(out, " #  ");
-       color_fprintf(out, color, "%6.2f%%", ratio);
-       fprintf(out, " of all dTLB cache hits ");
+       out->print_metric(out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio);
 }
 
-static void print_itlb_cache_misses(FILE *out, int cpu,
+static void print_itlb_cache_misses(int cpu,
                                    struct perf_evsel *evsel __maybe_unused,
-                                   double avg)
+                                   double avg,
+                                   struct perf_stat_output_ctx *out)
 {
        double total, ratio = 0.0;
        const char *color;
@@ -271,15 +282,13 @@ static void print_itlb_cache_misses(FILE *out, int cpu,
                ratio = avg / total * 100.0;
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-
-       fprintf(out, " #  ");
-       color_fprintf(out, color, "%6.2f%%", ratio);
-       fprintf(out, " of all iTLB cache hits ");
+       out->print_metric(out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio);
 }
 
-static void print_ll_cache_misses(FILE *out, int cpu,
+static void print_ll_cache_misses(int cpu,
                                  struct perf_evsel *evsel __maybe_unused,
-                                 double avg)
+                                 double avg,
+                                 struct perf_stat_output_ctx *out)
 {
        double total, ratio = 0.0;
        const char *color;
@@ -291,15 +300,15 @@ static void print_ll_cache_misses(FILE *out, int cpu,
                ratio = avg / total * 100.0;
 
        color = get_ratio_color(GRC_CACHE_MISSES, ratio);
-
-       fprintf(out, " #  ");
-       color_fprintf(out, color, "%6.2f%%", ratio);
-       fprintf(out, " of all LL-cache hits   ");
+       out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
 }
 
-void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
-                                  double avg, int cpu, enum aggr_mode aggr)
+void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
+                                  double avg, int cpu,
+                                  struct perf_stat_output_ctx *out)
 {
+       void *ctxp = out->ctx;
+       print_metric_t print_metric = out->print_metric;
        double total, ratio = 0.0, total2;
        int ctx = evsel_context(evsel);
 
@@ -307,119 +316,145 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
                total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
                if (total) {
                        ratio = avg / total;
-                       fprintf(out, " #   %5.2f  insns per cycle        ", ratio);
+                       print_metric(ctxp, NULL, "%7.2f ",
+                                       "insn per cycle", ratio);
                } else {
-                       fprintf(out, "                                   ");
+                       print_metric(ctxp, NULL, NULL, "insn per cycle", 0);
                }
                total = avg_stats(&runtime_stalled_cycles_front_stats[ctx][cpu]);
                total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[ctx][cpu]));
 
                if (total && avg) {
+                       out->new_line(ctxp);
                        ratio = total / avg;
-                       fprintf(out, "\n");
-                       if (aggr == AGGR_NONE)
-                               fprintf(out, "        ");
-                       fprintf(out, "                                                  #   %5.2f  stalled cycles per insn", ratio);
+                       print_metric(ctxp, NULL, "%7.2f ",
+                                       "stalled cycles per insn",
+                                       ratio);
+               } else if (have_frontend_stalled) {
+                       print_metric(ctxp, NULL, NULL,
+                                    "stalled cycles per insn", 0);
                }
-
-       } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
-                       runtime_branches_stats[ctx][cpu].n != 0) {
-               print_branch_misses(out, cpu, evsel, avg);
+       } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES)) {
+               if (runtime_branches_stats[ctx][cpu].n != 0)
+                       print_branch_misses(cpu, evsel, avg, out);
+               else
+                       print_metric(ctxp, NULL, NULL, "of all branches", 0);
        } else if (
                evsel->attr.type == PERF_TYPE_HW_CACHE &&
                evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1D |
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
-                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
-                       runtime_l1_dcache_stats[ctx][cpu].n != 0) {
-               print_l1_dcache_misses(out, cpu, evsel, avg);
+                                        ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
+               if (runtime_l1_dcache_stats[ctx][cpu].n != 0)
+                       print_l1_dcache_misses(cpu, evsel, avg, out);
+               else
+                       print_metric(ctxp, NULL, NULL, "of all L1-dcache hits", 0);
        } else if (
                evsel->attr.type == PERF_TYPE_HW_CACHE &&
                evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_L1I |
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
-                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
-                       runtime_l1_icache_stats[ctx][cpu].n != 0) {
-               print_l1_icache_misses(out, cpu, evsel, avg);
+                                        ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
+               if (runtime_l1_icache_stats[ctx][cpu].n != 0)
+                       print_l1_icache_misses(cpu, evsel, avg, out);
+               else
+                       print_metric(ctxp, NULL, NULL, "of all L1-icache hits", 0);
        } else if (
                evsel->attr.type == PERF_TYPE_HW_CACHE &&
                evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_DTLB |
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
-                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
-                       runtime_dtlb_cache_stats[ctx][cpu].n != 0) {
-               print_dtlb_cache_misses(out, cpu, evsel, avg);
+                                        ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
+               if (runtime_dtlb_cache_stats[ctx][cpu].n != 0)
+                       print_dtlb_cache_misses(cpu, evsel, avg, out);
+               else
+                       print_metric(ctxp, NULL, NULL, "of all dTLB cache hits", 0);
        } else if (
                evsel->attr.type == PERF_TYPE_HW_CACHE &&
                evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_ITLB |
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
-                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
-                       runtime_itlb_cache_stats[ctx][cpu].n != 0) {
-               print_itlb_cache_misses(out, cpu, evsel, avg);
+                                        ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
+               if (runtime_itlb_cache_stats[ctx][cpu].n != 0)
+                       print_itlb_cache_misses(cpu, evsel, avg, out);
+               else
+                       print_metric(ctxp, NULL, NULL, "of all iTLB cache hits", 0);
        } else if (
                evsel->attr.type == PERF_TYPE_HW_CACHE &&
                evsel->attr.config ==  ( PERF_COUNT_HW_CACHE_LL |
                                        ((PERF_COUNT_HW_CACHE_OP_READ) << 8) |
-                                       ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16)) &&
-                       runtime_ll_cache_stats[ctx][cpu].n != 0) {
-               print_ll_cache_misses(out, cpu, evsel, avg);
-       } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES) &&
-                       runtime_cacherefs_stats[ctx][cpu].n != 0) {
+                                        ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))) {
+               if (runtime_ll_cache_stats[ctx][cpu].n != 0)
+                       print_ll_cache_misses(cpu, evsel, avg, out);
+               else
+                       print_metric(ctxp, NULL, NULL, "of all LL-cache hits", 0);
+       } else if (perf_evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
                total = avg_stats(&runtime_cacherefs_stats[ctx][cpu]);
 
                if (total)
                        ratio = avg * 100 / total;
 
-               fprintf(out, " # %8.3f %% of all cache refs    ", ratio);
-
+               if (runtime_cacherefs_stats[ctx][cpu].n != 0)
+                       print_metric(ctxp, NULL, "%8.3f %%",
+                                    "of all cache refs", ratio);
+               else
+                       print_metric(ctxp, NULL, NULL, "of all cache refs", 0);
        } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
-               print_stalled_cycles_frontend(out, cpu, evsel, avg);
+               print_stalled_cycles_frontend(cpu, evsel, avg, out);
        } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_BACKEND)) {
-               print_stalled_cycles_backend(out, cpu, evsel, avg);
+               print_stalled_cycles_backend(cpu, evsel, avg, out);
        } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
                total = avg_stats(&runtime_nsecs_stats[cpu]);
 
                if (total) {
                        ratio = avg / total;
-                       fprintf(out, " # %8.3f GHz                    ", ratio);
+                       print_metric(ctxp, NULL, "%8.3f", "GHz", ratio);
                } else {
-                       fprintf(out, "                                   ");
+                       print_metric(ctxp, NULL, NULL, "Ghz", 0);
                }
        } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX)) {
                total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
                if (total)
-                       fprintf(out,
-                               " #   %5.2f%% transactional cycles   ",
-                               100.0 * (avg / total));
+                       print_metric(ctxp, NULL,
+                                       "%7.2f%%", "transactional cycles",
+                                       100.0 * (avg / total));
+               else
+                       print_metric(ctxp, NULL, NULL, "transactional cycles",
+                                    0);
        } else if (perf_stat_evsel__is(evsel, CYCLES_IN_TX_CP)) {
                total = avg_stats(&runtime_cycles_stats[ctx][cpu]);
                total2 = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
                if (total2 < avg)
                        total2 = avg;
                if (total)
-                       fprintf(out,
-                               " #   %5.2f%% aborted cycles         ",
+                       print_metric(ctxp, NULL, "%7.2f%%", "aborted cycles",
                                100.0 * ((total2-avg) / total));
-       } else if (perf_stat_evsel__is(evsel, TRANSACTION_START) &&
-                  runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
+               else
+                       print_metric(ctxp, NULL, NULL, "aborted cycles", 0);
+       } else if (perf_stat_evsel__is(evsel, TRANSACTION_START)) {
                total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
 
                if (avg)
                        ratio = total / avg;
 
-               fprintf(out, " # %8.0f cycles / transaction   ", ratio);
-       } else if (perf_stat_evsel__is(evsel, ELISION_START) &&
-                  runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
+               if (runtime_cycles_in_tx_stats[ctx][cpu].n != 0)
+                       print_metric(ctxp, NULL, "%8.0f",
+                                    "cycles / transaction", ratio);
+               else
+                       print_metric(ctxp, NULL, NULL, "cycles / transaction",
+                                    0);
+       } else if (perf_stat_evsel__is(evsel, ELISION_START)) {
                total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
 
                if (avg)
                        ratio = total / avg;
 
-               fprintf(out, " # %8.0f cycles / elision       ", ratio);
+               print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio);
        } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) {
                if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
-                       fprintf(out, " # %8.3f CPUs utilized          ", avg / ratio);
+                       print_metric(ctxp, NULL, "%8.3f", "CPUs utilized",
+                                    avg / ratio);
                else
-                       fprintf(out, "                                   ");
+                       print_metric(ctxp, NULL, NULL, "CPUs utilized", 0);
        } else if (runtime_nsecs_stats[cpu].n != 0) {
                char unit = 'M';
+               char unit_buf[10];
 
                total = avg_stats(&runtime_nsecs_stats[cpu]);
 
@@ -429,9 +464,9 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
                        ratio *= 1000;
                        unit = 'K';
                }
-
-               fprintf(out, " # %8.3f %c/sec                  ", ratio, unit);
+               snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit);
+               print_metric(ctxp, NULL, "%8.3f", unit_buf, ratio);
        } else {
-               fprintf(out, "                                   ");
+               print_metric(ctxp, NULL, NULL, NULL, 0);
        }
 }
index afb0c45eba34ba8db7a6cb6d258326f545f7aca1..4d9b481cf3b6edbb7d6161cbd238709241dedc5b 100644 (file)
@@ -97,7 +97,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
        }
 }
 
-void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
+static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
 {
        int i;
        struct perf_stat_evsel *ps = evsel->priv;
@@ -108,7 +108,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
        perf_stat_evsel_id_init(evsel);
 }
 
-int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
+static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
 {
        evsel->priv = zalloc(sizeof(struct perf_stat_evsel));
        if (evsel->priv == NULL)
@@ -117,13 +117,13 @@ int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
        return 0;
 }
 
-void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
+static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
 {
        zfree(&evsel->priv);
 }
 
-int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
-                                     int ncpus, int nthreads)
+static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
+                                            int ncpus, int nthreads)
 {
        struct perf_counts *counts;
 
@@ -134,13 +134,13 @@ int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
        return counts ? 0 : -ENOMEM;
 }
 
-void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
+static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
 {
        perf_counts__delete(evsel->prev_raw_counts);
        evsel->prev_raw_counts = NULL;
 }
 
-int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
+static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
 {
        int ncpus = perf_evsel__nr_cpus(evsel);
        int nthreads = thread_map__nr(evsel->threads);
index 086f4e128d6351f0e0de862c2ebcc44801cbc2f8..0150e786ccc7c1f48e407323b606f47155a076c9 100644 (file)
@@ -68,21 +68,23 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel);
 
 extern struct stats walltime_nsecs_stats;
 
+typedef void (*print_metric_t)(void *ctx, const char *color, const char *unit,
+                              const char *fmt, double val);
+typedef void (*new_line_t )(void *ctx);
+
+void perf_stat__init_shadow_stats(void);
 void perf_stat__reset_shadow_stats(void);
 void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
                                    int cpu);
-void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
-                                  double avg, int cpu, enum aggr_mode aggr);
-
-void perf_evsel__reset_stat_priv(struct perf_evsel *evsel);
-int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel);
-void perf_evsel__free_stat_priv(struct perf_evsel *evsel);
-
-int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
-                                     int ncpus, int nthreads);
-void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel);
+struct perf_stat_output_ctx {
+       void *ctx;
+       print_metric_t print_metric;
+       new_line_t new_line;
+};
 
-int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw);
+void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
+                                  double avg, int cpu,
+                                  struct perf_stat_output_ctx *out);
 
 int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
 void perf_evlist__free_stats(struct perf_evlist *evlist);
index 25671fa166188413c66758a978082e89a1ba08d2..d3d279275432ee663641a1a6dbb0a0cf8d3b8334 100644 (file)
@@ -51,30 +51,6 @@ void strbuf_grow(struct strbuf *sb, size_t extra)
        ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
 }
 
-static void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
-                                  const void *data, size_t dlen)
-{
-       if (pos + len < pos)
-               die("you want to use way too much memory");
-       if (pos > sb->len)
-               die("`pos' is too far after the end of the buffer");
-       if (pos + len > sb->len)
-               die("`pos + len' is too far after the end of the buffer");
-
-       if (dlen >= len)
-               strbuf_grow(sb, dlen - len);
-       memmove(sb->buf + pos + dlen,
-                       sb->buf + pos + len,
-                       sb->len - pos - len);
-       memcpy(sb->buf + pos, data, dlen);
-       strbuf_setlen(sb, sb->len + dlen - len);
-}
-
-void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
-{
-       strbuf_splice(sb, pos, len, NULL, 0);
-}
-
 void strbuf_add(struct strbuf *sb, const void *data, size_t len)
 {
        strbuf_grow(sb, len);
index 529f2f03524915ab9cae7c5608de444fd875812d..7a32c838884d8de6feaa3223e388199c5c939301 100644 (file)
@@ -77,8 +77,6 @@ static inline void strbuf_addch(struct strbuf *sb, int c) {
        sb->buf[sb->len] = '\0';
 }
 
-extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);
-
 extern void strbuf_add(struct strbuf *, const void *, size_t);
 static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
        strbuf_add(sb, s, strlen(s));
index 562b8ebeae5b2414b6bac867c928cb22ee9a5f13..b1dd68f358fcd8e7390b5929ed736a357c7853c1 100644 (file)
@@ -6,6 +6,7 @@
 #include <inttypes.h>
 
 #include "symbol.h"
+#include "demangle-java.h"
 #include "machine.h"
 #include "vdso.h"
 #include <symbol/kallsyms.h>
@@ -1077,6 +1078,8 @@ new_symbol:
                                demangle_flags = DMGL_PARAMS | DMGL_ANSI;
 
                        demangled = bfd_demangle(NULL, elf_name, demangle_flags);
+                       if (demangled == NULL)
+                               demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
                        if (demangled != NULL)
                                elf_name = demangled;
                }
index ab02209a7cf3b162431bfc006287f5fbd8c68f43..e7588dc915181729394c1d2195c78576c47d20df 100644 (file)
@@ -1466,7 +1466,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
         * Read the build id if possible. This is required for
         * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
         */
-       if (filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0)
+       if (is_regular_file(name) &&
+           filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0)
                dso__set_build_id(dso, build_id);
 
        /*
@@ -1487,6 +1488,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
                                                   root_dir, name, PATH_MAX))
                        continue;
 
+               if (!is_regular_file(name))
+                       continue;
+
                /* Name is now the name of the next image to try */
                if (symsrc__init(ss, dso, name, symtab_type) < 0)
                        continue;
@@ -1525,6 +1529,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
        if (!runtime_ss && syms_ss)
                runtime_ss = syms_ss;
 
+       if (syms_ss && syms_ss->type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
+               if (dso__build_id_is_kmod(dso, name, PATH_MAX))
+                       kmod = true;
+
        if (syms_ss)
                ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod);
        else
index ccd1caa40e116645be37025665388886d7c97546..a937053a0ae07a6214fb03753faa66819ed40884 100644 (file)
@@ -110,7 +110,8 @@ struct symbol_conf {
                        has_filter,
                        show_ref_callgraph,
                        hide_unresolved,
-                       raw_trace;
+                       raw_trace,
+                       report_hierarchy;
        const char      *vmlinux_name,
                        *kallsyms_name,
                        *source_prefix,
index 802bb868d446cafa7c5383982193ad13d87b785a..8ae051e0ec79090e674fdf9a6cc9fbece8275ebb 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/err.h>
 #include <traceevent/event-parse.h>
 #include <api/fs/tracing_path.h>
+#include <api/fs/fs.h>
 #include "trace-event.h"
 #include "machine.h"
 #include "util.h"
index 4d4210d4e13d1d7fbc32a5c1f4afff58a0810fd0..1b741646eed00b7754ba0a618b4fb57b8c87d9ac 100644 (file)
@@ -19,7 +19,7 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)
        u64 quot, rem;
 
        quot = cyc >> tc->time_shift;
-       rem  = cyc & ((1 << tc->time_shift) - 1);
+       rem  = cyc & (((u64)1 << tc->time_shift) - 1);
        return tc->time_zero + quot * tc->time_mult +
               ((rem * tc->time_mult) >> tc->time_shift);
 }
index ead9509835d23e2aee29b9f3548613973a5937fb..b7766c577b015d978fd3e9960c451692f81daa6e 100644 (file)
@@ -14,6 +14,7 @@
 #include <limits.h>
 #include <byteswap.h>
 #include <linux/kernel.h>
+#include <linux/log2.h>
 #include <unistd.h>
 #include "callchain.h"
 #include "strlist.h"
@@ -507,54 +508,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
        return ret;
 }
 
-int filename__read_str(const char *filename, char **buf, size_t *sizep)
-{
-       size_t size = 0, alloc_size = 0;
-       void *bf = NULL, *nbf;
-       int fd, n, err = 0;
-       char sbuf[STRERR_BUFSIZE];
-
-       fd = open(filename, O_RDONLY);
-       if (fd < 0)
-               return -errno;
-
-       do {
-               if (size == alloc_size) {
-                       alloc_size += BUFSIZ;
-                       nbf = realloc(bf, alloc_size);
-                       if (!nbf) {
-                               err = -ENOMEM;
-                               break;
-                       }
-
-                       bf = nbf;
-               }
-
-               n = read(fd, bf + size, alloc_size - size);
-               if (n < 0) {
-                       if (size) {
-                               pr_warning("read failed %d: %s\n", errno,
-                                        strerror_r(errno, sbuf, sizeof(sbuf)));
-                               err = 0;
-                       } else
-                               err = -errno;
-
-                       break;
-               }
-
-               size += n;
-       } while (n > 0);
-
-       if (!err) {
-               *sizep = size;
-               *buf   = bf;
-       } else
-               free(bf);
-
-       close(fd);
-       return err;
-}
-
 const char *get_filename_for_perf_kvm(void)
 {
        const char *filename;
@@ -691,3 +644,66 @@ out:
 
        return tip;
 }
+
+bool is_regular_file(const char *file)
+{
+       struct stat st;
+
+       if (stat(file, &st))
+               return false;
+
+       return S_ISREG(st.st_mode);
+}
+
+int fetch_current_timestamp(char *buf, size_t sz)
+{
+       struct timeval tv;
+       struct tm tm;
+       char dt[32];
+
+       if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
+               return -1;
+
+       if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
+               return -1;
+
+       scnprintf(buf, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
+
+       return 0;
+}
+
+void print_binary(unsigned char *data, size_t len,
+                 size_t bytes_per_line, print_binary_t printer,
+                 void *extra)
+{
+       size_t i, j, mask;
+
+       if (!printer)
+               return;
+
+       bytes_per_line = roundup_pow_of_two(bytes_per_line);
+       mask = bytes_per_line - 1;
+
+       printer(BINARY_PRINT_DATA_BEGIN, 0, extra);
+       for (i = 0; i < len; i++) {
+               if ((i & mask) == 0) {
+                       printer(BINARY_PRINT_LINE_BEGIN, -1, extra);
+                       printer(BINARY_PRINT_ADDR, i, extra);
+               }
+
+               printer(BINARY_PRINT_NUM_DATA, data[i], extra);
+
+               if (((i & mask) == mask) || i == len - 1) {
+                       for (j = 0; j < mask-(i & mask); j++)
+                               printer(BINARY_PRINT_NUM_PAD, -1, extra);
+
+                       printer(BINARY_PRINT_SEP, i, extra);
+                       for (j = i & ~mask; j <= i; j++)
+                               printer(BINARY_PRINT_CHAR_DATA, data[j], extra);
+                       for (j = 0; j < mask-(i & mask); j++)
+                               printer(BINARY_PRINT_CHAR_PAD, i, extra);
+                       printer(BINARY_PRINT_LINE_END, -1, extra);
+               }
+       }
+       printer(BINARY_PRINT_DATA_END, -1, extra);
+}
index fe915e616f9b65388e15be963d0ef5cf58c325fd..d0d50cef8b2af31703c7d298f68d93b68326c3c5 100644 (file)
@@ -82,6 +82,8 @@
 
 extern const char *graph_line;
 extern const char *graph_dotted_line;
+extern const char *spaces;
+extern const char *dots;
 extern char buildid_dir[];
 
 /* On most systems <limits.h> would have given us this, but
@@ -303,7 +305,6 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
                  bool show_sym, bool unwind_inlines);
 void free_srcline(char *srcline);
 
-int filename__read_str(const char *filename, char **buf, size_t *sizep);
 int perf_event_paranoid(void);
 
 void mem_bswap_64(void *src, int byte_size);
@@ -343,5 +344,27 @@ int fetch_kernel_version(unsigned int *puint,
 #define KVER_PARAM(x)  KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
 
 const char *perf_tip(const char *dirpath);
+bool is_regular_file(const char *file);
+int fetch_current_timestamp(char *buf, size_t sz);
+
+enum binary_printer_ops {
+       BINARY_PRINT_DATA_BEGIN,
+       BINARY_PRINT_LINE_BEGIN,
+       BINARY_PRINT_ADDR,
+       BINARY_PRINT_NUM_DATA,
+       BINARY_PRINT_NUM_PAD,
+       BINARY_PRINT_SEP,
+       BINARY_PRINT_CHAR_DATA,
+       BINARY_PRINT_CHAR_PAD,
+       BINARY_PRINT_LINE_END,
+       BINARY_PRINT_DATA_END,
+};
+
+typedef void (*print_binary_t)(enum binary_printer_ops,
+                              unsigned int val,
+                              void *extra);
 
+void print_binary(unsigned char *data, size_t len,
+                 size_t bytes_per_line, print_binary_t printer,
+                 void *extra);
 #endif /* GIT_COMPAT_UTIL_H */
index 622db685b4f9930ab4c2f67aadf947969652371f..89a55d5e32f301e13751101f3f6b9cf7c5c07450 100644 (file)
@@ -34,7 +34,10 @@ name as necessary to disambiguate it from others is necessary.  Note that option
 \fB--debug\fP displays additional system configuration information.  Invoking this parameter
 more than once may also enable internal turbostat debug information.
 .PP
-\fB--interval seconds\fP overrides the default 5-second measurement interval.
+\fB--interval seconds\fP overrides the default 5.0 second measurement interval.
+.PP
+\fB--out output_file\fP turbostat output is written to the specified output_file.
+The file is truncated if it already exists, and it is created if it does not exist.
 .PP
 \fB--help\fP displays usage for the most common parameters.
 .PP
@@ -61,7 +64,7 @@ displays the statistics gathered since it was forked.
 .nf
 \fBCPU\fP Linux CPU (logical processor) number.  Yes, it is okay that on many systems the CPUs are not listed in numerical order -- for efficiency reasons, turbostat runs in topology order, so HT siblings appear together.
 \fBAVG_MHz\fP number of cycles executed divided by time elapsed.
-\fB%Busy\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state.
+\fBBusy%\fP percent of the interval that the CPU retired instructions, aka. % of time in "C0" state.
 \fBBzy_MHz\fP average clock rate while the CPU was busy (in "c0" state).
 \fBTSC_MHz\fP average MHz that the TSC ran during the entire interval.
 .fi
@@ -83,13 +86,14 @@ Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading T
 \fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM.
 .fi
 .PP
-.SH EXAMPLE
+.SH PERIODIC EXAMPLE
 Without any parameters, turbostat displays statistics ever 5 seconds.
-(override interval with "-i sec" option, or specify a command
-for turbostat to fork).
+Periodic output goes to stdout, by default, unless --out is used to specify an output file.
+The 5-second interval can be changed with th "-i sec" option.
+Or a command may be specified as in "FORK EXAMPLE" below.
 .nf
 [root@hsw]# ./turbostat
-     CPU Avg_MHz   %Busy Bzy_MHz TSC_MHz
+     CPU Avg_MHz   Busy% Bzy_MHz TSC_MHz
        -     488   12.51    3898    3498
        0       0    0.01    3885    3498
        4    3897   99.99    3898    3498
@@ -145,7 +149,7 @@ cpu0: MSR_IA32_THERM_STATUS: 0x88340000 (48 C +/- 1)
 cpu1: MSR_IA32_THERM_STATUS: 0x88440000 (32 C +/- 1)
 cpu2: MSR_IA32_THERM_STATUS: 0x88450000 (31 C +/- 1)
 cpu3: MSR_IA32_THERM_STATUS: 0x88490000 (27 C +/- 1)
-    Core     CPU Avg_MHz   %Busy Bzy_MHz TSC_MHz     SMI  CPU%c1  CPU%c3  CPU%c6  CPU%c7 CoreTmp  PkgTmp PkgWatt CorWatt GFXWatt
+    Core     CPU Avg_MHz   Busy% Bzy_MHz TSC_MHz     SMI  CPU%c1  CPU%c3  CPU%c6  CPU%c7 CoreTmp  PkgTmp PkgWatt CorWatt GFXWatt
        -       -     493   12.64    3898    3498       0   12.64    0.00    0.00   74.72      47      47   21.62   13.74    0.00
        0       0       4    0.11    3894    3498       0   99.89    0.00    0.00    0.00      47      47   21.62   13.74    0.00
        0       4    3897   99.98    3898    3498       0    0.02
@@ -171,14 +175,16 @@ The --debug option adds additional columns to the measurement ouput, including C
 See the field definitions above.
 .SH FORK EXAMPLE
 If turbostat is invoked with a command, it will fork that command
-and output the statistics gathered when the command exits.
+and output the statistics gathered after the command exits.
+In this case, turbostat output goes to stderr, by default.
+Output can instead be saved to a file using the --out option.
 eg. Here a cycle soaker is run on 1 CPU (see %c0) for a few seconds
 until ^C while the other CPUs are mostly idle:
 
 .nf
 root@hsw: turbostat cat /dev/zero > /dev/null
 ^C
-     CPU Avg_MHz   %Busy Bzy_MHz TSC_MHz
+     CPU Avg_MHz   Busy% Bzy_MHz TSC_MHz
        -     482   12.51    3854    3498
        0       0    0.01    1960    3498
        4       0    0.00    2128    3498
@@ -192,12 +198,12 @@ root@hsw: turbostat cat /dev/zero > /dev/null
 
 .fi
 Above the cycle soaker drives cpu5 up its 3.9 GHz turbo limit.
-The first row shows the average MHz and %Busy across all the processors in the system.
+The first row shows the average MHz and Busy% across all the processors in the system.
 
 Note that the Avg_MHz column reflects the total number of cycles executed
-divided by the measurement interval.  If the %Busy column is 100%,
+divided by the measurement interval.  If the Busy% column is 100%,
 then the processor was running at that speed the entire interval.
-The Avg_MHz multiplied by the %Busy results in the Bzy_MHz --
+The Avg_MHz multiplied by the Busy% results in the Bzy_MHz --
 which is the average frequency while the processor was executing --
 not including any non-busy idle time.
 
@@ -233,7 +239,7 @@ in the brand string in /proc/cpuinfo.  On a system where
 the TSC stops in idle, TSC_MHz will drop
 below the processor's base frequency.
 
-%Busy = MPERF_delta/TSC_delta
+Busy% = MPERF_delta/TSC_delta
 
 Bzy_MHz = TSC_delta/APERF_delta/MPERF_delta/measurement_interval
 
index 0dac7e05a6ac9e5f1500eca1cebbce2d900ab511..20a257a12ea5000707edd0ba34a4368df79e35e2 100644 (file)
 #include <string.h>
 #include <ctype.h>
 #include <sched.h>
+#include <time.h>
 #include <cpuid.h>
 #include <linux/capability.h>
 #include <errno.h>
 
 char *proc_stat = "/proc/stat";
-unsigned int interval_sec = 5;
+FILE *outf;
+int *fd_percpu;
+struct timespec interval_ts = {5, 0};
 unsigned int debug;
 unsigned int rapl_joules;
 unsigned int summary_only;
@@ -72,6 +75,7 @@ unsigned int extra_msr_offset64;
 unsigned int extra_delta_offset32;
 unsigned int extra_delta_offset64;
 unsigned int aperf_mperf_multiplier = 1;
+int do_irq = 1;
 int do_smi;
 double bclk;
 double base_hz;
@@ -86,6 +90,10 @@ char *output_buffer, *outp;
 unsigned int do_rapl;
 unsigned int do_dts;
 unsigned int do_ptm;
+unsigned int do_gfx_rc6_ms;
+unsigned long long  gfx_cur_rc6_ms;
+unsigned int do_gfx_mhz;
+unsigned int gfx_cur_mhz;
 unsigned int tcc_activation_temp;
 unsigned int tcc_activation_temp_override;
 double rapl_power_units, rapl_time_units;
@@ -98,6 +106,12 @@ unsigned int crystal_hz;
 unsigned long long tsc_hz;
 int base_cpu;
 double discover_bclk(unsigned int family, unsigned int model);
+unsigned int has_hwp;  /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
+                       /* IA32_HWP_REQUEST, IA32_HWP_STATUS */
+unsigned int has_hwp_notify;           /* IA32_HWP_INTERRUPT */
+unsigned int has_hwp_activity_window;  /* IA32_HWP_REQUEST[bits 41:32] */
+unsigned int has_hwp_epp;              /* IA32_HWP_REQUEST[bits 31:24] */
+unsigned int has_hwp_pkg;              /* IA32_HWP_REQUEST_PKG */
 
 #define RAPL_PKG               (1 << 0)
                                        /* 0x610 MSR_PKG_POWER_LIMIT */
@@ -145,6 +159,7 @@ struct thread_data {
        unsigned long long extra_delta64;
        unsigned long long extra_msr32;
        unsigned long long extra_delta32;
+       unsigned int irq_count;
        unsigned int smi_count;
        unsigned int cpu_id;
        unsigned int flags;
@@ -172,6 +187,8 @@ struct pkg_data {
        unsigned long long pkg_any_core_c0;
        unsigned long long pkg_any_gfxe_c0;
        unsigned long long pkg_both_core_gfxe_c0;
+       unsigned long long gfx_rc6_ms;
+       unsigned int gfx_mhz;
        unsigned int package_id;
        unsigned int energy_pkg;        /* MSR_PKG_ENERGY_STATUS */
        unsigned int energy_dram;       /* MSR_DRAM_ENERGY_STATUS */
@@ -212,6 +229,9 @@ struct topo_params {
 
 struct timeval tv_even, tv_odd, tv_delta;
 
+int *irq_column_2_cpu; /* /proc/interrupts column numbers */
+int *irqs_per_cpu;             /* indexed by cpu_num */
+
 void setup_all_buffers(void);
 
 int cpu_is_not_present(int cpu)
@@ -262,23 +282,34 @@ int cpu_migrate(int cpu)
        else
                return 0;
 }
-
-int get_msr(int cpu, off_t offset, unsigned long long *msr)
+int get_msr_fd(int cpu)
 {
-       ssize_t retval;
        char pathname[32];
        int fd;
 
+       fd = fd_percpu[cpu];
+
+       if (fd)
+               return fd;
+
        sprintf(pathname, "/dev/cpu/%d/msr", cpu);
        fd = open(pathname, O_RDONLY);
        if (fd < 0)
                err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
 
-       retval = pread(fd, msr, sizeof *msr, offset);
-       close(fd);
+       fd_percpu[cpu] = fd;
+
+       return fd;
+}
+
+int get_msr(int cpu, off_t offset, unsigned long long *msr)
+{
+       ssize_t retval;
+
+       retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
 
        if (retval != sizeof *msr)
-               err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
+               err(-1, "msr %d offset 0x%llx read failed", cpu, (unsigned long long)offset);
 
        return 0;
 }
@@ -286,8 +317,8 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
 /*
  * Example Format w/ field column widths:
  *
- *  Package    Core     CPU Avg_MHz Bzy_MHz TSC_MHz     SMI   %Busy CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp  PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
- * 123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678
+ *  Package    Core     CPU Avg_MHz Bzy_MHz TSC_MHz     IRQ   SMI   Busy% CPU_%c1 CPU_%c3 CPU_%c6 CPU_%c7 CoreTmp  PkgTmp  GFXMHz Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 PkgWatt CorWatt GFXWatt
+ * 12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678
  */
 
 void print_header(void)
@@ -301,7 +332,7 @@ void print_header(void)
        if (has_aperf)
                outp += sprintf(outp, " Avg_MHz");
        if (has_aperf)
-               outp += sprintf(outp, "   %%Busy");
+               outp += sprintf(outp, "   Busy%%");
        if (has_aperf)
                outp += sprintf(outp, " Bzy_MHz");
        outp += sprintf(outp, " TSC_MHz");
@@ -318,6 +349,8 @@ void print_header(void)
        if (!debug)
                goto done;
 
+       if (do_irq)
+               outp += sprintf(outp, "     IRQ");
        if (do_smi)
                outp += sprintf(outp, "     SMI");
 
@@ -335,6 +368,12 @@ void print_header(void)
        if (do_ptm)
                outp += sprintf(outp, "  PkgTmp");
 
+       if (do_gfx_rc6_ms)
+               outp += sprintf(outp, " GFX%%rc6");
+
+       if (do_gfx_mhz)
+               outp += sprintf(outp, "  GFXMHz");
+
        if (do_skl_residency) {
                outp += sprintf(outp, " Totl%%C0");
                outp += sprintf(outp, "  Any%%C0");
@@ -409,6 +448,8 @@ int dump_counters(struct thread_data *t, struct core_data *c,
                        extra_msr_offset32, t->extra_msr32);
                outp += sprintf(outp, "msr0x%x: %016llX\n",
                        extra_msr_offset64, t->extra_msr64);
+               if (do_irq)
+                       outp += sprintf(outp, "IRQ: %08X\n", t->irq_count);
                if (do_smi)
                        outp += sprintf(outp, "SMI: %08X\n", t->smi_count);
        }
@@ -504,7 +545,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
                outp += sprintf(outp, "%8.0f",
                        1.0 / units * t->aperf / interval_float);
 
-       /* %Busy */
+       /* Busy% */
        if (has_aperf) {
                if (!skip_c0)
                        outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc/tsc_tweak);
@@ -542,6 +583,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
        if (!debug)
                goto done;
 
+       /* IRQ */
+       if (do_irq)
+               outp += sprintf(outp, "%8d", t->irq_count);
+
        /* SMI */
        if (do_smi)
                outp += sprintf(outp, "%8d", t->smi_count);
@@ -575,6 +620,14 @@ int format_counters(struct thread_data *t, struct core_data *c,
        if (do_ptm)
                outp += sprintf(outp, "%8d", p->pkg_temp_c);
 
+       /* GFXrc6 */
+       if (do_gfx_rc6_ms)
+               outp += sprintf(outp, "%8.2f", 100.0 * p->gfx_rc6_ms / 1000.0 / interval_float);
+
+       /* GFXMHz */
+       if (do_gfx_mhz)
+               outp += sprintf(outp, "%8d", p->gfx_mhz);
+
        /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
        if (do_skl_residency) {
                outp += sprintf(outp, "%8.2f", 100.0 * p->pkg_wtd_core_c0/t->tsc);
@@ -645,15 +698,24 @@ done:
        return 0;
 }
 
-void flush_stdout()
+void flush_output_stdout(void)
 {
-       fputs(output_buffer, stdout);
-       fflush(stdout);
+       FILE *filep;
+
+       if (outf == stderr)
+               filep = stdout;
+       else
+               filep = outf;
+
+       fputs(output_buffer, filep);
+       fflush(filep);
+
        outp = output_buffer;
 }
-void flush_stderr()
+void flush_output_stderr(void)
 {
-       fputs(output_buffer, stderr);
+       fputs(output_buffer, outf);
+       fflush(outf);
        outp = output_buffer;
 }
 void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
@@ -704,6 +766,9 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
        old->pc10 = new->pc10 - old->pc10;
        old->pkg_temp_c = new->pkg_temp_c;
 
+       old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;
+       old->gfx_mhz = new->gfx_mhz;
+
        DELTA_WRAP32(new->energy_pkg, old->energy_pkg);
        DELTA_WRAP32(new->energy_cores, old->energy_cores);
        DELTA_WRAP32(new->energy_gfx, old->energy_gfx);
@@ -745,9 +810,9 @@ delta_thread(struct thread_data *new, struct thread_data *old,
                } else {
 
                        if (!aperf_mperf_unstable) {
-                               fprintf(stderr, "%s: APERF or MPERF went backwards *\n", progname);
-                               fprintf(stderr, "* Frequency results do not cover entire interval *\n");
-                               fprintf(stderr, "* fix this by running Linux-2.6.30 or later *\n");
+                               fprintf(outf, "%s: APERF or MPERF went backwards *\n", progname);
+                               fprintf(outf, "* Frequency results do not cover entire interval *\n");
+                               fprintf(outf, "* fix this by running Linux-2.6.30 or later *\n");
 
                                aperf_mperf_unstable = 1;
                        }
@@ -782,7 +847,8 @@ delta_thread(struct thread_data *new, struct thread_data *old,
        }
 
        if (old->mperf == 0) {
-               if (debug > 1) fprintf(stderr, "cpu%d MPERF 0!\n", old->cpu_id);
+               if (debug > 1)
+                       fprintf(outf, "cpu%d MPERF 0!\n", old->cpu_id);
                old->mperf = 1; /* divide by 0 protection */
        }
 
@@ -797,6 +863,9 @@ delta_thread(struct thread_data *new, struct thread_data *old,
        old->extra_msr32 = new->extra_msr32;
        old->extra_msr64 = new->extra_msr64;
 
+       if (do_irq)
+               old->irq_count = new->irq_count - old->irq_count;
+
        if (do_smi)
                old->smi_count = new->smi_count - old->smi_count;
 }
@@ -826,10 +895,12 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
        t->mperf = 0;
        t->c1 = 0;
 
-       t->smi_count = 0;
        t->extra_delta32 = 0;
        t->extra_delta64 = 0;
 
+       t->irq_count = 0;
+       t->smi_count = 0;
+
        /* tells format_counters to dump all fields from this set */
        t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
 
@@ -861,6 +932,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
        p->rapl_pkg_perf_status = 0;
        p->rapl_dram_perf_status = 0;
        p->pkg_temp_c = 0;
+
+       p->gfx_rc6_ms = 0;
+       p->gfx_mhz = 0;
 }
 int sum_counters(struct thread_data *t, struct core_data *c,
        struct pkg_data *p)
@@ -873,6 +947,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
        average.threads.extra_delta32 += t->extra_delta32;
        average.threads.extra_delta64 += t->extra_delta64;
 
+       average.threads.irq_count += t->irq_count;
+       average.threads.smi_count += t->smi_count;
+
        /* sum per-core values only for 1st thread in core */
        if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
                return 0;
@@ -910,6 +987,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
        average.packages.energy_cores += p->energy_cores;
        average.packages.energy_gfx += p->energy_gfx;
 
+       average.packages.gfx_rc6_ms = p->gfx_rc6_ms;
+       average.packages.gfx_mhz = p->gfx_mhz;
+
        average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);
 
        average.packages.rapl_pkg_perf_status += p->rapl_pkg_perf_status;
@@ -970,7 +1050,6 @@ static unsigned long long rdtsc(void)
        return low | ((unsigned long long)high) << 32;
 }
 
-
 /*
  * get_counters(...)
  * migrate to cpu
@@ -980,23 +1059,74 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
 {
        int cpu = t->cpu_id;
        unsigned long long msr;
+       int aperf_mperf_retry_count = 0;
 
        if (cpu_migrate(cpu)) {
-               fprintf(stderr, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
+retry:
        t->tsc = rdtsc();       /* we are running on local CPU of interest */
 
        if (has_aperf) {
+               unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
+
+               /*
+                * The TSC, APERF and MPERF must be read together for
+                * APERF/MPERF and MPERF/TSC to give accurate results.
+                *
+                * Unfortunately, APERF and MPERF are read by
+                * individual system call, so delays may occur
+                * between them.  If the time to read them
+                * varies by a large amount, we re-read them.
+                */
+
+               /*
+                * This initial dummy APERF read has been seen to
+                * reduce jitter in the subsequent reads.
+                */
+
+               if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
+                       return -3;
+
+               t->tsc = rdtsc();       /* re-read close to APERF */
+
+               tsc_before = t->tsc;
+
                if (get_msr(cpu, MSR_IA32_APERF, &t->aperf))
                        return -3;
+
+               tsc_between = rdtsc();
+
                if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf))
                        return -4;
+
+               tsc_after = rdtsc();
+
+               aperf_time = tsc_between - tsc_before;
+               mperf_time = tsc_after - tsc_between;
+
+               /*
+                * If the system call latency to read APERF and MPERF
+                * differ by more than 2x, then try again.
+                */
+               if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) {
+                       aperf_mperf_retry_count++;
+                       if (aperf_mperf_retry_count < 5)
+                               goto retry;
+                       else
+                               warnx("cpu%d jitter %lld %lld",
+                                       cpu, aperf_time, mperf_time);
+               }
+               aperf_mperf_retry_count = 0;
+
                t->aperf = t->aperf * aperf_mperf_multiplier;
                t->mperf = t->mperf * aperf_mperf_multiplier;
        }
 
+       if (do_irq)
+               t->irq_count = irqs_per_cpu[cpu];
        if (do_smi) {
                if (get_msr(cpu, MSR_SMI_COUNT, &msr))
                        return -5;
@@ -1124,6 +1254,13 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                        return -17;
                p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
        }
+
+       if (do_gfx_rc6_ms)
+               p->gfx_rc6_ms = gfx_cur_rc6_ms;
+
+       if (do_gfx_mhz)
+               p->gfx_mhz = gfx_cur_mhz;
+
        return 0;
 }
 
@@ -1175,18 +1312,18 @@ dump_nhm_platform_info(void)
 
        get_msr(base_cpu, MSR_PLATFORM_INFO, &msr);
 
-       fprintf(stderr, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
+       fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
 
        ratio = (msr >> 40) & 0xFF;
-       fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency frequency\n",
+       fprintf(outf, "%d * %.0f = %.0f MHz max efficiency frequency\n",
                ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 8) & 0xFF;
-       fprintf(stderr, "%d * %.0f = %.0f MHz base frequency\n",
+       fprintf(outf, "%d * %.0f = %.0f MHz base frequency\n",
                ratio, bclk, ratio * bclk);
 
        get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);
-       fprintf(stderr, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
+       fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
                base_cpu, msr, msr & 0x2 ? "EN" : "DIS");
 
        return;
@@ -1200,16 +1337,16 @@ dump_hsw_turbo_ratio_limits(void)
 
        get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT2, &msr);
 
-       fprintf(stderr, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr);
+       fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT2: 0x%08llx\n", base_cpu, msr);
 
        ratio = (msr >> 8) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 18 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 18 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 0) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 17 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 17 active cores\n",
                        ratio, bclk, ratio * bclk);
        return;
 }
@@ -1222,46 +1359,46 @@ dump_ivt_turbo_ratio_limits(void)
 
        get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &msr);
 
-       fprintf(stderr, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr);
+       fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT1: 0x%08llx\n", base_cpu, msr);
 
        ratio = (msr >> 56) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 48) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 40) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 32) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 24) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 16) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 8) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 0) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
                        ratio, bclk, ratio * bclk);
        return;
 }
@@ -1274,46 +1411,46 @@ dump_nhm_turbo_ratio_limits(void)
 
        get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
 
-       fprintf(stderr, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
+       fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
 
        ratio = (msr >> 56) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 48) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 40) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 32) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 24) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 16) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 3 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 3 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 8) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 2 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 2 active cores\n",
                        ratio, bclk, ratio * bclk);
 
        ratio = (msr >> 0) & 0xFF;
        if (ratio)
-               fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
+               fprintf(outf, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
                        ratio, bclk, ratio * bclk);
        return;
 }
@@ -1321,21 +1458,23 @@ dump_nhm_turbo_ratio_limits(void)
 static void
 dump_knl_turbo_ratio_limits(void)
 {
-       int cores;
-       unsigned int ratio;
+       const unsigned int buckets_no = 7;
+
        unsigned long long msr;
-       int delta_cores;
-       int delta_ratio;
-       int i;
+       int delta_cores, delta_ratio;
+       int i, b_nr;
+       unsigned int cores[buckets_no];
+       unsigned int ratio[buckets_no];
 
        get_msr(base_cpu, MSR_NHM_TURBO_RATIO_LIMIT, &msr);
 
-       fprintf(stderr, "cpu%d: MSR_NHM_TURBO_RATIO_LIMIT: 0x%08llx\n",
+       fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n",
                base_cpu, msr);
 
        /**
         * Turbo encoding in KNL is as follows:
-        * [7:0] -- Base value of number of active cores of bucket 1.
+        * [0] -- Reserved
+        * [7:1] -- Base value of number of active cores of bucket 1.
         * [15:8] -- Base value of freq ratio of bucket 1.
         * [20:16] -- +ve delta of number of active cores of bucket 2.
         * i.e. active cores of bucket 2 =
@@ -1354,29 +1493,25 @@ dump_knl_turbo_ratio_limits(void)
         * [60:56]-- +ve delta of number of active cores of bucket 7.
         * [63:61]-- -ve delta of freq ratio of bucket 7.
         */
-       cores = msr & 0xFF;
-       ratio = (msr >> 8) && 0xFF;
-       if (ratio > 0)
-               fprintf(stderr,
-                       "%d * %.0f = %.0f MHz max turbo %d active cores\n",
-                       ratio, bclk, ratio * bclk, cores);
-
-       for (i = 16; i < 64; i = i + 8) {
+
+       b_nr = 0;
+       cores[b_nr] = (msr & 0xFF) >> 1;
+       ratio[b_nr] = (msr >> 8) & 0xFF;
+
+       for (i = 16; i < 64; i += 8) {
                delta_cores = (msr >> i) & 0x1F;
-               delta_ratio = (msr >> (i + 5)) && 0x7;
-               if (!delta_cores || !delta_ratio)
-                       return;
-               cores = cores + delta_cores;
-               ratio = ratio - delta_ratio;
-
-               /** -ve ratios will make successive ratio calculations
-                * negative. Hence return instead of carrying on.
-                */
-               if (ratio > 0)
-                       fprintf(stderr,
-                               "%d * %.0f = %.0f MHz max turbo %d active cores\n",
-                               ratio, bclk, ratio * bclk, cores);
+               delta_ratio = (msr >> (i + 5)) & 0x7;
+
+               cores[b_nr + 1] = cores[b_nr] + delta_cores;
+               ratio[b_nr + 1] = ratio[b_nr] - delta_ratio;
+               b_nr++;
        }
+
+       for (i = buckets_no - 1; i >= 0; i--)
+               if (i > 0 ? ratio[i] != ratio[i - 1] : 1)
+                       fprintf(outf,
+                               "%d * %.0f = %.0f MHz max turbo %d active cores\n",
+                               ratio[i], bclk, ratio[i] * bclk, cores[i]);
 }
 
 static void
@@ -1389,15 +1524,15 @@ dump_nhm_cst_cfg(void)
 #define SNB_C1_AUTO_UNDEMOTE              (1UL << 27)
 #define SNB_C3_AUTO_UNDEMOTE              (1UL << 28)
 
-       fprintf(stderr, "cpu%d: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", base_cpu, msr);
+       fprintf(outf, "cpu%d: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x%08llx", base_cpu, msr);
 
-       fprintf(stderr, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n",
+       fprintf(outf, " (%s%s%s%s%slocked: pkg-cstate-limit=%d: %s)\n",
                (msr & SNB_C3_AUTO_UNDEMOTE) ? "UNdemote-C3, " : "",
                (msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
                (msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
                (msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
                (msr & (1 << 15)) ? "" : "UN",
-               (unsigned int)msr & 7,
+               (unsigned int)msr & 0xF,
                pkg_cstate_limit_strings[pkg_cstate_limit]);
        return;
 }
@@ -1408,48 +1543,59 @@ dump_config_tdp(void)
        unsigned long long msr;
 
        get_msr(base_cpu, MSR_CONFIG_TDP_NOMINAL, &msr);
-       fprintf(stderr, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr);
-       fprintf(stderr, " (base_ratio=%d)\n", (unsigned int)msr & 0xEF);
+       fprintf(outf, "cpu%d: MSR_CONFIG_TDP_NOMINAL: 0x%08llx", base_cpu, msr);
+       fprintf(outf, " (base_ratio=%d)\n", (unsigned int)msr & 0xFF);
 
        get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_1, &msr);
-       fprintf(stderr, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr);
+       fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_1: 0x%08llx (", base_cpu, msr);
        if (msr) {
-               fprintf(stderr, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0xEFFF);
-               fprintf(stderr, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0xEFFF);
-               fprintf(stderr, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xEF);
-               fprintf(stderr, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0xEFFF);
+               fprintf(outf, "PKG_MIN_PWR_LVL1=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
+               fprintf(outf, "PKG_MAX_PWR_LVL1=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
+               fprintf(outf, "LVL1_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
+               fprintf(outf, "PKG_TDP_LVL1=%d", (unsigned int)(msr) & 0x7FFF);
        }
-       fprintf(stderr, ")\n");
+       fprintf(outf, ")\n");
 
        get_msr(base_cpu, MSR_CONFIG_TDP_LEVEL_2, &msr);
-       fprintf(stderr, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr);
+       fprintf(outf, "cpu%d: MSR_CONFIG_TDP_LEVEL_2: 0x%08llx (", base_cpu, msr);
        if (msr) {
-               fprintf(stderr, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0xEFFF);
-               fprintf(stderr, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0xEFFF);
-               fprintf(stderr, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xEF);
-               fprintf(stderr, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0xEFFF);
+               fprintf(outf, "PKG_MIN_PWR_LVL2=%d ", (unsigned int)(msr >> 48) & 0x7FFF);
+               fprintf(outf, "PKG_MAX_PWR_LVL2=%d ", (unsigned int)(msr >> 32) & 0x7FFF);
+               fprintf(outf, "LVL2_RATIO=%d ", (unsigned int)(msr >> 16) & 0xFF);
+               fprintf(outf, "PKG_TDP_LVL2=%d", (unsigned int)(msr) & 0x7FFF);
        }
-       fprintf(stderr, ")\n");
+       fprintf(outf, ")\n");
 
        get_msr(base_cpu, MSR_CONFIG_TDP_CONTROL, &msr);
-       fprintf(stderr, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr);
+       fprintf(outf, "cpu%d: MSR_CONFIG_TDP_CONTROL: 0x%08llx (", base_cpu, msr);
        if ((msr) & 0x3)
-               fprintf(stderr, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3);
-       fprintf(stderr, " lock=%d", (unsigned int)(msr >> 31) & 1);
-       fprintf(stderr, ")\n");
-       
+               fprintf(outf, "TDP_LEVEL=%d ", (unsigned int)(msr) & 0x3);
+       fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
+       fprintf(outf, ")\n");
+
        get_msr(base_cpu, MSR_TURBO_ACTIVATION_RATIO, &msr);
-       fprintf(stderr, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);
-       fprintf(stderr, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0x7F);
-       fprintf(stderr, " lock=%d", (unsigned int)(msr >> 31) & 1);
-       fprintf(stderr, ")\n");
+       fprintf(outf, "cpu%d: MSR_TURBO_ACTIVATION_RATIO: 0x%08llx (", base_cpu, msr);
+       fprintf(outf, "MAX_NON_TURBO_RATIO=%d", (unsigned int)(msr) & 0xFF);
+       fprintf(outf, " lock=%d", (unsigned int)(msr >> 31) & 1);
+       fprintf(outf, ")\n");
+}
+void free_fd_percpu(void)
+{
+       int i;
+
+       for (i = 0; i < topo.max_cpu_num; ++i) {
+               if (fd_percpu[i] != 0)
+                       close(fd_percpu[i]);
+       }
+
+       free(fd_percpu);
 }
 
 void free_all_buffers(void)
 {
        CPU_FREE(cpu_present_set);
        cpu_present_set = NULL;
-       cpu_present_set = 0;
+       cpu_present_setsize = 0;
 
        CPU_FREE(cpu_affinity_set);
        cpu_affinity_set = NULL;
@@ -1474,6 +1620,11 @@ void free_all_buffers(void)
        free(output_buffer);
        output_buffer = NULL;
        outp = NULL;
+
+       free_fd_percpu();
+
+       free(irq_column_2_cpu);
+       free(irqs_per_cpu);
 }
 
 /*
@@ -1481,7 +1632,7 @@ void free_all_buffers(void)
  */
 FILE *fopen_or_die(const char *path, const char *mode)
 {
-       FILE *filep = fopen(path, "r");
+       FILE *filep = fopen(path, mode);
        if (!filep)
                err(1, "%s: open failed", path);
        return filep;
@@ -1696,6 +1847,136 @@ int mark_cpu_present(int cpu)
        return 0;
 }
 
+/*
+ * snapshot_proc_interrupts()
+ *
+ * read and record summary of /proc/interrupts
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_proc_interrupts(void)
+{
+       static FILE *fp;
+       int column, retval;
+
+       if (fp == NULL)
+               fp = fopen_or_die("/proc/interrupts", "r");
+       else
+               rewind(fp);
+
+       /* read 1st line of /proc/interrupts to get cpu* name for each column */
+       for (column = 0; column < topo.num_cpus; ++column) {
+               int cpu_number;
+
+               retval = fscanf(fp, " CPU%d", &cpu_number);
+               if (retval != 1)
+                       break;
+
+               if (cpu_number > topo.max_cpu_num) {
+                       warn("/proc/interrupts: cpu%d: > %d", cpu_number, topo.max_cpu_num);
+                       return 1;
+               }
+
+               irq_column_2_cpu[column] = cpu_number;
+               irqs_per_cpu[cpu_number] = 0;
+       }
+
+       /* read /proc/interrupt count lines and sum up irqs per cpu */
+       while (1) {
+               int column;
+               char buf[64];
+
+               retval = fscanf(fp, " %s:", buf);       /* flush irq# "N:" */
+               if (retval != 1)
+                       break;
+
+               /* read the count per cpu */
+               for (column = 0; column < topo.num_cpus; ++column) {
+
+                       int cpu_number, irq_count;
+
+                       retval = fscanf(fp, " %d", &irq_count);
+                       if (retval != 1)
+                               break;
+
+                       cpu_number = irq_column_2_cpu[column];
+                       irqs_per_cpu[cpu_number] += irq_count;
+
+               }
+
+               while (getc(fp) != '\n')
+                       ;       /* flush interrupt description */
+
+       }
+       return 0;
+}
+/*
+ * snapshot_gfx_rc6_ms()
+ *
+ * record snapshot of
+ * /sys/class/drm/card0/power/rc6_residency_ms
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_gfx_rc6_ms(void)
+{
+       FILE *fp;
+       int retval;
+
+       fp = fopen_or_die("/sys/class/drm/card0/power/rc6_residency_ms", "r");
+
+       retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms);
+       if (retval != 1)
+               err(1, "GFX rc6");
+
+       fclose(fp);
+
+       return 0;
+}
+/*
+ * snapshot_gfx_mhz()
+ *
+ * record snapshot of
+ * /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_gfx_mhz(void)
+{
+       static FILE *fp;
+       int retval;
+
+       if (fp == NULL)
+               fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r");
+       else
+               rewind(fp);
+
+       retval = fscanf(fp, "%d", &gfx_cur_mhz);
+       if (retval != 1)
+               err(1, "GFX MHz");
+
+       return 0;
+}
+
+/*
+ * snapshot /proc and /sys files
+ *
+ * return 1 if configuration restart needed, else return 0
+ */
+int snapshot_proc_sysfs_files(void)
+{
+       if (snapshot_proc_interrupts())
+               return 1;
+
+       if (do_gfx_rc6_ms)
+               snapshot_gfx_rc6_ms();
+
+       if (do_gfx_mhz)
+               snapshot_gfx_mhz();
+
+       return 0;
+}
+
 void turbostat_loop()
 {
        int retval;
@@ -1704,6 +1985,7 @@ void turbostat_loop()
 restart:
        restarted++;
 
+       snapshot_proc_sysfs_files();
        retval = for_all_cpus(get_counters, EVEN_COUNTERS);
        if (retval < -1) {
                exit(retval);
@@ -1722,7 +2004,9 @@ restart:
                        re_initialize();
                        goto restart;
                }
-               sleep(interval_sec);
+               nanosleep(&interval_ts, NULL);
+               if (snapshot_proc_sysfs_files())
+                       goto restart;
                retval = for_all_cpus(get_counters, ODD_COUNTERS);
                if (retval < -1) {
                        exit(retval);
@@ -1735,8 +2019,10 @@ restart:
                for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS);
                compute_average(EVEN_COUNTERS);
                format_all_counters(EVEN_COUNTERS);
-               flush_stdout();
-               sleep(interval_sec);
+               flush_output_stdout();
+               nanosleep(&interval_ts, NULL);
+               if (snapshot_proc_sysfs_files())
+                       goto restart;
                retval = for_all_cpus(get_counters, EVEN_COUNTERS);
                if (retval < -1) {
                        exit(retval);
@@ -1749,7 +2035,7 @@ restart:
                for_all_cpus_2(delta_cpu, EVEN_COUNTERS, ODD_COUNTERS);
                compute_average(ODD_COUNTERS);
                format_all_counters(ODD_COUNTERS);
-               flush_stdout();
+               flush_output_stdout();
        }
 }
 
@@ -1889,6 +2175,7 @@ int has_nhm_turbo_ratio_limit(unsigned int family, unsigned int model)
        /* Nehalem compatible, but do not include turbo-ratio limit support */
        case 0x2E:      /* Nehalem-EX Xeon - Beckton */
        case 0x2F:      /* Westmere-EX Xeon - Eagleton */
+       case 0x57:      /* PHI - Knights Landing (different MSR definition) */
                return 0;
        default:
                return 1;
@@ -1970,7 +2257,7 @@ int has_config_tdp(unsigned int family, unsigned int model)
 }
 
 static void
-dump_cstate_pstate_config_info(family, model)
+dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
 {
        if (!do_nhm_platform_info)
                return;
@@ -2016,7 +2303,7 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                return 0;
 
        if (cpu_migrate(cpu)) {
-               fprintf(stderr, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -2037,7 +2324,98 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                epb_string = "custom";
                break;
        }
-       fprintf(stderr, "cpu%d: MSR_IA32_ENERGY_PERF_BIAS: 0x%08llx (%s)\n", cpu, msr, epb_string);
+       fprintf(outf, "cpu%d: MSR_IA32_ENERGY_PERF_BIAS: 0x%08llx (%s)\n", cpu, msr, epb_string);
+
+       return 0;
+}
+/*
+ * print_hwp()
+ * Decode the MSR_HWP_CAPABILITIES
+ */
+int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
+       unsigned long long msr;
+       int cpu;
+
+       if (!has_hwp)
+               return 0;
+
+       cpu = t->cpu_id;
+
+       /* MSR_HWP_CAPABILITIES is per-package */
+       if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
+               return 0;
+
+       if (cpu_migrate(cpu)) {
+               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+               return -1;
+       }
+
+       if (get_msr(cpu, MSR_PM_ENABLE, &msr))
+               return 0;
+
+       fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n",
+               cpu, msr, (msr & (1 << 0)) ? "" : "No-");
+
+       /* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
+       if ((msr & (1 << 0)) == 0)
+               return 0;
+
+       if (get_msr(cpu, MSR_HWP_CAPABILITIES, &msr))
+               return 0;
+
+       fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx "
+                       "(high 0x%x guar 0x%x eff 0x%x low 0x%x)\n",
+                       cpu, msr,
+                       (unsigned int)HWP_HIGHEST_PERF(msr),
+                       (unsigned int)HWP_GUARANTEED_PERF(msr),
+                       (unsigned int)HWP_MOSTEFFICIENT_PERF(msr),
+                       (unsigned int)HWP_LOWEST_PERF(msr));
+
+       if (get_msr(cpu, MSR_HWP_REQUEST, &msr))
+               return 0;
+
+       fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx "
+                       "(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x pkg 0x%x)\n",
+                       cpu, msr,
+                       (unsigned int)(((msr) >> 0) & 0xff),
+                       (unsigned int)(((msr) >> 8) & 0xff),
+                       (unsigned int)(((msr) >> 16) & 0xff),
+                       (unsigned int)(((msr) >> 24) & 0xff),
+                       (unsigned int)(((msr) >> 32) & 0xff3),
+                       (unsigned int)(((msr) >> 42) & 0x1));
+
+       if (has_hwp_pkg) {
+               if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr))
+                       return 0;
+
+               fprintf(outf, "cpu%d: MSR_HWP_REQUEST_PKG: 0x%08llx "
+                       "(min 0x%x max 0x%x des 0x%x epp 0x%x window 0x%x)\n",
+                       cpu, msr,
+                       (unsigned int)(((msr) >> 0) & 0xff),
+                       (unsigned int)(((msr) >> 8) & 0xff),
+                       (unsigned int)(((msr) >> 16) & 0xff),
+                       (unsigned int)(((msr) >> 24) & 0xff),
+                       (unsigned int)(((msr) >> 32) & 0xff3));
+       }
+       if (has_hwp_notify) {
+               if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr))
+                       return 0;
+
+               fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx "
+                       "(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n",
+                       cpu, msr,
+                       ((msr) & 0x1) ? "EN" : "Dis",
+                       ((msr) & 0x2) ? "EN" : "Dis");
+       }
+       if (get_msr(cpu, MSR_HWP_STATUS, &msr))
+               return 0;
+
+       fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "
+                       "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",
+                       cpu, msr,
+                       ((msr) & 0x1) ? "" : "No-",
+                       ((msr) & 0x2) ? "" : "No-");
 
        return 0;
 }
@@ -2057,14 +2435,14 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
                return 0;
 
        if (cpu_migrate(cpu)) {
-               fprintf(stderr, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
        if (do_core_perf_limit_reasons) {
                get_msr(cpu, MSR_CORE_PERF_LIMIT_REASONS, &msr);
-               fprintf(stderr, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
-               fprintf(stderr, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",
+               fprintf(outf, "cpu%d: MSR_CORE_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
+               fprintf(outf, " (Active: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)",
                        (msr & 1 << 15) ? "bit15, " : "",
                        (msr & 1 << 14) ? "bit14, " : "",
                        (msr & 1 << 13) ? "Transitions, " : "",
@@ -2079,7 +2457,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
                        (msr & 1 << 2) ? "bit2, " : "",
                        (msr & 1 << 1) ? "ThermStatus, " : "",
                        (msr & 1 << 0) ? "PROCHOT, " : "");
-               fprintf(stderr, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
+               fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
                        (msr & 1 << 31) ? "bit31, " : "",
                        (msr & 1 << 30) ? "bit30, " : "",
                        (msr & 1 << 29) ? "Transitions, " : "",
@@ -2098,8 +2476,8 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
        }
        if (do_gfx_perf_limit_reasons) {
                get_msr(cpu, MSR_GFX_PERF_LIMIT_REASONS, &msr);
-               fprintf(stderr, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
-               fprintf(stderr, " (Active: %s%s%s%s%s%s%s%s)",
+               fprintf(outf, "cpu%d: MSR_GFX_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
+               fprintf(outf, " (Active: %s%s%s%s%s%s%s%s)",
                        (msr & 1 << 0) ? "PROCHOT, " : "",
                        (msr & 1 << 1) ? "ThermStatus, " : "",
                        (msr & 1 << 4) ? "Graphics, " : "",
@@ -2108,7 +2486,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
                        (msr & 1 << 9) ? "GFXPwr, " : "",
                        (msr & 1 << 10) ? "PkgPwrL1, " : "",
                        (msr & 1 << 11) ? "PkgPwrL2, " : "");
-               fprintf(stderr, " (Logged: %s%s%s%s%s%s%s%s)\n",
+               fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n",
                        (msr & 1 << 16) ? "PROCHOT, " : "",
                        (msr & 1 << 17) ? "ThermStatus, " : "",
                        (msr & 1 << 20) ? "Graphics, " : "",
@@ -2120,15 +2498,15 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
        }
        if (do_ring_perf_limit_reasons) {
                get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);
-               fprintf(stderr, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
-               fprintf(stderr, " (Active: %s%s%s%s%s%s)",
+               fprintf(outf, "cpu%d: MSR_RING_PERF_LIMIT_REASONS, 0x%08llx", cpu, msr);
+               fprintf(outf, " (Active: %s%s%s%s%s%s)",
                        (msr & 1 << 0) ? "PROCHOT, " : "",
                        (msr & 1 << 1) ? "ThermStatus, " : "",
                        (msr & 1 << 6) ? "VR-Therm, " : "",
                        (msr & 1 << 8) ? "Amps, " : "",
                        (msr & 1 << 10) ? "PkgPwrL1, " : "",
                        (msr & 1 << 11) ? "PkgPwrL2, " : "");
-               fprintf(stderr, " (Logged: %s%s%s%s%s%s)\n",
+               fprintf(outf, " (Logged: %s%s%s%s%s%s)\n",
                        (msr & 1 << 16) ? "PROCHOT, " : "",
                        (msr & 1 << 17) ? "ThermStatus, " : "",
                        (msr & 1 << 22) ? "VR-Therm, " : "",
@@ -2142,7 +2520,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
 #define        RAPL_POWER_GRANULARITY  0x7FFF  /* 15 bit power granularity */
 #define        RAPL_TIME_GRANULARITY   0x3F /* 6 bit time granularity */
 
-double get_tdp(model)
+double get_tdp(unsigned int model)
 {
        unsigned long long msr;
 
@@ -2251,12 +2629,12 @@ void rapl_probe(unsigned int family, unsigned int model)
 
        rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
        if (debug)
-               fprintf(stderr, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
+               fprintf(outf, "RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n", rapl_joule_counter_range, tdp);
 
        return;
 }
 
-void perf_limit_reasons_probe(family, model)
+void perf_limit_reasons_probe(unsigned int family, unsigned int model)
 {
        if (!genuine_intel)
                return;
@@ -2293,7 +2671,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
                return 0;
 
        if (cpu_migrate(cpu)) {
-               fprintf(stderr, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -2302,7 +2680,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
                        return 0;
 
                dts = (msr >> 16) & 0x7F;
-               fprintf(stderr, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n",
+               fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n",
                        cpu, msr, tcc_activation_temp - dts);
 
 #ifdef THERM_DEBUG
@@ -2311,7 +2689,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
 
                dts = (msr >> 16) & 0x7F;
                dts2 = (msr >> 8) & 0x7F;
-               fprintf(stderr, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
+               fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
                        cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
 #endif
        }
@@ -2325,7 +2703,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
 
                dts = (msr >> 16) & 0x7F;
                resolution = (msr >> 27) & 0xF;
-               fprintf(stderr, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n",
+               fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n",
                        cpu, msr, tcc_activation_temp - dts, resolution);
 
 #ifdef THERM_DEBUG
@@ -2334,17 +2712,17 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
 
                dts = (msr >> 16) & 0x7F;
                dts2 = (msr >> 8) & 0x7F;
-               fprintf(stderr, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
+               fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
                        cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
 #endif
        }
 
        return 0;
 }
-       
+
 void print_power_limit_msr(int cpu, unsigned long long msr, char *label)
 {
-       fprintf(stderr, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n",
+       fprintf(outf, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n",
                cpu, label,
                ((msr >> 15) & 1) ? "EN" : "DIS",
                ((msr >> 0) & 0x7FFF) * rapl_power_units,
@@ -2368,7 +2746,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
 
        cpu = t->cpu_id;
        if (cpu_migrate(cpu)) {
-               fprintf(stderr, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
@@ -2376,7 +2754,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                return -1;
 
        if (debug) {
-               fprintf(stderr, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx "
+               fprintf(outf, "cpu%d: MSR_RAPL_POWER_UNIT: 0x%08llx "
                        "(%f Watts, %f Joules, %f sec.)\n", cpu, msr,
                        rapl_power_units, rapl_energy_units, rapl_time_units);
        }
@@ -2386,7 +2764,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                        return -5;
 
 
-               fprintf(stderr, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
+               fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
                        cpu, msr,
                        ((msr >>  0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
                        ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
@@ -2399,11 +2777,11 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                if (get_msr(cpu, MSR_PKG_POWER_LIMIT, &msr))
                        return -9;
 
-               fprintf(stderr, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n",
+               fprintf(outf, "cpu%d: MSR_PKG_POWER_LIMIT: 0x%08llx (%slocked)\n",
                        cpu, msr, (msr >> 63) & 1 ? "": "UN");
 
                print_power_limit_msr(cpu, msr, "PKG Limit #1");
-               fprintf(stderr, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n",
+               fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n",
                        cpu,
                        ((msr >> 47) & 1) ? "EN" : "DIS",
                        ((msr >> 32) & 0x7FFF) * rapl_power_units,
@@ -2415,7 +2793,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))
                        return -6;
 
-               fprintf(stderr, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
+               fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
                        cpu, msr,
                        ((msr >>  0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
                        ((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
@@ -2425,7 +2803,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
        if (do_rapl & RAPL_DRAM) {
                if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
                        return -9;
-               fprintf(stderr, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
+               fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
                                cpu, msr, (msr >> 31) & 1 ? "": "UN");
 
                print_power_limit_msr(cpu, msr, "DRAM Limit");
@@ -2435,7 +2813,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                        if (get_msr(cpu, MSR_PP0_POLICY, &msr))
                                return -7;
 
-                       fprintf(stderr, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
+                       fprintf(outf, "cpu%d: MSR_PP0_POLICY: %lld\n", cpu, msr & 0xF);
                }
        }
        if (do_rapl & RAPL_CORES) {
@@ -2443,7 +2821,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
 
                        if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
                                return -9;
-                       fprintf(stderr, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
+                       fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
                                        cpu, msr, (msr >> 31) & 1 ? "": "UN");
                        print_power_limit_msr(cpu, msr, "Cores Limit");
                }
@@ -2453,11 +2831,11 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                        if (get_msr(cpu, MSR_PP1_POLICY, &msr))
                                return -8;
 
-                       fprintf(stderr, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);
+                       fprintf(outf, "cpu%d: MSR_PP1_POLICY: %lld\n", cpu, msr & 0xF);
 
                        if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
                                return -9;
-                       fprintf(stderr, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
+                       fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
                                        cpu, msr, (msr >> 31) & 1 ? "": "UN");
                        print_power_limit_msr(cpu, msr, "GFX Limit");
                }
@@ -2583,23 +2961,23 @@ double slm_bclk(void)
        double freq;
 
        if (get_msr(base_cpu, MSR_FSB_FREQ, &msr))
-               fprintf(stderr, "SLM BCLK: unknown\n");
+               fprintf(outf, "SLM BCLK: unknown\n");
 
        i = msr & 0xf;
        if (i >= SLM_BCLK_FREQS) {
-               fprintf(stderr, "SLM BCLK[%d] invalid\n", i);
+               fprintf(outf, "SLM BCLK[%d] invalid\n", i);
                msr = 3;
        }
        freq = slm_freq_table[i];
 
-       fprintf(stderr, "SLM BCLK: %.1f Mhz\n", freq);
+       fprintf(outf, "SLM BCLK: %.1f Mhz\n", freq);
 
        return freq;
 }
 
 double discover_bclk(unsigned int family, unsigned int model)
 {
-       if (has_snb_msrs(family, model))
+       if (has_snb_msrs(family, model) || is_knl(family, model))
                return 100.00;
        else if (is_slm(family, model))
                return slm_bclk();
@@ -2635,13 +3013,13 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
 
        cpu = t->cpu_id;
        if (cpu_migrate(cpu)) {
-               fprintf(stderr, "Could not migrate to CPU %d\n", cpu);
+               fprintf(outf, "Could not migrate to CPU %d\n", cpu);
                return -1;
        }
 
        if (tcc_activation_temp_override != 0) {
                tcc_activation_temp = tcc_activation_temp_override;
-               fprintf(stderr, "cpu%d: Using cmdline TCC Target (%d C)\n",
+               fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n",
                        cpu, tcc_activation_temp);
                return 0;
        }
@@ -2656,7 +3034,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
        target_c_local = (msr >> 16) & 0xFF;
 
        if (debug)
-               fprintf(stderr, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
+               fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
                        cpu, msr, target_c_local);
 
        if (!target_c_local)
@@ -2668,37 +3046,93 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
 
 guess:
        tcc_activation_temp = TJMAX_DEFAULT;
-       fprintf(stderr, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n",
+       fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n",
                cpu, tcc_activation_temp);
 
        return 0;
 }
+
+void decode_feature_control_msr(void)
+{
+       unsigned long long msr;
+
+       if (!get_msr(base_cpu, MSR_IA32_FEATURE_CONTROL, &msr))
+               fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",
+                       base_cpu, msr,
+                       msr & FEATURE_CONTROL_LOCKED ? "" : "UN-",
+                       msr & (1 << 18) ? "SGX" : "");
+}
+
+void decode_misc_enable_msr(void)
+{
+       unsigned long long msr;
+
+       if (!get_msr(base_cpu, MSR_IA32_MISC_ENABLE, &msr))
+               fprintf(outf, "cpu%d: MSR_IA32_MISC_ENABLE: 0x%08llx (%s %s %s)\n",
+                       base_cpu, msr,
+                       msr & (1 << 3) ? "TCC" : "",
+                       msr & (1 << 16) ? "EIST" : "",
+                       msr & (1 << 18) ? "MONITOR" : "");
+}
+
+/*
+ * Decode MSR_MISC_PWR_MGMT
+ *
+ * Decode the bits according to the Nehalem documentation
+ * bit[0] seems to continue to have same meaning going forward
+ * bit[1] less so...
+ */
+void decode_misc_pwr_mgmt_msr(void)
+{
+       unsigned long long msr;
+
+       if (!do_nhm_platform_info)
+               return;
+
+       if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))
+               fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB)\n",
+                       base_cpu, msr,
+                       msr & (1 << 0) ? "DIS" : "EN",
+                       msr & (1 << 1) ? "EN" : "DIS");
+}
+
 void process_cpuid()
 {
-       unsigned int eax, ebx, ecx, edx, max_level;
+       unsigned int eax, ebx, ecx, edx, max_level, max_extended_level;
        unsigned int fms, family, model, stepping;
 
        eax = ebx = ecx = edx = 0;
 
-       __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
+       __cpuid(0, max_level, ebx, ecx, edx);
 
        if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
                genuine_intel = 1;
 
        if (debug)
-               fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
+               fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
                        (char *)&ebx, (char *)&edx, (char *)&ecx);
 
-       __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+       __cpuid(1, fms, ebx, ecx, edx);
        family = (fms >> 8) & 0xf;
        model = (fms >> 4) & 0xf;
        stepping = fms & 0xf;
        if (family == 6 || family == 0xf)
                model += ((fms >> 16) & 0xf) << 4;
 
-       if (debug)
-               fprintf(stderr, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
+       if (debug) {
+               fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
                        max_level, family, model, stepping, family, model, stepping);
+               fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s\n",
+                       ecx & (1 << 0) ? "SSE3" : "-",
+                       ecx & (1 << 3) ? "MONITOR" : "-",
+                       ecx & (1 << 6) ? "SMX" : "-",
+                       ecx & (1 << 7) ? "EIST" : "-",
+                       ecx & (1 << 8) ? "TM2" : "-",
+                       edx & (1 << 4) ? "TSC" : "-",
+                       edx & (1 << 5) ? "MSR" : "-",
+                       edx & (1 << 22) ? "ACPI-TM" : "-",
+                       edx & (1 << 29) ? "TM" : "-");
+       }
 
        if (!(edx & (1 << 5)))
                errx(1, "CPUID: no MSR");
@@ -2709,15 +3143,15 @@ void process_cpuid()
         * This check is valid for both Intel and AMD.
         */
        ebx = ecx = edx = 0;
-       __get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx);
+       __cpuid(0x80000000, max_extended_level, ebx, ecx, edx);
 
-       if (max_level >= 0x80000007) {
+       if (max_extended_level >= 0x80000007) {
 
                /*
                 * Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
                 * this check is valid for both Intel and AMD
                 */
-               __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
+               __cpuid(0x80000007, eax, ebx, ecx, edx);
                has_invariant_tsc = edx & (1 << 8);
        }
 
@@ -2726,20 +3160,48 @@ void process_cpuid()
         * this check is valid for both Intel and AMD
         */
 
-       __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+       __cpuid(0x6, eax, ebx, ecx, edx);
        has_aperf = ecx & (1 << 0);
        do_dts = eax & (1 << 0);
        do_ptm = eax & (1 << 6);
+       has_hwp = eax & (1 << 7);
+       has_hwp_notify = eax & (1 << 8);
+       has_hwp_activity_window = eax & (1 << 9);
+       has_hwp_epp = eax & (1 << 10);
+       has_hwp_pkg = eax & (1 << 11);
        has_epb = ecx & (1 << 3);
 
        if (debug)
-               fprintf(stderr, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sEPB\n",
-                       has_aperf ? "" : "No ",
-                       do_dts ? "" : "No ",
-                       do_ptm ? "" : "No ",
-                       has_epb ? "" : "No ");
+               fprintf(outf, "CPUID(6): %sAPERF, %sDTS, %sPTM, %sHWP, "
+                       "%sHWPnotify, %sHWPwindow, %sHWPepp, %sHWPpkg, %sEPB\n",
+                       has_aperf ? "" : "No-",
+                       do_dts ? "" : "No-",
+                       do_ptm ? "" : "No-",
+                       has_hwp ? "" : "No-",
+                       has_hwp_notify ? "" : "No-",
+                       has_hwp_activity_window ? "" : "No-",
+                       has_hwp_epp ? "" : "No-",
+                       has_hwp_pkg ? "" : "No-",
+                       has_epb ? "" : "No-");
+
+       if (debug)
+               decode_misc_enable_msr();
+
+       if (max_level >= 0x7) {
+               int has_sgx;
 
-       if (max_level > 0x15) {
+               ecx = 0;
+
+               __cpuid_count(0x7, 0, eax, ebx, ecx, edx);
+
+               has_sgx = ebx & (1 << 2);
+               fprintf(outf, "CPUID(7): %sSGX\n", has_sgx ? "" : "No-");
+
+               if (has_sgx)
+                       decode_feature_control_msr();
+       }
+
+       if (max_level >= 0x15) {
                unsigned int eax_crystal;
                unsigned int ebx_tsc;
 
@@ -2747,12 +3209,12 @@ void process_cpuid()
                 * CPUID 15H TSC/Crystal ratio, possibly Crystal Hz
                 */
                eax_crystal = ebx_tsc = crystal_hz = edx = 0;
-               __get_cpuid(0x15, &eax_crystal, &ebx_tsc, &crystal_hz, &edx);
+               __cpuid(0x15, eax_crystal, ebx_tsc, crystal_hz, edx);
 
                if (ebx_tsc != 0) {
 
                        if (debug && (ebx != 0))
-                               fprintf(stderr, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
+                               fprintf(outf, "CPUID(0x15): eax_crystal: %d ebx_tsc: %d ecx_crystal_hz: %d\n",
                                        eax_crystal, ebx_tsc, crystal_hz);
 
                        if (crystal_hz == 0)
@@ -2768,11 +3230,24 @@ void process_cpuid()
                        if (crystal_hz) {
                                tsc_hz =  (unsigned long long) crystal_hz * ebx_tsc / eax_crystal;
                                if (debug)
-                                       fprintf(stderr, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
+                                       fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
                                                tsc_hz / 1000000, crystal_hz, ebx_tsc,  eax_crystal);
                        }
                }
        }
+       if (max_level >= 0x16) {
+               unsigned int base_mhz, max_mhz, bus_mhz, edx;
+
+               /*
+                * CPUID 16H Base MHz, Max MHz, Bus MHz
+                */
+               base_mhz = max_mhz = bus_mhz = edx = 0;
+
+               __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx);
+               if (debug)
+                       fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n",
+                               base_mhz, max_mhz, bus_mhz);
+       }
 
        if (has_aperf)
                aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model);
@@ -2788,21 +3263,28 @@ void process_cpuid()
        do_slm_cstates = is_slm(family, model);
        do_knl_cstates  = is_knl(family, model);
 
+       if (debug)
+               decode_misc_pwr_mgmt_msr();
+
        rapl_probe(family, model);
        perf_limit_reasons_probe(family, model);
 
        if (debug)
-               dump_cstate_pstate_config_info();
+               dump_cstate_pstate_config_info(family, model);
 
        if (has_skl_msrs(family, model))
                calculate_tsc_tweak();
 
+       do_gfx_rc6_ms = !access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK);
+
+       do_gfx_mhz = !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK);
+
        return;
 }
 
 void help()
 {
-       fprintf(stderr,
+       fprintf(outf,
        "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
        "\n"
        "Turbostat forks the specified COMMAND and prints statistics\n"
@@ -2814,6 +3296,7 @@ void help()
        "--help         print this help message\n"
        "--counter msr  print 32-bit counter at address \"msr\"\n"
        "--Counter msr  print 64-bit Counter at address \"msr\"\n"
+       "--out file     create or truncate \"file\" for all output\n"
        "--msr msr      print 32-bit value at address \"msr\"\n"
        "--MSR msr      print 64-bit Value at address \"msr\"\n"
        "--version      print version information\n"
@@ -2858,7 +3341,7 @@ void topology_probe()
                show_cpu = 1;
 
        if (debug > 1)
-               fprintf(stderr, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
+               fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
 
        cpus = calloc(1, (topo.max_cpu_num  + 1) * sizeof(struct cpu_topology));
        if (cpus == NULL)
@@ -2893,7 +3376,7 @@ void topology_probe()
 
                if (cpu_is_not_present(i)) {
                        if (debug > 1)
-                               fprintf(stderr, "cpu%d NOT PRESENT\n", i);
+                               fprintf(outf, "cpu%d NOT PRESENT\n", i);
                        continue;
                }
                cpus[i].core_id = get_core_id(i);
@@ -2908,26 +3391,26 @@ void topology_probe()
                if (siblings > max_siblings)
                        max_siblings = siblings;
                if (debug > 1)
-                       fprintf(stderr, "cpu %d pkg %d core %d\n",
+                       fprintf(outf, "cpu %d pkg %d core %d\n",
                                i, cpus[i].physical_package_id, cpus[i].core_id);
        }
        topo.num_cores_per_pkg = max_core_id + 1;
        if (debug > 1)
-               fprintf(stderr, "max_core_id %d, sizing for %d cores per package\n",
+               fprintf(outf, "max_core_id %d, sizing for %d cores per package\n",
                        max_core_id, topo.num_cores_per_pkg);
        if (debug && !summary_only && topo.num_cores_per_pkg > 1)
                show_core = 1;
 
        topo.num_packages = max_package_id + 1;
        if (debug > 1)
-               fprintf(stderr, "max_package_id %d, sizing for %d packages\n",
+               fprintf(outf, "max_package_id %d, sizing for %d packages\n",
                        max_package_id, topo.num_packages);
        if (debug && !summary_only && topo.num_packages > 1)
                show_pkg = 1;
 
        topo.num_threads_per_core = max_siblings;
        if (debug > 1)
-               fprintf(stderr, "max_siblings %d\n", max_siblings);
+               fprintf(outf, "max_siblings %d\n", max_siblings);
 
        free(cpus);
 }
@@ -3019,10 +3502,27 @@ void allocate_output_buffer()
        if (outp == NULL)
                err(-1, "calloc output buffer");
 }
+void allocate_fd_percpu(void)
+{
+       fd_percpu = calloc(topo.max_cpu_num, sizeof(int));
+       if (fd_percpu == NULL)
+               err(-1, "calloc fd_percpu");
+}
+void allocate_irq_buffers(void)
+{
+       irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));
+       if (irq_column_2_cpu == NULL)
+               err(-1, "calloc %d", topo.num_cpus);
 
+       irqs_per_cpu = calloc(topo.max_cpu_num, sizeof(int));
+       if (irqs_per_cpu == NULL)
+               err(-1, "calloc %d", topo.max_cpu_num);
+}
 void setup_all_buffers(void)
 {
        topology_probe();
+       allocate_irq_buffers();
+       allocate_fd_percpu();
        allocate_counters(&thread_even, &core_even, &package_even);
        allocate_counters(&thread_odd, &core_odd, &package_odd);
        allocate_output_buffer();
@@ -3036,7 +3536,7 @@ void set_base_cpu(void)
                err(-ENODEV, "No valid cpus found");
 
        if (debug > 1)
-               fprintf(stderr, "base_cpu = %d\n", base_cpu);
+               fprintf(outf, "base_cpu = %d\n", base_cpu);
 }
 
 void turbostat_init()
@@ -3048,6 +3548,9 @@ void turbostat_init()
        process_cpuid();
 
 
+       if (debug)
+               for_all_cpus(print_hwp, ODD_COUNTERS);
+
        if (debug)
                for_all_cpus(print_epb, ODD_COUNTERS);
 
@@ -3100,9 +3603,10 @@ int fork_it(char **argv)
        for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS);
        compute_average(EVEN_COUNTERS);
        format_all_counters(EVEN_COUNTERS);
-       flush_stderr();
 
-       fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
+       fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
+
+       flush_output_stderr();
 
        return status;
 }
@@ -3119,13 +3623,13 @@ int get_and_dump_counters(void)
        if (status)
                return status;
 
-       flush_stdout();
+       flush_output_stdout();
 
        return status;
 }
 
 void print_version() {
-       fprintf(stderr, "turbostat version 4.8 26-Sep, 2015"
+       fprintf(outf, "turbostat version 4.11 27 Feb 2016"
                " - Len Brown <lenb@kernel.org>\n");
 }
 
@@ -3143,6 +3647,7 @@ void cmdline(int argc, char **argv)
                {"Joules",      no_argument,            0, 'J'},
                {"MSR",         required_argument,      0, 'M'},
                {"msr",         required_argument,      0, 'm'},
+               {"out",         required_argument,      0, 'o'},
                {"Package",     no_argument,            0, 'p'},
                {"processor",   no_argument,            0, 'p'},
                {"Summary",     no_argument,            0, 'S'},
@@ -3153,7 +3658,7 @@ void cmdline(int argc, char **argv)
 
        progname = argv[0];
 
-       while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:PpST:v",
+       while ((opt = getopt_long_only(argc, argv, "+C:c:Ddhi:JM:m:o:PpST:v",
                                long_options, &option_index)) != -1) {
                switch (opt) {
                case 'C':
@@ -3173,7 +3678,18 @@ void cmdline(int argc, char **argv)
                        help();
                        exit(1);
                case 'i':
-                       interval_sec = atoi(optarg);
+                       {
+                               double interval = strtod(optarg, NULL);
+
+                               if (interval < 0.001) {
+                                       fprintf(outf, "interval %f seconds is too small\n",
+                                               interval);
+                                       exit(2);
+                               }
+
+                               interval_ts.tv_sec = interval;
+                               interval_ts.tv_nsec = (interval - interval_ts.tv_sec) * 1000000000;
+                       }
                        break;
                case 'J':
                        rapl_joules++;
@@ -3184,6 +3700,9 @@ void cmdline(int argc, char **argv)
                case 'm':
                        sscanf(optarg, "%x", &extra_msr_offset32);
                        break;
+               case 'o':
+                       outf = fopen_or_die(optarg, "w");
+                       break;
                case 'P':
                        show_pkg_only++;
                        break;
@@ -3206,6 +3725,8 @@ void cmdline(int argc, char **argv)
 
 int main(int argc, char **argv)
 {
+       outf = stderr;
+
        cmdline(argc, argv);
 
        if (debug)
index 90bd2ea4103232b68e29e167873ff21a3f76b262..b3281dcd4a5d5502af9f66720dfcdccb1aca4d58 100644 (file)
@@ -217,13 +217,16 @@ static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr *nd_cmd,
        return rc;
 }
 
+#define NFIT_TEST_ARS_RECORDS 4
+
 static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap *nd_cmd,
                unsigned int buf_len)
 {
        if (buf_len < sizeof(*nd_cmd))
                return -EINVAL;
 
-       nd_cmd->max_ars_out = 256;
+       nd_cmd->max_ars_out = sizeof(struct nd_cmd_ars_status)
+               + NFIT_TEST_ARS_RECORDS * sizeof(struct nd_ars_record);
        nd_cmd->status = (ND_ARS_PERSISTENT | ND_ARS_VOLATILE) << 16;
 
        return 0;
@@ -246,7 +249,8 @@ static int nfit_test_cmd_ars_status(struct nd_cmd_ars_status *nd_cmd,
        if (buf_len < sizeof(*nd_cmd))
                return -EINVAL;
 
-       nd_cmd->out_length = 256;
+       nd_cmd->out_length = sizeof(struct nd_cmd_ars_status);
+       /* TODO: emit error records */
        nd_cmd->num_records = 0;
        nd_cmd->address = 0;
        nd_cmd->length = -1ULL;
index 844787a0d7bed618511a022f09700f8738018c11..5eb49b7f864c7cfd0ffa84b1f9975ae66d74f14c 100755 (executable)
@@ -33,7 +33,7 @@ if grep -Pq '\x00' < $file
 then
        print_warning Console output contains nul bytes, old qemu still running?
 fi
-egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|Stall ended before state dump start' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags
+egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|self-detected stall on CPU|Stall ended before state dump start|\?\?\? Writer stall state' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags
 if test -s $1.diags
 then
        print_warning Assertion failure in $file $title
@@ -64,10 +64,12 @@ then
        then
                summary="$summary  lockdep: $n_badness"
        fi
-       n_stalls=`egrep -c 'detected stalls on CPUs/tasks:|Stall ended before state dump start' $1`
+       n_stalls=`egrep -c 'detected stalls on CPUs/tasks:|self-detected stall on CPU|Stall ended before state dump start|\?\?\? Writer stall state' $1`
        if test "$n_stalls" -ne 0
        then
                summary="$summary  Stalls: $n_stalls"
        fi
        print_warning Summary: $summary
+else
+       rm $1.diags
 fi
index d0c473f6585058053d83ea2e6a3eee46321668a1..d5ce7d7aae3e41f22d276d39aa365a9e5faa9910 100644 (file)
@@ -4,15 +4,16 @@ include ../lib.mk
 
 .PHONY: all all_32 all_64 warn_32bit_failure clean
 
-TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall
-TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso \
+TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall \
+                       check_initial_reg_state sigreturn ldt_gdt
+TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
                        test_FCMOV test_FCOMI test_FISTTP \
-                       ldt_gdt \
                        vdso_restorer
 
 TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
+TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY)
 BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
-BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64)
+BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64)
 
 CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
 
@@ -40,7 +41,7 @@ clean:
 $(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c
        $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm
 
-$(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c
+$(TARGETS_C_64BIT_ALL:%=%_64): %_64: %.c
        $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
 
 # x86_64 users should be encouraged to install 32-bit libraries
@@ -65,3 +66,9 @@ endif
 sysret_ss_attrs_64: thunks.S
 ptrace_syscall_32: raw_syscall_helper_32.S
 test_syscall_vdso_32: thunks_32.S
+
+# check_initial_reg_state is special: it needs a custom entry, and it
+# needs to be static so that its interpreter doesn't destroy its initial
+# state.
+check_initial_reg_state_32: CFLAGS += -Wl,-ereal_start -static
+check_initial_reg_state_64: CFLAGS += -Wl,-ereal_start -static
diff --git a/tools/testing/selftests/x86/check_initial_reg_state.c b/tools/testing/selftests/x86/check_initial_reg_state.c
new file mode 100644 (file)
index 0000000..6aaed9b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * check_initial_reg_state.c - check that execve sets the correct state
+ * Copyright (c) 2014-2016 Andrew Lutomirski
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+
+unsigned long ax, bx, cx, dx, si, di, bp, sp, flags;
+unsigned long r8, r9, r10, r11, r12, r13, r14, r15;
+
+asm (
+       ".pushsection .text\n\t"
+       ".type real_start, @function\n\t"
+       ".global real_start\n\t"
+       "real_start:\n\t"
+#ifdef __x86_64__
+       "mov %rax, ax\n\t"
+       "mov %rbx, bx\n\t"
+       "mov %rcx, cx\n\t"
+       "mov %rdx, dx\n\t"
+       "mov %rsi, si\n\t"
+       "mov %rdi, di\n\t"
+       "mov %rbp, bp\n\t"
+       "mov %rsp, sp\n\t"
+       "mov %r8, r8\n\t"
+       "mov %r9, r9\n\t"
+       "mov %r10, r10\n\t"
+       "mov %r11, r11\n\t"
+       "mov %r12, r12\n\t"
+       "mov %r13, r13\n\t"
+       "mov %r14, r14\n\t"
+       "mov %r15, r15\n\t"
+       "pushfq\n\t"
+       "popq flags\n\t"
+#else
+       "mov %eax, ax\n\t"
+       "mov %ebx, bx\n\t"
+       "mov %ecx, cx\n\t"
+       "mov %edx, dx\n\t"
+       "mov %esi, si\n\t"
+       "mov %edi, di\n\t"
+       "mov %ebp, bp\n\t"
+       "mov %esp, sp\n\t"
+       "pushfl\n\t"
+       "popl flags\n\t"
+#endif
+       "jmp _start\n\t"
+       ".size real_start, . - real_start\n\t"
+       ".popsection");
+
+int main()
+{
+       int nerrs = 0;
+
+       if (sp == 0) {
+               printf("[FAIL]\tTest was built incorrectly\n");
+               return 1;
+       }
+
+       if (ax || bx || cx || dx || si || di || bp
+#ifdef __x86_64__
+           || r8 || r9 || r10 || r11 || r12 || r13 || r14 || r15
+#endif
+               ) {
+               printf("[FAIL]\tAll GPRs except SP should be 0\n");
+#define SHOW(x) printf("\t" #x " = 0x%lx\n", x);
+               SHOW(ax);
+               SHOW(bx);
+               SHOW(cx);
+               SHOW(dx);
+               SHOW(si);
+               SHOW(di);
+               SHOW(bp);
+               SHOW(sp);
+#ifdef __x86_64__
+               SHOW(r8);
+               SHOW(r9);
+               SHOW(r10);
+               SHOW(r11);
+               SHOW(r12);
+               SHOW(r13);
+               SHOW(r14);
+               SHOW(r15);
+#endif
+               nerrs++;
+       } else {
+               printf("[OK]\tAll GPRs except SP are 0\n");
+       }
+
+       if (flags != 0x202) {
+               printf("[FAIL]\tFLAGS is 0x%lx, but it should be 0x202\n", flags);
+               nerrs++;
+       } else {
+               printf("[OK]\tFLAGS is 0x202\n");
+       }
+
+       return nerrs ? 1 : 0;
+}
index 5105b49cd8aa560d78d0e52ec7d12700bfbf83e7..421456784bc64d7c2ad5b14753194bcf89905d1d 100644 (file)
@@ -103,6 +103,17 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
                err(1, "sigaction");
 }
 
+static void setsigign(int sig, int flags)
+{
+       struct sigaction sa;
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_sigaction = (void *)SIG_IGN;
+       sa.sa_flags = flags;
+       sigemptyset(&sa.sa_mask);
+       if (sigaction(sig, &sa, 0))
+               err(1, "sigaction");
+}
+
 static void clearhandler(int sig)
 {
        struct sigaction sa;
@@ -187,7 +198,7 @@ static void test_ptrace_syscall_restart(void)
 
        printf("[RUN]\tSYSEMU\n");
        if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
-               err(1, "PTRACE_SYSCALL");
+               err(1, "PTRACE_SYSEMU");
        wait_trap(chld);
 
        if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
@@ -218,7 +229,7 @@ static void test_ptrace_syscall_restart(void)
                err(1, "PTRACE_SETREGS");
 
        if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
-               err(1, "PTRACE_SYSCALL");
+               err(1, "PTRACE_SYSEMU");
        wait_trap(chld);
 
        if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
@@ -250,7 +261,7 @@ static void test_ptrace_syscall_restart(void)
                err(1, "PTRACE_SETREGS");
 
        if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
-               err(1, "PTRACE_SYSCALL");
+               err(1, "PTRACE_SYSEMU");
        wait_trap(chld);
 
        if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
@@ -277,6 +288,119 @@ static void test_ptrace_syscall_restart(void)
        }
 }
 
+static void test_restart_under_ptrace(void)
+{
+       printf("[RUN]\tkernel syscall restart under ptrace\n");
+       pid_t chld = fork();
+       if (chld < 0)
+               err(1, "fork");
+
+       if (chld == 0) {
+               if (ptrace(PTRACE_TRACEME, 0, 0, 0) != 0)
+                       err(1, "PTRACE_TRACEME");
+
+               printf("\tChild will take a nap until signaled\n");
+               setsigign(SIGUSR1, SA_RESTART);
+               raise(SIGSTOP);
+
+               syscall(SYS_pause, 0, 0, 0, 0, 0, 0);
+               _exit(0);
+       }
+
+       int status;
+
+       /* Wait for SIGSTOP. */
+       if (waitpid(chld, &status, 0) != chld || !WIFSTOPPED(status))
+               err(1, "waitpid");
+
+       struct user_regs_struct regs;
+
+       printf("[RUN]\tSYSCALL\n");
+       if (ptrace(PTRACE_SYSCALL, chld, 0, 0) != 0)
+               err(1, "PTRACE_SYSCALL");
+       wait_trap(chld);
+
+       /* We should be stopped at pause(2) entry. */
+
+       if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
+               err(1, "PTRACE_GETREGS");
+
+       if (regs.user_syscall_nr != SYS_pause ||
+           regs.user_arg0 != 0 || regs.user_arg1 != 0 ||
+           regs.user_arg2 != 0 || regs.user_arg3 != 0 ||
+           regs.user_arg4 != 0 || regs.user_arg5 != 0) {
+               printf("[FAIL]\tInitial args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", (unsigned long)regs.user_syscall_nr, (unsigned long)regs.user_arg0, (unsigned long)regs.user_arg1, (unsigned long)regs.user_arg2, (unsigned long)regs.user_arg3, (unsigned long)regs.user_arg4, (unsigned long)regs.user_arg5);
+               nerrs++;
+       } else {
+               printf("[OK]\tInitial nr and args are correct\n");
+       }
+
+       /* Interrupt it. */
+       kill(chld, SIGUSR1);
+
+       /* Advance.  We should be stopped at exit. */
+       printf("[RUN]\tSYSCALL\n");
+       if (ptrace(PTRACE_SYSCALL, chld, 0, 0) != 0)
+               err(1, "PTRACE_SYSCALL");
+       wait_trap(chld);
+
+       if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
+               err(1, "PTRACE_GETREGS");
+
+       if (regs.user_syscall_nr != SYS_pause ||
+           regs.user_arg0 != 0 || regs.user_arg1 != 0 ||
+           regs.user_arg2 != 0 || regs.user_arg3 != 0 ||
+           regs.user_arg4 != 0 || regs.user_arg5 != 0) {
+               printf("[FAIL]\tArgs after SIGUSR1 are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", (unsigned long)regs.user_syscall_nr, (unsigned long)regs.user_arg0, (unsigned long)regs.user_arg1, (unsigned long)regs.user_arg2, (unsigned long)regs.user_arg3, (unsigned long)regs.user_arg4, (unsigned long)regs.user_arg5);
+               nerrs++;
+       } else {
+               printf("[OK]\tArgs after SIGUSR1 are correct (ax = %ld)\n",
+                      (long)regs.user_ax);
+       }
+
+       /* Poke the regs back in.  This must not break anything. */
+       if (ptrace(PTRACE_SETREGS, chld, 0, &regs) != 0)
+               err(1, "PTRACE_SETREGS");
+
+       /* Catch the (ignored) SIGUSR1. */
+       if (ptrace(PTRACE_CONT, chld, 0, 0) != 0)
+               err(1, "PTRACE_CONT");
+       if (waitpid(chld, &status, 0) != chld)
+               err(1, "waitpid");
+       if (!WIFSTOPPED(status)) {
+               printf("[FAIL]\tChild was stopped for SIGUSR1 (status = 0x%x)\n", status);
+               nerrs++;
+       } else {
+               printf("[OK]\tChild got SIGUSR1\n");
+       }
+
+       /* The next event should be pause(2) again. */
+       printf("[RUN]\tStep again\n");
+       if (ptrace(PTRACE_SYSCALL, chld, 0, 0) != 0)
+               err(1, "PTRACE_SYSCALL");
+       wait_trap(chld);
+
+       /* We should be stopped at pause(2) entry. */
+
+       if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
+               err(1, "PTRACE_GETREGS");
+
+       if (regs.user_syscall_nr != SYS_pause ||
+           regs.user_arg0 != 0 || regs.user_arg1 != 0 ||
+           regs.user_arg2 != 0 || regs.user_arg3 != 0 ||
+           regs.user_arg4 != 0 || regs.user_arg5 != 0) {
+               printf("[FAIL]\tpause did not restart (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", (unsigned long)regs.user_syscall_nr, (unsigned long)regs.user_arg0, (unsigned long)regs.user_arg1, (unsigned long)regs.user_arg2, (unsigned long)regs.user_arg3, (unsigned long)regs.user_arg4, (unsigned long)regs.user_arg5);
+               nerrs++;
+       } else {
+               printf("[OK]\tpause(2) restarted correctly\n");
+       }
+
+       /* Kill it. */
+       kill(chld, SIGKILL);
+       if (waitpid(chld, &status, 0) != chld)
+               err(1, "waitpid");
+}
+
 int main()
 {
        printf("[RUN]\tCheck int80 return regs\n");
@@ -290,5 +414,7 @@ int main()
 
        test_ptrace_syscall_restart();
 
+       test_restart_under_ptrace();
+
        return 0;
 }
index b5aa1bab7416394918fd59a441b0bda3853cfd28..8a577e7070c64104d74aa1e4361cfe8709894e25 100644 (file)
 #include <sys/ptrace.h>
 #include <sys/user.h>
 
+/* Pull in AR_xyz defines. */
+typedef unsigned int u32;
+typedef unsigned short u16;
+#include "../../../../arch/x86/include/asm/desc_defs.h"
+
+/*
+ * Copied from asm/ucontext.h, as asm/ucontext.h conflicts badly with the glibc
+ * headers.
+ */
+#ifdef __x86_64__
+/*
+ * UC_SIGCONTEXT_SS will be set when delivering 64-bit or x32 signals on
+ * kernels that save SS in the sigcontext.  All kernels that set
+ * UC_SIGCONTEXT_SS will correctly restore at least the low 32 bits of esp
+ * regardless of SS (i.e. they implement espfix).
+ *
+ * Kernels that set UC_SIGCONTEXT_SS will also set UC_STRICT_RESTORE_SS
+ * when delivering a signal that came from 64-bit code.
+ *
+ * Sigreturn restores SS as follows:
+ *
+ * if (saved SS is valid || UC_STRICT_RESTORE_SS is set ||
+ *     saved CS is not 64-bit)
+ *         new SS = saved SS  (will fail IRET and signal if invalid)
+ * else
+ *         new SS = a flat 32-bit data segment
+ */
+#define UC_SIGCONTEXT_SS       0x2
+#define UC_STRICT_RESTORE_SS   0x4
+#endif
+
 /*
  * In principle, this test can run on Linux emulation layers (e.g.
  * Illumos "LX branded zones").  Solaris-based kernels reserve LDT
@@ -267,6 +298,9 @@ static gregset_t initial_regs, requested_regs, resulting_regs;
 /* Instructions for the SIGUSR1 handler. */
 static volatile unsigned short sig_cs, sig_ss;
 static volatile sig_atomic_t sig_trapped, sig_err, sig_trapno;
+#ifdef __x86_64__
+static volatile sig_atomic_t sig_corrupt_final_ss;
+#endif
 
 /* Abstractions for some 32-bit vs 64-bit differences. */
 #ifdef __x86_64__
@@ -305,9 +339,105 @@ static greg_t *csptr(ucontext_t *ctx)
 }
 #endif
 
+/*
+ * Checks a given selector for its code bitness or returns -1 if it's not
+ * a usable code segment selector.
+ */
+int cs_bitness(unsigned short cs)
+{
+       uint32_t valid = 0, ar;
+       asm ("lar %[cs], %[ar]\n\t"
+            "jnz 1f\n\t"
+            "mov $1, %[valid]\n\t"
+            "1:"
+            : [ar] "=r" (ar), [valid] "+rm" (valid)
+            : [cs] "r" (cs));
+
+       if (!valid)
+               return -1;
+
+       bool db = (ar & (1 << 22));
+       bool l = (ar & (1 << 21));
+
+       if (!(ar & (1<<11)))
+           return -1;  /* Not code. */
+
+       if (l && !db)
+               return 64;
+       else if (!l && db)
+               return 32;
+       else if (!l && !db)
+               return 16;
+       else
+               return -1;      /* Unknown bitness. */
+}
+
+/*
+ * Checks a given selector for its code bitness or returns -1 if it's not
+ * a usable code segment selector.
+ */
+bool is_valid_ss(unsigned short cs)
+{
+       uint32_t valid = 0, ar;
+       asm ("lar %[cs], %[ar]\n\t"
+            "jnz 1f\n\t"
+            "mov $1, %[valid]\n\t"
+            "1:"
+            : [ar] "=r" (ar), [valid] "+rm" (valid)
+            : [cs] "r" (cs));
+
+       if (!valid)
+               return false;
+
+       if ((ar & AR_TYPE_MASK) != AR_TYPE_RWDATA &&
+           (ar & AR_TYPE_MASK) != AR_TYPE_RWDATA_EXPDOWN)
+               return false;
+
+       return (ar & AR_P);
+}
+
 /* Number of errors in the current test case. */
 static volatile sig_atomic_t nerrs;
 
+static void validate_signal_ss(int sig, ucontext_t *ctx)
+{
+#ifdef __x86_64__
+       bool was_64bit = (cs_bitness(*csptr(ctx)) == 64);
+
+       if (!(ctx->uc_flags & UC_SIGCONTEXT_SS)) {
+               printf("[FAIL]\tUC_SIGCONTEXT_SS was not set\n");
+               nerrs++;
+
+               /*
+                * This happens on Linux 4.1.  The rest will fail, too, so
+                * return now to reduce the noise.
+                */
+               return;
+       }
+
+       /* UC_STRICT_RESTORE_SS is set iff we came from 64-bit mode. */
+       if (!!(ctx->uc_flags & UC_STRICT_RESTORE_SS) != was_64bit) {
+               printf("[FAIL]\tUC_STRICT_RESTORE_SS was wrong in signal %d\n",
+                      sig);
+               nerrs++;
+       }
+
+       if (is_valid_ss(*ssptr(ctx))) {
+               /*
+                * DOSEMU was written before 64-bit sigcontext had SS, and
+                * it tries to figure out the signal source SS by looking at
+                * the physical register.  Make sure that keeps working.
+                */
+               unsigned short hw_ss;
+               asm ("mov %%ss, %0" : "=rm" (hw_ss));
+               if (hw_ss != *ssptr(ctx)) {
+                       printf("[FAIL]\tHW SS didn't match saved SS\n");
+                       nerrs++;
+               }
+       }
+#endif
+}
+
 /*
  * SIGUSR1 handler.  Sets CS and SS as requested and points IP to the
  * int3 trampoline.  Sets SP to a large known value so that we can see
@@ -317,6 +447,8 @@ static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
 {
        ucontext_t *ctx = (ucontext_t*)ctx_void;
 
+       validate_signal_ss(sig, ctx);
+
        memcpy(&initial_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
 
        *csptr(ctx) = sig_cs;
@@ -334,13 +466,16 @@ static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
 }
 
 /*
- * Called after a successful sigreturn.  Restores our state so that
- * the original raise(SIGUSR1) returns.
+ * Called after a successful sigreturn (via int3) or from a failed
+ * sigreturn (directly by kernel).  Restores our state so that the
+ * original raise(SIGUSR1) returns.
  */
 static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
 {
        ucontext_t *ctx = (ucontext_t*)ctx_void;
 
+       validate_signal_ss(sig, ctx);
+
        sig_err = ctx->uc_mcontext.gregs[REG_ERR];
        sig_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO];
 
@@ -358,41 +493,62 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
        memcpy(&resulting_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
        memcpy(&ctx->uc_mcontext.gregs, &initial_regs, sizeof(gregset_t));
 
+#ifdef __x86_64__
+       if (sig_corrupt_final_ss) {
+               if (ctx->uc_flags & UC_STRICT_RESTORE_SS) {
+                       printf("[FAIL]\tUC_STRICT_RESTORE_SS was set inappropriately\n");
+                       nerrs++;
+               } else {
+                       /*
+                        * DOSEMU transitions from 32-bit to 64-bit mode by
+                        * adjusting sigcontext, and it requires that this work
+                        * even if the saved SS is bogus.
+                        */
+                       printf("\tCorrupting SS on return to 64-bit mode\n");
+                       *ssptr(ctx) = 0;
+               }
+       }
+#endif
+
        sig_trapped = sig;
 }
 
-/*
- * Checks a given selector for its code bitness or returns -1 if it's not
- * a usable code segment selector.
- */
-int cs_bitness(unsigned short cs)
+#ifdef __x86_64__
+/* Tests recovery if !UC_STRICT_RESTORE_SS */
+static void sigusr2(int sig, siginfo_t *info, void *ctx_void)
 {
-       uint32_t valid = 0, ar;
-       asm ("lar %[cs], %[ar]\n\t"
-            "jnz 1f\n\t"
-            "mov $1, %[valid]\n\t"
-            "1:"
-            : [ar] "=r" (ar), [valid] "+rm" (valid)
-            : [cs] "r" (cs));
+       ucontext_t *ctx = (ucontext_t*)ctx_void;
 
-       if (!valid)
-               return -1;
+       if (!(ctx->uc_flags & UC_STRICT_RESTORE_SS)) {
+               printf("[FAIL]\traise(2) didn't set UC_STRICT_RESTORE_SS\n");
+               nerrs++;
+               return;  /* We can't do the rest. */
+       }
 
-       bool db = (ar & (1 << 22));
-       bool l = (ar & (1 << 21));
+       ctx->uc_flags &= ~UC_STRICT_RESTORE_SS;
+       *ssptr(ctx) = 0;
 
-       if (!(ar & (1<<11)))
-           return -1;  /* Not code. */
+       /* Return.  The kernel should recover without sending another signal. */
+}
 
-       if (l && !db)
-               return 64;
-       else if (!l && db)
-               return 32;
-       else if (!l && !db)
-               return 16;
-       else
-               return -1;      /* Unknown bitness. */
+static int test_nonstrict_ss(void)
+{
+       clearhandler(SIGUSR1);
+       clearhandler(SIGTRAP);
+       clearhandler(SIGSEGV);
+       clearhandler(SIGILL);
+       sethandler(SIGUSR2, sigusr2, 0);
+
+       nerrs = 0;
+
+       printf("[RUN]\tClear UC_STRICT_RESTORE_SS and corrupt SS\n");
+       raise(SIGUSR2);
+       if (!nerrs)
+               printf("[OK]\tIt worked\n");
+
+       return nerrs;
 }
+#endif
 
 /* Finds a usable code segment of the requested bitness. */
 int find_cs(int bitness)
@@ -576,6 +732,12 @@ static int test_bad_iret(int cs_bits, unsigned short ss, int force_cs)
                       errdesc, strsignal(sig_trapped));
                return 0;
        } else {
+               /*
+                * This also implicitly tests UC_STRICT_RESTORE_SS:
+                * We check that these signals set UC_STRICT_RESTORE_SS and,
+                * if UC_STRICT_RESTORE_SS doesn't cause strict behavior,
+                * then we won't get SIGSEGV.
+                */
                printf("[FAIL]\tDid not get SIGSEGV\n");
                return 1;
        }
@@ -632,6 +794,14 @@ int main()
                                                    GDT3(gdt_data16_idx));
        }
 
+#ifdef __x86_64__
+       /* Nasty ABI case: check SS corruption handling. */
+       sig_corrupt_final_ss = 1;
+       total_nerrs += test_valid_sigreturn(32, false, -1);
+       total_nerrs += test_valid_sigreturn(32, true, -1);
+       sig_corrupt_final_ss = 0;
+#endif
+
        /*
         * We're done testing valid sigreturn cases.  Now we test states
         * for which sigreturn itself will succeed but the subsequent
@@ -680,5 +850,9 @@ int main()
        if (gdt_npdata32_idx)
                test_bad_iret(32, GDT3(gdt_npdata32_idx), -1);
 
+#ifdef __x86_64__
+       total_nerrs += test_nonstrict_ss();
+#endif
+
        return total_nerrs ? 1 : 0;
 }
index 60c06af4646a3de0034820a65d805d0be16307ab..43fcab367fb0a243c2b96703f3ef91bc323aa806 100644 (file)
@@ -17,6 +17,9 @@
 
 #include <stdio.h>
 #include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <err.h>
 #include <sys/syscall.h>
 #include <asm/processor-flags.h>
 
@@ -26,6 +29,8 @@
 # define WIDTH "l"
 #endif
 
+static unsigned int nerrs;
+
 static unsigned long get_eflags(void)
 {
        unsigned long eflags;
@@ -39,16 +44,52 @@ static void set_eflags(unsigned long eflags)
                      : : "rm" (eflags) : "flags");
 }
 
-int main()
+static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
+                      int flags)
 {
-       printf("[RUN]\tSet NT and issue a syscall\n");
-       set_eflags(get_eflags() | X86_EFLAGS_NT);
+       struct sigaction sa;
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_sigaction = handler;
+       sa.sa_flags = SA_SIGINFO | flags;
+       sigemptyset(&sa.sa_mask);
+       if (sigaction(sig, &sa, 0))
+               err(1, "sigaction");
+}
+
+static void sigtrap(int sig, siginfo_t *si, void *ctx_void)
+{
+}
+
+static void do_it(unsigned long extraflags)
+{
+       unsigned long flags;
+
+       set_eflags(get_eflags() | extraflags);
        syscall(SYS_getpid);
-       if (get_eflags() & X86_EFLAGS_NT) {
-               printf("[OK]\tThe syscall worked and NT is still set\n");
-               return 0;
+       flags = get_eflags();
+       if ((flags & extraflags) == extraflags) {
+               printf("[OK]\tThe syscall worked and flags are still set\n");
        } else {
-               printf("[FAIL]\tThe syscall worked but NT was cleared\n");
-               return 1;
+               printf("[FAIL]\tThe syscall worked but flags were cleared (flags = 0x%lx but expected 0x%lx set)\n",
+                      flags, extraflags);
+               nerrs++;
        }
 }
+
+int main(void)
+{
+       printf("[RUN]\tSet NT and issue a syscall\n");
+       do_it(X86_EFLAGS_NT);
+
+       /*
+        * Now try it again with TF set -- TF forces returns via IRET in all
+        * cases except non-ptregs-using 64-bit full fast path syscalls.
+        */
+
+       sethandler(SIGTRAP, sigtrap, 0);
+
+       printf("[RUN]\tSet NT|TF and issue a syscall\n");
+       do_it(X86_EFLAGS_NT | X86_EFLAGS_TF);
+
+       return nerrs == 0 ? 0 : 1;
+}
index 86e698d07e20d66931f7846b8061c82018927382..1889163f2f05823888f62bb233b2c5e9510f4cbb 100644 (file)
@@ -135,7 +135,7 @@ static void usage(void)
                "\nValid debug options (FZPUT may be combined)\n"
                "a / A          Switch on all debug options (=FZUP)\n"
                "-              Switch off all debug options\n"
-               "f / F          Sanity Checks (SLAB_DEBUG_FREE)\n"
+               "f / F          Sanity Checks (SLAB_CONSISTENCY_CHECKS)\n"
                "z / Z          Redzoning\n"
                "p / P          Poisoning\n"
                "u / U          Tracking\n"
index ea6064696fe43867d1d1baee35059b276d84817b..a9ad4fe3f68f07848876403985e19e4c544ef1d0 100644 (file)
@@ -34,6 +34,11 @@ static struct timecounter *timecounter;
 static struct workqueue_struct *wqueue;
 static unsigned int host_vtimer_irq;
 
+void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.timer_cpu.active_cleared_last = false;
+}
+
 static cycle_t kvm_phys_timer_read(void)
 {
        return timecounter->cc->read(timecounter->cc);
@@ -130,6 +135,7 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 
        BUG_ON(!vgic_initialized(vcpu->kvm));
 
+       timer->active_cleared_last = false;
        timer->irq.level = new_level;
        trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->map->virt_irq,
                                   timer->irq.level);
@@ -245,10 +251,35 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
        else
                phys_active = false;
 
+       /*
+        * We want to avoid hitting the (re)distributor as much as
+        * possible, as this is a potentially expensive MMIO access
+        * (not to mention locks in the irq layer), and a solution for
+        * this is to cache the "active" state in memory.
+        *
+        * Things to consider: we cannot cache an "active set" state,
+        * because the HW can change this behind our back (it becomes
+        * "clear" in the HW). We must then restrict the caching to
+        * the "clear" state.
+        *
+        * The cache is invalidated on:
+        * - vcpu put, indicating that the HW cannot be trusted to be
+        *   in a sane state on the next vcpu load,
+        * - any change in the interrupt state
+        *
+        * Usage conditions:
+        * - cached value is "active clear"
+        * - value to be programmed is "active clear"
+        */
+       if (timer->active_cleared_last && !phys_active)
+               return;
+
        ret = irq_set_irqchip_state(timer->map->irq,
                                    IRQCHIP_STATE_ACTIVE,
                                    phys_active);
        WARN_ON(ret);
+
+       timer->active_cleared_last = !phys_active;
 }
 
 /**
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c
new file mode 100644 (file)
index 0000000..ea00d69
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012-2015 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <clocksource/arm_arch_timer.h>
+#include <linux/compiler.h>
+#include <linux/kvm_host.h>
+
+#include <asm/kvm_hyp.h>
+
+/* vcpu is already in the HYP VA space */
+void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu)
+{
+       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       u64 val;
+
+       if (kvm->arch.timer.enabled) {
+               timer->cntv_ctl = read_sysreg_el0(cntv_ctl);
+               timer->cntv_cval = read_sysreg_el0(cntv_cval);
+       }
+
+       /* Disable the virtual timer */
+       write_sysreg_el0(0, cntv_ctl);
+
+       /* Allow physical timer/counter access for the host */
+       val = read_sysreg(cnthctl_el2);
+       val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN;
+       write_sysreg(val, cnthctl_el2);
+
+       /* Clear cntvoff for the host */
+       write_sysreg(0, cntvoff_el2);
+}
+
+void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu)
+{
+       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+       struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       u64 val;
+
+       /*
+        * Disallow physical timer access for the guest
+        * Physical counter access is allowed
+        */
+       val = read_sysreg(cnthctl_el2);
+       val &= ~CNTHCTL_EL1PCEN;
+       val |= CNTHCTL_EL1PCTEN;
+       write_sysreg(val, cnthctl_el2);
+
+       if (kvm->arch.timer.enabled) {
+               write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2);
+               write_sysreg_el0(timer->cntv_cval, cntv_cval);
+               isb();
+               write_sysreg_el0(timer->cntv_ctl, cntv_ctl);
+       }
+}
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
new file mode 100644 (file)
index 0000000..674bdf8
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2012-2015 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compiler.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/kvm_host.h>
+
+#include <asm/kvm_hyp.h>
+
+static void __hyp_text save_maint_int_state(struct kvm_vcpu *vcpu,
+                                           void __iomem *base)
+{
+       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+       int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+       u32 eisr0, eisr1;
+       int i;
+       bool expect_mi;
+
+       expect_mi = !!(cpu_if->vgic_hcr & GICH_HCR_UIE);
+
+       for (i = 0; i < nr_lr; i++) {
+               if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
+                               continue;
+
+               expect_mi |= (!(cpu_if->vgic_lr[i] & GICH_LR_HW) &&
+                             (cpu_if->vgic_lr[i] & GICH_LR_EOI));
+       }
+
+       if (expect_mi) {
+               cpu_if->vgic_misr = readl_relaxed(base + GICH_MISR);
+
+               if (cpu_if->vgic_misr & GICH_MISR_EOI) {
+                       eisr0  = readl_relaxed(base + GICH_EISR0);
+                       if (unlikely(nr_lr > 32))
+                               eisr1  = readl_relaxed(base + GICH_EISR1);
+                       else
+                               eisr1 = 0;
+               } else {
+                       eisr0 = eisr1 = 0;
+               }
+       } else {
+               cpu_if->vgic_misr = 0;
+               eisr0 = eisr1 = 0;
+       }
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       cpu_if->vgic_eisr = ((u64)eisr0 << 32) | eisr1;
+#else
+       cpu_if->vgic_eisr = ((u64)eisr1 << 32) | eisr0;
+#endif
+}
+
+static void __hyp_text save_elrsr(struct kvm_vcpu *vcpu, void __iomem *base)
+{
+       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+       int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+       u32 elrsr0, elrsr1;
+
+       elrsr0 = readl_relaxed(base + GICH_ELRSR0);
+       if (unlikely(nr_lr > 32))
+               elrsr1 = readl_relaxed(base + GICH_ELRSR1);
+       else
+               elrsr1 = 0;
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       cpu_if->vgic_elrsr = ((u64)elrsr0 << 32) | elrsr1;
+#else
+       cpu_if->vgic_elrsr = ((u64)elrsr1 << 32) | elrsr0;
+#endif
+}
+
+static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
+{
+       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+       int nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+       int i;
+
+       for (i = 0; i < nr_lr; i++) {
+               if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
+                       continue;
+
+               if (cpu_if->vgic_elrsr & (1UL << i)) {
+                       cpu_if->vgic_lr[i] &= ~GICH_LR_STATE;
+                       continue;
+               }
+
+               cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
+               writel_relaxed(0, base + GICH_LR0 + (i * 4));
+       }
+}
+
+/* vcpu is already in the HYP VA space */
+void __hyp_text __vgic_v2_save_state(struct kvm_vcpu *vcpu)
+{
+       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+       struct vgic_dist *vgic = &kvm->arch.vgic;
+       void __iomem *base = kern_hyp_va(vgic->vctrl_base);
+
+       if (!base)
+               return;
+
+       cpu_if->vgic_vmcr = readl_relaxed(base + GICH_VMCR);
+
+       if (vcpu->arch.vgic_cpu.live_lrs) {
+               cpu_if->vgic_apr = readl_relaxed(base + GICH_APR);
+
+               save_maint_int_state(vcpu, base);
+               save_elrsr(vcpu, base);
+               save_lrs(vcpu, base);
+
+               writel_relaxed(0, base + GICH_HCR);
+
+               vcpu->arch.vgic_cpu.live_lrs = 0;
+       } else {
+               cpu_if->vgic_eisr = 0;
+               cpu_if->vgic_elrsr = ~0UL;
+               cpu_if->vgic_misr = 0;
+               cpu_if->vgic_apr = 0;
+       }
+}
+
+/* vcpu is already in the HYP VA space */
+void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
+{
+       struct kvm *kvm = kern_hyp_va(vcpu->kvm);
+       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
+       struct vgic_dist *vgic = &kvm->arch.vgic;
+       void __iomem *base = kern_hyp_va(vgic->vctrl_base);
+       int i, nr_lr;
+       u64 live_lrs = 0;
+
+       if (!base)
+               return;
+
+       nr_lr = vcpu->arch.vgic_cpu.nr_lr;
+
+       for (i = 0; i < nr_lr; i++)
+               if (cpu_if->vgic_lr[i] & GICH_LR_STATE)
+                       live_lrs |= 1UL << i;
+
+       if (live_lrs) {
+               writel_relaxed(cpu_if->vgic_hcr, base + GICH_HCR);
+               writel_relaxed(cpu_if->vgic_apr, base + GICH_APR);
+               for (i = 0; i < nr_lr; i++) {
+                       if (!(live_lrs & (1UL << i)))
+                               continue;
+
+                       writel_relaxed(cpu_if->vgic_lr[i],
+                                      base + GICH_LR0 + (i * 4));
+               }
+       }
+
+       writel_relaxed(cpu_if->vgic_vmcr, base + GICH_VMCR);
+       vcpu->arch.vgic_cpu.live_lrs = live_lrs;
+}
diff --git a/virt/kvm/arm/pmu.c b/virt/kvm/arm/pmu.c
new file mode 100644 (file)
index 0000000..b5754c6
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd.
+ * Author: Shannon Zhao <shannon.zhao@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/cpu.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/perf_event.h>
+#include <linux/uaccess.h>
+#include <asm/kvm_emulate.h>
+#include <kvm/arm_pmu.h>
+#include <kvm/arm_vgic.h>
+
+/**
+ * kvm_pmu_get_counter_value - get PMU counter value
+ * @vcpu: The vcpu pointer
+ * @select_idx: The counter index
+ */
+u64 kvm_pmu_get_counter_value(struct kvm_vcpu *vcpu, u64 select_idx)
+{
+       u64 counter, reg, enabled, running;
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+       struct kvm_pmc *pmc = &pmu->pmc[select_idx];
+
+       reg = (select_idx == ARMV8_PMU_CYCLE_IDX)
+             ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx;
+       counter = vcpu_sys_reg(vcpu, reg);
+
+       /* The real counter value is equal to the value of counter register plus
+        * the value perf event counts.
+        */
+       if (pmc->perf_event)
+               counter += perf_event_read_value(pmc->perf_event, &enabled,
+                                                &running);
+
+       return counter & pmc->bitmask;
+}
+
+/**
+ * kvm_pmu_set_counter_value - set PMU counter value
+ * @vcpu: The vcpu pointer
+ * @select_idx: The counter index
+ * @val: The counter value
+ */
+void kvm_pmu_set_counter_value(struct kvm_vcpu *vcpu, u64 select_idx, u64 val)
+{
+       u64 reg;
+
+       reg = (select_idx == ARMV8_PMU_CYCLE_IDX)
+             ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + select_idx;
+       vcpu_sys_reg(vcpu, reg) += (s64)val - kvm_pmu_get_counter_value(vcpu, select_idx);
+}
+
+/**
+ * kvm_pmu_stop_counter - stop PMU counter
+ * @pmc: The PMU counter pointer
+ *
+ * If this counter has been configured to monitor some event, release it here.
+ */
+static void kvm_pmu_stop_counter(struct kvm_vcpu *vcpu, struct kvm_pmc *pmc)
+{
+       u64 counter, reg;
+
+       if (pmc->perf_event) {
+               counter = kvm_pmu_get_counter_value(vcpu, pmc->idx);
+               reg = (pmc->idx == ARMV8_PMU_CYCLE_IDX)
+                      ? PMCCNTR_EL0 : PMEVCNTR0_EL0 + pmc->idx;
+               vcpu_sys_reg(vcpu, reg) = counter;
+               perf_event_disable(pmc->perf_event);
+               perf_event_release_kernel(pmc->perf_event);
+               pmc->perf_event = NULL;
+       }
+}
+
+/**
+ * kvm_pmu_vcpu_reset - reset pmu state for cpu
+ * @vcpu: The vcpu pointer
+ *
+ */
+void kvm_pmu_vcpu_reset(struct kvm_vcpu *vcpu)
+{
+       int i;
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+
+       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
+               kvm_pmu_stop_counter(vcpu, &pmu->pmc[i]);
+               pmu->pmc[i].idx = i;
+               pmu->pmc[i].bitmask = 0xffffffffUL;
+       }
+}
+
+/**
+ * kvm_pmu_vcpu_destroy - free perf event of PMU for cpu
+ * @vcpu: The vcpu pointer
+ *
+ */
+void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+       int i;
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+
+       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
+               struct kvm_pmc *pmc = &pmu->pmc[i];
+
+               if (pmc->perf_event) {
+                       perf_event_disable(pmc->perf_event);
+                       perf_event_release_kernel(pmc->perf_event);
+                       pmc->perf_event = NULL;
+               }
+       }
+}
+
+u64 kvm_pmu_valid_counter_mask(struct kvm_vcpu *vcpu)
+{
+       u64 val = vcpu_sys_reg(vcpu, PMCR_EL0) >> ARMV8_PMU_PMCR_N_SHIFT;
+
+       val &= ARMV8_PMU_PMCR_N_MASK;
+       if (val == 0)
+               return BIT(ARMV8_PMU_CYCLE_IDX);
+       else
+               return GENMASK(val - 1, 0) | BIT(ARMV8_PMU_CYCLE_IDX);
+}
+
+/**
+ * kvm_pmu_enable_counter - enable selected PMU counter
+ * @vcpu: The vcpu pointer
+ * @val: the value guest writes to PMCNTENSET register
+ *
+ * Call perf_event_enable to start counting the perf event
+ */
+void kvm_pmu_enable_counter(struct kvm_vcpu *vcpu, u64 val)
+{
+       int i;
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+       struct kvm_pmc *pmc;
+
+       if (!(vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) || !val)
+               return;
+
+       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
+               if (!(val & BIT(i)))
+                       continue;
+
+               pmc = &pmu->pmc[i];
+               if (pmc->perf_event) {
+                       perf_event_enable(pmc->perf_event);
+                       if (pmc->perf_event->state != PERF_EVENT_STATE_ACTIVE)
+                               kvm_debug("fail to enable perf event\n");
+               }
+       }
+}
+
+/**
+ * kvm_pmu_disable_counter - disable selected PMU counter
+ * @vcpu: The vcpu pointer
+ * @val: the value guest writes to PMCNTENCLR register
+ *
+ * Call perf_event_disable to stop counting the perf event
+ */
+void kvm_pmu_disable_counter(struct kvm_vcpu *vcpu, u64 val)
+{
+       int i;
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+       struct kvm_pmc *pmc;
+
+       if (!val)
+               return;
+
+       for (i = 0; i < ARMV8_PMU_MAX_COUNTERS; i++) {
+               if (!(val & BIT(i)))
+                       continue;
+
+               pmc = &pmu->pmc[i];
+               if (pmc->perf_event)
+                       perf_event_disable(pmc->perf_event);
+       }
+}
+
+static u64 kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
+{
+       u64 reg = 0;
+
+       if ((vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E))
+               reg = vcpu_sys_reg(vcpu, PMOVSSET_EL0);
+               reg &= vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
+               reg &= vcpu_sys_reg(vcpu, PMINTENSET_EL1);
+               reg &= kvm_pmu_valid_counter_mask(vcpu);
+
+       return reg;
+}
+
+/**
+ * kvm_pmu_overflow_set - set PMU overflow interrupt
+ * @vcpu: The vcpu pointer
+ * @val: the value guest writes to PMOVSSET register
+ */
+void kvm_pmu_overflow_set(struct kvm_vcpu *vcpu, u64 val)
+{
+       u64 reg;
+
+       if (val == 0)
+               return;
+
+       vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= val;
+       reg = kvm_pmu_overflow_status(vcpu);
+       if (reg != 0)
+               kvm_vcpu_kick(vcpu);
+}
+
+static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
+{
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+       bool overflow;
+
+       if (!kvm_arm_pmu_v3_ready(vcpu))
+               return;
+
+       overflow = !!kvm_pmu_overflow_status(vcpu);
+       if (pmu->irq_level != overflow) {
+               pmu->irq_level = overflow;
+               kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+                                   pmu->irq_num, overflow);
+       }
+}
+
+/**
+ * kvm_pmu_flush_hwstate - flush pmu state to cpu
+ * @vcpu: The vcpu pointer
+ *
+ * Check if the PMU has overflowed while we were running in the host, and inject
+ * an interrupt if that was the case.
+ */
+void kvm_pmu_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+       kvm_pmu_update_state(vcpu);
+}
+
+/**
+ * kvm_pmu_sync_hwstate - sync pmu state from cpu
+ * @vcpu: The vcpu pointer
+ *
+ * Check if the PMU has overflowed while we were running in the guest, and
+ * inject an interrupt if that was the case.
+ */
+void kvm_pmu_sync_hwstate(struct kvm_vcpu *vcpu)
+{
+       kvm_pmu_update_state(vcpu);
+}
+
+static inline struct kvm_vcpu *kvm_pmc_to_vcpu(struct kvm_pmc *pmc)
+{
+       struct kvm_pmu *pmu;
+       struct kvm_vcpu_arch *vcpu_arch;
+
+       pmc -= pmc->idx;
+       pmu = container_of(pmc, struct kvm_pmu, pmc[0]);
+       vcpu_arch = container_of(pmu, struct kvm_vcpu_arch, pmu);
+       return container_of(vcpu_arch, struct kvm_vcpu, arch);
+}
+
+/**
+ * When perf event overflows, call kvm_pmu_overflow_set to set overflow status.
+ */
+static void kvm_pmu_perf_overflow(struct perf_event *perf_event,
+                                 struct perf_sample_data *data,
+                                 struct pt_regs *regs)
+{
+       struct kvm_pmc *pmc = perf_event->overflow_handler_context;
+       struct kvm_vcpu *vcpu = kvm_pmc_to_vcpu(pmc);
+       int idx = pmc->idx;
+
+       kvm_pmu_overflow_set(vcpu, BIT(idx));
+}
+
+/**
+ * kvm_pmu_software_increment - do software increment
+ * @vcpu: The vcpu pointer
+ * @val: the value guest writes to PMSWINC register
+ */
+void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val)
+{
+       int i;
+       u64 type, enable, reg;
+
+       if (val == 0)
+               return;
+
+       enable = vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
+       for (i = 0; i < ARMV8_PMU_CYCLE_IDX; i++) {
+               if (!(val & BIT(i)))
+                       continue;
+               type = vcpu_sys_reg(vcpu, PMEVTYPER0_EL0 + i)
+                      & ARMV8_PMU_EVTYPE_EVENT;
+               if ((type == ARMV8_PMU_EVTYPE_EVENT_SW_INCR)
+                   && (enable & BIT(i))) {
+                       reg = vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) + 1;
+                       reg = lower_32_bits(reg);
+                       vcpu_sys_reg(vcpu, PMEVCNTR0_EL0 + i) = reg;
+                       if (!reg)
+                               kvm_pmu_overflow_set(vcpu, BIT(i));
+               }
+       }
+}
+
+/**
+ * kvm_pmu_handle_pmcr - handle PMCR register
+ * @vcpu: The vcpu pointer
+ * @val: the value guest writes to PMCR register
+ */
+void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
+{
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+       struct kvm_pmc *pmc;
+       u64 mask;
+       int i;
+
+       mask = kvm_pmu_valid_counter_mask(vcpu);
+       if (val & ARMV8_PMU_PMCR_E) {
+               kvm_pmu_enable_counter(vcpu,
+                               vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & mask);
+       } else {
+               kvm_pmu_disable_counter(vcpu, mask);
+       }
+
+       if (val & ARMV8_PMU_PMCR_C)
+               kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0);
+
+       if (val & ARMV8_PMU_PMCR_P) {
+               for (i = 0; i < ARMV8_PMU_CYCLE_IDX; i++)
+                       kvm_pmu_set_counter_value(vcpu, i, 0);
+       }
+
+       if (val & ARMV8_PMU_PMCR_LC) {
+               pmc = &pmu->pmc[ARMV8_PMU_CYCLE_IDX];
+               pmc->bitmask = 0xffffffffffffffffUL;
+       }
+}
+
+static bool kvm_pmu_counter_is_enabled(struct kvm_vcpu *vcpu, u64 select_idx)
+{
+       return (vcpu_sys_reg(vcpu, PMCR_EL0) & ARMV8_PMU_PMCR_E) &&
+              (vcpu_sys_reg(vcpu, PMCNTENSET_EL0) & BIT(select_idx));
+}
+
+/**
+ * kvm_pmu_set_counter_event_type - set selected counter to monitor some event
+ * @vcpu: The vcpu pointer
+ * @data: The data guest writes to PMXEVTYPER_EL0
+ * @select_idx: The number of selected counter
+ *
+ * When OS accesses PMXEVTYPER_EL0, that means it wants to set a PMC to count an
+ * event with given hardware event number. Here we call perf_event API to
+ * emulate this action and create a kernel perf event for it.
+ */
+void kvm_pmu_set_counter_event_type(struct kvm_vcpu *vcpu, u64 data,
+                                   u64 select_idx)
+{
+       struct kvm_pmu *pmu = &vcpu->arch.pmu;
+       struct kvm_pmc *pmc = &pmu->pmc[select_idx];
+       struct perf_event *event;
+       struct perf_event_attr attr;
+       u64 eventsel, counter;
+
+       kvm_pmu_stop_counter(vcpu, pmc);
+       eventsel = data & ARMV8_PMU_EVTYPE_EVENT;
+
+       /* Software increment event does't need to be backed by a perf event */
+       if (eventsel == ARMV8_PMU_EVTYPE_EVENT_SW_INCR)
+               return;
+
+       memset(&attr, 0, sizeof(struct perf_event_attr));
+       attr.type = PERF_TYPE_RAW;
+       attr.size = sizeof(attr);
+       attr.pinned = 1;
+       attr.disabled = !kvm_pmu_counter_is_enabled(vcpu, select_idx);
+       attr.exclude_user = data & ARMV8_PMU_EXCLUDE_EL0 ? 1 : 0;
+       attr.exclude_kernel = data & ARMV8_PMU_EXCLUDE_EL1 ? 1 : 0;
+       attr.exclude_hv = 1; /* Don't count EL2 events */
+       attr.exclude_host = 1; /* Don't count host events */
+       attr.config = eventsel;
+
+       counter = kvm_pmu_get_counter_value(vcpu, select_idx);
+       /* The initial sample period (overflow count) of an event. */
+       attr.sample_period = (-counter) & pmc->bitmask;
+
+       event = perf_event_create_kernel_counter(&attr, -1, current,
+                                                kvm_pmu_perf_overflow, pmc);
+       if (IS_ERR(event)) {
+               pr_err_once("kvm: pmu event creation failed %ld\n",
+                           PTR_ERR(event));
+               return;
+       }
+
+       pmc->perf_event = event;
+}
+
+bool kvm_arm_support_pmu_v3(void)
+{
+       /*
+        * Check if HW_PERF_EVENTS are supported by checking the number of
+        * hardware performance counters. This could ensure the presence of
+        * a physical PMU and CONFIG_PERF_EVENT is selected.
+        */
+       return (perf_num_counters() > 0);
+}
+
+static int kvm_arm_pmu_v3_init(struct kvm_vcpu *vcpu)
+{
+       if (!kvm_arm_support_pmu_v3())
+               return -ENODEV;
+
+       if (!test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features) ||
+           !kvm_arm_pmu_irq_initialized(vcpu))
+               return -ENXIO;
+
+       if (kvm_arm_pmu_v3_ready(vcpu))
+               return -EBUSY;
+
+       kvm_pmu_vcpu_reset(vcpu);
+       vcpu->arch.pmu.ready = true;
+
+       return 0;
+}
+
+static bool irq_is_valid(struct kvm *kvm, int irq, bool is_ppi)
+{
+       int i;
+       struct kvm_vcpu *vcpu;
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               if (!kvm_arm_pmu_irq_initialized(vcpu))
+                       continue;
+
+               if (is_ppi) {
+                       if (vcpu->arch.pmu.irq_num != irq)
+                               return false;
+               } else {
+                       if (vcpu->arch.pmu.irq_num == irq)
+                               return false;
+               }
+       }
+
+       return true;
+}
+
+
+int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
+{
+       switch (attr->attr) {
+       case KVM_ARM_VCPU_PMU_V3_IRQ: {
+               int __user *uaddr = (int __user *)(long)attr->addr;
+               int irq;
+
+               if (!test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
+                       return -ENODEV;
+
+               if (get_user(irq, uaddr))
+                       return -EFAULT;
+
+               /*
+                * The PMU overflow interrupt could be a PPI or SPI, but for one
+                * VM the interrupt type must be same for each vcpu. As a PPI,
+                * the interrupt number is the same for all vcpus, while as an
+                * SPI it must be a separate number per vcpu.
+                */
+               if (irq < VGIC_NR_SGIS || irq >= vcpu->kvm->arch.vgic.nr_irqs ||
+                   !irq_is_valid(vcpu->kvm, irq, irq < VGIC_NR_PRIVATE_IRQS))
+                       return -EINVAL;
+
+               if (kvm_arm_pmu_irq_initialized(vcpu))
+                       return -EBUSY;
+
+               kvm_debug("Set kvm ARM PMU irq: %d\n", irq);
+               vcpu->arch.pmu.irq_num = irq;
+               return 0;
+       }
+       case KVM_ARM_VCPU_PMU_V3_INIT:
+               return kvm_arm_pmu_v3_init(vcpu);
+       }
+
+       return -ENXIO;
+}
+
+int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
+{
+       switch (attr->attr) {
+       case KVM_ARM_VCPU_PMU_V3_IRQ: {
+               int __user *uaddr = (int __user *)(long)attr->addr;
+               int irq;
+
+               if (!test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
+                       return -ENODEV;
+
+               if (!kvm_arm_pmu_irq_initialized(vcpu))
+                       return -ENXIO;
+
+               irq = vcpu->arch.pmu.irq_num;
+               return put_user(irq, uaddr);
+       }
+       }
+
+       return -ENXIO;
+}
+
+int kvm_arm_pmu_v3_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
+{
+       switch (attr->attr) {
+       case KVM_ARM_VCPU_PMU_V3_IRQ:
+       case KVM_ARM_VCPU_PMU_V3_INIT:
+               if (kvm_arm_support_pmu_v3() &&
+                   test_bit(KVM_ARM_VCPU_PMU_V3, vcpu->arch.features))
+                       return 0;
+       }
+
+       return -ENXIO;
+}
index 13907970d11c3a94b8dc0a5b1848973035cc41cf..1b0bee095427ecb4a563dcdc51a152073c4f157d 100644 (file)
@@ -320,6 +320,11 @@ static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu,
 }
 
 static const struct vgic_io_range vgic_dist_ranges[] = {
+       {
+               .base           = GIC_DIST_SOFTINT,
+               .len            = 4,
+               .handle_mmio    = handle_mmio_sgi_reg,
+       },
        {
                .base           = GIC_DIST_CTRL,
                .len            = 12,
@@ -386,11 +391,6 @@ static const struct vgic_io_range vgic_dist_ranges[] = {
                .bits_per_irq   = 2,
                .handle_mmio    = handle_mmio_cfg_reg,
        },
-       {
-               .base           = GIC_DIST_SOFTINT,
-               .len            = 4,
-               .handle_mmio    = handle_mmio_sgi_reg,
-       },
        {
                .base           = GIC_DIST_SGI_PENDING_CLEAR,
                .len            = VGIC_NR_SGIS,
index ff02f08df74d6bfa9a35f41a5a556a9f6c944a72..67ec334ce1d07f407cbd5c01a869798f6f4178ab 100644 (file)
@@ -176,6 +176,15 @@ static const struct vgic_ops vgic_v2_ops = {
 
 static struct vgic_params vgic_v2_params;
 
+static void vgic_cpu_init_lrs(void *params)
+{
+       struct vgic_params *vgic = params;
+       int i;
+
+       for (i = 0; i < vgic->nr_lr; i++)
+               writel_relaxed(0, vgic->vctrl_base + GICH_LR0 + (i * 4));
+}
+
 /**
  * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT
  * @node:      pointer to the DT node
@@ -257,6 +266,9 @@ int vgic_v2_probe(struct device_node *vgic_node,
 
        vgic->type = VGIC_V2;
        vgic->max_gic_vcpus = VGIC_V2_MAX_CPUS;
+
+       on_each_cpu(vgic_cpu_init_lrs, vgic, 1);
+
        *ops = &vgic_v2_ops;
        *params = vgic;
        goto out;
index 453eafd4dd6e5fa3f48b458e2fd62df0792c3554..999bdc6d9d9f6fbef40d73358ff6b46d3fcd02c8 100644 (file)
@@ -42,7 +42,7 @@ static u32 ich_vtr_el2;
 static struct vgic_lr vgic_v3_get_lr(const struct kvm_vcpu *vcpu, int lr)
 {
        struct vgic_lr lr_desc;
-       u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[VGIC_V3_LR_INDEX(lr)];
+       u64 val = vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr];
 
        if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
                lr_desc.irq = val & ICH_LR_VIRTUALID_MASK;
@@ -106,7 +106,7 @@ static void vgic_v3_set_lr(struct kvm_vcpu *vcpu, int lr,
                lr_val |= ((u64)lr_desc.hwirq) << ICH_LR_PHYS_ID_SHIFT;
        }
 
-       vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[VGIC_V3_LR_INDEX(lr)] = lr_val;
+       vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = lr_val;
 
        if (!(lr_desc.state & LR_STATE_MASK))
                vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr |= (1U << lr);
@@ -216,6 +216,11 @@ static const struct vgic_ops vgic_v3_ops = {
 
 static struct vgic_params vgic_v3_params;
 
+static void vgic_cpu_init_lrs(void *params)
+{
+       kvm_call_hyp(__vgic_v3_init_lrs);
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:      pointer to the DT node
@@ -284,6 +289,8 @@ int vgic_v3_probe(struct device_node *vgic_node,
        kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
                 vcpu_res.start, vgic->maint_irq);
 
+       on_each_cpu(vgic_cpu_init_lrs, vgic, 1);
+
        *ops = &vgic_v3_ops;
        *params = vgic;
 
index 043032c6a5a4dc6944c5b2bc6277ad6398decd23..00429b392c61cbbd32203877405631f635fc61e3 100644 (file)
@@ -1875,8 +1875,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
 static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 {
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
-
-       int sz = (nr_irqs - VGIC_NR_PRIVATE_IRQS) / 8;
+       int nr_longs = BITS_TO_LONGS(nr_irqs - VGIC_NR_PRIVATE_IRQS);
+       int sz = nr_longs * sizeof(unsigned long);
        vgic_cpu->pending_shared = kzalloc(sz, GFP_KERNEL);
        vgic_cpu->active_shared = kzalloc(sz, GFP_KERNEL);
        vgic_cpu->pend_act_shared = kzalloc(sz, GFP_KERNEL);
index 35315992245600a418874fd371e641ef336a0a22..f0d061f92674c674803720a0cadfdc04df8a4a0c 100644 (file)
@@ -97,8 +97,8 @@ static void async_pf_execute(struct work_struct *work)
         * This memory barrier pairs with prepare_to_wait's set_current_state()
         */
        smp_mb();
-       if (waitqueue_active(&vcpu->wq))
-               wake_up_interruptible(&vcpu->wq);
+       if (swait_active(&vcpu->wq))
+               swake_up(&vcpu->wq);
 
        mmput(mm);
        kvm_put_kvm(vcpu->kvm);
@@ -109,8 +109,8 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
        /* cancel outstanding work queue item */
        while (!list_empty(&vcpu->async_pf.queue)) {
                struct kvm_async_pf *work =
-                       list_entry(vcpu->async_pf.queue.next,
-                                  typeof(*work), queue);
+                       list_first_entry(&vcpu->async_pf.queue,
+                                        typeof(*work), queue);
                list_del(&work->queue);
 
 #ifdef CONFIG_KVM_ASYNC_PF_SYNC
@@ -127,8 +127,8 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
        spin_lock(&vcpu->async_pf.lock);
        while (!list_empty(&vcpu->async_pf.done)) {
                struct kvm_async_pf *work =
-                       list_entry(vcpu->async_pf.done.next,
-                                  typeof(*work), link);
+                       list_first_entry(&vcpu->async_pf.done,
+                                        typeof(*work), link);
                list_del(&work->link);
                kmem_cache_free(async_pf_cache, work);
        }
@@ -172,7 +172,7 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva,
         * do alloc nowait since if we are going to sleep anyway we
         * may as well sleep faulting in page
         */
-       work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT);
+       work = kmem_cache_zalloc(async_pf_cache, GFP_NOWAIT | __GFP_NOWARN);
        if (!work)
                return 0;
 
index a11cfd20a6a0d2aa86b1d06b8552bc41a8bfd8c9..7ba1d10ffed2d5a416701153caea619c7ab22f8d 100644 (file)
@@ -72,11 +72,11 @@ module_param(halt_poll_ns, uint, S_IRUGO | S_IWUSR);
 
 /* Default doubles per-vcpu halt_poll_ns. */
 static unsigned int halt_poll_ns_grow = 2;
-module_param(halt_poll_ns_grow, int, S_IRUGO);
+module_param(halt_poll_ns_grow, uint, S_IRUGO | S_IWUSR);
 
 /* Default resets per-vcpu halt_poll_ns . */
 static unsigned int halt_poll_ns_shrink;
-module_param(halt_poll_ns_shrink, int, S_IRUGO);
+module_param(halt_poll_ns_shrink, uint, S_IRUGO | S_IWUSR);
 
 /*
  * Ordering of locks:
@@ -216,8 +216,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
        vcpu->kvm = kvm;
        vcpu->vcpu_id = id;
        vcpu->pid = NULL;
-       vcpu->halt_poll_ns = 0;
-       init_waitqueue_head(&vcpu->wq);
+       init_swait_queue_head(&vcpu->wq);
        kvm_async_pf_vcpu_init(vcpu);
 
        vcpu->pre_pcpu = -1;
@@ -620,13 +619,10 @@ void *kvm_kvzalloc(unsigned long size)
 
 static void kvm_destroy_devices(struct kvm *kvm)
 {
-       struct list_head *node, *tmp;
+       struct kvm_device *dev, *tmp;
 
-       list_for_each_safe(node, tmp, &kvm->devices) {
-               struct kvm_device *dev =
-                       list_entry(node, struct kvm_device, vm_node);
-
-               list_del(node);
+       list_for_each_entry_safe(dev, tmp, &kvm->devices, vm_node) {
+               list_del(&dev->vm_node);
                dev->ops->destroy(dev);
        }
 }
@@ -1437,11 +1433,17 @@ kvm_pfn_t __gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn,
 {
        unsigned long addr = __gfn_to_hva_many(slot, gfn, NULL, write_fault);
 
-       if (addr == KVM_HVA_ERR_RO_BAD)
+       if (addr == KVM_HVA_ERR_RO_BAD) {
+               if (writable)
+                       *writable = false;
                return KVM_PFN_ERR_RO_FAULT;
+       }
 
-       if (kvm_is_error_hva(addr))
+       if (kvm_is_error_hva(addr)) {
+               if (writable)
+                       *writable = false;
                return KVM_PFN_NOSLOT;
+       }
 
        /* Do not map writable pfn in the readonly memslot. */
        if (writable && memslot_is_readonly(slot)) {
@@ -1943,14 +1945,18 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_mark_page_dirty);
 
 static void grow_halt_poll_ns(struct kvm_vcpu *vcpu)
 {
-       int old, val;
+       unsigned int old, val, grow;
 
        old = val = vcpu->halt_poll_ns;
+       grow = READ_ONCE(halt_poll_ns_grow);
        /* 10us base */
-       if (val == 0 && halt_poll_ns_grow)
+       if (val == 0 && grow)
                val = 10000;
        else
-               val *= halt_poll_ns_grow;
+               val *= grow;
+
+       if (val > halt_poll_ns)
+               val = halt_poll_ns;
 
        vcpu->halt_poll_ns = val;
        trace_kvm_halt_poll_ns_grow(vcpu->vcpu_id, val, old);
@@ -1958,13 +1964,14 @@ static void grow_halt_poll_ns(struct kvm_vcpu *vcpu)
 
 static void shrink_halt_poll_ns(struct kvm_vcpu *vcpu)
 {
-       int old, val;
+       unsigned int old, val, shrink;
 
        old = val = vcpu->halt_poll_ns;
-       if (halt_poll_ns_shrink == 0)
+       shrink = READ_ONCE(halt_poll_ns_shrink);
+       if (shrink == 0)
                val = 0;
        else
-               val /= halt_poll_ns_shrink;
+               val /= shrink;
 
        vcpu->halt_poll_ns = val;
        trace_kvm_halt_poll_ns_shrink(vcpu->vcpu_id, val, old);
@@ -1990,7 +1997,7 @@ static int kvm_vcpu_check_block(struct kvm_vcpu *vcpu)
 void kvm_vcpu_block(struct kvm_vcpu *vcpu)
 {
        ktime_t start, cur;
-       DEFINE_WAIT(wait);
+       DECLARE_SWAITQUEUE(wait);
        bool waited = false;
        u64 block_ns;
 
@@ -2015,7 +2022,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
        kvm_arch_vcpu_blocking(vcpu);
 
        for (;;) {
-               prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
+               prepare_to_swait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
 
                if (kvm_vcpu_check_block(vcpu) < 0)
                        break;
@@ -2024,7 +2031,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
                schedule();
        }
 
-       finish_wait(&vcpu->wq, &wait);
+       finish_swait(&vcpu->wq, &wait);
        cur = ktime_get();
 
        kvm_arch_vcpu_unblocking(vcpu);
@@ -2056,11 +2063,11 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
 {
        int me;
        int cpu = vcpu->cpu;
-       wait_queue_head_t *wqp;
+       struct swait_queue_head *wqp;
 
        wqp = kvm_arch_vcpu_wq(vcpu);
-       if (waitqueue_active(wqp)) {
-               wake_up_interruptible(wqp);
+       if (swait_active(wqp)) {
+               swake_up(wqp);
                ++vcpu->stat.halt_wakeup;
        }
 
@@ -2161,7 +2168,7 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me)
                                continue;
                        if (vcpu == me)
                                continue;
-                       if (waitqueue_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
+                       if (swait_active(&vcpu->wq) && !kvm_arch_vcpu_runnable(vcpu))
                                continue;
                        if (!kvm_vcpu_eligible_for_directed_yield(vcpu))
                                continue;